patch-2.4.0-test9 linux/drivers/usb/storage/shuttle_usbat.c
Next file: linux/drivers/usb/storage/shuttle_usbat.h
Previous file: linux/drivers/usb/storage/scsiglue.c
Back to the patch index
Back to the overall index
- Lines: 883
- Date:
Sun Oct 1 19:42:40 2000
- Orig file:
v2.4.0-test8/linux/drivers/usb/storage/shuttle_usbat.c
- Orig date:
Mon Aug 28 16:59:14 2000
diff -u --recursive --new-file v2.4.0-test8/linux/drivers/usb/storage/shuttle_usbat.c linux/drivers/usb/storage/shuttle_usbat.c
@@ -1,18 +1,6 @@
/* Driver for SCM Microsystems USB-ATAPI cable
*
- * $Id: shuttle_usbat.c,v 1.4 2000/08/25 00:13:51 mdharm Exp $
- *
- * SCM driver v0.2:
- *
- * Removed any reference to maxlen for bulk transfers.
- * Changed scm_bulk_transport to allow for transfers without commands.
- * Changed hp8200e transport to use the request_bufflen field in the
- * SCSI command for the length of the transfer, rather than calculating
- * it ourselves based on the command.
- *
- * SCM driver v0.1:
- *
- * First release - hp8200e.
+ * $Id: shuttle_usbat.c,v 1.10 2000/09/24 00:03:08 groovyjava Exp $
*
* Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
@@ -30,8 +18,8 @@
* as well. This driver is only guaranteed to work with the ATAPI
* translation.
*
- * The only peripherals that I know of (as of 14 Jul 2000) that uses this
- * device is the Hewlett-Packard 8200e CD-Writer Plus.
+ * The only peripheral that I know of (as of 8 Sep 2000) that uses this
+ * device is the Hewlett-Packard 8200e/8210e CD-Writer Plus.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -64,10 +52,12 @@
extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
unsigned int len, unsigned int *act_len);
-#define short_pack(b1,b2) ( ((u16)(b1)) | ( ((u16)(b2))<<8 ) )
+#define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
#define LSB_of(s) ((s)&0xFF)
#define MSB_of(s) ((s)>>8)
+int transferred = 0;
+
/*
* Send a control message and wait for the response.
*
@@ -98,16 +88,6 @@
int result;
- // If data is going to be sent or received with the URB,
- // then allocate a buffer for it. If data is to be sent,
- // copy the data into the buffer.
-/*
- if (xfer_len > 0) {
- buffer = kmalloc(xfer_len, GFP_KERNEL);
- if (!(command[0] & USB_DIR_IN))
- memcpy(buffer, xfer_data, xfer_len);
- }
-*/
// Send the URB to the device and wait for a response.
/* Why are request and request type reversed in this call? */
@@ -117,16 +97,6 @@
xfer_data, xfer_len);
- // If data was sent or received with the URB, free the buffer we
- // allocated earlier, but not before reading the data out of the
- // buffer if we wanted to receive data.
-/*
- if (xfer_len > 0) {
- if (command[0] & USB_DIR_IN)
- memcpy(xfer_data, buffer, xfer_len);
- kfree(buffer);
- }
-*/
// Check the return code for the command.
if (result < 0) {
@@ -192,7 +162,7 @@
if (result == -EPIPE) {
US_DEBUGP("usbat_raw_bulk():"
" output pipe stalled\n");
- return USB_STOR_TRANSPORT_FAILED;
+ return US_BULK_TRANSFER_SHORT;
}
/* the catch-all case */
@@ -206,7 +176,8 @@
return US_BULK_TRANSFER_SHORT;
}
- US_DEBUGP("Transfered %d of %d bytes\n", act_len, len);
+ US_DEBUGP("Transferred %s %d of %d bytes\n",
+ direction==SCSI_DATA_READ ? "in" : "out", act_len, len);
return US_BULK_TRANSFER_GOOD;
}
@@ -225,68 +196,18 @@
int result = USB_STOR_TRANSPORT_GOOD;
int transferred = 0;
- unsigned char execute[8] = {
- 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
int i;
struct scatterlist *sg;
- char string[64];
- int pipe;
-/*
- if (command_len != 0) {
-
- // Fix up the command's data length
-
- command[6] = len&0xFF;
- command[7] = (len>>8)&0xFF;
-
-
-
- result = usbat_send_control(us,
- execute,
- command,
- command_len);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
- }
-*/
if (len==0)
return USB_STOR_TRANSPORT_GOOD;
-
/* transfer the data payload for the command, if there is any */
-
if (command_len != 0)
direction = (command[0]&0x80) ? SCSI_DATA_READ :
SCSI_DATA_WRITE;
- if (direction == SCSI_DATA_WRITE) {
-
- /* Debug-print the first 48 bytes of the write transfer */
-
- if (!use_sg) {
- string[0] = 0;
- for (i=0; i<len && i<48; i++) {
- sprintf(string+strlen(string), "%02X ",
- data[i]);
- if ((i%16)==15) {
- US_DEBUGP("%s\n", string);
- string[0] = 0;
- }
- }
- if (string[0]!=0)
- US_DEBUGP("%s\n", string);
- }
- }
-
-
- US_DEBUGP("SCM data %s transfer %d sg buffers %d\n",
- ( direction==SCSI_DATA_READ ? "in" : "out"),
- len, use_sg);
-
if (!use_sg)
result = usbat_raw_bulk(us, direction, data, len);
else {
@@ -311,9 +232,6 @@
unsigned char *content) {
int result;
- unsigned char command[8] = {
- 0xC0, access, reg, 0x00, 0x00, 0x00, 0x00, 0x00
- };
result = usbat_send_control(us,
usb_rcvctrlpipe(us->pusb_dev,0),
@@ -324,8 +242,6 @@
content,
1);
- // result = usbat_send_control(us, command, content, 1);
-
return result;
}
@@ -335,9 +251,6 @@
unsigned char content) {
int result;
- unsigned char command[8] = {
- 0x40, access|0x01, reg, content, 0x00, 0x00, 0x00, 0x00
- };
result = usbat_send_control(us,
usb_sndctrlpipe(us->pusb_dev,0),
@@ -348,8 +261,6 @@
NULL,
0);
- // result = usbat_send_control(us, command, NULL, 0);
-
return result;
}
@@ -376,8 +287,6 @@
command,
8);
- // result = usbat_bulk_transport(us, command, 8, 0, NULL, 0, 0);
-
return result;
}
@@ -409,9 +318,6 @@
result = usbat_bulk_transport(us,
NULL, 0, SCSI_DATA_READ, content, len, use_sg);
- // result = usbat_bulk_transport(us,
- // command, 8, 0, content, len, use_sg);
-
return result;
}
@@ -420,40 +326,47 @@
* an error condition.
*/
-int usbat_wait_not_busy(struct us_data *us) {
+int usbat_wait_not_busy(struct us_data *us, int minutes) {
int i;
int result;
unsigned char status;
/* Synchronizing cache on a CDR could take a heck of a long time,
- but probably not more than 15 minutes or so */
+ * but probably not more than 10 minutes or so. On the other hand,
+ * doing a full blank on a CDRW at speed 1 will take about 75
+ * minutes!
+ */
+
+ for (i=0; i<1200+minutes*60; i++) {
- for (i=0; i<500; i++) {
result = usbat_read(us, USBAT_ATA, 0x17, &status);
- US_DEBUGP("SCM: Write ATA data status is %02X\n", status);
+
if (result!=USB_STOR_TRANSPORT_GOOD)
return result;
if (status&0x01) // check condition
return USB_STOR_TRANSPORT_FAILED;
if (status&0x20) // device fault
return USB_STOR_TRANSPORT_FAILED;
- if ((status&0x80)!=0x80) // not busy
- break;
- if (i<5)
- wait_ms(100);
- else if (i<20)
- wait_ms(500);
- else if (i<49)
- wait_ms(1000);
- else if (i<499)
- wait_ms(2000);
- }
- if (i==500)
- return USB_STOR_TRANSPORT_FAILED;
+ if ((status&0x80)!=0x80) { // not busy
+ US_DEBUGP("Waited not busy for %d steps\n", i);
+ return USB_STOR_TRANSPORT_GOOD;
+ }
- return USB_STOR_TRANSPORT_GOOD;
+ if (i<500)
+ wait_ms(10); // 5 seconds
+ else if (i<700)
+ wait_ms(50); // 10 seconds
+ else if (i<1200)
+ wait_ms(100); // 50 seconds
+ else
+ wait_ms(1000); // X minutes
+ }
+
+ US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
+ minutes);
+ return USB_STOR_TRANSPORT_FAILED;
}
int usbat_write_block(struct us_data *us,
@@ -461,7 +374,8 @@
unsigned char reg,
unsigned char *content,
unsigned short len,
- int use_sg) {
+ int use_sg,
+ int minutes) {
int result;
unsigned char command[8] = {
@@ -487,115 +401,157 @@
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- // result = usbat_bulk_transport(us,
- // command, 8, 0, content, len, use_sg);
-
- return usbat_wait_not_busy(us);
+ return usbat_wait_not_busy(us, minutes);
}
-int usbat_write_block_test(struct us_data *us,
+int usbat_rw_block_test(struct us_data *us,
unsigned char access,
unsigned char *registers,
unsigned char *data_out,
unsigned short num_registers,
unsigned char data_reg,
unsigned char status_reg,
- unsigned char qualifier,
unsigned char timeout,
+ unsigned char qualifier,
+ int direction,
unsigned char *content,
unsigned short len,
- int use_sg) {
+ int use_sg,
+ int minutes) {
int result;
// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
- // but that's what came out of the trace.
+ // but that's what came out of the trace every single time.
unsigned char command[16] = {
0x40, access|0x07, 0x07, 0x17, 0xfc, 0xe7,
LSB_of(num_registers*2), MSB_of(num_registers*2),
- 0x40, access|0x05, data_reg, status_reg,
- qualifier, timeout, LSB_of(len), MSB_of(len)
+ (direction==SCSI_DATA_WRITE ? 0x40 : 0xC0),
+ access|(direction==SCSI_DATA_WRITE ? 0x05 : 0x04),
+ data_reg, status_reg,
+ timeout, qualifier, LSB_of(len), MSB_of(len)
};
+
int i;
unsigned char data[num_registers*2];
- int transferred;
- struct scatterlist *sg;
- char string[64];
+ unsigned char status;
for (i=0; i<num_registers; i++) {
data[i<<1] = registers[i];
data[1+(i<<1)] = data_out[i];
}
- result = usbat_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 16);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
+ for (i=0; i<20; i++) {
- result = usbat_bulk_transport(us,
- NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0);
+ /*
+ * The first time we send the full command, which consists
+ * of downloading the SCSI command followed by downloading
+ * the data via a write-and-test. Any other time we only
+ * send the command to download the data -- the SCSI command
+ * is still 'active' in some sense in the device.
+ *
+ * We're only going to try sending the data 10 times. After
+ * that, we just return a failure.
+ */
+
+ result = usbat_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0x80,
+ 0x40,
+ 0,
+ 0,
+ (i==0 ? command : command+8),
+ (i==0 ? 16 : 8));
- // result = usbat_bulk_transport(us,
- // command, 16, 0, data, num_registers*2, 0);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (i==0) {
- // transferred = 0;
+ result = usbat_bulk_transport(us,
+ NULL, 0, SCSI_DATA_WRITE,
+ data, num_registers*2, 0);
- US_DEBUGP("Transfer out %d bytes, sg buffers %d\n",
- len, use_sg);
+ if (result!=USB_STOR_TRANSPORT_GOOD)
+ return result;
- result = usbat_bulk_transport(us,
- NULL, 0, SCSI_DATA_WRITE, content, len, use_sg);
+ }
-/*
- if (!use_sg) {
- // Debug-print the first 48 bytes of the transfer
+ //US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
+ // direction == SCSI_DATA_WRITE ? "out" : "in",
+ // len, use_sg);
+
+ result = usbat_bulk_transport(us,
+ NULL, 0, direction, content, len, use_sg);
+
+ /*
+ * If we get a stall on the bulk download, we'll retry
+ * the bulk download -- but not the SCSI command because
+ * in some sense the SCSI command is still 'active' and
+ * waiting for the data. Don't ask me why this should be;
+ * I'm only following what the Windoze driver did.
+ *
+ * Note that a stall for the test-and-read/write command means
+ * that the test failed. In this case we're testing to make
+ * sure that the device is error-free
+ * (i.e. bit 0 -- CHK -- of status is 0). The most likely
+ * hypothesis is that the USBAT chip somehow knows what
+ * the device will accept, but doesn't give the device any
+ * data until all data is received. Thus, the device would
+ * still be waiting for the first byte of data if a stall
+ * occurs, even if the stall implies that some data was
+ * transferred.
+ */
+
+ if (result == US_BULK_TRANSFER_SHORT) {
+
+ /*
+ * If we're reading and we stalled, then clear
+ * the bulk output pipe only the first time.
+ */
+
+ if (direction==SCSI_DATA_READ && i==0)
+ usb_clear_halt(us->pusb_dev,
+ usb_sndbulkpipe(us->pusb_dev,
+ us->ep_out));
+ /*
+ * Read status: is the device angry, or just busy?
+ */
+
+ result = usbat_read(us, USBAT_ATA,
+ direction==SCSI_DATA_WRITE ? 0x17 : 0x0E,
+ &status);
- string[0] = 0;
- for (i=0; i<len && i<48; i++) {
- sprintf(string+strlen(string), "%02X ",
- content[i]);
- if ((i%16)==15) {
- US_DEBUGP("%s\n", string);
- string[0] = 0;
- }
- }
- if (string[0]!=0)
- US_DEBUGP("%s\n", string);
+ if (result!=USB_STOR_TRANSPORT_GOOD)
+ return result;
+ if (status&0x01) // check condition
+ return USB_STOR_TRANSPORT_FAILED;
+ if (status&0x20) // device fault
+ return USB_STOR_TRANSPORT_FAILED;
- result = usbat_raw_bulk(us, SCSI_DATA_WRITE, content, len);
+ US_DEBUGP("Redoing %s\n",
+ direction==SCSI_DATA_WRITE ? "write" : "read");
- } else {
+ } else if (result != US_BULK_TRANSFER_GOOD)
+ return result;
+ else
+ return usbat_wait_not_busy(us, minutes);
- sg = (struct scatterlist *)content;
- for (i=0; i<use_sg && transferred<len; i++) {
- result = usbat_raw_bulk(us, SCSI_DATA_WRITE,
- sg[i].address,
- len-transferred > sg[i].length ?
- sg[i].length : len-transferred);
- if (result!=US_BULK_TRANSFER_GOOD)
- break;
- transferred += sg[i].length;
- }
}
-*/
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
- return usbat_wait_not_busy(us);
+ US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
+ direction==SCSI_DATA_WRITE ? "Writing" : "Reading");
+
+ return USB_STOR_TRANSPORT_FAILED;
}
+/*
+ * Write data to multiple registers at once. Not meant for large
+ * transfers of data!
+ */
+
int usbat_multiple_write(struct us_data *us,
unsigned char access,
unsigned char *registers,
@@ -630,21 +586,15 @@
result = usbat_bulk_transport(us,
NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0);
- // result = usbat_bulk_transport(us, cmd, 8, 0,
- // data, num_registers*2, 0);
-
if (result!=USB_STOR_TRANSPORT_GOOD)
return result;
- return usbat_wait_not_busy(us);
+ return usbat_wait_not_busy(us, 0);
}
int usbat_read_user_io(struct us_data *us,
unsigned char *data_flags) {
- unsigned char command[8] = {
- 0xC0, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
int result;
result = usbat_send_control(us,
@@ -656,8 +606,6 @@
data_flags,
1);
- // result = usbat_send_control(us, command, data_flags, 1);
-
return result;
}
@@ -665,9 +613,6 @@
unsigned char enable_flags,
unsigned char data_flags) {
- unsigned char command[8] = {
- 0x40, 0x82, enable_flags, data_flags, 0x00, 0x00, 0x00, 0x00
- };
int result;
result = usbat_send_control(us,
@@ -679,8 +624,138 @@
NULL,
0);
- // result = usbat_send_control(us, command, NULL, 0);
+ return result;
+}
+
+/*
+ * Squeeze a potentially huge (> 65535 byte) read10 command into
+ * a little ( <= 65535 byte) ATAPI pipe
+ */
+
+int usbat_handle_read10(struct us_data *us,
+ unsigned char *registers,
+ unsigned char *data,
+ Scsi_Cmnd *srb) {
+
+ int result = USB_STOR_TRANSPORT_GOOD;
+ unsigned char *buffer;
+ unsigned int len;
+ unsigned int sector;
+ unsigned int amount;
+ struct scatterlist *sg = NULL;
+ int sg_segment = 0;
+ int sg_offset = 0;
+
+ US_DEBUGP("handle_read10: transfersize %d\n",
+ srb->transfersize);
+
+ if (srb->request_bufflen < 0x10000) {
+
+ result = usbat_rw_block_test(us, USBAT_ATA,
+ registers, data, 19,
+ 0x10, 0x17, 0xFD, 0x30,
+ SCSI_DATA_READ,
+ srb->request_buffer,
+ srb->request_bufflen, srb->use_sg, 1);
+
+ return result;
+ }
+
+ /*
+ * Since we're requesting more data than we can handle in
+ * a single read command (max is 64k-1), we will perform
+ * multiple reads, but each read must be in multiples of
+ * a sector. Luckily the sector size is in srb->transfersize
+ * (see linux/drivers/scsi/sr.c).
+ */
+
+ if (data[7+0] == GPCMD_READ_CD) {
+ len = short_pack(data[7+9], data[7+8]);
+ len <<= 16;
+ len |= data[7+7];
+ srb->transfersize = srb->request_bufflen/len;
+ }
+
+
+ len = (65535/srb->transfersize) * srb->transfersize;
+ US_DEBUGP("Max read is %d bytes\n", len);
+ buffer = kmalloc(len, GFP_KERNEL);
+ if (buffer == NULL) // bloody hell!
+ return USB_STOR_TRANSPORT_FAILED;
+ sector = short_pack(data[7+3], data[7+2]);
+ sector <<= 16;
+ sector |= short_pack(data[7+5], data[7+4]);
+ transferred = 0;
+
+ if (srb->use_sg) {
+ sg = (struct scatterlist *)srb->request_buffer;
+ sg_segment = 0; // for keeping track of where we are in
+ sg_offset = 0; // the scatter/gather list
+ }
+
+ while (transferred != srb->request_bufflen) {
+
+ if (len > srb->request_bufflen - transferred)
+ len = srb->request_bufflen - transferred;
+
+ data[3] = len&0xFF; // (cylL) = expected length (L)
+ data[4] = (len>>8)&0xFF; // (cylH) = expected length (H)
+
+ // Fix up the SCSI command sector and num sectors
+
+ data[7+2] = MSB_of(sector>>16); // SCSI command sector
+ data[7+3] = LSB_of(sector>>16);
+ data[7+4] = MSB_of(sector&0xFFFF);
+ data[7+5] = LSB_of(sector&0xFFFF);
+ if (data[7+0] == GPCMD_READ_CD)
+ data[7+6] = 0;
+ data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
+ data[7+8] = LSB_of(len / srb->transfersize); // num sectors
+
+ result = usbat_rw_block_test(us, USBAT_ATA,
+ registers, data, 19,
+ 0x10, 0x17, 0xFD, 0x30,
+ SCSI_DATA_READ,
+ buffer,
+ len, 0, 1);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ break;
+
+ // Transfer the received data into the srb buffer
+
+ if (!srb->use_sg) {
+ memcpy(srb->request_buffer+transferred, buffer, len);
+ } else {
+ amount = 0;
+ while (amount<len) {
+ if (len - amount >=
+ sg[sg_segment].length-sg_offset) {
+ memcpy(sg[sg_segment].address + sg_offset,
+ buffer + amount,
+ sg[sg_segment].length - sg_offset);
+ amount +=
+ sg[sg_segment].length-sg_offset;
+ sg_segment++;
+ sg_offset=0;
+ } else {
+ memcpy(sg[sg_segment].address + sg_offset,
+ buffer + amount,
+ len - amount);
+ sg_offset += (len - amount);
+ amount = len;
+ }
+ }
+ }
+ // Update the amount transferred and the sector number
+
+ transferred += len;
+ sector += len / srb->transfersize;
+
+ } // while transferred != srb->request_bufflen
+
+ kfree(buffer);
return result;
}
@@ -870,102 +945,8 @@
int i;
char string[64];
- /* This table tells us:
- X = command not supported
- L = return length in cmnd[4] (8 bits).
- H = return length in cmnd[7] and cmnd[8] (16 bits).
- D = return length in cmnd[6] to cmnd[9] (32 bits).
- B = return length/blocksize in cmnd[6] to cmnd[8].
- T = return length in cmnd[6] to cmnd[8] (24 bits).
- 0-9 = fixed return length
- W = 24 bytes
- h = return length/2048 in cmnd[7-8].
- */
-
- static char *lengths =
-
- /* 0123456789ABCDEF 0123456789ABCDEF */
-
- "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */
- "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */
- "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */
- "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */
- "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */
-
-/* if (us->flags & US_FL_NEED_INIT) {
- US_DEBUGP("8200e: initializing\n");
- init_8200e(us);
- us->flags &= ~US_FL_NEED_INIT;
- } */
-
len = srb->request_bufflen;
-/* if (srb->sc_data_direction == SCSI_DATA_WRITE)
- len = srb->request_bufflen;
- else {
-
- switch (lengths[srb->cmnd[0]]) {
-
- case 'L':
- len = srb->cmnd[4];
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- len = lengths[srb->cmnd[0]]-'0';
- break;
- case 'H':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- break;
- case 'h':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- len <<= 11; // *2048
- break;
- case 'T':
- len = (((unsigned int)srb->cmnd[6])<<16) |
- (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
- case 'D':
- len = (((unsigned int)srb->cmnd[6])<<24) |
- (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
- case 'W':
- len = 24;
- break;
- case 'B':
- // Let's try using the command structure's
- // request_bufflen here
- len = srb->request_bufflen;
- break;
- default:
- US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n",
- srb->cmnd[0]);
- return USB_STOR_TRANSPORT_ERROR;
- }
- } */
-
- if (len > 0xFFFF) {
- US_DEBUGP("Error: len = %08X... what do I do now?\n",
- len);
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- // US_DEBUGP("XXXXXXXXXXXXXXXX req_bufflen %d, len %d, bufflen %d\n",
- // srb->request_bufflen, len, srb->bufflen);
-
/* Send A0 (ATA PACKET COMMAND).
Note: I guess we're never going to get any of the ATA
commands... just ATA Packet Commands.
@@ -986,20 +967,41 @@
data[5] = 0xB0; // (device sel) = slave
data[6] = 0xA0; // (command) = ATA PACKET COMMAND
- if (srb->sc_data_direction == SCSI_DATA_WRITE) {
+ for (i=7; i<19; i++) {
+ registers[i] = 0x10;
+ data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];
+ }
- for (i=7; i<19; i++) {
- registers[i] = 0x10;
- data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];
- }
+ if (srb->cmnd[0] == TEST_UNIT_READY)
+ transferred = 0;
+
+ if (srb->sc_data_direction == SCSI_DATA_WRITE) {
- result = usbat_write_block_test(us, USBAT_ATA,
+ result = usbat_rw_block_test(us, USBAT_ATA,
registers, data, 19,
0x10, 0x17, 0xFD, 0x30,
+ SCSI_DATA_WRITE,
srb->request_buffer,
- len, srb->use_sg);
+ len, srb->use_sg, 10);
+
+ if (result == USB_STOR_TRANSPORT_GOOD) {
+ transferred += len;
+ US_DEBUGP("Wrote %08X bytes\n", transferred);
+ }
return result;
+
+ } else if (srb->cmnd[0] == READ_10 ||
+ srb->cmnd[0] == GPCMD_READ_CD) {
+
+ return usbat_handle_read10(us, registers, data, srb);
+
+ }
+
+ if (len > 0xFFFF) {
+ US_DEBUGP("Error: len = %08X... what do I do now?\n",
+ len);
+ return USB_STOR_TRANSPORT_ERROR;
}
if ( (result = usbat_multiple_write(us,
@@ -1010,8 +1012,15 @@
// Write the 12-byte command header.
+ // If the command is BLANK then set the timer for 75 minutes.
+ // Otherwise set it for 10 minutes.
+
+ // NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
+ // AT SPEED 4 IS UNRELIABLE!!!
+
if ( (result = usbat_write_block(us,
- USBAT_ATA, 0x10, srb->cmnd, 12, 0)) !=
+ USBAT_ATA, 0x10, srb->cmnd, 12, 0,
+ srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
USB_STOR_TRANSPORT_GOOD) {
return result;
}
@@ -1060,8 +1069,6 @@
US_DEBUGP("%s\n", string);
}
}
-
- // US_DEBUGP("Command result %d\n", result);
return result;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)