File: /usr/src/linux/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     	SPRINTF("     Attached: %d\n", us->pusb_dev != NULL);
350     
351     	/*
352     	 * Calculate start of next buffer, and return value.
353     	 */
354     	*start = buffer + offset;
355     
356     	if ((pos - buffer) < offset)
357     		return (0);
358     	else if ((pos - buffer - offset) < length)
359     		return (pos - buffer - offset);
360     	else
361     		return (length);
362     }
363     
364     /*
365      * this defines our 'host'
366      */
367     
368     Scsi_Host_Template usb_stor_host_template = {
369     	name:			"usb-storage",
370     	proc_info:		proc_info,
371     	info:			host_info,
372     
373     	detect:			detect,
374     	release:		release,
375     	command:		command,
376     	queuecommand:		queuecommand,
377     
378     	eh_abort_handler:	command_abort,
379     	eh_device_reset_handler:device_reset,
380     	eh_bus_reset_handler:	bus_reset,
381     	eh_host_reset_handler:	host_reset,
382     
383     	can_queue:		1,
384     	this_id:		-1,
385     
386     	sg_tablesize:		SG_ALL,
387     	cmd_per_lun:		1,
388     	present:		0,
389     	unchecked_isa_dma:	FALSE,
390     	use_clustering:		TRUE,
391     	use_new_eh_code:	TRUE,
392     	emulated:		TRUE
393     };
394     
395     unsigned char usb_stor_sense_notready[18] = {
396     	[0]	= 0x70,			    /* current error */
397     	[2]	= 0x02,			    /* not ready */
398     	[5]	= 0x0a,			    /* additional length */
399     	[10]	= 0x04,			    /* not ready */
400     	[11]	= 0x03			    /* manual intervention */
401     };
402     
403     #define USB_STOR_SCSI_SENSE_HDRSZ 4
404     #define USB_STOR_SCSI_SENSE_10_HDRSZ 8
405     
406     struct usb_stor_scsi_sense_hdr
407     {
408       __u8* dataLength;
409       __u8* mediumType;
410       __u8* devSpecParms;
411       __u8* blkDescLength;
412     };
413     
414     typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr;
415     
416     union usb_stor_scsi_sense_hdr_u
417     {
418       Usb_Stor_Scsi_Sense_Hdr hdr;
419       __u8* array[USB_STOR_SCSI_SENSE_HDRSZ];
420     };
421     
422     typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u;
423     
424     struct usb_stor_scsi_sense_hdr_10
425     {
426       __u8* dataLengthMSB;
427       __u8* dataLengthLSB;
428       __u8* mediumType;
429       __u8* devSpecParms;
430       __u8* reserved1;
431       __u8* reserved2;
432       __u8* blkDescLengthMSB;
433       __u8* blkDescLengthLSB;
434     };
435     
436     typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10;
437     
438     union usb_stor_scsi_sense_hdr_10_u
439     {
440       Usb_Stor_Scsi_Sense_Hdr_10 hdr;
441       __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ];
442     };
443     
444     typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u;
445     
446     void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*,
447     				    Usb_Stor_Scsi_Sense_Hdr_10_u*, int* );
448     
449     int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
450     {
451       __u8 *buffer=0;
452       int outputBufferSize = 0;
453       int length=0;
454       struct scatterlist *sg = 0;
455       int i=0, j=0, element=0;
456       Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
457       Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
458       int sb=0,si=0,db=0,di=0;
459       int sgLength=0;
460     
461       US_DEBUGP("-- converting 10 byte sense data to 6 byte\n");
462       the10->cmnd[0] = the10->cmnd[0] & 0xBF;
463     
464       /* Determine buffer locations */
465       usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations,
466     				 &length );
467     
468       /* Work out minimum buffer to output */
469       outputBufferSize = *the10Locations.hdr.dataLengthLSB;
470       outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ;
471     
472       /* Check to see if we need to trucate the output */
473       if ( outputBufferSize > length )
474         {
475           printk( KERN_WARNING USB_STORAGE 
476     	      "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" );
477           printk( KERN_WARNING USB_STORAGE
478     	      "outputBufferSize is %d and length is %d.\n",
479     	      outputBufferSize, length );
480         }
481       outputBufferSize = length;
482     
483       /* Data length */
484       if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */
485         {
486           printk( KERN_WARNING USB_STORAGE 
487     	      "Command will be truncated to fit in SENSE6 buffer.\n" );
488           *the6Locations.hdr.dataLength = 0xff;
489         }
490       else
491         {
492           *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB;
493         }
494     
495       /* Medium type and DevSpecific parms */
496       *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType;
497       *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms;
498     
499       /* Block descriptor length */
500       if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */
501         {
502           printk( KERN_WARNING USB_STORAGE 
503     	      "Command will be truncated to fit in SENSE6 buffer.\n" );
504           *the6Locations.hdr.blkDescLength = 0xff;
505         }
506       else
507         {
508           *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB;
509         }
510     
511       if ( the10->use_sg == 0 )
512         {
513           buffer = the10->request_buffer;
514           /* Copy the rest of the data */
515           memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
516     	       &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
517     	       outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ );
518           /* initialise last bytes left in buffer due to smaller header */
519           memset( &(buffer[outputBufferSize
520     	    -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]),
521     	      0,
522     	      USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
523         }
524       else
525         {
526           sg = (struct scatterlist *) the10->request_buffer;
527           /* scan through this scatterlist and figure out starting positions */
528           for ( i=0; i < the10->use_sg; i++)
529     	{
530     	  sgLength = sg[i].length;
531     	  for ( j=0; j<sgLength; j++ )
532     	    {
533     	      /* get to end of header */
534     	      if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
535     		{
536     		  db=i;
537     		  di=j;
538     		}
539     	      if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
540     		{
541     		  sb=i;
542     		  si=j;
543     		  /* we've found both sets now, exit loops */
544     		  j=sgLength;
545     		  i=the10->use_sg;
546     		}
547     	      element++;
548     	    }
549     	}
550     
551           /* Now we know where to start the copy from */
552           element = USB_STOR_SCSI_SENSE_HDRSZ;
553           while ( element < outputBufferSize
554     	      -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
555     	{
556     	  /* check limits */
557     	  if ( sb >= the10->use_sg ||
558     	       si >= sg[sb].length ||
559     	       db >= the10->use_sg ||
560     	       di >= sg[db].length )
561     	    {
562     	      printk( KERN_ERR USB_STORAGE
563     		      "Buffer overrun averted, this shouldn't happen!\n" );
564     	      break;
565     	    }
566     
567     	  /* copy one byte */
568     	  sg[db].address[di] = sg[sb].address[si];
569     
570     	  /* get next destination */
571     	  if ( sg[db].length-1 == di )
572     	    {
573     	      db++;
574     	      di=0;
575     	    }
576     	  else
577     	    {
578     	      di++;
579     	    }
580     
581     	  /* get next source */
582     	  if ( sg[sb].length-1 == si )
583     	    {
584     	      sb++;
585     	      si=0;
586     	    }
587     	  else
588     	    {
589     	      si++;
590     	    }
591     
592     	  element++;
593     	}
594           /* zero the remaining bytes */
595           while ( element < outputBufferSize )
596     	{
597     	  /* check limits */
598     	  if ( db >= the10->use_sg ||
599     	       di >= sg[db].length )
600     	    {
601     	      printk( KERN_ERR USB_STORAGE
602     		      "Buffer overrun averted, this shouldn't happen!\n" );
603     	      break;
604     	    }
605     
606     	  sg[db].address[di] = 0;
607     
608     	  /* get next destination */
609     	  if ( sg[db].length-1 == di )
610     	    {
611     	      db++;
612     	      di=0;
613     	    }
614     	  else
615     	    {
616     	      di++;
617     	    }
618     	  element++;
619     	}
620         }
621     
622       /* All done any everything was fine */
623       return 0;
624     }
625     
626     int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
627     {
628       /* will be used to store part of buffer */  
629       __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ],
630         *buffer=0;
631       int outputBufferSize = 0;
632       int length=0;
633       struct scatterlist *sg = 0;
634       int i=0, j=0, element=0;
635       Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
636       Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
637       int sb=0,si=0,db=0,di=0;
638       int lsb=0,lsi=0,ldb=0,ldi=0;
639     
640       US_DEBUGP("-- converting 6 byte sense data to 10 byte\n");
641       the6->cmnd[0] = the6->cmnd[0] | 0x40;
642     
643       /* Determine buffer locations */
644       usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations,
645     				 &length );
646     
647       /* Work out minimum buffer to output */
648       outputBufferSize = *the6Locations.hdr.dataLength;
649       outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ;
650     
651       /* Check to see if we need to trucate the output */
652       if ( outputBufferSize > length )
653         {
654           printk( KERN_WARNING USB_STORAGE 
655     	      "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" );
656           printk( KERN_WARNING USB_STORAGE
657     	      "outputBufferSize is %d and length is %d.\n",
658     	      outputBufferSize, length );
659         }
660       outputBufferSize = length;
661     
662       /* Block descriptor length - save these before overwriting */
663       tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB;
664       tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB;
665       *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength;
666       *the10Locations.hdr.blkDescLengthMSB = 0;
667     
668       /* reserved - save these before overwriting */
669       tempBuffer[0] = *the10Locations.hdr.reserved1;
670       tempBuffer[1] = *the10Locations.hdr.reserved2;
671       *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0;
672     
673       /* Medium type and DevSpecific parms */
674       *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms;
675       *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType;
676     
677       /* Data length */
678       *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength;
679       *the10Locations.hdr.dataLengthMSB = 0;
680     
681       if ( !the6->use_sg )
682         {
683           buffer = the6->request_buffer;
684           /* Copy the rest of the data */
685           memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
686     	      &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
687     	      outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ );
688           /* Put the first four bytes (after header) in place */
689           memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
690     	      tempBuffer,
691     	      USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
692         }
693       else
694         {
695           sg = (struct scatterlist *) the6->request_buffer;
696           /* scan through this scatterlist and figure out ending positions */
697           for ( i=0; i < the6->use_sg; i++)
698     	{
699     	  for ( j=0; j<sg[i].length; j++ )
700     	    {
701     	      /* get to end of header */
702     	      if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
703     		{
704     		  ldb=i;
705     		  ldi=j;
706     		}
707     	      if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
708     		{
709     		  lsb=i;
710     		  lsi=j;
711     		  /* we've found both sets now, exit loops */
712     		  j=sg[i].length;
713     		  i=the6->use_sg;
714     		  break;
715     		}
716     	      element++;
717     	    }
718     	}
719           /* scan through this scatterlist and figure out starting positions */
720           element = length-1;
721           /* destination is the last element */
722           db=the6->use_sg-1;
723           di=sg[db].length-1;
724           for ( i=the6->use_sg-1; i >= 0; i--)
725     	{
726     	  for ( j=sg[i].length-1; j>=0; j-- )
727     	    {
728     	      /* get to end of header and find source for copy */
729     	      if ( element == length - 1
730     		   - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
731     		{
732     		  sb=i;
733     		  si=j;
734     		  /* we've found both sets now, exit loops */
735     		  j=-1;
736     		  i=-1;
737     		}
738     	      element--;
739     	    }
740     	}
741           /* Now we know where to start the copy from */
742           element = length-1
743     	- (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ);
744           while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ )
745     	{
746     	  /* check limits */
747     	  if ( ( sb <= lsb && si < lsi ) ||
748     	       ( db <= ldb && di < ldi ) )
749     	    {
750     	      printk( KERN_ERR USB_STORAGE
751     		      "Buffer overrun averted, this shouldn't happen!\n" );
752     	      break;
753     	    }
754     
755     	  /* copy one byte */
756     	  sg[db].address[di] = sg[sb].address[si];
757     
758     	  /* get next destination */
759     	  if ( di == 0 )
760     	    {
761     	      db--;
762     	      di=sg[db].length-1;
763     	    }
764     	  else
765     	    {
766     	      di--;
767     	    }
768     
769     	  /* get next source */
770     	  if ( si == 0 )
771     	    {
772     	      sb--;
773     	      si=sg[sb].length-1;
774     	    }
775     	  else
776     	    {
777     	      si--;
778     	    }
779     
780     	  element--;
781     	}
782           /* copy the remaining four bytes */
783           while ( element >= USB_STOR_SCSI_SENSE_HDRSZ )
784     	{
785     	  /* check limits */
786     	  if ( db <= ldb && di < ldi )
787     	    {
788     	      printk( KERN_ERR USB_STORAGE
789     		      "Buffer overrun averted, this shouldn't happen!\n" );
790     	      break;
791     	    }
792     
793     	  sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
794     
795     	  /* get next destination */
796     	  if ( di == 0 )
797     	    {
798     	      db--;
799     	      di=sg[db].length-1;
800     	    }
801     	  else
802     	    {
803     	      di--;
804     	    }
805     	  element--;
806     	}
807         }
808     
809       /* All done and everything was fine */
810       return 0;
811     }
812     
813     void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6,
814     			       Usb_Stor_Scsi_Sense_Hdr_10_u* the10,
815     			       int* length_p )
816     
817     {
818       int i = 0, j=0, element=0;
819       struct scatterlist *sg = 0;
820       int length = 0;
821       __u8* buffer=0;
822     
823       /* are we scatter-gathering? */
824       if ( srb->use_sg != 0 )
825         {
826           /* loop over all the scatter gather structures and 
827            * get pointer to the data members in the headers
828            * (also work out the length while we're here)
829            */
830           sg = (struct scatterlist *) srb->request_buffer;
831           for (i = 0; i < srb->use_sg; i++)
832     	{
833     	  length += sg[i].length;
834     	  /* We only do the inner loop for the headers */
835     	  if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
836     	    {
837     	      /* scan through this scatterlist */
838     	      for ( j=0; j<sg[i].length; j++ )
839     		{
840     		  if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
841     		    {
842     		      /* fill in the pointers for both header types */
843     		      the6->array[element] = &(sg[i].address[j]);
844     		      the10->array[element] = &(sg[i].address[j]);
845     		    }
846     		  else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
847     		    {
848     		      /* only the longer headers still cares now */
849     		      the10->array[element] = &(sg[i].address[j]);
850     		    }
851     		  /* increase element counter */
852     		  element++;
853     		}
854     	    }
855     	}
856         }
857       else
858         {
859           length = srb->request_bufflen;
860           buffer = srb->request_buffer;
861           if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ )
862     	printk( KERN_ERR USB_STORAGE
863     		"Buffer length smaller than header!!" );
864           for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ )
865     	{
866     	  if ( i < USB_STOR_SCSI_SENSE_HDRSZ )
867     	    {
868     	      the6->array[i] = &(buffer[i]);
869     	      the10->array[i] = &(buffer[i]);
870     	    }
871     	  else
872     	    {
873     	      the10->array[i] = &(buffer[i]);
874     	    }
875     	}
876         }
877     
878       /* Set value of length passed in */
879       *length_p = length;
880     }
881     
882