scsiglue.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:23k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* Driver for USB Mass Storage compliant devices
  2.  * SCSI layer glue code
  3.  *
  4.  * $Id: scsiglue.c,v 1.24 2001/11/11 03:33:58 mdharm Exp $
  5.  *
  6.  * Current development and maintenance by:
  7.  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  8.  *
  9.  * Developed with the assistance of:
  10.  *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
  11.  *   (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov)
  12.  *
  13.  * Initial work by:
  14.  *   (c) 1999 Michael Gee (michael@linuxspecific.com)
  15.  *
  16.  * This driver is based on the 'USB Mass Storage Class' document. This
  17.  * describes in detail the protocol used to communicate with such
  18.  * devices.  Clearly, the designers had SCSI and ATAPI commands in
  19.  * mind when they created this document.  The commands are all very
  20.  * similar to commands in the SCSI-II and ATAPI specifications.
  21.  *
  22.  * It is important to note that in a number of cases this class
  23.  * exhibits class-specific exemptions from the USB specification.
  24.  * Notably the usage of NAK, STALL and ACK differs from the norm, in
  25.  * that they are used to communicate wait, failed and OK on commands.
  26.  *
  27.  * Also, for certain devices, the interrupt endpoint is used to convey
  28.  * status of a command.
  29.  *
  30.  * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
  31.  * information about this driver.
  32.  *
  33.  * This program is free software; you can redistribute it and/or modify it
  34.  * under the terms of the GNU General Public License as published by the
  35.  * Free Software Foundation; either version 2, or (at your option) any
  36.  * later version.
  37.  *
  38.  * This program is distributed in the hope that it will be useful, but
  39.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  40.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  41.  * General Public License for more details.
  42.  *
  43.  * You should have received a copy of the GNU General Public License along
  44.  * with this program; if not, write to the Free Software Foundation, Inc.,
  45.  * 675 Mass Ave, Cambridge, MA 02139, USA.
  46.  */
  47. #include "scsiglue.h"
  48. #include "usb.h"
  49. #include "debug.h"
  50. #include "transport.h"
  51. #include <linux/slab.h>
  52. /*
  53.  * kernel thread actions
  54.  */
  55. #define US_ACT_COMMAND 1
  56. #define US_ACT_DEVICE_RESET 2
  57. #define US_ACT_BUS_RESET 3
  58. #define US_ACT_HOST_RESET 4
  59. #define US_ACT_EXIT 5
  60. /***********************************************************************
  61.  * Host functions 
  62.  ***********************************************************************/
  63. static const char* host_info(struct Scsi_Host *host)
  64. {
  65. return "SCSI emulation for USB Mass Storage devices";
  66. }
  67. /* detect a virtual adapter (always works) */
  68. static int detect(struct SHT *sht)
  69. {
  70. struct us_data *us;
  71. char local_name[32];
  72. /* This is not nice at all, but how else are we to get the
  73.  * data here? */
  74. us = (struct us_data *)sht->proc_dir;
  75. /* set up the name of our subdirectory under /proc/scsi/ */
  76. sprintf(local_name, "usb-storage-%d", us->host_number);
  77. sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
  78. if (!sht->proc_name)
  79. return 0;
  80. strcpy(sht->proc_name, local_name);
  81. /* we start with no /proc directory entry */
  82. sht->proc_dir = NULL;
  83. /* register the host */
  84. us->host = scsi_register(sht, sizeof(us));
  85. if (us->host) {
  86. us->host->hostdata[0] = (unsigned long)us;
  87. us->host_no = us->host->host_no;
  88. return 1;
  89. }
  90. /* odd... didn't register properly.  Abort and free pointers */
  91. kfree(sht->proc_name);
  92. sht->proc_name = NULL;
  93. return 0;
  94. }
  95. /* Release all resources used by the virtual host
  96.  *
  97.  * NOTE: There is no contention here, because we're already deregistered
  98.  * the driver and we're doing each virtual host in turn, not in parallel
  99.  */
  100. static int release(struct Scsi_Host *psh)
  101. {
  102. struct us_data *us = (struct us_data *)psh->hostdata[0];
  103. US_DEBUGP("release() called for host %sn", us->htmplt.name);
  104. /* Kill the control threads
  105.  *
  106.  * Enqueue the command, wake up the thread, and wait for 
  107.  * notification that it's exited.
  108.  */
  109. US_DEBUGP("-- sending US_ACT_EXIT command to threadn");
  110. us->action = US_ACT_EXIT;
  111. up(&(us->sema));
  112. wait_for_completion(&(us->notify));
  113. /* remove the pointer to the data structure we were using */
  114. (struct us_data*)psh->hostdata[0] = NULL;
  115. /* we always have a successful release */
  116. return 0;
  117. }
  118. /* run command */
  119. static int command( Scsi_Cmnd *srb )
  120. {
  121. US_DEBUGP("Bad use of us_commandn");
  122. return DID_BAD_TARGET << 16;
  123. }
  124. /* run command */
  125. static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
  126. {
  127. struct us_data *us = (struct us_data *)srb->host->hostdata[0];
  128. US_DEBUGP("queuecommand() calledn");
  129. srb->host_scribble = (unsigned char *)us;
  130. /* get exclusive access to the structures we want */
  131. down(&(us->queue_exclusion));
  132. /* enqueue the command */
  133. us->queue_srb = srb;
  134. srb->scsi_done = done;
  135. us->action = US_ACT_COMMAND;
  136. /* release the lock on the structure */
  137. up(&(us->queue_exclusion));
  138. /* wake up the process task */
  139. up(&(us->sema));
  140. return 0;
  141. }
  142. /***********************************************************************
  143.  * Error handling functions
  144.  ***********************************************************************/
  145. /* Command abort */
  146. static int command_abort( Scsi_Cmnd *srb )
  147. {
  148. struct us_data *us = (struct us_data *)srb->host->hostdata[0];
  149. US_DEBUGP("command_abort() calledn");
  150. /* if we're stuck waiting for an IRQ, simulate it */
  151. if (atomic_read(us->ip_wanted)) {
  152. US_DEBUGP("-- simulating missing IRQn");
  153. up(&(us->ip_waitq));
  154. }
  155. /* if the device has been removed, this worked */
  156. if (!us->pusb_dev) {
  157. US_DEBUGP("-- device removed alreadyn");
  158. return SUCCESS;
  159. }
  160. /* if we have an urb pending, let's wake the control thread up */
  161. if (us->current_urb->status == -EINPROGRESS) {
  162. /* cancel the URB -- this will automatically wake the thread */
  163. usb_unlink_urb(us->current_urb);
  164. /* wait for us to be done */
  165. wait_for_completion(&(us->notify));
  166. return SUCCESS;
  167. }
  168. US_DEBUGP ("-- nothing to abortn");
  169. return FAILED;
  170. }
  171. /* This invokes the transport reset mechanism to reset the state of the
  172.  * device */
  173. static int device_reset( Scsi_Cmnd *srb )
  174. {
  175. struct us_data *us = (struct us_data *)srb->host->hostdata[0];
  176. US_DEBUGP("device_reset() calledn" );
  177. return us->transport_reset(us);
  178. }
  179. /* This resets the device port, and simulates the device
  180.  * disconnect/reconnect for all drivers which have claimed other
  181.  * interfaces. */
  182. static int bus_reset( Scsi_Cmnd *srb )
  183. {
  184. struct us_data *us = (struct us_data *)srb->host->hostdata[0];
  185. int i;
  186. int result;
  187. /* we use the usb_reset_device() function to handle this for us */
  188. US_DEBUGP("bus_reset() calledn");
  189. /* if the device has been removed, this worked */
  190. if (!us->pusb_dev) {
  191. US_DEBUGP("-- device removed alreadyn");
  192. return SUCCESS;
  193. }
  194. /* release the IRQ, if we have one */
  195. down(&(us->irq_urb_sem));
  196. if (us->irq_urb) {
  197. US_DEBUGP("-- releasing irq URBn");
  198. result = usb_unlink_urb(us->irq_urb);
  199. US_DEBUGP("-- usb_unlink_urb() returned %dn", result);
  200. }
  201. up(&(us->irq_urb_sem));
  202. /* attempt to reset the port */
  203. if (usb_reset_device(us->pusb_dev) < 0)
  204. return FAILED;
  205. /* FIXME: This needs to lock out driver probing while it's working
  206.  * or we can have race conditions */
  207.         for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
  208.   struct usb_interface *intf =
  209. &us->pusb_dev->actconfig->interface[i];
  210. const struct usb_device_id *id;
  211. /* if this is an unclaimed interface, skip it */
  212. if (!intf->driver) {
  213. continue;
  214. }
  215. US_DEBUGP("Examinging driver %s...", intf->driver->name);
  216. /* skip interfaces which we've claimed */
  217. if (intf->driver == &usb_storage_driver) {
  218. US_DEBUGPX("skipping ourselves.n");
  219. continue;
  220. }
  221. /* simulate a disconnect and reconnect for all interfaces */
  222. US_DEBUGPX("simulating disconnect/reconnect.n");
  223. down(&intf->driver->serialize);
  224. intf->driver->disconnect(us->pusb_dev, intf->private_data);
  225. id = usb_match_id(us->pusb_dev, intf, intf->driver->id_table);
  226. intf->driver->probe(us->pusb_dev, i, id);
  227. up(&intf->driver->serialize);
  228. }
  229. /* re-allocate the IRQ URB and submit it to restore connectivity
  230.  * for CBI devices
  231.  */
  232. if (us->protocol == US_PR_CBI) {
  233. down(&(us->irq_urb_sem));
  234. us->irq_urb->dev = us->pusb_dev;
  235. result = usb_submit_urb(us->irq_urb);
  236. US_DEBUGP("usb_submit_urb() returns %dn", result);
  237. up(&(us->irq_urb_sem));
  238. }
  239. US_DEBUGP("bus_reset() completen");
  240. return SUCCESS;
  241. }
  242. /* FIXME: This doesn't do anything right now */
  243. static int host_reset( Scsi_Cmnd *srb )
  244. {
  245. printk(KERN_CRIT "usb-storage: host_reset() requested but not implementedn" );
  246. return FAILED;
  247. }
  248. /***********************************************************************
  249.  * /proc/scsi/ functions
  250.  ***********************************************************************/
  251. /* we use this macro to help us write into the buffer */
  252. #undef SPRINTF
  253. #define SPRINTF(args...) 
  254. do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
  255. static int proc_info (char *buffer, char **start, off_t offset, int length,
  256. int hostno, int inout)
  257. {
  258. struct us_data *us;
  259. char *pos = buffer;
  260. /* if someone is sending us data, just throw it away */
  261. if (inout)
  262. return length;
  263. /* lock the data structures */
  264. down(&us_list_semaphore);
  265. /* find our data from hostno */
  266. us = us_list;
  267. while (us) {
  268. if (us->host_no == hostno)
  269. break;
  270. us = us->next;
  271. }
  272. /* release our lock on the data structures */
  273. up(&us_list_semaphore);
  274. /* if we couldn't find it, we return an error */
  275. if (!us) {
  276. return -ESRCH;
  277. }
  278. /* print the controller name */
  279. SPRINTF("   Host scsi%d: usb-storagen", hostno);
  280. /* print product, vendor, and serial number strings */
  281. SPRINTF("       Vendor: %sn", us->vendor);
  282. SPRINTF("      Product: %sn", us->product);
  283. SPRINTF("Serial Number: %sn", us->serial);
  284. /* show the protocol and transport */
  285. SPRINTF("     Protocol: %sn", us->protocol_name);
  286. SPRINTF("    Transport: %sn", us->transport_name);
  287. /* show the GUID of the device */
  288. SPRINTF("         GUID: " GUID_FORMAT "n", GUID_ARGS(us->guid));
  289. SPRINTF("     Attached: %sn", us->pusb_dev ? "Yes" : "No");
  290. /*
  291.  * Calculate start of next buffer, and return value.
  292.  */
  293. *start = buffer + offset;
  294. if ((pos - buffer) < offset)
  295. return (0);
  296. else if ((pos - buffer - offset) < length)
  297. return (pos - buffer - offset);
  298. else
  299. return (length);
  300. }
  301. /*
  302.  * this defines our 'host'
  303.  */
  304. Scsi_Host_Template usb_stor_host_template = {
  305. name: "usb-storage",
  306. proc_info: proc_info,
  307. info: host_info,
  308. detect: detect,
  309. release: release,
  310. command: command,
  311. queuecommand: queuecommand,
  312. eh_abort_handler: command_abort,
  313. eh_device_reset_handler:device_reset,
  314. eh_bus_reset_handler: bus_reset,
  315. eh_host_reset_handler: host_reset,
  316. can_queue: 1,
  317. this_id: -1,
  318. sg_tablesize: SG_ALL,
  319. cmd_per_lun: 1,
  320. present: 0,
  321. unchecked_isa_dma: FALSE,
  322. use_clustering: TRUE,
  323. use_new_eh_code: TRUE,
  324. emulated: TRUE
  325. };
  326. unsigned char usb_stor_sense_notready[18] = {
  327. [0] = 0x70,     /* current error */
  328. [2] = 0x02,     /* not ready */
  329. [5] = 0x0a,     /* additional length */
  330. [10] = 0x04,     /* not ready */
  331. [11] = 0x03     /* manual intervention */
  332. };
  333. #define USB_STOR_SCSI_SENSE_HDRSZ 4
  334. #define USB_STOR_SCSI_SENSE_10_HDRSZ 8
  335. struct usb_stor_scsi_sense_hdr
  336. {
  337.   __u8* dataLength;
  338.   __u8* mediumType;
  339.   __u8* devSpecParms;
  340.   __u8* blkDescLength;
  341. };
  342. typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr;
  343. union usb_stor_scsi_sense_hdr_u
  344. {
  345.   Usb_Stor_Scsi_Sense_Hdr hdr;
  346.   __u8* array[USB_STOR_SCSI_SENSE_HDRSZ];
  347. };
  348. typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u;
  349. struct usb_stor_scsi_sense_hdr_10
  350. {
  351.   __u8* dataLengthMSB;
  352.   __u8* dataLengthLSB;
  353.   __u8* mediumType;
  354.   __u8* devSpecParms;
  355.   __u8* reserved1;
  356.   __u8* reserved2;
  357.   __u8* blkDescLengthMSB;
  358.   __u8* blkDescLengthLSB;
  359. };
  360. typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10;
  361. union usb_stor_scsi_sense_hdr_10_u
  362. {
  363.   Usb_Stor_Scsi_Sense_Hdr_10 hdr;
  364.   __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ];
  365. };
  366. typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u;
  367. void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*,
  368.     Usb_Stor_Scsi_Sense_Hdr_10_u*, int* );
  369. int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
  370. {
  371.   __u8 *buffer=0;
  372.   int outputBufferSize = 0;
  373.   int length=0;
  374.   struct scatterlist *sg = 0;
  375.   int i=0, j=0, element=0;
  376.   Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
  377.   Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
  378.   int sb=0,si=0,db=0,di=0;
  379.   int sgLength=0;
  380.   US_DEBUGP("-- converting 10 byte sense data to 6 byten");
  381.   the10->cmnd[0] = the10->cmnd[0] & 0xBF;
  382.   /* Determine buffer locations */
  383.   usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations,
  384.  &length );
  385.   /* Work out minimum buffer to output */
  386.   outputBufferSize = *the10Locations.hdr.dataLengthLSB;
  387.   outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ;
  388.   /* Check to see if we need to trucate the output */
  389.   if ( outputBufferSize > length )
  390.     {
  391.       printk( KERN_WARNING USB_STORAGE 
  392.       "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.n" );
  393.       printk( KERN_WARNING USB_STORAGE
  394.       "outputBufferSize is %d and length is %d.n",
  395.       outputBufferSize, length );
  396.     }
  397.   outputBufferSize = length;
  398.   /* Data length */
  399.   if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */
  400.     {
  401.       printk( KERN_WARNING USB_STORAGE 
  402.       "Command will be truncated to fit in SENSE6 buffer.n" );
  403.       *the6Locations.hdr.dataLength = 0xff;
  404.     }
  405.   else
  406.     {
  407.       *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB;
  408.     }
  409.   /* Medium type and DevSpecific parms */
  410.   *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType;
  411.   *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms;
  412.   /* Block descriptor length */
  413.   if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */
  414.     {
  415.       printk( KERN_WARNING USB_STORAGE 
  416.       "Command will be truncated to fit in SENSE6 buffer.n" );
  417.       *the6Locations.hdr.blkDescLength = 0xff;
  418.     }
  419.   else
  420.     {
  421.       *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB;
  422.     }
  423.   if ( the10->use_sg == 0 )
  424.     {
  425.       buffer = the10->request_buffer;
  426.       /* Copy the rest of the data */
  427.       memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
  428.        &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
  429.        outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ );
  430.       /* initialise last bytes left in buffer due to smaller header */
  431.       memset( &(buffer[outputBufferSize
  432.     -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]),
  433.       0,
  434.       USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
  435.     }
  436.   else
  437.     {
  438.       sg = (struct scatterlist *) the10->request_buffer;
  439.       /* scan through this scatterlist and figure out starting positions */
  440.       for ( i=0; i < the10->use_sg; i++)
  441. {
  442.   sgLength = sg[i].length;
  443.   for ( j=0; j<sgLength; j++ )
  444.     {
  445.       /* get to end of header */
  446.       if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
  447. {
  448.   db=i;
  449.   di=j;
  450. }
  451.       if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
  452. {
  453.   sb=i;
  454.   si=j;
  455.   /* we've found both sets now, exit loops */
  456.   j=sgLength;
  457.   i=the10->use_sg;
  458. }
  459.       element++;
  460.     }
  461. }
  462.       /* Now we know where to start the copy from */
  463.       element = USB_STOR_SCSI_SENSE_HDRSZ;
  464.       while ( element < outputBufferSize
  465.       -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
  466. {
  467.   /* check limits */
  468.   if ( sb >= the10->use_sg ||
  469.        si >= sg[sb].length ||
  470.        db >= the10->use_sg ||
  471.        di >= sg[db].length )
  472.     {
  473.       printk( KERN_ERR USB_STORAGE
  474.       "Buffer overrun averted, this shouldn't happen!n" );
  475.       break;
  476.     }
  477.   /* copy one byte */
  478.   sg[db].address[di] = sg[sb].address[si];
  479.   /* get next destination */
  480.   if ( sg[db].length-1 == di )
  481.     {
  482.       db++;
  483.       di=0;
  484.     }
  485.   else
  486.     {
  487.       di++;
  488.     }
  489.   /* get next source */
  490.   if ( sg[sb].length-1 == si )
  491.     {
  492.       sb++;
  493.       si=0;
  494.     }
  495.   else
  496.     {
  497.       si++;
  498.     }
  499.   element++;
  500. }
  501.       /* zero the remaining bytes */
  502.       while ( element < outputBufferSize )
  503. {
  504.   /* check limits */
  505.   if ( db >= the10->use_sg ||
  506.        di >= sg[db].length )
  507.     {
  508.       printk( KERN_ERR USB_STORAGE
  509.       "Buffer overrun averted, this shouldn't happen!n" );
  510.       break;
  511.     }
  512.   sg[db].address[di] = 0;
  513.   /* get next destination */
  514.   if ( sg[db].length-1 == di )
  515.     {
  516.       db++;
  517.       di=0;
  518.     }
  519.   else
  520.     {
  521.       di++;
  522.     }
  523.   element++;
  524. }
  525.     }
  526.   /* All done any everything was fine */
  527.   return 0;
  528. }
  529. int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
  530. {
  531.   /* will be used to store part of buffer */  
  532.   __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ],
  533.     *buffer=0;
  534.   int outputBufferSize = 0;
  535.   int length=0;
  536.   struct scatterlist *sg = 0;
  537.   int i=0, j=0, element=0;
  538.   Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
  539.   Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
  540.   int sb=0,si=0,db=0,di=0;
  541.   int lsb=0,lsi=0,ldb=0,ldi=0;
  542.   US_DEBUGP("-- converting 6 byte sense data to 10 byten");
  543.   the6->cmnd[0] = the6->cmnd[0] | 0x40;
  544.   /* Determine buffer locations */
  545.   usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations,
  546.  &length );
  547.   /* Work out minimum buffer to output */
  548.   outputBufferSize = *the6Locations.hdr.dataLength;
  549.   outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ;
  550.   /* Check to see if we need to trucate the output */
  551.   if ( outputBufferSize > length )
  552.     {
  553.       printk( KERN_WARNING USB_STORAGE 
  554.       "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.n" );
  555.       printk( KERN_WARNING USB_STORAGE
  556.       "outputBufferSize is %d and length is %d.n",
  557.       outputBufferSize, length );
  558.     }
  559.   outputBufferSize = length;
  560.   /* Block descriptor length - save these before overwriting */
  561.   tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB;
  562.   tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB;
  563.   *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength;
  564.   *the10Locations.hdr.blkDescLengthMSB = 0;
  565.   /* reserved - save these before overwriting */
  566.   tempBuffer[0] = *the10Locations.hdr.reserved1;
  567.   tempBuffer[1] = *the10Locations.hdr.reserved2;
  568.   *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0;
  569.   /* Medium type and DevSpecific parms */
  570.   *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms;
  571.   *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType;
  572.   /* Data length */
  573.   *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength;
  574.   *the10Locations.hdr.dataLengthMSB = 0;
  575.   if ( !the6->use_sg )
  576.     {
  577.       buffer = the6->request_buffer;
  578.       /* Copy the rest of the data */
  579.       memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
  580.       &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
  581.       outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ );
  582.       /* Put the first four bytes (after header) in place */
  583.       memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
  584.       tempBuffer,
  585.       USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
  586.     }
  587.   else
  588.     {
  589.       sg = (struct scatterlist *) the6->request_buffer;
  590.       /* scan through this scatterlist and figure out ending positions */
  591.       for ( i=0; i < the6->use_sg; i++)
  592. {
  593.   for ( j=0; j<sg[i].length; j++ )
  594.     {
  595.       /* get to end of header */
  596.       if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
  597. {
  598.   ldb=i;
  599.   ldi=j;
  600. }
  601.       if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
  602. {
  603.   lsb=i;
  604.   lsi=j;
  605.   /* we've found both sets now, exit loops */
  606.   j=sg[i].length;
  607.   i=the6->use_sg;
  608.   break;
  609. }
  610.       element++;
  611.     }
  612. }
  613.       /* scan through this scatterlist and figure out starting positions */
  614.       element = length-1;
  615.       /* destination is the last element */
  616.       db=the6->use_sg-1;
  617.       di=sg[db].length-1;
  618.       for ( i=the6->use_sg-1; i >= 0; i--)
  619. {
  620.   for ( j=sg[i].length-1; j>=0; j-- )
  621.     {
  622.       /* get to end of header and find source for copy */
  623.       if ( element == length - 1
  624.    - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
  625. {
  626.   sb=i;
  627.   si=j;
  628.   /* we've found both sets now, exit loops */
  629.   j=-1;
  630.   i=-1;
  631. }
  632.       element--;
  633.     }
  634. }
  635.       /* Now we know where to start the copy from */
  636.       element = length-1
  637. - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ);
  638.       while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ )
  639. {
  640.   /* check limits */
  641.   if ( ( sb <= lsb && si < lsi ) ||
  642.        ( db <= ldb && di < ldi ) )
  643.     {
  644.       printk( KERN_ERR USB_STORAGE
  645.       "Buffer overrun averted, this shouldn't happen!n" );
  646.       break;
  647.     }
  648.   /* copy one byte */
  649.   sg[db].address[di] = sg[sb].address[si];
  650.   /* get next destination */
  651.   if ( di == 0 )
  652.     {
  653.       db--;
  654.       di=sg[db].length-1;
  655.     }
  656.   else
  657.     {
  658.       di--;
  659.     }
  660.   /* get next source */
  661.   if ( si == 0 )
  662.     {
  663.       sb--;
  664.       si=sg[sb].length-1;
  665.     }
  666.   else
  667.     {
  668.       si--;
  669.     }
  670.   element--;
  671. }
  672.       /* copy the remaining four bytes */
  673.       while ( element >= USB_STOR_SCSI_SENSE_HDRSZ )
  674. {
  675.   /* check limits */
  676.   if ( db <= ldb && di < ldi )
  677.     {
  678.       printk( KERN_ERR USB_STORAGE
  679.       "Buffer overrun averted, this shouldn't happen!n" );
  680.       break;
  681.     }
  682.   sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
  683.   /* get next destination */
  684.   if ( di == 0 )
  685.     {
  686.       db--;
  687.       di=sg[db].length-1;
  688.     }
  689.   else
  690.     {
  691.       di--;
  692.     }
  693.   element--;
  694. }
  695.     }
  696.   /* All done and everything was fine */
  697.   return 0;
  698. }
  699. void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6,
  700.        Usb_Stor_Scsi_Sense_Hdr_10_u* the10,
  701.        int* length_p )
  702. {
  703.   int i = 0, j=0, element=0;
  704.   struct scatterlist *sg = 0;
  705.   int length = 0;
  706.   __u8* buffer=0;
  707.   /* are we scatter-gathering? */
  708.   if ( srb->use_sg != 0 )
  709.     {
  710.       /* loop over all the scatter gather structures and 
  711.        * get pointer to the data members in the headers
  712.        * (also work out the length while we're here)
  713.        */
  714.       sg = (struct scatterlist *) srb->request_buffer;
  715.       for (i = 0; i < srb->use_sg; i++)
  716. {
  717.   length += sg[i].length;
  718.   /* We only do the inner loop for the headers */
  719.   if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
  720.     {
  721.       /* scan through this scatterlist */
  722.       for ( j=0; j<sg[i].length; j++ )
  723. {
  724.   if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
  725.     {
  726.       /* fill in the pointers for both header types */
  727.       the6->array[element] = &(sg[i].address[j]);
  728.       the10->array[element] = &(sg[i].address[j]);
  729.     }
  730.   else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
  731.     {
  732.       /* only the longer headers still cares now */
  733.       the10->array[element] = &(sg[i].address[j]);
  734.     }
  735.   /* increase element counter */
  736.   element++;
  737. }
  738.     }
  739. }
  740.     }
  741.   else
  742.     {
  743.       length = srb->request_bufflen;
  744.       buffer = srb->request_buffer;
  745.       if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ )
  746. printk( KERN_ERR USB_STORAGE
  747. "Buffer length smaller than header!!" );
  748.       for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ )
  749. {
  750.   if ( i < USB_STOR_SCSI_SENSE_HDRSZ )
  751.     {
  752.       the6->array[i] = &(buffer[i]);
  753.       the10->array[i] = &(buffer[i]);
  754.     }
  755.   else
  756.     {
  757.       the10->array[i] = &(buffer[i]);
  758.     }
  759. }
  760.     }
  761.   /* Set value of length passed in */
  762.   *length_p = length;
  763. }