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