summaryrefslogtreecommitdiff
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)
Notes
Diffstat (limited to 'sys/dev/amr')
-rw-r--r--sys/dev/amr/amr.c2
-rw-r--r--sys/dev/amr/amr_cam.c138
2 files changed, 64 insertions, 76 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 */
- csio->ccb_h.status = CAM_REQ_CMP;
- break;
+ /* 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;
- 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 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 0x08:
+ csio->ccb_h.status = CAM_SCSI_BUSY;
+ break;
- case 0xf0:
- case 0xf4:
- default:
- csio->ccb_h.status = CAM_REQ_CMP_ERR;
- 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 */
- csio->ccb_h.status = CAM_REQ_CMP;
- break;
+ /* 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;
- 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 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 0x08:
+ csio->ccb_h.status = CAM_SCSI_BUSY;
+ break;
- case 0xf0:
- case 0xf4:
- default:
- csio->ccb_h.status = CAM_REQ_CMP_ERR;
- 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);
}