summaryrefslogtreecommitdiff
path: root/sys/dev/ic/isp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/isp.c')
-rw-r--r--sys/dev/ic/isp.c466
1 files changed, 269 insertions, 197 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c
index 098c296f49e..c9a3045760d 100644
--- a/sys/dev/ic/isp.c
+++ b/sys/dev/ic/isp.c
@@ -1,14 +1,12 @@
-/* $OpenBSD: isp.c,v 1.5 1999/03/17 12:54:31 mjacob Exp $ */
-/* release_03_16_99 */
+/* $OpenBSD: isp.c,v 1.6 1999/03/25 22:58:38 mjacob Exp $ */
+/* release_03_25_99 */
/*
* Machine and OS Independent (well, as best as possible)
* code for the Qlogic ISP SCSI adapters.
*
- *---------------------------------------
* Copyright (c) 1997, 1998 by Matthew Jacob
* NASA/Ames Research Center
* All rights reserved.
- *---------------------------------------
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -113,7 +111,7 @@ static void isp_fastpost_complete __P((struct ispsoftc *, int));
static void isp_fibre_init __P((struct ispsoftc *));
static void isp_mark_getpdb_all __P((struct ispsoftc *));
static int isp_getpdb __P((struct ispsoftc *, int, isp_pdb_t *));
-static int isp_fclink_test __P((struct ispsoftc *));
+static int isp_fclink_test __P((struct ispsoftc *, int));
static void isp_fw_state __P((struct ispsoftc *));
static void isp_dumpregs __P((struct ispsoftc *, const char *));
static void isp_dumpxflist __P((struct ispsoftc *));
@@ -189,11 +187,33 @@ isp_reset(isp)
if (IS_FC(isp)) {
revname = "2100";
} else if (IS_1080(isp)) {
+ u_int16_t l;
sdparam *sdp = isp->isp_param;
revname = "1080";
- sdp->isp_clock = 0; /* don't set clock */
- sdp->isp_diffmode = 1;
- sdp->isp_ultramode = 1;
+ sdp->isp_clock = 100;
+ l = ISP_READ(isp, SXP_PINS_DIFF) & ISP1080_MODE_MASK;
+ switch (l) {
+ case ISP1080_LVD_MODE:
+ sdp->isp_lvdmode = 1;
+ PRINTF("%s: LVD Mode\n", isp->isp_name);
+ break;
+ case ISP1080_HVD_MODE:
+ sdp->isp_diffmode = 1;
+ PRINTF("%s: Differential Mode\n", isp->isp_name);
+ break;
+ case ISP1080_SE_MODE:
+ sdp->isp_ultramode = 1;
+ PRINTF("%s: Single-Ended Mode\n", isp->isp_name);
+ break;
+ default:
+ /*
+ * Hmm. Up in a wierd mode. This means all SCSI I/O
+ * buffer lines are tristated, so we're in a lot of
+ * trouble if we don't set things up right.
+ */
+ PRINTF("%s: Illegal Mode 0x%x\n", isp->isp_name, l);
+ break;
+ }
} else {
sdparam *sdp = isp->isp_param;
i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
@@ -203,7 +223,7 @@ isp_reset(isp)
isp->isp_name, i);
/* FALLTHROUGH */
case 1:
- revname = "1020";
+ revname = "1020";
isp->isp_type = ISP_HA_SCSI_1020;
sdp->isp_clock = 40;
break;
@@ -213,7 +233,7 @@ isp_reset(isp)
* run the clock rate up for that unless told to
* do so by the Ultra Capable bits being set.
*/
- revname = "1020A";
+ revname = "1020A";
isp->isp_type = ISP_HA_SCSI_1020A;
sdp->isp_clock = 40;
break;
@@ -257,7 +277,7 @@ isp_reset(isp)
* even for the SBus version.
*/
sdp->isp_clock = 60;
- } else {
+ } else {
sdp->isp_ultramode = 0;
/*
* Clock is known. Gronk.
@@ -307,9 +327,9 @@ again:
* Clear data && control DMA engines.
*/
ISP_WRITE(isp, CDMA_CONTROL,
- DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
+ DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
ISP_WRITE(isp, DDMA_CONTROL,
- DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
+ DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
} else {
@@ -386,11 +406,11 @@ again:
}
#ifdef PTI_CARDS
if (((sdparam *) isp->isp_param)->isp_ultramode) {
- while(ISP_READ(isp, RISC_MTR) != 0x1313) {
+ while (ISP_READ(isp, RISC_MTR) != 0x1313) {
ISP_WRITE(isp, RISC_MTR, 0x1313);
ISP_WRITE(isp, HCCR, HCCR_CMD_STEP);
}
- } else {
+ } else {
ISP_WRITE(isp, RISC_MTR, 0x1212);
}
/*
@@ -550,7 +570,7 @@ again:
PRINTF("%s: Board Revision %s, %s F/W Revision %d.%d\n",
isp->isp_name, revname, dodnld? "loaded" : "resident",
mbs.param[1], mbs.param[2]);
- if (isp->isp_type & ISP_HA_FC) {
+ if (IS_FC(isp)) {
if (ISP_READ(isp, BIU2100_CSR) & BIU2100_PCI64) {
PRINTF("%s: in 64-Bit PCI slot\n", isp->isp_name);
}
@@ -590,7 +610,7 @@ isp_init(isp)
PRINTF("%s: can't setup dma mailboxes\n", isp->isp_name);
return;
}
-
+
/*
* If we're fibre, we have a completely different
* initialization method.
@@ -693,27 +713,25 @@ isp_init(isp)
/*
* It is not quite clear when this changed over so that
* we could force narrow and async, so assume >= 7.55.
- *
- * Otherwise, a SCSI bus reset issued below will force
- * the back to the narrow, async state (but see note
- * below also). Technically we should also do without
- * Parity.
*/
if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
sdf |= DPARM_NARROW | DPARM_ASYNC;
}
-
mbs.param[0] = MBOX_SET_TARGET_PARAMS;
mbs.param[1] = tgt << 8;
mbs.param[2] = sdf;
- mbs.param[3] = 0;
+ mbs.param[3] =
+ (sdp->isp_devparam[tgt].sync_offset << 8) |
+ (sdp->isp_devparam[tgt].sync_period);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
sdf = DPARM_SAFE_DFLT;
mbs.param[0] = MBOX_SET_TARGET_PARAMS;
mbs.param[1] = tgt << 8;
mbs.param[2] = sdf;
- mbs.param[3] = 0;
+ mbs.param[3] =
+ (sdp->isp_devparam[tgt].sync_offset << 8) |
+ (sdp->isp_devparam[tgt].sync_period);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
PRINTF("%s: failed even to set defaults for "
@@ -721,8 +739,26 @@ isp_init(isp)
continue;
}
}
- sdp->isp_devparam[tgt].cur_dflags = sdf;
-
+ /*
+ * We don't update dev_flags with what we've set
+ * because that's not the ultimate goal setting.
+ * If we succeed with the command, we *do* update
+ * cur_dflags.
+ */
+ mbs.param[0] = MBOX_GET_TARGET_PARAMS;
+ mbs.param[1] = (tgt << 8);
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ /*
+ * Urrr.... We'll set cur_dflags to DPARM_SAFE_DFLT so
+ * we don't try and do tags if tags aren't enabled.
+ */
+ sdp->isp_devparam[tgt].cur_dflags = DPARM_SAFE_DFLT;
+ } else {
+ sdp->isp_devparam[tgt].cur_dflags = mbs.param[2];
+ sdp->isp_devparam[tgt].cur_offset = mbs.param[3] >> 8;
+ sdp->isp_devparam[tgt].cur_period = mbs.param[3] & 0xff;
+ }
maxlun = (isp->isp_fwrev >= ISP_FW_REV(7, 55))? 32 : 8;
for (lun = 0; lun < maxlun; lun++) {
mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS;
@@ -770,25 +806,32 @@ isp_init(isp)
isp->isp_reqidx = isp->isp_reqodx = 0;
/*
- * Turn on Fast Posting
+ * Turn on Fast Posting, LVD transitions
*/
-#ifndef ISP_NO_FASTPOST_SCSI
- if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
+
+ if (IS_1080(isp) || isp->isp_fwrev >= ISP_FW_REV(7, 55)) {
mbs.param[0] = MBOX_SET_FW_FEATURES;
- mbs.param[1] = FW_FEATURE_FAST_POST;
- isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- PRINTF("%s: unable to enable FAST Posting\n",
- isp->isp_name);
+#ifndef ISP_NO_FASTPOST_SCSI
+ mbs.param[1] |= FW_FEATURE_FAST_POST;
+#else
+ mbs.param[1] = 0;
+#endif
+ if (IS_1080(isp))
+ mbs.param[1] |= FW_FEATURE_LVD_NOTIFY;
+ if (mbs.param[1] != 0) {
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ PRINTF("%s: unable enable FW features\n",
+ isp->isp_name);
+ }
}
}
-#endif
/*
* Let the outer layers decide whether to issue a SCSI bus reset.
*/
#if 0
- /*
+ /*
* XXX: See whether or not for 7.55 F/W or later we
* XXX: can do without this, and see whether we should
* XXX: honor the NVRAM SCSI_RESET_DISABLE token.
@@ -944,6 +987,8 @@ isp_fibre_init(isp)
isp->isp_state = ISP_INITSTATE;
fcp->isp_fwstate = FW_CONFIG_WAIT;
+ isp_mark_getpdb_all(isp);
+
#ifdef ISP_TARGET_MODE
if (isp_modify_lun(isp, 0, 1, 1)) {
PRINTF("%s: failed to enable target mode\n", isp->isp_name);
@@ -975,31 +1020,19 @@ isp_getpdb(isp, id, pdbp)
int id;
isp_pdb_t *pdbp;
{
-#ifdef GETPDB_WORKING_YET
fcparam *fcp = (fcparam *) isp->isp_param;
mbreg_t mbs;
-
- /*
- * Get Port Queue Parameters first- this is
- * a Q&D way to see whether we're logged into
- * this port.
- */
- mbs.param[0] = MBOX_GET_DEV_QUEUE_PARAMS;
- mbs.param[1] = id << 8;
- mbs.param[2] = 0;
-#ifdef ISP2100_SCCLUN
- mbs.param[3] = 0;
-#endif
- isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
- return (-1);
-
mbs.param[0] = MBOX_GET_PORT_DB;
mbs.param[1] = id << 8;
mbs.param[2] = (u_int16_t) (fcp->isp_scdma >> 16);
mbs.param[3] = (u_int16_t) (fcp->isp_scdma & 0xffff);
- mbs.param[4] = 0;
- mbs.param[5] = 0;
+ /*
+ * Unneeded. For the 2100, except for initializing f/w, registers
+ * 4/5 have to not be written to.
+ * mbs.param[4] = 0;
+ * mbs.param[5] = 0;
+ *
+ */
mbs.param[6] = 0;
mbs.param[7] = 0;
isp_mboxcmd(isp, &mbs);
@@ -1014,16 +1047,13 @@ isp_getpdb(isp, id, pdbp)
case MBOX_COMMAND_PARAM_ERROR:
/* Not Logged In */
IDPRINTF(3, ("%s: Comand Param Error on Get Port Database\n",
- isp->isp_name));
+ isp->isp_name));
return (-1);
default:
PRINTF("%s: error 0x%x getting port database for ID %d\n",
isp->isp_name, mbs.param[0], id);
return (-1);
}
-#else
- pdbp->pdb_options = 1;
-#endif
return (0);
}
@@ -1032,8 +1062,9 @@ isp_getpdb(isp, id, pdbp)
*/
static int
-isp_fclink_test(isp)
+isp_fclink_test(isp, waitdelay)
struct ispsoftc *isp;
+ int waitdelay;
{
mbreg_t mbs;
int count;
@@ -1044,10 +1075,9 @@ isp_fclink_test(isp)
/*
* Wait up to N microseconds for F/W to go to a ready state.
- * This is a platform specific
*/
lwfs = FW_CONFIG_WAIT;
- for (count = 0; count < FC_FW_READY_DELAY; count += 100) {
+ for (count = 0; count < waitdelay; count += 100) {
isp_fw_state(isp);
if (lwfs != fcp->isp_fwstate) {
PRINTF("%s: Firmware State %s -> %s\n",
@@ -1067,13 +1097,14 @@ isp_fclink_test(isp)
if (fcp->isp_fwstate != FW_READY) {
return (-1);
}
+
/*
* Get our Loop ID (if possible). We really need to have it.
*/
mbs.param[0] = MBOX_GET_LOOP_ID;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- PRINTF("%s: GET LOOP ID failed\n", isp->isp_name);
+ PRINTF("%s: GET LOOP ID failed\n", isp->isp_name);
return (-1);
}
fcp->isp_loopid = mbs.param[1];
@@ -1114,7 +1145,7 @@ ispscsicmd(xs)
/*
* We *could* do the different sequence type that has close
- * to the whole Queue Entry for the command,...
+ * to the whole Queue Entry for the command...
*/
if (XS_CDBLEN(xs) > ((isp->isp_type & ISP_HA_FC)? 16 : 12)) {
@@ -1137,30 +1168,18 @@ ispscsicmd(xs)
* our cached copy of it...
*/
if (fcp->isp_fwstate != FW_READY) {
- if (isp_fclink_test(isp)) {
+ if (isp_fclink_test(isp, FC_FW_READY_DELAY)) {
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
}
}
/*
- * Here's the spot we would need to find out whether
- * the port names have changed, whether it's still
- * a target role, etc..
+ * Refresh our port database if needed.
*/
if (pdbp->pdb_options == INVALID_PDB_OPTIONS) {
- /*
- * If we don't know what it is- don't talk to it.
- * This also handles cases where it's not logged
- * into this port/target.
- */
- if (isp_getpdb(isp, XS_TGT(xs), pdbp)) {
- XS_SETERR(xs, HBA_SELTIMEOUT);
- return (CMD_COMPLETE);
-#ifdef GETPDB_WORKING_YET
- } else {
+ if (isp_getpdb(isp, XS_TGT(xs), pdbp) == 0) {
isp_async(isp, ISPASYNC_PDB_CHANGE_COMPLETE,
(void *) (long) XS_TGT(xs));
-#endif
}
}
}
@@ -1242,6 +1261,7 @@ ispscsicmd(xs)
* See comment in isp_intr
*/
XS_RESID(xs) = 0;
+
/*
* Fibre Channel always requires some kind of tag.
* If we're marked as "Can't Tag", just do simple
@@ -1252,7 +1272,7 @@ ispscsicmd(xs)
if (XS_CANTAG(xs)) {
t2reqp->req_flags = XS_KINDOF_TAG(xs);
} else {
- t2reqp->req_flags = REQFLAG_STAG;
+ t2reqp->req_flags = REQFLAG_STAG;
}
} else {
sdparam *sdp = (sdparam *)isp->isp_param;
@@ -1365,7 +1385,7 @@ isp_control(isp, ctl, arg)
PRINTF("%s: driver initiated bus reset\n", isp->isp_name);
return (0);
- case ISPCTL_RESET_DEV:
+ case ISPCTL_RESET_DEV:
mbs.param[0] = MBOX_ABORT_TARGET;
mbs.param[1] = ((long)arg) << 8;
mbs.param[2] = 3; /* 'delay', in seconds */
@@ -1379,7 +1399,7 @@ isp_control(isp, ctl, arg)
isp->isp_sendmarker = 1;
return (0);
- case ISPCTL_ABORT_CMD:
+ case ISPCTL_ABORT_CMD:
xs = (ISP_SCSI_XFER_T *) arg;
for (i = 0; i < RQUEST_QUEUE_LEN; i++) {
if (xs == isp->isp_xflist[i]) {
@@ -1418,10 +1438,10 @@ isp_control(isp, ctl, arg)
case ISPCTL_UPDATE_PARAMS:
isp_update(isp);
- return(0);
+ return (0);
case ISPCTL_FCLINK_TEST:
- return (isp_fclink_test(isp));
+ return (isp_fclink_test(isp, FC_FW_READY_DELAY));
}
return (-1);
}
@@ -1448,7 +1468,7 @@ isp_intr(arg)
if (isr == 0 || (isr & BIU2100_ISR_RISC_INT) == 0) {
if (isr) {
IDPRINTF(4, ("%s: isp_intr isr=%x\n",
- isp->isp_name, isr));
+ isp->isp_name, isr));
}
return (0);
}
@@ -1456,7 +1476,7 @@ isp_intr(arg)
if (isr == 0 || (isr & BIU_ISR_RISC_INT) == 0) {
if (isr) {
IDPRINTF(4, ("%s: isp_intr isr=%x\n",
- isp->isp_name, isr));
+ isp->isp_name, isr));
}
return (0);
}
@@ -1465,10 +1485,8 @@ isp_intr(arg)
if (ISP_READ(isp, BIU_SEMA) & 1) {
u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0);
if (mbox & 0x4000) {
- if (mbox != MBOX_COMMAND_COMPLETE) {
- PRINTF("%s: isp_intr sees 0x%x\n",
- isp->isp_name,mbox);
- }
+ IDPRINTF(3, ("%s: isp_intr sees 0x%x\n",
+ isp->isp_name, mbox));
ISP_WRITE(isp, BIU_SEMA, 0);
} else {
u_int32_t fhandle = isp_parse_async(isp, (int) mbox);
@@ -1476,8 +1494,7 @@ isp_intr(arg)
if (fhandle < 0) {
return (1);
} else if (fhandle > 0) {
- xs = (ISP_SCSI_XFER_T *)
- isp->isp_xflist[fhandle - 1];
+ xs = (void *)isp->isp_xflist[fhandle - 1];
isp->isp_xflist[fhandle - 1] = NULL;
/*
* Since we don't have a result queue entry
@@ -1491,7 +1508,7 @@ isp_intr(arg)
}
if (isp->isp_nactive > 0)
isp->isp_nactive--;
- complist[ndone++] = xs;
+ complist[ndone++] = xs;
}
}
}
@@ -1565,7 +1582,7 @@ isp_intr(arg)
ISP_WRITE(isp, INMAILBOX5, optr);
continue;
}
- xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[sp->req_handle - 1];
+ xs = (void *) isp->isp_xflist[sp->req_handle - 1];
if (xs == NULL) {
PRINTF("%s: NULL xs in xflist (handle %x)\n",
isp->isp_name, sp->req_handle);
@@ -1674,7 +1691,7 @@ isp_intr(arg)
*/
if (nlooked) {
ISP_WRITE(isp, INMAILBOX5, optr);
- isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);
+ isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);
}
isp->isp_residx = optr;
for (i = 0; i < ndone; i++) {
@@ -1765,8 +1782,37 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_BUS_TRANSIT:
- PRINTF("%s: LBD->HVD Transition 0x%x\n",
- isp->isp_name, ISP_READ(isp, OUTMAILBOX1));
+ mbox = ISP_READ(isp, OUTMAILBOX2);
+ switch (mbox & 0x1c00) {
+ case SXP_PINS_LVD_MODE:
+ PRINTF("%s: Transition to LVD mode\n", isp->isp_name);
+ ((sdparam *)isp->isp_param)->isp_diffmode = 0;
+ ((sdparam *)isp->isp_param)->isp_ultramode = 0;
+ ((sdparam *)isp->isp_param)->isp_lvdmode = 1;
+ break;
+ case SXP_PINS_HVD_MODE:
+ PRINTF("%s: Transition to Differential mode\n",
+ isp->isp_name);
+ ((sdparam *)isp->isp_param)->isp_diffmode = 1;
+ ((sdparam *)isp->isp_param)->isp_ultramode = 0;
+ ((sdparam *)isp->isp_param)->isp_lvdmode = 0;
+ break;
+ case SXP_PINS_SE_MODE:
+ PRINTF("%s: Transition to Single Ended mode\n",
+ isp->isp_name);
+ ((sdparam *)isp->isp_param)->isp_diffmode = 0;
+ ((sdparam *)isp->isp_param)->isp_ultramode = 1;
+ ((sdparam *)isp->isp_param)->isp_lvdmode = 0;
+ break;
+ default:
+ PRINTF("%s: Transition to unknown mode 0x%x\n",
+ isp->isp_name, mbox);
+ break;
+ }
+ /*
+ * XXX: Set up to renegotiate again!
+ */
+ isp->isp_sendmarker = 1;
break;
case ASYNC_CMD_CMPLT:
@@ -1839,7 +1885,7 @@ isp_handle_other_response(isp, sp, optrp)
in_fcentry_t *inot_fc;
na_entry_t *nack;
na_fcentry_t *nack_fc;
- void *voidp;
+ void *voidp;
#define atio un.atio
#define at2io un.at2io
#define ctio un.ctio
@@ -1900,20 +1946,20 @@ isp_handle_other_response(isp, sp, optrp)
ptisp_got_msg(ptp, &inot);
break;
case IN_RSRC_UNAVAIL:
- PRINTF("%s: Firmware out of ATIOs\n", isp->isp_name);
- break;
- case IN_ABORT_TASK:
+ PRINTF("%s: Firmware out of ATIOs\n", isp->isp_name);
+ break;
+ case IN_ABORT_TASK:
PRINTF("%s: Abort Task iid %d rx_id 0x%x\n",
inot_fc->in_iid, seqid);
- break;
- case IN_PORT_LOGOUT:
+ break;
+ case IN_PORT_LOGOUT:
PRINTF("%s: Port Logout for Initiator %d\n",
isp->isp_name, inot_fc->in_iid);
- break;
- default:
+ break;
+ default:
PRINTF("%s: bad status (0x%x) in Immediate Notify\n",
- isp->isp_name, status);
- break;
+ isp->isp_name, status);
+ break;
}
isp_notify_ack(isp, un.voidp);
@@ -2001,7 +2047,7 @@ isp_handle_other_response(isp, sp, optrp)
ct2->req_m.mode0.req_scsi_status = CTIO2_STATUS_VALID;
ct2->req_seg_count = 1;
if (at2->req_cdb[0] == 0x12) {
- s = sizeof(tgtiqd);
+ s = sizeof (tgtiqd);
MEMCPY(fcp->isp_scratch, tgtiqd, s);
} else {
s = at2->req_datalen;
@@ -2073,7 +2119,7 @@ isp_handle_other_response(isp, sp, optrp)
PRINTF("%s: CTIO2 returned status 0x%x\n", isp->isp_name,
ct2->req_status);
/*
- * Return the ATIO to the board.
+ * Return the ATIO to the board.
*/
at2 = (ispatiot2_t *) sp;
at2->req_header.rqs_entry_type = RQSTYPE_ATIO2;
@@ -2274,7 +2320,7 @@ isp_handle_atio (isp, aep)
* did not set DiscPriv in the identify message. We don't care
* about this so it's ignored.
*/
- switch(status & ~TGTSVALID) {
+ switch (status & ~TGTSVALID) {
case AT_PATH_INVALID:
/*
* ATIO rejected by the firmware due to disabled lun.
@@ -2373,7 +2419,7 @@ isp_handle_atio2(isp, aep)
* why this ATIO was sent to us.
* If SenseValid is set, the firware has recommended Sense Data.
*/
- switch(status & ~TGTSVALID) {
+ switch (status & ~TGTSVALID) {
case AT_PATH_INVALID:
/*
* ATIO rejected by the firmware due to disabled lun.
@@ -2691,7 +2737,7 @@ isp_parse_status(isp, sp, xs)
default:
PRINTF("%s: comp status %x\n", isp->isp_name,
- sp->req_completion_status);
+ sp->req_completion_status);
break;
}
XS_SETERR(xs, HBA_BOTCH);
@@ -2728,7 +2774,7 @@ isp_fastpost_complete(isp, fph)
#define HINIB(x) ((x) >> 0x4)
#define LONIB(x) ((x) & 0xf)
-#define MAKNIB(a, b) (((a) << 4) | (b))
+#define MAKNIB(a, b) (((a) << 4) | (b))
static u_int8_t mbpcnt[] = {
MAKNIB(1, 1), /* 0x00: MBOX_NO_OP */
MAKNIB(5, 5), /* 0x01: MBOX_LOAD_RAM */
@@ -2754,7 +2800,7 @@ static u_int8_t mbpcnt[] = {
MAKNIB(4, 4), /* 0x15: MBOX_ABORT */
MAKNIB(2, 2), /* 0x16: MBOX_ABORT_DEVICE */
MAKNIB(3, 3), /* 0x17: MBOX_ABORT_TARGET */
- MAKNIB(2, 2), /* 0x18: MBOX_BUS_RESET */
+ MAKNIB(3, 1), /* 0x18: MBOX_BUS_RESET */
MAKNIB(2, 3), /* 0x19: MBOX_STOP_QUEUE */
MAKNIB(2, 3), /* 0x1a: MBOX_START_QUEUE */
MAKNIB(2, 3), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
@@ -2903,14 +2949,10 @@ isp_mboxcmd(isp, mbp)
command_known:
-#define NEW_MB_WAY 1
-#ifdef NEW_MB_WAY
/*
* Set semaphore on mailbox registers to win any races to acquire them.
*/
ISP_WRITE(isp, BIU_SEMA, 1);
-#endif
-
/*
* Make sure we can send some words. Check to see id there's
@@ -2964,13 +3006,38 @@ command_known:
}
/*
+ * If we're a 1080 or a 1240, make sure that for a couple of commands
+ * the port parameter is set. This is sort of a temporary solution
+ * to do it here rather than every place a mailbox command is formed.
+ */
+ if (IS_1080(isp) || IS_12X0(isp)) {
+ switch (mbp->param[0]) {
+ case MBOX_BUS_RESET:
+ mbp->param[2] = isp->isp_port;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
* Write input parameters.
*/
switch (inparam) {
case 8: ISP_WRITE(isp, INMAILBOX7, mbp->param[7]); mbp->param[7] = 0;
case 7: ISP_WRITE(isp, INMAILBOX6, mbp->param[6]); mbp->param[6] = 0;
- case 6: ISP_WRITE(isp, INMAILBOX5, mbp->param[5]); mbp->param[5] = 0;
- case 5: ISP_WRITE(isp, INMAILBOX4, mbp->param[4]); mbp->param[4] = 0;
+ case 6:
+ /*
+ * The Qlogic 2100 cannot have registers 4 and 5 written to
+ * after initialization or BAD THINGS HAPPEN (tm).
+ */
+ if (IS_SCSI(isp) || mbp->param[0] == MBOX_INIT_FIRMWARE)
+ ISP_WRITE(isp, INMAILBOX5, mbp->param[5]);
+ mbp->param[5] = 0;
+ case 5:
+ if (IS_SCSI(isp) || mbp->param[0] == MBOX_INIT_FIRMWARE)
+ ISP_WRITE(isp, INMAILBOX4, mbp->param[4]);
+ mbp->param[4] = 0;
case 4: ISP_WRITE(isp, INMAILBOX3, mbp->param[3]); mbp->param[3] = 0;
case 3: ISP_WRITE(isp, INMAILBOX2, mbp->param[2]); mbp->param[2] = 0;
case 2: ISP_WRITE(isp, INMAILBOX1, mbp->param[1]); mbp->param[1] = 0;
@@ -2994,40 +3061,6 @@ command_known:
*/
ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
-#ifndef NEW_MB_WAY
- /*
- * Wait until RISC int is set, except 2100
- */
- if ((isp->isp_type & ISP_HA_FC) == 0) {
- loops = MBOX_DELAY_COUNT;
- while ((ISP_READ(isp, BIU_ISR) & BIU_ISR_RISC_INT) == 0) {
- SYS_DELAY(100);
- if (--loops < 0) {
- PRINTF("%s: isp_mboxcmd timeout #2\n",
- isp->isp_name);
- return;
- }
- }
- }
-
- /*
- * Check to make sure that the semaphore has been set.
- */
- loops = MBOX_DELAY_COUNT;
- while ((ISP_READ(isp, BIU_SEMA) & 1) == 0) {
- SYS_DELAY(100);
- /*
- * Wierd- I've seen the case where the semaphore register
- * isn't getting set- sort of a violation of the protocol..
- */
- if (ISP_READ(isp, OUTMAILBOX0) & 0x4000)
- break;
- if (--loops < 0) {
- PRINTF("%s: isp_mboxcmd timeout #3\n", isp->isp_name);
- return;
- }
- }
-#else
/*
* Wait until HOST INT has gone away (meaning that the Qlogic
* has picked up the mailbox command. Wait a long time.
@@ -3059,7 +3092,6 @@ command_known:
return;
}
}
-#endif
/*
* Make sure that the MBOX_BUSY has gone away
@@ -3121,7 +3153,7 @@ command_known:
/*
* Just to be chatty here...
*/
- switch(mbp->param[0]) {
+ switch (mbp->param[0]) {
case MBOX_COMMAND_COMPLETE:
break;
case MBOX_INVALID_COMMAND:
@@ -3194,7 +3226,7 @@ isp_lostcmd(isp, xs)
}
if (mbs.param[1]) {
PRINTF("%s: %d commands on completion queue\n",
- isp->isp_name, mbs.param[1]);
+ isp->isp_name, mbs.param[1]);
}
if (XS_NULL(xs))
return;
@@ -3227,7 +3259,7 @@ isp_dumpregs(isp, msg)
else
PRINTF(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR));
PRINTF(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR),
- ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA));
+ ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA));
PRINTF("risc_hccr=%x\n", ISP_READ(isp, HCCR));
@@ -3329,6 +3361,12 @@ isp_update(isp)
continue;
}
+ /*
+ * If the goal is to update the status of the device,
+ * take what's in dev_flags and try and set the device
+ * toward that. Otherwise, if we're just refreshing the
+ * current device state, get the current parameters.
+ */
if (sdp->isp_devparam[tgt].dev_update) {
mbs.param[0] = MBOX_SET_TARGET_PARAMS;
mbs.param[2] = sdp->isp_devparam[tgt].dev_flags;
@@ -3336,8 +3374,20 @@ isp_update(isp)
(sdp->isp_devparam[tgt].sync_offset << 8) |
(sdp->isp_devparam[tgt].sync_period);
sdp->isp_devparam[tgt].dev_update = 0;
- sdp->isp_devparam[tgt].dev_refresh = 1;
- isp->isp_update = 1;
+ /*
+ * A command completion later that has
+ * RQSTF_NEGOTIATION set will cause
+ * the dev_refresh/announce cycle.
+ *
+ * Note: It is really important to update our current
+ * flags with at least the state of TAG capabilities-
+ * otherwise we might try and send a tagged command
+ * when we have it all turned off. So change it here
+ * to say that current already matches goal.
+ */
+ sdp->isp_devparam[tgt].cur_dflags &= ~DPARM_TQING;
+ sdp->isp_devparam[tgt].cur_dflags |=
+ (sdp->isp_devparam[tgt].dev_flags & DPARM_TQING);
get = 0;
} else if (sdp->isp_devparam[tgt].dev_refresh) {
mbs.param[0] = MBOX_GET_TARGET_PARAMS;
@@ -3360,16 +3410,14 @@ isp_update(isp)
* XXX: Need a SYNC_TARGET for efficiency...
*/
isp->isp_sendmarker = 1;
- sdp->isp_devparam[tgt].cur_dflags =
- sdp->isp_devparam[tgt].dev_flags;
continue;
}
flags = mbs.param[2];
period = mbs.param[3] & 0xff;
offset = mbs.param[3] >> 8;
if (sdp->isp_devparam[tgt].cur_dflags != flags ||
- sdp->isp_devparam[tgt].sync_period != period ||
- sdp->isp_devparam[tgt].sync_offset != offset) {
+ sdp->isp_devparam[tgt].cur_period != period ||
+ sdp->isp_devparam[tgt].cur_offset != offset) {
IDPRINTF(3, ("%s: tgt %d flags 0x%x period %d "
"off %d\n", isp->isp_name, tgt, flags,
period, offset));
@@ -3377,11 +3425,9 @@ isp_update(isp)
} else {
changed = 0;
}
-
sdp->isp_devparam[tgt].cur_dflags = flags;
- sdp->isp_devparam[tgt].dev_flags = flags;
- sdp->isp_devparam[tgt].sync_period = period;
- sdp->isp_devparam[tgt].sync_offset = offset;
+ sdp->isp_devparam[tgt].cur_period = period;
+ sdp->isp_devparam[tgt].cur_offset = offset;
if (sdp->isp_devparam[tgt].dev_announced == 0 || changed) {
if (isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &tgt))
sdp->isp_devparam[tgt].dev_announced = 0;
@@ -3395,7 +3441,7 @@ static void
isp_setdfltparm(isp)
struct ispsoftc *isp;
{
- int i;
+ int tgt;
mbreg_t mbs;
sdparam *sdp;
@@ -3408,9 +3454,17 @@ isp_setdfltparm(isp)
}
isp->isp_gotdparms = 1;
- if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0 &&
- (isp_read_nvram(isp) == 0)) {
- return;
+ /*
+ * If we've not been told to avoid reading NVRAM, try and read it.
+ * If we're successful reading it, we can return since NVRAM will
+ * tell us the right thing to do. Otherwise, establish some reasonable
+ * defaults.
+ */
+
+ if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
+ if (isp_read_nvram(isp) == 0) {
+ return;
+ }
}
if (IS_FC(isp)) {
fcparam *fcp = (fcparam *) isp->isp_param;
@@ -3441,19 +3495,32 @@ isp_setdfltparm(isp)
sdp->isp_data_line_active_neg = (mbs.param[1] >> 5) & 0x1;
}
- for (i = 0; i < MAX_TARGETS; i++) {
- sdp->isp_devparam[i].dev_flags = DPARM_DEFAULT;
- sdp->isp_devparam[i].cur_dflags = DPARM_SAFE_DFLT;
+ /*
+ * The trick here is to establish a default for the default (honk!)
+ * state (dev_flags). Then try and get the current status from
+ * the card to fill in the current state. We don't, in fact, set
+ * the default to the SAFE default state- that's not the goal state.
+ */
+ for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
+ sdp->isp_devparam[tgt].cur_offset = 0;
+ sdp->isp_devparam[tgt].cur_period = 0;
+ sdp->isp_devparam[tgt].dev_flags = DPARM_DEFAULT;
+ sdp->isp_devparam[tgt].cur_dflags = 0;
if (isp->isp_type < ISP_HA_SCSI_1040 ||
(sdp->isp_clock && sdp->isp_clock < 60)) {
- sdp->isp_devparam[i].sync_offset =
+ sdp->isp_devparam[tgt].sync_offset =
ISP_10M_SYNCPARMS >> 8;
- sdp->isp_devparam[i].sync_period =
+ sdp->isp_devparam[tgt].sync_period =
ISP_10M_SYNCPARMS & 0xff;
+ } else if (IS_1080(isp)) {
+ sdp->isp_devparam[tgt].sync_offset =
+ ISP_40M_SYNCPARMS >> 8;
+ sdp->isp_devparam[tgt].sync_period =
+ ISP_40M_SYNCPARMS & 0xff;
} else {
- sdp->isp_devparam[i].sync_offset =
+ sdp->isp_devparam[tgt].sync_offset =
ISP_20M_SYNCPARMS >> 8;
- sdp->isp_devparam[i].sync_period =
+ sdp->isp_devparam[tgt].sync_period =
ISP_20M_SYNCPARMS & 0xff;
}
@@ -3461,29 +3528,33 @@ isp_setdfltparm(isp)
* Don't get current target parameters if we've been
* told not to use NVRAM- it's really the same thing.
*/
- if (isp->isp_confopts & ISP_CFG_NONVRAM)
+ if (isp->isp_confopts & ISP_CFG_NONVRAM) {
continue;
+ }
mbs.param[0] = MBOX_GET_TARGET_PARAMS;
- mbs.param[1] = i << 8;
+ mbs.param[1] = tgt << 8;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
continue;
}
- sdp->isp_devparam[i].dev_flags = mbs.param[2];
+ sdp->isp_devparam[tgt].cur_dflags = mbs.param[2];
+ sdp->isp_devparam[tgt].dev_flags = mbs.param[2];
+ sdp->isp_devparam[tgt].cur_period = mbs.param[3] & 0xff;
+ sdp->isp_devparam[tgt].cur_offset = mbs.param[3] >> 8;
+
/*
* The maximum period we can really see
* here is 100 (decimal), or 400 ns.
* For some unknown reason we sometimes
* get back wildass numbers from the
- * boot device's parameters.
- *
- * XXX: Hmm- this may be based on a different
- * XXX: clock rate.
+ * boot device's parameters (alpha only).
*/
if ((mbs.param[3] & 0xff) <= 0x64) {
- sdp->isp_devparam[i].sync_period = mbs.param[3] & 0xff;
- sdp->isp_devparam[i].sync_offset = mbs.param[3] >> 8;
+ sdp->isp_devparam[tgt].sync_period =
+ mbs.param[3] & 0xff;
+ sdp->isp_devparam[tgt].sync_offset =
+ mbs.param[3] >> 8;
}
/*
@@ -3491,11 +3562,11 @@ isp_setdfltparm(isp)
*/
if (((sdp->isp_clock && sdp->isp_clock < 60) ||
(isp->isp_type < ISP_HA_SCSI_1020A)) &&
- (sdp->isp_devparam[i].sync_period ==
+ (sdp->isp_devparam[tgt].sync_period <=
(ISP_20M_SYNCPARMS & 0xff))) {
- sdp->isp_devparam[i].sync_offset =
+ sdp->isp_devparam[tgt].sync_offset =
ISP_10M_SYNCPARMS >> 8;
- sdp->isp_devparam[i].sync_period =
+ sdp->isp_devparam[tgt].sync_period =
ISP_10M_SYNCPARMS & 0xff;
}
}
@@ -3519,13 +3590,13 @@ isp_setdfltparm(isp)
sdp->isp_retry_count = 0;
sdp->isp_retry_delay = 1;
- for (i = 0; i < MAX_TARGETS; i++) {
- sdp->isp_devparam[i].exc_throttle = 16;
- sdp->isp_devparam[i].dev_enable = 1;
+ for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
+ sdp->isp_devparam[tgt].exc_throttle = 16;
+ sdp->isp_devparam[tgt].dev_enable = 1;
}
}
-/*
+/*
* Re-initialize the ISP and complete all orphaned commands
* with a 'botched' notice.
*
@@ -3653,7 +3724,7 @@ isp_read_nvram(isp)
sdp->isp_async_data_setup = 6;
}
}
-
+
sdp->isp_req_ack_active_neg =
ISP_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data);
@@ -3757,6 +3828,7 @@ isp_read_nvram(isp)
sdp->isp_devparam[i].dev_flags |= DPARM_PARITY;
if (ISP_NVRAM_TGT_DISC(nvram_data, i))
sdp->isp_devparam[i].dev_flags |= DPARM_DISC;
+ sdp->isp_devparam[i].cur_dflags = 0; /* we don't know */
if (isp->isp_dblev > 2) {
PRINTF(" Target %d: Enabled %d Throttle %d "
"Offset %d Period %d Flags 0x%x\n", i,