xref: /freebsd/sys/dev/usb/usb_msctest.c (revision 7e00348e7605b9906601438008341ffc37c00e2c)
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 /*
28  * The following file contains code that will detect USB autoinstall
29  * disks.
30  *
31  * TODO: Potentially we could add code to automatically detect USB
32  * mass storage quirks for not supported SCSI commands!
33  */
34 
35 #ifdef USB_GLOBAL_INCLUDE_FILE
36 #include USB_GLOBAL_INCLUDE_FILE
37 #else
38 #include <sys/stdint.h>
39 #include <sys/stddef.h>
40 #include <sys/param.h>
41 #include <sys/queue.h>
42 #include <sys/types.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/bus.h>
46 #include <sys/module.h>
47 #include <sys/lock.h>
48 #include <sys/mutex.h>
49 #include <sys/condvar.h>
50 #include <sys/sysctl.h>
51 #include <sys/sx.h>
52 #include <sys/unistd.h>
53 #include <sys/callout.h>
54 #include <sys/malloc.h>
55 #include <sys/priv.h>
56 
57 #include <dev/usb/usb.h>
58 #include <dev/usb/usbdi.h>
59 #include <dev/usb/usbdi_util.h>
60 
61 #define	USB_DEBUG_VAR usb_debug
62 
63 #include <dev/usb/usb_busdma.h>
64 #include <dev/usb/usb_process.h>
65 #include <dev/usb/usb_transfer.h>
66 #include <dev/usb/usb_msctest.h>
67 #include <dev/usb/usb_debug.h>
68 #include <dev/usb/usb_device.h>
69 #include <dev/usb/usb_request.h>
70 #include <dev/usb/usb_util.h>
71 #include <dev/usb/quirk/usb_quirk.h>
72 #endif			/* USB_GLOBAL_INCLUDE_FILE */
73 
74 enum {
75 	ST_COMMAND,
76 	ST_DATA_RD,
77 	ST_DATA_RD_CS,
78 	ST_DATA_WR,
79 	ST_DATA_WR_CS,
80 	ST_STATUS,
81 	ST_MAX,
82 };
83 
84 enum {
85 	DIR_IN,
86 	DIR_OUT,
87 	DIR_NONE,
88 };
89 
90 #define	SCSI_MAX_LEN	MAX(SCSI_FIXED_BLOCK_SIZE, USB_MSCTEST_BULK_SIZE)
91 #define	SCSI_INQ_LEN	0x24
92 #define	SCSI_SENSE_LEN	0xFF
93 #define	SCSI_FIXED_BLOCK_SIZE 512	/* bytes */
94 
95 static uint8_t scsi_test_unit_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
96 static uint8_t scsi_inquiry[] = { 0x12, 0x00, 0x00, 0x00, SCSI_INQ_LEN, 0x00 };
97 static uint8_t scsi_rezero_init[] =     { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
98 static uint8_t scsi_start_stop_unit[] = { 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00 };
99 static uint8_t scsi_ztestor_eject[] =   { 0x85, 0x01, 0x01, 0x01, 0x18, 0x01,
100 					  0x01, 0x01, 0x01, 0x01, 0x00, 0x00 };
101 static uint8_t scsi_cmotech_eject[] =   { 0xff, 0x52, 0x44, 0x45, 0x56, 0x43,
102 					  0x48, 0x47 };
103 static uint8_t scsi_huawei_eject[] =	{ 0x11, 0x06, 0x00, 0x00, 0x00, 0x00,
104 					  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 					  0x00, 0x00, 0x00, 0x00 };
106 static uint8_t scsi_huawei_eject2[] =	{ 0x11, 0x06, 0x20, 0x00, 0x00, 0x01,
107 					  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 					  0x00, 0x00, 0x00, 0x00 };
109 static uint8_t scsi_tct_eject[] =	{ 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 };
110 static uint8_t scsi_sync_cache[] =	{ 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
111 					  0x00, 0x00, 0x00, 0x00 };
112 static uint8_t scsi_request_sense[] =	{ 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
113 					  0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
114 static uint8_t scsi_read_capacity[] =	{ 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
115 					  0x00, 0x00, 0x00, 0x00 };
116 
117 #ifndef USB_MSCTEST_BULK_SIZE
118 #define	USB_MSCTEST_BULK_SIZE	64	/* dummy */
119 #endif
120 
121 #define	ERR_CSW_FAILED		-1
122 
123 /* Command Block Wrapper */
124 struct bbb_cbw {
125 	uDWord	dCBWSignature;
126 #define	CBWSIGNATURE	0x43425355
127 	uDWord	dCBWTag;
128 	uDWord	dCBWDataTransferLength;
129 	uByte	bCBWFlags;
130 #define	CBWFLAGS_OUT	0x00
131 #define	CBWFLAGS_IN	0x80
132 	uByte	bCBWLUN;
133 	uByte	bCDBLength;
134 #define	CBWCDBLENGTH	16
135 	uByte	CBWCDB[CBWCDBLENGTH];
136 } __packed;
137 
138 /* Command Status Wrapper */
139 struct bbb_csw {
140 	uDWord	dCSWSignature;
141 #define	CSWSIGNATURE	0x53425355
142 	uDWord	dCSWTag;
143 	uDWord	dCSWDataResidue;
144 	uByte	bCSWStatus;
145 #define	CSWSTATUS_GOOD	0x0
146 #define	CSWSTATUS_FAILED	0x1
147 #define	CSWSTATUS_PHASE	0x2
148 } __packed;
149 
150 struct bbb_transfer {
151 	struct mtx mtx;
152 	struct cv cv;
153 	struct bbb_cbw *cbw;
154 	struct bbb_csw *csw;
155 
156 	struct usb_xfer *xfer[ST_MAX];
157 
158 	uint8_t *data_ptr;
159 
160 	usb_size_t data_len;		/* bytes */
161 	usb_size_t data_rem;		/* bytes */
162 	usb_timeout_t data_timeout;	/* ms */
163 	usb_frlength_t actlen;		/* bytes */
164 	usb_frlength_t buffer_size;    	/* bytes */
165 
166 	uint8_t	cmd_len;		/* bytes */
167 	uint8_t	dir;
168 	uint8_t	lun;
169 	uint8_t	state;
170 	uint8_t	status_try;
171 	int	error;
172 
173 	uint8_t	*buffer;
174 };
175 
176 static usb_callback_t bbb_command_callback;
177 static usb_callback_t bbb_data_read_callback;
178 static usb_callback_t bbb_data_rd_cs_callback;
179 static usb_callback_t bbb_data_write_callback;
180 static usb_callback_t bbb_data_wr_cs_callback;
181 static usb_callback_t bbb_status_callback;
182 
183 static void	bbb_done(struct bbb_transfer *, int);
184 static void	bbb_transfer_start(struct bbb_transfer *, uint8_t);
185 static void	bbb_data_clear_stall_callback(struct usb_xfer *, uint8_t,
186 		    uint8_t);
187 static int	bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
188 		    void *, size_t, void *, size_t, usb_timeout_t);
189 static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t);
190 static void	bbb_detach(struct bbb_transfer *);
191 
192 static const struct usb_config bbb_config[ST_MAX] = {
193 
194 	[ST_COMMAND] = {
195 		.type = UE_BULK,
196 		.endpoint = UE_ADDR_ANY,
197 		.direction = UE_DIR_OUT,
198 		.bufsize = sizeof(struct bbb_cbw),
199 		.callback = &bbb_command_callback,
200 		.timeout = 4 * USB_MS_HZ,	/* 4 seconds */
201 	},
202 
203 	[ST_DATA_RD] = {
204 		.type = UE_BULK,
205 		.endpoint = UE_ADDR_ANY,
206 		.direction = UE_DIR_IN,
207 		.bufsize = SCSI_MAX_LEN,
208 		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
209 		.callback = &bbb_data_read_callback,
210 		.timeout = 4 * USB_MS_HZ,	/* 4 seconds */
211 	},
212 
213 	[ST_DATA_RD_CS] = {
214 		.type = UE_CONTROL,
215 		.endpoint = 0x00,	/* Control pipe */
216 		.direction = UE_DIR_ANY,
217 		.bufsize = sizeof(struct usb_device_request),
218 		.callback = &bbb_data_rd_cs_callback,
219 		.timeout = 1 * USB_MS_HZ,	/* 1 second  */
220 	},
221 
222 	[ST_DATA_WR] = {
223 		.type = UE_BULK,
224 		.endpoint = UE_ADDR_ANY,
225 		.direction = UE_DIR_OUT,
226 		.bufsize = SCSI_MAX_LEN,
227 		.flags = {.ext_buffer = 1,.proxy_buffer = 1,},
228 		.callback = &bbb_data_write_callback,
229 		.timeout = 4 * USB_MS_HZ,	/* 4 seconds */
230 	},
231 
232 	[ST_DATA_WR_CS] = {
233 		.type = UE_CONTROL,
234 		.endpoint = 0x00,	/* Control pipe */
235 		.direction = UE_DIR_ANY,
236 		.bufsize = sizeof(struct usb_device_request),
237 		.callback = &bbb_data_wr_cs_callback,
238 		.timeout = 1 * USB_MS_HZ,	/* 1 second  */
239 	},
240 
241 	[ST_STATUS] = {
242 		.type = UE_BULK,
243 		.endpoint = UE_ADDR_ANY,
244 		.direction = UE_DIR_IN,
245 		.bufsize = sizeof(struct bbb_csw),
246 		.flags = {.short_xfer_ok = 1,},
247 		.callback = &bbb_status_callback,
248 		.timeout = 1 * USB_MS_HZ,	/* 1 second  */
249 	},
250 };
251 
252 static void
253 bbb_done(struct bbb_transfer *sc, int error)
254 {
255 	sc->error = error;
256 	sc->state = ST_COMMAND;
257 	sc->status_try = 1;
258 	cv_signal(&sc->cv);
259 }
260 
261 static void
262 bbb_transfer_start(struct bbb_transfer *sc, uint8_t xfer_index)
263 {
264 	sc->state = xfer_index;
265 	usbd_transfer_start(sc->xfer[xfer_index]);
266 }
267 
268 static void
269 bbb_data_clear_stall_callback(struct usb_xfer *xfer,
270     uint8_t next_xfer, uint8_t stall_xfer)
271 {
272 	struct bbb_transfer *sc = usbd_xfer_softc(xfer);
273 
274 	if (usbd_clear_stall_callback(xfer, sc->xfer[stall_xfer])) {
275 		switch (USB_GET_STATE(xfer)) {
276 		case USB_ST_SETUP:
277 		case USB_ST_TRANSFERRED:
278 			bbb_transfer_start(sc, next_xfer);
279 			break;
280 		default:
281 			bbb_done(sc, USB_ERR_STALLED);
282 			break;
283 		}
284 	}
285 }
286 
287 static void
288 bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
289 {
290 	struct bbb_transfer *sc = usbd_xfer_softc(xfer);
291 	uint32_t tag;
292 
293 	switch (USB_GET_STATE(xfer)) {
294 	case USB_ST_TRANSFERRED:
295 		bbb_transfer_start
296 		    (sc, ((sc->dir == DIR_IN) ? ST_DATA_RD :
297 		    (sc->dir == DIR_OUT) ? ST_DATA_WR :
298 		    ST_STATUS));
299 		break;
300 
301 	case USB_ST_SETUP:
302 		sc->status_try = 0;
303 		tag = UGETDW(sc->cbw->dCBWTag) + 1;
304 		USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE);
305 		USETDW(sc->cbw->dCBWTag, tag);
306 		USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len);
307 		sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
308 		sc->cbw->bCBWLUN = sc->lun;
309 		sc->cbw->bCDBLength = sc->cmd_len;
310 		if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) {
311 			sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB);
312 			DPRINTFN(0, "Truncating long command\n");
313 		}
314 		usbd_xfer_set_frame_len(xfer, 0,
315 		    sizeof(struct bbb_cbw));
316 		usbd_transfer_submit(xfer);
317 		break;
318 
319 	default:			/* Error */
320 		bbb_done(sc, error);
321 		break;
322 	}
323 }
324 
325 static void
326 bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
327 {
328 	struct bbb_transfer *sc = usbd_xfer_softc(xfer);
329 	usb_frlength_t max_bulk = usbd_xfer_max_len(xfer);
330 	int actlen, sumlen;
331 
332 	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
333 
334 	switch (USB_GET_STATE(xfer)) {
335 	case USB_ST_TRANSFERRED:
336 		sc->data_rem -= actlen;
337 		sc->data_ptr += actlen;
338 		sc->actlen += actlen;
339 
340 		if (actlen < sumlen) {
341 			/* short transfer */
342 			sc->data_rem = 0;
343 		}
344 	case USB_ST_SETUP:
345 		DPRINTF("max_bulk=%d, data_rem=%d\n",
346 		    max_bulk, sc->data_rem);
347 
348 		if (sc->data_rem == 0) {
349 			bbb_transfer_start(sc, ST_STATUS);
350 			break;
351 		}
352 		if (max_bulk > sc->data_rem) {
353 			max_bulk = sc->data_rem;
354 		}
355 		usbd_xfer_set_timeout(xfer, sc->data_timeout);
356 		usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
357 		usbd_transfer_submit(xfer);
358 		break;
359 
360 	default:			/* Error */
361 		if (error == USB_ERR_CANCELLED) {
362 			bbb_done(sc, error);
363 		} else {
364 			bbb_transfer_start(sc, ST_DATA_RD_CS);
365 		}
366 		break;
367 	}
368 }
369 
370 static void
371 bbb_data_rd_cs_callback(struct usb_xfer *xfer, usb_error_t error)
372 {
373 	bbb_data_clear_stall_callback(xfer, ST_STATUS,
374 	    ST_DATA_RD);
375 }
376 
377 static void
378 bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
379 {
380 	struct bbb_transfer *sc = usbd_xfer_softc(xfer);
381 	usb_frlength_t max_bulk = usbd_xfer_max_len(xfer);
382 	int actlen, sumlen;
383 
384 	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
385 
386 	switch (USB_GET_STATE(xfer)) {
387 	case USB_ST_TRANSFERRED:
388 		sc->data_rem -= actlen;
389 		sc->data_ptr += actlen;
390 		sc->actlen += actlen;
391 
392 		if (actlen < sumlen) {
393 			/* short transfer */
394 			sc->data_rem = 0;
395 		}
396 	case USB_ST_SETUP:
397 		DPRINTF("max_bulk=%d, data_rem=%d\n",
398 		    max_bulk, sc->data_rem);
399 
400 		if (sc->data_rem == 0) {
401 			bbb_transfer_start(sc, ST_STATUS);
402 			break;
403 		}
404 		if (max_bulk > sc->data_rem) {
405 			max_bulk = sc->data_rem;
406 		}
407 		usbd_xfer_set_timeout(xfer, sc->data_timeout);
408 		usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
409 		usbd_transfer_submit(xfer);
410 		break;
411 
412 	default:			/* Error */
413 		if (error == USB_ERR_CANCELLED) {
414 			bbb_done(sc, error);
415 		} else {
416 			bbb_transfer_start(sc, ST_DATA_WR_CS);
417 		}
418 		break;
419 	}
420 }
421 
422 static void
423 bbb_data_wr_cs_callback(struct usb_xfer *xfer, usb_error_t error)
424 {
425 	bbb_data_clear_stall_callback(xfer, ST_STATUS,
426 	    ST_DATA_WR);
427 }
428 
429 static void
430 bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
431 {
432 	struct bbb_transfer *sc = usbd_xfer_softc(xfer);
433 	int actlen;
434 	int sumlen;
435 
436 	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
437 
438 	switch (USB_GET_STATE(xfer)) {
439 	case USB_ST_TRANSFERRED:
440 
441 		/* very simple status check */
442 
443 		if (actlen < (int)sizeof(struct bbb_csw)) {
444 			bbb_done(sc, USB_ERR_SHORT_XFER);
445 		} else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) {
446 			bbb_done(sc, 0);	/* success */
447 		} else {
448 			bbb_done(sc, ERR_CSW_FAILED);	/* error */
449 		}
450 		break;
451 
452 	case USB_ST_SETUP:
453 		usbd_xfer_set_frame_len(xfer, 0,
454 		    sizeof(struct bbb_csw));
455 		usbd_transfer_submit(xfer);
456 		break;
457 
458 	default:
459 		DPRINTF("Failed to read CSW: %s, try %d\n",
460 		    usbd_errstr(error), sc->status_try);
461 
462 		if (error == USB_ERR_CANCELLED || sc->status_try) {
463 			bbb_done(sc, error);
464 		} else {
465 			sc->status_try = 1;
466 			bbb_transfer_start(sc, ST_DATA_RD_CS);
467 		}
468 		break;
469 	}
470 }
471 
472 /*------------------------------------------------------------------------*
473  *	bbb_command_start - execute a SCSI command synchronously
474  *
475  * Return values
476  * 0: Success
477  * Else: Failure
478  *------------------------------------------------------------------------*/
479 static int
480 bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
481     void *data_ptr, size_t data_len, void *cmd_ptr, size_t cmd_len,
482     usb_timeout_t data_timeout)
483 {
484 	sc->lun = lun;
485 	sc->dir = data_len ? dir : DIR_NONE;
486 	sc->data_ptr = data_ptr;
487 	sc->data_len = data_len;
488 	sc->data_rem = data_len;
489 	sc->data_timeout = (data_timeout + USB_MS_HZ);
490 	sc->actlen = 0;
491 	sc->error = 0;
492 	sc->cmd_len = cmd_len;
493 	memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB));
494 	memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len);
495 	DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":");
496 
497 	mtx_lock(&sc->mtx);
498 	usbd_transfer_start(sc->xfer[sc->state]);
499 
500 	while (usbd_transfer_pending(sc->xfer[sc->state])) {
501 		cv_wait(&sc->cv, &sc->mtx);
502 	}
503 	mtx_unlock(&sc->mtx);
504 	return (sc->error);
505 }
506 
507 static struct bbb_transfer *
508 bbb_attach(struct usb_device *udev, uint8_t iface_index)
509 {
510 	struct usb_interface *iface;
511 	struct usb_interface_descriptor *id;
512 	struct bbb_transfer *sc;
513 	usb_error_t err;
514 
515 #if USB_HAVE_MSCTEST_DETACH
516 	uint8_t do_unlock;
517 
518 	/* Prevent re-enumeration */
519 	do_unlock = usbd_enum_lock(udev);
520 
521 	/*
522 	 * Make sure any driver which is hooked up to this interface,
523 	 * like umass is gone:
524 	 */
525 	usb_detach_device(udev, iface_index, 0);
526 
527 	if (do_unlock)
528 		usbd_enum_unlock(udev);
529 #endif
530 
531 	iface = usbd_get_iface(udev, iface_index);
532 	if (iface == NULL)
533 		return (NULL);
534 
535 	id = iface->idesc;
536 	if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
537 		return (NULL);
538 
539 	switch (id->bInterfaceSubClass) {
540 	case UISUBCLASS_SCSI:
541 	case UISUBCLASS_UFI:
542 	case UISUBCLASS_SFF8020I:
543 	case UISUBCLASS_SFF8070I:
544 		break;
545 	default:
546 		return (NULL);
547 	}
548 
549 	switch (id->bInterfaceProtocol) {
550 	case UIPROTO_MASS_BBB_OLD:
551 	case UIPROTO_MASS_BBB:
552 		break;
553 	default:
554 		return (NULL);
555 	}
556 
557 	sc = malloc(sizeof(*sc), M_USB, M_WAITOK | M_ZERO);
558 	mtx_init(&sc->mtx, "USB autoinstall", NULL, MTX_DEF);
559 	cv_init(&sc->cv, "WBBB");
560 
561 	err = usbd_transfer_setup(udev, &iface_index, sc->xfer, bbb_config,
562 	    ST_MAX, sc, &sc->mtx);
563 	if (err) {
564 		bbb_detach(sc);
565 		return (NULL);
566 	}
567 	/* store pointer to DMA buffers */
568 	sc->buffer = usbd_xfer_get_frame_buffer(
569 	    sc->xfer[ST_DATA_RD], 0);
570 	sc->buffer_size =
571 	    usbd_xfer_max_len(sc->xfer[ST_DATA_RD]);
572 	sc->cbw = usbd_xfer_get_frame_buffer(
573 	    sc->xfer[ST_COMMAND], 0);
574 	sc->csw = usbd_xfer_get_frame_buffer(
575 	    sc->xfer[ST_STATUS], 0);
576 
577 	return (sc);
578 }
579 
580 static void
581 bbb_detach(struct bbb_transfer *sc)
582 {
583 	usbd_transfer_unsetup(sc->xfer, ST_MAX);
584 	mtx_destroy(&sc->mtx);
585 	cv_destroy(&sc->cv);
586 	free(sc, M_USB);
587 }
588 
589 /*------------------------------------------------------------------------*
590  *	usb_iface_is_cdrom
591  *
592  * Return values:
593  * 1: This interface is an auto install disk (CD-ROM)
594  * 0: Not an auto install disk.
595  *------------------------------------------------------------------------*/
596 int
597 usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
598 {
599 	struct bbb_transfer *sc;
600 	uint8_t timeout;
601 	uint8_t is_cdrom;
602 	uint8_t sid_type;
603 	int err;
604 
605 	sc = bbb_attach(udev, iface_index);
606 	if (sc == NULL)
607 		return (0);
608 
609 	is_cdrom = 0;
610 	timeout = 4;	/* tries */
611 	while (--timeout) {
612 		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
613 		    SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
614 		    USB_MS_HZ);
615 
616 		if (err == 0 && sc->actlen > 0) {
617 			sid_type = sc->buffer[0] & 0x1F;
618 			if (sid_type == 0x05)
619 				is_cdrom = 1;
620 			break;
621 		} else if (err != ERR_CSW_FAILED)
622 			break;	/* non retryable error */
623 		usb_pause_mtx(NULL, hz);
624 	}
625 	bbb_detach(sc);
626 	return (is_cdrom);
627 }
628 
629 static uint8_t
630 usb_msc_get_max_lun(struct usb_device *udev, uint8_t iface_index)
631 {
632 	struct usb_device_request req;
633 	usb_error_t err;
634 	uint8_t buf = 0;
635 
636 
637 	/* The Get Max Lun command is a class-specific request. */
638 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
639 	req.bRequest = 0xFE;		/* GET_MAX_LUN */
640 	USETW(req.wValue, 0);
641 	req.wIndex[0] = iface_index;
642 	req.wIndex[1] = 0;
643 	USETW(req.wLength, 1);
644 
645 	err = usbd_do_request(udev, NULL, &req, &buf);
646 	if (err)
647 		buf = 0;
648 
649 	return (buf);
650 }
651 
652 usb_error_t
653 usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
654 {
655 	struct bbb_transfer *sc;
656 	uint8_t timeout;
657 	uint8_t is_no_direct;
658 	uint8_t sid_type;
659 	int err;
660 
661 	sc = bbb_attach(udev, iface_index);
662 	if (sc == NULL)
663 		return (0);
664 
665 	/*
666 	 * Some devices need a delay after that the configuration
667 	 * value is set to function properly:
668 	 */
669 	usb_pause_mtx(NULL, hz);
670 
671 	if (usb_msc_get_max_lun(udev, iface_index) == 0) {
672 		DPRINTF("Device has only got one LUN.\n");
673 		usbd_add_dynamic_quirk(udev, UQ_MSC_NO_GETMAXLUN);
674 	}
675 
676 	is_no_direct = 1;
677 	for (timeout = 4; timeout != 0; timeout--) {
678 		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
679 		    SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
680 		    USB_MS_HZ);
681 
682 		if (err == 0 && sc->actlen > 0) {
683 			sid_type = sc->buffer[0] & 0x1F;
684 			if (sid_type == 0x00)
685 				is_no_direct = 0;
686 			break;
687 		} else if (err != ERR_CSW_FAILED) {
688 			DPRINTF("Device is not responding "
689 			    "properly to SCSI INQUIRY command.\n");
690 			goto error;	/* non retryable error */
691 		}
692 		usb_pause_mtx(NULL, hz);
693 	}
694 
695 	if (is_no_direct) {
696 		DPRINTF("Device is not direct access.\n");
697 		goto done;
698 	}
699 
700 	err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
701 	    &scsi_test_unit_ready, sizeof(scsi_test_unit_ready),
702 	    USB_MS_HZ);
703 
704 	if (err != 0) {
705 
706 		if (err != ERR_CSW_FAILED)
707 			goto error;
708 	}
709 	timeout = 1;
710 
711 retry_sync_cache:
712 	err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
713 	    &scsi_sync_cache, sizeof(scsi_sync_cache),
714 	    USB_MS_HZ);
715 
716 	if (err != 0) {
717 
718 		if (err != ERR_CSW_FAILED)
719 			goto error;
720 
721 		DPRINTF("Device doesn't handle synchronize cache\n");
722 
723 		usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
724 
725 	} else {
726 
727 		/*
728 		 * Certain Kingston memory sticks fail the first
729 		 * read capacity after a synchronize cache command
730 		 * has been issued. Disable the synchronize cache
731 		 * command for such devices.
732 		 */
733 
734 		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
735 		    &scsi_read_capacity, sizeof(scsi_read_capacity),
736 		    USB_MS_HZ);
737 
738 		if (err != 0) {
739 			if (err != ERR_CSW_FAILED)
740 				goto error;
741 
742 			err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
743 			    &scsi_read_capacity, sizeof(scsi_read_capacity),
744 			    USB_MS_HZ);
745 
746 			if (err == 0) {
747 				if (timeout--)
748 					goto retry_sync_cache;
749 
750 				DPRINTF("Device most likely doesn't "
751 				    "handle synchronize cache\n");
752 
753 				usbd_add_dynamic_quirk(udev,
754 				    UQ_MSC_NO_SYNC_CACHE);
755 			} else {
756 				if (err != ERR_CSW_FAILED)
757 					goto error;
758 			}
759 		}
760 	}
761 
762 	/* clear sense status of any failed commands on the device */
763 
764 	err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
765 	    SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
766 	    USB_MS_HZ);
767 
768 	DPRINTF("Inquiry = %d\n", err);
769 
770 	if (err != 0) {
771 
772 		if (err != ERR_CSW_FAILED)
773 			goto error;
774 	}
775 
776 	err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
777 	    SCSI_SENSE_LEN, &scsi_request_sense,
778 	    sizeof(scsi_request_sense), USB_MS_HZ);
779 
780 	DPRINTF("Request sense = %d\n", err);
781 
782 	if (err != 0) {
783 
784 		if (err != ERR_CSW_FAILED)
785 			goto error;
786 	}
787 
788 done:
789 	bbb_detach(sc);
790 	return (0);
791 
792 error:
793  	bbb_detach(sc);
794 
795 	DPRINTF("Device did not respond, enabling all quirks\n");
796 
797 	usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
798 	usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY);
799 
800 	/* Need to re-enumerate the device */
801 	usbd_req_re_enumerate(udev, NULL);
802 
803 	return (USB_ERR_STALLED);
804 }
805 
806 usb_error_t
807 usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
808 {
809 	struct bbb_transfer *sc;
810 	usb_error_t err;
811 
812 	sc = bbb_attach(udev, iface_index);
813 	if (sc == NULL)
814 		return (USB_ERR_INVAL);
815 
816 	switch (method) {
817 	case MSC_EJECT_STOPUNIT:
818 		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
819 		    &scsi_test_unit_ready, sizeof(scsi_test_unit_ready),
820 		    USB_MS_HZ);
821 		DPRINTF("Test unit ready status: %s\n", usbd_errstr(err));
822 		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
823 		    &scsi_start_stop_unit, sizeof(scsi_start_stop_unit),
824 		    USB_MS_HZ);
825 		break;
826 	case MSC_EJECT_REZERO:
827 		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
828 		    &scsi_rezero_init, sizeof(scsi_rezero_init),
829 		    USB_MS_HZ);
830 		break;
831 	case MSC_EJECT_ZTESTOR:
832 		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
833 		    &scsi_ztestor_eject, sizeof(scsi_ztestor_eject),
834 		    USB_MS_HZ);
835 		break;
836 	case MSC_EJECT_CMOTECH:
837 		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
838 		    &scsi_cmotech_eject, sizeof(scsi_cmotech_eject),
839 		    USB_MS_HZ);
840 		break;
841 	case MSC_EJECT_HUAWEI:
842 		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
843 		    &scsi_huawei_eject, sizeof(scsi_huawei_eject),
844 		    USB_MS_HZ);
845 		break;
846 	case MSC_EJECT_HUAWEI2:
847 		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
848 		    &scsi_huawei_eject2, sizeof(scsi_huawei_eject2),
849 		    USB_MS_HZ);
850 		break;
851 	case MSC_EJECT_TCT:
852 		/*
853 		 * TCTMobile needs DIR_IN flag. To get it, we
854 		 * supply a dummy data with the command.
855 		 */
856 		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
857 		    sc->buffer_size, &scsi_tct_eject,
858 		    sizeof(scsi_tct_eject), USB_MS_HZ);
859 		break;
860 	default:
861 		DPRINTF("Unknown eject method (%d)\n", method);
862 		bbb_detach(sc);
863 		return (USB_ERR_INVAL);
864 	}
865 
866 	DPRINTF("Eject CD command status: %s\n", usbd_errstr(err));
867 
868 	bbb_detach(sc);
869 	return (0);
870 }
871 
872 usb_error_t
873 usb_msc_read_10(struct usb_device *udev, uint8_t iface_index,
874     uint32_t lba, uint32_t blocks, void *buffer)
875 {
876 	struct bbb_transfer *sc;
877 	uint8_t cmd[10];
878 	usb_error_t err;
879 
880 	cmd[0] = 0x28;		/* READ_10 */
881 	cmd[1] = 0;
882 	cmd[2] = lba >> 24;
883 	cmd[3] = lba >> 16;
884 	cmd[4] = lba >> 8;
885 	cmd[5] = lba >> 0;
886 	cmd[6] = 0;
887 	cmd[7] = blocks >> 8;
888 	cmd[8] = blocks;
889 	cmd[9] = 0;
890 
891 	sc = bbb_attach(udev, iface_index);
892 	if (sc == NULL)
893 		return (USB_ERR_INVAL);
894 
895 	err = bbb_command_start(sc, DIR_IN, 0, buffer,
896 	    blocks * SCSI_FIXED_BLOCK_SIZE, cmd, 10, USB_MS_HZ);
897 
898 	bbb_detach(sc);
899 
900 	return (err);
901 }
902 
903 usb_error_t
904 usb_msc_write_10(struct usb_device *udev, uint8_t iface_index,
905     uint32_t lba, uint32_t blocks, void *buffer)
906 {
907 	struct bbb_transfer *sc;
908 	uint8_t cmd[10];
909 	usb_error_t err;
910 
911 	cmd[0] = 0x2a;		/* WRITE_10 */
912 	cmd[1] = 0;
913 	cmd[2] = lba >> 24;
914 	cmd[3] = lba >> 16;
915 	cmd[4] = lba >> 8;
916 	cmd[5] = lba >> 0;
917 	cmd[6] = 0;
918 	cmd[7] = blocks >> 8;
919 	cmd[8] = blocks;
920 	cmd[9] = 0;
921 
922 	sc = bbb_attach(udev, iface_index);
923 	if (sc == NULL)
924 		return (USB_ERR_INVAL);
925 
926 	err = bbb_command_start(sc, DIR_OUT, 0, buffer,
927 	    blocks * SCSI_FIXED_BLOCK_SIZE, cmd, 10, USB_MS_HZ);
928 
929 	bbb_detach(sc);
930 
931 	return (err);
932 }
933 
934 usb_error_t
935 usb_msc_read_capacity(struct usb_device *udev, uint8_t iface_index,
936     uint32_t *lba_last, uint32_t *block_size)
937 {
938 	struct bbb_transfer *sc;
939 	usb_error_t err;
940 
941 	sc = bbb_attach(udev, iface_index);
942 	if (sc == NULL)
943 		return (USB_ERR_INVAL);
944 
945 	err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
946 	    &scsi_read_capacity, sizeof(scsi_read_capacity),
947 	    USB_MS_HZ);
948 
949 	*lba_last =
950 	    (sc->buffer[0] << 24) |
951 	    (sc->buffer[1] << 16) |
952 	    (sc->buffer[2] << 8) |
953 	    (sc->buffer[3]);
954 
955 	*block_size =
956 	    (sc->buffer[4] << 24) |
957 	    (sc->buffer[5] << 16) |
958 	    (sc->buffer[6] << 8) |
959 	    (sc->buffer[7]);
960 
961 	/* we currently only support one block size */
962 	if (*block_size != SCSI_FIXED_BLOCK_SIZE)
963 		err = USB_ERR_INVAL;
964 
965 	bbb_detach(sc);
966 
967 	return (err);
968 }
969