summaryrefslogtreecommitdiff
path: root/sys/dev/isp/isp.c
diff options
context:
space:
mode:
authorMatt Jacob <mjacob@FreeBSD.org>2002-02-22 19:56:43 +0000
committerMatt Jacob <mjacob@FreeBSD.org>2002-02-22 19:56:43 +0000
commitc8a1dd5db25be312728ef7713ce35266022ddab7 (patch)
tree9298504f535b91113da931bb46e0a35852f53f70 /sys/dev/isp/isp.c
parente321f959e37fe02d515e418f81739785db5d17cb (diff)
Notes
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r--sys/dev/isp/isp.c695
1 files changed, 628 insertions, 67 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 79768856a5e7..8f0ddaacd2dd 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -109,12 +109,13 @@ static const char sc4[] = "NVRAM";
/*
* Local function prototypes.
*/
-static int isp_parse_async(struct ispsoftc *, int);
+static int isp_parse_async(struct ispsoftc *, u_int16_t);
static int isp_handle_other_response(struct ispsoftc *, int, isphdr_t *,
u_int16_t *);
static void
isp_parse_status(struct ispsoftc *, ispstatusreq_t *, XS_T *);
static void isp_fastpost_complete(struct ispsoftc *, u_int16_t);
+static int isp_mbox_continue(struct ispsoftc *);
static void isp_scsi_init(struct ispsoftc *);
static void isp_scsi_channel_init(struct ispsoftc *, int);
static void isp_fibre_init(struct ispsoftc *);
@@ -129,6 +130,7 @@ static int isp_scan_loop(struct ispsoftc *);
static int isp_scan_fabric(struct ispsoftc *);
static void isp_register_fc4_type(struct ispsoftc *);
static void isp_fw_state(struct ispsoftc *);
+static void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *, int);
static void isp_mboxcmd(struct ispsoftc *, mbreg_t *, int);
static void isp_update(struct ispsoftc *);
@@ -213,7 +215,7 @@ isp_reset(struct ispsoftc *isp)
* Set up default request/response queue in-pointer/out-pointer
* register indices.
*/
- if (IS_2300(isp)) {
+ if (IS_23XX(isp)) {
isp->isp_rqstinrp = BIU_REQINP;
isp->isp_rqstoutrp = BIU_REQOUTP;
isp->isp_respinrp = BIU_RSPINP;
@@ -242,6 +244,9 @@ isp_reset(struct ispsoftc *isp)
case ISP_HA_FC_2300:
btype = "2300";
break;
+ case ISP_HA_FC_2312:
+ btype = "2312";
+ break;
default:
break;
}
@@ -535,7 +540,7 @@ again:
#endif
} else {
ISP_WRITE(isp, RISC_MTR2100, 0x1212);
- if (IS_2200(isp) || IS_2300(isp)) {
+ if (IS_2200(isp) || IS_23XX(isp)) {
ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE);
}
}
@@ -553,7 +558,7 @@ again:
* Avoid doing this on the 2312 because you can generate a PCI
* parity error (chip breakage).
*/
- if (IS_2300(isp)) {
+ if (IS_23XX(isp)) {
USEC_DELAY(5);
} else {
loops = MBOX_DELAY_COUNT;
@@ -619,26 +624,26 @@ again:
dodnld = 0;
}
- if (IS_2300(isp))
+ if (IS_23XX(isp))
code_org = ISP_CODE_ORG_2300;
else
code_org = ISP_CODE_ORG;
if (dodnld) {
- u_int16_t fwlen = isp->isp_mdvec->dv_ispfw[3];
- for (i = 0; i < fwlen; i++) {
- mbs.param[0] = MBOX_WRITE_RAM_WORD;
- mbs.param[1] = code_org + i;
- mbs.param[2] = isp->isp_mdvec->dv_ispfw[i];
- isp_mboxcmd(isp, &mbs, MBLOGNONE);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGERR,
- "F/W download failed at word %d", i);
- dodnld = 0;
- goto again;
- }
+ isp->isp_mbxworkp = (void *) &isp->isp_mdvec->dv_ispfw[1];
+ isp->isp_mbxwrk0 = isp->isp_mdvec->dv_ispfw[3] - 1;
+ isp->isp_mbxwrk1 = code_org + 1;
+ mbs.param[0] = MBOX_WRITE_RAM_WORD;
+ mbs.param[1] = code_org;
+ mbs.param[2] = isp->isp_mdvec->dv_ispfw[0];
+ isp_mboxcmd(isp, &mbs, MBLOGNONE);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGERR,
+ "F/W download failed at word %d",
+ isp->isp_mbxwrk1 - code_org);
+ dodnld = 0;
+ goto again;
}
-
/*
* Verify that it downloaded correctly.
*/
@@ -966,8 +971,15 @@ isp_scsi_init(struct ispsoftc *isp)
mbs.param[1] = 0;
if (IS_ULTRA2(isp))
mbs.param[1] |= FW_FEATURE_LVD_NOTIFY;
+#ifndef ISP_NO_RIO
+ if (IS_ULTRA2(isp) || IS_1240(isp))
+ mbs.param[1] |= FW_FEATURE_RIO_16BIT;
+#else
+#ifndef ISP_NO_FASTPOST
if (IS_ULTRA2(isp) || IS_1240(isp))
mbs.param[1] |= FW_FEATURE_FAST_POST;
+#endif
+#endif
if (mbs.param[1] != 0) {
u_int16_t sfeat = mbs.param[1];
isp_mboxcmd(isp, &mbs, MBLOGALL);
@@ -1128,7 +1140,7 @@ isp_fibre_init(struct ispsoftc *isp)
return;
}
- loopid = DEFAULT_LOOPID(isp);
+ loopid = fcp->isp_loopid;
MEMZERO(icbp, sizeof (*icbp));
icbp->icb_version = ICB_VERSION1;
@@ -1204,7 +1216,7 @@ isp_fibre_init(struct ispsoftc *isp)
*
* NB: for the 2300, ICBOPT_EXTENDED is required.
*/
- if (IS_2200(isp) || IS_2300(isp)) {
+ if (IS_2200(isp) || IS_23XX(isp)) {
icbp->icb_fwoptions |= ICBOPT_EXTENDED;
/*
* Prefer or force Point-To-Point instead Loop?
@@ -1223,8 +1235,8 @@ isp_fibre_init(struct ispsoftc *isp)
icbp->icb_xfwoptions |= ICBXOPT_LOOP_2_PTP;
break;
}
- if (IS_2300(isp)) {
- if (isp->isp_revision < 2) {
+ if (IS_23XX(isp)) {
+ if (IS_2300(isp) && isp->isp_revision < 2) {
icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
}
if (isp->isp_confopts & ISP_CFG_ONEGB) {
@@ -1237,8 +1249,18 @@ isp_fibre_init(struct ispsoftc *isp)
}
}
+#ifndef ISP_NO_RIO_FC
+ if ((isp->isp_role & ISP_ROLE_TARGET) == 0 &&
+ ((IS_2100(isp) && ISP_FW_REVX(isp->isp_fwrev) >=
+ ISP_FW_REV(1, 17, 0)) || IS_2200(isp) || IS_23XX(isp))) {
+ icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;
+ icbp->icb_racctimer = 4;
+ icbp->icb_idelaytimer = 8;
+ }
+#endif
+
if ((IS_2200(isp) && ISP_FW_REVX(isp->isp_fwrev) >=
- ISP_FW_REV(2, 1, 26)) || IS_2300(isp)) {
+ ISP_FW_REV(2, 1, 26)) || IS_23XX(isp)) {
/*
* Turn on LIP F8 async event (1)
* Turn on generate AE 8013 on all LIP Resets (2)
@@ -1252,7 +1274,7 @@ isp_fibre_init(struct ispsoftc *isp)
}
icbp->icb_logintime = 30; /* 30 second login timeout */
- if (IS_2300(isp)) {
+ if (IS_23XX(isp)) {
ISP_WRITE(isp, isp->isp_rqstinrp, 0);
ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
ISP_WRITE(isp, isp->isp_respinrp, 0);
@@ -1287,6 +1309,8 @@ isp_fibre_init(struct ispsoftc *isp)
icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
isp_prt(isp, ISP_LOGDEBUG1,
"isp_fibre_init: fwoptions 0x%x", fcp->isp_fwoptions);
+
+ FC_SCRATCH_ACQUIRE(isp);
isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch);
/*
@@ -1301,6 +1325,7 @@ isp_fibre_init(struct ispsoftc *isp)
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
isp_mboxcmd(isp, &mbs, MBLOGALL);
+ FC_SCRATCH_RELEASE(isp);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
@@ -1340,12 +1365,15 @@ isp_getmap(struct ispsoftc *isp, fcpos_map_t *map)
*/
mbs.param[6] = 0;
mbs.param[7] = 0;
+ FC_SCRATCH_ACQUIRE(isp);
isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
MEMCPY(map, fcp->isp_scratch, sizeof (fcpos_map_t));
map->fwmap = mbs.param[1] != 0;
+ FC_SCRATCH_RELEASE(isp);
return (0);
}
+ FC_SCRATCH_RELEASE(isp);
return (-1);
}
@@ -1378,11 +1406,14 @@ isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp)
*/
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ FC_SCRATCH_ACQUIRE(isp);
isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
isp_get_pdb(isp, (isp_pdb_t *)fcp->isp_scratch, pdbp);
+ FC_SCRATCH_RELEASE(isp);
return (0);
}
+ FC_SCRATCH_RELEASE(isp);
return (-1);
}
@@ -1517,7 +1548,7 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay)
return (-1);
}
fcp->isp_loopid = mbs.param[1];
- if (IS_2200(isp) || IS_2300(isp)) {
+ if (IS_2200(isp) || IS_23XX(isp)) {
int topo = (int) mbs.param[6];
if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
topo = TOPO_PTP_STUB;
@@ -1594,7 +1625,7 @@ not_on_fabric:
}
fcp->isp_gbspeed = 1;
- if (IS_2300(isp)) {
+ if (IS_23XX(isp)) {
mbs.param[0] = MBOX_GET_SET_DATA_RATE;
mbs.param[1] = MBGSD_GET_RATE;
/* mbs.param[2] undefined if we're just getting rate */
@@ -1607,7 +1638,7 @@ not_on_fabric:
}
}
- isp_prt(isp, ISP_LOGINFO, topology, fcp->isp_loopid, fcp->isp_alpa,
+ isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid, fcp->isp_alpa,
fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]);
/*
@@ -1803,7 +1834,7 @@ isp_pdb_sync(struct ispsoftc *isp)
nwwnn == lp->node_wwn && nwwpn == lp->port_wwn &&
lp->roles == nrole && lp->force_logout == 0) {
lp->loggedin = lp->valid = 1;
- isp_prt(isp, ISP_LOGINFO, lretained,
+ isp_prt(isp, ISP_LOGCONFIG, lretained,
(int) (lp - fcp->portdb),
(int) lp->loopid, lp->portid);
continue;
@@ -1849,7 +1880,7 @@ isp_pdb_sync(struct ispsoftc *isp)
mbs.param[1] = loopid << 8;
mbs.param[2] = portid >> 16;
mbs.param[3] = portid & 0xffff;
- if (IS_2200(isp) || IS_2300(isp)) {
+ if (IS_2200(isp) || IS_23XX(isp)) {
/* only issue a PLOGI if not logged in */
mbs.param[1] |= 0x1;
}
@@ -2278,7 +2309,6 @@ isp_scan_fabric(struct ispsoftc *isp)
first_portid = portid = fcp->isp_portid;
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
-
for (first_portid_seen = hicap = 0; hicap < 65535; hicap++) {
mbreg_t mbs;
sns_screq_t *rq;
@@ -2296,6 +2326,7 @@ isp_scan_fabric(struct ispsoftc *isp)
rq->snscb_data[0] = SNS_GAN;
rq->snscb_data[4] = portid & 0xffff;
rq->snscb_data[5] = (portid >> 16) & 0xff;
+ FC_SCRATCH_ACQUIRE(isp);
isp_put_sns_request(isp, rq, (sns_screq_t *) fcp->isp_scratch);
MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GAN_REQ_SIZE);
mbs.param[0] = MBOX_SEND_SNS;
@@ -2346,12 +2377,14 @@ isp_scan_fabric(struct ispsoftc *isp)
}
if (fcp->isp_fwstate != FW_READY ||
fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
return (-1);
}
MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GAN_RESP_SIZE);
rs1 = (sns_ganrsp_t *) fcp->isp_scratch;
rs0 = (sns_ganrsp_t *) ((u_int8_t *)fcp->isp_scratch + 0x100);
isp_get_gan_response(isp, rs0, rs1);
+ FC_SCRATCH_RELEASE(isp);
portid = (((u_int32_t) rs1->snscb_port_id[0]) << 16) |
(((u_int32_t) rs1->snscb_port_id[1]) << 8) |
(((u_int32_t) rs1->snscb_port_id[2]));
@@ -2404,6 +2437,7 @@ isp_register_fc4_type(struct ispsoftc *isp)
#if 0
reqp->snscb_data[6] |= 20; /* ISO/IEC 8802-2 LLC/SNAP */
#endif
+ FC_SCRATCH_ACQUIRE(isp);
isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch);
mbs.param[0] = MBOX_SEND_SNS;
mbs.param[1] = SNS_RFT_REQ_SIZE >> 1;
@@ -2415,6 +2449,7 @@ isp_register_fc4_type(struct ispsoftc *isp)
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
isp_mboxcmd(isp, &mbs, MBLOGALL);
+ FC_SCRATCH_RELEASE(isp);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded");
}
@@ -2979,7 +3014,9 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg)
* Limit our stack depth by sticking with the max likely number
* of completions on a request queue at any one time.
*/
-#define MAX_REQUESTQ_COMPLETIONS 32
+#ifndef MAX_REQUESTQ_COMPLETIONS
+#define MAX_REQUESTQ_COMPLETIONS 64
+#endif
void
isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
@@ -2988,12 +3025,14 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
u_int16_t iptr, optr, junk;
int i, nlooked = 0, ndone = 0;
+again:
/*
* Is this a mailbox related interrupt?
* The mailbox semaphore will be nonzero if so.
*/
if (sema) {
if (mbox & 0x4000) {
+ isp->isp_intmboxc++;
if (isp->isp_mboxbsy) {
int i = 0, obits = isp->isp_obits;
isp->isp_mboxtmp[i++] = mbox;
@@ -3004,18 +3043,19 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
isp->isp_mboxtmp[i] =
ISP_READ(isp, MBOX_OFF(i));
}
+ if (isp->isp_mbxwrk0) {
+ if (isp_mbox_continue(isp) == 0) {
+ return;
+ }
+ }
MBOX_NOTIFY_COMPLETE(isp);
} else {
isp_prt(isp, ISP_LOGWARN,
"Mbox Command Async (0x%x) with no waiters",
mbox);
}
- } else {
- int fhandle = isp_parse_async(isp, (int) mbox);
- isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
- if (fhandle > 0) {
- isp_fastpost_complete(isp, (u_int16_t) fhandle);
- }
+ } else if (isp_parse_async(isp, mbox) < 0) {
+ return;
}
if (IS_FC(isp) || isp->isp_state != ISP_RUNSTATE) {
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
@@ -3046,8 +3086,11 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
*
* If we're a 2300, we can ask what hardware what it thinks.
*/
- if (IS_2300(isp)) {
+ if (IS_23XX(isp)) {
optr = ISP_READ(isp, isp->isp_respoutrp);
+ /*
+ * Debug: to be taken out eventually
+ */
if (isp->isp_residx != optr) {
isp_prt(isp, ISP_LOGWARN, "optr %x soft optr %x",
optr, isp->isp_residx);
@@ -3059,8 +3102,10 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
/*
* You *must* read the Response Queue In Pointer
* prior to clearing the RISC interrupt.
+ *
+ * Debounce the 2300 if revision less than 2.
*/
- if (IS_2100(isp) || IS_2300(isp)) {
+ if (IS_2100(isp) || (IS_2300(isp) && isp->isp_revision < 2)) {
i = 0;
do {
iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
@@ -3088,7 +3133,7 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
* make sure the old interrupt went away (to avoid 'ringing'
* effects), but that didn't stop this from occurring.
*/
- if (IS_2300(isp)) {
+ if (IS_23XX(isp)) {
USEC_DELAY(100);
iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
junk = ISP_READ(isp, BIU_R2HSTSLO);
@@ -3096,10 +3141,19 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
junk = ISP_READ(isp, BIU_ISR);
}
if (optr == iptr) {
- isp_prt(isp, ISP_LOGDEBUG0,
+ if (IS_23XX(isp)) {
+ ;
+ } else {
+ sema = ISP_READ(isp, BIU_SEMA);
+ mbox = ISP_READ(isp, OUTMAILBOX0);
+ if ((sema & 0x3) && (mbox & 0x8000)) {
+ goto again;
+ }
+ }
+ isp->isp_intbogus++;
+ isp_prt(isp, ISP_LOGDEBUG1,
"bogus intr- isr %x (%x) iptr %x optr %x",
isr, junk, iptr, optr);
- isp->isp_intbogus++;
}
}
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
@@ -3125,6 +3179,15 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
if (type == RQSTYPE_RESPONSE) {
isp_get_response(isp, (ispstatusreq_t *) hp, sp);
+ } else if (type == RQSTYPE_RIO2) {
+ isp_rio2_t rio;
+ isp_get_rio2(isp, (isp_rio2_t *) hp, &rio);
+ for (i = 0; i < rio.req_header.rqs_seqno; i++) {
+ isp_fastpost_complete(isp, rio.req_handles[i]);
+ }
+ if (isp->isp_fpcchiwater < rio.req_header.rqs_seqno)
+ isp->isp_fpcchiwater = rio.req_header.rqs_seqno;
+ continue;
} else {
if (!isp_handle_other_response(isp, type, hp, &optr)) {
MEMZERO(hp, QENTRY_LEN); /* PERF */
@@ -3350,12 +3413,15 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
* While we're at it, reqad the requst queue out pointer.
*/
isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp);
+ if (isp->isp_rscchiwater < ndone)
+ isp->isp_rscchiwater = ndone;
}
isp->isp_residx = optr;
for (i = 0; i < ndone; i++) {
xs = complist[i];
if (xs) {
+ isp->isp_rsltccmplt++;
isp_done(xs);
}
}
@@ -3366,16 +3432,16 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
*/
static int
-isp_parse_async(struct ispsoftc *isp, int mbox)
+isp_parse_async(struct ispsoftc *isp, u_int16_t mbox)
{
int bus;
- u_int16_t fast_post_handle = 0;
if (IS_DUALBUS(isp)) {
bus = ISP_READ(isp, OUTMAILBOX6);
} else {
bus = 0;
}
+ isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
switch (mbox) {
case ASYNC_BUS_RESET:
@@ -3477,10 +3543,32 @@ isp_parse_async(struct ispsoftc *isp, int mbox)
isp->isp_sendmarker |= (1 << bus);
break;
+ /*
+ * We can use bus, which will always be zero for FC cards,
+ * as a mailbox pattern accumulator to be checked below.
+ */
+ case ASYNC_RIO5:
+ bus = 0x1ce; /* outgoing mailbox regs 1-3, 6-7 */
+ break;
+
+ case ASYNC_RIO4:
+ bus = 0x14e; /* outgoing mailbox regs 1-3, 6 */
+ break;
+
+ case ASYNC_RIO3:
+ bus = 0x10e; /* outgoing mailbox regs 1-3 */
+ break;
+
+ case ASYNC_RIO2:
+ bus = 0x106; /* outgoing mailbox regs 1-2 */
+ break;
+
+ case ASYNC_RIO1:
case ASYNC_CMD_CMPLT:
- fast_post_handle = ISP_READ(isp, OUTMAILBOX1);
- isp_prt(isp, ISP_LOGDEBUG3, "fast post completion of %u",
- fast_post_handle);
+ bus = 0x102; /* outgoing mailbox regs 1 */
+ break;
+
+ case ASYNC_RIO_RESP:
break;
case ASYNC_CTIO_DONE:
@@ -3489,13 +3577,13 @@ isp_parse_async(struct ispsoftc *isp, int mbox)
* Bus gets overloaded with the handle. Dual bus
* cards don't put bus# into the handle.
*/
- bus = (ISP_READ(isp, OUTMAILBOX2) << 16) |
- ISP_READ(isp, OUTMAILBOX1);
- isp_target_async(isp, bus, mbox);
+ isp_target_async(isp, ((ISP_READ(isp, OUTMAILBOX2) << 16) |
+ ISP_READ(isp, OUTMAILBOX1)), mbox);
#else
isp_prt(isp, ISP_LOGINFO, "Fast Posting CTIO done");
#endif
- break;
+ isp->isp_fphccmplt++; /* count it as a fast posting intr */
+ return (0);
case ASYNC_LIP_F8:
case ASYNC_LIP_OCCURRED:
@@ -3642,7 +3730,28 @@ isp_parse_async(struct ispsoftc *isp, int mbox)
isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
break;
}
- return (fast_post_handle);
+
+ if (bus & 0x100) {
+ int i, nh;
+ u_int16_t handles[5];
+
+ for (nh = 0, i = 1; i < MAX_MAILBOX; i++) {
+ if ((bus & (1 << i)) == 0) {
+ continue;
+ }
+ handles[nh++] = ISP_READ(isp, MBOX_OFF(i));
+ }
+ for (i = 0; i < nh; i++) {
+ isp_fastpost_complete(isp, handles[i]);
+ isp_prt(isp, ISP_LOGDEBUG3,
+ "fast post completion of %u", handles[i]);
+ }
+ if (isp->isp_fpcchiwater < nh)
+ isp->isp_fpcchiwater = nh;
+ } else {
+ isp->isp_intoasync++;
+ }
+ return (0);
}
/*
@@ -3669,6 +3778,7 @@ isp_handle_other_response(struct ispsoftc *isp, int type,
case RQSTYPE_ATIO2:
case RQSTYPE_CTIO2:
case RQSTYPE_CTIO3:
+ isp->isp_rsltccmplt++; /* count as a response completion */
#ifdef ISP_TARGET_MODE
return (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp));
#else
@@ -3998,6 +4108,24 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
*/
isp_prt(isp, ISP_LOGINFO,
"port logout for target %d", XS_TGT(xs));
+ /*
+ * If we're on a local loop, force a LIP (which is overkill)
+ * to force a re-login of this unit.
+ */
+ if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
+ FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
+ mbreg_t mbs;
+ mbs.param[0] = MBOX_INIT_LIP;
+ isp_mboxcmd_qnw(isp, &mbs, 1);
+ }
+
+ /*
+ * Probably overkill.
+ */
+ isp->isp_sendmarker = 1;
+ FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
+ isp_mark_getpdb_all(isp);
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_SELTIMEOUT);
}
@@ -4058,9 +4186,59 @@ isp_fastpost_complete(struct ispsoftc *isp, u_int16_t fph)
}
if (isp->isp_nactive)
isp->isp_nactive--;
+ isp->isp_fphccmplt++;
isp_done(xs);
}
+static int
+isp_mbox_continue(struct ispsoftc *isp)
+{
+ mbreg_t mbs;
+ u_int16_t *ptr;
+
+ switch (isp->isp_lastmbxcmd) {
+ case MBOX_WRITE_RAM_WORD:
+ case MBOX_READ_RAM_WORD:
+ case MBOX_READ_RAM_WORD_EXTENDED:
+ break;
+ default:
+ return (1);
+ }
+ if (isp->isp_mboxtmp[0] != MBOX_COMMAND_COMPLETE) {
+ isp->isp_mbxwrk0 = 0;
+ return (-1);
+ }
+
+
+ /*
+ * Clear the previous interrupt.
+ */
+ ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
+ ISP_WRITE(isp, BIU_SEMA, 0);
+
+ /*
+ * Continue with next word.
+ */
+ ptr = isp->isp_mbxworkp;
+ switch (isp->isp_lastmbxcmd) {
+ case MBOX_WRITE_RAM_WORD:
+ mbs.param[2] = *ptr++;
+ mbs.param[1] = isp->isp_mbxwrk1++;
+ break;
+ case MBOX_READ_RAM_WORD:
+ case MBOX_READ_RAM_WORD_EXTENDED:
+ *ptr++ = isp->isp_mboxtmp[2];
+ mbs.param[1] = isp->isp_mbxwrk1++;
+ break;
+ }
+ isp->isp_mbxworkp = ptr;
+ mbs.param[0] = isp->isp_lastmbxcmd;
+ isp->isp_mbxwrk0 -= 1;
+ isp_mboxcmd_qnw(isp, &mbs, 0);
+ return (0);
+}
+
+
#define HIBYT(x) ((x) >> 0x8)
#define LOBYT(x) ((x) & 0xff)
#define ISPOPMAP(a, b) (((a) << 8) | (b))
@@ -4276,7 +4454,7 @@ static u_int16_t mbpfc[] = {
ISPOPMAP(0x00, 0x00), /* 0x0c: */
ISPOPMAP(0x00, 0x00), /* 0x0d: */
ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
- ISPOPMAP(0x00, 0x00), /* 0x0f: */
+ ISPOPMAP(0x03, 0x07), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED(1) */
ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
ISPOPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
ISPOPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
@@ -4389,6 +4567,13 @@ static u_int16_t mbpfc[] = {
ISPOPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */
ISPOPMAP(0x07, 0x01) /* 0x7e: Lun RESET */
};
+/*
+ * Footnotes
+ *
+ * (1): this sets bits 21..16 in mailbox register #8, which we nominally
+ * do not access at this time in the core driver. The caller is
+ * responsible for setting this register first (Gross!).
+ */
#ifndef ISP_STRIPPED
static char *fc_mbcmd_names[] = {
@@ -4405,7 +4590,7 @@ static char *fc_mbcmd_names[] = {
"DUMP RAM",
NULL,
NULL,
- NULL,
+ "READ RAM WORD EXTENDED",
"CHECK FIRMWARE",
NULL,
"INIT REQUEST QUEUE",
@@ -4523,6 +4708,46 @@ static char *fc_mbcmd_names[] = {
#endif
static void
+isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay)
+{
+ unsigned int lim, ibits, obits, box, opcode;
+ u_int16_t *mcp;
+
+ if (IS_FC(isp)) {
+ mcp = mbpfc;
+ lim = (sizeof (mbpfc) / sizeof (mbpfc[0]));
+ } else {
+ mcp = mbpscsi;
+ lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0]));
+ }
+ opcode = mbp->param[0];
+ ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp);
+ obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp);
+ for (box = 0; box < MAX_MAILBOX; box++) {
+ if (ibits & (1 << box)) {
+ ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
+ }
+ if (nodelay == 0) {
+ isp->isp_mboxtmp[box] = mbp->param[box] = 0;
+ }
+ }
+ if (nodelay == 0) {
+ isp->isp_lastmbxcmd = opcode;
+ isp->isp_obits = obits;
+ isp->isp_mboxbsy = 1;
+ }
+ ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
+ /*
+ * Oddly enough, if we're not delaying for an answer,
+ * delay a bit to give the f/w a chance to pick up the
+ * command.
+ */
+ if (nodelay) {
+ USEC_DELAY(1000);
+ }
+}
+
+static void
isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask)
{
char *cname, *xname, tname[16], mname[16];
@@ -4870,22 +5095,31 @@ isp_setdfltparm(struct ispsoftc *isp, int channel)
* or the platform code wants to use what had been
* set in the defaults.
*/
- if (nvfail || (isp->isp_confopts & ISP_CFG_OWNWWN)) {
- isp_prt(isp, ISP_LOGCONFIG,
- "Using Node WWN 0x%08x%08x, Port WWN 0x%08x%08x",
+ if (nvfail) {
+ isp->isp_confopts |= ISP_CFG_OWNWWPN|ISP_CFG_OWNWWNN;
+ }
+ if (isp->isp_confopts & ISP_CFG_OWNWWNN) {
+ isp_prt(isp, ISP_LOGCONFIG, "Using Node WWN 0x%08x%08x",
(u_int32_t) (DEFAULT_NODEWWN(isp) >> 32),
- (u_int32_t) (DEFAULT_NODEWWN(isp) & 0xffffffff),
+ (u_int32_t) (DEFAULT_NODEWWN(isp) & 0xffffffff));
+ ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
+ } else {
+ /*
+ * We always start out with values derived
+ * from NVRAM or our platform default.
+ */
+ ISP_NODEWWN(isp) = fcp->isp_nodewwn;
+ }
+ if (isp->isp_confopts & ISP_CFG_OWNWWPN) {
+ isp_prt(isp, ISP_LOGCONFIG, "Using Port WWN 0x%08x%08x",
(u_int32_t) (DEFAULT_PORTWWN(isp) >> 32),
(u_int32_t) (DEFAULT_PORTWWN(isp) & 0xffffffff));
- isp->isp_confopts |= ISP_CFG_OWNWWN;
- ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
} else {
/*
* We always start out with values derived
* from NVRAM or our platform default.
*/
- ISP_NODEWWN(isp) = fcp->isp_nodewwn;
ISP_PORTWWN(isp) = fcp->isp_portwwn;
}
return;
@@ -5159,6 +5393,9 @@ isp_rdnvram_word(struct ispsoftc *isp, int wo, u_int16_t *rp)
if (IS_FC(isp)) {
wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1);
+ if (IS_2312(isp) && isp->isp_port) {
+ wo += 128;
+ }
rqst = (ISP_NVRAM_READ << 8) | wo;
cbits = 10;
} else if (IS_ULTRA2(isp)) {
@@ -5541,13 +5778,18 @@ isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data)
}
}
fcp->isp_portwwn = wwn;
- wwn = ISP2100_NVRAM_NODE_NAME(nvram_data);
- if (wwn) {
- isp_prt(isp, ISP_LOGCONFIG, "NVRAM Node WWN 0x%08x%08x",
- (u_int32_t) (wwn >> 32), (u_int32_t) (wwn & 0xffffffff));
- if ((wwn >> 60) == 0) {
- wwn |= (((u_int64_t) 2)<< 60);
+ if (IS_2200(isp) || IS_23XX(isp)) {
+ wwn = ISP2200_NVRAM_NODE_NAME(nvram_data);
+ if (wwn) {
+ isp_prt(isp, ISP_LOGCONFIG, "NVRAM Node WWN 0x%08x%08x",
+ (u_int32_t) (wwn >> 32),
+ (u_int32_t) (wwn & 0xffffffff));
+ if ((wwn >> 60) == 0) {
+ wwn |= (((u_int64_t) 2)<< 60);
+ }
}
+ } else {
+ wwn &= ~((u_int64_t) 0xfff << 48);
}
fcp->isp_nodewwn = wwn;
@@ -5594,3 +5836,322 @@ isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data)
"NVRAM: maxfrmlen %d execthrottle %d fwoptions 0x%x",
fcp->isp_maxfrmlen, fcp->isp_execthrottle, fcp->isp_fwoptions);
}
+
+#ifdef ISP_FW_CRASH_DUMP
+static void isp2200_fw_dump(struct ispsoftc *);
+static void isp2300_fw_dump(struct ispsoftc *);
+
+static void
+isp2200_fw_dump(struct ispsoftc *isp)
+{
+ int i, j;
+ mbreg_t mbs;
+ u_int16_t *ptr;
+
+ ptr = FCPARAM(isp)->isp_dump_data;
+ if (ptr == NULL) {
+ isp_prt(isp, ISP_LOGERR,
+ "No place to dump RISC registers and SRAM");
+ return;
+ }
+ if (*ptr++) {
+ isp_prt(isp, ISP_LOGERR,
+ "dump area for RISC registers and SRAM already used");
+ return;
+ }
+ ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+ for (i = 0; i < 100; i++) {
+ USEC_DELAY(100);
+ if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
+ break;
+ }
+ }
+ if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
+ /*
+ * PBIU Registers
+ */
+ for (i = 0; i < 8; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + (i << 1));
+ }
+
+ /*
+ * Mailbox Registers
+ */
+ for (i = 0; i < 8; i++) {
+ *ptr++ = ISP_READ(isp, MBOX_BLOCK + (i << 1));
+ }
+
+ /*
+ * DMA Registers
+ */
+ for (i = 0; i < 48; i++) {
+ *ptr++ = ISP_READ(isp, DMA_BLOCK + 0x20 + (i << 1));
+ }
+
+ /*
+ * RISC H/W Registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0);
+ for (i = 0; i < 16; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0xA0 + (i << 1));
+ }
+
+ /*
+ * RISC GP Registers
+ */
+ for (j = 0; j < 8; j++) {
+ ISP_WRITE(isp, BIU_BLOCK + 0xA4, 0x2000 + (j << 8));
+ for (i = 0; i < 16; i++) {
+ *ptr++ =
+ ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+ }
+
+ /*
+ * Frame Buffer Hardware Registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0x10);
+ for (i = 0; i < 16; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+
+ /*
+ * Fibre Protocol Module 0 Hardware Registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0x20);
+ for (i = 0; i < 64; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+
+ /*
+ * Fibre Protocol Module 1 Hardware Registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0x30);
+ for (i = 0; i < 64; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+ } else {
+ isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause");
+ return;
+ }
+ isp_prt(isp, ISP_LOGALL,
+ "isp_fw_dump: RISC registers dumped successfully");
+ ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
+ for (i = 0; i < 100; i++) {
+ USEC_DELAY(100);
+ if (ISP_READ(isp, OUTMAILBOX0) == 0) {
+ break;
+ }
+ }
+ if (ISP_READ(isp, OUTMAILBOX0) != 0) {
+ isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
+ return;
+ }
+ ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+ for (i = 0; i < 100; i++) {
+ USEC_DELAY(100);
+ if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
+ break;
+ }
+ }
+ if ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
+ isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause After Reset");
+ return;
+ }
+ ISP_WRITE(isp, RISC_EMB, 0xf2);
+ ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
+ for (i = 0; i < 100; i++) {
+ USEC_DELAY(100);
+ if ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
+ break;
+ }
+ }
+ ENABLE_INTS(isp);
+ mbs.param[0] = MBOX_READ_RAM_WORD;
+ mbs.param[1] = 0x1000;
+ isp->isp_mbxworkp = (void *) ptr;
+ isp->isp_mbxwrk0 = 0xefff; /* continuation count */
+ isp->isp_mbxwrk1 = 0x1001; /* next SRAM address */
+ isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGWARN,
+ "RAM DUMP FAILED @ WORD %x", isp->isp_mbxwrk1);
+ return;
+ }
+ ptr = isp->isp_mbxworkp; /* finish fetch of final word */
+ *ptr++ = isp->isp_mboxtmp[2];
+ isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped succesfully");
+ FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */
+}
+
+static void
+isp2300_fw_dump(struct ispsoftc *isp)
+{
+ int i, j;
+ mbreg_t mbs;
+ u_int16_t *ptr;
+
+ ptr = FCPARAM(isp)->isp_dump_data;
+ if (ptr == NULL) {
+ isp_prt(isp, ISP_LOGERR,
+ "No place to dump RISC registers and SRAM");
+ return;
+ }
+ if (*ptr++) {
+ isp_prt(isp, ISP_LOGERR,
+ "dump area for RISC registers and SRAM already used");
+ return;
+ }
+ ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+ for (i = 0; i < 100; i++) {
+ USEC_DELAY(100);
+ if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
+ break;
+ }
+ }
+ if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
+ /*
+ * PBIU registers
+ */
+ for (i = 0; i < 8; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + (i << 1));
+ }
+
+ /*
+ * ReqQ-RspQ-Risc2Host Status registers
+ */
+ for (i = 0; i < 8; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x10 + (i << 1));
+ }
+
+ /*
+ * Mailbox Registers
+ */
+ for (i = 0; i < 32; i++) {
+ *ptr++ =
+ ISP_READ(isp, PCI_MBOX_REGS2300_OFF + (i << 1));
+ }
+
+ /*
+ * Auto Request Response DMA registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0x40);
+ for (i = 0; i < 32; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+
+ /*
+ * DMA registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0x50);
+ for (i = 0; i < 48; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+
+ /*
+ * RISC hardware registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0);
+ for (i = 0; i < 16; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0xA0 + (i << 1));
+ }
+
+ /*
+ * RISC GP? registers
+ */
+ for (j = 0; j < 8; j++) {
+ ISP_WRITE(isp, BIU_BLOCK + 0xA4, 0x2000 + (j << 9));
+ for (i = 0; i < 16; i++) {
+ *ptr++ =
+ ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+ }
+
+ /*
+ * frame buffer hardware registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0x10);
+ for (i = 0; i < 64; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+
+ /*
+ * FPM B0 hardware registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0x20);
+ for (i = 0; i < 64; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+
+ /*
+ * FPM B1 hardware registers
+ */
+ ISP_WRITE(isp, BIU2100_CSR, 0x30);
+ for (i = 0; i < 64; i++) {
+ *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
+ }
+ } else {
+ isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause");
+ return;
+ }
+ isp_prt(isp, ISP_LOGALL,
+ "isp_fw_dump: RISC registers dumped successfully");
+ ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
+ for (i = 0; i < 100; i++) {
+ USEC_DELAY(100);
+ if (ISP_READ(isp, OUTMAILBOX0) == 0) {
+ break;
+ }
+ }
+ if (ISP_READ(isp, OUTMAILBOX0) != 0) {
+ isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
+ return;
+ }
+ ENABLE_INTS(isp);
+ mbs.param[0] = MBOX_READ_RAM_WORD;
+ mbs.param[1] = 0x800;
+ isp->isp_mbxworkp = (void *) ptr;
+ isp->isp_mbxwrk0 = 0xf7ff; /* continuation count */
+ isp->isp_mbxwrk1 = 0x801; /* next SRAM address */
+ isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGWARN,
+ "RAM DUMP FAILED @ WORD %x", isp->isp_mbxwrk1);
+ return;
+ }
+ ptr = isp->isp_mbxworkp; /* finish fetch of final word */
+ *ptr++ = isp->isp_mboxtmp[2];
+
+ /*
+ * We don't have access to mailbox registers 8.. onward
+ * in our 'common' device model- so we have to set it
+ * here and hope it stays the same!
+ */
+ ISP_WRITE(isp, PCI_MBOX_REGS2300_OFF + (8 << 1), 0x1);
+
+ mbs.param[0] = MBOX_READ_RAM_WORD_EXTENDED;
+ mbs.param[1] = 0;
+ isp->isp_mbxworkp = (void *) ptr;
+ isp->isp_mbxwrk0 = 0xffff; /* continuation count */
+ isp->isp_mbxwrk1 = 0x1; /* next SRAM address */
+ isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGWARN,
+ "RAM DUMP FAILED @ WORD %x", 0x10000 + isp->isp_mbxwrk1);
+ return;
+ }
+ ptr = isp->isp_mbxworkp; /* finish final word */
+ *ptr++ = mbs.param[2];
+ isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped succesfully");
+ FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */
+}
+
+void
+isp_fw_dump(struct ispsoftc *isp)
+{
+ if (IS_2200(isp))
+ isp2200_fw_dump(isp);
+ else if (IS_23XX(isp))
+ isp2300_fw_dump(isp);
+}
+#endif