Commit 58a5ae6a authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

USB storage

sync up with both the -dj and cvs version of the usb-storage code.
parent ea3aba35
/* Driver for Datafab USB Compact Flash reader
*
* $Id: datafab.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
*
* datafab driver v0.1:
*
......@@ -6,11 +8,18 @@
*
* Current development and maintenance by:
* (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
* many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
*
* Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
* which I used as a template for this driver.
*
* Some bugfixes and scatter-gather code by Gregory P. Smith
* (greg-usb@electricrain.com)
*
* Fix for media change by Joerg Schneider (js@joergschneider.com)
*
* Other contributors:
* (c) 2002 Alan Stern <stern@rowland.org>
*
* 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
* Free Software Foundation; either version 2, or (at your option) any
......@@ -102,7 +111,7 @@ static int datafab_raw_bulk(int direction,
if (result == -EPIPE) {
US_DEBUGP("datafab_raw_bulk: EPIPE. clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes\n", pipe, act_len);
usb_clear_halt(us->pusb_dev, pipe);
usb_stor_clear_halt(us, pipe);
}
if (result) {
......@@ -801,6 +810,23 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
}
if (srb->cmnd[0] == START_STOP) {
/* this is used by sd.c'check_scsidisk_media_change to detect
media change */
US_DEBUGP("datafab_transport: START_STOP.\n");
/* the first datafab_id_device after a media change returns
an error (determined experimentally) */
rc = datafab_id_device(us, info);
if (rc == USB_STOR_TRANSPORT_GOOD) {
info->sense_key = NO_SENSE;
srb->result = SUCCESS;
} else {
info->sense_key = UNIT_ATTENTION;
srb->result = CHECK_CONDITION;
}
return rc;
}
US_DEBUGP("datafab_transport: Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]);
return USB_STOR_TRANSPORT_ERROR;
}
/* Driver for USB Mass Storage compliant devices
* Debugging Functions Source Code File
*
* $Id: debug.c,v 1.5 2001/06/27 23:20:45 mdharm Exp $
* $Id: debug.c,v 1.9 2002/04/22 03:39:43 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
* (c) 2002 Alan Stern <stern@rowland.org>
*
* Initial work by:
* (c) 1999 Michael Gee (michael@linuxspecific.com)
......@@ -302,9 +305,11 @@ void usb_stor_show_sense(
case 0x1902: what="defect list error in primary list"; break;
case 0x1903: what="defect list error in grown list"; break;
case 0x1C00: what="defect list not found"; break;
case 0x2000: what="invalid command operation code"; break;
case 0x2400: what="invalid field in CDB"; break;
case 0x2703: what="associated write protect"; break;
case 0x2800: what="not ready to ready transition"; break;
case 0x2900: what="device reset occurred"; break;
case 0x2903: what="bus device reset function occurred"; break;
case 0x2904: what="device internal reset"; break;
case 0x2B00: what="copy can't execute / host can't disconnect"; break;
......@@ -327,7 +332,7 @@ void usb_stor_show_sense(
case 0x3502: what="enclosure services unavailable"; break;
case 0x3503: what="enclosure services transfer failure"; break;
case 0x3504: what="enclosure services transfer refused"; break;
case 0x3A00: what="medium not present"; break;
case 0x3A00: what="media not present"; break;
case 0x3B0F: what="end of medium reached"; break;
case 0x3F02: what="changed operating definition"; break;
case 0x4100: what="data path failure (should use 40 NN)"; break;
......
/* Driver for Freecom USB/IDE adaptor
*
* $Id: freecom.c,v 1.21 2001/12/29 03:47:33 mdharm Exp $
* $Id: freecom.c,v 1.22 2002/04/22 03:39:43 mdharm Exp $
*
* Freecom v0.1:
*
......
This diff is collapsed.
/* Driver for Lexar "Jumpshot" Compact Flash reader
*
* $Id: jumpshot.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
*
* jumpshot driver v0.1:
*
......@@ -6,11 +8,19 @@
*
* Current development and maintenance by:
* (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org)
* many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
*
* Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
* which I used as a template for this driver.
*
* Some bugfixes and scatter-gather code by Gregory P. Smith
* (greg-usb@electricrain.com)
*
* Fix for media change by Joerg Schneider (js@joergschneider.com)
*
* Developed with the assistance of:
*
* (C) 2002 Alan Stern <stern@rowland.org>
*
* 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
* Free Software Foundation; either version 2, or (at your option) any
......@@ -128,8 +138,8 @@ static int jumpshot_send_control(struct us_data *us,
/* a stall is a fatal condition from the device */
if (result == -EPIPE) {
US_DEBUGP("jumpshot_send_control: -- Stall on control pipe. Clearing\n");
result = usb_clear_halt(us->pusb_dev, pipe);
US_DEBUGP("jumpshot_send_control: -- usb_clear_halt() returns %d\n", result);
result = usb_stor_clear_halt(us, pipe);
US_DEBUGP("jumpshot_send_control: -- usb_stor_clear_halt() returns %d\n", result);
return USB_STOR_TRANSPORT_FAILED;
}
......@@ -161,7 +171,7 @@ static int jumpshot_raw_bulk(int direction,
if (result == -EPIPE) {
US_DEBUGP("jumpshot_raw_bulk: EPIPE. clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes\n", pipe, act_len);
usb_clear_halt(us->pusb_dev, pipe);
usb_stor_clear_halt(us, pipe);
}
if (result) {
......@@ -798,6 +808,23 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
//
return USB_STOR_TRANSPORT_GOOD;
}
if (srb->cmnd[0] == START_STOP) {
/* this is used by sd.c'check_scsidisk_media_change to detect
media change */
US_DEBUGP("jumpshot_transport: START_STOP.\n");
/* the first jumpshot_id_device after a media change returns
an error (determined experimentally) */
rc = jumpshot_id_device(us, info);
if (rc == USB_STOR_TRANSPORT_GOOD) {
info->sense_key = NO_SENSE;
srb->result = SUCCESS;
} else {
info->sense_key = UNIT_ATTENTION;
srb->result = CHECK_CONDITION;
}
return rc;
}
US_DEBUGP("jumpshot_transport: Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]);
return USB_STOR_TRANSPORT_ERROR;
......
/* Driver for USB Mass Storage compliant devices
*
* $Id: protocol.c,v 1.11 2002/01/13 06:40:25 mdharm Exp $
* $Id: protocol.c,v 1.14 2002/04/22 03:39:43 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
* (c) 2002 Alan Stern (stern@rowland.org)
*
* Initial work by:
* (c) 1999 Michael Gee (michael@linuxspecific.com)
......@@ -67,10 +68,16 @@ void fix_inquiry_data(Scsi_Cmnd *srb)
US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n");
/* find the location of the data */
if (srb->use_sg)
BUG();
if (srb->use_sg) {
/* this piece of code only works if the first page is big enough to
* hold more than 3 bytes -- which is _very_ likely
*/
struct scatterlist *sg;
data_ptr = (unsigned char *) srb->request_buffer;
sg = (struct scatterlist *) srb->request_buffer;
data_ptr = (unsigned char *) page_address(sg[0].page) + sg[0].offset;
} else
data_ptr = (unsigned char *)srb->request_buffer;
/* Change the SCSI revision number */
data_ptr[2] = (data_ptr[2] & ~7) | 2;
......@@ -94,9 +101,11 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) {
/* fix the INQUIRY data if necessary */
fix_inquiry_data(srb);
/* fix the INQUIRY data if necessary */
fix_inquiry_data(srb);
}
}
void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
......@@ -165,13 +174,15 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) {
/* Fix the MODE_SENSE data if we translated the command */
if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
usb_stor_scsiSense10to6(srb);
/* Fix the MODE_SENSE data if we translated the command */
if (old_cmnd == MODE_SENSE)
usb_stor_scsiSense10to6(srb);
/* fix the INQUIRY data if necessary */
fix_inquiry_data(srb);
/* fix the INQUIRY data if necessary */
fix_inquiry_data(srb);
}
}
......@@ -260,13 +271,15 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) {
/* Fix the MODE_SENSE data if we translated the command */
if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
usb_stor_scsiSense10to6(srb);
/* Fix the MODE_SENSE data if we translated the command */
if (old_cmnd == MODE_SENSE)
usb_stor_scsiSense10to6(srb);
/* Fix the data for an INQUIRY, if necessary */
fix_inquiry_data(srb);
/* Fix the data for an INQUIRY, if necessary */
fix_inquiry_data(srb);
}
}
void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
......@@ -327,13 +340,14 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) {
/* Fix the MODE_SENSE data if we translated the command */
if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE)
&& (status_byte(srb->result) == GOOD))
usb_stor_scsiSense10to6(srb);
/* Fix the MODE_SENSE data if we translated the command */
if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE))
usb_stor_scsiSense10to6(srb);
/* fix the INQUIRY data if necessary */
fix_inquiry_data(srb);
/* fix the INQUIRY data if necessary */
fix_inquiry_data(srb);
}
}
/* Driver for USB Mass Storage compliant devices
* SCSI layer glue code
*
* $Id: scsiglue.c,v 1.24 2001/11/11 03:33:58 mdharm Exp $
* $Id: scsiglue.c,v 1.26 2002/04/22 03:39:43 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
......@@ -177,22 +177,8 @@ static int command_abort( Scsi_Cmnd *srb )
US_DEBUGP("command_abort() called\n");
/* if we're stuck waiting for an IRQ, simulate it */
if (atomic_read(us->ip_wanted)) {
US_DEBUGP("-- simulating missing IRQ\n");
up(&(us->ip_waitq));
}
/* if the device has been removed, this worked */
if (!us->pusb_dev) {
US_DEBUGP("-- device removed already\n");
return SUCCESS;
}
/* if we have an urb pending, let's wake the control thread up */
if (us->current_urb->status == -EINPROGRESS) {
/* cancel the URB -- this will automatically wake the thread */
usb_unlink_urb(us->current_urb);
if (atomic_read(&us->sm_state) == US_STATE_RUNNING) {
usb_stor_abort_transport(us);
/* wait for us to be done */
wait_for_completion(&(us->notify));
......@@ -208,47 +194,57 @@ static int command_abort( Scsi_Cmnd *srb )
static int device_reset( Scsi_Cmnd *srb )
{
struct us_data *us = (struct us_data *)srb->host->hostdata[0];
int result;
US_DEBUGP("device_reset() called\n" );
return us->transport_reset(us);
/* if the device was removed, then we're already reset */
if (atomic_read(&us->sm_state) == US_STATE_DETACHED)
return SUCCESS;
/* lock the device pointers */
down(&(us->dev_semaphore));
us->srb = srb;
atomic_set(&us->sm_state, US_STATE_RESETTING);
result = us->transport_reset(us);
atomic_set(&us->sm_state, US_STATE_IDLE);
/* unlock the device pointers */
up(&(us->dev_semaphore));
return result;
}
/* This resets the device port, and simulates the device
* disconnect/reconnect for all drivers which have claimed other
* interfaces. */
* disconnect/reconnect for all drivers which have claimed
* interfaces, including ourself. */
static int bus_reset( Scsi_Cmnd *srb )
{
struct us_data *us = (struct us_data *)srb->host->hostdata[0];
int i;
int result;
struct usb_device *pusb_dev_save = us->pusb_dev;
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP("bus_reset() called\n");
/* if the device has been removed, this worked */
if (!us->pusb_dev) {
if (atomic_read(&us->sm_state) == US_STATE_DETACHED) {
US_DEBUGP("-- device removed already\n");
return SUCCESS;
}
/* release the IRQ, if we have one */
down(&(us->irq_urb_sem));
if (us->irq_urb) {
US_DEBUGP("-- releasing irq URB\n");
result = usb_unlink_urb(us->irq_urb);
US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
}
up(&(us->irq_urb_sem));
/* attempt to reset the port */
if (usb_reset_device(us->pusb_dev) < 0)
result = usb_reset_device(pusb_dev_save);
US_DEBUGP("usb_reset_device returns %d\n", result);
if (result < 0)
return FAILED;
/* FIXME: This needs to lock out driver probing while it's working
* or we can have race conditions */
for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
/* Is that still true? I don't see how... AS */
for (i = 0; i < pusb_dev_save->actconfig->bNumInterfaces; i++) {
struct usb_interface *intf =
&us->pusb_dev->actconfig->interface[i];
&pusb_dev_save->actconfig->interface[i];
const struct usb_device_id *id;
/* if this is an unclaimed interface, skip it */
......@@ -256,33 +252,17 @@ static int bus_reset( Scsi_Cmnd *srb )
continue;
}
US_DEBUGP("Examinging driver %s...", intf->driver->name);
/* skip interfaces which we've claimed */
if (intf->driver == &usb_storage_driver) {
US_DEBUGPX("skipping ourselves.\n");
continue;
}
US_DEBUGP("Examining driver %s...", intf->driver->name);
/* simulate a disconnect and reconnect for all interfaces */
US_DEBUGPX("simulating disconnect/reconnect.\n");
down(&intf->driver->serialize);
intf->driver->disconnect(us->pusb_dev, intf->private_data);
id = usb_match_id(us->pusb_dev, intf, intf->driver->id_table);
intf->driver->probe(us->pusb_dev, i, id);
intf->driver->disconnect(pusb_dev_save, intf->private_data);
id = usb_match_id(pusb_dev_save, intf, intf->driver->id_table);
intf->driver->probe(pusb_dev_save, i, id);
up(&intf->driver->serialize);
}
/* re-allocate the IRQ URB and submit it to restore connectivity
* for CBI devices
*/
if (us->protocol == US_PR_CBI) {
down(&(us->irq_urb_sem));
us->irq_urb->dev = us->pusb_dev;
result = usb_submit_urb(us->irq_urb, GFP_NOIO);
US_DEBUGP("usb_submit_urb() returns %d\n", result);
up(&(us->irq_urb_sem));
}
US_DEBUGP("bus_reset() complete\n");
return SUCCESS;
}
......@@ -346,7 +326,8 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
/* show the GUID of the device */
SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
SPRINTF(" Attached: %s\n", us->pusb_dev ? "Yes" : "No");
SPRINTF(" Attached: %s\n", (atomic_read(&us->sm_state) ==
US_STATE_DETACHED) ? "Yes" : "No");
/*
* Calculate start of next buffer, and return value.
......@@ -565,11 +546,11 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
/* copy one byte */
{
char *src = page_address(sg[sb].page) + sg[sb].offset + si;
char *dst = page_address(sg[db].page) + sg[db].offset + di;
char *src = page_address(sg[sb].page) + sg[sb].offset + si;
char *dst = page_address(sg[db].page) + sg[db].offset + di;
*dst = *src;
}
*dst = *src;
}
/* get next destination */
if ( sg[db].length-1 == di )
......@@ -607,7 +588,7 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
break;
}
*(char *)(page_address(sg[db].page) + sg[db].offset) = 0;
*(char*)(page_address(sg[db].page) + sg[db].offset) = 0;
/* get next destination */
if ( sg[db].length-1 == di )
......@@ -758,11 +739,11 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
/* copy one byte */
{
char *src = page_address(sg[sb].page) + sg[sb].offset + si;
char *dst = page_address(sg[db].page) + sg[db].offset + di;
char *src = page_address(sg[sb].page) + sg[sb].offset + si;
char *dst = page_address(sg[db].page) + sg[db].offset + di;
*dst = *src;
}
*dst = *src;
}
/* get next destination */
if ( di == 0 )
......@@ -799,11 +780,12 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
break;
}
{
char *dst = page_address(sg[db].page) + sg[db].offset + di;
{
char *dst = page_address(sg[db].page) + sg[db].offset + di;
*dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
}
*dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
}
/* get next destination */
if ( di == 0 )
......@@ -853,19 +835,18 @@ void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* t
if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
{
/* fill in the pointers for both header types */
the6->array[element] =
page_address(sg[i].page) +
sg[i].offset + j;
the10->array[element] =
page_address(sg[i].page) +
sg[i].offset + j;
the6->array[element] = page_address(sg[i].page) +
sg[i].offset + j;
the10->array[element] = page_address(sg[i].page) +
sg[i].offset + j;
}
else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
{
/* only the longer headers still cares now */
the10->array[element] =
page_address(sg[i].page) +
sg[i].offset + j;
the10->array[element] = page_address(sg[i].page) +
sg[i].offset + j;
}
/* increase element counter */
element++;
......
/* Driver for SanDisk SDDR-09 SmartMedia reader
*
* $Id: sddr09.c,v 1.24 2002/04/22 03:39:43 mdharm Exp $
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
* (c) 2002 Andries Brouwer (aeb@cwi.nl)
* Developed with the assistance of:
* (c) 2002 Alan Stern <stern@rowland.org>
*
* The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip.
* This chip is a programmable USB controller. In the SDDR-09, it has
......@@ -262,8 +265,8 @@ sddr09_send_control(struct us_data *us,
/* a stall is a fatal condition from the device */
if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n");
result = usb_clear_halt(us->pusb_dev, pipe);
US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
result = usb_stor_clear_halt(us, pipe);
US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
return USB_STOR_TRANSPORT_FAILED;
}
......@@ -317,13 +320,13 @@ sddr09_raw_bulk(struct us_data *us, int direction,
result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
US_DEBUGP("EPIPE: clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes\n",
pipe, act_len);
usb_clear_halt(us->pusb_dev, pipe);
}
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
US_DEBUGP("EPIPE: clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes\n",
pipe, act_len);
usb_stor_clear_halt(us, pipe);
}
if (result) {
/* -ENOENT -- we canceled this transfer */
......@@ -1386,15 +1389,6 @@ sddr09_read_map(struct us_data *us) {
// Each block is 64 bytes of control data, so block i is located in
// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
#if 0
/* No translation */
for (i=0; i<numblocks; i++) {
lba = i;
info->pba_to_lba[i] = lba;
info->lba_to_pba[lba] = i;
}
printk("sddr09: no translation today\n");
#else
for (i=0; i<numblocks; i++) {
ptr = page_address(sg[i>>11].page) +
sg[i>>11].offset + ((i&0x7ff)<<6);
......@@ -1482,7 +1476,6 @@ sddr09_read_map(struct us_data *us) {
info->pba_to_lba[i] = lba;
info->lba_to_pba[lba] = i;
}
#endif
/*
* Approximate capacity. This is not entirely correct yet,
......@@ -1508,7 +1501,7 @@ sddr09_read_map(struct us_data *us) {
US_DEBUGP("Found %d LBA's\n", lbact);
for (i=0; i<alloc_blocks; i++)
kfree(page_address(sg[i].page)+sg[i].offset);
kfree(page_address(sg[i].page) + sg[i].offset);
kfree(sg);
return 0;
}
......
/* Driver for SCM Microsystems USB-ATAPI cable
*
* $Id: shuttle_usbat.c,v 1.15 2001/12/08 23:32:48 mdharm Exp $
* $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $
*
* Current development and maintenance by:
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
*
* Developed with the assistance of:
* (c) 2002 Alan Stern <stern@rowland.org>
*
* Many originally ATAPI devices were slightly modified to meet the USB
* market by using some kind of translation from ATAPI to USB on the host,
* and the peripheral would translate from USB back to ATAPI.
......@@ -107,8 +110,8 @@ static int usbat_send_control(struct us_data *us,
/* a stall is a fatal condition from the device */
if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n");
result = usb_clear_halt(us->pusb_dev, pipe);
US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
result = usb_stor_clear_halt(us, pipe);
US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
return USB_STOR_TRANSPORT_FAILED;
}
......@@ -140,7 +143,7 @@ static int usbat_raw_bulk(struct us_data *us,
US_DEBUGP("EPIPE: clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes\n",
pipe, act_len);
usb_clear_halt(us->pusb_dev, pipe);
usb_stor_clear_halt(us, pipe);
}
if (result) {
......@@ -214,7 +217,7 @@ static int usbat_bulk_transport(struct us_data *us,
sg = (struct scatterlist *)data;
for (i=0; i<use_sg && transferred<len; i++) {
result = usbat_raw_bulk(us, direction,
page_address(sg[i].page) + sg[i].offset,
page_address(sg[i].page) + sg[i].offset,
len-transferred > sg[i].length ?
sg[i].length : len-transferred);
if (result!=US_BULK_TRANSFER_GOOD)
......@@ -515,7 +518,7 @@ int usbat_rw_block_test(struct us_data *us,
*/
if (direction==SCSI_DATA_READ && i==0)
usb_clear_halt(us->pusb_dev,
usb_stor_clear_halt(us,
usb_sndbulkpipe(us->pusb_dev,
us->ep_out));
/*
......@@ -675,9 +678,15 @@ int usbat_handle_read10(struct us_data *us,
len = short_pack(data[7+9], data[7+8]);
len <<= 16;
len |= data[7+7];
US_DEBUGP("handle_read10: GPCMD_READ_CD: len %d\n", len);
srb->transfersize = srb->request_bufflen/len;
}
if (!srb->transfersize) {
srb->transfersize = 2048; /* A guess */
US_DEBUGP("handle_read10: transfersize 0, forcing %d\n",
srb->transfersize);
}
len = (65535/srb->transfersize) * srb->transfersize;
US_DEBUGP("Max read is %d bytes\n", len);
......@@ -734,7 +743,7 @@ int usbat_handle_read10(struct us_data *us,
if (len - amount >=
sg[sg_segment].length-sg_offset) {
memcpy(page_address(sg[sg_segment].page) +
sg[sg_segment].offset + sg_offset,
sg[sg_sgement].offset + sg_offset,
buffer + amount,
sg[sg_segment].length - sg_offset);
amount +=
......
This diff is collapsed.
/* Driver for USB Mass Storage compliant devices
* Transport Functions Header File
*
* $Id: transport.h,v 1.15 2001/03/17 20:06:23 jrmayfield Exp $
* $Id: transport.h,v 1.18 2002/04/21 02:57:59 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
......@@ -146,11 +146,12 @@ extern int usb_stor_Bulk_reset(struct us_data*);
extern unsigned int usb_stor_transfer_length(Scsi_Cmnd*);
extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
extern void usb_stor_abort_transport(struct us_data*);
extern int usb_stor_transfer_partial(struct us_data*, char*, int);
extern int usb_stor_bulk_msg(struct us_data*, void*, int, unsigned int,
unsigned int*);
extern int usb_stor_control_msg(struct us_data*, unsigned int, u8, u8,
u16, u16, void*, u16);
extern int usb_stor_clear_halt(struct us_data*, int );
extern void usb_stor_transfer(Scsi_Cmnd*, struct us_data*);
extern int usb_stor_clear_halt(struct usb_device*, int );
#endif
/* Driver for USB Mass Storage compliant devices
* Ununsual Devices File
*
* $Id: unusual_devs.h,v 1.25 2002/01/13 06:39:17 mdharm Exp $
* $Id: unusual_devs.h,v 1.32 2002/02/25 02:41:24 mdharm Exp $
*
* Current development and maintenance by:
* (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 2000-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Initial work by:
* (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
......@@ -110,6 +110,13 @@ UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200,
"LS-120 Camera",
US_SC_UFI, US_PR_CBI, NULL, 0),
/* Reported by Peter Wchtler <pwaechtler@loewe-komp.de> */
UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074,
"ScanLogic",
"SL11R-IDE 0049SQFP-1.2 A002",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
/* Most of the following entries were developed with the help of
* Shuttle/SCM directly.
*/
......@@ -198,7 +205,7 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0422,
"Sony",
"DSC-S30/S70/S75/505V/F505",
"DSC-S30/S70/S75/505V/F505/F707",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
......@@ -289,9 +296,36 @@ UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
"Lexar",
"Jumpshot USB CF Reader",
US_SC_SCSI, US_PR_JUMPSHOT, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP ),
US_FL_MODE_XLATE ),
#endif
/* Reported by Carlos Villegas <cav@uniscope.co.jp>
* This device needs an INQUIRY of exactly 36-bytes to function.
* That is the only reason this entry is needed.
*/
UNUSUAL_DEV( 0x05e3, 0x0700, 0x0000, 0xffff,
"SIIG",
"CompactFlash Card Reader",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
/* Reported by Peter Marks <peter.marks@turner.com>
* Like the SIIG unit above, this unit needs an INQUIRY to ask for exactly
* 36 bytes of data. No more, no less. That is the only reason this entry
* is needed.
*/
UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff,
"EagleTec",
"External Hard Disk",
US_SC_SCSI, US_PR_BULK, 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),
UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100,
"TEAC",
"Floppy Drive",
......@@ -305,6 +339,14 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
US_FL_SINGLE_LUN | US_FL_START_STOP ),
#endif
/* Submitted by kedar@centillium
* Needed for START_STOP flag, but that is unconfirmed */
UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001,
"Minolta",
"Dimage S304",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_START_STOP ),
/* Submitted by f.brugmans@hccnet.nl
* Needed for START_STOP flag */
UNUSUAL_DEV( 0x0686, 0x4007, 0x0001, 0x0001,
......@@ -381,7 +423,7 @@ UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015,
"Datafab",
"MDCFE-B USB CF Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP ),
US_FL_MODE_XLATE ),
/*
* The following Datafab-based devices may or may not work
......@@ -398,38 +440,38 @@ UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
"SIIG/Datafab",
"SIIG/Datafab Memory Stick+CF Reader/Writer",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP ),
US_FL_MODE_XLATE ),
UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
"Datafab/Unknown",
"Datafab-based Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP ),
US_FL_MODE_XLATE ),
UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
"Datafab/Unknown",
"Datafab-based Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP ),
US_FL_MODE_XLATE ),
UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
"PNY/Datafab",
"PNY/Datafab CF+SM Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP ),
US_FL_MODE_XLATE ),
UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
"Simple Tech/Datafab",
"Simple Tech/Datafab CF+SM Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP ),
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 | US_FL_START_STOP ),
US_FL_MODE_XLATE ),
#endif
/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
......@@ -451,6 +493,12 @@ UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001,
US_SC_SCSI, US_PR_CB, NULL,
US_FL_MODE_XLATE ),
UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100,
"IBM",
"IBM USB Memory Key",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
"ATI",
......@@ -459,6 +507,13 @@ 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_START_STOP | US_FL_FIX_INQUIRY ),
/* Submitted by Brian Hall <brihall@bigfoot.com>
* Needed for START_STOP flag */
UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100,
......@@ -469,6 +524,8 @@ UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100,
/* Reported by Dan Pilone <pilone@slac.com>
* The device needs the flags only.
* Also reported by Brian Hall <brihall@bigfoot.com>, again for flags.
* I also suspect this device may have a broken serial number.
*/
UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x9999,
"CCYU TECHNOLOGY",
......
/* Driver for USB Mass Storage compliant devices
*
* $Id: usb.c,v 1.70 2002/01/06 07:14:12 mdharm Exp $
* $Id: usb.c,v 1.75 2002/04/22 03:39:43 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
......@@ -315,6 +315,7 @@ static int usb_stor_control_thread(void * __us)
* so get rid of all our resources..
*/
daemonize();
reparent_to_init();
/* avoid getting signals */
spin_lock_irq(&current->sigmask_lock);
......@@ -409,7 +410,7 @@ static int usb_stor_control_thread(void * __us)
down(&(us->dev_semaphore));
/* our device has gone - pretend not ready */
if (!us->pusb_dev) {
if (atomic_read(&us->sm_state) == US_STATE_DETACHED) {
US_DEBUGP("Request is for removed device\n");
/* For REQUEST_SENSE, it's the data. But
* for anything else, it should look like
......@@ -433,7 +434,7 @@ static int usb_stor_control_thread(void * __us)
sizeof(usb_stor_sense_notready));
us->srb->result = CHECK_CONDITION << 1;
}
} else { /* !us->pusb_dev */
} else { /* atomic_read(&us->sm_state) == STATE_DETACHED */
/* Handle those devices which need us to fake
* their inquiry data */
......@@ -449,7 +450,9 @@ static int usb_stor_control_thread(void * __us)
} else {
/* we've got a command, let's do it! */
US_DEBUG(usb_stor_show_command(us->srb));
atomic_set(&us->sm_state, US_STATE_RUNNING);
us->proto_handler(us->srb, us);
atomic_set(&us->sm_state, US_STATE_IDLE);
}
}
......@@ -713,6 +716,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* establish the connection to the new device upon reconnect */
ss->ifnum = ifnum;
ss->pusb_dev = dev;
atomic_set(&ss->sm_state, US_STATE_IDLE);
/* copy over the endpoint data */
if (ep_in)
......@@ -955,6 +959,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
ss->protocol_name = "Unknown";
kfree(ss->current_urb);
kfree(ss);
usb_dec_dev_use(dev);
return NULL;
break;
}
......@@ -962,6 +967,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* allocate an IRQ callback if one is needed */
if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) {
kfree(ss->current_urb);
kfree(ss);
usb_dec_dev_use(dev);
return NULL;
}
......@@ -990,6 +997,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
unusual_dev->initFunction(ss);
/* start up our control thread */
atomic_set(&ss->sm_state, US_STATE_IDLE);
ss->pid = kernel_thread(usb_stor_control_thread, ss,
CLONE_VM);
if (ss->pid < 0) {
......@@ -1006,7 +1014,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* now register - our detect function will be called */
ss->htmplt.module = THIS_MODULE;
scsi_register_host(&ss->htmplt);
scsi_register_host(&(ss->htmplt));
/* lock access to the data structures */
down(&us_list_semaphore);
......@@ -1066,6 +1074,7 @@ static void storage_disconnect(struct usb_device *dev, void *ptr)
/* mark the device as gone */
usb_dec_dev_use(ss->pusb_dev);
ss->pusb_dev = NULL;
atomic_set(&ss->sm_state, US_STATE_DETACHED);
/* unlock access to the device data structure */
up(&(ss->dev_semaphore));
......@@ -1112,7 +1121,7 @@ void __exit usb_stor_exit(void)
*/
for (next = us_list; next; next = next->next) {
US_DEBUGP("-- calling scsi_unregister_host()\n");
scsi_unregister_host(&next->htmplt);
scsi_unregister_host(&(next->htmplt));
}
/* While there are still structures, free them. Note that we are
......
/* Driver for USB Mass Storage compliant devices
* Main Header File
*
* $Id: usb.h,v 1.18 2001/07/30 00:27:59 mdharm Exp $
* $Id: usb.h,v 1.21 2002/04/21 02:57:59 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
......@@ -102,6 +102,12 @@ struct us_unusual_dev {
#define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */
#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */
#define US_STATE_DETACHED 1 /* State machine states */
#define US_STATE_IDLE 2
#define US_STATE_RUNNING 3
#define US_STATE_RESETTING 4
#define US_STATE_ABORTING 5
#define USB_STOR_STRING_LEN 32
typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
......@@ -152,10 +158,12 @@ struct us_data {
Scsi_Cmnd *queue_srb; /* the single queue slot */
int action; /* what to do */
int pid; /* control thread */
atomic_t sm_state;
/* interrupt info for CBI devices -- only good if attached */
struct semaphore ip_waitq; /* for CBI interrupts */
atomic_t ip_wanted[1]; /* is an IRQ expected? */
unsigned long bitflags; /* single-bit flags: */
#define IP_WANTED 1 /* is an IRQ expected? */
/* interrupt communications data */
struct semaphore irq_urb_sem; /* to protect irq_urb */
......@@ -188,4 +196,5 @@ extern struct usb_driver usb_storage_driver;
/* Function to fill an inquiry response. See usb.c for details */
extern void fill_inquiry_response(struct us_data *us,
unsigned char *data, unsigned int data_len);
#endif
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