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
This commit is contained in:
Bernd Walter 2003-04-14 14:28:17 +00:00
parent 050871cc4f
commit 65193b3e5d

View File

@ -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));
}