diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c index 9decb8c1d134..59e622570dd8 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)); }