aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/amr
diff options
context:
space:
mode:
authorScott Long <scottl@FreeBSD.org>2007-11-28 19:40:17 +0000
committerScott Long <scottl@FreeBSD.org>2007-11-28 19:40:17 +0000
commit0a5c91d058deecbbfa3f7a3ed9edc984088543c6 (patch)
tree3056ff76ccca86fa7c23913e6f26714d2371d5e2 /sys/dev/amr
parentfd4ae6dcff67c75224390d138c5a610d99cb7083 (diff)
downloadsrc-0a5c91d058deecbbfa3f7a3ed9edc984088543c6.tar.gz
src-0a5c91d058deecbbfa3f7a3ed9edc984088543c6.zip
Turn the CAM passthroug interface to AMR back ON. Adjust the
T_DIRECT filtering so that disk drives can be attached via the pass driver. Add CAM locking. Don't mark CAM commands as SG64 since the hardware isn't designed to deal with 64-bit passthru commands. Hopefully the bounce buffer changes that were done for the management/ioctl interface are robust enough to handle this deficiency for CAM as well.
Notes
Notes: svn path=/head/; revision=174030
Diffstat (limited to 'sys/dev/amr')
-rw-r--r--sys/dev/amr/amr.c2
-rw-r--r--sys/dev/amr/amr_cam.c146
2 files changed, 68 insertions, 80 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index 3681bae53a36..4c342d8e4a4c 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -92,7 +92,7 @@ __FBSDID("$FreeBSD$");
* The CAM interface appears to be completely broken. Disable it.
*/
#ifndef AMR_ENABLE_CAM
-#define AMR_ENABLE_CAM 0
+#define AMR_ENABLE_CAM 1
#endif
SYSCTL_NODE(_hw, OID_AUTO, amr, CTLFLAG_RD, 0, "AMR driver parameters");
diff --git a/sys/dev/amr/amr_cam.c b/sys/dev/amr/amr_cam.c
index 56b486fcec76..da57595d3740 100644
--- a/sys/dev/amr/amr_cam.c
+++ b/sys/dev/amr/amr_cam.c
@@ -122,7 +122,7 @@ int
amr_cam_attach(struct amr_softc *sc)
{
struct cam_devq *devq;
- int chn;
+ int chn, error;
/* initialise the ccb queue */
TAILQ_INIT(&sc->amr_cam_ccbq);
@@ -148,7 +148,7 @@ amr_cam_attach(struct amr_softc *sc)
"amr",
sc,
device_get_unit(sc->amr_dev),
- &Giant,
+ &sc->amr_list_lock,
1,
AMR_MAX_SCSI_CMDS,
devq)) == NULL) {
@@ -158,7 +158,10 @@ amr_cam_attach(struct amr_softc *sc)
}
/* register the bus ID so we can get it later */
- if (xpt_bus_register(sc->amr_cam_sim[chn], sc->amr_dev, chn)) {
+ mtx_lock(&sc->amr_list_lock);
+ error = xpt_bus_register(sc->amr_cam_sim[chn], sc->amr_dev, chn);
+ mtx_unlock(&sc->amr_list_lock);
+ if (error) {
device_printf(sc->amr_dev, "CAM XPT bus registration failed\n");
return(ENXIO);
}
@@ -178,6 +181,7 @@ amr_cam_detach(struct amr_softc *sc)
{
int chn;
+ mtx_lock(&sc->amr_list_lock);
for (chn = 0; chn < sc->amr_maxchan; chn++) {
/*
@@ -188,6 +192,7 @@ amr_cam_detach(struct amr_softc *sc)
cam_sim_free(sc->amr_cam_sim[chn], FALSE);
}
}
+ mtx_unlock(&sc->amr_list_lock);
/* Now free the devq */
if (sc->amr_cam_devq != NULL)
@@ -254,10 +259,8 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb)
/* save the channel number in the ccb */
csio->ccb_h.sim_priv.entries[0].field = cam_sim_bus(sim);
- mtx_lock(&sc->amr_list_lock);
amr_enqueue_ccb(sc, ccb);
amr_startio(sc);
- mtx_unlock(&sc->amr_list_lock);
return;
}
break;
@@ -281,7 +284,7 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb)
cpi->version_num = 1; /* XXX??? */
cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
cpi->target_sprt = 0;
- cpi->hba_misc = PIM_NOBUSRESET;
+ cpi->hba_misc = PIM_NOBUSRESET|PIM_SEQSCAN;
cpi->hba_eng_cnt = 0;
cpi->max_target = AMR_MAX_TARGETS;
cpi->max_lun = 0 /* AMR_MAX_LUNS*/;
@@ -364,6 +367,7 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.status = CAM_REQ_INVALID;
break;
}
+ mtx_assert(&sc->amr_list_lock, MA_OWNED);
xpt_done(ccb);
}
@@ -467,17 +471,11 @@ amr_cam_command(struct amr_softc *sc, struct amr_command **acp)
ac->ac_length = sizeof(*aep);
ac->ac_complete = amr_cam_complete_extcdb;
ac->ac_mailbox.mb_command = AMR_CMD_EXTPASS;
- if (AMR_IS_SG64(sc))
- ac->ac_flags |= AMR_CMD_SG64;
} else {
ac->ac_data = ap;
ac->ac_length = sizeof(*ap);
ac->ac_complete = amr_cam_complete;
- if (AMR_IS_SG64(sc)) {
- ac->ac_mailbox.mb_command = AMR_CMD_PASS_64;
- ac->ac_flags |= AMR_CMD_SG64;
- } else
- ac->ac_mailbox.mb_command = AMR_CMD_PASS;
+ ac->ac_mailbox.mb_command = AMR_CMD_PASS;
}
out:
@@ -526,44 +524,37 @@ amr_cam_complete(struct amr_command *ac)
* could add handling for that to allow disks to be selectively visible.
*/
- if ((ap->ap_cdb[0] == INQUIRY) && (SID_TYPE(inq) == T_DIRECT)) {
- bzero(csio->data_ptr, csio->dxfer_len);
- if (ap->ap_scsi_status == 0xf0) {
- csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
- } else {
- csio->ccb_h.status = CAM_DEV_NOT_THERE;
- }
- } else {
+ /* handle passthrough SCSI status */
+ switch(ap->ap_scsi_status) {
+ case 0: /* completed OK */
+ if ((ap->ap_cdb[0] == INQUIRY) && (SID_TYPE(inq) == T_DIRECT))
+ inq->device = (inq->device & 0xe0) | T_NODEVICE;
+ csio->ccb_h.status = CAM_REQ_CMP;
+ break;
- /* handle passthrough SCSI status */
- switch(ap->ap_scsi_status) {
- case 0: /* completed OK */
- csio->ccb_h.status = CAM_REQ_CMP;
- break;
-
- case 0x02:
- csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
- csio->scsi_status = SCSI_STATUS_CHECK_COND;
- bcopy(ap->ap_request_sense_area, &csio->sense_data, AMR_MAX_REQ_SENSE_LEN);
- csio->sense_len = AMR_MAX_REQ_SENSE_LEN;
- csio->ccb_h.status |= CAM_AUTOSNS_VALID;
- break;
-
- case 0x08:
- csio->ccb_h.status = CAM_SCSI_BUSY;
- break;
-
- case 0xf0:
- case 0xf4:
- default:
- csio->ccb_h.status = CAM_REQ_CMP_ERR;
- break;
- }
+ case 0x02:
+ csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+ csio->scsi_status = SCSI_STATUS_CHECK_COND;
+ bcopy(ap->ap_request_sense_area, &csio->sense_data, AMR_MAX_REQ_SENSE_LEN);
+ csio->sense_len = AMR_MAX_REQ_SENSE_LEN;
+ csio->ccb_h.status |= CAM_AUTOSNS_VALID;
+ break;
+
+ case 0x08:
+ csio->ccb_h.status = CAM_SCSI_BUSY;
+ break;
+
+ case 0xf0:
+ case 0xf4:
+ default:
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ break;
}
free(ap, M_DEVBUF);
if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr, " ");
xpt_done((union ccb *)csio);
+ mtx_assert(&ac->ac_sc->amr_list_lock, MA_OWNED);
amr_releasecmd(ac);
}
@@ -578,9 +569,11 @@ amr_cam_complete_extcdb(struct amr_command *ac)
struct ccb_scsiio *csio = (struct ccb_scsiio *)ac->ac_private;
struct scsi_inquiry_data *inq = (struct scsi_inquiry_data *)csio->data_ptr;
- /* XXX note that we're ignoring ac->ac_status - good idea? */
-
debug(1, "status 0x%x AEP scsi_status 0x%x", ac->ac_status, aep->ap_scsi_status);
+ if (ac->ac_status != AMR_STATUS_SUCCESS) {
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ goto out;
+ }
/*
* Hide disks from CAM so that they're not picked up and treated as 'normal' disks.
@@ -589,43 +582,38 @@ amr_cam_complete_extcdb(struct amr_command *ac)
* could add handling for that to allow disks to be selectively visible.
*/
- if ((aep->ap_cdb[0] == INQUIRY) && (SID_TYPE(inq) == T_DIRECT)) {
- bzero(csio->data_ptr, csio->dxfer_len);
- if (aep->ap_scsi_status == 0xf0) {
- csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
- } else {
- csio->ccb_h.status = CAM_DEV_NOT_THERE;
- }
- } else {
+ /* handle passthrough SCSI status */
+ switch(aep->ap_scsi_status) {
+ case 0: /* completed OK */
+ if ((aep->ap_cdb[0] == INQUIRY) && (SID_TYPE(inq) == T_DIRECT))
+ inq->device = (inq->device & 0xe0) | T_NODEVICE;
+ csio->ccb_h.status = CAM_REQ_CMP;
+ break;
- /* handle passthrough SCSI status */
- switch(aep->ap_scsi_status) {
- case 0: /* completed OK */
- csio->ccb_h.status = CAM_REQ_CMP;
- break;
-
- case 0x02:
- csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
- csio->scsi_status = SCSI_STATUS_CHECK_COND;
- bcopy(aep->ap_request_sense_area, &csio->sense_data, AMR_MAX_REQ_SENSE_LEN);
- csio->sense_len = AMR_MAX_REQ_SENSE_LEN;
- csio->ccb_h.status |= CAM_AUTOSNS_VALID;
- break;
-
- case 0x08:
- csio->ccb_h.status = CAM_SCSI_BUSY;
- break;
-
- case 0xf0:
- case 0xf4:
- default:
- csio->ccb_h.status = CAM_REQ_CMP_ERR;
- break;
- }
+ case 0x02:
+ csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+ csio->scsi_status = SCSI_STATUS_CHECK_COND;
+ bcopy(aep->ap_request_sense_area, &csio->sense_data, AMR_MAX_REQ_SENSE_LEN);
+ csio->sense_len = AMR_MAX_REQ_SENSE_LEN;
+ csio->ccb_h.status |= CAM_AUTOSNS_VALID;
+ break;
+
+ case 0x08:
+ csio->ccb_h.status = CAM_SCSI_BUSY;
+ break;
+
+ case 0xf0:
+ case 0xf4:
+ default:
+ csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ break;
}
+
+out:
free(aep, M_DEVBUF);
if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr, " ");
xpt_done((union ccb *)csio);
+ mtx_assert(&ac->ac_sc->amr_list_lock, MA_OWNED);
amr_releasecmd(ac);
}