1 /* Driver for USB Mass Storage compliant devices
4 * $Id: scsiglue.c,v 1.7 2000/07/28 20:33:18 gowdy Exp $
6 * Current development and maintainance by:
7 * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
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)
14 * (c) 1999 Michael Gee (michael@linuxspecific.com)
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.
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.
27 * Also, for certain devices, the interrupt endpoint is used to convey
28 * status of a command.
30 * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
31 * information about this driver.
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
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.
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.
51 #include <linux/malloc.h>
54 * kernel thread actions
57 #define US_ACT_COMMAND 1
58 #define US_ACT_DEVICE_RESET 2
59 #define US_ACT_BUS_RESET 3
60 #define US_ACT_HOST_RESET 4
63 /***********************************************************************
65 ***********************************************************************/
67 static const char* host_info(struct Scsi_Host
*host
)
69 return "SCSI emulation for USB Mass Storage devices";
72 /* detect a virtual adapter (always works) */
73 static int detect(struct SHT
*sht
)
78 /* This is not nice at all, but how else are we to get the
80 us
= (struct us_data
*)sht
->proc_dir
;
82 /* set up the name of our subdirectory under /proc/scsi/ */
83 sprintf(local_name
, "usb-storage-%d", us
->host_number
);
84 sht
->proc_name
= kmalloc (strlen(local_name
) + 1, GFP_KERNEL
);
87 strcpy(sht
->proc_name
, local_name
);
89 /* we start with no /proc directory entry */
92 /* register the host */
93 us
->host
= scsi_register(sht
, sizeof(us
));
95 us
->host
->hostdata
[0] = (unsigned long)us
;
96 us
->host_no
= us
->host
->host_no
;
100 /* odd... didn't register properly. Abort and free pointers */
101 kfree(sht
->proc_name
);
102 sht
->proc_name
= NULL
;
106 /* Release all resources used by the virtual host
108 * NOTE: There is no contention here, because we're allready deregistered
109 * the driver and we're doing each virtual host in turn, not in parallel
111 static int release(struct Scsi_Host
*psh
)
113 struct us_data
*us
= (struct us_data
*)psh
->hostdata
[0];
115 US_DEBUGP("us_release() called for host %s\n", us
->htmplt
.name
);
117 /* Kill the control threads
119 * Enqueue the command, wake up the thread, and wait for
120 * notification that it's exited.
122 US_DEBUGP("-- sending US_ACT_EXIT command to thread\n");
123 us
->action
= US_ACT_EXIT
;
127 /* free the data structure we were using */
128 US_DEBUGP("-- freeing URB\n");
129 kfree(us
->current_urb
);
130 (struct us_data
*)psh
->hostdata
[0] = NULL
;
132 /* we always have a successful release */
137 static int command( Scsi_Cmnd
*srb
)
139 US_DEBUGP("Bad use of us_command\n");
141 return DID_BAD_TARGET
<< 16;
145 static int queuecommand( Scsi_Cmnd
*srb
, void (*done
)(Scsi_Cmnd
*))
147 struct us_data
*us
= (struct us_data
*)srb
->host
->hostdata
[0];
149 US_DEBUGP("queuecommand() called\n");
150 srb
->host_scribble
= (unsigned char *)us
;
152 /* get exclusive access to the structures we want */
153 down(&(us
->queue_exclusion
));
155 /* enqueue the command */
157 srb
->scsi_done
= done
;
158 us
->action
= US_ACT_COMMAND
;
160 /* release the lock on the structure */
161 up(&(us
->queue_exclusion
));
163 /* wake up the process task */
169 /***********************************************************************
170 * Error handling functions
171 ***********************************************************************/
175 * Note that this is really only meaningful right now for CBI transport
176 * devices which have failed to give us the command completion interrupt
178 static int command_abort( Scsi_Cmnd
*srb
)
180 struct us_data
*us
= (struct us_data
*)srb
->host
->hostdata
[0];
181 wait_queue_head_t
*wqh
= (wait_queue_head_t
*)us
->current_urb
->context
;
183 US_DEBUGP("command_abort() called\n");
185 /* if we're stuck waiting for an IRQ, simulate it */
187 US_DEBUGP("-- simulating missing IRQ\n");
192 /* if we have an urb pending, let's wake the control thread up */
193 if (us
->current_urb
->status
== -EINPROGRESS
) {
195 usb_unlink_urb(us
->current_urb
);
197 /* wake the control thread up */
198 if (waitqueue_active(wqh
))
201 /* wait for us to be done */
206 US_DEBUGP ("-- nothing to abort\n");
210 /* FIXME: this doesn't do anything right now */
211 static int bus_reset( Scsi_Cmnd
*srb
)
213 // struct us_data *us = (struct us_data *)srb->host->hostdata[0];
215 printk(KERN_CRIT
"usb-storage: bus_reset() requested but not implemented\n" );
216 US_DEBUGP("Bus reset requested\n");
217 // us->transport_reset(us);
221 /* FIXME: This doesn't actually reset anything */
222 static int host_reset( Scsi_Cmnd
*srb
)
224 printk(KERN_CRIT
"usb-storage: host_reset() requested but not implemented\n" );
228 /***********************************************************************
229 * /proc/scsi/ functions
230 ***********************************************************************/
232 /* we use this macro to help us write into the buffer */
234 #define SPRINTF(args...) \
235 do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
237 static int proc_info (char *buffer
, char **start
, off_t offset
, int length
,
238 int hostno
, int inout
)
243 /* if someone is sending us data, just throw it away */
247 /* lock the data structures */
248 down(&us_list_semaphore
);
250 /* find our data from hostno */
253 if (us
->host_no
== hostno
)
258 /* if we couldn't find it, we return an error */
260 up(&us_list_semaphore
);
264 /* print the controler name */
265 SPRINTF(" Host scsi%d: usb-storage\n", hostno
);
267 /* print product, vendor, and serial number strings */
268 SPRINTF(" Vendor: %s\n", us
->vendor
);
269 SPRINTF(" Product: %s\n", us
->product
);
270 SPRINTF("Serial Number: %s\n", us
->serial
);
272 /* show the protocol and transport */
273 SPRINTF(" Protocol: %s\n", us
->protocol_name
);
274 SPRINTF(" Transport: %s\n", us
->transport_name
);
276 /* show the GUID of the device */
277 SPRINTF(" GUID: " GUID_FORMAT
"\n", GUID_ARGS(us
->guid
));
279 /* release our lock on the data structures */
280 up(&us_list_semaphore
);
283 * Calculate start of next buffer, and return value.
285 *start
= buffer
+ offset
;
287 if ((pos
- buffer
) < offset
)
289 else if ((pos
- buffer
- offset
) < length
)
290 return (pos
- buffer
- offset
);
296 * this defines our 'host'
299 Scsi_Host_Template usb_stor_host_template
= {
301 proc_info
: proc_info
,
307 queuecommand
: queuecommand
,
309 eh_abort_handler
: command_abort
,
310 eh_device_reset_handler
:bus_reset
,
311 eh_bus_reset_handler
: bus_reset
,
312 eh_host_reset_handler
: host_reset
,
317 sg_tablesize
: SG_ALL
,
320 unchecked_isa_dma
: FALSE
,
321 use_clustering
: TRUE
,
322 use_new_eh_code
: TRUE
,
326 unsigned char usb_stor_sense_notready
[18] = {
327 [0] = 0x70, /* current error */
328 [2] = 0x02, /* not ready */
329 [5] = 0x0a, /* additional length */
330 [10] = 0x04, /* not ready */
331 [11] = 0x03 /* manual intervention */
334 #define USB_STOR_SCSI_SENSE_HDRSZ 4
335 #define USB_STOR_SCSI_SENSE_10_HDRSZ 8
337 struct usb_stor_scsi_sense_hdr
345 typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr
;
347 union usb_stor_scsi_sense_hdr_u
349 Usb_Stor_Scsi_Sense_Hdr hdr
;
350 __u8
* array
[USB_STOR_SCSI_SENSE_HDRSZ
];
353 typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u
;
355 struct usb_stor_scsi_sense_hdr_10
363 __u8
* blkDescLengthMSB
;
364 __u8
* blkDescLengthLSB
;
367 typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10
;
369 union usb_stor_scsi_sense_hdr_10_u
371 Usb_Stor_Scsi_Sense_Hdr_10 hdr
;
372 __u8
* array
[USB_STOR_SCSI_SENSE_10_HDRSZ
];
375 typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u
;
377 void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd
* , Usb_Stor_Scsi_Sense_Hdr_u
*,
378 Usb_Stor_Scsi_Sense_Hdr_10_u
*, int* );
380 int usb_stor_scsiSense10to6( Scsi_Cmnd
* the10
)
383 int outputBufferSize
= 0;
385 struct scatterlist
*sg
= 0;
386 int i
=0, j
=0, element
=0;
387 Usb_Stor_Scsi_Sense_Hdr_u the6Locations
;
388 Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations
;
389 int sb
=0,si
=0,db
=0,di
=0;
392 US_DEBUGP("-- converting 10 byte sense data to 6 byte\n");
393 the10
->cmnd
[0] = the10
->cmnd
[0] & 0xBF;
395 /* Determine buffer locations */
396 usb_stor_scsiSenseParseBuffer( the10
, &the6Locations
, &the10Locations
,
399 /* Work out minimum buffer to output */
400 outputBufferSize
= *the10Locations
.hdr
.dataLengthLSB
;
401 outputBufferSize
+= USB_STOR_SCSI_SENSE_HDRSZ
;
403 /* Check to see if we need to trucate the output */
404 if ( outputBufferSize
> length
)
406 printk( KERN_WARNING USB_STORAGE
407 "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" );
408 printk( KERN_WARNING USB_STORAGE
409 "outputBufferSize is %d and length is %d.\n",
410 outputBufferSize
, length
);
412 outputBufferSize
= length
;
415 if ( *the10Locations
.hdr
.dataLengthMSB
!= 0 ) /* MSB must be zero */
417 printk( KERN_WARNING USB_STORAGE
418 "Command will be truncated to fit in SENSE6 buffer.\n" );
419 *the6Locations
.hdr
.dataLength
= 0xff;
423 *the6Locations
.hdr
.dataLength
= *the10Locations
.hdr
.dataLengthLSB
;
426 /* Medium type and DevSpecific parms */
427 *the6Locations
.hdr
.mediumType
= *the10Locations
.hdr
.mediumType
;
428 *the6Locations
.hdr
.devSpecParms
= *the10Locations
.hdr
.devSpecParms
;
430 /* Block descriptor length */
431 if ( *the10Locations
.hdr
.blkDescLengthMSB
!= 0 ) /* MSB must be zero */
433 printk( KERN_WARNING USB_STORAGE
434 "Command will be truncated to fit in SENSE6 buffer.\n" );
435 *the6Locations
.hdr
.blkDescLength
= 0xff;
439 *the6Locations
.hdr
.blkDescLength
= *the10Locations
.hdr
.blkDescLengthLSB
;
442 if ( the10
->use_sg
== 0 )
444 buffer
= the10
->request_buffer
;
445 /* Copy the rest of the data */
446 memmove( &(buffer
[USB_STOR_SCSI_SENSE_HDRSZ
]),
447 &(buffer
[USB_STOR_SCSI_SENSE_10_HDRSZ
]),
448 outputBufferSize
- USB_STOR_SCSI_SENSE_HDRSZ
);
449 /* initialise last bytes left in buffer due to smaller header */
450 memset( &(buffer
[outputBufferSize
451 -(USB_STOR_SCSI_SENSE_10_HDRSZ
-USB_STOR_SCSI_SENSE_HDRSZ
)]),
453 USB_STOR_SCSI_SENSE_10_HDRSZ
-USB_STOR_SCSI_SENSE_HDRSZ
);
457 sg
= (struct scatterlist
*) the10
->request_buffer
;
458 /* scan through this scatterlist and figure out starting positions */
459 for ( i
=0; i
< the10
->use_sg
; i
++)
461 sgLength
= sg
[i
].length
;
462 for ( j
=0; j
<sgLength
; j
++ )
464 /* get to end of header */
465 if ( element
== USB_STOR_SCSI_SENSE_HDRSZ
)
470 if ( element
== USB_STOR_SCSI_SENSE_10_HDRSZ
)
474 /* we've found both sets now, exit loops */
482 /* Now we know where to start the copy from */
483 element
= USB_STOR_SCSI_SENSE_HDRSZ
;
484 while ( element
< outputBufferSize
485 -(USB_STOR_SCSI_SENSE_10_HDRSZ
-USB_STOR_SCSI_SENSE_HDRSZ
) )
488 if ( sb
>= the10
->use_sg
||
489 si
>= sg
[sb
].length
||
490 db
>= the10
->use_sg
||
491 di
>= sg
[db
].length
)
493 printk( KERN_ERR USB_STORAGE
494 "Buffer overrun averted, this shouldn't happen!\n" );
499 sg
[db
].address
[di
] = sg
[sb
].address
[si
];
501 /* get next destination */
502 if ( sg
[db
].length
-1 == di
)
512 /* get next source */
513 if ( sg
[sb
].length
-1 == si
)
525 /* zero the remaining bytes */
526 while ( element
< outputBufferSize
)
529 if ( db
>= the10
->use_sg
||
530 di
>= sg
[db
].length
)
532 printk( KERN_ERR USB_STORAGE
533 "Buffer overrun averted, this shouldn't happen!\n" );
537 sg
[db
].address
[di
] = 0;
539 /* get next destination */
540 if ( sg
[db
].length
-1 == di
)
553 /* All done any everything was fine */
557 int usb_stor_scsiSense6to10( Scsi_Cmnd
* the6
)
559 /* will be used to store part of buffer */
560 __u8 tempBuffer
[USB_STOR_SCSI_SENSE_10_HDRSZ
-USB_STOR_SCSI_SENSE_HDRSZ
],
562 int outputBufferSize
= 0;
564 struct scatterlist
*sg
= 0;
565 int i
=0, j
=0, element
=0;
566 Usb_Stor_Scsi_Sense_Hdr_u the6Locations
;
567 Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations
;
568 int sb
=0,si
=0,db
=0,di
=0;
569 int lsb
=0,lsi
=0,ldb
=0,ldi
=0;
571 US_DEBUGP("-- converting 6 byte sense data to 10 byte\n");
572 the6
->cmnd
[0] = the6
->cmnd
[0] | 0x40;
574 /* Determine buffer locations */
575 usb_stor_scsiSenseParseBuffer( the6
, &the6Locations
, &the10Locations
,
578 /* Work out minimum buffer to output */
579 outputBufferSize
= *the6Locations
.hdr
.dataLength
;
580 outputBufferSize
+= USB_STOR_SCSI_SENSE_10_HDRSZ
;
582 /* Check to see if we need to trucate the output */
583 if ( outputBufferSize
> length
)
585 printk( KERN_WARNING USB_STORAGE
586 "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" );
587 printk( KERN_WARNING USB_STORAGE
588 "outputBufferSize is %d and length is %d.\n",
589 outputBufferSize
, length
);
591 outputBufferSize
= length
;
593 /* Block descriptor length - save these before overwriting */
594 tempBuffer
[2] = *the10Locations
.hdr
.blkDescLengthMSB
;
595 tempBuffer
[3] = *the10Locations
.hdr
.blkDescLengthLSB
;
596 *the10Locations
.hdr
.blkDescLengthLSB
= *the6Locations
.hdr
.blkDescLength
;
597 *the10Locations
.hdr
.blkDescLengthMSB
= 0;
599 /* reserved - save these before overwriting */
600 tempBuffer
[0] = *the10Locations
.hdr
.reserved1
;
601 tempBuffer
[1] = *the10Locations
.hdr
.reserved2
;
602 *the10Locations
.hdr
.reserved1
= *the10Locations
.hdr
.reserved2
= 0;
604 /* Medium type and DevSpecific parms */
605 *the10Locations
.hdr
.devSpecParms
= *the6Locations
.hdr
.devSpecParms
;
606 *the10Locations
.hdr
.mediumType
= *the6Locations
.hdr
.mediumType
;
609 *the10Locations
.hdr
.dataLengthLSB
= *the6Locations
.hdr
.dataLength
;
610 *the10Locations
.hdr
.dataLengthMSB
= 0;
614 buffer
= the6
->request_buffer
;
615 /* Copy the rest of the data */
616 memmove( &(buffer
[USB_STOR_SCSI_SENSE_10_HDRSZ
]),
617 &(buffer
[USB_STOR_SCSI_SENSE_HDRSZ
]),
618 outputBufferSize
-USB_STOR_SCSI_SENSE_10_HDRSZ
);
619 /* Put the first four bytes (after header) in place */
620 memcpy( &(buffer
[USB_STOR_SCSI_SENSE_10_HDRSZ
]),
622 USB_STOR_SCSI_SENSE_10_HDRSZ
-USB_STOR_SCSI_SENSE_HDRSZ
);
626 sg
= (struct scatterlist
*) the6
->request_buffer
;
627 /* scan through this scatterlist and figure out ending positions */
628 for ( i
=0; i
< the6
->use_sg
; i
++)
630 for ( j
=0; j
<sg
[i
].length
; j
++ )
632 /* get to end of header */
633 if ( element
== USB_STOR_SCSI_SENSE_HDRSZ
)
638 if ( element
== USB_STOR_SCSI_SENSE_10_HDRSZ
)
642 /* we've found both sets now, exit loops */
650 /* scan through this scatterlist and figure out starting positions */
652 /* destination is the last element */
655 for ( i
=the6
->use_sg
-1; i
>= 0; i
--)
657 for ( j
=sg
[i
].length
-1; j
>=0; j
-- )
659 /* get to end of header and find source for copy */
660 if ( element
== length
- 1
661 - (USB_STOR_SCSI_SENSE_10_HDRSZ
-USB_STOR_SCSI_SENSE_HDRSZ
) )
665 /* we've found both sets now, exit loops */
672 /* Now we know where to start the copy from */
674 - (USB_STOR_SCSI_SENSE_10_HDRSZ
-USB_STOR_SCSI_SENSE_HDRSZ
);
675 while ( element
>= USB_STOR_SCSI_SENSE_10_HDRSZ
)
678 if ( ( sb
<= lsb
&& si
< lsi
) ||
679 ( db
<= ldb
&& di
< ldi
) )
681 printk( KERN_ERR USB_STORAGE
682 "Buffer overrun averted, this shouldn't happen!\n" );
687 sg
[db
].address
[di
] = sg
[sb
].address
[si
];
689 /* get next destination */
700 /* get next source */
713 /* copy the remaining four bytes */
714 while ( element
>= USB_STOR_SCSI_SENSE_HDRSZ
)
717 if ( db
<= ldb
&& di
< ldi
)
719 printk( KERN_ERR USB_STORAGE
720 "Buffer overrun averted, this shouldn't happen!\n" );
724 sg
[db
].address
[di
] = tempBuffer
[element
-USB_STOR_SCSI_SENSE_HDRSZ
];
726 /* get next destination */
740 /* All done and everything was fine */
744 void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd
* srb
, Usb_Stor_Scsi_Sense_Hdr_u
* the6
,
745 Usb_Stor_Scsi_Sense_Hdr_10_u
* the10
,
749 int i
= 0, j
=0, element
=0;
750 struct scatterlist
*sg
= 0;
754 /* are we scatter-gathering? */
755 if ( srb
->use_sg
!= 0 )
757 /* loop over all the scatter gather structures and
758 * get pointer to the data members in the headers
759 * (also work out the length while we're here)
761 sg
= (struct scatterlist
*) srb
->request_buffer
;
762 for (i
= 0; i
< srb
->use_sg
; i
++)
764 length
+= sg
[i
].length
;
765 /* We only do the inner loop for the headers */
766 if ( element
< USB_STOR_SCSI_SENSE_10_HDRSZ
)
768 /* scan through this scatterlist */
769 for ( j
=0; j
<sg
[i
].length
; j
++ )
771 if ( element
< USB_STOR_SCSI_SENSE_HDRSZ
)
773 /* fill in the pointers for both header types */
774 the6
->array
[element
] = &(sg
[i
].address
[j
]);
775 the10
->array
[element
] = &(sg
[i
].address
[j
]);
777 else if ( element
< USB_STOR_SCSI_SENSE_10_HDRSZ
)
779 /* only the longer headers still cares now */
780 the10
->array
[element
] = &(sg
[i
].address
[j
]);
782 /* increase element counter */
790 length
= srb
->request_bufflen
;
791 buffer
= srb
->request_buffer
;
792 if ( length
< USB_STOR_SCSI_SENSE_10_HDRSZ
)
793 printk( KERN_ERR USB_STORAGE
794 "Buffer length smaller than header!!" );
795 for( i
=0; i
<USB_STOR_SCSI_SENSE_10_HDRSZ
; i
++ )
797 if ( i
< USB_STOR_SCSI_SENSE_HDRSZ
)
799 the6
->array
[i
] = &(buffer
[i
]);
800 the10
->array
[i
] = &(buffer
[i
]);
804 the10
->array
[i
] = &(buffer
[i
]);
809 /* Set value of length passed in */