kernel/usb4bsd: Install gadget example drivers and fix usbtest.
[dragonfly.git] / sys / bus / u4b / usb_msctest.c
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 }