Commit fd82bf1c authored by Matthew Dharm's avatar Matthew Dharm Committed by Greg Kroah-Hartman

[PATCH] USB: fix datafab and freecom to use I/O buffer

This patch makes the Datafab and the Freecom driver both use the I/O safe
buffer us->iobuf instead of local stack or local allocations.
parent 391366a4
...@@ -94,7 +94,7 @@ static int datafab_read_data(struct us_data *us, ...@@ -94,7 +94,7 @@ static int datafab_read_data(struct us_data *us,
unsigned char *dest, unsigned char *dest,
int use_sg) int use_sg)
{ {
unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x20, 0x01 }; unsigned char *command = us->iobuf;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
unsigned char *ptr; unsigned char *ptr;
unsigned char thistime; unsigned char thistime;
...@@ -116,8 +116,6 @@ static int datafab_read_data(struct us_data *us, ...@@ -116,8 +116,6 @@ static int datafab_read_data(struct us_data *us,
return rc; return rc;
} }
command[5] += (info->lun << 4);
totallen = sectors * info->ssize; totallen = sectors * info->ssize;
do { do {
...@@ -138,10 +136,13 @@ static int datafab_read_data(struct us_data *us, ...@@ -138,10 +136,13 @@ static int datafab_read_data(struct us_data *us,
command[3] = (sector >> 8) & 0xFF; command[3] = (sector >> 8) & 0xFF;
command[4] = (sector >> 16) & 0xFF; command[4] = (sector >> 16) & 0xFF;
command[5] = 0xE0 + (info->lun << 4);
command[5] |= (sector >> 24) & 0x0F; command[5] |= (sector >> 24) & 0x0F;
command[6] = 0x20;
command[7] = 0x01;
// send the read command // send the read command
result = datafab_bulk_write(us, command, sizeof(command)); result = datafab_bulk_write(us, command, 8);
if (result != USB_STOR_XFER_GOOD) if (result != USB_STOR_XFER_GOOD)
goto leave; goto leave;
...@@ -180,8 +181,8 @@ static int datafab_write_data(struct us_data *us, ...@@ -180,8 +181,8 @@ static int datafab_write_data(struct us_data *us,
unsigned char *src, unsigned char *src,
int use_sg) int use_sg)
{ {
unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x30, 0x02 }; unsigned char *command = us->iobuf;
unsigned char reply[2] = { 0, 0 }; unsigned char *reply = us->iobuf;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
unsigned char *ptr; unsigned char *ptr;
unsigned char thistime; unsigned char thistime;
...@@ -202,8 +203,6 @@ static int datafab_write_data(struct us_data *us, ...@@ -202,8 +203,6 @@ static int datafab_write_data(struct us_data *us,
return rc; return rc;
} }
command[5] += (info->lun << 4);
// If we're using scatter-gather, we have to create a new // If we're using scatter-gather, we have to create a new
// buffer to read all of the data in first, since a // buffer to read all of the data in first, since a
// scatter-gather buffer could in theory start in the middle // scatter-gather buffer could in theory start in the middle
...@@ -237,10 +236,13 @@ static int datafab_write_data(struct us_data *us, ...@@ -237,10 +236,13 @@ static int datafab_write_data(struct us_data *us,
command[3] = (sector >> 8) & 0xFF; command[3] = (sector >> 8) & 0xFF;
command[4] = (sector >> 16) & 0xFF; command[4] = (sector >> 16) & 0xFF;
command[5] = 0xE0 + (info->lun << 4);
command[5] |= (sector >> 24) & 0x0F; command[5] |= (sector >> 24) & 0x0F;
command[6] = 0x30;
command[7] = 0x02;
// send the command // send the command
result = datafab_bulk_write(us, command, sizeof(command)); result = datafab_bulk_write(us, command, 8);
if (result != USB_STOR_XFER_GOOD) if (result != USB_STOR_XFER_GOOD)
goto leave; goto leave;
...@@ -250,7 +252,7 @@ static int datafab_write_data(struct us_data *us, ...@@ -250,7 +252,7 @@ static int datafab_write_data(struct us_data *us,
goto leave; goto leave;
// read the result // read the result
result = datafab_bulk_read(us, reply, sizeof(reply)); result = datafab_bulk_read(us, reply, 2);
if (result != USB_STOR_XFER_GOOD) if (result != USB_STOR_XFER_GOOD)
goto leave; goto leave;
...@@ -291,13 +293,19 @@ static int datafab_determine_lun(struct us_data *us, ...@@ -291,13 +293,19 @@ static int datafab_determine_lun(struct us_data *us,
// //
// There might be a better way of doing this? // There might be a better way of doing this?
unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
unsigned char buf[512]; unsigned char *command = us->iobuf;
unsigned char *buf;
int count = 0, rc; int count = 0, rc;
if (!us || !info) if (!us || !info)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
memcpy(command, scommand, 8);
buf = kmalloc(512, GFP_NOIO);
if (!buf)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("datafab_determine_lun: locating...\n"); US_DEBUGP("datafab_determine_lun: locating...\n");
// we'll try 3 times before giving up... // we'll try 3 times before giving up...
...@@ -306,31 +314,41 @@ static int datafab_determine_lun(struct us_data *us, ...@@ -306,31 +314,41 @@ static int datafab_determine_lun(struct us_data *us,
command[5] = 0xa0; command[5] = 0xa0;
rc = datafab_bulk_write(us, command, 8); rc = datafab_bulk_write(us, command, 8);
if (rc != USB_STOR_XFER_GOOD) if (rc != USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR; rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
rc = datafab_bulk_read(us, buf, sizeof(buf)); rc = datafab_bulk_read(us, buf, 512);
if (rc == USB_STOR_XFER_GOOD) { if (rc == USB_STOR_XFER_GOOD) {
info->lun = 0; info->lun = 0;
return USB_STOR_TRANSPORT_GOOD; rc = USB_STOR_TRANSPORT_GOOD;
goto leave;
} }
command[5] = 0xb0; command[5] = 0xb0;
rc = datafab_bulk_write(us, command, 8); rc = datafab_bulk_write(us, command, 8);
if (rc != USB_STOR_XFER_GOOD) if (rc != USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR; rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
rc = datafab_bulk_read(us, buf, sizeof(buf)); rc = datafab_bulk_read(us, buf, 512);
if (rc == USB_STOR_XFER_GOOD) { if (rc == USB_STOR_XFER_GOOD) {
info->lun = 1; info->lun = 1;
return USB_STOR_TRANSPORT_GOOD; rc = USB_STOR_TRANSPORT_GOOD;
goto leave;
} }
wait_ms(20); wait_ms(20);
} }
return USB_STOR_TRANSPORT_ERROR; rc = USB_STOR_TRANSPORT_ERROR;
leave:
kfree(buf);
return rc;
} }
static int datafab_id_device(struct us_data *us, static int datafab_id_device(struct us_data *us,
...@@ -340,8 +358,9 @@ static int datafab_id_device(struct us_data *us, ...@@ -340,8 +358,9 @@ static int datafab_id_device(struct us_data *us,
// to the ATA spec, 'Sector Count' isn't used but the Windows driver // to the ATA spec, 'Sector Count' isn't used but the Windows driver
// sets this bit so we do too... // sets this bit so we do too...
// //
unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
unsigned char reply[512]; unsigned char *command = us->iobuf;
unsigned char *reply;
int rc; int rc;
if (!us || !info) if (!us || !info)
...@@ -353,11 +372,18 @@ static int datafab_id_device(struct us_data *us, ...@@ -353,11 +372,18 @@ static int datafab_id_device(struct us_data *us,
return rc; return rc;
} }
memcpy(command, scommand, 8);
reply = kmalloc(512, GFP_NOIO);
if (!reply)
return USB_STOR_TRANSPORT_ERROR;
command[5] += (info->lun << 4); command[5] += (info->lun << 4);
rc = datafab_bulk_write(us, command, 8); rc = datafab_bulk_write(us, command, 8);
if (rc != USB_STOR_XFER_GOOD) if (rc != USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR; rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
// we'll go ahead and extract the media capacity while we're here... // we'll go ahead and extract the media capacity while we're here...
// //
...@@ -369,10 +395,15 @@ static int datafab_id_device(struct us_data *us, ...@@ -369,10 +395,15 @@ static int datafab_id_device(struct us_data *us,
((u32)(reply[116]) << 16) | ((u32)(reply[116]) << 16) |
((u32)(reply[115]) << 8) | ((u32)(reply[115]) << 8) |
((u32)(reply[114]) ); ((u32)(reply[114]) );
return USB_STOR_TRANSPORT_GOOD; rc = USB_STOR_TRANSPORT_GOOD;
goto leave;
} }
return USB_STOR_TRANSPORT_ERROR; rc = USB_STOR_TRANSPORT_ERROR;
leave:
kfree(reply);
return rc;
} }
...@@ -571,8 +602,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -571,8 +602,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
// don't bother implementing READ_6 or WRITE_6. Just set MODE_XLATE and // don't bother implementing READ_6 or WRITE_6.
// let the usb storage code convert to READ_10/WRITE_10
// //
if (srb->cmnd[0] == READ_10) { if (srb->cmnd[0] == READ_10) {
block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
......
...@@ -44,11 +44,6 @@ static void pdump (void *, int); ...@@ -44,11 +44,6 @@ static void pdump (void *, int);
#define ERR_STAT 0x01 #define ERR_STAT 0x01
#define DRQ_STAT 0x08 #define DRQ_STAT 0x08
struct freecom_udata {
u8 buffer[64]; /* Common command block. */
};
typedef struct freecom_udata *freecom_udata_t;
/* All of the outgoing packets are 64 bytes long. */ /* All of the outgoing packets are 64 bytes long. */
struct freecom_cb_wrap { struct freecom_cb_wrap {
u8 Type; /* Command type. */ u8 Type; /* Command type. */
...@@ -112,9 +107,8 @@ static int ...@@ -112,9 +107,8 @@ static int
freecom_readdata (Scsi_Cmnd *srb, struct us_data *us, freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
unsigned int ipipe, unsigned int opipe, int count) unsigned int ipipe, unsigned int opipe, int count)
{ {
freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_xfer_wrap *fxfr = struct freecom_xfer_wrap *fxfr =
(struct freecom_xfer_wrap *) extra->buffer; (struct freecom_xfer_wrap *) us->iobuf;
int result; int result;
fxfr->Type = FCM_PACKET_INPUT | 0x00; fxfr->Type = FCM_PACKET_INPUT | 0x00;
...@@ -147,9 +141,8 @@ static int ...@@ -147,9 +141,8 @@ static int
freecom_writedata (Scsi_Cmnd *srb, struct us_data *us, freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
int unsigned ipipe, unsigned int opipe, int count) int unsigned ipipe, unsigned int opipe, int count)
{ {
freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_xfer_wrap *fxfr = struct freecom_xfer_wrap *fxfr =
(struct freecom_xfer_wrap *) extra->buffer; (struct freecom_xfer_wrap *) us->iobuf;
int result; int result;
fxfr->Type = FCM_PACKET_OUTPUT | 0x00; fxfr->Type = FCM_PACKET_OUTPUT | 0x00;
...@@ -190,12 +183,9 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -190,12 +183,9 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
int result; int result;
unsigned int partial; unsigned int partial;
int length; int length;
freecom_udata_t extra;
extra = (freecom_udata_t) us->extra; fcb = (struct freecom_cb_wrap *) us->iobuf;
fst = (struct freecom_status *) us->iobuf;
fcb = (struct freecom_cb_wrap *) extra->buffer;
fst = (struct freecom_status *) extra->buffer;
US_DEBUGP("Freecom TRANSPORT STARTED\n"); US_DEBUGP("Freecom TRANSPORT STARTED\n");
...@@ -386,18 +376,11 @@ int ...@@ -386,18 +376,11 @@ int
freecom_init (struct us_data *us) freecom_init (struct us_data *us)
{ {
int result; int result;
char buffer[33]; char *buffer = us->iobuf;
/* Allocate a buffer for us. The upper usb transport code will /* The DMA-mapped I/O buffer is 64 bytes long, just right for
* free this for us when cleaning up. */ * all our packets. No need to allocate any extra buffer space.
if (us->extra == NULL) { */
us->extra = kmalloc (sizeof (struct freecom_udata),
GFP_KERNEL);
if (us->extra == NULL) {
US_DEBUGP("Out of memory\n");
return USB_STOR_TRANSPORT_ERROR;
}
}
result = usb_stor_control_msg(us, us->recv_ctrl_pipe, result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ); 0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment