The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/usb_msctest.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 45ea3799f4c5e5fafa9114ce70c16ca7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.