Annotation of sys/dev/usb/umass.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: umass.c,v 1.52 2007/06/14 10:11:16 mbalmer Exp $ */
! 2: /* $NetBSD: umass.c,v 1.116 2004/06/30 05:53:46 mycroft Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 2003 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Charles M. Hannum.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: /*-
! 41: * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
! 42: * Nick Hibma <n_hibma@freebsd.org>
! 43: * All rights reserved.
! 44: *
! 45: * Redistribution and use in source and binary forms, with or without
! 46: * modification, are permitted provided that the following conditions
! 47: * are met:
! 48: * 1. Redistributions of source code must retain the above copyright
! 49: * notice, this list of conditions and the following disclaimer.
! 50: * 2. Redistributions in binary form must reproduce the above copyright
! 51: * notice, this list of conditions and the following disclaimer in the
! 52: * documentation and/or other materials provided with the distribution.
! 53: *
! 54: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 55: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 56: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 57: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 58: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 59: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 60: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 61: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 62: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 63: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 64: * SUCH DAMAGE.
! 65: *
! 66: * $FreeBSD: src/sys/dev/usb/umass.c,v 1.13 2000/03/26 01:39:12 n_hibma Exp $
! 67: */
! 68:
! 69: /*
! 70: * Universal Serial Bus Mass Storage Class specs:
! 71: * http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf
! 72: * http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf
! 73: * http://www.usb.org/developers/devclass_docs/usb_msc_cbi_1.1.pdf
! 74: * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf
! 75: */
! 76:
! 77: /*
! 78: * Ported to NetBSD by Lennart Augustsson <augustss@NetBSD.org>.
! 79: * Parts of the code written by Jason R. Thorpe <thorpej@shagadelic.org>.
! 80: */
! 81:
! 82: /*
! 83: * The driver handles 3 Wire Protocols
! 84: * - Command/Bulk/Interrupt (CBI)
! 85: * - Command/Bulk/Interrupt with Command Completion Interrupt (CBI with CCI)
! 86: * - Mass Storage Bulk-Only (BBB)
! 87: * (BBB refers Bulk/Bulk/Bulk for Command/Data/Status phases)
! 88: *
! 89: * Over these wire protocols it handles the following command protocols
! 90: * - SCSI
! 91: * - 8070 (ATA/ATAPI for rewritable removable media)
! 92: * - UFI (USB Floppy Interface)
! 93: *
! 94: * 8070i is a transformed version of the SCSI command set. UFI is a transformed
! 95: * version of the 8070i command set. The sc->transform method is used to
! 96: * convert the commands into the appropriate format (if at all necessary).
! 97: * For example, ATAPI requires all commands to be 12 bytes in length amongst
! 98: * other things.
! 99: *
! 100: * The source code below is marked and can be split into a number of pieces
! 101: * (in this order):
! 102: *
! 103: * - probe/attach/detach
! 104: * - generic transfer routines
! 105: * - BBB
! 106: * - CBI
! 107: * - CBI_I (in addition to functions from CBI)
! 108: * - CAM (Common Access Method)
! 109: * - SCSI
! 110: * - UFI
! 111: * - 8070i
! 112: *
! 113: * The protocols are implemented using a state machine, for the transfers as
! 114: * well as for the resets. The state machine is contained in umass_*_state.
! 115: * The state machine is started through either umass_*_transfer or
! 116: * umass_*_reset.
! 117: *
! 118: * The reason for doing this is a) CAM performs a lot better this way and b) it
! 119: * avoids using tsleep from interrupt context (for example after a failed
! 120: * transfer).
! 121: */
! 122:
! 123: /*
! 124: * The SCSI related part of this driver has been derived from the
! 125: * dev/ppbus/vpo.c driver, by Nicolas Souchu (nsouch@freebsd.org).
! 126: *
! 127: * The CAM layer uses so called actions which are messages sent to the host
! 128: * adapter for completion. The actions come in through umass_cam_action. The
! 129: * appropriate block of routines is called depending on the transport protocol
! 130: * in use. When the transfer has finished, these routines call
! 131: * umass_cam_cb again to complete the CAM command.
! 132: */
! 133:
! 134: #include "atapiscsi.h"
! 135:
! 136: #include <sys/param.h>
! 137: #include <sys/systm.h>
! 138: #include <sys/kernel.h>
! 139: #include <sys/conf.h>
! 140: #include <sys/buf.h>
! 141: #include <sys/device.h>
! 142: #include <sys/malloc.h>
! 143: #include <sys/timeout.h>
! 144: #undef KASSERT
! 145: #define KASSERT(cond, msg)
! 146: #include <machine/bus.h>
! 147:
! 148: #include <scsi/scsi_all.h>
! 149:
! 150: #include <dev/usb/usb.h>
! 151: #include <dev/usb/usbdi.h>
! 152: #include <dev/usb/usbdi_util.h>
! 153: #include <dev/usb/usbdivar.h>
! 154: #include <dev/usb/usbdevs.h>
! 155:
! 156: #include <dev/usb/umassvar.h>
! 157: #include <dev/usb/umass_quirks.h>
! 158: #include <dev/usb/umass_scsi.h>
! 159:
! 160:
! 161: #ifdef UMASS_DEBUG
! 162: int umassdebug = 0;
! 163:
! 164: char *states[TSTATE_STATES+1] = {
! 165: /* should be kept in sync with the list at transfer_state */
! 166: "Idle",
! 167: "BBB CBW",
! 168: "BBB Data",
! 169: "BBB Data bulk-in/-out clear stall",
! 170: "BBB CSW, 1st attempt",
! 171: "BBB CSW bulk-in clear stall",
! 172: "BBB CSW, 2nd attempt",
! 173: "BBB Reset",
! 174: "BBB bulk-in clear stall",
! 175: "BBB bulk-out clear stall",
! 176: "CBI Command",
! 177: "CBI Data",
! 178: "CBI Status",
! 179: "CBI Data bulk-in/-out clear stall",
! 180: "CBI Status intr-in clear stall",
! 181: "CBI Reset",
! 182: "CBI bulk-in clear stall",
! 183: "CBI bulk-out clear stall",
! 184: NULL
! 185: };
! 186: #endif
! 187:
! 188: /* USB device probe/attach/detach functions */
! 189: int umass_match(struct device *, void *, void *);
! 190: void umass_attach(struct device *, struct device *, void *);
! 191: int umass_detach(struct device *, int);
! 192: int umass_activate(struct device *, enum devact);
! 193:
! 194: struct cfdriver umass_cd = {
! 195: NULL, "umass", DV_DULL
! 196: };
! 197:
! 198: const struct cfattach umass_ca = {
! 199: sizeof(struct umass_softc),
! 200: umass_match,
! 201: umass_attach,
! 202: umass_detach,
! 203: umass_activate,
! 204: };
! 205: void umass_disco(struct umass_softc *sc);
! 206:
! 207: /* generic transfer functions */
! 208: usbd_status umass_polled_transfer(struct umass_softc *sc,
! 209: usbd_xfer_handle xfer);
! 210: usbd_status umass_setup_transfer(struct umass_softc *sc,
! 211: usbd_pipe_handle pipe,
! 212: void *buffer, int buflen, int flags,
! 213: usbd_xfer_handle xfer);
! 214: usbd_status umass_setup_ctrl_transfer(struct umass_softc *sc,
! 215: usb_device_request_t *req,
! 216: void *buffer, int buflen, int flags,
! 217: usbd_xfer_handle xfer);
! 218: void umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
! 219: usbd_xfer_handle xfer);
! 220: void umass_adjust_transfer(struct umass_softc *);
! 221: #if 0
! 222: void umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv);
! 223: #endif
! 224:
! 225: /* Bulk-Only related functions */
! 226: void umass_bbb_transfer(struct umass_softc *, int, void *, int, void *,
! 227: int, int, u_int, umass_callback, void *);
! 228: void umass_bbb_reset(struct umass_softc *, int);
! 229: void umass_bbb_state(usbd_xfer_handle, usbd_private_handle, usbd_status);
! 230:
! 231: usbd_status umass_bbb_get_max_lun(struct umass_softc *, u_int8_t *);
! 232:
! 233: /* CBI related functions */
! 234: void umass_cbi_transfer(struct umass_softc *, int, void *, int, void *,
! 235: int, int, u_int, umass_callback, void *);
! 236: void umass_cbi_reset(struct umass_softc *, int);
! 237: void umass_cbi_state(usbd_xfer_handle, usbd_private_handle, usbd_status);
! 238:
! 239: int umass_cbi_adsc(struct umass_softc *, char *, int, usbd_xfer_handle);
! 240:
! 241: const struct umass_wire_methods umass_bbb_methods = {
! 242: umass_bbb_transfer,
! 243: umass_bbb_reset,
! 244: umass_bbb_state
! 245: };
! 246:
! 247: const struct umass_wire_methods umass_cbi_methods = {
! 248: umass_cbi_transfer,
! 249: umass_cbi_reset,
! 250: umass_cbi_state
! 251: };
! 252:
! 253: #ifdef UMASS_DEBUG
! 254: /* General debugging functions */
! 255: void umass_bbb_dump_cbw(struct umass_softc *sc,
! 256: umass_bbb_cbw_t *cbw);
! 257: void umass_bbb_dump_csw(struct umass_softc *sc,
! 258: umass_bbb_csw_t *csw);
! 259: void umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer,
! 260: int buflen, int printlen);
! 261: #endif
! 262:
! 263:
! 264: /*
! 265: * USB device probe/attach/detach
! 266: */
! 267:
! 268: int
! 269: umass_match(struct device *parent, void *match, void *aux)
! 270: {
! 271: struct usb_attach_arg *uaa = aux;
! 272: const struct umass_quirk *quirk;
! 273: usb_interface_descriptor_t *id;
! 274:
! 275: if (uaa->iface == NULL)
! 276: return (UMATCH_NONE);
! 277:
! 278: quirk = umass_lookup(uaa->vendor, uaa->product);
! 279: if (quirk != NULL)
! 280: return (quirk->uq_match);
! 281:
! 282: id = usbd_get_interface_descriptor(uaa->iface);
! 283: if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
! 284: return (UMATCH_NONE);
! 285:
! 286: switch (id->bInterfaceSubClass) {
! 287: case UISUBCLASS_RBC:
! 288: case UISUBCLASS_SFF8020I:
! 289: case UISUBCLASS_QIC157:
! 290: case UISUBCLASS_UFI:
! 291: case UISUBCLASS_SFF8070I:
! 292: case UISUBCLASS_SCSI:
! 293: break;
! 294: default:
! 295: return (UMATCH_IFACECLASS);
! 296: }
! 297:
! 298: switch (id->bInterfaceProtocol) {
! 299: case UIPROTO_MASS_CBI_I:
! 300: case UIPROTO_MASS_CBI:
! 301: case UIPROTO_MASS_BBB_OLD:
! 302: case UIPROTO_MASS_BBB:
! 303: break;
! 304: default:
! 305: return (UMATCH_IFACECLASS_IFACESUBCLASS);
! 306: }
! 307:
! 308: return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
! 309: }
! 310:
! 311: void
! 312: umass_attach(struct device *parent, struct device *self, void *aux)
! 313: {
! 314: struct umass_softc *sc = (struct umass_softc *)self;
! 315: struct usb_attach_arg *uaa = aux;
! 316: const struct umass_quirk *quirk;
! 317: usb_interface_descriptor_t *id;
! 318: usb_endpoint_descriptor_t *ed;
! 319: const char *sWire, *sCommand;
! 320: char *devinfop;
! 321: usbd_status err;
! 322: int i, bno, error;
! 323:
! 324: devinfop = usbd_devinfo_alloc(uaa->device, 0);
! 325: printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
! 326: usbd_devinfo_free(devinfop);
! 327:
! 328: sc->sc_udev = uaa->device;
! 329: sc->sc_iface = uaa->iface;
! 330: sc->sc_ifaceno = uaa->ifaceno;
! 331:
! 332: quirk = umass_lookup(uaa->vendor, uaa->product);
! 333: if (quirk != NULL) {
! 334: sc->sc_wire = quirk->uq_wire;
! 335: sc->sc_cmd = quirk->uq_cmd;
! 336: sc->sc_quirks = quirk->uq_flags;
! 337: sc->sc_busquirks = quirk->uq_busquirks;
! 338:
! 339: if (quirk->uq_fixup != NULL)
! 340: (*quirk->uq_fixup)(sc);
! 341: } else {
! 342: sc->sc_wire = UMASS_WPROTO_UNSPEC;
! 343: sc->sc_cmd = UMASS_CPROTO_UNSPEC;
! 344: sc->sc_quirks = 0;
! 345: sc->sc_busquirks = 0;
! 346: }
! 347:
! 348: id = usbd_get_interface_descriptor(sc->sc_iface);
! 349: if (id == NULL)
! 350: return;
! 351:
! 352: if (sc->sc_wire == UMASS_WPROTO_UNSPEC) {
! 353: switch (id->bInterfaceProtocol) {
! 354: case UIPROTO_MASS_CBI:
! 355: sc->sc_wire = UMASS_WPROTO_CBI;
! 356: break;
! 357: case UIPROTO_MASS_CBI_I:
! 358: sc->sc_wire = UMASS_WPROTO_CBI_I;
! 359: break;
! 360: case UIPROTO_MASS_BBB:
! 361: case UIPROTO_MASS_BBB_OLD:
! 362: sc->sc_wire = UMASS_WPROTO_BBB;
! 363: break;
! 364: default:
! 365: DPRINTF(UDMASS_GEN,
! 366: ("%s: Unsupported wire protocol %u\n",
! 367: sc->sc_dev.dv_xname,
! 368: id->bInterfaceProtocol));
! 369: return;
! 370: }
! 371: }
! 372:
! 373: if (sc->sc_cmd == UMASS_CPROTO_UNSPEC) {
! 374: switch (id->bInterfaceSubClass) {
! 375: case UISUBCLASS_SCSI:
! 376: sc->sc_cmd = UMASS_CPROTO_SCSI;
! 377: break;
! 378: case UISUBCLASS_UFI:
! 379: sc->sc_cmd = UMASS_CPROTO_UFI;
! 380: break;
! 381: case UISUBCLASS_SFF8020I:
! 382: case UISUBCLASS_SFF8070I:
! 383: case UISUBCLASS_QIC157:
! 384: sc->sc_cmd = UMASS_CPROTO_ATAPI;
! 385: break;
! 386: case UISUBCLASS_RBC:
! 387: sc->sc_cmd = UMASS_CPROTO_RBC;
! 388: break;
! 389: default:
! 390: DPRINTF(UDMASS_GEN,
! 391: ("%s: Unsupported command protocol %u\n",
! 392: sc->sc_dev.dv_xname,
! 393: id->bInterfaceSubClass));
! 394: return;
! 395: }
! 396: }
! 397:
! 398: switch (sc->sc_wire) {
! 399: case UMASS_WPROTO_CBI:
! 400: sWire = "CBI";
! 401: break;
! 402: case UMASS_WPROTO_CBI_I:
! 403: sWire = "CBI with CCI";
! 404: break;
! 405: case UMASS_WPROTO_BBB:
! 406: sWire = "Bulk-Only";
! 407: break;
! 408: default:
! 409: sWire = "unknown";
! 410: break;
! 411: }
! 412:
! 413: switch (sc->sc_cmd) {
! 414: case UMASS_CPROTO_RBC:
! 415: sCommand = "RBC";
! 416: break;
! 417: case UMASS_CPROTO_SCSI:
! 418: sCommand = "SCSI";
! 419: break;
! 420: case UMASS_CPROTO_UFI:
! 421: sCommand = "UFI";
! 422: break;
! 423: case UMASS_CPROTO_ATAPI:
! 424: sCommand = "ATAPI";
! 425: break;
! 426: case UMASS_CPROTO_ISD_ATA:
! 427: sCommand = "ISD-ATA";
! 428: break;
! 429: default:
! 430: sCommand = "unknown";
! 431: break;
! 432: }
! 433:
! 434: printf("%s: using %s over %s\n", sc->sc_dev.dv_xname, sCommand,
! 435: sWire);
! 436:
! 437: if (quirk != NULL && quirk->uq_init != NULL) {
! 438: err = (*quirk->uq_init)(sc);
! 439: if (err) {
! 440: umass_disco(sc);
! 441: return;
! 442: }
! 443: }
! 444:
! 445: /*
! 446: * In addition to the Control endpoint the following endpoints
! 447: * are required:
! 448: * a) bulk-in endpoint.
! 449: * b) bulk-out endpoint.
! 450: * and for Control/Bulk/Interrupt with CCI (CBI_I)
! 451: * c) intr-in
! 452: *
! 453: * The endpoint addresses are not fixed, so we have to read them
! 454: * from the device descriptors of the current interface.
! 455: */
! 456: for (i = 0 ; i < id->bNumEndpoints ; i++) {
! 457: ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
! 458: if (ed == NULL) {
! 459: printf("%s: could not read endpoint descriptor\n",
! 460: sc->sc_dev.dv_xname);
! 461: return;
! 462: }
! 463: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
! 464: && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
! 465: sc->sc_epaddr[UMASS_BULKIN] = ed->bEndpointAddress;
! 466: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
! 467: && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
! 468: sc->sc_epaddr[UMASS_BULKOUT] = ed->bEndpointAddress;
! 469: } else if (sc->sc_wire == UMASS_WPROTO_CBI_I
! 470: && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
! 471: && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
! 472: sc->sc_epaddr[UMASS_INTRIN] = ed->bEndpointAddress;
! 473: #ifdef UMASS_DEBUG
! 474: if (UGETW(ed->wMaxPacketSize) > 2) {
! 475: DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n",
! 476: sc->sc_dev.dv_xname,
! 477: UGETW(ed->wMaxPacketSize)));
! 478: }
! 479: #endif
! 480: }
! 481: }
! 482:
! 483: /* check whether we found all the endpoints we need */
! 484: if (!sc->sc_epaddr[UMASS_BULKIN] || !sc->sc_epaddr[UMASS_BULKOUT] ||
! 485: (sc->sc_wire == UMASS_WPROTO_CBI_I &&
! 486: !sc->sc_epaddr[UMASS_INTRIN])) {
! 487: DPRINTF(UDMASS_USB, ("%s: endpoint not found %u/%u/%u\n",
! 488: sc->sc_dev.dv_xname, sc->sc_epaddr[UMASS_BULKIN],
! 489: sc->sc_epaddr[UMASS_BULKOUT],
! 490: sc->sc_epaddr[UMASS_INTRIN]));
! 491: return;
! 492: }
! 493:
! 494: /*
! 495: * Get the maximum LUN supported by the device.
! 496: */
! 497: if (sc->sc_wire == UMASS_WPROTO_BBB) {
! 498: err = umass_bbb_get_max_lun(sc, &sc->maxlun);
! 499: if (err) {
! 500: printf("%s: unable to get Max Lun: %s\n",
! 501: sc->sc_dev.dv_xname, usbd_errstr(err));
! 502: return;
! 503: }
! 504: } else {
! 505: sc->maxlun = 0;
! 506: }
! 507:
! 508: /* Open the bulk-in and -out pipe */
! 509: DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKOUT\n",
! 510: sc->sc_dev.dv_xname, sc->sc_iface,
! 511: sc->sc_epaddr[UMASS_BULKOUT]));
! 512: err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKOUT],
! 513: USBD_EXCLUSIVE_USE,
! 514: &sc->sc_pipe[UMASS_BULKOUT]);
! 515: if (err) {
! 516: DPRINTF(UDMASS_USB, ("%s: cannot open %u-out pipe (bulk)\n",
! 517: sc->sc_dev.dv_xname, sc->sc_epaddr[UMASS_BULKOUT]));
! 518: umass_disco(sc);
! 519: return;
! 520: }
! 521: DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKIN\n",
! 522: sc->sc_dev.dv_xname, sc->sc_iface,
! 523: sc->sc_epaddr[UMASS_BULKIN]));
! 524: err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKIN],
! 525: USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_BULKIN]);
! 526: if (err) {
! 527: DPRINTF(UDMASS_USB, ("%s: could not open %u-in pipe (bulk)\n",
! 528: sc->sc_dev.dv_xname, sc->sc_epaddr[UMASS_BULKIN]));
! 529: umass_disco(sc);
! 530: return;
! 531: }
! 532: /*
! 533: * Open the intr-in pipe if the protocol is CBI with CCI.
! 534: * Note: early versions of the Zip drive do have an interrupt pipe, but
! 535: * this pipe is unused
! 536: *
! 537: * We do not open the interrupt pipe as an interrupt pipe, but as a
! 538: * normal bulk endpoint. We send an IN transfer down the wire at the
! 539: * appropriate time, because we know exactly when to expect data on
! 540: * that endpoint. This saves bandwidth, but more important, makes the
! 541: * code for handling the data on that endpoint simpler. No data
! 542: * arriving concurrently.
! 543: */
! 544: if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
! 545: DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for INTRIN\n",
! 546: sc->sc_dev.dv_xname, sc->sc_iface,
! 547: sc->sc_epaddr[UMASS_INTRIN]));
! 548: err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_INTRIN],
! 549: USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_INTRIN]);
! 550: if (err) {
! 551: DPRINTF(UDMASS_USB, ("%s: couldn't open %u-in (intr)\n",
! 552: sc->sc_dev.dv_xname,
! 553: sc->sc_epaddr[UMASS_INTRIN]));
! 554: umass_disco(sc);
! 555: return;
! 556: }
! 557: }
! 558:
! 559: /* initialisation of generic part */
! 560: sc->transfer_state = TSTATE_IDLE;
! 561:
! 562: /* request a sufficient number of xfer handles */
! 563: for (i = 0; i < XFER_NR; i++) {
! 564: sc->transfer_xfer[i] = usbd_alloc_xfer(uaa->device);
! 565: if (sc->transfer_xfer[i] == NULL) {
! 566: DPRINTF(UDMASS_USB, ("%s: Out of memory\n",
! 567: sc->sc_dev.dv_xname));
! 568: umass_disco(sc);
! 569: return;
! 570: }
! 571: }
! 572: /* Allocate buffer for data transfer (it's huge). */
! 573: switch (sc->sc_wire) {
! 574: case UMASS_WPROTO_BBB:
! 575: bno = XFER_BBB_DATA;
! 576: goto dalloc;
! 577: case UMASS_WPROTO_CBI:
! 578: bno = XFER_CBI_DATA;
! 579: goto dalloc;
! 580: case UMASS_WPROTO_CBI_I:
! 581: bno = XFER_CBI_DATA;
! 582: dalloc:
! 583: sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno],
! 584: UMASS_MAX_TRANSFER_SIZE);
! 585: if (sc->data_buffer == NULL) {
! 586: umass_disco(sc);
! 587: return;
! 588: }
! 589: break;
! 590: default:
! 591: break;
! 592: }
! 593:
! 594: /* Initialise the wire protocol specific methods */
! 595: switch (sc->sc_wire) {
! 596: case UMASS_WPROTO_BBB:
! 597: sc->sc_methods = &umass_bbb_methods;
! 598: break;
! 599: case UMASS_WPROTO_CBI:
! 600: case UMASS_WPROTO_CBI_I:
! 601: sc->sc_methods = &umass_cbi_methods;
! 602: break;
! 603: default:
! 604: umass_disco(sc);
! 605: return;
! 606: }
! 607:
! 608: error = 0;
! 609: switch (sc->sc_cmd) {
! 610: case UMASS_CPROTO_RBC:
! 611: case UMASS_CPROTO_SCSI:
! 612: error = umass_scsi_attach(sc);
! 613: break;
! 614:
! 615: case UMASS_CPROTO_UFI:
! 616: case UMASS_CPROTO_ATAPI:
! 617: #if (NATAPIBUS > 0) || (NATAPISCSI > 0)
! 618: error = umass_atapi_attach(sc);
! 619: #else
! 620: printf("%s: atapiscsi not configured\n", sc->sc_dev.dv_xname);
! 621: #endif
! 622: break;
! 623:
! 624: case UMASS_CPROTO_ISD_ATA:
! 625: printf("%s: isdata not configured\n", sc->sc_dev.dv_xname);
! 626: break;
! 627:
! 628: default:
! 629: printf("%s: command protocol=0x%x not supported\n",
! 630: sc->sc_dev.dv_xname, sc->sc_cmd);
! 631: umass_disco(sc);
! 632: return;
! 633: }
! 634: if (error) {
! 635: printf("%s: bus attach failed\n", sc->sc_dev.dv_xname);
! 636: umass_disco(sc);
! 637: return;
! 638: }
! 639:
! 640: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
! 641: &sc->sc_dev);
! 642:
! 643: DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", sc->sc_dev.dv_xname));
! 644: }
! 645:
! 646: int
! 647: umass_detach(struct device *self, int flags)
! 648: {
! 649: struct umass_softc *sc = (struct umass_softc *)self;
! 650: struct umassbus_softc *scbus;
! 651: int rv = 0, i, s;
! 652:
! 653: DPRINTF(UDMASS_USB, ("%s: detached\n", sc->sc_dev.dv_xname));
! 654:
! 655: /* Abort the pipes to wake up any waiting processes. */
! 656: for (i = 0 ; i < UMASS_NEP ; i++) {
! 657: if (sc->sc_pipe[i] != NULL) {
! 658: usbd_abort_pipe(sc->sc_pipe[i]);
! 659: sc->sc_pipe[i] = NULL;
! 660: }
! 661: }
! 662:
! 663: /* Do we really need reference counting? Perhaps in ioctl() */
! 664: s = splusb();
! 665: if (--sc->sc_refcnt >= 0) {
! 666: #ifdef DIAGNOSTIC
! 667: printf("%s: waiting for refcnt\n", sc->sc_dev.dv_xname);
! 668: #endif
! 669: /* Wait for processes to go away. */
! 670: usb_detach_wait(&sc->sc_dev);
! 671: }
! 672: splx(s);
! 673:
! 674: scbus = sc->bus;
! 675: if (scbus != NULL) {
! 676: if (scbus->sc_child != NULL)
! 677: rv = config_detach(scbus->sc_child, flags);
! 678: free(scbus, M_DEVBUF);
! 679: sc->bus = NULL;
! 680: }
! 681:
! 682: if (rv != 0)
! 683: return (rv);
! 684:
! 685: umass_disco(sc);
! 686:
! 687: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
! 688: &sc->sc_dev);
! 689:
! 690: return (rv);
! 691: }
! 692:
! 693: int
! 694: umass_activate(struct device *dev, enum devact act)
! 695: {
! 696: struct umass_softc *sc = (struct umass_softc *)dev;
! 697: struct umassbus_softc *scbus = sc->bus;
! 698: int rv = 0;
! 699:
! 700: DPRINTF(UDMASS_USB, ("%s: umass_activate: %d\n",
! 701: sc->sc_dev.dv_xname, act));
! 702:
! 703: switch (act) {
! 704: case DVACT_ACTIVATE:
! 705: break;
! 706:
! 707: case DVACT_DEACTIVATE:
! 708: sc->sc_dying = 1;
! 709: if (scbus == NULL || scbus->sc_child == NULL)
! 710: break;
! 711: rv = config_deactivate(scbus->sc_child);
! 712: DPRINTF(UDMASS_USB, ("%s: umass_activate: child "
! 713: "returned %d\n", sc->sc_dev.dv_xname, rv));
! 714: break;
! 715: }
! 716: return (rv);
! 717: }
! 718:
! 719: void
! 720: umass_disco(struct umass_softc *sc)
! 721: {
! 722: int i;
! 723:
! 724: DPRINTF(UDMASS_GEN, ("umass_disco\n"));
! 725:
! 726: /* Free the xfers. */
! 727: for (i = 0; i < XFER_NR; i++)
! 728: if (sc->transfer_xfer[i] != NULL) {
! 729: usbd_free_xfer(sc->transfer_xfer[i]);
! 730: sc->transfer_xfer[i] = NULL;
! 731: }
! 732:
! 733: /* Remove all the pipes. */
! 734: for (i = 0 ; i < UMASS_NEP ; i++) {
! 735: if (sc->sc_pipe[i] != NULL) {
! 736: usbd_close_pipe(sc->sc_pipe[i]);
! 737: sc->sc_pipe[i] = NULL;
! 738: }
! 739: }
! 740: }
! 741:
! 742: /*
! 743: * Generic functions to handle transfers
! 744: */
! 745:
! 746: usbd_status
! 747: umass_polled_transfer(struct umass_softc *sc, usbd_xfer_handle xfer)
! 748: {
! 749: usbd_status err;
! 750:
! 751: if (sc->sc_dying)
! 752: return (USBD_IOERROR);
! 753:
! 754: /*
! 755: * If a polled transfer is already in progress, preserve the new
! 756: * usbd_xfer_handle and run it after the running one completes.
! 757: * This converts the recursive calls into the umass_*_state callbacks
! 758: * into iteration, preventing us from running out of stack under
! 759: * error conditions.
! 760: */
! 761: if (sc->polling_depth) {
! 762: if (sc->next_polled_xfer)
! 763: panic("%s: got polled xfer %p, but %p already "
! 764: "pending\n", sc->sc_dev.dv_xname, xfer,
! 765: sc->next_polled_xfer);
! 766:
! 767: DPRINTF(UDMASS_XFER, ("%s: saving polled xfer %p\n",
! 768: sc->sc_dev.dv_xname, xfer));
! 769: sc->next_polled_xfer = xfer;
! 770:
! 771: return (USBD_IN_PROGRESS);
! 772: }
! 773:
! 774: sc->polling_depth++;
! 775:
! 776: start_next_xfer:
! 777: DPRINTF(UDMASS_XFER, ("%s: start polled xfer %p\n",
! 778: sc->sc_dev.dv_xname, xfer));
! 779: err = usbd_transfer(xfer);
! 780: if (err && err != USBD_IN_PROGRESS && sc->next_polled_xfer == NULL) {
! 781: DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n",
! 782: sc->sc_dev.dv_xname, usbd_errstr(err)));
! 783: sc->polling_depth--;
! 784: return (err);
! 785: }
! 786:
! 787: if (err && err != USBD_IN_PROGRESS) {
! 788: DPRINTF(UDMASS_XFER, ("umass_polled_xfer %p has error %s\n",
! 789: xfer, usbd_errstr(err)));
! 790: }
! 791:
! 792: if (sc->next_polled_xfer != NULL) {
! 793: DPRINTF(UDMASS_XFER, ("umass_polled_xfer running next "
! 794: "transaction %p\n", sc->next_polled_xfer));
! 795: xfer = sc->next_polled_xfer;
! 796: sc->next_polled_xfer = NULL;
! 797: goto start_next_xfer;
! 798: }
! 799:
! 800: sc->polling_depth--;
! 801:
! 802: return (USBD_NORMAL_COMPLETION);
! 803: }
! 804:
! 805: usbd_status
! 806: umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe,
! 807: void *buffer, int buflen, int flags,
! 808: usbd_xfer_handle xfer)
! 809: {
! 810: usbd_status err;
! 811:
! 812: if (sc->sc_dying)
! 813: return (USBD_IOERROR);
! 814:
! 815: /* Initialise a USB transfer and then schedule it */
! 816:
! 817: usbd_setup_xfer(xfer, pipe, (void *)sc, buffer, buflen,
! 818: flags | sc->sc_xfer_flags, sc->timeout, sc->sc_methods->wire_state);
! 819:
! 820: if (sc->sc_udev->bus->use_polling) {
! 821: DPRINTF(UDMASS_XFER,("%s: start polled xfer buffer=%p "
! 822: "buflen=%d flags=0x%x timeout=%d\n", sc->sc_dev.dv_xname,
! 823: buffer, buflen, flags | sc->sc_xfer_flags, sc->timeout));
! 824: err = umass_polled_transfer(sc, xfer);
! 825: } else {
! 826: err = usbd_transfer(xfer);
! 827: DPRINTF(UDMASS_XFER,("%s: start xfer buffer=%p buflen=%d "
! 828: "flags=0x%x timeout=%d\n", sc->sc_dev.dv_xname,
! 829: buffer, buflen, flags | sc->sc_xfer_flags, sc->timeout));
! 830: }
! 831: if (err && err != USBD_IN_PROGRESS) {
! 832: DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n",
! 833: sc->sc_dev.dv_xname, usbd_errstr(err)));
! 834: return (err);
! 835: }
! 836:
! 837: return (USBD_NORMAL_COMPLETION);
! 838: }
! 839:
! 840:
! 841: usbd_status
! 842: umass_setup_ctrl_transfer(struct umass_softc *sc, usb_device_request_t *req,
! 843: void *buffer, int buflen, int flags, usbd_xfer_handle xfer)
! 844: {
! 845: usbd_status err;
! 846:
! 847: if (sc->sc_dying)
! 848: return (USBD_IOERROR);
! 849:
! 850: /* Initialise a USB control transfer and then schedule it */
! 851:
! 852: usbd_setup_default_xfer(xfer, sc->sc_udev, (void *) sc,
! 853: USBD_DEFAULT_TIMEOUT, req, buffer, buflen, flags,
! 854: sc->sc_methods->wire_state);
! 855:
! 856: if (sc->sc_udev->bus->use_polling) {
! 857: DPRINTF(UDMASS_XFER,("%s: start polled ctrl xfer buffer=%p "
! 858: "buflen=%d flags=0x%x\n", sc->sc_dev.dv_xname, buffer,
! 859: buflen, flags));
! 860: err = umass_polled_transfer(sc, xfer);
! 861: } else {
! 862: DPRINTF(UDMASS_XFER,("%s: start ctrl xfer buffer=%p buflen=%d "
! 863: "flags=0x%x\n", sc->sc_dev.dv_xname, buffer, buflen,
! 864: flags));
! 865: err = usbd_transfer(xfer);
! 866: }
! 867: if (err && err != USBD_IN_PROGRESS) {
! 868: DPRINTF(UDMASS_BBB, ("%s: failed to setup ctrl transfer, %s\n",
! 869: sc->sc_dev.dv_xname, usbd_errstr(err)));
! 870:
! 871: /* do not reset, as this would make us loop */
! 872: return (err);
! 873: }
! 874:
! 875: return (USBD_NORMAL_COMPLETION);
! 876: }
! 877:
! 878: void
! 879: umass_adjust_transfer(struct umass_softc *sc)
! 880: {
! 881: switch (sc->sc_cmd) {
! 882: case UMASS_CPROTO_UFI:
! 883: sc->cbw.bCDBLength = UFI_COMMAND_LENGTH;
! 884: /* Adjust the length field in certain scsi commands. */
! 885: switch (sc->cbw.CBWCDB[0]) {
! 886: case INQUIRY:
! 887: if (sc->transfer_datalen > 36) {
! 888: sc->transfer_datalen = 36;
! 889: sc->cbw.CBWCDB[4] = 36;
! 890: }
! 891: break;
! 892: case MODE_SENSE_BIG:
! 893: if (sc->transfer_datalen > 8) {
! 894: sc->transfer_datalen = 8;
! 895: sc->cbw.CBWCDB[7] = 0;
! 896: sc->cbw.CBWCDB[8] = 8;
! 897: }
! 898: break;
! 899: case REQUEST_SENSE:
! 900: if (sc->transfer_datalen > 18) {
! 901: sc->transfer_datalen = 18;
! 902: sc->cbw.CBWCDB[4] = 18;
! 903: }
! 904: break;
! 905: }
! 906: break;
! 907: case UMASS_CPROTO_ATAPI:
! 908: sc->cbw.bCDBLength = UFI_COMMAND_LENGTH;
! 909: break;
! 910: }
! 911: }
! 912:
! 913: void
! 914: umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
! 915: usbd_xfer_handle xfer)
! 916: {
! 917: if (sc->sc_dying)
! 918: return;
! 919:
! 920: DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n",
! 921: sc->sc_dev.dv_xname, sc->sc_epaddr[endpt]));
! 922:
! 923: usbd_clear_endpoint_toggle(sc->sc_pipe[endpt]);
! 924:
! 925: sc->sc_req.bmRequestType = UT_WRITE_ENDPOINT;
! 926: sc->sc_req.bRequest = UR_CLEAR_FEATURE;
! 927: USETW(sc->sc_req.wValue, UF_ENDPOINT_HALT);
! 928: USETW(sc->sc_req.wIndex, sc->sc_epaddr[endpt]);
! 929: USETW(sc->sc_req.wLength, 0);
! 930: umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer);
! 931: }
! 932:
! 933: #if 0
! 934: void
! 935: umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv)
! 936: {
! 937: sc->transfer_cb = cb;
! 938: sc->transfer_priv = priv;
! 939:
! 940: /* The reset is a forced reset, so no error (yet) */
! 941: sc->reset(sc, STATUS_CMD_OK);
! 942: }
! 943: #endif
! 944:
! 945: /*
! 946: * Bulk protocol specific functions
! 947: */
! 948:
! 949: void
! 950: umass_bbb_reset(struct umass_softc *sc, int status)
! 951: {
! 952: KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
! 953: ("sc->sc_wire == 0x%02x wrong for umass_bbb_reset\n",
! 954: sc->sc_wire));
! 955:
! 956: if (sc->sc_dying)
! 957: return;
! 958:
! 959: /*
! 960: * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
! 961: *
! 962: * For Reset Recovery the host shall issue in the following order:
! 963: * a) a Bulk-Only Mass Storage Reset
! 964: * b) a Clear Feature HALT to the Bulk-In endpoint
! 965: * c) a Clear Feature HALT to the Bulk-Out endpoint
! 966: *
! 967: * This is done in 3 steps, states:
! 968: * TSTATE_BBB_RESET1
! 969: * TSTATE_BBB_RESET2
! 970: * TSTATE_BBB_RESET3
! 971: *
! 972: * If the reset doesn't succeed, the device should be port reset.
! 973: */
! 974:
! 975: DPRINTF(UDMASS_BBB, ("%s: Bulk Reset\n",
! 976: sc->sc_dev.dv_xname));
! 977:
! 978: sc->transfer_state = TSTATE_BBB_RESET1;
! 979: sc->transfer_status = status;
! 980:
! 981: /* reset is a class specific interface write */
! 982: sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
! 983: sc->sc_req.bRequest = UR_BBB_RESET;
! 984: USETW(sc->sc_req.wValue, 0);
! 985: USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
! 986: USETW(sc->sc_req.wLength, 0);
! 987: umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0,
! 988: sc->transfer_xfer[XFER_BBB_RESET1]);
! 989: }
! 990:
! 991: void
! 992: umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
! 993: void *data, int datalen, int dir, u_int timeout,
! 994: umass_callback cb, void *priv)
! 995: {
! 996: static int dCBWtag = 42; /* unique for CBW of transfer */
! 997: usbd_status err;
! 998:
! 999: DPRINTF(UDMASS_BBB,("%s: umass_bbb_transfer cmd=0x%02x\n",
! 1000: sc->sc_dev.dv_xname, *(u_char *)cmd));
! 1001:
! 1002: KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
! 1003: ("sc->sc_wire == 0x%02x wrong for umass_bbb_transfer\n",
! 1004: sc->sc_wire));
! 1005:
! 1006: if (sc->sc_dying) {
! 1007: sc->polled_xfer_status = USBD_IOERROR;
! 1008: return;
! 1009: }
! 1010:
! 1011: /* Be a little generous. */
! 1012: sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
! 1013:
! 1014: /*
! 1015: * Do a Bulk-Only transfer with cmdlen bytes from cmd, possibly
! 1016: * a data phase of datalen bytes from/to the device and finally a
! 1017: * csw read phase.
! 1018: * If the data direction was inbound a maximum of datalen bytes
! 1019: * is stored in the buffer pointed to by data.
! 1020: *
! 1021: * umass_bbb_transfer initialises the transfer and lets the state
! 1022: * machine in umass_bbb_state handle the completion. It uses the
! 1023: * following states:
! 1024: * TSTATE_BBB_COMMAND
! 1025: * -> TSTATE_BBB_DATA
! 1026: * -> TSTATE_BBB_STATUS
! 1027: * -> TSTATE_BBB_STATUS2
! 1028: * -> TSTATE_BBB_IDLE
! 1029: *
! 1030: * An error in any of those states will invoke
! 1031: * umass_bbb_reset.
! 1032: */
! 1033:
! 1034: /* check the given arguments */
! 1035: KASSERT(datalen == 0 || data != NULL,
! 1036: ("%s: datalen > 0, but no buffer",sc->sc_dev.dv_xname));
! 1037: KASSERT(cmdlen <= CBWCDBLENGTH,
! 1038: ("%s: cmdlen exceeds CDB length in CBW (%d > %d)",
! 1039: sc->sc_dev.dv_xname, cmdlen, CBWCDBLENGTH));
! 1040: KASSERT(dir == DIR_NONE || datalen > 0,
! 1041: ("%s: datalen == 0 while direction is not NONE\n",
! 1042: sc->sc_dev.dv_xname));
! 1043: KASSERT(datalen == 0 || dir != DIR_NONE,
! 1044: ("%s: direction is NONE while datalen is not zero\n",
! 1045: sc->sc_dev.dv_xname));
! 1046: KASSERT(sizeof(umass_bbb_cbw_t) == UMASS_BBB_CBW_SIZE,
! 1047: ("%s: CBW struct does not have the right size (%d vs. %d)\n",
! 1048: sc->sc_dev.dv_xname,
! 1049: sizeof(umass_bbb_cbw_t), UMASS_BBB_CBW_SIZE));
! 1050: KASSERT(sizeof(umass_bbb_csw_t) == UMASS_BBB_CSW_SIZE,
! 1051: ("%s: CSW struct does not have the right size (%d vs. %d)\n",
! 1052: sc->sc_dev.dv_xname,
! 1053: sizeof(umass_bbb_csw_t), UMASS_BBB_CSW_SIZE));
! 1054:
! 1055: /*
! 1056: * Determine the direction of the data transfer and the length.
! 1057: *
! 1058: * dCBWDataTransferLength (datalen) :
! 1059: * This field indicates the number of bytes of data that the host
! 1060: * intends to transfer on the IN or OUT Bulk endpoint(as indicated by
! 1061: * the Direction bit) during the execution of this command. If this
! 1062: * field is set to 0, the device will expect that no data will be
! 1063: * transferred IN or OUT during this command, regardless of the value
! 1064: * of the Direction bit defined in dCBWFlags.
! 1065: *
! 1066: * dCBWFlags (dir) :
! 1067: * The bits of the Flags field are defined as follows:
! 1068: * Bits 0-6 reserved
! 1069: * Bit 7 Direction - this bit shall be ignored if the
! 1070: * dCBWDataTransferLength field is zero.
! 1071: * 0 = data Out from host to device
! 1072: * 1 = data In from device to host
! 1073: */
! 1074:
! 1075: /* Fill in the Command Block Wrapper */
! 1076: USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
! 1077: USETDW(sc->cbw.dCBWTag, dCBWtag);
! 1078: dCBWtag++; /* cannot be done in macro (it will be done 4 times) */
! 1079: USETDW(sc->cbw.dCBWDataTransferLength, datalen);
! 1080: /* DIR_NONE is treated as DIR_OUT (0x00) */
! 1081: sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT);
! 1082: sc->cbw.bCBWLUN = lun;
! 1083: sc->cbw.bCDBLength = cmdlen;
! 1084: bzero(sc->cbw.CBWCDB, sizeof(sc->cbw.CBWCDB));
! 1085: memcpy(sc->cbw.CBWCDB, cmd, cmdlen);
! 1086:
! 1087: DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw));
! 1088:
! 1089: /* store the details for the data transfer phase */
! 1090: sc->transfer_dir = dir;
! 1091: sc->transfer_data = data;
! 1092: sc->transfer_datalen = datalen;
! 1093: sc->transfer_actlen = 0;
! 1094: sc->transfer_cb = cb;
! 1095: sc->transfer_priv = priv;
! 1096: sc->transfer_status = STATUS_CMD_OK;
! 1097:
! 1098: /* move from idle to the command state */
! 1099: sc->transfer_state = TSTATE_BBB_COMMAND;
! 1100:
! 1101: /* Send the CBW from host to device via bulk-out endpoint. */
! 1102: umass_adjust_transfer(sc);
! 1103: if ((err = umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
! 1104: &sc->cbw, UMASS_BBB_CBW_SIZE, 0,
! 1105: sc->transfer_xfer[XFER_BBB_CBW])))
! 1106: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1107:
! 1108: if (sc->sc_udev->bus->use_polling)
! 1109: sc->polled_xfer_status = err;
! 1110: }
! 1111:
! 1112: void
! 1113: umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
! 1114: usbd_status err)
! 1115: {
! 1116: struct umass_softc *sc = (struct umass_softc *) priv;
! 1117: usbd_xfer_handle next_xfer;
! 1118:
! 1119: KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
! 1120: ("sc->sc_wire == 0x%02x wrong for umass_bbb_state\n",
! 1121: sc->sc_wire));
! 1122:
! 1123: if (sc->sc_dying)
! 1124: return;
! 1125:
! 1126: /*
! 1127: * State handling for BBB transfers.
! 1128: *
! 1129: * The subroutine is rather long. It steps through the states given in
! 1130: * Annex A of the Bulk-Only specification.
! 1131: * Each state first does the error handling of the previous transfer
! 1132: * and then prepares the next transfer.
! 1133: * Each transfer is done asynchronously so after the request/transfer
! 1134: * has been submitted you will find a 'return;'.
! 1135: */
! 1136:
! 1137: DPRINTF(UDMASS_BBB, ("%s: Handling BBB state %d (%s), xfer=%p, %s\n",
! 1138: sc->sc_dev.dv_xname, sc->transfer_state,
! 1139: states[sc->transfer_state], xfer, usbd_errstr(err)));
! 1140:
! 1141: switch (sc->transfer_state) {
! 1142:
! 1143: /***** Bulk Transfer *****/
! 1144: case TSTATE_BBB_COMMAND:
! 1145: /* Command transport phase, error handling */
! 1146: if (err) {
! 1147: DPRINTF(UDMASS_BBB, ("%s: failed to send CBW\n",
! 1148: sc->sc_dev.dv_xname));
! 1149: /* If the device detects that the CBW is invalid, then
! 1150: * the device may STALL both bulk endpoints and require
! 1151: * a Bulk-Reset
! 1152: */
! 1153: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1154: return;
! 1155: }
! 1156:
! 1157: /* Data transport phase, setup transfer */
! 1158: sc->transfer_state = TSTATE_BBB_DATA;
! 1159: if (sc->transfer_dir == DIR_IN) {
! 1160: if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
! 1161: sc->data_buffer, sc->transfer_datalen,
! 1162: USBD_SHORT_XFER_OK | USBD_NO_COPY,
! 1163: sc->transfer_xfer[XFER_BBB_DATA]))
! 1164: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1165:
! 1166: return;
! 1167: } else if (sc->transfer_dir == DIR_OUT) {
! 1168: memcpy(sc->data_buffer, sc->transfer_data,
! 1169: sc->transfer_datalen);
! 1170: if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
! 1171: sc->data_buffer, sc->transfer_datalen,
! 1172: USBD_NO_COPY,/* fixed length transfer */
! 1173: sc->transfer_xfer[XFER_BBB_DATA]))
! 1174: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1175:
! 1176: return;
! 1177: } else {
! 1178: DPRINTF(UDMASS_BBB, ("%s: no data phase\n",
! 1179: sc->sc_dev.dv_xname));
! 1180: }
! 1181:
! 1182: /* FALLTHROUGH if no data phase, err == 0 */
! 1183: case TSTATE_BBB_DATA:
! 1184: /* Command transport phase error handling (ignored if no data
! 1185: * phase (fallthrough from previous state)) */
! 1186: if (sc->transfer_dir != DIR_NONE) {
! 1187: /* retrieve the length of the transfer that was done */
! 1188: usbd_get_xfer_status(xfer, NULL, NULL,
! 1189: &sc->transfer_actlen, NULL);
! 1190: DPRINTF(UDMASS_BBB, ("%s: BBB_DATA actlen=%d\n",
! 1191: sc->sc_dev.dv_xname, sc->transfer_actlen));
! 1192:
! 1193: if (err) {
! 1194: DPRINTF(UDMASS_BBB, ("%s: Data-%s %d failed, "
! 1195: "%s\n", sc->sc_dev.dv_xname,
! 1196: (sc->transfer_dir == DIR_IN?"in":"out"),
! 1197: sc->transfer_datalen,usbd_errstr(err)));
! 1198:
! 1199: if (err == USBD_STALLED) {
! 1200: sc->transfer_state = TSTATE_BBB_DCLEAR;
! 1201: umass_clear_endpoint_stall(sc,
! 1202: (sc->transfer_dir == DIR_IN?
! 1203: UMASS_BULKIN:UMASS_BULKOUT),
! 1204: sc->transfer_xfer[XFER_BBB_DCLEAR]);
! 1205: } else {
! 1206: /* Unless the error is a pipe stall the
! 1207: * error is fatal.
! 1208: */
! 1209: umass_bbb_reset(sc,STATUS_WIRE_FAILED);
! 1210: }
! 1211: return;
! 1212: }
! 1213: }
! 1214:
! 1215: /* FALLTHROUGH, err == 0 (no data phase or successful) */
! 1216: case TSTATE_BBB_DCLEAR: /* stall clear after data phase */
! 1217: if (sc->transfer_dir == DIR_IN)
! 1218: memcpy(sc->transfer_data, sc->data_buffer,
! 1219: sc->transfer_actlen);
! 1220:
! 1221: DIF(UDMASS_BBB, if (sc->transfer_dir == DIR_IN)
! 1222: umass_dump_buffer(sc, sc->transfer_data,
! 1223: sc->transfer_datalen, 48));
! 1224:
! 1225: /* FALLTHROUGH, err == 0 (no data phase or successful) */
! 1226: case TSTATE_BBB_SCLEAR: /* stall clear after status phase */
! 1227: /* Reading of CSW after bulk stall condition in data phase
! 1228: * (TSTATE_BBB_DATA2) or bulk-in stall condition after
! 1229: * reading CSW (TSTATE_BBB_SCLEAR).
! 1230: * In the case of no data phase or successful data phase,
! 1231: * err == 0 and the following if block is passed.
! 1232: */
! 1233: if (err) { /* should not occur */
! 1234: printf("%s: BBB bulk-%s stall clear failed, %s\n",
! 1235: sc->sc_dev.dv_xname,
! 1236: (sc->transfer_dir == DIR_IN? "in":"out"),
! 1237: usbd_errstr(err));
! 1238: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1239: return;
! 1240: }
! 1241:
! 1242: /* Status transport phase, setup transfer */
! 1243: if (sc->transfer_state == TSTATE_BBB_COMMAND ||
! 1244: sc->transfer_state == TSTATE_BBB_DATA ||
! 1245: sc->transfer_state == TSTATE_BBB_DCLEAR) {
! 1246: /* After no data phase, successful data phase and
! 1247: * after clearing bulk-in/-out stall condition
! 1248: */
! 1249: sc->transfer_state = TSTATE_BBB_STATUS1;
! 1250: next_xfer = sc->transfer_xfer[XFER_BBB_CSW1];
! 1251: } else {
! 1252: /* After first attempt of fetching CSW */
! 1253: sc->transfer_state = TSTATE_BBB_STATUS2;
! 1254: next_xfer = sc->transfer_xfer[XFER_BBB_CSW2];
! 1255: }
! 1256:
! 1257: /* Read the Command Status Wrapper via bulk-in endpoint. */
! 1258: if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
! 1259: &sc->csw, UMASS_BBB_CSW_SIZE, 0, next_xfer)) {
! 1260: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1261: return;
! 1262: }
! 1263:
! 1264: return;
! 1265: case TSTATE_BBB_STATUS1: /* first attempt */
! 1266: case TSTATE_BBB_STATUS2: /* second attempt */
! 1267: /* Status transfer, error handling */
! 1268: if (err) {
! 1269: DPRINTF(UDMASS_BBB, ("%s: Failed to read CSW, %s%s\n",
! 1270: sc->sc_dev.dv_xname, usbd_errstr(err),
! 1271: (sc->transfer_state == TSTATE_BBB_STATUS1?
! 1272: ", retrying":"")));
! 1273:
! 1274: /* If this was the first attempt at fetching the CSW
! 1275: * retry it, otherwise fail.
! 1276: */
! 1277: if (sc->transfer_state == TSTATE_BBB_STATUS1) {
! 1278: sc->transfer_state = TSTATE_BBB_SCLEAR;
! 1279: umass_clear_endpoint_stall(sc, UMASS_BULKIN,
! 1280: sc->transfer_xfer[XFER_BBB_SCLEAR]);
! 1281: return;
! 1282: } else {
! 1283: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1284: return;
! 1285: }
! 1286: }
! 1287:
! 1288: DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw));
! 1289:
! 1290: /* Translate weird command-status signatures. */
! 1291: if ((sc->sc_quirks & UMASS_QUIRK_WRONG_CSWSIG) &&
! 1292: UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1)
! 1293: USETDW(sc->csw.dCSWSignature, CSWSIGNATURE);
! 1294:
! 1295: /* Translate invalid command-status tags */
! 1296: if (sc->sc_quirks & UMASS_QUIRK_WRONG_CSWTAG)
! 1297: USETDW(sc->csw.dCSWTag, UGETDW(sc->cbw.dCBWTag));
! 1298:
! 1299: /* Check CSW and handle any error */
! 1300: if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) {
! 1301: /* Invalid CSW: Wrong signature or wrong tag might
! 1302: * indicate that the device is confused -> reset it.
! 1303: */
! 1304: printf("%s: Invalid CSW: sig 0x%08x should be 0x%08x\n",
! 1305: sc->sc_dev.dv_xname,
! 1306: UGETDW(sc->csw.dCSWSignature),
! 1307: CSWSIGNATURE);
! 1308:
! 1309: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1310: return;
! 1311: } else if (UGETDW(sc->csw.dCSWTag)
! 1312: != UGETDW(sc->cbw.dCBWTag)) {
! 1313: printf("%s: Invalid CSW: tag %d should be %d\n",
! 1314: sc->sc_dev.dv_xname,
! 1315: UGETDW(sc->csw.dCSWTag),
! 1316: UGETDW(sc->cbw.dCBWTag));
! 1317:
! 1318: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1319: return;
! 1320:
! 1321: /* CSW is valid here */
! 1322: } else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) {
! 1323: printf("%s: Invalid CSW: status %d > %d\n",
! 1324: sc->sc_dev.dv_xname,
! 1325: sc->csw.bCSWStatus,
! 1326: CSWSTATUS_PHASE);
! 1327:
! 1328: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1329: return;
! 1330: } else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) {
! 1331: printf("%s: Phase Error, residue = %d\n",
! 1332: sc->sc_dev.dv_xname,
! 1333: UGETDW(sc->csw.dCSWDataResidue));
! 1334:
! 1335: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1336: return;
! 1337:
! 1338: } else if (sc->transfer_actlen > sc->transfer_datalen) {
! 1339: /* Buffer overrun! Don't let this go by unnoticed */
! 1340: panic("%s: transferred %d bytes instead of %d bytes",
! 1341: sc->sc_dev.dv_xname,
! 1342: sc->transfer_actlen, sc->transfer_datalen);
! 1343: #if 0
! 1344: } else if (sc->transfer_datalen - sc->transfer_actlen
! 1345: != UGETDW(sc->csw.dCSWDataResidue)) {
! 1346: DPRINTF(UDMASS_BBB, ("%s: actlen=%d != residue=%d\n",
! 1347: sc->sc_dev.dv_xname,
! 1348: sc->transfer_datalen - sc->transfer_actlen,
! 1349: UGETDW(sc->csw.dCSWDataResidue)));
! 1350:
! 1351: umass_bbb_reset(sc, STATUS_WIRE_FAILED);
! 1352: return;
! 1353: #endif
! 1354: } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) {
! 1355: DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n",
! 1356: sc->sc_dev.dv_xname,
! 1357: UGETDW(sc->csw.dCSWDataResidue)));
! 1358:
! 1359: /* SCSI command failed but transfer was successful */
! 1360: sc->transfer_state = TSTATE_IDLE;
! 1361: sc->transfer_cb(sc, sc->transfer_priv,
! 1362: UGETDW(sc->csw.dCSWDataResidue),
! 1363: STATUS_CMD_FAILED);
! 1364:
! 1365: return;
! 1366:
! 1367: } else { /* success */
! 1368: sc->transfer_state = TSTATE_IDLE;
! 1369: sc->transfer_cb(sc, sc->transfer_priv,
! 1370: UGETDW(sc->csw.dCSWDataResidue),
! 1371: STATUS_CMD_OK);
! 1372:
! 1373: return;
! 1374: }
! 1375:
! 1376: /***** Bulk Reset *****/
! 1377: case TSTATE_BBB_RESET1:
! 1378: if (err)
! 1379: printf("%s: BBB reset failed, %s\n",
! 1380: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1381:
! 1382: sc->transfer_state = TSTATE_BBB_RESET2;
! 1383: umass_clear_endpoint_stall(sc, UMASS_BULKIN,
! 1384: sc->transfer_xfer[XFER_BBB_RESET2]);
! 1385:
! 1386: return;
! 1387: case TSTATE_BBB_RESET2:
! 1388: if (err) /* should not occur */
! 1389: printf("%s: BBB bulk-in clear stall failed, %s\n",
! 1390: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1391: /* no error recovery, otherwise we end up in a loop */
! 1392:
! 1393: sc->transfer_state = TSTATE_BBB_RESET3;
! 1394: umass_clear_endpoint_stall(sc, UMASS_BULKOUT,
! 1395: sc->transfer_xfer[XFER_BBB_RESET3]);
! 1396:
! 1397: return;
! 1398: case TSTATE_BBB_RESET3:
! 1399: if (err) /* should not occur */
! 1400: printf("%s: BBB bulk-out clear stall failed, %s\n",
! 1401: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1402: /* no error recovery, otherwise we end up in a loop */
! 1403:
! 1404: sc->transfer_state = TSTATE_IDLE;
! 1405: if (sc->transfer_priv) {
! 1406: sc->transfer_cb(sc, sc->transfer_priv,
! 1407: sc->transfer_datalen,
! 1408: sc->transfer_status);
! 1409: }
! 1410:
! 1411: return;
! 1412:
! 1413: /***** Default *****/
! 1414: default:
! 1415: panic("%s: Unknown state %d",
! 1416: sc->sc_dev.dv_xname, sc->transfer_state);
! 1417: }
! 1418: }
! 1419:
! 1420: /*
! 1421: * Command/Bulk/Interrupt (CBI) specific functions
! 1422: */
! 1423:
! 1424: int
! 1425: umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen,
! 1426: usbd_xfer_handle xfer)
! 1427: {
! 1428: KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
! 1429: ("sc->sc_wire == 0x%02x wrong for umass_cbi_adsc\n",
! 1430: sc->sc_wire));
! 1431:
! 1432: sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
! 1433: sc->sc_req.bRequest = UR_CBI_ADSC;
! 1434: USETW(sc->sc_req.wValue, 0);
! 1435: USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
! 1436: USETW(sc->sc_req.wLength, buflen);
! 1437: return umass_setup_ctrl_transfer(sc, &sc->sc_req, buffer,
! 1438: buflen, 0, xfer);
! 1439: }
! 1440:
! 1441:
! 1442: void
! 1443: umass_cbi_reset(struct umass_softc *sc, int status)
! 1444: {
! 1445: int i;
! 1446: # define SEND_DIAGNOSTIC_CMDLEN 12
! 1447:
! 1448: KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
! 1449: ("sc->sc_wire == 0x%02x wrong for umass_cbi_reset\n",
! 1450: sc->sc_wire));
! 1451:
! 1452: if (sc->sc_dying)
! 1453: return;
! 1454:
! 1455: /*
! 1456: * Command Block Reset Protocol
! 1457: *
! 1458: * First send a reset request to the device. Then clear
! 1459: * any possibly stalled bulk endpoints.
! 1460:
! 1461: * This is done in 3 steps, states:
! 1462: * TSTATE_CBI_RESET1
! 1463: * TSTATE_CBI_RESET2
! 1464: * TSTATE_CBI_RESET3
! 1465: *
! 1466: * If the reset doesn't succeed, the device should be port reset.
! 1467: */
! 1468:
! 1469: DPRINTF(UDMASS_CBI, ("%s: CBI Reset\n",
! 1470: sc->sc_dev.dv_xname));
! 1471:
! 1472: KASSERT(sizeof(sc->cbl) >= SEND_DIAGNOSTIC_CMDLEN,
! 1473: ("%s: CBL struct is too small (%d < %d)\n",
! 1474: sc->sc_dev.dv_xname,
! 1475: sizeof(sc->cbl), SEND_DIAGNOSTIC_CMDLEN));
! 1476:
! 1477: sc->transfer_state = TSTATE_CBI_RESET1;
! 1478: sc->transfer_status = status;
! 1479:
! 1480: /* The 0x1d code is the SEND DIAGNOSTIC command. To distinguish between
! 1481: * the two the last 10 bytes of the cbl is filled with 0xff (section
! 1482: * 2.2 of the CBI spec).
! 1483: */
! 1484: sc->cbl[0] = 0x1d; /* Command Block Reset */
! 1485: sc->cbl[1] = 0x04;
! 1486: for (i = 2; i < SEND_DIAGNOSTIC_CMDLEN; i++)
! 1487: sc->cbl[i] = 0xff;
! 1488:
! 1489: umass_cbi_adsc(sc, sc->cbl, SEND_DIAGNOSTIC_CMDLEN,
! 1490: sc->transfer_xfer[XFER_CBI_RESET1]);
! 1491: /* XXX if the command fails we should reset the port on the bub */
! 1492: }
! 1493:
! 1494: void
! 1495: umass_cbi_transfer(struct umass_softc *sc, int lun,
! 1496: void *cmd, int cmdlen, void *data, int datalen, int dir,
! 1497: u_int timeout, umass_callback cb, void *priv)
! 1498: {
! 1499: usbd_status err;
! 1500:
! 1501: DPRINTF(UDMASS_CBI,("%s: umass_cbi_transfer cmd=0x%02x, len=%d\n",
! 1502: sc->sc_dev.dv_xname, *(u_char *)cmd, datalen));
! 1503:
! 1504: KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
! 1505: ("sc->sc_wire == 0x%02x wrong for umass_cbi_transfer\n",
! 1506: sc->sc_wire));
! 1507:
! 1508: if (sc->sc_dying) {
! 1509: sc->polled_xfer_status = USBD_IOERROR;
! 1510: return;
! 1511: }
! 1512:
! 1513: /* Be a little generous. */
! 1514: sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
! 1515:
! 1516: /*
! 1517: * Do a CBI transfer with cmdlen bytes from cmd, possibly
! 1518: * a data phase of datalen bytes from/to the device and finally a
! 1519: * csw read phase.
! 1520: * If the data direction was inbound a maximum of datalen bytes
! 1521: * is stored in the buffer pointed to by data.
! 1522: *
! 1523: * umass_cbi_transfer initialises the transfer and lets the state
! 1524: * machine in umass_cbi_state handle the completion. It uses the
! 1525: * following states:
! 1526: * TSTATE_CBI_COMMAND
! 1527: * -> XXX fill in
! 1528: *
! 1529: * An error in any of those states will invoke
! 1530: * umass_cbi_reset.
! 1531: */
! 1532:
! 1533: /* check the given arguments */
! 1534: KASSERT(datalen == 0 || data != NULL,
! 1535: ("%s: datalen > 0, but no buffer",sc->sc_dev.dv_xname));
! 1536: KASSERT(datalen == 0 || dir != DIR_NONE,
! 1537: ("%s: direction is NONE while datalen is not zero\n",
! 1538: sc->sc_dev.dv_xname));
! 1539:
! 1540: /* store the details for the data transfer phase */
! 1541: sc->transfer_dir = dir;
! 1542: sc->transfer_data = data;
! 1543: sc->transfer_datalen = datalen;
! 1544: sc->transfer_actlen = 0;
! 1545: sc->transfer_cb = cb;
! 1546: sc->transfer_priv = priv;
! 1547: sc->transfer_status = STATUS_CMD_OK;
! 1548:
! 1549: /* move from idle to the command state */
! 1550: sc->transfer_state = TSTATE_CBI_COMMAND;
! 1551:
! 1552: /* Send the Command Block from host to device via control endpoint. */
! 1553: sc->cbw.bCDBLength = cmdlen;
! 1554: bzero(sc->cbw.CBWCDB, sizeof(sc->cbw.CBWCDB));
! 1555: memcpy(sc->cbw.CBWCDB, cmd, cmdlen);
! 1556: umass_adjust_transfer(sc);
! 1557: if ((err = umass_cbi_adsc(sc, (void *)sc->cbw.CBWCDB, sc->cbw.bCDBLength,
! 1558: sc->transfer_xfer[XFER_CBI_CB])))
! 1559: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1560:
! 1561: if (sc->sc_udev->bus->use_polling)
! 1562: sc->polled_xfer_status = err;
! 1563: }
! 1564:
! 1565: void
! 1566: umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
! 1567: usbd_status err)
! 1568: {
! 1569: struct umass_softc *sc = (struct umass_softc *) priv;
! 1570:
! 1571: KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
! 1572: ("sc->sc_wire == 0x%02x wrong for umass_cbi_state\n",
! 1573: sc->sc_wire));
! 1574:
! 1575: if (sc->sc_dying)
! 1576: return;
! 1577:
! 1578: /*
! 1579: * State handling for CBI transfers.
! 1580: */
! 1581:
! 1582: DPRINTF(UDMASS_CBI, ("%s: Handling CBI state %d (%s), xfer=%p, %s\n",
! 1583: sc->sc_dev.dv_xname, sc->transfer_state,
! 1584: states[sc->transfer_state], xfer, usbd_errstr(err)));
! 1585:
! 1586: switch (sc->transfer_state) {
! 1587:
! 1588: /***** CBI Transfer *****/
! 1589: case TSTATE_CBI_COMMAND:
! 1590: if (err == USBD_STALLED) {
! 1591: DPRINTF(UDMASS_CBI, ("%s: Command Transport failed\n",
! 1592: sc->sc_dev.dv_xname));
! 1593: /* Status transport by control pipe (section 2.3.2.1).
! 1594: * The command contained in the command block failed.
! 1595: *
! 1596: * The control pipe has already been unstalled by the
! 1597: * USB stack.
! 1598: * Section 2.4.3.1.1 states that the bulk in endpoints
! 1599: * should not stalled at this point.
! 1600: */
! 1601:
! 1602: sc->transfer_state = TSTATE_IDLE;
! 1603: sc->transfer_cb(sc, sc->transfer_priv,
! 1604: sc->transfer_datalen,
! 1605: STATUS_CMD_FAILED);
! 1606:
! 1607: return;
! 1608: } else if (err) {
! 1609: DPRINTF(UDMASS_CBI, ("%s: failed to send ADSC\n",
! 1610: sc->sc_dev.dv_xname));
! 1611: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1612: return;
! 1613: }
! 1614:
! 1615: /* Data transport phase, setup transfer */
! 1616: sc->transfer_state = TSTATE_CBI_DATA;
! 1617: if (sc->transfer_dir == DIR_IN) {
! 1618: if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
! 1619: sc->data_buffer, sc->transfer_datalen,
! 1620: USBD_SHORT_XFER_OK | USBD_NO_COPY,
! 1621: sc->transfer_xfer[XFER_CBI_DATA]))
! 1622: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1623:
! 1624: return;
! 1625: } else if (sc->transfer_dir == DIR_OUT) {
! 1626: memcpy(sc->data_buffer, sc->transfer_data,
! 1627: sc->transfer_datalen);
! 1628: if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
! 1629: sc->data_buffer, sc->transfer_datalen,
! 1630: USBD_NO_COPY,/* fixed length transfer */
! 1631: sc->transfer_xfer[XFER_CBI_DATA]))
! 1632: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1633:
! 1634: return;
! 1635: } else {
! 1636: DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
! 1637: sc->sc_dev.dv_xname));
! 1638: }
! 1639:
! 1640: /* FALLTHROUGH if no data phase, err == 0 */
! 1641: case TSTATE_CBI_DATA:
! 1642: /* Command transport phase error handling (ignored if no data
! 1643: * phase (fallthrough from previous state)) */
! 1644: if (sc->transfer_dir != DIR_NONE) {
! 1645: /* retrieve the length of the transfer that was done */
! 1646: usbd_get_xfer_status(xfer, NULL, NULL,
! 1647: &sc->transfer_actlen, NULL);
! 1648: DPRINTF(UDMASS_CBI, ("%s: CBI_DATA actlen=%d\n",
! 1649: sc->sc_dev.dv_xname, sc->transfer_actlen));
! 1650:
! 1651: if (err) {
! 1652: DPRINTF(UDMASS_CBI, ("%s: Data-%s %d failed, "
! 1653: "%s\n", sc->sc_dev.dv_xname,
! 1654: (sc->transfer_dir == DIR_IN?"in":"out"),
! 1655: sc->transfer_datalen,usbd_errstr(err)));
! 1656:
! 1657: if (err == USBD_STALLED) {
! 1658: sc->transfer_state = TSTATE_CBI_DCLEAR;
! 1659: umass_clear_endpoint_stall(sc,
! 1660: (sc->transfer_dir == DIR_IN?
! 1661: UMASS_BULKIN:UMASS_BULKOUT),
! 1662: sc->transfer_xfer[XFER_CBI_DCLEAR]);
! 1663: } else {
! 1664: /* Unless the error is a pipe stall the
! 1665: * error is fatal.
! 1666: */
! 1667: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1668: }
! 1669: return;
! 1670: }
! 1671: }
! 1672:
! 1673: if (sc->transfer_dir == DIR_IN)
! 1674: memcpy(sc->transfer_data, sc->data_buffer,
! 1675: sc->transfer_actlen);
! 1676:
! 1677: DIF(UDMASS_CBI, if (sc->transfer_dir == DIR_IN)
! 1678: umass_dump_buffer(sc, sc->transfer_data,
! 1679: sc->transfer_actlen, 48));
! 1680:
! 1681: /* Status phase */
! 1682: if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
! 1683: sc->transfer_state = TSTATE_CBI_STATUS;
! 1684: memset(&sc->sbl, 0, sizeof(sc->sbl));
! 1685: if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN],
! 1686: &sc->sbl, sizeof(sc->sbl),
! 1687: 0, /* fixed length transfer */
! 1688: sc->transfer_xfer[XFER_CBI_STATUS]))
! 1689: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1690: } else {
! 1691: /* No command completion interrupt. Request
! 1692: * sense to get status of command.
! 1693: */
! 1694: sc->transfer_state = TSTATE_IDLE;
! 1695: sc->transfer_cb(sc, sc->transfer_priv,
! 1696: sc->transfer_datalen - sc->transfer_actlen,
! 1697: STATUS_CMD_UNKNOWN);
! 1698: }
! 1699: return;
! 1700:
! 1701: case TSTATE_CBI_STATUS:
! 1702: if (err) {
! 1703: DPRINTF(UDMASS_CBI, ("%s: Status Transport failed\n",
! 1704: sc->sc_dev.dv_xname));
! 1705: /* Status transport by interrupt pipe (section 2.3.2.2).
! 1706: */
! 1707:
! 1708: if (err == USBD_STALLED) {
! 1709: sc->transfer_state = TSTATE_CBI_SCLEAR;
! 1710: umass_clear_endpoint_stall(sc, UMASS_INTRIN,
! 1711: sc->transfer_xfer[XFER_CBI_SCLEAR]);
! 1712: } else {
! 1713: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1714: }
! 1715: return;
! 1716: }
! 1717:
! 1718: /* Dissect the information in the buffer */
! 1719:
! 1720: {
! 1721: u_int32_t actlen;
! 1722: usbd_get_xfer_status(xfer, NULL, NULL, &actlen, NULL);
! 1723: DPRINTF(UDMASS_CBI, ("%s: CBI_STATUS actlen=%d\n",
! 1724: sc->sc_dev.dv_xname, actlen));
! 1725: if (actlen != 2)
! 1726: break;
! 1727: }
! 1728:
! 1729: if (sc->sc_cmd == UMASS_CPROTO_UFI) {
! 1730: int status;
! 1731:
! 1732: /* Section 3.4.3.1.3 specifies that the UFI command
! 1733: * protocol returns an ASC and ASCQ in the interrupt
! 1734: * data block.
! 1735: */
! 1736:
! 1737: DPRINTF(UDMASS_CBI, ("%s: UFI CCI, ASC = 0x%02x, "
! 1738: "ASCQ = 0x%02x\n",
! 1739: sc->sc_dev.dv_xname,
! 1740: sc->sbl.ufi.asc, sc->sbl.ufi.ascq));
! 1741:
! 1742: if ((sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0) ||
! 1743: sc->sc_sense)
! 1744: status = STATUS_CMD_OK;
! 1745: else
! 1746: status = STATUS_CMD_FAILED;
! 1747:
! 1748: /* No autosense, command successful */
! 1749: sc->transfer_state = TSTATE_IDLE;
! 1750: sc->transfer_cb(sc, sc->transfer_priv,
! 1751: sc->transfer_datalen - sc->transfer_actlen, status);
! 1752: } else {
! 1753: int status;
! 1754:
! 1755: /* Command Interrupt Data Block */
! 1756:
! 1757: DPRINTF(UDMASS_CBI, ("%s: type=0x%02x, value=0x%02x\n",
! 1758: sc->sc_dev.dv_xname,
! 1759: sc->sbl.common.type, sc->sbl.common.value));
! 1760:
! 1761: if (sc->sbl.common.type == IDB_TYPE_CCI) {
! 1762: switch (sc->sbl.common.value &
! 1763: IDB_VALUE_STATUS_MASK) {
! 1764: case IDB_VALUE_PASS:
! 1765: status = STATUS_CMD_OK;
! 1766: break;
! 1767: case IDB_VALUE_FAIL:
! 1768: case IDB_VALUE_PERSISTENT:
! 1769: status = STATUS_CMD_FAILED;
! 1770: break;
! 1771: case IDB_VALUE_PHASE:
! 1772: status = STATUS_WIRE_FAILED;
! 1773: break;
! 1774: }
! 1775:
! 1776: sc->transfer_state = TSTATE_IDLE;
! 1777: sc->transfer_cb(sc, sc->transfer_priv,
! 1778: sc->transfer_datalen - sc->transfer_actlen,
! 1779: status);
! 1780: }
! 1781: }
! 1782: return;
! 1783:
! 1784: case TSTATE_CBI_DCLEAR:
! 1785: if (err) { /* should not occur */
! 1786: printf("%s: CBI bulk-in/out stall clear failed, %s\n",
! 1787: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1788: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1789: } else {
! 1790: sc->transfer_state = TSTATE_IDLE;
! 1791: sc->transfer_cb(sc, sc->transfer_priv,
! 1792: sc->transfer_datalen, STATUS_CMD_FAILED);
! 1793: }
! 1794: return;
! 1795:
! 1796: case TSTATE_CBI_SCLEAR:
! 1797: if (err) { /* should not occur */
! 1798: printf("%s: CBI intr-in stall clear failed, %s\n",
! 1799: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1800: umass_cbi_reset(sc, STATUS_WIRE_FAILED);
! 1801: } else {
! 1802: sc->transfer_state = TSTATE_IDLE;
! 1803: sc->transfer_cb(sc, sc->transfer_priv,
! 1804: sc->transfer_datalen, STATUS_CMD_FAILED);
! 1805: }
! 1806: return;
! 1807:
! 1808: /***** CBI Reset *****/
! 1809: case TSTATE_CBI_RESET1:
! 1810: if (err)
! 1811: printf("%s: CBI reset failed, %s\n",
! 1812: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1813:
! 1814: sc->transfer_state = TSTATE_CBI_RESET2;
! 1815: umass_clear_endpoint_stall(sc, UMASS_BULKIN,
! 1816: sc->transfer_xfer[XFER_CBI_RESET2]);
! 1817:
! 1818: return;
! 1819: case TSTATE_CBI_RESET2:
! 1820: if (err) /* should not occur */
! 1821: printf("%s: CBI bulk-in stall clear failed, %s\n",
! 1822: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1823: /* no error recovery, otherwise we end up in a loop */
! 1824:
! 1825: sc->transfer_state = TSTATE_CBI_RESET3;
! 1826: umass_clear_endpoint_stall(sc, UMASS_BULKOUT,
! 1827: sc->transfer_xfer[XFER_CBI_RESET3]);
! 1828:
! 1829: return;
! 1830: case TSTATE_CBI_RESET3:
! 1831: if (err) /* should not occur */
! 1832: printf("%s: CBI bulk-out stall clear failed, %s\n",
! 1833: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1834: /* no error recovery, otherwise we end up in a loop */
! 1835:
! 1836: sc->transfer_state = TSTATE_IDLE;
! 1837: if (sc->transfer_priv) {
! 1838: sc->transfer_cb(sc, sc->transfer_priv,
! 1839: sc->transfer_datalen,
! 1840: sc->transfer_status);
! 1841: }
! 1842:
! 1843: return;
! 1844:
! 1845:
! 1846: /***** Default *****/
! 1847: default:
! 1848: panic("%s: Unknown state %d",
! 1849: sc->sc_dev.dv_xname, sc->transfer_state);
! 1850: }
! 1851: }
! 1852:
! 1853: usbd_status
! 1854: umass_bbb_get_max_lun(struct umass_softc *sc, u_int8_t *maxlun)
! 1855: {
! 1856: usb_device_request_t req;
! 1857: usbd_status err;
! 1858:
! 1859: *maxlun = 0; /* Default to 0. */
! 1860:
! 1861: DPRINTF(UDMASS_BBB, ("%s: Get Max Lun\n", sc->sc_dev.dv_xname));
! 1862:
! 1863: /* The Get Max Lun command is a class-specific request. */
! 1864: req.bmRequestType = UT_READ_CLASS_INTERFACE;
! 1865: req.bRequest = UR_BBB_GET_MAX_LUN;
! 1866: USETW(req.wValue, 0);
! 1867: USETW(req.wIndex, sc->sc_ifaceno);
! 1868: USETW(req.wLength, 1);
! 1869:
! 1870: err = usbd_do_request_flags(sc->sc_udev, &req, maxlun,
! 1871: USBD_SHORT_XFER_OK, 0, USBD_DEFAULT_TIMEOUT);
! 1872: switch (err) {
! 1873: case USBD_NORMAL_COMPLETION:
! 1874: DPRINTF(UDMASS_BBB, ("%s: Max Lun %d\n",
! 1875: sc->sc_dev.dv_xname, *maxlun));
! 1876: break;
! 1877:
! 1878: case USBD_STALLED:
! 1879: /*
! 1880: * Device doesn't support Get Max Lun request.
! 1881: */
! 1882: err = USBD_NORMAL_COMPLETION;
! 1883: DPRINTF(UDMASS_BBB, ("%s: Get Max Lun not supported\n",
! 1884: sc->sc_dev.dv_xname));
! 1885: break;
! 1886:
! 1887: case USBD_SHORT_XFER:
! 1888: /*
! 1889: * XXX This must mean Get Max Lun is not supported, too!
! 1890: */
! 1891: err = USBD_NORMAL_COMPLETION;
! 1892: DPRINTF(UDMASS_BBB, ("%s: Get Max Lun SHORT_XFER\n",
! 1893: sc->sc_dev.dv_xname));
! 1894: break;
! 1895:
! 1896: default:
! 1897: printf("%s: Get Max Lun failed: %s\n",
! 1898: sc->sc_dev.dv_xname, usbd_errstr(err));
! 1899: /* XXX Should we port_reset the device? */
! 1900: break;
! 1901: }
! 1902:
! 1903: return (err);
! 1904: }
! 1905:
! 1906: #ifdef UMASS_DEBUG
! 1907: void
! 1908: umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw)
! 1909: {
! 1910: int clen = cbw->bCDBLength;
! 1911: int dlen = UGETDW(cbw->dCBWDataTransferLength);
! 1912: u_int8_t *c = cbw->CBWCDB;
! 1913: int tag = UGETDW(cbw->dCBWTag);
! 1914: int flags = cbw->bCBWFlags;
! 1915:
! 1916: DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmdlen=%d "
! 1917: "(0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%s), "
! 1918: "data = %d bytes, dir = %s\n",
! 1919: sc->sc_dev.dv_xname, tag, clen,
! 1920: c[0], c[1], c[2], c[3], c[4], c[5],
! 1921: c[6], c[7], c[8], c[9],
! 1922: (clen > 10? "...":""),
! 1923: dlen, (flags == CBWFLAGS_IN? "in":
! 1924: (flags == CBWFLAGS_OUT? "out":"<invalid>"))));
! 1925: }
! 1926:
! 1927: void
! 1928: umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw)
! 1929: {
! 1930: int sig = UGETDW(csw->dCSWSignature);
! 1931: int tag = UGETDW(csw->dCSWTag);
! 1932: int res = UGETDW(csw->dCSWDataResidue);
! 1933: int status = csw->bCSWStatus;
! 1934:
! 1935: DPRINTF(UDMASS_BBB, ("%s: CSW %d: sig = 0x%08x (%s), tag = %d, "
! 1936: "res = %d, status = 0x%02x (%s)\n", sc->sc_dev.dv_xname,
! 1937: tag, sig, (sig == CSWSIGNATURE? "valid":"invalid"),
! 1938: tag, res,
! 1939: status, (status == CSWSTATUS_GOOD? "good":
! 1940: (status == CSWSTATUS_FAILED? "failed":
! 1941: (status == CSWSTATUS_PHASE? "phase":"<invalid>")))));
! 1942: }
! 1943:
! 1944: void
! 1945: umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen,
! 1946: int printlen)
! 1947: {
! 1948: int i, j;
! 1949: char s1[40];
! 1950: char s2[40];
! 1951: char s3[5];
! 1952:
! 1953: s1[0] = '\0';
! 1954: s3[0] = '\0';
! 1955:
! 1956: snprintf(s2, sizeof s2, " buffer=%p, buflen=%d", buffer, buflen);
! 1957: for (i = 0; i < buflen && i < printlen; i++) {
! 1958: j = i % 16;
! 1959: if (j == 0 && i != 0) {
! 1960: DPRINTF(UDMASS_GEN, ("%s: 0x %s%s\n",
! 1961: sc->sc_dev.dv_xname, s1, s2));
! 1962: s2[0] = '\0';
! 1963: }
! 1964: snprintf(&s1[j*2], sizeof s1 - j*2, "%02x", buffer[i] & 0xff);
! 1965: }
! 1966: if (buflen > printlen)
! 1967: snprintf(s3, sizeof s3, " ...");
! 1968: DPRINTF(UDMASS_GEN, ("%s: 0x %s%s%s\n",
! 1969: sc->sc_dev.dv_xname, s1, s2, s3));
! 1970: }
! 1971: #endif
CVSweb