patch-2.3.31 linux/drivers/usb/usb_scsi.c
Next file: linux/fs/Config.in
Previous file: linux/drivers/usb/usb-core.c
Back to the patch index
Back to the overall index
- Lines: 2352
- Date:
Tue Dec 7 10:07:45 1999
- Orig file:
v2.3.30/linux/drivers/usb/usb_scsi.c
- Orig date:
Tue Nov 23 22:42:21 1999
diff -u --recursive --new-file v2.3.30/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c
@@ -1,11 +1,12 @@
-
/* Driver for USB SCSI-like devices
*
- * (C) Michael Gee (michael@linuxspecific.com) 1999
+ * (c) 1999 Michael Gee (michael@linuxspecific.com)
+ * (c) 1999 Matthew Dharm (mdharm@one-eyed-alien.net)
*
- * This driver is schizoid - it makes a USB device appear as both a SCSI device
- * and a character device. The latter is only available if the device has an
- * interrupt endpoint, and is used specifically to receive interrupt events.
+ * This driver is schizoid - it makes a USB device appear as both a SCSI
+ * device and a character device. The latter is only available if the device
+ * has an interrupt endpoint, and is used specifically to receive interrupt
+ * events.
*
* In order to support various 'strange' devices, this module supports plug-in
* device-specific filter modules, which can do their own thing when required.
@@ -58,7 +59,7 @@
#ifdef REWRITE_PROJECT
#define IRQ_PERIOD 255
#else
-#define IRQ_PERIOD 0 /* single IRQ transfer then remove it */
+#define IRQ_PERIOD 0 /* single IRQ transfer then remove it */
#endif
/*
@@ -70,38 +71,37 @@
int usbscsi_debug = 1;
struct us_data {
- struct us_data *next; /* next device */
- struct usb_device *pusb_dev;
- struct usb_scsi_filter *filter; /* filter driver */
- void *fdata; /* filter data */
- unsigned int flags; /* from filter initially */
- __u8 ifnum; /* interface number */
- __u8 ep_in; /* in endpoint */
- __u8 ep_out; /* out ....... */
- __u8 ep_int; /* interrupt . */
- __u8 subclass; /* as in overview */
- __u8 protocol; /* .............. */
- __u8 attention_done; /* force attention on first command */
- int (*pop)(Scsi_Cmnd *); /* protocol specific do cmd */
- int (*pop_reset)(struct us_data *); /* ................. device reset */
- GUID(guid); /* unique dev id */
- struct Scsi_Host *host; /* our dummy host data */
- Scsi_Host_Template *htmplt; /* own host template */
- int host_number; /* to find us */
- int host_no; /* allocated by scsi */
- int fixedlength; /* expand commands */
- Scsi_Cmnd *srb; /* current srb */
- int action; /* what to do */
- wait_queue_head_t waitq; /* thread waits */
- wait_queue_head_t ip_waitq; /* for CBI interrupts */
- __u16 ip_data; /* interrupt data */
- int ip_wanted; /* needed */
- int pid; /* control thread */
- struct semaphore *notify; /* wait for thread to begin */
- void *irq_handle; /* for USB interrupt requests */
- unsigned int irqpipe; /* remember pipe for release_irq */
- int mode_xlate; /* if current SCSI command is MODE_6 */
- /* but is translated to MODE_10 for UFI */
+ struct us_data *next; /* next device */
+ struct usb_device *pusb_dev;
+ struct usb_scsi_filter *filter; /* filter driver */
+ void *fdata; /* filter data */
+ unsigned int flags; /* from filter initially */
+ __u8 ifnum; /* interface number */
+ __u8 ep_in; /* in endpoint */
+ __u8 ep_out; /* out ....... */
+ __u8 ep_int; /* interrupt . */
+ __u8 subclass; /* as in overview */
+ __u8 protocol; /* .............. */
+ __u8 attention_done; /* force attn on first cmd */
+ int (*pop)(Scsi_Cmnd *); /* protocol specific do cmd */
+ int (*pop_reset)(struct us_data *); /* ........... device reset */
+ GUID(guid); /* unique dev id */
+ struct Scsi_Host *host; /* our dummy host data */
+ Scsi_Host_Template *htmplt; /* own host template */
+ int host_number; /* to find us */
+ int host_no; /* allocated by scsi */
+ int fixedlength; /* expand commands */
+ Scsi_Cmnd *srb; /* current srb */
+ int action; /* what to do */
+ wait_queue_head_t waitq; /* thread waits */
+ wait_queue_head_t ip_waitq; /* for CBI interrupts */
+ __u16 ip_data; /* interrupt data */
+ int ip_wanted; /* needed */
+ int pid; /* control thread */
+ struct semaphore *notify; /* wait for thread to begin */
+ void *irq_handle; /* for USB int requests */
+ unsigned int irqpipe; /* pipe for release_irq */
+ int mode_xlate; /* trans MODE_6 to _10? */
};
/*
@@ -131,230 +131,230 @@
static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
{
- int max_size = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe)) * 16;
- int this_xfer;
- int result;
- unsigned long partial;
- int maxtry = 100;
- while (length) {
- this_xfer = length > max_size ? max_size : length;
- length -= this_xfer;
- do {
- /* US_DEBUGP("Bulk xfer %x(%d)\n", (unsigned int)buf, this_xfer); */
- result = usb_bulk_msg(us->pusb_dev, pipe, buf,
- this_xfer, &partial, HZ*5);
-
- if (result != 0 || partial != this_xfer)
- US_DEBUGP("bulk_msg returned %d xferred %lu/%d\n",
- result, partial, this_xfer);
-
- if (result == USB_ST_STALL) {
- US_DEBUGP("clearing endpoint halt for pipe %x\n", pipe);
- usb_clear_halt(us->pusb_dev,
- usb_pipeendpoint(pipe) | (pipe & USB_DIR_IN));
- }
-
- /* we want to retry if the device reported NAK */
- if (result == USB_ST_TIMEOUT) {
- if (partial != this_xfer) {
- return 0; /* I do not like this */
- }
- if (!maxtry--)
- break;
- this_xfer -= partial;
- buf += partial;
- } else if (!result && partial != this_xfer) {
- /* short data - assume end */
- result = USB_ST_DATAUNDERRUN;
- break;
- } else if (result == USB_ST_STALL && us->protocol == US_PR_CB) {
- if (!maxtry--)
- break;
- this_xfer -= partial;
- buf += partial;
- } else
- break;
- } while ( this_xfer );
- if (result)
- return result;
- buf += this_xfer;
- }
+ int max_size = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe)) * 16;
+ int this_xfer;
+ int result;
+ unsigned long partial;
+ int maxtry = 100;
+ while (length) {
+ this_xfer = length > max_size ? max_size : length;
+ length -= this_xfer;
+ do {
+ US_DEBUGP("Bulk xfer %x(%d)\n", (unsigned int)buf, this_xfer);
+ result = usb_bulk_msg(us->pusb_dev, pipe, buf,
+ this_xfer, &partial, HZ*5);
+
+ if (result != 0 || partial != this_xfer)
+ US_DEBUGP("bulk_msg returned %d xferred %lu/%d\n",
+ result, partial, this_xfer);
+
+ if (result == USB_ST_STALL) {
+ US_DEBUGP("clearing endpoint halt for pipe %x\n", pipe);
+ usb_clear_halt(us->pusb_dev,
+ usb_pipeendpoint(pipe) | (pipe & USB_DIR_IN));
+ }
- return 0;
+ /* we want to retry if the device reported NAK */
+ if (result == USB_ST_TIMEOUT) {
+ if (partial != this_xfer) {
+ return 0; /* I do not like this */
+ }
+ if (!maxtry--)
+ break;
+ this_xfer -= partial;
+ buf += partial;
+ } else if (!result && partial != this_xfer) {
+ /* short data - assume end */
+ result = USB_ST_DATAUNDERRUN;
+ break;
+ } else if (result == USB_ST_STALL && us->protocol == US_PR_CB) {
+ if (!maxtry--)
+ break;
+ this_xfer -= partial;
+ buf += partial;
+ } else
+ break;
+ } while ( this_xfer );
+ if (result)
+ return result;
+ buf += this_xfer;
+ }
+
+ return 0;
}
static int us_transfer(Scsi_Cmnd *srb, int dir_in)
{
- struct us_data *us = (struct us_data *)srb->host_scribble;
- int i;
- int result = -1;
- unsigned int pipe = dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) :
- usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- if (srb->use_sg) {
- struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
-
- for (i = 0; i < srb->use_sg; i++) {
- result = us_one_transfer(us, pipe, sg[i].address, sg[i].length);
- if (result)
- break;
+ struct us_data *us = (struct us_data *)srb->host_scribble;
+ int i;
+ int result = -1;
+ unsigned int pipe = dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) :
+ usb_sndbulkpipe(us->pusb_dev, us->ep_out);
+
+ if (srb->use_sg) {
+ struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
+
+ for (i = 0; i < srb->use_sg; i++) {
+ result = us_one_transfer(us, pipe, sg[i].address, sg[i].length);
+ if (result)
+ break;
+ }
}
- }
- else
- result = us_one_transfer(us, pipe,
- srb->request_buffer, srb->request_bufflen);
-
- if (result)
- US_DEBUGP("us_transfer returning error %d\n", result);
- return result;
+ else
+ result = us_one_transfer(us, pipe,
+ srb->request_buffer, srb->request_bufflen);
+
+ if (result)
+ US_DEBUGP("us_transfer returning error %d\n", result);
+ return result;
}
static unsigned int us_transfer_length(Scsi_Cmnd *srb)
{
- int i;
- unsigned int total = 0;
+ int i;
+ unsigned int total = 0;
- /* always zero for some commands */
- switch (srb->cmnd[0]) {
- case SEEK_6:
- case SEEK_10:
- case REZERO_UNIT:
- case ALLOW_MEDIUM_REMOVAL:
- case START_STOP:
- case TEST_UNIT_READY:
- return 0;
+ /* always zero for some commands */
+ switch (srb->cmnd[0]) {
+ case SEEK_6:
+ case SEEK_10:
+ case REZERO_UNIT:
+ case ALLOW_MEDIUM_REMOVAL:
+ case START_STOP:
+ case TEST_UNIT_READY:
+ return 0;
+
+ default:
+ break;
+ }
+
+ if (srb->use_sg) {
+ struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
- default:
- break;
- }
-
- if (srb->use_sg) {
- struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
-
- for (i = 0; i < srb->use_sg; i++) {
- total += sg[i].length;
- }
- return total;
- }
- else
- return srb->request_bufflen;
+ for (i = 0; i < srb->use_sg; i++) {
+ total += sg[i].length;
+ }
+ return total;
+ }
+ else
+ return srb->request_bufflen;
}
static int pop_CBI_irq(int state, void *buffer, int len, void *dev_id)
{
- struct us_data *us = (struct us_data *)dev_id;
+ struct us_data *us = (struct us_data *)dev_id;
- if (state != USB_ST_REMOVED) {
- us->ip_data = le16_to_cpup((__u16 *)buffer);
- /* US_DEBUGP("Interrupt Status %x\n", us->ip_data); */
- }
- if (us->ip_wanted) {
- us->ip_wanted = 0;
- wake_up(&us->ip_waitq);
- }
+ if (state != USB_ST_REMOVED) {
+ us->ip_data = le16_to_cpup((__u16 *)buffer);
+ /* US_DEBUGP("Interrupt Status %x\n", us->ip_data); */
+ }
+ if (us->ip_wanted) {
+ us->ip_wanted = 0;
+ wake_up(&us->ip_waitq);
+ }
- /* we don't want another interrupt */
- return 0;
+ /* we don't want another interrupt */
+ return 0;
}
static int pop_CB_reset(struct us_data *us)
{
- unsigned char cmd[12];
- int result;
+ unsigned char cmd[12];
+ int result;
- US_DEBUGP("pop_CB_reset\n");
+ US_DEBUGP("pop_CB_reset\n");
- memset(cmd, -1, sizeof(cmd));
- cmd[0] = SEND_DIAGNOSTIC;
- cmd[1] = 4;
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
- 0, us->ifnum, cmd, sizeof(cmd), HZ*5);
+ memset(cmd, -1, sizeof(cmd));
+ cmd[0] = SEND_DIAGNOSTIC;
+ cmd[1] = 4;
+ result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+ US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ 0, us->ifnum, cmd, sizeof(cmd), HZ*5);
- /* long wait for reset */
+ /* long wait for reset */
- schedule_timeout(HZ*6);
+ schedule_timeout(HZ*6);
- US_DEBUGP("pop_CB_reset: clearing endpoint halt\n");
- usb_clear_halt(us->pusb_dev, us->ep_in | USB_DIR_IN);
- usb_clear_halt(us->pusb_dev, us->ep_out | USB_DIR_OUT);
+ US_DEBUGP("pop_CB_reset: clearing endpoint halt\n");
+ usb_clear_halt(us->pusb_dev, us->ep_in | USB_DIR_IN);
+ usb_clear_halt(us->pusb_dev, us->ep_out | USB_DIR_OUT);
- US_DEBUGP("pop_CB_reset done\n");
- return 0;
+ US_DEBUGP("pop_CB_reset done\n");
+ return 0;
}
static int pop_CB_command(Scsi_Cmnd *srb)
{
- struct us_data *us = (struct us_data *)srb->host_scribble;
- unsigned char cmd[16];
- int result;
- int retry = 5;
- int done_start = 0;
+ struct us_data *us = (struct us_data *)srb->host_scribble;
+ unsigned char cmd[16];
+ int result;
+ int retry = 5;
+ int done_start = 0;
- while (retry--) {
+ while (retry--) {
- if (us->flags & US_FL_FIXED_COMMAND) {
- memset(cmd, 0, us->fixedlength);
+ if (us->flags & US_FL_FIXED_COMMAND) {
+ memset(cmd, 0, us->fixedlength);
- /* fix some commands */
+ /* fix some commands */
- switch (srb->cmnd[0]) {
- case WRITE_6:
- case READ_6:
- cmd[0] = srb->cmnd[0] | 0x20;
- cmd[1] = srb->cmnd[1] & 0xE0;
- cmd[2] = 0;
- cmd[3] = srb->cmnd[1] & 0x1F;
- cmd[4] = srb->cmnd[2];
- cmd[5] = srb->cmnd[3];
- cmd[8] = srb->cmnd[4];
- break;
+ switch (srb->cmnd[0]) {
+ case WRITE_6:
+ case READ_6:
+ cmd[0] = srb->cmnd[0] | 0x20;
+ cmd[1] = srb->cmnd[1] & 0xE0;
+ cmd[2] = 0;
+ cmd[3] = srb->cmnd[1] & 0x1F;
+ cmd[4] = srb->cmnd[2];
+ cmd[5] = srb->cmnd[3];
+ cmd[8] = srb->cmnd[4];
+ break;
- case MODE_SENSE:
- case MODE_SELECT:
- us->mode_xlate = (srb->cmnd[0] == MODE_SENSE);
- cmd[0] = srb->cmnd[0] | 0x40;
- cmd[1] = srb->cmnd[1];
- cmd[2] = srb->cmnd[2];
- cmd[8] = srb->cmnd[4];
- break;
+ case MODE_SENSE:
+ case MODE_SELECT:
+ us->mode_xlate = (srb->cmnd[0] == MODE_SENSE);
+ cmd[0] = srb->cmnd[0] | 0x40;
+ cmd[1] = srb->cmnd[1];
+ cmd[2] = srb->cmnd[2];
+ cmd[8] = srb->cmnd[4];
+ break;
- default:
- us->mode_xlate = 0;
- memcpy(cmd, srb->cmnd, srb->cmd_len);
- break;
- }
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
- 0, us->ifnum,
- cmd, us->fixedlength, HZ*5);
- if (!done_start && (us->subclass == US_SC_UFI /*|| us->subclass == US_SC_8070*/)
- && cmd[0] == TEST_UNIT_READY && result) {
- /* as per spec try a start command, wait and retry */
-
- done_start++;
- memset(cmd, 0, sizeof(cmd));
- cmd[0] = START_STOP;
- cmd[4] = 1; /* start */
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
- 0, us->ifnum,
- cmd, us->fixedlength, HZ*5);
- wait_ms(100);
- retry++;
- continue;
- }
- } else {
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
- 0, us->ifnum,
- srb->cmnd, srb->cmd_len, HZ*5);
- }
- if (/*result != USB_ST_STALL &&*/ result != USB_ST_TIMEOUT)
- return result;
- }
+ default:
+ us->mode_xlate = 0;
+ memcpy(cmd, srb->cmnd, srb->cmd_len);
+ break;
+ }
+ result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+ US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ 0, us->ifnum,
+ cmd, us->fixedlength, HZ*5);
+ if (!done_start && (us->subclass == US_SC_UFI /*|| us->subclass == US_SC_8070*/)
+ && cmd[0] == TEST_UNIT_READY && result) {
+ /* as per spec try a start command, wait and retry */
+
+ done_start++;
+ memset(cmd, 0, sizeof(cmd));
+ cmd[0] = START_STOP;
+ cmd[4] = 1; /* start */
+ result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+ US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ 0, us->ifnum,
+ cmd, us->fixedlength, HZ*5);
+ wait_ms(100);
+ retry++;
+ continue;
+ }
+ } else {
+ result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+ US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ 0, us->ifnum,
+ srb->cmnd, srb->cmd_len, HZ*5);
+ }
+ if (/*result != USB_ST_STALL &&*/ result != USB_ST_TIMEOUT)
+ return result;
+ }
- return result;
+ return result;
}
/*
@@ -363,237 +363,237 @@
static int pop_CB_status(Scsi_Cmnd *srb)
{
- struct us_data *us = (struct us_data *)srb->host_scribble;
- int result;
- __u8 status[2];
- int retry = 5;
-
- US_DEBUGP("pop_CB_status, proto=%x\n", us->protocol);
- switch (us->protocol) {
- case US_PR_CB:
- /* get from control */
-
- while (retry--) {
- result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_TYPE_STANDARD | USB_RT_DEVICE,
- 0, us->ifnum,
- status, sizeof(status), HZ*5);
- if (result != USB_ST_TIMEOUT)
+ struct us_data *us = (struct us_data *)srb->host_scribble;
+ int result;
+ __u8 status[2];
+ int retry = 5;
+
+ US_DEBUGP("pop_CB_status, proto=%x\n", us->protocol);
+ switch (us->protocol) {
+ case US_PR_CB:
+ /* get from control */
+
+ while (retry--) {
+ result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_TYPE_STANDARD | USB_RT_DEVICE,
+ 0, us->ifnum,
+ status, sizeof(status), HZ*5);
+ if (result != USB_ST_TIMEOUT)
+ break;
+ }
+ if (result) {
+ US_DEBUGP("Bad AP status request %d\n", result);
+ return DID_ABORT << 16;
+ }
+ US_DEBUGP("Got AP status %x %x\n", status[0], status[1]);
+ if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY &&
+ ( (status[0] & ~3) || status[1]))
+ return (DID_OK << 16) | 2;
+ else
+ return DID_OK << 16;
break;
- }
- if (result) {
- US_DEBUGP("Bad AP status request %d\n", result);
- return DID_ABORT << 16;
- }
- US_DEBUGP("Got AP status %x %x\n", status[0], status[1]);
- if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY &&
- ( (status[0] & ~3) || status[1]))
- return (DID_OK << 16) | 2;
- else
- return DID_OK << 16;
- break;
- case US_PR_CBI:
- /* get from interrupt pipe */
+ case US_PR_CBI:
+ /* get from interrupt pipe */
- /* add interrupt transfer, marked for removal */
- us->ip_wanted = 1;
- us->irqpipe = usb_rcvintpipe(us->pusb_dev, us->ep_int);
- result = usb_request_irq(us->pusb_dev, us->irqpipe, pop_CBI_irq,
- IRQ_PERIOD, (void *)us, &us->irq_handle);
- if (result) {
- US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n",
- result);
- return DID_ABORT << 16;
- }
+ /* add interrupt transfer, marked for removal */
+ us->ip_wanted = 1;
+ us->irqpipe = usb_rcvintpipe(us->pusb_dev, us->ep_int);
+ result = usb_request_irq(us->pusb_dev, us->irqpipe, pop_CBI_irq,
+ IRQ_PERIOD, (void *)us, &us->irq_handle);
+ if (result) {
+ US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n",
+ result);
+ return DID_ABORT << 16;
+ }
- sleep_on(&us->ip_waitq);
+ sleep_on(&us->ip_waitq);
#ifdef REWRITE_PROJECT
- usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe);
- us->irq_handle = NULL;
+ usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe);
+ us->irq_handle = NULL;
#endif
- if (us->ip_wanted) {
- US_DEBUGP("Did not get interrupt on CBI\n");
- us->ip_wanted = 0;
- return DID_ABORT << 16;
- }
+ if (us->ip_wanted) {
+ US_DEBUGP("Did not get interrupt on CBI\n");
+ us->ip_wanted = 0;
+ return DID_ABORT << 16;
+ }
- US_DEBUGP("Got interrupt data %x\n", us->ip_data);
+ US_DEBUGP("Got interrupt data %x\n", us->ip_data);
- /* sort out what it means */
+ /* sort out what it means */
- if (us->subclass == US_SC_UFI) {
- /* gives us asc and ascq, as per request sense */
+ if (us->subclass == US_SC_UFI) {
+ /* gives us asc and ascq, as per request sense */
- if (srb->cmnd[0] == REQUEST_SENSE ||
- srb->cmnd[0] == INQUIRY)
- return DID_OK << 16;
- else
- return (DID_OK << 16) + ((us->ip_data & 0xff) ? 2 : 0);
+ if (srb->cmnd[0] == REQUEST_SENSE ||
+ srb->cmnd[0] == INQUIRY)
+ return DID_OK << 16;
+ else
+ return (DID_OK << 16) + ((us->ip_data & 0xff) ? 2 : 0);
+ }
+ if (us->ip_data & 0xff) {
+ US_DEBUGP("Bad CBI interrupt data %x\n", us->ip_data);
+ return DID_ABORT << 16;
+ }
+ return (DID_OK << 16) + ((us->ip_data & 0x300) ? 2 : 0);
}
- if (us->ip_data & 0xff) {
- US_DEBUGP("Bad CBI interrupt data %x\n", us->ip_data);
- return DID_ABORT << 16;
- }
- return (DID_OK << 16) + ((us->ip_data & 0x300) ? 2 : 0);
- }
- return DID_ERROR << 16;
+ return DID_ERROR << 16;
}
/* Protocol command handlers */
static int pop_CBI(Scsi_Cmnd *srb)
{
- int result;
+ int result;
- /* run the command */
+ /* run the command */
- if ((result = pop_CB_command(srb))) {
- US_DEBUGP("CBI command %x\n", result);
- if (result == USB_ST_STALL || result == USB_ST_TIMEOUT) {
- return (DID_OK << 16) | 2;
+ if ((result = pop_CB_command(srb))) {
+ US_DEBUGP("CBI command %x\n", result);
+ if (result == USB_ST_STALL || result == USB_ST_TIMEOUT) {
+ return (DID_OK << 16) | 2;
+ }
+ return DID_ERROR << 16;
}
- return DID_ERROR << 16;
- }
- /* transfer the data */
+ /* transfer the data */
- if (us_transfer_length(srb)) {
- result = us_transfer(srb, US_DIRECTION(srb->cmnd[0]));
- if (result && result != USB_ST_DATAUNDERRUN && result != USB_ST_STALL) {
- US_DEBUGP("CBI transfer %x\n", result);
- return DID_ERROR << 16;
- }
+ if (us_transfer_length(srb)) {
+ result = us_transfer(srb, US_DIRECTION(srb->cmnd[0]));
+ if (result && result != USB_ST_DATAUNDERRUN && result != USB_ST_STALL) {
+ US_DEBUGP("CBI transfer %x\n", result);
+ return DID_ERROR << 16;
+ }
#if 0
- else if (result == USB_ST_DATAUNDERRUN) {
- return DID_OK << 16;
- }
- } else {
- if (!result) {
- return DID_OK << 16;
- }
+ else if (result == USB_ST_DATAUNDERRUN) {
+ return DID_OK << 16;
+ }
+ } else {
+ if (!result) {
+ return DID_OK << 16;
+ }
#endif
- }
+ }
- /* get status */
- return pop_CB_status(srb);
+ /* get status */
+ return pop_CB_status(srb);
}
static int pop_Bulk_reset(struct us_data *us)
{
- int result;
+ int result;
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_BULK_RESET, USB_TYPE_CLASS | USB_RT_INTERFACE,
- US_BULK_RESET_HARD, us->ifnum,
- NULL, 0, HZ*5);
- if (result)
- US_DEBUGP("Bulk hard reset failed %d\n", result);
- usb_clear_halt(us->pusb_dev, us->ep_in | USB_DIR_IN);
- usb_clear_halt(us->pusb_dev, us->ep_out | USB_DIR_OUT);
+ result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+ US_BULK_RESET, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ US_BULK_RESET_HARD, us->ifnum,
+ NULL, 0, HZ*5);
+ if (result)
+ US_DEBUGP("Bulk hard reset failed %d\n", result);
+ usb_clear_halt(us->pusb_dev, us->ep_in | USB_DIR_IN);
+ usb_clear_halt(us->pusb_dev, us->ep_out | USB_DIR_OUT);
- /* long wait for reset */
+ /* long wait for reset */
- schedule_timeout(HZ*6);
+ schedule_timeout(HZ*6);
- return result;
+ return result;
}
/*
* The bulk only protocol handler.
- * Uses the in and out endpoints to transfer commands and data (nasty)
+ * Uses the in and out endpoints to transfer commands and data (nasty)
*/
static int pop_Bulk(Scsi_Cmnd *srb)
{
- struct us_data *us = (struct us_data *)srb->host_scribble;
- struct bulk_cb_wrap bcb;
- struct bulk_cs_wrap bcs;
- int result;
- unsigned long partial;
- int stall;
-
- /* set up the command wrapper */
-
- bcb.Signature = US_BULK_CB_SIGN;
- bcb.DataTransferLength = us_transfer_length(srb);;
- bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7;
- bcb.Tag = srb->serial_number;
- bcb.Lun = 0;
- memset(bcb.CDB, 0, sizeof(bcb.CDB));
- memcpy(bcb.CDB, srb->cmnd, srb->cmd_len);
- if (us->flags & US_FL_FIXED_COMMAND) {
- bcb.Length = us->fixedlength;
- } else {
- bcb.Length = srb->cmd_len;
- }
-
- /* send it to out endpoint */
-
- US_DEBUGP("Bulk command S %x T %x L %d F %d CL %d\n",
- bcb.Signature, bcb.Tag, bcb.DataTransferLength,
- bcb.Flags, bcb.Length);
- result = usb_bulk_msg(us->pusb_dev,
- usb_sndbulkpipe(us->pusb_dev, us->ep_out), &bcb,
- US_BULK_CB_WRAP_LEN, &partial, HZ*5);
- if (result) {
- US_DEBUGP("Bulk command result %x\n", result);
- return DID_ABORT << 16;
- }
-
- //return DID_BAD_TARGET << 16;
- /* send/receive data */
-
- if (bcb.DataTransferLength) {
- result = us_transfer(srb, bcb.Flags);
- if (result && result != USB_ST_DATAUNDERRUN && result != USB_ST_STALL) {
- US_DEBUGP("Bulk transfer result %x\n", result);
- return DID_ABORT << 16;
+ struct us_data *us = (struct us_data *)srb->host_scribble;
+ struct bulk_cb_wrap bcb;
+ struct bulk_cs_wrap bcs;
+ int result;
+ unsigned long partial;
+ int stall;
+
+ /* set up the command wrapper */
+
+ bcb.Signature = US_BULK_CB_SIGN;
+ bcb.DataTransferLength = us_transfer_length(srb);;
+ bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7;
+ bcb.Tag = srb->serial_number;
+ bcb.Lun = 0;
+ memset(bcb.CDB, 0, sizeof(bcb.CDB));
+ memcpy(bcb.CDB, srb->cmnd, srb->cmd_len);
+ if (us->flags & US_FL_FIXED_COMMAND) {
+ bcb.Length = us->fixedlength;
+ } else {
+ bcb.Length = srb->cmd_len;
}
- }
- /* get status */
+ /* send it to out endpoint */
- stall = 0;
- do {
+ US_DEBUGP("Bulk command S %x T %x L %d F %d CL %d\n",
+ bcb.Signature, bcb.Tag, bcb.DataTransferLength,
+ bcb.Flags, bcb.Length);
result = usb_bulk_msg(us->pusb_dev,
- usb_rcvbulkpipe(us->pusb_dev, us->ep_in), &bcs,
- US_BULK_CS_WRAP_LEN, &partial, HZ*5);
- if (result == USB_ST_STALL || result == USB_ST_TIMEOUT)
- stall++;
- else
- break;
- } while ( stall < 3);
- if (result && result != USB_ST_DATAUNDERRUN) {
- US_DEBUGP("Bulk status result = %x\n", result);
- return DID_ABORT << 16;
- }
-
- /* check bulk status */
-
- US_DEBUGP("Bulk status S %x T %x R %d V %x\n",
- bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status);
- if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag ||
- bcs.Status > US_BULK_STAT_PHASE) {
- US_DEBUGP("Bulk logical error\n");
- return DID_ABORT << 16;
- }
- switch (bcs.Status) {
- case US_BULK_STAT_OK:
- return DID_OK << 16;
-
- case US_BULK_STAT_FAIL:
- /* check for underrun - dont report */
- if (bcs.Residue)
- return DID_OK << 16;
- //pop_Bulk_reset(us);
- break;
+ usb_sndbulkpipe(us->pusb_dev, us->ep_out), &bcb,
+ US_BULK_CB_WRAP_LEN, &partial, HZ*5);
+ if (result) {
+ US_DEBUGP("Bulk command result %x\n", result);
+ return DID_ABORT << 16;
+ }
- case US_BULK_STAT_PHASE:
- return DID_ERROR << 16;
- }
+ //return DID_BAD_TARGET << 16;
+ /* send/receive data */
+
+ if (bcb.DataTransferLength) {
+ result = us_transfer(srb, bcb.Flags);
+ if (result && result != USB_ST_DATAUNDERRUN && result != USB_ST_STALL) {
+ US_DEBUGP("Bulk transfer result %x\n", result);
+ return DID_ABORT << 16;
+ }
+ }
+
+ /* get status */
+
+ stall = 0;
+ do {
+ result = usb_bulk_msg(us->pusb_dev,
+ usb_rcvbulkpipe(us->pusb_dev, us->ep_in), &bcs,
+ US_BULK_CS_WRAP_LEN, &partial, HZ*5);
+ if (result == USB_ST_STALL || result == USB_ST_TIMEOUT)
+ stall++;
+ else
+ break;
+ } while ( stall < 3);
+ if (result && result != USB_ST_DATAUNDERRUN) {
+ US_DEBUGP("Bulk status result = %x\n", result);
+ return DID_ABORT << 16;
+ }
+
+ /* check bulk status */
+
+ US_DEBUGP("Bulk status S %x T %x R %d V %x\n",
+ bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status);
+ if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag ||
+ bcs.Status > US_BULK_STAT_PHASE) {
+ US_DEBUGP("Bulk logical error\n");
+ return DID_ABORT << 16;
+ }
+ switch (bcs.Status) {
+ case US_BULK_STAT_OK:
+ return DID_OK << 16;
+
+ case US_BULK_STAT_FAIL:
+ /* check for underrun - dont report */
+ if (bcs.Residue)
+ return DID_OK << 16;
+ //pop_Bulk_reset(us);
+ break;
+
+ case US_BULK_STAT_PHASE:
+ return DID_ERROR << 16;
+ }
- return (DID_OK << 16) | 2; /* check sense required */
+ return (DID_OK << 16) | 2; /* check sense required */
}
/* Host functions */
@@ -601,25 +601,25 @@
/* detect adapter (always true ) */
static int us_detect(struct SHT *sht)
{
- /* FIXME - not nice at all, but how else ? */
- struct us_data *us = (struct us_data *)sht->proc_dir;
- char name[32];
-
- sprintf(name, "usbscsi%d", us->host_number);
- sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL);
- if (!sht->proc_name)
+ /* FIXME - not nice at all, but how else ? */
+ struct us_data *us = (struct us_data *)sht->proc_dir;
+ char name[32];
+
+ sprintf(name, "usbscsi%d", us->host_number);
+ sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL);
+ if (!sht->proc_name)
+ return 0;
+ strcpy(sht->proc_name, name);
+ sht->proc_dir = NULL;
+ us->host = scsi_register(sht, sizeof(us));
+ if (us->host) {
+ us->host->hostdata[0] = (unsigned long)us;
+ us->host_no = us->host->host_no;
+ return 1;
+ }
+ kfree(sht->proc_name);
+ sht->proc_name = sht->name = NULL;
return 0;
- strcpy(sht->proc_name, name);
- sht->proc_dir = NULL;
- us->host = scsi_register(sht, sizeof(us));
- if (us->host) {
- us->host->hostdata[0] = (unsigned long)us;
- us->host_no = us->host->host_no;
- return 1;
- }
- kfree(sht->proc_name);
- sht->proc_name = sht->name = NULL;
- return 0;
}
/* release - must be here to stop scsi
@@ -628,71 +628,71 @@
*/
static int us_release(struct Scsi_Host *psh)
{
- struct us_data *us = (struct us_data *)psh->hostdata[0];
- struct us_data *prev = (struct us_data *)&us_list;
+ struct us_data *us = (struct us_data *)psh->hostdata[0];
+ struct us_data *prev = (struct us_data *)&us_list;
- if (us->irq_handle) {
- usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe);
- us->irq_handle = NULL;
- }
- if (us->filter)
- us->filter->release(us->fdata);
- if (us->pusb_dev)
- usb_deregister(&scsi_driver);
-
- /* FIXME - leaves hanging host template copy */
- /* (because scsi layer uses it after removal !!!) */
- while (prev->next != us)
- prev = prev->next;
- prev->next = us->next;
- return 0;
+ if (us->irq_handle) {
+ usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe);
+ us->irq_handle = NULL;
+ }
+ if (us->filter)
+ us->filter->release(us->fdata);
+ if (us->pusb_dev)
+ usb_deregister(&scsi_driver);
+
+ /* FIXME - leaves hanging host template copy */
+ /* (because scsi layer uses it after removal !!!) */
+ while (prev->next != us)
+ prev = prev->next;
+ prev->next = us->next;
+ return 0;
}
/* run command */
static int us_command( Scsi_Cmnd *srb )
{
- US_DEBUGP("Bad use of us_command\n");
+ US_DEBUGP("Bad use of us_command\n");
- return DID_BAD_TARGET << 16;
+ return DID_BAD_TARGET << 16;
}
/* run command */
static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
{
- struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+ struct us_data *us = (struct us_data *)srb->host->hostdata[0];
- US_DEBUGP("Command wakeup\n");
- if (us->srb) {
- /* busy */
- }
- srb->host_scribble = (unsigned char *)us;
- us->srb = srb;
- srb->scsi_done = done;
- us->action = US_ACT_COMMAND;
+ US_DEBUGP("Command wakeup\n");
+ if (us->srb) {
+ /* busy */
+ }
+ srb->host_scribble = (unsigned char *)us;
+ us->srb = srb;
+ srb->scsi_done = done;
+ us->action = US_ACT_COMMAND;
- /* wake up the process task */
+ /* wake up the process task */
- wake_up_interruptible(&us->waitq);
+ wake_up_interruptible(&us->waitq);
- return 0;
+ return 0;
}
static int us_abort( Scsi_Cmnd *srb )
{
- return 0;
+ return 0;
}
static int us_bus_reset( Scsi_Cmnd *srb )
{
- struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+ struct us_data *us = (struct us_data *)srb->host->hostdata[0];
- us->pop_reset(us);
- return SUCCESS;
+ us->pop_reset(us);
+ return SUCCESS;
}
static int us_host_reset( Scsi_Cmnd *srb )
{
- return 0;
+ return 0;
}
#undef SPRINTF
@@ -700,62 +700,62 @@
int usb_scsi_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout)
{
- struct us_data *us = us_list;
- char *pos = buffer;
- char *vendor;
- char *product;
- char *style = "";
-
- /* find our data from hostno */
-
- while (us) {
- if (us->host_no == hostno)
- break;
- us = us->next;
- }
-
- if (!us)
- return -ESRCH;
-
- /* null on outward */
-
- if (inout)
- return length;
-
- if (!us->pusb_dev || !(vendor = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer)))
- vendor = "?";
- if (!us->pusb_dev || !(product = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct)))
- product = "?";
-
- switch (us->protocol) {
- case US_PR_CB:
- style = "Control/Bulk";
- break;
-
- case US_PR_CBI:
- style = "Control/Bulk/Interrupt";
- break;
-
- case US_PR_ZIP:
- style = "Bulk only";
- break;
-
- }
- SPRINTF ("Host scsi%d: usb-scsi\n", hostno);
- SPRINTF ("Device: %s %s - GUID " GUID_FORMAT "\n", vendor, product, GUID_ARGS(us->guid) );
- SPRINTF ("Style: %s\n", style);
-
- /*
- * Calculate start of next buffer, and return value.
- */
- *start = buffer + offset;
-
- if ((pos - buffer) < offset)
- return (0);
- else if ((pos - buffer - offset) < length)
- return (pos - buffer - offset);
- else
- return (length);
+ struct us_data *us = us_list;
+ char *pos = buffer;
+ char *vendor;
+ char *product;
+ char *style = "";
+
+ /* find our data from hostno */
+
+ while (us) {
+ if (us->host_no == hostno)
+ break;
+ us = us->next;
+ }
+
+ if (!us)
+ return -ESRCH;
+
+ /* null on outward */
+
+ if (inout)
+ return length;
+
+ if (!us->pusb_dev || !(vendor = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer)))
+ vendor = "?";
+ if (!us->pusb_dev || !(product = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct)))
+ product = "?";
+
+ switch (us->protocol) {
+ case US_PR_CB:
+ style = "Control/Bulk";
+ break;
+
+ case US_PR_CBI:
+ style = "Control/Bulk/Interrupt";
+ break;
+
+ case US_PR_ZIP:
+ style = "Bulk only";
+ break;
+
+ }
+ SPRINTF ("Host scsi%d: usb-scsi\n", hostno);
+ SPRINTF ("Device: %s %s - GUID " GUID_FORMAT "\n", vendor, product, GUID_ARGS(us->guid) );
+ SPRINTF ("Style: %s\n", style);
+
+ /*
+ * Calculate start of next buffer, and return value.
+ */
+ *start = buffer + offset;
+
+ if ((pos - buffer) < offset)
+ return (0);
+ else if ((pos - buffer - offset) < length)
+ return (pos - buffer - offset);
+ else
+ return (length);
}
/*
@@ -763,599 +763,599 @@
*/
static Scsi_Host_Template my_host_template = {
- NULL, /* next */
- NULL, /* module */
- NULL, /* proc_dir */
- usb_scsi_proc_info,
- NULL, /* name - points to unique */
- us_detect,
- us_release,
- NULL, /* info */
- NULL, /* ioctl */
- us_command,
- us_queuecommand,
- NULL, /* eh_strategy */
- us_abort,
- us_bus_reset,
- us_bus_reset,
- us_host_reset,
- NULL, /* abort */
- NULL, /* reset */
- NULL, /* slave_attach */
- NULL, /* bios_param */
- 1, /* can_queue */
- -1, /* this_id */
- SG_ALL, /* sg_tablesize */
- 1, /* cmd_per_lun */
- 0, /* present */
- FALSE, /* unchecked_isa_dma */
- FALSE, /* use_clustering */
- TRUE, /* use_new_eh_code */
- TRUE /* emulated */
+ NULL, /* next */
+ NULL, /* module */
+ NULL, /* proc_dir */
+ usb_scsi_proc_info,
+ NULL, /* name - points to unique */
+ us_detect,
+ us_release,
+ NULL, /* info */
+ NULL, /* ioctl */
+ us_command,
+ us_queuecommand,
+ NULL, /* eh_strategy */
+ us_abort,
+ us_bus_reset,
+ us_bus_reset,
+ us_host_reset,
+ NULL, /* abort */
+ NULL, /* reset */
+ NULL, /* slave_attach */
+ NULL, /* bios_param */
+ 1, /* can_queue */
+ -1, /* this_id */
+ SG_ALL, /* sg_tablesize */
+ 1, /* cmd_per_lun */
+ 0, /* present */
+ FALSE, /* unchecked_isa_dma */
+ FALSE, /* use_clustering */
+ TRUE, /* use_new_eh_code */
+ TRUE /* emulated */
};
static unsigned char sense_notready[] = {
- 0x70, /* current error */
- 0x00,
- 0x02, /* not ready */
- 0x00,
- 0x00,
- 10, /* additional length */
- 0x00,
- 0x00,
- 0x00,
- 0x00,
- 0x04, /* not ready */
- 0x03, /* manual intervention */
- 0x00,
- 0x00,
- 0x00,
- 0x00
+ 0x70, /* current error */
+ 0x00,
+ 0x02, /* not ready */
+ 0x00,
+ 0x00,
+ 10, /* additional length */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x04, /* not ready */
+ 0x03, /* manual intervention */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
};
static int usbscsi_control_thread(void * __us)
{
- struct us_data *us = (struct us_data *)__us;
- int action;
+ struct us_data *us = (struct us_data *)__us;
+ int action;
- lock_kernel();
+ lock_kernel();
- /*
- * This thread doesn't need any user-level access,
- * so get rid of all our resources..
- */
- exit_mm(current);
- exit_files(current);
- //exit_fs(current);
-
- sprintf(current->comm, "usbscsi%d", us->host_number);
-
- unlock_kernel();
-
- up(us->notify);
-
- for(;;) {
- siginfo_t info;
- int unsigned long signr;
-
- interruptible_sleep_on(&us->waitq);
-
- action = us->action;
- us->action = 0;
-
- switch (action) {
- case US_ACT_COMMAND:
- if (us->srb->target || us->srb->lun) {
- /* bad device */
- US_DEBUGP( "Bad device number (%d/%d) or dev %x\n",
- us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev);
- us->srb->result = DID_BAD_TARGET << 16;
- } else if (!us->pusb_dev) {
-
- /* our device has gone - pretend not ready */
-
- if (us->srb->cmnd[0] == REQUEST_SENSE) {
- memcpy(us->srb->request_buffer, sense_notready, sizeof(sense_notready));
- us->srb->result = DID_OK << 16;
- } else {
- us->srb->result = (DID_OK << 16) | 2;
- }
- } else {
- US_DEBUG(us_show_command(us->srb));
+ /*
+ * This thread doesn't need any user-level access,
+ * so get rid of all our resources..
+ */
+ exit_mm(current);
+ exit_files(current);
+ //exit_fs(current);
+
+ sprintf(current->comm, "usbscsi%d", us->host_number);
+
+ unlock_kernel();
+
+ up(us->notify);
+
+ for(;;) {
+ siginfo_t info;
+ int unsigned long signr;
+
+ interruptible_sleep_on(&us->waitq);
+
+ action = us->action;
+ us->action = 0;
+
+ switch (action) {
+ case US_ACT_COMMAND:
+ if (us->srb->target || us->srb->lun) {
+ /* bad device */
+ US_DEBUGP( "Bad device number (%d/%d) or dev %x\n",
+ us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev);
+ us->srb->result = DID_BAD_TARGET << 16;
+ } else if (!us->pusb_dev) {
+
+ /* our device has gone - pretend not ready */
+
+ if (us->srb->cmnd[0] == REQUEST_SENSE) {
+ memcpy(us->srb->request_buffer, sense_notready, sizeof(sense_notready));
+ us->srb->result = DID_OK << 16;
+ } else {
+ us->srb->result = (DID_OK << 16) | 2;
+ }
+ } else {
+ US_DEBUG(us_show_command(us->srb));
- /* check for variable length - do properly if so */
+ /* check for variable length - do properly if so */
- if (us->filter && us->filter->command)
- us->srb->result = us->filter->command(us->fdata, us->srb);
- else if (us->srb->cmnd[0] == START_STOP &&
- us->pusb_dev->descriptor.idProduct == 0x0001 &&
- us->pusb_dev->descriptor.idVendor == 0x04e6)
- us->srb->result = DID_OK << 16;
- else {
- unsigned int savelen = us->srb->request_bufflen;
- unsigned int saveallocation = 0;
-
- switch (us->srb->cmnd[0]) {
- case REQUEST_SENSE:
- if (us->srb->request_bufflen > 18)
- us->srb->request_bufflen = 18;
- else
- break;
- saveallocation = us->srb->cmnd[4];
- us->srb->cmnd[4] = 18;
- break;
-
- case INQUIRY:
- if (us->srb->request_bufflen > 36)
- us->srb->request_bufflen = 36;
- else
- break;
- saveallocation = us->srb->cmnd[4];
- us->srb->cmnd[4] = 36;
- break;
+ if (us->filter && us->filter->command)
+ us->srb->result = us->filter->command(us->fdata, us->srb);
+ else if (us->srb->cmnd[0] == START_STOP &&
+ us->pusb_dev->descriptor.idProduct == 0x0001 &&
+ us->pusb_dev->descriptor.idVendor == 0x04e6)
+ us->srb->result = DID_OK << 16;
+ else {
+ unsigned int savelen = us->srb->request_bufflen;
+ unsigned int saveallocation = 0;
+
+ switch (us->srb->cmnd[0]) {
+ case REQUEST_SENSE:
+ if (us->srb->request_bufflen > 18)
+ us->srb->request_bufflen = 18;
+ else
+ break;
+ saveallocation = us->srb->cmnd[4];
+ us->srb->cmnd[4] = 18;
+ break;
+
+ case INQUIRY:
+ if (us->srb->request_bufflen > 36)
+ us->srb->request_bufflen = 36;
+ else
+ break;
+ saveallocation = us->srb->cmnd[4];
+ us->srb->cmnd[4] = 36;
+ break;
+
+ case MODE_SENSE:
+ if (us->srb->request_bufflen > 4)
+ us->srb->request_bufflen = 4;
+ else
+ break;
+ saveallocation = us->srb->cmnd[4];
+ us->srb->cmnd[4] = 4;
+ break;
+
+ case LOG_SENSE:
+ case MODE_SENSE_10:
+ if (us->srb->request_bufflen > 8)
+ us->srb->request_bufflen = 8;
+ else
+ break;
+ saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8];
+ us->srb->cmnd[7] = 0;
+ us->srb->cmnd[8] = 8;
+ break;
+
+ default:
+ break;
+ } /* end switch on cmnd[0] */
+ us->srb->result = us->pop(us->srb);
+
+ if (savelen != us->srb->request_bufflen &&
+ us->srb->result == (DID_OK << 16)) {
+ unsigned char *p = (unsigned char *)us->srb->request_buffer;
+ unsigned int length = 0;
+
+ /* set correct length and retry */
+ switch (us->srb->cmnd[0]) {
+ case REQUEST_SENSE:
+ /* simply return 18 bytes */
+ p[7] = 10;
+ length = us->srb->request_bufflen;;
+ break;
+
+ case INQUIRY:
+ length = p[4] + 5 > savelen ? savelen : p[4] + 5;
+ us->srb->cmnd[4] = length;
+ break;
+
+ case MODE_SENSE:
+ length = p[0] + 4 > savelen ? savelen : p[0] + 4;
+ us->srb->cmnd[4] = 4;
+ break;
+
+ case LOG_SENSE:
+ length = ((p[2] << 8) + p[3]) + 4 > savelen ? savelen : ((p[2] << 8) + p[3]) + 4;
+ us->srb->cmnd[7] = length >> 8;
+ us->srb->cmnd[8] = length;
+ break;
+
+ case MODE_SENSE_10:
+ length = ((p[0] << 8) + p[1]) + 8 > savelen ? savelen : ((p[0] << 8) + p[1]) + 8;
+ us->srb->cmnd[7] = length >> 8;
+ us->srb->cmnd[8] = length;
+ break;
+ } /* end switch on cmnd[0] */
+
+ US_DEBUGP("Old/New length = %d/%d\n",
+ savelen, length);
+
+ if (us->srb->request_bufflen != length) {
+ US_DEBUGP("redoing cmd with len=%d\n", length);
+ us->srb->request_bufflen = length;
+ us->srb->result = us->pop(us->srb);
+ }
+ /* reset back to original values */
+
+ us->srb->request_bufflen = savelen;
+ switch (us->srb->cmnd[0]) {
+ case REQUEST_SENSE:
+ case INQUIRY:
+ case MODE_SENSE:
+ if (us->srb->use_sg == 0 && length > 0) {
+ int i;
+ printk(KERN_DEBUG "Data is");
+ for (i = 0; i < 32 && i < length; ++i)
+ printk(" %.2x", ((unsigned char *)us->srb->request_buffer)[i]);
+ if (i < length)
+ printk(" ...");
+ printk("\n");
+ }
+ us->srb->cmnd[4] = saveallocation;
+ if (us->mode_xlate) {
+ /* convert MODE_SENSE_10 return data
+ * format to MODE_SENSE_6 format */
+ unsigned char *dta = (unsigned char *)us->srb->request_buffer;
+ dta[0] = dta[1]; /* data len */
+ dta[1] = dta[2]; /* med type */
+ dta[2] = dta[3]; /* dev-spec prm */
+ dta[3] = dta[7]; /* block desc len */
+ printk (KERN_DEBUG USB_SCSI "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n",
+ dta[0], dta[1], dta[2], dta[3]);
+ }
+ break;
+
+ case LOG_SENSE:
+ case MODE_SENSE_10:
+ us->srb->cmnd[7] = saveallocation >> 8;
+ us->srb->cmnd[8] = saveallocation;
+ break;
+ } /* end switch on cmnd[0] */
+ }
+ /* force attention on first command */
+ if (!us->attention_done) {
+ US_DEBUGP("forcing unit attention\n");
+ if (us->srb->cmnd[0] == REQUEST_SENSE) {
+ if (us->srb->result == (DID_OK << 16)) {
+ unsigned char *p = (unsigned char *)us->srb->request_buffer;
+
+ us->attention_done = 1;
+ if ((p[2] & 0x0f) != UNIT_ATTENTION) {
+ p[2] = UNIT_ATTENTION;
+ p[12] = 0x29; /* power on, reset or bus-reset */
+ p[13] = 0;
+ }
+ }
+ } else if (us->srb->cmnd[0] != INQUIRY &&
+ us->srb->result == (DID_OK << 16)) {
+ us->srb->result |= 2; /* force check condition */
+ }
+ }
+ }
+ }
+ US_DEBUGP("scsi cmd done, result=%x\n", us->srb->result);
+ us->srb->scsi_done(us->srb);
+ us->srb = NULL;
+ break;
+
+ case US_ACT_ABORT:
+ break;
+
+ case US_ACT_DEVICE_RESET:
+ break;
+
+ case US_ACT_BUS_RESET:
+ break;
+
+ case US_ACT_HOST_RESET:
+ break;
+
+ } /* end switch on action */
+
+ if (signal_pending(current)) {
+ /* sending SIGUSR1 makes us print out some info */
+ spin_lock_irq(¤t->sigmask_lock);
+ signr = dequeue_signal(¤t->blocked, &info);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ if (signr == SIGUSR2) {
+ usbscsi_debug = !usbscsi_debug;
+ printk(USB_SCSI "debug toggle = %d\n", usbscsi_debug);
+ } else {
+ break; /* exit the loop on any other signal */
+ }
+ }
+ }
- case MODE_SENSE:
- if (us->srb->request_bufflen > 4)
- us->srb->request_bufflen = 4;
- else
- break;
- saveallocation = us->srb->cmnd[4];
- us->srb->cmnd[4] = 4;
- break;
-
- case LOG_SENSE:
- case MODE_SENSE_10:
- if (us->srb->request_bufflen > 8)
- us->srb->request_bufflen = 8;
- else
- break;
- saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8];
- us->srb->cmnd[7] = 0;
- us->srb->cmnd[8] = 8;
- break;
+ MOD_DEC_USE_COUNT;
- default:
- break;
- } /* end switch on cmnd[0] */
- us->srb->result = us->pop(us->srb);
-
- if (savelen != us->srb->request_bufflen &&
- us->srb->result == (DID_OK << 16)) {
- unsigned char *p = (unsigned char *)us->srb->request_buffer;
- unsigned int length = 0;
-
- /* set correct length and retry */
- switch (us->srb->cmnd[0]) {
- case REQUEST_SENSE:
- /* simply return 18 bytes */
- p[7] = 10;
- length = us->srb->request_bufflen;;
- break;
+ printk("usbscsi_control_thread exiting\n");
- case INQUIRY:
- length = p[4] + 5 > savelen ? savelen : p[4] + 5;
- us->srb->cmnd[4] = length;
- break;
+ return 0;
+}
- case MODE_SENSE:
- length = p[0] + 4 > savelen ? savelen : p[0] + 4;
- us->srb->cmnd[4] = 4;
+static void * scsi_probe(struct usb_device *dev, unsigned int ifnum)
+{
+ struct usb_interface_descriptor *interface;
+ int i;
+ char *mf; /* manufacturer */
+ char *prod; /* product */
+ char *serial; /* serial number */
+ struct us_data *ss = NULL;
+ struct usb_scsi_filter *filter = filters;
+ void *fdata = NULL;
+ unsigned int flags = 0;
+ GUID(guid);
+ struct us_data *prev;
+ Scsi_Host_Template *htmplt;
+ int protocol = 0;
+ int subclass = 0;
+
+ GUID_CLEAR(guid);
+ mf = usb_string(dev, dev->descriptor.iManufacturer);
+ prod = usb_string(dev, dev->descriptor.iProduct);
+ serial = usb_string(dev, dev->descriptor.iSerialNumber);
+
+ /* probe with filters first */
+
+ if (mf && prod) {
+ while (filter) {
+ if ((fdata = filter->probe(dev, mf, prod, serial)) != NULL) {
+ flags = filter->flags;
+ printk(KERN_INFO "USB Scsi filter %s\n", filter->name);
break;
+ }
+ filter = filter->next;
+ }
+ }
- case LOG_SENSE:
- length = ((p[2] << 8) + p[3]) + 4 > savelen ? savelen : ((p[2] << 8) + p[3]) + 4;
- us->srb->cmnd[7] = length >> 8;
- us->srb->cmnd[8] = length;
- break;
+ /* generic devices next */
- case MODE_SENSE_10:
- length = ((p[0] << 8) + p[1]) + 8 > savelen ? savelen : ((p[0] << 8) + p[1]) + 8;
- us->srb->cmnd[7] = length >> 8;
- us->srb->cmnd[8] = length;
- break;
- } /* end switch on cmnd[0] */
+ if (fdata == NULL) {
- US_DEBUGP("Old/New length = %d/%d\n",
- savelen, length);
+ /* some exceptions */
+ if (dev->descriptor.idVendor == 0x04e6 &&
+ dev->descriptor.idProduct == 0x0001) {
+ /* shuttle E-USB */
+ protocol = US_PR_CB;
+ subclass = US_SC_8070; /* an assumption */
+ } else if (dev->descriptor.bDeviceClass != 0 ||
+ dev->actconfig->interface[ifnum].altsetting[0].bInterfaceClass !=
+ USB_CLASS_MASS_STORAGE ||
+ dev->actconfig->interface[ifnum].altsetting[0].bInterfaceSubClass < US_SC_MIN ||
+ dev->actconfig->interface[ifnum].altsetting[0].bInterfaceSubClass > US_SC_MAX) {
+ return NULL;
+ }
- if (us->srb->request_bufflen != length) {
- US_DEBUGP("redoing cmd with len=%d\n", length);
- us->srb->request_bufflen = length;
- us->srb->result = us->pop(us->srb);
- }
- /* reset back to original values */
-
- us->srb->request_bufflen = savelen;
- switch (us->srb->cmnd[0]) {
- case REQUEST_SENSE:
- case INQUIRY:
- case MODE_SENSE:
- if (us->srb->use_sg == 0 && length > 0) {
- int i;
- printk(KERN_DEBUG "Data is");
- for (i = 0; i < 32 && i < length; ++i)
- printk(" %.2x", ((unsigned char *)us->srb->request_buffer)[i]);
- if (i < length)
- printk(" ...");
- printk("\n");
- }
- us->srb->cmnd[4] = saveallocation;
- if (us->mode_xlate) {
- /* convert MODE_SENSE_10 return data
- * format to MODE_SENSE_6 format */
- unsigned char *dta = (unsigned char *)us->srb->request_buffer;
- dta[0] = dta[1]; /* data len */
- dta[1] = dta[2]; /* med type */
- dta[2] = dta[3]; /* dev-spec prm */
- dta[3] = dta[7]; /* block desc len */
- printk (KERN_DEBUG USB_SCSI "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n",
- dta[0], dta[1], dta[2], dta[3]);
- }
- break;
+ /* now check if we have seen it before */
- case LOG_SENSE:
- case MODE_SENSE_10:
- us->srb->cmnd[7] = saveallocation >> 8;
- us->srb->cmnd[8] = saveallocation;
+ if (dev->descriptor.iSerialNumber &&
+ usb_string(dev, dev->descriptor.iSerialNumber) ) {
+ make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct,
+ usb_string(dev, dev->descriptor.iSerialNumber));
+ } else {
+ make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct,
+ "0");
+ }
+ for (ss = us_list; ss; ss = ss->next) {
+ if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid)) {
+ US_DEBUGP("Found existing GUID " GUID_FORMAT "\n",
+ GUID_ARGS(guid));
+ flags = ss->flags;
break;
- } /* end switch on cmnd[0] */
}
- /* force attention on first command */
- if (!us->attention_done) {
- US_DEBUGP("forcing unit attention\n");
- if (us->srb->cmnd[0] == REQUEST_SENSE) {
- if (us->srb->result == (DID_OK << 16)) {
- unsigned char *p = (unsigned char *)us->srb->request_buffer;
-
- us->attention_done = 1;
- if ((p[2] & 0x0f) != UNIT_ATTENTION) {
- p[2] = UNIT_ATTENTION;
- p[12] = 0x29; /* power on, reset or bus-reset */
- p[13] = 0;
- }
- }
- } else if (us->srb->cmnd[0] != INQUIRY &&
- us->srb->result == (DID_OK << 16)) {
- us->srb->result |= 2; /* force check condition */
- }
- }
- }
}
- US_DEBUGP("scsi cmd done, result=%x\n", us->srb->result);
- us->srb->scsi_done(us->srb);
- us->srb = NULL;
- break;
+ }
- case US_ACT_ABORT:
- break;
+ if (!ss) {
+ if ((ss = (struct us_data *)kmalloc(sizeof(*ss), GFP_KERNEL)) == NULL) {
+ printk(KERN_WARNING USB_SCSI "Out of memory\n");
+ if (filter)
+ filter->release(fdata);
+ return NULL;
+ }
+ memset(ss, 0, sizeof(struct us_data));
+ }
+
+ interface = &dev->actconfig->interface[ifnum].altsetting[0];
+ ss->filter = filter;
+ ss->fdata = fdata;
+ ss->flags = flags;
+ if (subclass) {
+ ss->subclass = subclass;
+ ss->protocol = protocol;
+ } else {
+ ss->subclass = interface->bInterfaceSubClass;
+ ss->protocol = interface->bInterfaceProtocol;
+ }
+ ss->attention_done = 0;
+
+ /* set the protocol op */
- case US_ACT_DEVICE_RESET:
+ US_DEBUGP("Protocol ");
+ switch (ss->protocol) {
+ case US_PR_CB:
+ US_DEBUGPX("Control/Bulk\n");
+ ss->pop = pop_CBI;
+ ss->pop_reset = pop_CB_reset;
break;
- case US_ACT_BUS_RESET:
+ case US_PR_CBI:
+ US_DEBUGPX("Control/Bulk/Interrupt\n");
+ ss->pop = pop_CBI;
+ ss->pop_reset = pop_CB_reset;
break;
- case US_ACT_HOST_RESET:
+ default:
+ US_DEBUGPX("Bulk\n");
+ ss->pop = pop_Bulk;
+ ss->pop_reset = pop_Bulk_reset;
break;
+ }
- } /* end switch on action */
+ /*
+ * We are expecting a minimum of 2 endpoints - in and out (bulk).
+ * An optional interrupt is OK (necessary for CBI protocol).
+ * We will ignore any others.
+ */
+
+ for (i = 0; i < interface->bNumEndpoints; i++) {
+ if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_BULK) {
+ if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN)
+ ss->ep_in = interface->endpoint[i].bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
+ else
+ ss->ep_out = interface->endpoint[i].bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
+ } else if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT) {
+ ss->ep_int = interface->endpoint[i].bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
+ }
+ }
+ US_DEBUGP("Endpoints In %d Out %d Int %d\n",
+ ss->ep_in, ss->ep_out, ss->ep_int);
- if (signal_pending(current)) {
- /* sending SIGUSR1 makes us print out some info */
- spin_lock_irq(¤t->sigmask_lock);
- signr = dequeue_signal(¤t->blocked, &info);
- spin_unlock_irq(¤t->sigmask_lock);
-
- if (signr == SIGUSR2) {
- usbscsi_debug = !usbscsi_debug;
- printk(USB_SCSI "debug toggle = %d\n", usbscsi_debug);
- } else {
- break; /* exit the loop on any other signal */
- }
- }
- }
+ /* save the interface number */
+ ss->ifnum = ifnum;
- MOD_DEC_USE_COUNT;
+ /* exit if strange looking */
- printk("usbscsi_control_thread exiting\n");
+ if (usb_set_interface(dev, interface->bInterfaceNumber, 0) ||
+ !ss->ep_in || !ss->ep_out || (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
+ US_DEBUGP("Problems with device\n");
+ if (ss->host) {
+ scsi_unregister_module(MODULE_SCSI_HA, ss->htmplt);
+ kfree(ss->htmplt->name);
+ kfree(ss->htmplt);
+ }
+ if (filter)
+ filter->release(fdata);
+ kfree(ss);
+ return NULL; /* no endpoints */
+ }
- return 0;
-}
+ if (dev->actconfig->iConfiguration && usb_string(dev, dev->actconfig->iConfiguration))
+ US_DEBUGP("Configuration %s\n",
+ usb_string(dev, dev->actconfig->iConfiguration));
+ if (interface->iInterface && usb_string(dev, interface->iInterface))
+ US_DEBUGP("Interface %s\n",
+ usb_string(dev, interface->iInterface));
+
+ ss->pusb_dev = dev;
+
+ /* Now generate a scsi host definition, and register with scsi above us */
+
+ if (!ss->host) {
+
+ /* make unique id if possible */
+
+ US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
+ memcpy(ss->guid, guid, sizeof(guid));
+
+ /* set class specific stuff */
+
+ US_DEBUGP("SubClass ");
+ switch (ss->subclass) {
+ case US_SC_RBC:
+ US_DEBUGPX("Reduced Block Commands\n");
+ break;
+ case US_SC_8020:
+ US_DEBUGPX("8020\n");
+ break;
+ case US_SC_QIC:
+ US_DEBUGPX("QIC157\n");
+ break;
+ case US_SC_8070:
+ US_DEBUGPX("8070\n");
+ ss->flags |= US_FL_FIXED_COMMAND;
+ ss->fixedlength = 12;
+ break;
+ case US_SC_SCSI:
+ US_DEBUGPX("Transparent SCSI\n");
+ break;
+ case US_SC_UFI:
+ US_DEBUGPX(" UFF\n");
+ ss->flags |= US_FL_FIXED_COMMAND;
+ ss->fixedlength = 12;
+ break;
-static void * scsi_probe(struct usb_device *dev, unsigned int ifnum)
-{
- struct usb_interface_descriptor *interface;
- int i;
- char *mf; /* manufacturer */
- char *prod; /* product */
- char *serial; /* serial number */
- struct us_data *ss = NULL;
- struct usb_scsi_filter *filter = filters;
- void *fdata = NULL;
- unsigned int flags = 0;
- GUID(guid);
- struct us_data *prev;
- Scsi_Host_Template *htmplt;
- int protocol = 0;
- int subclass = 0;
-
- GUID_CLEAR(guid);
- mf = usb_string(dev, dev->descriptor.iManufacturer);
- prod = usb_string(dev, dev->descriptor.iProduct);
- serial = usb_string(dev, dev->descriptor.iSerialNumber);
-
- /* probe with filters first */
-
- if (mf && prod) {
- while (filter) {
- if ((fdata = filter->probe(dev, mf, prod, serial)) != NULL) {
- flags = filter->flags;
- printk(KERN_INFO "USB Scsi filter %s\n", filter->name);
- break;
- }
- filter = filter->next;
- }
- }
-
- /* generic devices next */
-
- if (fdata == NULL) {
-
- /* some exceptions */
- if (dev->descriptor.idVendor == 0x04e6 &&
- dev->descriptor.idProduct == 0x0001) {
- /* shuttle E-USB */
- protocol = US_PR_CB;
- subclass = US_SC_8070; /* an assumption */
- } else if (dev->descriptor.bDeviceClass != 0 ||
- dev->actconfig->interface[ifnum].altsetting[0].bInterfaceClass !=
- USB_CLASS_MASS_STORAGE ||
- dev->actconfig->interface[ifnum].altsetting[0].bInterfaceSubClass < US_SC_MIN ||
- dev->actconfig->interface[ifnum].altsetting[0].bInterfaceSubClass > US_SC_MAX) {
- return NULL;
- }
-
- /* now check if we have seen it before */
-
- if (dev->descriptor.iSerialNumber &&
- usb_string(dev, dev->descriptor.iSerialNumber) ) {
- make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct,
- usb_string(dev, dev->descriptor.iSerialNumber));
- } else {
- make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct,
- "0");
- }
- for (ss = us_list; ss; ss = ss->next) {
- if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid)) {
- US_DEBUGP("Found existing GUID " GUID_FORMAT "\n",
- GUID_ARGS(guid));
- flags = ss->flags;
- break;
- }
- }
- }
+ default:
+ break;
+ }
- if (!ss) {
- if ((ss = (struct us_data *)kmalloc(sizeof(*ss), GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING USB_SCSI "Out of memory\n");
- if (filter)
- filter->release(fdata);
- return NULL;
- }
- memset(ss, 0, sizeof(struct us_data));
- }
-
- interface = &dev->actconfig->interface[ifnum].altsetting[0];
- ss->filter = filter;
- ss->fdata = fdata;
- ss->flags = flags;
- if (subclass) {
- ss->subclass = subclass;
- ss->protocol = protocol;
- } else {
- ss->subclass = interface->bInterfaceSubClass;
- ss->protocol = interface->bInterfaceProtocol;
- }
- ss->attention_done = 0;
-
- /* set the protocol op */
-
- US_DEBUGP("Protocol ");
- switch (ss->protocol) {
- case US_PR_CB:
- US_DEBUGPX("Control/Bulk\n");
- ss->pop = pop_CBI;
- ss->pop_reset = pop_CB_reset;
- break;
-
- case US_PR_CBI:
- US_DEBUGPX("Control/Bulk/Interrupt\n");
- ss->pop = pop_CBI;
- ss->pop_reset = pop_CB_reset;
- break;
-
- default:
- US_DEBUGPX("Bulk\n");
- ss->pop = pop_Bulk;
- ss->pop_reset = pop_Bulk_reset;
- break;
- }
-
- /*
- * We are expecting a minimum of 2 endpoints - in and out (bulk).
- * An optional interrupt is OK (necessary for CBI protocol).
- * We will ignore any others.
- */
-
- for (i = 0; i < interface->bNumEndpoints; i++) {
- if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_BULK) {
- if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN)
- ss->ep_in = interface->endpoint[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- else
- ss->ep_out = interface->endpoint[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- } else if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_INT) {
- ss->ep_int = interface->endpoint[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- }
- }
- US_DEBUGP("Endpoints In %d Out %d Int %d\n",
- ss->ep_in, ss->ep_out, ss->ep_int);
-
- /* save the interface number */
- ss->ifnum = ifnum;
-
- /* exit if strange looking */
-
- if (usb_set_interface(dev, interface->bInterfaceNumber, 0) ||
- !ss->ep_in || !ss->ep_out || (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
- US_DEBUGP("Problems with device\n");
- if (ss->host) {
- scsi_unregister_module(MODULE_SCSI_HA, ss->htmplt);
- kfree(ss->htmplt->name);
- kfree(ss->htmplt);
- }
- if (filter)
- filter->release(fdata);
- kfree(ss);
- return NULL; /* no endpoints */
- }
-
- if (dev->actconfig->iConfiguration && usb_string(dev, dev->actconfig->iConfiguration))
- US_DEBUGP("Configuration %s\n",
- usb_string(dev, dev->actconfig->iConfiguration));
- if (interface->iInterface && usb_string(dev, interface->iInterface))
- US_DEBUGP("Interface %s\n",
- usb_string(dev, interface->iInterface));
-
- ss->pusb_dev = dev;
-
- /* Now generate a scsi host definition, and register with scsi above us */
-
- if (!ss->host) {
-
- /* make unique id if possible */
-
- US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
- memcpy(ss->guid, guid, sizeof(guid));
-
- /* set class specific stuff */
-
- US_DEBUGP("SubClass ");
- switch (ss->subclass) {
- case US_SC_RBC:
- US_DEBUGPX("Reduced Block Commands\n");
- break;
- case US_SC_8020:
- US_DEBUGPX("8020\n");
- break;
- case US_SC_QIC:
- US_DEBUGPX("QIC157\n");
- break;
- case US_SC_8070:
- US_DEBUGPX("8070\n");
- ss->flags |= US_FL_FIXED_COMMAND;
- ss->fixedlength = 12;
- break;
- case US_SC_SCSI:
- US_DEBUGPX("Transparent SCSI\n");
- break;
- case US_SC_UFI:
- US_DEBUGPX(" UFF\n");
- ss->flags |= US_FL_FIXED_COMMAND;
- ss->fixedlength = 12;
- break;
+ /* create unique host template */
- default:
- break;
- }
+ if ((htmplt = (Scsi_Host_Template *)kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) {
+ printk(KERN_WARNING USB_SCSI "Out of memory\n");
+ if (filter)
+ filter->release(fdata);
+ kfree(ss);
+ return NULL;
+ }
+ memcpy(htmplt, &my_host_template, sizeof(my_host_template));
+ ss->host_number = my_host_number++;
- /* create unique host template */
+ (struct us_data *)htmplt->proc_dir = ss;
- if ((htmplt = (Scsi_Host_Template *)kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) {
- printk(KERN_WARNING USB_SCSI "Out of memory\n");
- if (filter)
- filter->release(fdata);
- kfree(ss);
- return NULL;
- }
- memcpy(htmplt, &my_host_template, sizeof(my_host_template));
- ss->host_number = my_host_number++;
-
- (struct us_data *)htmplt->proc_dir = ss;
-
- if (dev->descriptor.idVendor == 0x04e6 &&
- dev->descriptor.idProduct == 0x0001) {
- __u8 qstat[2];
- int result;
-
- /* shuttle E-USB */
- result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0),
- 1, 0xC0,
- 0, ss->ifnum,
- qstat, 2, HZ*5);
- US_DEBUGP("C0 status %x %x\n", qstat[0], qstat[1]);
- init_waitqueue_head(&ss->ip_waitq);
- ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
- result = usb_request_irq(ss->pusb_dev, ss->irqpipe, pop_CBI_irq,
- IRQ_PERIOD, (void *)ss, &ss->irq_handle);
- if (result)
- return NULL;
+ if (dev->descriptor.idVendor == 0x04e6 &&
+ dev->descriptor.idProduct == 0x0001) {
+ __u8 qstat[2];
+ int result;
+
+ /* shuttle E-USB */
+ result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0),
+ 1, 0xC0,
+ 0, ss->ifnum,
+ qstat, 2, HZ*5);
+ US_DEBUGP("C0 status %x %x\n", qstat[0], qstat[1]);
+ init_waitqueue_head(&ss->ip_waitq);
+ ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
+ result = usb_request_irq(ss->pusb_dev, ss->irqpipe, pop_CBI_irq,
+ IRQ_PERIOD, (void *)ss, &ss->irq_handle);
+ if (result)
+ return NULL;
- interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6);
+ interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6);
#ifdef REWRITE_PROJECT
- /* FIXME: Don't know if this release_irq() call is at the
- right place/time. */
- usb_release_irq(ss->pusb_dev, ss->irq_handle, ss->irqpipe);
- ss->irq_handle = NULL;
+ /* FIXME: Don't know if this release_irq() call is at the
+ right place/time. */
+ usb_release_irq(ss->pusb_dev, ss->irq_handle, ss->irqpipe);
+ ss->irq_handle = NULL;
#endif
- } else if (ss->protocol == US_PR_CBI)
- init_waitqueue_head(&ss->ip_waitq);
+ } else if (ss->protocol == US_PR_CBI)
+ init_waitqueue_head(&ss->ip_waitq);
- /* start up our thread */
+ /* start up our thread */
- {
- DECLARE_MUTEX_LOCKED(sem);
+ {
+ DECLARE_MUTEX_LOCKED(sem);
- init_waitqueue_head(&ss->waitq);
-
- ss->notify = &sem;
- ss->pid = kernel_thread(usbscsi_control_thread, ss,
- CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- if (ss->pid < 0) {
- printk(KERN_WARNING USB_SCSI "Unable to start control thread\n");
- kfree(htmplt);
- if (filter)
- filter->release(fdata);
- kfree(ss);
- return NULL;
- }
+ init_waitqueue_head(&ss->waitq);
+
+ ss->notify = &sem;
+ ss->pid = kernel_thread(usbscsi_control_thread, ss,
+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ if (ss->pid < 0) {
+ printk(KERN_WARNING USB_SCSI "Unable to start control thread\n");
+ kfree(htmplt);
+ if (filter)
+ filter->release(fdata);
+ kfree(ss);
+ return NULL;
+ }
- /* wait for it to start */
+ /* wait for it to start */
- down(&sem);
- }
+ down(&sem);
+ }
- /* now register - our detect function will be called */
+ /* now register - our detect function will be called */
- scsi_register_module(MODULE_SCSI_HA, htmplt);
+ scsi_register_module(MODULE_SCSI_HA, htmplt);
- /* put us in the list */
+ /* put us in the list */
- prev = (struct us_data *)&us_list;
- while (prev->next)
- prev = prev->next;
- prev->next = ss;
- }
+ prev = (struct us_data *)&us_list;
+ while (prev->next)
+ prev = prev->next;
+ prev->next = ss;
+ }
- printk(KERN_WARNING "DANGEROUS: USB SCSI driver data integrity not assured !!!\n");
- printk(KERN_INFO "USB SCSI device found at address %d\n", dev->devnum);
+ printk(KERN_WARNING "DANGEROUS: USB SCSI driver data integrity not assured !!!\n");
+ printk(KERN_INFO "USB SCSI device found at address %d\n", dev->devnum);
- return ss;
+ return ss;
}
static void scsi_disconnect(struct usb_device *dev, void *ptr)
@@ -1363,7 +1363,7 @@
struct us_data *ss = ptr;
if (!ss)
- return;
+ return;
if (ss->filter)
ss->filter->release(ss->fdata);
ss->pusb_dev = NULL;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)