diff options
| author | augustss <augustss@NetBSD.org> | 2000-05-30 01:12:51 +0000 |
|---|---|---|
| committer | augustss <augustss@NetBSD.org> | 2000-05-30 01:12:51 +0000 |
| commit | ea5a1744950e4fd4dbbde6a48c5566d98a28950f (patch) | |
| tree | 840e3e968bc4a4d31e00ac13706b11d962687831 /sys/dev | |
| parent | 997c3c5b8a0b568d601a19d6e18b897e073c8aeb (diff) | |
Massage the SCSI commands when using the UFI protocol in a better way.
Now the Y-E Data Flashbuster floppy seems to work.
Thanks to Y-E Data for giving one to the project when I couldn't find
one easily.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/usb/umass.c | 102 |
1 files changed, 90 insertions, 12 deletions
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c index 6368b6dbaa9..3d3e9394870 100644 --- a/sys/dev/usb/umass.c +++ b/sys/dev/usb/umass.c @@ -1,4 +1,4 @@ -/* $NetBSD: umass.c,v 1.34 2000/04/28 21:34:05 augustss Exp $ */ +/* $NetBSD: umass.c,v 1.35 2000/05/30 01:12:51 augustss Exp $ */ /*- * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>, * Nick Hibma <n_hibma@freebsd.org> @@ -172,7 +172,7 @@ int umassdebug = 0; //UDMASS_ALL; /* Generic definitions */ -#define UFI_PROTO_LEN 12 +#define UFI_COMMAND_LENGTH 12 /* Direction for umass_*_transfer */ #define DIR_NONE 0 @@ -595,6 +595,9 @@ Static void umass_scsipi_sense_cb __P((struct umass_softc *sc, void *priv, int residue, int status)); Static int scsipiprint __P((void *aux, const char *pnp)); +Static int umass_ufi_transform __P((struct umass_softc *sc, + struct scsipi_generic *cmd, int cmdlen, + struct scsipi_generic *rcmd, int *rcmdlen)); #if NATAPIBUS > 0 Static void umass_atapi_probedev __P((struct atapibus_softc *, int)); #endif @@ -1052,8 +1055,10 @@ USB_ATTACH(umass) * fill in the prototype scsipi_link. */ switch (sc->proto & PROTO_COMMAND) { - case PROTO_SCSI: case PROTO_UFI: + sc->u.sc_link.quirks |= SDEV_ONLYBIG; + /* fall into */ + case PROTO_SCSI: sc->u.sc_link.type = BUS_SCSI; sc->u.sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE; sc->u.sc_link.adapter_softc = sc; @@ -1064,7 +1069,7 @@ USB_ATTACH(umass) sc->u.sc_link.scsipi_scsi.max_target = UMASS_SCSIID_DEVICE; sc->u.sc_link.scsipi_scsi.max_lun = sc->maxlun; - if(sc->quirks & NO_TEST_UNIT_READY) + if (sc->quirks & NO_TEST_UNIT_READY) sc->u.sc_link.quirks |= ADEV_NOTUR; break; @@ -3045,6 +3050,7 @@ umass_scsipi_cmd(xs) { struct scsipi_link *sc_link = xs->sc_link; struct umass_softc *sc = sc_link->adapter_softc; + struct scsipi_generic *cmd, trcmd; int cmdlen; int dir; @@ -3111,17 +3117,23 @@ umass_scsipi_cmd(xs) goto done; } + cmd = xs->cmd; cmdlen = xs->cmdlen; - /* All UFI commands are 12 bytes. We'll get a few garbage bytes by extending... */ - if (sc->proto & PROTO_UFI) - cmdlen = UFI_PROTO_LEN; + if (sc->proto & PROTO_UFI) { + if (!umass_ufi_transform(sc, cmd, cmdlen, &trcmd, &cmdlen)) { + xs->error = XS_DRIVER_STUFFUP; + goto done; + } + cmd = &trcmd; + + } if (xs->xs_control & XS_CTL_POLL) { /* Use sync transfer. XXX Broken! */ DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: sync dir=%d\n", dir)); sc->sc_xfer_flags = USBD_SYNCHRONOUS; sc->sc_sync_status = USBD_INVAL; - sc->transfer(sc, sc_link->scsipi_scsi.lun, xs->cmd, cmdlen, + sc->transfer(sc, sc_link->scsipi_scsi.lun, cmd, cmdlen, xs->data, xs->datalen, dir, 0, xs); sc->sc_xfer_flags = 0; DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n", @@ -3142,7 +3154,7 @@ umass_scsipi_cmd(xs) DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: async dir=%d, cmdlen=%d" " datalen=%d\n", dir, cmdlen, xs->datalen)); - sc->transfer(sc, sc_link->scsipi_scsi.lun, xs->cmd, cmdlen, + sc->transfer(sc, sc_link->scsipi_scsi.lun, cmd, cmdlen, xs->data, xs->datalen, dir, umass_scsipi_cb, xs); return (SUCCESSFULLY_QUEUED); } @@ -3216,8 +3228,8 @@ umass_scsipi_cb(struct umass_softc *sc, void *priv, int residue, int status) sc->sc_sense_cmd.length = sizeof(xs->sense); cmdlen = sizeof(sc->sc_sense_cmd); - if (sc->proto & PROTO_UFI) - cmdlen = UFI_PROTO_LEN; + if (sc->proto & PROTO_UFI) /* XXX */ + cmdlen = UFI_COMMAND_LENGTH; sc->transfer(sc, sc_link->scsipi_scsi.lun, &sc->sc_sense_cmd, cmdlen, &xs->sense, sizeof(xs->sense), DIR_IN, @@ -3261,7 +3273,8 @@ umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue, case STATUS_CMD_OK: case STATUS_CMD_UNKNOWN: /* getting sense data succeeded */ - if (xs->cmd->opcode == INQUIRY && xs->resid < xs->datalen) { + if (xs->cmd->opcode == INQUIRY && (xs->resid < xs->datalen + || ((sc->quirks & RS_NO_CLEAR_UA) /* XXX */) )) { /* * Some drivers return SENSE errors even after INQUIRY. * The upper layer doesn't like that. @@ -3293,6 +3306,71 @@ umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue, splx(s); } +/* + * UFI specific functions + */ + +Static int +umass_ufi_transform(struct umass_softc *sc, struct scsipi_generic *cmd, + int cmdlen, struct scsipi_generic *rcmd, int *rcmdlen) +{ + *rcmdlen = UFI_COMMAND_LENGTH; + memset(rcmd, 0, sizeof *rcmd); + + /* Handle any quirks */ + if (cmd->opcode == TEST_UNIT_READY + && (sc->quirks & NO_TEST_UNIT_READY)) { + /* + * Some devices do not support this command. + * Start Stop Unit should give the same results + */ + DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY " + "to START_UNIT\n", USBDEVNAME(sc->sc_dev))); + cmd->opcode = START_STOP; + cmd->bytes[3] = SSS_START; + return 1; + } + + switch (cmd->opcode) { + /* Commands of which the format has been verified. They should work. */ + case TEST_UNIT_READY: + case SCSI_REZERO_UNIT: + case REQUEST_SENSE: + case INQUIRY: + case START_STOP: + /*case SEND_DIAGNOSTIC: ??*/ + case PREVENT_ALLOW: + case READ_CAPACITY: + case READ_BIG: + case WRITE_BIG: + case POSITION_TO_ELEMENT: /* SEEK_10 */ + case SCSI_MODE_SELECT_BIG: + case SCSI_MODE_SENSE_BIG: + /* Copy the command into the (zeroed out) destination buffer */ + memcpy(rcmd, cmd, cmdlen); + return (1); /* success */ + + /* + * Other UFI commands: FORMAT_UNIT, MODE_SELECT, READ_FORMAT_CAPACITY, + * VERIFY, WRITE_AND_VERIFY. + * These should be checked whether they somehow can be made to fit. + */ + + /* These commands are known _not_ to work. They should be converted. */ + case SCSI_READ_COMMAND: + case SCSI_WRITE_COMMAND: + case SCSI_MODE_SENSE: + case SCSI_MODE_SELECT: + default: + printf("%s: Unsupported UFI command 0x%02x", + USBDEVNAME(sc->sc_dev), cmd->opcode); + if (cmdlen == 6) + printf(", 6 byte command should have been converted"); + printf("\n"); + return (0); /* failure */ + } +} + #if NATAPIBUS > 0 Static void umass_atapi_probedev(atapi, target) |
