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