From 6bcdc2b5d294b68eff57d05482e825105759bee9 Mon Sep 17 00:00:00 2001 From: mjacob <mjacob@NetBSD.org> Date: Sat, 30 Jan 1999 07:31:50 +0000 Subject: [PATCH] Implement and use Fast Posting for both parallel && fibre. Redo a bit of the startup code. Implement a call to outer framework function so that asynchronous events can be handled (e.g., speed negotiation, target mode). Roll internal release tags. --- sys/dev/ic/isp.c | 468 +++++++++++++++++++++++----------------- sys/dev/ic/isp_netbsd.c | 55 ++++- sys/dev/ic/isp_netbsd.h | 5 +- sys/dev/ic/ispmbox.h | 8 +- sys/dev/ic/ispreg.h | 5 +- sys/dev/ic/ispvar.h | 36 +++- 6 files changed, 363 insertions(+), 214 deletions(-) diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c index c6f7b0ae0820..41ca063db62b 100644 --- a/sys/dev/ic/isp.c +++ b/sys/dev/ic/isp.c @@ -1,5 +1,5 @@ -/* $NetBSD: isp.c,v 1.30 1999/01/10 05:07:53 mjacob Exp $ */ -/* release_12_28_98_A+ */ +/* $NetBSD: isp.c,v 1.31 1999/01/30 07:31:50 mjacob Exp $ */ +/* release_01_29_99 */ /* * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. @@ -118,7 +118,7 @@ static void isp_rdnvram_word __P((struct ispsoftc *, int, u_int16_t *)); /* * Reset Hardware. * - * Hit the chip over the head, download new f/w. + * Hit the chip over the head, download new f/w and set it running. * * Locking done elsewhere. */ @@ -128,7 +128,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,17 +139,40 @@ isp_reset(isp) * here. */ isp->isp_dblev = DFLT_DBLEVEL; - deadchip = ISP_READ(isp, HCCR) & HCCR_RESET; - if (deadchip) { + + /* + * Get the current running firmware revision out of the + * chip before we hit it over the head (if this is our + * first time through). Note that we store this as the + * 'ROM' firmware revision- which it may not be. In any + * case, we don't really use this yet, but we may in + * the future. + */ + if (once == 1) { + /* + * Just in case it was paused... + */ ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); - if (ISP_READ(isp, HCCR) & HCCR_RESET) { - isp_dumpregs(isp, "still reset after release"); - SYS_DELAY(1000); + once = 0; + mbs.param[0] = MBOX_ABOUT_FIRMWARE; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + /* + * If this fails, it probably means we're running + * an old prom, if anything at all... + */ + isp->isp_romfw_rev = 0; } else { - deadchip = 1; + isp->isp_romfw_rev = + (((u_int16_t) mbs.param[1]) << 10) + mbs.param[2]; } } + /* + * Put it into PAUSE mode. + */ + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + if (isp->isp_type & ISP_HA_FC) { revname = "2100"; } else { @@ -192,62 +215,36 @@ isp_reset(isp) break; } /* - * Try and figure out if we're connected to a differential bus. - * You have to pause the RISC processor to read SXP registers. + * Now, while we're at it, gather info about ultra + * and/or differential mode. */ - 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; - } - } + if (isp->isp_bustype != ISP_BT_SBUS) { + ISP_SETBITS(isp, BIU_CONF1, BIU_PCI_CONF1_SXP); + } + if (ISP_READ(isp, SXP_PINS_DIFF) & SXP_PINS_DIFF_MODE) { + PRINTF("%s: Differential Mode\n", isp->isp_name); + sdp->isp_diffmode = 1; } else { - i = 0; + sdp->isp_diffmode = 0; } - if (i > 0) { - if (isp->isp_bustype != ISP_BT_SBUS) { - ISP_SETBITS(isp, BIU_CONF1, BIU_PCI_CONF1_SXP); - } - if (ISP_READ(isp, SXP_PINS_DIFF) & SXP_PINS_DIFF_MODE) { - IDPRINTF(2, ("%s: Differential Mode Set\n", - isp->isp_name)); - sdp->isp_diffmode = 1; - } else { - sdp->isp_diffmode = 0; - } - - if (isp->isp_bustype != ISP_BT_SBUS) { - ISP_CLRBITS(isp, BIU_CONF1, BIU_PCI_CONF1_SXP); - } - - /* - * Figure out whether we're ultra capable. - */ - i = ISP_READ(isp, RISC_PSR); - if (isp->isp_bustype != ISP_BT_SBUS) { - i &= RISC_PSR_PCI_ULTRA; - } else { - i &= RISC_PSR_SBUS_ULTRA; - } - if (i) { - IDPRINTF(2, ("%s: Ultra Mode Capable\n", - isp->isp_name)); - sdp->isp_clock = 60; - } else { - sdp->isp_clock = 40; - } - /* - * Restart processor, if necessary. - */ - if (deadchip == 0) - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); + i = ISP_READ(isp, RISC_PSR); + if (isp->isp_bustype == ISP_BT_SBUS) { + i &= RISC_PSR_SBUS_ULTRA; + } else { + i &= RISC_PSR_PCI_ULTRA; } + if (isp->isp_bustype != ISP_BT_SBUS) { + ISP_CLRBITS(isp, BIU_CONF1, BIU_PCI_CONF1_SXP); + } + if (i != 0) { + PRINTF("%s: Ultra Mode Capable\n", isp->isp_name); + sdp->isp_ultramode = 1; + sdp->isp_clock = 60; + } else { + sdp->isp_ultramode = 0; + sdp->isp_clock = 40; + } + /* * Machine dependent clock (if set) overrides * our generic determinations. @@ -257,6 +254,7 @@ isp_reset(isp) sdp->isp_clock = isp->isp_mdvec->dv_clock; } } + } /* @@ -264,27 +262,7 @@ isp_reset(isp) */ ISP_RESET0(isp); - if (once == 1 && deadchip == 0) { - once = 0; - /* - * Get the current running firmware revision out of the - * chip before we hit it over the head (if this is our - * first time through). Note that we store this as the - * 'ROM' firmware revision- which it may not be. In any - * case, we don't really use this yet, but we may in - * the future. - */ - mbs.param[0] = MBOX_ABOUT_FIRMWARE; - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - IDPRINTF(3, ("%s: initial ABOUT FIRMWARE command " - "failed\n", isp->isp_name)); - } else { - isp->isp_romfw_rev = - (((u_int16_t) mbs.param[1]) << 10) + mbs.param[2]; - } - } - +again: /* * Hit the chip over the head with hammer, @@ -311,6 +289,10 @@ isp_reset(isp) * A slight delay... */ SYS_DELAY(100); + + /* + * Clear data && control DMA engines. + */ ISP_WRITE(isp, CDMA2100_CONTROL, DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT); ISP_WRITE(isp, TDMA2100_CONTROL, @@ -337,41 +319,62 @@ isp_reset(isp) return; } } + /* - * More initialization + * After we've fired this chip up, zero out the conf1 register + * for SCSI adapters and other settings for the 2100. */ - if (isp->isp_type & ISP_HA_SCSI) { + + if (isp->isp_type & ISP_HA_SCSI) { ISP_WRITE(isp, BIU_CONF1, 0); } else { ISP_WRITE(isp, BIU2100_CSR, 0); - /* - * All 2100's are 60Mhz with fast rams onboard. - */ - ISP_WRITE(isp, RISC_MTR2100, 0x1212); } + /* + * Reset RISC Processor + */ ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); SYS_DELAY(100); /* - * Establish some initial burst rate thingies + * Establish some initial burst rate stuff. * (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; + u_int16_t tmp = 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; + tmp &= BIU_BURST_ENABLE; } - ISP_SETBITS(isp, BIU_CONF1, conf1); - if (conf1 & BIU_BURST_ENABLE) { + ISP_SETBITS(isp, BIU_CONF1, tmp); + if (tmp & BIU_BURST_ENABLE) { ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST); ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST); } +#ifdef PTI_CARDS + if (((sdparam *) isp->isp_param)->isp_ultramode) { + while(ISP_READ(isp, RISC_MTR) != 0x1313) { + ISP_WRITE(isp, RISC_MTR, 0x1313); + ISP_WRITE(isp, HCCR, HCCR_CMD_STEP); + } + } else { + ISP_WRITE(isp, RISC_MTR, 0x1212); + } + /* + * PTI specific register + */ + ISP_WRITE(isp, RISC_EMB, DUAL_BANK) +#else + ISP_WRITE(isp, RISC_MTR, 0x1212); +#endif + } else { + ISP_WRITE(isp, RISC_MTR2100, 0x1212); } + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); /* release paused processor */ /* @@ -384,6 +387,25 @@ isp_reset(isp) */ ENABLE_INTS(isp); + /* + * Wait for everything to finish firing up... + */ + loops = MBOX_DELAY_COUNT; + while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) { + SYS_DELAY(100); + if (--loops < 0) { + PRINTF("%s: MBOX_BUSY never cleared on reset\n", + isp->isp_name); + return; + } + } + + /* + * Up until this point we've done everything by just reading or + * setting registers. From this point on we rely on at least *some* + * kind of firmware running in the card. + */ + /* * Do some sanity checking. */ @@ -430,29 +452,29 @@ isp_reset(isp) dodnld = 0; } - if (dodnld) { + if (dodnld && isp->isp_mdvec->dv_fwlen) { for (i = 0; i < isp->isp_mdvec->dv_fwlen; i++) { mbs.param[0] = MBOX_WRITE_RAM_WORD; mbs.param[1] = isp->isp_mdvec->dv_codeorg + i; mbs.param[2] = isp->isp_mdvec->dv_ispfw[i]; isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_dumpregs(isp, "f/w download failed"); - return; + PRINTF("%s: F/W download failed at word %d\n", + isp->isp_name, i); + dodnld = 0; + goto again; } } - if (isp->isp_mdvec->dv_fwlen) { - /* - * Verify that it downloaded correctly. - */ - mbs.param[0] = MBOX_VERIFY_CHECKSUM; - mbs.param[1] = isp->isp_mdvec->dv_codeorg; - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_dumpregs(isp, "ram checksum failure"); - return; - } + /* + * Verify that it downloaded correctly. + */ + mbs.param[0] = MBOX_VERIFY_CHECKSUM; + mbs.param[1] = isp->isp_mdvec->dv_codeorg; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_dumpregs(isp, "ram checksum failure"); + return; } } else { IDPRINTF(3, ("%s: skipping f/w download\n", isp->isp_name)); @@ -466,7 +488,10 @@ isp_reset(isp) */ mbs.param[0] = MBOX_EXEC_FIRMWARE; - mbs.param[1] = isp->isp_mdvec->dv_codeorg; + if (isp->isp_mdvec->dv_codeorg) + mbs.param[1] = isp->isp_mdvec->dv_codeorg; + else + mbs.param[1] = 0x1000; isp_mboxcmd(isp, &mbs); if (isp->isp_type & ISP_HA_SCSI) { @@ -506,7 +531,7 @@ isp_reset(isp) } /* - * Initialize Hardware to known state + * Initialize Parameters of Hardware to a known state. * * Locks are held before coming here. */ @@ -674,6 +699,10 @@ isp_init(isp) break; } } + /* + * And mark this as an unannounced device + */ + sdp->isp_devparam[tgt].dev_announced = 0; } /* @@ -710,6 +739,19 @@ isp_init(isp) } isp->isp_reqidx = isp->isp_reqodx = 0; + /* + * Turn on Fast Posting + */ + if (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); + } + } + /* * XXX: See whether or not for 7.55 F/W or later we * XXX: can do without this, and see whether we should @@ -763,6 +805,15 @@ isp_fibre_init(isp) loopid = fcp->isp_loopid; #endif +#if defined(ISP2100_FABRIC) && defined(ISP2100_SCCLUN) + PRINTF("%s: Fabric Support, Expanded Lun Support\n", isp->isp_name); +#endif +#if defined(ISP2100_FABRIC) && !defined(ISP2100_SCCLUN) + PRINTF("%s: Fabric Support\n", isp->isp_name); +#endif +#if !defined(ISP2100_FABRIC) && defined(ISP2100_SCCLUN) + PRINTF("%s: Expanded Lun Support\n", isp->isp_name); +#endif icbp = (isp_icb_t *) fcp->isp_scratch; MEMZERO(icbp, sizeof (*icbp)); @@ -773,7 +824,7 @@ isp_fibre_init(isp) #else fcp->isp_fwoptions = 0; #endif - fcp->isp_fwoptions |= ICBOPT_INI_ADISC|ICBOPT_FAIRNESS; + fcp->isp_fwoptions |= ICBOPT_INI_ADISC|ICBOPT_FAIRNESS|ICBOPT_FAST_POST; fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; #ifdef CHECKME @@ -785,6 +836,7 @@ isp_fibre_init(isp) */ fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; #endif + icbp->icb_fwoptions = fcp->isp_fwoptions; icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || @@ -1058,7 +1110,7 @@ ispscsicmd(xs) #endif } - memcpy(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); + MEMCPY(reqp->req_cdb, XS_CDBP(xs), 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, @@ -1227,9 +1279,28 @@ 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)) - return (1); + u_int32_t fast_post_handle = isp_parse_async(isp, (int) mbox); ISP_WRITE(isp, BIU_SEMA, 0); + if (fast_post_handle < 0) { + return (1); + } else if (fast_post_handle > 0) { + xs = (ISP_SCSI_XFER_T *) + isp->isp_xflist[fast_post_handle - 1]; + isp->isp_xflist[fast_post_handle - 1] = NULL; + /* + * Since we don't have a result queue entry item, + * we must believe that SCSI status is zero and + * that all data transferred. + */ + XS_RESID(xs) = 0; + XS_STS(xs) = 0; + if (XS_XFRLEN(xs)) { + ISP_DMAFREE(isp, xs, fast_post_handle - 1); + } + if (isp->isp_nactive > 0) + isp->isp_nactive--; + complist[ndone++] = xs; + } } ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); @@ -1319,14 +1390,24 @@ 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, + MEMCPY(XS_SNSP(xs), sp->req_sense_data, XS_SNSLEN(xs)); XS_SNS_IS_VALID(xs); } + /* + * A new synchronous rate was negotiated for this + * target. Mark state such that we'll go look up + * that which has changed later. + */ + if (sp->req_status_flags & RQSTF_NEGOTIATION) { + sdparam *sdp = isp->isp_param; + isp->isp_update = 1; + sdp->isp_devparam[XS_TGT(xs)].dev_refresh = 1; + } } else { if (XS_STS(xs) == SCSI_CHECK) { XS_SNS_IS_VALID(xs); - memcpy(XS_SNSP(xs), sp->req_sense_data, + MEMCPY(XS_SNSP(xs), sp->req_sense_data, XS_SNSLEN(xs)); sp->req_state_flags |= RQSF_GOT_SENSE; } @@ -1419,6 +1500,8 @@ isp_parse_async(isp, mbox) struct ispsoftc *isp; int mbox; { + u_int32_t fast_post_handle = 0; + switch (mbox) { case ASYNC_BUS_RESET: PRINTF("%s: SCSI bus reset detected\n", isp->isp_name); @@ -1434,7 +1517,7 @@ isp_parse_async(isp, mbox) isp->isp_name, mbox); isp_restart(isp); /* no point continuing after this */ - return (1); + return (-1); case ASYNC_RQS_XFER_ERR: PRINTF("%s: Request Queue Transfer Error\n", isp->isp_name); @@ -1489,11 +1572,10 @@ isp_parse_async(isp, mbox) break; case ASYNC_CMD_CMPLT: - PRINTF("%s: fast post completion\n", isp->isp_name); -#if 0 - fast_post_handle = (ISP_READ(isp, OUTMAILBOX1) << 16) | - ISP_READ(isp, OUTMAILBOX2); -#endif + fast_post_handle = (ISP_READ(isp, OUTMAILBOX2) << 16) | + ISP_READ(isp, OUTMAILBOX1); + IDPRINTF(3, ("%s: fast post completion of %u\n", isp->isp_name, + fast_post_handle)); break; case ASYNC_CTIO_DONE: @@ -1532,7 +1614,7 @@ isp_parse_async(isp, mbox) PRINTF("%s: async %x\n", isp->isp_name, mbox); break; } - return (0); + return (fast_post_handle); } static int @@ -1718,7 +1800,7 @@ 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); + MEMCPY(fcp->isp_scratch, tgtiqd, s); } else { s = at2->req_datalen; MEMZERO(fcp->isp_scratch, s); @@ -1773,7 +1855,7 @@ 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, + MEMCPY(ct2->req_m.mode1.req_response, at2->req_sense, sizeof (at2->req_sense)); } break; @@ -1826,7 +1908,7 @@ isp_handle_other_response(isp, sp, optrp) PRINTF("%s: Request Queue Overflow other response\n", isp->isp_name); } else { - memcpy(reqp, ireqp, reqsize); + MEMCPY(reqp, ireqp, reqsize); ISP_WRITE(isp, INMAILBOX4, iptr); isp->isp_reqidx = iptr; } @@ -1954,7 +2036,7 @@ isp_notify_ack(isp, ptrp) PRINTF("%s: Request Queue Overflow For isp_notify_ack\n", isp->isp_name); } else { - memcpy(reqp, ireqp, sizeof (un)); + MEMCPY(reqp, ireqp, sizeof (un)); ISP_WRITE(isp, INMAILBOX4, iptr); isp->isp_reqidx = iptr; } @@ -2009,7 +2091,7 @@ isp_handle_atio (isp, aep) if (status & TGTSVALID) { - memcpy(&cdp->cd_sensedata, aep->at_sense, + 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); @@ -2050,7 +2132,7 @@ isp_handle_atio (isp, aep) 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); + 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); @@ -2126,7 +2208,7 @@ isp_handle_atio2(isp, aep) cdp->cd_iid = aep->at_iid; cdp->cd_tgt = 0; cdp->cd_lun = aep->at_lun; - memcpy(cdp->cd_cdb, aep->at_cdb, 16); + MEMCPY(cdp->cd_cdb, aep->at_cdb, 16); cdp->cd_rxid = aep->at_rxid; cdp->cp_origdlen = aep->at_datalen; cdp->cp_totbytes = 0; @@ -2354,8 +2436,8 @@ isp_parse_status(isp, sp, xs) if (isp->isp_type & ISP_HA_SCSI) { sdparam *sdp = isp->isp_param; isp->isp_update = 1; - sdp->isp_devparam[XS_TGT(xs)].dev_update = 1; sdp->isp_devparam[XS_TGT(xs)].dev_flags &= ~DPARM_WIDE; + sdp->isp_devparam[XS_TGT(xs)].dev_update = 1; } XS_SETERR(xs, HBA_NOERROR); return; @@ -2366,8 +2448,8 @@ isp_parse_status(isp, sp, xs) if (isp->isp_type & ISP_HA_SCSI) { sdparam *sdp = isp->isp_param; isp->isp_update = 1; - sdp->isp_devparam[XS_TGT(xs)].dev_update = 1; sdp->isp_devparam[XS_TGT(xs)].dev_flags &= ~DPARM_SYNC; + sdp->isp_devparam[XS_TGT(xs)].dev_update = 1; } break; @@ -2491,8 +2573,8 @@ static u_int8_t mbpcnt[] = { MAKNIB(0, 0), /* 0x47: */ MAKNIB(0, 0), /* 0x48: */ MAKNIB(0, 0), /* 0x49: */ - MAKNIB(0, 0), /* 0x4a: */ - MAKNIB(0, 0), /* 0x4b: */ + MAKNIB(2, 1), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */ + MAKNIB(1, 2), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */ MAKNIB(0, 0), /* 0x4c: */ MAKNIB(0, 0), /* 0x4d: */ MAKNIB(0, 0), /* 0x4e: */ @@ -2879,77 +2961,68 @@ isp_update(isp) sdp = isp->isp_param; for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + u_int16_t flags, period, offset, changed; + int get; + if (sdp->isp_devparam[tgt].dev_enable == 0) { continue; } - if (sdp->isp_devparam[tgt].dev_update == 0) { + + if (sdp->isp_devparam[tgt].dev_update) { + mbs.param[0] = MBOX_SET_TARGET_PARAMS; + mbs.param[2] = sdp->isp_devparam[tgt].dev_flags; + mbs.param[3] = + (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; + get = 0; + } else if (sdp->isp_devparam[tgt].dev_refresh) { + mbs.param[0] = MBOX_GET_TARGET_PARAMS; + sdp->isp_devparam[tgt].dev_refresh = 0; + get = 1; + } else { + continue; + } + mbs.param[1] = tgt << 8; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + PRINTF("%s: failed to %cet SCSI parameters for " + "target %d\n", isp->isp_name, (get)? 'g' : 's', + tgt); continue; } - mbs.param[0] = MBOX_SET_TARGET_PARAMS; - mbs.param[1] = tgt << 8; - mbs.param[2] = sdp->isp_devparam[tgt].dev_flags; - mbs.param[3] = - (sdp->isp_devparam[tgt].sync_offset << 8) | - (sdp->isp_devparam[tgt].sync_period); - - IDPRINTF(3, ("\n%s: tgt %d cflags %x offset %x period %x\n", - isp->isp_name, tgt, mbs.param[2], mbs.param[3] >> 8, - mbs.param[3] & 0xff)); - - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed to change SCSI parameters for " - "target %d\n", isp->isp_name, tgt); - } else { - char *wt; - int x, flags; - - flags = sdp->isp_devparam[tgt].cur_dflags = + if (get == 0) { + sdp->isp_devparam[tgt].cur_dflags = sdp->isp_devparam[tgt].dev_flags; - - x = sdp->isp_devparam[tgt].sync_period & 0xff; - if (flags & DPARM_SYNC) { - if (x == (ISP_20M_SYNCPARMS & 0xff)) { - x = 20; - } else if (x == (ISP_10M_SYNCPARMS & 0xff)) { - x = 10; - } else if (x == (ISP_08M_SYNCPARMS & 0xff)) { - x = 8; - } else if (x == (ISP_05M_SYNCPARMS & 0xff)) { - x = 5; - } else if (x == (ISP_04M_SYNCPARMS & 0xff)) { - x = 4; - } else { - x = 0; - } - } else { - x = 0; - } - switch (flags & (DPARM_WIDE|DPARM_TQING)) { - case DPARM_WIDE: - wt = ", 16 bit wide\n"; - break; - case DPARM_TQING: - wt = ", Tagged Queueing Enabled\n"; - break; - case DPARM_WIDE|DPARM_TQING: - wt = ", 16 bit wide, Tagged Queueing Enabled\n"; - break; - - default: - wt = "\n"; - break; - } - if (x) { - IDPRINTF(3, ("%s: Target %d maximum Sync Mode " - "at %dMHz%s", isp->isp_name, tgt, x, wt)); - } else { - IDPRINTF(3, ("%s: Target %d Async Mode%s", - isp->isp_name, tgt, wt)); - } + 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) { + IDPRINTF(3, ("%s: tgt %d flags 0x%x period %d " + "off %d\n", isp->isp_name, tgt, flags, + period, offset)); + changed = 1; + } 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; + 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; + else + sdp->isp_devparam[tgt].dev_announced = 1; } - sdp->isp_devparam[tgt].dev_update = 0; } } @@ -3283,7 +3356,6 @@ isp_read_nvram(isp) ISP_NVRAM_MAX_QUEUE_DEPTH(nvram_data); 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, diff --git a/sys/dev/ic/isp_netbsd.c b/sys/dev/ic/isp_netbsd.c index 209e624b6993..3b762a7da071 100644 --- a/sys/dev/ic/isp_netbsd.c +++ b/sys/dev/ic/isp_netbsd.c @@ -1,5 +1,5 @@ -/* $NetBSD: isp_netbsd.c,v 1.8 1998/12/28 19:10:43 mjacob Exp $ */ -/* release_12_28_98_A */ +/* $NetBSD: isp_netbsd.c,v 1.9 1999/01/30 07:31:50 mjacob Exp $ */ +/* release_01_29_99 */ /* * Platform (NetBSD) dependent common attachment code for Qlogic adapters. * @@ -300,3 +300,54 @@ isp_uninit(isp) ISP_IUNLOCK(isp); } + +int +isp_async(isp, cmd, arg) + struct ispsoftc *isp; + ispasync_t cmd; + void *arg; +{ + switch (cmd) { + case ISPASYNC_NEW_TGT_PARAMS: + if (isp->isp_type & ISP_HA_SCSI) { + sdparam *sdp = isp->isp_param; + char *wt; + int ns, flags, tgt; + + tgt = *((int *) arg); + + flags = sdp->isp_devparam[tgt].dev_flags; + if (flags & DPARM_SYNC) { + ns = sdp->isp_devparam[tgt].sync_period * 4; + } else { + ns = 0; + } + switch (flags & (DPARM_WIDE|DPARM_TQING)) { + case DPARM_WIDE: + wt = ", 16 bit wide\n"; + break; + case DPARM_TQING: + wt = ", Tagged Queueing Enabled\n"; + break; + case DPARM_WIDE|DPARM_TQING: + wt = ", 16 bit wide, Tagged Queueing Enabled\n"; + break; + default: + wt = "\n"; + break; + } + if (ns) { + printf("%s: Target %d at %dMHz Max Offset %d%s", + isp->isp_name, tgt, 1000 / ns, + sdp->isp_devparam[tgt].sync_offset, wt); + } else { + printf("%s: Target %d Async Mode%s", + isp->isp_name, tgt, wt); + } + } + break; + default: + break; + } + return (0); +} diff --git a/sys/dev/ic/isp_netbsd.h b/sys/dev/ic/isp_netbsd.h index 73fc2107b716..0681198a768a 100644 --- a/sys/dev/ic/isp_netbsd.h +++ b/sys/dev/ic/isp_netbsd.h @@ -1,5 +1,5 @@ -/* $NetBSD: isp_netbsd.h,v 1.8 1999/01/10 05:04:18 mjacob Exp $ */ -/* release_12_28_98_A+ */ +/* $NetBSD: isp_netbsd.h,v 1.9 1999/01/30 07:31:50 mjacob Exp $ */ +/* release_01_29_99 */ /* * NetBSD Specific definitions for the Qlogic ISP Host Adapter * @@ -81,6 +81,7 @@ struct isposinfo { #define IDPRINTF(lev, x) if (isp->isp_dblev >= lev) printf x #define MEMZERO bzero +#define MEMCPY(dst, src, count) bcopy((src), (dst), (count)) #if defined(SCSIDEBUG) #define DFLT_DBLEVEL 3 diff --git a/sys/dev/ic/ispmbox.h b/sys/dev/ic/ispmbox.h index 0dbe8f302f13..1d54fb6ef9df 100644 --- a/sys/dev/ic/ispmbox.h +++ b/sys/dev/ic/ispmbox.h @@ -1,5 +1,5 @@ -/* $NetBSD: ispmbox.h,v 1.11 1998/12/28 19:10:43 mjacob Exp $ */ -/* release_12_28_98_A */ +/* $NetBSD: ispmbox.h,v 1.12 1999/01/30 07:31:51 mjacob Exp $ */ +/* release_01_29_99 */ /* * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters. * @@ -109,6 +109,10 @@ #define MBOX_RETURN_BIOS_BLOCK_ADDR 0x0040 #define MBOX_WRITE_FOUR_RAM_WORDS 0x0041 #define MBOX_EXEC_BIOS_IOCB 0x0042 +#define MBOX_SET_FW_FEATURES 0x004a +#define MBOX_GET_FW_FEATURES 0x004b +#define FW_FEATURE_LVD_NOTIFY 0x2 +#define FW_FEATURE_FAST_POST 0x1 /* These are for the ISP2100 FC cards */ #define MBOX_GET_LOOP_ID 0x20 diff --git a/sys/dev/ic/ispreg.h b/sys/dev/ic/ispreg.h index 5497d779b1c8..ce30f9ebb14a 100644 --- a/sys/dev/ic/ispreg.h +++ b/sys/dev/ic/ispreg.h @@ -1,5 +1,5 @@ -/* $NetBSD: ispreg.h,v 1.10 1998/12/28 19:10:43 mjacob Exp $ */ -/* release_12_28_98_A */ +/* $NetBSD: ispreg.h,v 1.11 1999/01/30 07:31:51 mjacob Exp $ */ +/* release_01_29_99 */ /* * Machine Independent (well, as best as possible) register * definitions for Qlogic ISP SCSI adapters. @@ -514,6 +514,7 @@ #define RISC_MTR2100 RISC_BLOCK+0x30 #define RISC_EMB RISC_BLOCK+0x30 /* RW*: Ext Mem Boundary */ +#define DUAL_BANK 8 #define RISC_SP RISC_BLOCK+0x32 /* RW*: Stack Pointer */ #define RISC_HRL RISC_BLOCK+0x3e /* R *: Hardware Rev Level */ #define HCCR RISC_BLOCK+0x40 /* RW : Host Command & Ctrl */ diff --git a/sys/dev/ic/ispvar.h b/sys/dev/ic/ispvar.h index 74d08416fecb..8be5919a7afb 100644 --- a/sys/dev/ic/ispvar.h +++ b/sys/dev/ic/ispvar.h @@ -1,5 +1,5 @@ -/* $NetBSD: ispvar.h,v 1.16 1999/01/10 05:04:46 mjacob Exp $ */ -/* release_12_28_98_A+ */ +/* $NetBSD: ispvar.h,v 1.17 1999/01/30 07:31:51 mjacob Exp $ */ +/* release_01_29_99 */ /* * Soft Definitions for for Qlogic ISP SCSI adapters. * @@ -51,7 +51,7 @@ #define ISP_CORE_VERSION_MINOR 5 /* - * Vector for MD code to provide specific services. + * Vector for bus specific code to provide specific services. */ struct ispsoftc; struct ispmdvec { @@ -91,7 +91,7 @@ struct ispmdvec { ((in == out)? (qlen - 1) : ((in > out)? \ ((qlen - 1) - (in - out)) : (out - in - 1))) /* - * SCSI (as opposed to FC-PH) Specific Host Adapter Parameters + * SCSI Specific Host Adapter Parameters */ typedef struct { @@ -100,6 +100,7 @@ typedef struct { isp_cmd_dma_burst_enable: 1, isp_data_dma_burst_enabl: 1, isp_fifo_threshold : 3, + isp_ultramode : 1, isp_diffmode : 1, isp_fast_mttr : 1, isp_initiator_id : 4, @@ -112,8 +113,11 @@ typedef struct { u_int8_t isp_retry_count; u_int8_t isp_retry_delay; struct { - u_int dev_update : 1, + u_int dev_enable : 1, + dev_announced : 1, + dev_update : 1, + dev_refresh : 1, exc_throttle : 7, sync_offset : 4, sync_period : 8; @@ -272,7 +276,7 @@ struct ispsoftc { * jeez, so I blow a couple of KB per host adapter... * and it *is* faster. */ - volatile ISP_SCSI_XFER_T *isp_xflist[RQUEST_QUEUE_LEN]; + ISP_SCSI_XFER_T *isp_xflist[RQUEST_QUEUE_LEN]; /* * request/result queues and dma handles for them. @@ -340,7 +344,7 @@ struct ispsoftc { #define ISP_HA_FC_2100 0x10 /* - * Macros to read, write ISP registers through MD code + * Macros to read, write ISP registers through bus specific code. */ #define ISP_READ(isp, reg) \ @@ -403,13 +407,14 @@ int isp_intr __P((void *)); int32_t ispscsicmd __P((ISP_SCSI_XFER_T *)); /* - * Platform Dependent to Internal Control Point + * Platform Dependent to External to Internal Control Function * * For: Aborting a running command - arg is an ISP_SCSI_XFER_T * * Resetting a Device - arg is target to reset * Resetting a BUS - arg is ignored * Updating parameters - arg is ignored * + * First argument is this instance's softc pointer. * Second argument is an index into xflist array. * Assumes all locks must be held already. */ @@ -421,6 +426,21 @@ typedef enum { } ispctl_t; int isp_control __P((struct ispsoftc *, ispctl_t, void *)); + +/* + * Platform Dependent to Internal to External Control Function + * (each platform must provide such a function) + * + * For: Announcing Target Paramter Changes (arg is target) + * + * Assumes all locks are held. + */ + +typedef enum { + ISPASYNC_NEW_TGT_PARAMS +} ispasync_t; +int isp_async __P((struct ispsoftc *, ispasync_t, void *)); + /* * lost command routine (XXXX IN TRANSITION XXXX) */