summaryrefslogtreecommitdiff
path: root/sys/dev/isp/isp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r--sys/dev/isp/isp.c813
1 files changed, 198 insertions, 615 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 1b8b9d893a7e..b93775007e83 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -1,5 +1,4 @@
-/* $Id: isp.c,v 1.10 1999/01/10 02:55:10 mjacob Exp $ */
-/* release_12_28_98_A+ */
+/* $FreeBSD$ */
/*
* Machine and OS Independent (well, as best as possible)
* code for the Qlogic ISP SCSI adapters.
@@ -52,7 +51,7 @@
#include <dev/isp/isp_freebsd.h>
#endif
#ifdef __linux__
-#include "isp_linux.h"
+#include <isp_linux.h>
#endif
/*
@@ -64,7 +63,7 @@
/*
* Local static data
*/
-#ifdef ISP_TARGET_MODE
+#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)
static const char tgtiqd[36] = {
0x03, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
0x51, 0x4C, 0x4F, 0x47, 0x49, 0x43, 0x20, 0x20,
@@ -89,16 +88,11 @@ static const char tgtiqd[36] = {
/*
* Local function prototypes.
*/
-static int isp_parse_async __P((struct ispsoftc *, int));
+static int isp_parse_async __P((struct ispsoftc *, u_int16_t));
static int isp_handle_other_response
__P((struct ispsoftc *, ispstatusreq_t *, u_int8_t *));
-#ifdef ISP_TARGET_MODE
+#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)
static int isp_modify_lun __P((struct ispsoftc *, int, int, int));
-static void isp_notify_ack __P((struct ispsoftc *, void *));
-static void isp_handle_atio __P((struct ispsoftc *, void *));
-static void isp_handle_atio2 __P((struct ispsoftc *, void *));
-static void isp_handle_ctio __P((struct ispsoftc *, void *));
-static void isp_handle_ctio2 __P((struct ispsoftc *, void *));
#endif
static void isp_parse_status
__P((struct ispsoftc *, ispstatusreq_t *, ISP_SCSI_XFER_T *));
@@ -107,7 +101,7 @@ static void isp_fw_state __P((struct ispsoftc *));
static void isp_dumpregs __P((struct ispsoftc *, const char *));
static void isp_dumpxflist __P((struct ispsoftc *));
static void isp_prtstst __P((ispstatusreq_t *));
-static char *isp2100_fw_statename __P((int));
+static char *isp2100_fw_statename __P((u_int8_t));
static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *));
static void isp_update __P((struct ispsoftc *));
@@ -128,7 +122,7 @@ isp_reset(isp)
{
static char once = 1;
mbreg_t mbs;
- int loops, i, dodnld = 1, deadchip;
+ int loops, i, dodnld = 1;
char *revname;
isp->isp_state = ISP_NILSTATE;
@@ -139,26 +133,16 @@ isp_reset(isp)
* here.
*/
isp->isp_dblev = DFLT_DBLEVEL;
- deadchip = ISP_READ(isp, HCCR) & HCCR_RESET;
- if (deadchip) {
- ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
- if (ISP_READ(isp, HCCR) & HCCR_RESET) {
- isp_dumpregs(isp, "still reset after release");
- SYS_DELAY(1000);
- } else {
- deadchip = 1;
- }
- }
-
if (isp->isp_type & ISP_HA_FC) {
revname = "2100";
} else {
sdparam *sdp = isp->isp_param;
- i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
- switch (i) {
+
+ int rev = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
+ switch (rev) {
default:
PRINTF("%s: unknown chip rev. 0x%x- assuming a 1020\n",
- isp->isp_name, i);
+ isp->isp_name, rev);
/* FALLTHROUGH */
case 1:
revname = "1020";
@@ -195,20 +179,16 @@ isp_reset(isp)
* Try and figure out if we're connected to a differential bus.
* You have to pause the RISC processor to read SXP registers.
*/
- if (deadchip == 0) {
- ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
- i = 100;
- while ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
- SYS_DELAY(20);
- if (--i == 0) {
- isp_dumpregs(isp,
- "cannot stop RISC processor");
- i = -1;
- break;
- }
+ ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+ i = 100;
+ while ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
+ SYS_DELAY(20);
+ if (--i == 0) {
+ PRINTF("%s: unable to pause RISC processor\n",
+ isp->isp_name);
+ i = -1;
+ break;
}
- } else {
- i = 0;
}
if (i > 0) {
if (isp->isp_bustype != ISP_BT_SBUS) {
@@ -243,10 +223,9 @@ isp_reset(isp)
sdp->isp_clock = 40;
}
/*
- * Restart processor, if necessary.
+ * Restart processor
*/
- if (deadchip == 0)
- ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
+ ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
}
/*
* Machine dependent clock (if set) overrides
@@ -264,7 +243,7 @@ isp_reset(isp)
*/
ISP_RESET0(isp);
- if (once == 1 && deadchip == 0) {
+ if (once == 1) {
once = 0;
/*
* Get the current running firmware revision out of the
@@ -285,7 +264,6 @@ isp_reset(isp)
}
}
-
/*
* Hit the chip over the head with hammer,
* and give the ISP a chance to recover.
@@ -353,21 +331,9 @@ isp_reset(isp)
ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
SYS_DELAY(100);
- /*
- * Establish some initial burst rate thingies
- * (only for the 1XX0 boards). This really should
- * be done later after fetching from NVRAM.
- */
if (isp->isp_type & ISP_HA_SCSI) {
- u_int16_t conf1 = isp->isp_mdvec->dv_conf1;
- /*
- * Busted FIFO. Turn off all but burst enables.
- */
- if (isp->isp_type == ISP_HA_SCSI_1040A) {
- conf1 &= BIU_BURST_ENABLE;
- }
- ISP_SETBITS(isp, BIU_CONF1, conf1);
- if (conf1 & BIU_BURST_ENABLE) {
+ ISP_SETBITS(isp, BIU_CONF1, isp->isp_mdvec->dv_conf1);
+ if (isp->isp_mdvec->dv_conf1 & BIU_BURST_ENABLE) {
ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST);
ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST);
}
@@ -740,7 +706,7 @@ isp_fibre_init(isp)
fcparam *fcp;
isp_icb_t *icbp;
mbreg_t mbs;
- int count, loopid;
+ int count;
u_int8_t lwfs;
fcp = isp->isp_param;
@@ -749,41 +715,16 @@ isp_fibre_init(isp)
PRINTF("%s: can't setup DMA for mailboxes\n", isp->isp_name);
return;
}
- /*
- * For systems that don't have BIOS methods for which
- * we can easily change the NVRAM based loopid, we'll
- * override that here. Note that when we initialize
- * the firmware we may get back a different loopid than
- * we asked for anyway. XXX This is probably not the
- * best way to figure this out XXX
- */
-#ifndef __i386__
- loopid = DEFAULT_LOOPID;
-#else
- loopid = fcp->isp_loopid;
-#endif
-
icbp = (isp_icb_t *) fcp->isp_scratch;
- MEMZERO(icbp, sizeof (*icbp));
+ bzero(icbp, sizeof (*icbp));
icbp->icb_version = ICB_VERSION1;
-#ifdef ISP_TARGET_MODE
- fcp->isp_fwoptions = ICBOPT_TGT_ENABLE|ICBOPT_INI_TGTTYPE;
-#else
+
fcp->isp_fwoptions = 0;
-#endif
- fcp->isp_fwoptions |= ICBOPT_INI_ADISC|ICBOPT_FAIRNESS;
- fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
- fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
-#ifdef CHECKME
- fcp->isp_fwoptions |= ICBOPT_USE_PORTNAME;
-#endif
-#ifdef THIS_WORKED
- /*
- * This has unhappiness in target mode
- */
- fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;
+#ifdef ISP2100_TARGET_MODE
+ fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE | ICBOPT_INI_TGTTYPE;
+ icbp->icb_iqdevtype = 0x23; /* DPQ_SUPPORTED/PROCESSOR */
#endif
icbp->icb_fwoptions = fcp->isp_fwoptions;
icbp->icb_maxfrmlen = fcp->isp_maxfrmlen;
@@ -796,13 +737,9 @@ isp_fibre_init(isp)
icbp->icb_execthrottle = fcp->isp_execthrottle;
icbp->icb_retry_delay = fcp->isp_retry_delay;
icbp->icb_retry_count = fcp->isp_retry_count;
- icbp->icb_hardaddr = loopid;
MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwn);
- if (icbp->icb_fwoptions & ICBOPT_USE_PORTNAME) {
- u_int64_t portname = fcp->isp_wwn | (2LL << 56);
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, portname);
- }
+
icbp->icb_rqstqlen = RQUEST_QUEUE_LEN;
icbp->icb_rsltqlen = RESULT_QUEUE_LEN;
icbp->icb_rqstaddr[RQRSP_ADDR0015] =
@@ -851,15 +788,24 @@ isp_fibre_init(isp)
isp->isp_residx = 0;
/*
- * Wait up to 5 seconds for FW to go to READY state.
+ * Wait up to 12 seconds for FW to go to READY state.
+ * This used to be 3 seconds, but that lost.
+ *
+ * This is all very much not right. The problem here
+ * is that the cable may not be plugged in, or there
+ * may be many many members of the loop that haven't
+ * been logged into.
+ *
+ * This model of doing things doesn't support dynamic
+ * attachment, so we just plain lose (for now).
*/
lwfs = FW_CONFIG_WAIT;
for (count = 0; count < 12000; count++) {
isp_fw_state(isp);
if (lwfs != fcp->isp_fwstate) {
PRINTF("%s: Firmware State %s -> %s\n",
- isp->isp_name, isp2100_fw_statename((int)lwfs),
- isp2100_fw_statename((int)fcp->isp_fwstate));
+ isp->isp_name, isp2100_fw_statename(lwfs),
+ isp2100_fw_statename(fcp->isp_fwstate));
lwfs = fcp->isp_fwstate;
}
if (fcp->isp_fwstate == FW_READY) {
@@ -882,14 +828,16 @@ isp_fibre_init(isp)
}
fcp->isp_loopid = mbs.param[1];
fcp->isp_alpa = mbs.param[2];
- PRINTF("%s: Loop ID %d, ALPA 0x%x\n", isp->isp_name,
+ PRINTF("%s: Loop ID 0x%x, ALPA 0x%x\n", isp->isp_name,
fcp->isp_loopid, fcp->isp_alpa);
isp->isp_state = ISP_INITSTATE;
-#ifdef ISP_TARGET_MODE
+#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)
DISABLE_INTS(isp);
- if (isp_modify_lun(isp, 0, 1, 1)) {
- PRINTF("%s: failed to enable target mode\n",
- isp->isp_name);
+ if (isp->isp_fwrev >= ISP_FW_REV(1, 13)) {
+ if (isp_modify_lun(isp, 0, 1, 1)) {
+ PRINTF("%s: failed to establish target mode\n",
+ isp->isp_name);
+ }
}
ENABLE_INTS(isp);
#endif
@@ -900,6 +848,29 @@ isp_fibre_init(isp)
}
/*
+ * Free any associated resources prior to decommissioning and
+ * set the card to a known state (so it doesn't wake up and kick
+ * us when we aren't expecting it to).
+ *
+ * Locks are held before coming here.
+ */
+void
+isp_uninit(isp)
+ struct ispsoftc *isp;
+{
+ /*
+ * Leave with interrupts disabled.
+ */
+ DISABLE_INTS(isp);
+
+ /*
+ * Stop the watchdog timer (if started).
+ */
+ STOP_WATCHDOG(isp_watch, isp);
+}
+
+
+/*
* Start a command. Locking is assumed done in the caller.
*/
@@ -964,7 +935,7 @@ ispscsicmd(xs)
u_int8_t niptr;
ispmarkreq_t *marker = (ispmarkreq_t *) reqp;
- MEMZERO((void *) marker, sizeof (*marker));
+ bzero((void *) marker, sizeof (*marker));
marker->req_header.rqs_entry_count = 1;
marker->req_header.rqs_entry_type = RQSTYPE_MARKER;
marker->req_modifier = SYNC_ALL;
@@ -991,7 +962,7 @@ ispscsicmd(xs)
iptr = niptr;
}
- MEMZERO((void *) reqp, UZSIZE);
+ bzero((void *) reqp, UZSIZE);
reqp->req_header.rqs_entry_count = 1;
if (isp->isp_type & ISP_HA_FC) {
reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
@@ -1046,19 +1017,12 @@ ispscsicmd(xs)
reqp->req_flags = 0;
}
}
+ reqp->req_lun_trn = XS_LUN(xs);
reqp->req_target = XS_TGT(xs);
if (isp->isp_type & ISP_HA_SCSI) {
- reqp->req_lun_trn = XS_LUN(xs);
reqp->req_cdblen = XS_CDBLEN(xs);
- } else {
-#ifdef SCCLUN
- reqp->req_scclun = XS_LUN(xs);
-#else
- reqp->req_lun_trn = XS_LUN(xs);
-#endif
-
}
- MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs));
+ bcopy((void *)XS_CDBP(xs), reqp->req_cdb, XS_CDBLEN(xs));
IDPRINTF(5, ("%s(%d.%d): START%d cmd 0x%x datalen %d\n", isp->isp_name,
XS_TGT(xs), XS_LUN(xs), reqp->req_header.rqs_seqno,
@@ -1158,18 +1122,7 @@ isp_control(isp, ctl, arg)
break;
}
mbs.param[0] = MBOX_ABORT;
-#ifdef SCCLUN
- if (isp->isp_type & ISP_HA_FC) {
- mbs.param[1] = XS_TGT(xs) << 8;
- mbs.param[4] = 0;
- mbs.param[5] = 0;
- mbs.param[6] = XS_LUN(xs);
- } else {
- mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs);
- }
-#else
- mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs);
-#endif
+ mbs.param[1] = XS_TGT(xs) | XS_LUN(xs);
mbs.param[2] = (i+1) >> 16;
mbs.param[3] = (i+1) & 0xffff;
isp_mboxcmd(isp, &mbs);
@@ -1227,7 +1180,7 @@ isp_intr(arg)
if (ISP_READ(isp, BIU_SEMA) & 1) {
u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0);
- if (isp_parse_async(isp, (int) mbox))
+ if (isp_parse_async(isp, mbox))
return (1);
ISP_WRITE(isp, BIU_SEMA, 0);
}
@@ -1319,14 +1272,14 @@ isp_intr(arg)
XS_STS(xs) = sp->req_scsi_status & 0xff;
if (isp->isp_type & ISP_HA_SCSI) {
if (sp->req_state_flags & RQSF_GOT_SENSE) {
- MEMCPY(XS_SNSP(xs), sp->req_sense_data,
+ bcopy(sp->req_sense_data, XS_SNSP(xs),
XS_SNSLEN(xs));
XS_SNS_IS_VALID(xs);
}
} else {
if (XS_STS(xs) == SCSI_CHECK) {
XS_SNS_IS_VALID(xs);
- MEMCPY(XS_SNSP(xs), sp->req_sense_data,
+ bcopy(sp->req_sense_data, XS_SNSP(xs),
XS_SNSLEN(xs));
sp->req_state_flags |= RQSF_GOT_SENSE;
}
@@ -1346,9 +1299,8 @@ isp_intr(arg)
} else {
PRINTF("%s: unknown return %x\n", isp->isp_name,
sp->req_header.rqs_entry_type);
- if (XS_NOERR(xs)) {
+ if (XS_NOERR(xs))
XS_SETERR(xs, HBA_BOTCH);
- }
}
if (isp->isp_type & ISP_HA_SCSI) {
XS_RESID(xs) = sp->req_resid;
@@ -1368,8 +1320,7 @@ isp_intr(arg)
*/
if (XS_STS(xs) == SCSI_CHECK && !(XS_IS_SNS_VALID(xs))) {
if (XS_NOERR(xs)) {
- PRINTF("%s: ARQ failure for target %d lun %d\n",
- isp->isp_name, XS_TGT(xs), XS_LUN(xs));
+ PRINTF("%s: ARQ Failure\n", isp->isp_name);
XS_SETERR(xs, HBA_ARQFAIL);
}
}
@@ -1389,8 +1340,9 @@ isp_intr(arg)
}
ISP_WRITE(isp, INMAILBOX5, optr);
- if (isp->isp_nactive > 0)
- isp->isp_nactive--;
+ isp->isp_nactive--;
+ if (isp->isp_nactive < 0)
+ isp->isp_nactive = 0;
complist[ndone++] = xs; /* defer completion call until later */
}
/*
@@ -1417,15 +1369,12 @@ isp_intr(arg)
static int
isp_parse_async(isp, mbox)
struct ispsoftc *isp;
- int mbox;
+ u_int16_t mbox;
{
switch (mbox) {
case ASYNC_BUS_RESET:
PRINTF("%s: SCSI bus reset detected\n", isp->isp_name);
isp->isp_sendmarker = 1;
-#ifdef ISP_TARGET_MODE
- isp_notify_ack(isp, NULL);
-#endif
break;
case ASYNC_SYSTEM_ERROR:
@@ -1452,16 +1401,10 @@ isp_parse_async(isp, mbox)
case ASYNC_TIMEOUT_RESET:
PRINTF("%s: timeout initiated SCSI bus reset\n", isp->isp_name);
isp->isp_sendmarker = 1;
-#ifdef ISP_TARGET_MODE
- isp_notify_ack(isp, NULL);
-#endif
break;
- case ASYNC_DEVICE_RESET:
- PRINTF("%s: device reset\n", isp->isp_name);
-#ifdef ISP_TARGET_MODE
- isp_notify_ack(isp, NULL);
-#endif
+ case ASYNC_UNSPEC_TMODE:
+ PRINTF("%s: mystery async target completion\n", isp->isp_name);
break;
case ASYNC_EXTMSG_UNDERRUN:
@@ -1497,7 +1440,6 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_CTIO_DONE:
- /* Should only occur when Fast Posting Set for 2100s */
PRINTF("%s: CTIO done\n", isp->isp_name);
break;
@@ -1515,9 +1457,6 @@ isp_parse_async(isp, mbox)
case ASYNC_LOOP_RESET:
PRINTF("%s: Loop RESET\n", isp->isp_name);
-#ifdef ISP_TARGET_MODE
- isp_notify_ack(isp, NULL);
-#endif
break;
case ASYNC_PDB_CHANGED:
@@ -1544,122 +1483,62 @@ isp_handle_other_response(isp, sp, optrp)
u_int8_t iptr, optr;
int reqsize = 0;
void *ireqp = NULL;
-#ifdef ISP_TARGET_MODE
- union {
- at_entry_t *atio;
- at2_entry_t *at2io;
- ct_entry_t *ctio;
- ct2_entry_t *ct2io;
- lun_entry_t *lunen;
- in_entry_t *inot;
- in_fcentry_t *inot_fc;
- na_entry_t *nack;
- na_fcentry_t *nack_fc;
- void *voidp;
-#define atio un.atio
-#define at2io un.at2io
-#define ctio un.ctio
-#define ct2io un.ct2io
-#define lunen un.lunen
-#define inot un.inot
-#define inot_fc un.inot_fc
-#define nack un.nack
-#define nack_fc un.nack_fc
- } un;
-
- un.voidp = sp;
-#endif
-
switch (sp->req_header.rqs_entry_type) {
case RQSTYPE_REQUEST:
return (-1);
-#ifdef ISP_TARGET_MODE
+#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)
case RQSTYPE_NOTIFY_ACK:
{
- static const char *f =
- "%s: Notify Ack Status 0x%x Sequence Id 0x%x\n"
- /*
- * The ISP is acknowleding our ack of an Immediate Notify.
- */
- if (isp->isp_type & ISP_HA_FC) {
- PRINTF(f, isp->isp_name,
- nack_fc->na-status, nack_fc->na_seqid);
- } else {
- PRINTF(f, isp->isp_name,
- nack->na_status, nack->na_seqid);
- }
+ ispnotify_t *spx = (ispnotify_t *) sp;
+ PRINTF("%s: Immediate Notify Ack %d.%d Status 0x%x Sequence "
+ "0x%x\n", isp->isp_name, spx->req_initiator, spx->req_lun,
+ spx->req_status, spx->req_sequence);
break;
}
case RQSTYPE_NOTIFY:
{
- u_int16_t seqid, status;
-
- /*
- * Either the ISP received a SCSI message it cannot handle
- * or some other out of band condition (e.g., Port Logout)
- * or it is returning an Immediate Notify entry we sent.
- */
- if (isp->isp_type & ISP_HA_FC) {
- status = inot_fc->status;
- seqid = inot_fc->in_seqid;
- } else {
- status = inot->status;
- seqid = inot->seqid & 0xff;
- }
- PRINTF("%s: Immediate Notify Status 0x%x Sequence Id 0x%x\n",
- isp->isp_name, status, seqid);
-
- switch (status) {
- case IN_MSG_RECEIVED:
- case IN_IDE_RECEIVED:
- 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: Abort Task iid %d rx_id 0x%x\n",
- inot_fc->in_iid, seqid);
- break;
- case IN_PORT_LOGOUT:
- PRINTF("%s: Port Logout for Initiator %d\n",
- isp->isp_name, inot_fc->in_iid);
- break;
- default:
- PRINTF("%s: bad status (0x%x) in Immediate Notify\n",
- isp->isp_name, status);
- break;
-
- }
- isp_notify_ack(isp, un.voidp);
- reqsize = 0;
+ ispnotify_t *spx = (ispnotify_t *) sp;
+
+ PRINTF("%s: Notify loopid %d to lun %d req_status 0x%x "
+ "req_task_flags 0x%x seq 0x%x\n", isp->isp_name, spx->req_initiator, spx->req_lun, spx->req_status,
+ spx->req_task_flags, spx->req_sequence);
+ reqsize = sizeof (*spx);
+ spx->req_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
+ spx->req_header.rqs_entry_count = 1;
+ spx->req_header.rqs_flags = 0;
+ spx->req_header.rqs_seqno = isp->isp_seqno++;
+ spx->req_handle = (spx->req_initiator<<16) | RQSTYPE_NOTIFY_ACK;
+ if (spx->req_status == IN_RSRC_UNAVAIL)
+ spx->req_flags = LUN_INCR_CMD;
+ else if (spx->req_status == IN_NOCAP)
+ spx->req_flags = LUN_INCR_IMMED;
+ else {
+ reqsize = 0;
+ }
+ ireqp = spx;
break;
}
case RQSTYPE_ENABLE_LUN:
- case RQSTYPE_MODIFY_LUN:
- if (lunen->req_status != 1) {
- PRINTF("%s: ENABLE/MODIFY LUN returned status 0x%x\n",
- isp->isp_name, lunen->req_status);
+ {
+ isplun_t *ip = (isplun_t *) sp;
+ if (ip->req_status != 1) {
+ PRINTF("%s: ENABLE LUN returned status 0x%x\n",
+ isp->isp_name, ip->req_status);
}
break;
+ }
case RQSTYPE_ATIO2:
{
fcparam *fcp = isp->isp_param;
ispctiot2_t local, *ct2 = NULL;
ispatiot2_t *at2 = (ispatiot2_t *) sp;
- int s, lun;
+ int s;
-#ifdef SCCLUN
- lun = at2->req_scclun;
-#else
- lun = at2->req_lun;
-#endif
- PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags0x%x "
- "tflags0x%x ecodes0x%x rqstatus0x%x\n", isp->isp_name,
- at2->req_initiator, lun, at2->req_rxid,
- at2->req_flags, at2->req_taskflags, at2->req_execodes,
- at2->req_status);
+ PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags 0x%x "
+ "task flags 0x%x exec codes 0x%x\n", isp->isp_name,
+ at2->req_initiator, at2->req_lun, at2->req_rxid,
+ at2->req_flags, at2->req_taskflags, at2->req_execodes);
switch (at2->req_status & ~ATIO_SENSEVALID) {
case ATIO_PATH_INVALID:
@@ -1692,15 +1571,13 @@ isp_handle_other_response(isp, sp, optrp)
}
PRINTF("%s: datalen %d cdb0=0x%x\n", isp->isp_name,
at2->req_datalen, at2->req_cdb[0]);
- MEMZERO((void *) ct2, sizeof (*ct2));
+ bzero ((void *) ct2, sizeof (*ct2));
ct2->req_header.rqs_entry_type = RQSTYPE_CTIO2;
ct2->req_header.rqs_entry_count = 1;
ct2->req_header.rqs_flags = 0;
ct2->req_header.rqs_seqno = isp->isp_seqno++;
- ct2->req_handle = (at2->req_initiator << 16) | lun;
-#ifndef SCCLUN
- ct2->req_lun = lun;
-#endif
+ ct2->req_handle = (at2->req_initiator << 16) | at2->req_lun;
+ ct2->req_lun = at2->req_lun;
ct2->req_initiator = at2->req_initiator;
ct2->req_rxid = at2->req_rxid;
@@ -1718,16 +1595,16 @@ isp_handle_other_response(isp, sp, optrp)
ct2->req_seg_count = 1;
if (at2->req_cdb[0] == 0x12) {
s = sizeof(tgtiqd);
- MEMCPY(fcp->isp_scratch, tgtiqd, s);
+ bcopy((void *)tgtiqd, fcp->isp_scratch, s);
} else {
s = at2->req_datalen;
- MEMZERO(fcp->isp_scratch, s);
+ bzero(fcp->isp_scratch, s);
}
ct2->req_m.mode0.req_dataseg[0].ds_base =
fcp->isp_scdma;
ct2->req_m.mode0.req_dataseg[0].ds_count = s;
ct2->req_m.mode0.req_datalen = s;
-#if 1
+#if 0
if (at2->req_datalen < s) {
ct2->req_m.mode1.req_scsi_status |=
CTIO2_RESP_VALID|CTIO2_RSPOVERUN;
@@ -1741,7 +1618,7 @@ isp_handle_other_response(isp, sp, optrp)
default: /* ALL OTHERS */
ct2->req_flags |= CTIO_NODATA | CTIO2_SMODE1;
ct2->req_m.mode1.req_scsi_status = 0;
-#if 1
+#if 0
if (at2->req_datalen) {
ct2->req_m.mode1.req_scsi_status |=
CTIO2_RSPUNDERUN;
@@ -1773,8 +1650,9 @@ isp_handle_other_response(isp, sp, optrp)
ct2->req_m.mode1.req_sense_len = 18;
ct2->req_m.mode1.req_scsi_status |=
at2->req_scsi_status;
- MEMCPY(ct2->req_m.mode1.req_response,
- at2->req_sense, sizeof (at2->req_sense));
+ bcopy((void *)at2->req_sense,
+ (void *)ct2->req_m.mode1.req_response,
+ sizeof (at2->req_sense));
}
break;
}
@@ -1801,15 +1679,6 @@ isp_handle_other_response(isp, sp, optrp)
ireqp = at2;
break;
}
-#undef atio
-#undef at2io
-#undef ctio
-#undef ct2io
-#undef lunen
-#undef inot
-#undef inot_fc
-#undef nack
-#undef nack_fc
#endif
default:
PRINTF("%s: other response type %x\n", isp->isp_name,
@@ -1826,7 +1695,7 @@ isp_handle_other_response(isp, sp, optrp)
PRINTF("%s: Request Queue Overflow other response\n",
isp->isp_name);
} else {
- MEMCPY(reqp, ireqp, reqsize);
+ bcopy(ireqp, reqp, reqsize);
ISP_WRITE(isp, INMAILBOX4, iptr);
isp->isp_reqidx = iptr;
}
@@ -1834,37 +1703,7 @@ isp_handle_other_response(isp, sp, optrp)
return (0);
}
-#ifdef ISP_TARGET_MODE
-
-static void isp_tmd_newcmd_dflt __P((void *, tmd_cmd_t *));
-static void isp_tmd_event_dflt __P((void *, int));
-static void isp_tmd_notify_dflt __P((void *, tmd_notify_t *));
-
-static void isp_tgt_data_xfer __P ((tmd_cmd_t *));
-static void isp_tgt_endcmd __P ((tmd_cmd_t *, u_int8_t));
-static void isp_tgt_done __P ((tmd_cmd_t *));
-
-static void
-isp_tmd_newcmd_dflt(arg0, cmdp)
- void *arg0;
- tmd_cmd_t *cmdp;
-{
-}
-
-static void
-isp_tmd_event_dflt(arg0, event)
- void *arg0;
- int event;
-{
-}
-
-static void
-isp_tmd_notify_dflt(arg0, npt)
- void *arg0;
- tmd_notify_t *npt;
-{
-}
-
+#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)
/*
* Locks held, and ints disabled (if FC).
*
@@ -1890,14 +1729,13 @@ isp_modify_lun(isp, lun, icnt, ccnt)
return (-1);
}
- MEMZERO((void *) ip, sizeof (*ip));
+ bzero((void *) ip, sizeof (*ip));
ip->req_header.rqs_entry_type = RQSTYPE_ENABLE_LUN;
ip->req_header.rqs_entry_count = 1;
+ ip->req_header.rqs_flags = 0;
ip->req_header.rqs_seqno = isp->isp_seqno++;
ip->req_handle = RQSTYPE_ENABLE_LUN;
- if (isp->isp_type & ISP_HA_SCSI) {
- ip->req_lun = lun;
- }
+ ip->req_lun = lun;
ip->req_cmdcount = ccnt;
ip->req_imcount = icnt;
ip->req_timeout = 0; /* default 30 seconds */
@@ -1905,263 +1743,6 @@ isp_modify_lun(isp, lun, icnt, ccnt)
isp->isp_reqidx = iptr;
return (0);
}
-
-static void
-isp_notify_ack(isp, ptrp)
- struct ispsoftc *isp;
- void *ptrp;
-{
- void *reqp;
- u_int8_t iptr, optr;
- union {
- na_fcentry_t _naf;
- na_entry_t _nas;
- } un;
-
- MEMZERO((caddr_t)&un, sizeof (un));
- un._nas.na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
- un._nas.na_header.rqs_entry_count = 1;
-
- if (isp->isp_type & ISP_HA_FC) {
- na_fcentry_t *na = &un._nas;
- if (ptrp) {
- in_fcentry_t *inp = ptrp;
- na->na_iid = inp->in_iid;
- na->na_lun = inp->in_lun;
- na->na_task_flags = inp->in_task_flags;
- na->na_seqid = inp->in_seqid;
- na->na_status = inp->in_status;
- } else {
- na->na_flags = NAFC_RST_CLRD;
- }
- } else {
- na_entry_t *na = &un._nas;
- if (ptrp) {
- in_entry_t *inp = ptrp;
- na->na_iid = inp->in_iid;
- na->na_lun = inp->in_lun;
- na->na_tgt = inp->in_tgt;
- na->na_seqid = inp->in_seqid;
- } else {
- na->na_flags = NA_RST_CLRD;
- }
- }
- optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);
- iptr = isp->isp_reqidx;
- reqp = (void *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
- iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN);
- if (iptr == optr) {
- PRINTF("%s: Request Queue Overflow For isp_notify_ack\n",
- isp->isp_name);
- } else {
- MEMCPY(reqp, ireqp, sizeof (un));
- ISP_WRITE(isp, INMAILBOX4, iptr);
- isp->isp_reqidx = iptr;
- }
-}
-
-/*
- * These are dummy stubs for now until the outside framework is plugged in.
- */
-
-static void
-isp_handle_atio (isp, aep)
- struct ispsoftc *isp;
- at_entry_t *aep;
-{
- int status, connected;
- tmd_cmd_t local, *cdp = &local;
-
- /*
- * Get the ATIO status and see if we're still connected.
- */
- status = aep->at_status;
- connected = ((aep->at_flags & AT_NODISC) != 0);
-
- PRINTF("%s: ATIO status=0x%x, connected=%d\n", isp->isp_name,
- status, connected);
-
- /*
- * The firmware status (except for the SenseValid bit) indicates
- * why this ATIO was sent to us.
- * If SenseValid is set, the firware has recommended Sense Data.
- * If the Disconnects Disabled bit is set in the flags field,
- * we're still connected on the SCSI bus - i.e. the initiator
- * did not set DiscPriv in the identify message. We don't care
- * about this so it's ignored.
- */
- switch(status & ~TGTSVALID) {
- case AT_PATH_INVALID:
- /*
- * ATIO rejected by the firmware due to disabled lun.
- */
- PRINTF("%s: Firmware rejected ATIO for disabled lun %d\n",
- isp->isp_name, aep->at_lun);
- break;
-
- case AT_PHASE_ERROR:
- /*
- * Bus Pase Sequence error.
- *
- * The firmware should have filled in the correct
- * sense data.
- */
-
-
- if (status & TGTSVALID) {
- MEMCPY(&cdp->cd_sensedata, aep->at_sense,
- sizeof (cdp->cd_sensedata));
- PRINTF("%s: Bus Phase Sequence error key 0x%x\n",
- isp->isp_name, cdp->cd_sensedata[2] & 0xf);
- } else {
- PRINTF("%s: Bus Phase Sequence With No Sense\n",
- isp->isp_name);
- }
- (*isp->isp_tmd_newcmd)(isp, cdp);
- break;
-
- case AT_NOCAP:
- /*
- * Requested Capability not available
- * We sent an ATIO that overflowed the firmware's
- * command resource count.
- */
- PRINTF("%s: Firmware rejected ATIO, command count overflow\n",
- isp->isp_name);
- break;
-
- case AT_BDR_MSG:
- /*
- * If we send an ATIO to the firmware to increment
- * its command resource count, and the firmware is
- * recovering from a Bus Device Reset, it returns
- * the ATIO with this status.
- */
- PRINTF("%s: ATIO returned with BDR received\n", isp->isp_name);
- break;
-
- case AT_CDB:
- /*
- * New CDB
- */
- cdp->cd_hba = isp;
- cdp->cd_iid = aep->at_iid;
- cdp->cd_tgt = aep->at_tgt;
- cdp->cd_lun = aep->at_lun;
- cdp->cd_tagtype = aep->at_tag_type;
- cdp->cd_tagval = aep->at_tag_val;
- MEMCPY(cdp->cd_cdb, aep->at_cdb, 16);
- PRINTF("%s: CDB 0x%x itl %d/%d/%d\n", isp->isp_name,
- cdp->cd_cdb[0], cdp->cd_iid, cdp->cd_tgt, cdp->cd_lun);
- (*isp->isp_tmd_newcmd)(isp, cdp);
- break;
-
- default:
- PRINTF("%s: Unknown status (0x%x) in ATIO\n",
- isp->isp_name, status);
- cdp->cd_hba = isp;
- cdp->cd_iid = aep->at_iid;
- cdp->cd_tgt = aep->at_tgt;
- cdp->cd_lun = aep->at_lun;
- cdp->cd_tagtype = aep->at_tag_type;
- cdp->cd_tagval = aep->at_tag_val;
- isp_tgtcmd_done(cdp);
- break;
- }
-}
-
-static void
-isp_handle_atio2(isp, aep)
- struct ispsoftc *isp;
- at2_entry_t *aep;
-{
- int status;
- tmd_cmd_t local, *cdp = &local;
-
- /*
- * Get the ATIO2 status.
- */
- status = aep->at_status;
- PRINTD("%s: ATIO2 status=0x%x\n", status);
-
- /*
- * The firmware status (except for the SenseValid bit) indicates
- * why this ATIO was sent to us.
- * If SenseValid is set, the firware has recommended Sense Data.
- */
- switch(status & ~TGTSVALID) {
- case AT_PATH_INVALID:
- /*
- * ATIO rejected by the firmware due to disabled lun.
- */
- PRINTF("%s: Firmware rejected ATIO2 for disabled lun %d\n",
- isp->isp_name, aep->at_lun);
- break;
-
- case AT_NOCAP:
- /*
- * Requested Capability not available
- * We sent an ATIO that overflowed the firmware's
- * command resource count.
- */
- PRINTF("%s: Firmware rejected ATIO2, command count overflow\n",
- isp->isp_name);
- break;
-
- case AT_BDR_MSG:
- /*
- * If we send an ATIO to the firmware to increment
- * its command resource count, and the firmware is
- * recovering from a Bus Device Reset, it returns
- * the ATIO with this status.
- */
- PRINTF("%s: ATIO2 returned with BDR rcvd\n", isp->isp_name);
- break;
-
- case AT_CDB:
- /*
- * New CDB
- */
- cdp->cd_hba = isp;
- cdp->cd_iid = aep->at_iid;
- cdp->cd_tgt = 0;
- cdp->cd_lun = aep->at_lun;
- MEMCPY(cdp->cd_cdb, aep->at_cdb, 16);
- cdp->cd_rxid = aep->at_rxid;
- cdp->cp_origdlen = aep->at_datalen;
- cdp->cp_totbytes = 0;
- PRINTF("%s: CDB 0x%x rx_id 0x%x itl %d/%d/%d dlen %d\n",
- isp->isp_name, cdp->cd_cdb[0], cdp->cd_tagval, cdp->cd_iid,
- cdp->cd_tgt, cdp->cd_lun, aep->at_datalen);
- (*isp->isp_tmd_newcmd)(isp, cdp);
- break;
-
- default:
- PRINTF("%s: Unknown status (0x%x) in ATIO2\n",
- isp->isp_name, status);
- cdp->cd_hba = isp;
- cdp->cd_iid = aep->at_iid;
- cdp->cd_tgt = aep->at_tgt;
- cdp->cd_lun = aep->at_lun;
- cdp->cp_rxid = aep->at_rxid;
- isp_tgtcmd_done(cdp);
- break;
- }
-}
-
-static void
-isp_handle_ctio(isp, cep)
- struct ispsoftc *isp;
- ct_entry_t *aep;
-{
-}
-
-static void
-isp_handle_ctio2(isp, cep)
- struct ispsoftc *isp;
- at2_entry_t *aep;
-{
-}
#endif
static void
@@ -2288,7 +1869,7 @@ isp_parse_status(isp, sp, xs)
break;
case RQCS_UNEXP_BUS_FREE:
- PRINTF("%s: target %d lun %d had an unexpected bus free\n",
+ PRINTF("%s: target %d lun %d had unexeptected bus free\n",
isp->isp_name, XS_TGT(xs), XS_LUN(xs));
break;
@@ -2323,17 +1904,8 @@ isp_parse_status(isp, sp, xs)
break;
case RQCS_QUEUE_FULL:
- PRINTF("%s: internal queues full for target %d lun %d "
- "status 0x%x\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs),
- XS_STS(xs));
- /*
- * If QFULL or some other status byte is set, then this
- * isn't an error, per se.
- */
- if (XS_STS(xs) != 0) {
- XS_SETERR(xs, HBA_NOERROR);
- return;
- }
+ PRINTF("%s: internal queues full for target %d lun %d\n",
+ isp->isp_name, XS_TGT(xs), XS_LUN(xs));
break;
case RQCS_PHASE_SKIPPED:
@@ -2556,29 +2128,6 @@ isp_mboxcmd(isp, mbp)
}
- /*
- * Check for variants
- */
-#ifdef SCCLUN
- if (isp->isp_type & ISP_HA_FC) {
- switch (mbp->param[0]) {
- case MBOX_ABORT:
- inparam = 7;
- break;
- case MBOX_ABORT_DEVICE:
- case MBOX_START_QUEUE:
- case MBOX_STOP_QUEUE:
- case MBOX_SINGLE_STEP_QUEUE:
- case MBOX_ABORT_QUEUE:
- case MBOX_GET_DEV_QUEUE_STATUS:
- inparam = 3;
- break;
- default:
- break;
- }
- }
-#endif
-
command_known:
/*
@@ -2597,7 +2146,7 @@ command_known:
isp->isp_name, ISP_READ(isp, BIU_ISR));
if (ISP_READ(isp, BIU_SEMA) & 1) {
u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0);
- if (isp_parse_async(isp, (int) mbox))
+ if (isp_parse_async(isp, mbox))
return;
ISP_WRITE(isp, BIU_SEMA, 0);
}
@@ -2726,13 +2275,8 @@ command_known:
isp->isp_name, opcode);
break;
- /*
- * Be silent about these...
- */
-
case ASYNC_LOOP_UP:
case ASYNC_LIP_OCCURRED:
- case ASYNC_PDB_CHANGED:
break;
default:
@@ -2850,7 +2394,6 @@ again:
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
if (mbs.param[0] == ASYNC_LIP_OCCURRED ||
- mbs.param[0] == ASYNC_PDB_CHANGED ||
mbs.param[0] == ASYNC_LOOP_UP) {
if (once++ < 2) {
goto again;
@@ -3106,14 +2649,59 @@ isp_restart(isp)
if (XS_NULL(xs)) {
continue;
}
- if (isp->isp_nactive > 0)
- isp->isp_nactive--;
+ isp->isp_nactive--;
+ if (isp->isp_nactive < 0) {
+ isp->isp_nactive = 0;
+ }
XS_RESID(xs) = XS_XFRLEN(xs);
XS_SETERR(xs, HBA_BUSRESET);
XS_CMD_DONE(xs);
}
}
+void
+isp_watch(arg)
+ void *arg;
+{
+ int i;
+ struct ispsoftc *isp = arg;
+ ISP_SCSI_XFER_T *xs;
+ ISP_LOCKVAL_DECL;
+
+ /*
+ * Look for completely dead commands (but not polled ones).
+ */
+ ISP_ILOCK(isp);
+ for (i = 0; i < RQUEST_QUEUE_LEN; i++) {
+ if ((xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[i]) == NULL) {
+ continue;
+ }
+ if (XS_TIME(xs) == 0) {
+ continue;
+ }
+ XS_TIME(xs) -= (WATCH_INTERVAL * 1000);
+ /*
+ * Avoid later thinking that this
+ * transaction is not being timed.
+ * Then give ourselves to watchdog
+ * periods of grace.
+ */
+ if (XS_TIME(xs) == 0)
+ XS_TIME(xs) = 1;
+ else if (XS_TIME(xs) > -(2 * WATCH_INTERVAL * 1000)) {
+ continue;
+ }
+ if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
+ PRINTF("%s: isp_watch failed to abort command\n",
+ isp->isp_name);
+ isp_restart(isp);
+ break;
+ }
+ }
+ ISP_IUNLOCK(isp);
+ RESTART_WATCHDOG(isp_watch, isp);
+}
+
/*
* Miscellaneous debug statements.
*/
@@ -3159,7 +2747,7 @@ isp_prtstst(sp)
static char *
isp2100_fw_statename(state)
- int state;
+ u_int8_t state;
{
switch(state) {
case FW_CONFIG_WAIT: return "Config Wait";
@@ -3232,9 +2820,9 @@ isp_read_nvram(isp)
if (isp->isp_type & ISP_HA_SCSI) {
sdparam *sdp = (sdparam *) isp->isp_param;
+ /* XXX CHECK THIS FOR SANITY XXX */
sdp->isp_fifo_threshold =
- ISP_NVRAM_FIFO_THRESHOLD(nvram_data) |
- (ISP_NVRAM_FIFO_THRESHOLD_128(nvram_data) << 2);
+ ISP_NVRAM_FIFO_THRESHOLD(nvram_data);
sdp->isp_initiator_id =
ISP_NVRAM_INITIATOR_ID(nvram_data);
@@ -3276,6 +2864,8 @@ isp_read_nvram(isp)
sdp->isp_tag_aging =
ISP_NVRAM_TAG_AGE_LIMIT(nvram_data);
+ /* XXX ISP_NVRAM_FIFO_THRESHOLD_128 XXX */
+
sdp->isp_selection_timeout =
ISP_NVRAM_SELECTION_TIMEOUT(nvram_data);
@@ -3284,12 +2874,6 @@ isp_read_nvram(isp)
sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data);
-#if 0
- PRINTF("%s: fifo_threshold = 0x%x cbena%d dbena%d\n",
- isp->isp_name, sdp->isp_fifo_threshold,
- sdp->isp_cmd_dma_burst_enable,
- sdp->isp_data_dma_burst_enabl);
-#endif
for (i = 0; i < 16; i++) {
sdp->isp_devparam[i].dev_enable =
ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, i);
@@ -3364,9 +2948,8 @@ isp_read_nvram(isp)
fcp->isp_wwn = wwnstore.full64;
wwnstore.full64 = ISP2100_NVRAM_BOOT_NODE_NAME(nvram_data);
if (wwnstore.full64 != 0) {
- PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n",
- isp->isp_name, wwnstore.wds.hi32,
- wwnstore.wds.lo32);
+ PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n", isp->isp_name,
+ wwnstore.wds.hi32, wwnstore.wds.lo32);
}
fcp->isp_maxalloc =
ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);