1 /* Driver for USB Mass Storage compliant devices
3 * $Id: protocol.c,v 1.7 2000/11/13 22:28:33 mdharm Exp $
5 * Current development and maintenance by:
6 * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
8 * Developed with the assistance of:
9 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
12 * (c) 1999 Michael Gee (michael@linuxspecific.com)
14 * This driver is based on the 'USB Mass Storage Class' document. This
15 * describes in detail the protocol used to communicate with such
16 * devices. Clearly, the designers had SCSI and ATAPI commands in
17 * mind when they created this document. The commands are all very
18 * similar to commands in the SCSI-II and ATAPI specifications.
20 * It is important to note that in a number of cases this class
21 * exhibits class-specific exemptions from the USB specification.
22 * Notably the usage of NAK, STALL and ACK differs from the norm, in
23 * that they are used to communicate wait, failed and OK on commands.
25 * Also, for certain devices, the interrupt endpoint is used to convey
26 * status of a command.
28 * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
29 * information about this driver.
31 * This program is free software; you can redistribute it and/or modify it
32 * under the terms of the GNU General Public License as published by the
33 * Free Software Foundation; either version 2, or (at your option) any
36 * This program is distributed in the hope that it will be useful, but
37 * WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 * General Public License for more details.
41 * You should have received a copy of the GNU General Public License along
42 * with this program; if not, write to the Free Software Foundation, Inc.,
43 * 675 Mass Ave, Cambridge, MA 02139, USA.
50 #include "transport.h"
52 /***********************************************************************
54 ***********************************************************************/
56 /* Fix-up the return data from an INQUIRY command to show
57 * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
59 void fix_inquiry_data(Scsi_Cmnd *srb)
61 unsigned char *data_ptr;
63 /* verify that it's an INQUIRY command */
64 if (srb->cmnd[0] != INQUIRY)
67 US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n");
69 /* find the location of the data */
71 struct scatterlist *sg;
73 sg = (struct scatterlist *) srb->request_buffer;
74 data_ptr = (unsigned char *) sg[0].address;
76 data_ptr = (unsigned char *)srb->request_buffer;
78 /* Change the SCSI revision number */
82 /***********************************************************************
84 ***********************************************************************/
86 void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
88 /* Pad the ATAPI command with zeros
89 * NOTE: This only works because a Scsi_Cmnd struct field contains
90 * a unsigned char cmnd[12], so we know we have storage available
92 for (; srb->cmd_len<12; srb->cmd_len++)
93 srb->cmnd[srb->cmd_len] = 0;
95 /* set command length to 12 bytes */
98 /* send the command to the transport layer */
99 usb_stor_invoke_transport(srb, us);
101 /* fix the INQUIRY data if necessary */
102 fix_inquiry_data(srb);
105 void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
109 /* Fix some commands -- this is a form of mode translation
110 * ATAPI devices only accept 12 byte long commands
112 * NOTE: This only works because a Scsi_Cmnd struct field contains
113 * a unsigned char cmnd[12], so we know we have storage available
116 /* Pad the ATAPI command with zeros */
117 for (; srb->cmd_len<12; srb->cmd_len++)
118 srb->cmnd[srb->cmd_len] = 0;
120 /* set command length to 12 bytes */
123 /* determine the correct (or minimum) data length for these commands */
124 switch (srb->cmnd[0]) {
126 /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
129 /* save the command so we can tell what it was */
130 old_cmnd = srb->cmnd[0];
135 srb->cmnd[8] = srb->cmnd[4];
141 srb->cmnd[2] = srb->cmnd[2];
142 srb->cmnd[1] = srb->cmnd[1];
143 srb->cmnd[0] = srb->cmnd[0] | 0x40;
146 /* change READ_6/WRITE_6 to READ_10/WRITE_10, which
147 * are ATAPI commands */
153 srb->cmnd[8] = srb->cmnd[4];
156 srb->cmnd[5] = srb->cmnd[3];
157 srb->cmnd[4] = srb->cmnd[2];
158 srb->cmnd[3] = srb->cmnd[1] & 0x1F;
160 srb->cmnd[1] = srb->cmnd[1] & 0xE0;
161 srb->cmnd[0] = srb->cmnd[0] | 0x20;
163 } /* end switch on cmnd[0] */
165 /* convert MODE_SELECT data here */
166 if (old_cmnd == MODE_SELECT)
167 usb_stor_scsiSense6to10(srb);
169 /* send the command to the transport layer */
170 usb_stor_invoke_transport(srb, us);
172 /* Fix the MODE_SENSE data if we translated the command */
173 if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
174 usb_stor_scsiSense10to6(srb);
176 /* fix the INQUIRY data if necessary */
177 fix_inquiry_data(srb);
181 void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
185 /* fix some commands -- this is a form of mode translation
186 * UFI devices only accept 12 byte long commands
188 * NOTE: This only works because a Scsi_Cmnd struct field contains
189 * a unsigned char cmnd[12], so we know we have storage available
192 /* set command length to 12 bytes (this affects the transport layer) */
195 /* determine the correct (or minimum) data length for these commands */
196 switch (srb->cmnd[0]) {
198 /* for INQUIRY, UFI devices only ever return 36 bytes */
203 /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
206 /* save the command so we can tell what it was */
207 old_cmnd = srb->cmnd[0];
213 /* if we're sending data, we send all. If getting data,
215 if (srb->cmnd[0] == MODE_SELECT)
216 srb->cmnd[8] = srb->cmnd[4];
225 srb->cmnd[2] = srb->cmnd[2];
226 srb->cmnd[1] = srb->cmnd[1];
227 srb->cmnd[0] = srb->cmnd[0] | 0x40;
230 /* again, for MODE_SENSE_10, we get the minimum (8) */
236 /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */
241 /* change READ_6/WRITE_6 to READ_10/WRITE_10, which
242 * are UFI commands */
248 srb->cmnd[8] = srb->cmnd[4];
251 srb->cmnd[5] = srb->cmnd[3];
252 srb->cmnd[4] = srb->cmnd[2];
253 srb->cmnd[3] = srb->cmnd[1] & 0x1F;
255 srb->cmnd[1] = srb->cmnd[1] & 0xE0;
256 srb->cmnd[0] = srb->cmnd[0] | 0x20;
258 } /* end switch on cmnd[0] */
260 /* convert MODE_SELECT data here */
261 if (old_cmnd == MODE_SELECT)
262 usb_stor_scsiSense6to10(srb);
264 /* send the command to the transport layer */
265 usb_stor_invoke_transport(srb, us);
267 /* Fix the MODE_SENSE data if we translated the command */
268 if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
269 usb_stor_scsiSense10to6(srb);
271 /* Fix the data for an INQUIRY, if necessary */
272 fix_inquiry_data(srb);
275 void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
277 /* This code supports devices which do not support {READ|WRITE}_6
278 * Apparently, neither Windows or MacOS will use these commands,
279 * so some devices do not support them
281 if (us->flags & US_FL_MODE_XLATE) {
283 /* translate READ_6 to READ_10 */
284 if (srb->cmnd[0] == 0x08) {
286 /* get the control */
287 srb->cmnd[9] = us->srb->cmnd[5];
290 srb->cmnd[8] = us->srb->cmnd[6];
293 /* set the reserved area to 0 */
297 srb->cmnd[5] = us->srb->cmnd[3];
298 srb->cmnd[4] = us->srb->cmnd[2];
302 /* LUN and other info in cmnd[1] can stay */
304 /* fix command code */
307 US_DEBUGP("Changing READ_6 to READ_10\n");
308 US_DEBUG(usb_stor_show_command(srb));
311 /* translate WRITE_6 to WRITE_10 */
312 if (srb->cmnd[0] == 0x0A) {
314 /* get the control */
315 srb->cmnd[9] = us->srb->cmnd[5];
318 srb->cmnd[8] = us->srb->cmnd[4];
321 /* set the reserved area to 0 */
325 srb->cmnd[5] = us->srb->cmnd[3];
326 srb->cmnd[4] = us->srb->cmnd[2];
330 /* LUN and other info in cmnd[1] can stay */
332 /* fix command code */
335 US_DEBUGP("Changing WRITE_6 to WRITE_10\n");
336 US_DEBUG(usb_stor_show_command(us->srb));
338 } /* if (us->flags & US_FL_MODE_XLATE) */
340 /* send the command to the transport layer */
341 usb_stor_invoke_transport(srb, us);
343 /* fix the INQUIRY data if necessary */
344 fix_inquiry_data(srb);