diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-10 01:06:30 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-10 01:06:30 +0000 |
commit | 01154f067a56aa07988e8f6f978c93f5749d7bd0 (patch) | |
tree | e66eb59427ef6576bb47caf275dac1a1d9485c0c | |
parent | a212fb84295ebd29990fc0934a40623c363eb376 (diff) |
Kill junk from recent merge.
-rw-r--r-- | drivers/usb/usb-storage-debug.h | 89 | ||||
-rw-r--r-- | drivers/usb/usb-storage.c | 2787 | ||||
-rw-r--r-- | drivers/usb/usb-storage.h | 160 |
3 files changed, 0 insertions, 3036 deletions
diff --git a/drivers/usb/usb-storage-debug.h b/drivers/usb/usb-storage-debug.h deleted file mode 100644 index 1c5fcc0e2..000000000 --- a/drivers/usb/usb-storage-debug.h +++ /dev/null @@ -1,89 +0,0 @@ -#include <linux/config.h> -#ifdef CONFIG_USB_STORAGE_DEBUG - -/* Debug output for Driver for USB mass storage (scsi-like) devices - * - * (C) Michael Gee (michael@linuxspecific.com) 1999 - * - */ - -void us_show_command(Scsi_Cmnd *srb) -{ - char *what = NULL; - - switch (srb->cmnd[0]) { - case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; - case REZERO_UNIT: what = "REZERO_UNIT"; break; - case REQUEST_SENSE: what = "REQUEST_SENSE"; break; - case FORMAT_UNIT: what = "FORMAT_UNIT"; break; - case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; - case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; - case READ_6: what = "READ_6"; break; - case WRITE_6: what = "WRITE_6"; break; - case SEEK_6: what = "SEEK_6"; break; - case READ_REVERSE: what = "READ_REVERSE"; break; - case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; - case SPACE: what = "SPACE"; break; - case INQUIRY: what = "INQUIRY"; break; - case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; - case MODE_SELECT: what = "MODE_SELECT"; break; - case RESERVE: what = "RESERVE"; break; - case RELEASE: what = "RELEASE"; break; - case COPY: what = "COPY"; break; - case ERASE: what = "ERASE"; break; - case MODE_SENSE: what = "MODE_SENSE"; break; - case START_STOP: what = "START_STOP"; break; - case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; - case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; - case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; - case SET_WINDOW: what = "SET_WINDOW"; break; - case READ_CAPACITY: what = "READ_CAPACITY"; break; - case READ_10: what = "READ_10"; break; - case WRITE_10: what = "WRITE_10"; break; - case SEEK_10: what = "SEEK_10"; break; - case WRITE_VERIFY: what = "WRITE_VERIFY"; break; - case VERIFY: what = "VERIFY"; break; - case SEARCH_HIGH: what = "SEARCH_HIGH"; break; - case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; - case SEARCH_LOW: what = "SEARCH_LOW"; break; - case SET_LIMITS: what = "SET_LIMITS"; break; - case READ_POSITION: what = "READ_POSITION"; break; - case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; - case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; - case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; - case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; - case COMPARE: what = "COMPARE"; break; - case COPY_VERIFY: what = "COPY_VERIFY"; break; - case WRITE_BUFFER: what = "WRITE_BUFFER"; break; - case READ_BUFFER: what = "READ_BUFFER"; break; - case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; - case READ_LONG: what = "READ_LONG"; break; - case WRITE_LONG: what = "WRITE_LONG"; break; - case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; - case WRITE_SAME: what = "WRITE_SAME"; break; - case READ_TOC: what = "READ_TOC"; break; - case LOG_SELECT: what = "LOG_SELECT"; break; - case LOG_SENSE: what = "LOG_SENSE"; break; - case MODE_SELECT_10: what = "MODE_SELECT_10"; break; - case MODE_SENSE_10: what = "MODE_SENSE_10"; break; - case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break; - case READ_12: what = "READ_12"; break; - case WRITE_12: what = "WRITE_12"; break; - case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; - case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; - case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; - case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; - case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; - case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; - case WRITE_LONG_2: what = "WRITE_LONG_2"; break; - default: break; - } - printk(KERN_DEBUG USB_STORAGE - "Command %s (%d bytes)\n", what, srb->cmd_len); - printk(KERN_DEBUG USB_STORAGE - " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], - srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]); -} - -#endif diff --git a/drivers/usb/usb-storage.c b/drivers/usb/usb-storage.c deleted file mode 100644 index 6d88d360b..000000000 --- a/drivers/usb/usb-storage.c +++ /dev/null @@ -1,2787 +0,0 @@ -/* Driver for USB Mass Storage compliant devices - * - * $Id: usb-storage.c,v 1.11 2000/06/20 03:19:31 mdharm Exp $ - * - * Current development and maintainance by: - * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) - * - * Developed with the assistance of: - * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) - * - * Initial work by: - * (c) 1999 Michael Gee (michael@linuxspecific.com) - * - * This driver is based on the 'USB Mass Storage Class' document. This - * describes in detail the protocol used to communicate with such - * devices. Clearly, the designers had SCSI and ATAPI commands in - * mind when they created this document. The commands are all very - * similar to commands in the SCSI-II and ATAPI specifications. - * - * It is important to note that in a number of cases this class - * exhibits class-specific exemptions from the USB specification. - * Notably the usage of NAK, STALL and ACK differs from the norm, in - * that they are used to communicate wait, failed and OK on commands. - * - * Also, for certain devices, the interrupt endpoint is used to convey - * status of a command. - * - * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more - * information about this driver. - * - * 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 - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/signal.h> -#include <linux/errno.h> -#include <linux/random.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/malloc.h> -#include <linux/smp_lock.h> -#include <linux/usb.h> - -#include <linux/blk.h> -#include "../scsi/scsi.h" -#include "../scsi/hosts.h" -#include "../scsi/sd.h" - -#include "usb-storage.h" -#include "usb-storage-debug.h" - -/* direction table -- this indicates the direction of the data - * transfer for each command code -- a 1 indicates input - */ -/* FIXME: we need to use the new direction indicators in the Scsi_Cmnd - * structure, not this table. First we need to evaluate if it's being set - * correctly for us, though - */ -unsigned char us_direction[256/8] = { - 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, - 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* - * Per device data - */ - -static int my_host_number; - -struct us_data; - -typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*); -typedef int (*trans_reset)(struct us_data*); -typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); - -/* we allocate one of these for every device that we remember */ -struct us_data { - struct us_data *next; /* next device */ - - /* the device we're working with */ - struct semaphore dev_semaphore; /* protect pusb_dev */ - struct usb_device *pusb_dev; /* this usb_device */ - - unsigned int flags; /* from filter initially */ - - /* information about the device -- always good */ - char vendor[USB_STOR_STRING_LEN]; - char product[USB_STOR_STRING_LEN]; - char serial[USB_STOR_STRING_LEN]; - char *transport_name; - char *protocol_name; - u8 subclass; - u8 protocol; - u8 max_lun; - - /* information about the device -- only good if device is attached */ - u8 ifnum; /* interface number */ - u8 ep_in; /* bulk in endpoint */ - u8 ep_out; /* bulk out endpoint */ - struct usb_endpoint_descriptor *ep_int; /* interrupt endpoint */ - - /* function pointers for this device */ - trans_cmnd transport; /* transport function */ - trans_reset transport_reset; /* transport device reset */ - proto_cmnd proto_handler; /* protocol handler */ - - /* SCSI interfaces */ - 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 */ - Scsi_Cmnd *srb; /* current srb */ - - /* thread information */ - Scsi_Cmnd *queue_srb; /* the single queue slot */ - int action; /* what to do */ - int pid; /* control thread */ - - /* interrupt info for CBI devices -- only good if attached */ - struct semaphore ip_waitq; /* for CBI interrupts */ - int ip_wanted; /* is an IRQ expected? */ - - /* interrupt communications data */ - struct semaphore irq_urb_sem; /* to protect irq_urb */ - struct urb *irq_urb; /* for USB int requests */ - unsigned char irqbuf[2]; /* buffer for USB IRQ */ - - /* control and bulk communications data */ - struct semaphore current_urb_sem; /* to protect irq_urb */ - struct urb *current_urb; /* non-int USB requests */ - - /* mutual exclusion structures */ - struct semaphore notify; /* thread begin/end */ - struct semaphore sleeper; /* to sleep the thread on */ - struct semaphore queue_exclusion; /* to protect data structs */ -}; - -/* - * kernel thread actions - */ - -#define US_ACT_COMMAND 1 -#define US_ACT_DEVICE_RESET 2 -#define US_ACT_BUS_RESET 3 -#define US_ACT_HOST_RESET 4 -#define US_ACT_EXIT 5 - -/* The list of structures and the protective lock for them */ -static struct us_data *us_list; -struct semaphore us_list_semaphore; - -static void * storage_probe(struct usb_device *dev, unsigned int ifnum); -static void storage_disconnect(struct usb_device *dev, void *ptr); -static struct usb_driver storage_driver = { - name: "usb-storage", - probe: storage_probe, - disconnect: storage_disconnect, -}; - -/*********************************************************************** - * Data transfer routines - ***********************************************************************/ - -/* This is the completion handler which will wake us up when an URB - * completes. - */ -static void usb_stor_blocking_completion(urb_t *urb) -{ - api_wrapper_data *awd = (api_wrapper_data *)urb->context; - - if (waitqueue_active(awd->wakeup)) - wake_up(awd->wakeup); -} - -/* This is our function to emulate usb_control_msg() but give us enough - * access to make aborts/resets work - */ -int usb_stor_control_msg(struct us_data *us, unsigned int pipe, - u8 request, u8 requesttype, u16 value, u16 index, - void *data, u16 size) -{ - DECLARE_WAITQUEUE(wait, current); - DECLARE_WAIT_QUEUE_HEAD(wqh); - api_wrapper_data awd; - int status; - devrequest *dr; - - /* allocate the device request structure */ - dr = kmalloc(sizeof(devrequest), GFP_KERNEL); - if (!dr) - return -ENOMEM; - - /* fill in the structure */ - dr->requesttype = requesttype; - dr->request = request; - dr->value = cpu_to_le16(value); - dr->index = cpu_to_le16(index); - dr->length = cpu_to_le16(size); - - /* set up data structures for the wakeup system */ - awd.wakeup = &wqh; - awd.handler = 0; - init_waitqueue_head(&wqh); - add_wait_queue(&wqh, &wait); - - /* lock the URB */ - down(&(us->current_urb_sem)); - - /* fill the URB */ - FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, - (unsigned char*) dr, data, size, - usb_stor_blocking_completion, &awd); - - /* submit the URB */ - set_current_state(TASK_UNINTERRUPTIBLE); - status = usb_submit_urb(us->current_urb); - if (status) { - /* something went wrong */ - up(&(us->current_urb_sem)); - remove_wait_queue(&wqh, &wait); - kfree(dr); - return status; - } - - /* wait for the completion of the URB */ - up(&(us->current_urb_sem)); - if (us->current_urb->status == -EINPROGRESS) - schedule_timeout(10*HZ); - down(&(us->current_urb_sem)); - - /* we either timed out or got woken up -- clean up either way */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&wqh, &wait); - - /* did we time out? */ - if (us->current_urb->status == -EINPROGRESS) { - US_DEBUGP("usb_stor_control_msg() timeout\n"); - usb_unlink_urb(us->current_urb); - status = -ETIMEDOUT; - } else - status = us->current_urb->status; - - /* return the actual length of the data transferred if no error*/ - if (status >= 0) - status = us->current_urb->actual_length; - - /* release the lock and return status */ - up(&(us->current_urb_sem)); - kfree(dr); - return status; -} - -/* This is our function to emulate usb_bulk_msg() but give us enough - * access to make aborts/resets work - */ -int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, - unsigned int len, unsigned int *act_len) -{ - DECLARE_WAITQUEUE(wait, current); - DECLARE_WAIT_QUEUE_HEAD(wqh); - api_wrapper_data awd; - int status; - - /* set up data structures for the wakeup system */ - awd.wakeup = &wqh; - awd.handler = 0; - init_waitqueue_head(&wqh); - add_wait_queue(&wqh, &wait); - - /* lock the URB */ - down(&(us->current_urb_sem)); - - /* fill the URB */ - FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len, - usb_stor_blocking_completion, &awd); - - /* submit the URB */ - set_current_state(TASK_UNINTERRUPTIBLE); - status = usb_submit_urb(us->current_urb); - if (status) { - /* something went wrong */ - up(&(us->current_urb_sem)); - remove_wait_queue(&wqh, &wait); - return status; - } - - /* wait for the completion of the URB */ - up(&(us->current_urb_sem)); - if (us->current_urb->status == -EINPROGRESS) - schedule_timeout(10*HZ); - down(&(us->current_urb_sem)); - - /* we either timed out or got woken up -- clean up either way */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&wqh, &wait); - - /* did we time out? */ - if (us->current_urb->status == -EINPROGRESS) { - US_DEBUGP("usb_stor_bulk_msg() timeout\n"); - usb_unlink_urb(us->current_urb); - status = -ETIMEDOUT; - } else - status = us->current_urb->status; - - /* return the actual length of the data transferred */ - *act_len = us->current_urb->actual_length; - - /* release the lock and return status */ - up(&(us->current_urb_sem)); - return status; -} - -/* - * Transfer one SCSI scatter-gather buffer via bulk transfer - * - * Note that this function is necessary because we want the ability to - * use scatter-gather memory. Good performance is achieved by a combination - * of scatter-gather and clustering (which makes each chunk bigger). - * - * Note that the lower layer will always retry when a NAK occurs, up to the - * timeout limit. Thus we don't have to worry about it for individual - * packets. - */ -static int us_transfer_partial(struct us_data *us, char *buf, int length) -{ - int result; - int partial; - int pipe; - - /* calculate the appropriate pipe information */ - if (US_DIRECTION(us->srb->cmnd[0])) - pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - else - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - - /* transfer the data */ - US_DEBUGP("us_transfer_partial(): xfer %d bytes\n", length); - result = usb_stor_bulk_msg(us, buf, pipe, length, &partial); - US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n", - result, partial, length); - - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - } - - /* did we send all the data? */ - if (partial == length) { - US_DEBUGP("us_transfer_partial(): transfer complete\n"); - return US_BULK_TRANSFER_GOOD; - } - - /* uh oh... we have an error code, so something went wrong. */ - if (result) { - /* NAK - that means we've retried a few times allready */ - if (result == -ETIMEDOUT) { - US_DEBUGP("us_transfer_partial(): device NAKed\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { - US_DEBUGP("us_transfer_partial(): transfer aborted\n"); - return US_BULK_TRANSFER_ABORTED; - } - - /* the catch-all case */ - US_DEBUGP("us_transfer_partial(): unknown error\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* no error code, so we must have transferred some data, - * just not all of it */ - return US_BULK_TRANSFER_SHORT; -} - -/* - * Transfer an entire SCSI command's worth of data payload over the bulk - * pipe. - * - * Note that this uses us_transfer_partial to achieve it's goals -- this - * function simply determines if we're going to use scatter-gather or not, - * and acts appropriately. For now, it also re-interprets the error codes. - */ -static void us_transfer(Scsi_Cmnd *srb, struct us_data* us, int dir_in) -{ - int i; - int result = -1; - struct scatterlist *sg; - - /* are we scatter-gathering? */ - if (srb->use_sg) { - - /* loop over all the scatter gather structures and - * make the appropriate requests for each, until done - */ - sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) { - result = us_transfer_partial(us, sg[i].address, - sg[i].length); - if (result) - break; - } - } - else - /* no scatter-gather, just make the request */ - result = us_transfer_partial(us, srb->request_buffer, - srb->request_bufflen); - - /* return the result in the data structure itself */ - srb->result = result; -} - -/* Calculate the length of the data transfer (not the command) for any - * given SCSI command - */ -static unsigned int us_transfer_length(Scsi_Cmnd *srb, struct us_data *us) -{ - int i; - unsigned int total = 0; - struct scatterlist *sg; - - /* support those devices which need the length calculated - * differently - */ - if (us->flags & US_FL_ALT_LENGTH) { - if (srb->cmnd[0] == INQUIRY) { - srb->cmnd[4] = 36; - } - - if ((srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE)) - return srb->cmnd[4]; - - if (srb->cmnd[0] == TEST_UNIT_READY) - return 0; - } - - /* Are we going to scatter gather? */ - if (srb->use_sg) { - /* Add up the sizes of all the scatter-gather segments */ - sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) - total += sg[i].length; - - return total; - } - else - /* Just return the length of the buffer */ - return srb->request_bufflen; -} - -/*********************************************************************** - * Transport routines - ***********************************************************************/ - -/* Invoke the transport and basic error-handling/recovery methods - * - * This is used by the protocol layers to actually send the message to - * the device and recieve the response. - */ -static void invoke_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - int need_auto_sense; - int result; - - /* send the command to the transport layer */ - result = us->transport(srb, us); - - /* Determine if we need to auto-sense - * - * I normally don't use a flag like this, but it's almost impossible - * to understand what's going on here if I don't. - */ - need_auto_sense = 0; - - /* - * If we're running the CB transport, which is incapable - * of determining status on it's own, we need to auto-sense almost - * every time. - */ - if (us->protocol == US_PR_CB) { - US_DEBUGP("-- CB transport device requiring auto-sense\n"); - need_auto_sense = 1; - - /* There are some exceptions to this. Notably, if this is - * a UFI device and the command is REQUEST_SENSE or INQUIRY, - * then it is impossible to truly determine status. - */ - if (us->subclass == US_SC_UFI && - ((srb->cmnd[0] == REQUEST_SENSE) || - (srb->cmnd[0] == INQUIRY))) { - US_DEBUGP("** no auto-sense for a special command\n"); - need_auto_sense = 0; - } - } - - /* - * If we have an error, we're going to do a REQUEST_SENSE - * automatically. Note that we differentiate between a command - * "failure" and an "error" in the transport mechanism. - */ - if (result == USB_STOR_TRANSPORT_FAILED) { - US_DEBUGP("-- transport indicates command failure\n"); - need_auto_sense = 1; - } - if (result == USB_STOR_TRANSPORT_ERROR) { - /* FIXME: we need to invoke a transport reset here */ - US_DEBUGP("-- transport indicates transport failure\n"); - need_auto_sense = 0; - srb->result = DID_ERROR << 16; - return; - } - - /* - * Also, if we have a short transfer on a command that can't have - * a short transfer, we're going to do this. - */ - if ((srb->result == US_BULK_TRANSFER_SHORT) && - !((srb->cmnd[0] == REQUEST_SENSE) || - (srb->cmnd[0] == INQUIRY) || - (srb->cmnd[0] == MODE_SENSE) || - (srb->cmnd[0] == LOG_SENSE) || - (srb->cmnd[0] == MODE_SENSE_10))) { - US_DEBUGP("-- unexpectedly short transfer\n"); - need_auto_sense = 1; - } - - /* Now, if we need to do the auto-sense, let's do it */ - if (need_auto_sense) { - int temp_result; - void* old_request_buffer; - int old_sg; - int old_request_bufflen; - unsigned char old_cmnd[MAX_COMMAND_SIZE]; - - US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); - - /* save the old command */ - memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); - - /* set the command and the LUN */ - srb->cmnd[0] = REQUEST_SENSE; - srb->cmnd[1] = old_cmnd[1] & 0xE0; - srb->cmnd[2] = 0; - srb->cmnd[3] = 0; - srb->cmnd[4] = 18; - srb->cmnd[5] = 0; - - /* set the buffer length for transfer */ - old_request_buffer = srb->request_buffer; - old_request_bufflen = srb->request_bufflen; - old_sg = srb->use_sg; - srb->use_sg = 0; - srb->request_bufflen = 18; - srb->request_buffer = srb->sense_buffer; - - /* issue the auto-sense command */ - temp_result = us->transport(us->srb, us); - if (temp_result != USB_STOR_TRANSPORT_GOOD) { - /* FIXME: we need to invoke a transport reset here */ - US_DEBUGP("-- auto-sense failure\n"); - srb->result = DID_ERROR << 16; - return; - } - - US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); - US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", - srb->sense_buffer[0], - srb->sense_buffer[2] & 0xf, - srb->sense_buffer[12], - srb->sense_buffer[13]); - - /* set the result so the higher layers expect this data */ - srb->result = CHECK_CONDITION; - - /* we're done here, let's clean up */ - srb->request_buffer = old_request_buffer; - srb->request_bufflen = old_request_bufflen; - srb->use_sg = old_sg; - memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); - - /* If things are really okay, then let's show that */ - if ((srb->sense_buffer[2] & 0xf) == 0x0) - srb->result = GOOD; - } else /* if (need_auto_sense) */ - srb->result = GOOD; - - /* Regardless of auto-sense, if we _know_ we have an error - * condition, show that in the result code - */ - if (result == USB_STOR_TRANSPORT_FAILED) - srb->result = CHECK_CONDITION; - - /* If we think we're good, then make sure the sense data shows it. - * This is necessary because the auto-sense for some devices always - * sets byte 0 == 0x70, even if there is no error - */ - if ((us->protocol == US_PR_CB) && - (result == USB_STOR_TRANSPORT_GOOD) && - ((srb->sense_buffer[2] & 0xf) == 0x0)) - srb->sense_buffer[0] = 0x0; -} - -/* - * Control/Bulk/Interrupt transport - */ - -/* The interrupt handler for CBI devices */ -static void CBI_irq(struct urb *urb) -{ - struct us_data *us = (struct us_data *)urb->context; - - US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no); - US_DEBUGP("-- IRQ data length is %d\n", urb->actual_length); - US_DEBUGP("-- IRQ state is %d\n", urb->status); - - /* is the device removed? */ - if (urb->status != -ENOENT) { - /* save the data for interpretation later */ - US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n", - ((unsigned char*)urb->transfer_buffer)[0], - ((unsigned char*)urb->transfer_buffer)[1]); - - - /* was this a wanted interrupt? */ - if (us->ip_wanted) { - us->ip_wanted = 0; - up(&(us->ip_waitq)); - } else - US_DEBUGP("ERROR: Unwanted interrupt received!\n"); - } else - US_DEBUGP("-- device has been removed\n"); -} - -static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - int result; - - /* COMMAND STAGE */ - /* let's send the command via the control pipe */ - result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, - us->ifnum, srb->cmnd, srb->cmd_len); - - /* check the return code for the command */ - US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); - if (result < 0) { - /* STALL must be cleared when they are detected */ - if (result == -EPIPE) { - US_DEBUGP("-- Stall on control pipe. Clearing\n"); - result = usb_clear_halt(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev, - 0)); - US_DEBUGP("-- usb_clear_halt() returns %d\n", result); - return USB_STOR_TRANSPORT_FAILED; - } - - /* Uh oh... serious problem here */ - return USB_STOR_TRANSPORT_ERROR; - } - - /* Set up for status notification */ - us->ip_wanted = 1; - - /* DATA STAGE */ - /* transfer the data payload for this command, if one exists*/ - if (us_transfer_length(srb, us)) { - us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); - US_DEBUGP("CBI data stage result is 0x%x\n", srb->result); - } - - /* STATUS STAGE */ - - /* go to sleep until we get this interrupt */ - down(&(us->ip_waitq)); - - /* if we were woken up by an abort instead of the actual interrupt */ - if (us->ip_wanted) { - US_DEBUGP("Did not get interrupt on CBI\n"); - us->ip_wanted = 0; - return USB_STOR_TRANSPORT_ERROR; - } - - US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", - ((unsigned char*)us->irq_urb->transfer_buffer)[0], - ((unsigned char*)us->irq_urb->transfer_buffer)[1]); - - /* UFI gives us ASC and ASCQ, like a request sense - * - * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI - * devices, so we ignore the information for those commands. Note - * that this means we could be ignoring a real error on these - * commands, but that can't be helped. - */ - if (us->subclass == US_SC_UFI) { - if (srb->cmnd[0] == REQUEST_SENSE || - srb->cmnd[0] == INQUIRY) - return USB_STOR_TRANSPORT_GOOD; - else - if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) - return USB_STOR_TRANSPORT_FAILED; - else - return USB_STOR_TRANSPORT_GOOD; - } - - /* If not UFI, we interpret the data as a result code - * The first byte should always be a 0x0 - * The second byte & 0x0F should be 0x0 for good, otherwise error - */ - if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) { - US_DEBUGP("CBI IRQ data showed reserved bType\n"); - return USB_STOR_TRANSPORT_ERROR; - } - switch (((unsigned char*)us->irq_urb->transfer_buffer)[1] & 0x0F) { - case 0x00: - return USB_STOR_TRANSPORT_GOOD; - case 0x01: - return USB_STOR_TRANSPORT_FAILED; - default: - return USB_STOR_TRANSPORT_ERROR; - } - - US_DEBUGP("CBI_transport() reached end of function\n"); - return USB_STOR_TRANSPORT_ERROR; -} - -/* - * Control/Bulk transport - */ -static int CB_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - int result; - - /* COMMAND STAGE */ - /* let's send the command via the control pipe */ - result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, - us->ifnum, srb->cmnd, srb->cmd_len); - - /* check the return code for the command */ - US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); - if (result < 0) { - /* 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, - usb_sndctrlpipe(us->pusb_dev, - 0)); - US_DEBUGP("-- usb_clear_halt() returns %d\n", result); - return USB_STOR_TRANSPORT_FAILED; - } - - /* Uh oh... serious problem here */ - return USB_STOR_TRANSPORT_ERROR; - } - - /* DATA STAGE */ - /* transfer the data payload for this command, if one exists*/ - if (us_transfer_length(srb, us)) { - us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); - US_DEBUGP("CB data stage result is 0x%x\n", srb->result); - } - - - /* STATUS STAGE */ - /* NOTE: CB does not have a status stage. Silly, I know. So - * we have to catch this at a higher level. - */ - return USB_STOR_TRANSPORT_GOOD; -} - -/* - * Bulk only transport - */ - -/* Determine what the maximum LUN supported is */ -static int Bulk_max_lun(struct us_data *us) -{ - unsigned char data; - int result; - int pipe; - - /* issue the command */ - pipe = usb_rcvctrlpipe(us->pusb_dev, 0); - result = usb_control_msg(us->pusb_dev, pipe, - US_BULK_GET_MAX_LUN, - USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, - 0, us->ifnum, &data, sizeof(data), HZ); - - US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", - result, data); - - /* if we have a successful request, return the result */ - if (result == 1) - return data; - - /* if we get a STALL, clear the stall */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - } - - /* return the default -- no LUNs */ - return 0; -} - -static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - struct bulk_cb_wrap bcb; - struct bulk_cs_wrap bcs; - int result; - int pipe; - int partial; - - /* set up the command wrapper */ - bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN); - bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb, us)); - bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7; - bcb.Tag = srb->serial_number; - bcb.Lun = srb->cmnd[1] >> 5; - bcb.Length = srb->cmd_len; - - /* construct the pipe handle */ - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - - /* copy the command payload */ - memset(bcb.CDB, 0, sizeof(bcb.CDB)); - memcpy(bcb.CDB, srb->cmnd, bcb.Length); - - /* send it to out endpoint */ - US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n", - le32_to_cpu(bcb.Signature), bcb.Tag, bcb.Lun, - bcb.DataTransferLength, bcb.Flags, bcb.Length); - result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, - &partial); - US_DEBUGP("Bulk command transfer result=%d\n", result); - - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - } else if (result) { - /* unknown error -- we've got a problem */ - return USB_STOR_TRANSPORT_ERROR; - } - - /* if the command transfered well, then we go to the data stage */ - if (result == 0) { - /* send/receive data payload, if there is any */ - if (bcb.DataTransferLength) { - us_transfer(srb, us, bcb.Flags); - US_DEBUGP("Bulk data transfer result 0x%x\n", - srb->result); - } - } - - /* See flow chart on pg 15 of the Bulk Only Transport spec for - * an explanation of how this code works. - */ - - /* construct the pipe handle */ - pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - - /* get CSW for device status */ - US_DEBUGP("Attempting to get CSW...\n"); - result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, - &partial); - - /* did the attempt to read the CSW fail? */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - - /* get the status again */ - US_DEBUGP("Attempting to get CSW (2nd try)...\n"); - result = usb_stor_bulk_msg(us, &bcs, pipe, - US_BULK_CS_WRAP_LEN, &partial); - - /* if it fails again, we need a reset and return an error*/ - if (result == -EPIPE) { - US_DEBUGP("clearing halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - return USB_STOR_TRANSPORT_ERROR; - } - } - - /* if we still have a failure at this point, we're in trouble */ - US_DEBUGP("Bulk status result = %d\n", result); - if (result) { - return USB_STOR_TRANSPORT_ERROR; - } - - /* check bulk status */ - US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n", - le32_to_cpu(bcs.Signature), bcs.Tag, - bcs.Residue, bcs.Status); - if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) || - bcs.Tag != bcb.Tag || - bcs.Status > US_BULK_STAT_PHASE || partial != 13) { - US_DEBUGP("Bulk logical error\n"); - return USB_STOR_TRANSPORT_ERROR; - } - - /* based on the status code, we report good or bad */ - switch (bcs.Status) { - case US_BULK_STAT_OK: - /* command good -- note that we could be short on data */ - return USB_STOR_TRANSPORT_GOOD; - - case US_BULK_STAT_FAIL: - /* command failed */ - return USB_STOR_TRANSPORT_FAILED; - - case US_BULK_STAT_PHASE: - /* phase error */ - return USB_STOR_TRANSPORT_ERROR; - } - - /* we should never get here, but if we do, we're in trouble */ - return USB_STOR_TRANSPORT_ERROR; -} - -/*********************************************************************** - * Protocol routines - ***********************************************************************/ - -static void ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) -{ - int old_cmnd = 0; - - /* Fix some commands -- this is a form of mode translation - * ATAPI devices only accept 12 byte long commands - * - * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available - */ - - /* set command length to 12 bytes */ - srb->cmd_len = 12; - - /* determine the correct (or minimum) data length for these commands */ - switch (srb->cmnd[0]) { - - /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ - case MODE_SENSE: - case MODE_SELECT: - /* save the command so we can tell what it was */ - old_cmnd = srb->cmnd[0]; - - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; - - /* change READ_6/WRITE_6 to READ_10/WRITE_10, which - * are ATAPI commands */ - case WRITE_6: - case READ_6: - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; - } /* end switch on cmnd[0] */ - - /* convert MODE_SELECT data here */ - if (old_cmnd == MODE_SELECT) - usb_stor_scsiSense6to10(srb); - - /* send the command to the transport layer */ - invoke_transport(srb, us); - - /* Fix the MODE_SENSE data if we translated the command */ - if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD)) - usb_stor_scsiSense10to6(srb); - - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ - if (srb->cmnd[0] == INQUIRY) { - ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; - } -} - - -static void ufi_command(Scsi_Cmnd *srb, struct us_data *us) -{ - int old_cmnd = 0; - - /* fix some commands -- this is a form of mode translation - * UFI devices only accept 12 byte long commands - * - * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available - */ - - /* set command length to 12 bytes (this affects the transport layer) */ - srb->cmd_len = 12; - - /* determine the correct (or minimum) data length for these commands */ - switch (srb->cmnd[0]) { - - /* for INQUIRY, UFI devices only ever return 36 bytes */ - case INQUIRY: - srb->cmnd[4] = 36; - break; - - /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ - case MODE_SENSE: - case MODE_SELECT: - /* save the command so we can tell what it was */ - old_cmnd = srb->cmnd[0]; - - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - - /* if we're sending data, we send all. If getting data, - * get the minimum */ - if (srb->cmnd[0] == MODE_SELECT) - srb->cmnd[8] = srb->cmnd[4]; - else - srb->cmnd[8] = 8; - - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; - - /* again, for MODE_SENSE_10, we get the minimum (8) */ - case MODE_SENSE_10: - srb->cmnd[7] = 0; - srb->cmnd[8] = 8; - break; - - /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */ - case REQUEST_SENSE: - srb->cmnd[4] = 18; - break; - - /* change READ_6/WRITE_6 to READ_10/WRITE_10, which - * are UFI commands */ - case WRITE_6: - case READ_6: - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; - } /* end switch on cmnd[0] */ - - /* convert MODE_SELECT data here */ - if (old_cmnd == MODE_SELECT) - usb_stor_scsiSense6to10(srb); - - /* send the command to the transport layer */ - invoke_transport(srb, us); - - /* Fix the MODE_SENSE data if we translated the command */ - if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD)) - usb_stor_scsiSense10to6(srb); - - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ - if (srb->cmnd[0] == INQUIRY) { - ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; - } -} - -static void transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) -{ - /* This code supports devices which do not support {READ|WRITE}_6 - * Apparently, neither Windows or MacOS will use these commands, - * so some devices do not support them - */ - if (us->flags & US_FL_MODE_XLATE) { - - /* translate READ_6 to READ_10 */ - if (srb->cmnd[0] == 0x08) { - - /* get the control */ - srb->cmnd[9] = us->srb->cmnd[5]; - - /* get the length */ - srb->cmnd[8] = us->srb->cmnd[6]; - srb->cmnd[7] = 0; - - /* set the reserved area to 0 */ - srb->cmnd[6] = 0; - - /* get LBA */ - srb->cmnd[5] = us->srb->cmnd[3]; - srb->cmnd[4] = us->srb->cmnd[2]; - srb->cmnd[3] = 0; - srb->cmnd[2] = 0; - - /* LUN and other info in cmnd[1] can stay */ - - /* fix command code */ - srb->cmnd[0] = 0x28; - - US_DEBUGP("Changing READ_6 to READ_10\n"); - US_DEBUG(us_show_command(srb)); - } - - /* translate WRITE_6 to WRITE_10 */ - if (srb->cmnd[0] == 0x0A) { - - /* get the control */ - srb->cmnd[9] = us->srb->cmnd[5]; - - /* get the length */ - srb->cmnd[8] = us->srb->cmnd[4]; - srb->cmnd[7] = 0; - - /* set the reserved area to 0 */ - srb->cmnd[6] = 0; - - /* get LBA */ - srb->cmnd[5] = us->srb->cmnd[3]; - srb->cmnd[4] = us->srb->cmnd[2]; - srb->cmnd[3] = 0; - srb->cmnd[2] = 0; - - /* LUN and other info in cmnd[1] can stay */ - - /* fix command code */ - srb->cmnd[0] = 0x2A; - - US_DEBUGP("Changing WRITE_6 to WRITE_10\n"); - US_DEBUG(us_show_command(us->srb)); - } - } /* if (us->flags & US_FL_MODE_XLATE) */ - - /* send the command to the transport layer */ - invoke_transport(srb, us); - - /* fix the results of an INQUIRY */ - if (srb->cmnd[0] == INQUIRY) { - US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n"); - ((unsigned char*)us->srb->request_buffer)[2] |= 2; - } -} - -/*********************************************************************** - * Reset routines - ***********************************************************************/ - -/* This issues a CB[I] Reset to the device in question - */ -static int CB_reset(struct us_data *us) -{ - unsigned char cmd[12]; - int result; - - US_DEBUGP("CB_reset() called\n"); - - memset(cmd, 0xFF, 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_RECIP_INTERFACE, - 0, us->ifnum, cmd, sizeof(cmd), HZ*5); - - /* long wait for reset */ - schedule_timeout(HZ*6); - - US_DEBUGP("CB_reset: clearing endpoint halt\n"); - usb_clear_halt(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); - usb_clear_halt(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_out)); - - US_DEBUGP("CB_reset done\n"); - return 0; -} - -/* FIXME: Does this work? */ -static int Bulk_reset(struct us_data *us) -{ - int result; - - result = usb_control_msg(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev,0), - US_BULK_RESET_REQUEST, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, NULL, 0, HZ*5); - - if (result < 0) - US_DEBUGP("Bulk hard reset failed %d\n", result); - - usb_clear_halt(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); - usb_clear_halt(us->pusb_dev, - usb_sndbulkpipe(us->pusb_dev, us->ep_out)); - - /* long wait for reset */ - schedule_timeout(HZ*6); - - return result; -} - -/*********************************************************************** - * Host functions - ***********************************************************************/ - -static const char* us_info(struct Scsi_Host *host) -{ - return "SCSI emulation for USB Mass Storage devices"; -} - -/* detect a virtual adapter (always works) */ -static int us_detect(struct SHT *sht) -{ - struct us_data *us; - char local_name[32]; - - /* This is not nice at all, but how else are we to get the - * data here? */ - us = (struct us_data *)sht->proc_dir; - - /* set up the name of our subdirectory under /proc/scsi/ */ - sprintf(local_name, "usb-storage-%d", us->host_number); - sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); - if (!sht->proc_name) - return 0; - strcpy(sht->proc_name, local_name); - - /* we start with no /proc directory entry */ - sht->proc_dir = NULL; - - /* register the host */ - 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; - } - - /* odd... didn't register properly. Abort and free pointers */ - kfree(sht->proc_name); - sht->proc_name = NULL; - return 0; -} - -/* Release all resources used by the virtual host - * - * NOTE: There is no contention here, because we're allready deregistered - * the driver and we're doing each virtual host in turn, not in parallel - */ -static int us_release(struct Scsi_Host *psh) -{ - struct us_data *us = (struct us_data *)psh->hostdata[0]; - - US_DEBUGP("us_release() called for host %s\n", us->htmplt.name); - - /* Kill the control threads - * - * Enqueue the command, wake up the thread, and wait for - * notification that it's exited. - */ - US_DEBUGP("-- sending US_ACT_EXIT command to thread\n"); - us->action = US_ACT_EXIT; - up(&(us->sleeper)); - down(&(us->notify)); - - /* free the data structure we were using */ - US_DEBUGP("-- freeing URB\n"); - kfree(us->current_urb); - (struct us_data*)psh->hostdata[0] = NULL; - - /* we always have a successful release */ - return 0; -} - -/* run command */ -static int us_command( Scsi_Cmnd *srb ) -{ - US_DEBUGP("Bad use of us_command\n"); - - 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]; - - US_DEBUGP("us_queuecommand() called\n"); - srb->host_scribble = (unsigned char *)us; - - /* get exclusive access to the structures we want */ - down(&(us->queue_exclusion)); - - /* enqueue the command */ - us->queue_srb = srb; - srb->scsi_done = done; - us->action = US_ACT_COMMAND; - - /* wake up the process task */ - up(&(us->queue_exclusion)); - up(&(us->sleeper)); - - return 0; -} - -/*********************************************************************** - * Error handling functions - ***********************************************************************/ - -/* Command abort - * - * Note that this is really only meaningful right now for CBI transport - * devices which have failed to give us the command completion interrupt - */ -static int us_abort( Scsi_Cmnd *srb ) -{ - struct us_data *us = (struct us_data *)srb->host->hostdata[0]; - - US_DEBUGP("us_abort() called\n"); - - /* if we're stuck waiting for an IRQ, simulate it */ - if (us->ip_wanted) { - US_DEBUGP("-- simulating missing IRQ\n"); - up(&(us->ip_waitq)); - return SUCCESS; - } - - return FAILED; -} - -/* FIXME: this doesn't do anything right now */ -static int us_bus_reset( Scsi_Cmnd *srb ) -{ - // struct us_data *us = (struct us_data *)srb->host->hostdata[0]; - - printk(KERN_CRIT "usb-storage: bus_reset() requested but not implemented\n" ); - US_DEBUGP("Bus reset requested\n"); - // us->transport_reset(us); - return FAILED; -} - -/* FIXME: This doesn't actually reset anything */ -static int us_host_reset( Scsi_Cmnd *srb ) -{ - printk(KERN_CRIT "usb-storage: host_reset() requested but not implemented\n" ); - return FAILED; -} - -/*********************************************************************** - * /proc/scsi/ functions - ***********************************************************************/ - -/* we use this macro to help us write into the buffer */ -#undef SPRINTF -#define SPRINTF(args...) \ - do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) - -int usb_stor_proc_info (char *buffer, char **start, off_t offset, - int length, int hostno, int inout) -{ - struct us_data *us; - char *pos = buffer; - - /* if someone is sending us data, just throw it away */ - if (inout) - return length; - - /* lock the data structures */ - down(&us_list_semaphore); - - /* find our data from hostno */ - us = us_list; - while (us) { - if (us->host_no == hostno) - break; - us = us->next; - } - - /* if we couldn't find it, we return an error */ - if (!us) { - up(&us_list_semaphore); - return -ESRCH; - } - - /* print the controler name */ - SPRINTF(" Host scsi%d: usb-storage\n", hostno); - - /* print product, vendor, and serial number strings */ - SPRINTF(" Vendor: %s\n", us->vendor); - SPRINTF(" Product: %s\n", us->product); - SPRINTF("Serial Number: %s\n", us->serial); - - /* show the protocol and transport */ - SPRINTF(" Protocol: %s\n", us->protocol_name); - SPRINTF(" Transport: %s\n", us->transport_name); - - /* show the GUID of the device */ - SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); - - /* release our lock on the data structures */ - up(&us_list_semaphore); - - /* - * 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); -} - -/* - * this defines our 'host' - */ - -static Scsi_Host_Template my_host_template = { - name: "usb-storage", - proc_info: usb_stor_proc_info, - info: us_info, - - detect: us_detect, - release: us_release, - command: us_command, - queuecommand: us_queuecommand, - - eh_abort_handler: us_abort, - eh_device_reset_handler:us_bus_reset, - eh_bus_reset_handler: us_bus_reset, - eh_host_reset_handler: us_host_reset, - - can_queue: 1, - this_id: -1, - - sg_tablesize: SG_ALL, - cmd_per_lun: 1, - present: 0, - unchecked_isa_dma: FALSE, - use_clustering: TRUE, - use_new_eh_code: TRUE, - emulated: TRUE -}; - -static unsigned char sense_notready[] = { - [0] = 0x70, /* current error */ - [2] = 0x02, /* not ready */ - [5] = 0x0a, /* additional length */ - [10] = 0x04, /* not ready */ - [11] = 0x03 /* manual intervention */ -}; - -static int usb_stor_control_thread(void * __us) -{ - struct us_data *us = (struct us_data *)__us; - int action; - - lock_kernel(); - - /* - * This thread doesn't need any user-level access, - * so get rid of all our resources.. - */ - daemonize(); - - /* set our name for identification purposes */ - sprintf(current->comm, "usb-storage-%d", us->host_number); - - unlock_kernel(); - - /* signal that we've started the thread */ - up(&(us->notify)); - - for(;;) { - US_DEBUGP("*** thread sleeping.\n"); - down(&(us->sleeper)); - down(&(us->queue_exclusion)); - US_DEBUGP("*** thread awakened.\n"); - - /* take the command off the queue */ - action = us->action; - us->action = 0; - us->srb = us->queue_srb; - - /* release the queue lock as fast as possible */ - up(&(us->queue_exclusion)); - - switch (action) { - case US_ACT_COMMAND: - /* reject if target != 0 or if LUN is higher than - * the maximum known LUN - */ - if (us->srb->target || (us->srb->lun > us->max_lun)) { - US_DEBUGP("Bad device number (%d/%d)\n", - us->srb->target, us->srb->lun); - - us->srb->result = DID_BAD_TARGET << 16; - - us->srb->scsi_done(us->srb); - us->srb = NULL; - break; - } - - /* handle those devices which can't do a START_STOP */ - if ((us->srb->cmnd[0] == START_STOP) && - (us->flags & US_FL_START_STOP)) { - us->srb->result = GOOD; - us->srb->scsi_done(us->srb); - us->srb = NULL; - break; - } - - /* lock the device pointers */ - down(&(us->dev_semaphore)); - - /* our device has gone - pretend not ready */ - if (!us->pusb_dev) { - US_DEBUGP("Request is for removed device\n"); - /* For REQUEST_SENSE, it's the data. But - * for anything else, it should look like - * we auto-sensed for it. - */ - if (us->srb->cmnd[0] == REQUEST_SENSE) { - memcpy(us->srb->request_buffer, - sense_notready, - sizeof(sense_notready)); - us->srb->result = GOOD; - } else { - memcpy(us->srb->sense_buffer, - sense_notready, - sizeof(sense_notready)); - us->srb->result = CHECK_CONDITION; - } - } else { /* !us->pusb_dev */ - /* we've got a command, let's do it! */ - US_DEBUG(us_show_command(us->srb)); - us->proto_handler(us->srb, us); - } - - /* unlock the device pointers */ - up(&(us->dev_semaphore)); - - /* indicate that the command is done */ - US_DEBUGP("scsi cmd done, result=0x%x\n", - us->srb->result); - us->srb->scsi_done(us->srb); - us->srb = NULL; - break; - - case US_ACT_DEVICE_RESET: - break; - - case US_ACT_BUS_RESET: - break; - - case US_ACT_HOST_RESET: - break; - - } /* end switch on action */ - - /* exit if we get a signal to exit */ - if (action == US_ACT_EXIT) { - US_DEBUGP("-- US_ACT_EXIT command recieved\n"); - break; - } - } /* for (;;) */ - - /* notify the exit routine that we're actually exiting now */ - up(&(us->notify)); - - return 0; -} - -/* This is the list of devices we recognize, along with their flag data */ -static struct us_unusual_dev us_unusual_dev_list[] = { - { 0x03f0, 0x0107, 0x0200, 0x0200, "HP USB CD-Writer Plus", - US_SC_8070, US_PR_CB, 0}, - { 0x04e6, 0x0001, 0x0200, 0x0200, "Matshita LS-120", - US_SC_8020, US_PR_CB, US_FL_SINGLE_LUN}, - { 0x04e6, 0x0002, 0x0100, 0x0100, "Shuttle eUSCSI Bridge", - US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x04e6, 0x0006, 0x0100, 0x0100, "Shuttle eUSB MMC Adapter", - US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, - { 0x054c, 0x0010, 0x0210, 0x0210, "Sony DSC-S30", - US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP | - US_FL_MODE_XLATE | US_FL_ALT_LENGTH}, - { 0x054c, 0x002d, 0x0100, 0x0100, "Sony Memorystick MSAC-US1", - US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP | - US_FL_MODE_XLATE | US_FL_ALT_LENGTH}, - { 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data Flashbuster-U", - US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN}, - { 0x057b, 0x0000, 0x0300, 0x9999, "Y-E Data Flashbuster-U", - US_SC_UFI, US_PR_CBI, US_FL_SINGLE_LUN}, - { 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara FlashGate SmartMedia", - US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-01)", - US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP}, - { 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk Imagemate (SDDR-31)", - US_SC_SCSI, US_PR_BULK, US_FL_IGNORE_SER}, - { 0x07af, 0x0005, 0x0100, 0x0100, "Microtech USB-SCSI-HD50", - US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x05ab, 0x0031, 0x0100, 0x0100, "In-System USB/IDE Bridge", - US_SC_8070, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x0693, 0x0005, 0x0100, 0x0100, "Hagiwara Flashgate", - US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0 }}; - -/* Search our ususual device list, based on vendor/product combinations - * to see if we can support this device. Returns a pointer to a structure - * defining how we should support this device, or NULL if it's not in the - * list - */ -static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct, - u16 bcdDevice) -{ - struct us_unusual_dev* ptr; - - US_DEBUGP("Searching unusual device list for (0x%x, 0x%x, 0x%x)...\n", - idVendor, idProduct, bcdDevice); - - ptr = us_unusual_dev_list; - while ((ptr->idVendor != 0x0000) && - !((ptr->idVendor == idVendor) && - (ptr->idProduct == idProduct) && - (ptr->bcdDeviceMin <= bcdDevice) && - (ptr->bcdDeviceMax >= bcdDevice))) - ptr++; - - /* if the search ended because we hit the end record, we failed */ - if (ptr->idVendor == 0x0000) { - US_DEBUGP("-- did not find a matching device\n"); - return NULL; - } - - /* otherwise, we found one! */ - US_DEBUGP("-- found matching device: %s\n", ptr->name); - return ptr; -} - -/* Set up the IRQ pipe and handler - * Note that this function assumes that all the data in the us_data - * strucuture is current. This includes the ep_int field, which gives us - * the endpoint for the interrupt. - * Returns non-zero on failure, zero on success - */ -static int usb_stor_allocate_irq(struct us_data *ss) -{ - unsigned int pipe; - int maxp; - int result; - - US_DEBUGP("Allocating IRQ for CBI transport\n"); - - /* lock access to the data structure */ - down(&(ss->irq_urb_sem)); - - /* allocate the URB */ - ss->irq_urb = usb_alloc_urb(0); - if (!ss->irq_urb) { - up(&(ss->irq_urb_sem)); - US_DEBUGP("couldn't allocate interrupt URB"); - return 1; - } - - /* calculate the pipe and max packet size */ - pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK); - maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe)); - if (maxp > sizeof(ss->irqbuf)) - maxp = sizeof(ss->irqbuf); - - /* fill in the URB with our data */ - FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp, - CBI_irq, ss, ss->ep_int->bInterval); - - /* submit the URB for processing */ - result = usb_submit_urb(ss->irq_urb); - US_DEBUGP("usb_submit_urb() returns %d\n", result); - if (result) { - usb_free_urb(ss->irq_urb); - up(&(ss->irq_urb_sem)); - return 2; - } - - /* unlock the data structure and return success */ - up(&(ss->irq_urb_sem)); - return 0; -} - -/* Probe to see if a new device is actually a SCSI device */ -static void * storage_probe(struct usb_device *dev, unsigned int ifnum) -{ - int i; - char mf[USB_STOR_STRING_LEN]; /* manufacturer */ - char prod[USB_STOR_STRING_LEN]; /* product */ - char serial[USB_STOR_STRING_LEN]; /* serial number */ - GUID(guid); /* Global Unique Identifier */ - unsigned int flags; - struct us_unusual_dev *unusual_dev; - struct us_data *ss = NULL; - int result; - - /* these are temporary copies -- we test on these, then put them - * in the us-data structure - */ - struct usb_endpoint_descriptor *ep_in = NULL; - struct usb_endpoint_descriptor *ep_out = NULL; - struct usb_endpoint_descriptor *ep_int = NULL; - u8 subclass = 0; - u8 protocol = 0; - - /* the altsettting 0 on the interface we're probing */ - struct usb_interface_descriptor *altsetting = - &(dev->actconfig->interface[ifnum].altsetting[0]); - - /* clear the temporary strings */ - memset(mf, 0, sizeof(mf)); - memset(prod, 0, sizeof(prod)); - memset(serial, 0, sizeof(serial)); - - /* search for this device in our unusual device list */ - unusual_dev = us_find_dev(dev->descriptor.idVendor, - dev->descriptor.idProduct, - dev->descriptor.bcdDevice); - - /* - * Can we support this device, either because we know about it - * from our unusual device list, or because it advertises that it's - * compliant to the specification? - */ - if (!unusual_dev && - !(dev->descriptor.bDeviceClass == 0 && - altsetting->bInterfaceClass == USB_CLASS_MASS_STORAGE && - altsetting->bInterfaceSubClass >= US_SC_MIN && - altsetting->bInterfaceSubClass <= US_SC_MAX)) { - /* if it's not a mass storage, we go no further */ - return NULL; - } - - /* At this point, we know we've got a live one */ - US_DEBUGP("USB Mass Storage device detected\n"); - - /* Determine subclass and protocol, or copy from the interface */ - if (unusual_dev) { - subclass = unusual_dev->useProtocol; - protocol = unusual_dev->useTransport; - flags = unusual_dev->flags; - } else { - subclass = altsetting->bInterfaceSubClass; - protocol = altsetting->bInterfaceProtocol; - flags = 0; - } - - /* - * Find the endpoints we need - * 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 < altsetting->bNumEndpoints; i++) { - /* is it an BULK endpoint? */ - if ((altsetting->endpoint[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { - /* BULK in or out? */ - if (altsetting->endpoint[i].bEndpointAddress & - USB_DIR_IN) - ep_in = &altsetting->endpoint[i]; - else - ep_out = &altsetting->endpoint[i]; - } - - /* is it an interrupt endpoint? */ - if ((altsetting->endpoint[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { - ep_int = &altsetting->endpoint[i]; - } - } - US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n", - ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0); - - /* set the interface -- STALL is an acceptable response here */ - result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0); - US_DEBUGP("Result from usb_set_interface is %d\n", result); - if (result == -EPIPE) { - US_DEBUGP("-- clearing stall on control interface\n"); - usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); - } else if (result != 0) { - /* it's not a stall, but another error -- time to bail */ - US_DEBUGP("-- Unknown error. Rejecting device\n"); - return NULL; - } - - /* Do some basic sanity checks, and bail if we find a problem */ - if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) { - US_DEBUGP("Sanity check failed. Rejecting device.\n"); - return NULL; - } - - /* At this point, we're committed to using the device */ - - /* clear the GUID and fetch the strings */ - GUID_CLEAR(guid); - if (dev->descriptor.iManufacturer) - usb_string(dev, dev->descriptor.iManufacturer, - mf, sizeof(mf)); - if (dev->descriptor.iProduct) - usb_string(dev, dev->descriptor.iProduct, - prod, sizeof(prod)); - if (dev->descriptor.iSerialNumber && !(flags & US_FL_IGNORE_SER)) - usb_string(dev, dev->descriptor.iSerialNumber, - serial, sizeof(serial)); - - /* Create a GUID for this device */ - if (dev->descriptor.iSerialNumber && serial[0]) { - /* If we have a serial number, and it's a non-NULL string */ - make_guid(guid, dev->descriptor.idVendor, - dev->descriptor.idProduct, serial); - } else { - /* We don't have a serial number, so we use 0 */ - make_guid(guid, dev->descriptor.idVendor, - dev->descriptor.idProduct, "0"); - } - - /* lock access to the data structures */ - down(&us_list_semaphore); - - /* - * Now check if we have seen this GUID before - * We're looking for a device with a matching GUID that isn't - * allready on the system - */ - ss = us_list; - while ((ss != NULL) && - ((ss->pusb_dev) || !GUID_EQUAL(guid, ss->guid))) - ss = ss->next; - - if (ss != NULL) { - /* Existing device -- re-connect */ - US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", - GUID_ARGS(guid)); - - /* establish the connection to the new device upon reconnect */ - ss->ifnum = ifnum; - ss->pusb_dev = dev; - - /* copy over the endpoint data */ - if (ep_in) - ss->ep_in = ep_in->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - if (ep_out) - ss->ep_out = ep_out->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - ss->ep_int = ep_int; - - /* allocate an IRQ callback if one is needed */ - if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) - return NULL; - } else { - /* New device -- allocate memory and initialize */ - US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); - - if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data), - GFP_KERNEL)) == NULL) { - printk(KERN_WARNING USB_STORAGE "Out of memory\n"); - up(&us_list_semaphore); - return NULL; - } - memset(ss, 0, sizeof(struct us_data)); - - /* allocate the URB we're going to use */ - ss->current_urb = usb_alloc_urb(0); - if (!ss->current_urb) { - kfree(ss); - return NULL; - } - - /* Initialize the mutexes only when the struct is new */ - init_MUTEX_LOCKED(&(ss->sleeper)); - init_MUTEX_LOCKED(&(ss->notify)); - init_MUTEX_LOCKED(&(ss->ip_waitq)); - init_MUTEX(&(ss->queue_exclusion)); - init_MUTEX(&(ss->irq_urb_sem)); - init_MUTEX(&(ss->current_urb_sem)); - init_MUTEX(&(ss->dev_semaphore)); - - /* copy over the subclass and protocol data */ - ss->subclass = subclass; - ss->protocol = protocol; - ss->flags = flags; - - /* copy over the endpoint data */ - if (ep_in) - ss->ep_in = ep_in->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - if (ep_out) - ss->ep_out = ep_out->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - ss->ep_int = ep_int; - - /* establish the connection to the new device */ - ss->ifnum = ifnum; - ss->pusb_dev = dev; - - /* copy over the identifiying strings */ - strncpy(ss->vendor, mf, USB_STOR_STRING_LEN); - strncpy(ss->product, prod, USB_STOR_STRING_LEN); - strncpy(ss->serial, serial, USB_STOR_STRING_LEN); - if (strlen(ss->vendor) == 0) - strncpy(ss->vendor, "Unknown", USB_STOR_STRING_LEN); - if (strlen(ss->product) == 0) - strncpy(ss->product, "Unknown", USB_STOR_STRING_LEN); - if (strlen(ss->serial) == 0) - strncpy(ss->serial, "None", USB_STOR_STRING_LEN); - - /* copy the GUID we created before */ - memcpy(ss->guid, guid, sizeof(guid)); - - /* - * Set the handler pointers based on the protocol - * Again, this data is persistant across reattachments - */ - switch (ss->protocol) { - case US_PR_CB: - ss->transport_name = "Control/Bulk"; - ss->transport = CB_transport; - ss->transport_reset = CB_reset; - ss->max_lun = 7; - break; - - case US_PR_CBI: - ss->transport_name = "Control/Bulk/Interrupt"; - ss->transport = CBI_transport; - ss->transport_reset = CB_reset; - ss->max_lun = 7; - break; - - case US_PR_BULK: - ss->transport_name = "Bulk"; - ss->transport = Bulk_transport; - ss->transport_reset = Bulk_reset; - ss->max_lun = Bulk_max_lun(ss); - break; - - default: - ss->transport_name = "Unknown"; - up(&us_list_semaphore); - kfree(ss->current_urb); - kfree(ss); - return NULL; - break; - } - US_DEBUGP("Transport: %s\n", ss->transport_name); - - /* fix for single-lun devices */ - if (ss->flags & US_FL_SINGLE_LUN) - ss->max_lun = 0; - - switch (ss->subclass) { - case US_SC_RBC: - ss->protocol_name = "Reduced Block Commands (RBC)"; - ss->proto_handler = transparent_scsi_command; - break; - - case US_SC_8020: - ss->protocol_name = "8020i"; - ss->proto_handler = ATAPI_command; - break; - - case US_SC_QIC: - ss->protocol_name = "QIC-157"; - US_DEBUGP("Sorry, device not supported. Please\n"); - US_DEBUGP("contact mdharm-usb@one-eyed-alien.net\n"); - US_DEBUGP("if you see this message.\n"); - up(&us_list_semaphore); - kfree(ss->current_urb); - kfree(ss); - return NULL; - break; - - case US_SC_8070: - ss->protocol_name = "8070i"; - ss->proto_handler = ATAPI_command; - break; - - case US_SC_SCSI: - ss->protocol_name = "Transparent SCSI"; - ss->proto_handler = transparent_scsi_command; - break; - - case US_SC_UFI: - ss->protocol_name = "Uniform Floppy Interface (UFI)"; - ss->proto_handler = ufi_command; - break; - - default: - ss->protocol_name = "Unknown"; - up(&us_list_semaphore); - kfree(ss->current_urb); - kfree(ss); - return NULL; - break; - } - US_DEBUGP("Protocol: %s\n", ss->protocol_name); - - /* allocate an IRQ callback if one is needed */ - if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) - return NULL; - - /* - * Since this is a new device, we need to generate a scsi - * host definition, and register with the higher SCSI layers - */ - - /* Initialize the host template based on the default one */ - memcpy(&(ss->htmplt), &my_host_template, - sizeof(my_host_template)); - - /* Grab the next host number */ - ss->host_number = my_host_number++; - - /* We abuse this pointer so we can pass the ss pointer to - * the host controler thread in us_detect. But how else are - * we to do it? - */ - (struct us_data *)ss->htmplt.proc_dir = ss; - - /* start up our control thread */ - ss->pid = kernel_thread(usb_stor_control_thread, ss, - CLONE_FS | CLONE_FILES | - CLONE_SIGHAND); - if (ss->pid < 0) { - printk(KERN_WARNING USB_STORAGE - "Unable to start control thread\n"); - kfree(ss->current_urb); - kfree(ss); - return NULL; - } - - /* wait for the thread to start */ - down(&(ss->notify)); - - /* now register - our detect function will be called */ - ss->htmplt.module = THIS_MODULE; - scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt)); - - /* put us in the list */ - ss->next = us_list; - us_list = ss; - } - - /* release the data structure lock */ - up(&us_list_semaphore); - - printk(KERN_DEBUG - "WARNING: USB Mass Storage data integrity not assured\n"); - printk(KERN_DEBUG - "USB Mass Storage device found at %d\n", dev->devnum); - - /* return a pointer for the disconnect function */ - return ss; -} - -/* Handle a disconnect event from the USB core */ -static void storage_disconnect(struct usb_device *dev, void *ptr) -{ - struct us_data *ss = ptr; - int result; - - US_DEBUGP("storage_disconnect() called\n"); - - /* this is the odd case -- we disconnected but weren't using it */ - if (!ss) { - US_DEBUGP("-- device was not in use\n"); - return; - } - - /* lock access to the device data structure */ - down(&(ss->dev_semaphore)); - - /* release the IRQ, if we have one */ - down(&(ss->irq_urb_sem)); - if (ss->irq_urb) { - US_DEBUGP("-- releasing irq handle\n"); - result = usb_unlink_urb(ss->irq_urb); - ss->irq_urb = NULL; - US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); - usb_free_urb(ss->irq_urb); - } - up(&(ss->irq_urb_sem)); - - /* mark the device as gone */ - ss->pusb_dev = NULL; - - /* lock access to the device data structure */ - up(&(ss->dev_semaphore)); -} - -/************************************************************** - **************************************************************/ - -#define USB_STOR_SCSI_SENSE_HDRSZ 4 -#define USB_STOR_SCSI_SENSE_10_HDRSZ 8 - -struct usb_stor_scsi_sense_hdr -{ - __u8* dataLength; - __u8* mediumType; - __u8* devSpecParms; - __u8* blkDescLength; -}; - -typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr; - -union usb_stor_scsi_sense_hdr_u -{ - Usb_Stor_Scsi_Sense_Hdr hdr; - __u8* array[USB_STOR_SCSI_SENSE_HDRSZ]; -}; - -typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u; - -struct usb_stor_scsi_sense_hdr_10 -{ - __u8* dataLengthMSB; - __u8* dataLengthLSB; - __u8* mediumType; - __u8* devSpecParms; - __u8* reserved1; - __u8* reserved2; - __u8* blkDescLengthMSB; - __u8* blkDescLengthLSB; -}; - -typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10; - -union usb_stor_scsi_sense_hdr_10_u -{ - Usb_Stor_Scsi_Sense_Hdr_10 hdr; - __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ]; -}; - -typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u; - -void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*, - Usb_Stor_Scsi_Sense_Hdr_10_u*, int* ); -void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd ); - -int -usb_stor_scsiSense10to6( Scsi_Cmnd* the10 ) -{ - __u8 *buffer=0; - int outputBufferSize = 0; - int length=0; - struct scatterlist *sg = 0; - int i=0, j=0, element=0; - Usb_Stor_Scsi_Sense_Hdr_u the6Locations; - Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; - int sb=0,si=0,db=0,di=0; - int sgLength=0; - -#if 0 - /* Make sure we get a MODE_SENSE_10 command */ - if ( the10->cmnd[0] != MODE_SENSE_10 ) - { - printk( KERN_ERR USB_STORAGE - "Scsi_Cmnd was not a MODE_SENSE_10.\n" ); - return -1; - } - - /* Now start to format the output */ - the10->cmnd[0] = MODE_SENSE; -#endif - US_DEBUGP("-- converting 10 byte sense data to 6 byte\n"); - the10->cmnd[0] = the10->cmnd[0] & 0xBF; - - /* Determine buffer locations */ - usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations, - &length ); - - /* Work out minimum buffer to output */ - outputBufferSize = *the10Locations.hdr.dataLengthLSB; - outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ; - - /* Check to see if we need to truncate the output */ - if ( outputBufferSize > length ) - { - printk( KERN_WARNING USB_STORAGE - "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" ); - printk( KERN_WARNING USB_STORAGE - "outputBufferSize is %d and length is %d.\n", - outputBufferSize, length ); - } - outputBufferSize = length; - - /* Data length */ - if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */ - { - printk( KERN_WARNING USB_STORAGE - "Command will be truncated to fit in SENSE6 buffer.\n" ); - *the6Locations.hdr.dataLength = 0xff; - } - else - { - *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB; - } - - /* Medium type and DevSpecific parms */ - *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType; - *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms; - - /* Block descriptor length */ - if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */ - { - printk( KERN_WARNING USB_STORAGE - "Command will be truncated to fit in SENSE6 buffer.\n" ); - *the6Locations.hdr.blkDescLength = 0xff; - } - else - { - *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB; - } - - if ( the10->use_sg == 0 ) - { - buffer = the10->request_buffer; - /* Copy the rest of the data */ - memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), - &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ ); - /* initialise last bytes left in buffer due to smaller header */ - memset( &(buffer[outputBufferSize - -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]), - 0, - USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); - } - else - { - sg = (struct scatterlist *) the10->request_buffer; - /* scan through this scatterlist and figure out starting positions */ - for ( i=0; i < the10->use_sg; i++) - { - sgLength = sg[i].length; - for ( j=0; j<sgLength; j++ ) - { - /* get to end of header */ - if ( element == USB_STOR_SCSI_SENSE_HDRSZ ) - { - db=i; - di=j; - } - if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - sb=i; - si=j; - /* we've found both sets now, exit loops */ - j=sgLength; - i=the10->use_sg; - } - element++; - } - } - - /* Now we know where to start the copy from */ - element = USB_STOR_SCSI_SENSE_HDRSZ; - while ( element < outputBufferSize - -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) - { - /* check limits */ - if ( sb >= the10->use_sg || - si >= sg[sb].length || - db >= the10->use_sg || - di >= sg[db].length ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - /* copy one byte */ - sg[db].address[di] = sg[sb].address[si]; - - /* get next destination */ - if ( sg[db].length-1 == di ) - { - db++; - di=0; - } - else - { - di++; - } - - /* get next source */ - if ( sg[sb].length-1 == si ) - { - sb++; - si=0; - } - else - { - si++; - } - - element++; - } - /* zero the remaining bytes */ - while ( element < outputBufferSize ) - { - /* check limits */ - if ( db >= the10->use_sg || - di >= sg[db].length ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - sg[db].address[di] = 0; - - /* get next destination */ - if ( sg[db].length-1 == di ) - { - db++; - di=0; - } - else - { - di++; - } - element++; - } - } - - /* All done any everything was fine */ - return 0; -} - -int -usb_stor_scsiSense6to10( Scsi_Cmnd* the6 ) -{ - /* will be used to store part of buffer */ - __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ], - *buffer=0; - int outputBufferSize = 0; - int length=0; - struct scatterlist *sg = 0; - int i=0, j=0, element=0; - Usb_Stor_Scsi_Sense_Hdr_u the6Locations; - Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; - int sb=0,si=0,db=0,di=0; - int lsb=0,lsi=0,ldb=0,ldi=0; - -#if 0 - /* Make sure we get a MODE_SENSE command */ - if ( the6->cmnd[0] != MODE_SENSE ) - { - printk( KERN_ERR USB_STORAGE - "Scsi_Cmnd was not MODE_SENSE.\n" ); - return -1; - } - - /* Now start to format the output */ - the6->cmnd[0] = MODE_SENSE_10; -#endif - US_DEBUGP("-- converting 6 byte sense data to 10 byte\n"); - the6->cmnd[0] = the6->cmnd[0] | 0x40; - - /* Determine buffer locations */ - usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations, - &length ); - - /* Work out minimum buffer to output */ - outputBufferSize = *the6Locations.hdr.dataLength; - outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ; - - /* Check to see if we need to trucate the output */ - if ( outputBufferSize > length ) - { - printk( KERN_WARNING USB_STORAGE - "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" ); - printk( KERN_WARNING USB_STORAGE - "outputBufferSize is %d and length is %d.\n", - outputBufferSize, length ); - } - outputBufferSize = length; - - /* Block descriptor length - save these before overwriting */ - tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB; - tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB; - *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength; - *the10Locations.hdr.blkDescLengthMSB = 0; - - /* reserved - save these before overwriting */ - tempBuffer[0] = *the10Locations.hdr.reserved1; - tempBuffer[1] = *the10Locations.hdr.reserved2; - *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0; - - /* Medium type and DevSpecific parms */ - *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms; - *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType; - - /* Data length */ - *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength; - *the10Locations.hdr.dataLengthMSB = 0; - - if ( !the6->use_sg ) - { - buffer = the6->request_buffer; - /* Copy the rest of the data */ - memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), - outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ ); - /* Put the first four bytes (after header) in place */ - memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - tempBuffer, - USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); - } - else - { - sg = (struct scatterlist *) the6->request_buffer; - /* scan through this scatterlist and figure out ending positions */ - for ( i=0; i < the6->use_sg; i++) - { - for ( j=0; j<sg[i].length; j++ ) - { - /* get to end of header */ - if ( element == USB_STOR_SCSI_SENSE_HDRSZ ) - { - ldb=i; - ldi=j; - } - if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - lsb=i; - lsi=j; - /* we've found both sets now, exit loops */ - j=sg[i].length; - i=the6->use_sg; - break; - } - element++; - } - } - /* scan through this scatterlist and figure out starting positions */ - element = length-1; - /* destination is the last element */ - db=the6->use_sg-1; - di=sg[db].length-1; - for ( i=the6->use_sg-1; i >= 0; i--) - { - for ( j=sg[i].length-1; j>=0; j-- ) - { - /* get to end of header and find source for copy */ - if ( element == length - 1 - - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) - { - sb=i; - si=j; - /* we've found both sets now, exit loops */ - j=-1; - i=-1; - } - element--; - } - } - /* Now we know where to start the copy from */ - element = length-1 - - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ); - while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* check limits */ - if ( ( sb <= lsb && si < lsi ) || - ( db <= ldb && di < ldi ) ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - /* copy one byte */ - sg[db].address[di] = sg[sb].address[si]; - - /* get next destination */ - if ( di == 0 ) - { - db--; - di=sg[db].length-1; - } - else - { - di--; - } - - /* get next source */ - if ( si == 0 ) - { - sb--; - si=sg[sb].length-1; - } - else - { - si--; - } - - element--; - } - /* copy the remaining four bytes */ - while ( element >= USB_STOR_SCSI_SENSE_HDRSZ ) - { - /* check limits */ - if ( db <= ldb && di < ldi ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; - - /* get next destination */ - if ( di == 0 ) - { - db--; - di=sg[db].length-1; - } - else - { - di--; - } - element--; - } - } - - /* All done and everything was fine */ - return 0; -} - -void -usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6, - Usb_Stor_Scsi_Sense_Hdr_10_u* the10, - int* length_p ) - -{ - int i = 0, j=0, element=0; - struct scatterlist *sg = 0; - int length = 0; - __u8* buffer=0; - - /* are we scatter-gathering? */ - if ( srb->use_sg != 0 ) - { - /* loop over all the scatter gather structures and - * get pointer to the data members in the headers - * (also work out the length while we're here) - */ - sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) - { - length += sg[i].length; - /* We only do the inner loop for the headers */ - if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* scan through this scatterlist */ - for ( j=0; j<sg[i].length; j++ ) - { - if ( element < USB_STOR_SCSI_SENSE_HDRSZ ) - { - /* fill in the pointers for both header types */ - the6->array[element] = &(sg[i].address[j]); - the10->array[element] = &(sg[i].address[j]); - } - else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* only the longer headers still cares now */ - the10->array[element] = &(sg[i].address[j]); - } - /* increase element counter */ - element++; - } - } - } - } - else - { - length = srb->request_bufflen; - buffer = srb->request_buffer; - if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ ) - printk( KERN_ERR USB_STORAGE - "Buffer length smaller than header!!" ); - for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ ) - { - if ( i < USB_STOR_SCSI_SENSE_HDRSZ ) - { - the6->array[i] = &(buffer[i]); - the10->array[i] = &(buffer[i]); - } - else - { - the10->array[i] = &(buffer[i]); - } - } - } - - /* Set value of length passed in */ - *length_p = length; -} - -void -usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd ) -{ - int i=0, bufferSize = cmd->request_bufflen; - __u8* buffer = cmd->request_buffer; - struct scatterlist* sg = (struct scatterlist*)cmd->request_buffer; - - printk( KERN_ERR "Dumping information about %p.\n", cmd ); - printk( KERN_ERR "cmd->cmnd[0] value is %d.\n", cmd->cmnd[0] ); - printk( KERN_ERR "(MODE_SENSE is %d and MODE_SENSE_10 is %d)\n", - MODE_SENSE, MODE_SENSE_10 ); - - printk( KERN_ERR "buffer is %p with length %d.\n", buffer, bufferSize ); - for ( i=0; i<bufferSize; i+=16 ) - { - printk( KERN_ERR "%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", - buffer[i], - buffer[i+1], - buffer[i+2], - buffer[i+3], - buffer[i+4], - buffer[i+5], - buffer[i+6], - buffer[i+7], - buffer[i+8], - buffer[i+9], - buffer[i+10], - buffer[i+11], - buffer[i+12], - buffer[i+13], - buffer[i+14], - buffer[i+15] ); - } - - printk( KERN_ERR "Buffer has %d scatterlists.\n", cmd->use_sg ); - for ( i=0; i<cmd->use_sg; i++ ) - { - printk( KERN_ERR "Length of scatterlist %d is %d.\n", i, sg[i].length ); - printk( KERN_ERR "%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", - sg[i].address[0], - sg[i].address[1], - sg[i].address[2], - sg[i].address[3], - sg[i].address[4], - sg[i].address[5], - sg[i].address[6], - sg[i].address[7], - sg[i].address[8], - sg[i].address[9], - sg[i].address[10], - sg[i].address[11], - sg[i].address[12], - sg[i].address[13], - sg[i].address[14], - sg[i].address[15] ); - } -} - -/************************************************************** - **************************************************************/ - -/*********************************************************************** - * Initialization and registration - ***********************************************************************/ - -int __init usb_stor_init(void) -{ - /* initialize internal global data elements */ - us_list = NULL; - init_MUTEX(&us_list_semaphore); - my_host_number = 0; - - /* register the driver, return -1 if error */ - if (usb_register(&storage_driver) < 0) - return -1; - - /* we're all set */ - printk(KERN_INFO "USB Mass Storage support registered.\n"); - return 0; -} - -void __exit usb_stor_exit(void) -{ - struct us_data *next; - - US_DEBUGP("usb_stor_exit() called\n"); - - /* Deregister the driver - * This eliminates races with probes and disconnects - */ - US_DEBUGP("-- calling usb_deregister()\n"); - usb_deregister(&storage_driver) ; - - /* lock access to the data structures */ - down(&us_list_semaphore); - - /* While there are still virtual hosts, unregister them - * - * Note that the us_release() routine will destroy the local data - * structure. So we have to peel these off the top of the list - * and keep updating the head pointer as we go. - */ - while (us_list) { - /* keep track of where the next one is */ - next = us_list->next; - - US_DEBUGP("-- calling scsi_unregister_module()\n"); - scsi_unregister_module(MODULE_SCSI_HA, &(us_list->htmplt)); - - /* Now that scsi_unregister_module is done with the host - * template, we can free the us_data structure (the host - * template is inline in this structure). */ - kfree (us_list); - - /* advance the list pointer */ - us_list = next; - } - - /* unlock the data structures */ - up(&us_list_semaphore); -} - -module_init(usb_stor_init) ; -module_exit(usb_stor_exit) ; diff --git a/drivers/usb/usb-storage.h b/drivers/usb/usb-storage.h deleted file mode 100644 index 82475f094..000000000 --- a/drivers/usb/usb-storage.h +++ /dev/null @@ -1,160 +0,0 @@ -/* Driver for USB mass storage - include file - * - * (c) 1999 Michael Gee (michael@linuxspecific.com) - * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) - * - */ - -#include <linux/config.h> - -#define USB_STORAGE "usb-storage.c: " -#define USB_STOR_STRING_LEN 32 - -#ifdef CONFIG_USB_STORAGE_DEBUG -void us_show_command(Scsi_Cmnd *srb); -#define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE ## x ) -#define US_DEBUGPX(x...) printk( ## x ) -#define US_DEBUG(x) x -#else -#define US_DEBUGP(x...) -#define US_DEBUGPX(x...) -#define US_DEBUG(x) -#endif - -/* bit set if input */ -extern unsigned char us_direction[256/8]; -#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) - -/* Sub Classes */ - -#define US_SC_RBC 0x01 /* Typically, flash devices */ -#define US_SC_8020 0x02 /* CD-ROM */ -#define US_SC_QIC 0x03 /* QIC-157 Tapes */ -#define US_SC_UFI 0x04 /* Floppy */ -#define US_SC_8070 0x05 /* Removable media */ -#define US_SC_SCSI 0x06 /* Transparent */ -#define US_SC_MIN US_SC_RBC -#define US_SC_MAX US_SC_SCSI - -/* Protocols */ - -#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ -#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ -#define US_PR_BULK 0x50 /* bulk only */ - -/* - * Bulk only data structures - */ - -/* command block wrapper */ -struct bulk_cb_wrap { - __u32 Signature; /* contains 'USBC' */ - __u32 Tag; /* unique per command id */ - __u32 DataTransferLength; /* size of data */ - __u8 Flags; /* direction in bit 0 */ - __u8 Lun; /* LUN normally 0 */ - __u8 Length; /* of of the CDB */ - __u8 CDB[16]; /* max command */ -}; - -#define US_BULK_CB_WRAP_LEN 31 -#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ -#define US_BULK_FLAG_IN 1 -#define US_BULK_FLAG_OUT 0 - -/* command status wrapper */ -struct bulk_cs_wrap { - __u32 Signature; /* should = 'USBS' */ - __u32 Tag; /* same as original command */ - __u32 Residue; /* amount not transferred */ - __u8 Status; /* see below */ - __u8 Filler[18]; -}; - -#define US_BULK_CS_WRAP_LEN 13 -#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ -#define US_BULK_STAT_OK 0 -#define US_BULK_STAT_FAIL 1 -#define US_BULK_STAT_PHASE 2 - -/* bulk-only class specific requests */ -#define US_BULK_RESET_REQUEST 0xff -#define US_BULK_GET_MAX_LUN 0xfe - -/* - * us_bulk_transfer() return codes - */ -#define US_BULK_TRANSFER_GOOD 0 /* good transfer */ -#define US_BULK_TRANSFER_SHORT 1 /* transfered less than expected */ -#define US_BULK_TRANSFER_FAILED 2 /* transfer died in the middle */ -#define US_BULK_TRANSFER_ABORTED 3 /* transfer canceled */ - -/* - * Transport return codes - */ - -#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */ -#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */ -#define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */ -#define USB_STOR_TRANSPORT_ABORTED 3 /* Transport aborted */ - -/* - * CBI accept device specific command - */ - -#define US_CBI_ADSC 0 - -/* - * GUID definitions - */ - -#define GUID(x) __u32 x[3] -#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2]) -#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0; -#define GUID_NONE(x) (!x[0] && !x[1] && !x[2]) -#define GUID_FORMAT "%08x%08x%08x" -#define GUID_ARGS(x) x[0], x[1], x[2] - -static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial) -{ - pg[0] = (vendor << 16) | product; - pg[1] = pg[2] = 0; - while (*serial) { - pg[1] <<= 4; - pg[1] |= pg[2] >> 28; - pg[2] <<= 4; - if (*serial >= 'a') - *serial -= 'a' - 'A'; - pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0' - : *serial - 'A' + 10; - serial++; - } -} - -/* - * Unusual device list definitions - */ - -struct us_unusual_dev { - /* we search the list based on these parameters */ - __u16 idVendor; - __u16 idProduct; - __u16 bcdDeviceMin; - __u16 bcdDeviceMax; - - /* the list specifies these parameters */ - const char* name; - __u8 useProtocol; - __u8 useTransport; - unsigned int flags; -}; - -/* Flag definitions */ -#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ -#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 comands for - Win/MacOS compatibility */ -#define US_FL_START_STOP 0x00000004 /* ignore START_STOP commands */ -#define US_FL_ALT_LENGTH 0x00000008 /* use the alternate algorithm for - us_transfer_length() */ -#define US_FL_IGNORE_SER 0x00000010 /* Ignore the serial number given */ - |