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