xref: /openbmc/linux/drivers/usb/storage/protocol.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /* Driver for USB Mass Storage compliant devices
2*1da177e4SLinus Torvalds  *
3*1da177e4SLinus Torvalds  * $Id: protocol.c,v 1.14 2002/04/22 03:39:43 mdharm Exp $
4*1da177e4SLinus Torvalds  *
5*1da177e4SLinus Torvalds  * Current development and maintenance by:
6*1da177e4SLinus Torvalds  *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
7*1da177e4SLinus Torvalds  *
8*1da177e4SLinus Torvalds  * Developed with the assistance of:
9*1da177e4SLinus Torvalds  *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
10*1da177e4SLinus Torvalds  *   (c) 2002 Alan Stern (stern@rowland.org)
11*1da177e4SLinus Torvalds  *
12*1da177e4SLinus Torvalds  * Initial work by:
13*1da177e4SLinus Torvalds  *   (c) 1999 Michael Gee (michael@linuxspecific.com)
14*1da177e4SLinus Torvalds  *
15*1da177e4SLinus Torvalds  * This driver is based on the 'USB Mass Storage Class' document. This
16*1da177e4SLinus Torvalds  * describes in detail the protocol used to communicate with such
17*1da177e4SLinus Torvalds  * devices.  Clearly, the designers had SCSI and ATAPI commands in
18*1da177e4SLinus Torvalds  * mind when they created this document.  The commands are all very
19*1da177e4SLinus Torvalds  * similar to commands in the SCSI-II and ATAPI specifications.
20*1da177e4SLinus Torvalds  *
21*1da177e4SLinus Torvalds  * It is important to note that in a number of cases this class
22*1da177e4SLinus Torvalds  * exhibits class-specific exemptions from the USB specification.
23*1da177e4SLinus Torvalds  * Notably the usage of NAK, STALL and ACK differs from the norm, in
24*1da177e4SLinus Torvalds  * that they are used to communicate wait, failed and OK on commands.
25*1da177e4SLinus Torvalds  *
26*1da177e4SLinus Torvalds  * Also, for certain devices, the interrupt endpoint is used to convey
27*1da177e4SLinus Torvalds  * status of a command.
28*1da177e4SLinus Torvalds  *
29*1da177e4SLinus Torvalds  * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
30*1da177e4SLinus Torvalds  * information about this driver.
31*1da177e4SLinus Torvalds  *
32*1da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify it
33*1da177e4SLinus Torvalds  * under the terms of the GNU General Public License as published by the
34*1da177e4SLinus Torvalds  * Free Software Foundation; either version 2, or (at your option) any
35*1da177e4SLinus Torvalds  * later version.
36*1da177e4SLinus Torvalds  *
37*1da177e4SLinus Torvalds  * This program is distributed in the hope that it will be useful, but
38*1da177e4SLinus Torvalds  * WITHOUT ANY WARRANTY; without even the implied warranty of
39*1da177e4SLinus Torvalds  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
40*1da177e4SLinus Torvalds  * General Public License for more details.
41*1da177e4SLinus Torvalds  *
42*1da177e4SLinus Torvalds  * You should have received a copy of the GNU General Public License along
43*1da177e4SLinus Torvalds  * with this program; if not, write to the Free Software Foundation, Inc.,
44*1da177e4SLinus Torvalds  * 675 Mass Ave, Cambridge, MA 02139, USA.
45*1da177e4SLinus Torvalds  */
46*1da177e4SLinus Torvalds 
47*1da177e4SLinus Torvalds #include <linux/highmem.h>
48*1da177e4SLinus Torvalds #include <scsi/scsi.h>
49*1da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h>
50*1da177e4SLinus Torvalds 
51*1da177e4SLinus Torvalds #include "usb.h"
52*1da177e4SLinus Torvalds #include "protocol.h"
53*1da177e4SLinus Torvalds #include "debug.h"
54*1da177e4SLinus Torvalds #include "scsiglue.h"
55*1da177e4SLinus Torvalds #include "transport.h"
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds /***********************************************************************
58*1da177e4SLinus Torvalds  * Protocol routines
59*1da177e4SLinus Torvalds  ***********************************************************************/
60*1da177e4SLinus Torvalds 
61*1da177e4SLinus Torvalds void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us)
62*1da177e4SLinus Torvalds {
63*1da177e4SLinus Torvalds 	/* Pad the ATAPI command with zeros
64*1da177e4SLinus Torvalds 	 *
65*1da177e4SLinus Torvalds 	 * NOTE: This only works because a scsi_cmnd struct field contains
66*1da177e4SLinus Torvalds 	 * a unsigned char cmnd[16], so we know we have storage available
67*1da177e4SLinus Torvalds 	 */
68*1da177e4SLinus Torvalds 	for (; srb->cmd_len<12; srb->cmd_len++)
69*1da177e4SLinus Torvalds 		srb->cmnd[srb->cmd_len] = 0;
70*1da177e4SLinus Torvalds 
71*1da177e4SLinus Torvalds 	/* set command length to 12 bytes */
72*1da177e4SLinus Torvalds 	srb->cmd_len = 12;
73*1da177e4SLinus Torvalds 
74*1da177e4SLinus Torvalds 	/* send the command to the transport layer */
75*1da177e4SLinus Torvalds 	usb_stor_invoke_transport(srb, us);
76*1da177e4SLinus Torvalds }
77*1da177e4SLinus Torvalds 
78*1da177e4SLinus Torvalds void usb_stor_ATAPI_command(struct scsi_cmnd *srb, struct us_data *us)
79*1da177e4SLinus Torvalds {
80*1da177e4SLinus Torvalds 	/* Pad the ATAPI command with zeros
81*1da177e4SLinus Torvalds 	 *
82*1da177e4SLinus Torvalds 	 * NOTE: This only works because a scsi_cmnd struct field contains
83*1da177e4SLinus Torvalds 	 * a unsigned char cmnd[16], so we know we have storage available
84*1da177e4SLinus Torvalds 	 */
85*1da177e4SLinus Torvalds 
86*1da177e4SLinus Torvalds 	/* Pad the ATAPI command with zeros */
87*1da177e4SLinus Torvalds 	for (; srb->cmd_len<12; srb->cmd_len++)
88*1da177e4SLinus Torvalds 		srb->cmnd[srb->cmd_len] = 0;
89*1da177e4SLinus Torvalds 
90*1da177e4SLinus Torvalds 	/* set command length to 12 bytes */
91*1da177e4SLinus Torvalds 	srb->cmd_len = 12;
92*1da177e4SLinus Torvalds 
93*1da177e4SLinus Torvalds 	/* send the command to the transport layer */
94*1da177e4SLinus Torvalds 	usb_stor_invoke_transport(srb, us);
95*1da177e4SLinus Torvalds }
96*1da177e4SLinus Torvalds 
97*1da177e4SLinus Torvalds 
98*1da177e4SLinus Torvalds void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us)
99*1da177e4SLinus Torvalds {
100*1da177e4SLinus Torvalds 	/* fix some commands -- this is a form of mode translation
101*1da177e4SLinus Torvalds 	 * UFI devices only accept 12 byte long commands
102*1da177e4SLinus Torvalds 	 *
103*1da177e4SLinus Torvalds 	 * NOTE: This only works because a scsi_cmnd struct field contains
104*1da177e4SLinus Torvalds 	 * a unsigned char cmnd[16], so we know we have storage available
105*1da177e4SLinus Torvalds 	 */
106*1da177e4SLinus Torvalds 
107*1da177e4SLinus Torvalds 	/* Pad the ATAPI command with zeros */
108*1da177e4SLinus Torvalds 	for (; srb->cmd_len<12; srb->cmd_len++)
109*1da177e4SLinus Torvalds 		srb->cmnd[srb->cmd_len] = 0;
110*1da177e4SLinus Torvalds 
111*1da177e4SLinus Torvalds 	/* set command length to 12 bytes (this affects the transport layer) */
112*1da177e4SLinus Torvalds 	srb->cmd_len = 12;
113*1da177e4SLinus Torvalds 
114*1da177e4SLinus Torvalds 	/* XXX We should be constantly re-evaluating the need for these */
115*1da177e4SLinus Torvalds 
116*1da177e4SLinus Torvalds 	/* determine the correct data length for these commands */
117*1da177e4SLinus Torvalds 	switch (srb->cmnd[0]) {
118*1da177e4SLinus Torvalds 
119*1da177e4SLinus Torvalds 		/* for INQUIRY, UFI devices only ever return 36 bytes */
120*1da177e4SLinus Torvalds 	case INQUIRY:
121*1da177e4SLinus Torvalds 		srb->cmnd[4] = 36;
122*1da177e4SLinus Torvalds 		break;
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds 		/* again, for MODE_SENSE_10, we get the minimum (8) */
125*1da177e4SLinus Torvalds 	case MODE_SENSE_10:
126*1da177e4SLinus Torvalds 		srb->cmnd[7] = 0;
127*1da177e4SLinus Torvalds 		srb->cmnd[8] = 8;
128*1da177e4SLinus Torvalds 		break;
129*1da177e4SLinus Torvalds 
130*1da177e4SLinus Torvalds 		/* for REQUEST_SENSE, UFI devices only ever return 18 bytes */
131*1da177e4SLinus Torvalds 	case REQUEST_SENSE:
132*1da177e4SLinus Torvalds 		srb->cmnd[4] = 18;
133*1da177e4SLinus Torvalds 		break;
134*1da177e4SLinus Torvalds 	} /* end switch on cmnd[0] */
135*1da177e4SLinus Torvalds 
136*1da177e4SLinus Torvalds 	/* send the command to the transport layer */
137*1da177e4SLinus Torvalds 	usb_stor_invoke_transport(srb, us);
138*1da177e4SLinus Torvalds }
139*1da177e4SLinus Torvalds 
140*1da177e4SLinus Torvalds void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
141*1da177e4SLinus Torvalds 				       struct us_data *us)
142*1da177e4SLinus Torvalds {
143*1da177e4SLinus Torvalds 	/* send the command to the transport layer */
144*1da177e4SLinus Torvalds 	usb_stor_invoke_transport(srb, us);
145*1da177e4SLinus Torvalds }
146*1da177e4SLinus Torvalds 
147*1da177e4SLinus Torvalds /***********************************************************************
148*1da177e4SLinus Torvalds  * Scatter-gather transfer buffer access routines
149*1da177e4SLinus Torvalds  ***********************************************************************/
150*1da177e4SLinus Torvalds 
151*1da177e4SLinus Torvalds /* Copy a buffer of length buflen to/from the srb's transfer buffer.
152*1da177e4SLinus Torvalds  * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer
153*1da177e4SLinus Torvalds  * points to a list of s-g entries and we ignore srb->request_bufflen.
154*1da177e4SLinus Torvalds  * For non-scatter-gather transfers, srb->request_buffer points to the
155*1da177e4SLinus Torvalds  * transfer buffer itself and srb->request_bufflen is the buffer's length.)
156*1da177e4SLinus Torvalds  * Update the *index and *offset variables so that the next copy will
157*1da177e4SLinus Torvalds  * pick up from where this one left off. */
158*1da177e4SLinus Torvalds 
159*1da177e4SLinus Torvalds unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
160*1da177e4SLinus Torvalds 	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
161*1da177e4SLinus Torvalds 	unsigned int *offset, enum xfer_buf_dir dir)
162*1da177e4SLinus Torvalds {
163*1da177e4SLinus Torvalds 	unsigned int cnt;
164*1da177e4SLinus Torvalds 
165*1da177e4SLinus Torvalds 	/* If not using scatter-gather, just transfer the data directly.
166*1da177e4SLinus Torvalds 	 * Make certain it will fit in the available buffer space. */
167*1da177e4SLinus Torvalds 	if (srb->use_sg == 0) {
168*1da177e4SLinus Torvalds 		if (*offset >= srb->request_bufflen)
169*1da177e4SLinus Torvalds 			return 0;
170*1da177e4SLinus Torvalds 		cnt = min(buflen, srb->request_bufflen - *offset);
171*1da177e4SLinus Torvalds 		if (dir == TO_XFER_BUF)
172*1da177e4SLinus Torvalds 			memcpy((unsigned char *) srb->request_buffer + *offset,
173*1da177e4SLinus Torvalds 					buffer, cnt);
174*1da177e4SLinus Torvalds 		else
175*1da177e4SLinus Torvalds 			memcpy(buffer, (unsigned char *) srb->request_buffer +
176*1da177e4SLinus Torvalds 					*offset, cnt);
177*1da177e4SLinus Torvalds 		*offset += cnt;
178*1da177e4SLinus Torvalds 
179*1da177e4SLinus Torvalds 	/* Using scatter-gather.  We have to go through the list one entry
180*1da177e4SLinus Torvalds 	 * at a time.  Each s-g entry contains some number of pages, and
181*1da177e4SLinus Torvalds 	 * each page has to be kmap()'ed separately.  If the page is already
182*1da177e4SLinus Torvalds 	 * in kernel-addressable memory then kmap() will return its address.
183*1da177e4SLinus Torvalds 	 * If the page is not directly accessible -- such as a user buffer
184*1da177e4SLinus Torvalds 	 * located in high memory -- then kmap() will map it to a temporary
185*1da177e4SLinus Torvalds 	 * position in the kernel's virtual address space. */
186*1da177e4SLinus Torvalds 	} else {
187*1da177e4SLinus Torvalds 		struct scatterlist *sg =
188*1da177e4SLinus Torvalds 				(struct scatterlist *) srb->request_buffer
189*1da177e4SLinus Torvalds 				+ *index;
190*1da177e4SLinus Torvalds 
191*1da177e4SLinus Torvalds 		/* This loop handles a single s-g list entry, which may
192*1da177e4SLinus Torvalds 		 * include multiple pages.  Find the initial page structure
193*1da177e4SLinus Torvalds 		 * and the starting offset within the page, and update
194*1da177e4SLinus Torvalds 		 * the *offset and *index values for the next loop. */
195*1da177e4SLinus Torvalds 		cnt = 0;
196*1da177e4SLinus Torvalds 		while (cnt < buflen && *index < srb->use_sg) {
197*1da177e4SLinus Torvalds 			struct page *page = sg->page +
198*1da177e4SLinus Torvalds 					((sg->offset + *offset) >> PAGE_SHIFT);
199*1da177e4SLinus Torvalds 			unsigned int poff =
200*1da177e4SLinus Torvalds 					(sg->offset + *offset) & (PAGE_SIZE-1);
201*1da177e4SLinus Torvalds 			unsigned int sglen = sg->length - *offset;
202*1da177e4SLinus Torvalds 
203*1da177e4SLinus Torvalds 			if (sglen > buflen - cnt) {
204*1da177e4SLinus Torvalds 
205*1da177e4SLinus Torvalds 				/* Transfer ends within this s-g entry */
206*1da177e4SLinus Torvalds 				sglen = buflen - cnt;
207*1da177e4SLinus Torvalds 				*offset += sglen;
208*1da177e4SLinus Torvalds 			} else {
209*1da177e4SLinus Torvalds 
210*1da177e4SLinus Torvalds 				/* Transfer continues to next s-g entry */
211*1da177e4SLinus Torvalds 				*offset = 0;
212*1da177e4SLinus Torvalds 				++*index;
213*1da177e4SLinus Torvalds 				++sg;
214*1da177e4SLinus Torvalds 			}
215*1da177e4SLinus Torvalds 
216*1da177e4SLinus Torvalds 			/* Transfer the data for all the pages in this
217*1da177e4SLinus Torvalds 			 * s-g entry.  For each page: call kmap(), do the
218*1da177e4SLinus Torvalds 			 * transfer, and call kunmap() immediately after. */
219*1da177e4SLinus Torvalds 			while (sglen > 0) {
220*1da177e4SLinus Torvalds 				unsigned int plen = min(sglen, (unsigned int)
221*1da177e4SLinus Torvalds 						PAGE_SIZE - poff);
222*1da177e4SLinus Torvalds 				unsigned char *ptr = kmap(page);
223*1da177e4SLinus Torvalds 
224*1da177e4SLinus Torvalds 				if (dir == TO_XFER_BUF)
225*1da177e4SLinus Torvalds 					memcpy(ptr + poff, buffer + cnt, plen);
226*1da177e4SLinus Torvalds 				else
227*1da177e4SLinus Torvalds 					memcpy(buffer + cnt, ptr + poff, plen);
228*1da177e4SLinus Torvalds 				kunmap(page);
229*1da177e4SLinus Torvalds 
230*1da177e4SLinus Torvalds 				/* Start at the beginning of the next page */
231*1da177e4SLinus Torvalds 				poff = 0;
232*1da177e4SLinus Torvalds 				++page;
233*1da177e4SLinus Torvalds 				cnt += plen;
234*1da177e4SLinus Torvalds 				sglen -= plen;
235*1da177e4SLinus Torvalds 			}
236*1da177e4SLinus Torvalds 		}
237*1da177e4SLinus Torvalds 	}
238*1da177e4SLinus Torvalds 
239*1da177e4SLinus Torvalds 	/* Return the amount actually transferred */
240*1da177e4SLinus Torvalds 	return cnt;
241*1da177e4SLinus Torvalds }
242*1da177e4SLinus Torvalds 
243*1da177e4SLinus Torvalds /* Store the contents of buffer into srb's transfer buffer and set the
244*1da177e4SLinus Torvalds  * SCSI residue. */
245*1da177e4SLinus Torvalds void usb_stor_set_xfer_buf(unsigned char *buffer,
246*1da177e4SLinus Torvalds 	unsigned int buflen, struct scsi_cmnd *srb)
247*1da177e4SLinus Torvalds {
248*1da177e4SLinus Torvalds 	unsigned int index = 0, offset = 0;
249*1da177e4SLinus Torvalds 
250*1da177e4SLinus Torvalds 	usb_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
251*1da177e4SLinus Torvalds 			TO_XFER_BUF);
252*1da177e4SLinus Torvalds 	if (buflen < srb->request_bufflen)
253*1da177e4SLinus Torvalds 		srb->resid = srb->request_bufflen - buflen;
254*1da177e4SLinus Torvalds }
255