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