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