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