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