From owner-p4-projects@FreeBSD.ORG Tue Dec 19 04:11:27 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id A987116A47B; Tue, 19 Dec 2006 04:11:27 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 6918D16A403 for ; Tue, 19 Dec 2006 04:11:27 +0000 (UTC) (envelope-from mjacob@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.FreeBSD.org (Postfix) with ESMTP id BC35F43C9F for ; Tue, 19 Dec 2006 04:11:26 +0000 (GMT) (envelope-from mjacob@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id kBJ4BQ0a009737 for ; Tue, 19 Dec 2006 04:11:26 GMT (envelope-from mjacob@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id kBJ4BOeV009703 for perforce@freebsd.org; Tue, 19 Dec 2006 04:11:24 GMT (envelope-from mjacob@freebsd.org) Date: Tue, 19 Dec 2006 04:11:24 GMT Message-Id: <200612190411.kBJ4BOeV009703@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to mjacob@freebsd.org using -f From: Matt Jacob To: Perforce Change Reviews Cc: Subject: PERFORCE change 111920 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Dec 2006 04:11:27 -0000 http://perforce.freebsd.org/chv.cgi?CH=111920 Change 111920 by mjacob@mjexp_6 on 2006/12/19 04:10:55 Wankatootl Fruitl! Pull the -current isp && mpt driver bundles into a RELENG_6 tree for integration testing. Affected files ... .. //depot/projects/mjexp_6/sys/dev/isp/isp.c#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_freebsd.c#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_freebsd.h#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_ioctl.h#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_library.c#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_library.h#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_pci.c#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_sbus.c#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_stds.h#1 add .. //depot/projects/mjexp_6/sys/dev/isp/isp_target.c#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_target.h#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/isp_tpublic.h#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/ispmbox.h#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/ispreg.h#2 edit .. //depot/projects/mjexp_6/sys/dev/isp/ispvar.h#2 edit .. //depot/projects/mjexp_6/sys/dev/ispfw/asm_2400.h#1 add .. //depot/projects/mjexp_6/sys/dev/ispfw/ispfw.c#2 edit .. //depot/projects/mjexp_6/sys/dev/mpt/mpt.c#2 edit .. //depot/projects/mjexp_6/sys/dev/mpt/mpt.h#2 edit .. //depot/projects/mjexp_6/sys/dev/mpt/mpt_cam.c#2 edit .. //depot/projects/mjexp_6/sys/dev/mpt/mpt_debug.c#2 edit .. //depot/projects/mjexp_6/sys/dev/mpt/mpt_raid.c#2 edit Differences ... ==== //depot/projects/mjexp_6/sys/dev/isp/isp.c#2 (text+ko) ==== @@ -26,8 +26,9 @@ /* * Machine and OS Independent (well, as best as possible) - * code for the Qlogic ISP SCSI adapters. + * code for the Qlogic ISP SCSI and FC-SCSI adapters. */ + /* * Inspiration and ideas about this driver are from Erik Moe's Linux driver * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some @@ -60,30 +61,16 @@ */ #define MBOX_DELAY_COUNT 1000000 / 100 +#define ISP_MARK_PORTDB(a, b) \ + isp_prt(isp, ISP_LOGSANCFG, "line %d: markportdb", __LINE__); \ + isp_mark_portdb(a, b) /* * Local static data */ -static const char portshift[] = - "Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)"; -static const char portdup[] = - "Target %d duplicates Target %d- killing off both"; -static const char retained[] = - "Retaining Loop ID 0x%x for Target %d (Port 0x%x)"; -static const char lretained[] = - "Retained login of Target %d (Loop ID 0x%x) Port 0x%x"; -static const char plogout[] = - "Logging out Target %d at Loop ID 0x%x (Port 0x%x)"; -static const char plogierr[] = - "Command Error in PLOGI for Port 0x%x (0x%x)"; -static const char nopdb[] = - "Could not get PDB for Device @ Port 0x%x"; -static const char pdbmfail1[] = - "PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)"; -static const char pdbmfail2[] = - "PDB Port info for Device @ Port 0x%x does not match up (0x%x)"; -static const char ldumped[] = - "Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch"; +static const char fconf[] = + "PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n" + " database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)"; static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d"; static const char xact1[] = @@ -95,9 +82,9 @@ static const char pskip[] = "SCSI phase skipped for target %d.%d.%d"; static const char topology[] = - "Loop ID %d, Port ID 0x%x, Loop State 0x%x, Topology '%s'"; -static const char swrej[] = - "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x"; + "HBA PortID 0x%06x N-Port Handle %d, Connection Topology '%s'"; +static const char ourwwn[] = + "HBA WWNN 0x%08x%08x HBA WWPN 0x%08x%08x"; static const char finmsg[] = "%d.%d.%d: FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x"; static const char sc0[] = @@ -115,38 +102,51 @@ */ static int isp_parse_async(ispsoftc_t *, uint16_t); static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, - uint16_t *); + uint32_t *); +static void +isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *); static void -isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *); +isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *); static void isp_fastpost_complete(ispsoftc_t *, uint16_t); static int isp_mbox_continue(ispsoftc_t *); static void isp_scsi_init(ispsoftc_t *); static void isp_scsi_channel_init(ispsoftc_t *, int); static void isp_fibre_init(ispsoftc_t *); -static void isp_mark_getpdb_all(ispsoftc_t *); -static int isp_getmap(ispsoftc_t *, fcpos_map_t *); -static int isp_getpdb(ispsoftc_t *, int, isp_pdb_t *); +static void isp_fibre_init_2400(ispsoftc_t *); +static void isp_mark_portdb(ispsoftc_t *, int); +static int isp_plogx(ispsoftc_t *, uint16_t, uint32_t, int, int); +static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t); +static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t); +static int isp_getpdb(ispsoftc_t *, uint16_t, isp_pdb_t *, int); static uint64_t isp_get_portname(ispsoftc_t *, int, int); static int isp_fclink_test(ispsoftc_t *, int); -static const char *isp2100_fw_statename(int); +static const char *ispfc_fw_statename(int); static int isp_pdb_sync(ispsoftc_t *); static int isp_scan_loop(ispsoftc_t *); -static int isp_fabric_mbox_cmd(ispsoftc_t *, mbreg_t *); -static int isp_scan_fabric(ispsoftc_t *, int); -static void isp_register_fc4_type(ispsoftc_t *); +static int isp_gid_ft_sns(ispsoftc_t *); +static int isp_gid_ft_ct_passthru(ispsoftc_t *); +static int isp_scan_fabric(ispsoftc_t *); +static int isp_login_device(ispsoftc_t *, uint32_t, isp_pdb_t *, uint16_t *); +static int isp_register_fc4_type(ispsoftc_t *); +static int isp_register_fc4_type_24xx(ispsoftc_t *); +static uint16_t isp_nxt_handle(ispsoftc_t *, uint16_t); static void isp_fw_state(ispsoftc_t *); static void isp_mboxcmd_qnw(ispsoftc_t *, mbreg_t *, int); -static void isp_mboxcmd(ispsoftc_t *, mbreg_t *, int); +static void isp_mboxcmd(ispsoftc_t *, mbreg_t *); static void isp_update(ispsoftc_t *); static void isp_update_bus(ispsoftc_t *, int); static void isp_setdfltparm(ispsoftc_t *, int); static int isp_read_nvram(ispsoftc_t *); +static int isp_read_nvram_2400(ispsoftc_t *); static void isp_rdnvram_word(ispsoftc_t *, int, uint16_t *); +static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *); static void isp_parse_nvram_1020(ispsoftc_t *, uint8_t *); static void isp_parse_nvram_1080(ispsoftc_t *, int, uint8_t *); static void isp_parse_nvram_12160(ispsoftc_t *, int, uint8_t *); +static void isp_fix_nvram_wwns(ispsoftc_t *); static void isp_parse_nvram_2100(ispsoftc_t *, uint8_t *); +static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *); /* * Reset Hardware. @@ -160,9 +160,10 @@ isp_reset(ispsoftc_t *isp) { mbreg_t mbs; - uint32_t code_org; + uint32_t code_org, val; int loops, i, dodnld = 1; - char *btype = "????"; + static const char *btype = "????"; + static const char dcrc[] = "Downloaded RISC Code Checksum Failure"; isp->isp_state = ISP_NILSTATE; @@ -202,10 +203,16 @@ /* * Just in case it was paused... */ - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, + HCCR_2400_CMD_RELEASE); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); + } MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_ABOUT_FIRMWARE; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { isp->isp_romfw_rev[0] = mbs.param[1]; isp->isp_romfw_rev[1] = mbs.param[2]; @@ -215,21 +222,51 @@ isp->isp_touched = 1; } - DISABLE_INTS(isp); + ISP_DISABLE_INTS(isp); + + /* + * Pick an initial maxcmds value which will be used + * to allocate xflist pointer space. It may be changed + * later by the firmware. + */ + if (IS_24XX(isp)) { + isp->isp_maxcmds = 4096; + } else if (IS_2322(isp)) { + isp->isp_maxcmds = 2048; + } else if (IS_23XX(isp) || IS_2200(isp)) { + isp->isp_maxcmds = 1024; + } else { + isp->isp_maxcmds = 512; + } + + /* + * Set up DMA for the request and result queues. + * + * We do this now so we can use the request queue + * for a dma + */ + if (ISP_MBOXDMASETUP(isp) != 0) { + isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); + return; + } + /* * Set up default request/response queue in-pointer/out-pointer * register indices. */ - if (IS_23XX(isp)) { + if (IS_24XX(isp)) { + isp->isp_rqstinrp = BIU2400_REQINP; + isp->isp_rqstoutrp = BIU2400_REQOUTP; + isp->isp_respinrp = BIU2400_RSPINP; + isp->isp_respoutrp = BIU2400_RSPOUTP; + isp->isp_atioinrp = BIU2400_ATIO_RSPINP; + isp->isp_atiooutrp = BIU2400_ATIO_REQINP; + } else if (IS_23XX(isp)) { isp->isp_rqstinrp = BIU_REQINP; isp->isp_rqstoutrp = BIU_REQOUTP; isp->isp_respinrp = BIU_RSPINP; isp->isp_respoutrp = BIU_RSPOUTP; - ISP_WRITE(isp, isp->isp_rqstinrp, 0); - ISP_WRITE(isp, isp->isp_rqstoutrp, 0); - ISP_WRITE(isp, isp->isp_respinrp, 0); - ISP_WRITE(isp, isp->isp_respoutrp, 0); } else { isp->isp_rqstinrp = INMAILBOX4; isp->isp_rqstoutrp = OUTMAILBOX4; @@ -241,7 +278,13 @@ * Put the board into PAUSE mode (so we can read the SXP registers * or write FPM/FBM registers). */ - ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + } if (IS_FC(isp)) { switch (isp->isp_type) { @@ -260,20 +303,24 @@ case ISP_HA_FC_2322: btype = "2322"; break; - case ISP_HA_FC_2422: + case ISP_HA_FC_2400: btype = "2422"; break; default: break; } - /* - * While we're paused, reset the FPM module and FBM fifos. - */ - ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); - ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); - ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); - ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); - ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); + + if (!IS_24XX(isp)) { + /* + * While we're paused, reset the FPM module and FBM + * fifos. + */ + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); + ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); + ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); + } } else if (IS_1240(isp)) { sdparam *sdp = isp->isp_param; btype = "1240"; @@ -443,8 +490,6 @@ */ ISP_RESET0(isp); -again: - /* * Hit the chip over the head with hammer, * and give the ISP a chance to recover. @@ -466,6 +511,44 @@ DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT); + } else if (IS_24XX(isp)) { + /* + * Stop DMA and wait for it to stop. + */ + ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4)); + for (val = loops = 0; loops < 30000; loops++) { + USEC_DELAY(10); + val = ISP_READ(isp, BIU2400_CSR); + if ((val & BIU2400_DMA_ACTIVE) == 0) { + break; + } + } + if (val & BIU2400_DMA_ACTIVE) { + ISP_RESET0(isp); + isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset"); + return; + } + /* + * Hold it in SOFT_RESET and STOP state for 100us. + */ + ISP_WRITE(isp, BIU2400_CSR, + BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4)); + USEC_DELAY(100); + for (loops = 0; loops < 10000; loops++) { + USEC_DELAY(5); + val = ISP_READ(isp, OUTMAILBOX0); + } + for (val = loops = 0; loops < 500000; loops ++) { + val = ISP_READ(isp, BIU2400_CSR); + if ((val & BIU2400_SOFT_RESET) == 0) { + break; + } + } + if (val & BIU2400_SOFT_RESET) { + ISP_RESET0(isp); + isp_prt(isp, ISP_LOGERR, "Failed to come out of reset"); + return; + } } else { ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET); /* @@ -490,8 +573,13 @@ loops = MBOX_DELAY_COUNT; for (;;) { if (IS_SCSI(isp)) { - if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET)) + if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET)) { + break; + } + } else if (IS_24XX(isp)) { + if (ISP_READ(isp, OUTMAILBOX0) == 0) { break; + } } else { if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET)) break; @@ -499,6 +587,7 @@ USEC_DELAY(100); if (--loops < 0) { ISP_DUMPREGS(isp, "chip reset timed out"); + ISP_RESET0(isp); return; } } @@ -510,24 +599,41 @@ if (IS_SCSI(isp)) { ISP_WRITE(isp, BIU_CONF1, 0); - } else { + } else if (!IS_24XX(isp)) { ISP_WRITE(isp, BIU2100_CSR, 0); } /* * Reset RISC Processor */ - ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); - USEC_DELAY(100); - /* Clear semaphore register (just to be sure) */ - ISP_WRITE(isp, BIU_SEMA, 0); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); + USEC_DELAY(100); + ISP_WRITE(isp, BIU_SEMA, 0); + } + /* - * Establish some initial burst rate stuff. - * (only for the 1XX0 boards). This really should - * be done later after fetching from NVRAM. + * Post-RISC Reset stuff. */ - if (IS_SCSI(isp)) { + if (IS_24XX(isp)) { + for (val = loops = 0; loops < 5000000; loops++) { + USEC_DELAY(5); + val = ISP_READ(isp, OUTMAILBOX0); + if (val == 0) { + break; + } + } + if (val != 0) { + ISP_RESET0(isp); + isp_prt(isp, ISP_LOGERR, "reset didn't clear"); + return; + } + } else if (IS_SCSI(isp)) { uint16_t tmp = isp->isp_mdvec->dv_conf1; /* * Busted FIFO. Turn off all but burst enables. @@ -540,15 +646,36 @@ ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST); ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST); } - ISP_WRITE(isp, RISC_MTR, 0x1212); + if (SDPARAM(isp)->isp_ptisp) { + if (SDPARAM(isp)->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); + } + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); } else { ISP_WRITE(isp, RISC_MTR2100, 0x1212); if (IS_2200(isp) || IS_23XX(isp)) { ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE); } + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); } - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); /* release paused processor */ + ISP_WRITE(isp, isp->isp_rqstinrp, 0); + ISP_WRITE(isp, isp->isp_rqstoutrp, 0); + ISP_WRITE(isp, isp->isp_respinrp, 0); + ISP_WRITE(isp, isp->isp_respoutrp, 0); + /* * Do MD specific post initialization @@ -561,13 +688,14 @@ * Avoid doing this on the 2312 because you can generate a PCI * parity error (chip breakage). */ - if (IS_23XX(isp)) { - USEC_DELAY(5); + if (IS_2312(isp)) { + USEC_DELAY(100); } else { loops = MBOX_DELAY_COUNT; while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) { USEC_DELAY(100); if (--loops < 0) { + ISP_RESET0(isp); isp_prt(isp, ISP_LOGERR, "MBOX_BUSY never cleared on reset"); return; @@ -586,12 +714,14 @@ */ MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_NO_OP; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + ISP_RESET0(isp); return; } - if (IS_SCSI(isp)) { + if (IS_SCSI(isp) || IS_24XX(isp)) { MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_MAILBOX_REG_TEST; mbs.param[1] = 0xdead; @@ -599,13 +729,18 @@ mbs.param[3] = 0xffff; mbs.param[4] = 0x1111; mbs.param[5] = 0xa5a5; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.param[6] = 0x0000; + mbs.param[7] = 0x0000; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + ISP_RESET0(isp); return; } if (mbs.param[1] != 0xdead || mbs.param[2] != 0xbeef || mbs.param[3] != 0xffff || mbs.param[4] != 0x1111 || mbs.param[5] != 0xa5a5) { + ISP_RESET0(isp); isp_prt(isp, ISP_LOGERR, "Register Test Failed (0x%x 0x%x 0x%x 0x%x 0x%x)", mbs.param[1], mbs.param[2], mbs.param[3], @@ -629,12 +764,173 @@ dodnld = 0; } - if (IS_23XX(isp)) { + if (IS_24XX(isp)) { + code_org = ISP_CODE_ORG_2400; + } else if (IS_23XX(isp)) { code_org = ISP_CODE_ORG_2300; } else { code_org = ISP_CODE_ORG; } - if (dodnld) { + + if (dodnld && IS_24XX(isp)) { + uint32_t *ptr = isp->isp_mdvec->dv_ispfw; + + /* + * NB: Whatever you do do, do *not* issue the VERIFY FIRMWARE + * NB: command to the 2400 while loading new firmware. This + * NB: causes the new f/w to start and immediately crash back + * NB: to the ROM. + */ + + /* + * Keep loading until we run out of f/w. + */ + code_org = ptr[2]; /* 1st load address is our start addr */ + + for (;;) { + uint32_t la, wi, wl; + + isp_prt(isp, ISP_LOGDEBUG0, + "load 0x%x words of code at load address 0x%x", + ptr[3], ptr[2]); + + wi = 0; + la = ptr[2]; + wl = ptr[3]; + + while (wi < ptr[3]) { + uint32_t *cp; + uint32_t nw; + + nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 2; + if (nw > wl) { + nw = wl; + } + cp = isp->isp_rquest; + for (i = 0; i < nw; i++) { + cp[i] = ptr[wi++]; + wl--; + } + MEMORYBARRIER(isp, SYNC_REQUEST, + 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp))); + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_LOAD_RISC_RAM; + mbs.param[1] = la; + mbs.param[2] = DMA_WD1(isp->isp_rquest_dma); + mbs.param[3] = DMA_WD0(isp->isp_rquest_dma); + mbs.param[4] = nw >> 16; + mbs.param[5] = nw; + mbs.param[6] = DMA_WD3(isp->isp_rquest_dma); + mbs.param[7] = DMA_WD2(isp->isp_rquest_dma); + mbs.param[8] = la >> 16; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, + "F/W Risc Ram Load Failed"); + ISP_RESET0(isp); + return; + } + la += nw; + } + + if (ptr[1] == 0) { + break; + } + ptr += ptr[3]; + } + isp->isp_loaded_fw = 1; + } else if (dodnld && IS_23XX(isp)) { + uint16_t *ptr = isp->isp_mdvec->dv_ispfw; + uint16_t wi, wl, segno; + uint32_t la; + + la = code_org; + segno = 0; + + for (;;) { + uint32_t nxtaddr; + + isp_prt(isp, ISP_LOGDEBUG0, + "load 0x%x words of code at load address 0x%x", + ptr[3], la); + + wi = 0; + wl = ptr[3]; + + while (wi < ptr[3]) { + uint16_t *cp; + uint32_t nw; + + nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 1; + if (nw > wl) { + nw = wl; + } + if (nw > (1 << 15)) { + nw = 1 << 15; + } + cp = isp->isp_rquest; + for (i = 0; i < nw; i++) { + cp[i] = ptr[wi++]; + wl--; + } + MEMORYBARRIER(isp, SYNC_REQUEST, + 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp))); + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_LOAD_RISC_RAM; + mbs.param[1] = la; + mbs.param[2] = DMA_WD1(isp->isp_rquest_dma); + mbs.param[3] = DMA_WD0(isp->isp_rquest_dma); + mbs.param[4] = nw; + mbs.param[6] = DMA_WD3(isp->isp_rquest_dma); + mbs.param[7] = DMA_WD2(isp->isp_rquest_dma); + mbs.param[8] = la >> 16; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, + "F/W Risc Ram Load Failed"); + ISP_RESET0(isp); + return; + } + la += nw; + } + + if (!IS_2322(isp)) { + /* + * Verify that it downloaded correctly. + */ + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_VERIFY_CHECKSUM; + mbs.param[1] = code_org; + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, dcrc); + ISP_RESET0(isp); + return; + } + break; + } + + if (++segno == 3) { + break; + } + + /* + * If we're a 2322, the firmware actually comes in + * three chunks. We loaded the first at the code_org + * address. The other two chunks, which follow right + * after each other in memory here, get loaded at + * addresses specfied at offset 0x9..0xB. + */ + + nxtaddr = ptr[3]; + ptr = &ptr[nxtaddr]; + la = ptr[5] | ((ptr[4] & 0x3f) << 16); + } + isp->isp_loaded_fw = 1; + } else if (dodnld) { uint16_t *ptr = isp->isp_mdvec->dv_ispfw; isp->isp_mbxworkp = &ptr[1]; @@ -644,76 +940,27 @@ mbs.param[0] = MBOX_WRITE_RAM_WORD; mbs.param[1] = code_org; mbs.param[2] = ptr[0]; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); 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; + ISP_RESET0(isp); + return; } - /* - * If we're a 2322, the firmware actually comes in three chunks. - * We loaded the first at the code_org address. The other two - * chunks, which follow right after each other in memory here, - * get loaded at addresses specfied at offset 0x9..0xB. + * Verify that it downloaded correctly. */ - if (IS_2322(isp)) { - uint32_t nxtaddr; - uint32_t offset; - - nxtaddr = ptr[3]; - ptr = &ptr[nxtaddr]; - offset = ptr[5] | (((uint32_t)(ptr[4] & 0x3f)) << 16); - isp->isp_mbxworkp = &ptr[1]; - isp->isp_mbxwrk0 = ptr[3] - 1; - isp->isp_mbxwrk1 = offset + 1; - isp->isp_mbxwrk8 = (offset + 1) >> 16; - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_WRITE_RAM_WORD_EXTENDED; - mbs.param[1] = offset; - mbs.param[2] = ptr[0]; - mbs.param[8] = offset >> 16; - isp_mboxcmd(isp, &mbs, MBLOGNONE); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, - "Receive Sequencer F/W Load Failed"); - return; - } - - nxtaddr = ptr[3]; - ptr = &ptr[nxtaddr]; - offset = ptr[5] | (((uint32_t)(ptr[4] & 0x3f)) << 16); - isp->isp_mbxworkp = &ptr[1]; - isp->isp_mbxwrk0 = ptr[3] - 1; - isp->isp_mbxwrk1 = (offset + 1); - isp->isp_mbxwrk8 = (offset + 1) >> 16; - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_WRITE_RAM_WORD_EXTENDED; - mbs.param[1] = offset; - mbs.param[2] = ptr[0]; - mbs.param[8] = offset >> 16; - isp_mboxcmd(isp, &mbs, MBLOGNONE); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, - "Transmit Sequencer F/W Load Failed"); - return; - } - } else { - /* - * Verify that it downloaded correctly. - */ - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_VERIFY_CHECKSUM; - mbs.param[1] = code_org; - isp_mboxcmd(isp, &mbs, MBLOGNONE); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, - "Downloaded RISC Code Checksum Failure"); - return; - } - + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_VERIFY_CHECKSUM; + mbs.param[1] = code_org; + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, dcrc); + ISP_RESET0(isp); + return; } isp->isp_loaded_fw = 1; } else { @@ -730,28 +977,40 @@ MEMZERO(&mbs, sizeof (mbs)); + mbs.timeout = 1000000; mbs.param[0] = MBOX_EXEC_FIRMWARE; - mbs.param[1] = code_org; - if (IS_2322(isp) || IS_24XX(isp)) { + if (IS_24XX(isp)) { + mbs.param[1] = code_org >> 16; + mbs.param[2] = code_org; + if (isp->isp_loaded_fw) { + mbs.param[3] = 0; + } else { + mbs.param[3] = 1; + } + } else if (IS_2322(isp)) { + mbs.param[1] = code_org; if (isp->isp_loaded_fw) { mbs.param[2] = 0; } else { mbs.param[2] = 1; } + } else { + mbs.param[1] = code_org; } - isp_mboxcmd(isp, &mbs, MBLOGNONE); + + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (IS_2322(isp) || IS_24XX(isp)) { if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, "EXEC F/W failed: 0x%x", - mbs.param[0]); + ISP_RESET0(isp); return; } } /* - * Give it a chance to start. + * Give it a chance to finish starting up. */ - USEC_DELAY(500); + USEC_DELAY(250000); if (IS_SCSI(isp)) { /* @@ -760,15 +1019,24 @@ if (isp->isp_clock) { mbs.param[0] = MBOX_SET_CLOCK_RATE; mbs.param[1] = isp->isp_clock; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); /* we will try not to care if this fails */ } } MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_ABOUT_FIRMWARE; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + ISP_RESET0(isp); + return; + } + + if (IS_24XX(isp) && mbs.param[1] == 0xdead) { + isp_prt(isp, ISP_LOGERR, "f/w didn't *really* start"); + ISP_RESET0(isp); return; } @@ -794,7 +1062,7 @@ isp->isp_fwrev[2] = mbs.param[3]; } - isp_prt(isp, ISP_LOGCONFIG, + isp_prt(isp, ISP_LOGALL, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d", btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]); @@ -805,9 +1073,9 @@ * than 1.17.0, unless it's the firmware we specifically * are loading. * - * Note that all 22XX and 23XX f/w is greater than 1.X.0. + * Note that all 22XX and later f/w is greater than 1.X.0. */ - if (!(ISP_FW_NEWER_THAN(isp, 1, 17, 0))) { + if ((ISP_FW_OLDER_THAN(isp, 1, 17, 1))) { #ifdef USE_SMALLER_2100_FIRMWARE FCPARAM(isp)->isp_fwattr = ISP_FW_ATTR_SCCLUN; #else @@ -818,7 +1086,26 @@ isp_prt(isp, ISP_LOGDEBUG0, "Firmware Attributes = 0x%x", mbs.param[6]); } - if (IS_2KLOGIN(isp)) { + FCPARAM(isp)->isp_2klogin = 0; + FCPARAM(isp)->isp_sccfw = 0; + FCPARAM(isp)->isp_tmode = 0; + if (IS_24XX(isp)) { + FCPARAM(isp)->isp_2klogin = 1; + FCPARAM(isp)->isp_sccfw = 1; + FCPARAM(isp)->isp_tmode = 1; + } else { + if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + FCPARAM(isp)->isp_sccfw = 1; + } + if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_2KLOGINS) { + FCPARAM(isp)->isp_2klogin = 1; + FCPARAM(isp)->isp_sccfw = 1; + } + if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) { + FCPARAM(isp)->isp_tmode = 1; + } + } + if (FCPARAM(isp)->isp_2klogin) { isp_prt(isp, ISP_LOGCONFIG, "2K Logins Supported"); } } @@ -830,24 +1117,23 @@ isp->isp_romfw_rev[2]); } - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_GET_FIRMWARE_STATUS; - isp_mboxcmd(isp, &mbs, MBLOGALL); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - return; + if (!IS_24XX(isp)) { + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_GET_FIRMWARE_STATUS; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + ISP_RESET0(isp); + return; + } + if (isp->isp_maxcmds >= mbs.param[2]) { + isp->isp_maxcmds = mbs.param[2]; + } } - isp->isp_maxcmds = mbs.param[2]; - isp_prt(isp, ISP_LOGINFO, - "%d max I/O commands supported", mbs.param[2]); + isp_prt(isp, ISP_LOGCONFIG, + "%d max I/O command limit set", isp->isp_maxcmds); isp_fw_state(isp); - /* - * Set up DMA for the request and result mailboxes. - */ - if (ISP_MBOXDMASETUP(isp) != 0) { - isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); - return; - } isp->isp_state = ISP_RESETSTATE; /* @@ -878,7 +1164,7 @@ isp->isp_maxluns = 8; } } else { - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + if (FCPARAM(isp)->isp_sccfw) { isp->isp_maxluns = 16384; } else { isp->isp_maxluns = 16; @@ -902,8 +1188,22 @@ if (IS_DUALBUS(isp)) { isp_setdfltparm(isp, 1); } + if (IS_FC(isp)) { - isp_fibre_init(isp); + /* + * Do this *before* initializing the firmware. + */ + ISP_MARK_PORTDB(isp, 0); + FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; + FCPARAM(isp)->isp_loopstate = LOOP_NIL; + + if (isp->isp_role != ISP_ROLE_NONE) { + if (IS_24XX(isp)) { + isp_fibre_init_2400(isp); + } else { + isp_fibre_init(isp); + } + } } else { isp_scsi_init(isp); } @@ -947,8 +1247,8 @@ mbs.param[2] = sdp_chan0->isp_retry_delay; mbs.param[6] = sdp_chan1->isp_retry_count; mbs.param[7] = sdp_chan1->isp_retry_delay; - - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -960,7 +1260,8 @@ mbs.param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME; mbs.param[1] = sdp_chan0->isp_async_data_setup; mbs.param[2] = sdp_chan1->isp_async_data_setup; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; >>> TRUNCATED FOR MAIL (1000 lines) <<<