Commit 03e7d40d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 947af82f c748be11
......@@ -1701,6 +1701,15 @@ static const struct driver_info zaurus_slb500_info = {
.in = 1, .out = 2,
};
static const struct driver_info zaurus_slc700_info = {
.description = "Sharp Zaurus SL-C700",
.flags = FLAG_FRAMING_Z,
.check_connect = always_connected,
.tx_fixup = zaurus_tx_fixup,
.in = 1, .out = 2,
};
// SL-5600 and C-700 are PXA based; should resemble A300
......@@ -2751,6 +2760,15 @@ static const struct usb_device_id products [] = {
.bInterfaceSubClass = 0x0a,
.bInterfaceProtocol = 0x00,
.driver_info = (unsigned long) &zaurus_slb500_info,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x8007,
.bInterfaceClass = 0x02,
.bInterfaceSubClass = 0x0a,
.bInterfaceProtocol = 0x00,
.driver_info = (unsigned long) &zaurus_slc700_info,
},
#endif
......
......@@ -166,7 +166,11 @@ static int device_reset( Scsi_Cmnd *srb )
/* lock the device pointers and do the reset */
down(&(us->dev_semaphore));
result = us->transport_reset(us);
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
result = FAILED;
US_DEBUGP("No reset during disconnect\n");
} else
result = us->transport_reset(us);
up(&(us->dev_semaphore));
/* lock access to the state and clear it */
......@@ -202,7 +206,7 @@ static int bus_reset( Scsi_Cmnd *srb )
down(&(us->dev_semaphore));
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
result = -EIO;
US_DEBUGP("Attempt to reset during disconnect\n");
US_DEBUGP("No reset during disconnect\n");
} else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {
result = -EBUSY;
US_DEBUGP("Refusing to reset a multi-interface device\n");
......
......@@ -147,9 +147,19 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
us->current_urb->context = &urb_done;
us->current_urb->actual_length = 0;
us->current_urb->error_count = 0;
us->current_urb->transfer_flags = URB_ASYNC_UNLINK;
us->current_urb->status = 0;
/* we assume that if transfer_buffer isn't us->iobuf then it
* hasn't been mapped for DMA. Yes, this is clunky, but it's
* easier than always having the caller tell us whether the
* transfer buffer has already been mapped. */
us->current_urb->transfer_flags =
URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;
if (us->current_urb->transfer_buffer == us->iobuf)
us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
us->current_urb->transfer_dma = us->iobuf_dma;
us->current_urb->setup_dma = us->cr_dma;
/* submit the URB */
status = usb_submit_urb(us->current_urb, GFP_NOIO);
if (status) {
......@@ -207,15 +217,15 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
value, index, size);
/* fill in the devrequest structure */
us->dr->bRequestType = requesttype;
us->dr->bRequest = request;
us->dr->wValue = cpu_to_le16(value);
us->dr->wIndex = cpu_to_le16(index);
us->dr->wLength = cpu_to_le16(size);
us->cr->bRequestType = requesttype;
us->cr->bRequest = request;
us->cr->wValue = cpu_to_le16(value);
us->cr->wIndex = cpu_to_le16(index);
us->cr->wLength = cpu_to_le16(size);
/* fill and submit the URB */
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) us->dr, data, size,
(unsigned char*) us->cr, data, size,
usb_stor_blocking_completion, NULL);
status = usb_stor_msg_common(us, timeout);
......@@ -346,15 +356,15 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
value, index, size);
/* fill in the devrequest structure */
us->dr->bRequestType = requesttype;
us->dr->bRequest = request;
us->dr->wValue = cpu_to_le16(value);
us->dr->wIndex = cpu_to_le16(index);
us->dr->wLength = cpu_to_le16(size);
us->cr->bRequestType = requesttype;
us->cr->bRequest = request;
us->cr->wValue = cpu_to_le16(value);
us->cr->wIndex = cpu_to_le16(index);
us->cr->wLength = cpu_to_le16(size);
/* fill and submit the URB */
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) us->dr, data, size,
(unsigned char*) us->cr, data, size,
usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us, 0);
......@@ -786,9 +796,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
}
/* STATUS STAGE */
result = usb_stor_intr_transfer(us, us->irqdata, sizeof(us->irqdata));
result = usb_stor_intr_transfer(us, us->iobuf, 2);
US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
us->irqdata[0], us->irqdata[1]);
us->iobuf[0], us->iobuf[1]);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
......@@ -804,7 +814,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->cmnd[0] == INQUIRY)
return USB_STOR_TRANSPORT_GOOD;
else {
if (us->irqdata[0])
if (us->iobuf[0])
return USB_STOR_TRANSPORT_FAILED;
else
return USB_STOR_TRANSPORT_GOOD;
......@@ -815,13 +825,13 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
* The first byte should always be a 0x0
* The second byte & 0x0F should be 0x0 for good, otherwise error
*/
if (us->irqdata[0]) {
if (us->iobuf[0]) {
US_DEBUGP("CBI IRQ data showed reserved bType %d\n",
us->irqdata[0]);
us->iobuf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
switch (us->irqdata[1] & 0x0F) {
switch (us->iobuf[1] & 0x0F) {
case 0x00:
return USB_STOR_TRANSPORT_GOOD;
case 0x01:
......@@ -889,7 +899,6 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* Determine what the maximum LUN supported is */
int usb_stor_Bulk_max_lun(struct us_data *us)
{
unsigned char data;
int result;
/* issue the command */
......@@ -897,14 +906,14 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE,
0, us->ifnum, &data, sizeof(data), HZ);
0, us->ifnum, us->iobuf, 1, HZ);
US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
result, data);
result, us->iobuf[0]);
/* if we have a successful request, return the result */
if (result == 1)
return data;
return us->iobuf[0];
/* return the default -- no LUNs */
return 0;
......@@ -912,33 +921,34 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
{
struct bulk_cb_wrap bcb;
struct bulk_cs_wrap bcs;
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
unsigned int transfer_length = srb->request_bufflen;
int result;
int fake_sense = 0;
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb.DataTransferLength = cpu_to_le32(transfer_length);
bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number;
bcb.Lun = srb->device->lun;
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(transfer_length);
bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb->Tag = srb->serial_number;
bcb->Lun = srb->device->lun;
if (us->flags & US_FL_SCM_MULT_TARG)
bcb.Lun |= srb->device->id << 4;
bcb.Length = srb->cmd_len;
bcb->Lun |= srb->device->id << 4;
bcb->Length = srb->cmd_len;
/* copy the command payload */
memset(bcb.CDB, 0, sizeof(bcb.CDB));
memcpy(bcb.CDB, srb->cmnd, bcb.Length);
memset(bcb->CDB, 0, sizeof(bcb->CDB));
memcpy(bcb->CDB, srb->cmnd, bcb->Length);
/* send it to out endpoint */
US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
le32_to_cpu(bcb.Signature), bcb.Tag,
(bcb.Lun >> 4), (bcb.Lun & 0x0F),
le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
le32_to_cpu(bcb->Signature), bcb->Tag,
(bcb->Lun >> 4), (bcb->Lun & 0x0F),
le32_to_cpu(bcb->DataTransferLength),
bcb->Flags, bcb->Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
&bcb, US_BULK_CB_WRAP_LEN, NULL);
bcb, US_BULK_CB_WRAP_LEN, NULL);
US_DEBUGP("Bulk command transfer result=%d\n", result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
......@@ -972,7 +982,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
&bcs, US_BULK_CS_WRAP_LEN, NULL);
bcs, US_BULK_CS_WRAP_LEN, NULL);
/* did the attempt to read the CSW fail? */
if (result == USB_STOR_XFER_STALLED) {
......@@ -980,7 +990,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
&bcs, US_BULK_CS_WRAP_LEN, NULL);
bcs, US_BULK_CS_WRAP_LEN, NULL);
}
/* if we still have a failure at this point, we're in trouble */
......@@ -990,17 +1000,18 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* check bulk status */
US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
le32_to_cpu(bcs.Signature), bcs.Tag,
bcs.Residue, bcs.Status);
if ((bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs.Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
bcs.Tag != bcb.Tag ||
bcs.Status > US_BULK_STAT_PHASE) {
le32_to_cpu(bcs->Signature), bcs->Tag,
bcs->Residue, bcs->Status);
if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
bcs->Tag != srb->serial_number ||
bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* based on the status code, we report good or bad */
switch (bcs.Status) {
switch (bcs->Status) {
case US_BULK_STAT_OK:
/* device babbled -- return fake sense data */
if (fake_sense) {
......@@ -1065,6 +1076,10 @@ static int usb_stor_reset_common(struct us_data *us,
schedule_timeout(HZ*6);
set_current_state(TASK_RUNNING);
down(&us->dev_semaphore);
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
US_DEBUGP("Reset interrupted by disconnect\n");
return FAILED;
}
US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
......@@ -1083,18 +1098,18 @@ static int usb_stor_reset_common(struct us_data *us,
/* This issues a CB[I] Reset to the device in question
*/
#define CB_RESET_CMD_SIZE 12
int usb_stor_CB_reset(struct us_data *us)
{
unsigned char cmd[12];
US_DEBUGP("CB_reset() called\n");
US_DEBUGP("%s called\n", __FUNCTION__);
memset(cmd, 0xFF, sizeof(cmd));
cmd[0] = SEND_DIAGNOSTIC;
cmd[1] = 4;
memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
us->iobuf[0] = SEND_DIAGNOSTIC;
us->iobuf[1] = 4;
return usb_stor_reset_common(us, US_CBI_ADSC,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, cmd, sizeof(cmd));
0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE);
}
/* This issues a Bulk-only Reset to the device in question, including
......@@ -1102,7 +1117,7 @@ int usb_stor_CB_reset(struct us_data *us)
*/
int usb_stor_Bulk_reset(struct us_data *us)
{
US_DEBUGP("Bulk reset requested\n");
US_DEBUGP("%s called\n", __FUNCTION__);
return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
......
......@@ -252,6 +252,14 @@ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100,
US_SC_UFI, US_PR_CB, NULL,
US_FL_SINGLE_LUN ),
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110,
"Sony",
"Portable USB Harddrive V2",
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
#endif
UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
"Sony",
"Memorystick MSAC-US1",
......@@ -295,26 +303,6 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
"USB Hard Disk",
US_SC_RBC, US_PR_CB, NULL, 0 ),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"Pentax",
"Optio 2/3/400",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110,
"In-System",
......@@ -339,12 +327,6 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110,
"USB Storage Adapter V2",
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110,
"Sony",
"Portable USB Harddrive V2",
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
#endif
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
......@@ -385,12 +367,6 @@ UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
UNUSUAL_DEV( 0x05e3, 0x0700, 0x0000, 0x9999,
"Unknown",
"GL641USB based CF Card reader",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY | US_FL_MODE_XLATE),
/* Reported by Hanno Boeck <hanno@gmx.de>
* Taken from the Lycoris Kernel */
UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999,
......@@ -520,13 +496,6 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
"Simple Tech/Datafab CF+SM Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE ),
/* Submitted by Olaf Hering <olh@suse.de> */
UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff,
"Datafab Systems, Inc.",
"USB to CF + SM Combo (LC1)",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE ),
#endif
#ifdef CONFIG_USB_STORAGE_SDDR55
......@@ -538,6 +507,15 @@ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
US_FL_FIX_INQUIRY ),
#endif
#ifdef CONFIG_USB_STORAGE_DATAFAB
/* Submitted by Olaf Hering <olh@suse.de> */
UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff,
"Datafab Systems, Inc.",
"USB to CF + SM Combo (LC1)",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE ),
#endif
/* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
* Only revision 1.13 tested (same for all of the above devices,
* based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY.
......@@ -563,19 +541,28 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
US_SC_8070, US_PR_CB, NULL,
US_FL_FIX_INQUIRY ),
/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
"Samsung",
"Digimax 410",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY),
/* Aiptek PocketCAM 3Mega
* Nicolas DUPEUX <nicolas@dupeux.net>
*/
UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
"AIPTEK",
"PocketCAM 3Mega",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_MODE_XLATE ),
/* aeb */
UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
"Feiya",
"5-in-1 Card Reader",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_CAPACITY ),
/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
"Samsung",
"Digimax 410",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY),
UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001,
"Minds@Work",
......@@ -589,22 +576,26 @@ UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100,
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100,
"IBM",
"IBM USB Memory Key",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
/* Pentax Optio S digital camera
* adapted from http://www2.goldfisch.at/knowledge/233
* (Peter Pilsl <pilsl@goldfisch.at>)
* by Christoph Weidemann <cweidema@indiana.edu> */
UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CB, NULL,
US_FL_MODE_XLATE|US_FL_FIX_INQUIRY),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"Pentax",
"Optio 2/3/400",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
"ATI",
......@@ -613,13 +604,6 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
0 ),
#endif
/* EasyDisk support. Submitted by Stanislav Karchebny <berk@madfire.net> */
UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x0001,
"Global Channel Solutions",
"EasyDisk EDxxxx",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_MODE_XLATE | US_FL_FIX_INQUIRY ),
/* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
* Tested on hardware version 1.10.
* Entry is needed only for the initializer function override.
......@@ -648,13 +632,3 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
US_SC_SCSI, US_PR_SDDR55, NULL,
US_FL_SINGLE_LUN),
#endif
/* Aiptek PocketCAM 3Mega
* Nicolas DUPEUX <nicolas@dupeux.net>
*/
UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
"AIPTEK",
"PocketCAM 3Mega",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_MODE_XLATE ),
......@@ -338,10 +338,16 @@ static int usb_stor_control_thread(void * __us)
/* lock the device pointers */
down(&(us->dev_semaphore));
/* don't do anything if we are disconnecting */
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
US_DEBUGP("No command during disconnect\n");
us->srb->result = DID_BAD_TARGET << 16;
}
/* reject the command if the direction indicator
* is UNKNOWN
*/
if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
else if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
US_DEBUGP("UNKNOWN data direction\n");
us->srb->result = DID_ERROR << 16;
}
......@@ -421,12 +427,44 @@ static int usb_stor_control_thread(void * __us)
* Device probing and disconnecting
***********************************************************************/
/* Associate our private data with the USB device */
static int associate_dev(struct us_data *us, struct usb_interface *intf)
{
US_DEBUGP("-- %s\n", __FUNCTION__);
/* Fill in the device-related fields */
us->pusb_dev = interface_to_usbdev(intf);
us->pusb_intf = intf;
us->ifnum = intf->altsetting->desc.bInterfaceNumber;
/* Store our private data in the interface and increment the
* device's reference count */
usb_set_intfdata(intf, us);
usb_get_dev(us->pusb_dev);
/* Allocate the device-related DMA-mapped buffers */
us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr),
GFP_KERNEL, &us->cr_dma);
if (!us->cr) {
US_DEBUGP("usb_ctrlrequest allocation failed\n");
return -ENOMEM;
}
us->iobuf = usb_buffer_alloc(us->pusb_dev, US_IOBUF_SIZE,
GFP_KERNEL, &us->iobuf_dma);
if (!us->iobuf) {
US_DEBUGP("I/O buffer allocation failed\n");
return -ENOMEM;
}
return 0;
}
/* Get the unusual_devs entries and the string descriptors */
static void get_device_info(struct us_data *us, int id_index)
{
struct usb_device *dev = us->pusb_dev;
struct usb_host_interface *altsetting =
&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting];
struct usb_interface_descriptor *idesc =
&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting].desc;
struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
struct usb_device_id *id = &storage_usb_ids[id_index];
......@@ -438,10 +476,10 @@ static void get_device_info(struct us_data *us, int id_index)
/* Store the entries */
us->unusual_dev = unusual_dev;
us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
altsetting->desc.bInterfaceSubClass :
idesc->bInterfaceSubClass :
unusual_dev->useProtocol;
us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
altsetting->desc.bInterfaceProtocol :
idesc->bInterfaceProtocol :
unusual_dev->useTransport;
us->flags = unusual_dev->flags;
......@@ -455,20 +493,26 @@ static void get_device_info(struct us_data *us, int id_index)
"an unneeded SubClass entry",
"an unneeded Protocol entry",
"unneeded SubClass and Protocol entries"};
struct usb_device_descriptor *ddesc = &dev->descriptor;
int msg = -1;
if (unusual_dev->useProtocol != US_SC_DEVICE &&
us->subclass == altsetting->desc.bInterfaceSubClass)
us->subclass == idesc->bInterfaceSubClass)
msg += 1;
if (unusual_dev->useTransport != US_PR_DEVICE &&
us->protocol == altsetting->desc.bInterfaceProtocol)
us->protocol == idesc->bInterfaceProtocol)
msg += 2;
if (msg >= 0)
printk(KERN_NOTICE USB_STORAGE "This device "
"(%04x,%04x) has %s in unusual_devs.h\n"
"(%04x,%04x,%04x S %02x P %02x)"
" has %s in unusual_devs.h\n"
" Please send a copy of this message to "
"<linux-usb-devel@lists.sourceforge.net>\n",
id->idVendor, id->idProduct, msgs[msg]);
ddesc->idVendor, ddesc->idProduct,
ddesc->bcdDevice,
idesc->bInterfaceSubClass,
idesc->bInterfaceProtocol,
msgs[msg]);
}
/* Read the device's string descriptors */
......@@ -485,15 +529,15 @@ static void get_device_info(struct us_data *us, int id_index)
/* Use the unusual_dev strings if the device didn't provide them */
if (strlen(us->vendor) == 0) {
if (unusual_dev->vendorName)
strncpy(us->vendor, unusual_dev->vendorName,
sizeof(us->vendor) - 1);
strlcpy(us->vendor, unusual_dev->vendorName,
sizeof(us->vendor));
else
strcpy(us->vendor, "Unknown");
}
if (strlen(us->product) == 0) {
if (unusual_dev->productName)
strncpy(us->product, unusual_dev->productName,
sizeof(us->product) - 1);
strlcpy(us->product, unusual_dev->productName,
sizeof(us->product));
else
strcpy(us->product, "Unknown");
}
......@@ -714,18 +758,9 @@ static int usb_stor_acquire_resources(struct us_data *us)
{
int p;
/* Allocate the USB control blocks */
US_DEBUGP("Allocating usb_ctrlrequest\n");
us->dr = kmalloc(sizeof(*us->dr), GFP_KERNEL);
if (!us->dr) {
US_DEBUGP("allocation failed\n");
return -ENOMEM;
}
US_DEBUGP("Allocating URB\n");
us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!us->current_urb) {
US_DEBUGP("allocation failed\n");
US_DEBUGP("URB allocation failed\n");
return -ENOMEM;
}
......@@ -778,8 +813,24 @@ static void dissociate_dev(struct us_data *us)
{
US_DEBUGP("-- %s\n", __FUNCTION__);
down(&us->dev_semaphore);
/* Free the device-related DMA-mapped buffers */
if (us->cr) {
usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
us->cr_dma);
us->cr = NULL;
}
if (us->iobuf) {
usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,
us->iobuf_dma);
us->iobuf = NULL;
}
/* Remove our private data from the interface and decrement the
* device's reference count */
usb_set_intfdata(us->pusb_intf, NULL);
usb_put_dev(us->pusb_dev);
us->pusb_dev = NULL;
us->pusb_intf = NULL;
up(&us->dev_semaphore);
......@@ -818,16 +869,11 @@ void usb_stor_release_resources(struct us_data *us)
us->extra_destructor(us->extra);
}
/* Destroy the extra data */
if (us->extra) {
/* Free the extra data and the URB */
if (us->extra)
kfree(us->extra);
}
/* Free the USB control blocks */
if (us->current_urb)
usb_free_urb(us->current_urb);
if (us->dr)
kfree(us->dr);
/* Free the structure itself */
kfree(us);
......@@ -857,15 +903,10 @@ static int storage_probe(struct usb_interface *intf,
init_MUTEX_LOCKED(&(us->sema));
init_completion(&(us->notify));
/* Fill in the device-related fields */
us->pusb_dev = interface_to_usbdev(intf);
us->pusb_intf = intf;
us->ifnum = intf->altsetting->desc.bInterfaceNumber;
/* Store our private data in the interface and increment the
* device's reference count */
usb_set_intfdata(intf, us);
usb_get_dev(us->pusb_dev);
/* Associate the us_data structure with the USB device */
result = associate_dev(us, intf);
if (result)
goto BadDevice;
/*
* Get the unusual_devs entries and the descriptors
......
......@@ -92,6 +92,15 @@ struct us_unusual_dev {
#define USB_STOR_STRING_LEN 32
/*
* We provide a DMA-mapped I/O buffer for use with small USB transfers.
* It turns out that CB[I] needs a 12-byte buffer and Bulk-only needs a
* 31-byte buffer. But Freecom needs a 64-byte buffer, so that's the
* size we'll allocate.
*/
#define US_IOBUF_SIZE 64 /* Size of the DMA-mapped I/O buffer */
typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
typedef int (*trans_reset)(struct us_data*);
typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
......@@ -106,6 +115,7 @@ struct us_data {
struct semaphore dev_semaphore; /* protect pusb_dev */
struct usb_device *pusb_dev; /* this usb_device */
struct usb_interface *pusb_intf; /* this interface */
struct us_unusual_dev *unusual_dev; /* device-filter entry */
unsigned long flags; /* from filter initially */
unsigned int send_bulk_pipe; /* cached pipe values */
unsigned int recv_bulk_pipe;
......@@ -139,20 +149,19 @@ struct us_data {
int pid; /* control thread */
int sm_state; /* what we are doing */
/* interrupt communications data */
unsigned char irqdata[2]; /* data from USB IRQ */
/* control and bulk communications data */
struct urb *current_urb; /* non-int USB requests */
struct usb_ctrlrequest *dr; /* control requests */
struct usb_sg_request current_sg; /* scatter-gather USB */
/* the semaphore for sleeping the control thread */
struct semaphore sema; /* to sleep thread on */
struct urb *current_urb; /* USB requests */
struct usb_ctrlrequest *cr; /* control requests */
struct usb_sg_request current_sg; /* scatter-gather req. */
unsigned char *iobuf; /* I/O buffer */
dma_addr_t cr_dma; /* buffer DMA addresses */
dma_addr_t iobuf_dma;
/* mutual exclusion structures */
struct semaphore sema; /* to sleep thread on */
struct completion notify; /* thread begin/end */
struct us_unusual_dev *unusual_dev; /* If unusual device */
/* subdriver information */
void *extra; /* Any extra data */
extra_data_destructor extra_destructor;/* extra data destructor */
};
......
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