1 /* $NetBSD: usscanner.c,v 1.40 2016/07/07 06:55:42 msaitoh Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net) and LLoyd Parkes. 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This driver is partly based on information taken from the Linux driver 34 * by John Fremlin, Oliver Neukum, and Jeremy Hall. 35 */ 36 /* 37 * Protocol: 38 * Send raw SCSI command on the bulk-out pipe. 39 * If output command then 40 * send further data on the bulk-out pipe 41 * else if input command then 42 * read data on the bulk-in pipe 43 * else 44 * don't do anything. 45 * Read status byte on the interrupt pipe (which doesn't seem to be 46 * an interrupt pipe at all). This operation sometimes times out. 47 */ 48 49 #include <sys/cdefs.h> 50 __KERNEL_RCSID(0, "$NetBSD: usscanner.c,v 1.40 2016/07/07 06:55:42 msaitoh Exp $"); 51 52 #include "scsibus.h" 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/kernel.h> 56 #include <sys/lwp.h> 57 #include <sys/device.h> 58 #include <sys/conf.h> 59 #include <sys/buf.h> 60 61 #include <dev/usb/usb.h> 62 #include <dev/usb/usbdi.h> 63 #include <dev/usb/usbdi_util.h> 64 65 #include <dev/usb/usbdevs.h> 66 67 #include <sys/scsiio.h> 68 #include <dev/scsipi/scsi_spc.h> 69 #include <dev/scsipi/scsi_all.h> 70 #include <dev/scsipi/scsipi_all.h> 71 #include <dev/scsipi/scsiconf.h> 72 #include <dev/scsipi/atapiconf.h> 73 74 #ifdef USSCANNER_DEBUG 75 #define DPRINTF(x) if (usscannerdebug) printf x 76 #define DPRINTFN(n,x) if (usscannerdebug>(n)) printf x 77 int usscannerdebug = 0; 78 #else 79 #define DPRINTF(x) 80 #define DPRINTFN(n,x) 81 #endif 82 83 84 #define USSCANNER_CONFIG_NO 1 85 #define USSCANNER_IFACE_IDX 0 86 87 #define USSCANNER_SCSIID_HOST 0x00 88 #define USSCANNER_SCSIID_DEVICE 0x01 89 90 #define USSCANNER_MAX_TRANSFER_SIZE MAXPHYS 91 92 #define USSCANNER_TIMEOUT 2000 93 94 struct usscanner_softc { 95 device_t sc_dev; 96 struct usbd_device *sc_udev; 97 struct usbd_interface *sc_iface; 98 99 int sc_in_addr; 100 struct usbd_pipe *sc_in_pipe; 101 102 int sc_intr_addr; 103 struct usbd_pipe *sc_intr_pipe; 104 struct usbd_xfer *sc_intr_xfer; 105 u_char sc_status; 106 107 int sc_out_addr; 108 struct usbd_pipe *sc_out_pipe; 109 110 struct usbd_xfer *sc_cmd_xfer; 111 void *sc_cmd_buffer; 112 struct usbd_xfer *sc_datain_xfer; 113 void *sc_datain_buffer; 114 struct usbd_xfer *sc_dataout_xfer; 115 void *sc_dataout_buffer; 116 117 int sc_state; 118 #define UAS_IDLE 0 119 #define UAS_CMD 1 120 #define UAS_DATA 2 121 #define UAS_SENSECMD 3 122 #define UAS_SENSEDATA 4 123 #define UAS_STATUS 5 124 125 struct scsipi_xfer *sc_xs; 126 127 device_t sc_child; /* child device, for detach */ 128 129 struct scsipi_adapter sc_adapter; 130 struct scsipi_channel sc_channel; 131 132 int sc_refcnt; 133 char sc_dying; 134 }; 135 136 137 Static void usscanner_cleanup(struct usscanner_softc *); 138 Static void usscanner_scsipi_request(struct scsipi_channel *, 139 scsipi_adapter_req_t, void *); 140 Static void usscanner_scsipi_minphys(struct buf *); 141 Static void usscanner_done(struct usscanner_softc *); 142 Static void usscanner_sense(struct usscanner_softc *); 143 typedef void callback(struct usbd_xfer *, void *, usbd_status); 144 Static callback usscanner_intr_cb; 145 Static callback usscanner_cmd_cb; 146 Static callback usscanner_data_cb; 147 Static callback usscanner_sensecmd_cb; 148 Static callback usscanner_sensedata_cb; 149 150 int usscanner_match(device_t, cfdata_t, void *); 151 void usscanner_attach(device_t, device_t, void *); 152 void usscanner_childdet(device_t, device_t); 153 int usscanner_detach(device_t, int); 154 int usscanner_activate(device_t, enum devact); 155 extern struct cfdriver usscanner_cd; 156 CFATTACH_DECL2_NEW(usscanner, sizeof(struct usscanner_softc), 157 usscanner_match, usscanner_attach, usscanner_detach, usscanner_activate, 158 NULL, usscanner_childdet); 159 160 int 161 usscanner_match(device_t parent, cfdata_t match, void *aux) 162 { 163 struct usb_attach_arg *uaa = aux; 164 165 DPRINTFN(50,("usscanner_match\n")); 166 167 if (uaa->uaa_vendor == USB_VENDOR_HP && 168 uaa->uaa_product == USB_PRODUCT_HP_5300C) 169 return UMATCH_VENDOR_PRODUCT; 170 else 171 return UMATCH_NONE; 172 } 173 174 void 175 usscanner_attach(device_t parent, device_t self, void *aux) 176 { 177 struct usscanner_softc *sc = device_private(self); 178 struct usb_attach_arg *uaa = aux; 179 struct usbd_device * dev = uaa->uaa_device; 180 struct usbd_interface * iface; 181 char *devinfop; 182 usbd_status err; 183 usb_endpoint_descriptor_t *ed; 184 uint8_t epcount; 185 int i; 186 int error; 187 188 DPRINTFN(10,("usscanner_attach: sc=%p\n", sc)); 189 190 sc->sc_dev = self; 191 192 aprint_naive("\n"); 193 aprint_normal("\n"); 194 195 devinfop = usbd_devinfo_alloc(dev, 0); 196 aprint_normal_dev(self, "%s\n", devinfop); 197 usbd_devinfo_free(devinfop); 198 199 err = usbd_set_config_no(dev, USSCANNER_CONFIG_NO, 1); 200 if (err) { 201 aprint_error_dev(self, "failed to set configuration, err=%s\n", 202 usbd_errstr(err)); 203 return; 204 } 205 206 err = usbd_device2interface_handle(dev, USSCANNER_IFACE_IDX, &iface); 207 if (err) { 208 aprint_error_dev(self, "getting interface handle failed\n"); 209 return; 210 } 211 212 sc->sc_udev = dev; 213 sc->sc_iface = iface; 214 215 epcount = 0; 216 (void)usbd_endpoint_count(iface, &epcount); 217 218 sc->sc_in_addr = -1; 219 sc->sc_intr_addr = -1; 220 sc->sc_out_addr = -1; 221 for (i = 0; i < epcount; i++) { 222 ed = usbd_interface2endpoint_descriptor(iface, i); 223 if (ed == NULL) { 224 aprint_error_dev(self, "couldn't get ep %d\n", i); 225 return; 226 } 227 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 228 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 229 sc->sc_in_addr = ed->bEndpointAddress; 230 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 231 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 232 sc->sc_intr_addr = ed->bEndpointAddress; 233 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 234 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 235 sc->sc_out_addr = ed->bEndpointAddress; 236 } 237 } 238 if (sc->sc_in_addr == -1 || sc->sc_intr_addr == -1 || 239 sc->sc_out_addr == -1) { 240 aprint_error_dev(self, "missing endpoint\n"); 241 return; 242 } 243 244 err = usbd_open_pipe(sc->sc_iface, sc->sc_in_addr, 245 USBD_EXCLUSIVE_USE, &sc->sc_in_pipe); 246 if (err) { 247 aprint_error_dev(self, "open in pipe failed, err=%d\n", err); 248 return; 249 } 250 251 /* The interrupt endpoint must be opened as a normal pipe. */ 252 err = usbd_open_pipe(sc->sc_iface, sc->sc_intr_addr, 253 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe); 254 255 if (err) { 256 aprint_error_dev(self, "open intr pipe failed, err=%d\n", err); 257 usscanner_cleanup(sc); 258 return; 259 } 260 err = usbd_open_pipe(sc->sc_iface, sc->sc_out_addr, 261 USBD_EXCLUSIVE_USE, &sc->sc_out_pipe); 262 if (err) { 263 aprint_error_dev(self, "open out pipe failed, err=%d\n", err); 264 usscanner_cleanup(sc); 265 return; 266 } 267 268 /* XXX too big */ 269 error = usbd_create_xfer(sc->sc_out_pipe, USSCANNER_MAX_TRANSFER_SIZE, 270 0, 0, &sc->sc_cmd_xfer); 271 if (error) { 272 aprint_error_dev(self, "alloc cmd xfer failed, error=%d\n", 273 error); 274 usscanner_cleanup(sc); 275 return; 276 } 277 278 sc->sc_cmd_buffer = usbd_get_buffer(sc->sc_cmd_xfer); 279 280 error = usbd_create_xfer(sc->sc_intr_pipe, 1, USBD_SHORT_XFER_OK, 281 0, &sc->sc_intr_xfer); 282 if (error) { 283 aprint_error_dev(self, "alloc intr xfer failed, error=%d\n", 284 error); 285 usscanner_cleanup(sc); 286 return; 287 } 288 289 error = usbd_create_xfer(sc->sc_in_pipe, USSCANNER_MAX_TRANSFER_SIZE, 290 USBD_SHORT_XFER_OK, 0, &sc->sc_datain_xfer); 291 if (error) { 292 aprint_error_dev(self, "alloc data xfer failed, error=%d\n", 293 error); 294 usscanner_cleanup(sc); 295 return; 296 } 297 sc->sc_datain_buffer = usbd_get_buffer(sc->sc_datain_xfer); 298 299 error = usbd_create_xfer(sc->sc_out_pipe, USSCANNER_MAX_TRANSFER_SIZE, 300 USBD_SHORT_XFER_OK, 0, &sc->sc_dataout_xfer); 301 if (error) { 302 aprint_error_dev(self, "alloc data xfer failed, err=%d\n", err); 303 usscanner_cleanup(sc); 304 return; 305 } 306 sc->sc_dataout_buffer = usbd_get_buffer(sc->sc_dataout_xfer); 307 308 /* 309 * Fill in the adapter. 310 */ 311 sc->sc_adapter.adapt_request = usscanner_scsipi_request; 312 sc->sc_adapter.adapt_dev = sc->sc_dev; 313 sc->sc_adapter.adapt_nchannels = 1; 314 sc->sc_adapter.adapt_openings = 1; 315 sc->sc_adapter.adapt_max_periph = 1; 316 sc->sc_adapter.adapt_minphys = usscanner_scsipi_minphys; 317 318 #if NSCSIBUS > 0 319 /* 320 * fill in the scsipi_channel. 321 */ 322 sc->sc_channel.chan_adapter = &sc->sc_adapter; 323 sc->sc_channel.chan_bustype = &scsi_bustype; 324 sc->sc_channel.chan_channel = 0; 325 sc->sc_channel.chan_ntargets = USSCANNER_SCSIID_DEVICE + 1; 326 sc->sc_channel.chan_nluns = 1; 327 sc->sc_channel.chan_id = USSCANNER_SCSIID_HOST; 328 329 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 330 331 sc->sc_child = config_found(sc->sc_dev, &sc->sc_channel, scsiprint); 332 333 DPRINTFN(10, ("usscanner_attach: %p\n", sc->sc_udev)); 334 335 return; 336 337 #else 338 /* No SCSI bus, just ignore it */ 339 usscanner_cleanup(sc); 340 341 aprint_error_dev(self, 342 "no scsibus configured, see usscanner(4) for details\n"); 343 344 return; 345 346 #endif 347 } 348 349 void 350 usscanner_childdet(device_t self, device_t child) 351 { 352 struct usscanner_softc *sc = device_private(self); 353 354 KASSERT(sc->sc_child == NULL); 355 sc->sc_child = NULL; 356 } 357 358 int 359 usscanner_detach(device_t self, int flags) 360 { 361 struct usscanner_softc *sc = device_private(self); 362 int rv, s; 363 364 DPRINTF(("usscanner_detach: sc=%p flags=%d\n", sc, flags)); 365 366 sc->sc_dying = 1; 367 /* Abort all pipes. Causes processes waiting for transfer to wake. */ 368 if (sc->sc_in_pipe != NULL) 369 usbd_abort_pipe(sc->sc_in_pipe); 370 if (sc->sc_intr_pipe != NULL) 371 usbd_abort_pipe(sc->sc_intr_pipe); 372 if (sc->sc_out_pipe != NULL) 373 usbd_abort_pipe(sc->sc_out_pipe); 374 375 s = splusb(); 376 if (--sc->sc_refcnt >= 0) { 377 /* Wait for processes to go away. */ 378 usb_detach_waitold(sc->sc_dev); 379 } 380 splx(s); 381 382 if (sc->sc_child != NULL) 383 rv = config_detach(sc->sc_child, flags); 384 else 385 rv = 0; 386 387 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 388 389 return rv; 390 } 391 392 Static void 393 usscanner_cleanup(struct usscanner_softc *sc) 394 { 395 if (sc->sc_cmd_xfer != NULL) { 396 usbd_destroy_xfer(sc->sc_cmd_xfer); 397 sc->sc_cmd_xfer = NULL; 398 } 399 if (sc->sc_datain_xfer != NULL) { 400 usbd_destroy_xfer(sc->sc_datain_xfer); 401 sc->sc_datain_xfer = NULL; 402 } 403 if (sc->sc_dataout_xfer != NULL) { 404 usbd_destroy_xfer(sc->sc_dataout_xfer); 405 sc->sc_dataout_xfer = NULL; 406 } 407 if (sc->sc_in_pipe != NULL) { 408 usbd_close_pipe(sc->sc_in_pipe); 409 sc->sc_in_pipe = NULL; 410 } 411 if (sc->sc_intr_pipe != NULL) { 412 usbd_close_pipe(sc->sc_intr_pipe); 413 sc->sc_intr_pipe = NULL; 414 } 415 if (sc->sc_out_pipe != NULL) { 416 usbd_close_pipe(sc->sc_out_pipe); 417 sc->sc_out_pipe = NULL; 418 } 419 } 420 421 int 422 usscanner_activate(device_t self, enum devact act) 423 { 424 struct usscanner_softc *sc = device_private(self); 425 426 switch (act) { 427 case DVACT_DEACTIVATE: 428 sc->sc_dying = 1; 429 return 0; 430 default: 431 return EOPNOTSUPP; 432 } 433 } 434 435 Static void 436 usscanner_scsipi_minphys(struct buf *bp) 437 { 438 if (bp->b_bcount > USSCANNER_MAX_TRANSFER_SIZE) 439 bp->b_bcount = USSCANNER_MAX_TRANSFER_SIZE; 440 minphys(bp); 441 } 442 443 Static void 444 usscanner_sense(struct usscanner_softc *sc) 445 { 446 struct scsipi_xfer *xs = sc->sc_xs; 447 struct scsipi_periph *periph = xs->xs_periph; 448 struct scsi_request_sense sense_cmd; 449 usbd_status err; 450 451 /* fetch sense data */ 452 memset(&sense_cmd, 0, sizeof(sense_cmd)); 453 sense_cmd.opcode = SCSI_REQUEST_SENSE; 454 sense_cmd.byte2 = periph->periph_lun << SCSI_CMD_LUN_SHIFT; 455 sense_cmd.length = sizeof(xs->sense); 456 457 sc->sc_state = UAS_SENSECMD; 458 memcpy(sc->sc_cmd_buffer, &sense_cmd, sizeof(sense_cmd)); 459 460 usbd_setup_xfer(sc->sc_cmd_xfer, sc, sc->sc_cmd_buffer, 461 sizeof(sense_cmd), 0, USSCANNER_TIMEOUT, 462 usscanner_sensecmd_cb); 463 err = usbd_transfer(sc->sc_cmd_xfer); 464 if (err == USBD_IN_PROGRESS) 465 return; 466 467 xs->error = XS_DRIVER_STUFFUP; 468 usscanner_done(sc); 469 } 470 471 Static void 472 usscanner_intr_cb(struct usbd_xfer *xfer, void *priv, usbd_status status) 473 { 474 struct usscanner_softc *sc = priv; 475 int s; 476 477 DPRINTFN(10, ("usscanner_data_cb status=%d\n", status)); 478 479 #ifdef USSCANNER_DEBUG 480 if (sc->sc_state != UAS_STATUS) { 481 printf("%s: !UAS_STATUS\n", device_xname(sc->sc_dev)); 482 } 483 if (sc->sc_status != 0) { 484 printf("%s: status byte=0x%02x\n", device_xname(sc->sc_dev), 485 sc->sc_status); 486 } 487 #endif 488 /* XXX what should we do on non-0 status */ 489 490 sc->sc_state = UAS_IDLE; 491 492 s = splbio(); 493 KERNEL_LOCK(1, curlwp); 494 scsipi_done(sc->sc_xs); 495 KERNEL_UNLOCK_ONE(curlwp); 496 splx(s); 497 } 498 499 Static void 500 usscanner_data_cb(struct usbd_xfer *xfer, void *priv, usbd_status status) 501 { 502 struct usscanner_softc *sc = priv; 503 struct scsipi_xfer *xs = sc->sc_xs; 504 uint32_t len; 505 506 DPRINTFN(10, ("usscanner_data_cb status=%d\n", status)); 507 508 #ifdef USSCANNER_DEBUG 509 if (sc->sc_state != UAS_DATA) { 510 printf("%s: !UAS_DATA\n", device_xname(sc->sc_dev)); 511 } 512 #endif 513 514 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); 515 516 xs->resid = xs->datalen - len; 517 518 switch (status) { 519 case USBD_NORMAL_COMPLETION: 520 xs->error = XS_NOERROR; 521 break; 522 case USBD_TIMEOUT: 523 xs->error = XS_TIMEOUT; 524 break; 525 case USBD_CANCELLED: 526 if (xs->error == XS_SENSE) { 527 usscanner_sense(sc); 528 return; 529 } 530 break; 531 default: 532 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */ 533 break; 534 } 535 usscanner_done(sc); 536 } 537 538 Static void 539 usscanner_sensedata_cb(struct usbd_xfer *xfer, void *priv, usbd_status status) 540 { 541 struct usscanner_softc *sc = priv; 542 struct scsipi_xfer *xs = sc->sc_xs; 543 uint32_t len; 544 545 DPRINTFN(10, ("usscanner_sensedata_cb status=%d\n", status)); 546 547 #ifdef USSCANNER_DEBUG 548 if (sc->sc_state != UAS_SENSEDATA) { 549 printf("%s: !UAS_SENSEDATA\n", device_xname(sc->sc_dev)); 550 } 551 #endif 552 553 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); 554 555 switch (status) { 556 case USBD_NORMAL_COMPLETION: 557 memcpy(&xs->sense, sc->sc_datain_buffer, len); 558 if (len < sizeof(xs->sense)) 559 xs->error = XS_SHORTSENSE; 560 break; 561 case USBD_TIMEOUT: 562 xs->error = XS_TIMEOUT; 563 break; 564 case USBD_CANCELLED: 565 xs->error = XS_RESET; 566 break; 567 default: 568 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */ 569 break; 570 } 571 usscanner_done(sc); 572 } 573 574 Static void 575 usscanner_done(struct usscanner_softc *sc) 576 { 577 struct scsipi_xfer *xs = sc->sc_xs; 578 usbd_status err; 579 580 DPRINTFN(10,("usscanner_done: error=%d\n", sc->sc_xs->error)); 581 582 sc->sc_state = UAS_STATUS; 583 usbd_setup_xfer(sc->sc_intr_xfer, sc, &sc->sc_status, 1, 584 USBD_SHORT_XFER_OK, USSCANNER_TIMEOUT, usscanner_intr_cb); 585 err = usbd_transfer(sc->sc_intr_xfer); 586 if (err == USBD_IN_PROGRESS) 587 return; 588 xs->error = XS_DRIVER_STUFFUP; 589 } 590 591 Static void 592 usscanner_sensecmd_cb(struct usbd_xfer *xfer, void *priv, usbd_status status) 593 { 594 struct usscanner_softc *sc = priv; 595 struct scsipi_xfer *xs = sc->sc_xs; 596 usbd_status err; 597 598 DPRINTFN(10, ("usscanner_sensecmd_cb status=%d\n", status)); 599 600 #ifdef USSCANNER_DEBUG 601 if (usscannerdebug > 15) 602 xs->xs_periph->periph_flags |= 1; /* XXX 1 */ 603 604 if (sc->sc_state != UAS_SENSECMD) { 605 aprint_error_dev(sc->sc_dev, "!UAS_SENSECMD\n"); 606 xs->error = XS_DRIVER_STUFFUP; 607 goto done; 608 } 609 #endif 610 611 switch (status) { 612 case USBD_NORMAL_COMPLETION: 613 break; 614 case USBD_TIMEOUT: 615 xs->error = XS_TIMEOUT; 616 goto done; 617 default: 618 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */ 619 goto done; 620 } 621 622 sc->sc_state = UAS_SENSEDATA; 623 usbd_setup_xfer(sc->sc_datain_xfer, sc, sc->sc_datain_buffer, 624 sizeof(xs->sense), USBD_SHORT_XFER_OK, 625 USSCANNER_TIMEOUT, usscanner_sensedata_cb); 626 err = usbd_transfer(sc->sc_datain_xfer); 627 if (err == USBD_IN_PROGRESS) 628 return; 629 xs->error = XS_DRIVER_STUFFUP; 630 done: 631 usscanner_done(sc); 632 } 633 634 Static void 635 usscanner_cmd_cb(struct usbd_xfer *xfer, void *priv, usbd_status status) 636 { 637 struct usscanner_softc *sc = priv; 638 struct scsipi_xfer *xs = sc->sc_xs; 639 struct usbd_xfer *dxfer; 640 usbd_status err; 641 642 DPRINTFN(10, ("usscanner_cmd_cb status=%d\n", status)); 643 644 #ifdef USSCANNER_DEBUG 645 if (usscannerdebug > 15) 646 xs->xs_periph->periph_flags |= 1; /* XXX 1 */ 647 648 if (sc->sc_state != UAS_CMD) { 649 aprint_error_dev(sc->sc_dev, "!UAS_CMD\n"); 650 xs->error = XS_DRIVER_STUFFUP; 651 goto done; 652 } 653 #endif 654 655 switch (status) { 656 case USBD_NORMAL_COMPLETION: 657 break; 658 case USBD_TIMEOUT: 659 xs->error = XS_TIMEOUT; 660 goto done; 661 case USBD_CANCELLED: 662 goto done; 663 default: 664 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */ 665 goto done; 666 } 667 668 if (xs->datalen == 0) { 669 DPRINTFN(4, ("usscanner_cmd_cb: no data phase\n")); 670 xs->error = XS_NOERROR; 671 goto done; 672 } 673 674 if (xs->xs_control & XS_CTL_DATA_IN) { 675 DPRINTFN(4, ("usscanner_cmd_cb: data in len=%d\n", 676 xs->datalen)); 677 dxfer = sc->sc_datain_xfer; 678 } else { 679 DPRINTFN(4, ("usscanner_cmd_cb: data out len=%d\n", 680 xs->datalen)); 681 dxfer = sc->sc_dataout_xfer; 682 } 683 sc->sc_state = UAS_DATA; 684 usbd_setup_xfer(dxfer, sc, xs->data, xs->datalen, 685 USBD_SHORT_XFER_OK, xs->timeout, usscanner_data_cb); 686 err = usbd_transfer(dxfer); 687 if (err == USBD_IN_PROGRESS) 688 return; 689 xs->error = XS_DRIVER_STUFFUP; 690 691 done: 692 usscanner_done(sc); 693 } 694 695 Static void 696 usscanner_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 697 void *arg) 698 { 699 struct scsipi_xfer *xs; 700 struct usscanner_softc *sc = 701 device_private(chan->chan_adapter->adapt_dev); 702 usbd_status err; 703 704 switch (req) { 705 case ADAPTER_REQ_RUN_XFER: 706 xs = arg; 707 708 DPRINTFN(8, ("%s: usscanner_scsipi_request: %d:%d " 709 "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n", 710 device_xname(sc->sc_dev), 711 xs->xs_periph->periph_target, xs->xs_periph->periph_lun, 712 xs, xs->cmd->opcode, xs->datalen, 713 xs->xs_periph->periph_quirks, 714 xs->xs_control & XS_CTL_POLL)); 715 716 if (sc->sc_dying) { 717 xs->error = XS_DRIVER_STUFFUP; 718 goto done; 719 } 720 721 #ifdef USSCANNER_DEBUG 722 if (xs->xs_periph->periph_target != USSCANNER_SCSIID_DEVICE) { 723 DPRINTF(("%s: wrong SCSI ID %d\n", 724 device_xname(sc->sc_dev), 725 xs->xs_periph->periph_target)); 726 xs->error = XS_DRIVER_STUFFUP; 727 goto done; 728 } 729 if (sc->sc_state != UAS_IDLE) { 730 printf("%s: !UAS_IDLE\n", device_xname(sc->sc_dev)); 731 xs->error = XS_DRIVER_STUFFUP; 732 goto done; 733 } 734 #endif 735 736 if (xs->datalen > USSCANNER_MAX_TRANSFER_SIZE) { 737 aprint_normal_dev(sc->sc_dev, 738 "usscanner_scsipi_request: large datalen, %d\n", 739 xs->datalen); 740 xs->error = XS_DRIVER_STUFFUP; 741 goto done; 742 } 743 744 DPRINTFN(4, ("%s: usscanner_scsipi_request: async cmdlen=%d" 745 " datalen=%d\n", device_xname(sc->sc_dev), xs->cmdlen, 746 xs->datalen)); 747 sc->sc_state = UAS_CMD; 748 sc->sc_xs = xs; 749 memcpy(sc->sc_cmd_buffer, xs->cmd, xs->cmdlen); 750 usbd_setup_xfer(sc->sc_cmd_xfer, sc, sc->sc_cmd_buffer, 751 xs->cmdlen, 0, USSCANNER_TIMEOUT, usscanner_cmd_cb); 752 err = usbd_transfer(sc->sc_cmd_xfer); 753 if (err != USBD_IN_PROGRESS) { 754 xs->error = XS_DRIVER_STUFFUP; 755 goto done; 756 } 757 758 return; 759 760 761 done: 762 sc->sc_state = UAS_IDLE; 763 KERNEL_LOCK(1, curlwp); 764 scsipi_done(xs); 765 KERNEL_UNLOCK_ONE(curlwp); 766 return; 767 768 case ADAPTER_REQ_GROW_RESOURCES: 769 /* XXX Not supported. */ 770 return; 771 case ADAPTER_REQ_SET_XFER_MODE: 772 /* XXX Not supported. */ 773 return; 774 } 775 776 } 777