summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorticso <ticso@FreeBSD.org>2003-04-14 14:28:17 +0000
committerticso <ticso@FreeBSD.org>2003-04-14 14:28:17 +0000
commit57c77ee3ed080d13311e8f98ed653bf45cafea82 (patch)
tree29fcdfcab955e57e0d9f97d0e00bf79eb7da7cdc /sys
parent1cfbbefd6c0c68b66ef5099fb1967e94e5542fd9 (diff)
downloadFreeBSD-src-57c77ee3ed080d13311e8f98ed653bf45cafea82.zip
FreeBSD-src-57c77ee3ed080d13311e8f98ed653bf45cafea82.tar.gz
Use a sim for each device on it's own instead of one for all umass
devices. This reduces complexity and fixes a number of small problems. Approved by: gallatin (mentor) Reviewed by: njl
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/umass.c207
1 files changed, 62 insertions, 145 deletions
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c
index 9decb8c..59e6225 100644
--- a/sys/dev/usb/umass.c
+++ b/sys/dev/usb/umass.c
@@ -162,28 +162,10 @@ SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW,
/* CAM specific definitions */
-/* We only have one bus */
-#define UMASS_SCSI_BUS 0
-
-/* All USB drives are 'connected' to one SIM (SCSI controller). umass3
- * 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, so umass0 corresponds to SCSI target 0.
- */
-#ifndef USB_DEBUG
-#define UMASS_SCSIID_MAX 32 /* maximum number of drives expected */
-#else
-/* while debugging avoid unnecessary clutter in the output at umass_cam_rescan
- * (XPT_PATH_INQ)
- */
-#define UMASS_SCSIID_MAX 3 /* maximum number of drives expected */
-#endif
+#define UMASS_SCSIID_MAX 1 /* maximum number of drives expected */
#define UMASS_SCSIID_HOST UMASS_SCSIID_MAX
-#define UMASS_SIM_UNIT 0 /* we use one sim for all drives */
-
-#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
+#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
/* Bulk-Only features */
@@ -406,6 +388,8 @@ struct umass_softc {
USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_udev; /* USB device */
+ struct cam_sim *umass_sim; /* SCSI Interface Module */
+
unsigned char flags; /* various device flags */
# define UMASS_FLAGS_GONE 0x01 /* devices is no more */
@@ -545,7 +529,6 @@ char *states[TSTATE_STATES+1] = {
};
#endif
-Static struct cam_sim *umass_sim; /* SCSI Interface Module */
/* If device cannot return valid inquiry data, fake it */
Static uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = {
0, /*removable*/ 0x80, SCSI_REV_2, SCSI_REV_2,
@@ -616,10 +599,9 @@ Static void umass_cam_rescan_callback
(struct cam_periph *periph,union ccb *ccb);
Static void umass_cam_rescan (void *addr);
-Static int umass_cam_attach_sim (void);
+Static int umass_cam_attach_sim (struct umass_softc *sc);
Static int umass_cam_attach (struct umass_softc *sc);
-Static int umass_cam_detach_sim (void);
-Static int umass_cam_detach (struct umass_softc *sc);
+Static int umass_cam_detach_sim (struct umass_softc *sc);
/* SCSI specific functions */
@@ -1030,18 +1012,16 @@ USB_ATTACH(umass)
sc->cam_scsi_sense.opcode = REQUEST_SENSE;
sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY;
- /* If this is the first device register the SIM */
- if (umass_sim == NULL) {
- err = umass_cam_attach_sim();
- if (err) {
- umass_detach(self);
- USB_ATTACH_ERROR_RETURN;
- }
+ /* register the SIM */
+ err = umass_cam_attach_sim(sc);
+ if (err) {
+ umass_detach(self);
+ USB_ATTACH_ERROR_RETURN;
}
-
- /* Attach the new device to our SCSI host controller (SIM) */
+ /* scan the new sim */
err = umass_cam_attach(sc);
if (err) {
+ umass_cam_detach_sim(sc);
umass_detach(self);
USB_ATTACH_ERROR_RETURN;
}
@@ -1070,8 +1050,8 @@ USB_DETACH(umass)
(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);
+ /* detach the SCSI host controller (SIM) */
+ err = umass_cam_detach_sim(sc);
for (i = 0; i < XFER_NR; i++)
if (sc->transfer_xfer[i])
@@ -1526,6 +1506,12 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1)
USETDW(sc->csw.dCSWSignature, CSWSIGNATURE);
+ int Residue;
+ Residue = UGETDW(sc->csw.dCSWDataResidue);
+ if (Residue == 0 &&
+ sc->transfer_datalen - sc->transfer_actlen != 0)
+ Residue = sc->transfer_datalen - sc->transfer_actlen;
+
/* Check CSW and handle any error */
if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) {
/* Invalid CSW: Wrong signature or wrong tag might
@@ -1559,8 +1545,7 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
return;
} else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) {
printf("%s: Phase Error, residue = %d\n",
- USBDEVNAME(sc->sc_dev),
- UGETDW(sc->csw.dCSWDataResidue));
+ USBDEVNAME(sc->sc_dev), Residue);
umass_bbb_reset(sc, STATUS_WIRE_FAILED);
return;
@@ -1570,34 +1555,20 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
panic("%s: transferred %db instead of %db\n",
USBDEVNAME(sc->sc_dev),
sc->transfer_actlen, sc->transfer_datalen);
- } else if (sc->transfer_datalen - sc->transfer_actlen
- != 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);
- umass_bbb_reset(sc, STATUS_WIRE_FAILED);
- return;
} else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) {
DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n",
- USBDEVNAME(sc->sc_dev),
- UGETDW(sc->csw.dCSWDataResidue)));
+ USBDEVNAME(sc->sc_dev), Residue));
/* SCSI command failed but transfer was succesful */
sc->transfer_state = TSTATE_IDLE;
- sc->transfer_cb(sc, sc->transfer_priv,
- UGETDW(sc->csw.dCSWDataResidue),
+ sc->transfer_cb(sc, sc->transfer_priv, Residue,
STATUS_CMD_FAILED);
-
return;
} else { /* success */
sc->transfer_state = TSTATE_IDLE;
- sc->transfer_cb(sc, sc->transfer_priv,
- UGETDW(sc->csw.dCSWDataResidue),
+ sc->transfer_cb(sc, sc->transfer_priv, Residue,
STATUS_CMD_OK);
return;
@@ -2090,7 +2061,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
*/
Static int
-umass_cam_attach_sim()
+umass_cam_attach_sim(struct umass_softc *sc)
{
struct cam_devq *devq; /* Per device Queue */
@@ -2104,17 +2075,20 @@ umass_cam_attach_sim()
if (devq == NULL)
return(ENOMEM);
- umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll, DEVNAME_SIM,
- NULL /*priv*/, UMASS_SIM_UNIT /*unit number*/,
+ sc->umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll,
+ DEVNAME_SIM,
+ sc /*priv*/,
+ USBDEVUNIT(sc->sc_dev) /*unit number*/,
1 /*maximum device openings*/,
0 /*maximum tagged device openings*/,
devq);
- if (umass_sim == NULL) {
+ if (sc->umass_sim == NULL) {
cam_simq_free(devq);
return(ENOMEM);
}
- if(xpt_bus_register(umass_sim, UMASS_SCSI_BUS) != CAM_SUCCESS)
+ if(xpt_bus_register(sc->umass_sim, USBDEVUNIT(sc->sc_dev)) !=
+ CAM_SUCCESS)
return(ENOMEM);
return(0);
@@ -2125,12 +2099,12 @@ umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
{
#ifdef USB_DEBUG
if (ccb->ccb_h.status != CAM_REQ_CMP) {
- DPRINTF(UDMASS_SCSI, ("scbus%d: Rescan failed, 0x%04x\n",
- cam_sim_path(umass_sim),
+ DPRINTF(UDMASS_SCSI, ("%s:%d Rescan failed, 0x%04x\n",
+ periph->periph_name, periph->unit_number,
ccb->ccb_h.status));
} else {
- DPRINTF(UDMASS_SCSI, ("scbus%d: Rescan succeeded\n",
- cam_sim_path(umass_sim)));
+ DPRINTF(UDMASS_SCSI, ("%s%d: Rescan succeeded\n",
+ periph->periph_name, periph->unit_number));
}
#endif
@@ -2141,24 +2115,18 @@ umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
Static void
umass_cam_rescan(void *addr)
{
- /* Note: The sc is only passed in for debugging prints. If the device
- * is disconnected before umass_cam_rescan has been able to run the
- * driver might bomb.
- */
-#ifdef USB_DEBUG
struct umass_softc *sc = (struct umass_softc *) addr;
-#endif
struct cam_path *path;
union ccb *ccb = malloc(sizeof(union ccb), M_USBDEV, M_WAITOK);
memset(ccb, 0, sizeof(union ccb));
DPRINTF(UDMASS_SCSI, ("scbus%d: scanning for %s:%d:%d:%d\n",
- cam_sim_path(umass_sim),
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ cam_sim_path(sc->umass_sim),
+ USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD));
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(umass_sim),
+ if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->umass_sim),
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)
!= CAM_REQ_CMP)
return;
@@ -2175,27 +2143,13 @@ umass_cam_rescan(void *addr)
Static int
umass_cam_attach(struct umass_softc *sc)
{
- /* SIM already attached at module load. The device is a target on the
- * one SIM we registered: target device_get_unit(self).
- */
-
- /* The artificial limit UMASS_SCSIID_MAX is there because CAM expects
- * a limit to the number of targets that are present on a SIM.
- */
- if (device_get_unit(sc->sc_dev) >= UMASS_SCSIID_MAX) {
- printf("scbus%d: Increase UMASS_SCSIID_MAX (currently %d) in %s"
- " and try again.\n",
- cam_sim_path(umass_sim), UMASS_SCSIID_MAX, __FILE__);
- return(1);
- }
-
#ifndef USB_DEBUG
if (bootverbose)
#endif
- printf("%s:%d:%d:%d: Attached to scbus%d as device %d\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
- USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD,
- cam_sim_path(umass_sim), USBDEVUNIT(sc->sc_dev));
+ printf("%s:%d:%d:%d: Attached to scbus%d\n",
+ USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
+ USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD,
+ cam_sim_path(sc->umass_sim));
if (!cold) {
/* Notify CAM of the new device after 1 second delay. Any
@@ -2219,45 +2173,20 @@ umass_cam_attach(struct umass_softc *sc)
*/
Static int
-umass_cam_detach_sim()
+umass_cam_detach_sim(struct umass_softc *sc)
{
- if (umass_sim) {
- if (xpt_bus_deregister(cam_sim_path(umass_sim)))
- cam_sim_free(umass_sim, /*free_devq*/TRUE);
+ if (sc->umass_sim) {
+ if (xpt_bus_deregister(cam_sim_path(sc->umass_sim)))
+ cam_sim_free(sc->umass_sim, /*free_devq*/TRUE);
else
return(EBUSY);
- umass_sim = NULL;
+ sc->umass_sim = NULL;
}
return(0);
}
-Static int
-umass_cam_detach(struct umass_softc *sc)
-{
- struct cam_path *path;
-
- if (umass_sim) {
- /* detach of sim not done until module unload */
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: losing CAM device entry\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
- USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD));
-
- if (xpt_create_path(&path, NULL, cam_sim_path(umass_sim),
- USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD)
- != CAM_REQ_CMP)
- return(ENOMEM);
-
- xpt_async(AC_LOST_DEVICE, path, NULL);
- xpt_free_path(path);
- }
-
- return(0);
-}
-
-
-
/* umass_cam_action
* CAM requests for action come through here
*/
@@ -2265,8 +2194,7 @@ umass_cam_detach(struct umass_softc *sc)
Static void
umass_cam_action(struct cam_sim *sim, union ccb *ccb)
{
- struct umass_softc *sc = devclass_get_softc(umass_devclass,
- ccb->ccb_h.target_id);
+ struct umass_softc *sc = (struct umass_softc *)sim->softc;
/* The softc is still there, but marked as going away. umass_cam_detach
* has not yet notified CAM of the lost device however.
@@ -2274,7 +2202,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc && (sc->flags & UMASS_FLAGS_GONE)) {
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
"Invalid target (gone)\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.func_code));
ccb->ccb_h.status = CAM_TID_INVALID;
@@ -2299,7 +2227,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc == NULL) {
printf("%s:%d:%d:%d:func_code 0x%04x: "
"Invalid target (target needed)\n",
- DEVNAME_SIM, cam_sim_path(umass_sim),
+ DEVNAME_SIM, cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.func_code);
@@ -2317,7 +2245,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
"Invalid target (no wildcard)\n",
- DEVNAME_SIM, cam_sim_path(umass_sim),
+ DEVNAME_SIM, cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.func_code));
@@ -2345,7 +2273,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
"cmd: 0x%02x, flags: 0x%02x, "
"%db cmd/%db data/%db sense\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
csio->cdb_io.cdb_bytes[0],
ccb->ccb_h.flags & CAM_DIR_MASK,
@@ -2363,7 +2291,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 in progress, deferring (state %d, %s)\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
sc->transfer_state,states[sc->transfer_state]));
ccb->ccb_h.status = CAM_SCSI_BUSY;
@@ -2455,7 +2383,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_PATH_INQ:.\n",
(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- cam_sim_path(umass_sim),
+ cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
/* host specific information */
@@ -2470,7 +2398,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
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;
+ cpi->bus_id = USBDEVUNIT(sc->sc_dev);
if (sc == NULL) {
cpi->base_transfer_speed = 0;
@@ -2491,7 +2419,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
case XPT_RESET_DEV:
{
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_RESET_DEV:.\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
ccb->ccb_h.status = CAM_REQ_INPROG;
@@ -2503,7 +2431,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts = &ccb->cts;
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_GET_TRAN_SETTINGS:.\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
cts->valid = 0;
@@ -2516,7 +2444,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
case XPT_SET_TRAN_SETTINGS:
{
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SET_TRAN_SETTINGS:.\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
@@ -2551,7 +2479,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
{
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_NOOP:.\n",
(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- cam_sim_path(umass_sim),
+ cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
ccb->ccb_h.status = CAM_REQ_CMP;
@@ -2562,7 +2490,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
"Not implemented\n",
(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- cam_sim_path(umass_sim),
+ cam_sim_path(sc->umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.func_code));
@@ -2782,20 +2710,9 @@ umass_cam_quirk_cb(struct umass_softc *sc, void *priv, int residue, int status)
Static int
umass_driver_load(module_t mod, int what, void *arg)
{
- int err;
-
switch (what) {
case MOD_UNLOAD:
- err = umass_cam_detach_sim();
- if (err)
- return(err);
- return(usbd_driver_load(mod, what, arg));
case MOD_LOAD:
- /* We don't attach to CAM at this point, because it will try
- * and malloc memory for it. This is not possible when the
- * boot loader loads umass as a module before the kernel
- * has been bootstrapped.
- */
default:
return(usbd_driver_load(mod, what, arg));
}
OpenPOWER on IntegriCloud