USB polling patches - 3/3 - umass_scsi changes for polled transfers. Change the wire_xfer functions so that they return the status of the transfer. When in polling mode this provides an indication of whether the transaction made it onto the wire or not. Combine this with the SCSI transaction's status to determine whether the transaction went OK. diff -rup dev/usb-2/umass.c dev/usb/umass.c --- dev/usb-2/umass.c Wed Jul 21 18:01:30 2004 +++ dev/usb/umass.c Fri Feb 25 15:32:11 2005 @@ -213,20 +213,23 @@ Static void umass_reset(struct umass_sof #endif /* Bulk-Only related functions */ -Static void umass_bbb_transfer(struct umass_softc *, int, void *, int, void *, - int, int, u_int, umass_callback, void *); +Static usbd_status umass_bbb_transfer(struct umass_softc *, int, void *, int, + void *, int, int, u_int, umass_callback, + void *); Static void umass_bbb_reset(struct umass_softc *, int); Static void umass_bbb_state(usbd_xfer_handle, usbd_private_handle, usbd_status); usbd_status umass_bbb_get_max_lun(struct umass_softc *, u_int8_t *); /* CBI related functions */ -Static void umass_cbi_transfer(struct umass_softc *, int, void *, int, void *, - int, int, u_int, umass_callback, void *); +Static usbd_status umass_cbi_transfer(struct umass_softc *, int, void *, int, + void *, int, int, u_int, umass_callback, + void *); Static void umass_cbi_reset(struct umass_softc *, int); Static void umass_cbi_state(usbd_xfer_handle, usbd_private_handle, usbd_status); -Static int umass_cbi_adsc(struct umass_softc *, char *, int, usbd_xfer_handle); +Static usbd_status umass_cbi_adsc(struct umass_softc *, char *, int, + usbd_xfer_handle); const struct umass_wire_methods umass_bbb_methods = { umass_bbb_transfer, @@ -875,12 +878,13 @@ umass_bbb_reset(struct umass_softc *sc, sc->transfer_xfer[XFER_BBB_RESET1]); } -Static void +Static usbd_status umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, void *data, int datalen, int dir, u_int timeout, umass_callback cb, void *priv) { static int dCBWtag = 42; /* unique for CBW of transfer */ + usbd_status err; DPRINTF(UDMASS_BBB,("%s: umass_bbb_transfer cmd=0x%02x\n", USBDEVNAME(sc->sc_dev), *(u_char *)cmd)); @@ -890,7 +894,7 @@ umass_bbb_transfer(struct umass_softc *s sc->sc_wire)); if (sc->sc_dying) - return; + return (USBD_IOERROR); /* Be a little generous. */ sc->timeout = timeout + USBD_DEFAULT_TIMEOUT; @@ -982,11 +986,13 @@ umass_bbb_transfer(struct umass_softc *s sc->transfer_state = TSTATE_BBB_COMMAND; /* Send the CBW from host to device via bulk-out endpoint. */ - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT], + if ((err = umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT], &sc->cbw, UMASS_BBB_CBW_SIZE, 0, - sc->transfer_xfer[XFER_BBB_CBW])) { + sc->transfer_xfer[XFER_BBB_CBW])) != 0) { umass_bbb_reset(sc, STATUS_WIRE_FAILED); } + + return (err); } @@ -1302,7 +1308,7 @@ umass_bbb_state(usbd_xfer_handle xfer, u * Command/Bulk/Interrupt (CBI) specific functions */ -Static int +Static usbd_status umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen, usbd_xfer_handle xfer) { @@ -1372,11 +1378,13 @@ umass_cbi_reset(struct umass_softc *sc, /* XXX if the command fails we should reset the port on the bub */ } -Static void +Static usbd_status umass_cbi_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, void *data, int datalen, int dir, u_int timeout, umass_callback cb, void *priv) { + usbd_status err; + DPRINTF(UDMASS_CBI,("%s: umass_cbi_transfer cmd=0x%02x, len=%d\n", USBDEVNAME(sc->sc_dev), *(u_char *)cmd, datalen)); @@ -1385,7 +1393,7 @@ umass_cbi_transfer(struct umass_softc *s sc->sc_wire)); if (sc->sc_dying) - return; + return (USBD_IOERROR); /* Be a little generous. */ sc->timeout = timeout + USBD_DEFAULT_TIMEOUT; @@ -1427,8 +1435,11 @@ umass_cbi_transfer(struct umass_softc *s sc->transfer_state = TSTATE_CBI_COMMAND; /* Send the Command Block from host to device via control endpoint. */ - if (umass_cbi_adsc(sc, cmd, cmdlen, sc->transfer_xfer[XFER_CBI_CB])) + if ((err = umass_cbi_adsc(sc, cmd, cmdlen, + sc->transfer_xfer[XFER_CBI_CB])) != 0) umass_cbi_reset(sc, STATUS_WIRE_FAILED); + + return (err); } Static void diff -rup dev/usb-2/umass_scsi.c dev/usb/umass_scsi.c --- dev/usb-2/umass_scsi.c Thu Jul 22 12:40:21 2004 +++ dev/usb/umass_scsi.c Fri Feb 25 15:32:11 2005 @@ -173,7 +173,6 @@ umass_scsi_cmd(struct scsi_xfer *xs) { struct scsi_link *sc_link = xs->sc_link; struct umass_softc *sc = sc_link->adapter_softc; - struct umass_scsi_softc *scbus = (struct umass_scsi_softc *)sc->bus; struct scsi_generic *cmd; int cmdlen, dir, s; @@ -239,27 +238,30 @@ umass_scsi_cmd(struct scsi_xfer *xs) } if (xs->flags & SCSI_POLL) { + usbd_status sync_status; + /* Use sync transfer. XXX Broken! */ DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: sync dir=%d\n", dir)); - sc->sc_xfer_flags = USBD_SYNCHRONOUS; - scbus->sc_sync_status = USBD_INVAL; - sc->sc_methods->wire_xfer(sc, sc_link->lun, cmd, cmdlen, - xs->data, xs->datalen, dir, - xs->timeout, 0, xs); + sc->sc_xfer_flags = USBD_SYNCHRONOUS | USBD_USE_POLLING; + sync_status = sc->sc_methods->wire_xfer(sc, sc_link->lun, cmd, + cmdlen, xs->data, xs->datalen, dir, xs->timeout, + umass_scsi_cb, xs); sc->sc_xfer_flags = 0; - DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n", - scbus->sc_sync_status)); - switch (scbus->sc_sync_status) { - case USBD_NORMAL_COMPLETION: - xs->error = XS_NOERROR; - break; - case USBD_TIMEOUT: - xs->error = XS_TIMEOUT; - break; - default: - xs->error = XS_DRIVER_STUFFUP; - break; + if (xs->error == XS_NOERROR) { + switch (sync_status) { + case USBD_NORMAL_COMPLETION: + xs->error = XS_NOERROR; + break; + case USBD_TIMEOUT: + xs->error = XS_TIMEOUT; + break; + default: + xs->error = XS_DRIVER_STUFFUP; + break; + } } + DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done status=%d, " + "error=%d\n", sync_status, xs->error)); goto done; } else { DPRINTF(UDMASS_SCSI, @@ -378,6 +380,9 @@ umass_scsi_cb(struct umass_softc *sc, vo panic("%s: Unknown status %d in umass_scsi_cb", USBDEVNAME(sc->sc_dev), status); } + + if (xs->flags & SCSI_POLL) + return; xs->flags |= ITSDONE; diff -rup dev/usb-2/umassvar.h dev/usb/umassvar.h --- dev/usb-2/umassvar.h Wed Jul 21 17:43:41 2004 +++ dev/usb/umassvar.h Fri Feb 25 15:32:11 2005 @@ -133,8 +133,9 @@ typedef void (*umass_callback)(struct um #define STATUS_CMD_FAILED 2 /* transfer was ok, command failed */ #define STATUS_WIRE_FAILED 3 /* couldn't even get command across */ -typedef void (*umass_wire_xfer)(struct umass_softc *, int, void *, int, void *, - int, int, u_int, umass_callback, void *); +typedef usbd_status (*umass_wire_xfer)(struct umass_softc *, int, void *, int, + void *, int, int, u_int, umass_callback, + void *); typedef void (*umass_wire_reset)(struct umass_softc *, int); typedef void (*umass_wire_state)(usbd_xfer_handle, usbd_private_handle, usbd_status);