Rewrite the probe routine. This makes adding drives and quirks more easy.

While there change a few names to less confusing ones.
This commit is contained in:
n_hibma 2002-06-16 20:53:35 +00:00
parent 078dff0f24
commit bc70083f07

View File

@ -152,9 +152,8 @@ int umassdebug = UDMASS_ALL;
#define DEVNAME_SIM "umass-sim"
#define UMASS_MAX_TRANSFER_SIZE 65536
#define UMASS_DEFAULT_TRANSFER_SPEED 150 /* in kb/s, conservative est. */
#define UMASS_DEFAULT_TRANSFER_SPEED 1000
#define UMASS_FLOPPY_TRANSFER_SPEED 20
#define UMASS_ZIP100_TRANSFER_SPEED 650
#define UMASS_TIMEOUT 5000 /* msecs */
@ -167,8 +166,7 @@ int umassdebug = UDMASS_ALL;
* ends up being target 3 on that SIM. When a request for target 3
* comes in we fetch the softc with devclass_get_softc(target_id).
*
* The SIM is the highest target number. This makes sure that umass0 corresponds
* to target 0 on the USB SCSI bus.
* The SIM is the highest target number, so umass0 corresponds to SCSI target 0.
*/
#ifndef UMASS_DEBUG
#define UMASS_SCSIID_MAX 32 /* maximum number of drives expected */
@ -267,56 +265,121 @@ typedef int (*command_transform_f) (struct umass_softc *sc,
unsigned char **rcmd, int *rcmdlen);
struct umass_devdescr_t {
u_int32_t vid;
# define VID_WILDCARD 0xffffffff
# define VID_EOT 0xfffffffe
u_int32_t pid;
# define PID_WILDCARD 0xffffffff
# define PID_EOT 0xfffffffe
u_int32_t rid;
# define RID_WILDCARD 0xffffffff
# define RID_EOT 0xfffffffe
/* wire and command protocol */
u_int16_t proto;
# define UMASS_PROTO_BBB 0x0001 /* USB wire protocol */
# define UMASS_PROTO_CBI 0x0002
# define UMASS_PROTO_CBI_I 0x0004
# define UMASS_PROTO_WIRE 0x00ff /* USB wire protocol mask */
# define UMASS_PROTO_SCSI 0x0100 /* command protocol */
# define UMASS_PROTO_ATAPI 0x0200
# define UMASS_PROTO_UFI 0x0400
# define UMASS_PROTO_RBC 0x0800
# define UMASS_PROTO_COMMAND 0xff00 /* command protocol mask */
/* Device specific quirks */
u_int16_t quirks;
# define NO_QUIRKS 0x0000
/* The drive does not support Test Unit Ready. Convert to Start Unit
*/
# define NO_TEST_UNIT_READY 0x0001
/* The drive does not reset the Unit Attention state after REQUEST
* SENSE has been sent. The INQUIRY command does not reset the UA
* either, and so CAM runs in circles trying to retrieve the initial
* INQUIRY data.
*/
# define RS_NO_CLEAR_UA 0x0002
/* The drive does not support START STOP. */
# define NO_START_STOP 0x0004
/* Don't ask for full inquiry data (255b). */
# define FORCE_SHORT_INQUIRY 0x0008
/* Needs to be initialised the Shuttle way */
# define SHUTTLE_INIT 0x0010
/* Drive needs to be switched to alternate iface 1 */
# define ALT_IFACE_1 0x0020
/* Drive does not do 1Mb/s, but just floppy speeds (20kb/s) */
# define FLOPPY_SPEED 0x0040
/* The device can't count and gets the residue of transfers wrong */
# define IGNORE_RESIDUE 0x0080
/* No GetMaxLun call */
# define NO_GETMAXLUN 0x0100
/* The device uses a weird CSWSIGNATURE. */
# define WRONG_CSWSIG 0x0200
};
Static struct umass_devdescr_t umass_devdescrs[] = {
{ USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100, RID_WILDCARD,
UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
RS_NO_CLEAR_UA
},
{ USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200, RID_WILDCARD,
UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
NO_TEST_UNIT_READY | NO_START_STOP
},
{ USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE, RID_WILDCARD,
UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
NO_TEST_UNIT_READY | NO_START_STOP | ALT_IFACE_1
},
{ USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100, RID_WILDCARD,
/* XXX This is not correct as there are Zip drives that use ATAPI.
*/
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
NO_TEST_UNIT_READY
},
{ USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM, RID_WILDCARD,
UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
NO_TEST_UNIT_READY | NO_START_STOP
},
{ USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1, RID_WILDCARD,
UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
WRONG_CSWSIG
},
{ USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R, RID_WILDCARD,
UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
NO_QUIRKS
},
{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB, RID_WILDCARD,
UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
NO_TEST_UNIT_READY | NO_START_STOP | SHUTTLE_INIT
},
{ USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, RID_WILDCARD,
UMASS_PROTO_RBC | UMASS_PROTO_CBI,
NO_QUIRKS
},
{ USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC, RID_WILDCARD,
UMASS_PROTO_RBC | UMASS_PROTO_CBI,
NO_QUIRKS
},
{ USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO, RID_WILDCARD,
UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
FORCE_SHORT_INQUIRY
},
{ VID_EOT, PID_EOT, RID_EOT, 0, 0 }
};
/* the per device structure */
struct umass_softc {
USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_udev; /* USB device */
unsigned char flags; /* various device flags */
# define UMASS_FLAGS_GONE 0x01 /* devices is no more */
# define UMASS_FLAGS_GONE 0x01 /* devices is no more */
unsigned char drive;
# define DRIVE_GENERIC 0 /* use defaults for this one */
# define ZIP_100 1 /* to be used for quirks */
# define ZIP_250 2
# define SHUTTLE_EUSB 3
# define INSYSTEM_USBCABLE 4
unsigned char quirks;
/* The drive does not support Test Unit Ready. Convert to
* Start Unit
* Y-E Data, Zip 100
*/
# define NO_TEST_UNIT_READY 0x01
/* The drive does not reset the Unit Attention state after
* REQUEST SENSE has been sent. The INQUIRY command does not reset
* the UA either, and so CAM runs in circles trying to retrieve the
* initial INQUIRY data.
* Y-E Data
*/
# define RS_NO_CLEAR_UA 0x02
/* The drive does not support START STOP.
* Shuttle E-USB
*/
# define NO_START_STOP 0x04
/* Don't ask for full inquiry data (255 bytes).
* Yano ATAPI-USB
*/
# define FORCE_SHORT_INQUIRY 0x08
/* The device uses a weird CSWSIGNATURE. */
# define WRONG_CSWSIG 0x10
unsigned int proto;
# define PROTO_UNKNOWN 0x0000 /* unknown protocol */
# define PROTO_BBB 0x0001 /* USB wire protocol */
# define PROTO_CBI 0x0002
# define PROTO_CBI_I 0x0004
# define PROTO_WIRE 0x00ff /* USB wire protocol mask */
# 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 */
u_int16_t proto; /* wire and cmd protocol */
u_int16_t quirks; /* they got it almost right */
usbd_interface_handle iface; /* Mass Storage interface */
int ifaceno; /* MS iface number */
@ -422,7 +485,6 @@ struct umass_softc {
struct scsi_sense cam_scsi_sense;
struct scsi_sense cam_scsi_test_unit_ready;
int transfer_speed; /* in kb/s */
int maxlun; /* maximum LUN number */
};
@ -535,13 +597,13 @@ Static int umass_scsi_6_to_10 (unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen);
/* UFI specific functions */
#define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12b */
#define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12 bytes */
Static int umass_ufi_transform (struct umass_softc *sc,
unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen);
/* ATAPI (8070i) specific functions */
#define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12b */
#define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12 bytes */
Static int umass_atapi_transform (struct umass_softc *sc,
unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen);
@ -570,8 +632,8 @@ MODULE_DEPEND(umass, cam, 1,1,1);
/*
* Match the device we are seeing with the devices supported. Fill in the
* proto and drive fields in the softc accordingly.
* This function is called from both probe and attach.
* description in the softc accordingly. This function is called from both
* probe and attach.
*/
Static int
@ -580,64 +642,18 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
{
usb_device_descriptor_t *dd;
usb_interface_descriptor_t *id;
int i;
int found = 0;
sc->sc_udev = udev;
/*
* Fill in sc->drive and sc->proto and return a match
* value if both are determined and 0 otherwise.
*/
sc->drive = DRIVE_GENERIC;
sc->proto = PROTO_UNKNOWN;
sc->transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED;
sc->proto = 0;
sc->quirks = 0;
dd = usbd_get_device_descriptor(udev);
if (UGETW(dd->idVendor) == USB_VENDOR_SHUTTLE
&& UGETW(dd->idProduct) == USB_PRODUCT_SHUTTLE_EUSB) {
sc->drive = SHUTTLE_EUSB;
#if CBI_I
sc->proto = PROTO_ATAPI | PROTO_CBI_I;
#else
sc->proto = PROTO_ATAPI | PROTO_CBI;
#endif
sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
return(UMATCH_VENDOR_PRODUCT);
}
if (UGETW(dd->idVendor) == USB_VENDOR_INSYSTEM
&& UGETW(dd->idProduct) == USB_PRODUCT_INSYSTEM_USBCABLE) {
sc->drive = INSYSTEM_USBCABLE;
sc->proto = PROTO_ATAPI | PROTO_CBI;
sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
return(UMATCH_VENDOR_PRODUCT);
}
if (UGETW(dd->idVendor) == USB_VENDOR_YANO
&& UGETW(dd->idProduct) == USB_PRODUCT_YANO_U640MO) {
sc->proto = PROTO_ATAPI | PROTO_CBI_I;
sc->quirks |= FORCE_SHORT_INQUIRY;
return(UMATCH_VENDOR_PRODUCT);
}
if (UGETW(dd->idVendor) == USB_VENDOR_HP
&& UGETW(dd->idProduct) == USB_PRODUCT_HP_CDW8200) {
sc->drive = SHUTTLE_EUSB;
#if CBI_I
sc->proto = PROTO_ATAPI | PROTO_CBI_I;
#else
sc->proto = PROTO_ATAPI | PROTO_CBI;
#endif
sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
return(UMATCH_VENDOR_PRODUCT);
}
if (UGETW(dd->idVendor) == USB_VENDOR_FUJIPHOTO
&& UGETW(dd->idProduct) == USB_PRODUCT_FUJIPHOTO_MASS0100) {
sc->quirks |= RS_NO_CLEAR_UA;
}
/* An entry specifically for Y-E Data devices as they don't fit in the
* device description table.
*/
if (UGETW(dd->idVendor) == USB_VENDOR_YEDATA
&& UGETW(dd->idProduct) == USB_PRODUCT_YEDATA_FLASHBUSTERU) {
@ -645,13 +661,9 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
* very well.
*/
if (UGETW(dd->bcdDevice) < 0x128) {
sc->proto = PROTO_UFI | PROTO_CBI;
sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI;
} else {
#if CBI_I
sc->proto = PROTO_UFI | PROTO_CBI_I;
#else
sc->proto = PROTO_UFI | PROTO_CBI;
#endif
sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI_I;
}
/*
@ -661,60 +673,46 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
if (UGETW(dd->bcdDevice) <= 0x128)
sc->quirks |= NO_TEST_UNIT_READY;
sc->quirks |= RS_NO_CLEAR_UA;
sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
sc->quirks |= RS_NO_CLEAR_UA | FLOPPY_SPEED;
return(UMATCH_VENDOR_PRODUCT);
}
if (UGETW(dd->idVendor) == USB_VENDOR_MICROTECH
&& UGETW(dd->idProduct) == USB_PRODUCT_MICROTECH_DPCM) {
/* the cameramate does not provide valid
class/subclass information. fake it. */
sc->proto = PROTO_SCSI | PROTO_CBI;
sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
return(UMATCH_VENDOR_PRODUCT);
/* Check the list of supported devices for a match. While looking,
* check for wildcarded and fully matched. First match wins.
*/
for (i = 0; umass_devdescrs[i].vid != VID_EOT && !found; i++) {
if (umass_devdescrs[i].vid == UGETW(dd->idVendor)
&& umass_devdescrs[i].pid == UGETW(dd->idProduct)) {
if (umass_devdescrs[i].rid == RID_WILDCARD) {
sc->proto = umass_devdescrs[i].proto;
sc->quirks = umass_devdescrs[i].quirks;
return UMATCH_VENDOR_PRODUCT;
} else if (umass_devdescrs[i].rid == UGETW(dd->bcdDevice)) {
sc->proto = umass_devdescrs[i].proto;
sc->quirks = umass_devdescrs[i].quirks;
return UMATCH_VENDOR_PRODUCT_REV;
} /* else RID does not match */
}
}
/* Check for a standards compliant device */
id = usbd_get_interface_descriptor(iface);
if (id == NULL || id->bInterfaceClass != UICLASS_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;
}
if (UGETW(dd->idVendor) == USB_VENDOR_OLYMPUS &&
UGETW(dd->idProduct) == USB_PRODUCT_OLYMPUS_C1) {
/*
* The Olympus C-1 camera uses a different command-status
* signature.
*/
sc->quirks |= WRONG_CSWSIG;
}
switch (id->bInterfaceSubClass) {
case UISUBCLASS_SCSI:
sc->proto |= PROTO_SCSI;
sc->proto |= UMASS_PROTO_SCSI;
break;
case UISUBCLASS_UFI:
sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
sc->proto |= PROTO_UFI;
sc->proto |= UMASS_PROTO_UFI;
break;
case UISUBCLASS_RBC:
sc->proto |= PROTO_RBC;
sc->proto |= UMASS_PROTO_RBC;
break;
case UISUBCLASS_SFF8020I:
case UISUBCLASS_SFF8070I:
sc->proto |= PROTO_ATAPI;
sc->proto |= UMASS_PROTO_ATAPI;
break;
default:
DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n",
@ -724,23 +722,14 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
switch (id->bInterfaceProtocol) {
case UIPROTO_MASS_CBI:
sc->proto |= PROTO_CBI;
sc->proto |= UMASS_PROTO_CBI;
break;
case UIPROTO_MASS_CBI_I:
#if CBI_I
sc->proto |= PROTO_CBI_I;
#else
sc->proto |= PROTO_CBI;
#endif
sc->proto |= UMASS_PROTO_CBI_I;
break;
case UIPROTO_MASS_BBB_OLD:
sc->proto |= PROTO_BBB;
break;
case UIPROTO_MASS_BBB:
sc->drive = ZIP_100;
sc->proto |= PROTO_BBB;
sc->transfer_speed = UMASS_ZIP100_TRANSFER_SPEED;
sc->quirks |= NO_TEST_UNIT_READY;
sc->proto |= UMASS_PROTO_BBB;
break;
default:
DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n",
@ -748,16 +737,6 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
return(UMATCH_NONE);
}
if (UGETW(dd->idVendor) == USB_VENDOR_SCANLOGIC
&& UGETW(dd->idProduct) == 0x0002) {
/* ScanLogic SL11R IDE adapter claims to support
* SCSI, but really needs ATAPI.
* Note also that these devices need firmware > 0.71
*/
sc->proto &= ~PROTO_SCSI;
sc->proto |= PROTO_ATAPI;
}
return(UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO);
}
@ -798,44 +777,54 @@ USB_ATTACH(umass)
(void) umass_match_proto(sc, sc->iface, uaa->device);
id = usbd_get_interface_descriptor(sc->iface);
printf("%s: %s", USBDEVNAME(sc->sc_dev), devinfo);
printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
#ifdef UMASS_DEBUG
printf(", ");
switch (sc->proto&PROTO_COMMAND) {
case PROTO_SCSI:
printf("%s: ", USBDEVNAME(sc->sc_dev));
switch (sc->proto&UMASS_PROTO_COMMAND) {
case UMASS_PROTO_SCSI:
printf("SCSI");
break;
case PROTO_ATAPI:
case UMASS_PROTO_ATAPI:
printf("8070i (ATAPI)");
break;
case PROTO_UFI:
case UMASS_PROTO_UFI:
printf("UFI");
break;
case PROTO_RBC:
case UMASS_PROTO_RBC:
printf("RBC");
break;
default:
printf("(unknown 0x%02x)", sc->proto&PROTO_COMMAND);
printf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_COMMAND);
break;
}
printf(" over ");
switch (sc->proto&PROTO_WIRE) {
case PROTO_BBB:
switch (sc->proto&UMASS_PROTO_WIRE) {
case UMASS_PROTO_BBB:
printf("Bulk-Only");
break;
case PROTO_CBI: /* uses Comand/Bulk pipes */
case UMASS_PROTO_CBI: /* uses Comand/Bulk pipes */
printf("CBI");
break;
case PROTO_CBI_I: /* uses Comand/Bulk/Interrupt pipes */
case UMASS_PROTO_CBI_I: /* uses Comand/Bulk/Interrupt pipes */
printf("CBI with CCI");
#ifndef CBI_I
printf(" (using CBI)");
#endif
break;
default:
printf("(unknown 0x%02x)", sc->proto&PROTO_WIRE);
printf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_WIRE);
}
printf("; quirks = 0x%04x\n", sc->quirks);
#endif
#ifndef CBI_I
if (sc->proto & UMASS_PROTO_CBI_I) {
/* See beginning of file for comment on the use of CBI with CCI */
sc->proto = (sc->proto & ~UMASS_PROTO_CBI_I) | UMASS_PROTO_CBI;
}
#endif
printf("\n");
if (sc->drive == INSYSTEM_USBCABLE) {
if (sc->quirks & ALT_IFACE_1) {
err = usbd_set_interface(0, 1);
if (err) {
DPRINTF(UDMASS_USB, ("%s: could not switch to "
@ -870,7 +859,7 @@ USB_ATTACH(umass)
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
&& (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
sc->bulkout = ed->bEndpointAddress;
} else if (sc->proto & PROTO_CBI_I
} else if (sc->proto & UMASS_PROTO_CBI_I
&& UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
&& (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
sc->intrin = ed->bEndpointAddress;
@ -886,7 +875,7 @@ USB_ATTACH(umass)
/* check whether we found all the endpoints we need */
if (!sc->bulkin || !sc->bulkout
|| (sc->proto & PROTO_CBI_I && !sc->intrin) ) {
|| (sc->proto & UMASS_PROTO_CBI_I && !sc->intrin) ) {
DPRINTF(UDMASS_USB, ("%s: endpoint not found %d/%d/%d\n",
USBDEVNAME(sc->sc_dev),
sc->bulkin, sc->bulkout, sc->intrin));
@ -922,7 +911,7 @@ USB_ATTACH(umass)
* code for handling the data on that endpoint simpler. No data
* arriving concurently.
*/
if (sc->proto & PROTO_CBI_I) {
if (sc->proto & UMASS_PROTO_CBI_I) {
err = usbd_open_pipe(sc->iface, sc->intrin,
USBD_EXCLUSIVE_USE, &sc->intrin_pipe);
if (err) {
@ -948,11 +937,11 @@ USB_ATTACH(umass)
}
/* Initialise the wire protocol specific methods */
if (sc->proto & PROTO_BBB) {
if (sc->proto & UMASS_PROTO_BBB) {
sc->reset = umass_bbb_reset;
sc->transfer = umass_bbb_transfer;
sc->state = umass_bbb_state;
} else if ((sc->proto & PROTO_CBI) || (sc->proto & PROTO_CBI_I)) {
} else if (sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I)) {
sc->reset = umass_cbi_reset;
sc->transfer = umass_cbi_transfer;
sc->state = umass_cbi_state;
@ -963,36 +952,36 @@ USB_ATTACH(umass)
#endif
}
if (sc->proto & PROTO_SCSI)
if (sc->proto & UMASS_PROTO_SCSI)
sc->transform = umass_scsi_transform;
else if (sc->proto & PROTO_UFI)
else if (sc->proto & UMASS_PROTO_UFI)
sc->transform = umass_ufi_transform;
else if (sc->proto & PROTO_ATAPI)
else if (sc->proto & UMASS_PROTO_ATAPI)
sc->transform = umass_atapi_transform;
else if (sc->proto & PROTO_RBC)
else if (sc->proto & UMASS_PROTO_RBC)
sc->transform = umass_rbc_transform;
#ifdef UMASS_DEBUG
else
panic("No transformation defined for command proto 0x%02x\n",
sc->proto & PROTO_COMMAND);
sc->proto & UMASS_PROTO_COMMAND);
#endif
/* From here onwards the device can be used. */
if (sc->drive == SHUTTLE_EUSB)
if (sc->quirks & SHUTTLE_INIT)
umass_init_shuttle(sc);
/* Get the maximum LUN supported by the device.
*/
if ((sc->proto & PROTO_WIRE) == PROTO_BBB)
if ((sc->proto & UMASS_PROTO_WIRE) == UMASS_PROTO_BBB)
sc->maxlun = umass_bbb_get_max_lun(sc);
else
sc->maxlun = 0;
if ((sc->proto & PROTO_SCSI) ||
(sc->proto & PROTO_ATAPI) ||
(sc->proto & PROTO_UFI) ||
(sc->proto & PROTO_RBC)) {
if ((sc->proto & UMASS_PROTO_SCSI) ||
(sc->proto & UMASS_PROTO_ATAPI) ||
(sc->proto & UMASS_PROTO_UFI) ||
(sc->proto & UMASS_PROTO_RBC)) {
/* Prepare the SCSI command block */
sc->cam_scsi_sense.opcode = REQUEST_SENSE;
sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY;
@ -1033,10 +1022,10 @@ USB_DETACH(umass)
sc->flags |= UMASS_FLAGS_GONE;
if ((sc->proto & PROTO_SCSI) ||
(sc->proto & PROTO_ATAPI) ||
(sc->proto & PROTO_UFI) ||
(sc->proto & PROTO_RBC))
if ((sc->proto & UMASS_PROTO_SCSI) ||
(sc->proto & UMASS_PROTO_ATAPI) ||
(sc->proto & UMASS_PROTO_UFI) ||
(sc->proto & UMASS_PROTO_RBC))
/* detach the device from the SCSI host controller (SIM) */
err = umass_cam_detach(sc);
@ -1065,11 +1054,14 @@ umass_init_shuttle(struct umass_softc *sc)
* command does.
*/
req.bmRequestType = UT_READ_VENDOR_DEVICE;
req.bRequest = 1;
req.bRequest = 1; /* XXX unknown command */
USETW(req.wValue, 0);
USETW(req.wIndex, sc->ifaceno);
USETW(req.wLength, sizeof status);
(void) usbd_do_request(sc->sc_udev, &req, &status);
DPRINTF(UDMASS_GEN, ("%s: Shuttle init returned 0x%02x%02x\n",
USBDEVNAME(sc->sc_dev), status[0], status[1]));
}
/*
@ -1167,7 +1159,7 @@ umass_bbb_reset(struct umass_softc *sc, int status)
{
usbd_device_handle udev;
KASSERT(sc->proto & PROTO_BBB,
KASSERT(sc->proto & UMASS_PROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_reset\n", sc->proto));
/*
@ -1209,7 +1201,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
void *data, int datalen, int dir,
transfer_cb_f cb, void *priv)
{
KASSERT(sc->proto & PROTO_BBB,
KASSERT(sc->proto & UMASS_PROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_transfer\n",
sc->proto));
@ -1278,7 +1270,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
* We fill in all the fields, so there is no need to bzero it first.
*/
USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
/* We don't care what the initial value was, as long as the values are unique */
/* We don't care about the initial value, as long as the values are unique */
USETDW(sc->cbw.dCBWTag, UGETDW(sc->cbw.dCBWTag) + 1);
USETDW(sc->cbw.dCBWDataTransferLength, datalen);
/* DIR_NONE is treated as DIR_OUT (0x00) */
@ -1317,7 +1309,7 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
struct umass_softc *sc = (struct umass_softc *) priv;
usbd_xfer_handle next_xfer;
KASSERT(sc->proto & PROTO_BBB,
KASSERT(sc->proto & UMASS_PROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_state\n",sc->proto));
/*
@ -1533,12 +1525,13 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
USBDEVNAME(sc->sc_dev),
sc->transfer_actlen, sc->transfer_datalen);
} else if (sc->transfer_datalen - sc->transfer_actlen
!= UGETDW(sc->csw.dCSWDataResidue)) {
DPRINTF(UDMASS_BBB, ("%s: residue=%d != calc.res.=%d\n",
!= UGETDW(sc->csw.dCSWDataResidue)
&& !(sc->quirks & IGNORE_RESIDUE)) {
printf("%s: Residue incorrect, was %d, "
"should've been %d\n",
USBDEVNAME(sc->sc_dev),
UGETDW(sc->csw.dCSWDataResidue),
sc->transfer_datalen - sc->transfer_actlen));
sc->transfer_datalen-sc->transfer_actlen);
umass_bbb_reset(sc, STATUS_WIRE_FAILED);
return;
@ -1658,7 +1651,7 @@ umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen,
{
usbd_device_handle udev;
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_adsc\n",sc->proto));
usbd_interface2device_handle(sc->iface, &udev);
@ -1679,7 +1672,7 @@ umass_cbi_reset(struct umass_softc *sc, int status)
int i;
# define SEND_DIAGNOSTIC_CMDLEN 12
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_reset\n",sc->proto));
/*
@ -1726,7 +1719,7 @@ umass_cbi_transfer(struct umass_softc *sc, int lun,
void *cmd, int cmdlen, void *data, int datalen, int dir,
transfer_cb_f cb, void *priv)
{
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_transfer\n",
sc->proto));
@ -1779,7 +1772,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
{
struct umass_softc *sc = (struct umass_softc *) priv;
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_state\n", sc->proto));
/*
@ -1835,7 +1828,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
sc->transfer_xfer[XFER_CBI_DATA]))
umass_cbi_reset(sc, STATUS_WIRE_FAILED);
} else if (sc->proto & PROTO_CBI_I) {
} else if (sc->proto & UMASS_PROTO_CBI_I) {
DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
USBDEVNAME(sc->sc_dev)));
sc->transfer_state = TSTATE_CBI_STATUS;
@ -1883,7 +1876,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
umass_dump_buffer(sc, sc->transfer_data,
sc->transfer_actlen, 48));
if (sc->proto & PROTO_CBI_I) {
if (sc->proto & UMASS_PROTO_CBI_I) {
sc->transfer_state = TSTATE_CBI_STATUS;
if (umass_setup_transfer(sc, sc->intrin_pipe,
&sc->sbl, sizeof(sc->sbl),
@ -1922,7 +1915,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
/* Dissect the information in the buffer */
if (sc->proto & PROTO_UFI) {
if (sc->proto & UMASS_PROTO_UFI) {
int status;
/* Section 3.4.3.1.3 specifies that the UFI command
@ -2156,11 +2149,11 @@ umass_cam_attach(struct umass_softc *sc)
cam_sim_path(umass_sim), USBDEVUNIT(sc->sc_dev));
if (!cold) {
/* Notify CAM of the new device. Any failure is benign, as the
* user can still do it by hand (camcontrol rescan <busno>).
* Only do this if we are not booting, because CAM does a scan
* after booting has completed, when interrupts have been
* enabled.
/* Notify CAM of the new device after 1 second delay. Any
* failure is benign, as the user can still do it by hand
* (camcontrol rescan <busno>). Only do this if we are not
* booting, because CAM does a scan after booting has
* completed, when interrupts have been enabled.
*/
/* XXX This will bomb if the driver is unloaded between attach
@ -2179,9 +2172,6 @@ umass_cam_attach(struct umass_softc *sc)
Static int
umass_cam_detach_sim()
{
if (umass_sim)
return(EBUSY); /* XXX CAM can't handle disappearing SIMs yet */
if (umass_sim) {
if (xpt_bus_deregister(cam_sim_path(umass_sim)))
cam_sim_free(umass_sim, /*free_devq*/TRUE);
@ -2323,7 +2313,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc->transfer_state != TSTATE_IDLE) {
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
"I/O requested while busy (state %d, %s)\n",
"I/O in progress, deferring (state %d, %s)\n",
USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
sc->transfer_state,states[sc->transfer_state]));
@ -2391,18 +2381,24 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
cpi->hba_misc = 0;
cpi->hba_eng_cnt = 0;
cpi->max_target = UMASS_SCSIID_MAX; /* one target */
if (sc == NULL)
cpi->max_lun = 0;
else
cpi->max_lun = sc->maxlun;
cpi->initiator_id = UMASS_SCSIID_HOST;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "USB SCSI", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
cpi->unit_number = cam_sim_unit(sim);
cpi->bus_id = UMASS_SCSI_BUS;
if (sc)
cpi->base_transfer_speed = sc->transfer_speed;
if (sc == NULL) {
cpi->base_transfer_speed = 0;
cpi->max_lun = 0;
} else {
if (sc->quirks & FLOPPY_SPEED) {
cpi->base_transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
} else {
cpi->base_transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED;
}
cpi->max_lun = sc->maxlun;
}
cpi->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
@ -2445,35 +2441,16 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
}
case XPT_CALC_GEOMETRY:
{
#ifdef UMASS_DEBUG
struct ccb_calc_geometry *ccg = &ccb->ccg;
#endif
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_CALC_GEOMETRY: "
"Volume size = %d\n",
"Volume size = %d (unimplemented)\n",
USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccg->volume_size));
/* XXX We should probably ask the drive for the details
* instead of cluching them up ourselves
*/
if (sc->drive == ZIP_100) {
ccg->heads = 64;
ccg->secs_per_track = 32;
ccg->cylinders = ccg->volume_size / ccg->heads
/ ccg->secs_per_track;
ccb->ccb_h.status = CAM_REQ_CMP;
break;
} else if (sc->proto & PROTO_UFI) {
ccg->heads = 2;
if (ccg->volume_size == 2880)
ccg->secs_per_track = 18;
else
ccg->secs_per_track = 9;
ccg->cylinders = 80;
break;
} else {
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
}
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
xpt_done(ccb);
break;
@ -2608,9 +2585,9 @@ umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
switch (status) {
case STATUS_CMD_OK:
case STATUS_CMD_UNKNOWN:
/* Getting sense data succeeded. The length of the sense data
* is not returned in any way. The sense data itself contains
* the length of the sense data that is valid.
case STATUS_CMD_FAILED:
/* Getting sense data always succeeds (apart from wire
* failures).
*/
if (sc->quirks & RS_NO_CLEAR_UA
&& csio->cdb_io.cdb_bytes[0] == INQUIRY
@ -2632,11 +2609,13 @@ umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
(csio->cdb_io.cdb_bytes[0] == READ_CAPACITY) &&
((csio->sense_data.flags & SSD_KEY)
== SSD_KEY_UNIT_ATTENTION)) {
/* Ignore unit attention errors in the case where
* the Unit Attention state is not cleared on
* REQUEST SENSE. They will appear again at the next
* command.
*/
/* Some devices do not clear the unit attention error
* on request sense. We insert a test unit ready
* command to make sure we clear the unit attention
* condition.
*/
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
| CAM_AUTOSNS_VALID;
csio->scsi_status = SCSI_STATUS_CHECK_COND;
@ -2867,8 +2846,13 @@ umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
*rcmdlen = UFI_COMMAND_LENGTH;
memset(*rcmd, 0, UFI_COMMAND_LENGTH);
/* Convert 6 byte commands that have a 10 byte version as well to the
* longer one. Many devices do not understand the 6 byte ones and
* wedge, mainly the drives that use the ATAPI & UFI command sets.
*/
if (umass_scsi_6_to_10(cmd, cmdlen, rcmd, rcmdlen))
return (1);
switch (cmd[0]) {
/* Commands of which the format has been verified. They should work.
* Copy the command into the (zeroed out) destination buffer.