diff options
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r-- | sys/dev/isp/isp.c | 257 |
1 files changed, 134 insertions, 123 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 4863075..4049eb5 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -109,37 +109,37 @@ static const char sc4[] = "NVRAM"; /* * Local function prototypes. */ -static int isp_parse_async __P((struct ispsoftc *, int)); -static int isp_handle_other_response -__P((struct ispsoftc *, ispstatusreq_t *, u_int16_t *)); -static void isp_parse_status -__P((struct ispsoftc *, ispstatusreq_t *, XS_T *)); -static void isp_fastpost_complete __P((struct ispsoftc *, u_int16_t)); -static void isp_scsi_init __P((struct ispsoftc *)); -static void isp_scsi_channel_init __P((struct ispsoftc *, int)); -static void isp_fibre_init __P((struct ispsoftc *)); -static void isp_mark_getpdb_all __P((struct ispsoftc *)); -static int isp_getmap __P((struct ispsoftc *, fcpos_map_t *)); -static int isp_getpdb __P((struct ispsoftc *, int, isp_pdb_t *)); -static u_int64_t isp_get_portname __P((struct ispsoftc *, int, int)); -static int isp_fclink_test __P((struct ispsoftc *, int)); -static char *isp2100_fw_statename __P((int)); -static int isp_pdb_sync __P((struct ispsoftc *)); -static int isp_scan_loop __P((struct ispsoftc *)); -static int isp_scan_fabric __P((struct ispsoftc *)); -static void isp_register_fc4_type __P((struct ispsoftc *)); -static void isp_fw_state __P((struct ispsoftc *)); -static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *, int)); - -static void isp_update __P((struct ispsoftc *)); -static void isp_update_bus __P((struct ispsoftc *, int)); -static void isp_setdfltparm __P((struct ispsoftc *, int)); -static int isp_read_nvram __P((struct ispsoftc *)); -static void isp_rdnvram_word __P((struct ispsoftc *, int, u_int16_t *)); -static void isp_parse_nvram_1020 __P((struct ispsoftc *, u_int8_t *)); -static void isp_parse_nvram_1080 __P((struct ispsoftc *, int, u_int8_t *)); -static void isp_parse_nvram_12160 __P((struct ispsoftc *, int, u_int8_t *)); -static void isp_parse_nvram_2100 __P((struct ispsoftc *, u_int8_t *)); +static int isp_parse_async(struct ispsoftc *, int); +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 void isp_scsi_init(struct ispsoftc *); +static void isp_scsi_channel_init(struct ispsoftc *, int); +static void isp_fibre_init(struct ispsoftc *); +static void isp_mark_getpdb_all(struct ispsoftc *); +static int isp_getmap(struct ispsoftc *, fcpos_map_t *); +static int isp_getpdb(struct ispsoftc *, int, isp_pdb_t *); +static u_int64_t isp_get_portname(struct ispsoftc *, int, int); +static int isp_fclink_test(struct ispsoftc *, int); +static char *isp2100_fw_statename(int); +static int isp_pdb_sync(struct ispsoftc *); +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(struct ispsoftc *, mbreg_t *, int); + +static void isp_update(struct ispsoftc *); +static void isp_update_bus(struct ispsoftc *, int); +static void isp_setdfltparm(struct ispsoftc *, int); +static int isp_read_nvram(struct ispsoftc *); +static void isp_rdnvram_word(struct ispsoftc *, int, u_int16_t *); +static void isp_parse_nvram_1020(struct ispsoftc *, u_int8_t *); +static void isp_parse_nvram_1080(struct ispsoftc *, int, u_int8_t *); +static void isp_parse_nvram_12160(struct ispsoftc *, int, u_int8_t *); +static void isp_parse_nvram_2100(struct ispsoftc *, u_int8_t *); /* * Reset Hardware. @@ -692,7 +692,7 @@ again: * major, minor, micro revisions in the mailbox registers, which * is really, really, annoying. */ - if (isp->isp_bustype == ISP_BT_SBUS) { + if (ISP_SBUS_SUPPORTED && isp->isp_bustype == ISP_BT_SBUS) { if (dodnld) { #ifdef ISP_TARGET_MODE isp->isp_fwrev[0] = 7; @@ -1107,7 +1107,7 @@ static void isp_fibre_init(struct ispsoftc *isp) { fcparam *fcp; - isp_icb_t *icbp; + isp_icb_t local, *icbp = &local; mbreg_t mbs; int loopid; u_int64_t nwwn, pwwn; @@ -1129,9 +1129,7 @@ isp_fibre_init(struct ispsoftc *isp) } loopid = DEFAULT_LOOPID(isp); - icbp = (isp_icb_t *) fcp->isp_scratch; MEMZERO(icbp, sizeof (*icbp)); - icbp->icb_version = ICB_VERSION1; /* @@ -1289,8 +1287,7 @@ 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); - ISP_SWIZZLE_ICB(isp, icbp); - + isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch); /* * Init the firmware @@ -1383,7 +1380,7 @@ isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp) mbs.param[7] = DMA_WD2(fcp->isp_scdma); isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - ISP_UNSWIZZLE_AND_COPY_PDBP(isp, pdbp, fcp->isp_scratch); + isp_get_pdb(isp, (isp_pdb_t *)fcp->isp_scratch, pdbp); return (0); } return (-1); @@ -2264,9 +2261,6 @@ isp_scan_fabric(struct ispsoftc *isp) { fcparam *fcp = isp->isp_param; u_int32_t portid, first_portid, last_portid; - sns_screq_t *reqp; - sns_scrsp_t *resp; - mbreg_t mbs; int hicap, first_portid_seen, last_port_same; if (fcp->isp_onfabric == 0) { @@ -2274,8 +2268,7 @@ isp_scan_fabric(struct ispsoftc *isp) return (0); } - reqp = (sns_screq_t *) fcp->isp_scratch; - resp = (sns_scrsp_t *) (&((char *)fcp->isp_scratch)[0x100]); + /* * Since Port IDs are 24 bits, we can check against having seen * anything yet with this value. @@ -2285,22 +2278,26 @@ 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++) { - MEMZERO((void *) reqp, SNS_GAN_REQ_SIZE); - reqp->snscb_rblen = SNS_GAN_RESP_SIZE >> 1; - reqp->snscb_addr[RQRSP_ADDR0015] = - DMA_WD0(fcp->isp_scdma + 0x100); - reqp->snscb_addr[RQRSP_ADDR1631] = - DMA_WD1(fcp->isp_scdma + 0x100); - reqp->snscb_addr[RQRSP_ADDR3247] = - DMA_WD2(fcp->isp_scdma + 0x100); - reqp->snscb_addr[RQRSP_ADDR4863] = - DMA_WD3(fcp->isp_scdma + 0x100); - reqp->snscb_sblen = 6; - reqp->snscb_data[0] = SNS_GAN; - reqp->snscb_data[4] = portid & 0xffff; - reqp->snscb_data[5] = (portid >> 16) & 0xff; - ISP_SWIZZLE_SNS_REQ(isp, reqp); + mbreg_t mbs; + sns_screq_t *rq; + sns_scrsp_t *rs0, *rs1; + u_int8_t sc[SNS_GAN_REQ_SIZE]; + + rq = (sns_screq_t *)sc; + MEMZERO((void *) rq, SNS_GAN_REQ_SIZE); + rq->snscb_rblen = SNS_GAN_RESP_SIZE >> 1; + rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+0x100); + rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+0x100); + rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+0x100); + rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+0x100); + rq->snscb_sblen = 6; + rq->snscb_data[0] = SNS_GAN; + rq->snscb_data[4] = portid & 0xffff; + rq->snscb_data[5] = (portid >> 16) & 0xff; + 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; mbs.param[1] = SNS_GAN_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -2351,11 +2348,14 @@ isp_scan_fabric(struct ispsoftc *isp) fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { return (-1); } - ISP_UNSWIZZLE_SNS_RSP(isp, resp, SNS_GAN_RESP_SIZE >> 1); - portid = (((u_int32_t) resp->snscb_port_id[0]) << 16) | - (((u_int32_t) resp->snscb_port_id[1]) << 8) | - (((u_int32_t) resp->snscb_port_id[2])); - (void) isp_async(isp, ISPASYNC_FABRIC_DEV, resp); + MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GAN_RESP_SIZE); + rs1 = (sns_scrsp_t *) fcp->isp_scratch; + rs0 = (sns_scrsp_t *) ((u_int8_t *)fcp->isp_scratch + 0x100); + isp_get_sns_response(isp, rs0, rs1, SNS_GAN_RESP_SIZE >> 1); + 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])); + (void) isp_async(isp, ISPASYNC_FABRIC_DEV, rs1); if (first_portid == portid) { fcp->isp_loopstate = LOOP_FSCAN_DONE; return (0); @@ -2386,10 +2386,10 @@ static void isp_register_fc4_type(struct ispsoftc *isp) { fcparam *fcp = isp->isp_param; - sns_screq_t *reqp; + u_int8_t local[SNS_RFT_REQ_SIZE]; + sns_screq_t *reqp = (sns_screq_t *) local; mbreg_t mbs; - reqp = (sns_screq_t *) fcp->isp_scratch; MEMZERO((void *) reqp, SNS_RFT_REQ_SIZE); reqp->snscb_rblen = SNS_RFT_RESP_SIZE >> 1; reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100); @@ -2404,7 +2404,7 @@ isp_register_fc4_type(struct ispsoftc *isp) #if 0 reqp->snscb_data[6] |= 20; /* ISO/IEC 8802-2 LLC/SNAP */ #endif - ISP_SWIZZLE_SNS_REQ(isp, reqp); + 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; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -2428,14 +2428,9 @@ int isp_start(XS_T *xs) { struct ispsoftc *isp; - u_int16_t iptr, optr, handle; - union { - ispreq_t *_reqp; - ispreqt2_t *_t2reqp; - } _u; -#define reqp _u._reqp -#define t2reqp _u._t2reqp -#define UZSIZE max(sizeof (ispreq_t), sizeof (ispreqt2_t)) + u_int16_t nxti, optr, handle; + u_int8_t local[QENTRY_LEN]; + ispreq_t *reqp, *qep; int target, i; XS_INITERR(xs); @@ -2667,7 +2662,7 @@ isp_start(XS_T *xs) isp_update(isp); } - if (isp_getrqentry(isp, &iptr, &optr, (void **) &reqp)) { + if (isp_getrqentry(isp, &nxti, &optr, (void **)&qep)) { isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow"); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); @@ -2678,6 +2673,7 @@ isp_start(XS_T *xs) * We do dual duty here (cough) for synchronizing for busses other * than which we got here to send a command to. */ + reqp = (ispreq_t *) local; if (isp->isp_sendmarker) { u_int8_t n = (IS_DUALBUS(isp)? 2: 1); /* @@ -2687,15 +2683,15 @@ isp_start(XS_T *xs) if ((isp->isp_sendmarker & (1 << i)) == 0) { continue; } - MEMZERO((void *) reqp, sizeof (*reqp)); + MEMZERO((void *) reqp, QENTRY_LEN); reqp->req_header.rqs_entry_count = 1; reqp->req_header.rqs_entry_type = RQSTYPE_MARKER; reqp->req_modifier = SYNC_ALL; reqp->req_target = i << 7; /* insert bus number */ - ISP_SWIZZLE_REQUEST(isp, reqp); - ISP_ADD_REQUEST(isp, iptr); - - if (isp_getrqentry(isp, &iptr, &optr, (void **)&reqp)) { + isp_put_request(isp, reqp, qep); + ISP_ADD_REQUEST(isp, nxti); + isp->isp_sendmarker &= ~(1 << i); + if (isp_getrqentry(isp, &nxti, &optr, (void **) &qep)) { isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow+"); XS_SETERR(xs, HBA_BOTCH); @@ -2704,7 +2700,7 @@ isp_start(XS_T *xs) } } - MEMZERO((void *) reqp, UZSIZE); + MEMZERO((void *)reqp, QENTRY_LEN); reqp->req_header.rqs_entry_count = 1; if (IS_FC(isp)) { reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS; @@ -2728,16 +2724,16 @@ isp_start(XS_T *xs) * but this breaks for some devices (IBM drives). */ if (XS_TAG_P(xs)) { - t2reqp->req_flags = XS_TAG_TYPE(xs); + ((ispreqt2_t *)reqp)->req_flags = XS_TAG_TYPE(xs); } else { /* * If we don't know what tag to use, use HEAD OF QUEUE * for Request Sense or Simple. */ if (XS_CDBP(xs)[0] == 0x3) /* REQUEST SENSE */ - t2reqp->req_flags = REQFLAG_HTAG; + ((ispreqt2_t *)reqp)->req_flags = REQFLAG_HTAG; else - t2reqp->req_flags = REQFLAG_STAG; + ((ispreqt2_t *)reqp)->req_flags = REQFLAG_STAG; } } else { sdparam *sdp = (sdparam *)isp->isp_param; @@ -2753,34 +2749,29 @@ isp_start(XS_T *xs) reqp->req_cdblen = XS_CDBLEN(xs); } else { if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) - t2reqp->req_scclun = XS_LUN(xs); + ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs); else - t2reqp->req_lun_trn = XS_LUN(xs); + ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs); } MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); reqp->req_time = XS_TIME(xs) / 1000; - if (reqp->req_time == 0 && XS_TIME(xs)) + if (reqp->req_time == 0 && XS_TIME(xs)) { reqp->req_time = 1; - - /* - * Always give a bit more leeway to commands after a bus reset. - * XXX: DOES NOT DISTINGUISH WHICH PORT MAY HAVE BEEN SYNCED - */ - if (isp->isp_sendmarker && reqp->req_time < 5) { - reqp->req_time = 5; } + if (isp_save_xs(isp, xs, &handle)) { isp_prt(isp, ISP_LOGDEBUG0, "out of xflist pointers"); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } reqp->req_handle = handle; + /* * Set up DMA and/or do any bus swizzling of the request entry * so that the Qlogic F/W understands what is being asked of it. - */ - i = ISP_DMASETUP(isp, xs, reqp, &iptr, optr); + */ + i = ISP_DMASETUP(isp, xs, reqp, &nxti, optr); if (i != CMD_QUEUED) { isp_destroy_handle(isp, handle); /* @@ -2794,13 +2785,9 @@ isp_start(XS_T *xs) "START cmd for %d.%d.%d cmd 0x%x datalen %ld", XS_CHANNEL(xs), target, XS_LUN(xs), XS_CDBP(xs)[0], (long) XS_XFRLEN(xs)); - ISP_ADD_REQUEST(isp, iptr); + ISP_ADD_REQUEST(isp, nxti); isp->isp_nactive++; - if (isp->isp_sendmarker) - isp->isp_sendmarker = 0; return (CMD_QUEUED); -#undef reqp -#undef t2reqp } /* @@ -3007,8 +2994,8 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) */ if (sema) { if (mbox & 0x4000) { - int obits, i = 0; - if ((obits = isp->isp_mboxbsy) != 0) { + if (isp->isp_mboxbsy) { + int i = 0, obits = isp->isp_obits; isp->isp_mboxtmp[i++] = mbox; for (i = 1; i < MAX_MAILBOX; i++) { if ((obits & (1 << i)) == 0) { @@ -3119,25 +3106,38 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) ISP_WRITE(isp, BIU_SEMA, 0); while (optr != iptr) { - ispstatusreq_t *sp; + ispstatusreq_t local, *sp = &local; + isphdr_t *hp; + int type; u_int16_t oop; int buddaboom = 0; - sp = (ispstatusreq_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr); + hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr); oop = optr; optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp)); nlooked++; /* - * Do any appropriate unswizzling of what the Qlogic f/w has - * written into memory so it makes sense to us. This is a - * per-platform thing. Also includes any memory barriers. + * Synchronize our view of this response queue entry. */ - ISP_UNSWIZZLE_RESPONSE(isp, sp, oop); - if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) { - if (isp_handle_other_response(isp, sp, &optr) == 0) { - MEMZERO(sp, sizeof (isphdr_t)); + MEMORYBARRIER(isp, SYNC_RESULT, oop, QENTRY_LEN); + + type = isp_get_response_type(isp, hp); + + if (type == RQSTYPE_RESPONSE) { + isp_get_response(isp, (ispstatusreq_t *) hp, sp); + } else { + if (!isp_handle_other_response(isp, type, hp, &optr)) { + MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; } + + /* + * After this point, we'll just look at the header as + * we don't know how to deal with the rest of the + * response. + */ + isp_get_response(isp, (ispstatusreq_t *) hp, sp); + /* * It really has to be a bounced request just copied * from the request queue to the response queue. If @@ -3151,7 +3151,7 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) isp_print_bytes(isp, "Queue Entry", QENTRY_LEN, sp); } - MEMZERO(sp, sizeof (isphdr_t)); + MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; } buddaboom = 1; @@ -3190,7 +3190,7 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) #undef _RQS_OFLAGS } if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) { - MEMZERO(sp, sizeof (isphdr_t)); + MEMZERO(hp, QENTRY_LEN); /* PERF */ isp_prt(isp, ISP_LOGERR, "bad request handle %d (type 0x%x, flags 0x%x)", sp->req_handle, sp->req_header.rqs_entry_type, @@ -3200,7 +3200,7 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) } xs = isp_find_xs(isp, sp->req_handle); if (xs == NULL) { - MEMZERO(sp, sizeof (isphdr_t)); + MEMZERO(hp, QENTRY_LEN); /* PERF */ isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x in xflist", sp->req_handle); @@ -3209,6 +3209,7 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) } isp_destroy_handle(isp, sp->req_handle); if (sp->req_status_flags & RQSTF_BUS_RESET) { + XS_SETERR(xs, HBA_BUSRESET); isp->isp_sendmarker |= (1 << XS_CHANNEL(xs)); } if (buddaboom) { @@ -3332,7 +3333,7 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) if (isp->isp_nactive > 0) isp->isp_nactive--; complist[ndone++] = xs; /* defer completion call until later */ - MEMZERO(sp, sizeof (isphdr_t)); + MEMZERO(hp, QENTRY_LEN); /* PERF */ if (ndone == MAX_REQUESTQ_COMPLETIONS) { break; } @@ -3651,10 +3652,10 @@ isp_parse_async(struct ispsoftc *isp, int mbox) */ static int -isp_handle_other_response(struct ispsoftc *isp, - ispstatusreq_t *sp, u_int16_t *optrp) +isp_handle_other_response(struct ispsoftc *isp, int type, + isphdr_t *hp, u_int16_t *optrp) { - switch (sp->req_header.rqs_entry_type) { + switch (type) { case RQSTYPE_STATUS_CONT: isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response"); return (0); @@ -3669,18 +3670,18 @@ isp_handle_other_response(struct ispsoftc *isp, case RQSTYPE_CTIO2: case RQSTYPE_CTIO3: #ifdef ISP_TARGET_MODE - return (isp_target_notify(isp, sp, optrp)); + return (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)); #else optrp = optrp; /* FALLTHROUGH */ #endif case RQSTYPE_REQUEST: default: - if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, sp)) { + if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, hp)) { return (0); } isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x", - sp->req_header.rqs_entry_type); + isp_get_response_type(isp, hp)); return (-1); } } @@ -4568,7 +4569,8 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) /* * We assume that we can't overwrite a previous command. */ - isp->isp_mboxbsy = obits; + isp->isp_obits = obits; + isp->isp_mboxbsy = 1; /* * Set Host Interrupt condition so that RISC will pick up mailbox regs. @@ -4580,6 +4582,15 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) */ MBOX_WAIT_COMPLETE(isp); + if (isp->isp_mboxbsy) { + /* + * Command timed out. + */ + isp->isp_mboxbsy = 0; + MBOX_RELEASE(isp); + return; + } + /* * Copy back output registers. */ |