ChangeSet 1.1595.8.7, 2003/07/30 10:34:49-07:00, stern@rowland.harvard.edu [PATCH] USB: Proper I/O buffering for the shuttle_usbat subdriver This patch makes the shuttle_usbat subdriver use proper DMA I/O buffering. Although I try to be careful with these changes, I can't test them. So I urge you to read through it carefully to verify that nothing seems to be wrong. drivers/usb/storage/shuttle_usbat.c | 186 ++++++++++++++++++++++-------------- 1 files changed, 115 insertions(+), 71 deletions(-) diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c --- a/drivers/usb/storage/shuttle_usbat.c Fri Aug 1 10:56:21 2003 +++ b/drivers/usb/storage/shuttle_usbat.c Fri Aug 1 10:56:21 2003 @@ -103,10 +103,16 @@ unsigned char subcountL) { int result; - unsigned char command[8] = { - 0x40, 0x81, epp_control, external_trigger, - test_pattern, mask_byte, subcountL, subcountH - }; + unsigned char *command = us->iobuf; + + command[0] = 0x40; + command[1] = 0x81; + command[2] = epp_control; + command[3] = external_trigger; + command[4] = test_pattern; + command[5] = mask_byte; + command[6] = subcountL; + command[7] = subcountH; result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, @@ -128,14 +134,20 @@ int use_sg) { int result; - unsigned char command[8] = { - 0xC0, access|0x02, reg, 0x00, 0x00, 0x00, - LSB_of(len), MSB_of(len) - }; + unsigned char *command = us->iobuf; if (!len) return USB_STOR_TRANSPORT_GOOD; + command[0] = 0xC0; + command[1] = access | 0x02; + command[2] = reg; + command[3] = 0; + command[4] = 0; + command[5] = 0; + command[6] = LSB_of(len); + command[7] = MSB_of(len); + result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, 0x80, @@ -164,7 +176,7 @@ int i; int result; - unsigned char status; + unsigned char *status = us->iobuf; /* Synchronizing cache on a CDR could take a heck of a long time, * but probably not more than 10 minutes or so. On the other hand, @@ -174,18 +186,18 @@ for (i=0; i<1200+minutes*60; i++) { - result = usbat_read(us, USBAT_ATA, 0x17, &status); + result = usbat_read(us, USBAT_ATA, 0x17, status); if (result!=USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (status&0x01) { // check condition - result = usbat_read(us, USBAT_ATA, 0x10, &status); + if (*status & 0x01) { // check condition + result = usbat_read(us, USBAT_ATA, 0x10, status); return USB_STOR_TRANSPORT_FAILED; } - if (status&0x20) // device fault + if (*status & 0x20) // device fault return USB_STOR_TRANSPORT_FAILED; - if ((status&0x80)==0x00) { // not busy + if ((*status & 0x80)==0x00) { // not busy US_DEBUGP("Waited not busy for %d steps\n", i); return USB_STOR_TRANSPORT_GOOD; } @@ -214,14 +226,20 @@ int minutes) { int result; - unsigned char command[8] = { - 0x40, access|0x03, reg, 0x00, 0x00, 0x00, - LSB_of(len), MSB_of(len) - }; + unsigned char *command = us->iobuf; if (!len) return USB_STOR_TRANSPORT_GOOD; + command[0] = 0x40; + command[1] = access | 0x03; + command[2] = reg; + command[3] = 0; + command[4] = 0; + command[5] = 0; + command[6] = LSB_of(len); + command[7] = MSB_of(len); + result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, 0x80, @@ -265,23 +283,13 @@ // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here, // 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), - (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) - }; + unsigned char *command = us->iobuf; + int i, j; + int cmdlen; + unsigned char *data = us->iobuf; + unsigned char *status = us->iobuf; - int i; - unsigned char data[num_registers*2]; - unsigned char status; - - for (i=0; i US_IOBUF_SIZE/2); for (i=0; i<20; i++) { @@ -296,20 +304,48 @@ * that, we just return a failure. */ + if (i==0) { + cmdlen = 16; + command[0] = 0x40; + command[1] = access | 0x07; + command[2] = 0x07; + command[3] = 0x17; + command[4] = 0xFC; + command[5] = 0xE7; + command[6] = LSB_of(num_registers*2); + command[7] = MSB_of(num_registers*2); + } else + cmdlen = 8; + + command[cmdlen-8] = (direction==SCSI_DATA_WRITE ? 0x40 : 0xC0); + command[cmdlen-7] = access | + (direction==SCSI_DATA_WRITE ? 0x05 : 0x04); + command[cmdlen-6] = data_reg; + command[cmdlen-5] = status_reg; + command[cmdlen-4] = timeout; + command[cmdlen-3] = qualifier; + command[cmdlen-2] = LSB_of(len); + command[cmdlen-1] = MSB_of(len); + result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, 0x80, 0x40, 0, 0, - (i==0 ? command : command+8), - (i==0 ? 16 : 8)); + command, + cmdlen); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; if (i==0) { + for (j=0; jsend_bulk_pipe, data, num_registers*2, NULL); @@ -366,13 +402,13 @@ result = usbat_read(us, USBAT_ATA, direction==SCSI_DATA_WRITE ? 0x17 : 0x0E, - &status); + status); if (result!=USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (status&0x01) // check condition + if (*status & 0x01) // check condition return USB_STOR_TRANSPORT_FAILED; - if (status&0x20) // device fault + if (*status & 0x20) // device fault return USB_STOR_TRANSPORT_FAILED; US_DEBUGP("Redoing %s\n", @@ -403,17 +439,20 @@ unsigned short num_registers) { int result; - unsigned char data[num_registers*2]; + unsigned char *data = us->iobuf; int i; - unsigned char command[8] = { - 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00, - LSB_of(num_registers*2), MSB_of(num_registers*2) - }; + unsigned char *command = us->iobuf; - for (i=0; i US_IOBUF_SIZE/2); + + command[0] = 0x40; + command[1] = access | 0x07; + command[2] = 0; + command[3] = 0; + command[4] = 0; + command[5] = 0; + command[6] = LSB_of(num_registers*2); + command[7] = MSB_of(num_registers*2); result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, @@ -427,6 +466,11 @@ if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; + for (i=0; isend_bulk_pipe, data, num_registers*2, NULL); @@ -593,7 +637,7 @@ static int hp_8200e_select_and_test_registers(struct us_data *us) { int selector; - unsigned char status; + unsigned char *status = us->iobuf; // try device = master, then device = slave. @@ -603,19 +647,19 @@ USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (usbat_read(us, USBAT_ATA, 0x17, &status) != + if (usbat_read(us, USBAT_ATA, 0x17, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (usbat_read(us, USBAT_ATA, 0x16, &status) != + if (usbat_read(us, USBAT_ATA, 0x16, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (usbat_read(us, USBAT_ATA, 0x14, &status) != + if (usbat_read(us, USBAT_ATA, 0x14, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (usbat_read(us, USBAT_ATA, 0x15, &status) != + if (usbat_read(us, USBAT_ATA, 0x15, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -627,11 +671,11 @@ USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (usbat_read(us, USBAT_ATA, 0x14, &status) != + if (usbat_read(us, USBAT_ATA, 0x14, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (usbat_read(us, USBAT_ATA, 0x15, &status) != + if (usbat_read(us, USBAT_ATA, 0x15, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; } @@ -642,7 +686,7 @@ int init_8200e(struct us_data *us) { int result; - unsigned char status; + unsigned char *status = us->iobuf; // Enable peripheral control signals @@ -655,13 +699,13 @@ wait_ms(2000); - if (usbat_read_user_io(us, &status) != + if (usbat_read_user_io(us, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; US_DEBUGP("INIT 2\n"); - if (usbat_read_user_io(us, &status) != + if (usbat_read_user_io(us, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -699,13 +743,13 @@ // Read ISA port 0x27 - if (usbat_read(us, USBAT_ISA, 0x27, &status) != + if (usbat_read(us, USBAT_ISA, 0x27, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; US_DEBUGP("INIT 7\n"); - if (usbat_read_user_io(us, &status) != + if (usbat_read_user_io(us, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -717,7 +761,7 @@ US_DEBUGP("INIT 9\n"); - if (usbat_read_user_io(us, &status) != + if (usbat_read_user_io(us, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -732,7 +776,7 @@ US_DEBUGP("INIT 11\n"); - if (usbat_read_user_io(us, &status) != + if (usbat_read_user_io(us, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -740,7 +784,7 @@ wait_ms(1400); - if (usbat_read_user_io(us, &status) != + if (usbat_read_user_io(us, status) != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -768,7 +812,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) { int result; - unsigned char status; + unsigned char *status = us->iobuf; unsigned char registers[32]; unsigned char data[32]; unsigned int len; @@ -802,8 +846,8 @@ data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7]; } - result = usbat_read(us, USBAT_ATA, 0x17, &status); - US_DEBUGP("Status = %02X\n", status); + result = usbat_read(us, USBAT_ATA, 0x17, status); + US_DEBUGP("Status = %02X\n", *status); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; if (srb->cmnd[0] == TEST_UNIT_READY) @@ -866,21 +910,21 @@ // How many bytes to read in? Check cylL register - if (usbat_read(us, USBAT_ATA, 0x14, &status) != + if (usbat_read(us, USBAT_ATA, 0x14, status) != USB_STOR_XFER_GOOD) { return USB_STOR_TRANSPORT_ERROR; } if (len > 0xFF) { // need to read cylH also - len = status; - if (usbat_read(us, USBAT_ATA, 0x15, &status) != + len = *status; + if (usbat_read(us, USBAT_ATA, 0x15, status) != USB_STOR_XFER_GOOD) { return USB_STOR_TRANSPORT_ERROR; } - len += ((unsigned int)status)<<8; + len += ((unsigned int) *status)<<8; } else - len = status; + len = *status; result = usbat_read_block(us, USBAT_ATA, 0x10,