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