1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2016 The FreeBSD Foundation 5 * 6 * This software was developed by Edward Tomasz Napierala under sponsorship 7 * from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 /* 32 * USB Mass Storage Class Bulk-Only (BBB) Transport target. 33 * 34 * http://www.usb.org/developers/docs/devclass_docs/usbmassbulk_10.pdf 35 * 36 * This code implements the USB Mass Storage frontend driver for the CAM 37 * Target Layer (ctl(4)) subsystem. 38 */ 39 40 #include <sys/cdefs.h> 41 #include <sys/param.h> 42 #include <sys/bus.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/module.h> 46 #include <sys/mutex.h> 47 #include <sys/refcount.h> 48 #include <sys/stdint.h> 49 #include <sys/sysctl.h> 50 #include <sys/systm.h> 51 52 #include <dev/usb/usb.h> 53 #include <dev/usb/usbdi.h> 54 #include "usbdevs.h" 55 #include "usb_if.h" 56 57 #include <cam/scsi/scsi_all.h> 58 #include <cam/scsi/scsi_da.h> 59 #include <cam/ctl/ctl_io.h> 60 #include <cam/ctl/ctl.h> 61 #include <cam/ctl/ctl_backend.h> 62 #include <cam/ctl/ctl_error.h> 63 #include <cam/ctl/ctl_frontend.h> 64 #include <cam/ctl/ctl_debug.h> 65 #include <cam/ctl/ctl_ha.h> 66 #include <cam/ctl/ctl_ioctl.h> 67 #include <cam/ctl/ctl_private.h> 68 69 SYSCTL_NODE(_hw_usb, OID_AUTO, cfumass, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 70 "CAM Target Layer USB Mass Storage Frontend"); 71 static int debug = 1; 72 SYSCTL_INT(_hw_usb_cfumass, OID_AUTO, debug, CTLFLAG_RWTUN, 73 &debug, 1, "Enable debug messages"); 74 static int max_lun = 0; 75 SYSCTL_INT(_hw_usb_cfumass, OID_AUTO, max_lun, CTLFLAG_RWTUN, 76 &max_lun, 1, "Maximum advertised LUN number"); 77 static int ignore_stop = 1; 78 SYSCTL_INT(_hw_usb_cfumass, OID_AUTO, ignore_stop, CTLFLAG_RWTUN, 79 &ignore_stop, 1, "Ignore START STOP UNIT with START and LOEJ bits cleared"); 80 81 /* 82 * The driver uses a single, global CTL port. It could create its ports 83 * in cfumass_attach() instead, but that would make it impossible to specify 84 * "port cfumass0" in ctl.conf(5), as the port generally wouldn't exist 85 * at the time ctld(8) gets run. 86 */ 87 struct ctl_port cfumass_port; 88 bool cfumass_port_online; 89 volatile u_int cfumass_refcount; 90 91 #ifndef CFUMASS_BULK_SIZE 92 #define CFUMASS_BULK_SIZE (1U << 17) /* bytes */ 93 #endif 94 95 /* 96 * USB transfer definitions. 97 */ 98 #define CFUMASS_T_COMMAND 0 99 #define CFUMASS_T_DATA_OUT 1 100 #define CFUMASS_T_DATA_IN 2 101 #define CFUMASS_T_STATUS 3 102 #define CFUMASS_T_MAX 4 103 104 /* 105 * USB interface specific control requests. 106 */ 107 #define UR_RESET 0xff /* Bulk-Only Mass Storage Reset */ 108 #define UR_GET_MAX_LUN 0xfe /* Get Max LUN */ 109 110 /* 111 * Command Block Wrapper. 112 */ 113 struct cfumass_cbw_t { 114 uDWord dCBWSignature; 115 #define CBWSIGNATURE 0x43425355 /* "USBC" */ 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 CBWCBLENGTH 16 124 uByte CBWCB[CBWCBLENGTH]; 125 } __packed; 126 127 #define CFUMASS_CBW_SIZE 31 128 CTASSERT(sizeof(struct cfumass_cbw_t) == CFUMASS_CBW_SIZE); 129 130 /* 131 * Command Status Wrapper. 132 */ 133 struct cfumass_csw_t { 134 uDWord dCSWSignature; 135 #define CSWSIGNATURE 0x53425355 /* "USBS" */ 136 uDWord dCSWTag; 137 uDWord dCSWDataResidue; 138 uByte bCSWStatus; 139 #define CSWSTATUS_GOOD 0x0 140 #define CSWSTATUS_FAILED 0x1 141 #define CSWSTATUS_PHASE 0x2 142 } __packed; 143 144 #define CFUMASS_CSW_SIZE 13 145 CTASSERT(sizeof(struct cfumass_csw_t) == CFUMASS_CSW_SIZE); 146 147 struct cfumass_softc { 148 device_t sc_dev; 149 struct usb_device *sc_udev; 150 struct usb_xfer *sc_xfer[CFUMASS_T_MAX]; 151 152 struct cfumass_cbw_t *sc_cbw; 153 struct cfumass_csw_t *sc_csw; 154 155 struct mtx sc_mtx; 156 int sc_online; 157 int sc_ctl_initid; 158 159 /* 160 * This is used to communicate between CTL callbacks 161 * and USB callbacks; basically, it holds the state 162 * for the current command ("the" command, since there 163 * is no queueing in USB Mass Storage). 164 */ 165 bool sc_current_stalled; 166 167 /* 168 * The following are set upon receiving a SCSI command. 169 */ 170 int sc_current_tag; 171 int sc_current_transfer_length; 172 int sc_current_flags; 173 174 /* 175 * The following are set in ctl_datamove(). 176 */ 177 int sc_current_residue; 178 union ctl_io *sc_ctl_io; 179 180 /* 181 * The following is set in cfumass_done(). 182 */ 183 int sc_current_status; 184 185 /* 186 * Number of requests queued to CTL. 187 */ 188 volatile u_int sc_queued; 189 }; 190 191 /* 192 * USB interface. 193 */ 194 static device_probe_t cfumass_probe; 195 static device_attach_t cfumass_attach; 196 static device_detach_t cfumass_detach; 197 static device_suspend_t cfumass_suspend; 198 static device_resume_t cfumass_resume; 199 static usb_handle_request_t cfumass_handle_request; 200 201 static usb_callback_t cfumass_t_command_callback; 202 static usb_callback_t cfumass_t_data_callback; 203 static usb_callback_t cfumass_t_status_callback; 204 205 static device_method_t cfumass_methods[] = { 206 /* USB interface. */ 207 DEVMETHOD(usb_handle_request, cfumass_handle_request), 208 209 /* Device interface. */ 210 DEVMETHOD(device_probe, cfumass_probe), 211 DEVMETHOD(device_attach, cfumass_attach), 212 DEVMETHOD(device_detach, cfumass_detach), 213 DEVMETHOD(device_suspend, cfumass_suspend), 214 DEVMETHOD(device_resume, cfumass_resume), 215 216 DEVMETHOD_END 217 }; 218 219 static driver_t cfumass_driver = { 220 .name = "cfumass", 221 .methods = cfumass_methods, 222 .size = sizeof(struct cfumass_softc), 223 }; 224 225 DRIVER_MODULE(cfumass, uhub, cfumass_driver, NULL, NULL); 226 MODULE_VERSION(cfumass, 0); 227 MODULE_DEPEND(cfumass, usb, 1, 1, 1); 228 MODULE_DEPEND(cfumass, usb_template, 1, 1, 1); 229 230 static struct usb_config cfumass_config[CFUMASS_T_MAX] = { 231 [CFUMASS_T_COMMAND] = { 232 .type = UE_BULK, 233 .endpoint = UE_ADDR_ANY, 234 .direction = UE_DIR_OUT, 235 .bufsize = sizeof(struct cfumass_cbw_t), 236 .callback = &cfumass_t_command_callback, 237 .usb_mode = USB_MODE_DEVICE, 238 }, 239 240 [CFUMASS_T_DATA_OUT] = { 241 .type = UE_BULK, 242 .endpoint = UE_ADDR_ANY, 243 .direction = UE_DIR_OUT, 244 .bufsize = CFUMASS_BULK_SIZE, 245 .flags = {.proxy_buffer = 1, .short_xfer_ok = 1, 246 .ext_buffer = 1}, 247 .callback = &cfumass_t_data_callback, 248 .usb_mode = USB_MODE_DEVICE, 249 }, 250 251 [CFUMASS_T_DATA_IN] = { 252 .type = UE_BULK, 253 .endpoint = UE_ADDR_ANY, 254 .direction = UE_DIR_IN, 255 .bufsize = CFUMASS_BULK_SIZE, 256 .flags = {.proxy_buffer = 1, .short_xfer_ok = 1, 257 .ext_buffer = 1}, 258 .callback = &cfumass_t_data_callback, 259 .usb_mode = USB_MODE_DEVICE, 260 }, 261 262 [CFUMASS_T_STATUS] = { 263 .type = UE_BULK, 264 .endpoint = UE_ADDR_ANY, 265 .direction = UE_DIR_IN, 266 .bufsize = sizeof(struct cfumass_csw_t), 267 .flags = {.short_xfer_ok = 1}, 268 .callback = &cfumass_t_status_callback, 269 .usb_mode = USB_MODE_DEVICE, 270 }, 271 }; 272 273 /* 274 * CTL frontend interface. 275 */ 276 static int cfumass_init(void); 277 static int cfumass_shutdown(void); 278 static void cfumass_online(void *arg); 279 static void cfumass_offline(void *arg); 280 static void cfumass_datamove(union ctl_io *io); 281 static void cfumass_done(union ctl_io *io); 282 283 static struct ctl_frontend cfumass_frontend = { 284 .name = "umass", 285 .init = cfumass_init, 286 .shutdown = cfumass_shutdown, 287 }; 288 CTL_FRONTEND_DECLARE(ctlcfumass, cfumass_frontend); 289 290 #define CFUMASS_DEBUG(S, X, ...) \ 291 do { \ 292 if (debug > 1) { \ 293 device_printf(S->sc_dev, "%s: " X "\n", \ 294 __func__, ## __VA_ARGS__); \ 295 } \ 296 } while (0) 297 298 #define CFUMASS_WARN(S, X, ...) \ 299 do { \ 300 if (debug > 0) { \ 301 device_printf(S->sc_dev, "WARNING: %s: " X "\n",\ 302 __func__, ## __VA_ARGS__); \ 303 } \ 304 } while (0) 305 306 #define CFUMASS_LOCK(X) mtx_lock(&X->sc_mtx) 307 #define CFUMASS_UNLOCK(X) mtx_unlock(&X->sc_mtx) 308 309 static void cfumass_transfer_start(struct cfumass_softc *sc, 310 uint8_t xfer_index); 311 static void cfumass_terminate(struct cfumass_softc *sc); 312 313 static int 314 cfumass_probe(device_t dev) 315 { 316 struct usb_attach_arg *uaa; 317 struct usb_interface_descriptor *id; 318 319 uaa = device_get_ivars(dev); 320 321 if (uaa->usb_mode != USB_MODE_DEVICE) 322 return (ENXIO); 323 324 /* 325 * Check for a compliant device. 326 */ 327 id = usbd_get_interface_descriptor(uaa->iface); 328 if ((id == NULL) || 329 (id->bInterfaceClass != UICLASS_MASS) || 330 (id->bInterfaceSubClass != UISUBCLASS_SCSI) || 331 (id->bInterfaceProtocol != UIPROTO_MASS_BBB)) { 332 return (ENXIO); 333 } 334 335 return (BUS_PROBE_GENERIC); 336 } 337 338 static int 339 cfumass_attach(device_t dev) 340 { 341 struct cfumass_softc *sc; 342 struct usb_attach_arg *uaa; 343 int error; 344 345 sc = device_get_softc(dev); 346 uaa = device_get_ivars(dev); 347 348 sc->sc_dev = dev; 349 sc->sc_udev = uaa->device; 350 351 CFUMASS_DEBUG(sc, "go"); 352 353 usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE); 354 device_set_usb_desc(dev); 355 356 mtx_init(&sc->sc_mtx, "cfumass", NULL, MTX_DEF); 357 refcount_acquire(&cfumass_refcount); 358 359 error = usbd_transfer_setup(uaa->device, 360 &uaa->info.bIfaceIndex, sc->sc_xfer, cfumass_config, 361 CFUMASS_T_MAX, sc, &sc->sc_mtx); 362 if (error != 0) { 363 CFUMASS_WARN(sc, "usbd_transfer_setup() failed: %s", 364 usbd_errstr(error)); 365 refcount_release(&cfumass_refcount); 366 return (ENXIO); 367 } 368 369 sc->sc_cbw = 370 usbd_xfer_get_frame_buffer(sc->sc_xfer[CFUMASS_T_COMMAND], 0); 371 sc->sc_csw = 372 usbd_xfer_get_frame_buffer(sc->sc_xfer[CFUMASS_T_STATUS], 0); 373 374 sc->sc_ctl_initid = ctl_add_initiator(&cfumass_port, -1, 0, NULL); 375 if (sc->sc_ctl_initid < 0) { 376 CFUMASS_WARN(sc, "ctl_add_initiator() failed with error %d", 377 sc->sc_ctl_initid); 378 usbd_transfer_unsetup(sc->sc_xfer, CFUMASS_T_MAX); 379 refcount_release(&cfumass_refcount); 380 return (ENXIO); 381 } 382 383 refcount_init(&sc->sc_queued, 0); 384 385 CFUMASS_LOCK(sc); 386 cfumass_transfer_start(sc, CFUMASS_T_COMMAND); 387 CFUMASS_UNLOCK(sc); 388 389 return (0); 390 } 391 392 static int 393 cfumass_detach(device_t dev) 394 { 395 struct cfumass_softc *sc; 396 int error; 397 398 sc = device_get_softc(dev); 399 400 CFUMASS_DEBUG(sc, "go"); 401 402 CFUMASS_LOCK(sc); 403 cfumass_terminate(sc); 404 CFUMASS_UNLOCK(sc); 405 usbd_transfer_unsetup(sc->sc_xfer, CFUMASS_T_MAX); 406 407 if (sc->sc_ctl_initid != -1) { 408 error = ctl_remove_initiator(&cfumass_port, sc->sc_ctl_initid); 409 if (error != 0) { 410 CFUMASS_WARN(sc, "ctl_remove_initiator() failed " 411 "with error %d", error); 412 } 413 sc->sc_ctl_initid = -1; 414 } 415 416 mtx_destroy(&sc->sc_mtx); 417 refcount_release(&cfumass_refcount); 418 419 return (0); 420 } 421 422 static int 423 cfumass_suspend(device_t dev) 424 { 425 struct cfumass_softc *sc; 426 427 sc = device_get_softc(dev); 428 CFUMASS_DEBUG(sc, "go"); 429 430 return (0); 431 } 432 433 static int 434 cfumass_resume(device_t dev) 435 { 436 struct cfumass_softc *sc; 437 438 sc = device_get_softc(dev); 439 CFUMASS_DEBUG(sc, "go"); 440 441 return (0); 442 } 443 444 static void 445 cfumass_transfer_start(struct cfumass_softc *sc, uint8_t xfer_index) 446 { 447 448 usbd_transfer_start(sc->sc_xfer[xfer_index]); 449 } 450 451 static void 452 cfumass_transfer_stop_and_drain(struct cfumass_softc *sc, uint8_t xfer_index) 453 { 454 455 usbd_transfer_stop(sc->sc_xfer[xfer_index]); 456 CFUMASS_UNLOCK(sc); 457 usbd_transfer_drain(sc->sc_xfer[xfer_index]); 458 CFUMASS_LOCK(sc); 459 } 460 461 static void 462 cfumass_terminate(struct cfumass_softc *sc) 463 { 464 int last; 465 466 for (;;) { 467 cfumass_transfer_stop_and_drain(sc, CFUMASS_T_COMMAND); 468 cfumass_transfer_stop_and_drain(sc, CFUMASS_T_DATA_IN); 469 cfumass_transfer_stop_and_drain(sc, CFUMASS_T_DATA_OUT); 470 471 if (sc->sc_ctl_io != NULL) { 472 CFUMASS_DEBUG(sc, "terminating CTL transfer"); 473 ctl_set_data_phase_error(&sc->sc_ctl_io->scsiio); 474 ctl_datamove_done(sc->sc_ctl_io, false); 475 sc->sc_ctl_io = NULL; 476 } 477 478 cfumass_transfer_stop_and_drain(sc, CFUMASS_T_STATUS); 479 480 refcount_acquire(&sc->sc_queued); 481 last = refcount_release(&sc->sc_queued); 482 if (last != 0) 483 break; 484 485 CFUMASS_DEBUG(sc, "%d CTL tasks pending", sc->sc_queued); 486 msleep(__DEVOLATILE(void *, &sc->sc_queued), &sc->sc_mtx, 487 0, "cfumass_reset", hz / 100); 488 } 489 } 490 491 static int 492 cfumass_handle_request(device_t dev, 493 const void *preq, void **pptr, uint16_t *plen, 494 uint16_t offset, uint8_t *pstate) 495 { 496 static uint8_t max_lun_tmp; 497 struct cfumass_softc *sc; 498 const struct usb_device_request *req; 499 uint8_t is_complete; 500 501 sc = device_get_softc(dev); 502 req = preq; 503 is_complete = *pstate; 504 505 CFUMASS_DEBUG(sc, "go"); 506 507 if (is_complete) 508 return (ENXIO); 509 510 if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) && 511 (req->bRequest == UR_RESET)) { 512 CFUMASS_WARN(sc, "received Bulk-Only Mass Storage Reset"); 513 *plen = 0; 514 515 CFUMASS_LOCK(sc); 516 cfumass_terminate(sc); 517 cfumass_transfer_start(sc, CFUMASS_T_COMMAND); 518 CFUMASS_UNLOCK(sc); 519 520 CFUMASS_DEBUG(sc, "Bulk-Only Mass Storage Reset done"); 521 return (0); 522 } 523 524 if ((req->bmRequestType == UT_READ_CLASS_INTERFACE) && 525 (req->bRequest == UR_GET_MAX_LUN)) { 526 CFUMASS_DEBUG(sc, "received Get Max LUN"); 527 if (offset == 0) { 528 *plen = 1; 529 /* 530 * The protocol doesn't support LUN numbers higher 531 * than 15. Also, some initiators (namely Windows XP 532 * SP3 Version 2002) can't properly query the number 533 * of LUNs, resulting in inaccessible "fake" ones - thus 534 * the default limit of one LUN. 535 */ 536 if (max_lun < 0 || max_lun > 15) { 537 CFUMASS_WARN(sc, 538 "invalid hw.usb.cfumass.max_lun, must be " 539 "between 0 and 15; defaulting to 0"); 540 max_lun_tmp = 0; 541 } else { 542 max_lun_tmp = max_lun; 543 } 544 *pptr = &max_lun_tmp; 545 } else { 546 *plen = 0; 547 } 548 return (0); 549 } 550 551 return (ENXIO); 552 } 553 554 static int 555 cfumass_quirk(struct cfumass_softc *sc, unsigned char *cdb, int cdb_len) 556 { 557 struct scsi_start_stop_unit *sssu; 558 559 switch (cdb[0]) { 560 case START_STOP_UNIT: 561 /* 562 * Some initiators - eg OSX, Darwin Kernel Version 15.6.0, 563 * root:xnu-3248.60.11~2/RELEASE_X86_64 - attempt to stop 564 * the unit on eject, but fail to start it when it's plugged 565 * back. Just ignore the command. 566 */ 567 568 if (cdb_len < sizeof(*sssu)) { 569 CFUMASS_DEBUG(sc, "received START STOP UNIT with " 570 "bCDBLength %d, should be %zd", 571 cdb_len, sizeof(*sssu)); 572 break; 573 } 574 575 sssu = (struct scsi_start_stop_unit *)cdb; 576 if ((sssu->how & SSS_PC_MASK) != 0) 577 break; 578 579 if ((sssu->how & SSS_START) != 0) 580 break; 581 582 if ((sssu->how & SSS_LOEJ) != 0) 583 break; 584 585 if (ignore_stop == 0) { 586 break; 587 } else if (ignore_stop == 1) { 588 CFUMASS_WARN(sc, "ignoring START STOP UNIT request"); 589 } else { 590 CFUMASS_DEBUG(sc, "ignoring START STOP UNIT request"); 591 } 592 593 sc->sc_current_status = 0; 594 cfumass_transfer_start(sc, CFUMASS_T_STATUS); 595 596 return (1); 597 default: 598 break; 599 } 600 601 return (0); 602 } 603 604 static void 605 cfumass_t_command_callback(struct usb_xfer *xfer, usb_error_t usb_error) 606 { 607 struct cfumass_softc *sc; 608 uint32_t signature; 609 union ctl_io *io; 610 int error = 0; 611 612 sc = usbd_xfer_softc(xfer); 613 614 KASSERT(sc->sc_ctl_io == NULL, 615 ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io)); 616 617 switch (USB_GET_STATE(xfer)) { 618 case USB_ST_TRANSFERRED: 619 CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED"); 620 621 signature = UGETDW(sc->sc_cbw->dCBWSignature); 622 if (signature != CBWSIGNATURE) { 623 CFUMASS_WARN(sc, "wrong dCBWSignature 0x%08x, " 624 "should be 0x%08x", signature, CBWSIGNATURE); 625 break; 626 } 627 628 if (sc->sc_cbw->bCDBLength <= 0 || 629 sc->sc_cbw->bCDBLength > sizeof(sc->sc_cbw->CBWCB)) { 630 CFUMASS_WARN(sc, "invalid bCDBLength %d, should be <= %zd", 631 sc->sc_cbw->bCDBLength, sizeof(sc->sc_cbw->CBWCB)); 632 break; 633 } 634 635 sc->sc_current_stalled = false; 636 sc->sc_current_status = 0; 637 sc->sc_current_tag = UGETDW(sc->sc_cbw->dCBWTag); 638 sc->sc_current_transfer_length = 639 UGETDW(sc->sc_cbw->dCBWDataTransferLength); 640 sc->sc_current_flags = sc->sc_cbw->bCBWFlags; 641 642 /* 643 * Make sure to report proper residue if the datamove wasn't 644 * required, or wasn't called due to SCSI error. 645 */ 646 sc->sc_current_residue = sc->sc_current_transfer_length; 647 648 if (cfumass_quirk(sc, 649 sc->sc_cbw->CBWCB, sc->sc_cbw->bCDBLength) != 0) 650 break; 651 652 if (!cfumass_port_online) { 653 CFUMASS_DEBUG(sc, "cfumass port is offline; stalling"); 654 usbd_xfer_set_stall(xfer); 655 break; 656 } 657 658 /* 659 * Those CTL functions cannot be called with mutex held. 660 */ 661 CFUMASS_UNLOCK(sc); 662 io = ctl_alloc_io(cfumass_port.ctl_pool_ref); 663 ctl_zero_io(io); 664 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = sc; 665 io->io_hdr.io_type = CTL_IO_SCSI; 666 io->io_hdr.nexus.initid = sc->sc_ctl_initid; 667 io->io_hdr.nexus.targ_port = cfumass_port.targ_port; 668 io->io_hdr.nexus.targ_lun = ctl_decode_lun(sc->sc_cbw->bCBWLUN); 669 io->scsiio.tag_num = UGETDW(sc->sc_cbw->dCBWTag); 670 io->scsiio.tag_type = CTL_TAG_UNTAGGED; 671 io->scsiio.cdb_len = sc->sc_cbw->bCDBLength; 672 memcpy(io->scsiio.cdb, sc->sc_cbw->CBWCB, sc->sc_cbw->bCDBLength); 673 refcount_acquire(&sc->sc_queued); 674 error = ctl_queue(io); 675 if (error != CTL_RETVAL_COMPLETE) { 676 CFUMASS_WARN(sc, 677 "ctl_queue() failed; error %d; stalling", error); 678 ctl_free_io(io); 679 refcount_release(&sc->sc_queued); 680 CFUMASS_LOCK(sc); 681 usbd_xfer_set_stall(xfer); 682 break; 683 } 684 685 CFUMASS_LOCK(sc); 686 break; 687 688 case USB_ST_SETUP: 689 tr_setup: 690 CFUMASS_DEBUG(sc, "USB_ST_SETUP"); 691 692 usbd_xfer_set_frame_len(xfer, 0, sizeof(*sc->sc_cbw)); 693 usbd_transfer_submit(xfer); 694 break; 695 696 default: 697 if (usb_error == USB_ERR_CANCELLED) { 698 CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED"); 699 break; 700 } 701 702 CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error)); 703 704 goto tr_setup; 705 } 706 } 707 708 static void 709 cfumass_t_data_callback(struct usb_xfer *xfer, usb_error_t usb_error) 710 { 711 struct cfumass_softc *sc = usbd_xfer_softc(xfer); 712 union ctl_io *io = sc->sc_ctl_io; 713 uint32_t max_bulk; 714 struct ctl_sg_entry sg_entry, *sglist; 715 int actlen, sumlen, sg_count; 716 717 switch (USB_GET_STATE(xfer)) { 718 case USB_ST_TRANSFERRED: 719 CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED"); 720 721 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 722 sc->sc_current_residue -= actlen; 723 io->scsiio.ext_data_filled += actlen; 724 io->scsiio.kern_data_resid -= actlen; 725 if (actlen < sumlen || 726 sc->sc_current_residue == 0 || 727 io->scsiio.kern_data_resid == 0) { 728 sc->sc_ctl_io = NULL; 729 ctl_datamove_done(io, false); 730 break; 731 } 732 /* FALLTHROUGH */ 733 734 case USB_ST_SETUP: 735 tr_setup: 736 CFUMASS_DEBUG(sc, "USB_ST_SETUP"); 737 738 if (io->scsiio.kern_sg_entries > 0) { 739 sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; 740 sg_count = io->scsiio.kern_sg_entries; 741 } else { 742 sglist = &sg_entry; 743 sglist->addr = io->scsiio.kern_data_ptr; 744 sglist->len = io->scsiio.kern_data_len; 745 sg_count = 1; 746 } 747 748 sumlen = io->scsiio.ext_data_filled - 749 io->scsiio.kern_rel_offset; 750 while (sumlen >= sglist->len && sg_count > 0) { 751 sumlen -= sglist->len; 752 sglist++; 753 sg_count--; 754 } 755 KASSERT(sg_count > 0, ("Run out of S/G list entries")); 756 757 max_bulk = usbd_xfer_max_len(xfer); 758 actlen = min(sglist->len - sumlen, max_bulk); 759 actlen = min(actlen, sc->sc_current_transfer_length - 760 io->scsiio.ext_data_filled); 761 CFUMASS_DEBUG(sc, "requested %d, done %d, max_bulk %d, " 762 "segment %zd => transfer %d", 763 sc->sc_current_transfer_length, io->scsiio.ext_data_filled, 764 max_bulk, sglist->len - sumlen, actlen); 765 766 usbd_xfer_set_frame_data(xfer, 0, 767 (uint8_t *)sglist->addr + sumlen, actlen); 768 usbd_transfer_submit(xfer); 769 break; 770 771 default: 772 if (usb_error == USB_ERR_CANCELLED) { 773 CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED"); 774 break; 775 } 776 CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error)); 777 goto tr_setup; 778 } 779 } 780 781 static void 782 cfumass_t_status_callback(struct usb_xfer *xfer, usb_error_t usb_error) 783 { 784 struct cfumass_softc *sc; 785 786 sc = usbd_xfer_softc(xfer); 787 788 KASSERT(sc->sc_ctl_io == NULL, 789 ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io)); 790 791 switch (USB_GET_STATE(xfer)) { 792 case USB_ST_TRANSFERRED: 793 CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED"); 794 795 cfumass_transfer_start(sc, CFUMASS_T_COMMAND); 796 break; 797 798 case USB_ST_SETUP: 799 tr_setup: 800 CFUMASS_DEBUG(sc, "USB_ST_SETUP"); 801 802 if (sc->sc_current_residue > 0 && !sc->sc_current_stalled) { 803 CFUMASS_DEBUG(sc, "non-zero residue, stalling"); 804 usbd_xfer_set_stall(xfer); 805 sc->sc_current_stalled = true; 806 } 807 808 USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE); 809 USETDW(sc->sc_csw->dCSWTag, sc->sc_current_tag); 810 USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_current_residue); 811 sc->sc_csw->bCSWStatus = sc->sc_current_status; 812 813 usbd_xfer_set_frame_len(xfer, 0, sizeof(*sc->sc_csw)); 814 usbd_transfer_submit(xfer); 815 break; 816 817 default: 818 if (usb_error == USB_ERR_CANCELLED) { 819 CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED"); 820 break; 821 } 822 823 CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s", 824 usbd_errstr(usb_error)); 825 826 goto tr_setup; 827 } 828 } 829 830 static void 831 cfumass_online(void *arg __unused) 832 { 833 834 cfumass_port_online = true; 835 } 836 837 static void 838 cfumass_offline(void *arg __unused) 839 { 840 841 cfumass_port_online = false; 842 } 843 844 static void 845 cfumass_datamove(union ctl_io *io) 846 { 847 struct cfumass_softc *sc; 848 849 sc = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 850 851 CFUMASS_DEBUG(sc, "go"); 852 853 CFUMASS_LOCK(sc); 854 855 KASSERT(sc->sc_ctl_io == NULL, 856 ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io)); 857 sc->sc_ctl_io = io; 858 859 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) { 860 /* 861 * Verify that CTL wants us to send the data in the direction 862 * expected by the initiator. 863 */ 864 if (sc->sc_current_flags != CBWFLAGS_IN) { 865 CFUMASS_WARN(sc, "wrong bCBWFlags 0x%x, should be 0x%x", 866 sc->sc_current_flags, CBWFLAGS_IN); 867 goto fail; 868 } 869 870 cfumass_transfer_start(sc, CFUMASS_T_DATA_IN); 871 } else { 872 if (sc->sc_current_flags != CBWFLAGS_OUT) { 873 CFUMASS_WARN(sc, "wrong bCBWFlags 0x%x, should be 0x%x", 874 sc->sc_current_flags, CBWFLAGS_OUT); 875 goto fail; 876 } 877 878 cfumass_transfer_start(sc, CFUMASS_T_DATA_OUT); 879 } 880 881 CFUMASS_UNLOCK(sc); 882 return; 883 884 fail: 885 ctl_set_data_phase_error(&io->scsiio); 886 ctl_datamove_done(io, true); 887 sc->sc_ctl_io = NULL; 888 } 889 890 static void 891 cfumass_done(union ctl_io *io) 892 { 893 struct cfumass_softc *sc; 894 895 sc = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 896 897 CFUMASS_DEBUG(sc, "go"); 898 899 KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE), 900 ("invalid CTL status %#x", io->io_hdr.status)); 901 KASSERT(sc->sc_ctl_io == NULL, 902 ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io)); 903 904 if (io->io_hdr.io_type == CTL_IO_TASK && 905 io->taskio.task_action == CTL_TASK_I_T_NEXUS_RESET) { 906 /* 907 * Implicit task termination has just completed; nothing to do. 908 */ 909 ctl_free_io(io); 910 return; 911 } 912 913 /* 914 * Do not return status for aborted commands. 915 * There are exceptions, but none supported by CTL yet. 916 */ 917 if (((io->io_hdr.flags & CTL_FLAG_ABORT) && 918 (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) || 919 (io->io_hdr.flags & CTL_FLAG_STATUS_SENT)) { 920 ctl_free_io(io); 921 return; 922 } 923 924 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) 925 sc->sc_current_status = 0; 926 else 927 sc->sc_current_status = 1; 928 929 /* XXX: How should we report BUSY, RESERVATION CONFLICT, etc? */ 930 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SCSI_ERROR && 931 io->scsiio.scsi_status == SCSI_STATUS_CHECK_COND) 932 ctl_queue_sense(io); 933 else 934 ctl_free_io(io); 935 936 CFUMASS_LOCK(sc); 937 cfumass_transfer_start(sc, CFUMASS_T_STATUS); 938 CFUMASS_UNLOCK(sc); 939 940 refcount_release(&sc->sc_queued); 941 } 942 943 int 944 cfumass_init(void) 945 { 946 int error; 947 948 cfumass_port.frontend = &cfumass_frontend; 949 cfumass_port.port_type = CTL_PORT_UMASS; 950 cfumass_port.num_requested_ctl_io = 1; 951 cfumass_port.port_name = "cfumass"; 952 cfumass_port.physical_port = 0; 953 cfumass_port.virtual_port = 0; 954 cfumass_port.port_online = cfumass_online; 955 cfumass_port.port_offline = cfumass_offline; 956 cfumass_port.onoff_arg = NULL; 957 cfumass_port.fe_datamove = cfumass_datamove; 958 cfumass_port.fe_done = cfumass_done; 959 cfumass_port.targ_port = -1; 960 961 error = ctl_port_register(&cfumass_port); 962 if (error != 0) { 963 printf("%s: ctl_port_register() failed " 964 "with error %d", __func__, error); 965 } 966 967 cfumass_port_online = true; 968 refcount_init(&cfumass_refcount, 0); 969 970 return (error); 971 } 972 973 int 974 cfumass_shutdown(void) 975 { 976 int error; 977 978 if (cfumass_refcount > 0) { 979 if (debug > 1) { 980 printf("%s: still have %u attachments; " 981 "returning EBUSY\n", __func__, cfumass_refcount); 982 } 983 return (EBUSY); 984 } 985 986 error = ctl_port_deregister(&cfumass_port); 987 if (error != 0) { 988 printf("%s: ctl_port_deregister() failed " 989 "with error %d\n", __func__, error); 990 } 991 992 return (error); 993 } 994