diff options
-rw-r--r-- | sys/dev/usb/umass.c | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c index fbe8c15..01bce13 100644 --- a/sys/dev/usb/umass.c +++ b/sys/dev/usb/umass.c @@ -305,6 +305,7 @@ struct umass_softc { # define PROTO_SCSI 0x0100 /* command protocol */ # define PROTO_ATAPI 0x0200 # define PROTO_UFI 0x0400 +# define PROTO_RBC 0x0800 # define PROTO_COMMAND 0xff00 /* command protocol mask */ usbd_interface_handle iface; /* Mass Storage interface */ @@ -525,6 +526,10 @@ Static int umass_atapi_transform (struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen); +/* RBC specific functions */ +Static int umass_rbc_transform __P((struct umass_softc *sc, + unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen)); #ifdef UMASS_DEBUG /* General debugging functions */ @@ -624,7 +629,20 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface, id = usbd_get_interface_descriptor(iface); if (id == NULL || id->bInterfaceClass != UCLASS_MASS) return(UMATCH_NONE); - + + if (UGETW(dd->idVendor) == USB_VENDOR_SONY + && id->bInterfaceSubClass==0xff) { + + /* Sony DSC devices set the sub class to 0xff + * instead of 1 (RBC). Fix that here. + */ + id->bInterfaceSubClass = 1; + + /* They also should be able to do higher speed. + */ + sc->transfer_speed = 500; + } + switch (id->bInterfaceSubClass) { case USUBCLASS_SCSI: sc->proto |= PROTO_SCSI; @@ -633,6 +651,9 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface, sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED; sc->proto |= PROTO_UFI; break; + case USUBCLASS_RBC: + sc->proto |= PROTO_RBC; + break; case USUBCLASS_SFF8020I: case USUBCLASS_SFF8070I: #if 0 @@ -723,6 +744,9 @@ USB_ATTACH(umass) case PROTO_UFI: printf("UFI"); break; + case PROTO_RBC: + printf("RBC"); + break; default: printf("(unknown 0x%02x)", sc->proto&PROTO_COMMAND); break; @@ -878,6 +902,8 @@ USB_ATTACH(umass) sc->transform = umass_ufi_transform; else if (sc->proto & PROTO_ATAPI) sc->transform = umass_atapi_transform; + else if (sc->proto & PROTO_RBC) + sc->transform = umass_rbc_transform; #ifdef UMASS_DEBUG else panic("No transformation defined for command proto 0x%02x\n", @@ -898,7 +924,8 @@ USB_ATTACH(umass) if ((sc->proto & PROTO_SCSI) || (sc->proto & PROTO_ATAPI) || - (sc->proto & PROTO_UFI)) { + (sc->proto & PROTO_UFI) || + (sc->proto & PROTO_RBC)) { /* Prepare the SCSI command block */ sc->cam_scsi_sense.opcode = REQUEST_SENSE; @@ -940,7 +967,8 @@ USB_DETACH(umass) if ((sc->proto & PROTO_SCSI) || (sc->proto & PROTO_ATAPI) || - (sc->proto & PROTO_UFI)) + (sc->proto & PROTO_UFI) || + (sc->proto & PROTO_RBC)) /* detach the device from the SCSI host controller (SIM) */ err = umass_cam_detach(sc); @@ -2577,6 +2605,40 @@ umass_scsi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, return 1; /* success */ } +/* RBC specific functions */ +Static int +umass_rbc_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen) +{ + switch (cmd[0]) { + /* these commands are defined in RBC: */ + case READ_10: + case READ_CAPACITY: + case START_STOP_UNIT: + case SYNCHRONIZE_CACHE: + case WRITE_10: + case 0x2f: /* VERIFY_10 is absent from scsi_all.h??? */ + case INQUIRY: + case MODE_SELECT_10: + case MODE_SENSE_10: + case TEST_UNIT_READY: + case WRITE_BUFFER: + /* The following commands are not listed in my copy of the RBC specs. + * CAM however seems to want those, and at least the Sony DSC device + * appears to support those as well */ + case REQUEST_SENSE: + case PREVENT_ALLOW: + *rcmd = cmd; /* We don't need to copy it */ + *rcmdlen = cmdlen; + return 1; /* success */ + /* All other commands are not legal in RBC */ + default: + printf("%s: Unsupported RBC command 0x%02x", + USBDEVNAME(sc->sc_dev), cmd[0]); + printf("\n"); + return 0; /* failure */ + } +} /* * UFI specific functions |