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