summaryrefslogtreecommitdiff
path: root/sys/dev/isp/isp_target.c
diff options
context:
space:
mode:
authorMatt Jacob <mjacob@FreeBSD.org>2001-07-04 19:14:22 +0000
committerMatt Jacob <mjacob@FreeBSD.org>2001-07-04 19:14:22 +0000
commit011b768701e47a206d7645f32606be8811fd8bd3 (patch)
tree3cf7efb7c4f62bf30a8fbfa90e0bac092cbf9f34 /sys/dev/isp/isp_target.c
parent63ab2cfb65e18033ff845319d8574e362f707ad5 (diff)
Notes
Diffstat (limited to 'sys/dev/isp/isp_target.c')
-rw-r--r--sys/dev/isp/isp_target.c236
1 files changed, 86 insertions, 150 deletions
diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c
index 51b78fb8fd72..86ab25b36347 100644
--- a/sys/dev/isp/isp_target.c
+++ b/sys/dev/isp/isp_target.c
@@ -46,14 +46,14 @@
#endif
#ifdef ISP_TARGET_MODE
-static char *atiocope =
+static const char atiocope[] =
"ATIO returned for lun %d because it was in the middle of Bus Device Reset";
-static char *atior =
+static const char atior[] =
"ATIO returned for lun %d from initiator %d because a Bus Reset occurred";
-static void isp_got_msg __P((struct ispsoftc *, int, in_entry_t *));
-static void isp_got_msg_fc __P((struct ispsoftc *, int, in_fcentry_t *));
-static void isp_notify_ack __P((struct ispsoftc *, void *));
+static void isp_got_msg(struct ispsoftc *, int, in_entry_t *);
+static void isp_got_msg_fc(struct ispsoftc *, int, in_fcentry_t *);
+static void isp_notify_ack(struct ispsoftc *, void *);
static void isp_handle_atio(struct ispsoftc *, at_entry_t *);
static void isp_handle_atio2(struct ispsoftc *, at2_entry_t *);
static void isp_handle_ctio(struct ispsoftc *, ct_entry_t *);
@@ -106,10 +106,7 @@ static void isp_handle_ctio2(struct ispsoftc *, ct2_entry_t *);
*/
int
-isp_target_notify(isp, vptr, optrp)
- struct ispsoftc *isp;
- void *vptr;
- u_int16_t *optrp;
+isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp)
{
u_int16_t status, seqid;
union {
@@ -268,13 +265,8 @@ isp_target_notify(isp, vptr, optrp)
* response entry. The caller is responsible for synchronizing this.
*/
int
-isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque)
- struct ispsoftc *isp;
- int cmd;
- int bus;
- int tgt;
- int lun;
- u_int32_t opaque;
+isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun,
+ int cmd_cnt, int inot_cnt, u_int32_t opaque)
{
lun_entry_t el;
u_int16_t iptr, optr;
@@ -285,8 +277,8 @@ isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque)
if (IS_DUALBUS(isp)) {
el.le_rsvd = (bus & 0x1) << 7;
}
- el.le_cmd_count = DFLT_CMD_CNT;
- el.le_in_count = DFLT_INOTIFY;
+ el.le_cmd_count = cmd_cnt;
+ el.le_in_count = inot_cnt;
if (cmd == RQSTYPE_ENABLE_LUN) {
if (IS_SCSI(isp)) {
el.le_flags = LUN_TQAE|LUN_DISAD;
@@ -312,6 +304,7 @@ isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque)
} else if (isp->isp_maxluns <= 16) {
el.le_lun = lun;
}
+ el.le_timeout = 2;
if (isp_getrqentry(isp, &iptr, &optr, &outp)) {
isp_prt(isp, ISP_LOGWARN,
@@ -326,9 +319,7 @@ isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque)
int
-isp_target_put_entry(isp, ap)
- struct ispsoftc *isp;
- void *ap;
+isp_target_put_entry(struct ispsoftc *isp, void *ap)
{
void *outp;
u_int16_t iptr, optr;
@@ -365,13 +356,7 @@ isp_target_put_entry(isp, ap)
}
int
-isp_target_put_atio(isp, iid, tgt, lun, ttype, tval)
- struct ispsoftc *isp;
- int iid;
- int tgt;
- int lun;
- int ttype;
- int tval;
+isp_target_put_atio(struct ispsoftc *isp, void *arg)
{
union {
at_entry_t _atio;
@@ -380,23 +365,27 @@ isp_target_put_atio(isp, iid, tgt, lun, ttype, tval)
MEMZERO(&atun, sizeof atun);
if (IS_FC(isp)) {
+ at2_entry_t *aep = arg;
atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
atun._atio2.at_header.rqs_entry_count = 1;
if (isp->isp_maxluns > 16) {
- atun._atio2.at_scclun = (u_int16_t) lun;
+ atun._atio2.at_scclun = (u_int16_t) aep->at_scclun;
} else {
- atun._atio2.at_lun = (u_int8_t) lun;
+ atun._atio2.at_lun = (u_int8_t) aep->at_scclun;
}
atun._atio2.at_status = CT_OK;
} else {
+ at_entry_t *aep = arg;
atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO;
atun._atio.at_header.rqs_entry_count = 1;
- atun._atio.at_iid = iid;
- atun._atio.at_tgt = tgt;
- atun._atio.at_lun = lun;
- atun._atio.at_tag_type = ttype;
- atun._atio.at_tag_val = tval;
- atun._atio.at_status = CT_OK;
+ atun._atio.at_handle = aep->at_handle;
+ atun._atio.at_iid = aep->at_iid;
+ atun._atio.at_tgt = aep->at_tgt;
+ atun._atio.at_lun = aep->at_lun;
+ atun._atio.at_tag_type = aep->at_tag_type;
+ atun._atio.at_tag_val = aep->at_tag_val;
+ atun._atio.at_status = (aep->at_flags & AT_TQAE);
+ atun._atio.at_status |= CT_OK;
}
return (isp_target_put_entry(isp, &atun));
}
@@ -412,7 +401,7 @@ isp_target_put_atio(isp, iid, tgt, lun, ttype, tval)
* values.
*
* NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't
- * NB: inline SCSI sense reporting.
+ * NB: inline SCSI sense reporting. As such, we lose this information. XXX.
*
* For both parallel && fibre channel, we use the feature that does
* an automatic resource autoreplenish so we don't have then later do
@@ -449,7 +438,7 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl)
}
if (aep->at_datalen) {
cto->ct_resid = aep->at_datalen;
- cto->ct_flags |= CT2_DATA_UNDER;
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
}
if ((sts & 0xff) == SCSI_CHECK && (sts & ECMD_SVALID)) {
cto->rsp.m1.ct_resp[0] = 0xf0;
@@ -458,9 +447,9 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl)
cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
cto->rsp.m1.ct_senselen = 16;
- cto->ct_flags |= CT2_SNSLEN_VALID;
+ cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
}
- cto->ct_reserved = hdl;
+ cto->ct_syshandle = hdl;
} else {
at_entry_t *aep = arg;
ct_entry_t *cto = &un._ctio;
@@ -473,21 +462,21 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl)
cto->ct_lun = aep->at_lun;
cto->ct_tag_type = aep->at_tag_type;
cto->ct_tag_val = aep->at_tag_val;
+ if (aep->at_flags & AT_TQAE) {
+ cto->ct_flags |= CT_TQAE;
+ }
cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA;
if (hdl == 0) {
cto->ct_flags |= CT_CCINCR;
}
cto->ct_scsi_status = sts;
- cto->ct_reserved = hdl;
+ cto->ct_syshandle = hdl;
}
return (isp_target_put_entry(isp, &un));
}
void
-isp_target_async(isp, bus, event)
- struct ispsoftc *isp;
- int bus;
- int event;
+isp_target_async(struct ispsoftc *isp, int bus, int event)
{
tmd_event_t evt;
tmd_msg_t msg;
@@ -550,10 +539,7 @@ isp_target_async(isp, bus, event)
*/
static void
-isp_got_msg(isp, bus, inp)
- struct ispsoftc *isp;
- int bus;
- in_entry_t *inp;
+isp_got_msg(struct ispsoftc *isp, int bus, in_entry_t *inp)
{
u_int8_t status = inp->in_status & ~QLTM_SVALID;
@@ -579,13 +565,10 @@ isp_got_msg(isp, bus, inp)
* Synthesize a message from the task management flags in a FCP_CMND_IU.
*/
static void
-isp_got_msg_fc(isp, bus, inp)
- struct ispsoftc *isp;
- int bus;
- in_fcentry_t *inp;
+isp_got_msg_fc(struct ispsoftc *isp, int bus, in_fcentry_t *inp)
{
- static char *f1 = "%s from iid %d lun %d seq 0x%x";
- static char *f2 =
+ static const char f1[] = "%s from iid %d lun %d seq 0x%x";
+ static const char f2[] =
"unknown %s 0x%x lun %d iid %d task flags 0x%x seq 0x%x\n";
if (inp->in_status != IN_MSG_RECEIVED) {
@@ -638,9 +621,7 @@ isp_got_msg_fc(isp, bus, inp)
}
static void
-isp_notify_ack(isp, arg)
- struct ispsoftc *isp;
- void *arg;
+isp_notify_ack(struct ispsoftc *isp, void *arg)
{
char storage[QENTRY_LEN];
u_int16_t iptr, optr;
@@ -701,9 +682,7 @@ isp_notify_ack(isp, arg)
}
static void
-isp_handle_atio(isp, aep)
- struct ispsoftc *isp;
- at_entry_t *aep;
+isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep)
{
int lun;
lun = aep->at_lun;
@@ -776,16 +755,13 @@ isp_handle_atio(isp, aep)
isp_prt(isp, ISP_LOGERR,
"Unknown ATIO status 0x%x from initiator %d for lun %d",
aep->at_status, aep->at_iid, lun);
- (void) isp_target_put_atio(isp, aep->at_iid, aep->at_tgt,
- lun, aep->at_tag_type, aep->at_tag_val);
+ (void) isp_target_put_atio(isp, aep);
break;
}
}
static void
-isp_handle_atio2(isp, aep)
- struct ispsoftc *isp;
- at2_entry_t *aep;
+isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep)
{
int lun;
@@ -862,26 +838,23 @@ isp_handle_atio2(isp, aep)
isp_prt(isp, ISP_LOGERR,
"Unknown ATIO2 status 0x%x from initiator %d for lun %d",
aep->at_status, aep->at_iid, lun);
- (void) isp_target_put_atio(isp, aep->at_iid, 0, lun, 0, 0);
+ (void) isp_target_put_atio(isp, aep);
break;
}
}
static void
-isp_handle_ctio(isp, ct)
- struct ispsoftc *isp;
- ct_entry_t *ct;
+isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct)
{
- XS_T *xs;
+ void *xs;
int pl = ISP_LOGTDEBUG2;
char *fmsg = NULL;
- if (ct->ct_reserved) {
- xs = isp_find_xs(isp, ct->ct_reserved);
+ if (ct->ct_syshandle) {
+ xs = isp_find_xs(isp, ct->ct_syshandle);
if (xs == NULL)
pl = ISP_LOGALL;
} else {
- pl = ISP_LOGTDEBUG1;
xs = NULL;
}
@@ -966,8 +939,13 @@ isp_handle_ctio(isp, ct)
isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
break;
+ case CT_PANIC:
+ if (fmsg == NULL)
+ fmsg = "Unrecoverable Error";
+ /*FALLTHROUGH*/
case CT_ERR:
- fmsg = "Completed with Error";
+ if (fmsg == NULL)
+ fmsg = "Completed with Error";
/*FALLTHROUGH*/
case CT_PHASE_ERROR:
if (fmsg == NULL)
@@ -980,16 +958,7 @@ isp_handle_ctio(isp, ct)
case CT_NOACK:
if (fmsg == NULL)
fmsg = "unacknowledged Immediate Notify pending";
-
isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
-#if 0
- if (status & SENSEVALID) {
- bcopy((caddr_t) (cep + CTIO_SENSE_OFFSET),
- (caddr_t) &cdp->cd_sensedata,
- sizeof(scsi_sense_t));
- cdp->cd_flags |= CDF_SENSEVALID;
- }
-#endif
break;
default:
isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x",
@@ -1005,7 +974,7 @@ isp_handle_ctio(isp, ct)
* The assumption is that they'll all be returned in the
* order we got them.
*/
- if (ct->ct_reserved == 0) {
+ if (ct->ct_syshandle == 0) {
if ((ct->ct_flags & CT_SENDSTATUS) == 0) {
isp_prt(isp, pl,
"intermediate CTIO completed ok");
@@ -1016,53 +985,45 @@ isp_handle_ctio(isp, ct)
} else {
isp_prt(isp, pl,
"NO xs for CTIO (handle 0x%x) status 0x%x",
- ct->ct_reserved, ct->ct_status & ~QLTM_SVALID);
+ ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
}
} else {
- if (ct->ct_flags & CT_SENDSTATUS) {
- /*
- * Sent status and command complete.
- *
- * We're now really done with this command, so we
- * punt to the platform dependent layers because
- * only there can we do the appropriate command
- * complete thread synchronization.
- */
- isp_prt(isp, pl, "status CTIO complete");
- } else {
- /*
- * Final CTIO completed. Release DMA resources and
- * notify platform dependent layers.
- */
- isp_prt(isp, pl, "data CTIO complete");
- ISP_DMAFREE(isp, xs, ct->ct_reserved);
+ /*
+ * Final CTIO completed. Release DMA resources and
+ * notify platform dependent layers.
+ */
+ if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
+ ISP_DMAFREE(isp, xs, ct->ct_syshandle);
}
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
+ isp_prt(isp, pl, "final CTIO complete");
/*
* The platform layer will destroy the handle if appropriate.
*/
+ (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
}
}
static void
-isp_handle_ctio2(isp, ct)
- struct ispsoftc *isp;
- ct2_entry_t *ct;
+isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct)
{
XS_T *xs;
int pl = ISP_LOGTDEBUG2;
char *fmsg = NULL;
- if (ct->ct_reserved) {
- xs = isp_find_xs(isp, ct->ct_reserved);
+ if (ct->ct_syshandle) {
+ xs = isp_find_xs(isp, ct->ct_syshandle);
if (xs == NULL)
pl = ISP_LOGALL;
} else {
- pl = ISP_LOGTDEBUG1;
xs = NULL;
}
switch(ct->ct_status & ~QLTM_SVALID) {
+ case CT_BUS_ERROR:
+ isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
+ /* FALL Through */
+ case CT_DATA_OVER:
+ case CT_DATA_UNDER:
case CT_OK:
/*
* There are generally 2 possibilities as to why we'd get
@@ -1075,19 +1036,18 @@ isp_handle_ctio2(isp, ct)
case CT_BDR_MSG:
/*
- * Bus Device Reset message received or the SCSI Bus has
- * been Reset; the firmware has gone to Bus Free.
+ * Target Reset function received.
*
* The firmware generates an async mailbox interupt to
* notify us of this and returns outstanding CTIOs with this
* status. These CTIOs are handled in that same way as
* CT_ABORTED ones, so just fall through here.
*/
- fmsg = "Bus Device Reset";
+ fmsg = "TARGET RESET Task Management Function Received";
/*FALLTHROUGH*/
case CT_RESET:
if (fmsg == NULL)
- fmsg = "Bus Reset";
+ fmsg = "LIP Reset";
/*FALLTHROUGH*/
case CT_ABORTED:
/*
@@ -1096,7 +1056,7 @@ isp_handle_ctio2(isp, ct)
* set, then sends us an Immediate Notify entry.
*/
if (fmsg == NULL)
- fmsg = "ABORT TASK sent by Initiator";
+ fmsg = "ABORT Task Management Function Received";
isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s", fmsg);
break;
@@ -1108,38 +1068,18 @@ isp_handle_ctio2(isp, ct)
isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data directiond");
break;
- case CT_NOPATH:
- /*
- * CTIO rejected by the firmware due "no path for the
- * nondisconnecting nexus specified". This means that
- * we tried to access the bus while a non-disconnecting
- * command is in process.
- */
- isp_prt(isp, ISP_LOGERR,
- "Firmware rejected CTIO2 for bad nexus %d->%d",
- ct->ct_iid, ct->ct_lun);
- break;
-
case CT_RSELTMO:
- fmsg = "Reselection";
+ fmsg = "failure to reconnect to initiator";
/*FALLTHROUGH*/
case CT_TIMEOUT:
if (fmsg == NULL)
- fmsg = "Command";
+ fmsg = "command";
isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
break;
case CT_ERR:
fmsg = "Completed with Error";
/*FALLTHROUGH*/
- case CT_PHASE_ERROR: /* Bus phase sequence error */
- if (fmsg == NULL)
- fmsg = "Phase Sequence Error";
- /*FALLTHROUGH*/
- case CT_TERMINATED:
- if (fmsg == NULL)
- fmsg = "terminated by TERMINATE TRANSFER";
- /*FALLTHROUGH*/
case CT_LOGOUT:
if (fmsg == NULL)
fmsg = "Port Logout";
@@ -1147,19 +1087,13 @@ isp_handle_ctio2(isp, ct)
case CT_PORTNOTAVAIL:
if (fmsg == NULL)
fmsg = "Port not available";
+ case CT_PORTCHANGED:
+ if (fmsg == NULL)
+ fmsg = "Port Changed";
case CT_NOACK:
if (fmsg == NULL)
fmsg = "unacknowledged Immediate Notify pending";
-
isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
-#if 0
- if (status & SENSEVALID) {
- bcopy((caddr_t) (cep + CTIO_SENSE_OFFSET),
- (caddr_t) &cdp->cd_sensedata,
- sizeof(scsi_sense_t));
- cdp->cd_flags |= CDF_SENSEVALID;
- }
-#endif
break;
case CT_INVRXID:
@@ -1172,7 +1106,7 @@ isp_handle_ctio2(isp, ct)
break;
default:
- isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x",
+ isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x",
ct->ct_status & ~QLTM_SVALID);
break;
}
@@ -1185,7 +1119,7 @@ isp_handle_ctio2(isp, ct)
* The assumption is that they'll all be returned in the
* order we got them.
*/
- if (ct->ct_reserved == 0) {
+ if (ct->ct_syshandle == 0) {
if ((ct->ct_flags & CT_SENDSTATUS) == 0) {
isp_prt(isp, pl,
"intermediate CTIO completed ok");
@@ -1196,9 +1130,12 @@ isp_handle_ctio2(isp, ct)
} else {
isp_prt(isp, pl,
"NO xs for CTIO (handle 0x%x) status 0x%x",
- ct->ct_reserved, ct->ct_status & ~QLTM_SVALID);
+ ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
}
} else {
+ if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
+ ISP_DMAFREE(isp, xs, ct->ct_syshandle);
+ }
if (ct->ct_flags & CT_SENDSTATUS) {
/*
* Sent status and command complete.
@@ -1215,7 +1152,6 @@ isp_handle_ctio2(isp, ct)
* notify platform dependent layers.
*/
isp_prt(isp, pl, "data CTIO complete");
- ISP_DMAFREE(isp, xs, ct->ct_reserved);
}
(void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
/*