diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/isp.c | 5707 | ||||
-rw-r--r-- | sys/dev/ic/isp_library.c | 2681 | ||||
-rw-r--r-- | sys/dev/ic/isp_library.h | 215 | ||||
-rw-r--r-- | sys/dev/ic/isp_openbsd.c | 496 | ||||
-rw-r--r-- | sys/dev/ic/isp_openbsd.h | 223 | ||||
-rw-r--r-- | sys/dev/ic/isp_stds.h | 12 | ||||
-rw-r--r-- | sys/dev/ic/isp_target.c | 1036 | ||||
-rw-r--r-- | sys/dev/ic/isp_target.h | 146 | ||||
-rw-r--r-- | sys/dev/ic/isp_tpublic.h | 124 | ||||
-rw-r--r-- | sys/dev/ic/ispmbox.h | 67 | ||||
-rw-r--r-- | sys/dev/ic/ispreg.h | 52 | ||||
-rw-r--r-- | sys/dev/ic/ispvar.h | 326 | ||||
-rw-r--r-- | sys/dev/pci/isp_pci.c | 767 | ||||
-rw-r--r-- | sys/dev/sbus/isp_sbus.c | 105 |
14 files changed, 7988 insertions, 3969 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c index 8ccfe47c05f..2d0f10fdd18 100644 --- a/sys/dev/ic/isp.c +++ b/sys/dev/ic/isp.c @@ -1,33 +1,35 @@ -/* $OpenBSD: isp.c,v 1.45 2009/06/03 05:11:09 krw Exp $ */ +/* $OpenBSD: isp.c,v 1.46 2009/06/24 11:00:53 krw Exp $ */ /* $FreeBSD: src/sys/dev/isp/isp.c,v 1.150 2008/12/15 21:42:38 marius Exp $*/ +/*- + * Copyright (c) 1997-2007 by Matthew Jacob + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + /* * Machine and OS Independent (well, as best as possible) - * code for the QLogic ISP SCSI adapters. - * - * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob - * Feral Software - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * code for the Qlogic ISP SCSI and FC-SCSI adapters. */ /* @@ -39,11 +41,14 @@ /* * Include header file appropriate for platform we're building on. */ - #ifdef __NetBSD__ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD$"); #include <dev/ic/isp_netbsd.h> #endif #ifdef __FreeBSD__ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/sys/dev/isp/isp.c,v 1.149 2007/07/10 07:55:04 mjacob Exp $"); #include <dev/isp/isp_freebsd.h> #endif #ifdef __OpenBSD__ @@ -61,30 +66,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[] = @@ -96,11 +87,11 @@ static const char xact3[] = static const char pskip[] = "SCSI phase skipped for target %d.%d.%d"; static const char topology[] = - "Loop ID %d, AL_PA 0x%x, 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 %lu STS 0x%x SKEY %c XS_ERR=0x%x"; + "%d.%d.%d: FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x"; static const char sc0[] = "%s CHAN %d FTHRSH %d IID %d RESETD %d RETRYC %d RETRYD %d ASD 0x%x"; static const char sc1[] = @@ -114,40 +105,54 @@ static const char bun[] = /* * Local function prototypes. */ -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 *); -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_fabric_mbox_cmd(struct ispsoftc *, mbreg_t *); -static int isp_scan_fabric(struct ispsoftc *, int); -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 *); -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 *); +int isp_parse_async(struct ispsoftc *, u_int16_t); +int isp_handle_other_response(struct ispsoftc *, int, isphdr_t *, + u_int32_t *); +void +isp_parse_status(struct ispsoftc *, ispstatusreq_t *, XS_T *, long *); +void +isp_parse_status_24xx(struct ispsoftc *, isp24xx_statusreq_t *, XS_T *, long *); +void isp_fastpost_complete(struct ispsoftc *, u_int16_t); +int isp_mbox_continue(struct ispsoftc *); +void isp_scsi_init(struct ispsoftc *); +void isp_scsi_channel_init(struct ispsoftc *, int); +void isp_fibre_init(struct ispsoftc *); +void isp_fibre_init_2400(struct ispsoftc *); +void isp_mark_portdb(struct ispsoftc *, int); +int isp_plogx(struct ispsoftc *, u_int16_t, u_int32_t, int, int); +int isp_port_login(struct ispsoftc *, u_int16_t, u_int32_t); +int isp_port_logout(struct ispsoftc *, u_int16_t, u_int32_t); +int isp_getpdb(struct ispsoftc *, u_int16_t, isp_pdb_t *, int); +u_int64_t isp_get_portname(struct ispsoftc *, int, int); +int isp_fclink_test(struct ispsoftc *, int); +const char *ispfc_fw_statename(int); +int isp_pdb_sync(struct ispsoftc *); +int isp_scan_loop(struct ispsoftc *); +int isp_gid_ft_sns(struct ispsoftc *); +int isp_gid_ft_ct_passthru(struct ispsoftc *); +int isp_scan_fabric(struct ispsoftc *); +int isp_login_device(struct ispsoftc *, u_int32_t, isp_pdb_t *, u_int16_t *); +int isp_register_fc4_type(struct ispsoftc *); +int isp_register_fc4_type_24xx(struct ispsoftc *); +u_int16_t isp_nxt_handle(struct ispsoftc *, u_int16_t); +void isp_fw_state(struct ispsoftc *); +void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *, int); +void isp_mboxcmd(struct ispsoftc *, mbreg_t *); + +void isp_update(struct ispsoftc *); +void isp_update_bus(struct ispsoftc *, int); +void isp_setdfltparm(struct ispsoftc *, int); +void isp_setdfltfcparm(struct ispsoftc *); +int isp_read_nvram(struct ispsoftc *); +int isp_read_nvram_2400(struct ispsoftc *); +void isp_rdnvram_word(struct ispsoftc *, int, u_int16_t *); +void isp_rd_2400_nvram(struct ispsoftc *, u_int32_t, u_int32_t *); +void isp_parse_nvram_1020(struct ispsoftc *, u_int8_t *); +void isp_parse_nvram_1080(struct ispsoftc *, int, u_int8_t *); +void isp_parse_nvram_12160(struct ispsoftc *, int, u_int8_t *); +void isp_fix_nvram_wwns(struct ispsoftc *); +void isp_parse_nvram_2100(struct ispsoftc *, u_int8_t *); +void isp_parse_nvram_2400(struct ispsoftc *, u_int8_t *); /* * Reset Hardware. @@ -161,9 +166,10 @@ void isp_reset(struct ispsoftc *isp) { mbreg_t mbs; - u_int16_t code_org; + u_int32_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; @@ -203,10 +209,16 @@ isp_reset(struct ispsoftc *isp) /* * 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]; @@ -216,13 +228,47 @@ isp_reset(struct ispsoftc *isp) 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; @@ -238,7 +284,13 @@ isp_reset(struct ispsoftc *isp) * 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) { @@ -254,17 +306,27 @@ isp_reset(struct ispsoftc *isp) case ISP_HA_FC_2312: btype = "2312"; break; + case ISP_HA_FC_2322: + btype = "2322"; + break; + 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"; @@ -447,8 +509,6 @@ isp_reset(struct ispsoftc *isp) */ ISP_RESET0(isp); -again: - /* * Hit the chip over the head with hammer, * and give the ISP a chance to recover. @@ -470,6 +530,44 @@ again: 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); /* @@ -494,8 +592,13 @@ again: 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; @@ -503,6 +606,7 @@ again: USEC_DELAY(100); if (--loops < 0) { ISP_DUMPREGS(isp, "chip reset timed out"); + ISP_RESET0(isp); return; } } @@ -514,24 +618,41 @@ again: 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)) { u_int16_t tmp = isp->isp_mdvec->dv_conf1; /* * Busted FIFO. Turn off all but burst enables. @@ -544,30 +665,36 @@ again: 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); + 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); } - /* - * PTI specific register - */ - ISP_WRITE(isp, RISC_EMB, DUAL_BANK) -#else - ISP_WRITE(isp, RISC_MTR, 0x1212); -#endif + 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 @@ -580,13 +707,14 @@ again: * 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; @@ -605,12 +733,14 @@ again: */ 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; @@ -618,13 +748,18 @@ again: 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], @@ -648,26 +783,193 @@ again: 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 + } else { code_org = ISP_CODE_ORG; + } + + if (dodnld && IS_24XX(isp)) { + const u_int32_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 (;;) { + u_int32_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]) { + u_int32_t *cp; + u_int32_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++) { + ISP_IOXPUT_32(isp, ptr[wi++], &cp[i]); + 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)) { + const u_int16_t *ptr = isp->isp_mdvec->dv_ispfw; + u_int16_t wi, wl, segno; + u_int32_t la; + + la = code_org; + segno = 0; + + for (;;) { + u_int32_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]) { + u_int16_t *cp; + u_int32_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++) { + ISP_IOXPUT_16(isp, ptr[wi++], &cp[i]); + 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. + */ - if (dodnld) { - isp->isp_mbxworkp = (void *) &isp->isp_mdvec->dv_ispfw[1]; - isp->isp_mbxwrk0 = isp->isp_mdvec->dv_ispfw[3] - 1; + nxtaddr = ptr[3]; + ptr = &ptr[nxtaddr]; + la = ptr[5] | ((ptr[4] & 0x3f) << 16); + } + isp->isp_loaded_fw = 1; + } else if (dodnld) { + union { + const u_int16_t *cp; + u_int16_t *np; + } u; + u.cp = isp->isp_mdvec->dv_ispfw; + isp->isp_mbxworkp = &u.np[1]; + isp->isp_mbxwrk0 = u.np[3] - 1; isp->isp_mbxwrk1 = code_org + 1; MEMZERO(&mbs, sizeof (mbs)); 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); + mbs.param[2] = u.np[0]; + 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; } /* * Verify that it downloaded correctly. @@ -675,9 +977,11 @@ again: MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_VERIFY_CHECKSUM; mbs.param[1] = code_org; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, "Ram Checksum Failure"); + isp_prt(isp, ISP_LOGERR, dcrc); + ISP_RESET0(isp); return; } isp->isp_loaded_fw = 1; @@ -695,13 +999,40 @@ again: MEMZERO(&mbs, sizeof (mbs)); + mbs.timeout = 1000000; mbs.param[0] = MBOX_EXEC_FIRMWARE; - mbs.param[1] = code_org; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + 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; + } + + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (IS_2322(isp) || IS_24XX(isp)) { + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + 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)) { /* @@ -711,15 +1042,24 @@ again: MEMZERO(&mbs, sizeof (mbs)); 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; } @@ -744,7 +1084,8 @@ again: isp->isp_fwrev[1] = mbs.param[2]; 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]); @@ -755,9 +1096,9 @@ again: * 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 @@ -768,9 +1109,27 @@ again: isp_prt(isp, ISP_LOGDEBUG0, "Firmware Attributes = 0x%x", mbs.param[6]); } - if (ISP_READ(isp, BIU2100_CSR) & BIU2100_PCI64) { - isp_prt(isp, ISP_LOGCONFIG, - "Installed in 64-Bit PCI slot"); + 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"); } } @@ -781,24 +1140,23 @@ again: 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; /* @@ -829,12 +1187,24 @@ again: 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; } } + /* + * Must do this first to get defaults established. + */ + if (IS_SCSI(isp)) { + isp_setdfltparm(isp, 0); + if (IS_DUALBUS(isp)) { + isp_setdfltparm(isp, 1); + } + } else { + isp_setdfltfcparm(isp); + } + } /* @@ -846,21 +1216,27 @@ again: void isp_init(struct ispsoftc *isp) { - /* - * Must do this first to get defaults established. - */ - isp_setdfltparm(isp, 0); - 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); } } -static void +void isp_scsi_init(struct ispsoftc *isp) { sdparam *sdp_chan0, *sdp_chan1; @@ -898,8 +1274,8 @@ isp_scsi_init(struct ispsoftc *isp) 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; } @@ -911,7 +1287,8 @@ isp_scsi_init(struct ispsoftc *isp) 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; } @@ -927,8 +1304,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[2] = (sdp_chan1->isp_req_ack_active_neg << 4) | (sdp_chan1->isp_data_line_active_neg << 5); - - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "failed to set active negation state (%d,%d), (%d,%d)", @@ -948,7 +1325,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[0] = MBOX_SET_TAG_AGE_LIMIT; mbs.param[1] = sdp_chan0->isp_tag_aging; mbs.param[2] = sdp_chan1->isp_tag_aging; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "failed to set tag age limit (%d,%d)", sdp_chan0->isp_tag_aging, sdp_chan1->isp_tag_aging); @@ -962,7 +1340,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[0] = MBOX_SET_SELECT_TIMEOUT; mbs.param[1] = sdp_chan0->isp_selection_timeout; mbs.param[2] = sdp_chan1->isp_selection_timeout; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -985,7 +1364,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[4] = 0; mbs.param[6] = DMA_WD3(isp->isp_result_dma); mbs.param[7] = DMA_WD2(isp->isp_result_dma); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -999,7 +1379,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[5] = 0; mbs.param[6] = DMA_WD3(isp->isp_result_dma); mbs.param[7] = DMA_WD2(isp->isp_result_dma); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1011,7 +1392,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[2] = DMA_WD1(isp->isp_result_dma); mbs.param[3] = DMA_WD0(isp->isp_result_dma); mbs.param[4] = 0; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1023,7 +1405,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[2] = DMA_WD1(isp->isp_rquest_dma); mbs.param[3] = DMA_WD0(isp->isp_rquest_dma); mbs.param[5] = 0; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1048,14 +1431,13 @@ isp_scsi_init(struct ispsoftc *isp) 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); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGINFO, "Enabled FW features (0x%x)", sfeat); @@ -1068,7 +1450,7 @@ isp_scsi_init(struct ispsoftc *isp) isp->isp_state = ISP_INITSTATE; } -static void +void isp_scsi_channel_init(struct ispsoftc *isp, int channel) { sdparam *sdp; @@ -1084,7 +1466,8 @@ isp_scsi_channel_init(struct ispsoftc *isp, int channel) MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SET_INIT_SCSI_ID; mbs.param[1] = (channel << 7) | sdp->isp_initiator_id; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1140,7 +1523,8 @@ isp_scsi_channel_init(struct ispsoftc *isp, int channel) "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x", channel, tgt, mbs.param[2], mbs.param[3] >> 8, mbs.param[3] & 0xff); - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { sdf = DPARM_SAFE_DFLT; MEMZERO(&mbs, sizeof (mbs)); @@ -1148,7 +1532,8 @@ isp_scsi_channel_init(struct ispsoftc *isp, int channel) mbs.param[1] = (tgt << 8) | (channel << 15); mbs.param[2] = sdf; mbs.param[3] = 0; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { continue; } @@ -1172,7 +1557,8 @@ isp_scsi_channel_init(struct ispsoftc *isp, int channel) mbs.param[1] = (channel << 15) | (tgt << 8) | lun; mbs.param[2] = sdp->isp_max_queue_depth; mbs.param[3] = sdp->isp_devparam[tgt].exc_throttle; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } @@ -1189,37 +1575,21 @@ isp_scsi_channel_init(struct ispsoftc *isp, int channel) /* * Fibre Channel specific initialization. - * - * Locks are held before coming here. */ -static void +void isp_fibre_init(struct ispsoftc *isp) { fcparam *fcp; isp_icb_t local, *icbp = &local; mbreg_t mbs; - int loopid; + int ownloopid; u_int64_t nwwn, pwwn; fcp = isp->isp_param; - /* - * Do this *before* initializing the firmware. - */ - isp_mark_getpdb_all(isp); - fcp->isp_fwstate = FW_CONFIG_WAIT; - fcp->isp_loopstate = LOOP_NIL; - - /* - * If we have no role (neither target nor initiator), return. - */ - if (isp->isp_role == ISP_ROLE_NONE) { - return; - } - - loopid = fcp->isp_loopid; MEMZERO(icbp, sizeof (*icbp)); icbp->icb_version = ICB_VERSION1; + icbp->icb_fwoptions = fcp->isp_fwoptions; /* * Firmware Options are either retrieved from NVRAM or @@ -1231,8 +1601,8 @@ isp_fibre_init(struct ispsoftc *isp) /* * If this is a 2100 < revision 5, we have to turn off FAIRNESS. */ - if ((isp->isp_type == ISP_HA_FC_2100) && isp->isp_revision < 5) { - fcp->isp_fwoptions &= ~ICBOPT_FAIRNESS; + if (IS_2100(isp) && isp->isp_revision < 5) { + icbp->icb_fwoptions &= ~ICBOPT_FAIRNESS; } /* @@ -1241,27 +1611,29 @@ isp_fibre_init(struct ispsoftc *isp) * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0. */ if (!ISP_FW_NEWER_THAN(isp, 1, 17, 0)) { - fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; + icbp->icb_fwoptions |= ICBOPT_FULL_LOGIN; } /* * Insist on Port Database Update Async notifications */ - fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; + icbp->icb_fwoptions |= ICBOPT_PDBCHANGE_AE; /* * Make sure that target role reflects into fwoptions. */ if (isp->isp_role & ISP_ROLE_TARGET) { - fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE; + icbp->icb_fwoptions |= ICBOPT_TGT_ENABLE; } else { - fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE; + icbp->icb_fwoptions &= ~ICBOPT_TGT_ENABLE; + } + + if (isp->isp_role & ISP_ROLE_INITIATOR) { + icbp->icb_fwoptions &= ~ICBOPT_INI_DISABLE; + } else { + icbp->icb_fwoptions |= ICBOPT_INI_DISABLE; } - /* - * Propagate all of this into the ICB structure. - */ - icbp->icb_fwoptions = fcp->isp_fwoptions; icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { @@ -1285,7 +1657,21 @@ isp_fibre_init(struct ispsoftc *isp) } icbp->icb_retry_delay = fcp->isp_retry_delay; icbp->icb_retry_count = fcp->isp_retry_count; - icbp->icb_hardaddr = loopid; + icbp->icb_hardaddr = fcp->isp_loopid; + ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0; + if (icbp->icb_hardaddr > 125) { + icbp->icb_hardaddr = 0; + ownloopid = 0; + } + + /* + * Our life seems so much better with 2200s and later with + * the latest f/w if we set Hard Address. + */ + if (ownloopid || ISP_FW_NEWER_THAN(isp, 2, 2, 5)) { + icbp->icb_fwoptions |= ICBOPT_HARD_ADDRESS; + } + /* * Right now we just set extended options to prefer point-to-point * over loop based upon some soft config options. @@ -1311,26 +1697,21 @@ isp_fibre_init(struct ispsoftc *isp) icbp->icb_xfwoptions |= ICBXOPT_LOOP_2_PTP; break; } - if (IS_23XX(isp)) { + if (IS_2200(isp)) { + icbp->icb_fwoptions &= ~ICBOPT_FAST_POST; + } else { /* * QLogic recommends that FAST Posting be turned * off for 23XX cards and instead allow the HBA * to write response queue entries and interrupt * after a delay (ZIO). - * - * If we set ZIO, it will disable fast posting, - * so we don't need to clear it in fwoptions. - */ - icbp->icb_xfwoptions |= ICBXOPT_ZIO; -#if 0 - /* - * Values, in 100us increments. The default - * is 2 (200us) if a value 0 (default) is - * selected. */ - icbp->icb_idelaytimer = 2; -#endif - + icbp->icb_fwoptions &= ~ICBOPT_FAST_POST; + if ((fcp->isp_xfwoptions & ICBXOPT_TIMER_MASK) == + ICBXOPT_ZIO) { + icbp->icb_xfwoptions |= ICBXOPT_ZIO; + icbp->icb_idelaytimer = 10; + } if (isp->isp_confopts & ISP_CFG_ONEGB) { icbp->icb_zfwoptions |= ICBZOPT_RATE_ONEGB; } else if (isp->isp_confopts & ISP_CFG_TWOGB) { @@ -1338,32 +1719,15 @@ isp_fibre_init(struct ispsoftc *isp) } else { icbp->icb_zfwoptions |= ICBZOPT_RATE_AUTO; } + if (fcp->isp_zfwoptions & ICBZOPT_50_OHM) { + icbp->icb_zfwoptions |= ICBZOPT_50_OHM; + } } } -#ifndef ISP_NO_RIO_FC - /* - * RIO seems to be enabled in 2100s for fw >= 1.17.0. - * - * I've had some questionable problems with RIO on 2200. - * More specifically, on a 2204 I had problems with RIO - * on a Linux system where I was dropping commands right - * and left. It's not clear to me what the actual problem - * was. - * - * 23XX Cards do not support RIO. Instead they support ZIO. - */ -#if 0 - if (!IS_23XX(isp) && ISP_FW_NEWER_THAN(isp, 1, 17, 0)) { - icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT; - icbp->icb_racctimer = 4; - icbp->icb_idelaytimer = 8; - } -#endif -#endif /* - * For 22XX > 2.1.26 && 23XX, set someoptions. + * For 22XX > 2.1.26 && 23XX, set some options. * XXX: Probably okay for newer 2100 f/w too. */ if (ISP_FW_NEWER_THAN(isp, 2, 26, 0)) { @@ -1377,16 +1741,14 @@ isp_fibre_init(struct ispsoftc *isp) mbs.param[1] = 0xb; mbs.param[2] = 0; mbs.param[3] = 0; - isp_mboxcmd(isp, &mbs, MBLOGALL); - } - icbp->icb_logintime = 30; /* 30 second login timeout */ - - 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); - ISP_WRITE(isp, isp->isp_respoutrp, 0); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } } + icbp->icb_logintime = ICB_LOGIN_TOV; + icbp->icb_lunetimeout = ICB_LUN_ENABLE_TOV; nwwn = ISP_NODEWWN(isp); pwwn = ISP_PORTWWN(isp); @@ -1400,12 +1762,25 @@ isp_fibre_init(struct ispsoftc *isp) ((u_int32_t) (nwwn & 0xffffffff)), ((u_int32_t) (pwwn >> 32)), ((u_int32_t) (pwwn & 0xffffffff))); + } else if (pwwn) { + icbp->icb_fwoptions &= ~ICBOPT_BOTH_WWNS; + MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn); + isp_prt(isp, ISP_LOGDEBUG1, + "Setting ICB Port 0x%08x%08x", + ((u_int32_t) (pwwn >> 32)), + ((u_int32_t) (pwwn & 0xffffffff))); } else { - isp_prt(isp, ISP_LOGDEBUG1, "Not using any WWNs"); - icbp->icb_fwoptions &= ~(ICBOPT_BOTH_WWNS|ICBOPT_FULL_LOGIN); + isp_prt(isp, ISP_LOGERR, "No valid WWNs to use"); + return; } icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp); + if (icbp->icb_rqstqlen < 1) { + isp_prt(isp, ISP_LOGERR, "bad request queue length"); + } icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp); + if (icbp->icb_rsltqlen < 1) { + isp_prt(isp, ISP_LOGERR, "bad result queue length"); + } icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma); icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma); icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma); @@ -1414,6 +1789,7 @@ isp_fibre_init(struct ispsoftc *isp) icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma); icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma); icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma); + isp_prt(isp, ISP_LOGDEBUG0, "isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x", icbp->icb_fwoptions, icbp->icb_xfwoptions, icbp->icb_zfwoptions); @@ -1430,17 +1806,21 @@ isp_fibre_init(struct ispsoftc *isp) mbs.param[3] = DMA_WD0(fcp->isp_scdma); mbs.param[6] = DMA_WD3(fcp->isp_scdma); mbs.param[7] = DMA_WD2(fcp->isp_scdma); + mbs.logval = MBLOGALL; + mbs.timeout = 30 * 1000000; isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %p (%08x%08x)", - fcp->isp_scratch, (uint32_t) ((uint64_t)fcp->isp_scdma >> 32), - (uint32_t) fcp->isp_scdma); - isp_mboxcmd(isp, &mbs, MBLOGALL); + fcp->isp_scratch, (u_int32_t) ((u_int64_t)fcp->isp_scdma >> 32), + (u_int32_t) fcp->isp_scdma); + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp)); + isp_mboxcmd(isp, &mbs); FC_SCRATCH_RELEASE(isp); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_print_bytes(isp, "isp_fibre_init", sizeof (*icbp), icbp); return; } - isp->isp_reqidx = isp->isp_reqodx = 0; + isp->isp_reqidx = 0; + isp->isp_reqodx = 0; isp->isp_residx = 0; - isp->isp_sendmarker = 1; /* * Whatever happens, we're now committed to being here. @@ -1448,84 +1828,615 @@ isp_fibre_init(struct ispsoftc *isp) isp->isp_state = ISP_INITSTATE; } -/* - * Fibre Channel Support- get the port database for the id. - * - * Locks are held before coming here. Return 0 if success, - * else failure. - */ - -static int -isp_getmap(struct ispsoftc *isp, fcpos_map_t *map) +void +isp_fibre_init_2400(struct ispsoftc *isp) { - fcparam *fcp = (fcparam *) isp->isp_param; + fcparam *fcp; + isp_icb_2400_t local, *icbp = &local; mbreg_t mbs; + int ownloopid; + u_int64_t nwwn, pwwn; + + fcp = isp->isp_param; + + /* + * Turn on LIP F8 async event (1) + */ + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_SET_FIRMWARE_OPTIONS; + mbs.param[1] = 1; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } + + /* + * XXX: This should be applied to icb- not fwoptions + */ + if (isp->isp_role & ISP_ROLE_TARGET) { + fcp->isp_fwoptions |= ICB2400_OPT1_TGT_ENABLE; + } else { + fcp->isp_fwoptions &= ~ICB2400_OPT1_TGT_ENABLE; + } + + if (isp->isp_role & ISP_ROLE_INITIATOR) { + fcp->isp_fwoptions &= ~ICB2400_OPT1_INI_DISABLE; + } else { + fcp->isp_fwoptions |= ICB2400_OPT1_INI_DISABLE; + } + + MEMZERO(icbp, sizeof (*icbp)); + icbp->icb_version = ICB_VERSION1; + icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; + if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || + icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { + isp_prt(isp, ISP_LOGERR, + "bad frame length (%d) from NVRAM- using %d", + fcp->isp_maxfrmlen, ICB_DFLT_FRMLEN); + icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN; + } + + icbp->icb_execthrottle = fcp->isp_execthrottle; + if (icbp->icb_execthrottle < 1) { + isp_prt(isp, ISP_LOGERR, + "bad execution throttle of %d- using 16", + fcp->isp_execthrottle); + icbp->icb_execthrottle = ICB_DFLT_THROTTLE; + } + + if (isp->isp_role & ISP_ROLE_TARGET) { + /* + * Get current resource count + */ + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_GET_RESOURCE_COUNT; + mbs.obits = 0x4cf; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } + icbp->icb_xchgcnt = mbs.param[3]; + } - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_GET_FC_AL_POSITION_MAP; + icbp->icb_fwoptions1 = fcp->isp_fwoptions; + + icbp->icb_hardaddr = fcp->isp_loopid; + ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0; + if (icbp->icb_hardaddr > 125) { + icbp->icb_hardaddr = 0; + ownloopid = 0; + } + if (ownloopid) { + icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS; + } + + icbp->icb_fwoptions2 = fcp->isp_xfwoptions; + switch(isp->isp_confopts & ISP_CFG_PORT_PREF) { + case ISP_CFG_NPORT: + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; + icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_2_LOOP; + break; + case ISP_CFG_NPORT_ONLY: + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; + icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY; + break; + case ISP_CFG_LPORT_ONLY: + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; + icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY; + break; + default: + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; + icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP; + break; + } + + switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) { + case ICB2400_OPT2_ZIO: + case ICB2400_OPT2_ZIO1: + icbp->icb_idelaytimer = 0; + break; + case 0: + break; + default: + isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", + icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK); + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK; + break; + } + + icbp->icb_fwoptions3 = fcp->isp_zfwoptions; + icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_AUTO; + if (isp->isp_confopts & ISP_CFG_ONEGB) { + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_ONEGB; + } else if (isp->isp_confopts & ISP_CFG_TWOGB) { + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_TWOGB; + } else if (isp->isp_confopts & ISP_CFG_FOURGB) { + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_FOURGB; + } else { + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO; + } + + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { + icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID; + } + icbp->icb_logintime = ICB_LOGIN_TOV; + + nwwn = ISP_NODEWWN(isp); + pwwn = ISP_PORTWWN(isp); + + if (nwwn && pwwn) { + icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS; + MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, nwwn); + MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn); + isp_prt(isp, ISP_LOGDEBUG1, + "Setting ICB Node 0x%08x%08x Port 0x%08x%08x", + ((u_int32_t) (nwwn >> 32)), + ((u_int32_t) (nwwn & 0xffffffff)), + ((u_int32_t) (pwwn >> 32)), + ((u_int32_t) (pwwn & 0xffffffff))); + } else if (pwwn) { + icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS; + MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn); + isp_prt(isp, ISP_LOGDEBUG1, + "Setting ICB Port 0x%08x%08x", + ((u_int32_t) (pwwn >> 32)), + ((u_int32_t) (pwwn & 0xffffffff))); + } else { + isp_prt(isp, ISP_LOGERR, "No valid WWNs to use"); + return; + } + icbp->icb_retry_count = fcp->isp_retry_count; + + icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp); + if (icbp->icb_rqstqlen < 8) { + isp_prt(isp, ISP_LOGERR, "bad request queue length %d", + icbp->icb_rqstqlen); + return; + } + icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp); + if (icbp->icb_rsltqlen < 8) { + isp_prt(isp, ISP_LOGERR, "bad result queue length %d", + icbp->icb_rsltqlen); + return; + } + icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma); + + icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma); + +#ifdef ISP_TARGET_MODE + if (isp->isp_role & ISP_ROLE_TARGET) { + icbp->icb_atioqlen = RESULT_QUEUE_LEN(isp); + if (icbp->icb_atioqlen < 8) { + isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", + icbp->icb_atioqlen); + return; + } + icbp->icb_atioqaddr[RQRSP_ADDR0015] = + DMA_WD0(isp->isp_atioq_dma); + icbp->icb_atioqaddr[RQRSP_ADDR1631] = + DMA_WD1(isp->isp_atioq_dma); + icbp->icb_atioqaddr[RQRSP_ADDR3247] = + DMA_WD2(isp->isp_atioq_dma); + icbp->icb_atioqaddr[RQRSP_ADDR4863] = + DMA_WD3(isp->isp_atioq_dma); + isp_prt(isp, ISP_LOGDEBUG0, + "isp_fibre_init_2400: atioq %04x%04x%04x%04x", + DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma), + DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma)); + } +#endif + + isp_prt(isp, ISP_LOGDEBUG0, + "isp_fibre_init_2400: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", + icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3); + + isp_prt(isp, ISP_LOGDEBUG0, + "isp_fibre_init_2400: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x", + DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma), + DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), + DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma), + DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma)); + + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "isp_fibre_init_2400", sizeof (*icbp), + icbp); + } + FC_SCRATCH_ACQUIRE(isp); + isp_put_icb_2400(isp, icbp, fcp->isp_scratch); + + + /* + * Init the firmware + */ + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_INIT_FIRMWARE; mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); - 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); - } + mbs.param[6] = DMA_WD3(fcp->isp_scdma); + mbs.param[7] = DMA_WD2(fcp->isp_scdma); + mbs.logval = MBLOGALL; + mbs.timeout = 30 * 1000000; + isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x", + DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma), + DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma)); + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp)); + isp_mboxcmd(isp, &mbs); FC_SCRATCH_RELEASE(isp); - return (-1); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } + isp->isp_reqidx = 0; + isp->isp_reqodx = 0; + isp->isp_residx = 0; + + /* + * Whatever happens, we're now committed to being here. + */ + isp->isp_state = ISP_INITSTATE; } -static void -isp_mark_getpdb_all(struct ispsoftc *isp) +void +isp_mark_portdb(struct ispsoftc *isp, int onprobation) { fcparam *fcp = (fcparam *) isp->isp_param; int i; + for (i = 0; i < MAX_FC_TARG; i++) { - fcp->portdb[i].valid = fcp->portdb[i].fabric_dev = 0; + if (onprobation == 0) { + MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t)); + } else { + switch (fcp->portdb[i].state) { + case FC_PORTDB_STATE_CHANGED: + case FC_PORTDB_STATE_PENDING_VALID: + case FC_PORTDB_STATE_VALID: + case FC_PORTDB_STATE_PROBATIONAL: + fcp->portdb[i].state = + FC_PORTDB_STATE_PROBATIONAL; + break; + case FC_PORTDB_STATE_ZOMBIE: + break; + case FC_PORTDB_STATE_NIL: + default: + MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t)); + fcp->portdb[i].state = + FC_PORTDB_STATE_NIL; + break; + } + } + } +} + +/* + * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards + * or via FABRIC LOGIN/FABRIC LOGOUT for other cards. + */ +int +isp_plogx(struct ispsoftc *isp, u_int16_t handle, u_int32_t portid, int flags, int gs) +{ + mbreg_t mbs; + u_int8_t q[QENTRY_LEN]; + isp_plogx_t *plp; + u_int8_t *scp; + u_int32_t sst, parm1; + int rval; + + if (!IS_24XX(isp)) { + int action = flags & PLOGX_FLG_CMD_MASK; + if (action == PLOGX_FLG_CMD_PLOGI) { + return (isp_port_login(isp, handle, portid)); + } else if (action == PLOGX_FLG_CMD_LOGO) { + return (isp_port_logout(isp, handle, portid)); + } else { + return (MBOX_INVALID_COMMAND); + } + } + + MEMZERO(q, QENTRY_LEN); + plp = (isp_plogx_t *) q; + plp->plogx_header.rqs_entry_count = 1; + plp->plogx_header.rqs_entry_type = RQSTYPE_LOGIN; + plp->plogx_handle = 0xffffffff; + plp->plogx_nphdl = handle; + plp->plogx_portlo = portid; + plp->plogx_rspsz_porthi = (portid >> 16) & 0xff; + plp->plogx_flags = flags; + + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, plp); + } + + if (gs == 0) { + FC_SCRATCH_ACQUIRE(isp); + } + scp = FCPARAM(isp)->isp_scratch; + isp_put_plogx(isp, plp, (isp_plogx_t *) scp); + + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64; + mbs.param[1] = QENTRY_LEN; + mbs.param[2] = DMA_WD1(FCPARAM(isp)->isp_scdma); + mbs.param[3] = DMA_WD0(FCPARAM(isp)->isp_scdma); + mbs.param[6] = DMA_WD3(FCPARAM(isp)->isp_scdma); + mbs.param[7] = DMA_WD2(FCPARAM(isp)->isp_scdma); + mbs.timeout = 500000; + mbs.logval = MBLOGALL; + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + rval = mbs.param[0]; + goto out; + } + MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN); + scp += QENTRY_LEN; + isp_get_plogx(isp, (isp_plogx_t *) scp, plp); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, plp); + } + + if (plp->plogx_status == PLOGX_STATUS_OK) { + rval = 0; + goto out; + } else if (plp->plogx_status != PLOGX_STATUS_IOCBERR) { + isp_prt(isp, ISP_LOGWARN, "status 0x%x on port login IOCB", + plp->plogx_status); + rval = -1; + goto out; + } + + sst = plp->plogx_ioparm[0].lo16 | (plp->plogx_ioparm[0].hi16 << 16); + parm1 = plp->plogx_ioparm[1].lo16 | (plp->plogx_ioparm[1].hi16 << 16); + + rval = -1; + + switch (sst) { + case PLOGX_IOCBERR_NOLINK: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no link"); + break; + case PLOGX_IOCBERR_NOIOCB: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no IOCB buffer"); + break; + case PLOGX_IOCBERR_NOXGHG: + isp_prt(isp, ISP_LOGERR, + "PLOGX failed- no Exchange Control Block"); + break; + case PLOGX_IOCBERR_FAILED: + isp_prt(isp, ISP_LOGERR, + "PLOGX(0x%x) of Port 0x%06x failed: reason 0x%x (last LOGIN" + " state 0x%x)", flags, portid, parm1 & 0xff, + (parm1 >> 8) & 0xff); + break; + case PLOGX_IOCBERR_NOFABRIC: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no fabric"); + break; + case PLOGX_IOCBERR_NOTREADY: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- f/w not ready"); + break; + case PLOGX_IOCBERR_NOLOGIN: + isp_prt(isp, ISP_LOGERR, + "PLOGX failed- not logged in (last LOGIN state 0x%x)", + parm1); + rval = MBOX_NOT_LOGGED_IN; + break; + case PLOGX_IOCBERR_REJECT: + isp_prt(isp, ISP_LOGERR, "PLOGX failed: LS_RJT = 0x%x", parm1); + break; + case PLOGX_IOCBERR_NOPCB: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no PCB allocated"); + break; + case PLOGX_IOCBERR_EINVAL: + isp_prt(isp, ISP_LOGERR, + "PLOGX failed: invalid parameter at offset 0x%x", parm1); + break; + case PLOGX_IOCBERR_PORTUSED: + isp_prt(isp, ISP_LOGDEBUG0, + "portid 0x%x already logged in with N-port handle 0x%x", + portid, parm1); + rval = MBOX_PORT_ID_USED | (handle << 16); + break; + case PLOGX_IOCBERR_HNDLUSED: + isp_prt(isp, ISP_LOGDEBUG0, + "N-port handle 0x%x already used for portid 0x%x", + handle, parm1); + rval = MBOX_LOOP_ID_USED; + break; + case PLOGX_IOCBERR_NOHANDLE: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no handle allocated"); + break; + case PLOGX_IOCBERR_NOFLOGI: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no FLOGI_ACC"); + break; + default: + isp_prt(isp, ISP_LOGERR, "status %x from %x", plp->plogx_status, + flags); + rval = -1; + break; } +out: + if (gs == 0) { + FC_SCRATCH_RELEASE(isp); + } + return (rval); } -static int -isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp) +int +isp_port_login(struct ispsoftc *isp, u_int16_t handle, u_int32_t portid) +{ + mbreg_t mbs; + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_FABRIC_LOGIN; + if (FCPARAM(isp)->isp_2klogin) { + mbs.param[1] = handle; + mbs.ibits = (1 << 10); + } else { + mbs.param[1] = handle << 8; + } + mbs.param[2] = portid >> 16; + mbs.param[3] = portid; + mbs.logval = MBLOGNONE; + mbs.timeout = 500000; + isp_mboxcmd(isp, &mbs); + + switch (mbs.param[0]) { + case MBOX_PORT_ID_USED: + isp_prt(isp, ISP_LOGDEBUG0, + "isp_plogi_old: portid 0x%06x already logged in as %u", + portid, mbs.param[1]); + return (MBOX_PORT_ID_USED | (mbs.param[1] << 16)); + + case MBOX_LOOP_ID_USED: + isp_prt(isp, ISP_LOGDEBUG0, + "isp_plogi_old: handle %u in use for port id 0x%02xXXXX", + handle, mbs.param[1] & 0xff); + return (MBOX_LOOP_ID_USED); + + case MBOX_COMMAND_COMPLETE: + return (0); + + case MBOX_COMMAND_ERROR: + isp_prt(isp, ISP_LOGINFO, + "isp_plogi_old: error 0x%x in PLOGI to port 0x%06x", + mbs.param[1], portid); + return (MBOX_COMMAND_ERROR); + + case MBOX_ALL_IDS_USED: + isp_prt(isp, ISP_LOGINFO, + "isp_plogi_old: all IDs used for fabric login"); + return (MBOX_ALL_IDS_USED); + + default: + isp_prt(isp, ISP_LOGINFO, + "isp_plogi_old: error 0x%x on port login of 0x%06x@0x%0x", + mbs.param[0], portid, handle); + return (mbs.param[0]); + } +} + +int +isp_port_logout(struct ispsoftc *isp, u_int16_t handle, u_int32_t portid) +{ + mbreg_t mbs; + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_FABRIC_LOGOUT; + if (FCPARAM(isp)->isp_2klogin) { + mbs.param[1] = handle; + mbs.ibits = (1 << 10); + } else { + mbs.param[1] = handle << 8; + } + mbs.logval = MBLOGNONE; + mbs.timeout = 100000; + isp_mboxcmd(isp, &mbs); + return (mbs.param[0] == MBOX_COMMAND_COMPLETE? 0 : mbs.param[0]); +} + +int +isp_getpdb(struct ispsoftc *isp, u_int16_t id, isp_pdb_t *pdb, int dolock) { fcparam *fcp = (fcparam *) isp->isp_param; mbreg_t mbs; + union { + isp_pdb_21xx_t fred; + isp_pdb_24xx_t bill; + } un; - MEMZERO(&mbs, sizeof (mbs)); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_PORT_DB; - mbs.param[1] = id << 8; + if (IS_24XX(isp)) { + mbs.ibits = 0x3ff; + mbs.param[1] = id; + } else if (FCPARAM(isp)->isp_2klogin) { + mbs.param[1] = id; + mbs.ibits = (1 << 10); + } else { + mbs.param[1] = id << 8; + } mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); 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); + mbs.timeout = 250000; + mbs.logval = MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR; + if (dolock) { + FC_SCRATCH_ACQUIRE(isp); + } + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (un)); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + if (dolock) { + FC_SCRATCH_RELEASE(isp); + } + return (-1); + } + if (IS_24XX(isp)) { + isp_get_pdb_24xx(isp, fcp->isp_scratch, &un.bill); + pdb->handle = un.bill.pdb_handle; + pdb->s3_role = un.bill.pdb_prli_svc3; + pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits); + MEMCPY(pdb->portname, un.bill.pdb_portname, 8); + MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8); + } else { + isp_get_pdb_21xx(isp, fcp->isp_scratch, &un.fred); + pdb->handle = un.fred.pdb_loopid; + pdb->s3_role = un.fred.pdb_prli_svc3; + pdb->portid = BITS2WORD(un.fred.pdb_portid_bits); + MEMCPY(pdb->portname, un.fred.pdb_portname, 8); + MEMCPY(pdb->nodename, un.fred.pdb_nodename, 8); + } + if (dolock) { FC_SCRATCH_RELEASE(isp); - return (0); } - FC_SCRATCH_RELEASE(isp); - return (-1); + return (0); } -static u_int64_t +u_int64_t isp_get_portname(struct ispsoftc *isp, int loopid, int nodename) { - u_int64_t wwn = 0; + u_int64_t wwn = (u_int64_t) -1; mbreg_t mbs; - MEMZERO(&mbs, sizeof (mbs)); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_PORT_NAME; - mbs.param[1] = loopid << 8; - if (nodename) - mbs.param[1] |= 1; - isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); - if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { + if (FCPARAM(isp)->isp_2klogin || IS_24XX(isp)) { + mbs.param[1] = loopid; + mbs.ibits = (1 << 10); + if (nodename) { + mbs.param[10] = 1; + } + } else { + mbs.param[1] = loopid << 8; + if (nodename) { + mbs.param[1] |= 1; + } + } + mbs.logval = MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return (wwn); + } + if (IS_24XX(isp)) { wwn = - (((u_int64_t)(mbs.param[2] & 0xff)) << 56) | + (((u_int64_t)(mbs.param[2] >> 8)) << 56) | + (((u_int64_t)(mbs.param[2] & 0xff)) << 48) | + (((u_int64_t)(mbs.param[3] >> 8)) << 40) | + (((u_int64_t)(mbs.param[3] & 0xff)) << 32) | + (((u_int64_t)(mbs.param[6] >> 8)) << 24) | + (((u_int64_t)(mbs.param[6] & 0xff)) << 16) | + (((u_int64_t)(mbs.param[7] >> 8)) << 8) | + (((u_int64_t)(mbs.param[7] & 0xff))); + } else { + wwn = + (((u_int64_t)(mbs.param[2] & 0xff)) << 56) | (((u_int64_t)(mbs.param[2] >> 8)) << 48) | (((u_int64_t)(mbs.param[3] & 0xff)) << 40) | (((u_int64_t)(mbs.param[3] >> 8)) << 32) | @@ -1538,13 +2449,13 @@ isp_get_portname(struct ispsoftc *isp, int loopid, int nodename) } /* - * Make sure we have good FC link and know our Loop ID. + * Make sure we have good FC link. */ -static int +int isp_fclink_test(struct ispsoftc *isp, int usdelay) { - static char *toponames[] = { + static const char *toponames[] = { "Private Loop", "FL Port", "N-Port to N-Port", @@ -1554,15 +2465,15 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay) mbreg_t mbs; int count, check_for_fabric; u_int8_t lwfs; + int loopid; fcparam *fcp; - struct lportdb *lp; + fcportdb_t *lp; isp_pdb_t pdb; fcp = isp->isp_param; - /* - * XXX: Here is where we would start a 'loop dead' timeout - */ + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Link Test Entry"); + ISP_MARK_PORTDB(isp, 1); /* * Wait up to N microseconds for F/W to go to a ready state. @@ -1577,12 +2488,14 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay) GET_NANOTIME(&hra); isp_fw_state(isp); if (lwfs != fcp->isp_fwstate) { - isp_prt(isp, ISP_LOGINFO, "Firmware State <%s->%s>", - isp2100_fw_statename((int)lwfs), - isp2100_fw_statename((int)fcp->isp_fwstate)); + isp_prt(isp, ISP_LOGCONFIG|ISP_LOGSANCFG, + "Firmware State <%s->%s>", + ispfc_fw_statename((int)lwfs), + ispfc_fw_statename((int)fcp->isp_fwstate)); lwfs = fcp->isp_fwstate; } - if (fcp->isp_fwstate == FW_READY) { + if (fcp->isp_fwstate == FW_READY && + fcp->isp_loopstate >= LOOP_PDB_RCVD) { break; } GET_NANOTIME(&hrb); @@ -1631,36 +2544,38 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay) * If we haven't gone to 'ready' state, return. */ if (fcp->isp_fwstate != FW_READY) { + isp_prt(isp, ISP_LOGSANCFG, + "isp_fclink_test: not at FW_READY state"); return (-1); } /* - * Get our Loop ID (if possible). We really need to have it. + * Get our Loop ID and Port ID. */ MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_LOOP_ID; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return (-1); } - fcp->isp_loopid = mbs.param[1]; - if (IS_2200(isp) || IS_23XX(isp)) { + + if (FCPARAM(isp)->isp_2klogin) { + fcp->isp_loopid = mbs.param[1]; + } else { + fcp->isp_loopid = mbs.param[1] & 0xff; + } + + if (IS_2100(isp)) { + fcp->isp_topo = TOPO_NL_PORT; + } else { int topo = (int) mbs.param[6]; - if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) + if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) { topo = TOPO_PTP_STUB; + } fcp->isp_topo = topo; - } else { - fcp->isp_topo = TOPO_NL_PORT; } - fcp->isp_portid = fcp->isp_alpa = mbs.param[2] & 0xff; - - /* - * Check to see if we're on a fabric by trying to see if we - * can talk to the fabric name server. This can be a bit - * tricky because if we're a 2100, we should check always - * (in case we're connected to a server doing aliasing). - */ - fcp->isp_onfabric = 0; + fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16); if (IS_2100(isp)) { /* @@ -1675,122 +2590,92 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay) } else if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_F_PORT) { check_for_fabric = 1; - } else + } else { check_for_fabric = 0; + } - if (check_for_fabric && isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) { - int loopid = FL_PORT_ID; + if (IS_24XX(isp)) { + loopid = NPH_FL_ID; + } else { + loopid = FL_ID; + } + + if (check_for_fabric && isp_getpdb(isp, loopid, &pdb, 1) == 0) { + int r; if (IS_2100(isp)) { fcp->isp_topo = TOPO_FL_PORT; } - - if (BITS2WORD(pdb.pdb_portid_bits) == 0) { + if (pdb.portid == 0) { /* * Crock. */ fcp->isp_topo = TOPO_NL_PORT; goto not_on_fabric; } - fcp->isp_portid = mbs.param[2] | ((int) mbs.param[3] << 16); /* * Save the Fabric controller's port database entry. */ - lp = &fcp->portdb[loopid]; - lp->node_wwn = - (((u_int64_t)pdb.pdb_nodename[0]) << 56) | - (((u_int64_t)pdb.pdb_nodename[1]) << 48) | - (((u_int64_t)pdb.pdb_nodename[2]) << 40) | - (((u_int64_t)pdb.pdb_nodename[3]) << 32) | - (((u_int64_t)pdb.pdb_nodename[4]) << 24) | - (((u_int64_t)pdb.pdb_nodename[5]) << 16) | - (((u_int64_t)pdb.pdb_nodename[6]) << 8) | - (((u_int64_t)pdb.pdb_nodename[7])); - lp->port_wwn = - (((u_int64_t)pdb.pdb_portname[0]) << 56) | - (((u_int64_t)pdb.pdb_portname[1]) << 48) | - (((u_int64_t)pdb.pdb_portname[2]) << 40) | - (((u_int64_t)pdb.pdb_portname[3]) << 32) | - (((u_int64_t)pdb.pdb_portname[4]) << 24) | - (((u_int64_t)pdb.pdb_portname[5]) << 16) | - (((u_int64_t)pdb.pdb_portname[6]) << 8) | - (((u_int64_t)pdb.pdb_portname[7])); - lp->roles = - (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; - lp->portid = BITS2WORD(pdb.pdb_portid_bits); - lp->loopid = pdb.pdb_loopid; - lp->loggedin = lp->valid = 1; - fcp->isp_onfabric = 1; - (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); - isp_register_fc4_type(isp); + lp = &fcp->portdb[FL_ID]; + lp->state = FC_PORTDB_STATE_PENDING_VALID; + MAKE_WWN_FROM_NODE_NAME(lp->node_wwn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(lp->port_wwn, pdb.portname); + lp->roles = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + lp->portid = pdb.portid; + lp->handle = pdb.handle; + lp->new_portid = lp->portid; + lp->new_roles = lp->roles; + if (IS_24XX(isp)) { + r = isp_register_fc4_type_24xx(isp); + } else { + r = isp_register_fc4_type(isp); + } + if (r) { + isp_prt(isp, ISP_LOGSANCFG, + "isp_fclink_test: register fc4 type failed"); + return (-1); + } } else { not_on_fabric: - fcp->isp_onfabric = 0; - fcp->portdb[FL_PORT_ID].valid = 0; + fcp->portdb[FL_ID].state = FC_PORTDB_STATE_NIL; } fcp->isp_gbspeed = 1; - if (IS_23XX(isp)) { - MEMZERO(&mbs, sizeof (mbs)); + if (IS_23XX(isp) || IS_24XX(isp)) { + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_SET_DATA_RATE; mbs.param[1] = MBGSD_GET_RATE; /* mbs.param[2] undefined if we're just getting rate */ - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + mbs.timeout = 3000000; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - if (mbs.param[1] == MBGSD_TWOGB) { + if (mbs.param[1] == MBGSD_FOURGB) { + isp_prt(isp, ISP_LOGINFO, "4Gb link speed/s"); + fcp->isp_gbspeed = 4; + } if (mbs.param[1] == MBGSD_TWOGB) { isp_prt(isp, ISP_LOGINFO, "2Gb link speed/s"); fcp->isp_gbspeed = 2; } } } - isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid, fcp->isp_alpa, - fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]); - /* - * Announce ourselves, too. This involves synthesizing an entry. + * Announce ourselves, too. */ - if (fcp->isp_iid_set == 0) { - fcp->isp_iid_set = 1; - fcp->isp_iid = fcp->isp_loopid; - lp = &fcp->portdb[fcp->isp_iid]; - } else { - lp = &fcp->portdb[fcp->isp_iid]; - if (fcp->isp_portid != lp->portid || - fcp->isp_loopid != lp->loopid || - fcp->isp_nodewwn != ISP_NODEWWN(isp) || - fcp->isp_portwwn != ISP_PORTWWN(isp)) { - lp->valid = 0; - count = fcp->isp_iid; - (void) isp_async(isp, ISPASYNC_PROMENADE, &count); - } - } - lp->loopid = fcp->isp_loopid; - lp->portid = fcp->isp_portid; - lp->node_wwn = ISP_NODEWWN(isp); - lp->port_wwn = ISP_PORTWWN(isp); - switch (isp->isp_role) { - case ISP_ROLE_NONE: - lp->roles = 0; - break; - case ISP_ROLE_TARGET: - lp->roles = SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT; - break; - case ISP_ROLE_INITIATOR: - lp->roles = SVC3_INI_ROLE >> SVC3_ROLE_SHIFT; - break; - case ISP_ROLE_BOTH: - lp->roles = (SVC3_INI_ROLE|SVC3_TGT_ROLE) >> SVC3_ROLE_SHIFT; - break; - } - lp->loggedin = lp->valid = 1; - count = fcp->isp_iid; - (void) isp_async(isp, ISPASYNC_PROMENADE, &count); + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, topology, fcp->isp_portid, + fcp->isp_loopid, toponames[fcp->isp_topo]); + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, ourwwn, + (u_int32_t) (ISP_NODEWWN(isp) >> 32), + (u_int32_t) ISP_NODEWWN(isp), + (u_int32_t) (ISP_PORTWWN(isp) >> 32), + (u_int32_t) ISP_PORTWWN(isp)); + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Link Test Complete"); return (0); } -static char * -isp2100_fw_statename(int state) +const char * +ispfc_fw_statename(int state) { switch(state) { case FW_CONFIG_WAIT: return "Config Wait"; @@ -1806,17 +2691,35 @@ isp2100_fw_statename(int state) } /* - * Synchronize our soft copy of the port database with what the f/w thinks - * (with a view toward possibly for a specific target....) + * Complete the synchronization of our Port Database. + * + * At this point, we've scanned the local loop (if any) and the fabric + * and performed fabric logins on all new devices. + * + * Our task here is to go through our port database and remove any entities + * that are still marked probational (issuing PLOGO for ones which we had + * PLOGI'd into) or are dead. + * + * Our task here is to also check policy to decide whether devices which + * have *changed* in some way should still be kept active. For example, + * if a device has just changed PortID, we can either elect to treat it + * as an old device or as a newly arrived device (and notify the outer + * layer appropriately). + * + * We also do initiator map target id assignment here for new initiator + * devices and refresh old ones ot make sure that they point to the corret + * entities. */ - -static int +int isp_pdb_sync(struct ispsoftc *isp) { - struct lportdb *lp; fcparam *fcp = isp->isp_param; - isp_pdb_t pdb; - int loopid, base, lim; + fcportdb_t *lp; + u_int16_t dbidx; + + if (fcp->isp_loopstate == LOOP_READY) { + return (0); + } /* * Make sure we're okay for doing this right now. @@ -1824,289 +2727,127 @@ isp_pdb_sync(struct ispsoftc *isp) if (fcp->isp_loopstate != LOOP_PDB_RCVD && fcp->isp_loopstate != LOOP_FSCAN_DONE && fcp->isp_loopstate != LOOP_LSCAN_DONE) { + isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: bad loopstate %d", + fcp->isp_loopstate); return (-1); } - if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT || + if (fcp->isp_topo == TOPO_FL_PORT || + fcp->isp_topo == TOPO_NL_PORT || fcp->isp_topo == TOPO_N_PORT) { if (fcp->isp_loopstate < LOOP_LSCAN_DONE) { if (isp_scan_loop(isp) != 0) { + isp_prt(isp, ISP_LOGWARN, + "isp_pdb_sync: isp_scan_loop failed"); return (-1); } } } - fcp->isp_loopstate = LOOP_SYNCING_PDB; - - /* - * If we get this far, we've settled our differences with the f/w - * (for local loop device) and we can say that the loop state is ready. - */ - - if (fcp->isp_topo == TOPO_NL_PORT) { - fcp->loop_seen_once = 1; - fcp->isp_loopstate = LOOP_READY; - return (0); - } - /* - * Find all Fabric Entities that didn't make it from one scan to the - * next and let the world know they went away. Scan the whole database. - */ - for (lp = &fcp->portdb[0]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { - if (lp->was_fabric_dev && lp->fabric_dev == 0) { - loopid = lp - fcp->portdb; - lp->valid = 0; /* should already be set */ - (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); - MEMZERO((void *) lp, sizeof (*lp)); - continue; + if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { + if (fcp->isp_loopstate < LOOP_FSCAN_DONE) { + if (isp_scan_fabric(isp) != 0) { + isp_prt(isp, ISP_LOGWARN, + "isp_pdb_sync: isp_scan_fabric failed"); + return (-1); + } } - lp->was_fabric_dev = lp->fabric_dev; } - if (fcp->isp_topo == TOPO_FL_PORT) - base = FC_SNS_ID+1; - else - base = 0; - - if (fcp->isp_topo == TOPO_N_PORT) - lim = 1; - else - lim = MAX_FC_TARG; - - /* - * Now log in any fabric devices that the outer layer has - * left for us to see. This seems the most sane policy - * for the moment. - */ - for (lp = &fcp->portdb[base]; lp < &fcp->portdb[lim]; lp++) { - u_int32_t portid; - mbreg_t mbs; + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Synchronizing PDBs"); - loopid = lp - fcp->portdb; - if (loopid >= FL_PORT_ID && loopid <= FC_SNS_ID) { - continue; - } + fcp->isp_loopstate = LOOP_SYNCING_PDB; - /* - * Anything here? - */ - if (lp->port_wwn == 0) { - continue; - } + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + lp = &fcp->portdb[dbidx]; - /* - * Don't try to log into yourself. - */ - if ((portid = lp->portid) == fcp->isp_portid) { + if (lp->state == FC_PORTDB_STATE_NIL) { continue; } - - /* - * If we'd been logged in- see if we still are and we haven't - * changed. If so, no need to log ourselves out, etc.. - * - * Unfortunately, our charming QLogic f/w has decided to - * return a valid port database entry for a fabric device - * that has, in fact, gone away. And it hangs trying to - * log it out. - */ - if (lp->loggedin && lp->force_logout == 0 && - isp_getpdb(isp, lp->loopid, &pdb) == 0) { - int nrole; - u_int64_t nwwnn, nwwpn; - nwwnn = - (((u_int64_t)pdb.pdb_nodename[0]) << 56) | - (((u_int64_t)pdb.pdb_nodename[1]) << 48) | - (((u_int64_t)pdb.pdb_nodename[2]) << 40) | - (((u_int64_t)pdb.pdb_nodename[3]) << 32) | - (((u_int64_t)pdb.pdb_nodename[4]) << 24) | - (((u_int64_t)pdb.pdb_nodename[5]) << 16) | - (((u_int64_t)pdb.pdb_nodename[6]) << 8) | - (((u_int64_t)pdb.pdb_nodename[7])); - nwwpn = - (((u_int64_t)pdb.pdb_portname[0]) << 56) | - (((u_int64_t)pdb.pdb_portname[1]) << 48) | - (((u_int64_t)pdb.pdb_portname[2]) << 40) | - (((u_int64_t)pdb.pdb_portname[3]) << 32) | - (((u_int64_t)pdb.pdb_portname[4]) << 24) | - (((u_int64_t)pdb.pdb_portname[5]) << 16) | - (((u_int64_t)pdb.pdb_portname[6]) << 8) | - (((u_int64_t)pdb.pdb_portname[7])); - nrole = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> - SVC3_ROLE_SHIFT; - if (pdb.pdb_loopid == lp->loopid && lp->portid == - (u_int32_t) BITS2WORD(pdb.pdb_portid_bits) && - nwwnn == lp->node_wwn && nwwpn == lp->port_wwn && - lp->roles == nrole && lp->force_logout == 0) { - lp->loggedin = lp->valid = 1; - isp_prt(isp, ISP_LOGCONFIG, lretained, - (int) (lp - fcp->portdb), - (int) lp->loopid, lp->portid); - continue; + if (lp->state == FC_PORTDB_STATE_VALID) { + if (dbidx != FL_ID) { + isp_prt(isp, + ISP_LOGERR, "portdb idx %d already valid", + dbidx); } + continue; } - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); - } - - /* - * Force a logout if we were logged in. - */ - if (lp->loggedin) { - if (lp->force_logout || - isp_getpdb(isp, lp->loopid, &pdb) == 0) { - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_FABRIC_LOGOUT; - mbs.param[1] = lp->loopid << 8; - isp_mboxcmd(isp, &mbs, MBLOGNONE); - isp_prt(isp, ISP_LOGINFO, plogout, - (int) (lp - fcp->portdb), lp->loopid, - lp->portid); + switch (lp->state) { + case FC_PORTDB_STATE_PROBATIONAL: + case FC_PORTDB_STATE_DEAD: + /* + * It's up to the outer layers to clear isp_ini_map. + */ + lp->state = FC_PORTDB_STATE_NIL; + isp_async(isp, ISPASYNC_DEV_GONE, lp); + if (lp->autologin == 0) { + (void) isp_plogx(isp, lp->handle, lp->portid, + PLOGX_FLG_CMD_LOGO | + PLOGX_FLG_IMPLICIT | + PLOGX_FLG_FREE_NPHDL, 0); + } else { + lp->autologin = 0; } - lp->force_logout = lp->loggedin = 0; - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); + lp->new_roles = 0; + lp->new_portid = 0; + /* + * Note that we might come out of this with our state + * set to FC_PORTDB_STATE_ZOMBIE. + */ + break; + case FC_PORTDB_STATE_NEW: + /* + * It's up to the outer layers to assign a virtual + * target id in isp_ini_map (if any). + */ + lp->portid = lp->new_portid; + lp->roles = lp->new_roles; + lp->state = FC_PORTDB_STATE_VALID; + isp_async(isp, ISPASYNC_DEV_ARRIVED, lp); + lp->new_roles = 0; + lp->new_portid = 0; + lp->reserved = 0; + lp->new_reserved = 0; + break; + case FC_PORTDB_STATE_CHANGED: +/* + * XXXX FIX THIS + */ + lp->state = FC_PORTDB_STATE_VALID; + isp_async(isp, ISPASYNC_DEV_CHANGED, lp); + lp->new_roles = 0; + lp->new_portid = 0; + lp->reserved = 0; + lp->new_reserved = 0; + break; + case FC_PORTDB_STATE_PENDING_VALID: + lp->portid = lp->new_portid; + lp->roles = lp->new_roles; + if (lp->ini_map_idx) { + int t = lp->ini_map_idx - 1; + fcp->isp_ini_map[t] = dbidx + 1; } - } - - /* - * And log in.... - */ - loopid = lp - fcp->portdb; - lp->loopid = FL_PORT_ID; - do { - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_FABRIC_LOGIN; - mbs.param[1] = loopid << 8; - mbs.param[2] = portid >> 16; - mbs.param[3] = portid & 0xffff; - isp_mboxcmd(isp, &mbs, MBLOGALL & ~(MBOX_LOOP_ID_USED | - MBOX_PORT_ID_USED | MBOX_COMMAND_ERROR)); - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); + lp->state = FC_PORTDB_STATE_VALID; + isp_async(isp, ISPASYNC_DEV_STAYED, lp); + if (dbidx != FL_ID) { + lp->new_roles = 0; + lp->new_portid = 0; } - switch (mbs.param[0]) { - case MBOX_LOOP_ID_USED: - /* - * Try the next available loop id. - */ - loopid++; - break; - case MBOX_PORT_ID_USED: - /* - * This port is already logged in. - * Snaffle the loop id it's using if it's - * nonzero, otherwise we're hosed. - */ - if (mbs.param[1] != 0) { - loopid = mbs.param[1]; - isp_prt(isp, ISP_LOGINFO, retained, - loopid, (int) (lp - fcp->portdb), - lp->portid); - } else { - loopid = MAX_FC_TARG; - break; - } - /* FALLTHROUGH */ - case MBOX_COMMAND_COMPLETE: - lp->loggedin = 1; - lp->loopid = loopid; - break; - case MBOX_COMMAND_ERROR: - isp_prt(isp, ISP_LOGINFO, plogierr, - portid, mbs.param[1]); - /* FALLTHROUGH */ - case MBOX_ALL_IDS_USED: /* We're outta IDs */ - default: - loopid = MAX_FC_TARG; - break; - } - } while (lp->loopid == FL_PORT_ID && loopid < MAX_FC_TARG); - - /* - * If we get here and we haven't set a Loop ID, - * we failed to log into this device. - */ - - if (lp->loopid == FL_PORT_ID) { - lp->loopid = 0; - continue; - } - - /* - * Make sure we can get the appropriate port information. - */ - if (isp_getpdb(isp, lp->loopid, &pdb) != 0) { - isp_prt(isp, ISP_LOGWARN, nopdb, lp->portid); - goto dump_em; - } - - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); - } - - if (pdb.pdb_loopid != lp->loopid) { - isp_prt(isp, ISP_LOGWARN, pdbmfail1, - lp->portid, pdb.pdb_loopid); - goto dump_em; - } - - if (lp->portid != (u_int32_t) BITS2WORD(pdb.pdb_portid_bits)) { - isp_prt(isp, ISP_LOGWARN, pdbmfail2, - lp->portid, BITS2WORD(pdb.pdb_portid_bits)); - goto dump_em; - } - - lp->roles = - (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; - lp->node_wwn = - (((u_int64_t)pdb.pdb_nodename[0]) << 56) | - (((u_int64_t)pdb.pdb_nodename[1]) << 48) | - (((u_int64_t)pdb.pdb_nodename[2]) << 40) | - (((u_int64_t)pdb.pdb_nodename[3]) << 32) | - (((u_int64_t)pdb.pdb_nodename[4]) << 24) | - (((u_int64_t)pdb.pdb_nodename[5]) << 16) | - (((u_int64_t)pdb.pdb_nodename[6]) << 8) | - (((u_int64_t)pdb.pdb_nodename[7])); - lp->port_wwn = - (((u_int64_t)pdb.pdb_portname[0]) << 56) | - (((u_int64_t)pdb.pdb_portname[1]) << 48) | - (((u_int64_t)pdb.pdb_portname[2]) << 40) | - (((u_int64_t)pdb.pdb_portname[3]) << 32) | - (((u_int64_t)pdb.pdb_portname[4]) << 24) | - (((u_int64_t)pdb.pdb_portname[5]) << 16) | - (((u_int64_t)pdb.pdb_portname[6]) << 8) | - (((u_int64_t)pdb.pdb_portname[7])); - /* - * Check to make sure this all makes sense. - */ - if (lp->node_wwn && lp->port_wwn) { - lp->valid = 1; - loopid = lp - fcp->portdb; - (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); - continue; - } -dump_em: - lp->valid = 0; - isp_prt(isp, ISP_LOGINFO, - ldumped, loopid, lp->loopid, lp->portid); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_FABRIC_LOGOUT; - mbs.param[1] = lp->loopid << 8; - mbs.param[2] = 0; - mbs.param[3] = 0; - isp_mboxcmd(isp, &mbs, MBLOGNONE); - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); + lp->reserved = 0; + lp->new_reserved = 0; + break; + case FC_PORTDB_STATE_ZOMBIE: + break; + default: + isp_prt(isp, ISP_LOGWARN, + "isp_scan_loop: state %d for idx %d", + lp->state, dbidx); + isp_dump_portdb(isp); } } + /* * If we get here, we've for sure seen not only a valid loop * but know what is or isn't on it, so mark this for usage @@ -2117,799 +2858,969 @@ dump_em: return (0); } -static int +/* + * Scan local loop for devices. + */ +int isp_scan_loop(struct ispsoftc *isp) { - struct lportdb *lp; + fcportdb_t *lp, tmp; fcparam *fcp = isp->isp_param; + int i; isp_pdb_t pdb; - int loopid, lim, hival; + u_int16_t handle, lim = 0; + if (fcp->isp_fwstate < FW_READY || + fcp->isp_loopstate < LOOP_PDB_RCVD) { + return (-1); + } + + if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) { + return (0); + } + + /* + * Check our connection topology. + * + * If we're a public or private loop, we scan 0..125 as handle values. + * The firmware has (typically) peformed a PLOGI for us. + * + * If we're a N-port connection, we treat this is a short loop (0..1). + * + * If we're in target mode, we can all possible handles to see who + * might have logged into us. + */ switch (fcp->isp_topo) { case TOPO_NL_PORT: - hival = FL_PORT_ID; + case TOPO_FL_PORT: + lim = LOCAL_LOOP_LIM; break; case TOPO_N_PORT: - hival = 2; - break; - case TOPO_FL_PORT: - hival = FC_PORT_ID; + lim = 2; break; default: + isp_prt(isp, ISP_LOGDEBUG0, "no loop topology to scan"); fcp->isp_loopstate = LOOP_LSCAN_DONE; return (0); } + fcp->isp_loopstate = LOOP_SCANNING_LOOP; - /* - * make sure the temp port database is clean... - */ - MEMZERO((void *)fcp->tport, sizeof (fcp->tport)); + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC scan loop 0..%d", lim-1); + /* - * Run through the local loop ports and get port database info - * for each loop ID. - * - * There's a somewhat unexplained situation where the f/w passes back - * the wrong database entity- if that happens, just restart (up to - * FL_PORT_ID times). + * Run through the list and get the port database info for each one. */ - for (lim = loopid = 0; loopid < hival; loopid++) { - lp = &fcp->tport[loopid]; - + for (handle = 0; handle < lim; handle++) { /* - * Don't even try for ourselves... + * But don't even try for ourselves... */ - if (loopid == fcp->isp_loopid) + if (handle == fcp->isp_loopid) { continue; + } - lp->node_wwn = isp_get_portname(isp, loopid, 1); - if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) - return (-1); - if (lp->node_wwn == 0) - continue; - lp->port_wwn = isp_get_portname(isp, loopid, 0); - if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) - return (-1); - if (lp->port_wwn == 0) { - lp->node_wwn = 0; - continue; + /* + * In older cards with older f/w GET_PORT_DATABASE has been + * known to hang. This trick gets around that problem. + */ + if (IS_2100(isp) || IS_2200(isp)) { + u_int64_t node_wwn = isp_get_portname(isp, handle, 1); + if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { + return (-1); + } + if (node_wwn == 0) { + continue; + } } /* - * Get an entry.... + * Get the port database entity for this index. */ - if (isp_getpdb(isp, loopid, &pdb) != 0) { - if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) + if (isp_getpdb(isp, handle, &pdb, 1) != 0) { + if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { + ISP_MARK_PORTDB(isp, 1); return (-1); + } continue; } + if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { + ISP_MARK_PORTDB(isp, 1); return (-1); } /* - * If the returned database element doesn't match what we - * asked for, restart the process entirely (up to a point...). + * On *very* old 2100 firmware we would end up sometimes + * with the firmware returning the port database entry + * for something else. We used to restart this, but + * now we just punt. */ - if (pdb.pdb_loopid != loopid) { - loopid = 0; - if (lim++ < hival) { - continue; - } + if (IS_2100(isp) && pdb.handle != handle) { isp_prt(isp, ISP_LOGWARN, "giving up on synchronizing the port database"); + ISP_MARK_PORTDB(isp, 1); return (-1); } /* * Save the pertinent info locally. */ - lp->node_wwn = - (((u_int64_t)pdb.pdb_nodename[0]) << 56) | - (((u_int64_t)pdb.pdb_nodename[1]) << 48) | - (((u_int64_t)pdb.pdb_nodename[2]) << 40) | - (((u_int64_t)pdb.pdb_nodename[3]) << 32) | - (((u_int64_t)pdb.pdb_nodename[4]) << 24) | - (((u_int64_t)pdb.pdb_nodename[5]) << 16) | - (((u_int64_t)pdb.pdb_nodename[6]) << 8) | - (((u_int64_t)pdb.pdb_nodename[7])); - lp->port_wwn = - (((u_int64_t)pdb.pdb_portname[0]) << 56) | - (((u_int64_t)pdb.pdb_portname[1]) << 48) | - (((u_int64_t)pdb.pdb_portname[2]) << 40) | - (((u_int64_t)pdb.pdb_portname[3]) << 32) | - (((u_int64_t)pdb.pdb_portname[4]) << 24) | - (((u_int64_t)pdb.pdb_portname[5]) << 16) | - (((u_int64_t)pdb.pdb_portname[6]) << 8) | - (((u_int64_t)pdb.pdb_portname[7])); - lp->roles = - (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; - lp->portid = BITS2WORD(pdb.pdb_portid_bits); - lp->loopid = pdb.pdb_loopid; - } - - /* - * Mark all of the permanent local loop database entries as invalid - * (except our own entry). - */ - for (loopid = 0; loopid < hival; loopid++) { - if (loopid == fcp->isp_iid) { - fcp->portdb[loopid].valid = 1; - fcp->portdb[loopid].loopid = fcp->isp_loopid; - continue; - } - fcp->portdb[loopid].valid = 0; - } - - /* - * Now merge our local copy of the port database into our saved copy. - * Notify the outer layers of new devices arriving. - */ - for (loopid = 0; loopid < hival; loopid++) { - int i; - - /* - * If we don't have a non-zero Port WWN, we're not here. - */ - if (fcp->tport[loopid].port_wwn == 0) { - continue; - } + MAKE_WWN_FROM_NODE_NAME(tmp.node_wwn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(tmp.port_wwn, pdb.portname); + tmp.roles = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + tmp.portid = pdb.portid; + tmp.handle = pdb.handle; /* - * Skip ourselves. + * Check to make sure it's still a valid entry. The 24XX seems + * to return a portid but not a WWPN/WWNN or role for devices + * which shift on a loop. */ - if (loopid == fcp->isp_iid) { + if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) { + int a, b, c; + a = (tmp.node_wwn == 0); + b = (tmp.port_wwn == 0); + c = (tmp.portid == 0); + isp_prt(isp, ISP_LOGWARN, + "bad pdb (%1d%1d%1d) @ handle 0x%x", a, b, c, + handle); + isp_dump_portdb(isp); continue; } /* - * For the purposes of deciding whether this is the - * 'same' device or not, we only search for an identical - * Port WWN. Node WWNs may or may not be the same as - * the Port WWN, and there may be multiple different - * Port WWNs with the same Node WWN. It would be chaos - * to have multiple identical Port WWNs, so we don't - * allow that. + * Now search the entire port database + * for the same Port and Node WWN. */ - - for (i = 0; i < hival; i++) { - int j; - if (fcp->portdb[i].port_wwn == 0) + for (i = 0; i < MAX_FC_TARG; i++) { + lp = &fcp->portdb[i]; + if (lp->state == FC_PORTDB_STATE_NIL) { continue; - if (fcp->portdb[i].port_wwn != - fcp->tport[loopid].port_wwn) + } + if (lp->node_wwn != tmp.node_wwn) { + continue; + } + if (lp->port_wwn != tmp.port_wwn) { continue; + } + /* - * We found this WWN elsewhere- it's changed - * loopids then. We don't change its actual - * position in our cached port database- we - * just change the actual loop ID we'd use. + * Okay- we've found a non-nil entry that matches. + * Check to make sure it's probational or a zombie. */ - if (fcp->portdb[i].loopid != loopid) { - isp_prt(isp, ISP_LOGINFO, portshift, i, - fcp->portdb[i].loopid, - fcp->portdb[i].portid, loopid, - fcp->tport[loopid].portid); + if (lp->state != FC_PORTDB_STATE_PROBATIONAL && + lp->state != FC_PORTDB_STATE_ZOMBIE) { + isp_prt(isp, ISP_LOGERR, + "[%d] not probational/zombie (0x%x)", + i, lp->state); + isp_dump_portdb(isp); + ISP_MARK_PORTDB(isp, 1); + return (-1); } - fcp->portdb[i].portid = fcp->tport[loopid].portid; - fcp->portdb[i].loopid = loopid; - fcp->portdb[i].valid = 1; - fcp->portdb[i].roles = fcp->tport[loopid].roles; /* - * Now make sure this Port WWN doesn't exist elsewhere - * in the port database. + * Mark the device as something the f/w logs into + * automatically. */ - for (j = i+1; j < hival; j++) { - if (fcp->portdb[i].port_wwn != - fcp->portdb[j].port_wwn) { - continue; - } - isp_prt(isp, ISP_LOGWARN, portdup, j, i); - /* - * Invalidate the 'old' *and* 'new' ones. - * This is really harsh and not quite right, - * but if this happens, we really don't know - * who is what at this point. - */ - fcp->portdb[i].valid = 0; - fcp->portdb[j].valid = 0; + lp->autologin = 1; + + /* + * Check to make see if really still the same + * device. If it is, we mark it pending valid. + */ + if (lp->portid == tmp.portid && + lp->handle == tmp.handle && + lp->roles == tmp.roles) { + lp->new_portid = tmp.portid; + lp->new_roles = tmp.roles; + lp->state = FC_PORTDB_STATE_PENDING_VALID; + isp_prt(isp, ISP_LOGSANCFG, + "Loop Port 0x%02x@0x%x Pending Valid", + tmp.portid, tmp.handle); + break; } + + /* + * We can wipe out the old handle value + * here because it's no longer valid. + */ + lp->handle = tmp.handle; + + /* + * Claim that this has changed and let somebody else + * decide what to do. + */ + isp_prt(isp, ISP_LOGSANCFG, + "Loop Port 0x%02x@0x%x changed", + tmp.portid, tmp.handle); + lp->state = FC_PORTDB_STATE_CHANGED; + lp->new_portid = tmp.portid; + lp->new_roles = tmp.roles; break; } /* - * If we didn't traverse the entire port database, - * then we found (and remapped) an existing entry. - * No need to notify anyone- go for the next one. + * Did we find and update an old entry? */ - if (i < hival) { - isp_prt(isp, ISP_LOGINFO, retained, - fcp->portdb[i].loopid, i, fcp->portdb[i].portid); + if (i < MAX_FC_TARG) { continue; } /* - * We've not found this Port WWN anywhere. It's a new entry. - * See if we can leave it where it is (with target == loopid). + * Ah. A new device entry. Find an empty slot + * for it and save info for later disposition. */ - if (fcp->portdb[loopid].port_wwn != 0) { - for (lim = 0; lim < hival; lim++) { - if (fcp->portdb[lim].port_wwn == 0) - break; - } - /* "Cannot Happen" */ - if (lim == hival) { - isp_prt(isp, ISP_LOGWARN, "Remap Overflow"); - continue; + for (i = 0; i < MAX_FC_TARG; i++) { + if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) { + break; } - i = lim; - } else { - i = loopid; } - - /* - * NB: The actual loopid we use here is loopid- we may - * in fact be at a completely different index (target). - */ - fcp->portdb[i].loopid = loopid; - fcp->portdb[i].port_wwn = fcp->tport[loopid].port_wwn; - fcp->portdb[i].node_wwn = fcp->tport[loopid].node_wwn; - fcp->portdb[i].roles = fcp->tport[loopid].roles; - fcp->portdb[i].portid = fcp->tport[loopid].portid; - fcp->portdb[i].valid = 1; - - /* - * Tell the outside world we've arrived. - */ - (void) isp_async(isp, ISPASYNC_PROMENADE, &i); - } - - /* - * Now find all previously used targets that are now invalid and - * notify the outer layers that they're gone. - */ - for (lp = &fcp->portdb[0]; lp < &fcp->portdb[hival]; lp++) { - if (lp->valid || lp->port_wwn == 0) { + if (i == MAX_FC_TARG) { + isp_prt(isp, ISP_LOGERR, "out of portdb entries"); continue; } + lp = &fcp->portdb[i]; - /* - * Tell the outside world we've gone - * away and erase our pdb entry. - * - */ - loopid = lp - fcp->portdb; - (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); - MEMZERO((void *) lp, sizeof (*lp)); + MEMZERO(lp, sizeof (fcportdb_t)); + lp->autologin = 1; + lp->state = FC_PORTDB_STATE_NEW; + lp->new_portid = tmp.portid; + lp->new_roles = tmp.roles; + lp->handle = tmp.handle; + lp->port_wwn = tmp.port_wwn; + lp->node_wwn = tmp.node_wwn; + isp_prt(isp, ISP_LOGSANCFG, + "Loop Port 0x%02x@0x%x is New Entry", + tmp.portid, tmp.handle); } fcp->isp_loopstate = LOOP_LSCAN_DONE; return (0); } +/* + * Scan the fabric for devices and add them to our port database. + * + * Use the GID_FT command to get all Port IDs for FC4 SCSI devices it knows. + * + * For 2100-23XX cards, we can use the SNS mailbox command to pass simple + * name server commands to the switch management server via the QLogic f/w. + * + * For the 24XX card, we have to use CT-Pass through run via the Execute IOCB + * mailbox command. + * + * The net result is to leave the list of Port IDs setting untranslated in + * offset IGPOFF of the FC scratch area, whereupon we'll canonicalize it to + * host order at OGPOFF. + */ + +/* + * Take less than half of our scratch area to store Port IDs + */ +#define GIDLEN ((ISP2100_SCRLEN >> 1) - 16 - SNS_GID_FT_REQ_SIZE) +#define NGENT ((GIDLEN - 16) >> 2) + +#define IGPOFF (2 * QENTRY_LEN) +#define OGPOFF (ISP2100_SCRLEN >> 1) +#define ZTXOFF (ISP2100_SCRLEN - (1 * QENTRY_LEN)) +#define CTXOFF (ISP2100_SCRLEN - (2 * QENTRY_LEN)) +#define XTXOFF (ISP2100_SCRLEN - (3 * QENTRY_LEN)) -static int -isp_fabric_mbox_cmd(struct ispsoftc *isp, mbreg_t *mbp) +int +isp_gid_ft_sns(struct ispsoftc *isp) { - /* the caller sets up the mailbox */ - isp_mboxcmd(isp, mbp, MBLOGNONE); - if (mbp->param[0] != MBOX_COMMAND_COMPLETE) { - if (FCPARAM(isp)->isp_loopstate == LOOP_SCANNING_FABRIC) { - FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; - } - if (mbp->param[0] == MBOX_COMMAND_ERROR) { - char tbuf[16]; - char *m; - switch (mbp->param[1]) { - case 1: - m = "No Loop"; - break; - case 2: - m = "Failed to allocate IOCB buffer"; - break; - case 3: - m = "Failed to allocate XCB buffer"; - break; - case 4: - m = "timeout or transmit failed"; - break; - case 5: - m = "no fabric loop"; - break; - case 6: - m = "remote device not a target"; - break; - default: - SNPRINTF(tbuf, sizeof tbuf, "%x", - mbp->param[1]); - m = tbuf; - break; - } - isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m); - } - return (-1); - } + union { + sns_gid_ft_req_t _x; + u_int8_t _y[SNS_GID_FT_REQ_SIZE]; + } un; + fcparam *fcp = FCPARAM(isp); + sns_gid_ft_req_t *rq = &un._x; + mbreg_t mbs; - if (FCPARAM(isp)->isp_fwstate != FW_READY || - FCPARAM(isp)->isp_loopstate < LOOP_SCANNING_FABRIC) { - return (-1); + isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT) via SNS"); + + MEMZERO(rq, SNS_GID_FT_REQ_SIZE); + rq->snscb_rblen = GIDLEN >> 1; + rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + IGPOFF); + rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + IGPOFF); + rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + IGPOFF); + rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + IGPOFF); + rq->snscb_sblen = 6; + rq->snscb_cmd = SNS_GID_FT; + rq->snscb_mword_div_2 = NGENT; + rq->snscb_fc4_type = FC4_SCSI; + + isp_put_gid_ft_request(isp, rq, fcp->isp_scratch); + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE); + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_SEND_SNS; + mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1; + mbs.param[2] = DMA_WD1(fcp->isp_scdma); + mbs.param[3] = DMA_WD0(fcp->isp_scdma); + mbs.param[6] = DMA_WD3(fcp->isp_scdma); + mbs.param[7] = DMA_WD2(fcp->isp_scdma); + mbs.logval = MBLOGALL; + mbs.timeout = 10000000; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + if (mbs.param[0] == MBOX_INVALID_COMMAND) { + return (1); + } else { + return (-1); + } } - return(0); + return (0); } -#ifdef ISP_USE_GA_NXT -static int -isp_scan_fabric(struct ispsoftc *isp, int ftype) +int +isp_gid_ft_ct_passthru(struct ispsoftc *isp) { - fcparam *fcp = isp->isp_param; - u_int32_t portid, first_portid, last_portid; - int hicap, last_port_same; - - if (fcp->isp_onfabric == 0) { - fcp->isp_loopstate = LOOP_FSCAN_DONE; - return (0); + mbreg_t mbs; + fcparam *fcp = FCPARAM(isp); + union { + isp_ct_pt_t plocal; + ct_hdr_t clocal; + u_int8_t q[QENTRY_LEN]; + } un; + isp_ct_pt_t *pt; + ct_hdr_t *ct; + u_int32_t *rp; + u_int8_t *scp = fcp->isp_scratch; + + isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT) via CT"); + + if (!IS_24XX(isp)) { + return (1); } - FC_SCRATCH_ACQUIRE(isp); - /* - * Since Port IDs are 24 bits, we can check against having seen - * anything yet with this value. + * Build a Passthrough IOCB in memory. */ - last_port_same = 0; - last_portid = 0xffffffff; /* not a port */ - first_portid = portid = fcp->isp_portid; - fcp->isp_loopstate = LOOP_SCANNING_FABRIC; - - for (hicap = 0; hicap < GA_NXT_MAX; hicap++) { - mbreg_t mbs; - sns_screq_t *rq; - sns_ga_nxt_rsp_t *rs0, *rs1; - struct lportdb lcl; - u_int8_t sc[SNS_GA_NXT_RESP_SIZE]; - - rq = (sns_screq_t *)sc; - MEMZERO((void *) rq, SNS_GA_NXT_REQ_SIZE); - rq->snscb_rblen = SNS_GA_NXT_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_GA_NXT; - 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_GA_NXT_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); - /* - * Leave 4 and 5 alone - */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; - } - FC_SCRATCH_RELEASE(isp); - return (-1); - } - MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GA_NXT_RESP_SIZE); - rs1 = (sns_ga_nxt_rsp_t *) sc; - rs0 = (sns_ga_nxt_rsp_t *) ((u_int8_t *)fcp->isp_scratch+0x100); - isp_get_ga_nxt_response(isp, rs0, rs1); - if (rs1->snscb_cthdr.ct_response != FS_ACC) { - int level; - if (rs1->snscb_cthdr.ct_reason == 9 && - rs1->snscb_cthdr.ct_explanation == 7) - level = ISP_LOGDEBUG0; - else - level = ISP_LOGWARN; - isp_prt(isp, level, swrej, "GA_NXT", - rs1->snscb_cthdr.ct_reason, - rs1->snscb_cthdr.ct_explanation, portid); - FC_SCRATCH_RELEASE(isp); - fcp->isp_loopstate = LOOP_FSCAN_DONE; - return (0); - } - 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])); + pt = &un.plocal; + MEMZERO(un.q, QENTRY_LEN); + pt->ctp_header.rqs_entry_count = 1; + pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU; + pt->ctp_handle = 0xffffffff; + pt->ctp_nphdl = NPH_SNS_ID; + pt->ctp_cmd_cnt = 1; + pt->ctp_time = 30; + pt->ctp_rsp_cnt = 1; + pt->ctp_rsp_bcnt = GIDLEN; + pt->ctp_cmd_bcnt = sizeof (*ct) + sizeof (u_int32_t); + pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF); + pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF); + pt->ctp_dataseg[0].ds_count = sizeof (*ct) + sizeof (u_int32_t); + pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_count = GIDLEN; + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "ct IOCB", QENTRY_LEN, pt); + } + isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]); - /* - * XXX: We should check to make sure that this entry - * XXX: supports the type(s) we are interested in. - */ - /* - * Okay, we now have information about a fabric object. - * If it is the type we're interested in, tell the outer layers - * about it. The outer layer needs to know: Port ID, WWNN, - * WWPN, FC4 type, and port type. - * - * The lportdb structure is adequate for this. - */ - MEMZERO(&lcl, sizeof (lcl)); - lcl.port_type = rs1->snscb_port_type; - lcl.fc4_type = ftype; - lcl.portid = portid; - lcl.node_wwn = - (((u_int64_t)rs1->snscb_nodename[0]) << 56) | - (((u_int64_t)rs1->snscb_nodename[1]) << 48) | - (((u_int64_t)rs1->snscb_nodename[2]) << 40) | - (((u_int64_t)rs1->snscb_nodename[3]) << 32) | - (((u_int64_t)rs1->snscb_nodename[4]) << 24) | - (((u_int64_t)rs1->snscb_nodename[5]) << 16) | - (((u_int64_t)rs1->snscb_nodename[6]) << 8) | - (((u_int64_t)rs1->snscb_nodename[7])); - lcl.port_wwn = - (((u_int64_t)rs1->snscb_portname[0]) << 56) | - (((u_int64_t)rs1->snscb_portname[1]) << 48) | - (((u_int64_t)rs1->snscb_portname[2]) << 40) | - (((u_int64_t)rs1->snscb_portname[3]) << 32) | - (((u_int64_t)rs1->snscb_portname[4]) << 24) | - (((u_int64_t)rs1->snscb_portname[5]) << 16) | - (((u_int64_t)rs1->snscb_portname[6]) << 8) | - (((u_int64_t)rs1->snscb_portname[7])); + /* + * Build the CT header and command in memory. + * + * Note that the CT header has to end up as Big Endian format in memory. + */ + ct = &un.clocal; + MEMZERO(ct, sizeof (*ct)); + ct->ct_revision = CT_REVISION; + ct->ct_fcs_type = CT_FC_TYPE_FC; + ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; + ct->ct_cmd_resp = SNS_GID_FT; + ct->ct_bcnt_resid = (GIDLEN - 16) >> 2; + + isp_put_ct_hdr(isp, ct, (ct_hdr_t *) &scp[XTXOFF]); + rp = (u_int32_t *) &scp[XTXOFF+sizeof (*ct)]; + ISP_IOZPUT_32(isp, FC4_SCSI, rp); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "CT HDR + payload after put", + sizeof (*ct) + sizeof (u_int32_t), &scp[XTXOFF]); + } + MEMZERO(&scp[ZTXOFF], QENTRY_LEN); + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64; + mbs.param[1] = QENTRY_LEN; + mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF); + mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF); + mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF); + mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF); + mbs.timeout = 500000; + mbs.logval = MBLOGALL; + MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return (-1); + } + MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN); + pt = &un.plocal; + isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt); + } - /* - * Does this fabric object support the type we want? - * If not, skip it. - */ - if (rs1->snscb_fc4_types[ftype >> 5] & (1 << (ftype & 0x1f))) { - if (first_portid == portid) { - lcl.last_fabric_dev = 1; - } else { - lcl.last_fabric_dev = 0; - } - (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl); - } else { - isp_prt(isp, ISP_LOGDEBUG0, - "PortID 0x%x doesn't support FC4 type 0x%x", - portid, ftype); - } - if (first_portid == portid) { - fcp->isp_loopstate = LOOP_FSCAN_DONE; - FC_SCRATCH_RELEASE(isp); - return (0); - } - if (portid == last_portid) { - if (last_port_same++ > 20) { - isp_prt(isp, ISP_LOGWARN, - "tangled fabric database detected"); - break; - } - } else { - last_port_same = 0 ; - last_portid = portid; - } + if (pt->ctp_status && pt->ctp_status != RQCS_DATA_UNDERRUN) { + isp_prt(isp, ISP_LOGWARN, "CT Passthrough returned 0x%x", + pt->ctp_status); + return (-1); } - FC_SCRATCH_RELEASE(isp); - if (hicap >= GA_NXT_MAX) { - isp_prt(isp, ISP_LOGWARN, "fabric too big (> %d)", GA_NXT_MAX); + MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN + 16); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "CT response", GIDLEN+16, &scp[IGPOFF]); } - fcp->isp_loopstate = LOOP_FSCAN_DONE; return (0); } -#else -#define GIDLEN ((ISP2100_SCRLEN >> 1) + 16) -#define NGENT ((GIDLEN - 16) >> 2) - -#define IGPOFF (ISP2100_SCRLEN - GIDLEN) -#define GXOFF (256) -static int -isp_scan_fabric(struct ispsoftc *isp, int ftype) +int +isp_scan_fabric(struct ispsoftc *isp) { fcparam *fcp = FCPARAM(isp); - mbreg_t mbs; - int i; - sns_gid_ft_req_t *rq; + u_int32_t portid; + u_int16_t handle, oldhandle; + int portidx, portlim, r; sns_gid_ft_rsp_t *rs0, *rs1; - if (fcp->isp_onfabric == 0) { + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Scan Fabric"); + if (fcp->isp_fwstate != FW_READY || + fcp->isp_loopstate < LOOP_LSCAN_DONE) { + return (-1); + } + if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) { + return (0); + } + if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) { fcp->isp_loopstate = LOOP_FSCAN_DONE; + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "FC Scan Fabric Done (no fabric)"); return (0); } FC_SCRATCH_ACQUIRE(isp); fcp->isp_loopstate = LOOP_SCANNING_FABRIC; - rq = (sns_gid_ft_req_t *)fcp->tport; - MEMZERO((void *) rq, SNS_GID_FT_REQ_SIZE); - rq->snscb_rblen = GIDLEN >> 1; - rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+IGPOFF); - rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+IGPOFF); - rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+IGPOFF); - rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+IGPOFF); - rq->snscb_sblen = 6; - rq->snscb_cmd = SNS_GID_FT; - rq->snscb_mword_div_2 = NGENT; - rq->snscb_fc4_type = ftype; - isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); + if (IS_24XX(isp)) { + r = isp_gid_ft_ct_passthru(isp); + } else { + r = isp_gid_ft_sns(isp); + } - /* - * Leave 4 and 5 alone - */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; - } + if (r > 0) { + fcp->isp_loopstate = LOOP_FSCAN_DONE; FC_SCRATCH_RELEASE(isp); - return (-1); + return (0); + } else if (r < 0) { + fcp->isp_loopstate = LOOP_PDB_RCVD; /* try again */ + FC_SCRATCH_RELEASE(isp); + return (0); } if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { FC_SCRATCH_RELEASE(isp); return (-1); } + MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN); - rs1 = (sns_gid_ft_rsp_t *) fcp->tport; rs0 = (sns_gid_ft_rsp_t *) ((u_int8_t *)fcp->isp_scratch+IGPOFF); + rs1 = (sns_gid_ft_rsp_t *) ((u_int8_t *)fcp->isp_scratch+OGPOFF); isp_get_gid_ft_response(isp, rs0, rs1, NGENT); - if (rs1->snscb_cthdr.ct_response != FS_ACC) { + if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) { int level; if (rs1->snscb_cthdr.ct_reason == 9 && - rs1->snscb_cthdr.ct_explanation == 7) - level = ISP_LOGDEBUG0; - else + rs1->snscb_cthdr.ct_explanation == 7) { + level = ISP_LOGSANCFG|ISP_LOGDEBUG0; + } else { level = ISP_LOGWARN; - isp_prt(isp, level, swrej, "GID_FT", - rs1->snscb_cthdr.ct_reason, - rs1->snscb_cthdr.ct_explanation, 0); + } + isp_prt(isp, level, "Fabric Nameserver rejected GID_FT " + "(Reason=0x%x Expl=0x%x)", rs1->snscb_cthdr.ct_reason, + rs1->snscb_cthdr.ct_explanation); FC_SCRATCH_RELEASE(isp); fcp->isp_loopstate = LOOP_FSCAN_DONE; return (0); } + /* - * Okay, we now have a list of Port IDs for this class of device. - * Go through the list and for each one get the WWPN/WWNN for it - * and tell the outer layers about it. The outer layer needs to - * know: Port ID, WWNN, WWPN, FC4 type, and (possibly) port type. + * If we get this far, we certainly still have the fabric controller. + */ + fcp->portdb[FL_ID].state = FC_PORTDB_STATE_PENDING_VALID; + + /* + * Prime the handle we will start using. + */ + oldhandle = NIL_HANDLE; + + /* + * Okay, we now have a list of Port IDs for all FC4 SCSI devices + * that the Fabric Name server knows about. Go through the list + * and remove duplicate port ids. + */ + + portlim = 0; + portidx = 0; + for (portidx = 0; portidx < NGENT-1; portidx++) { + if (rs1->snscb_ports[portidx].control & 0x80) { + break; + } + } + + /* + * If we're not at the last entry, our list wasn't big enough. + */ + if ((rs1->snscb_ports[portidx].control & 0x80) == 0) { + isp_prt(isp, ISP_LOGWARN, + "fabric too big for scratch area: increase ISP2100_SCRLEN"); + } + portlim = portidx + 1; + isp_prt(isp, ISP_LOGSANCFG, + "got %d ports back from name server", portlim); + + for (portidx = 0; portidx < portlim; portidx++) { + int npidx; + + portid = + ((rs1->snscb_ports[portidx].portid[0]) << 16) | + ((rs1->snscb_ports[portidx].portid[1]) << 8) | + ((rs1->snscb_ports[portidx].portid[2])); + + for (npidx = portidx + 1; npidx < portlim; npidx++) { + u_int32_t new_portid = + ((rs1->snscb_ports[npidx].portid[0]) << 16) | + ((rs1->snscb_ports[npidx].portid[1]) << 8) | + ((rs1->snscb_ports[npidx].portid[2])); + if (new_portid == portid) { + break; + } + } + + if (npidx < portlim) { + rs1->snscb_ports[npidx].portid[0] = 0; + rs1->snscb_ports[npidx].portid[1] = 0; + rs1->snscb_ports[npidx].portid[2] = 0; + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "removing duplicate PortID 0x%x entry from list", + portid); + } + } + + /* + * Okay, we now have a list of Port IDs for all FC4 SCSI devices + * that the Fabric Name server knows about. + * + * For each entry on this list go through our port database looking + * for probational entries- if we find one, then an old entry is + * is maybe still this one. We get some information to find out. * - * The lportdb structure is adequate for this. + * Otherwise, it's a new fabric device, and we log into it + * (unconditionally). After searching the entire database + * again to make sure that we never ever ever ever have more + * than one entry that has the same PortID or the same + * WWNN/WWPN duple, we enter the device into our database. */ - i = -1; - do { - sns_gxn_id_req_t grqbuf, *gq = &grqbuf; - sns_gxn_id_rsp_t *gs0, grsbuf, *gs1 = &grsbuf; - struct lportdb lcl; -#if 0 - sns_gff_id_rsp_t *fs0, ffsbuf, *fs1 = &ffsbuf; -#endif - i++; - MEMZERO(&lcl, sizeof (lcl)); - lcl.fc4_type = ftype; - lcl.portid = - (((u_int32_t) rs1->snscb_ports[i].portid[0]) << 16) | - (((u_int32_t) rs1->snscb_ports[i].portid[1]) << 8) | - (((u_int32_t) rs1->snscb_ports[i].portid[2])); - - MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t)); - gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1; - gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF); - gq->snscb_sblen = 6; - gq->snscb_cmd = SNS_GPN_ID; - gq->snscb_portid = lcl.portid; - isp_put_gxn_id_request(isp, gq, - (sns_gxn_id_req_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); + for (portidx = 0; portidx < portlim; portidx++) { + fcportdb_t *lp; + isp_pdb_t pdb; + u_int64_t wwnn, wwpn; + int dbidx, nr; + + portid = + ((rs1->snscb_ports[portidx].portid[0]) << 16) | + ((rs1->snscb_ports[portidx].portid[1]) << 8) | + ((rs1->snscb_ports[portidx].portid[2])); + + if (portid == 0) { + isp_prt(isp, ISP_LOGSANCFG, + "skipping null PortID at idx %d", portidx); + continue; + } + /* - * Leave 4 and 5 alone + * Skip ourselves... */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; - } - FC_SCRATCH_RELEASE(isp); - return (-1); + if (portid == fcp->isp_portid) { + isp_prt(isp, ISP_LOGSANCFG, + "skip ourselves @ PortID 0x%06x", portid); + continue; } - if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { - FC_SCRATCH_RELEASE(isp); - return (-1); + isp_prt(isp, ISP_LOGSANCFG, + "Checking Fabric Port 0x%06x", portid); + + /* + * We now search our Port Database for any + * probational entries with this PortID. We don't + * look for zombies here- only probational + * entries (we've already logged out of zombies). + */ + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + lp = &fcp->portdb[dbidx]; + + if (lp->state != FC_PORTDB_STATE_PROBATIONAL) { + continue; + } + if (lp->portid == portid) { + break; + } } - MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE); - gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF); - isp_get_gxn_id_response(isp, gs0, gs1); - if (gs1->snscb_cthdr.ct_response != FS_ACC) { - isp_prt(isp, ISP_LOGWARN, swrej, "GPN_ID", - gs1->snscb_cthdr.ct_reason, - gs1->snscb_cthdr.ct_explanation, lcl.portid); + + /* + * We found a probational entry with this Port ID. + */ + if (dbidx < MAX_FC_TARG) { + int handle_changed = 0; + + lp = &fcp->portdb[dbidx]; + + /* + * See if we're still logged into it. + * + * If we aren't, mark it as a dead device and + * leave the new portid in the database entry + * for somebody further along to decide what to + * do (policy choice). + * + * If we are, check to see if it's the same + * device still (it should be). If for some + * reason it isn't, mark it as a changed device + * and leave the new portid and role in the + * database entry for somebody further along to + * decide what to do (policy choice). + * + */ + + r = isp_getpdb(isp, lp->handle, &pdb, 0); if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { FC_SCRATCH_RELEASE(isp); + ISP_MARK_PORTDB(isp, 1); return (-1); } + if (r != 0) { + lp->new_portid = portid; + lp->state = FC_PORTDB_STATE_DEAD; + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "Fabric Port 0x%06x considered dead", + portid); + continue; + } + + + /* + * Check to make sure that handle, portid, WWPN and + * WWNN agree. If they don't, then the association + * between this PortID and the stated handle has been + * broken by the firmware. + */ + MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); + if (pdb.handle != lp->handle || + pdb.portid != portid || + wwpn != lp->port_wwn || + wwnn != lp->node_wwn) { + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + fconf, dbidx, pdb.handle, pdb.portid, + (u_int32_t) (wwnn >> 32), (u_int32_t) wwnn, + (u_int32_t) (wwpn >> 32), (u_int32_t) wwpn, + lp->handle, portid, + (u_int32_t) (lp->node_wwn >> 32), + (u_int32_t) lp->node_wwn, + (u_int32_t) (lp->port_wwn >> 32), + (u_int32_t) lp->port_wwn); + /* + * Try to re-login to this device using a + * new handle. If that fails, mark it dead. + * + * isp_login_device will check for handle and + * portid consistency after re-login. + * + */ + if (isp_login_device(isp, portid, &pdb, + &oldhandle)) { + lp->new_portid = portid; + lp->state = FC_PORTDB_STATE_DEAD; + if (fcp->isp_loopstate != + LOOP_SCANNING_FABRIC) { + FC_SCRATCH_RELEASE(isp); + ISP_MARK_PORTDB(isp, 1); + return (-1); + } + continue; + } + MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); + if (wwpn != lp->port_wwn || + wwnn != lp->node_wwn) { + isp_prt(isp, ISP_LOGWARN, "changed WWN" + " after relogin"); + lp->new_portid = portid; + lp->state = FC_PORTDB_STATE_DEAD; + continue; + } + + lp->handle = pdb.handle; + handle_changed++; + } + + nr = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + + /* + * Check to see whether the portid and roles have + * stayed the same. If they have stayed the same, + * we believe that this is the same device and it + * hasn't become disconnected and reconnected, so + * mark it as pending valid. + * + * If they aren't the same, mark the device as a + * changed device and save the new port id and role + * and let somebody else decide. + */ + + lp->new_portid = portid; + lp->new_roles = nr; + if (pdb.portid != lp->portid || nr != lp->roles || + handle_changed) { + isp_prt(isp, ISP_LOGSANCFG, + "Fabric Port 0x%06x changed", portid); + lp->state = FC_PORTDB_STATE_CHANGED; + } else { + isp_prt(isp, ISP_LOGSANCFG, + "Fabric Port 0x%06x Now Pending Valid", + portid); + lp->state = FC_PORTDB_STATE_PENDING_VALID; + } continue; } - lcl.port_wwn = - (((u_int64_t)gs1->snscb_wwn[0]) << 56) | - (((u_int64_t)gs1->snscb_wwn[1]) << 48) | - (((u_int64_t)gs1->snscb_wwn[2]) << 40) | - (((u_int64_t)gs1->snscb_wwn[3]) << 32) | - (((u_int64_t)gs1->snscb_wwn[4]) << 24) | - (((u_int64_t)gs1->snscb_wwn[5]) << 16) | - (((u_int64_t)gs1->snscb_wwn[6]) << 8) | - (((u_int64_t)gs1->snscb_wwn[7])); - - MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t)); - gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1; - gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF); - gq->snscb_sblen = 6; - gq->snscb_cmd = SNS_GNN_ID; - gq->snscb_portid = lcl.portid; - isp_put_gxn_id_request(isp, gq, - (sns_gxn_id_req_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); + /* - * Leave 4 and 5 alone + * Ah- a new entry. Search the database again for all non-NIL + * entries to make sure we never ever make a new database entry + * with the same port id. While we're at it, mark where the + * last free entry was. */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; + + dbidx = MAX_FC_TARG; + for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { + if (lp >= &fcp->portdb[FL_ID] && + lp <= &fcp->portdb[SNS_ID]) { + continue; } - FC_SCRATCH_RELEASE(isp); - return (-1); - } - if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { - FC_SCRATCH_RELEASE(isp); - return (-1); - } - MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE); - gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF); - isp_get_gxn_id_response(isp, gs0, gs1); - if (gs1->snscb_cthdr.ct_response != FS_ACC) { - isp_prt(isp, ISP_LOGWARN, swrej, "GNN_ID", - gs1->snscb_cthdr.ct_reason, - gs1->snscb_cthdr.ct_explanation, lcl.portid); - if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { - FC_SCRATCH_RELEASE(isp); - return (-1); + if (lp->state == FC_PORTDB_STATE_NIL) { + if (dbidx == MAX_FC_TARG) { + dbidx = lp - fcp->portdb; + } + continue; + } + if (lp->state == FC_PORTDB_STATE_ZOMBIE) { + continue; } + if (lp->portid == portid) { + break; + } + } + + if (lp < &fcp->portdb[MAX_FC_TARG]) { + isp_prt(isp, ISP_LOGWARN, + "PortID 0x%06x already at %d handle %d state %d", + portid, dbidx, lp->handle, lp->state); continue; } - lcl.node_wwn = - (((u_int64_t)gs1->snscb_wwn[0]) << 56) | - (((u_int64_t)gs1->snscb_wwn[1]) << 48) | - (((u_int64_t)gs1->snscb_wwn[2]) << 40) | - (((u_int64_t)gs1->snscb_wwn[3]) << 32) | - (((u_int64_t)gs1->snscb_wwn[4]) << 24) | - (((u_int64_t)gs1->snscb_wwn[5]) << 16) | - (((u_int64_t)gs1->snscb_wwn[6]) << 8) | - (((u_int64_t)gs1->snscb_wwn[7])); /* - * The QLogic f/w is bouncing this with a parameter error. + * We should have the index of the first free entry seen. */ -#if 0 + if (dbidx == MAX_FC_TARG) { + isp_prt(isp, ISP_LOGERR, + "port database too small to login PortID 0x%06x" + "- increase MAX_FC_TARG", portid); + continue; + } + /* - * Try and get FC4 Features (FC-GS-3 only). - * We can use the sns_gxn_id_req_t for this request. + * Otherwise, point to our new home. */ - MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t)); - gq->snscb_rblen = SNS_GFF_ID_RESP_SIZE >> 1; - gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF); - gq->snscb_sblen = 6; - gq->snscb_cmd = SNS_GFF_ID; - gq->snscb_portid = lcl.portid; - isp_put_gxn_id_request(isp, gq, - (sns_gxn_id_req_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); + lp = &fcp->portdb[dbidx]; + /* - * Leave 4 and 5 alone + * Try to see if we are logged into this device, + * and maybe log into it. + * + * isp_login_device will check for handle and + * portid consistency after login. */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; - } - FC_SCRATCH_RELEASE(isp); - return (-1); - } - if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { - FC_SCRATCH_RELEASE(isp); - return (-1); - } - MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GFF_ID_RESP_SIZE); - fs0 = (sns_gff_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF); - isp_get_gff_id_response(isp, fs0, fs1); - if (fs1->snscb_cthdr.ct_response != FS_ACC) { - isp_prt(isp, /* ISP_LOGDEBUG0 */ ISP_LOGWARN, - swrej, "GFF_ID", - fs1->snscb_cthdr.ct_reason, - fs1->snscb_cthdr.ct_explanation, lcl.portid); + if (isp_login_device(isp, portid, &pdb, &oldhandle)) { if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { FC_SCRATCH_RELEASE(isp); + ISP_MARK_PORTDB(isp, 1); return (-1); } - } else { - int index = (ftype >> 3); - int bshft = (ftype & 0x7) * 4; - int fc4_fval = - (fs1->snscb_fc4_features[index] >> bshft) & 0xf; - if (fc4_fval & 0x1) { - lcl.roles |= - (SVC3_INI_ROLE >> SVC3_ROLE_SHIFT); + continue; + } + + handle = pdb.handle; + MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); + nr = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + + /* + * And go through the database *one* more time to make sure + * that we do not make more than one entry that has the same + * WWNN/WWPN duple + */ + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + if (dbidx >= FL_ID && dbidx <= SNS_ID) { + continue; + } + if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) { + continue; } - if (fc4_fval & 0x2) { - lcl.roles |= - (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); + if (fcp->portdb[dbidx].node_wwn == wwnn && + fcp->portdb[dbidx].port_wwn == wwpn) { + break; } } -#endif + + if (dbidx == MAX_FC_TARG) { + MEMZERO(lp, sizeof (fcportdb_t)); + lp->handle = handle; + lp->node_wwn = wwnn; + lp->port_wwn = wwpn; + lp->new_portid = portid; + lp->new_roles = nr; + lp->state = FC_PORTDB_STATE_NEW; + isp_prt(isp, ISP_LOGSANCFG, + "Fabric Port 0x%06x is New Entry", portid); + continue; + } + + if (fcp->portdb[dbidx].state != FC_PORTDB_STATE_ZOMBIE) { + isp_prt(isp, ISP_LOGWARN, + "PortID 0x%x 0x%08x%08x/0x%08x%08x %ld already at " + "idx %d, state 0x%x", portid, + (u_int32_t) (wwnn >> 32), (u_int32_t) wwnn, + (u_int32_t) (wwpn >> 32), (u_int32_t) wwpn, + (long) (lp - fcp->portdb), dbidx, + fcp->portdb[dbidx].state); + continue; + } /* - * If we really want to know what kind of port type this is, - * we have to run another CT command. Otherwise, we'll leave - * it as undefined. - * - lcl.port_type = 0; + * We found a zombie entry that matches us. + * Revive it. We know that WWN and WWPN + * are the same. For fabric devices, we + * don't care that handle is different + * as we assign that. If role or portid + * are different, it maybe a changed device. */ - if (rs1->snscb_ports[i].control & 0x80) { - lcl.last_fabric_dev = 1; + lp = &fcp->portdb[dbidx]; + lp->handle = handle; + lp->new_portid = portid; + lp->new_roles = nr; + if (lp->portid != portid || lp->roles != nr) { + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "Zombie Fabric Port 0x%06x Now Changed", portid); + lp->state = FC_PORTDB_STATE_CHANGED; } else { - lcl.last_fabric_dev = 0; + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "Zombie Fabric Port 0x%06x Now Pending Valid", + portid); + lp->state = FC_PORTDB_STATE_PENDING_VALID; } - (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl); + } - } while ((rs1->snscb_ports[i].control & 0x80) == 0 && i < NGENT-1); + FC_SCRATCH_RELEASE(isp); + if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { + ISP_MARK_PORTDB(isp, 1); + return (-1); + } + fcp->isp_loopstate = LOOP_FSCAN_DONE; + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Scan Fabric Done"); + return (0); +} + +/* + * Find an unused handle and try and use to login to a port. + */ +int +isp_login_device(struct ispsoftc *isp, u_int32_t portid, isp_pdb_t *p, u_int16_t *ohp) +{ + int lim, i, r; + u_int16_t handle; + + if (FCPARAM(isp)->isp_2klogin) { + lim = NPH_MAX_2K; + } else { + lim = NPH_MAX; + } + + handle = isp_nxt_handle(isp, *ohp); + for (i = 0; i < lim; i++) { + /* + * See if we're still logged into something with + * this handle and that something agrees with this + * port id. + */ + r = isp_getpdb(isp, handle, p, 0); + if (r == 0 && p->portid != portid) { + (void) isp_plogx(isp, handle, portid, + PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT, 1); + } else if (r == 0) { + break; + } + if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) { + return (-1); + } + /* + * Now try and log into the device + */ + r = isp_plogx(isp, handle, portid, PLOGX_FLG_CMD_PLOGI, 1); + if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) { + return (-1); + } + if (r == 0) { + *ohp = handle; + break; + } else if ((r & 0xffff) == MBOX_PORT_ID_USED) { + handle = r >> 16; + break; + } else if (r != MBOX_LOOP_ID_USED) { + i = lim; + break; + } else { + *ohp = handle; + handle = isp_nxt_handle(isp, *ohp); + } + } + + if (i == lim) { + isp_prt(isp, ISP_LOGWARN, "PLOGI 0x%06x failed", portid); + return (-1); + } /* - * If we're not at the last entry, our list isn't big enough. + * If we successfully logged into it, get the PDB for it + * so we can crosscheck that it is still what we think it + * is and that we also have the role it plays */ - if ((rs1->snscb_ports[i].control & 0x80) == 0) { - isp_prt(isp, ISP_LOGWARN, "fabric too big for scratch area"); + r = isp_getpdb(isp, handle, p, 0); + if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) { + return (-1); + } + if (r != 0) { + isp_prt(isp, ISP_LOGERR, "new device 0x%06x@0x%x disappeared", + portid, handle); + return (-1); } - FC_SCRATCH_RELEASE(isp); - fcp->isp_loopstate = LOOP_FSCAN_DONE; + if (p->handle != handle || p->portid != portid) { + isp_prt(isp, ISP_LOGERR, + "new device 0x%06x@0x%x changed (0x%06x@0x%0x)", + portid, handle, p->portid, p->handle); + return (-1); + } return (0); } -#endif -static void +int isp_register_fc4_type(struct ispsoftc *isp) { fcparam *fcp = isp->isp_param; @@ -2928,9 +3839,6 @@ isp_register_fc4_type(struct ispsoftc *isp) reqp->snscb_data[4] = fcp->isp_portid & 0xffff; reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff; reqp->snscb_data[6] = (1 << FC4_SCSI); -#if 0 - reqp->snscb_data[6] |= (1 << FC4_IP); /* ISO/IEC 8802-2 LLC/SNAP */ -#endif FC_SCRATCH_ACQUIRE(isp); isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch); MEMZERO(&mbs, sizeof (mbs)); @@ -2938,18 +3846,167 @@ isp_register_fc4_type(struct ispsoftc *isp) mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); - /* - * Leave 4 and 5 alone - */ mbs.param[6] = DMA_WD3(fcp->isp_scdma); mbs.param[7] = DMA_WD2(fcp->isp_scdma); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + mbs.timeout = 10000000; + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_RFT_ID_REQ_SIZE); + isp_mboxcmd(isp, &mbs); FC_SCRATCH_RELEASE(isp); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded"); + return (0); + } else { + return (-1); } } +int +isp_register_fc4_type_24xx(struct ispsoftc *isp) +{ + mbreg_t mbs; + fcparam *fcp = FCPARAM(isp); + union { + isp_ct_pt_t plocal; + rft_id_t clocal; + u_int8_t q[QENTRY_LEN]; + } un; + isp_ct_pt_t *pt; + ct_hdr_t *ct; + rft_id_t *rp; + u_int8_t *scp = fcp->isp_scratch; + + FC_SCRATCH_ACQUIRE(isp); + /* + * Build a Passthrough IOCB in memory. + */ + MEMZERO(un.q, QENTRY_LEN); + pt = &un.plocal; + pt->ctp_header.rqs_entry_count = 1; + pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU; + pt->ctp_handle = 0xffffffff; + pt->ctp_nphdl = NPH_SNS_ID; + pt->ctp_cmd_cnt = 1; + pt->ctp_time = 1; + pt->ctp_rsp_cnt = 1; + pt->ctp_rsp_bcnt = sizeof (ct_hdr_t); + pt->ctp_cmd_bcnt = sizeof (rft_id_t); + pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF); + pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF); + pt->ctp_dataseg[0].ds_count = sizeof (rft_id_t); + pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t); + isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]); + + /* + * Build the CT header and command in memory. + * + * Note that the CT header has to end up as Big Endian format in memory. + */ + MEMZERO(&un.clocal, sizeof (un.clocal)); + ct = &un.clocal.rftid_hdr; + ct->ct_revision = CT_REVISION; + ct->ct_fcs_type = CT_FC_TYPE_FC; + ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; + ct->ct_cmd_resp = SNS_RFT_ID; + ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2; + rp = &un.clocal; + rp->rftid_portid[0] = fcp->isp_portid >> 16; + rp->rftid_portid[1] = fcp->isp_portid >> 8; + rp->rftid_portid[2] = fcp->isp_portid; + rp->rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f); + isp_put_rft_id(isp, rp, (rft_id_t *) &scp[XTXOFF]); + + MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t)); + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64; + mbs.param[1] = QENTRY_LEN; + mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF); + mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF); + mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF); + mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF); + mbs.timeout = 500000; + mbs.logval = MBLOGALL; + MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + FC_SCRATCH_RELEASE(isp); + return (-1); + } + MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN); + pt = &un.plocal; + isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt); + } + if (pt->ctp_status) { + FC_SCRATCH_RELEASE(isp); + isp_prt(isp, ISP_LOGWARN, "CT Passthrough returned 0x%x", + pt->ctp_status); + return (-1); + } + + isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct); + FC_SCRATCH_RELEASE(isp); + + if (ct->ct_cmd_resp == LS_RJT) { + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "Register FC4 Type rejected"); + return (-1); + } else if (ct->ct_cmd_resp == LS_ACC) { + isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, + "Register FC4 Type accepted"); + return(0); + } else { + isp_prt(isp, ISP_LOGWARN, + "Register FC4 Type: 0x%x", ct->ct_cmd_resp); + return (-1); + } +} + +u_int16_t +isp_nxt_handle(struct ispsoftc *isp, u_int16_t handle) +{ + int i; + if (handle == NIL_HANDLE) { + if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) { + handle = 0; + } else { + handle = SNS_ID+1; + } + } else { + handle += 1; + if (handle >= FL_ID && handle <= SNS_ID) { + handle = SNS_ID+1; + } + if (handle >= NPH_RESERVED && handle <= NPH_FL_ID) { + handle = NPH_FL_ID+1; + } + if (FCPARAM(isp)->isp_2klogin) { + if (handle == NPH_MAX_2K) { + handle = 0; + } + } else { + if (handle == NPH_MAX) { + handle = 0; + } + } + } + if (handle == FCPARAM(isp)->isp_loopid) { + return (isp_nxt_handle(isp, handle)); + } + for (i = 0; i < MAX_FC_TARG; i++) { + if (FCPARAM(isp)->portdb[i].state == FC_PORTDB_STATE_NIL) { + continue; + } + if (FCPARAM(isp)->portdb[i].handle == handle) { + return (isp_nxt_handle(isp, handle)); + } + } + return (handle); +} + /* * Start a command. Locking is assumed done in the caller. */ @@ -2958,10 +4015,12 @@ int isp_start(XS_T *xs) { struct ispsoftc *isp; - u_int16_t nxti, optr, handle; + u_int32_t nxti, optr, handle; u_int8_t local[QENTRY_LEN]; ispreq_t *reqp, *qep; - int target, i; + void *cdbp; + u_int16_t *tptr; + int target, i, hdlidx = 0; XS_INITERR(xs); isp = XS_ISP(xs); @@ -3000,201 +4059,54 @@ isp_start(XS_T *xs) } /* - * Check to see whether we have good firmware state still or - * need to refresh our port database for this target. + * Translate the target to device handle as appropriate, checking + * for correct device state as well. */ target = XS_TGT(xs); if (IS_FC(isp)) { fcparam *fcp = isp->isp_param; - struct lportdb *lp; -#ifdef HANDLE_LOOPSTATE_IN_OUTER_LAYERS - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_READY) { - return (CMD_RQLATER); - } - - /* - * If we're not on a Fabric, we can't have a target - * above FL_PORT_ID-1. - * - * If we're on a fabric and *not* connected as an F-port, - * we can't have a target less than FC_SNS_ID+1. This - * keeps us from having to sort out the difference between - * local public loop devices and those which we might get - * from a switch's database. - */ - if (fcp->isp_onfabric == 0) { - if (target >= FL_PORT_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - } else { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - /* - * We used to exclude having local loop ports - * at the same time that we have fabric ports. - * That is, we used to exclude having ports - * at < FL_PORT_ID if we're FL-port. - * - * That's wrong. The only thing that could be - * dicey is if the switch you're connected to - * has these local loop ports appear on the - * fabric and we somehow attach them twice. - */ - } -#else - /* - * Check for f/w being in ready state. If the f/w - * isn't in ready state, then we don't know our - * loop ID and the f/w hasn't completed logging - * into all targets on the loop. If this is the - * case, then bounce the command. We pretend this is - * a SELECTION TIMEOUT error if we've never gone to - * FW_READY state at all- in this case we may not - * be hooked to a loop at all and we shouldn't hang - * the machine for this. Otherwise, defer this command - * until later. - */ - if (fcp->isp_fwstate != FW_READY) { - /* - * Give ourselves at most a 250ms delay. - */ - if (isp_fclink_test(isp, 250000)) { - XS_SETERR(xs, HBA_SELTIMEOUT); - if (fcp->loop_seen_once) { - return (CMD_RQLATER); - } else { - return (CMD_COMPLETE); - } - } - } /* - * If we're not on a Fabric, we can't have a target - * above FL_PORT_ID-1. - * - * If we're on a fabric and *not* connected as an F-port, - * we can't have a target less than FC_SNS_ID+1. This - * keeps us from having to sort out the difference between - * local public loop devices and those which we might get - * from a switch's database. + * Try again later. */ - if (fcp->isp_onfabric == 0) { - if (target >= FL_PORT_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - } else { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - if (fcp->isp_topo != TOPO_F_PORT && - target < FL_PORT_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - } - - /* - * If our loop state is such that we haven't yet received - * a "Port Database Changed" notification (after a LIP or - * a Loop Reset or firmware initialization), then defer - * sending commands for a little while, but only if we've - * seen a valid loop at one point (otherwise we can get - * stuck at initialization time). - */ - if (fcp->isp_loopstate < LOOP_PDB_RCVD) { - XS_SETERR(xs, HBA_SELTIMEOUT); - if (fcp->loop_seen_once) { - return (CMD_RQLATER); - } else { - return (CMD_COMPLETE); - } - } - - /* - * If we're in the middle of loop or fabric scanning - * or merging the port databases, retry this command later. - */ - if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC || - fcp->isp_loopstate == LOOP_SCANNING_LOOP || - fcp->isp_loopstate == LOOP_SYNCING_PDB) { + if (fcp->isp_fwstate != FW_READY || + fcp->isp_loopstate != LOOP_READY) { return (CMD_RQLATER); } - /* - * If our loop state is now such that we've just now - * received a Port Database Change notification, then - * we have to go off and (re)scan the fabric. We back - * out and try again later if this doesn't work. - */ - if (fcp->isp_loopstate == LOOP_PDB_RCVD && fcp->isp_onfabric) { - if (isp_scan_fabric(isp, FC4_SCSI)) { - return (CMD_RQLATER); - } - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate < LOOP_FSCAN_DONE) { - return (CMD_RQLATER); - } - } - - /* - * If our loop state is now such that we've just now - * received a Port Database Change notification, then - * we have to go off and (re)synchronize our port - * database. - */ - if (fcp->isp_loopstate < LOOP_READY) { - if (isp_pdb_sync(isp)) { - return (CMD_RQLATER); - } - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_READY) { - return (CMD_RQLATER); - } + if (XS_TGT(xs) >= MAX_FC_TARG) { + XS_SETERR(xs, HBA_SELTIMEOUT); + return (CMD_COMPLETE); } - /* - * XXX: Here's were we would cancel any loop_dead flag - * XXX: also cancel in dead_loop timeout that's running - */ -#endif - - /* - * Now check whether we should even think about pursuing this. - */ - lp = &fcp->portdb[target]; - if (lp->valid == 0) { + hdlidx = fcp->isp_ini_map[XS_TGT(xs)] - 1; + isp_prt(isp, ISP_LOGDEBUG1, "XS_TGT(xs)=%d- hdlidx value %d", + XS_TGT(xs), hdlidx); + if (hdlidx < 0 || hdlidx >= MAX_FC_TARG) { XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); } - if ((lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT)) == 0) { - isp_prt(isp, ISP_LOGDEBUG2, - "Target %d does not have target service", target); + if (fcp->portdb[hdlidx].state == FC_PORTDB_STATE_ZOMBIE) { + return (CMD_RQLATER); + } + if (fcp->portdb[hdlidx].state != FC_PORTDB_STATE_VALID) { XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); } - /* - * Now turn target into what the actual Loop ID is. - */ - target = lp->loopid; - xs->sc_link->node_wwn = lp->node_wwn; - xs->sc_link->port_wwn = lp->port_wwn; - + target = fcp->portdb[hdlidx].handle; + xs->sc_link->node_wwn = fcp->portdb[hdlidx].node_wwn; + xs->sc_link->port_wwn = fcp->portdb[hdlidx].port_wwn; } /* - * Next check to see if any HBA or Device - * parameters need to be updated. + * Next check to see if any HBA or Device parameters need to be updated. */ if (isp->isp_update != 0) { isp_update(isp); } + start_again: + if (isp_getrqentry(isp, &nxti, &optr, (void *)&qep)) { isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow"); XS_SETERR(xs, HBA_BOTCH); @@ -3208,34 +4120,40 @@ isp_start(XS_T *xs) */ reqp = (ispreq_t *) local; if (isp->isp_sendmarker) { - u_int8_t n = (IS_DUALBUS(isp)? 2: 1); - /* - * Check ports to send markers for... - */ - for (i = 0; i < n; i++) { - if ((isp->isp_sendmarker & (1 << i)) == 0) { - continue; - } - 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_put_request(isp, reqp, qep); + if (IS_24XX(isp)) { + isp_marker_24xx_t *m = (isp_marker_24xx_t *) qep; + MEMZERO(m, QENTRY_LEN); + m->mrk_header.rqs_entry_count = 1; + m->mrk_header.rqs_entry_type = RQSTYPE_MARKER; + m->mrk_modifier = SYNC_ALL; + isp_put_marker_24xx(isp, m, (isp_marker_24xx_t *)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); - return (CMD_EAGAIN); + isp->isp_sendmarker = 0; + goto start_again; + } else { + for (i = 0; i < (IS_DUALBUS(isp)? 2: 1); i++) { + isp_marker_t *m = (isp_marker_t *) qep; + if ((isp->isp_sendmarker & (1 << i)) == 0) { + continue; + } + MEMZERO(m, QENTRY_LEN); + m->mrk_header.rqs_entry_count = 1; + m->mrk_header.rqs_entry_type = RQSTYPE_MARKER; + m->mrk_target = (i << 7); /* bus # */ + m->mrk_modifier = SYNC_ALL; + isp_put_marker(isp, m, (isp_marker_t *) qep); + ISP_ADD_REQUEST(isp, nxti); + isp->isp_sendmarker &= ~(1 << i); + goto start_again; } } } MEMZERO((void *)reqp, QENTRY_LEN); reqp->req_header.rqs_entry_count = 1; - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS; + } else if (IS_FC(isp)) { reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS; } else { if (XS_CDBLEN(xs) > 12) @@ -3245,7 +4163,26 @@ isp_start(XS_T *xs) } /* reqp->req_header.rqs_flags = 0; */ /* reqp->req_header.rqs_seqno = 0; */ - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + int ttype; + if (XS_TAG_P(xs)) { + ttype = XS_TAG_TYPE(xs); + } else { + if (XS_CDBP(xs)[0] == 0x3) { + ttype = REQFLAG_HTAG; + } else { + ttype = REQFLAG_STAG; + } + } + if (ttype == REQFLAG_OTAG) { + ttype = FCP_CMND_TASK_ATTR_ORDERED; + } else if (ttype == REQFLAG_HTAG) { + ttype = FCP_CMND_TASK_ATTR_HEAD; + } else { + ttype = FCP_CMND_TASK_ATTR_SIMPLE; + } + ((ispreqt7_t *)reqp)->req_task_attribute = ttype; + } else if (IS_FC(isp)) { /* * See comment in isp_intr */ @@ -3253,7 +4190,7 @@ isp_start(XS_T *xs) /* * Fibre Channel always requires some kind of tag. - * The QLogic drivers seem be happy not to use a tag, + * The Qlogic drivers seem be happy not to use a tag, * but this breaks for some devices (IBM drives). */ if (XS_TAG_P(xs)) { @@ -3276,21 +4213,45 @@ isp_start(XS_T *xs) reqp->req_flags = XS_TAG_TYPE(xs); } } - reqp->req_target = target | (XS_CHANNEL(xs) << 7); + cdbp = reqp->req_cdb; + tptr = &reqp->req_time; + if (IS_SCSI(isp)) { + reqp->req_target = target | (XS_CHANNEL(xs) << 7); reqp->req_lun_trn = XS_LUN(xs); reqp->req_cdblen = XS_CDBLEN(xs); + } else if (IS_24XX(isp)) { + fcportdb_t *lp; + + lp = &FCPARAM(isp)->portdb[hdlidx]; + ((ispreqt7_t *)reqp)->req_nphdl = target; + ((ispreqt7_t *)reqp)->req_tidlo = lp->portid; + ((ispreqt7_t *)reqp)->req_tidhi = lp->portid >> 16; + if (XS_LUN(xs) > 256) { + ((ispreqt7_t *)reqp)->req_lun[0] = XS_LUN(xs) >> 8; + ((ispreqt7_t *)reqp)->req_lun[0] |= 0x40; + } + ((ispreqt7_t *)reqp)->req_lun[1] = XS_LUN(xs); + cdbp = ((ispreqt7_t *)reqp)->req_cdb; + tptr = &((ispreqt7_t *)reqp)->req_time; + } else if (FCPARAM(isp)->isp_2klogin) { + ((ispreqt2e_t *)reqp)->req_target = target; + ((ispreqt2e_t *)reqp)->req_scclun = XS_LUN(xs); + } else if (FCPARAM(isp)->isp_sccfw) { + ((ispreqt2_t *)reqp)->req_target = target; + ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs); } else { - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) - ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs); - else - ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs); + ((ispreqt2_t *)reqp)->req_target = target; + ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs); } - MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); + MEMCPY(cdbp, XS_CDBP(xs), XS_CDBLEN(xs)); - reqp->req_time = XS_TIME(xs) / 1000; - if (reqp->req_time == 0 && XS_TIME(xs)) { - reqp->req_time = 1; + *tptr = XS_TIME(xs) / 1000; + if (*tptr == 0 && XS_TIME(xs)) { + *tptr = 1; + } + if (IS_24XX(isp) && *tptr > 0x1999) { + *tptr = 0x1999; } if (isp_save_xs(isp, xs, &handle)) { @@ -3298,11 +4259,12 @@ isp_start(XS_T *xs) XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } + /* Whew. Thankfully the same for type 7 requests */ 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. + * so that the Qlogic F/W understands what is being asked of it. */ i = ISP_DMASETUP(isp, xs, reqp, &nxti, optr); if (i != CMD_QUEUED) { @@ -3314,7 +4276,7 @@ isp_start(XS_T *xs) return (i); } XS_SETERR(xs, HBA_NOERROR); - isp_prt(isp, ISP_LOGDEBUG2, + isp_prt(isp, ISP_LOGDEBUG0, "START cmd for %d.%d.%d cmd 0x%x datalen %ld", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0], (long) XS_XFRLEN(xs)); @@ -3334,7 +4296,9 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) XS_T *xs; mbreg_t mbs; int bus, tgt; - u_int16_t handle; + u_int32_t handle; + + MEMZERO(&mbs, sizeof (mbs)); switch (ctl) { default: @@ -3345,22 +4309,26 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) /* * Issue a bus reset. */ - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_BUS_RESET; - if (IS_SCSI(isp)) { - mbs.param[1] = - ((sdparam *) isp->isp_param)->isp_bus_reset_delay; - if (mbs.param[1] < 2) + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGWARN, "RESET BUS NOT IMPLEMENTED"); + break; + } else if (IS_FC(isp)) { + mbs.param[1] = 10; + bus = 0; + } else { + mbs.param[1] = SDPARAM(isp)->isp_bus_reset_delay; + if (mbs.param[1] < 2) { mbs.param[1] = 2; + } bus = *((int *) arg); - if (IS_DUALBUS(isp)) + if (IS_DUALBUS(isp)) { mbs.param[2] = bus; - } else { - mbs.param[1] = 10; - bus = 0; + } } + mbs.param[0] = MBOX_BUS_RESET; isp->isp_sendmarker |= (1 << bus); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } @@ -3370,12 +4338,25 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) case ISPCTL_RESET_DEV: tgt = (*((int *) arg)) & 0xffff; - bus = (*((int *) arg)) >> 16; - MEMZERO(&mbs, sizeof (mbs)); + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGWARN, "RESET DEV NOT IMPLEMENTED"); + break; + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_2klogin) { + mbs.param[1] = tgt; + mbs.ibits = (1 << 10); + } else { + mbs.param[1] = (tgt << 8); + } + bus = 0; + } else { + bus = (*((int *) arg)) >> 16; + mbs.param[1] = (bus << 15) | (tgt << 8); + } mbs.param[0] = MBOX_ABORT_TARGET; - mbs.param[1] = (tgt << 8) | (bus << 15); mbs.param[2] = 3; /* 'delay', in seconds */ - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } @@ -3387,38 +4368,39 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) case ISPCTL_ABORT_CMD: xs = (XS_T *) arg; tgt = XS_TGT(xs); + handle = isp_find_handle(isp, xs); if (handle == 0) { isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort"); break; } - bus = XS_CHANNEL(xs); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_ABORT; - if (IS_FC(isp)) { - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - mbs.param[1] = tgt << 8; - mbs.param[4] = 0; - mbs.param[5] = 0; + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGWARN, "ABORT CMD NOT IMPLEMENTED"); + break; + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_sccfw) { + if (FCPARAM(isp)->isp_2klogin) { + mbs.param[1] = tgt; + } else { + mbs.param[1] = tgt << 8; + } mbs.param[6] = XS_LUN(xs); } else { mbs.param[1] = tgt << 8 | XS_LUN(xs); } } else { - mbs.param[1] = - (bus << 15) | (XS_TGT(xs) << 8) | XS_LUN(xs); + bus = XS_CHANNEL(xs); + mbs.param[1] = (bus << 15) | (tgt << 8) | XS_LUN(xs); } + mbs.param[0] = MBOX_ABORT; mbs.param[2] = handle; - isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_ERROR); - if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - return (0); + mbs.logval = MBLOGALL & ~MBOX_COMMAND_ERROR; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + break; } - /* - * XXX: Look for command in the REQUEST QUEUE. That is, - * XXX: It hasn't been picked up by firmware yet. - */ - break; + return (0); case ISPCTL_UPDATE_PARAMS: @@ -3428,7 +4410,10 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) case ISPCTL_FCLINK_TEST: if (IS_FC(isp)) { - int usdelay = (arg)? *((int *) arg) : 250000; + int usdelay = *((int *) arg); + if (usdelay == 0) { + usdelay = 250000; + } return (isp_fclink_test(isp, usdelay)); } break; @@ -3436,8 +4421,7 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) case ISPCTL_SCAN_FABRIC: if (IS_FC(isp)) { - int ftype = (arg)? *((int *) arg) : FC4_SCSI; - return (isp_scan_fabric(isp, ftype)); + return (isp_scan_fabric(isp)); } break; @@ -3457,28 +4441,64 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) case ISPCTL_SEND_LIP: - if (IS_FC(isp)) { - MEMZERO(&mbs, sizeof (mbs)); + if (IS_FC(isp) && !IS_24XX(isp)) { mbs.param[0] = MBOX_INIT_LIP; - isp_mboxcmd(isp, &mbs, MBLOGALL); + if (FCPARAM(isp)->isp_2klogin) { + mbs.ibits = (1 << 10); + } + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { return (0); } } break; - case ISPCTL_GET_POSMAP: - + case ISPCTL_GET_PDB: if (IS_FC(isp) && arg) { - return (isp_getmap(isp, arg)); + int id = *((int *)arg); + isp_pdb_t *pdb = arg; + return (isp_getpdb(isp, id, pdb, 1)); } break; + case ISPCTL_GET_PORTNAME: + { + u_int64_t *wwnp = arg; + int loopid = *wwnp; + *wwnp = isp_get_portname(isp, loopid, 0); + if (*wwnp == (u_int64_t) -1) { + break; + } else { + return (0); + } + } case ISPCTL_RUN_MBOXCMD: - isp_mboxcmd(isp, arg, MBLOGALL); + isp_mboxcmd(isp, arg); return(0); + case ISPCTL_PLOGX: + { + isp_plcmd_t *p = arg; + int r; + + if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || + (p->handle != NIL_HANDLE)) { + return (isp_plogx(isp, p->handle, p->portid, + p->flags, 0)); + } + do { + p->handle = isp_nxt_handle(isp, p->handle); + r = isp_plogx(isp, p->handle, p->portid, p->flags, 0); + if ((r & 0xffff) == MBOX_PORT_ID_USED) { + p->handle = r >> 16; + r = 0; + break; + } + } while ((r & 0xffff) == MBOX_LOOP_ID_USED); + return (r); + } #ifdef ISP_TARGET_MODE case ISPCTL_TOGGLE_TMODE: { @@ -3489,11 +4509,11 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) */ if (IS_SCSI(isp)) { int param = *(int *)arg; - MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_ENABLE_TARGET_MODE; mbs.param[1] = param & 0xffff; mbs.param[2] = param >> 16; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } @@ -3517,17 +4537,18 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) * of completions on a request queue at any one time. */ #ifndef MAX_REQUESTQ_COMPLETIONS -#define MAX_REQUESTQ_COMPLETIONS 64 +#define MAX_REQUESTQ_COMPLETIONS 32 #endif void -isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) +isp_intr(struct ispsoftc *isp, u_int32_t isr, u_int16_t sema, u_int16_t mbox) { XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs; - u_int16_t iptr, optr, junk; + u_int32_t iptr, optr, junk; int i, nlooked = 0, ndone = 0; again: + optr = isp->isp_residx; /* * Is this a mailbox related interrupt? * The mailbox semaphore will be nonzero if so. @@ -3538,7 +4559,7 @@ again: if (isp->isp_mboxbsy) { int obits = isp->isp_obits; isp->isp_mboxtmp[0] = mbox; - for (i = 1; i < MAX_MAILBOX; i++) { + for (i = 1; i < MAX_MAILBOX(isp); i++) { if ((obits & (1 << i)) == 0) { continue; } @@ -3553,17 +4574,14 @@ again: MBOX_NOTIFY_COMPLETE(isp); } else { isp_prt(isp, ISP_LOGWARN, - "Mbox Command Async (0x%x) with no waiters", - mbox); + "mailbox cmd (0x%x) with no waiters", mbox); } } else if (isp_parse_async(isp, mbox) < 0) { return; } if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) || isp->isp_state != ISP_RUNSTATE) { - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); - return; + goto out; } } @@ -3571,32 +4589,73 @@ again: * We can't be getting this now. */ if (isp->isp_state != ISP_RUNSTATE) { - isp_prt(isp, ISP_LOGWARN, + isp_prt(isp, ISP_LOGINFO, "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema); /* * Thank you very much! *Burrrp*! */ - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, - READ_RESPONSE_QUEUE_IN_POINTER(isp)); + ISP_WRITE(isp, isp->isp_respoutrp, + ISP_READ(isp, isp->isp_respinrp)); + if (IS_24XX(isp)) { + ISP_DISABLE_INTS(isp); + } + goto out; + } - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); - return; +#ifdef ISP_TARGET_MODE + /* + * Check for ATIO Queue entries. + */ + if (isp->isp_rspbsy == 0 && (isp->isp_role & ISP_ROLE_TARGET) && + IS_24XX(isp)) { + iptr = ISP_READ(isp, isp->isp_atioinrp); + optr = ISP_READ(isp, isp->isp_atiooutrp); + + isp->isp_rspbsy = 1; + while (optr != iptr) { + u_int8_t qe[QENTRY_LEN]; + isphdr_t *hp; + u_int32_t oop; + void *addr; + + oop = optr; + MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN); + addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop); + isp_get_hdr(isp, addr, (isphdr_t *)qe); + hp = (isphdr_t *)qe; + switch (hp->rqs_entry_type) { + case RQSTYPE_NOTIFY: + case RQSTYPE_ATIO: + (void) isp_target_notify(isp, addr, &oop); + break; + default: + isp_print_qentry(isp, "?ATIOQ entry?", + oop, addr); + break; + } + optr = ISP_NXT_QENTRY(oop, RESULT_QUEUE_LEN(isp)); + ISP_WRITE(isp, isp->isp_atiooutrp, optr); + } + isp->isp_rspbsy = 0; + optr = isp->isp_residx; } +#endif /* * Get the current Response Queue Out Pointer. * - * If we're a 2300, we can ask what hardware what it thinks. + * If we're a 2300 or 2400, we can ask what hardware what it thinks. */ - if (IS_23XX(isp)) { + if (IS_23XX(isp) || IS_24XX(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", + isp_prt(isp, ISP_LOGINFO, + "isp_intr: hard optr=%x, soft optr %x", optr, isp->isp_residx); + isp->isp_residx = optr; } } else { optr = isp->isp_residx; @@ -3611,19 +4670,18 @@ again: if (IS_2100(isp) || (IS_2300(isp) && isp->isp_revision < 2)) { i = 0; do { - iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); - junk = READ_RESPONSE_QUEUE_IN_POINTER(isp); + iptr = ISP_READ(isp, isp->isp_respinrp); + junk = ISP_READ(isp, isp->isp_respinrp); } while (junk != iptr && ++i < 1000); if (iptr != junk) { - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); isp_prt(isp, ISP_LOGWARN, "Response Queue Out Pointer Unstable (%x, %x)", iptr, junk); - return; + goto out; } } else { - iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); + iptr = ISP_READ(isp, isp->isp_respinrp); } isp->isp_resodx = iptr; @@ -3637,15 +4695,17 @@ again: * make sure the old interrupt went away (to avoid 'ringing' * effects), but that didn't stop this from occurring. */ - if (IS_23XX(isp)) { + if (IS_24XX(isp)) { + junk = 0; + } else if (IS_23XX(isp)) { USEC_DELAY(100); - iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); + iptr = ISP_READ(isp, isp->isp_respinrp); junk = ISP_READ(isp, BIU_R2HSTSLO); } else { junk = ISP_READ(isp, BIU_ISR); } if (optr == iptr) { - if (IS_23XX(isp)) { + if (IS_23XX(isp) || IS_24XX(isp)) { ; } else { sema = ISP_READ(isp, BIU_SEMA); @@ -3661,42 +4721,75 @@ again: } } isp->isp_resodx = iptr; - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); + if (isp->isp_rspbsy) { - return; + goto out; } isp->isp_rspbsy = 1; - while (optr != iptr) { - ispstatusreq_t local, *sp = &local; + u_int8_t qe[QENTRY_LEN]; + ispstatusreq_t *sp = (ispstatusreq_t *) qe; isphdr_t *hp; - int type; + int buddaboom, etype, scsi_status, completion_status; + int req_status_flags, req_state_flags; + u_int8_t *snsp, *resp; + u_int32_t rlen, slen; + long resid; u_int16_t oop; - int buddaboom = 0; hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr); oop = optr; optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp)); nlooked++; + read_again: + buddaboom = req_status_flags = req_state_flags = 0; + resid = 0L; + /* * Synchronize our view of this response queue entry. */ MEMORYBARRIER(isp, SYNC_RESULT, oop, QENTRY_LEN); - - type = isp_get_response_type(isp, hp); - - if (type == RQSTYPE_RESPONSE) { + isp_get_hdr(isp, hp, &sp->req_header); + etype = sp->req_header.rqs_entry_type; + + if (IS_24XX(isp) && etype == RQSTYPE_RESPONSE) { + isp24xx_statusreq_t *sp2 = (isp24xx_statusreq_t *)qe; + isp_get_24xx_response(isp, + (isp24xx_statusreq_t *)hp, sp2); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, + "Response Queue Entry", QENTRY_LEN, sp2); + } + scsi_status = sp2->req_scsi_status; + completion_status = sp2->req_completion_status; + req_state_flags = 0; + resid = sp2->req_resid; + } else if (etype == 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_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, + "Response Queue Entry", QENTRY_LEN, sp); + } + scsi_status = sp->req_scsi_status; + completion_status = sp->req_completion_status; + req_status_flags = sp->req_status_flags; + req_state_flags = sp->req_state_flags; + resid = sp->req_resid; + } else if (etype == RQSTYPE_RIO2) { + isp_rio2_t *rio = (isp_rio2_t *)qe; + isp_get_rio2(isp, (isp_rio2_t *) hp, rio); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, + "Response Queue Entry", QENTRY_LEN, 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; } - if (isp->isp_fpcchiwater < rio.req_header.rqs_seqno) - isp->isp_fpcchiwater = rio.req_header.rqs_seqno; MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; } else { @@ -3705,7 +4798,12 @@ again: * may have updated the response queue pointers for * us, so we reload our goal index. */ - if (isp_handle_other_response(isp, type, hp, &optr)) { + int r; + r = isp_handle_other_response(isp, etype, hp, &optr); + if (r < 0) { + goto read_again; + } + if (r > 0) { iptr = isp->isp_resodx; MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; @@ -3716,34 +4814,33 @@ again: * 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 * not, something bad has happened. */ - if (sp->req_header.rqs_entry_type != RQSTYPE_REQUEST) { + if (etype != RQSTYPE_REQUEST) { isp_prt(isp, ISP_LOGERR, notresp, - sp->req_header.rqs_entry_type, oop, optr, - nlooked); - if (isp->isp_dblev & ISP_LOGDEBUG0) { - isp_print_bytes(isp, "Queue Entry", - QENTRY_LEN, sp); - } + etype, oop, optr, nlooked); + isp_print_bytes(isp, + "Request Queue Entry", QENTRY_LEN, sp); MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; } buddaboom = 1; + scsi_status = sp->req_scsi_status; + completion_status = sp->req_completion_status; + req_status_flags = sp->req_status_flags; + req_state_flags = sp->req_state_flags; + resid = sp->req_resid; } - if (sp->req_header.rqs_flags & 0xf) { -#define _RQS_OFLAGS \ - ~(RQSFLAG_CONTINUATION|RQSFLAG_FULL|RQSFLAG_BADHEADER|RQSFLAG_BADPACKET) + if (sp->req_header.rqs_flags & RQSFLAG_MASK) { if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) { isp_prt(isp, ISP_LOGWARN, "continuation segment"); - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + ISP_WRITE(isp, isp->isp_respoutrp, optr); continue; } if (sp->req_header.rqs_flags & RQSFLAG_FULL) { @@ -3754,53 +4851,47 @@ again: */ } if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) { - isp_prt(isp, ISP_LOGERR, "bad header flag"); + isp_print_bytes(isp, "bad header flag", + QENTRY_LEN, sp); buddaboom++; } if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) { - isp_prt(isp, ISP_LOGERR, "bad request packet"); + isp_print_bytes(isp, "bad request packet", + QENTRY_LEN, sp); buddaboom++; } - if (sp->req_header.rqs_flags & _RQS_OFLAGS) { - isp_prt(isp, ISP_LOGERR, - "unknown flags (0x%x) in response", - sp->req_header.rqs_flags); - buddaboom++; - } -#undef _RQS_OFLAGS } + if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) { - 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, - sp->req_header.rqs_flags); - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + "bad request handle %d (type 0x%x)", + sp->req_handle, etype); + MEMZERO(hp, QENTRY_LEN); /* PERF */ + ISP_WRITE(isp, isp->isp_respoutrp, optr); continue; } xs = isp_find_xs(isp, sp->req_handle); if (xs == NULL) { - u_int8_t ts = sp->req_completion_status & 0xff; - MEMZERO(hp, QENTRY_LEN); /* PERF */ + u_int8_t ts = completion_status & 0xff; /* * Only whine if this isn't the expected fallout of * aborting the command. */ - if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) { + if (etype != RQSTYPE_RESPONSE) { isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", - sp->req_handle, - sp->req_header.rqs_entry_type); + sp->req_handle, etype); } else if (ts != RQCS_ABORTED) { isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts); } - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + MEMZERO(hp, QENTRY_LEN); /* PERF */ + ISP_WRITE(isp, isp->isp_respoutrp, optr); continue; } isp_destroy_handle(isp, sp->req_handle); - if (sp->req_status_flags & RQSTF_BUS_RESET) { + if (req_status_flags & RQSTF_BUS_RESET) { XS_SETERR(xs, HBA_BUSRESET); isp->isp_sendmarker |= (1 << XS_CHANNEL(xs)); } @@ -3808,39 +4899,71 @@ again: XS_SETERR(xs, HBA_BOTCH); } - if (IS_FC(isp) && (sp->req_scsi_status & RQCS_SV)) { + resp = NULL; + rlen = 0; + snsp = NULL; + slen = 0; + if (IS_24XX(isp) && (scsi_status & (RQCS_RV|RQCS_SV)) != 0) { + resp = ((isp24xx_statusreq_t *)sp)->req_rsp_sense; + rlen = ((isp24xx_statusreq_t *)sp)->req_response_len; + } else if (IS_FC(isp) && (scsi_status & RQCS_RV) != 0) { + resp = sp->req_response; + rlen = sp->req_response_len; + } + if (IS_FC(isp) && (scsi_status & RQCS_SV) != 0) { /* * Fibre Channel F/W doesn't say we got status * if there's Sense Data instead. I guess they * think it goes w/o saying. */ - sp->req_state_flags |= RQSF_GOT_STATUS; + req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE; + if (IS_24XX(isp)) { + snsp = + ((isp24xx_statusreq_t *)sp)->req_rsp_sense; + snsp += rlen; + slen = + ((isp24xx_statusreq_t *)sp)->req_sense_len; + } else { + snsp = sp->req_sense_data; + slen = sp->req_sense_len; + } + } else if (IS_SCSI(isp) && (req_state_flags & RQSF_GOT_SENSE)) { + snsp = sp->req_sense_data; + slen = sp->req_sense_len; } - if (sp->req_state_flags & RQSF_GOT_STATUS) { - *XS_STSP(xs) = sp->req_scsi_status & 0xff; + if (req_state_flags & RQSF_GOT_STATUS) { + *XS_STSP(xs) = scsi_status & 0xff; } - switch (sp->req_header.rqs_entry_type) { + switch (etype) { case RQSTYPE_RESPONSE: XS_SET_STATE_STAT(isp, xs, sp); - isp_parse_status(isp, sp, xs); + if (resp && rlen >= 4 && + resp[FCP_RSPNS_CODE_OFFSET] != 0) { + isp_prt(isp, ISP_LOGWARN, + "%d.%d.%d FCP RESPONSE: 0x%x", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), + resp[FCP_RSPNS_CODE_OFFSET]); + XS_SETERR(xs, HBA_BOTCH); + } + if (IS_24XX(isp)) { + isp_parse_status_24xx(isp, + (isp24xx_statusreq_t *)sp, xs, &resid); + } else { + isp_parse_status(isp, (void *)sp, xs, &resid); + } if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) && (*XS_STSP(xs) == SCSI_BUSY)) { XS_SETERR(xs, HBA_TGTBSY); } if (IS_SCSI(isp)) { - XS_RESID(xs) = sp->req_resid; - if ((sp->req_state_flags & RQSF_GOT_STATUS) && - (*XS_STSP(xs) == SCSI_CHECK) && - (sp->req_state_flags & RQSF_GOT_SENSE)) { - XS_SAVE_SENSE(xs, sp); - } + XS_RESID(xs) = resid; /* * 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) { + if (req_status_flags & RQSTF_NEGOTIATION) { int t = XS_TGT(xs); sdparam *sdp = isp->isp_param; sdp += XS_CHANNEL(xs); @@ -3849,26 +4972,26 @@ again: (1 << XS_CHANNEL(xs)); } } else { - if (sp->req_status_flags & RQSF_XFER_COMPLETE) { + if (req_status_flags & RQSF_XFER_COMPLETE) { XS_RESID(xs) = 0; - } else if (sp->req_scsi_status & RQCS_RESID) { - XS_RESID(xs) = sp->req_resid; + } else if (scsi_status & RQCS_RESID) { + XS_RESID(xs) = resid; } else { XS_RESID(xs) = 0; } - if ((sp->req_state_flags & RQSF_GOT_STATUS) && - (*XS_STSP(xs) == SCSI_CHECK) && - (sp->req_scsi_status & RQCS_SV)) { - XS_SAVE_SENSE(xs, sp); - /* solely for the benefit of debug */ - sp->req_state_flags |= RQSF_GOT_SENSE; - } + } + if (snsp && slen) { + XS_SAVE_SENSE(xs, snsp, slen); } isp_prt(isp, ISP_LOGDEBUG2, - "asked for %ld got resid %ld", (long) XS_XFRLEN(xs), - (long) sp->req_resid); + "asked for %ld got raw resid %ld settled for %ld", + (long) XS_XFRLEN(xs), resid, (long) XS_RESID(xs)); break; case RQSTYPE_REQUEST: + case RQSTYPE_A64: + case RQSTYPE_T2RQS: + case RQSTYPE_T3RQS: + case RQSTYPE_T7RQS: if (sp->req_header.rqs_flags & RQSFLAG_FULL) { /* * Force Queue Full status. @@ -3879,16 +5002,19 @@ again: /* * ???? */ + XS_SETERR(xs, HBA_BOTCH); isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Entry bounced back"); - XS_SETERR(xs, HBA_BOTCH); + if ((isp->isp_dblev & ISP_LOGDEBUG1) == 0) { + isp_print_bytes(isp, "Bounced Request", + QENTRY_LEN, qe); + } } XS_RESID(xs) = XS_XFRLEN(xs); break; default: - isp_prt(isp, ISP_LOGWARN, - "unhandled response queue type 0x%x", - sp->req_header.rqs_entry_type); + isp_print_bytes(isp, "Unhandled Response Type", + QENTRY_LEN, qe); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BOTCH); } @@ -3896,17 +5022,18 @@ again: } /* - * Free any dma resources. As a side effect, this may - * also do any cache flushing necessary for data coherence. */ + * Free any DMA resources. As a side effect, this may + * also do any cache flushing necessary for data coherence. + */ if (XS_XFRLEN(xs)) { ISP_DMAFREE(isp, xs, sp->req_handle); } if (((isp->isp_dblev & (ISP_LOGDEBUG2|ISP_LOGDEBUG3))) || - ((isp->isp_dblev & ISP_LOGDEBUG1) && ((!XS_NOERR(xs)) || + ((isp->isp_dblev & ISP_LOGDEBUG0) && ((!XS_NOERR(xs)) || (*XS_STSP(xs) != SCSI_GOOD)))) { char skey; - if (sp->req_state_flags & RQSF_GOT_SENSE) { + if (req_state_flags & RQSF_GOT_SENSE) { skey = XS_SNSKEY(xs) & 0xf; if (skey < 10) skey += '0'; @@ -3918,8 +5045,7 @@ again: skey = '.'; } isp_prt(isp, ISP_LOGALL, finmsg, XS_CHANNEL(xs), - XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs), - (ulong)XS_RESID(xs), + XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs), XS_RESID(xs), *XS_STSP(xs), skey, XS_ERR(xs)); } @@ -3938,13 +5064,23 @@ again: * ISP's notion of what we've seen so far. */ if (nlooked) { - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + ISP_WRITE(isp, isp->isp_respoutrp, optr); /* - * While we're at it, read the request queue out pointer. + * While we're at it, read the requst queue out pointer. */ - isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp); - if (isp->isp_rscchiwater < ndone) + isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp); + if (isp->isp_rscchiwater < ndone) { isp->isp_rscchiwater = ndone; + } + } + +out: + + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + ISP_WRITE(isp, BIU_SEMA, 0); } isp->isp_residx = optr; @@ -3962,7 +5098,7 @@ again: * Support routines. */ -static int +int isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) { int rval = 0; @@ -3979,26 +5115,32 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) case ASYNC_BUS_RESET: isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif isp_async(isp, ISPASYNC_BUS_RESET, &bus); break; case ASYNC_SYSTEM_ERROR: -#ifdef ISP_FW_CRASH_DUMP + isp->isp_state = ISP_CRASHED; + if (IS_FC(isp)) { + FCPARAM(isp)->isp_loopstate = LOOP_NIL; + FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; + } /* - * If we have crash dumps enabled, it's up to the handler - * for isp_async to reinit stuff and restart the firmware - * after performing the crash dump. The reason we do things - * this way is that we may need to activate a kernel thread - * to do all the crash dump goop. + * Were we waiting for a mailbox command to complete? + * If so, it's dead, so wake up the waiter. + */ + if (isp->isp_mboxbsy) { + isp->isp_obits = 1; + isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR; + MBOX_NOTIFY_COMPLETE(isp); + } + /* + * It's up to the handler for isp_async to reinit stuff and + * restart the firmware */ isp_async(isp, ISPASYNC_FW_CRASH, NULL); -#else - isp_async(isp, ISPASYNC_FW_CRASH, NULL); - isp_reinit(isp); - isp_async(isp, ISPASYNC_FW_RESTARTED, NULL); -#endif rval = -1; break; @@ -4016,7 +5158,7 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) * We don't need to be chatty about this- just unlatch things * and move on. */ - mbox = READ_REQUEST_QUEUE_OUT_POINTER(isp); + mbox = ISP_READ(isp, isp->isp_rqstoutrp); break; case ASYNC_TIMEOUT_RESET: @@ -4024,8 +5166,9 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) "timeout initiated SCSI bus reset of bus %d", bus); isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif break; @@ -4033,8 +5176,9 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) isp_prt(isp, ISP_LOGINFO, "device reset on bus %d", bus); isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif break; @@ -4125,29 +5269,33 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) int handle = (ISP_READ(isp, OUTMAILBOX2) << 16) | (ISP_READ(isp, OUTMAILBOX1)); - if (isp_target_async(isp, handle, mbox)) + if (isp_target_async(isp, handle, mbox)) { rval = -1; + } else { + /* count it as a fast posting intr */ + isp->isp_fphccmplt++; + } #else isp_prt(isp, ISP_LOGINFO, "Fast Posting CTIO done"); -#endif isp->isp_fphccmplt++; /* count it as a fast posting intr */ +#endif break; } + case ASYNC_LIP_ERROR: case ASYNC_LIP_F8: case ASYNC_LIP_OCCURRED: - FCPARAM(isp)->isp_lipseq = - ISP_READ(isp, OUTMAILBOX1); FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp->isp_sendmarker = 1; - isp_mark_getpdb_all(isp); + ISP_MARK_PORTDB(isp, 1); isp_async(isp, ISPASYNC_LIP, NULL); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif /* - * We've had problems with data corruption occurring on + * We've had problems with data corruption occuring on * commands that complete (with no apparent error) after * we receive a LIP. This has been observed mostly on * Local Loop topologies. To be safe, let's just mark @@ -4175,11 +5323,12 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) isp->isp_sendmarker = 1; FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; - isp_mark_getpdb_all(isp); + ISP_MARK_PORTDB(isp, 1); isp_async(isp, ISPASYNC_LOOP_UP, NULL); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif break; @@ -4187,11 +5336,12 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) isp->isp_sendmarker = 1; FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_NIL; - isp_mark_getpdb_all(isp); + ISP_MARK_PORTDB(isp, 1); isp_async(isp, ISPASYNC_LOOP_DOWN, NULL); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif break; @@ -4199,50 +5349,49 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) isp->isp_sendmarker = 1; FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_NIL; - isp_mark_getpdb_all(isp); + ISP_MARK_PORTDB(isp, 1); isp_async(isp, ISPASYNC_LOOP_RESET, NULL); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif break; case ASYNC_PDB_CHANGED: isp->isp_sendmarker = 1; FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; - isp_mark_getpdb_all(isp); + ISP_MARK_PORTDB(isp, 1); isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_PDB); break; case ASYNC_CHANGE_NOTIFY: - /* - * Not correct, but it will force us to rescan the loop. - */ - FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; - isp_mark_getpdb_all(isp); + if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) { + FCPARAM(isp)->isp_loopstate = LOOP_LSCAN_DONE; + } else { + FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; + } + ISP_MARK_PORTDB(isp, 1); isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_SNS); break; case ASYNC_PTPMODE: - if (FCPARAM(isp)->isp_onfabric) - FCPARAM(isp)->isp_topo = TOPO_F_PORT; - else - FCPARAM(isp)->isp_topo = TOPO_N_PORT; - isp_mark_getpdb_all(isp); + ISP_MARK_PORTDB(isp, 1); isp->isp_sendmarker = 1; FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif isp_prt(isp, ISP_LOGINFO, "Point-to-Point mode"); break; case ASYNC_CONNMODE: mbox = ISP_READ(isp, OUTMAILBOX1); - isp_mark_getpdb_all(isp); + ISP_MARK_PORTDB(isp, 1); switch (mbox) { case ISP_CONN_LOOP: isp_prt(isp, ISP_LOGINFO, @@ -4258,13 +5407,7 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) break; case ISP_CONN_FATAL: isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR"); -#ifdef ISP_FW_CRASH_DUMP isp_async(isp, ISPASYNC_FW_CRASH, NULL); -#else - isp_async(isp, ISPASYNC_FW_CRASH, NULL); - isp_reinit(isp); - isp_async(isp, ISPASYNC_FW_RESTARTED, NULL); -#endif return (-1); case ISP_CONN_LOOPBACK: isp_prt(isp, ISP_LOGWARN, @@ -4281,6 +5424,15 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; break; + case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */ + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent"); + break; + } else if (IS_2200(isp)) { + isp_prt(isp, ISP_LOGTDEBUG0, "QFULL sent"); + break; + } + /* FALLTHROUGH */ default: isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox); break; @@ -4288,9 +5440,9 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) if (bus & 0x100) { int i, nh; - u_int16_t handles[5]; + u_int16_t handles[16]; - for (nh = 0, i = 1; i < MAX_MAILBOX; i++) { + for (nh = 0, i = 1; i < MAX_MAILBOX(isp); i++) { if ((bus & (1 << i)) == 0) { continue; } @@ -4301,8 +5453,9 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) isp_prt(isp, ISP_LOGDEBUG3, "fast post completion of %u", handles[i]); } - if (isp->isp_fpcchiwater < nh) + if (isp->isp_fpcchiwater < nh) { isp->isp_fpcchiwater = nh; + } } else { isp->isp_intoasync++; } @@ -4315,13 +5468,16 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) * this is not used currently. */ -static int +int isp_handle_other_response(struct ispsoftc *isp, int type, - isphdr_t *hp, u_int16_t *optrp) + isphdr_t *hp, u_int32_t *optrp) { switch (type) { case RQSTYPE_STATUS_CONT: - isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response"); + isp_prt(isp, ISP_LOGDEBUG0, "Ignored Continuation Response"); + return (1); + case RQSTYPE_MARKER: + isp_prt(isp, ISP_LOGDEBUG0, "Marker Response"); return (1); case RQSTYPE_ATIO: case RQSTYPE_CTIO: @@ -4333,6 +5489,9 @@ isp_handle_other_response(struct ispsoftc *isp, int type, case RQSTYPE_ATIO2: case RQSTYPE_CTIO2: case RQSTYPE_CTIO3: + case RQSTYPE_CTIO7: + case RQSTYPE_ABTS_RCVD: + case RQSTYPE_ABTS_RSP: isp->isp_rsltccmplt++; /* count as a response completion */ #ifdef ISP_TARGET_MODE if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)) { @@ -4342,17 +5501,31 @@ isp_handle_other_response(struct ispsoftc *isp, int type, /* FALLTHROUGH */ case RQSTYPE_REQUEST: default: - if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, hp)) { - return (1); + USEC_DELAY(100); + if (type != isp_get_response_type(isp, hp)) { + /* + * This is questionable- we're just papering over + * something we've seen on SMP linux in target + * mode- we don't really know what's happening + * here that causes us to think we've gotten + * an entry, but that either the entry isn't + * filled out yet or our CPU read data is stale. + */ + isp_prt(isp, ISP_LOGINFO, + "unstable type in response queue"); + return (-1); } isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x", isp_get_response_type(isp, hp)); + if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, hp)) { + return (1); + } return (0); } } -static void -isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) +void +isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) { switch (sp->req_completion_status & 0xff) { case RQCS_COMPLETE: @@ -4368,6 +5541,7 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_SELTIMEOUT); + *rp = XS_XFRLEN(xs); } return; } @@ -4380,6 +5554,7 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) case RQCS_DMA_ERROR: isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + *rp = XS_XFRLEN(xs); break; case RQCS_TRANSPORT_ERROR: @@ -4435,6 +5610,7 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) isp_prt(isp, ISP_LOGERR, "%s", buf); isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d:\n%s", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), buf); + *rp = XS_XFRLEN(xs); break; } case RQCS_RESET_OCCURRED: @@ -4445,6 +5621,7 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BUSRESET); } + *rp = XS_XFRLEN(xs); return; case RQCS_ABORTED: @@ -4460,15 +5637,8 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); /* - * Check to see if we logged out the device. + * XXX: Check to see if we logged out of the device. */ - if (IS_FC(isp)) { - if ((sp->req_completion_status & RQSTF_LOGOUT) && - FCPARAM(isp)->portdb[XS_TGT(xs)].valid && - FCPARAM(isp)->portdb[XS_TGT(xs)].fabric_dev) { - FCPARAM(isp)->portdb[XS_TGT(xs)].relogin = 1; - } - } if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_CMDTIMEOUT); } @@ -4675,40 +5845,214 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) * No such port on the loop. Moral equivalent of SELTIMEO */ case RQCS_PORT_LOGGED_OUT: + { + const char *reason; + u_int8_t sts = sp->req_completion_status & 0xff; + /* * It was there (maybe)- treat as a selection timeout. */ - if ((sp->req_completion_status & 0xff) == RQCS_PORT_UNAVAILABLE) - isp_prt(isp, ISP_LOGINFO, - "port unavailable for target %d", XS_TGT(xs)); - else - isp_prt(isp, ISP_LOGINFO, - "port logout for target %d", XS_TGT(xs)); + if (sts == RQCS_PORT_UNAVAILABLE) { + reason = "unavailable"; + } else { + reason = "logout"; + } + + isp_prt(isp, ISP_LOGINFO, "port %s for target %d", + reason, 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 we're on fabric, - * then we'll have to relogin as a matter of course. + * then we'll have to log in again as a matter of course. */ if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT || FCPARAM(isp)->isp_topo == TOPO_FL_PORT) { mbreg_t mbs; MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_INIT_LIP; + if (FCPARAM(isp)->isp_2klogin) { + mbs.ibits = (1 << 10); + } + mbs.logval = MBLOGALL; isp_mboxcmd_qnw(isp, &mbs, 1); } + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + } + return; + } + case RQCS_PORT_CHANGED: + isp_prt(isp, ISP_LOGWARN, + "port changed for target %d", XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + } + return; + + case RQCS_PORT_BUSY: + isp_prt(isp, ISP_LOGWARN, + "port busy for target %d", XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_TGTBSY); + } + return; + + default: + isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x", + sp->req_completion_status); + break; + } + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_BOTCH); + } +} + +void +isp_parse_status_24xx(struct ispsoftc *isp, isp24xx_statusreq_t *sp, + XS_T *xs, long *rp) +{ + int ru_marked, sv_marked; + switch (sp->req_completion_status) { + case RQCS_COMPLETE: + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_NOERROR); + } + return; + + case RQCS_DMA_ERROR: + isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + break; + case RQCS_TRANSPORT_ERROR: + isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + break; + + case RQCS_RESET_OCCURRED: + isp_prt(isp, ISP_LOGWARN, + "bus reset destroyed command for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp->isp_sendmarker |= (1 << XS_CHANNEL(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_BUSRESET); + } + return; + + case RQCS_ABORTED: + isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp->isp_sendmarker |= (1 << XS_CHANNEL(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_ABORTED); + } + return; + + case RQCS_TIMEOUT: + isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_CMDTIMEOUT); + } + return; + + case RQCS_DATA_OVERRUN: + XS_RESID(xs) = sp->req_resid; + isp_prt(isp, ISP_LOGERR, + "data overrun for command on %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_DATAOVR); + } + return; + + case RQCS_24XX_DRE: /* data reassembly error */ + isp_prt(isp, ISP_LOGERR, "data reassembly error for target %d", + XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_ABORTED); + } + *rp = XS_XFRLEN(xs); + return; + + case RQCS_24XX_TABORT: /* aborted by target */ + isp_prt(isp, ISP_LOGERR, "target %d sent ABTS", + XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_ABORTED); + } + return; + + case RQCS_DATA_UNDERRUN: + ru_marked = (sp->req_scsi_status & RQCS_RU) != 0; /* - * Probably overkill. + * We can get an underrun w/o things being marked + * if we got a non-zero status. */ - 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); + sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0; + if ((ru_marked == 0 && sv_marked == 0) || + (sp->req_resid > XS_XFRLEN(xs))) { + isp_prt(isp, ISP_LOGWARN, bun, XS_TGT(xs), + XS_LUN(xs), XS_XFRLEN(xs), sp->req_resid, + (ru_marked)? "marked" : "not marked"); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_BOTCH); + } + return; + } + XS_RESID(xs) = sp->req_resid; + isp_prt(isp, ISP_LOGDEBUG0, + "%d.%d.%d data underrun (%d) for command 0x%x", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), + sp->req_resid, XS_CDBP(xs)[0] & 0xff); if (XS_NOERR(xs)) { - XS_SETERR(xs, HBA_SELTIMEOUT); + XS_SETERR(xs, HBA_NOERROR); } return; + case RQCS_PORT_UNAVAILABLE: + /* + * No such port on the loop. Moral equivalent of SELTIMEO + */ + case RQCS_PORT_LOGGED_OUT: + { + const char *reason; + u_int8_t sts = sp->req_completion_status & 0xff; + + /* + * It was there (maybe)- treat as a selection timeout. + */ + if (sts == RQCS_PORT_UNAVAILABLE) { + reason = "unavailable"; + } else { + reason = "logout"; + } + + isp_prt(isp, ISP_LOGINFO, "port %s for target %d", + reason, 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 we're on fabric, + * then we'll have to log in again as a matter of course. + */ + if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT || + FCPARAM(isp)->isp_topo == TOPO_FL_PORT) { + mbreg_t mbs; + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_INIT_LIP; + if (FCPARAM(isp)->isp_2klogin) { + mbs.ibits = (1 << 10); + } + mbs.logval = MBLOGALL; + isp_mboxcmd_qnw(isp, &mbs, 1); + } + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + } + return; + } case RQCS_PORT_CHANGED: isp_prt(isp, ISP_LOGWARN, "port changed for target %d", XS_TGT(xs)); @@ -4717,10 +6061,22 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) } return; - case RQCS_PORT_BUSY: + + case RQCS_24XX_ENOMEM: /* f/w resource unavailable */ isp_prt(isp, ISP_LOGWARN, - "port busy for target %d", XS_TGT(xs)); + "f/w resource unavailable for target %d", XS_TGT(xs)); + if (XS_NOERR(xs)) { + *XS_STSP(xs) = SCSI_BUSY; + XS_SETERR(xs, HBA_TGTBSY); + } + return; + + case RQCS_24XX_TMO: /* task management overrun */ + isp_prt(isp, ISP_LOGWARN, + "command for target %d overlapped task management", + XS_TGT(xs)); if (XS_NOERR(xs)) { + *XS_STSP(xs) = SCSI_BUSY; XS_SETERR(xs, HBA_TGTBSY); } return; @@ -4735,7 +6091,7 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) } } -static void +void isp_fastpost_complete(struct ispsoftc *isp, u_int16_t fph) { XS_T *xs; @@ -4745,7 +6101,7 @@ isp_fastpost_complete(struct ispsoftc *isp, u_int16_t fph) } xs = isp_find_xs(isp, fph); if (xs == NULL) { - isp_prt(isp, ISP_LOGWARN, + isp_prt(isp, ISP_LOGDEBUG1, "Command for fast post handle 0x%x not found", fph); return; } @@ -4768,15 +6124,17 @@ isp_fastpost_complete(struct ispsoftc *isp, u_int16_t fph) isp_done(xs); } -static int +int isp_mbox_continue(struct ispsoftc *isp) { mbreg_t mbs; u_int16_t *ptr; + u_int32_t offset; switch (isp->isp_lastmbxcmd) { case MBOX_WRITE_RAM_WORD: case MBOX_READ_RAM_WORD: + case MBOX_WRITE_RAM_WORD_EXTENDED: case MBOX_READ_RAM_WORD_EXTENDED: break; default: @@ -4787,12 +6145,15 @@ isp_mbox_continue(struct ispsoftc *isp) return (-1); } - /* * Clear the previous interrupt. */ - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + ISP_WRITE(isp, BIU_SEMA, 0); + } /* * Continue with next word. @@ -4801,27 +6162,46 @@ isp_mbox_continue(struct ispsoftc *isp) ptr = isp->isp_mbxworkp; switch (isp->isp_lastmbxcmd) { case MBOX_WRITE_RAM_WORD: - mbs.param[2] = *ptr++; - mbs.param[1] = isp->isp_mbxwrk1++; + mbs.param[1] = isp->isp_mbxwrk1++;; + mbs.param[2] = *ptr++;; break; case MBOX_READ_RAM_WORD: - case MBOX_READ_RAM_WORD_EXTENDED: *ptr++ = isp->isp_mboxtmp[2]; mbs.param[1] = isp->isp_mbxwrk1++; break; + case MBOX_WRITE_RAM_WORD_EXTENDED: + offset = isp->isp_mbxwrk1; + offset |= isp->isp_mbxwrk8 << 16; + + mbs.param[2] = *ptr++;; + mbs.param[1] = offset; + mbs.param[8] = offset >> 16; + isp->isp_mbxwrk1 = ++offset; + isp->isp_mbxwrk8 = offset >> 16; + break; + case MBOX_READ_RAM_WORD_EXTENDED: + offset = isp->isp_mbxwrk1; + offset |= isp->isp_mbxwrk8 << 16; + + *ptr++ = isp->isp_mboxtmp[2]; + mbs.param[1] = offset; + mbs.param[8] = offset >> 16; + isp->isp_mbxwrk1 = ++offset; + isp->isp_mbxwrk8 = offset >> 16; + break; } isp->isp_mbxworkp = ptr; + isp->isp_mbxwrk0--; mbs.param[0] = isp->isp_lastmbxcmd; - isp->isp_mbxwrk0 -= 1; + mbs.logval = MBLOGALL; 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)) -static const u_int16_t mbpscsi[] = { +#define HIWRD(x) ((x) >> 16) +#define LOWRD(x) ((x) & 0xffff) +#define ISPOPMAP(a, b) (((a) << 16) | (b)) +static const u_int32_t mbpscsi[] = { ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ @@ -4829,7 +6209,7 @@ static const u_int16_t mbpscsi[] = { ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ ISPOPMAP(0x3f, 0x3f), /* 0x06: MBOX_MAILBOX_REG_TEST */ - ISPOPMAP(0x03, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ + ISPOPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ ISPOPMAP(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */ ISPOPMAP(0x00, 0x00), /* 0x09: */ ISPOPMAP(0x00, 0x00), /* 0x0a: */ @@ -4906,7 +6286,7 @@ static const u_int16_t mbpscsi[] = { ISPOPMAP(0xdf, 0xdf), /* 0x51: DUMP RAM A64 */ ISPOPMAP(0xdf, 0xff), /* 0x52: INITIALIZE REQUEST QUEUE A64 */ ISPOPMAP(0xef, 0xff), /* 0x53: INITIALIZE RESPONSE QUEUE A64 */ - ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */ + ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUCUTE COMMAND IOCB A64 */ ISPOPMAP(0x07, 0x01), /* 0x55: ENABLE TARGET MODE */ ISPOPMAP(0x03, 0x0f), /* 0x56: GET TARGET STATUS */ ISPOPMAP(0x00, 0x00), /* 0x57: */ @@ -4922,8 +6302,8 @@ static const u_int16_t mbpscsi[] = { #define ISP_STRIPPED #endif -#ifndef ISP_STRIPPED -static char *scsi_mbcmd_names[] = { +#ifndef ISP_STRIPPED +static const char *scsi_mbcmd_names[] = { "NO-OP", "LOAD RAM", "EXEC FIRMWARE", @@ -5021,23 +6401,23 @@ static char *scsi_mbcmd_names[] = { }; #endif -static const u_int16_t mbpfc[] = { +static const u_int32_t mbpfc[] = { ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ - ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ + ISPOPMAP(0x0f, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ ISPOPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */ ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ ISPOPMAP(0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */ - ISPOPMAP(0x03, 0x05), /* 0x07: MBOX_VERIFY_CHECKSUM */ + ISPOPMAP(0x03, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ ISPOPMAP(0x01, 0x4f), /* 0x08: MBOX_ABOUT_FIRMWARE */ - ISPOPMAP(0xdf, 0x01), /* 0x09: LOAD RAM */ + ISPOPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */ ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */ - ISPOPMAP(0x00, 0x00), /* 0x0b: */ + ISPOPMAP(0x1ff, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */ ISPOPMAP(0x00, 0x00), /* 0x0c: */ - ISPOPMAP(0x00, 0x00), /* 0x0d: */ + ISPOPMAP(0x10f, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */ ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ - ISPOPMAP(0x03, 0x07), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED(1) */ + ISPOPMAP(0x10f, 0x05), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */ ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */ ISPOPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */ ISPOPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */ @@ -5088,8 +6468,8 @@ static const u_int16_t mbpfc[] = { ISPOPMAP(0x00, 0x00), /* 0x3f: */ ISPOPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */ ISPOPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */ - ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_GET_RESOURCE_COUNTS */ - ISPOPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_NON_PARTICIPATING_MODE */ + ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_GET_RESOURCE_COUNT */ + ISPOPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */ ISPOPMAP(0x00, 0x00), /* 0x44: */ ISPOPMAP(0x00, 0x00), /* 0x45: */ ISPOPMAP(0x00, 0x00), /* 0x46: */ @@ -5118,7 +6498,7 @@ static const u_int16_t mbpfc[] = { ISPOPMAP(0x07, 0x03), /* 0x5d: MBOX_GET_SET_DATA_RATE */ ISPOPMAP(0x00, 0x00), /* 0x5e: */ ISPOPMAP(0x00, 0x00), /* 0x5f: */ - ISPOPMAP(0xfd, 0x31), /* 0x60: MBOX_INIT_FIRMWARE */ + ISPOPMAP(0xcd, 0x01), /* 0x60: MBOX_INIT_FIRMWARE */ ISPOPMAP(0x00, 0x00), /* 0x61: */ ISPOPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ ISPOPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ @@ -5148,18 +6528,19 @@ static const u_int16_t mbpfc[] = { ISPOPMAP(0x00, 0x00), /* 0x7b: */ ISPOPMAP(0x4f, 0x03), /* 0x7c: Get ID List */ ISPOPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */ - ISPOPMAP(0x07, 0x01) /* 0x7e: Lun RESET */ + ISPOPMAP(0x0f, 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!). + * responsible for setting this register first (Gross!). The assumption + * is that we won't overflow. */ -#ifndef ISP_STRIPPED -static char *fc_mbcmd_names[] = { +#ifndef ISP_STRIPPED +static const char *fc_mbcmd_names[] = { "NO-OP", "LOAD RAM", "EXEC FIRMWARE", @@ -5171,7 +6552,7 @@ static char *fc_mbcmd_names[] = { "ABOUT FIRMWARE", "LOAD RAM", "DUMP RAM", - NULL, + "WRITE RAM WORD EXTENDED", NULL, "READ RAM WORD EXTENDED", "CHECK FIRMWARE", @@ -5226,12 +6607,12 @@ static char *fc_mbcmd_names[] = { NULL, "LOOP PORT BYPASS", "LOOP PORT ENABLE", - "GET RESOURCE COUNTS", + "GET RESOURCE COUNT", "REQUEST NON PARTICIPATING MODE", NULL, NULL, NULL, - "GET PORT DATABASE,, ENHANCED", + "GET PORT DATABASE ENHANCED", NULL, NULL, NULL, @@ -5290,26 +6671,24 @@ static char *fc_mbcmd_names[] = { }; #endif -static void +void isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay) { - unsigned int lim, ibits, obits, box, opcode; - const u_int16_t *mcp; + unsigned int ibits, obits, box, opcode; + const u_int32_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++) { + ibits = HIWRD(mcp[opcode]) & NMBOX_BMASK(isp); + obits = LOWRD(mcp[opcode]) & NMBOX_BMASK(isp); + ibits |= mbp->ibits; + obits |= mbp->obits; + for (box = 0; box < MAX_MAILBOX(isp); box++) { if (ibits & (1 << box)) { - isp_prt(isp, ISP_LOGDEBUG1, "IN mbox %d = 0x%x", box, - mbp->param[box]); ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); } if (nodelay == 0) { @@ -5321,7 +6700,11 @@ isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay) isp->isp_obits = obits; isp->isp_mboxbsy = 1; } - ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT); + } else { + 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 @@ -5332,12 +6715,13 @@ isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay) } } -static void -isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) +void +isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp) { - char *cname, *xname, tname[16], mname[16]; + const char *cname, *xname; + char tname[16], mname[16]; unsigned int lim, ibits, obits, box, opcode; - const u_int16_t *mcp; + const u_int32_t *mcp; if (IS_FC(isp)) { mcp = mbpfc; @@ -5353,8 +6737,14 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) return; } - ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp); - obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp); + ibits = HIWRD(mcp[opcode]) & NMBOX_BMASK(isp); + obits = LOWRD(mcp[opcode]) & NMBOX_BMASK(isp); + + /* + * Pick up any additional bits that the caller might have set. + */ + ibits |= mbp->ibits; + obits |= mbp->obits; if (ibits == 0 && obits == 0) { mbp->param[0] = MBOX_COMMAND_PARAM_ERROR; @@ -5365,10 +6755,15 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) /* * Get exclusive usage of mailbox registers. */ - MBOX_ACQUIRE(isp); + if (MBOX_ACQUIRE(isp)) { + mbp->param[0] = MBOX_REGS_BUSY; + goto out; + } - for (box = 0; box < MAX_MAILBOX; box++) { + for (box = 0; box < MAX_MAILBOX(isp); box++) { if (ibits & (1 << box)) { + isp_prt(isp, ISP_LOGDEBUG1, "IN mbox %d = 0x%04x", box, + mbp->param[box]); ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); } isp->isp_mboxtmp[box] = mbp->param[box] = 0; @@ -5385,39 +6780,43 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) /* * Set Host Interrupt condition so that RISC will pick up mailbox regs. */ - ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); + } /* * While we haven't finished the command, spin our wheels here. */ - MBOX_WAIT_COMPLETE(isp); + MBOX_WAIT_COMPLETE(isp, mbp); - if (isp->isp_mboxbsy) { - /* - * Command timed out. - */ - isp->isp_mboxbsy = 0; + /* + * Did the command time out? + */ + if (mbp->param[0] == MBOX_TIMEOUT) { MBOX_RELEASE(isp); - return; + goto out; } /* * Copy back output registers. */ - for (box = 0; box < MAX_MAILBOX; box++) { + for (box = 0; box < MAX_MAILBOX(isp); box++) { if (obits & (1 << box)) { mbp->param[box] = isp->isp_mboxtmp[box]; - isp_prt(isp, ISP_LOGDEBUG1, "OUT mbox %d = 0x%x", box, + isp_prt(isp, ISP_LOGDEBUG1, "OUT mbox %d = 0x%04x", box, mbp->param[box]); } } MBOX_RELEASE(isp); - - if (logmask == 0 || opcode == MBOX_EXEC_FIRMWARE) { + out: + isp->isp_mboxbsy = 0; + if (mbp->logval == 0 || opcode == MBOX_EXEC_FIRMWARE) { return; } -#ifdef ISP_STRIPPED +#ifdef ISP_STRIPPED cname = NULL; #else cname = (IS_FC(isp))? fc_mbcmd_names[opcode] : scsi_mbcmd_names[opcode]; @@ -5435,38 +6834,49 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) case MBOX_COMMAND_COMPLETE: break; case MBOX_INVALID_COMMAND: - if (logmask & MBLOGMASK(MBOX_COMMAND_COMPLETE)) + if (mbp->logval & MBLOGMASK(MBOX_COMMAND_COMPLETE)) { xname = "INVALID COMMAND"; + } break; case MBOX_HOST_INTERFACE_ERROR: - if (logmask & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR)) + if (mbp->logval & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR)) { xname = "HOST INTERFACE ERROR"; + } break; case MBOX_TEST_FAILED: - if (logmask & MBLOGMASK(MBOX_TEST_FAILED)) + if (mbp->logval & MBLOGMASK(MBOX_TEST_FAILED)) { xname = "TEST FAILED"; + } break; case MBOX_COMMAND_ERROR: - if (logmask & MBLOGMASK(MBOX_COMMAND_ERROR)) + if (mbp->logval & MBLOGMASK(MBOX_COMMAND_ERROR)) { xname = "COMMAND ERROR"; + } break; case MBOX_COMMAND_PARAM_ERROR: - if (logmask & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR)) + if (mbp->logval & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR)) { xname = "COMMAND PARAMETER ERROR"; + } break; case MBOX_LOOP_ID_USED: - if (logmask & MBLOGMASK(MBOX_LOOP_ID_USED)) + if (mbp->logval & MBLOGMASK(MBOX_LOOP_ID_USED)) { xname = "LOOP ID ALREADY IN USE"; + } break; case MBOX_PORT_ID_USED: - if (logmask & MBLOGMASK(MBOX_PORT_ID_USED)) + if (mbp->logval & MBLOGMASK(MBOX_PORT_ID_USED)) { xname = "PORT ID ALREADY IN USE"; + } break; case MBOX_ALL_IDS_USED: - if (logmask & MBLOGMASK(MBOX_ALL_IDS_USED)) + if (mbp->logval & MBLOGMASK(MBOX_ALL_IDS_USED)) { xname = "ALL LOOP IDS IN USE"; + } + break; + case MBOX_REGS_BUSY: + xname = "REGISTERS BUSY"; break; - case 0: /* special case */ + case MBOX_TIMEOUT: xname = "TIMEOUT"; break; default: @@ -5474,12 +6884,13 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) xname = mname; break; } - if (xname) + if (xname) { isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s)", cname, xname); + } } -static void +void isp_fw_state(struct ispsoftc *isp) { if (IS_FC(isp)) { @@ -5488,14 +6899,15 @@ isp_fw_state(struct ispsoftc *isp) MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_FW_STATE; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { fcp->isp_fwstate = mbs.param[1]; } } } -static void +void isp_update(struct ispsoftc *isp) { int bus, upmask; @@ -5508,7 +6920,7 @@ isp_update(struct ispsoftc *isp) } } -static void +void isp_update_bus(struct ispsoftc *isp, int bus) { int tgt; @@ -5550,17 +6962,16 @@ isp_update_bus(struct ispsoftc *isp, int bus) */ if (sdp->isp_devparam[tgt].dev_refresh) { mbs.param[0] = MBOX_GET_TARGET_PARAMS; - sdp->isp_devparam[tgt].dev_refresh = 0; get = 1; } else if (sdp->isp_devparam[tgt].dev_update) { mbs.param[0] = MBOX_SET_TARGET_PARAMS; + /* * Make sure goal_flags has "Renegotiate on Error" * on and "Freeze Queue on Error" off. */ sdp->isp_devparam[tgt].goal_flags |= DPARM_RENEG; sdp->isp_devparam[tgt].goal_flags &= ~DPARM_QFRZ; - mbs.param[2] = sdp->isp_devparam[tgt].goal_flags; /* @@ -5594,26 +7005,31 @@ isp_update_bus(struct ispsoftc *isp, int bus) "bus %d set tgt %d flags 0x%x off 0x%x period 0x%x", bus, tgt, mbs.param[2], mbs.param[3] >> 8, mbs.param[3] & 0xff); - sdp->isp_devparam[tgt].dev_update = 0; - sdp->isp_devparam[tgt].dev_refresh = 1; get = 0; } else { continue; } mbs.param[1] = (bus << 15) | (tgt << 8); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + continue; + } if (get == 0) { isp->isp_sendmarker |= (1 << bus); - continue; + sdp->isp_devparam[tgt].dev_update = 0; + sdp->isp_devparam[tgt].dev_refresh = 1; + } else { + sdp->isp_devparam[tgt].dev_refresh = 0; + flags = mbs.param[2]; + period = mbs.param[3] & 0xff; + offset = mbs.param[3] >> 8; + sdp->isp_devparam[tgt].actv_flags = flags; + sdp->isp_devparam[tgt].actv_period = period; + sdp->isp_devparam[tgt].actv_offset = offset; + get = (bus << 16) | tgt; + (void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get); } - flags = mbs.param[2]; - period = mbs.param[3] & 0xff; - offset = mbs.param[3] >> 8; - sdp->isp_devparam[tgt].actv_flags = flags; - sdp->isp_devparam[tgt].actv_period = period; - sdp->isp_devparam[tgt].actv_offset = offset; - get = (bus << 16) | tgt; - (void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get); } for (tgt = 0; tgt < MAX_TARGETS; tgt++) { @@ -5625,100 +7041,16 @@ isp_update_bus(struct ispsoftc *isp, int bus) } } -#ifndef DEFAULT_FRAMESIZE -#define DEFAULT_FRAMESIZE(isp) ICB_DFLT_FRMLEN -#endif #ifndef DEFAULT_EXEC_THROTTLE #define DEFAULT_EXEC_THROTTLE(isp) ISP_EXEC_THROTTLE #endif -static void +void isp_setdfltparm(struct ispsoftc *isp, int channel) { int tgt; sdparam *sdp; - if (IS_FC(isp)) { - fcparam *fcp = (fcparam *) isp->isp_param; - int nvfail; - - fcp += channel; - if (fcp->isp_gotdparms) { - return; - } - fcp->isp_gotdparms = 1; - fcp->isp_maxfrmlen = DEFAULT_FRAMESIZE(isp); - fcp->isp_maxalloc = ICB_DFLT_ALLOC; - fcp->isp_execthrottle = DEFAULT_EXEC_THROTTLE(isp); - fcp->isp_retry_delay = ICB_DFLT_RDELAY; - fcp->isp_retry_count = ICB_DFLT_RCOUNT; - /* Platform specific.... */ - fcp->isp_loopid = DEFAULT_LOOPID(isp); - fcp->isp_nodewwn = DEFAULT_NODEWWN(isp); - fcp->isp_portwwn = DEFAULT_PORTWWN(isp); - fcp->isp_fwoptions = 0; - fcp->isp_fwoptions |= ICBOPT_FAIRNESS; - fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; - fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; -#ifndef ISP_NO_FASTPOST_FC - fcp->isp_fwoptions |= ICBOPT_FAST_POST; -#endif - if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) - fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX; - - /* - * Make sure this is turned off now until we get - * extended options from NVRAM - */ - fcp->isp_fwoptions &= ~ICBOPT_EXTENDED; - - /* - * Now try and read NVRAM unless told to not do so. - * This will set fcparam's isp_nodewwn && isp_portwwn. - */ - if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { - nvfail = isp_read_nvram(isp); - if (nvfail) - isp->isp_confopts |= ISP_CFG_NONVRAM; - } else { - nvfail = 1; - } - /* - * Set node && port to override platform set defaults - * unless the nvram read failed (or none was done), - * or the platform code wants to use what had been - * set in the defaults. - */ - 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)); - 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_PORTWWN(isp) = DEFAULT_PORTWWN(isp); - } else { - /* - * We always start out with values derived - * from NVRAM or our platform default. - */ - ISP_PORTWWN(isp) = fcp->isp_portwwn; - } - return; - } - sdp = (sdparam *) isp->isp_param; sdp += channel; @@ -5729,7 +7061,7 @@ isp_setdfltparm(struct ispsoftc *isp, int channel) return; } sdp->isp_gotdparms = 1; - + sdp->isp_bad_nvram = 0; /* * Establish some default parameters. */ @@ -5769,6 +7101,7 @@ isp_setdfltparm(struct ispsoftc *isp, int channel) if (isp_read_nvram(isp) == 0) { return; } + sdp->isp_bad_nvram = 1; } /* @@ -5779,7 +7112,8 @@ isp_setdfltparm(struct ispsoftc *isp, int channel) MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_ACT_NEG_STATE; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { sdp->isp_req_ack_active_neg = 1; sdp->isp_data_line_active_neg = 1; @@ -5817,7 +7151,7 @@ isp_setdfltparm(struct ispsoftc *isp, int channel) /* * We default to Wide/Fast for versions less than a 1040 - * (unless its SBus). + * (unless it's SBus). */ if (IS_ULTRA3(isp)) { off = ISP_80M_SYNCPARMS >> 8; @@ -5852,20 +7186,125 @@ isp_setdfltparm(struct ispsoftc *isp, int channel) } } +#ifndef DEFAULT_FRAMESIZE +#define DEFAULT_FRAMESIZE(isp) ICB_DFLT_FRMLEN +#endif +void +isp_setdfltfcparm(struct ispsoftc *isp) +{ + fcparam *fcp = FCPARAM(isp); + + if (fcp->isp_gotdparms) { + return; + } + fcp->isp_gotdparms = 1; + fcp->isp_bad_nvram = 0; + fcp->isp_maxfrmlen = DEFAULT_FRAMESIZE(isp); + fcp->isp_maxalloc = ICB_DFLT_ALLOC; + fcp->isp_execthrottle = DEFAULT_EXEC_THROTTLE(isp); + fcp->isp_retry_delay = ICB_DFLT_RDELAY; + fcp->isp_retry_count = ICB_DFLT_RCOUNT; + /* Platform specific.... */ + fcp->isp_loopid = DEFAULT_LOOPID(isp); + fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp); + fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp); + fcp->isp_fwoptions = 0; + fcp->isp_fwoptions |= ICBOPT_FAIRNESS; + fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; + fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; + fcp->isp_fwoptions |= ICBOPT_FAST_POST; + if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) { + fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX; + } + + /* + * Make sure this is turned off now until we get + * extended options from NVRAM + */ + fcp->isp_fwoptions &= ~ICBOPT_EXTENDED; + + /* + * Now try and read NVRAM unless told to not do so. + * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram. + */ + if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { + int i, j = 0; + /* + * Give a couple of tries at reading NVRAM. + */ + for (i = 0; i < 2; i++) { + j = isp_read_nvram(isp); + if (j == 0) { + break; + } + } + if (j) { + fcp->isp_bad_nvram = 1; + isp->isp_confopts |= ISP_CFG_NONVRAM; + isp->isp_confopts |= ISP_CFG_OWNWWPN; + isp->isp_confopts |= ISP_CFG_OWNWWNN; + } + } else { + isp->isp_confopts |= ISP_CFG_OWNWWPN|ISP_CFG_OWNWWNN; + } + + /* + * Set node && port to override platform set defaults + * unless the nvram read failed (or none was done), + * or the platform code wants to use what had been + * set in the defaults. + */ + 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)); + 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_wwnn_nvram; + if (fcp->isp_wwnn_nvram == 0) { + isp_prt(isp, ISP_LOGCONFIG, + "bad WWNN- using default"); + ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp); + } + } + 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_PORTWWN(isp) = DEFAULT_PORTWWN(isp); + } else { + /* + * We always start out with values derived + * from NVRAM or our platform default. + */ + ISP_PORTWWN(isp) = fcp->isp_wwpn_nvram; + if (fcp->isp_wwpn_nvram == 0) { + isp_prt(isp, ISP_LOGCONFIG, + "bad WWPN- using default"); + ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp); + } + } +} + /* * Re-initialize the ISP and complete all orphaned commands * with a 'botched' notice. The reset/init routines should * not disturb an already active list of commands. - * - * Locks held prior to coming here. */ void isp_reinit(struct ispsoftc *isp) { XS_T *xs; - u_int16_t handle; + u_int32_t tmp; + if (IS_FC(isp)) { + ISP_MARK_PORTDB(isp, 0); + } isp_reset(isp); if (isp->isp_state != ISP_RESETSTATE) { isp_prt(isp, ISP_LOGERR, "isp_reinit cannot reset card"); @@ -5877,15 +7316,36 @@ isp_reinit(struct ispsoftc *isp) if (isp->isp_state != ISP_RUNSTATE) { isp_prt(isp, ISP_LOGERR, "isp_reinit cannot restart card"); + ISP_DISABLE_INTS(isp); } - } + } else { + ISP_DISABLE_INTS(isp); + if (IS_FC(isp)) { + /* + * If we're in ISP_ROLE_NONE, turn off the lasers. + */ + if (!IS_24XX(isp)) { + 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); + } + } + } isp->isp_nactive = 0; - for (handle = 1; (int) handle <= isp->isp_maxcmds; handle++) { - xs = isp_find_xs(isp, handle); + for (tmp = 0; tmp < isp->isp_maxcmds; tmp++) { + u_int32_t handle; + + xs = isp->isp_xflist[tmp]; if (xs == NULL) { continue; } + handle = isp_find_handle(isp, xs); + if (handle == 0) { + continue; + } isp_destroy_handle(isp, handle); if (XS_XFRLEN(xs)) { ISP_DMAFREE(isp, xs, handle); @@ -5896,15 +7356,18 @@ isp_reinit(struct ispsoftc *isp) XS_SETERR(xs, HBA_BUSRESET); isp_done(xs); } +#ifdef ISP_TARGET_MODE + MEMZERO(isp->isp_tgtlist, isp->isp_maxcmds * sizeof (void **)); +#endif } /* * NVRAM Routines */ -static int +int isp_read_nvram(struct ispsoftc *isp) { - int i, amt; + int i, amt, retval; u_int8_t csum, minversion; union { u_int8_t _x[ISP2100_NVRAM_SIZE]; @@ -5913,7 +7376,9 @@ isp_read_nvram(struct ispsoftc *isp) #define nvram_data _n._x #define nvram_words _n._s - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + return (isp_read_nvram_2400(isp)); + } else if (IS_FC(isp)) { amt = ISP2100_NVRAM_SIZE; minversion = 1; } else if (IS_ULTRA2(isp)) { @@ -5924,13 +7389,10 @@ isp_read_nvram(struct ispsoftc *isp) minversion = 2; } - /* - * Just read the first two words first to see if we have a valid - * NVRAM to continue reading the rest with. - */ - for (i = 0; i < 2; i++) { + for (i = 0; i < amt>>1; i++) { isp_rdnvram_word(isp, i, &nvram_words[i]); } + if (nvram_data[0] != 'I' || nvram_data[1] != 'S' || nvram_data[2] != 'P') { if (isp->isp_bustype != ISP_BT_SBUS) { @@ -5938,22 +7400,24 @@ isp_read_nvram(struct ispsoftc *isp) isp_prt(isp, ISP_LOGDEBUG0, "%x %x %x", nvram_data[0], nvram_data[1], nvram_data[2]); } - return (-1); - } - for (i = 2; i < amt>>1; i++) { - isp_rdnvram_word(isp, i, &nvram_words[i]); + retval = -1; + goto out; } + for (csum = 0, i = 0; i < amt; i++) { csum += nvram_data[i]; } if (csum != 0) { isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum"); - return (-1); + retval = -1; + goto out; } + if (ISP_NVRAM_VERSION(nvram_data) < minversion) { isp_prt(isp, ISP_LOGWARN, "version %d NVRAM not understood", ISP_NVRAM_VERSION(nvram_data)); - return (-1); + retval = -1; + goto out; } if (IS_ULTRA3(isp)) { @@ -5970,24 +7434,66 @@ isp_read_nvram(struct ispsoftc *isp) } else { isp_parse_nvram_2100(isp, nvram_data); } - return (0); + retval = 0; +out: + return (retval); #undef nvram_data #undef nvram_words } -static void +int +isp_read_nvram_2400(struct ispsoftc *isp) +{ + u_int8_t *nvram_data = FCPARAM(isp)->isp_scratch; + int retval = 0; + u_int32_t addr, csum, lwrds, *dptr; + + if (isp->isp_port) { + addr = ISP2400_NVRAM_PORT1_ADDR; + } else { + addr = ISP2400_NVRAM_PORT0_ADDR; + } + + dptr = (u_int32_t *) nvram_data; + for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) { + isp_rd_2400_nvram(isp, addr++, dptr++); + } + if (nvram_data[0] != 'I' || nvram_data[1] != 'S' || + nvram_data[2] != 'P') { + isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)", + nvram_data[0], nvram_data[1], nvram_data[2]); + retval = -1; + goto out; + } + dptr = (u_int32_t *) nvram_data; + for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) { + u_int32_t tmp; + ISP_IOXGET_32(isp, &dptr[lwrds], tmp); + csum += tmp; + } + if (csum != 0) { + isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum"); + retval = -1; + goto out; + } + isp_parse_nvram_2400(isp, nvram_data); +out: + return (retval); +} + +void isp_rdnvram_word(struct ispsoftc *isp, int wo, u_int16_t *rp) { int i, cbits; - u_int16_t bit, rqst; + u_int16_t bit, rqst, junk; ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT); - USEC_DELAY(2); + USEC_DELAY(10); ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK); - USEC_DELAY(2); + USEC_DELAY(10); if (IS_FC(isp)) { - wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1); + wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1); if (IS_2312(isp) && isp->isp_port) { wo += 128; } @@ -6013,11 +7519,14 @@ isp_rdnvram_word(struct ispsoftc *isp, int wo, u_int16_t *rp) bit = BIU_NVRAM_SELECT; } ISP_WRITE(isp, BIU_NVRAM, bit); - USEC_DELAY(2); + USEC_DELAY(10); + junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */ ISP_WRITE(isp, BIU_NVRAM, bit | BIU_NVRAM_CLOCK); - USEC_DELAY(2); + USEC_DELAY(10); + junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */ ISP_WRITE(isp, BIU_NVRAM, bit); - USEC_DELAY(2); + USEC_DELAY(10); + junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */ } /* * Now read the result back in (bits come back in MSB format). @@ -6027,21 +7536,46 @@ isp_rdnvram_word(struct ispsoftc *isp, int wo, u_int16_t *rp) u_int16_t rv; *rp <<= 1; ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK); - USEC_DELAY(2); + USEC_DELAY(10); rv = ISP_READ(isp, BIU_NVRAM); if (rv & BIU_NVRAM_DATAIN) { *rp |= 1; } - USEC_DELAY(2); + USEC_DELAY(10); ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT); - USEC_DELAY(2); + USEC_DELAY(10); + junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */ } ISP_WRITE(isp, BIU_NVRAM, 0); - USEC_DELAY(2); + USEC_DELAY(10); + junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */ ISP_SWIZZLE_NVRAM_WORD(isp, rp); } -static void +void +isp_rd_2400_nvram(struct ispsoftc *isp, u_int32_t addr, u_int32_t *rp) +{ + int loops = 0; + const u_int32_t base = 0x7ffe0000; + u_int32_t tmp = 0; + + ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr); + for (loops = 0; loops < 5000; loops++) { + USEC_DELAY(10); + tmp = ISP_READ(isp, BIU2400_FLASH_ADDR); + if ((tmp & (1U << 31)) != 0) { + break; + } + } + if (tmp & (1U << 31)) { + *rp = ISP_READ(isp, BIU2400_FLASH_DATA); + ISP_SWIZZLE_NVRAM_LONG(isp, rp); + } else { + *rp = 0xffffffff; + } +} + +void isp_parse_nvram_1020(struct ispsoftc *isp, u_int8_t *nvram_data) { sdparam *sdp = (sdparam *) isp->isp_param; @@ -6167,7 +7701,7 @@ isp_parse_nvram_1020(struct ispsoftc *isp, u_int8_t *nvram_data) } } -static void +void isp_parse_nvram_1080(struct ispsoftc *isp, int bus, u_int8_t *nvram_data) { sdparam *sdp = (sdparam *) isp->isp_param; @@ -6259,7 +7793,7 @@ isp_parse_nvram_1080(struct ispsoftc *isp, int bus, u_int8_t *nvram_data) } } -static void +void isp_parse_nvram_12160(struct ispsoftc *isp, int bus, u_int8_t *nvram_data) { sdparam *sdp = (sdparam *) isp->isp_param; @@ -6350,10 +7884,42 @@ isp_parse_nvram_12160(struct ispsoftc *isp, int bus, u_int8_t *nvram_data) } } -static void +void +isp_fix_nvram_wwns(struct ispsoftc *isp) +{ + fcparam *fcp = FCPARAM(isp); + + /* + * Make sure we have both Node and Port as non-zero values. + */ + if (fcp->isp_wwnn_nvram != 0 && fcp->isp_wwpn_nvram == 0) { + fcp->isp_wwpn_nvram = fcp->isp_wwnn_nvram; + } else if (fcp->isp_wwnn_nvram == 0 && fcp->isp_wwpn_nvram != 0) { + fcp->isp_wwnn_nvram = fcp->isp_wwpn_nvram; + } + + /* + * Make the Node and Port values sane if they're NAA == 2. + * This means to clear bits 48..56 for the Node WWN and + * make sure that there's some non-zero value in 48..56 + * for the Port WWN. + */ + if (fcp->isp_wwnn_nvram && fcp->isp_wwpn_nvram) { + if ((fcp->isp_wwnn_nvram & (((u_int64_t) 0xfff) << 48)) != 0 && + (fcp->isp_wwnn_nvram >> 60) == 2) { + fcp->isp_wwnn_nvram &= ~((u_int64_t) 0xfff << 48); + } + if ((fcp->isp_wwpn_nvram & (((u_int64_t) 0xfff) << 48)) == 0 && + (fcp->isp_wwpn_nvram >> 60) == 2) { + fcp->isp_wwpn_nvram |= ((u_int64_t) 1 << 56); + } + } +} + +void isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data) { - fcparam *fcp = (fcparam *) isp->isp_param; + fcparam *fcp = FCPARAM(isp); u_int64_t wwn; /* @@ -6362,7 +7928,7 @@ isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data) * I can find. However, we should account for this being set * at some point in the future. * - * QLogic WWNs have an NAA of 2, but usually nothing shows up in + * Qlogic WWNs have an NAA of 2, but usually nothing shows up in * bits 48..60. In the case of the 2202, it appears that they do * use bit 48 to distinguish between the two instances on the card. * The 2204, which I've never seen, *probably* extends this method. @@ -6375,9 +7941,9 @@ isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data) wwn |= (((u_int64_t) 2)<< 60); } } - fcp->isp_portwwn = wwn; + fcp->isp_wwpn_nvram = wwn; if (IS_2200(isp) || IS_23XX(isp)) { - wwn = ISP2200_NVRAM_NODE_NAME(nvram_data); + 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), @@ -6389,70 +7955,113 @@ isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data) } else { wwn &= ~((u_int64_t) 0xfff << 48); } - fcp->isp_nodewwn = wwn; + fcp->isp_wwnn_nvram = wwn; - /* - * Make sure we have both Node and Port as non-zero values. - */ - if (fcp->isp_nodewwn != 0 && fcp->isp_portwwn == 0) { - fcp->isp_portwwn = fcp->isp_nodewwn; - } else if (fcp->isp_nodewwn == 0 && fcp->isp_portwwn != 0) { - fcp->isp_nodewwn = fcp->isp_portwwn; + isp_fix_nvram_wwns(isp); + + fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); + if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) { + fcp->isp_maxfrmlen = ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data); } + fcp->isp_retry_delay = ISP2100_NVRAM_RETRY_DELAY(nvram_data); + fcp->isp_retry_count = ISP2100_NVRAM_RETRY_COUNT(nvram_data); + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { + fcp->isp_loopid = ISP2100_NVRAM_HARDLOOPID(nvram_data); + } + if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) { + fcp->isp_execthrottle = + ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data); + } + fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data); + isp_prt(isp, ISP_LOGDEBUG0, + "NVRAM 0x%08x%08x 0x%08x%08x maxalloc %d maxframelen %d", + (u_int32_t) (fcp->isp_wwnn_nvram >> 32), (u_int32_t) fcp->isp_wwnn_nvram, + (u_int32_t) (fcp->isp_wwpn_nvram >> 32), (u_int32_t) fcp->isp_wwpn_nvram, + ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data), + ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data)); + isp_prt(isp, ISP_LOGDEBUG0, + "execthrottle %d fwoptions 0x%x hardloop %d tov %d", + ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data), + ISP2100_NVRAM_OPTIONS(nvram_data), + ISP2100_NVRAM_HARDLOOPID(nvram_data), + ISP2100_NVRAM_TOV(nvram_data)); + fcp->isp_xfwoptions = ISP2100_XFW_OPTIONS(nvram_data); + fcp->isp_zfwoptions = ISP2100_ZFW_OPTIONS(nvram_data); + isp_prt(isp, ISP_LOGDEBUG0, + "xfwoptions 0x%x zfw options 0x%x", + ISP2100_XFW_OPTIONS(nvram_data), ISP2100_ZFW_OPTIONS(nvram_data)); +} - /* - * Make the Node and Port values sane if they're NAA == 2. - * This means to clear bits 48..56 for the Node WWN and - * make sure that there's some non-zero value in 48..56 - * for the Port WWN. - */ - if (fcp->isp_nodewwn && fcp->isp_portwwn) { - if ((fcp->isp_nodewwn & (((u_int64_t) 0xfff) << 48)) != 0 && - (fcp->isp_nodewwn >> 60) == 2) { - fcp->isp_nodewwn &= ~((u_int64_t) 0xfff << 48); +void +isp_parse_nvram_2400(struct ispsoftc *isp, u_int8_t *nvram_data) +{ + fcparam *fcp = FCPARAM(isp); + u_int64_t wwn; + + isp_prt(isp, ISP_LOGDEBUG0, + "NVRAM 0x%08x%08x 0x%08x%08x exchg_cnt %d maxframelen %d", + (u_int32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32), + (u_int32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)), + (u_int32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32), + (u_int32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)), + ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data), + ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data)); + isp_prt(isp, ISP_LOGDEBUG0, + "NVRAM execthr %d loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", + ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data), + ISP2400_NVRAM_HARDLOOPID(nvram_data), + ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data), + ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data), + ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data)); + + wwn = ISP2400_NVRAM_PORT_NAME(nvram_data); + if (wwn) { + if ((wwn >> 60) != 2 && (wwn >> 60) != 5) { + wwn = 0; } - if ((fcp->isp_portwwn & (((u_int64_t) 0xfff) << 48)) == 0 && - (fcp->isp_portwwn >> 60) == 2) { - fcp->isp_portwwn |= ((u_int64_t) 1 << 56); + } + fcp->isp_wwpn_nvram = wwn; + + wwn = ISP2400_NVRAM_NODE_NAME(nvram_data); + if (wwn) { + if ((wwn >> 60) != 2 && (wwn >> 60) != 5) { + wwn = 0; } } + fcp->isp_wwnn_nvram = wwn; - isp_prt(isp, ISP_LOGDEBUG0, - "NVRAM: maxfrmlen %d execthrottle %d fwoptions 0x%x loopid %x", - ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data), - ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data), - ISP2100_NVRAM_OPTIONS(nvram_data), - ISP2100_NVRAM_HARDLOOPID(nvram_data)); - - fcp->isp_maxalloc = - ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); - if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) - fcp->isp_maxfrmlen = - ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data); - fcp->isp_retry_delay = - ISP2100_NVRAM_RETRY_DELAY(nvram_data); - fcp->isp_retry_count = - ISP2100_NVRAM_RETRY_COUNT(nvram_data); - if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) - fcp->isp_loopid = - ISP2100_NVRAM_HARDLOOPID(nvram_data); - if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) + isp_fix_nvram_wwns(isp); + + if (ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data)) { + fcp->isp_maxalloc = ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data); + } + if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) { + fcp->isp_maxfrmlen = ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data); + } + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { + fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data); + } + if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) { fcp->isp_execthrottle = - ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data); - fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data); + ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data); + } + fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data); + fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data); + fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data); } #ifdef ISP_FW_CRASH_DUMP -static void isp2200_fw_dump(struct ispsoftc *); -static void isp2300_fw_dump(struct ispsoftc *); +void isp2200_fw_dump(struct ispsoftc *); +void isp2300_fw_dump(struct ispsoftc *); -static void +void isp2200_fw_dump(struct ispsoftc *isp) { int i, j; mbreg_t mbs; u_int16_t *ptr; + MEMZERO(&mbs, sizeof (mbs)); ptr = FCPARAM(isp)->isp_dump_data; if (ptr == NULL) { isp_prt(isp, ISP_LOGERR, @@ -6571,8 +8180,7 @@ isp2200_fw_dump(struct ispsoftc *isp) break; } } - ENABLE_INTS(isp); - MEMZERO(&mbs, sizeof (mbs)); + ISP_ENABLE_INTS(isp); mbs.param[0] = MBOX_READ_RAM_WORD; mbs.param[1] = 0x1000; isp->isp_mbxworkp = (void *) ptr; @@ -6591,13 +8199,14 @@ isp2200_fw_dump(struct ispsoftc *isp) (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0); } -static void +void isp2300_fw_dump(struct ispsoftc *isp) { int i, j; mbreg_t mbs; u_int16_t *ptr; + MEMZERO(&mbs, sizeof (mbs)); ptr = FCPARAM(isp)->isp_dump_data; if (ptr == NULL) { isp_prt(isp, ISP_LOGERR, @@ -6714,7 +8323,7 @@ isp2300_fw_dump(struct ispsoftc *isp) isp_prt(isp, ISP_LOGERR, "Board Would Not Reset"); return; } - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_READ_RAM_WORD; mbs.param[1] = 0x800; @@ -6729,20 +8338,13 @@ isp2300_fw_dump(struct ispsoftc *isp) } 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); - MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_READ_RAM_WORD_EXTENDED; - mbs.param[1] = 0; + mbs.param[8] = 1; isp->isp_mbxworkp = (void *) ptr; isp->isp_mbxwrk0 = 0xffff; /* continuation count */ isp->isp_mbxwrk1 = 0x1; /* next SRAM address */ + isp->isp_mbxwrk8 = 0x1; isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGWARN, @@ -6763,5 +8365,8 @@ isp_fw_dump(struct ispsoftc *isp) isp2200_fw_dump(isp); else if (IS_23XX(isp)) isp2300_fw_dump(isp); + else if (IS_24XX(isp)) + isp_prt(isp, ISP_LOGERR, "24XX dump method undefined"); + } #endif diff --git a/sys/dev/ic/isp_library.c b/sys/dev/ic/isp_library.c index bf67fdbcd28..ffc955c0120 100644 --- a/sys/dev/ic/isp_library.c +++ b/sys/dev/ic/isp_library.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_library.c,v 1.1 2008/11/16 00:00:13 krw Exp $ */ +/* $OpenBSD: isp_library.c,v 1.2 2009/06/24 11:00:53 krw Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob * All rights reserved. @@ -28,15 +28,32 @@ /* * Qlogic Host Adapter Internal Library Functions */ - +#ifdef __NetBSD__ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD$"); +#include <dev/ic/isp_netbsd.h> +#endif +#ifdef __FreeBSD__ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/sys/dev/isp/isp_library.c,v 1.14 2007/07/02 20:08:20 mjacob Exp $"); +#include <dev/isp/isp_freebsd.h> +#endif +#ifdef __OpenBSD__ #include <dev/ic/isp_openbsd.h> +#endif +#ifdef __linux__ +#include "isp_linux.h" +#endif +#ifdef __svr4__ +#include "isp_solaris.h" +#endif int -isp_save_xs(struct ispsoftc *isp, XS_T *xs, u_int16_t *handlep) +isp_save_xs(struct ispsoftc *isp, XS_T *xs, u_int32_t *handlep) { - int i, j; + u_int16_t i, j; - for (j = isp->isp_lasthdls, i = 0; i < (int) isp->isp_maxcmds; i++) { + for (j = isp->isp_lasthdls, i = 0; i < isp->isp_maxcmds; i++) { if (isp->isp_xflist[j] == NULL) { break; } @@ -49,66 +66,58 @@ isp_save_xs(struct ispsoftc *isp, XS_T *xs, u_int16_t *handlep) } isp->isp_xflist[j] = xs; *handlep = j+1; - if (++j == isp->isp_maxcmds) + if (++j == isp->isp_maxcmds) { j = 0; - isp->isp_lasthdls = (u_int16_t)j; + } + isp->isp_lasthdls = (u_int32_t)j; return (0); } XS_T * -isp_find_xs(struct ispsoftc *isp, u_int16_t handle) +isp_find_xs(struct ispsoftc *isp, u_int32_t handle) { - if (handle < 1 || handle > (u_int16_t) isp->isp_maxcmds) { + if (handle < 1 || handle > (u_int32_t) isp->isp_maxcmds) { return (NULL); } else { return (isp->isp_xflist[handle - 1]); } } -u_int16_t +u_int32_t isp_find_handle(struct ispsoftc *isp, XS_T *xs) { - int i; + u_int16_t i; if (xs != NULL) { for (i = 0; i < isp->isp_maxcmds; i++) { if (isp->isp_xflist[i] == xs) { - return ((u_int16_t) i+1); + return ((u_int32_t) (i+1)); } } } return (0); } -int -isp_handle_index(u_int16_t handle) +u_int32_t +isp_handle_index(u_int32_t handle) { - return (handle-1); + return (handle - 1); } void -isp_destroy_handle(struct ispsoftc *isp, u_int16_t handle) +isp_destroy_handle(struct ispsoftc *isp, u_int32_t handle) { - if (handle > 0 && handle <= (u_int16_t) isp->isp_maxcmds) { - isp->isp_xflist[isp_handle_index(handle)] = NULL; + if (handle > 0 && handle <= (u_int32_t) isp->isp_maxcmds) { + isp->isp_xflist[handle - 1] = NULL; } } -void -isp_remove_handle(struct ispsoftc *isp, XS_T *xs) -{ - isp_destroy_handle(isp, isp_find_handle(isp, xs)); -} - -int -isp_getrqentry(struct ispsoftc *, u_int16_t *, u_int16_t *, void **); - int -isp_getrqentry(struct ispsoftc *isp, u_int16_t *iptrp, - u_int16_t *optrp, void **resultp) +isp_getrqentry(struct ispsoftc *isp, u_int32_t *iptrp, + u_int32_t *optrp, void **resultp) { - volatile u_int16_t iptr, optr; + volatile u_int32_t iptr, optr; - optr = isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp); + optr = isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp); iptr = isp->isp_reqidx; *resultp = ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN(isp)); @@ -122,6 +131,7 @@ isp_getrqentry(struct ispsoftc *isp, u_int16_t *iptrp, return (0); } +#define TBA (4 * (((QENTRY_LEN >> 2) * 3) + 1) + 1) void isp_print_qentry(struct ispsoftc *isp, char *msg, int idx, void *arg) { @@ -141,7 +151,7 @@ isp_print_qentry(struct ispsoftc *isp, char *msg, int idx, void *arg) } void -isp_print_bytes(struct ispsoftc *isp, char *msg, int amt, void *arg) +isp_print_bytes(struct ispsoftc *isp, const char *msg, int amt, void *arg) { char buf[128]; u_int8_t *ptr = arg; @@ -173,10 +183,6 @@ isp_print_bytes(struct ispsoftc *isp, char *msg, int amt, void *arg) * action because things may have changed while we were doing this. * Any failure or change of state causes us to return a nonzero value. * - * We honor HBA roles in that if we're not in Initiator mode, we don't - * attempt to sync up the database (that's for somebody else to do, - * if ever). - * * We assume we enter here with any locks held. */ @@ -186,35 +192,120 @@ isp_fc_runstate(struct ispsoftc *isp, int tval) fcparam *fcp; int *tptr; - if (IS_SCSI(isp)) + if (isp->isp_role == ISP_ROLE_NONE) { return (0); - - tptr = tval? &tval : NULL; - if (isp_control(isp, ISPCTL_FCLINK_TEST, tptr) != 0) { - return (-1); } fcp = FCPARAM(isp); - if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) - return (-1); - if (isp_control(isp, ISPCTL_SCAN_FABRIC, NULL) != 0) { - return (-1); - } - if (isp_control(isp, ISPCTL_SCAN_LOOP, NULL) != 0) { - return (-1); + tptr = &tval; + if (fcp->isp_fwstate < FW_READY || + fcp->isp_loopstate < LOOP_PDB_RCVD) { + if (isp_control(isp, ISPCTL_FCLINK_TEST, tptr) != 0) { + isp_prt(isp, ISP_LOGSANCFG, + "isp_fc_runstate: linktest failed"); + return (-1); + } + if (fcp->isp_fwstate != FW_READY || + fcp->isp_loopstate < LOOP_PDB_RCVD) { + isp_prt(isp, ISP_LOGSANCFG, + "isp_fc_runstate: f/w not ready"); + return (-1); + } } if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) { return (0); } + if (isp_control(isp, ISPCTL_SCAN_LOOP, NULL) != 0) { + isp_prt(isp, ISP_LOGSANCFG, + "isp_fc_runstate: scan loop fails"); + return (LOOP_PDB_RCVD); + } + if (isp_control(isp, ISPCTL_SCAN_FABRIC, NULL) != 0) { + isp_prt(isp, ISP_LOGSANCFG, + "isp_fc_runstate: scan fabric fails"); + return (LOOP_LSCAN_DONE); + } if (isp_control(isp, ISPCTL_PDB_SYNC, NULL) != 0) { - return (-1); + isp_prt(isp, ISP_LOGSANCFG, "isp_fc_runstate: pdb_sync fails"); + return (LOOP_FSCAN_DONE); } if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) { + isp_prt(isp, ISP_LOGSANCFG, + "isp_fc_runstate: f/w not ready again"); return (-1); } return (0); } /* + * Fibre Channel Support- get the port database for the id. + */ +void +isp_dump_portdb(struct ispsoftc *isp) +{ + fcparam *fcp = (fcparam *) isp->isp_param; + int i; + + for (i = 0; i < MAX_FC_TARG; i++) { + char mb[4]; + const char *dbs[8] = { + "NIL ", + "PROB", + "DEAD", + "CHGD", + "NEW ", + "PVLD", + "ZOMB", + "VLD " + }; + const char *roles[4] = { + " UNK", " TGT", " INI", "TINI" + }; + fcportdb_t *lp = &fcp->portdb[i]; + + if (lp->state == FC_PORTDB_STATE_NIL) { + continue; + } + if (lp->ini_map_idx) { + SNPRINTF(mb, sizeof (mb), "%3d", + ((int) lp->ini_map_idx) - 1); + } else { + SNPRINTF(mb, sizeof (mb), "---"); + } + isp_prt(isp, ISP_LOGALL, "%d: hdl 0x%x %s al%d tgt %s %s " + "0x%06x =>%s 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x", i, + lp->handle, dbs[lp->state], lp->autologin, mb, + roles[lp->roles], lp->portid, + roles[lp->new_roles], lp->new_portid, + (u_int32_t) (lp->node_wwn >> 32), + (u_int32_t) (lp->node_wwn), + (u_int32_t) (lp->port_wwn >> 32), + (u_int32_t) (lp->port_wwn)); + } +} + +void +isp_shutdown(struct ispsoftc *isp) +{ + if (IS_FC(isp)) { + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_ICR, 0); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); + } else { + ISP_WRITE(isp, BIU_ICR, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + 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 { + ISP_WRITE(isp, BIU_ICR, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + } +} + +/* * Functions to move stuff to a form that the QLogic RISC engine understands * and functions to move stuff back to a form the processor understands. * @@ -225,12 +316,15 @@ isp_fc_runstate(struct ispsoftc *isp, int tval) * (with a few exceptions for efficiency). */ +#define ISP_IS_SBUS(isp) \ + (ISP_SBUS_SUPPORTED && (isp)->isp_bustype == ISP_BT_SBUS) + +#define ASIZE(x) (sizeof (x) / sizeof (x[0])) /* * Swizzle/Copy Functions */ - void -isp_copy_out_hdr(struct ispsoftc *isp, isphdr_t *hpsrc, isphdr_t *hpdst) +isp_put_hdr(struct ispsoftc *isp, isphdr_t *hpsrc, isphdr_t *hpdst) { if (ISP_IS_SBUS(isp)) { ISP_IOXPUT_8(isp, hpsrc->rqs_entry_type, @@ -254,7 +348,7 @@ isp_copy_out_hdr(struct ispsoftc *isp, isphdr_t *hpsrc, isphdr_t *hpdst) } void -isp_copy_in_hdr(struct ispsoftc *isp, isphdr_t *hpsrc, isphdr_t *hpdst) +isp_get_hdr(struct ispsoftc *isp, isphdr_t *hpsrc, isphdr_t *hpdst) { if (ISP_IS_SBUS(isp)) { ISP_IOXGET_8(isp, &hpsrc->rqs_entry_type, @@ -293,7 +387,7 @@ void isp_put_request(struct ispsoftc *isp, ispreq_t *rqsrc, ispreq_t *rqdst) { int i; - isp_copy_out_hdr(isp, &rqsrc->req_header, &rqdst->req_header); + isp_put_hdr(isp, &rqsrc->req_header, &rqdst->req_header); ISP_IOXPUT_32(isp, rqsrc->req_handle, &rqdst->req_handle); if (ISP_IS_SBUS(isp)) { ISP_IOXPUT_8(isp, rqsrc->req_lun_trn, &rqdst->req_target); @@ -306,7 +400,7 @@ isp_put_request(struct ispsoftc *isp, ispreq_t *rqsrc, ispreq_t *rqdst) ISP_IOXPUT_16(isp, rqsrc->req_flags, &rqdst->req_flags); ISP_IOXPUT_16(isp, rqsrc->req_time, &rqdst->req_time); ISP_IOXPUT_16(isp, rqsrc->req_seg_count, &rqdst->req_seg_count); - for (i = 0; i < 12; i++) { + for (i = 0; i < ASIZE(rqsrc->req_cdb); i++) { ISP_IOXPUT_8(isp, rqsrc->req_cdb[i], &rqdst->req_cdb[i]); } for (i = 0; i < ISP_RQDSEG; i++) { @@ -318,153 +412,343 @@ isp_put_request(struct ispsoftc *isp, ispreq_t *rqsrc, ispreq_t *rqdst) } void -isp_put_request_t2(struct ispsoftc *isp, ispreqt2_t *tqsrc, ispreqt2_t *tqdst) +isp_put_marker(struct ispsoftc *isp, isp_marker_t *src, isp_marker_t *dst) { int i; - isp_copy_out_hdr(isp, &tqsrc->req_header, &tqdst->req_header); - ISP_IOXPUT_32(isp, tqsrc->req_handle, &tqdst->req_handle); - ISP_IOXPUT_8(isp, tqsrc->req_lun_trn, &tqdst->req_lun_trn); - ISP_IOXPUT_8(isp, tqsrc->req_target, &tqdst->req_target); - ISP_IOXPUT_16(isp, tqsrc->req_scclun, &tqdst->req_scclun); - ISP_IOXPUT_16(isp, tqsrc->req_flags, &tqdst->req_flags); - ISP_IOXPUT_16(isp, tqsrc->req_reserved, &tqdst->req_reserved); - ISP_IOXPUT_16(isp, tqsrc->req_time, &tqdst->req_time); - ISP_IOXPUT_16(isp, tqsrc->req_seg_count, &tqdst->req_seg_count); - for (i = 0; i < 16; i++) { - ISP_IOXPUT_8(isp, tqsrc->req_cdb[i], &tqdst->req_cdb[i]); + isp_put_hdr(isp, &src->mrk_header, &dst->mrk_header); + ISP_IOXPUT_32(isp, src->mrk_handle, &dst->mrk_handle); + if (ISP_IS_SBUS(isp)) { + ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_target); + ISP_IOXPUT_8(isp, src->mrk_target, &dst->mrk_reserved0); + } else { + ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_reserved0); + ISP_IOXPUT_8(isp, src->mrk_target, &dst->mrk_target); + } + ISP_IOXPUT_16(isp, src->mrk_modifier, &dst->mrk_modifier); + ISP_IOXPUT_16(isp, src->mrk_flags, &dst->mrk_flags); + ISP_IOXPUT_16(isp, src->mrk_lun, &dst->mrk_lun); + for (i = 0; i < ASIZE(src->mrk_reserved1); i++) { + ISP_IOXPUT_8(isp, src->mrk_reserved1[i], + &dst->mrk_reserved1[i]); } - ISP_IOXPUT_32(isp, tqsrc->req_totalcnt, &tqdst->req_totalcnt); +} + +void +isp_put_marker_24xx(struct ispsoftc *isp, + isp_marker_24xx_t *src, isp_marker_24xx_t *dst) +{ + int i; + isp_put_hdr(isp, &src->mrk_header, &dst->mrk_header); + ISP_IOXPUT_32(isp, src->mrk_handle, &dst->mrk_handle); + ISP_IOXPUT_16(isp, src->mrk_nphdl, &dst->mrk_nphdl); + ISP_IOXPUT_8(isp, src->mrk_modifier, &dst->mrk_modifier); + ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_reserved0); + ISP_IOXPUT_8(isp, src->mrk_reserved1, &dst->mrk_reserved1); + ISP_IOXPUT_8(isp, src->mrk_vphdl, &dst->mrk_vphdl); + ISP_IOXPUT_8(isp, src->mrk_reserved2, &dst->mrk_reserved2); + for (i = 0; i < ASIZE(src->mrk_lun); i++) { + ISP_IOXPUT_8(isp, src->mrk_lun[i], &dst->mrk_lun[i]); + } + for (i = 0; i < ASIZE(src->mrk_reserved3); i++) { + ISP_IOXPUT_8(isp, src->mrk_reserved3[i], + &dst->mrk_reserved3[i]); + } +} + +void +isp_put_request_t2(struct ispsoftc *isp, ispreqt2_t *src, ispreqt2_t *dst) +{ + int i; + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn); + ISP_IOXPUT_8(isp, src->req_target, &dst->req_target); + ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt); for (i = 0; i < ISP_RQDSEG_T2; i++) { - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_base, - &tqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_count, - &tqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_put_request_t3(struct ispsoftc *isp, ispreqt3_t *tqsrc, ispreqt3_t *tqdst) +isp_put_request_t2e(struct ispsoftc *isp, ispreqt2e_t *src, ispreqt2e_t *dst) { int i; - isp_copy_out_hdr(isp, &tqsrc->req_header, &tqdst->req_header); - ISP_IOXPUT_32(isp, tqsrc->req_handle, &tqdst->req_handle); - ISP_IOXPUT_8(isp, tqsrc->req_lun_trn, &tqdst->req_lun_trn); - ISP_IOXPUT_8(isp, tqsrc->req_target, &tqdst->req_target); - ISP_IOXPUT_16(isp, tqsrc->req_scclun, &tqdst->req_scclun); - ISP_IOXPUT_16(isp, tqsrc->req_flags, &tqdst->req_flags); - ISP_IOXPUT_16(isp, tqsrc->req_reserved, &tqdst->req_reserved); - ISP_IOXPUT_16(isp, tqsrc->req_time, &tqdst->req_time); - ISP_IOXPUT_16(isp, tqsrc->req_seg_count, &tqdst->req_seg_count); - for (i = 0; i < 16; i++) { - ISP_IOXPUT_8(isp, tqsrc->req_cdb[i], &tqdst->req_cdb[i]); + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_16(isp, src->req_target, &dst->req_target); + ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt); + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } - ISP_IOXPUT_32(isp, tqsrc->req_totalcnt, &tqdst->req_totalcnt); +} + +void +isp_put_request_t3(struct ispsoftc *isp, ispreqt3_t *src, ispreqt3_t *dst) +{ + int i; + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn); + ISP_IOXPUT_8(isp, src->req_target, &dst->req_target); + ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt); + for (i = 0; i < ISP_RQDSEG_T3; i++) { + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, + &dst->req_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); + } +} + +void +isp_put_request_t3e(struct ispsoftc *isp, ispreqt3e_t *src, ispreqt3e_t *dst) +{ + int i; + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_16(isp, src->req_target, &dst->req_target); + ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt); for (i = 0; i < ISP_RQDSEG_T3; i++) { - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_base, - &tqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_basehi, - &tqdst->req_dataseg[i].ds_basehi); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_count, - &tqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, + &dst->req_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_put_extended_request(struct ispsoftc *isp, ispextreq_t *xqsrc, - ispextreq_t *xqdst) +isp_put_extended_request(struct ispsoftc *isp, ispextreq_t *src, ispextreq_t *dst) { int i; - isp_copy_out_hdr(isp, &xqsrc->req_header, &xqdst->req_header); - ISP_IOXPUT_32(isp, xqsrc->req_handle, &xqdst->req_handle); + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, xqsrc->req_lun_trn, &xqdst->req_target); - ISP_IOXPUT_8(isp, xqsrc->req_target, &xqdst->req_lun_trn); + ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_target); + ISP_IOXPUT_8(isp, src->req_target, &dst->req_lun_trn); } else { - ISP_IOXPUT_8(isp, xqsrc->req_lun_trn, &xqdst->req_lun_trn); - ISP_IOXPUT_8(isp, xqsrc->req_target, &xqdst->req_target); + ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn); + ISP_IOXPUT_8(isp, src->req_target, &dst->req_target); } - ISP_IOXPUT_16(isp, xqsrc->req_cdblen, &xqdst->req_cdblen); - ISP_IOXPUT_16(isp, xqsrc->req_flags, &xqdst->req_flags); - ISP_IOXPUT_16(isp, xqsrc->req_time, &xqdst->req_time); - ISP_IOXPUT_16(isp, xqsrc->req_seg_count, &xqdst->req_seg_count); - for (i = 0; i < 44; i++) { - ISP_IOXPUT_8(isp, xqsrc->req_cdb[i], &xqdst->req_cdb[i]); + ISP_IOXPUT_16(isp, src->req_cdblen, &dst->req_cdblen); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); } } void -isp_put_cont_req(struct ispsoftc *isp, ispcontreq_t *cqsrc, ispcontreq_t *cqdst) +isp_put_request_t7(struct ispsoftc *isp, ispreqt7_t *src, ispreqt7_t *dst) { int i; - isp_copy_out_hdr(isp, &cqsrc->req_header, &cqdst->req_header); + u_int32_t *a, *b; + + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_16(isp, src->req_nphdl, &dst->req_nphdl); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + a = (u_int32_t *) src->req_lun; + b = (u_int32_t *) dst->req_lun; + for (i = 0; i < (ASIZE(src->req_lun) >> 2); i++ ) { + *b++ = ISP_SWAP32(isp, *a++); + } + ISP_IOXPUT_8(isp, src->req_alen_datadir, &dst->req_alen_datadir); + ISP_IOXPUT_8(isp, src->req_task_management, &dst->req_task_management); + ISP_IOXPUT_8(isp, src->req_task_attribute, &dst->req_task_attribute); + ISP_IOXPUT_8(isp, src->req_crn, &dst->req_crn); + a = (u_int32_t *) src->req_cdb; + b = (u_int32_t *) dst->req_cdb; + for (i = 0; i < (ASIZE(src->req_cdb) >> 2); i++) { + *b++ = ISP_SWAP32(isp, *a++); + } + ISP_IOXPUT_32(isp, src->req_dl, &dst->req_dl); + ISP_IOXPUT_16(isp, src->req_tidlo, &dst->req_tidlo); + ISP_IOXPUT_8(isp, src->req_tidhi, &dst->req_tidhi); + ISP_IOXPUT_8(isp, src->req_vpidx, &dst->req_vpidx); + ISP_IOXPUT_32(isp, src->req_dataseg.ds_base, + &dst->req_dataseg.ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg.ds_basehi, + &dst->req_dataseg.ds_basehi); + ISP_IOXPUT_32(isp, src->req_dataseg.ds_count, + &dst->req_dataseg.ds_count); +} + +void +isp_put_24xx_abrt(struct ispsoftc *isp, isp24xx_abrt_t *src, isp24xx_abrt_t *dst) +{ + int i; + isp_put_hdr(isp, &src->abrt_header, &dst->abrt_header); + ISP_IOXPUT_32(isp, src->abrt_handle, &dst->abrt_handle); + ISP_IOXPUT_16(isp, src->abrt_nphdl, &dst->abrt_nphdl); + ISP_IOXPUT_16(isp, src->abrt_options, &dst->abrt_options); + ISP_IOXPUT_32(isp, src->abrt_cmd_handle, &dst->abrt_cmd_handle); + for (i = 0; i < ASIZE(src->abrt_reserved); i++) { + ISP_IOXPUT_8(isp, src->abrt_reserved[i], + &dst->abrt_reserved[i]); + } + ISP_IOXPUT_16(isp, src->abrt_tidlo, &dst->abrt_tidlo); + ISP_IOXPUT_8(isp, src->abrt_tidhi, &dst->abrt_tidhi); + ISP_IOXPUT_8(isp, src->abrt_vpidx, &dst->abrt_vpidx); + for (i = 0; i < ASIZE(src->abrt_reserved1); i++) { + ISP_IOXPUT_8(isp, src->abrt_reserved1[i], + &dst->abrt_reserved1[i]); + } +} + +void +isp_put_cont_req(struct ispsoftc *isp, ispcontreq_t *src, ispcontreq_t *dst) +{ + int i; + isp_put_hdr(isp, &src->req_header, &dst->req_header); for (i = 0; i < ISP_CDSEG; i++) { - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_base, - &cqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_count, - &cqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_put_cont64_req(struct ispsoftc *isp, ispcontreq64_t *cqsrc, - ispcontreq64_t *cqdst) +isp_put_cont64_req(struct ispsoftc *isp, ispcontreq64_t *src, ispcontreq64_t *dst) { int i; - isp_copy_out_hdr(isp, &cqsrc->req_header, &cqdst->req_header); + isp_put_hdr(isp, &src->req_header, &dst->req_header); for (i = 0; i < ISP_CDSEG64; i++) { - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_base, - &cqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_basehi, - &cqdst->req_dataseg[i].ds_basehi); - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_count, - &cqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, + &dst->req_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_get_response(struct ispsoftc *isp, ispstatusreq_t *spsrc, - ispstatusreq_t *spdst) +isp_get_response(struct ispsoftc *isp, ispstatusreq_t *src, ispstatusreq_t *dst) { int i; - isp_copy_in_hdr(isp, &spsrc->req_header, &spdst->req_header); - ISP_IOXGET_32(isp, &spsrc->req_handle, spdst->req_handle); - ISP_IOXGET_16(isp, &spsrc->req_scsi_status, spdst->req_scsi_status); - ISP_IOXGET_16(isp, &spsrc->req_completion_status, - spdst->req_completion_status); - ISP_IOXGET_16(isp, &spsrc->req_state_flags, spdst->req_state_flags); - ISP_IOXGET_16(isp, &spsrc->req_status_flags, spdst->req_status_flags); - ISP_IOXGET_16(isp, &spsrc->req_time, spdst->req_time); - ISP_IOXGET_16(isp, &spsrc->req_sense_len, spdst->req_sense_len); - ISP_IOXGET_32(isp, &spsrc->req_resid, spdst->req_resid); + isp_get_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXGET_32(isp, &src->req_handle, dst->req_handle); + ISP_IOXGET_16(isp, &src->req_scsi_status, dst->req_scsi_status); + ISP_IOXGET_16(isp, &src->req_completion_status, + dst->req_completion_status); + ISP_IOXGET_16(isp, &src->req_state_flags, dst->req_state_flags); + ISP_IOXGET_16(isp, &src->req_status_flags, dst->req_status_flags); + ISP_IOXGET_16(isp, &src->req_time, dst->req_time); + ISP_IOXGET_16(isp, &src->req_sense_len, dst->req_sense_len); + ISP_IOXGET_32(isp, &src->req_resid, dst->req_resid); for (i = 0; i < 8; i++) { - ISP_IOXGET_8(isp, &spsrc->req_response[i], - spdst->req_response[i]); + ISP_IOXGET_8(isp, &src->req_response[i], + dst->req_response[i]); } for (i = 0; i < 32; i++) { - ISP_IOXGET_8(isp, &spsrc->req_sense_data[i], - spdst->req_sense_data[i]); + ISP_IOXGET_8(isp, &src->req_sense_data[i], + dst->req_sense_data[i]); + } +} + +void +isp_get_24xx_response(struct ispsoftc *isp, isp24xx_statusreq_t *src, + isp24xx_statusreq_t *dst) +{ + int i; + u_int32_t *s, *d; + + isp_get_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXGET_32(isp, &src->req_handle, dst->req_handle); + ISP_IOXGET_16(isp, &src->req_completion_status, + dst->req_completion_status); + ISP_IOXGET_16(isp, &src->req_oxid, dst->req_oxid); + ISP_IOXGET_32(isp, &src->req_resid, dst->req_resid); + ISP_IOXGET_16(isp, &src->req_reserved0, dst->req_reserved0); + ISP_IOXGET_16(isp, &src->req_state_flags, dst->req_state_flags); + ISP_IOXGET_16(isp, &src->req_reserved1, dst->req_reserved1); + ISP_IOXGET_16(isp, &src->req_scsi_status, dst->req_scsi_status); + ISP_IOXGET_32(isp, &src->req_fcp_residual, dst->req_fcp_residual); + ISP_IOXGET_32(isp, &src->req_sense_len, dst->req_sense_len); + ISP_IOXGET_32(isp, &src->req_response_len, dst->req_response_len); + s = (u_int32_t *)src->req_rsp_sense; + d = (u_int32_t *)dst->req_rsp_sense; + for (i = 0; i < (ASIZE(src->req_rsp_sense) >> 2); i++) { + d[i] = ISP_SWAP32(isp, s[i]); } } void -isp_get_response_x(struct ispsoftc *isp, ispstatus_cont_t *cpsrc, - ispstatus_cont_t *cpdst) +isp_get_24xx_abrt(struct ispsoftc *isp, isp24xx_abrt_t *src, isp24xx_abrt_t *dst) { int i; - isp_copy_in_hdr(isp, &cpsrc->req_header, &cpdst->req_header); - for (i = 0; i < 60; i++) { - ISP_IOXGET_8(isp, &cpsrc->req_sense_data[i], - cpdst->req_sense_data[i]); + isp_get_hdr(isp, &src->abrt_header, &dst->abrt_header); + ISP_IOXGET_32(isp, &src->abrt_handle, dst->abrt_handle); + ISP_IOXGET_16(isp, &src->abrt_nphdl, dst->abrt_nphdl); + ISP_IOXGET_16(isp, &src->abrt_options, dst->abrt_options); + ISP_IOXGET_32(isp, &src->abrt_cmd_handle, dst->abrt_cmd_handle); + for (i = 0; i < ASIZE(src->abrt_reserved); i++) { + ISP_IOXGET_8(isp, &src->abrt_reserved[i], + dst->abrt_reserved[i]); + } + ISP_IOXGET_16(isp, &src->abrt_tidlo, dst->abrt_tidlo); + ISP_IOXGET_8(isp, &src->abrt_tidhi, dst->abrt_tidhi); + ISP_IOXGET_8(isp, &src->abrt_vpidx, dst->abrt_vpidx); + for (i = 0; i < ASIZE(src->abrt_reserved1); i++) { + ISP_IOXGET_8(isp, &src->abrt_reserved1[i], + dst->abrt_reserved1[i]); } } + void isp_get_rio2(struct ispsoftc *isp, isp_rio2_t *r2src, isp_rio2_t *r2dst) { int i; - isp_copy_in_hdr(isp, &r2src->req_header, &r2dst->req_header); - if (r2dst->req_header.rqs_seqno > 30) + isp_get_hdr(isp, &r2src->req_header, &r2dst->req_header); + if (r2dst->req_header.rqs_seqno > 30) { r2dst->req_header.rqs_seqno = 30; + } for (i = 0; i < r2dst->req_header.rqs_seqno; i++) { ISP_IOXGET_16(isp, &r2src->req_handles[i], r2dst->req_handles[i]); @@ -475,53 +759,128 @@ isp_get_rio2(struct ispsoftc *isp, isp_rio2_t *r2src, isp_rio2_t *r2dst) } void -isp_put_icb(struct ispsoftc *isp, isp_icb_t *Is, isp_icb_t *Id) +isp_put_icb(struct ispsoftc *isp, isp_icb_t *src, isp_icb_t *dst) +{ + int i; + if (ISP_IS_SBUS(isp)) { + ISP_IOXPUT_8(isp, src->icb_version, &dst->icb_reserved0); + ISP_IOXPUT_8(isp, src->icb_reserved0, &dst->icb_version); + } else { + ISP_IOXPUT_8(isp, src->icb_version, &dst->icb_version); + ISP_IOXPUT_8(isp, src->icb_reserved0, &dst->icb_reserved0); + } + ISP_IOXPUT_16(isp, src->icb_fwoptions, &dst->icb_fwoptions); + ISP_IOXPUT_16(isp, src->icb_maxfrmlen, &dst->icb_maxfrmlen); + ISP_IOXPUT_16(isp, src->icb_maxalloc, &dst->icb_maxalloc); + ISP_IOXPUT_16(isp, src->icb_execthrottle, &dst->icb_execthrottle); + if (ISP_IS_SBUS(isp)) { + ISP_IOXPUT_8(isp, src->icb_retry_count, &dst->icb_retry_delay); + ISP_IOXPUT_8(isp, src->icb_retry_delay, &dst->icb_retry_count); + } else { + ISP_IOXPUT_8(isp, src->icb_retry_count, &dst->icb_retry_count); + ISP_IOXPUT_8(isp, src->icb_retry_delay, &dst->icb_retry_delay); + } + for (i = 0; i < 8; i++) { + ISP_IOXPUT_8(isp, src->icb_portname[i], &dst->icb_portname[i]); + } + ISP_IOXPUT_16(isp, src->icb_hardaddr, &dst->icb_hardaddr); + if (ISP_IS_SBUS(isp)) { + ISP_IOXPUT_8(isp, src->icb_iqdevtype, &dst->icb_logintime); + ISP_IOXPUT_8(isp, src->icb_logintime, &dst->icb_iqdevtype); + } else { + ISP_IOXPUT_8(isp, src->icb_iqdevtype, &dst->icb_iqdevtype); + ISP_IOXPUT_8(isp, src->icb_logintime, &dst->icb_logintime); + } + for (i = 0; i < 8; i++) { + ISP_IOXPUT_8(isp, src->icb_nodename[i], &dst->icb_nodename[i]); + } + ISP_IOXPUT_16(isp, src->icb_rqstout, &dst->icb_rqstout); + ISP_IOXPUT_16(isp, src->icb_rspnsin, &dst->icb_rspnsin); + ISP_IOXPUT_16(isp, src->icb_rqstqlen, &dst->icb_rqstqlen); + ISP_IOXPUT_16(isp, src->icb_rsltqlen, &dst->icb_rsltqlen); + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_rqstaddr[i], &dst->icb_rqstaddr[i]); + } + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_respaddr[i], &dst->icb_respaddr[i]); + } + ISP_IOXPUT_16(isp, src->icb_lunenables, &dst->icb_lunenables); + if (ISP_IS_SBUS(isp)) { + ISP_IOXPUT_8(isp, src->icb_ccnt, &dst->icb_icnt); + ISP_IOXPUT_8(isp, src->icb_icnt, &dst->icb_ccnt); + } else { + ISP_IOXPUT_8(isp, src->icb_ccnt, &dst->icb_ccnt); + ISP_IOXPUT_8(isp, src->icb_icnt, &dst->icb_icnt); + } + ISP_IOXPUT_16(isp, src->icb_lunetimeout, &dst->icb_lunetimeout); + ISP_IOXPUT_16(isp, src->icb_reserved1, &dst->icb_reserved1); + ISP_IOXPUT_16(isp, src->icb_xfwoptions, &dst->icb_xfwoptions); + if (ISP_IS_SBUS(isp)) { + ISP_IOXPUT_8(isp, src->icb_racctimer, &dst->icb_idelaytimer); + ISP_IOXPUT_8(isp, src->icb_idelaytimer, &dst->icb_racctimer); + } else { + ISP_IOXPUT_8(isp, src->icb_racctimer, &dst->icb_racctimer); + ISP_IOXPUT_8(isp, src->icb_idelaytimer, &dst->icb_idelaytimer); + } + ISP_IOXPUT_16(isp, src->icb_zfwoptions, &dst->icb_zfwoptions); +} + +void +isp_put_icb_2400(struct ispsoftc *isp, isp_icb_2400_t *src, isp_icb_2400_t *dst) { int i; - ISP_SWAP8(Is->icb_version, Is->icb_reserved0); - ISP_IOXPUT_8(isp, Is->icb_version, &Id->icb_version); - ISP_IOXPUT_8(isp, Is->icb_reserved0, &Id->icb_reserved0); - ISP_IOXPUT_16(isp, Is->icb_fwoptions, &Id->icb_fwoptions); - ISP_IOXPUT_16(isp, Is->icb_maxfrmlen, &Id->icb_maxfrmlen); - ISP_IOXPUT_16(isp, Is->icb_maxalloc, &Id->icb_maxalloc); - ISP_IOXPUT_16(isp, Is->icb_execthrottle, &Id->icb_execthrottle); - ISP_SWAP8(Is->icb_retry_count, Is->icb_retry_delay); - ISP_IOXPUT_8(isp, Is->icb_retry_count, &Id->icb_retry_count); - ISP_IOXPUT_8(isp, Is->icb_retry_delay, &Id->icb_retry_delay); + ISP_IOXPUT_16(isp, src->icb_version, &dst->icb_version); + ISP_IOXPUT_16(isp, src->icb_reserved0, &dst->icb_reserved0); + ISP_IOXPUT_16(isp, src->icb_maxfrmlen, &dst->icb_maxfrmlen); + ISP_IOXPUT_16(isp, src->icb_execthrottle, &dst->icb_execthrottle); + ISP_IOXPUT_16(isp, src->icb_xchgcnt, &dst->icb_xchgcnt); + ISP_IOXPUT_16(isp, src->icb_hardaddr, &dst->icb_hardaddr); for (i = 0; i < 8; i++) { - ISP_IOXPUT_8(isp, Is->icb_portname[i], &Id->icb_portname[i]); + ISP_IOXPUT_8(isp, src->icb_portname[i], &dst->icb_portname[i]); } - ISP_IOXPUT_16(isp, Is->icb_hardaddr, &Id->icb_hardaddr); - ISP_SWAP8(Is->icb_iqdevtype, Is->icb_logintime); - ISP_IOXPUT_8(isp, Is->icb_iqdevtype, &Id->icb_iqdevtype); - ISP_IOXPUT_8(isp, Is->icb_logintime, &Id->icb_logintime); for (i = 0; i < 8; i++) { - ISP_IOXPUT_8(isp, Is->icb_nodename[i], &Id->icb_nodename[i]); + ISP_IOXPUT_8(isp, src->icb_nodename[i], &dst->icb_nodename[i]); + } + ISP_IOXPUT_16(isp, src->icb_rspnsin, &dst->icb_rspnsin); + ISP_IOXPUT_16(isp, src->icb_rqstout, &dst->icb_rqstout); + ISP_IOXPUT_16(isp, src->icb_retry_count, &dst->icb_retry_count); + ISP_IOXPUT_16(isp, src->icb_priout, &dst->icb_priout); + ISP_IOXPUT_16(isp, src->icb_rsltqlen, &dst->icb_rsltqlen); + ISP_IOXPUT_16(isp, src->icb_rqstqlen, &dst->icb_rqstqlen); + ISP_IOXPUT_16(isp, src->icb_ldn_nols, &dst->icb_ldn_nols); + ISP_IOXPUT_16(isp, src->icb_prqstqlen, &dst->icb_prqstqlen); + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_rqstaddr[i], &dst->icb_rqstaddr[i]); + } + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_respaddr[i], &dst->icb_respaddr[i]); } - ISP_IOXPUT_16(isp, Is->icb_rqstout, &Id->icb_rqstout); - ISP_IOXPUT_16(isp, Is->icb_rspnsin, &Id->icb_rspnsin); - ISP_IOXPUT_16(isp, Is->icb_rqstqlen, &Id->icb_rqstqlen); - ISP_IOXPUT_16(isp, Is->icb_rsltqlen, &Id->icb_rsltqlen); for (i = 0; i < 4; i++) { - ISP_IOXPUT_16(isp, Is->icb_rqstaddr[i], &Id->icb_rqstaddr[i]); + ISP_IOXPUT_16(isp, src->icb_priaddr[i], &dst->icb_priaddr[i]); } for (i = 0; i < 4; i++) { - ISP_IOXPUT_16(isp, Is->icb_respaddr[i], &Id->icb_respaddr[i]); + ISP_IOXPUT_16(isp, src->icb_reserved1[i], + &dst->icb_reserved1[i]); + } + ISP_IOXPUT_16(isp, src->icb_atio_in, &dst->icb_atio_in); + ISP_IOXPUT_16(isp, src->icb_atioqlen, &dst->icb_atioqlen); + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_atioqaddr[i], + &dst->icb_atioqaddr[i]); + } + ISP_IOXPUT_16(isp, src->icb_idelaytimer, &dst->icb_idelaytimer); + ISP_IOXPUT_16(isp, src->icb_logintime, &dst->icb_logintime); + ISP_IOXPUT_32(isp, src->icb_fwoptions1, &dst->icb_fwoptions1); + ISP_IOXPUT_32(isp, src->icb_fwoptions2, &dst->icb_fwoptions2); + ISP_IOXPUT_32(isp, src->icb_fwoptions3, &dst->icb_fwoptions3); + for (i = 0; i < 12; i++) { + ISP_IOXPUT_16(isp, src->icb_reserved2[i], + &dst->icb_reserved2[i]); } - ISP_IOXPUT_16(isp, Is->icb_lunenables, &Id->icb_lunenables); - ISP_SWAP8(Is->icb_ccnt, Is->icb_icnt); - ISP_IOXPUT_8(isp, Is->icb_ccnt, &Id->icb_ccnt); - ISP_IOXPUT_8(isp, Is->icb_icnt, &Id->icb_icnt); - ISP_IOXPUT_16(isp, Is->icb_lunetimeout, &Id->icb_lunetimeout); - ISP_IOXPUT_16(isp, Is->icb_xfwoptions, &Id->icb_xfwoptions); - ISP_SWAP8(Is->icb_racctimer, Is->icb_idelaytimer); - ISP_IOXPUT_8(isp, Is->icb_racctimer, &Id->icb_racctimer); - ISP_IOXPUT_8(isp, Is->icb_idelaytimer, &Id->icb_idelaytimer); - ISP_IOXPUT_16(isp, Is->icb_zfwoptions, &Id->icb_zfwoptions); } void -isp_get_pdb(struct ispsoftc *isp, isp_pdb_t *src, isp_pdb_t *dst) +isp_get_pdb_21xx(struct ispsoftc *isp, isp_pdb_21xx_t *src, isp_pdb_21xx_t *dst) { int i; ISP_IOXGET_16(isp, &src->pdb_options, dst->pdb_options); @@ -574,29 +933,204 @@ isp_get_pdb(struct ispsoftc *isp, isp_pdb_t *src, isp_pdb_t *dst) ISP_IOXGET_16(isp, &src->pdb_sl_ptr, dst->pdb_sl_ptr); } +void +isp_get_pdb_24xx(struct ispsoftc *isp, isp_pdb_24xx_t *src, isp_pdb_24xx_t *dst) +{ + int i; + ISP_IOXGET_16(isp, &src->pdb_flags, dst->pdb_flags); + ISP_IOXGET_8(isp, &src->pdb_curstate, dst->pdb_curstate); + ISP_IOXGET_8(isp, &src->pdb_laststate, dst->pdb_laststate); + for (i = 0; i < 4; i++) { + ISP_IOXGET_8(isp, &src->pdb_hardaddr_bits[i], + dst->pdb_hardaddr_bits[i]); + } + for (i = 0; i < 4; i++) { + ISP_IOXGET_8(isp, &src->pdb_portid_bits[i], + dst->pdb_portid_bits[i]); + } + ISP_IOXGET_16(isp, &src->pdb_retry_timer, dst->pdb_retry_timer); + ISP_IOXGET_16(isp, &src->pdb_handle, dst->pdb_handle); + ISP_IOXGET_16(isp, &src->pdb_rcv_dsize, dst->pdb_rcv_dsize); + ISP_IOXGET_16(isp, &src->pdb_reserved0, dst->pdb_reserved0); + ISP_IOXGET_16(isp, &src->pdb_prli_svc0, dst->pdb_prli_svc0); + ISP_IOXGET_16(isp, &src->pdb_prli_svc3, dst->pdb_prli_svc3); + for (i = 0; i < 8; i++) { + ISP_IOXGET_8(isp, &src->pdb_nodename[i], dst->pdb_nodename[i]); + } + for (i = 0; i < 8; i++) { + ISP_IOXGET_8(isp, &src->pdb_portname[i], dst->pdb_portname[i]); + } + for (i = 0; i < 24; i++) { + ISP_IOXGET_8(isp, &src->pdb_reserved1[i], + dst->pdb_reserved1[i]); + } +} /* - * CT_HDR canonicalization- only needed for SNS responses + * PLOGI/LOGO IOCB canonicalization */ + void -isp_get_ct_hdr(struct ispsoftc *isp, ct_hdr_t *src, ct_hdr_t *dst) +isp_get_plogx(struct ispsoftc *isp, isp_plogx_t *src, isp_plogx_t *dst) +{ + int i; + isp_get_hdr(isp, &src->plogx_header, &dst->plogx_header); + ISP_IOXGET_32(isp, &src->plogx_handle, dst->plogx_handle); + ISP_IOXGET_16(isp, &src->plogx_status, dst->plogx_status); + ISP_IOXGET_16(isp, &src->plogx_nphdl, dst->plogx_nphdl); + ISP_IOXGET_16(isp, &src->plogx_flags, dst->plogx_flags); + ISP_IOXGET_16(isp, &src->plogx_vphdl, dst->plogx_vphdl); + ISP_IOXGET_16(isp, &src->plogx_portlo, dst->plogx_portlo); + ISP_IOXGET_16(isp, &src->plogx_rspsz_porthi, dst->plogx_rspsz_porthi); + for (i = 0; i < 11; i++) { + ISP_IOXGET_16(isp, &src->plogx_ioparm[i].lo16, + dst->plogx_ioparm[i].lo16); + ISP_IOXGET_16(isp, &src->plogx_ioparm[i].hi16, + dst->plogx_ioparm[i].hi16); + } +} + +void +isp_put_plogx(struct ispsoftc *isp, isp_plogx_t *src, isp_plogx_t *dst) { - ISP_IOXGET_8(isp, &src->ct_revision, dst->ct_revision); - ISP_IOXGET_8(isp, &src->ct_portid[0], dst->ct_portid[0]); - ISP_IOXGET_8(isp, &src->ct_portid[1], dst->ct_portid[1]); - ISP_IOXGET_8(isp, &src->ct_portid[2], dst->ct_portid[2]); - ISP_IOXGET_8(isp, &src->ct_fcs_type, dst->ct_fcs_type); - ISP_IOXGET_8(isp, &src->ct_fcs_subtype, dst->ct_fcs_subtype); - ISP_IOXGET_8(isp, &src->ct_options, dst->ct_options); - ISP_IOXGET_8(isp, &src->ct_res0, dst->ct_res0); - ISP_IOXGET_16(isp, &src->ct_response, dst->ct_response); - dst->ct_response = (dst->ct_response << 8) | (dst->ct_response >> 8); - ISP_IOXGET_16(isp, &src->ct_resid, dst->ct_resid); - dst->ct_resid = (dst->ct_resid << 8) | (dst->ct_resid >> 8); - ISP_IOXGET_8(isp, &src->ct_res1, dst->ct_res1); - ISP_IOXGET_8(isp, &src->ct_reason, dst->ct_reason); - ISP_IOXGET_8(isp, &src->ct_explanation, dst->ct_explanation); - ISP_IOXGET_8(isp, &src->ct_vunique, dst->ct_vunique); + int i; + isp_put_hdr(isp, &src->plogx_header, &dst->plogx_header); + ISP_IOXPUT_32(isp, src->plogx_handle, &dst->plogx_handle); + ISP_IOXPUT_16(isp, src->plogx_status, &dst->plogx_status); + ISP_IOXPUT_16(isp, src->plogx_nphdl, &dst->plogx_nphdl); + ISP_IOXPUT_16(isp, src->plogx_flags, &dst->plogx_flags); + ISP_IOXPUT_16(isp, src->plogx_vphdl, &dst->plogx_vphdl); + ISP_IOXPUT_16(isp, src->plogx_portlo, &dst->plogx_portlo); + ISP_IOXPUT_16(isp, src->plogx_rspsz_porthi, &dst->plogx_rspsz_porthi); + for (i = 0; i < 11; i++) { + ISP_IOXPUT_16(isp, src->plogx_ioparm[i].lo16, + &dst->plogx_ioparm[i].lo16); + ISP_IOXPUT_16(isp, src->plogx_ioparm[i].hi16, + &dst->plogx_ioparm[i].hi16); + } +} + +/* + * CT Passthru canonicalization + */ +void +isp_get_ct_pt(struct ispsoftc *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->ctp_header, &dst->ctp_header); + ISP_IOXGET_32(isp, &src->ctp_handle, dst->ctp_handle); + ISP_IOXGET_16(isp, &src->ctp_status, dst->ctp_status); + ISP_IOXGET_16(isp, &src->ctp_nphdl, dst->ctp_nphdl); + ISP_IOXGET_16(isp, &src->ctp_cmd_cnt, dst->ctp_cmd_cnt); + ISP_IOXGET_16(isp, &src->ctp_vpidx, dst->ctp_vpidx); + ISP_IOXGET_16(isp, &src->ctp_time, dst->ctp_time); + ISP_IOXGET_16(isp, &src->ctp_reserved0, dst->ctp_reserved0); + ISP_IOXGET_16(isp, &src->ctp_rsp_cnt, dst->ctp_rsp_cnt); + for (i = 0; i < 5; i++) { + ISP_IOXGET_16(isp, &src->ctp_reserved1[i], + dst->ctp_reserved1[i]); + } + ISP_IOXGET_32(isp, &src->ctp_rsp_bcnt, dst->ctp_rsp_bcnt); + ISP_IOXGET_32(isp, &src->ctp_cmd_bcnt, dst->ctp_cmd_bcnt); + for (i = 0; i < 2; i++) { + ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_base, + dst->ctp_dataseg[i].ds_base); + ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_basehi, + dst->ctp_dataseg[i].ds_basehi); + ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_count, + dst->ctp_dataseg[i].ds_count); + } +} + +void +isp_get_ms(struct ispsoftc *isp, isp_ms_t *src, isp_ms_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->ms_header, &dst->ms_header); + ISP_IOXGET_32(isp, &src->ms_handle, dst->ms_handle); + ISP_IOXGET_16(isp, &src->ms_nphdl, dst->ms_nphdl); + ISP_IOXGET_16(isp, &src->ms_status, dst->ms_status); + ISP_IOXGET_16(isp, &src->ms_flags, dst->ms_flags); + ISP_IOXGET_16(isp, &src->ms_reserved1, dst->ms_reserved1); + ISP_IOXGET_16(isp, &src->ms_time, dst->ms_time); + ISP_IOXGET_16(isp, &src->ms_cmd_cnt, dst->ms_cmd_cnt); + ISP_IOXGET_16(isp, &src->ms_tot_cnt, dst->ms_tot_cnt); + ISP_IOXGET_8(isp, &src->ms_type, dst->ms_type); + ISP_IOXGET_8(isp, &src->ms_r_ctl, dst->ms_r_ctl); + ISP_IOXGET_16(isp, &src->ms_rxid, dst->ms_rxid); + ISP_IOXGET_16(isp, &src->ms_reserved2, dst->ms_reserved2); + ISP_IOXGET_32(isp, &src->ms_rsp_bcnt, dst->ms_rsp_bcnt); + ISP_IOXGET_32(isp, &src->ms_cmd_bcnt, dst->ms_cmd_bcnt); + for (i = 0; i < 2; i++) { + ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_base, + dst->ms_dataseg[i].ds_base); + ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_basehi, + dst->ms_dataseg[i].ds_basehi); + ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_count, + dst->ms_dataseg[i].ds_count); + } +} + +void +isp_put_ct_pt(struct ispsoftc *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->ctp_header, &dst->ctp_header); + ISP_IOXPUT_32(isp, src->ctp_handle, &dst->ctp_handle); + ISP_IOXPUT_16(isp, src->ctp_status, &dst->ctp_status); + ISP_IOXPUT_16(isp, src->ctp_nphdl, &dst->ctp_nphdl); + ISP_IOXPUT_16(isp, src->ctp_cmd_cnt, &dst->ctp_cmd_cnt); + ISP_IOXPUT_16(isp, src->ctp_vpidx, &dst->ctp_vpidx); + ISP_IOXPUT_16(isp, src->ctp_time, &dst->ctp_time); + ISP_IOXPUT_16(isp, src->ctp_reserved0, &dst->ctp_reserved0); + ISP_IOXPUT_16(isp, src->ctp_rsp_cnt, &dst->ctp_rsp_cnt); + for (i = 0; i < 5; i++) { + ISP_IOXPUT_16(isp, src->ctp_reserved1[i], + &dst->ctp_reserved1[i]); + } + ISP_IOXPUT_32(isp, src->ctp_rsp_bcnt, &dst->ctp_rsp_bcnt); + ISP_IOXPUT_32(isp, src->ctp_cmd_bcnt, &dst->ctp_cmd_bcnt); + for (i = 0; i < 2; i++) { + ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_base, + &dst->ctp_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_basehi, + &dst->ctp_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_count, + &dst->ctp_dataseg[i].ds_count); + } +} + +void +isp_put_ms(struct ispsoftc *isp, isp_ms_t *src, isp_ms_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->ms_header, &dst->ms_header); + ISP_IOXPUT_32(isp, src->ms_handle, &dst->ms_handle); + ISP_IOXPUT_16(isp, src->ms_nphdl, &dst->ms_nphdl); + ISP_IOXPUT_16(isp, src->ms_status, &dst->ms_status); + ISP_IOXPUT_16(isp, src->ms_flags, &dst->ms_flags); + ISP_IOXPUT_16(isp, src->ms_reserved1, &dst->ms_reserved1); + ISP_IOXPUT_16(isp, src->ms_time, &dst->ms_time); + ISP_IOXPUT_16(isp, src->ms_cmd_cnt, &dst->ms_cmd_cnt); + ISP_IOXPUT_16(isp, src->ms_tot_cnt, &dst->ms_tot_cnt); + ISP_IOXPUT_8(isp, src->ms_type, &dst->ms_type); + ISP_IOXPUT_8(isp, src->ms_r_ctl, &dst->ms_r_ctl); + ISP_IOXPUT_16(isp, src->ms_rxid, &dst->ms_rxid); + ISP_IOXPUT_16(isp, src->ms_reserved2, &dst->ms_reserved2); + ISP_IOXPUT_32(isp, src->ms_rsp_bcnt, &dst->ms_rsp_bcnt); + ISP_IOXPUT_32(isp, src->ms_cmd_bcnt, &dst->ms_cmd_bcnt); + for (i = 0; i < 2; i++) { + ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_base, + &dst->ms_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_basehi, + &dst->ms_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_count, + &dst->ms_dataseg[i].ds_count); + } } /* @@ -774,330 +1308,969 @@ isp_get_ga_nxt_response(struct ispsoftc *isp, sns_ga_nxt_rsp_t *src, } } +void +isp_get_els(struct ispsoftc *isp, els_t *src, els_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->els_hdr, &dst->els_hdr); + ISP_IOXGET_32(isp, &src->els_handle, dst->els_handle); + ISP_IOXGET_16(isp, &src->els_status, dst->els_status); + ISP_IOXGET_16(isp, &src->els_nphdl, dst->els_nphdl); + ISP_IOXGET_16(isp, &src->els_xmit_dsd_count, dst->els_xmit_dsd_count); + ISP_IOXGET_8(isp, &src->els_vphdl, dst->els_vphdl); + ISP_IOXGET_8(isp, &src->els_sof, dst->els_sof); + ISP_IOXGET_32(isp, &src->els_rxid, dst->els_rxid); + ISP_IOXGET_16(isp, &src->els_recv_dsd_count, dst->els_recv_dsd_count); + ISP_IOXGET_8(isp, &src->els_opcode, dst->els_opcode); + ISP_IOXGET_8(isp, &src->els_reserved2, dst->els_reserved1); + ISP_IOXGET_8(isp, &src->els_did_lo, dst->els_did_lo); + ISP_IOXGET_8(isp, &src->els_did_mid, dst->els_did_mid); + ISP_IOXGET_8(isp, &src->els_did_hi, dst->els_did_hi); + ISP_IOXGET_8(isp, &src->els_reserved2, dst->els_reserved2); + ISP_IOXGET_16(isp, &src->els_reserved3, dst->els_reserved3); + ISP_IOXGET_16(isp, &src->els_ctl_flags, dst->els_ctl_flags); + ISP_IOXGET_32(isp, &src->els_bytecnt, dst->els_bytecnt); + ISP_IOXGET_32(isp, &src->els_subcode1, dst->els_subcode1); + ISP_IOXGET_32(isp, &src->els_subcode2, dst->els_subcode2); + for (i = 0; i < 20; i++) { + ISP_IOXGET_8(isp, &src->els_reserved4[i], + dst->els_reserved4[i]); + } +} + +void +isp_put_els(struct ispsoftc *isp, els_t *src, els_t *dst) +{ + isp_put_hdr(isp, &src->els_hdr, &dst->els_hdr); + ISP_IOXPUT_32(isp, src->els_handle, &dst->els_handle); + ISP_IOXPUT_16(isp, src->els_status, &dst->els_status); + ISP_IOXPUT_16(isp, src->els_nphdl, &dst->els_nphdl); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_count, &dst->els_xmit_dsd_count); + ISP_IOXPUT_8(isp, src->els_vphdl, &dst->els_vphdl); + ISP_IOXPUT_8(isp, src->els_sof, &dst->els_sof); + ISP_IOXPUT_32(isp, src->els_rxid, &dst->els_rxid); + ISP_IOXPUT_16(isp, src->els_recv_dsd_count, &dst->els_recv_dsd_count); + ISP_IOXPUT_8(isp, src->els_opcode, &dst->els_opcode); + ISP_IOXPUT_8(isp, src->els_reserved2, &dst->els_reserved1); + ISP_IOXPUT_8(isp, src->els_did_lo, &dst->els_did_lo); + ISP_IOXPUT_8(isp, src->els_did_mid, &dst->els_did_mid); + ISP_IOXPUT_8(isp, src->els_did_hi, &dst->els_did_hi); + ISP_IOXPUT_8(isp, src->els_reserved2, &dst->els_reserved2); + ISP_IOXPUT_16(isp, src->els_reserved3, &dst->els_reserved3); + ISP_IOXPUT_16(isp, src->els_ctl_flags, &dst->els_ctl_flags); + ISP_IOXPUT_32(isp, src->els_recv_bytecnt, &dst->els_recv_bytecnt); + ISP_IOXPUT_32(isp, src->els_xmit_bytecnt, &dst->els_xmit_bytecnt); + ISP_IOXPUT_32(isp, src->els_xmit_dsd_length, &dst->els_xmit_dsd_length); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_a1500, &dst->els_xmit_dsd_a1500); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_a3116, &dst->els_xmit_dsd_a3116); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_a4732, &dst->els_xmit_dsd_a4732); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_a6348, &dst->els_xmit_dsd_a6348); + ISP_IOXPUT_32(isp, src->els_recv_dsd_length, &dst->els_recv_dsd_length); + ISP_IOXPUT_16(isp, src->els_recv_dsd_a1500, &dst->els_recv_dsd_a1500); + ISP_IOXPUT_16(isp, src->els_recv_dsd_a3116, &dst->els_recv_dsd_a3116); + ISP_IOXPUT_16(isp, src->els_recv_dsd_a4732, &dst->els_recv_dsd_a4732); + ISP_IOXPUT_16(isp, src->els_recv_dsd_a6348, &dst->els_recv_dsd_a6348); +} + +/* + * FC Structure Canonicalization + */ + +void +isp_get_fc_hdr(struct ispsoftc *isp, fc_hdr_t *src, fc_hdr_t *dst) +{ + ISP_IOZGET_8(isp, &src->r_ctl, dst->r_ctl); + ISP_IOZGET_8(isp, &src->d_id[0], dst->d_id[0]); + ISP_IOZGET_8(isp, &src->d_id[1], dst->d_id[1]); + ISP_IOZGET_8(isp, &src->d_id[2], dst->d_id[2]); + ISP_IOZGET_8(isp, &src->cs_ctl, dst->cs_ctl); + ISP_IOZGET_8(isp, &src->s_id[0], dst->s_id[0]); + ISP_IOZGET_8(isp, &src->s_id[1], dst->s_id[1]); + ISP_IOZGET_8(isp, &src->s_id[2], dst->s_id[2]); + ISP_IOZGET_8(isp, &src->type, dst->type); + ISP_IOZGET_8(isp, &src->f_ctl, dst->f_ctl); + ISP_IOZGET_8(isp, &src->seq_id, dst->seq_id); + ISP_IOZGET_8(isp, &src->df_ctl, dst->df_ctl); + ISP_IOZGET_16(isp, &src->seq_cnt, dst->seq_cnt); + /* XXX SOMETHING WAS AND STILL CONTINUES WRONG HERE XXX */ +#if 0 + ISP_IOZGET_16(isp, &src->ox_id, dst->ox_id); + ISP_IOZGET_16(isp, &src->rx_id, dst->rx_id); +#else + ISP_IOZGET_32(isp, &src->ox_id, dst->parameter); + dst->ox_id = dst->parameter; + dst->rx_id = dst->parameter >> 16; +#endif + ISP_IOZGET_32(isp, &src->parameter, dst->parameter); +} + +void +isp_get_fcp_cmnd_iu(struct ispsoftc *isp, fcp_cmnd_iu_t *src, fcp_cmnd_iu_t *dst) +{ + int i; + + for (i = 0; i < 8; i++) { + ISP_IOZGET_8(isp, &src->fcp_cmnd_lun[i], dst->fcp_cmnd_lun[i]); + } + ISP_IOZGET_8(isp, &src->fcp_cmnd_crn, dst->fcp_cmnd_crn); + ISP_IOZGET_8(isp, &src->fcp_cmnd_task_attribute, + dst->fcp_cmnd_task_attribute); + ISP_IOZGET_8(isp, &src->fcp_cmnd_task_management, + dst->fcp_cmnd_task_management); + ISP_IOZGET_8(isp, &src->fcp_cmnd_alen_datadir, + dst->fcp_cmnd_alen_datadir); + for (i = 0; i < 16; i++) { + ISP_IOZGET_8(isp, &src->cdb_dl.sf.fcp_cmnd_cdb[i], + dst->cdb_dl.sf.fcp_cmnd_cdb[i]); + } + ISP_IOZGET_32(isp, &src->cdb_dl.sf.fcp_cmnd_dl, + dst->cdb_dl.sf.fcp_cmnd_dl); +} + +void +isp_put_rft_id(struct ispsoftc *isp, rft_id_t *src, rft_id_t *dst) +{ + int i; + isp_put_ct_hdr(isp, &src->rftid_hdr, &dst->rftid_hdr); + ISP_IOZPUT_8(isp, src->rftid_reserved, &dst->rftid_reserved); + for (i = 0; i < 3; i++) { + ISP_IOZPUT_8(isp, src->rftid_portid[i], &dst->rftid_portid[i]); + } + for (i = 0; i < 8; i++) { + ISP_IOZPUT_32(isp, src->rftid_fc4types[i], + &dst->rftid_fc4types[i]); + } +} + +void +isp_get_ct_hdr(struct ispsoftc *isp, ct_hdr_t *src, ct_hdr_t *dst) +{ + ISP_IOZGET_8(isp, &src->ct_revision, dst->ct_revision); + ISP_IOZGET_8(isp, &src->ct_in_id[0], dst->ct_in_id[0]); + ISP_IOZGET_8(isp, &src->ct_in_id[1], dst->ct_in_id[1]); + ISP_IOZGET_8(isp, &src->ct_in_id[2], dst->ct_in_id[2]); + ISP_IOZGET_8(isp, &src->ct_fcs_type, dst->ct_fcs_type); + ISP_IOZGET_8(isp, &src->ct_fcs_subtype, dst->ct_fcs_subtype); + ISP_IOZGET_8(isp, &src->ct_options, dst->ct_options); + ISP_IOZGET_8(isp, &src->ct_reserved0, dst->ct_reserved0); + ISP_IOZGET_16(isp, &src->ct_cmd_resp, dst->ct_cmd_resp); + ISP_IOZGET_16(isp, &src->ct_bcnt_resid, dst->ct_bcnt_resid); + ISP_IOZGET_8(isp, &src->ct_reserved1, dst->ct_reserved1); + ISP_IOZGET_8(isp, &src->ct_reason, dst->ct_reason); + ISP_IOZGET_8(isp, &src->ct_explanation, dst->ct_explanation); + ISP_IOZGET_8(isp, &src->ct_vunique, dst->ct_vunique); +} + +void +isp_put_ct_hdr(struct ispsoftc *isp, ct_hdr_t *src, ct_hdr_t *dst) +{ + ISP_IOZPUT_8(isp, src->ct_revision, &dst->ct_revision); + ISP_IOZPUT_8(isp, src->ct_in_id[0], &dst->ct_in_id[0]); + ISP_IOZPUT_8(isp, src->ct_in_id[1], &dst->ct_in_id[1]); + ISP_IOZPUT_8(isp, src->ct_in_id[2], &dst->ct_in_id[2]); + ISP_IOZPUT_8(isp, src->ct_fcs_type, &dst->ct_fcs_type); + ISP_IOZPUT_8(isp, src->ct_fcs_subtype, &dst->ct_fcs_subtype); + ISP_IOZPUT_8(isp, src->ct_options, &dst->ct_options); + ISP_IOZPUT_8(isp, src->ct_reserved0, &dst->ct_reserved0); + ISP_IOZPUT_16(isp, src->ct_cmd_resp, &dst->ct_cmd_resp); + ISP_IOZPUT_16(isp, src->ct_bcnt_resid, &dst->ct_bcnt_resid); + ISP_IOZPUT_8(isp, src->ct_reserved1, &dst->ct_reserved1); + ISP_IOZPUT_8(isp, src->ct_reason, &dst->ct_reason); + ISP_IOZPUT_8(isp, src->ct_explanation, &dst->ct_explanation); + ISP_IOZPUT_8(isp, src->ct_vunique, &dst->ct_vunique); +} + #ifdef ISP_TARGET_MODE +int +isp_save_xs_tgt(struct ispsoftc *isp, void *xs, u_int32_t *handlep) +{ + int i; + + for (i = 0; i < (int) isp->isp_maxcmds; i++) { + if (isp->isp_tgtlist[i] == NULL) { + break; + } + } + if (i == isp->isp_maxcmds) { + return (-1); + } + isp->isp_tgtlist[i] = xs; + *handlep = (i+1) | 0x8000; + return (0); +} + +void * +isp_find_xs_tgt(struct ispsoftc *isp, u_int32_t handle) +{ + if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 || + (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) { + isp_prt(isp, ISP_LOGERR, "bad handle in isp_find_xs_tgt"); + return (NULL); + } else { + return (isp->isp_tgtlist[(handle & ISP_HANDLE_MASK) - 1]); + } +} + +u_int32_t +isp_find_tgt_handle(struct ispsoftc *isp, void *xs) +{ + int i; + if (xs != NULL) { + for (i = 0; i < isp->isp_maxcmds; i++) { + if (isp->isp_tgtlist[i] == xs) { + return ((i+1) & ISP_HANDLE_MASK); + } + } + } + return (0); +} + void -isp_put_atio(struct ispsoftc *isp, at_entry_t *atsrc, at_entry_t *atdst) +isp_destroy_tgt_handle(struct ispsoftc *isp, u_int32_t handle) +{ + if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 || + (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) { + isp_prt(isp, ISP_LOGERR, + "bad handle in isp_destroy_tgt_handle"); + } else { + isp->isp_tgtlist[(handle & ISP_HANDLE_MASK) - 1] = NULL; + } +} + +void +isp_put_atio(struct ispsoftc *isp, at_entry_t *src, at_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXPUT_16(isp, atsrc->at_reserved, &atdst->at_reserved); - ISP_IOXPUT_16(isp, atsrc->at_handle, &atdst->at_handle); + isp_put_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXPUT_16(isp, src->at_reserved, &dst->at_reserved); + ISP_IOXPUT_16(isp, src->at_handle, &dst->at_handle); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, atsrc->at_lun, &atdst->at_iid); - ISP_IOXPUT_8(isp, atsrc->at_iid, &atdst->at_lun); - ISP_IOXPUT_8(isp, atsrc->at_cdblen, &atdst->at_tgt); - ISP_IOXPUT_8(isp, atsrc->at_tgt, &atdst->at_cdblen); - ISP_IOXPUT_8(isp, atsrc->at_status, &atdst->at_scsi_status); - ISP_IOXPUT_8(isp, atsrc->at_scsi_status, &atdst->at_status); - ISP_IOXPUT_8(isp, atsrc->at_tag_val, &atdst->at_tag_type); - ISP_IOXPUT_8(isp, atsrc->at_tag_type, &atdst->at_tag_val); + ISP_IOXPUT_8(isp, src->at_lun, &dst->at_iid); + ISP_IOXPUT_8(isp, src->at_iid, &dst->at_lun); + ISP_IOXPUT_8(isp, src->at_cdblen, &dst->at_tgt); + ISP_IOXPUT_8(isp, src->at_tgt, &dst->at_cdblen); + ISP_IOXPUT_8(isp, src->at_status, &dst->at_scsi_status); + ISP_IOXPUT_8(isp, src->at_scsi_status, &dst->at_status); + ISP_IOXPUT_8(isp, src->at_tag_val, &dst->at_tag_type); + ISP_IOXPUT_8(isp, src->at_tag_type, &dst->at_tag_val); } else { - ISP_IOXPUT_8(isp, atsrc->at_lun, &atdst->at_lun); - ISP_IOXPUT_8(isp, atsrc->at_iid, &atdst->at_iid); - ISP_IOXPUT_8(isp, atsrc->at_cdblen, &atdst->at_cdblen); - ISP_IOXPUT_8(isp, atsrc->at_tgt, &atdst->at_tgt); - ISP_IOXPUT_8(isp, atsrc->at_status, &atdst->at_status); - ISP_IOXPUT_8(isp, atsrc->at_scsi_status, - &atdst->at_scsi_status); - ISP_IOXPUT_8(isp, atsrc->at_tag_val, &atdst->at_tag_val); - ISP_IOXPUT_8(isp, atsrc->at_tag_type, &atdst->at_tag_type); - } - ISP_IOXPUT_32(isp, atsrc->at_flags, &atdst->at_flags); + ISP_IOXPUT_8(isp, src->at_lun, &dst->at_lun); + ISP_IOXPUT_8(isp, src->at_iid, &dst->at_iid); + ISP_IOXPUT_8(isp, src->at_cdblen, &dst->at_cdblen); + ISP_IOXPUT_8(isp, src->at_tgt, &dst->at_tgt); + ISP_IOXPUT_8(isp, src->at_status, &dst->at_status); + ISP_IOXPUT_8(isp, src->at_scsi_status, + &dst->at_scsi_status); + ISP_IOXPUT_8(isp, src->at_tag_val, &dst->at_tag_val); + ISP_IOXPUT_8(isp, src->at_tag_type, &dst->at_tag_type); + } + ISP_IOXPUT_32(isp, src->at_flags, &dst->at_flags); for (i = 0; i < ATIO_CDBLEN; i++) { - ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]); + ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]); } for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXPUT_8(isp, atsrc->at_sense[i], &atdst->at_sense[i]); + ISP_IOXPUT_8(isp, src->at_sense[i], &dst->at_sense[i]); } } void -isp_get_atio(struct ispsoftc *isp, at_entry_t *atsrc, at_entry_t *atdst) +isp_get_atio(struct ispsoftc *isp, at_entry_t *src, at_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXGET_16(isp, &atsrc->at_reserved, atdst->at_reserved); - ISP_IOXGET_16(isp, &atsrc->at_handle, atdst->at_handle); + isp_get_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXGET_16(isp, &src->at_reserved, dst->at_reserved); + ISP_IOXGET_16(isp, &src->at_handle, dst->at_handle); if (ISP_IS_SBUS(isp)) { - ISP_IOXGET_8(isp, &atsrc->at_lun, atdst->at_iid); - ISP_IOXGET_8(isp, &atsrc->at_iid, atdst->at_lun); - ISP_IOXGET_8(isp, &atsrc->at_cdblen, atdst->at_tgt); - ISP_IOXGET_8(isp, &atsrc->at_tgt, atdst->at_cdblen); - ISP_IOXGET_8(isp, &atsrc->at_status, atdst->at_scsi_status); - ISP_IOXGET_8(isp, &atsrc->at_scsi_status, atdst->at_status); - ISP_IOXGET_8(isp, &atsrc->at_tag_val, atdst->at_tag_type); - ISP_IOXGET_8(isp, &atsrc->at_tag_type, atdst->at_tag_val); + ISP_IOXGET_8(isp, &src->at_lun, dst->at_iid); + ISP_IOXGET_8(isp, &src->at_iid, dst->at_lun); + ISP_IOXGET_8(isp, &src->at_cdblen, dst->at_tgt); + ISP_IOXGET_8(isp, &src->at_tgt, dst->at_cdblen); + ISP_IOXGET_8(isp, &src->at_status, dst->at_scsi_status); + ISP_IOXGET_8(isp, &src->at_scsi_status, dst->at_status); + ISP_IOXGET_8(isp, &src->at_tag_val, dst->at_tag_type); + ISP_IOXGET_8(isp, &src->at_tag_type, dst->at_tag_val); } else { - ISP_IOXGET_8(isp, &atsrc->at_lun, atdst->at_lun); - ISP_IOXGET_8(isp, &atsrc->at_iid, atdst->at_iid); - ISP_IOXGET_8(isp, &atsrc->at_cdblen, atdst->at_cdblen); - ISP_IOXGET_8(isp, &atsrc->at_tgt, atdst->at_tgt); - ISP_IOXGET_8(isp, &atsrc->at_status, atdst->at_status); - ISP_IOXGET_8(isp, &atsrc->at_scsi_status, - atdst->at_scsi_status); - ISP_IOXGET_8(isp, &atsrc->at_tag_val, atdst->at_tag_val); - ISP_IOXGET_8(isp, &atsrc->at_tag_type, atdst->at_tag_type); - } - ISP_IOXGET_32(isp, &atsrc->at_flags, atdst->at_flags); + ISP_IOXGET_8(isp, &src->at_lun, dst->at_lun); + ISP_IOXGET_8(isp, &src->at_iid, dst->at_iid); + ISP_IOXGET_8(isp, &src->at_cdblen, dst->at_cdblen); + ISP_IOXGET_8(isp, &src->at_tgt, dst->at_tgt); + ISP_IOXGET_8(isp, &src->at_status, dst->at_status); + ISP_IOXGET_8(isp, &src->at_scsi_status, + dst->at_scsi_status); + ISP_IOXGET_8(isp, &src->at_tag_val, dst->at_tag_val); + ISP_IOXGET_8(isp, &src->at_tag_type, dst->at_tag_type); + } + ISP_IOXGET_32(isp, &src->at_flags, dst->at_flags); for (i = 0; i < ATIO_CDBLEN; i++) { - ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]); + ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]); } for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXGET_8(isp, &atsrc->at_sense[i], atdst->at_sense[i]); + ISP_IOXGET_8(isp, &src->at_sense[i], dst->at_sense[i]); } } void -isp_put_atio2(struct ispsoftc *isp, at2_entry_t *atsrc, at2_entry_t *atdst) +isp_put_atio2(struct ispsoftc *isp, at2_entry_t *src, at2_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXPUT_32(isp, atsrc->at_reserved, &atdst->at_reserved); - ISP_IOXPUT_8(isp, atsrc->at_lun, &atdst->at_lun); - ISP_IOXPUT_8(isp, atsrc->at_iid, &atdst->at_iid); - ISP_IOXPUT_16(isp, atsrc->at_rxid, &atdst->at_rxid); - ISP_IOXPUT_16(isp, atsrc->at_flags, &atdst->at_flags); - ISP_IOXPUT_16(isp, atsrc->at_status, &atdst->at_status); - ISP_IOXPUT_8(isp, atsrc->at_reserved1, &atdst->at_reserved1); - ISP_IOXPUT_8(isp, atsrc->at_taskcodes, &atdst->at_taskcodes); - ISP_IOXPUT_8(isp, atsrc->at_taskflags, &atdst->at_taskflags); - ISP_IOXPUT_8(isp, atsrc->at_execodes, &atdst->at_execodes); + isp_put_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXPUT_32(isp, src->at_reserved, &dst->at_reserved); + ISP_IOXPUT_8(isp, src->at_lun, &dst->at_lun); + ISP_IOXPUT_8(isp, src->at_iid, &dst->at_iid); + ISP_IOXPUT_16(isp, src->at_rxid, &dst->at_rxid); + ISP_IOXPUT_16(isp, src->at_flags, &dst->at_flags); + ISP_IOXPUT_16(isp, src->at_status, &dst->at_status); + ISP_IOXPUT_8(isp, src->at_crn, &dst->at_crn); + ISP_IOXPUT_8(isp, src->at_taskcodes, &dst->at_taskcodes); + ISP_IOXPUT_8(isp, src->at_taskflags, &dst->at_taskflags); + ISP_IOXPUT_8(isp, src->at_execodes, &dst->at_execodes); for (i = 0; i < ATIO2_CDBLEN; i++) { - ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]); + ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]); } - ISP_IOXPUT_32(isp, atsrc->at_datalen, &atdst->at_datalen); - ISP_IOXPUT_16(isp, atsrc->at_scclun, &atdst->at_scclun); + ISP_IOXPUT_32(isp, src->at_datalen, &dst->at_datalen); + ISP_IOXPUT_16(isp, src->at_scclun, &dst->at_scclun); for (i = 0; i < 4; i++) { - ISP_IOXPUT_16(isp, atsrc->at_wwpn[i], &atdst->at_wwpn[i]); + ISP_IOXPUT_16(isp, src->at_wwpn[i], &dst->at_wwpn[i]); } for (i = 0; i < 6; i++) { - ISP_IOXPUT_16(isp, atsrc->at_reserved2[i], - &atdst->at_reserved2[i]); + ISP_IOXPUT_16(isp, src->at_reserved2[i], + &dst->at_reserved2[i]); } - ISP_IOXPUT_16(isp, atsrc->at_oxid, &atdst->at_oxid); + ISP_IOXPUT_16(isp, src->at_oxid, &dst->at_oxid); } void -isp_get_atio2(struct ispsoftc *isp, at2_entry_t *atsrc, at2_entry_t *atdst) +isp_put_atio2e(struct ispsoftc *isp, at2e_entry_t *src, at2e_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXGET_32(isp, &atsrc->at_reserved, atdst->at_reserved); - ISP_IOXGET_8(isp, &atsrc->at_lun, atdst->at_lun); - ISP_IOXGET_8(isp, &atsrc->at_iid, atdst->at_iid); - ISP_IOXGET_16(isp, &atsrc->at_rxid, atdst->at_rxid); - ISP_IOXGET_16(isp, &atsrc->at_flags, atdst->at_flags); - ISP_IOXGET_16(isp, &atsrc->at_status, atdst->at_status); - ISP_IOXGET_8(isp, &atsrc->at_reserved1, atdst->at_reserved1); - ISP_IOXGET_8(isp, &atsrc->at_taskcodes, atdst->at_taskcodes); - ISP_IOXGET_8(isp, &atsrc->at_taskflags, atdst->at_taskflags); - ISP_IOXGET_8(isp, &atsrc->at_execodes, atdst->at_execodes); + isp_put_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXPUT_32(isp, src->at_reserved, &dst->at_reserved); + ISP_IOXPUT_16(isp, src->at_iid, &dst->at_iid); + ISP_IOXPUT_16(isp, src->at_rxid, &dst->at_rxid); + ISP_IOXPUT_16(isp, src->at_flags, &dst->at_flags); + ISP_IOXPUT_16(isp, src->at_status, &dst->at_status); + ISP_IOXPUT_8(isp, src->at_crn, &dst->at_crn); + ISP_IOXPUT_8(isp, src->at_taskcodes, &dst->at_taskcodes); + ISP_IOXPUT_8(isp, src->at_taskflags, &dst->at_taskflags); + ISP_IOXPUT_8(isp, src->at_execodes, &dst->at_execodes); for (i = 0; i < ATIO2_CDBLEN; i++) { - ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]); + ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]); } - ISP_IOXGET_32(isp, &atsrc->at_datalen, atdst->at_datalen); - ISP_IOXGET_16(isp, &atsrc->at_scclun, atdst->at_scclun); + ISP_IOXPUT_32(isp, src->at_datalen, &dst->at_datalen); + ISP_IOXPUT_16(isp, src->at_scclun, &dst->at_scclun); for (i = 0; i < 4; i++) { - ISP_IOXGET_16(isp, &atsrc->at_wwpn[i], atdst->at_wwpn[i]); + ISP_IOXPUT_16(isp, src->at_wwpn[i], &dst->at_wwpn[i]); } for (i = 0; i < 6; i++) { - ISP_IOXGET_16(isp, &atsrc->at_reserved2[i], - atdst->at_reserved2[i]); + ISP_IOXPUT_16(isp, src->at_reserved2[i], + &dst->at_reserved2[i]); } - ISP_IOXGET_16(isp, &atsrc->at_oxid, atdst->at_oxid); + ISP_IOXPUT_16(isp, src->at_oxid, &dst->at_oxid); } void -isp_put_ctio(struct ispsoftc *isp, ct_entry_t *ctsrc, ct_entry_t *ctdst) +isp_get_atio2(struct ispsoftc *isp, at2_entry_t *src, at2_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXPUT_16(isp, ctsrc->ct_reserved, &ctdst->ct_reserved); - ISP_IOXPUT_16(isp, ctsrc->ct_fwhandle, &ctdst->ct_fwhandle); + isp_get_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXGET_32(isp, &src->at_reserved, dst->at_reserved); + ISP_IOXGET_8(isp, &src->at_lun, dst->at_lun); + ISP_IOXGET_8(isp, &src->at_iid, dst->at_iid); + ISP_IOXGET_16(isp, &src->at_rxid, dst->at_rxid); + ISP_IOXGET_16(isp, &src->at_flags, dst->at_flags); + ISP_IOXGET_16(isp, &src->at_status, dst->at_status); + ISP_IOXGET_8(isp, &src->at_crn, dst->at_crn); + ISP_IOXGET_8(isp, &src->at_taskcodes, dst->at_taskcodes); + ISP_IOXGET_8(isp, &src->at_taskflags, dst->at_taskflags); + ISP_IOXGET_8(isp, &src->at_execodes, dst->at_execodes); + for (i = 0; i < ATIO2_CDBLEN; i++) { + ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]); + } + ISP_IOXGET_32(isp, &src->at_datalen, dst->at_datalen); + ISP_IOXGET_16(isp, &src->at_scclun, dst->at_scclun); + for (i = 0; i < 4; i++) { + ISP_IOXGET_16(isp, &src->at_wwpn[i], dst->at_wwpn[i]); + } + for (i = 0; i < 6; i++) { + ISP_IOXGET_16(isp, &src->at_reserved2[i], + dst->at_reserved2[i]); + } + ISP_IOXGET_16(isp, &src->at_oxid, dst->at_oxid); +} + +void +isp_get_atio2e(struct ispsoftc *isp, at2e_entry_t *src, at2e_entry_t *dst) +{ + int i; + isp_get_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXGET_32(isp, &src->at_reserved, dst->at_reserved); + ISP_IOXGET_16(isp, &src->at_iid, dst->at_iid); + ISP_IOXGET_16(isp, &src->at_rxid, dst->at_rxid); + ISP_IOXGET_16(isp, &src->at_flags, dst->at_flags); + ISP_IOXGET_16(isp, &src->at_status, dst->at_status); + ISP_IOXGET_8(isp, &src->at_crn, dst->at_crn); + ISP_IOXGET_8(isp, &src->at_taskcodes, dst->at_taskcodes); + ISP_IOXGET_8(isp, &src->at_taskflags, dst->at_taskflags); + ISP_IOXGET_8(isp, &src->at_execodes, dst->at_execodes); + for (i = 0; i < ATIO2_CDBLEN; i++) { + ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]); + } + ISP_IOXGET_32(isp, &src->at_datalen, dst->at_datalen); + ISP_IOXGET_16(isp, &src->at_scclun, dst->at_scclun); + for (i = 0; i < 4; i++) { + ISP_IOXGET_16(isp, &src->at_wwpn[i], dst->at_wwpn[i]); + } + for (i = 0; i < 6; i++) { + ISP_IOXGET_16(isp, &src->at_reserved2[i], + dst->at_reserved2[i]); + } + ISP_IOXGET_16(isp, &src->at_oxid, dst->at_oxid); +} + +void +isp_get_atio7(struct ispsoftc *isp, at7_entry_t *src, at7_entry_t *dst) +{ + ISP_IOXGET_8(isp, &src->at_type, dst->at_type); + ISP_IOXGET_8(isp, &src->at_count, dst->at_count); + ISP_IOXGET_16(isp, &src->at_ta_len, dst->at_ta_len); + ISP_IOXGET_32(isp, &src->at_rxid, dst->at_rxid); + isp_get_fc_hdr(isp, &src->at_hdr, &dst->at_hdr); + isp_get_fcp_cmnd_iu(isp, &src->at_cmnd, &dst->at_cmnd); +} + +void +isp_put_ctio(struct ispsoftc *isp, ct_entry_t *src, ct_entry_t *dst) +{ + int i; + isp_put_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXPUT_16(isp, src->ct_syshandle, &dst->ct_syshandle); + ISP_IOXPUT_16(isp, src->ct_fwhandle, &dst->ct_fwhandle); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, ctsrc->ct_iid, &ctdst->ct_lun); - ISP_IOXPUT_8(isp, ctsrc->ct_lun, &ctdst->ct_iid); - ISP_IOXPUT_8(isp, ctsrc->ct_tgt, &ctdst->ct_reserved2); - ISP_IOXPUT_8(isp, ctsrc->ct_reserved2, &ctdst->ct_tgt); - ISP_IOXPUT_8(isp, ctsrc->ct_status, &ctdst->ct_scsi_status); - ISP_IOXPUT_8(isp, ctsrc->ct_scsi_status, &ctdst->ct_status); - ISP_IOXPUT_8(isp, ctsrc->ct_tag_type, &ctdst->ct_tag_val); - ISP_IOXPUT_8(isp, ctsrc->ct_tag_val, &ctdst->ct_tag_type); + ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_lun); + ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_iid); + ISP_IOXPUT_8(isp, src->ct_tgt, &dst->ct_reserved2); + ISP_IOXPUT_8(isp, src->ct_reserved2, &dst->ct_tgt); + ISP_IOXPUT_8(isp, src->ct_status, &dst->ct_scsi_status); + ISP_IOXPUT_8(isp, src->ct_scsi_status, &dst->ct_status); + ISP_IOXPUT_8(isp, src->ct_tag_type, &dst->ct_tag_val); + ISP_IOXPUT_8(isp, src->ct_tag_val, &dst->ct_tag_type); } else { - ISP_IOXPUT_8(isp, ctsrc->ct_iid, &ctdst->ct_iid); - ISP_IOXPUT_8(isp, ctsrc->ct_lun, &ctdst->ct_lun); - ISP_IOXPUT_8(isp, ctsrc->ct_tgt, &ctdst->ct_tgt); - ISP_IOXPUT_8(isp, ctsrc->ct_reserved2, &ctdst->ct_reserved2); - ISP_IOXPUT_8(isp, ctsrc->ct_scsi_status, - &ctdst->ct_scsi_status); - ISP_IOXPUT_8(isp, ctsrc->ct_status, &ctdst->ct_status); - ISP_IOXPUT_8(isp, ctsrc->ct_tag_type, &ctdst->ct_tag_type); - ISP_IOXPUT_8(isp, ctsrc->ct_tag_val, &ctdst->ct_tag_val); - } - ISP_IOXPUT_32(isp, ctsrc->ct_flags, &ctdst->ct_flags); - ISP_IOXPUT_32(isp, ctsrc->ct_xfrlen, &ctdst->ct_xfrlen); - ISP_IOXPUT_32(isp, ctsrc->ct_resid, &ctdst->ct_resid); - ISP_IOXPUT_16(isp, ctsrc->ct_timeout, &ctdst->ct_timeout); - ISP_IOXPUT_16(isp, ctsrc->ct_seg_count, &ctdst->ct_seg_count); + ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_iid); + ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_lun); + ISP_IOXPUT_8(isp, src->ct_tgt, &dst->ct_tgt); + ISP_IOXPUT_8(isp, src->ct_reserved2, &dst->ct_reserved2); + ISP_IOXPUT_8(isp, src->ct_scsi_status, + &dst->ct_scsi_status); + ISP_IOXPUT_8(isp, src->ct_status, &dst->ct_status); + ISP_IOXPUT_8(isp, src->ct_tag_type, &dst->ct_tag_type); + ISP_IOXPUT_8(isp, src->ct_tag_val, &dst->ct_tag_val); + } + ISP_IOXPUT_32(isp, src->ct_flags, &dst->ct_flags); + ISP_IOXPUT_32(isp, src->ct_xfrlen, &dst->ct_xfrlen); + ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid); + ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout); + ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count); for (i = 0; i < ISP_RQDSEG; i++) { - ISP_IOXPUT_32(isp, ctsrc->ct_dataseg[i].ds_base, - &ctdst->ct_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, ctsrc->ct_dataseg[i].ds_count, - &ctdst->ct_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_base, + &dst->ct_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_count, + &dst->ct_dataseg[i].ds_count); } } void -isp_get_ctio(struct ispsoftc *isp, ct_entry_t *ctsrc, ct_entry_t *ctdst) +isp_get_ctio(struct ispsoftc *isp, ct_entry_t *src, ct_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXGET_16(isp, &ctsrc->ct_reserved, ctdst->ct_reserved); - ISP_IOXGET_16(isp, &ctsrc->ct_fwhandle, ctdst->ct_fwhandle); + isp_get_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXGET_16(isp, &src->ct_syshandle, dst->ct_syshandle); + ISP_IOXGET_16(isp, &src->ct_fwhandle, dst->ct_fwhandle); if (ISP_IS_SBUS(isp)) { - ISP_IOXGET_8(isp, &ctsrc->ct_lun, ctdst->ct_iid); - ISP_IOXGET_8(isp, &ctsrc->ct_iid, ctdst->ct_lun); - ISP_IOXGET_8(isp, &ctsrc->ct_reserved2, ctdst->ct_tgt); - ISP_IOXGET_8(isp, &ctsrc->ct_tgt, ctdst->ct_reserved2); - ISP_IOXGET_8(isp, &ctsrc->ct_status, ctdst->ct_scsi_status); - ISP_IOXGET_8(isp, &ctsrc->ct_scsi_status, ctdst->ct_status); - ISP_IOXGET_8(isp, &ctsrc->ct_tag_val, ctdst->ct_tag_type); - ISP_IOXGET_8(isp, &ctsrc->ct_tag_type, ctdst->ct_tag_val); + ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_iid); + ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_lun); + ISP_IOXGET_8(isp, &src->ct_reserved2, dst->ct_tgt); + ISP_IOXGET_8(isp, &src->ct_tgt, dst->ct_reserved2); + ISP_IOXGET_8(isp, &src->ct_status, dst->ct_scsi_status); + ISP_IOXGET_8(isp, &src->ct_scsi_status, dst->ct_status); + ISP_IOXGET_8(isp, &src->ct_tag_val, dst->ct_tag_type); + ISP_IOXGET_8(isp, &src->ct_tag_type, dst->ct_tag_val); } else { - ISP_IOXGET_8(isp, &ctsrc->ct_lun, ctdst->ct_lun); - ISP_IOXGET_8(isp, &ctsrc->ct_iid, ctdst->ct_iid); - ISP_IOXGET_8(isp, &ctsrc->ct_reserved2, ctdst->ct_reserved2); - ISP_IOXGET_8(isp, &ctsrc->ct_tgt, ctdst->ct_tgt); - ISP_IOXGET_8(isp, &ctsrc->ct_status, ctdst->ct_status); - ISP_IOXGET_8(isp, &ctsrc->ct_scsi_status, - ctdst->ct_scsi_status); - ISP_IOXGET_8(isp, &ctsrc->ct_tag_val, ctdst->ct_tag_val); - ISP_IOXGET_8(isp, &ctsrc->ct_tag_type, ctdst->ct_tag_type); - } - ISP_IOXGET_32(isp, &ctsrc->ct_flags, ctdst->ct_flags); - ISP_IOXGET_32(isp, &ctsrc->ct_xfrlen, ctdst->ct_xfrlen); - ISP_IOXGET_32(isp, &ctsrc->ct_resid, ctdst->ct_resid); - ISP_IOXGET_16(isp, &ctsrc->ct_timeout, ctdst->ct_timeout); - ISP_IOXGET_16(isp, &ctsrc->ct_seg_count, ctdst->ct_seg_count); + ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_lun); + ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_iid); + ISP_IOXGET_8(isp, &src->ct_reserved2, dst->ct_reserved2); + ISP_IOXGET_8(isp, &src->ct_tgt, dst->ct_tgt); + ISP_IOXGET_8(isp, &src->ct_status, dst->ct_status); + ISP_IOXGET_8(isp, &src->ct_scsi_status, + dst->ct_scsi_status); + ISP_IOXGET_8(isp, &src->ct_tag_val, dst->ct_tag_val); + ISP_IOXGET_8(isp, &src->ct_tag_type, dst->ct_tag_type); + } + ISP_IOXGET_32(isp, &src->ct_flags, dst->ct_flags); + ISP_IOXGET_32(isp, &src->ct_xfrlen, dst->ct_xfrlen); + ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid); + ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout); + ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count); for (i = 0; i < ISP_RQDSEG; i++) { ISP_IOXGET_32(isp, - &ctsrc->ct_dataseg[i].ds_base, - ctdst->ct_dataseg[i].ds_base); + &src->ct_dataseg[i].ds_base, + dst->ct_dataseg[i].ds_base); ISP_IOXGET_32(isp, - &ctsrc->ct_dataseg[i].ds_count, - ctdst->ct_dataseg[i].ds_count); - } -} - -void -isp_put_ctio2(struct ispsoftc *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst) -{ - int i; - isp_copy_out_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXPUT_16(isp, ctsrc->ct_reserved, &ctdst->ct_reserved); - ISP_IOXPUT_16(isp, ctsrc->ct_fwhandle, &ctdst->ct_fwhandle); - ISP_IOXPUT_8(isp, ctsrc->ct_lun, &ctdst->ct_lun); - ISP_IOXPUT_8(isp, ctsrc->ct_iid, &ctdst->ct_iid); - ISP_IOXPUT_16(isp, ctsrc->ct_rxid, &ctdst->ct_rxid); - ISP_IOXPUT_16(isp, ctsrc->ct_flags, &ctdst->ct_flags); - ISP_IOXPUT_16(isp, ctsrc->ct_timeout, &ctdst->ct_timeout); - ISP_IOXPUT_16(isp, ctsrc->ct_seg_count, &ctdst->ct_seg_count); - ISP_IOXPUT_32(isp, ctsrc->ct_resid, &ctdst->ct_resid); - ISP_IOXPUT_32(isp, ctsrc->ct_reloff, &ctdst->ct_reloff); - if ((ctsrc->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { - ISP_IOXPUT_32(isp, ctsrc->rsp.m0._reserved, - &ctdst->rsp.m0._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m0._reserved2, - &ctdst->rsp.m0._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m0.ct_scsi_status, - &ctdst->rsp.m0.ct_scsi_status); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_xfrlen, - &ctdst->rsp.m0.ct_xfrlen); - if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + &src->ct_dataseg[i].ds_count, + dst->ct_dataseg[i].ds_count); + } +} + +void +isp_put_ctio2(struct ispsoftc *isp, ct2_entry_t *src, ct2_entry_t *dst) +{ + int i; + isp_put_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle); + ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_lun); + ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_iid); + ISP_IOXPUT_16(isp, src->ct_rxid, &dst->ct_rxid); + ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags); + ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout); + ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count); + ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid); + ISP_IOXPUT_32(isp, src->ct_reloff, &dst->ct_reloff); + if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXPUT_32(isp, src->rsp.m0._reserved, + &dst->rsp.m0._reserved); + ISP_IOXPUT_16(isp, src->rsp.m0._reserved2, + &dst->rsp.m0._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status, + &dst->rsp.m0.ct_scsi_status); + ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, + &dst->rsp.m0.ct_xfrlen); + if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { for (i = 0; i < ISP_RQDSEG_T2; i++) { ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg[i].ds_base, - &ctdst->rsp.m0.ct_dataseg[i].ds_base); + src->rsp.m0.u.ct_dataseg[i].ds_base, + &dst->rsp.m0.u.ct_dataseg[i].ds_base); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg[i].ds_count, - &ctdst->rsp.m0.ct_dataseg[i].ds_count); + src->rsp.m0.u.ct_dataseg[i].ds_count, + &dst->rsp.m0.u.ct_dataseg[i].ds_count); } - } else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + } else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { for (i = 0; i < ISP_RQDSEG_T3; i++) { ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_base, - &ctdst->rsp.m0.ct_dataseg64[i].ds_base); + src->rsp.m0.u.ct_dataseg64[i].ds_base, + &dst->rsp.m0.u.ct_dataseg64[i].ds_base); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_basehi, - &ctdst->rsp.m0.ct_dataseg64[i].ds_basehi); + src->rsp.m0.u.ct_dataseg64[i].ds_basehi, + &dst->rsp.m0.u.ct_dataseg64[i].ds_basehi); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_count, - &ctdst->rsp.m0.ct_dataseg64[i].ds_count); + src->rsp.m0.u.ct_dataseg64[i].ds_count, + &dst->rsp.m0.u.ct_dataseg64[i].ds_count); } - } else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { - ISP_IOXPUT_16(isp, ctsrc->rsp.m0.ct_dslist.ds_type, - &ctdst->rsp.m0.ct_dslist.ds_type); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_dslist.ds_segment, - &ctdst->rsp.m0.ct_dslist.ds_segment); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_dslist.ds_base, - &ctdst->rsp.m0.ct_dslist.ds_base); + } else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type, + &dst->rsp.m0.u.ct_dslist.ds_type); + ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment, + &dst->rsp.m0.u.ct_dslist.ds_segment); + ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base, + &dst->rsp.m0.u.ct_dslist.ds_base); } - } else if ((ctsrc->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { - ISP_IOXPUT_16(isp, ctsrc->rsp.m1._reserved, - &ctdst->rsp.m1._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1._reserved2, - &ctdst->rsp.m1._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_senselen, - &ctdst->rsp.m1.ct_senselen); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_scsi_status, - &ctdst->rsp.m1.ct_scsi_status); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_resplen, - &ctdst->rsp.m1.ct_resplen); + } else if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXPUT_16(isp, src->rsp.m1._reserved, + &dst->rsp.m1._reserved); + ISP_IOXPUT_16(isp, src->rsp.m1._reserved2, + &dst->rsp.m1._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen, + &dst->rsp.m1.ct_senselen); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status, + &dst->rsp.m1.ct_scsi_status); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, + &dst->rsp.m1.ct_resplen); for (i = 0; i < MAXRESPLEN; i++) { - ISP_IOXPUT_8(isp, ctsrc->rsp.m1.ct_resp[i], - &ctdst->rsp.m1.ct_resp[i]); + ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i], + &dst->rsp.m1.ct_resp[i]); } } else { - ISP_IOXPUT_32(isp, ctsrc->rsp.m2._reserved, - &ctdst->rsp.m2._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m2._reserved2, - &ctdst->rsp.m2._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m2._reserved3, - &ctdst->rsp.m2._reserved3); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_datalen, - &ctdst->rsp.m2.ct_datalen); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_fcp_rsp_iudata.ds_base, - &ctdst->rsp.m2.ct_fcp_rsp_iudata.ds_base); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_fcp_rsp_iudata.ds_count, - &ctdst->rsp.m2.ct_fcp_rsp_iudata.ds_count); - } -} - -void -isp_get_ctio2(struct ispsoftc *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst) -{ - int i; - isp_copy_in_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXGET_16(isp, &ctsrc->ct_reserved, ctdst->ct_reserved); - ISP_IOXGET_16(isp, &ctsrc->ct_fwhandle, ctdst->ct_fwhandle); - ISP_IOXGET_8(isp, &ctsrc->ct_lun, ctdst->ct_lun); - ISP_IOXGET_8(isp, &ctsrc->ct_iid, ctdst->ct_iid); - ISP_IOXGET_16(isp, &ctsrc->ct_rxid, ctdst->ct_rxid); - ISP_IOXGET_16(isp, &ctsrc->ct_flags, ctdst->ct_flags); - ISP_IOXGET_16(isp, &ctsrc->ct_status, ctdst->ct_status); - ISP_IOXGET_16(isp, &ctsrc->ct_timeout, ctdst->ct_timeout); - ISP_IOXGET_16(isp, &ctsrc->ct_seg_count, ctdst->ct_seg_count); - ISP_IOXGET_32(isp, &ctsrc->ct_reloff, ctdst->ct_reloff); - ISP_IOXGET_32(isp, &ctsrc->ct_resid, ctdst->ct_resid); - for (i = 0; i < 4; i++) { - ISP_IOXGET_32(isp, &ctsrc->rsp.fw._reserved[i], - ctdst->rsp.fw._reserved[i]); + ISP_IOXPUT_32(isp, src->rsp.m2._reserved, + &dst->rsp.m2._reserved); + ISP_IOXPUT_16(isp, src->rsp.m2._reserved2, + &dst->rsp.m2._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m2._reserved3, + &dst->rsp.m2._reserved3); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, + &dst->rsp.m2.ct_datalen); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); } - ISP_IOXGET_16(isp, &ctsrc->rsp.fw.ct_scsi_status, - ctdst->rsp.fw.ct_scsi_status); - for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXGET_8(isp, &ctsrc->rsp.fw.ct_sense[i], - ctdst->rsp.fw.ct_sense[i]); +} + +void +isp_put_ctio2e(struct ispsoftc *isp, ct2e_entry_t *src, ct2e_entry_t *dst) +{ + int i; + isp_put_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle); + ISP_IOXPUT_16(isp, src->ct_iid, &dst->ct_iid); + ISP_IOXPUT_16(isp, src->ct_rxid, &dst->ct_rxid); + ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags); + ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout); + ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count); + ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid); + ISP_IOXPUT_32(isp, src->ct_reloff, &dst->ct_reloff); + if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXPUT_32(isp, src->rsp.m0._reserved, + &dst->rsp.m0._reserved); + ISP_IOXPUT_16(isp, src->rsp.m0._reserved2, + &dst->rsp.m0._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status, + &dst->rsp.m0.ct_scsi_status); + ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, + &dst->rsp.m0.ct_xfrlen); + if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXPUT_32(isp, + src->rsp.m0.u.ct_dataseg[i].ds_base, + &dst->rsp.m0.u.ct_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, + src->rsp.m0.u.ct_dataseg[i].ds_count, + &dst->rsp.m0.u.ct_dataseg[i].ds_count); + } + } else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + for (i = 0; i < ISP_RQDSEG_T3; i++) { + ISP_IOXPUT_32(isp, + src->rsp.m0.u.ct_dataseg64[i].ds_base, + &dst->rsp.m0.u.ct_dataseg64[i].ds_base); + ISP_IOXPUT_32(isp, + src->rsp.m0.u.ct_dataseg64[i].ds_basehi, + &dst->rsp.m0.u.ct_dataseg64[i].ds_basehi); + ISP_IOXPUT_32(isp, + src->rsp.m0.u.ct_dataseg64[i].ds_count, + &dst->rsp.m0.u.ct_dataseg64[i].ds_count); + } + } else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type, + &dst->rsp.m0.u.ct_dslist.ds_type); + ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment, + &dst->rsp.m0.u.ct_dslist.ds_segment); + ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base, + &dst->rsp.m0.u.ct_dslist.ds_base); + } + } else if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXPUT_16(isp, src->rsp.m1._reserved, + &dst->rsp.m1._reserved); + ISP_IOXPUT_16(isp, src->rsp.m1._reserved2, + &dst->rsp.m1._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen, + &dst->rsp.m1.ct_senselen); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status, + &dst->rsp.m1.ct_scsi_status); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, + &dst->rsp.m1.ct_resplen); + for (i = 0; i < MAXRESPLEN; i++) { + ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i], + &dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXPUT_32(isp, src->rsp.m2._reserved, + &dst->rsp.m2._reserved); + ISP_IOXPUT_16(isp, src->rsp.m2._reserved2, + &dst->rsp.m2._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m2._reserved3, + &dst->rsp.m2._reserved3); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, + &dst->rsp.m2.ct_datalen); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } +} + +void +isp_put_ctio7(struct ispsoftc *isp, ct7_entry_t *src, ct7_entry_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle); + ISP_IOXPUT_16(isp, src->ct_nphdl, &dst->ct_nphdl); + ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout); + ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count); + ISP_IOXPUT_8(isp, src->ct_vpindex, &dst->ct_vpindex); + ISP_IOXPUT_8(isp, src->ct_xflags, &dst->ct_xflags); + ISP_IOXPUT_16(isp, src->ct_iid_lo, &dst->ct_iid_lo); + ISP_IOXPUT_8(isp, src->ct_iid_hi, &dst->ct_iid_hi); + ISP_IOXPUT_8(isp, src->ct_reserved, &dst->ct_reserved); + ISP_IOXPUT_32(isp, src->ct_rxid, &dst->ct_rxid); + ISP_IOXPUT_16(isp, src->ct_senselen, &dst->ct_senselen); + ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags); + ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid); + ISP_IOXPUT_16(isp, src->ct_oxid, &dst->ct_oxid); + ISP_IOXPUT_16(isp, src->ct_scsi_status, &dst->ct_scsi_status); + if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE0) { + ISP_IOXPUT_32(isp, src->rsp.m0.reloff, &dst->rsp.m0.reloff); + ISP_IOXPUT_32(isp, src->rsp.m0.reserved0, + &dst->rsp.m0.reserved0); + ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, + &dst->rsp.m0.ct_xfrlen); + ISP_IOXPUT_32(isp, src->rsp.m0.reserved1, + &dst->rsp.m0.reserved1); + ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_base, + &dst->rsp.m0.ds.ds_base); + ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_basehi, + &dst->rsp.m0.ds.ds_basehi); + ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_count, + &dst->rsp.m0.ds.ds_count); + } else if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE1) { + ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, + &dst->rsp.m1.ct_resplen); + ISP_IOXPUT_16(isp, src->rsp.m1.reserved, &dst->rsp.m1.reserved); + for (i = 0; i < MAXRESPLEN_24XX; i++) { + ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i], + &dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXPUT_32(isp, src->rsp.m2.reserved0, + &dst->rsp.m2.reserved0); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, + &dst->rsp.m2.ct_datalen); + ISP_IOXPUT_32(isp, src->rsp.m2.reserved1, + &dst->rsp.m2.reserved1); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } +} + + +void +isp_get_ctio2(struct ispsoftc *isp, ct2_entry_t *src, ct2_entry_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle); + ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_lun); + ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_iid); + ISP_IOXGET_16(isp, &src->ct_rxid, dst->ct_rxid); + ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags); + ISP_IOXGET_16(isp, &src->ct_status, dst->ct_status); + ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout); + ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count); + ISP_IOXGET_32(isp, &src->ct_reloff, dst->ct_reloff); + ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid); + if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXGET_32(isp, &src->rsp.m0._reserved, + dst->rsp.m0._reserved); + ISP_IOXGET_16(isp, &src->rsp.m0._reserved2, + dst->rsp.m0._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status, + dst->rsp.m0.ct_scsi_status); + ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, + dst->rsp.m0.ct_xfrlen); + if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg[i].ds_base, + dst->rsp.m0.u.ct_dataseg[i].ds_base); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg[i].ds_count, + dst->rsp.m0.u.ct_dataseg[i].ds_count); + } + } else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + for (i = 0; i < ISP_RQDSEG_T3; i++) { + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_base, + dst->rsp.m0.u.ct_dataseg64[i].ds_base); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_basehi, + dst->rsp.m0.u.ct_dataseg64[i].ds_basehi); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_count, + dst->rsp.m0.u.ct_dataseg64[i].ds_count); + } + } else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type, + dst->rsp.m0.u.ct_dslist.ds_type); + ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment, + dst->rsp.m0.u.ct_dslist.ds_segment); + ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base, + dst->rsp.m0.u.ct_dslist.ds_base); + } + } else if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXGET_16(isp, &src->rsp.m1._reserved, + dst->rsp.m1._reserved); + ISP_IOXGET_16(isp, &src->rsp.m1._reserved2, + dst->rsp.m1._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen, + dst->rsp.m1.ct_senselen); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status, + dst->rsp.m1.ct_scsi_status); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, + dst->rsp.m1.ct_resplen); + for (i = 0; i < MAXRESPLEN; i++) { + ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], + dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXGET_32(isp, &src->rsp.m2._reserved, + dst->rsp.m2._reserved); + ISP_IOXGET_16(isp, &src->rsp.m2._reserved2, + dst->rsp.m2._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m2._reserved3, + dst->rsp.m2._reserved3); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, + dst->rsp.m2.ct_datalen); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } +} + +void +isp_get_ctio2e(struct ispsoftc *isp, ct2e_entry_t *src, ct2e_entry_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle); + ISP_IOXGET_16(isp, &src->ct_iid, dst->ct_iid); + ISP_IOXGET_16(isp, &src->ct_rxid, dst->ct_rxid); + ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags); + ISP_IOXGET_16(isp, &src->ct_status, dst->ct_status); + ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout); + ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count); + ISP_IOXGET_32(isp, &src->ct_reloff, dst->ct_reloff); + ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid); + if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXGET_32(isp, &src->rsp.m0._reserved, + dst->rsp.m0._reserved); + ISP_IOXGET_16(isp, &src->rsp.m0._reserved2, + dst->rsp.m0._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status, + dst->rsp.m0.ct_scsi_status); + ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, + dst->rsp.m0.ct_xfrlen); + if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg[i].ds_base, + dst->rsp.m0.u.ct_dataseg[i].ds_base); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg[i].ds_count, + dst->rsp.m0.u.ct_dataseg[i].ds_count); + } + } else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + for (i = 0; i < ISP_RQDSEG_T3; i++) { + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_base, + dst->rsp.m0.u.ct_dataseg64[i].ds_base); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_basehi, + dst->rsp.m0.u.ct_dataseg64[i].ds_basehi); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_count, + dst->rsp.m0.u.ct_dataseg64[i].ds_count); + } + } else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type, + dst->rsp.m0.u.ct_dslist.ds_type); + ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment, + dst->rsp.m0.u.ct_dslist.ds_segment); + ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base, + dst->rsp.m0.u.ct_dslist.ds_base); + } + } else if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXGET_16(isp, &src->rsp.m1._reserved, + dst->rsp.m1._reserved); + ISP_IOXGET_16(isp, &src->rsp.m1._reserved2, + dst->rsp.m1._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen, + dst->rsp.m1.ct_senselen); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status, + dst->rsp.m1.ct_scsi_status); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, + dst->rsp.m1.ct_resplen); + for (i = 0; i < MAXRESPLEN; i++) { + ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], + dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXGET_32(isp, &src->rsp.m2._reserved, + dst->rsp.m2._reserved); + ISP_IOXGET_16(isp, &src->rsp.m2._reserved2, + dst->rsp.m2._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m2._reserved3, + dst->rsp.m2._reserved3); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, + dst->rsp.m2.ct_datalen); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } +} + +void +isp_get_ctio7(struct ispsoftc *isp, ct7_entry_t *src, ct7_entry_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle); + ISP_IOXGET_16(isp, &src->ct_nphdl, dst->ct_nphdl); + ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout); + ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count); + ISP_IOXGET_8(isp, &src->ct_vpindex, dst->ct_vpindex); + ISP_IOXGET_8(isp, &src->ct_xflags, dst->ct_xflags); + ISP_IOXGET_16(isp, &src->ct_iid_lo, dst->ct_iid_lo); + ISP_IOXGET_8(isp, &src->ct_iid_hi, dst->ct_iid_hi); + ISP_IOXGET_8(isp, &src->ct_reserved, dst->ct_reserved); + ISP_IOXGET_32(isp, &src->ct_rxid, dst->ct_rxid); + ISP_IOXGET_16(isp, &src->ct_senselen, dst->ct_senselen); + ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags); + ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid); + ISP_IOXGET_16(isp, &src->ct_oxid, dst->ct_oxid); + ISP_IOXGET_16(isp, &src->ct_scsi_status, dst->ct_scsi_status); + if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE0) { + ISP_IOXGET_32(isp, &src->rsp.m0.reloff, dst->rsp.m0.reloff); + ISP_IOXGET_32(isp, &src->rsp.m0.reserved0, + dst->rsp.m0.reserved0); + ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, + dst->rsp.m0.ct_xfrlen); + ISP_IOXGET_32(isp, &src->rsp.m0.reserved1, + dst->rsp.m0.reserved1); + ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_base, + dst->rsp.m0.ds.ds_base); + ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_basehi, + dst->rsp.m0.ds.ds_basehi); + ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_count, + dst->rsp.m0.ds.ds_count); + } else if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE1) { + ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, + dst->rsp.m1.ct_resplen); + ISP_IOXGET_16(isp, &src->rsp.m1.reserved, dst->rsp.m1.reserved); + for (i = 0; i < MAXRESPLEN_24XX; i++) { + ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], + dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXGET_32(isp, &src->rsp.m2.reserved0, + dst->rsp.m2.reserved0); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, + dst->rsp.m2.ct_datalen); + ISP_IOXGET_32(isp, &src->rsp.m2.reserved1, + dst->rsp.m2.reserved1); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); } } @@ -1105,7 +2278,7 @@ void isp_put_enable_lun(struct ispsoftc *isp, lun_entry_t *lesrc, lun_entry_t *ledst) { int i; - isp_copy_out_hdr(isp, &lesrc->le_header, &ledst->le_header); + isp_put_hdr(isp, &lesrc->le_header, &ledst->le_header); ISP_IOXPUT_32(isp, lesrc->le_reserved, &ledst->le_reserved); if (ISP_IS_SBUS(isp)) { ISP_IOXPUT_8(isp, lesrc->le_lun, &ledst->le_rsvd); @@ -1142,7 +2315,7 @@ void isp_get_enable_lun(struct ispsoftc *isp, lun_entry_t *lesrc, lun_entry_t *ledst) { int i; - isp_copy_in_hdr(isp, &lesrc->le_header, &ledst->le_header); + isp_get_hdr(isp, &lesrc->le_header, &ledst->le_header); ISP_IOXGET_32(isp, &lesrc->le_reserved, ledst->le_reserved); if (ISP_IS_SBUS(isp)) { ISP_IOXGET_8(isp, &lesrc->le_lun, ledst->le_rsvd); @@ -1176,202 +2349,554 @@ isp_get_enable_lun(struct ispsoftc *isp, lun_entry_t *lesrc, lun_entry_t *ledst) } void -isp_put_notify(struct ispsoftc *isp, in_entry_t *insrc, in_entry_t *indst) +isp_put_notify(struct ispsoftc *isp, in_entry_t *src, in_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXPUT_32(isp, insrc->in_reserved, &indst->in_reserved); + isp_put_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_iid); - ISP_IOXPUT_8(isp, insrc->in_iid, &indst->in_lun); - ISP_IOXPUT_8(isp, insrc->in_reserved2, &indst->in_tgt); - ISP_IOXPUT_8(isp, insrc->in_tgt, &indst->in_reserved2); - ISP_IOXPUT_8(isp, insrc->in_status, &indst->in_rsvd2); - ISP_IOXPUT_8(isp, insrc->in_rsvd2, &indst->in_status); - ISP_IOXPUT_8(isp, insrc->in_tag_val, &indst->in_tag_type); - ISP_IOXPUT_8(isp, insrc->in_tag_type, &indst->in_tag_val); + ISP_IOXPUT_8(isp, src->in_lun, &dst->in_iid); + ISP_IOXPUT_8(isp, src->in_iid, &dst->in_lun); + ISP_IOXPUT_8(isp, src->in_reserved2, &dst->in_tgt); + ISP_IOXPUT_8(isp, src->in_tgt, &dst->in_reserved2); + ISP_IOXPUT_8(isp, src->in_status, &dst->in_rsvd2); + ISP_IOXPUT_8(isp, src->in_rsvd2, &dst->in_status); + ISP_IOXPUT_8(isp, src->in_tag_val, &dst->in_tag_type); + ISP_IOXPUT_8(isp, src->in_tag_type, &dst->in_tag_val); } else { - ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_lun); - ISP_IOXPUT_8(isp, insrc->in_iid, &indst->in_iid); - ISP_IOXPUT_8(isp, insrc->in_reserved2, &indst->in_reserved2); - ISP_IOXPUT_8(isp, insrc->in_tgt, &indst->in_tgt); - ISP_IOXPUT_8(isp, insrc->in_status, &indst->in_status); - ISP_IOXPUT_8(isp, insrc->in_rsvd2, &indst->in_rsvd2); - ISP_IOXPUT_8(isp, insrc->in_tag_val, &indst->in_tag_val); - ISP_IOXPUT_8(isp, insrc->in_tag_type, &indst->in_tag_type); - } - ISP_IOXPUT_32(isp, insrc->in_flags, &indst->in_flags); - ISP_IOXPUT_16(isp, insrc->in_seqid, &indst->in_seqid); + ISP_IOXPUT_8(isp, src->in_lun, &dst->in_lun); + ISP_IOXPUT_8(isp, src->in_iid, &dst->in_iid); + ISP_IOXPUT_8(isp, src->in_reserved2, &dst->in_reserved2); + ISP_IOXPUT_8(isp, src->in_tgt, &dst->in_tgt); + ISP_IOXPUT_8(isp, src->in_status, &dst->in_status); + ISP_IOXPUT_8(isp, src->in_rsvd2, &dst->in_rsvd2); + ISP_IOXPUT_8(isp, src->in_tag_val, &dst->in_tag_val); + ISP_IOXPUT_8(isp, src->in_tag_type, &dst->in_tag_type); + } + ISP_IOXPUT_32(isp, src->in_flags, &dst->in_flags); + ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid); for (i = 0; i < IN_MSGLEN; i++) { - ISP_IOXPUT_8(isp, insrc->in_msg[i], &indst->in_msg[i]); + ISP_IOXPUT_8(isp, src->in_msg[i], &dst->in_msg[i]); } for (i = 0; i < IN_RSVDLEN; i++) { - ISP_IOXPUT_8(isp, insrc->in_reserved3[i], - &indst->in_reserved3[i]); + ISP_IOXPUT_8(isp, src->in_reserved3[i], + &dst->in_reserved3[i]); } for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXPUT_8(isp, insrc->in_sense[i], - &indst->in_sense[i]); + ISP_IOXPUT_8(isp, src->in_sense[i], + &dst->in_sense[i]); } } void -isp_get_notify(struct ispsoftc *isp, in_entry_t *insrc, in_entry_t *indst) +isp_get_notify(struct ispsoftc *isp, in_entry_t *src, in_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXGET_32(isp, &insrc->in_reserved, indst->in_reserved); + isp_get_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved); if (ISP_IS_SBUS(isp)) { - ISP_IOXGET_8(isp, &insrc->in_lun, indst->in_iid); - ISP_IOXGET_8(isp, &insrc->in_iid, indst->in_lun); - ISP_IOXGET_8(isp, &insrc->in_reserved2, indst->in_tgt); - ISP_IOXGET_8(isp, &insrc->in_tgt, indst->in_reserved2); - ISP_IOXGET_8(isp, &insrc->in_status, indst->in_rsvd2); - ISP_IOXGET_8(isp, &insrc->in_rsvd2, indst->in_status); - ISP_IOXGET_8(isp, &insrc->in_tag_val, indst->in_tag_type); - ISP_IOXGET_8(isp, &insrc->in_tag_type, indst->in_tag_val); + ISP_IOXGET_8(isp, &src->in_lun, dst->in_iid); + ISP_IOXGET_8(isp, &src->in_iid, dst->in_lun); + ISP_IOXGET_8(isp, &src->in_reserved2, dst->in_tgt); + ISP_IOXGET_8(isp, &src->in_tgt, dst->in_reserved2); + ISP_IOXGET_8(isp, &src->in_status, dst->in_rsvd2); + ISP_IOXGET_8(isp, &src->in_rsvd2, dst->in_status); + ISP_IOXGET_8(isp, &src->in_tag_val, dst->in_tag_type); + ISP_IOXGET_8(isp, &src->in_tag_type, dst->in_tag_val); } else { - ISP_IOXGET_8(isp, &insrc->in_lun, indst->in_lun); - ISP_IOXGET_8(isp, &insrc->in_iid, indst->in_iid); - ISP_IOXGET_8(isp, &insrc->in_reserved2, indst->in_reserved2); - ISP_IOXGET_8(isp, &insrc->in_tgt, indst->in_tgt); - ISP_IOXGET_8(isp, &insrc->in_status, indst->in_status); - ISP_IOXGET_8(isp, &insrc->in_rsvd2, indst->in_rsvd2); - ISP_IOXGET_8(isp, &insrc->in_tag_val, indst->in_tag_val); - ISP_IOXGET_8(isp, &insrc->in_tag_type, indst->in_tag_type); - } - ISP_IOXGET_32(isp, &insrc->in_flags, indst->in_flags); - ISP_IOXGET_16(isp, &insrc->in_seqid, indst->in_seqid); + ISP_IOXGET_8(isp, &src->in_lun, dst->in_lun); + ISP_IOXGET_8(isp, &src->in_iid, dst->in_iid); + ISP_IOXGET_8(isp, &src->in_reserved2, dst->in_reserved2); + ISP_IOXGET_8(isp, &src->in_tgt, dst->in_tgt); + ISP_IOXGET_8(isp, &src->in_status, dst->in_status); + ISP_IOXGET_8(isp, &src->in_rsvd2, dst->in_rsvd2); + ISP_IOXGET_8(isp, &src->in_tag_val, dst->in_tag_val); + ISP_IOXGET_8(isp, &src->in_tag_type, dst->in_tag_type); + } + ISP_IOXGET_32(isp, &src->in_flags, dst->in_flags); + ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid); for (i = 0; i < IN_MSGLEN; i++) { - ISP_IOXGET_8(isp, &insrc->in_msg[i], indst->in_msg[i]); + ISP_IOXGET_8(isp, &src->in_msg[i], dst->in_msg[i]); } for (i = 0; i < IN_RSVDLEN; i++) { - ISP_IOXGET_8(isp, &insrc->in_reserved3[i], - indst->in_reserved3[i]); + ISP_IOXGET_8(isp, &src->in_reserved3[i], + dst->in_reserved3[i]); } for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXGET_8(isp, &insrc->in_sense[i], - indst->in_sense[i]); + ISP_IOXGET_8(isp, &src->in_sense[i], + dst->in_sense[i]); } } void -isp_put_notify_fc(struct ispsoftc *isp, in_fcentry_t *insrc, - in_fcentry_t *indst) +isp_put_notify_fc(struct ispsoftc *isp, in_fcentry_t *src, + in_fcentry_t *dst) +{ + isp_put_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved); + ISP_IOXPUT_8(isp, src->in_lun, &dst->in_lun); + ISP_IOXPUT_8(isp, src->in_iid, &dst->in_iid); + ISP_IOXPUT_16(isp, src->in_scclun, &dst->in_scclun); + ISP_IOXPUT_32(isp, src->in_reserved2, &dst->in_reserved2); + ISP_IOXPUT_16(isp, src->in_status, &dst->in_status); + ISP_IOXPUT_16(isp, src->in_task_flags, &dst->in_task_flags); + ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid); +} + +void +isp_put_notify_fc_e(struct ispsoftc *isp, in_fcentry_e_t *src, + in_fcentry_e_t *dst) +{ + isp_put_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved); + ISP_IOXPUT_16(isp, src->in_iid, &dst->in_iid); + ISP_IOXPUT_16(isp, src->in_scclun, &dst->in_scclun); + ISP_IOXPUT_32(isp, src->in_reserved2, &dst->in_reserved2); + ISP_IOXPUT_16(isp, src->in_status, &dst->in_status); + ISP_IOXPUT_16(isp, src->in_task_flags, &dst->in_task_flags); + ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid); +} + +void +isp_put_notify_24xx(struct ispsoftc *isp, in_fcentry_24xx_t *src, + in_fcentry_24xx_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved); + ISP_IOXPUT_16(isp, src->in_nphdl, &dst->in_nphdl); + ISP_IOXPUT_16(isp, src->in_reserved1, &dst->in_reserved1); + ISP_IOXPUT_16(isp, src->in_flags, &dst->in_flags); + ISP_IOXPUT_16(isp, src->in_srr_rxid, &dst->in_srr_rxid); + ISP_IOXPUT_16(isp, src->in_status, &dst->in_status); + ISP_IOXPUT_8(isp, src->in_status_subcode, &dst->in_status_subcode); + ISP_IOXPUT_16(isp, src->in_reserved2, &dst->in_reserved2); + ISP_IOXPUT_32(isp, src->in_rxid, &dst->in_rxid); + ISP_IOXPUT_16(isp, src->in_srr_reloff_hi, &dst->in_srr_reloff_hi); + ISP_IOXPUT_16(isp, src->in_srr_reloff_lo, &dst->in_srr_reloff_lo); + ISP_IOXPUT_16(isp, src->in_srr_iu, &dst->in_srr_iu); + ISP_IOXPUT_16(isp, src->in_srr_oxid, &dst->in_srr_oxid); + for (i = 0; i < 18; i++) { + ISP_IOXPUT_8(isp, src->in_reserved3[i], &dst->in_reserved3[i]); + } + ISP_IOXPUT_8(isp, src->in_reserved4, &dst->in_reserved4); + ISP_IOXPUT_8(isp, src->in_vpindex, &dst->in_vpindex); + ISP_IOXPUT_32(isp, src->in_reserved5, &dst->in_reserved5); + ISP_IOXPUT_16(isp, src->in_portid_lo, &dst->in_portid_lo); + ISP_IOXPUT_8(isp, src->in_portid_hi, &dst->in_portid_hi); + ISP_IOXPUT_8(isp, src->in_reserved6, &dst->in_reserved6); + ISP_IOXPUT_16(isp, src->in_reserved7, &dst->in_reserved7); + ISP_IOXPUT_16(isp, src->in_oxid, &dst->in_oxid); +} + +void +isp_get_notify_fc(struct ispsoftc *isp, in_fcentry_t *src, + in_fcentry_t *dst) { - isp_copy_out_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXPUT_32(isp, insrc->in_reserved, &indst->in_reserved); - ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_lun); - ISP_IOXPUT_8(isp, insrc->in_iid, &indst->in_iid); - ISP_IOXPUT_16(isp, insrc->in_scclun, &indst->in_scclun); - ISP_IOXPUT_32(isp, insrc->in_reserved2, &indst->in_reserved2); - ISP_IOXPUT_16(isp, insrc->in_status, &indst->in_status); - ISP_IOXPUT_16(isp, insrc->in_task_flags, &indst->in_task_flags); - ISP_IOXPUT_16(isp, insrc->in_seqid, &indst->in_seqid); + isp_get_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved); + ISP_IOXGET_8(isp, &src->in_lun, dst->in_lun); + ISP_IOXGET_8(isp, &src->in_iid, dst->in_iid); + ISP_IOXGET_16(isp, &src->in_scclun, dst->in_scclun); + ISP_IOXGET_32(isp, &src->in_reserved2, dst->in_reserved2); + ISP_IOXGET_16(isp, &src->in_status, dst->in_status); + ISP_IOXGET_16(isp, &src->in_task_flags, dst->in_task_flags); + ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid); } void -isp_get_notify_fc(struct ispsoftc *isp, in_fcentry_t *insrc, - in_fcentry_t *indst) +isp_get_notify_fc_e(struct ispsoftc *isp, in_fcentry_e_t *src, + in_fcentry_e_t *dst) { - isp_copy_in_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXGET_32(isp, &insrc->in_reserved, indst->in_reserved); - ISP_IOXGET_8(isp, &insrc->in_lun, indst->in_lun); - ISP_IOXGET_8(isp, &insrc->in_iid, indst->in_iid); - ISP_IOXGET_16(isp, &insrc->in_scclun, indst->in_scclun); - ISP_IOXGET_32(isp, &insrc->in_reserved2, indst->in_reserved2); - ISP_IOXGET_16(isp, &insrc->in_status, indst->in_status); - ISP_IOXGET_16(isp, &insrc->in_task_flags, indst->in_task_flags); - ISP_IOXGET_16(isp, &insrc->in_seqid, indst->in_seqid); + isp_get_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved); + ISP_IOXGET_16(isp, &src->in_iid, dst->in_iid); + ISP_IOXGET_16(isp, &src->in_scclun, dst->in_scclun); + ISP_IOXGET_32(isp, &src->in_reserved2, dst->in_reserved2); + ISP_IOXGET_16(isp, &src->in_status, dst->in_status); + ISP_IOXGET_16(isp, &src->in_task_flags, dst->in_task_flags); + ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid); } void -isp_put_notify_ack(struct ispsoftc *isp, na_entry_t *nasrc, na_entry_t *nadst) +isp_get_notify_24xx(struct ispsoftc *isp, in_fcentry_24xx_t *src, + in_fcentry_24xx_t *dst) { int i; - isp_copy_out_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXPUT_32(isp, nasrc->na_reserved, &nadst->na_reserved); + + isp_get_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved); + ISP_IOXGET_16(isp, &src->in_nphdl, dst->in_nphdl); + ISP_IOXGET_16(isp, &src->in_reserved1, dst->in_reserved1); + ISP_IOXGET_16(isp, &src->in_flags, dst->in_flags); + ISP_IOXGET_16(isp, &src->in_srr_rxid, dst->in_srr_rxid); + ISP_IOXGET_16(isp, &src->in_status, dst->in_status); + ISP_IOXGET_8(isp, &src->in_status_subcode, dst->in_status_subcode); + ISP_IOXGET_16(isp, &src->in_reserved2, dst->in_reserved2); + ISP_IOXGET_32(isp, &src->in_rxid, dst->in_rxid); + ISP_IOXGET_16(isp, &src->in_srr_reloff_hi, dst->in_srr_reloff_hi); + ISP_IOXGET_16(isp, &src->in_srr_reloff_lo, dst->in_srr_reloff_lo); + ISP_IOXGET_16(isp, &src->in_srr_iu, dst->in_srr_iu); + ISP_IOXGET_16(isp, &src->in_srr_oxid, dst->in_srr_oxid); + for (i = 0; i < 18; i++) { + ISP_IOXGET_8(isp, &src->in_reserved3[i], dst->in_reserved3[i]); + } + ISP_IOXGET_8(isp, &src->in_reserved4, dst->in_reserved4); + ISP_IOXGET_8(isp, &src->in_vpindex, dst->in_vpindex); + ISP_IOXGET_32(isp, &src->in_reserved5, dst->in_reserved5); + ISP_IOXGET_16(isp, &src->in_portid_lo, dst->in_portid_lo); + ISP_IOXGET_8(isp, &src->in_portid_hi, dst->in_portid_hi); + ISP_IOXGET_8(isp, &src->in_reserved6, dst->in_reserved6); + ISP_IOXGET_16(isp, &src->in_reserved7, dst->in_reserved7); + ISP_IOXGET_16(isp, &src->in_oxid, dst->in_oxid); +} + +void +isp_put_notify_ack(struct ispsoftc *isp, na_entry_t *src, na_entry_t *dst) +{ + int i; + isp_put_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, nasrc->na_lun, &nadst->na_iid); - ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_lun); - ISP_IOXPUT_8(isp, nasrc->na_status, &nadst->na_event); - ISP_IOXPUT_8(isp, nasrc->na_event, &nadst->na_status); + ISP_IOXPUT_8(isp, src->na_lun, &dst->na_iid); + ISP_IOXPUT_8(isp, src->na_iid, &dst->na_lun); + ISP_IOXPUT_8(isp, src->na_status, &dst->na_event); + ISP_IOXPUT_8(isp, src->na_event, &dst->na_status); } else { - ISP_IOXPUT_8(isp, nasrc->na_lun, &nadst->na_lun); - ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_iid); - ISP_IOXPUT_8(isp, nasrc->na_status, &nadst->na_status); - ISP_IOXPUT_8(isp, nasrc->na_event, &nadst->na_event); + ISP_IOXPUT_8(isp, src->na_lun, &dst->na_lun); + ISP_IOXPUT_8(isp, src->na_iid, &dst->na_iid); + ISP_IOXPUT_8(isp, src->na_status, &dst->na_status); + ISP_IOXPUT_8(isp, src->na_event, &dst->na_event); } - ISP_IOXPUT_32(isp, nasrc->na_flags, &nadst->na_flags); + ISP_IOXPUT_32(isp, src->na_flags, &dst->na_flags); for (i = 0; i < NA_RSVDLEN; i++) { - ISP_IOXPUT_16(isp, nasrc->na_reserved3[i], - &nadst->na_reserved3[i]); + ISP_IOXPUT_16(isp, src->na_reserved3[i], + &dst->na_reserved3[i]); } } void -isp_get_notify_ack(struct ispsoftc *isp, na_entry_t *nasrc, na_entry_t *nadst) +isp_get_notify_ack(struct ispsoftc *isp, na_entry_t *src, na_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXGET_32(isp, &nasrc->na_reserved, nadst->na_reserved); + isp_get_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved); if (ISP_IS_SBUS(isp)) { - ISP_IOXGET_8(isp, &nasrc->na_lun, nadst->na_iid); - ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_lun); - ISP_IOXGET_8(isp, &nasrc->na_status, nadst->na_event); - ISP_IOXGET_8(isp, &nasrc->na_event, nadst->na_status); + ISP_IOXGET_8(isp, &src->na_lun, dst->na_iid); + ISP_IOXGET_8(isp, &src->na_iid, dst->na_lun); + ISP_IOXGET_8(isp, &src->na_status, dst->na_event); + ISP_IOXGET_8(isp, &src->na_event, dst->na_status); } else { - ISP_IOXGET_8(isp, &nasrc->na_lun, nadst->na_lun); - ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_iid); - ISP_IOXGET_8(isp, &nasrc->na_status, nadst->na_status); - ISP_IOXGET_8(isp, &nasrc->na_event, nadst->na_event); + ISP_IOXGET_8(isp, &src->na_lun, dst->na_lun); + ISP_IOXGET_8(isp, &src->na_iid, dst->na_iid); + ISP_IOXGET_8(isp, &src->na_status, dst->na_status); + ISP_IOXGET_8(isp, &src->na_event, dst->na_event); } - ISP_IOXGET_32(isp, &nasrc->na_flags, nadst->na_flags); + ISP_IOXGET_32(isp, &src->na_flags, dst->na_flags); for (i = 0; i < NA_RSVDLEN; i++) { - ISP_IOXGET_16(isp, &nasrc->na_reserved3[i], - nadst->na_reserved3[i]); + ISP_IOXGET_16(isp, &src->na_reserved3[i], + dst->na_reserved3[i]); } } void -isp_put_notify_ack_fc(struct ispsoftc *isp, na_fcentry_t *nasrc, - na_fcentry_t *nadst) +isp_put_notify_ack_fc(struct ispsoftc *isp, na_fcentry_t *src, + na_fcentry_t *dst) { int i; - isp_copy_out_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXPUT_32(isp, nasrc->na_reserved, &nadst->na_reserved); - ISP_IOXPUT_8(isp, nasrc->na_lun, &nadst->na_lun); - ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_iid); - ISP_IOXPUT_16(isp, nasrc->na_scclun, &nadst->na_scclun); - ISP_IOXPUT_16(isp, nasrc->na_flags, &nadst->na_flags); - ISP_IOXPUT_16(isp, nasrc->na_reserved2, &nadst->na_reserved2); - ISP_IOXPUT_16(isp, nasrc->na_status, &nadst->na_status); - ISP_IOXPUT_16(isp, nasrc->na_task_flags, &nadst->na_task_flags); - ISP_IOXPUT_16(isp, nasrc->na_seqid, &nadst->na_seqid); + isp_put_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved); + ISP_IOXPUT_8(isp, src->na_reserved1, &dst->na_reserved1); + ISP_IOXPUT_8(isp, src->na_iid, &dst->na_iid); + ISP_IOXPUT_16(isp, src->na_response, &dst->na_response); + ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags); + ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2); + ISP_IOXPUT_16(isp, src->na_status, &dst->na_status); + ISP_IOXPUT_16(isp, src->na_task_flags, &dst->na_task_flags); + ISP_IOXPUT_16(isp, src->na_seqid, &dst->na_seqid); for (i = 0; i < NA2_RSVDLEN; i++) { - ISP_IOXPUT_16(isp, nasrc->na_reserved3[i], - &nadst->na_reserved3[i]); + ISP_IOXPUT_16(isp, src->na_reserved3[i], + &dst->na_reserved3[i]); } } void -isp_get_notify_ack_fc(struct ispsoftc *isp, na_fcentry_t *nasrc, - na_fcentry_t *nadst) +isp_put_notify_ack_fc_e(struct ispsoftc *isp, na_fcentry_e_t *src, + na_fcentry_e_t *dst) { int i; - isp_copy_in_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXGET_32(isp, &nasrc->na_reserved, nadst->na_reserved); - ISP_IOXGET_8(isp, &nasrc->na_lun, nadst->na_lun); - ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_iid); - ISP_IOXGET_16(isp, &nasrc->na_scclun, nadst->na_scclun); - ISP_IOXGET_16(isp, &nasrc->na_flags, nadst->na_flags); - ISP_IOXGET_16(isp, &nasrc->na_reserved2, nadst->na_reserved2); - ISP_IOXGET_16(isp, &nasrc->na_status, nadst->na_status); - ISP_IOXGET_16(isp, &nasrc->na_task_flags, nadst->na_task_flags); - ISP_IOXGET_16(isp, &nasrc->na_seqid, nadst->na_seqid); + isp_put_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved); + ISP_IOXPUT_16(isp, src->na_iid, &dst->na_iid); + ISP_IOXPUT_16(isp, src->na_response, &dst->na_response); + ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags); + ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2); + ISP_IOXPUT_16(isp, src->na_status, &dst->na_status); + ISP_IOXPUT_16(isp, src->na_task_flags, &dst->na_task_flags); + ISP_IOXPUT_16(isp, src->na_seqid, &dst->na_seqid); for (i = 0; i < NA2_RSVDLEN; i++) { - ISP_IOXGET_16(isp, &nasrc->na_reserved3[i], - nadst->na_reserved3[i]); + ISP_IOXPUT_16(isp, src->na_reserved3[i], + &dst->na_reserved3[i]); } } -#endif + +void +isp_put_notify_24xx_ack(struct ispsoftc *isp, na_fcentry_24xx_t *src, + na_fcentry_24xx_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXPUT_32(isp, src->na_handle, &dst->na_handle); + ISP_IOXPUT_16(isp, src->na_nphdl, &dst->na_nphdl); + ISP_IOXPUT_16(isp, src->na_reserved1, &dst->na_reserved1); + ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags); + ISP_IOXPUT_16(isp, src->na_srr_rxid, &dst->na_srr_rxid); + ISP_IOXPUT_16(isp, src->na_status, &dst->na_status); + ISP_IOXPUT_8(isp, src->na_status_subcode, &dst->na_status_subcode); + ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2); + ISP_IOXPUT_32(isp, src->na_rxid, &dst->na_rxid); + ISP_IOXPUT_16(isp, src->na_srr_reloff_hi, &dst->na_srr_reloff_hi); + ISP_IOXPUT_16(isp, src->na_srr_reloff_lo, &dst->na_srr_reloff_lo); + ISP_IOXPUT_16(isp, src->na_srr_iu, &dst->na_srr_iu); + ISP_IOXPUT_16(isp, src->na_srr_flags, &dst->na_srr_flags); + for (i = 0; i < 18; i++) { + ISP_IOXPUT_8(isp, src->na_reserved3[i], &dst->na_reserved3[i]); + } + ISP_IOXPUT_8(isp, src->na_reserved4, &dst->na_reserved4); + ISP_IOXPUT_8(isp, src->na_vpindex, &dst->na_vpindex); + ISP_IOXPUT_8(isp, src->na_srr_reject_vunique, + &dst->na_srr_reject_vunique); + ISP_IOXPUT_8(isp, src->na_srr_reject_explanation, + &dst->na_srr_reject_explanation); + ISP_IOXPUT_8(isp, src->na_srr_reject_code, &dst->na_srr_reject_code); + ISP_IOXPUT_8(isp, src->na_reserved5, &dst->na_reserved5); + for (i = 0; i < 6; i++) { + ISP_IOXPUT_8(isp, src->na_reserved6[i], &dst->na_reserved6[i]); + } + ISP_IOXPUT_16(isp, src->na_oxid, &dst->na_oxid); +} + +void +isp_get_notify_ack_fc(struct ispsoftc *isp, na_fcentry_t *src, + na_fcentry_t *dst) +{ + int i; + isp_get_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved); + ISP_IOXGET_8(isp, &src->na_reserved1, dst->na_reserved1); + ISP_IOXGET_8(isp, &src->na_iid, dst->na_iid); + ISP_IOXGET_16(isp, &src->na_response, dst->na_response); + ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags); + ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2); + ISP_IOXGET_16(isp, &src->na_status, dst->na_status); + ISP_IOXGET_16(isp, &src->na_task_flags, dst->na_task_flags); + ISP_IOXGET_16(isp, &src->na_seqid, dst->na_seqid); + for (i = 0; i < NA2_RSVDLEN; i++) { + ISP_IOXGET_16(isp, &src->na_reserved3[i], + dst->na_reserved3[i]); + } +} + +void +isp_get_notify_ack_fc_e(struct ispsoftc *isp, na_fcentry_e_t *src, + na_fcentry_e_t *dst) +{ + int i; + isp_get_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved); + ISP_IOXGET_16(isp, &src->na_iid, dst->na_iid); + ISP_IOXGET_16(isp, &src->na_response, dst->na_response); + ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags); + ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2); + ISP_IOXGET_16(isp, &src->na_status, dst->na_status); + ISP_IOXGET_16(isp, &src->na_task_flags, dst->na_task_flags); + ISP_IOXGET_16(isp, &src->na_seqid, dst->na_seqid); + for (i = 0; i < NA2_RSVDLEN; i++) { + ISP_IOXGET_16(isp, &src->na_reserved3[i], + dst->na_reserved3[i]); + } +} + +void +isp_get_notify_ack_24xx(struct ispsoftc *isp, na_fcentry_24xx_t *src, + na_fcentry_24xx_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXGET_32(isp, &src->na_handle, dst->na_handle); + ISP_IOXGET_16(isp, &src->na_nphdl, dst->na_nphdl); + ISP_IOXGET_16(isp, &src->na_reserved1, dst->na_reserved1); + ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags); + ISP_IOXGET_16(isp, &src->na_srr_rxid, dst->na_srr_rxid); + ISP_IOXGET_16(isp, &src->na_status, dst->na_status); + ISP_IOXGET_8(isp, &src->na_status_subcode, dst->na_status_subcode); + ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2); + ISP_IOXGET_32(isp, &src->na_rxid, dst->na_rxid); + ISP_IOXGET_16(isp, &src->na_srr_reloff_hi, dst->na_srr_reloff_hi); + ISP_IOXGET_16(isp, &src->na_srr_reloff_lo, dst->na_srr_reloff_lo); + ISP_IOXGET_16(isp, &src->na_srr_iu, dst->na_srr_iu); + ISP_IOXGET_16(isp, &src->na_srr_flags, dst->na_srr_flags); + for (i = 0; i < 18; i++) { + ISP_IOXGET_8(isp, &src->na_reserved3[i], dst->na_reserved3[i]); + } + ISP_IOXGET_8(isp, &src->na_reserved4, dst->na_reserved4); + ISP_IOXGET_8(isp, &src->na_vpindex, dst->na_vpindex); + ISP_IOXGET_8(isp, &src->na_srr_reject_vunique, + dst->na_srr_reject_vunique); + ISP_IOXGET_8(isp, &src->na_srr_reject_explanation, + dst->na_srr_reject_explanation); + ISP_IOXGET_8(isp, &src->na_srr_reject_code, dst->na_srr_reject_code); + ISP_IOXGET_8(isp, &src->na_reserved5, dst->na_reserved5); + for (i = 0; i < 6; i++) { + ISP_IOXGET_8(isp, &src->na_reserved6[i], dst->na_reserved6[i]); + } + ISP_IOXGET_16(isp, &src->na_oxid, dst->na_oxid); +} + +void +isp_get_abts(struct ispsoftc *isp, abts_t *src, abts_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->abts_header, &dst->abts_header); + for (i = 0; i < 6; i++) { + ISP_IOXGET_8(isp, &src->abts_reserved0[i], + dst->abts_reserved0[i]); + } + ISP_IOXGET_16(isp, &src->abts_nphdl, dst->abts_nphdl); + ISP_IOXGET_16(isp, &src->abts_reserved1, dst->abts_reserved1); + ISP_IOXGET_16(isp, &src->abts_sof, dst->abts_sof); + ISP_IOXGET_32(isp, &src->abts_rxid_abts, dst->abts_rxid_abts); + ISP_IOXGET_16(isp, &src->abts_did_lo, dst->abts_did_lo); + ISP_IOXGET_8(isp, &src->abts_did_hi, dst->abts_did_hi); + ISP_IOXGET_8(isp, &src->abts_r_ctl, dst->abts_r_ctl); + ISP_IOXGET_16(isp, &src->abts_sid_lo, dst->abts_sid_lo); + ISP_IOXGET_8(isp, &src->abts_sid_hi, dst->abts_sid_hi); + ISP_IOXGET_8(isp, &src->abts_cs_ctl, dst->abts_cs_ctl); + ISP_IOXGET_16(isp, &src->abts_fs_ctl, dst->abts_fs_ctl); + ISP_IOXGET_8(isp, &src->abts_f_ctl, dst->abts_f_ctl); + ISP_IOXGET_8(isp, &src->abts_type, dst->abts_type); + ISP_IOXGET_16(isp, &src->abts_seq_cnt, dst->abts_seq_cnt); + ISP_IOXGET_8(isp, &src->abts_df_ctl, dst->abts_df_ctl); + ISP_IOXGET_8(isp, &src->abts_seq_id, dst->abts_seq_id); + ISP_IOXGET_16(isp, &src->abts_rx_id, dst->abts_rx_id); + ISP_IOXGET_16(isp, &src->abts_ox_id, dst->abts_ox_id); + ISP_IOXGET_32(isp, &src->abts_param, dst->abts_param); + for (i = 0; i < 16; i++) { + ISP_IOXGET_8(isp, &src->abts_reserved2[i], + dst->abts_reserved2[i]); + } + ISP_IOXGET_32(isp, &src->abts_rxid_task, dst->abts_rxid_task); +} + +void +isp_put_abts_rsp(struct ispsoftc *isp, abts_rsp_t *src, abts_rsp_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->abts_rsp_header, &dst->abts_rsp_header); + ISP_IOXPUT_32(isp, src->abts_rsp_handle, &dst->abts_rsp_handle); + ISP_IOXPUT_16(isp, src->abts_rsp_status, &dst->abts_rsp_status); + ISP_IOXPUT_16(isp, src->abts_rsp_nphdl, &dst->abts_rsp_nphdl); + ISP_IOXPUT_16(isp, src->abts_rsp_ctl_flags, &dst->abts_rsp_ctl_flags); + ISP_IOXPUT_16(isp, src->abts_rsp_sof, &dst->abts_rsp_sof); + ISP_IOXPUT_32(isp, src->abts_rsp_rxid_abts, &dst->abts_rsp_rxid_abts); + ISP_IOXPUT_16(isp, src->abts_rsp_did_lo, &dst->abts_rsp_did_lo); + ISP_IOXPUT_8(isp, src->abts_rsp_did_hi, &dst->abts_rsp_did_hi); + ISP_IOXPUT_8(isp, src->abts_rsp_r_ctl, &dst->abts_rsp_r_ctl); + ISP_IOXPUT_16(isp, src->abts_rsp_sid_lo, &dst->abts_rsp_sid_lo); + ISP_IOXPUT_8(isp, src->abts_rsp_sid_hi, &dst->abts_rsp_sid_hi); + ISP_IOXPUT_8(isp, src->abts_rsp_cs_ctl, &dst->abts_rsp_cs_ctl); + ISP_IOXPUT_16(isp, src->abts_rsp_f_ctl_lo, &dst->abts_rsp_f_ctl_lo); + ISP_IOXPUT_8(isp, src->abts_rsp_f_ctl_hi, &dst->abts_rsp_f_ctl_hi); + ISP_IOXPUT_8(isp, src->abts_rsp_type, &dst->abts_rsp_type); + ISP_IOXPUT_16(isp, src->abts_rsp_seq_cnt, &dst->abts_rsp_seq_cnt); + ISP_IOXPUT_8(isp, src->abts_rsp_df_ctl, &dst->abts_rsp_df_ctl); + ISP_IOXPUT_8(isp, src->abts_rsp_seq_id, &dst->abts_rsp_seq_id); + ISP_IOXPUT_16(isp, src->abts_rsp_rx_id, &dst->abts_rsp_rx_id); + ISP_IOXPUT_16(isp, src->abts_rsp_ox_id, &dst->abts_rsp_ox_id); + ISP_IOXPUT_32(isp, src->abts_rsp_param, &dst->abts_rsp_param); + if (src->abts_rsp_r_ctl == BA_ACC) { + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.reserved, + &dst->abts_rsp_payload.ba_acc.reserved); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.last_seq_id, + &dst->abts_rsp_payload.ba_acc.last_seq_id); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.seq_id_valid, + &dst->abts_rsp_payload.ba_acc.seq_id_valid); + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_rx_id, + &dst->abts_rsp_payload.ba_acc.aborted_rx_id); + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_ox_id, + &dst->abts_rsp_payload.ba_acc.aborted_ox_id); + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.high_seq_cnt, + &dst->abts_rsp_payload.ba_acc.high_seq_cnt); + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.low_seq_cnt, + &dst->abts_rsp_payload.ba_acc.low_seq_cnt); + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, + src->abts_rsp_payload.ba_acc.reserved2[i], + &dst->abts_rsp_payload.ba_acc.reserved2[i]); + } + } else if (src->abts_rsp_r_ctl == BA_RJT) { + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.vendor_unique, + &dst->abts_rsp_payload.ba_rjt.vendor_unique); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.explanation, + &dst->abts_rsp_payload.ba_rjt.explanation); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reason, + &dst->abts_rsp_payload.ba_rjt.reason); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reserved, + &dst->abts_rsp_payload.ba_rjt.reserved); + for (i = 0; i < 12; i++) { + ISP_IOXPUT_16(isp, + src->abts_rsp_payload.ba_rjt.reserved2[i], + &dst->abts_rsp_payload.ba_rjt.reserved2[i]); + } + } else { + for (i = 0; i < 16; i++) { + ISP_IOXPUT_8(isp, src->abts_rsp_payload.reserved[i], + &dst->abts_rsp_payload.reserved[i]); + } + } + ISP_IOXPUT_32(isp, src->abts_rsp_rxid_task, &dst->abts_rsp_rxid_task); +} + +void +isp_get_abts_rsp(struct ispsoftc *isp, abts_rsp_t *src, abts_rsp_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->abts_rsp_header, &dst->abts_rsp_header); + ISP_IOXGET_32(isp, &src->abts_rsp_handle, dst->abts_rsp_handle); + ISP_IOXGET_16(isp, &src->abts_rsp_status, dst->abts_rsp_status); + ISP_IOXGET_16(isp, &src->abts_rsp_nphdl, dst->abts_rsp_nphdl); + ISP_IOXGET_16(isp, &src->abts_rsp_ctl_flags, dst->abts_rsp_ctl_flags); + ISP_IOXGET_16(isp, &src->abts_rsp_sof, dst->abts_rsp_sof); + ISP_IOXGET_32(isp, &src->abts_rsp_rxid_abts, dst->abts_rsp_rxid_abts); + ISP_IOXGET_16(isp, &src->abts_rsp_did_lo, dst->abts_rsp_did_lo); + ISP_IOXGET_8(isp, &src->abts_rsp_did_hi, dst->abts_rsp_did_hi); + ISP_IOXGET_8(isp, &src->abts_rsp_r_ctl, dst->abts_rsp_r_ctl); + ISP_IOXGET_16(isp, &src->abts_rsp_sid_lo, dst->abts_rsp_sid_lo); + ISP_IOXGET_8(isp, &src->abts_rsp_sid_hi, dst->abts_rsp_sid_hi); + ISP_IOXGET_8(isp, &src->abts_rsp_cs_ctl, dst->abts_rsp_cs_ctl); + ISP_IOXGET_16(isp, &src->abts_rsp_f_ctl_lo, dst->abts_rsp_f_ctl_lo); + ISP_IOXGET_8(isp, &src->abts_rsp_f_ctl_hi, dst->abts_rsp_f_ctl_hi); + ISP_IOXGET_8(isp, &src->abts_rsp_type, dst->abts_rsp_type); + ISP_IOXGET_16(isp, &src->abts_rsp_seq_cnt, dst->abts_rsp_seq_cnt); + ISP_IOXGET_8(isp, &src->abts_rsp_df_ctl, dst->abts_rsp_df_ctl); + ISP_IOXGET_8(isp, &src->abts_rsp_seq_id, dst->abts_rsp_seq_id); + ISP_IOXGET_16(isp, &src->abts_rsp_rx_id, dst->abts_rsp_rx_id); + ISP_IOXGET_16(isp, &src->abts_rsp_ox_id, dst->abts_rsp_ox_id); + ISP_IOXGET_32(isp, &src->abts_rsp_param, dst->abts_rsp_param); + for (i = 0; i < 8; i++) { + ISP_IOXGET_8(isp, &src->abts_rsp_payload.rsp.reserved[i], + dst->abts_rsp_payload.rsp.reserved[i]); + } + ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode1, + dst->abts_rsp_payload.rsp.subcode1); + ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode2, + dst->abts_rsp_payload.rsp.subcode2); + ISP_IOXGET_32(isp, &src->abts_rsp_rxid_task, dst->abts_rsp_rxid_task); +} +#endif /* ISP_TARGET_MODE */ diff --git a/sys/dev/ic/isp_library.h b/sys/dev/ic/isp_library.h index 3b9ec400c87..a42dcd322ec 100644 --- a/sys/dev/ic/isp_library.h +++ b/sys/dev/ic/isp_library.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_library.h,v 1.1 2008/11/16 00:00:13 krw Exp $ */ +/* $OpenBSD: isp_library.h,v 1.2 2009/06/24 11:00:53 krw Exp $ */ /* $FreeBSD: src/sys/dev/isp/isp_library.h,v 1.8 2007/04/02 01:04:20 mjacob Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob @@ -29,122 +29,197 @@ #ifndef _ISP_LIBRARY_H #define _ISP_LIBRARY_H -#include <dev/ic/isp_openbsd.h> - -extern int isp_save_xs(struct ispsoftc *, XS_T *, u_int16_t *); -extern XS_T *isp_find_xs(struct ispsoftc *, u_int16_t); -extern u_int16_t isp_find_handle(struct ispsoftc *, XS_T *); -extern int isp_handle_index(u_int16_t); -extern void isp_destroy_handle(struct ispsoftc *, u_int16_t); -extern void isp_remove_handle(struct ispsoftc *, XS_T *); - -extern int -isp_getrqentry(struct ispsoftc *, u_int16_t *, u_int16_t *, void **); - +extern int isp_save_xs(ispsoftc_t *, XS_T *, u_int32_t *); +extern XS_T *isp_find_xs(ispsoftc_t *, u_int32_t); +extern u_int32_t isp_find_handle(ispsoftc_t *, XS_T *); +extern u_int32_t isp_handle_index(u_int32_t); +extern void isp_destroy_handle(ispsoftc_t *, u_int32_t); +extern int isp_getrqentry(ispsoftc_t *, u_int32_t *, u_int32_t *, void **); +extern void isp_print_qentry (ispsoftc_t *, char *, int, void *); +extern void isp_print_bytes(ispsoftc_t *, const char *, int, void *); +extern int isp_fc_runstate(ispsoftc_t *, int); +extern void isp_dump_portdb(ispsoftc_t *); +extern void isp_shutdown(ispsoftc_t *); +extern void isp_put_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *); +extern void isp_get_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *); +extern int isp_get_response_type(ispsoftc_t *, isphdr_t *); extern void -isp_print_qentry (struct ispsoftc *, char *, int, void *); - - -#define TBA (4 * (((QENTRY_LEN >> 2) * 3) + 1) + 1) - +isp_put_request(ispsoftc_t *, ispreq_t *, ispreq_t *); extern void -isp_print_bytes(struct ispsoftc *, char *, int, void *); - -extern int isp_fc_runstate(struct ispsoftc *, int); - -extern void isp_copy_out_hdr(struct ispsoftc *, isphdr_t *, isphdr_t *); -extern void isp_copy_in_hdr(struct ispsoftc *, isphdr_t *, isphdr_t *); -extern int isp_get_response_type(struct ispsoftc *, isphdr_t *); - +isp_put_marker(ispsoftc_t *, isp_marker_t *, isp_marker_t *); +extern void +isp_put_marker_24xx(ispsoftc_t *, isp_marker_24xx_t *, isp_marker_24xx_t *); +extern void +isp_put_request_t2(ispsoftc_t *, ispreqt2_t *, ispreqt2_t *); +extern void +isp_put_request_t2e(ispsoftc_t *, ispreqt2e_t *, ispreqt2e_t *); extern void -isp_put_request(struct ispsoftc *, ispreq_t *, ispreq_t *); +isp_put_request_t3(ispsoftc_t *, ispreqt3_t *, ispreqt3_t *); extern void -isp_put_request_t2(struct ispsoftc *, ispreqt2_t *, ispreqt2_t *); +isp_put_request_t3e(ispsoftc_t *, ispreqt3e_t *, ispreqt3e_t *); extern void -isp_put_request_t3(struct ispsoftc *, ispreqt3_t *, ispreqt3_t *); +isp_put_extended_request(ispsoftc_t *, ispextreq_t *, ispextreq_t *); extern void -isp_put_extended_request(struct ispsoftc *, ispextreq_t *, ispextreq_t *); +isp_put_request_t7(ispsoftc_t *, ispreqt7_t *, ispreqt7_t *); extern void -isp_put_cont_req(struct ispsoftc *, ispcontreq_t *, ispcontreq_t *); +isp_put_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *); extern void -isp_put_cont64_req(struct ispsoftc *, ispcontreq64_t *, ispcontreq64_t *); +isp_put_cont_req(ispsoftc_t *, ispcontreq_t *, ispcontreq_t *); extern void -isp_get_response(struct ispsoftc *, ispstatusreq_t *, ispstatusreq_t *); +isp_put_cont64_req(ispsoftc_t *, ispcontreq64_t *, ispcontreq64_t *); extern void -isp_get_response_x(struct ispsoftc *, ispstatus_cont_t *, ispstatus_cont_t *); +isp_get_response(ispsoftc_t *, ispstatusreq_t *, ispstatusreq_t *); +extern void isp_get_24xx_response(ispsoftc_t *, isp24xx_statusreq_t *, + isp24xx_statusreq_t *); +void +isp_get_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *); extern void -isp_get_rio2(struct ispsoftc *, isp_rio2_t *, isp_rio2_t *); +isp_get_rio2(ispsoftc_t *, isp_rio2_t *, isp_rio2_t *); extern void -isp_put_icb(struct ispsoftc *, isp_icb_t *, isp_icb_t *); +isp_put_icb(ispsoftc_t *, isp_icb_t *, isp_icb_t *); extern void -isp_get_pdb(struct ispsoftc *, isp_pdb_t *, isp_pdb_t *); +isp_put_icb_2400(ispsoftc_t *, isp_icb_2400_t *, isp_icb_2400_t *); extern void -isp_get_ct_hdr(struct ispsoftc *isp, ct_hdr_t *, ct_hdr_t *); +isp_get_pdb_21xx(ispsoftc_t *, isp_pdb_21xx_t *, isp_pdb_21xx_t *); extern void -isp_put_sns_request(struct ispsoftc *, sns_screq_t *, sns_screq_t *); +isp_get_pdb_24xx(ispsoftc_t *, isp_pdb_24xx_t *, isp_pdb_24xx_t *); extern void -isp_put_gid_ft_request(struct ispsoftc *, sns_gid_ft_req_t *, +isp_get_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *); +extern void +isp_put_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *); +extern void +isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *); +extern void +isp_get_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *); +extern void +isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *); +extern void +isp_put_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *); +extern void +isp_put_sns_request(ispsoftc_t *, sns_screq_t *, sns_screq_t *); +extern void +isp_put_gid_ft_request(ispsoftc_t *, sns_gid_ft_req_t *, sns_gid_ft_req_t *); extern void -isp_put_gxn_id_request(struct ispsoftc *, sns_gxn_id_req_t *, +isp_put_gxn_id_request(ispsoftc_t *, sns_gxn_id_req_t *, sns_gxn_id_req_t *); extern void -isp_get_sns_response(struct ispsoftc *, sns_scrsp_t *, sns_scrsp_t *, int); +isp_get_sns_response(ispsoftc_t *, sns_scrsp_t *, sns_scrsp_t *, int); extern void -isp_get_gid_ft_response(struct ispsoftc *, sns_gid_ft_rsp_t *, +isp_get_gid_ft_response(ispsoftc_t *, sns_gid_ft_rsp_t *, sns_gid_ft_rsp_t *, int); extern void -isp_get_gxn_id_response(struct ispsoftc *, sns_gxn_id_rsp_t *, +isp_get_gxn_id_response(ispsoftc_t *, sns_gxn_id_rsp_t *, sns_gxn_id_rsp_t *); extern void -isp_get_gff_id_response(struct ispsoftc *, sns_gff_id_rsp_t *, +isp_get_gff_id_response(ispsoftc_t *, sns_gff_id_rsp_t *, sns_gff_id_rsp_t *); extern void -isp_get_ga_nxt_response(struct ispsoftc *, sns_ga_nxt_rsp_t *, +isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *, sns_ga_nxt_rsp_t *); +extern void +isp_get_els(ispsoftc_t *, els_t *, els_t *); +extern void +isp_put_els(ispsoftc_t *, els_t *, els_t *); +extern void +isp_get_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *); +extern void +isp_get_fcp_cmnd_iu(ispsoftc_t *, fcp_cmnd_iu_t *, fcp_cmnd_iu_t *); +extern void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *); +extern void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *); +extern void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *); + +#define ISP_HANDLE_MASK 0x7fff + #ifdef ISP_TARGET_MODE -#ifndef _ISP_TARGET_H +#if defined(__NetBSD__) || defined(__OpenBSD__) +#include <dev/ic/isp_target.h> +#elif defined(__FreeBSD__) +#include <dev/isp/isp_target.h> +#else #include "isp_target.h" #endif + +#define IS_TARGET_HANDLE(x) ((x) & 0x8000) + +extern int isp_save_xs_tgt(ispsoftc_t *, void *, u_int32_t *); +extern void *isp_find_xs_tgt(ispsoftc_t *, u_int32_t); +extern u_int32_t isp_find_tgt_handle(ispsoftc_t *, void *); +extern void isp_destroy_tgt_handle(ispsoftc_t *, u_int32_t); + extern void -isp_put_atio(struct ispsoftc *, at_entry_t *, at_entry_t *); +isp_put_atio(ispsoftc_t *, at_entry_t *, at_entry_t *); extern void -isp_get_atio(struct ispsoftc *, at_entry_t *, at_entry_t *); +isp_get_atio(ispsoftc_t *, at_entry_t *, at_entry_t *); extern void -isp_put_atio2(struct ispsoftc *, at2_entry_t *, at2_entry_t *); +isp_put_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *); extern void -isp_get_atio2(struct ispsoftc *, at2_entry_t *, at2_entry_t *); +isp_put_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *); extern void -isp_put_ctio(struct ispsoftc *, ct_entry_t *, ct_entry_t *); +isp_get_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *); extern void -isp_get_ctio(struct ispsoftc *, ct_entry_t *, ct_entry_t *); +isp_get_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *); extern void -isp_put_ctio2(struct ispsoftc *, ct2_entry_t *, ct2_entry_t *); +isp_get_atio7(ispsoftc_t *isp, at7_entry_t *, at7_entry_t *); extern void -isp_get_ctio2(struct ispsoftc *, ct2_entry_t *, ct2_entry_t *); +isp_put_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *); extern void -isp_put_enable_lun(struct ispsoftc *, lun_entry_t *, lun_entry_t *); +isp_get_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *); extern void -isp_get_enable_lun(struct ispsoftc *, lun_entry_t *, lun_entry_t *); +isp_put_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *); extern void -isp_put_notify(struct ispsoftc *, in_entry_t *, in_entry_t *); +isp_put_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *); extern void -isp_get_notify(struct ispsoftc *, in_entry_t *, in_entry_t *); +isp_put_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *); extern void -isp_put_notify_fc(struct ispsoftc *, in_fcentry_t *, in_fcentry_t *); +isp_get_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *); extern void -isp_get_notify_fc(struct ispsoftc *, in_fcentry_t *, in_fcentry_t *); +isp_get_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *); extern void -isp_put_notify_ack(struct ispsoftc *, na_entry_t *, na_entry_t *); +isp_get_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *); extern void -isp_get_notify_ack(struct ispsoftc *, na_entry_t *, na_entry_t *); +isp_put_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *); extern void -isp_put_notify_ack_fc(struct ispsoftc *, na_fcentry_t *, na_fcentry_t *); +isp_get_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *); extern void -isp_get_notify_ack_fc(struct ispsoftc *, na_fcentry_t *, na_fcentry_t *); -#endif - -#define ISP_IS_SBUS(isp) \ - (ISP_SBUS_SUPPORTED && (isp)->isp_bustype == ISP_BT_SBUS) - +isp_put_notify(ispsoftc_t *, in_entry_t *, in_entry_t *); +extern void +isp_get_notify(ispsoftc_t *, in_entry_t *, in_entry_t *); +extern void +isp_put_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *); +extern void +isp_put_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *); +extern void +isp_put_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *); +extern void +isp_get_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *); +extern void +isp_get_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *); +extern void +isp_get_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *); +extern void +isp_put_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *); +extern void +isp_get_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *); +extern void +isp_put_notify_24xx_ack(ispsoftc_t *, na_fcentry_24xx_t *, na_fcentry_24xx_t *); +extern void +isp_put_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *); +extern void +isp_put_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *); +extern void isp_put_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *, + na_fcentry_24xx_t *); +extern void +isp_get_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *); +extern void +isp_get_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *); +extern void isp_get_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *, + na_fcentry_24xx_t *); +extern void +isp_get_abts(ispsoftc_t *, abts_t *, abts_t *); +extern void +isp_put_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *); +extern void +isp_get_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *); +#endif /* ISP_TARGET_MODE */ #endif /* _ISP_LIBRARY_H */ diff --git a/sys/dev/ic/isp_openbsd.c b/sys/dev/ic/isp_openbsd.c index ef65d585b58..1f979ebba07 100644 --- a/sys/dev/ic/isp_openbsd.c +++ b/sys/dev/ic/isp_openbsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_openbsd.c,v 1.35 2009/02/16 21:19:06 miod Exp $ */ +/* $OpenBSD: isp_openbsd.c,v 1.36 2009/06/24 11:00:53 krw Exp $ */ /* * Platform (OpenBSD) dependent common attachment code for QLogic adapters. * @@ -40,8 +40,6 @@ * San Francisco, CA, 94131 */ -/* expand expensive inline functions here. */ -#define EXPENSIVE_INLINE #include <dev/ic/isp_openbsd.h> /* @@ -66,18 +64,28 @@ static void ispminphys(struct buf *, struct scsi_link *); static int32_t ispcmd_slow(XS_T *); static int32_t ispcmd(XS_T *); -static struct scsi_device isp_dev = { NULL, NULL, NULL, NULL }; +struct scsi_device isp_dev = { NULL, NULL, NULL, NULL }; -static int isp_polled_cmd (struct ispsoftc *, XS_T *); -static void isp_wdog (void *); -static void isp_requeue(void *); -static void isp_trestart(void *); -static void isp_restart(struct ispsoftc *); +int isp_polled_cmd (struct ispsoftc *, XS_T *); +void isp_wdog (void *); +void isp_make_here(ispsoftc_t *, int); +void isp_make_gone(ispsoftc_t *, int); +void isp_requeue(void *); +void isp_trestart(void *); +void isp_restart(struct ispsoftc *); +void isp_add2_blocked_queue(struct ispsoftc *isp, XS_T *xs); +int isp_mstohz(int ms); struct cfdriver isp_cd = { NULL, "isp", DV_DULL }; +static const char *roles[4] = { + "(none)", "Target", "Initiator", "Target/Initiator" +}; +static const char prom3[] = + "PortID 0x%06x Departed from Target %u because of %s"; +#define isp_change_is_bad 0 /* * Complete attachment of hardware, include subdevices. @@ -104,8 +112,7 @@ isp_attach(struct ispsoftc *isp) isp->isp_osinfo._adapter.scsi_cmd = ispcmd_slow; if (IS_FC(isp)) { lptr->adapter_buswidth = MAX_FC_TARG; - /* We can set max lun width here */ - /* loopid set below */ + lptr->adapter_target = MAX_FC_TARG; /* i.e. ignore. */ } else { sdparam *sdp = isp->isp_param; lptr->adapter_buswidth = MAX_TARGETS; @@ -147,17 +154,10 @@ isp_attach(struct ispsoftc *isp) */ delay(4 * 1000000); } else { - fcparam *fcp = isp->isp_param; - int defid = MAX_FC_TARG; delay(2 * 1000000); ISP_LOCK(isp); isp_fc_runstate(isp, 10 * 1000000); - if (fcp->isp_fwstate == FW_READY && - fcp->isp_loopstate >= LOOP_PDB_RCVD) { - defid = fcp->isp_loopid; - } ISP_UNLOCK(isp); - lptr->adapter_target = defid; } bzero(&saa, sizeof(saa)); @@ -195,7 +195,7 @@ ispminphys(struct buf *bp, struct scsi_link *sl) minphys(bp); } -static int32_t +int32_t ispcmd_slow(XS_T *xs) { sdparam *sdp; @@ -273,9 +273,7 @@ ispcmd_slow(XS_T *xs) return (ispcmd(xs)); } -static INLINE void isp_add2_blocked_queue(struct ispsoftc *, XS_T *); - -static INLINE void +void isp_add2_blocked_queue(struct ispsoftc *isp, XS_T *xs) { if (isp->isp_osinfo.wqf != NULL) { @@ -287,7 +285,7 @@ isp_add2_blocked_queue(struct ispsoftc *isp, XS_T *xs) xs->free_list.le_next = NULL; } -static int32_t +int32_t ispcmd(XS_T *xs) { struct ispsoftc *isp; @@ -308,16 +306,16 @@ ispcmd(XS_T *xs) ISP_LOCK(isp); if (isp->isp_state < ISP_RUNSTATE) { - DISABLE_INTS(isp); + ISP_DISABLE_INTS(isp); isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); ISP_UNLOCK(isp); XS_SETERR(xs, HBA_BOTCH); return (CMD_COMPLETE); } isp->isp_state = ISP_RUNSTATE; - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); } /* @@ -385,7 +383,7 @@ ispcmd(XS_T *xs) return (result); } -static int +int isp_polled_cmd(struct ispsoftc *isp, XS_T *xs) { int result; @@ -418,7 +416,8 @@ isp_polled_cmd(struct ispsoftc *isp, XS_T *xs) infinite = 1; while (mswait || infinite) { - u_int16_t isr, sema, mbox; + u_int32_t isr; + u_int16_t sema, mbox; if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { isp_intr(isp, isr, sema, mbox); if (XS_CMD_DONE_P(xs)) { @@ -470,7 +469,7 @@ isp_done(XS_T *xs) } } -static void +void isp_wdog(void *arg) { XS_T *xs = arg; @@ -485,7 +484,8 @@ isp_wdog(void *arg) ISP_LOCK(isp); handle = isp_find_handle(isp, xs); if (handle) { - u_int16_t isr, sema, mbox; + u_int32_t isr; + u_int16_t sema, mbox; if (XS_CMD_DONE_P(xs)) { isp_prt(isp, ISP_LOGDEBUG1, @@ -534,7 +534,7 @@ isp_wdog(void *arg) XS_CMD_S_CLEAR(xs); isp_done(xs); } else { - u_int16_t nxti, optr; + u_int32_t optr, nxti; ispreq_t local, *mp = &local, *qe; isp_prt(isp, ISP_LOGWARN, @@ -551,7 +551,7 @@ isp_wdog(void *arg) MEMZERO((void *) mp, sizeof (*mp)); mp->req_header.rqs_entry_count = 1; mp->req_header.rqs_entry_type = RQSTYPE_MARKER; - mp->req_modifier = SYNC_ALL; + mp->req_cdblen = SYNC_ALL; mp->req_target = XS_CHANNEL(xs) << 7; isp_put_request(isp, mp, qe); ISP_ADD_REQUEST(isp, nxti); @@ -562,6 +562,18 @@ isp_wdog(void *arg) ISP_UNLOCK(isp); } +void +isp_make_here(ispsoftc_t *isp, int tgt) +{ + isp_prt(isp, ISP_LOGINFO, "target %d has arrived", tgt); +} + +void +isp_make_gone(ispsoftc_t *isp, int tgt) +{ + isp_prt(isp, ISP_LOGINFO, "target %d has departed", tgt); +} + /* * Free any associated resources prior to decommissioning and * set the card to a known state (so it doesn't wake up and kick @@ -576,7 +588,7 @@ isp_uninit(struct ispsoftc *isp) /* * Leave with interrupts disabled. */ - DISABLE_INTS(isp); + ISP_DISABLE_INTS(isp); ISP_UNLOCK(isp); } @@ -584,7 +596,7 @@ isp_uninit(struct ispsoftc *isp) /* * Restart function for a command to be requeued later. */ -static void +void isp_requeue(void *arg) { int r; @@ -629,7 +641,7 @@ isp_requeue(void *arg) * Restart function after a LOOP UP event or a command completing, * sometimes done as a timeout for some hysteresis. */ -static void +void isp_trestart(void *arg) { struct ispsoftc *isp = arg; @@ -657,7 +669,7 @@ isp_trestart(void *arg) } } -static void +void isp_restart(struct ispsoftc *isp) { struct scsi_xfer *list; @@ -683,6 +695,14 @@ int isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) { int bus, tgt; + char *msg = NULL; + static const char prom[] = + "PortID 0x%06x handle 0x%x role %s %s\n" + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + static const char prom2[] = + "PortID 0x%06x handle 0x%x role %s %s tgt %u\n" + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + fcportdb_t *lp; switch (cmd) { case ISPASYNC_NEW_TGT_PARAMS: @@ -779,147 +799,157 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) timeout_add(&isp->isp_osinfo.rqt, 1); isp_prt(isp, ISP_LOGINFO, "Loop UP"); break; - case ISPASYNC_PROMENADE: - if (IS_FC(isp) && isp->isp_dblev) { - const char *fmt = "Target %d (Loop 0x%x) Port ID 0x%x " - "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x"; - const static char *roles[4] = { - "No", "Target", "Initiator", "Target/Initiator" - }; - fcparam *fcp = isp->isp_param; - int tgt = *((int *) arg); - struct lportdb *lp = &fcp->portdb[tgt]; - - isp_prt(isp, ISP_LOGINFO, fmt, tgt, lp->loopid, lp->portid, - roles[lp->roles & 0x3], - (lp->valid)? "Arrived" : "Departed", - (u_int32_t) (lp->port_wwn >> 32), - (u_int32_t) (lp->port_wwn & 0xffffffffLL), - (u_int32_t) (lp->node_wwn >> 32), - (u_int32_t) (lp->node_wwn & 0xffffffffLL)); - break; - } - case ISPASYNC_CHANGE_NOTIFY: - if (arg == (void *) 1) { - isp_prt(isp, ISP_LOGINFO, - "Name Server Database Changed"); + case ISPASYNC_DEV_ARRIVED: + lp = arg; + lp->reserved = 0; + if ((isp->isp_role & ISP_ROLE_INITIATOR) && + (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) { + int dbidx = lp - FCPARAM(isp)->portdb; + int i; + + for (i = 0; i < MAX_FC_TARG; i++) { + if (i >= FL_ID && i <= SNS_ID) { + continue; + } + if (FCPARAM(isp)->isp_ini_map[i] == 0) { + break; + } + } + if (i < MAX_FC_TARG) { + FCPARAM(isp)->isp_ini_map[i] = dbidx + 1; + lp->ini_map_idx = i + 1; + printf("ISPASYNC_DEV_ARRIVED: %d/%d\n", + i, FCPARAM(isp)->isp_ini_map[i]); + } else { + isp_prt(isp, ISP_LOGWARN, "out of target ids"); + isp_dump_portdb(isp); + } + } + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles], "arrived at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + isp_make_here(isp, tgt); } else { - isp_prt(isp, ISP_LOGINFO, - "Name Server Database Changed"); + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles], "arrived", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); } break; - case ISPASYNC_FABRIC_DEV: - { - int target, base, lim; - fcparam *fcp = isp->isp_param; - struct lportdb *lp = NULL; - struct lportdb *clp = (struct lportdb *) arg; - char *pt; - - switch (clp->port_type) { - case 1: - pt = " N_Port"; - break; - case 2: - pt = " NL_Port"; - break; - case 3: - pt = "F/NL_Port"; - break; - case 0x7f: - pt = " Nx_Port"; - break; - case 0x81: - pt = " F_port"; - break; - case 0x82: - pt = " FL_Port"; - break; - case 0x84: - pt = " E_port"; - break; - default: - pt = " "; - break; - } - - isp_prt(isp, ISP_LOGINFO, - "%s Fabric Device @ PortID 0x%x", pt, clp->portid); - - /* - * If we don't have an initiator role we bail. - * - * We just use ISPASYNC_FABRIC_DEV for announcement purposes. - */ - - if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) { - break; - } - - /* - * Is this entry for us? If so, we bail. - */ - - if (fcp->isp_portid == clp->portid) { - break; - } - - /* - * Else, the default policy is to find room for it in - * our local port database. Later, when we execute - * the call to isp_pdb_sync either this newly arrived - * or already logged in device will be (re)announced. - */ - - if (fcp->isp_topo == TOPO_FL_PORT) - base = FC_SNS_ID+1; - else - base = 0; - - if (fcp->isp_topo == TOPO_N_PORT) - lim = 1; - else - lim = MAX_FC_TARG; - - /* - * Is it already in our list? - */ - for (target = base; target < lim; target++) { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - continue; + case ISPASYNC_DEV_CHANGED: + lp = arg; + if (isp_change_is_bad) { + lp->state = FC_PORTDB_STATE_NIL; + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + FCPARAM(isp)->isp_ini_map[tgt] = 0; + printf("ISPASYNC_DEV_CHANGED: %d/%d\n", + tgt, FCPARAM(isp)->isp_ini_map[tgt]); + lp->ini_map_idx = 0; + isp_prt(isp, ISP_LOGCONFIG, prom3, + lp->portid, tgt, "change is bad"); + isp_make_gone(isp, tgt); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles], + "changed and departed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); } - lp = &fcp->portdb[target]; - if (lp->port_wwn == clp->port_wwn && - lp->node_wwn == clp->node_wwn) { - lp->fabric_dev = 1; - break; + } else { + lp->portid = lp->new_portid; + lp->roles = lp->new_roles; + if (lp->ini_map_idx) { + int t = lp->ini_map_idx - 1; + FCPARAM(isp)->isp_ini_map[t] = + (lp - FCPARAM(isp)->portdb) + 1; + printf("ISPASYNC_DEV_CHANGED(2): %d/%d\n", + t, FCPARAM(isp)->isp_ini_map[t]); + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles], "changed at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles], "changed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); } } - if (target < lim) { - break; + break; + case ISPASYNC_DEV_STAYED: + lp = arg; + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles], "stayed at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles], "stayed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); } - for (target = base; target < lim; target++) { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - continue; - } - lp = &fcp->portdb[target]; - if (lp->port_wwn == 0) { - break; - } + break; + case ISPASYNC_DEV_GONE: + lp = arg; + if (lp->ini_map_idx && lp->reserved == 0) { + lp->reserved = 1; + lp->state = FC_PORTDB_STATE_ZOMBIE; + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles], "gone zombie at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } else if (lp->reserved == 0) { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles], "departed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); } - if (target == lim) { - isp_prt(isp, ISP_LOGWARN, - "out of space for fabric devices"); - break; + break; + case ISPASYNC_CHANGE_NOTIFY: + if (arg == ISPASYNC_CHANGE_PDB) { + msg = "Port Database Changed"; + } else if (arg == ISPASYNC_CHANGE_SNS) { + msg = "Name Server Database Changed"; + } else { + msg = "Other Change Notify"; } - lp->port_type = clp->port_type; - lp->fc4_type = clp->fc4_type; - lp->node_wwn = clp->node_wwn; - lp->port_wwn = clp->port_wwn; - lp->portid = clp->portid; - lp->fabric_dev = 1; + isp_prt(isp, ISP_LOGINFO, msg); break; - } case ISPASYNC_FW_CRASH: { u_int16_t mbox1, mbox6; @@ -961,3 +991,135 @@ isp_prt(struct ispsoftc *isp, int level, const char *fmt, ...) va_end(ap); printf("\n"); } + +int +isp_mbox_acquire(ispsoftc_t *isp) +{ + if (isp->isp_osinfo.mboxbsy) { + return (1); + } else { + isp->isp_osinfo.mboxcmd_done = 0; + isp->isp_osinfo.mboxbsy = 1; + return (0); + } +} + +void +isp_lock(struct ispsoftc *isp) +{ + int s = splbio(); + if (isp->isp_osinfo.islocked++ == 0) { + isp->isp_osinfo.splsaved = s; + } else { + splx(s); + } +} + +void +isp_unlock(struct ispsoftc *isp) +{ + if (isp->isp_osinfo.islocked-- <= 1) { + isp->isp_osinfo.islocked = 0; + splx(isp->isp_osinfo.splsaved); + } +} + +u_int64_t +isp_nanotime_sub(struct timespec *b, struct timespec *a) +{ + struct timespec x; + u_int64_t elapsed; + timespecsub(b, a, &x); + elapsed = GET_NANOSEC(&x); + if (elapsed == 0) + elapsed++; + return (elapsed); +} + +void +isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp) +{ + unsigned int usecs = mbp->timeout; + unsigned int max, olim, ilim; + + if (usecs == 0) { + usecs = MBCMD_DEFAULT_TIMEOUT; + } + max = isp->isp_mbxwrk0 + 1; + + if (isp->isp_osinfo.mbox_sleep_ok) { + unsigned int ms = (usecs + 999) / 1000; + + isp->isp_osinfo.mbox_sleep_ok = 0; + isp->isp_osinfo.mbox_sleeping = 1; + for (olim = 0; olim < max; olim++) { + tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep", + isp_mstohz(ms)); + if (isp->isp_osinfo.mboxcmd_done) { + break; + } + } + isp->isp_osinfo.mbox_sleep_ok = 1; + isp->isp_osinfo.mbox_sleeping = 0; + } else { + for (olim = 0; olim < max; olim++) { + for (ilim = 0; ilim < usecs; ilim += 100) { + uint32_t isr; + uint16_t sema, mbox; + if (isp->isp_osinfo.mboxcmd_done) { + break; + } + if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { + isp_intr(isp, isr, sema, mbox); + if (isp->isp_osinfo.mboxcmd_done) { + break; + } + } + USEC_DELAY(100); + } + if (isp->isp_osinfo.mboxcmd_done) { + break; + } + } + } + if (isp->isp_osinfo.mboxcmd_done == 0) { + isp_prt(isp, ISP_LOGWARN, + "%s Mailbox Command (0x%x) Timeout (%uus)", + isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled", + isp->isp_lastmbxcmd, usecs); + mbp->param[0] = MBOX_TIMEOUT; + isp->isp_osinfo.mboxcmd_done = 1; + } +} + +void +isp_mbox_notify_done(ispsoftc_t *isp) +{ + if (isp->isp_osinfo.mbox_sleeping) { + wakeup(&isp->isp_mbxworkp); + } + isp->isp_osinfo.mboxcmd_done = 1; +} + +void +isp_mbox_release(ispsoftc_t *isp) +{ + isp->isp_osinfo.mboxbsy = 0; +} + +int +isp_mstohz(int ms) +{ + int hz; + struct timeval t; + t.tv_sec = ms / 1000; + t.tv_usec = (ms % 1000) * 1000; + hz = tvtohz(&t); + if (hz < 0) { + hz = 0x7fffffff; + } + if (hz == 0) { + hz = 1; + } + return (hz); +} diff --git a/sys/dev/ic/isp_openbsd.h b/sys/dev/ic/isp_openbsd.h index 19531cffcd2..01d3d6eccb7 100644 --- a/sys/dev/ic/isp_openbsd.h +++ b/sys/dev/ic/isp_openbsd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_openbsd.h,v 1.30 2008/11/17 00:22:13 krw Exp $ */ +/* $OpenBSD: isp_openbsd.h,v 1.31 2009/06/24 11:00:53 krw Exp $ */ /* * OpenBSD Specific definitions for the QLogic ISP Host Adapter */ @@ -62,8 +62,8 @@ #define ISP_SBUS_SUPPORTED 0 #endif -#define ISP_PLATFORM_VERSION_MAJOR 2 -#define ISP_PLATFORM_VERSION_MINOR 1 +#define ISP_PLATFORM_VERSION_MAJOR 5 +#define ISP_PLATFORM_VERSION_MINOR 9 struct isposinfo { struct device _dev; @@ -75,20 +75,29 @@ struct isposinfo { u_int32_t islocked; u_int32_t onintstack; #if !(defined(__sparc__) && !defined(__sparcv9__)) + bus_space_tag_t bus_tag; + bus_space_handle_t bus_handle; bus_dma_tag_t dmatag; - bus_dmamap_t rqdmap; - bus_dmamap_t rsdmap; - bus_dmamap_t scdmap; /* FC only */ + bus_dmamap_t cdmap; #define isp_dmatag isp_osinfo.dmatag -#define isp_rqdmap isp_osinfo.rqdmap -#define isp_rsdmap isp_osinfo.rsdmap -#define isp_scdmap isp_osinfo.scdmap +#define isp_cdmap isp_osinfo.cdmap +#define isp_bus_tag isp_osinfo.bus_tag +#define isp_bus_handle isp_osinfo.bus_handle #endif - unsigned int : 28, - - rtpend : 1, + uint32_t : 5, + simqfrozen : 3, + hysteresis : 8, + gdt_running : 1, + ldt_running : 1, + disabled : 1, + fcbsy : 1, + mbox_sleeping : 1, + mbox_sleep_ok : 1, + mboxcmd_done : 1, + mboxbsy : 1, no_mbox_ints : 1, - blocked : 2; + blocked : 2, + rtpend : 1; int _iid; union { u_int64_t _wwn; @@ -111,30 +120,20 @@ struct isposinfo { * Required Macros/Defines */ -#define INLINE __inline - -/* We don't want expensive inline functions. */ -#define EXP_INLINE - -#define ISP2100_SCRLEN 0x800 +#define ISP2100_SCRLEN 0x1000 #define MEMZERO bzero #define MEMCPY(dst, src, amt) bcopy((src), (dst), (amt)) #define SNPRINTF snprintf -#define USEC_DELAY(x) delay(x) -#define USEC_SLEEP(isp, x) \ - if (!MUST_POLL(isp)) \ - ISP_UNLOCK(isp); \ - delay(x); \ - if (!MUST_POLL(isp)) \ - ISP_LOCK(isp) +#define USEC_DELAY delay +#define USEC_SLEEP(isp, x) delay(x) #define NANOTIME_T struct timespec #define GET_NANOTIME nanotime #define GET_NANOSEC(x) (((x)->tv_sec * 1000000000 + (x)->tv_nsec)) #define NANOTIME_SUB isp_nanotime_sub -#define MAXISPREQUEST(isp) 256 +#define MAXISPREQUEST(isp) ((IS_FC(isp) || IS_ULTRA2(isp))? 1024 : 256) #if !(defined(__sparc__) && !defined(__sparcv9__)) #define MEMORYBARRIER(isp, type, offset, size) \ @@ -142,32 +141,37 @@ switch (type) { \ case SYNC_REQUEST: \ { \ off_t off = (off_t) offset * QENTRY_LEN; \ - bus_dmamap_sync(isp->isp_dmatag, isp->isp_rqdmap, \ + bus_dmamap_sync(isp->isp_dmatag, isp->isp_cdmap, \ off, size, BUS_DMASYNC_PREWRITE); \ break; \ } \ case SYNC_RESULT: \ { \ - off_t off = (off_t) offset * QENTRY_LEN; \ - bus_dmamap_sync(isp->isp_dmatag, isp->isp_rsdmap, \ + off_t off = (off_t) offset * QENTRY_LEN + \ + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); \ + bus_dmamap_sync(isp->isp_dmatag, isp->isp_cdmap, \ off, size, BUS_DMASYNC_POSTREAD); \ break; \ } \ case SYNC_SFORDEV: \ { \ off_t off = (off_t) offset; \ - bus_dmamap_sync(isp->isp_dmatag, isp->isp_scdmap, \ + bus_dmamap_sync(isp->isp_dmatag, isp->isp_cdmap, \ off, size, BUS_DMASYNC_PREWRITE); \ break; \ } \ case SYNC_SFORCPU: \ { \ off_t off = (off_t) offset; \ - bus_dmamap_sync(isp->isp_dmatag, isp->isp_scdmap, \ + bus_dmamap_sync(isp->isp_dmatag, isp->isp_cdmap, \ off, size, BUS_DMASYNC_POSTREAD); \ break; \ } \ case SYNC_REG: \ + bus_space_barrier(isp->isp_bus_tag, \ + isp->isp_bus_handle, offset, size, \ + BUS_SPACE_BARRIER_READ); \ + break; \ default: \ break; \ } @@ -175,20 +179,18 @@ default: \ #define MEMORYBARRIER(isp, type, offset, size) #endif -#define MBOX_ACQUIRE(isp) -#define MBOX_WAIT_COMPLETE isp_wait_complete +#define MBOX_ACQUIRE isp_mbox_acquire +#define MBOX_WAIT_COMPLETE isp_mbox_wait_complete +#define MBOX_NOTIFY_COMPLETE isp_mbox_notify_done +#define MBOX_RELEASE isp_mbox_release -#define MBOX_NOTIFY_COMPLETE(isp) \ - if (isp->isp_osinfo.mboxwaiting) { \ - isp->isp_osinfo.mboxwaiting = 0; \ - wakeup(&isp->isp_osinfo.mboxwaiting); \ - } \ - isp->isp_mboxbsy = 0 - -#define MBOX_RELEASE(isp) - -#define FC_SCRATCH_ACQUIRE(isp) -#define FC_SCRATCH_RELEASE(isp) +#define FC_SCRATCH_ACQUIRE(isp) \ + if (isp->isp_osinfo.fcbsy) { \ + isp_prt(isp, ISP_LOGWARN, \ + "FC scratch area busy (line %d)!", __LINE__); \ + } else \ + isp->isp_osinfo.fcbsy = 1 +#define FC_SCRATCH_RELEASE(isp) isp->isp_osinfo.fcbsy = 0 #ifndef SCSI_GOOD #define SCSI_GOOD 0x0 @@ -204,6 +206,11 @@ default: \ #endif #define XS_T struct scsi_xfer +#if !(defined(__sparc__) && !defined(__sparcv9__)) +#define XS_DMA_ADDR_T bus_addr_t +#else +#define XS_DMA_ADDR_T u_int32_t +#endif #define XS_CHANNEL(xs) (((xs)->sc_link->flags & SDEV_2NDBUS)? 1 : 0) #define XS_ISP(xs) (xs)->sc_link->adapter_softc #define XS_LUN(xs) ((int) (xs)->sc_link->lun) @@ -238,12 +245,11 @@ default: \ #define XS_INITERR(xs) (xs)->error = 0, XS_CMD_S_CLEAR(xs) -#define XS_SAVE_SENSE(xs, sp) \ +#define XS_SAVE_SENSE(xs, sp, len) \ if (xs->error == XS_NOERROR) { \ xs->error = XS_SENSE; \ } \ - bcopy(sp->req_sense_data, &(xs)->sense, \ - imin(XS_SNSLEN(xs), sp->req_sense_len)) + bcopy(sp, &(xs)->sense, imin(XS_SNSLEN(xs), len)) #define XS_SET_STATE_STAT(a, b, c) @@ -251,8 +257,8 @@ default: \ #define DEFAULT_LOOPID(x) 107 #define DEFAULT_NODEWWN(isp) (isp)->isp_osinfo.un._wwn #define DEFAULT_PORTWWN(isp) (isp)->isp_osinfo.un._wwn -#define ISP_NODEWWN(isp) FCPARAM(isp)->isp_nodewwn -#define ISP_PORTWWN(isp) FCPARAM(isp)->isp_portwwn +#define ISP_NODEWWN(isp) FCPARAM(isp)->isp_wwnn_nvram +#define ISP_PORTWWN(isp) FCPARAM(isp)->isp_wwpn_nvram #if BYTE_ORDER == BIG_ENDIAN #ifdef ISP_SBUS_SUPPORTED @@ -278,6 +284,16 @@ default: \ #define ISP_IOXGET_32(isp, s, d) d = swap32(*((u_int32_t *)s)) #endif #define ISP_SWIZZLE_NVRAM_WORD(isp, rp) *rp = swap16(*rp) +#define ISP_SWIZZLE_NVRAM_LONG(isp, rp) *rp = swap32(*rp) + +#define ISP_IOZGET_8(isp, s, d) d = (*((u_int8_t *)s)) +#define ISP_IOZGET_16(isp, s, d) d = (*((u_int16_t *)s)) +#define ISP_IOZGET_32(isp, s, d) d = (*((u_int32_t *)s)) +#define ISP_IOZPUT_8(isp, s, d) *(d) = s +#define ISP_IOZPUT_16(isp, s, d) *(d) = s +#define ISP_IOZPUT_32(isp, s, d) *(d) = s + + #else #define ISP_IOXPUT_8(isp, s, d) *(d) = s #define ISP_IOXPUT_16(isp, s, d) *(d) = s @@ -286,8 +302,20 @@ default: \ #define ISP_IOXGET_16(isp, s, d) d = *(s) #define ISP_IOXGET_32(isp, s, d) d = *(s) #define ISP_SWIZZLE_NVRAM_WORD(isp, rp) +#define ISP_SWIZZLE_NVRAM_LONG(isp, rp) + +#define ISP_IOZPUT_8(isp, s, d) *(d) = s +#define ISP_IOZPUT_16(isp, s, d) *(d) = swap16(s) +#define ISP_IOZPUT_32(isp, s, d) *(d) = swap32(s) + +#define ISP_IOZGET_8(isp, s, d) d = (*((u_int8_t *)(s))) +#define ISP_IOZGET_16(isp, s, d) d = swap16(*((u_int16_t *)(s))) +#define ISP_IOZGET_32(isp, s, d) d = swap32(*((u_int32_t *)(s))) #endif +#define ISP_SWAP16(isp, s) swap16(s) +#define ISP_SWAP32(isp, s) swap32(s) + /* * Includes of common header files */ @@ -308,11 +336,14 @@ default: \ void isp_attach(struct ispsoftc *); void isp_uninit(struct ispsoftc *); -static INLINE void isp_lock(struct ispsoftc *); -static INLINE void isp_unlock(struct ispsoftc *); -static INLINE u_int64_t -isp_nanotime_sub(struct timespec *, struct timespec *); -static void isp_wait_complete(struct ispsoftc *); +void isp_lock(struct ispsoftc *); +void isp_unlock(struct ispsoftc *); +void isp_prt(struct ispsoftc *, int level, const char *, ...); +u_int64_t isp_nanotime_sub(struct timespec *, struct timespec *); +int isp_mbox_acquire(ispsoftc_t *); +void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *); +void isp_mbox_notify_done(ispsoftc_t *); +void isp_mbox_release(ispsoftc_t *); /* * Driver wide data... @@ -345,88 +376,6 @@ static void isp_wait_complete(struct ispsoftc *); #define XS_CMD_S_CLEAR(xs) (xs)->flags &= ~XS_PSTS_ALL -/* - * Platform specific 'INLINE' or support functions - */ -static INLINE void -isp_lock(struct ispsoftc *isp) -{ - int s = splbio(); - if (isp->isp_osinfo.islocked++ == 0) { - isp->isp_osinfo.splsaved = s; - } else { - splx(s); - } -} - -static INLINE void -isp_unlock(struct ispsoftc *isp) -{ - if (isp->isp_osinfo.islocked-- <= 1) { - isp->isp_osinfo.islocked = 0; - splx(isp->isp_osinfo.splsaved); - } -} - -static INLINE u_int64_t -isp_nanotime_sub(struct timespec *b, struct timespec *a) -{ - struct timespec x; - u_int64_t elapsed; - timespecsub(b, a, &x); - elapsed = GET_NANOSEC(&x); - if (elapsed == 0) - elapsed++; - return (elapsed); -} - -static INLINE void -isp_wait_complete(struct ispsoftc *isp) -{ - int delaytime; - if (isp->isp_mbxwrk0) - delaytime = 60; - else - delaytime = 5; - if (MUST_POLL(isp)) { - int usecs = 0; - delaytime *= 1000000; /* convert to usecs */ - while (usecs < delaytime) { - u_int16_t isr, sema, mbox; - if (isp->isp_mboxbsy == 0) { - break; - } - if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { - isp_intr(isp, isr, sema, mbox); - if (isp->isp_mboxbsy == 0) { - break; - } - } - USEC_DELAY(500); - usecs += 500; - } - if (isp->isp_mboxbsy != 0) { - isp_prt(isp, ISP_LOGWARN, - "Polled Mailbox Command (0x%x) Timeout", - isp->isp_lastmbxcmd); - } - } else { - int rv = 0; - isp->isp_osinfo.mboxwaiting = 1; - while (isp->isp_osinfo.mboxwaiting && rv == 0) { - rv = tsleep(&isp->isp_osinfo.mboxwaiting, - PRIBIO, "isp_mboxcmd", delaytime * hz); - } - if (rv == EWOULDBLOCK) { - isp->isp_mboxbsy = 0; - isp->isp_osinfo.mboxwaiting = 0; - isp_prt(isp, ISP_LOGWARN, - "Interrupting Mailbox Command (0x%x) Timeout", - isp->isp_lastmbxcmd); - } - } -} - #include <dev/ic/isp_library.h> #endif /* _ISP_OPENBSD_H */ diff --git a/sys/dev/ic/isp_stds.h b/sys/dev/ic/isp_stds.h index be87fc89159..174731ebc45 100644 --- a/sys/dev/ic/isp_stds.h +++ b/sys/dev/ic/isp_stds.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_stds.h,v 1.1 2008/11/02 03:06:26 krw Exp $ */ +/* $OpenBSD: isp_stds.h,v 1.2 2009/06/24 11:00:53 krw Exp $ */ /* $FreeBSD: src/sys/dev/isp/isp_stds.h,v 1.4 2007/03/10 02:39:54 mjacob Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob @@ -109,14 +109,14 @@ typedef struct { typedef struct { uint8_t ct_revision; - uint8_t ct_portid[3]; + uint8_t ct_in_id[3]; uint8_t ct_fcs_type; uint8_t ct_fcs_subtype; uint8_t ct_options; - uint8_t ct_res0; - uint16_t ct_response; - uint16_t ct_resid; - uint8_t ct_res1; + uint8_t ct_reserved0; + uint16_t ct_cmd_resp; + uint16_t ct_bcnt_resid; + uint8_t ct_reserved1; uint8_t ct_reason; uint8_t ct_explanation; uint8_t ct_vunique; diff --git a/sys/dev/ic/isp_target.c b/sys/dev/ic/isp_target.c index d04983a9188..597b4b1ff96 100644 --- a/sys/dev/ic/isp_target.c +++ b/sys/dev/ic/isp_target.c @@ -1,33 +1,33 @@ -/* $OpenBSD: isp_target.c,v 1.15 2008/01/21 20:00:33 sobrado Exp $ */ +/* $OpenBSD: isp_target.c,v 1.16 2009/06/24 11:00:53 krw Exp $ */ +/*- + * Copyright (c) 1997-2007 by Matthew Jacob + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ /* - * Machine and OS Independent Target Mode Code for the QLogic SCSI/FC adapters. - * - * Copyright (c) 1999, 2000, 2001 by Matthew Jacob - * All rights reserved. - * mjacob@feral.com - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters. */ - /* * Bug fixes gratefully acknowledged from: * Oded Kedem <oded@kashya.com> @@ -40,6 +40,8 @@ #include <dev/ic/isp_netbsd.h> #endif #ifdef __FreeBSD__ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/sys/dev/isp/isp_target.c,v 1.45 2007/10/12 06:03:43 kevlo Exp $"); #include <dev/isp/isp_freebsd.h> #endif #ifdef __OpenBSD__ @@ -54,19 +56,20 @@ static const char atiocope[] = "ATIO returned for lun %d because it was in the middle of Bus Device Reset " "on bus %d"; static const char atior[] = - "ATIO returned on for lun %d on from IID %d because a Bus Reset occurred " - "on bus %d"; - -static void isp_got_msg(struct ispsoftc *, int, in_entry_t *); -static void isp_got_msg_fc(struct ispsoftc *, int, in_fcentry_t *); -static void isp_notify_ack(struct ispsoftc *, void *); -static void isp_handle_atio(struct ispsoftc *, at_entry_t *); -static void isp_handle_atio2(struct ispsoftc *, at2_entry_t *); -static void isp_handle_ctio(struct ispsoftc *, ct_entry_t *); -static void isp_handle_ctio2(struct ispsoftc *, ct2_entry_t *); + "ATIO returned on for lun %d on from loopid %d because a Bus Reset " + "occurred on bus %d"; + +static void isp_got_msg(ispsoftc_t *, in_entry_t *); +static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *); +static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *); +static void isp_handle_atio(ispsoftc_t *, at_entry_t *); +static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *); +static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *); +static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *); +static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *); /* - * The QLogic driver gets an interrupt to look at response queue entries. + * The Qlogic driver gets an interrupt to look at response queue entries. * Some of these are status completions for initiatior mode commands, but * if target mode is enabled, we get a whole wad of response queue entries * to be handled here. @@ -86,7 +89,7 @@ static void isp_handle_ctio2(struct ispsoftc *, ct2_entry_t *); * be moved and/or status to be sent) and finally finishing with sending * to the f/w's response queue an ATIO which then completes the handshake * with the f/w for that command. There's a lot of variations on this theme, - * including flags you can set in the CTIO for the QLogic 2X00 fibre channel + * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic * gist of it. * @@ -107,39 +110,62 @@ static void isp_handle_ctio2(struct ispsoftc *, ct2_entry_t *); * has already swizzled it into the platform dependent from canonical form. * * Because of the way this driver is designed, unfortunately most of the - * actual synchronization work has to be done in the platform-specific - * code - we have no synchronization primitives in the common code. + * actual synchronization work has to be done in the platform specific + * code- we have no synchroniation primitives in the common code. */ int -isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) +isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) { - u_int16_t status, seqid; + uint16_t status; + uint32_t seqid; union { at_entry_t *atiop; at2_entry_t *at2iop; + at2e_entry_t *at2eiop; + at7_entry_t *at7iop; ct_entry_t *ctiop; ct2_entry_t *ct2iop; + ct2e_entry_t *ct2eiop; + ct7_entry_t *ct7iop; lun_entry_t *lunenp; in_entry_t *inotp; in_fcentry_t *inot_fcp; + in_fcentry_e_t *inote_fcp; + in_fcentry_24xx_t *inot_24xx; na_entry_t *nackp; na_fcentry_t *nack_fcp; + na_fcentry_e_t *nacke_fcp; + na_fcentry_24xx_t *nack_24xx; isphdr_t *hp; + abts_t *abts; + abts_rsp_t *abts_rsp; + els_t *els; void * *vp; #define atiop unp.atiop #define at2iop unp.at2iop +#define at2eiop unp.at2eiop +#define at7iop unp.at7iop #define ctiop unp.ctiop #define ct2iop unp.ct2iop +#define ct2eiop unp.ct2eiop +#define ct7iop unp.ct7iop #define lunenp unp.lunenp #define inotp unp.inotp #define inot_fcp unp.inot_fcp +#define inote_fcp unp.inote_fcp +#define inot_24xx unp.inot_24xx #define nackp unp.nackp #define nack_fcp unp.nack_fcp +#define nacke_fcp unp.nacke_fcp +#define nack_24xx unp.nack_24xx +#define abts unp.abts +#define abts_rsp unp.abts_rsp +#define els unp.els #define hdrp unp.hp } unp; - u_int8_t local[QENTRY_LEN]; - int bus, type, rval = 1; + uint8_t local[QENTRY_LEN]; + int bus, type, level, rval = 1; type = isp_get_response_type(isp, (isphdr_t *)vptr); unp.vp = vptr; @@ -148,21 +174,72 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) switch(type) { case RQSTYPE_ATIO: - isp_get_atio(isp, atiop, (at_entry_t *) local); - isp_handle_atio(isp, (at_entry_t *) local); + if (IS_24XX(isp)) { + int len; + + isp_get_atio7(isp, at7iop, (at7_entry_t *) local); + at7iop = (at7_entry_t *) local; + /* + * Check for and do something with commands whose IULEN + * extends past a singel queue entry. + */ + len = at7iop->at_ta_len & 0xfffff; + if (len > (QENTRY_LEN - 8)) { + len -= (QENTRY_LEN - 8); + isp_prt(isp, ISP_LOGINFO, + "long IU length (%d) ignored", len); + while (len > 0) { + *optrp = ISP_NXT_QENTRY(*optrp, + RESULT_QUEUE_LEN(isp)); + len -= QENTRY_LEN; + } + } + /* + * Check for a task management function + */ + if (at7iop->at_cmnd.fcp_cmnd_task_management) { + isp_got_tmf_24xx(isp, at7iop); + break; + } + /* + * Just go straight to outer layer for this one. + */ + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, local); + } else { + isp_get_atio(isp, atiop, (at_entry_t *) local); + isp_handle_atio(isp, (at_entry_t *) local); + } break; + case RQSTYPE_CTIO: isp_get_ctio(isp, ctiop, (ct_entry_t *) local); isp_handle_ctio(isp, (ct_entry_t *) local); break; + case RQSTYPE_ATIO2: - isp_get_atio2(isp, at2iop, (at2_entry_t *) local); + if (FCPARAM(isp)->isp_2klogin) { + isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local); + } else { + isp_get_atio2(isp, at2iop, (at2_entry_t *) local); + } isp_handle_atio2(isp, (at2_entry_t *) local); break; + + case RQSTYPE_CTIO3: case RQSTYPE_CTIO2: - isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); + if (FCPARAM(isp)->isp_2klogin) { + isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local); + } else { + isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); + } isp_handle_ctio2(isp, (ct2_entry_t *) local); break; + + case RQSTYPE_CTIO7: + isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local); + isp_handle_ctio7(isp, (ct7_entry_t *) local); + break; + case RQSTYPE_ENABLE_LUN: case RQSTYPE_MODIFY_LUN: isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local); @@ -178,8 +255,42 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) * (we set this initially in the Enable Lun entry). */ bus = 0; - if (IS_FC(isp)) { - isp_get_notify_fc(isp, inot_fcp, (in_fcentry_t *)local); + if (IS_24XX(isp)) { + isp_get_notify_24xx(isp, inot_24xx, + (in_fcentry_24xx_t *)local); + inot_24xx = (in_fcentry_24xx_t *) local; + status = inot_24xx->in_status; + seqid = inot_24xx->in_rxid; + isp_prt(isp, ISP_LOGTDEBUG0, + "Immediate Notify status=0x%x seqid=0x%x", + status, seqid); + switch (status) { + case IN24XX_LIP_RESET: + case IN24XX_LINK_RESET: + case IN24XX_PORT_LOGOUT: + case IN24XX_PORT_CHANGED: + case IN24XX_LINK_FAILED: + case IN24XX_SRR_RCVD: + case IN24XX_ELS_RCVD: + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, + &local); + break; + default: + isp_prt(isp, ISP_LOGINFO, + "isp_target_notify: unknown status (0x%x)", + status); + isp_notify_ack(isp, local); + break; + } + break; + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_2klogin) { + isp_get_notify_fc_e(isp, inote_fcp, + (in_fcentry_e_t *)local); + } else { + isp_get_notify_fc(isp, inot_fcp, + (in_fcentry_t *)local); + } inot_fcp = (in_fcentry_t *) local; status = inot_fcp->in_status; seqid = inot_fcp->in_seqid; @@ -193,29 +304,43 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) SET_BUS_VAL(inotp->in_iid, 0); } } + isp_prt(isp, ISP_LOGTDEBUG0, "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", bus, status, seqid); - /* - * ACK it right away. - */ - isp_notify_ack(isp, (status == IN_RESET)? NULL : local); switch (status) { - case IN_RESET: - (void) isp_async(isp, ISPASYNC_BUS_RESET, &bus); - break; case IN_MSG_RECEIVED: case IN_IDE_RECEIVED: if (IS_FC(isp)) { - isp_got_msg_fc(isp, bus, (in_fcentry_t *)local); + isp_got_msg_fc(isp, (in_fcentry_t *)local); } else { - isp_got_msg(isp, bus, (in_entry_t *)local); + isp_got_msg(isp, (in_entry_t *)local); } break; case IN_RSRC_UNAVAIL: - isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs"); + isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs"); + isp_notify_ack(isp, local); + break; + case IN_RESET: + { + /* + * We form the notify structure here because we need + * to mark it as needing a NOTIFY ACK on return. + */ + tmd_notify_t notify; + + MEMZERO(¬ify, sizeof (tmd_notify_t)); + notify.nt_hba = isp; + notify.nt_iid = INI_ANY; + /* nt_tgt set in outer layers */ + notify.nt_lun = LUN_ANY; + notify.nt_tagval = TAG_ANY; + notify.nt_ncode = NT_BUS_RESET; + notify.nt_need_ack = 1; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); break; + } case IN_PORT_LOGOUT: case IN_ABORT_TASK: case IN_PORT_CHANGED: @@ -223,8 +348,10 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); break; default: - isp_prt(isp, ISP_LOGERR, - "bad status (0x%x) in isp_target_notify", status); + isp_prt(isp, ISP_LOGINFO, + "isp_target_notify: unknown status (0x%x)", + status); + isp_notify_ack(isp, local); break; } break; @@ -234,21 +361,68 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) * The ISP is acknowledging our acknowledgement of an * Immediate Notify entry for some asynchronous event. */ - if (IS_FC(isp)) { - isp_get_notify_ack_fc(isp, nack_fcp, - (na_fcentry_t *)local); + if (IS_24XX(isp)) { + isp_get_notify_ack_24xx(isp, nack_24xx, + (na_fcentry_24xx_t *) local); + nack_24xx = (na_fcentry_24xx_t *) local; + if (nack_24xx->na_status != NA_OK) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG1; + } + isp_prt(isp, level, + "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x", + nack_24xx->na_status, nack_24xx->na_status_subcode, + nack_24xx->na_rxid); + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_2klogin) { + isp_get_notify_ack_fc_e(isp, nacke_fcp, + (na_fcentry_e_t *)local); + } else { + isp_get_notify_ack_fc(isp, nack_fcp, + (na_fcentry_t *)local); + } nack_fcp = (na_fcentry_t *)local; - isp_prt(isp, ISP_LOGTDEBUG1, - "Notify Ack status=0x%x seqid 0x%x", + if (nack_fcp->na_status != NA_OK) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG1; + } + isp_prt(isp, level, + "Notify Ack Status=0x%x seqid 0x%x", nack_fcp->na_status, nack_fcp->na_seqid); } else { isp_get_notify_ack(isp, nackp, (na_entry_t *)local); nackp = (na_entry_t *)local; - isp_prt(isp, ISP_LOGTDEBUG1, + if (nackp->na_status != NA_OK) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG1; + } + isp_prt(isp, level, "Notify Ack event 0x%x status=0x%x seqid 0x%x", nackp->na_event, nackp->na_status, nackp->na_seqid); } break; + + case RQSTYPE_ABTS_RCVD: + isp_get_abts(isp, abts, (abts_t *)local); + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); + break; + case RQSTYPE_ABTS_RSP: + isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local); + abts_rsp = (abts_rsp_t *) local; + if (abts_rsp->abts_rsp_status) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG0; + } + isp_prt(isp, level, + "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)", + abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status, + abts_rsp->abts_rsp_payload.rsp.subcode1, + abts_rsp->abts_rsp_payload.rsp.subcode2); + break; default: isp_prt(isp, ISP_LOGERR, "Unknown entry type 0x%x in isp_target_notify", type); @@ -257,13 +431,24 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) } #undef atiop #undef at2iop +#undef at2eiop +#undef at7iop #undef ctiop #undef ct2iop +#undef ct2eiop +#undef ct7iop #undef lunenp #undef inotp #undef inot_fcp +#undef inote_fcp +#undef inot_24xx #undef nackp #undef nack_fcp +#undef nacke_fcp +#undef hack_24xx +#undef abts +#undef abts_rsp +#undef els #undef hdrp return (rval); } @@ -279,11 +464,11 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) * response entry. The caller is responsible for synchronizing this. */ int -isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun, - int cmd_cnt, int inot_cnt, u_int32_t opaque) +isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun, + int cmd_cnt, int inot_cnt, uint32_t opaque) { lun_entry_t el; - u_int16_t nxti, optr; + uint32_t nxti, optr; void *outp; @@ -315,10 +500,10 @@ isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun, if (IS_SCSI(isp)) { el.le_tgt = tgt; el.le_lun = lun; - } else if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { + } else if (FCPARAM(isp)->isp_sccfw == 0) { el.le_lun = lun; } - el.le_timeout = 2; + el.le_timeout = 30; if (isp_getrqentry(isp, &nxti, &optr, &outp)) { isp_prt(isp, ISP_LOGERR, @@ -333,11 +518,11 @@ isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun, int -isp_target_put_entry(struct ispsoftc *isp, void *ap) +isp_target_put_entry(ispsoftc_t *isp, void *ap) { void *outp; - u_int16_t nxti, optr; - u_int8_t etype = ((isphdr_t *) ap)->rqs_entry_type; + uint32_t nxti, optr; + uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type; if (isp_getrqentry(isp, &nxti, &optr, &outp)) { isp_prt(isp, ISP_LOGWARN, @@ -349,31 +534,46 @@ isp_target_put_entry(struct ispsoftc *isp, void *ap) isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp); break; case RQSTYPE_ATIO2: - isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp); + if (FCPARAM(isp)->isp_2klogin) { + isp_put_atio2e(isp, (at2e_entry_t *) ap, + (at2e_entry_t *) outp); + } else { + isp_put_atio2(isp, (at2_entry_t *) ap, + (at2_entry_t *) outp); + } break; case RQSTYPE_CTIO: isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp); break; case RQSTYPE_CTIO2: - isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp); + if (FCPARAM(isp)->isp_2klogin) { + isp_put_ctio2e(isp, (ct2e_entry_t *) ap, + (ct2e_entry_t *) outp); + } else { + isp_put_ctio2(isp, (ct2_entry_t *) ap, + (ct2_entry_t *) outp); + } + break; + case RQSTYPE_CTIO7: + isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp); break; default: isp_prt(isp, ISP_LOGERR, "Unknown type 0x%x in isp_put_entry", etype); return (-1); } - ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap); ISP_ADD_REQUEST(isp, nxti); return (0); } int -isp_target_put_atio(struct ispsoftc *isp, void *arg) +isp_target_put_atio(ispsoftc_t *isp, void *arg) { union { at_entry_t _atio; at2_entry_t _atio2; + at2e_entry_t _atio2e; } atun; MEMZERO(&atun, sizeof atun); @@ -381,12 +581,16 @@ isp_target_put_atio(struct ispsoftc *isp, void *arg) at2_entry_t *aep = arg; atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; atun._atio2.at_header.rqs_entry_count = 1; - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - atun._atio2.at_scclun = (u_int16_t) aep->at_scclun; + if (FCPARAM(isp)->isp_sccfw) { + atun._atio2.at_scclun = aep->at_scclun; + } else { + atun._atio2.at_lun = (uint8_t) aep->at_lun; + } + if (FCPARAM(isp)->isp_2klogin) { + atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; } else { - atun._atio2.at_lun = (u_int8_t) aep->at_lun; + atun._atio2.at_iid = aep->at_iid; } - atun._atio2.at_iid = aep->at_iid; atun._atio2.at_rxid = aep->at_rxid; atun._atio2.at_status = CT_OK; } else { @@ -424,29 +628,62 @@ isp_target_put_atio(struct ispsoftc *isp, void *arg) */ int -isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl) +isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl) { int sts; union { ct_entry_t _ctio; ct2_entry_t _ctio2; + ct2e_entry_t _ctio2e; + ct7_entry_t _ctio7; } un; MEMZERO(&un, sizeof un); sts = code & 0xff; - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + at7_entry_t *aep = arg; + ct7_entry_t *cto = &un._ctio7; + + cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; + cto->ct_header.rqs_entry_count = 1; +/* XXXX */ cto->ct_nphdl = aep->at_hdr.seq_id; + cto->ct_rxid = aep->at_rxid; + cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | + aep->at_hdr.s_id[2]; + cto->ct_iid_hi = aep->at_hdr.s_id[0]; + cto->ct_oxid = aep->at_hdr.ox_id; + cto->ct_scsi_status = sts; + cto->ct_flags = CT7_FLAG_MODE1 | CT7_NO_DATA | CT7_SENDSTATUS; + if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { + cto->rsp.m1.ct_resplen = 16; + cto->rsp.m1.ct_resp[0] = 0xf0; + cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; + cto->rsp.m1.ct_resp[7] = 8; + cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; + cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; + } + if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) { + cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl; + cto->ct_scsi_status |= CT2_DATA_UNDER; + } + cto->ct_syshandle = hdl; + } else if (IS_FC(isp)) { at2_entry_t *aep = arg; ct2_entry_t *cto = &un._ctio2; cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; cto->ct_header.rqs_entry_count = 1; - cto->ct_iid = aep->at_iid; - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { + if (FCPARAM(isp)->isp_sccfw == 0) { cto->ct_lun = aep->at_lun; } + if (FCPARAM(isp)->isp_2klogin) { + un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid; + } else { + cto->ct_iid = aep->at_iid; + } cto->ct_rxid = aep->at_rxid; - cto->rsp.m1.ct_scsi_status = sts & 0xff; + cto->rsp.m1.ct_scsi_status = sts; cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1; if (hdl == 0) { cto->ct_flags |= CT2_CCINCR; @@ -455,7 +692,7 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl) cto->ct_resid = aep->at_datalen; cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER; } - if ((sts & 0xff) == SCSI_CHECK && (sts & ECMD_SVALID)) { + if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { cto->rsp.m1.ct_resp[0] = 0xf0; cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; cto->rsp.m1.ct_resp[7] = 8; @@ -490,63 +727,87 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl) return (isp_target_put_entry(isp, &un)); } +/* + * These are either broadcast events or specifically CTIO fast completion + */ int -isp_target_async(struct ispsoftc *isp, int bus, int event) +isp_target_async(ispsoftc_t *isp, int bus, int event) { - tmd_event_t evt; - tmd_msg_t msg; + tmd_notify_t notify; + + MEMZERO(¬ify, sizeof (tmd_notify_t)); + notify.nt_hba = isp; + notify.nt_iid = INI_ANY; + /* nt_tgt set in outer layers */ + notify.nt_lun = LUN_ANY; + notify.nt_tagval = TAG_ANY; + + if (IS_SCSI(isp)) { + TAG_INSERT_BUS(notify.nt_tagval, bus); + } switch (event) { - /* - * These three we handle here to propagate an effective bus reset - * upstream, but these do not require any immediate notify actions - * so we return when done. - */ - case ASYNC_LIP_F8: - case ASYNC_LIP_OCCURRED: case ASYNC_LOOP_UP: + case ASYNC_PTPMODE: + notify.nt_ncode = NT_LINK_UP; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); + break; case ASYNC_LOOP_DOWN: + notify.nt_ncode = NT_LINK_DOWN; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); + break; + case ASYNC_LIP_ERROR: + case ASYNC_LIP_F8: + case ASYNC_LIP_OCCURRED: case ASYNC_LOOP_RESET: - case ASYNC_PTPMODE: - /* - * These don't require any immediate notify actions. We used - * treat them like SCSI Bus Resets, but that was just plain - * wrong. Let the normal CTIO completion report what occurred. - */ - return (0); - + notify.nt_ncode = NT_LIP_RESET; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); + break; case ASYNC_BUS_RESET: - case ASYNC_TIMEOUT_RESET: - if (IS_FC(isp)) { - return (0); /* we'll be getting an inotify instead */ - } - evt.ev_bus = bus; - evt.ev_event = event; - (void) isp_async(isp, ISPASYNC_TARGET_EVENT, &evt); + case ASYNC_TIMEOUT_RESET: /* XXX: where does this come from ? */ + notify.nt_ncode = NT_BUS_RESET; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); break; case ASYNC_DEVICE_RESET: - /* - * Bus Device Reset resets a specific target, so - * we pass this as a synthesized message. - */ - MEMZERO(&msg, sizeof msg); - if (IS_FC(isp)) { - msg.nt_iid = FCPARAM(isp)->isp_loopid; + notify.nt_ncode = NT_TARGET_RESET; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); + break; + case ASYNC_CTIO_DONE: + { + uint8_t storage[QENTRY_LEN]; + memset(storage, 0, QENTRY_LEN); + if (IS_24XX(isp)) { + ct7_entry_t *ct = (ct7_entry_t *) storage; + ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7; + ct->ct_nphdl = CT7_OK; + ct->ct_syshandle = bus; + ct->ct_flags = CT7_SENDSTATUS|CT7_FASTPOST; + } else if (IS_FC(isp)) { + /* This should also suffice for 2K login code */ + ct2_entry_t *ct = (ct2_entry_t *) storage; + ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; + ct->ct_status = CT_OK; + ct->ct_syshandle = bus; + ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST; } else { - msg.nt_iid = SDPARAM(isp)->isp_initiator_id; + ct_entry_t *ct = (ct_entry_t *) storage; + ct->ct_header.rqs_entry_type = RQSTYPE_CTIO; + ct->ct_status = CT_OK; + ct->ct_fwhandle = bus; + ct->ct_flags = CT_SENDSTATUS; } - msg.nt_bus = bus; - msg.nt_msg[0] = MSG_BUS_DEV_RESET; - (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg); + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage); break; + } default: isp_prt(isp, ISP_LOGERR, "isp_target_async: unknown event 0x%x", event); + if (isp->isp_state == ISP_RUNSTATE) { + isp_notify_ack(isp, NULL); + } break; } - if (isp->isp_state == ISP_RUNSTATE) - isp_notify_ack(isp, NULL); - return(0); + return (0); } @@ -559,25 +820,53 @@ isp_target_async(struct ispsoftc *isp, int bus, int event) */ static void -isp_got_msg(struct ispsoftc *isp, int bus, in_entry_t *inp) +isp_got_msg(ispsoftc_t *isp, in_entry_t *inp) { - u_int8_t status = inp->in_status & ~QLTM_SVALID; + tmd_notify_t nt; + uint8_t status = inp->in_status & ~QLTM_SVALID; + + MEMZERO(&nt, sizeof (nt)); + nt.nt_hba = isp; + nt.nt_iid = GET_IID_VAL(inp->in_iid); + nt.nt_tgt = inp->in_tgt; + nt.nt_lun = inp->in_lun; + IN_MAKE_TAGID(nt.nt_tagval, GET_BUS_VAL(inp->in_iid), 0, inp); + nt.nt_lreserved = inp; if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) { - tmd_msg_t msg; - - MEMZERO(&msg, sizeof (msg)); - msg.nt_bus = bus; - msg.nt_iid = inp->in_iid; - msg.nt_tgt = inp->in_tgt; - msg.nt_lun = inp->in_lun; - msg.nt_tagtype = inp->in_tag_type; - msg.nt_tagval = inp->in_tag_val; - MEMCPY(msg.nt_msg, inp->in_msg, IN_MSGLEN); - (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg); + switch (inp->in_msg[0]) { + case MSG_ABORT: + nt.nt_ncode = NT_ABORT_TASK_SET; + break; + case MSG_BUS_DEV_RESET: + nt.nt_ncode = NT_TARGET_RESET; + break; + case MSG_ABORT_TAG: + nt.nt_ncode = NT_ABORT_TASK; + break; + case MSG_CLEAR_QUEUE: + nt.nt_ncode = NT_CLEAR_TASK_SET; + break; + case MSG_REL_RECOVERY: + nt.nt_ncode = NT_CLEAR_ACA; + break; + case MSG_TERM_IO_PROC: + nt.nt_ncode = NT_ABORT_TASK; + break; + case MSG_LUN_RESET: + nt.nt_ncode = NT_LUN_RESET; + break; + default: + isp_prt(isp, ISP_LOGERR, + "unhandled message 0x%x", inp->in_msg[0]); + isp_notify_ack(isp, inp); + return; + } + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); } else { isp_prt(isp, ISP_LOGERR, "unknown immediate notify status 0x%x", inp->in_status); + isp_notify_ack(isp, inp); } } @@ -585,69 +874,140 @@ isp_got_msg(struct ispsoftc *isp, int bus, in_entry_t *inp) * Synthesize a message from the task management flags in a FCP_CMND_IU. */ static void -isp_got_msg_fc(struct ispsoftc *isp, int bus, in_fcentry_t *inp) +isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) { - int lun; - static const char f1[] = "%s from iid %d lun %d seq 0x%x"; - static const char f2[] = - "unknown %s 0x%x lun %d iid %d task flags 0x%x seq 0x%x\n"; - - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - lun = inp->in_scclun; + tmd_notify_t nt; + static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x"; + static const char f2[] = "unknown %s 0x%x lun %d N-Port handle 0x%x " + "task flags 0x%x seq 0x%x\n"; + uint16_t seqid, loopid; + + MEMZERO(&nt, sizeof (tmd_notify_t)); + nt.nt_hba = isp; + if (FCPARAM(isp)->isp_2klogin) { + nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid; + loopid = ((in_fcentry_e_t *)inp)->in_iid; + seqid = ((in_fcentry_e_t *)inp)->in_seqid; } else { - lun = inp->in_lun; + nt.nt_iid = inp->in_iid; + loopid = inp->in_iid; + seqid = inp->in_seqid; } + /* nt_tgt set in outer layers */ + if (FCPARAM(isp)->isp_sccfw) { + nt.nt_lun = inp->in_scclun; + } else { + nt.nt_lun = inp->in_lun; + } + IN_FC_MAKE_TAGID(nt.nt_tagval, 0, 0, seqid); + nt.nt_need_ack = 1; + nt.nt_lreserved = inp; if (inp->in_status != IN_MSG_RECEIVED) { isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", - inp->in_status, lun, inp->in_iid, - inp->in_task_flags, inp->in_seqid); + inp->in_status, nt.nt_lun, loopid, inp->in_task_flags, + inp->in_seqid); + isp_notify_ack(isp, inp); + return; + } + + if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", + loopid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_ABORT_TASK_SET; + } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", + loopid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_CLEAR_TASK_SET; + } else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", + loopid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_LUN_RESET; + } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", + loopid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_TARGET_RESET; + } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", + loopid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_CLEAR_ACA; } else { - tmd_msg_t msg; - - MEMZERO(&msg, sizeof (msg)); - msg.nt_bus = bus; - msg.nt_iid = inp->in_iid; - msg.nt_tagval = inp->in_seqid; - msg.nt_lun = lun; - - if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK) { - isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_ABORT_TAG; - } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { - isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_CLEAR_QUEUE; - } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { - isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_BUS_DEV_RESET; - } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { - isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", - inp->in_iid, lun, inp->in_seqid); - /* ???? */ - msg.nt_msg[0] = MSG_REL_RECOVERY; - } else if (inp->in_task_flags & TASK_FLAGS_TERMINATE_TASK) { - isp_prt(isp, ISP_LOGINFO, f1, "TERMINATE TASK", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_TERM_IO_PROC; - } else { - isp_prt(isp, ISP_LOGWARN, f2, "task flag", - inp->in_status, lun, inp->in_iid, - inp->in_task_flags, inp->in_seqid); - } - if (msg.nt_msg[0]) { - (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg); - } + isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, + nt.nt_lun, loopid, inp->in_task_flags, inp->in_seqid); + isp_notify_ack(isp, inp); + return; } + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); } +#define HILO(x) (uint32_t) (x >> 32), (uint32_t) x static void -isp_notify_ack(struct ispsoftc *isp, void *arg) +isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep) +{ + tmd_notify_t nt; + static const char f1[] = + "%s from PortID 0x%06x lun %d seq 0x%08x%08x"; + static const char f2[] = + "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%08x%08x"; + uint32_t sid; + + MEMZERO(&nt, sizeof (tmd_notify_t)); + nt.nt_hba = isp; + nt.nt_iid = INI_ANY; + nt.nt_lun = + (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | + (aep->at_cmnd.fcp_cmnd_lun[1]); + /* + * XXX: VPIDX HAS TO BE DERIVED FROM DESTINATION PORT + */ + nt.nt_tagval = aep->at_rxid; + nt.nt_lreserved = aep; + sid = + (aep->at_hdr.s_id[0] << 16) | + (aep->at_hdr.s_id[1] << 8) | + (aep->at_hdr.s_id[2]); + + if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_ABORT_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", + sid, nt.nt_lun, HILO(nt.nt_tagval)); + nt.nt_ncode = NT_ABORT_TASK_SET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_CLEAR_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", + sid, nt.nt_lun, HILO(nt.nt_tagval)); + nt.nt_ncode = NT_CLEAR_TASK_SET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_LUN_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", + sid, nt.nt_lun, HILO(nt.nt_tagval)); + nt.nt_ncode = NT_LUN_RESET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_TGT_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", + sid, nt.nt_lun, HILO(nt.nt_tagval)); + nt.nt_ncode = NT_TARGET_RESET; + nt.nt_lun = LUN_ANY; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_CLEAR_ACA) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", + sid, nt.nt_lun, HILO(nt.nt_tagval)); + nt.nt_ncode = NT_CLEAR_ACA; + } else { + isp_prt(isp, ISP_LOGWARN, f2, + aep->at_cmnd.fcp_cmnd_task_management, + nt.nt_lun, sid, HILO(nt.nt_tagval)); + isp_endcmd(isp, aep, 0, 0); + return; + } + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); +} + +void +isp_notify_ack(ispsoftc_t *isp, void *arg) { char storage[QENTRY_LEN]; - u_int16_t nxti, optr; + uint32_t nxti, optr; void *outp; if (isp_getrqentry(isp, &nxti, &optr, &outp)) { @@ -658,30 +1018,82 @@ isp_notify_ack(struct ispsoftc *isp, void *arg) MEMZERO(storage, QENTRY_LEN); - if (IS_FC(isp)) { + if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) { + at7_entry_t *aep = arg; + isp_endcmd(isp, aep, 0, 0); + return; + } else if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ABTS_RSP)) { + abts_rsp_t *abts_rsp = (abts_rsp_t *) storage; + /* + * The caller will have set response values as appropriate + * in the ABTS structure just before calling us. + */ + MEMCPY(abts_rsp, arg, QENTRY_LEN); + isp_put_abts_rsp(isp, abts_rsp, (abts_rsp_t *)outp); + } else if (IS_24XX(isp)) { + na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage; + if (arg) { + in_fcentry_24xx_t *in = arg; + na->na_nphdl = in->in_nphdl; + na->na_status = in->in_status; + na->na_status_subcode = in->in_status_subcode; + na->na_rxid = in->in_rxid; + na->na_oxid = in->in_oxid; + if (in->in_status == IN24XX_SRR_RCVD) { + na->na_srr_rxid = in->in_srr_rxid; + na->na_srr_reloff_hi = in->in_srr_reloff_hi; + na->na_srr_reloff_lo = in->in_srr_reloff_lo; + na->na_srr_iu = in->in_srr_iu; + na->na_srr_flags = 1; + na->na_srr_reject_vunique = 0; + na->na_srr_reject_explanation = 1; + na->na_srr_reject_code = 1; + } + } + na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; + na->na_header.rqs_entry_count = 1; + isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp); + } else if (IS_FC(isp)) { na_fcentry_t *na = (na_fcentry_t *) storage; + int iid = 0; + if (arg) { in_fcentry_t *inp = arg; MEMCPY(storage, arg, sizeof (isphdr_t)); - na->na_iid = inp->in_iid; - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - na->na_lun = inp->in_scclun; + if (FCPARAM(isp)->isp_2klogin) { + ((na_fcentry_e_t *)na)->na_iid = + ((in_fcentry_e_t *)inp)->in_iid; + iid = ((na_fcentry_e_t *)na)->na_iid; } else { - na->na_lun = inp->in_lun; + na->na_iid = inp->in_iid; + iid = na->na_iid; } - na->na_task_flags = inp->in_task_flags; + na->na_task_flags = + inp->in_task_flags & TASK_FLAGS_RESERVED_MASK; na->na_seqid = inp->in_seqid; na->na_flags = NAFC_RCOUNT; na->na_status = inp->in_status; if (inp->in_status == IN_RESET) { na->na_flags |= NAFC_RST_CLRD; } + if (inp->in_status == IN_MSG_RECEIVED) { + na->na_flags |= NAFC_TVALID; + na->na_response = 0; /* XXX SUCCEEDED XXX */ + } } else { na->na_flags = NAFC_RST_CLRD; } na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; na->na_header.rqs_entry_count = 1; - isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); + if (FCPARAM(isp)->isp_2klogin) { + isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, + (na_fcentry_e_t *)outp); + } else { + isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); + } + isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x " + "flags %x tflags %x response %x", iid, na->na_seqid, + na->na_flags, na->na_task_flags, na->na_response); } else { na_entry_t *na = (na_entry_t *) storage; if (arg) { @@ -700,13 +1112,16 @@ isp_notify_ack(struct ispsoftc *isp, void *arg) na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; na->na_header.rqs_entry_count = 1; isp_put_notify_ack(isp, na, (na_entry_t *)outp); + isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt " + "%u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, + na->na_seqid, na->na_event); } ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage); ISP_ADD_REQUEST(isp, nxti); } static void -isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep) +isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep) { int lun; lun = aep->at_lun; @@ -714,7 +1129,7 @@ isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep) * The firmware status (except for the QLTM_SVALID bit) indicates * why this ATIO was sent to us. * - * If QLTM_SVALID is set, the firmware has recommended Sense Data. + * If QLTM_SVALID is set, the firware has recommended Sense Data. * * If the DISCONNECTS DISABLED bit is set in the flags field, * we're still connected on the SCSI bus - i.e. the initiator @@ -779,7 +1194,7 @@ isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep) default: isp_prt(isp, ISP_LOGERR, - "Unknown ATIO status 0x%x from initiator %d for lun %d", + "Unknown ATIO status 0x%x from loopid %d for lun %d", aep->at_status, aep->at_iid, lun); (void) isp_target_put_atio(isp, aep); break; @@ -787,21 +1202,27 @@ isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep) } static void -isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep) +isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) { - int lun; + int lun, iid; - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + if (FCPARAM(isp)->isp_sccfw) { lun = aep->at_scclun; } else { lun = aep->at_lun; } + if (FCPARAM(isp)->isp_2klogin) { + iid = ((at2e_entry_t *)aep)->at_iid; + } else { + iid = aep->at_iid; + } + /* * The firmware status (except for the QLTM_SVALID bit) indicates * why this ATIO was sent to us. * - * If QLTM_SVALID is set, the firmware has recommended Sense Data. + * If QLTM_SVALID is set, the firware has recommended Sense Data. * * If the DISCONNECTS DISABLED bit is set in the flags field, * we're still connected on the SCSI bus - i.e. the initiator @@ -856,30 +1277,31 @@ isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep) * Ignore it because the async event will clear things * up for us. */ - isp_prt(isp, ISP_LOGERR, atior, lun, aep->at_iid, 0); + isp_prt(isp, ISP_LOGERR, atior, lun, iid, 0); break; default: isp_prt(isp, ISP_LOGERR, - "Unknown ATIO2 status 0x%x from initiator %d for lun %d", - aep->at_status, aep->at_iid, lun); + "Unknown ATIO2 status 0x%x from loopid %d for lun %d", + aep->at_status, iid, lun); (void) isp_target_put_atio(isp, aep); break; } } static void -isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct) +isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) { void *xs; int pl = ISP_LOGTDEBUG2; char *fmsg = NULL; if (ct->ct_syshandle) { - xs = isp_find_xs(isp, ct->ct_syshandle); - if (xs == NULL) + xs = isp_find_xs_tgt(isp, ct->ct_syshandle); + if (xs == NULL) { pl = ISP_LOGALL; + } } else { xs = NULL; } @@ -931,7 +1353,7 @@ isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct) if (fmsg == NULL) fmsg = "ABORT TAG message sent by Initiator"; - isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg); + isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg); break; case CT_INVAL: @@ -1030,16 +1452,17 @@ isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct) } static void -isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) +isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) { - XS_T *xs; + void *xs; int pl = ISP_LOGTDEBUG2; char *fmsg = NULL; if (ct->ct_syshandle) { - xs = isp_find_xs(isp, ct->ct_syshandle); - if (xs == NULL) + xs = isp_find_xs_tgt(isp, ct->ct_syshandle); + if (xs == NULL) { pl = ISP_LOGALL; + } } else { xs = NULL; } @@ -1069,7 +1492,7 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) * status. These CTIOs are handled in that same way as * CT_ABORTED ones, so just fall through here. */ - fmsg = "TARGET RESET Task Management Function Received"; + fmsg = "TARGET RESET"; /*FALLTHROUGH*/ case CT_RESET: if (fmsg == NULL) @@ -1081,10 +1504,12 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) * Bus Free and returns all outstanding CTIOs with the status * set, then sends us an Immediate Notify entry. */ - if (fmsg == NULL) - fmsg = "ABORT Task Management Function Received"; + if (fmsg == NULL) { + fmsg = "ABORT"; + } - isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s", fmsg); + isp_prt(isp, ISP_LOGTDEBUG0, + "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); break; case CT_INVAL: @@ -1110,16 +1535,18 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) if (fmsg == NULL) fmsg = "Port Logout"; /*FALLTHROUGH*/ - case CT_PORTNOTAVAIL: + case CT_PORTUNAVAIL: if (fmsg == NULL) fmsg = "Port not available"; + /*FALLTHROUGH*/ case CT_PORTCHANGED: if (fmsg == NULL) fmsg = "Port Changed"; + /*FALLTHROUGH*/ case CT_NOACK: if (fmsg == NULL) fmsg = "unacknowledged Immediate Notify pending"; - isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); + isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); break; case CT_INVRXID: @@ -1127,7 +1554,7 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) * CTIO rejected by the firmware because an invalid RX_ID. * Just print a message. */ - isp_prt(isp, ISP_LOGERR, + isp_prt(isp, ISP_LOGWARN, "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid); break; @@ -1146,7 +1573,7 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) * order we got them. */ if (ct->ct_syshandle == 0) { - if ((ct->ct_flags & CT_SENDSTATUS) == 0) { + if ((ct->ct_flags & CT2_SENDSTATUS) == 0) { isp_prt(isp, pl, "intermediate CTIO completed ok"); } else { @@ -1162,7 +1589,160 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { ISP_DMAFREE(isp, xs, ct->ct_syshandle); } - if (ct->ct_flags & CT_SENDSTATUS) { + if (ct->ct_flags & CT2_SENDSTATUS) { + /* + * Sent status and command complete. + * + * We're now really done with this command, so we + * punt to the platform dependent layers because + * only there can we do the appropriate command + * complete thread synchronization. + */ + isp_prt(isp, pl, "status CTIO complete"); + } else { + /* + * Final CTIO completed. Release DMA resources and + * notify platform dependent layers. + */ + isp_prt(isp, pl, "data CTIO complete"); + } + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); + /* + * The platform layer will destroy the handle if appropriate. + */ + } +} + +static void +isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct) +{ + void *xs; + int pl = ISP_LOGTDEBUG2; + char *fmsg = NULL; + + if (ct->ct_syshandle) { + xs = isp_find_xs_tgt(isp, ct->ct_syshandle); + if (xs == NULL) { + pl = ISP_LOGALL; + } + } else { + xs = NULL; + } + + switch(ct->ct_nphdl) { + case CT7_BUS_ERROR: + isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); + /* FALL Through */ + case CT7_DATA_OVER: + case CT7_DATA_UNDER: + case CT7_OK: + /* + * There are generally 2 possibilities as to why we'd get + * this condition: + * We sent or received data. + * We sent status & command complete. + */ + + break; + + case CT7_RESET: + if (fmsg == NULL) { + fmsg = "LIP Reset"; + } + /*FALLTHROUGH*/ + case CT7_ABORTED: + /* + * When an Abort message is received the firmware goes to + * Bus Free and returns all outstanding CTIOs with the status + * set, then sends us an Immediate Notify entry. + */ + if (fmsg == NULL) { + fmsg = "ABORT"; + } + isp_prt(isp, ISP_LOGTDEBUG0, + "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); + break; + + case CT7_TIMEOUT: + if (fmsg == NULL) { + fmsg = "command"; + } + isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); + break; + + case CT7_ERR: + fmsg = "Completed with Error"; + /*FALLTHROUGH*/ + case CT7_LOGOUT: + if (fmsg == NULL) { + fmsg = "Port Logout"; + } + /*FALLTHROUGH*/ + case CT7_PORTUNAVAIL: + if (fmsg == NULL) { + fmsg = "Port not available"; + } + /*FALLTHROUGH*/ + case CT7_PORTCHANGED: + if (fmsg == NULL) { + fmsg = "Port Changed"; + } + isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); + break; + + case CT7_INVRXID: + /* + * CTIO rejected by the firmware because an invalid RX_ID. + * Just print a message. + */ + isp_prt(isp, ISP_LOGWARN, + "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid); + break; + + case CT7_REASSY_ERR: + isp_prt(isp, ISP_LOGWARN, "reassembly error"); + break; + + case CT7_SRR: + isp_prt(isp, ISP_LOGWARN, "SRR received"); + break; + + default: + isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", + ct->ct_nphdl); + break; + } + + if (xs == NULL) { + /* + * There may be more than one CTIO for a data transfer, + * or this may be a status CTIO we're not monitoring. + * + * The assumption is that they'll all be returned in the + * order we got them. + */ + if (ct->ct_syshandle == 0) { + if (ct->ct_flags & CT7_TERMINATE) { + isp_prt(isp, ISP_LOGINFO, + "termination of 0x%x complete", + ct->ct_rxid); + } else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) { + isp_prt(isp, pl, + "intermediate CTIO completed ok"); + } else { + isp_prt(isp, pl, + "unmonitored CTIO completed ok"); + } + } else { + isp_prt(isp, pl, + "NO xs for CTIO (handle 0x%x) status 0x%x", + ct->ct_syshandle, ct->ct_nphdl); + } + } else { + if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { + ISP_DMAFREE(isp, xs, ct->ct_syshandle); + } + if (ct->ct_flags & CT2_SENDSTATUS) { /* * Sent status and command complete. * diff --git a/sys/dev/ic/isp_target.h b/sys/dev/ic/isp_target.h index 93dcd1602fe..d40a068807e 100644 --- a/sys/dev/ic/isp_target.h +++ b/sys/dev/ic/isp_target.h @@ -1,30 +1,5 @@ -/* $OpenBSD: isp_target.h,v 1.13 2008/11/02 02:01:47 krw Exp $ */ +/* $OpenBSD: isp_target.h,v 1.14 2009/06/24 11:00:53 krw Exp $ */ /* $FreeBSD: src/sys/dev/isp/isp_target.h,v 1.30 2007/03/10 02:39:54 mjacob Exp $ */ -/* - * Copyright (c) 1997, 1998 - * Patrick Stirling - * pms@psconsult.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ /*- * Copyright (c) 1997-2007 by Matthew Jacob * All rights reserved. @@ -170,33 +145,13 @@ typedef struct { /* * Values for the in_task_flags field- should only get one at a time! */ -#define TASK_FLAGS_ABORT_TASK (1<<9) -#define TASK_FLAGS_CLEAR_TASK_SET (1<<10) -#define TASK_FLAGS_TARGET_RESET (1<<13) #define TASK_FLAGS_RESERVED_MASK (0xe700) #define TASK_FLAGS_CLEAR_ACA (1<<14) -#define TASK_FLAGS_TERMINATE_TASK (1<<15) #define TASK_FLAGS_TARGET_RESET (1<<13) #define TASK_FLAGS_LUN_RESET (1<<12) #define TASK_FLAGS_CLEAR_TASK_SET (1<<10) #define TASK_FLAGS_ABORT_TASK_SET (1<<9) -#ifndef MSG_ABORT_TAG -#define MSG_ABORT_TAG 0x06 -#endif -#ifndef MSG_CLEAR_QUEUE -#define MSG_CLEAR_QUEUE 0x0e -#endif -#ifndef MSG_BUS_DEV_RESET -#define MSG_BUS_DEV_RESET 0x0b -#endif -#ifndef MSG_REL_RECOVERY -#define MSG_REL_RECOVERY 0x10 -#endif -#ifndef MSG_TERM_IO_PROC -#define MSG_TERM_IO_PROC 0x11 -#endif - /* * ISP24XX Immediate Notify */ @@ -268,9 +223,9 @@ typedef struct { typedef struct { isphdr_t na_header; u_int32_t na_reserved; - u_int8_t na_lun; /* lun */ - u_int8_t na_iid; /* initiator */ - u_int16_t na_scclun; + u_int8_t na_reserved1; + u_int8_t na_iid; /* initiator loop id */ + u_int16_t na_response; u_int16_t na_flags; u_int16_t na_reserved2; u_int16_t na_status; @@ -367,21 +322,29 @@ typedef struct { * Macros to create and fetch and test concatenated handle and tag value macros */ -#define AT_MAKE_TAGID(tid, aep) \ - tid = ((aep)->at_handle << 16); \ - if ((aep)->at_flags & AT_TQAE) \ - (tid) |= ((aep)->at_tag_val + 1) +#define AT_MAKE_TAGID(tid, bus, inst, aep) \ + tid = aep->at_handle; \ + if (aep->at_flags & AT_TQAE) { \ + tid |= (aep->at_tag_val << 16); \ + tid |= (1 << 24); \ + } \ + tid |= (bus << 25); \ + tid |= (inst << 26) -#define CT_MAKE_TAGID(tid, ct) \ - tid = ((ct)->ct_fwhandle << 16); \ - if ((ct)->ct_flags & CT_TQAE) \ - (tid) |= ((ct)->ct_tag_val + 1) +#define CT_MAKE_TAGID(tid, bus, inst, ct) \ + tid = ct->ct_fwhandle; \ + if (ct->ct_flags & CT_TQAE) { \ + tid |= (ct->ct_tag_val << 16); \ + tid |= (1 << 24); \ + } \ + tid |= ((bus & 0x1) << 25); \ + tid |= (inst << 26) -#define AT_HAS_TAG(val) ((val) & 0xffff) -#define AT_GET_TAG(val) AT_HAS_TAG(val) - 1 +#define AT_HAS_TAG(val) ((val) & (1 << 24)) +#define AT_GET_TAG(val) (((val) >> 16) & 0xff) #define AT_GET_INST(val) (((val) >> 26) & 0x3f) #define AT_GET_BUS(val) (((val) >> 25) & 0x1) -#define AT_GET_HANDLE(val) ((val) >> 16) +#define AT_GET_HANDLE(val) ((val) & 0xffff) #define IN_MAKE_TAGID(tid, bus, inst, inp) \ tid = inp->in_seqid; \ @@ -411,7 +374,7 @@ typedef struct { u_int16_t at_rxid; /* response ID */ u_int16_t at_flags; u_int16_t at_status; /* firmware status */ - u_int8_t at_reserved1; + u_int8_t at_crn; /* command reference number */ u_int8_t at_taskcodes; u_int8_t at_taskflags; u_int8_t at_execodes; @@ -523,8 +486,7 @@ typedef struct { */ typedef struct { isphdr_t ct_header; - u_int16_t ct_reserved; -#define ct_syshandle ct_reserved /* we use this */ + u_int16_t ct_syshandle; u_int16_t ct_fwhandle; /* required by f/w */ u_int8_t ct_lun; /* lun */ u_int8_t ct_iid; /* initiator id */ @@ -539,14 +501,7 @@ typedef struct { u_int32_t ct_resid; /* residual length */ u_int16_t ct_timeout; u_int16_t ct_seg_count; - /* - * This is so we can share tag name space with - * CTIO{2,3,4} with the minimum of pain. - */ - union { - ispds_t ct_a[ISP_RQDSEG]; - } _u; -#define ct_dataseg _u.ct_a + ispds_t ct_dataseg[ISP_RQDSEG]; } ct_entry_t; /* @@ -598,7 +553,7 @@ typedef struct { #define CT_DATA_UNDER 0x15 /* (FC only) Data Underrun */ #define CT_BDR_MSG 0x17 /* Bus Device Reset msg received */ #define CT_TERMINATED 0x19 /* due to Terminate Transfer mbox cmd */ -#define CT_PORTNOTAVAIL 0x28 /* port not available */ +#define CT_PORTUNAVAIL 0x28 /* port not available */ #define CT_LOGOUT 0x29 /* port logout */ #define CT_PORTCHANGED 0x2A /* port changed */ #define CT_IDE 0x33 /* Initiator Detected Error */ @@ -627,8 +582,7 @@ typedef struct { #define MAXRESPLEN 26 typedef struct { isphdr_t ct_header; - u_int16_t ct_reserved; - u_int16_t ct_fwhandle; /* just to match CTIO */ + u_int32_t ct_syshandle; u_int8_t ct_lun; /* lun */ u_int8_t ct_iid; /* initiator id */ u_int16_t ct_rxid; /* response ID */ @@ -658,13 +612,10 @@ typedef struct { u_int16_t ct_scsi_status; u_int32_t ct_xfrlen; union { - ispds_t ct_a[ISP_RQDSEG_T2]; /* CTIO2 */ - ispds64_t ct_b[ISP_RQDSEG_T3]; /* CTIO3 */ - ispdslist_t ct_c; /* CTIO4 */ - } _u; -#define ct_dataseg _u.ct_a -#define ct_dataseg64 _u.ct_b -#define ct_dslist _u.ct_c + ispds_t ct_dataseg[ISP_RQDSEG_T2]; + ispds64_t ct_dataseg64[ISP_RQDSEG_T3]; + ispdslist_t ct_dslist; + } u; } m0; struct { u_int16_t _reserved; @@ -681,14 +632,6 @@ typedef struct { u_int32_t ct_datalen; ispds_t ct_fcp_rsp_iudata; } m2; - /* - * CTIO2 returned from F/W... - */ - struct { - u_int32_t _reserved[4]; - u_int16_t ct_scsi_status; - u_int8_t ct_sense[QLTM_SENSELEN]; - } fw; } rsp; } ct2_entry_t; @@ -740,10 +683,10 @@ typedef struct { #define CT2_FLAG_MODE1 0x0001 #define CT2_FLAG_MODE2 0x0002 #define CT2_FLAG_MMASK 0x0003 -#define CT2_DATA_IN CT_DATA_IN -#define CT2_DATA_OUT CT_DATA_OUT -#define CT2_NO_DATA CT_NO_DATA -#define CT2_DATAMASK CT_DATAMASK +#define CT2_DATA_IN 0x0040 +#define CT2_DATA_OUT 0x0080 +#define CT2_NO_DATA 0x00C0 +#define CT2_DATAMASK 0x00C0 #define CT2_CCINCR 0x0100 #define CT2_FASTPOST 0x0200 #define CT2_CONFIRM 0x2000 @@ -948,7 +891,7 @@ typedef struct { #define ISP_TDQE(isp, msg, idx, arg) \ if (isp->isp_dblev & ISP_LOGTDEBUG2) isp_print_qentry(isp, msg, idx, arg) -#ifdef ISP_TARGET_FUNCTIONS +#ifndef ISP_TOOLS /* * The functions below are for the publicly available * target mode functions that are internal to the QLogic driver. @@ -957,7 +900,7 @@ typedef struct { /* * This function handles new response queue entry appropriate for target mode. */ -int isp_target_notify(struct ispsoftc *, void *, u_int16_t *); +int isp_target_notify(ispsoftc_t *, void *, u_int32_t *); /* * This function externalizes the ability to acknowledge an Immediate Notify @@ -970,13 +913,13 @@ void isp_notify_ack(ispsoftc_t *, void *); * (softc, cmd, bus, tgt, lun, cmd_cnt, inotify_cnt, opaque) */ #define DFLT_CMND_CNT 0xfe /* unmonitored */ -#define DFLT_INOT_CNT 16 -int isp_lun_cmd(struct ispsoftc *, int, int, int, int, int, int, u_int32_t); +#define DFLT_INOT_CNT 0xfe /* unmonitored */ +int isp_lun_cmd(ispsoftc_t *, int, int, int, int, int, int, u_int32_t); /* * General request queue 'put' routine for target mode entries. */ -int isp_target_put_entry(struct ispsoftc *isp, void *); +int isp_target_put_entry(ispsoftc_t *isp, void *); /* * General routine to put back an ATIO entry- @@ -984,13 +927,13 @@ int isp_target_put_entry(struct ispsoftc *isp, void *); * The argument is a pointer to a source ATIO * or ATIO2. */ -int isp_target_put_atio(struct ispsoftc *, void *); +int isp_target_put_atio(ispsoftc_t *, void *); /* * General routine to send a final CTIO for a command- used mostly for * local responses. */ -int isp_endcmd(struct ispsoftc *, void *, u_int32_t, u_int16_t); +int isp_endcmd(ispsoftc_t *, void *, u_int32_t, u_int32_t); #define ECMD_SVALID 0x100 /* @@ -998,7 +941,6 @@ int isp_endcmd(struct ispsoftc *, void *, u_int32_t, u_int16_t); * * Return nonzero if the interrupt that generated this event has been dismissed. */ - -int isp_target_async(struct ispsoftc *, int, int); +int isp_target_async(ispsoftc_t *, int, int); #endif #endif /* _ISP_TARGET_H */ diff --git a/sys/dev/ic/isp_tpublic.h b/sys/dev/ic/isp_tpublic.h index 5c27602ba67..c6ff0aa6798 100644 --- a/sys/dev/ic/isp_tpublic.h +++ b/sys/dev/ic/isp_tpublic.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_tpublic.h,v 1.11 2008/11/01 18:54:27 krw Exp $ */ +/* $OpenBSD: isp_tpublic.h,v 1.12 2009/06/24 11:00:53 krw Exp $ */ /* $FreeBSD: src/sys/dev/isp/isp_tpublic.h,v 1.19 2007/05/05 20:17:23 mjacob Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob @@ -39,10 +39,11 @@ */ typedef enum { QOUT_HBA_REG=0, /* the argument is a pointer to a hba_register_t */ - QOUT_TMD_START, /* the argument is a pointer to a tmd_cmd_t */ - QOUT_TMD_DONE, /* the argument is a pointer to a tmd_cmd_t */ - QOUT_TEVENT, /* the argument is a pointer to a tmd_event_t */ - QOUT_TMSG, /* the argument is a pointer to a tmd_msg_t */ + QOUT_ENABLE, /* the argument is a pointer to a enadis_t */ + QOUT_DISABLE, /* the argument is a pointer to a enadis_t */ + QOUT_TMD_START, /* the argument is a pointer to a tmd_cmd_t */ + QOUT_TMD_DONE, /* the argument is a pointer to a tmd_cmd_t */ + QOUT_NOTIFY, /* the argument is a pointer to a tmd_notify_t */ QOUT_HBA_UNREG /* the argument is a pointer to a hba_register_t */ } tact_e; @@ -51,28 +52,18 @@ typedef enum { * MD driver to figure out what to do with. */ typedef enum { - QIN_HBA_REG=6, /* the argument is a pointer to a hba_register_t */ - QIN_ENABLE, /* the argument is a pointer to a tmd_cmd_t */ - QIN_DISABLE, /* the argument is a pointer to a tmd_cmd_t */ + QIN_HBA_REG=99, /* the argument is a pointer to a hba_register_t */ + QIN_GETINFO, /* the argument is a pointer to a info_t */ + QIN_SETINFO, /* the argument is a pointer to a info_t */ + QIN_GETDLIST, /* the argument is a pointer to a fc_dlist_t */ + QIN_ENABLE, /* the argument is a pointer to a enadis_t */ + QIN_DISABLE, /* the argument is a pointer to a enadis_t */ QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */ QIN_TMD_FIN, /* the argument is a pointer to a tmd_cmd_t */ + QIN_NOTIFY_ACK, /* the argument is a pointer to a tmd_notify_t */ QIN_HBA_UNREG /* the argument is a pointer to a hba_register_t */ } qact_e; -#ifndef IN_MSGLEN -#define IN_MSGLEN 8 -#endif -typedef struct { - void * nt_hba; /* HBA tag */ - u_int64_t nt_iid; /* initiator id */ - u_int64_t nt_tgt; /* target id */ - u_int64_t nt_lun; /* logical unit */ - u_int8_t nt_bus; /* bus */ - u_int8_t nt_tagtype; /* tag type */ - u_int16_t nt_tagval; /* tag value */ - u_int8_t nt_msg[IN_MSGLEN]; /* message content */ -} tmd_msg_t; - /* * This structure is used to register to other software modules the * binding of an HBA identifier, driver name and instance and the @@ -85,20 +76,18 @@ typedef struct { */ #define QR_VERSION 16 typedef struct { - void * r_identity; - char r_name[8]; - int r_inst; - int r_lunwidth; - int r_buswidth; - void (*r_action)(int, void *); + /* NB: tags from here to r_version must never change */ + void * r_identity; + void (*r_action)(qact_e, void *); + char r_name[8]; + int r_inst; + int r_version; + u_int32_t r_locator; + u_int32_t r_nchannels; + enum { R_FC, R_SPI } r_type; + void * r_private; } hba_register_t; -typedef struct { - void * ev_hba; /* HBA tag */ - u_int16_t ev_bus; /* bus */ - u_int16_t ev_event; /* type of async event */ -} tmd_event_t; - /* * An information structure that is used to get or set per-channel transport layer parameters. */ @@ -295,26 +284,6 @@ typedef struct { * */ -#ifndef _LP64 -#if defined(__alpha__) || defined(__sparcv9cpu) || defined(__sparc_v9__) ||\ - defined(__ia64__) -#define _LP64 -#endif -#endif - -#ifndef _TMD_PAD_LEN -#ifdef _LP64 -#define _TMD_PAD_LEN 12 -#else -#define _TMD_PAD_LEN 24 -#endif -#endif -#ifndef ATIO_CDBLEN -#define ATIO_CDBLEN 26 -#endif -#ifndef QLTM_SENSELEN -#define QLTM_SENSELEN 18 -#endif #ifndef TMD_CDBLEN #define TMD_CDBLEN 16 #endif @@ -331,20 +300,26 @@ typedef struct tmd_cmd { void * cd_data; /* 'pointer' to data */ u_int64_t cd_iid; /* initiator ID */ u_int64_t cd_tgt; /* target id */ - u_int64_t cd_lun; /* logical unit */ - u_int8_t cd_bus; /* bus */ - u_int8_t cd_tagtype; /* tag type */ - u_int32_t cd_tagval; /* tag value */ - u_int8_t cd_cdb[ATIO_CDBLEN]; /* Command */ - u_int8_t cd_lflags; /* flags lower level sets */ - u_int8_t cd_hflags; /* flags higher level sets */ - u_int32_t cd_totlen; /* total data requirement */ + u_int8_t cd_lun[8]; /* logical unit */ + u_int64_t cd_tagval; /* tag value */ + u_int32_t cd_channel; /* channel index */ + u_int32_t cd_lflags; /* flags lower level sets */ + u_int32_t cd_hflags; /* flags higher level sets */ + u_int32_t cd_totlen; /* total data load */ u_int32_t cd_resid; /* total data residual */ u_int32_t cd_xfrlen; /* current data load */ int32_t cd_error; /* current error */ - u_int8_t cd_sense[QLTM_SENSELEN]; - u_int16_t cd_scsi_status; /* closing SCSI status */ - u_int8_t cd_reserved[_TMD_PAD_LEN]; + u_int8_t cd_tagtype; /* tag type */ + u_int8_t cd_scsi_status; + u_int8_t cd_sense[TMD_SENSELEN]; + u_int8_t cd_cdb[TMD_CDBLEN]; + union { + void * ptrs[QCDS / sizeof (void *)]; + u_int64_t llongs[QCDS / sizeof (u_int64_t)]; + u_int32_t longs[QCDS / sizeof (u_int32_t)]; + u_int16_t shorts[QCDS / sizeof (u_int16_t)]; + u_int8_t bytes[QCDS]; + } cd_lreserved[4], cd_hreserved[4]; } tmd_cmd_t; /* defined tags */ @@ -389,22 +364,21 @@ typedef struct tmd_cmd { * flags CDFH_DATA_IN and CDFH_DATA_OUT define which direction. */ #define CDFL_SNSVALID 0x01 /* sense data (from f/w) good */ -#define CDFL_NODISC 0x02 /* disconnects disabled */ -#define CDFL_SENTSENSE 0x04 /* last action sent sense data */ -#define CDFL_SENTSTATUS 0x08 /* last action sent status */ -#define CDFL_BIDIR 0x0C /* bidirectional data */ -#define CDFL_ERROR 0x10 /* last action ended in error */ -#define CDFL_BUSY 0x40 /* this command is not on a free list */ -#define CDFL_PRIVATE_0 0x80 /* private layer flags */ - +#define CDFL_SENTSTATUS 0x02 /* last action sent status */ +#define CDFL_DATA_IN 0x04 /* target (us) -> initiator (them) */ +#define CDFL_DATA_OUT 0x08 /* initiator (them) -> target (us) */ +#define CDFL_BIDIR 0x0C /* bidirectional data */ +#define CDFL_ERROR 0x10 /* last action ended in error */ +#define CDFL_NODISC 0x20 /* disconnects disabled */ +#define CDFL_SENTSENSE 0x40 /* last action sent sense data */ +#define CDFL_BUSY 0x80 /* this command is not on a free list */ +#define CDFL_PRIVATE 0xFF000000 /* private layer flags */ -#define CDFH_NODATA 0x00 /* no data transfer expected */ #define CDFH_SNSVALID 0x01 /* sense data (from outer layer) good */ #define CDFH_STSVALID 0x02 /* status valid */ #define CDFH_DATA_IN 0x04 /* target (us) -> initiator (them) */ #define CDFH_DATA_OUT 0x08 /* initiator (them) -> target (us) */ #define CDFH_DATA_MASK 0x0C /* mask to cover data direction */ -#define CDFH_PRIVATE_0 0x80 /* private layer flags */ #define CDFH_PRIVATE 0xFF000000 /* private layer flags */ diff --git a/sys/dev/ic/ispmbox.h b/sys/dev/ic/ispmbox.h index b2ec96b60b6..b805c082923 100644 --- a/sys/dev/ic/ispmbox.h +++ b/sys/dev/ic/ispmbox.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ispmbox.h,v 1.22 2008/11/02 03:17:22 krw Exp $ */ +/* $OpenBSD: ispmbox.h,v 1.23 2009/06/24 11:00:53 krw Exp $ */ /* $FreeBSD: src/sys/dev/isp/ispmbox.h,v 1.59 2007/03/10 02:39:54 mjacob Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob @@ -165,10 +165,6 @@ #define MBOX_BUSY 0x04 -typedef struct { - u_int16_t param[8]; -} mbreg_t; - /* * Mailbox Command Complete Status Codes */ @@ -254,18 +250,6 @@ typedef struct { */ #define QENTRY_LEN 64 -#define WRITE_REQUEST_QUEUE_IN_POINTER(isp, value) \ - ISP_WRITE(isp, isp->isp_rqstinrp, value) - -#define READ_REQUEST_QUEUE_OUT_POINTER(isp) \ - ISP_READ(isp, isp->isp_rqstoutrp) - -#define READ_RESPONSE_QUEUE_IN_POINTER(isp) \ - ISP_READ(isp, isp->isp_respinrp) - -#define WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, value) \ - ISP_WRITE(isp, isp->isp_respoutrp, value) - /* * Command Structure Definitions */ @@ -337,7 +321,7 @@ typedef struct { #define RQSTYPE_T4RQS 0x15 #define RQSTYPE_ATIO2 0x16 /* Target Mode */ #define RQSTYPE_CTIO2 0x17 /* Target Mode */ -#define RQSTYPE_CSET0 0x18 +#define RQSTYPE_T7RQS 0x18 #define RQSTYPE_T3RQS 0x19 #define RQSTYPE_IP_XMIT_64 0x1b #define RQSTYPE_CTIO4 0x1e /* Target Mode */ @@ -362,7 +346,6 @@ typedef struct { u_int8_t req_lun_trn; u_int8_t req_target; u_int16_t req_cdblen; -#define req_modifier req_cdblen /* marker packet */ u_int16_t req_flags; u_int16_t req_reserved; u_int16_t req_time; @@ -826,7 +809,7 @@ typedef struct { * * Version One (prime) format. */ -typedef struct isp_icb { +typedef struct { u_int8_t icb_version; u_int8_t icb_reserved0; u_int16_t icb_fwoptions; @@ -898,16 +881,15 @@ typedef struct isp_icb { #define ICBXOPT_RIO_32BIT 2 #define ICBXOPT_RIO_16BIT_IOCB 3 #define ICBXOPT_RIO_32BIT_IOCB 4 -#define ICBXOPT_ZIO (1 << 5) +#define ICBXOPT_ZIO 5 #define ICBXOPT_TIMER_MASK 0x7 +#define ICBZOPT_RATE_MASK 0xC000 +#define ICBZOPT_RATE_ONEGB 0x0000 +#define ICBZOPT_RATE_AUTO 0x8000 +#define ICBZOPT_RATE_TWOGB 0x4000 #define ICBZOPT_50_OHM 0x2000 #define ICBZOPT_ENA_OOF 0x0040 /* out of order frame handling */ -/* These 3 only apply to the 2300 */ -#define ICBZOPT_RATE_ONEGB (MBGSD_ONEGB << 14) -#define ICBZOPT_RATE_TWOGB (MBGSD_TWOGB << 14) -#define ICBZOPT_RATE_AUTO (MBGSD_AUTO << 14) - #define ICBZOPT_RSPSZ_MASK 0x0030 #define ICBZOPT_RSPSZ_24 0x0000 #define ICBZOPT_RSPSZ_12 0x0010 @@ -1030,22 +1012,6 @@ typedef struct { array[ICB_NNM6] = (u_int8_t) ((wwn >> 48) & 0xff), \ array[ICB_NNM7] = (u_int8_t) ((wwn >> 56) & 0xff) -/* - * FC-AL Position Map - * - * This is an at most 128 byte map that returns either - * the LILP or Firmware generated list of ports. - * - * We deviate a bit from the returned QLogic format to - * use an extra bit to say whether this was a LILP or - * f/w generated map. - */ -typedef struct { - u_int8_t fwmap : 1, - count : 7; - u_int8_t map[127]; -} fcpos_map_t; - #define MAKE_WWN_FROM_NODE_NAME(wwn, array) \ wwn = ((u_int64_t) array[ICB_NNM0]) | \ ((u_int64_t) array[ICB_NNM1] << 8) | \ @@ -1099,7 +1065,7 @@ typedef struct { u_int16_t pdb_loopid; u_int16_t pdb_il_ptr; u_int16_t pdb_sl_ptr; -} isp_pdb_t; +} isp_pdb_21xx_t; #define PDB_OPTIONS_XMITTING (1<<11) #define PDB_OPTIONS_LNKXMIT (1<<10) @@ -1158,13 +1124,14 @@ typedef struct { /* * Common elements from the above two structures that are actually useful to us. */ - -#define FS_ACC 0x8002 -#define FS_RJT 0x8001 - -#define FC4_IP 5 /* ISO/EEC 8802-2 LLC/SNAP "Out of Order Delivery" */ -#define FC4_SCSI 8 /* SCSI-3 via Fivre Channel Protocol (FCP) */ -#define FC4_FC_SVC 0x20 /* Fibre Channel Services */ +typedef struct { + u_int16_t handle; + u_int16_t reserved; + u_int32_t s3_role : 8, + portid : 24; + u_int8_t portname[8]; + u_int8_t nodename[8]; +} isp_pdb_t; /* * Genericized Port Login/Logout software structure diff --git a/sys/dev/ic/ispreg.h b/sys/dev/ic/ispreg.h index 2989672e587..5429c47d9dd 100644 --- a/sys/dev/ic/ispreg.h +++ b/sys/dev/ic/ispreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ispreg.h,v 1.15 2008/10/25 22:53:30 krw Exp $ */ +/* $OpenBSD: ispreg.h,v 1.16 2009/06/24 11:00:53 krw Exp $ */ /* $FreeBSD: src/sys/dev/isp/ispreg.h,v 1.29 2007/03/10 02:39:54 mjacob Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob @@ -203,7 +203,6 @@ #define BIU2100_FB_REGS (1 << 4) /* FrameBuffer Regs */ #define BIU2100_FPM0_REGS (2 << 4) /* FPM 0 Regs */ #define BIU2100_FPM1_REGS (3 << 4) /* FPM 1 Regs */ -#define BIU2100_PCI64 0x04 /* R: 64 Bit PCI slot */ #define BIU2100_NVRAM_OFFSET (1 << 14) #define BIU2100_FLASH_UPPER_64K 0x04 /* RW: Upper 64K Bank Select */ #define BIU2100_FLASH_ENABLE 0x02 /* RW: Enable Flash RAM */ @@ -230,16 +229,7 @@ #define BIU2100_ICR_ENABLE_TXDMA_INT 0x0001 #define BIU2100_ICR_DISABLE_ALL_INTS 0x0000 -#define ENABLE_INTS(isp) (IS_SCSI(isp))? \ - ISP_WRITE(isp, BIU_ICR, BIU_ICR_ENABLE_RISC_INT | BIU_ICR_ENABLE_ALL_INTS) : \ - ISP_WRITE(isp, BIU_ICR, BIU2100_ICR_ENA_RISC_INT | BIU2100_ICR_ENABLE_ALL_INTS) - -#define INTS_ENABLED(isp) ((IS_SCSI(isp))? \ - (ISP_READ(isp, BIU_ICR) & (BIU_ICR_ENABLE_RISC_INT|BIU_ICR_ENABLE_ALL_INTS)) :\ - (ISP_READ(isp, BIU_ICR) & \ - (BIU2100_ICR_ENA_RISC_INT|BIU2100_ICR_ENABLE_ALL_INTS))) - -#define DISABLE_INTS(isp) ISP_WRITE(isp, BIU_ICR, 0) +#define BIU2100_IMASK (BIU2100_ICR_ENA_RISC_INT|BIU2100_ICR_ENABLE_ALL_INTS) /* BUS STATUS REGISTER */ #define BIU_ISR_DMA_INT 0x0020 /* DMA interrupt pending */ @@ -256,11 +246,14 @@ #define BIU2100_ISR_RXDMA_INT_PENDING 0x0002 /* Global interrupt pending */ #define BIU2100_ISR_TXDMA_INT_PENDING 0x0001 /* Global interrupt pending */ -#define INT_PENDING(isp, isr) (IS_FC(isp)? \ - ((isr & BIU2100_ISR_RISC_INT) != 0) : ((isr & BIU_ISR_RISC_INT) != 0)) +#define INT_PENDING(isp, isr) \ + IS_FC(isp)? \ + (IS_24XX(isp)? (isr & BIU2400_ISR_RISC_INT) : (isr & BIU2100_ISR_RISC_INT)) :\ + (isr & BIU_ISR_RISC_INT) #define INT_PENDING_MASK(isp) \ - (IS_FC(isp)? BIU2100_ISR_RISC_INT: BIU_ISR_RISC_INT) + (IS_FC(isp)? (IS_24XX(isp)? BIU2400_ISR_RISC_INT : BIU2100_ISR_RISC_INT) : \ + (BIU_ISR_RISC_INT)) /* BUS SEMAPHORE REGISTER */ #define BIU_SEMA_STATUS 0x0002 /* Semaphore Status Bit */ @@ -464,12 +457,23 @@ #define MBOX_OFF(n) (MBOX_BLOCK + ((n) << 1)) #define NMBOX(isp) \ (((((isp)->isp_type & ISP_HA_SCSI) >= ISP_HA_SCSI_1040A) || \ - ((isp)->isp_type & ISP_HA_FC))? 8 : 6) + ((isp)->isp_type & ISP_HA_FC))? 12 : 6) #define NMBOX_BMASK(isp) \ (((((isp)->isp_type & ISP_HA_SCSI) >= ISP_HA_SCSI_1040A) || \ - ((isp)->isp_type & ISP_HA_FC))? 0xff : 0x3f) - -#define MAX_MAILBOX 8 + ((isp)->isp_type & ISP_HA_FC))? 0xfff : 0x3f) + +#define MAX_MAILBOX(isp) ((IS_FC(isp))? 12 : 8) +#define MAILBOX_STORAGE 12 +/* if timeout == 0, then default timeout is picked */ +#define MBCMD_DEFAULT_TIMEOUT 100000 /* 100 ms */ +typedef struct { + u_int16_t param[MAILBOX_STORAGE]; + u_int16_t ibits; + u_int16_t obits; + u_int32_t : 28, + logval : 4; + u_int32_t timeout; +} mbreg_t; /* * Fibre Protocol Module and Frame Buffer Register Offsets/Definitions (2X00). @@ -1046,7 +1050,7 @@ #define ISP2100_NVRAM_SIZE 256 /* ISP_NVRAM_VERSION is in same overall place */ #define ISP2100_NVRAM_RISCVER(c) (c)[6] -#define ISP2100_NVRAM_OPTIONS(c) (c)[8] +#define ISP2100_NVRAM_OPTIONS(c) ((c)[8] | ((c)[9] << 8)) #define ISP2100_NVRAM_MAXFRAMELENGTH(c) (((c)[10]) | ((c)[11] << 8)) #define ISP2100_NVRAM_MAXIOCBALLOCATION(c) (((c)[12]) | ((c)[13] << 8)) #define ISP2100_NVRAM_EXECUTION_THROTTLE(c) (((c)[14]) | ((c)[15] << 8)) @@ -1063,10 +1067,10 @@ (((u_int64_t)(c)[24]) << 8) | \ (((u_int64_t)(c)[25]) << 0)) -#define ISP2100_NVRAM_HARDLOOPID(c) (c)[26] +#define ISP2100_NVRAM_HARDLOOPID(c) ((c)[26] | ((c)[27] << 8)) #define ISP2100_NVRAM_TOV(c) ((c)[29]) -#define ISP2200_NVRAM_NODE_NAME(c) (\ +#define ISP2100_NVRAM_NODE_NAME(c) (\ (((u_int64_t)(c)[30]) << 56) | \ (((u_int64_t)(c)[31]) << 48) | \ (((u_int64_t)(c)[32]) << 40) | \ @@ -1076,7 +1080,6 @@ (((u_int64_t)(c)[36]) << 8) | \ (((u_int64_t)(c)[37]) << 0)) -#define ISP2100_NVRAM_HBA_OPTIONS(c) (c)[70] #define ISP2100_XFW_OPTIONS(c) ((c)[38] | ((c)[39] << 8)) #define ISP2100_RACC_TIMER(c) (c)[40] @@ -1086,6 +1089,7 @@ #define ISP2100_SERIAL_LINK(c) ((c)[68] | ((c)[69] << 8)) +#define ISP2100_NVRAM_HBA_OPTIONS(c) ((c)[70] | ((c)[71] << 8)) #define ISP2100_NVRAM_HBA_DISABLE(c) ISPBSMX(c, 70, 0, 0x01) #define ISP2100_NVRAM_BIOS_DISABLE(c) ISPBSMX(c, 70, 1, 0x01) #define ISP2100_NVRAM_LUN_DISABLE(c) ISPBSMX(c, 70, 2, 0x01) @@ -1106,7 +1110,7 @@ #define ISP2100_NVRAM_BOOT_LUN(c) (c)[80] #define ISP2100_RESET_DELAY(c) (c)[81] -#define ISP2200_HBA_FEATURES(c) (c)[232] | ((c)[233] << 8) +#define ISP2100_HBA_FEATURES(c) ((c)[232] | ((c)[233] << 8)) /* * Qlogic 2400 NVRAM is an array of 512 bytes with a 32 bit checksum. diff --git a/sys/dev/ic/ispvar.h b/sys/dev/ic/ispvar.h index fe90c295954..d0da6b35931 100644 --- a/sys/dev/ic/ispvar.h +++ b/sys/dev/ic/ispvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ispvar.h,v 1.26 2008/11/02 03:17:22 krw Exp $ */ +/* $OpenBSD: ispvar.h,v 1.27 2009/06/24 11:00:53 krw Exp $ */ /* $FreeBSD: src/sys/dev/isp/ispvar.h,v 1.85 2007/07/02 20:08:20 mjacob Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob @@ -36,49 +36,40 @@ #if defined(__NetBSD__) || defined(__OpenBSD__) #include <dev/ic/isp_stds.h> #include <dev/ic/ispmbox.h> -#ifdef ISP_TARGET_MODE -#include <dev/ic/isp_target.h> -#include <dev/ic/isp_tpublic.h> -#endif #endif #ifdef __FreeBSD__ #include <dev/isp/isp_stds.h> #include <dev/isp/ispmbox.h> -#ifdef ISP_TARGET_MODE -#include <dev/isp/isp_target.h> -#include <dev/isp/isp_tpublic.h> -#endif #endif #ifdef __linux__ #include "isp_stds.h" #include "ispmbox.h" -#ifdef ISP_TARGET_MODE -#include "isp_target.h" -#include "isp_tpublic.h" #endif +#ifdef __svr4__ +#include "isp_stds.h" +#include "ispmbox.h" #endif -#define ISP_CORE_VERSION_MAJOR 2 -#define ISP_CORE_VERSION_MINOR 7 +#define ISP_CORE_VERSION_MAJOR 3 +#define ISP_CORE_VERSION_MINOR 0 /* * Vector for bus specific code to provide specific services. */ -struct ispsoftc; +typedef struct ispsoftc ispsoftc_t; struct ispmdvec { int (*dv_rd_isr) - (struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); - u_int16_t (*dv_rd_reg) (struct ispsoftc *, int); - void (*dv_wr_reg) (struct ispsoftc *, int, u_int16_t); + (struct ispsoftc *, u_int32_t *, u_int16_t *, u_int16_t *); + u_int32_t (*dv_rd_reg) (struct ispsoftc *, int); + void (*dv_wr_reg) (struct ispsoftc *, int, u_int32_t); int (*dv_mbxdma) (struct ispsoftc *); - int (*dv_dmaset) (struct ispsoftc *, - XS_T *, ispreq_t *, u_int16_t *, u_int16_t); - void (*dv_dmaclr) - (struct ispsoftc *, XS_T *, u_int16_t); + int (*dv_dmaset) + (struct ispsoftc *, XS_T *, ispreq_t *, u_int32_t *, u_int32_t); + void (*dv_dmaclr) (struct ispsoftc *, XS_T *, u_int32_t); void (*dv_reset0) (struct ispsoftc *); void (*dv_reset1) (struct ispsoftc *); void (*dv_dregs) (struct ispsoftc *, const char *); - u_int16_t *dv_ispfw; /* ptr to f/w */ + const void * dv_ispfw; /* ptr to f/w */ u_int16_t dv_conf1; u_int16_t dv_clock; /* clock frequency */ }; @@ -87,20 +78,11 @@ struct ispmdvec { * Overall parameters */ #define MAX_TARGETS 16 -#define MAX_FC_TARG 256 +#define MAX_FC_TARG 512 #define ISP_MAX_TARGETS(isp) (IS_FC(isp)? MAX_FC_TARG : MAX_TARGETS) #define ISP_MAX_LUNS(isp) (isp)->isp_maxluns /* - * 'Types' - */ -#ifdef ISP_DAC_SUPPORTED -typedef u_int64_t isp_dma_addr_t; -#else -typedef u_int32_t isp_dma_addr_t; -#endif - -/* * Macros to access ISP registers through bus specific layers- * mostly wrappers to vector through the mdvec structure. */ @@ -163,7 +145,7 @@ typedef u_int32_t isp_dma_addr_t; #define RESULT_QUEUE_LEN(x) \ (((MAXISPREQUEST(x) >> 2) < 64)? 64 : MAXISPREQUEST(x) >> 2) #endif -#define ISP_QUEUE_ENTRY(q, idx) ((q) + ((idx) * QENTRY_LEN)) +#define ISP_QUEUE_ENTRY(q, idx) (((u_int8_t *)q) + ((idx) * QENTRY_LEN)) #define ISP_QUEUE_SIZE(n) ((n) * QENTRY_LEN) #define ISP_NXT_QENTRY(idx, qlen) (((idx) + 1) & ((qlen)-1)) #define ISP_QFREE(in, out, qlen) \ @@ -174,20 +156,22 @@ typedef u_int32_t isp_dma_addr_t; #define ISP_ADD_REQUEST(isp, nxti) \ MEMORYBARRIER(isp, SYNC_REQUEST, isp->isp_reqidx, QENTRY_LEN); \ - WRITE_REQUEST_QUEUE_IN_POINTER(isp, nxti); \ + ISP_WRITE(isp, isp->isp_rqstinrp, nxti); \ isp->isp_reqidx = nxti /* * SCSI Specific Host Adapter Parameters- per bus, per target */ - typedef struct { - u_int isp_gotdparms : 1, + u_int32_t : 10, + isp_bad_nvram : 1, + isp_gotdparms : 1, isp_req_ack_active_neg : 1, isp_data_line_active_neg: 1, isp_cmd_dma_burst_enable: 1, isp_data_dma_burst_enabl: 1, isp_fifo_threshold : 3, + isp_ptisp : 1, isp_ultramode : 1, isp_diffmode : 1, isp_lvdmode : 1, @@ -249,14 +233,10 @@ typedef struct { /* * Fibre Channel Specifics */ -#define FL_PORT_ID 0x7e /* FL_Port Special ID */ -#define FC_PORT_ID 0x7f /* Fabric Controller Special ID */ -#define FC_SNS_ID 0x80 /* SNS Server Special ID */ - -/* #define ISP_USE_GA_NXT 1 */ /* Use GA_NXT with switches */ -#ifndef GA_NXT_MAX -#define GA_NXT_MAX 256 -#endif +/* These are for non-2K Login Firmware cards */ +#define FL_ID 0x7e /* FL_Port Special ID */ +#define SNS_ID 0x80 /* SNS Server Special ID */ +#define NPH_MAX 0xfe /* These are for 2K Login Firmware cards */ #define NPH_RESERVED 0x7F0 /* begin of reserved N-port handles */ @@ -333,64 +313,102 @@ typedef struct { * value. */ typedef struct { - u_int32_t isp_fwoptions : 16, - isp_gbspeed : 2, - isp_iid_set : 1, - loop_seen_once : 1, - isp_loopstate : 4, /* Current Loop State */ - isp_fwstate : 3, /* ISP F/W state */ + /* + * This is the handle that the firmware needs in order for us to + * send commands to the device. For pre-24XX cards, this would be + * the 'loopid'. + */ + u_int16_t handle; + /* + * The ini_map_idx, if nonzero, is the system virtual target ID (+1) + * as a cross-reference with the isp_ini_map. + * + * A device is 'autologin' if the firmware automatically logs into + * it (re-logins as needed). Basically, local private loop devices. + * + * The state is the current state of thsi entry. + * + * Role is Initiator, Target, Both + * + * Portid is obvious, as or node && port WWNs. The new_role and + * new_portid is for when we are pending a change. + */ + u_int16_t ini_map_idx : 12, + autologin : 1, /* F/W does PLOGI/PLOGO */ + state : 3; + u_int32_t reserved : 6, + roles : 2, + portid : 24; + u_int32_t new_reserved : 6, + new_roles : 2, + new_portid : 24; + u_int64_t node_wwn; + u_int64_t port_wwn; +} fcportdb_t; + +#define FC_PORTDB_STATE_NIL 0 +#define FC_PORTDB_STATE_PROBATIONAL 1 +#define FC_PORTDB_STATE_DEAD 2 +#define FC_PORTDB_STATE_CHANGED 3 +#define FC_PORTDB_STATE_NEW 4 +#define FC_PORTDB_STATE_PENDING_VALID 5 +#define FC_PORTDB_STATE_ZOMBIE 6 +#define FC_PORTDB_STATE_VALID 7 + +/* + * FC card specific information + */ +typedef struct { + u_int32_t : 10, + isp_tmode : 1, + isp_2klogin : 1, + isp_sccfw : 1, + isp_gbspeed : 3, + : 1, + : 1, isp_gotdparms : 1, + isp_bad_nvram : 1, + isp_loopstate : 4, /* Current Loop State */ + isp_fwstate : 4, /* ISP F/W state */ isp_topo : 3, - isp_onfabric : 1; - u_int8_t isp_iid; /* 'initiator' id */ - u_int8_t isp_loopid; /* hard loop id */ - u_int8_t isp_alpa; /* ALPA */ - u_int32_t isp_portid; - volatile u_int16_t isp_lipseq; /* LIP sequence # */ + loop_seen_once : 1; + u_int32_t : 8, + isp_portid : 24; /* S_ID */ + u_int16_t isp_fwoptions; + u_int16_t isp_xfwoptions; + u_int16_t isp_zfwoptions; + u_int16_t isp_loopid; /* hard loop id */ u_int16_t isp_fwattr; /* firmware attributes */ - u_int8_t isp_execthrottle; + u_int16_t isp_execthrottle; u_int8_t isp_retry_delay; u_int8_t isp_retry_count; u_int8_t isp_reserved; u_int16_t isp_maxalloc; u_int16_t isp_maxfrmlen; - u_int64_t isp_nodewwn; - u_int64_t isp_portwwn; + u_int64_t isp_wwnn_nvram; + u_int64_t isp_wwpn_nvram; + /* - * Port Data Base. This is indexed by 'target', which is invariate. - * However, elements within can move around due to loop changes, - * so the actual loop ID passed to the F/W is in this structure. - * The first time the loop is seen up, loopid will match the index - * (except for fabric nodes which are above mapped above FC_SNS_ID - * and are completely virtual), but subsequent LIPs can cause things - * to move around. + * Our Port Data Base */ - struct lportdb { - u_int32_t - port_type : 8, - loopid : 8, - fc4_type : 4, - last_fabric_dev : 1, - : 2, - relogin : 1, - force_logout : 1, - was_fabric_dev : 1, - fabric_dev : 1, - loggedin : 1, - roles : 2, - valid : 1; - u_int32_t portid; - u_int64_t node_wwn; - u_int64_t port_wwn; - } portdb[MAX_FC_TARG], tport[FC_PORT_ID]; + fcportdb_t portdb[MAX_FC_TARG]; + + /* + * This maps system virtual 'target' id to a portdb entry. + * + * The mapping function is to take any non-zero entry and + * subtract one to get the portdb index. This means that + * entries which are zero are unmapped (i.e., don't exist). + */ + u_int16_t isp_ini_map[MAX_FC_TARG]; /* * Scratch DMA mapped in area to fetch Port Database stuff, etc. */ - caddr_t isp_scratch; - isp_dma_addr_t isp_scdma; + void * isp_scratch; + XS_DMA_ADDR_T isp_scdma; #ifdef ISP_FW_CRASH_DUMP - u_int16_t *isp_dump_data; + u_int16_t * isp_dump_data; #endif } fcparam; @@ -406,10 +424,10 @@ typedef struct { #define LOOP_NIL 0 #define LOOP_LIP_RCVD 1 #define LOOP_PDB_RCVD 2 -#define LOOP_SCANNING_FABRIC 3 -#define LOOP_FSCAN_DONE 4 -#define LOOP_SCANNING_LOOP 5 -#define LOOP_LSCAN_DONE 6 +#define LOOP_SCANNING_LOOP 3 +#define LOOP_LSCAN_DONE 4 +#define LOOP_SCANNING_FABRIC 5 +#define LOOP_FSCAN_DONE 6 #define LOOP_SYNCING_PDB 7 #define LOOP_READY 8 @@ -422,7 +440,7 @@ typedef struct { /* * Soft Structure per host adapter */ -typedef struct ispsoftc { +struct ispsoftc { /* * Platform (OS) specific data */ @@ -459,10 +477,12 @@ typedef struct ispsoftc { u_int32_t isp_confopts; /* config options */ - u_int16_t isp_rqstinrp; /* register for REQINP */ - u_int16_t isp_rqstoutrp; /* register for REQOUTP */ - u_int16_t isp_respinrp; /* register for RESINP */ - u_int16_t isp_respoutrp; /* register for RESOUTP */ + u_int32_t isp_rqstinrp; /* register for REQINP */ + u_int32_t isp_rqstoutrp; /* register for REQOUTP */ + u_int32_t isp_respinrp; /* register for RESINP */ + u_int32_t isp_respoutrp; /* register for RESOUTP */ + u_int32_t isp_atioinrp; /* register for ATIOINP */ + u_int32_t isp_atiooutrp; /* register for ATIOOUTP */ /* * Instrumentation @@ -480,24 +500,25 @@ typedef struct ispsoftc { * Volatile state */ - volatile u_int32_t - isp_obits : 8, /* mailbox command output */ + volatile u_int32_t : 8, isp_mboxbsy : 1, /* mailbox command active */ isp_state : 3, isp_sendmarker : 2, /* send a marker entry */ isp_update : 2, /* update parameters */ isp_nactive : 16; /* how many commands active */ - volatile u_int16_t isp_reqodx; /* index of last ISP pickup */ - volatile u_int16_t isp_reqidx; /* index of next request */ - volatile u_int16_t isp_residx; /* index of next result */ - volatile u_int16_t isp_resodx; /* index of next result */ - volatile u_int16_t isp_rspbsy; - volatile u_int16_t isp_lasthdls; /* last handle seed */ - volatile u_int16_t isp_mboxtmp[MAX_MAILBOX]; + volatile u_int32_t isp_reqodx; /* index of last ISP pickup */ + volatile u_int32_t isp_reqidx; /* index of next request */ + volatile u_int32_t isp_residx; /* index of next result */ + volatile u_int32_t isp_resodx; /* index of next result */ + volatile u_int32_t isp_rspbsy; + volatile u_int32_t isp_lasthdls; /* last handle seed */ + volatile u_int32_t isp_obits; /* mailbox command output */ + volatile u_int16_t isp_mboxtmp[MAILBOX_STORAGE]; volatile u_int16_t isp_lastmbxcmd; /* last mbox command sent */ volatile u_int16_t isp_mbxwrk0; volatile u_int16_t isp_mbxwrk1; volatile u_int16_t isp_mbxwrk2; + volatile u_int16_t isp_mbxwrk8; void * isp_mbxworkp; /* @@ -505,14 +526,26 @@ typedef struct ispsoftc { */ XS_T **isp_xflist; +#ifdef ISP_TARGET_MODE + /* + * Active target commands are stored here, indexed by handle function. + */ + void **isp_tgtlist; +#endif + /* - * request/result queue pointers and dma handles for them. + * request/result queue pointers and DMA handles for them. */ - caddr_t isp_rquest; - caddr_t isp_result; - isp_dma_addr_t isp_rquest_dma; - isp_dma_addr_t isp_result_dma; -} ispsoftc_t; + void * isp_rquest; + void * isp_result; + XS_DMA_ADDR_T isp_rquest_dma; + XS_DMA_ADDR_T isp_result_dma; +#ifdef ISP_TARGET_MODE + /* for 24XX only */ + void * isp_atioq; + XS_DMA_ADDR_T isp_atioq_dma; +#endif +}; #define SDPARAM(isp) ((sdparam *) (isp)->isp_param) #define FCPARAM(isp) ((fcparam *) (isp)->isp_param) @@ -521,9 +554,10 @@ typedef struct ispsoftc { * ISP Driver Run States */ #define ISP_NILSTATE 0 -#define ISP_RESETSTATE 1 -#define ISP_INITSTATE 2 -#define ISP_RUNSTATE 3 +#define ISP_CRASHED 1 +#define ISP_RESETSTATE 2 +#define ISP_INITSTATE 3 +#define ISP_RUNSTATE 4 /* * ISP Configuration Options @@ -567,8 +601,8 @@ typedef struct ispsoftc { * */ #define ISP_ROLE_NONE 0x0 -#define ISP_ROLE_INITIATOR 0x1 -#define ISP_ROLE_TARGET 0x2 +#define ISP_ROLE_TARGET 0x1 +#define ISP_ROLE_INITIATOR 0x2 #define ISP_ROLE_BOTH (ISP_ROLE_TARGET|ISP_ROLE_INITIATOR) #define ISP_ROLE_EITHER ISP_ROLE_BOTH #ifndef ISP_DEFAULT_ROLES @@ -649,7 +683,8 @@ typedef struct ispsoftc { #define IS_FC(isp) ((isp)->isp_type & ISP_HA_FC) #define IS_2100(isp) ((isp)->isp_type == ISP_HA_FC_2100) #define IS_2200(isp) ((isp)->isp_type == ISP_HA_FC_2200) -#define IS_23XX(isp) ((isp)->isp_type >= ISP_HA_FC_2300) +#define IS_23XX(isp) ((isp)->isp_type >= ISP_HA_FC_2300 && \ + (isp)->isp_type < ISP_HA_FC_2400) #define IS_2300(isp) ((isp)->isp_type == ISP_HA_FC_2300) #define IS_2312(isp) ((isp)->isp_type == ISP_HA_FC_2312) #define IS_2322(isp) ((isp)->isp_type == ISP_HA_FC_2322) @@ -658,15 +693,10 @@ typedef struct ispsoftc { /* * DMA related macros */ -#ifdef ISP_DAC_SUPPORTRED -#define DMA_WD3(x) (((x) >> 48) & 0xffff) -#define DMA_WD2(x) (((x) >> 32) & 0xffff) -#else -#define DMA_WD3(x) 0 -#define DMA_WD2(x) 0 -#endif -#define DMA_WD1(x) (((x) >> 16) & 0xffff) -#define DMA_WD0(x) (((x) & 0xffff)) +#define DMA_WD3(x) (((u_int16_t)(((u_int64_t)x) >> 48)) & 0xffff) +#define DMA_WD2(x) (((u_int16_t)(((u_int64_t)x) >> 32)) & 0xffff) +#define DMA_WD1(x) ((u_int16_t)((x) >> 16) & 0xffff) +#define DMA_WD0(x) ((u_int16_t)((x) & 0xffff)) #define DMA_LO32(x) ((u_int32_t) (x)) #define DMA_HI32(x) ((u_int32_t)(((u_int64_t)x) >> 32)) @@ -705,7 +735,7 @@ void isp_fw_dump(struct ispsoftc *isp); * semaphore register and first mailbox register (if appropriate). This also * means that most spurious/bogus interrupts not for us can be filtered first. */ -void isp_intr(struct ispsoftc *, u_int16_t, u_int16_t, u_int16_t); +void isp_intr(struct ispsoftc *, u_int32_t, u_int16_t, u_int16_t); /* @@ -768,9 +798,11 @@ typedef enum { ISPCTL_SCAN_LOOP, /* (Re)scan Local Loop */ ISPCTL_PDB_SYNC, /* Synchronize Port Database */ ISPCTL_SEND_LIP, /* Send a LIP */ - ISPCTL_GET_POSMAP, /* Get FC-AL position map */ + ISPCTL_GET_PORTNAME, /* get portname from an N-port handle */ ISPCTL_RUN_MBOXCMD, /* run a mailbox command */ - ISPCTL_TOGGLE_TMODE /* toggle target mode */ + ISPCTL_TOGGLE_TMODE, /* toggle target mode */ + ISPCTL_GET_PDB, /* get a single port database entry */ + ISPCTL_PLOGX /* do a port login/logout */ } ispctl_t; int isp_control(struct ispsoftc *, ispctl_t, void *); @@ -823,11 +855,12 @@ typedef enum { ISPASYNC_LIP, /* LIP Received */ ISPASYNC_LOOP_RESET, /* Loop Reset Received */ ISPASYNC_CHANGE_NOTIFY, /* FC Change Notification */ - ISPASYNC_FABRIC_DEV, /* FC Fabric Device Arrival */ - ISPASYNC_PROMENADE, /* FC Objects coming && going */ - ISPASYNC_TARGET_MESSAGE, /* target message */ - ISPASYNC_TARGET_EVENT, /* target asynchronous event */ - ISPASYNC_TARGET_ACTION, /* other target command action */ + ISPASYNC_DEV_ARRIVED, /* FC Device Arrival */ + ISPASYNC_DEV_CHANGED, /* FC Device Change */ + ISPASYNC_DEV_STAYED, /* FC Device Stayed the Same */ + ISPASYNC_DEV_GONE, /* FC Device Depart */ + ISPASYNC_TARGET_NOTIFY, /* target asynchronous notification event */ + ISPASYNC_TARGET_ACTION, /* target action requested */ ISPASYNC_CONF_CHANGE, /* Platform Configuration Change */ ISPASYNC_UNHANDLED_RESPONSE, /* Unhandled Response Entry */ ISPASYNC_FW_CRASH, /* Firmware has crashed */ @@ -850,12 +883,6 @@ int isp_async(struct ispsoftc *, ispasync_t, void *); * but due to compiler differences on different platforms this won't be * formally done here. Instead, it goes in each platform definition file. */ -#ifdef __GNUC__ -void isp_prt(struct ispsoftc *, int level, const char *, ...) - __attribute__((__format__(__printf__,3,4))); -#else -void isp_prt(struct ispsoftc *, int level, const char *, ...); -#endif #define ISP_LOGALL 0x0 /* log always */ #define ISP_LOGCONFIG 0x1 /* log configuration messages */ @@ -866,7 +893,7 @@ void isp_prt(struct ispsoftc *, int level, const char *, ...); #define ISP_LOGDEBUG1 0x20 /* log intermediate debug messages */ #define ISP_LOGDEBUG2 0x40 /* log most debug messages */ #define ISP_LOGDEBUG3 0x80 /* log high frequency debug messages */ -#define ISP_LOGDEBUG4 0x100 /* log high frequency debug messages */ +#define ISP_LOGSANCFG 0x100 /* log SAN configuration */ #define ISP_LOGTDEBUG0 0x200 /* log simple debug messages (target mode) */ #define ISP_LOGTDEBUG1 0x400 /* log intermediate debug messages (target) */ #define ISP_LOGTDEBUG2 0x800 /* log all debug messages (target) */ @@ -906,7 +933,7 @@ void isp_prt(struct ispsoftc *, int level, const char *, ...); * of the same object is consistent. * * MBOX_ACQUIRE(struct ispsoftc *) acquire lock on mailbox regs - * MBOX_WAIT_COMPLETE(struct ispsoftc *) wait for mailbox cmd to be done + * MBOX_WAIT_COMPLETE(struct ispsoftc *, mbreg_t *) wait for cmd to be done * MBOX_NOTIFY_COMPLETE(struct ispsoftc *) notification of mbox cmd donee * MBOX_RELEASE(struct ispsoftc *) release lock on mailbox regs * @@ -919,6 +946,7 @@ void isp_prt(struct ispsoftc *, int level, const char *, ...); * SCSI_QFULL SCSI 'Queue Full' Status * * XS_T Platform SCSI transaction type (i.e., command for HBA) + * XS_DMA_ADDR_T Platform PCI DMA Address Type * XS_ISP(xs) gets an instance out of an XS_T * XS_CHANNEL(xs) gets the channel (bus # for DUALBUS cards) "" * XS_TGT(xs) gets the target "" @@ -950,17 +978,17 @@ void isp_prt(struct ispsoftc *, int level, const char *, ...); * XS_NOERR(xs) there is no error currently set * XS_INITERR(xs) initialize error state * - * XS_SAVE_SENSE(xs, sp) save sense data + * XS_SAVE_SENSE(xs, sp, len) save sense data * * XS_SET_STATE_STAT(isp, sp, xs) platform dependent interpreter of * response queue entry status bits * * * DEFAULT_IID(struct ispsoftc *) Default SCSI initiator ID - * DEFAULT_LOOPID(struct ispsoftc *) Default FC Loop ID - * DEFAULT_NODEWWN(struct ispsoftc *) Default Node WWN - * DEFAULT_PORTWWN(struct ispsoftc *) Default Port WWN - * DEFAULT_FRAMESIZE(struct ispsoftc *) Default Frame Size + * DEFAULT_LOOPID(struct ispsoftc *) Default FC Loop ID + * DEFAULT_NODEWWN(struct ispsoftc *) Default Node WWN + * DEFAULT_PORTWWN(struct ispsoftc *) Default Port WWN + * DEFAULT_FRAMESIZE(struct ispsoftc *) Default Frame Size * DEFAULT_EXEC_THROTTLE(struct ispsoftc *) Default Execution Throttle * These establish reasonable defaults for each platform. * These must be available independent of card NVRAM and are @@ -970,7 +998,7 @@ void isp_prt(struct ispsoftc *, int level, const char *, ...); * ISP_PORTWWN(struct ispsoftc *) FC Port WWN to use * * These are to be used after NVRAM is read. The tags - * in fcparam.isp_{node,port}wwn reflect the values + * in fcparam.isp_ww{n,p}n_nvram reflect the values * read from NVRAM (possibly corrected for card botches). * Each platform can take that information and override * it or ignore and return the Node and Port WWNs to be diff --git a/sys/dev/pci/isp_pci.c b/sys/dev/pci/isp_pci.c index 3f12d0a40cd..a0caffdc95c 100644 --- a/sys/dev/pci/isp_pci.c +++ b/sys/dev/pci/isp_pci.c @@ -1,12 +1,8 @@ -/* $OpenBSD: isp_pci.c,v 1.46 2009/05/31 17:42:13 miod Exp $ */ -/* - * PCI specific probe and attach routines for QLogic ISP SCSI adapters. - * - *--------------------------------------- - * Copyright (c) 1997, 1998, 1999 by Matthew Jacob - * NASA/Ames Research Center +/* $OpenBSD: isp_pci.c,v 1.47 2009/06/24 11:00:53 krw Exp $ */ +/* $FreeBSD: src/sys/dev/isp/isp_pci.c,v 1.148 2007/06/26 23:08:57 mjacob Exp $*/ +/*- + * Copyright (c) 1997-2006 by Matthew Jacob * All rights reserved. - *--------------------------------------- * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -14,10 +10,7 @@ * 1. Redistributions of source code must retain the above copyright * notice immediately at the beginning of the file, without modification, * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products + * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND @@ -31,7 +24,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + */ +/* + * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. + * FreeBSD Version. */ #include <dev/ic/isp_openbsd.h> @@ -48,79 +44,36 @@ #include <mips64/archtype.h> #endif -static u_int16_t isp_pci_rd_reg(struct ispsoftc *, int); -static void isp_pci_wr_reg(struct ispsoftc *, int, u_int16_t); -#if !(defined(ISP_DISABLE_1080_SUPPORT) && defined(ISP_DISABLE_12160_SUPPORT)) -static u_int16_t isp_pci_rd_reg_1080(struct ispsoftc *, int); -static void isp_pci_wr_reg_1080(struct ispsoftc *, int, u_int16_t); -#endif -static int -isp_pci_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); -#ifndef ISP_DISABLE_2300_SUPPORT -static int -isp_pci_rd_isr_2300(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); -#endif -static int isp_pci_mbxdma(struct ispsoftc *); -static int isp_pci_dmasetup(struct ispsoftc *, struct scsi_xfer *, - ispreq_t *, u_int16_t *, u_int16_t); -static void -isp_pci_dmateardown (struct ispsoftc *, struct scsi_xfer *, u_int16_t); -static void isp_pci_reset1 (struct ispsoftc *); -static void isp_pci_dumpregs (struct ispsoftc *, const char *); -static int isp_pci_intr (void *); - -#ifdef ISP_COMPILE_FW -#define ISP_COMPILE_1040_FW 1 -#define ISP_COMPILE_1080_FW 1 -#define ISP_COMPILE_12160_FW 1 -#define ISP_COMPILE_2100_FW 1 -#define ISP_COMPILE_2200_FW 1 -#define ISP_COMPILE_2300_FW 1 -#endif - -#if defined(ISP_DISABLE_1040_SUPPORT) || !defined(ISP_COMPILE_1040_FW) -#define ISP_1040_RISC_CODE NULL -#else -#define ISP_1040_RISC_CODE (u_int16_t *) isp_1040_risc_code #include <dev/microcode/isp/asm_1040.h> -#endif - -#if defined(ISP_DISABLE_1080_SUPPORT) || !defined(ISP_COMPILE_1080_FW) -#define ISP_1080_RISC_CODE NULL -#else -#define ISP_1080_RISC_CODE (u_int16_t *) isp_1080_risc_code #include <dev/microcode/isp/asm_1080.h> -#endif - -#if defined(ISP_DISABLE_12160_SUPPORT) || !defined(ISP_COMPILE_12160_FW) -#define ISP_12160_RISC_CODE (u_int16_t *) NULL -#else -#define ISP_12160_RISC_CODE (u_int16_t *) isp_12160_risc_code #include <dev/microcode/isp/asm_12160.h> -#endif - -#if defined(ISP_DISABLE_2100_SUPPORT) || !defined(ISP_COMPILE_2100_FW) -#define ISP_2100_RISC_CODE NULL -#else -#define ISP_2100_RISC_CODE (u_int16_t *) isp_2100_risc_code #include <dev/microcode/isp/asm_2100.h> -#endif - -#if defined(ISP_DISABLE_2200_SUPPORT) || !defined(ISP_COMPILE_2200_FW) -#define ISP_2200_RISC_CODE NULL -#else -#define ISP_2200_RISC_CODE (u_int16_t *) isp_2200_risc_code #include <dev/microcode/isp/asm_2200.h> -#endif - -#if defined(ISP_DISABLE_2300_SUPPORT) || !defined(ISP_COMPILE_2300_FW) -#define ISP_2300_RISC_CODE NULL -#else -#define ISP_2300_RISC_CODE (u_int16_t *) isp_2300_risc_code #include <dev/microcode/isp/asm_2300.h> -#endif +#include <dev/microcode/isp/asm_2400.h> + +#define BUS_PROBE_DEFAULT 0 + +uint32_t isp_pci_rd_reg(ispsoftc_t *, int); +void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t); +uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int); +void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t); +uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int); +void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t); +int isp_pci_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); +int isp_pci_rd_isr_2300(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); +int isp_pci_rd_isr_2400(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); +int isp_pci_mbxdma(ispsoftc_t *); +int isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t); +void isp_pci_reset0(ispsoftc_t *); +void isp_pci_reset1(ispsoftc_t *); +void isp_pci_dumpregs(ispsoftc_t *, const char *); + + +int isp_pci_rd_debounced(struct ispsoftc *, int, u_int16_t *); +int isp_pci_intr (void *); +void isp_pci_dmateardown(struct ispsoftc *, XS_T *, u_int32_t); -#ifndef ISP_DISABLE_1020_SUPPORT static struct ispmdvec mdvec = { isp_pci_rd_isr, isp_pci_rd_reg, @@ -128,15 +81,13 @@ static struct ispmdvec mdvec = { isp_pci_mbxdma, isp_pci_dmasetup, isp_pci_dmateardown, - NULL, + isp_pci_reset0, isp_pci_reset1, isp_pci_dumpregs, - ISP_1040_RISC_CODE, + NULL, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 }; -#endif -#ifndef ISP_DISABLE_1080_SUPPORT static struct ispmdvec mdvec_1080 = { isp_pci_rd_isr, isp_pci_rd_reg_1080, @@ -144,15 +95,13 @@ static struct ispmdvec mdvec_1080 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_pci_dmateardown, - NULL, + isp_pci_reset0, isp_pci_reset1, isp_pci_dumpregs, - ISP_1080_RISC_CODE, + isp_1080_risc_code, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 }; -#endif -#ifndef ISP_DISABLE_12160_SUPPORT static struct ispmdvec mdvec_12160 = { isp_pci_rd_isr, isp_pci_rd_reg_1080, @@ -160,15 +109,13 @@ static struct ispmdvec mdvec_12160 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_pci_dmateardown, - NULL, + isp_pci_reset0, isp_pci_reset1, isp_pci_dumpregs, - ISP_12160_RISC_CODE, + isp_12160_risc_code, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 }; -#endif -#ifndef ISP_DISABLE_2100_SUPPORT static struct ispmdvec mdvec_2100 = { isp_pci_rd_isr, isp_pci_rd_reg, @@ -176,14 +123,12 @@ static struct ispmdvec mdvec_2100 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_pci_dmateardown, - NULL, + isp_pci_reset0, isp_pci_reset1, isp_pci_dumpregs, - ISP_2100_RISC_CODE + isp_2100_risc_code }; -#endif -#ifndef ISP_DISABLE_2200_SUPPORT static struct ispmdvec mdvec_2200 = { isp_pci_rd_isr, isp_pci_rd_reg, @@ -191,14 +136,12 @@ static struct ispmdvec mdvec_2200 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_pci_dmateardown, - NULL, + isp_pci_reset0, isp_pci_reset1, isp_pci_dumpregs, - ISP_2200_RISC_CODE + isp_2200_risc_code }; -#endif -#ifndef ISP_DISABLE_2300_SUPPORT static struct ispmdvec mdvec_2300 = { isp_pci_rd_isr_2300, isp_pci_rd_reg, @@ -206,15 +149,58 @@ static struct ispmdvec mdvec_2300 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_pci_dmateardown, - NULL, + isp_pci_reset0, isp_pci_reset1, isp_pci_dumpregs, - ISP_2300_RISC_CODE + isp_2300_risc_code +}; + +static struct ispmdvec mdvec_2400 = { + isp_pci_rd_isr_2400, + isp_pci_rd_reg_2400, + isp_pci_wr_reg_2400, + isp_pci_mbxdma, + isp_pci_dmasetup, + isp_pci_dmateardown, + isp_pci_reset0, + isp_pci_reset1, + NULL }; + +#ifndef PCIM_CMD_INVEN +#define PCIM_CMD_INVEN 0x10 +#endif +#ifndef PCIM_CMD_BUSMASTEREN +#define PCIM_CMD_BUSMASTEREN 0x0004 +#endif +#ifndef PCIM_CMD_PERRESPEN +#define PCIM_CMD_PERRESPEN 0x0040 +#endif +#ifndef PCIM_CMD_SEREN +#define PCIM_CMD_SEREN 0x0100 +#endif +#ifndef PCIM_CMD_INTX_DISABLE +#define PCIM_CMD_INTX_DISABLE 0x0400 +#endif + +#ifndef PCIR_COMMAND +#define PCIR_COMMAND 0x04 +#endif + +#ifndef PCIR_CACHELNSZ +#define PCIR_CACHELNSZ 0x0c +#endif + +#ifndef PCIR_LATTIMER +#define PCIR_LATTIMER 0x0d +#endif + +#ifndef PCIR_ROMADDR +#define PCIR_ROMADDR 0x30 #endif #ifndef PCI_VENDOR_QLOGIC -#define PCI_VENDOR_QLOGIC 0x1077 +#define PCI_VENDOR_QLOGIC 0x1077 #endif #ifndef PCI_PRODUCT_QLOGIC_ISP1020 @@ -225,14 +211,6 @@ static struct ispmdvec mdvec_2300 = { #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 #endif -#ifndef PCI_PRODUCT_QLOGIC_ISP1240 -#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 -#endif - -#ifndef PCI_PRODUCT_QLOGIC_ISP1280 -#define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 -#endif - #ifndef PCI_PRODUCT_QLOGIC_ISP10160 #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016 #endif @@ -241,6 +219,14 @@ static struct ispmdvec mdvec_2300 = { #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 #endif +#ifndef PCI_PRODUCT_QLOGIC_ISP1240 +#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 +#endif + +#ifndef PCI_PRODUCT_QLOGIC_ISP1280 +#define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 +#endif + #ifndef PCI_PRODUCT_QLOGIC_ISP2100 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 #endif @@ -257,20 +243,32 @@ static struct ispmdvec mdvec_2300 = { #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 #endif +#ifndef PCI_PRODUCT_QLOGIC_ISP2322 +#define PCI_PRODUCT_QLOGIC_ISP2322 0x2322 +#endif + +#ifndef PCI_PRODUCT_QLOGIC_ISP2422 +#define PCI_PRODUCT_QLOGIC_ISP2422 0x2422 +#endif + +#ifndef PCI_PRODUCT_QLOGIC_ISP2432 +#define PCI_PRODUCT_QLOGIC_ISP2432 0x2432 +#endif + #ifndef PCI_PRODUCT_QLOGIC_ISP6312 #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312 #endif -#define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) +#ifndef PCI_PRODUCT_QLOGIC_ISP6322 +#define PCI_PRODUCT_QLOGIC_ISP6322 0x6322 +#endif -#define PCI_QLOGIC_ISP1080 \ - ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) -#define PCI_QLOGIC_ISP1240 \ - ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) +#define PCI_QLOGIC_ISP1020 \ + ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) -#define PCI_QLOGIC_ISP1280 \ - ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) +#define PCI_QLOGIC_ISP1080 \ + ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) #define PCI_QLOGIC_ISP10160 \ ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC) @@ -278,6 +276,12 @@ static struct ispmdvec mdvec_2300 = { #define PCI_QLOGIC_ISP12160 \ ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC) +#define PCI_QLOGIC_ISP1240 \ + ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) + +#define PCI_QLOGIC_ISP1280 \ + ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) + #define PCI_QLOGIC_ISP2100 \ ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) @@ -290,18 +294,28 @@ static struct ispmdvec mdvec_2300 = { #define PCI_QLOGIC_ISP2312 \ ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) +#define PCI_QLOGIC_ISP2322 \ + ((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC) + +#define PCI_QLOGIC_ISP2422 \ + ((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC) + +#define PCI_QLOGIC_ISP2432 \ + ((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC) + #define PCI_QLOGIC_ISP6312 \ ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC) +#define PCI_QLOGIC_ISP6322 \ + ((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC) + /* * Odd case for some AMI raid cards... We need to *not* attach to this. */ #define AMI_RAID_SUBVENDOR_ID 0x101e - -#define IO_MAP_REG 0x10 -#define MEM_MAP_REG 0x14 -#define PCIR_ROMADDR 0x30 +#define IO_MAP_REG 0x10 +#define MEM_MAP_REG 0x14 #define PCI_DFLT_LTNCY 0x40 #define PCI_DFLT_LNSZ 0x10 @@ -314,9 +328,29 @@ static struct ispmdvec mdvec_2300 = { #endif #endif -static int isp_pci_probe (struct device *, void *, void *); -static void isp_pci_attach (struct device *, struct device *, void *); +const struct pci_matchid ispdev[] = { + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1020 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1080 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1240 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1280 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP10160 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP12160 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2100 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2200 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2300 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2312 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2322 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2422 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2432 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP6312 }, + { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP6322 }, + { 0, 0 } +}; + +int isp_pci_probe (struct device *, void *, void *); +void isp_pci_attach (struct device *, struct device *, void *); +#define ISP_PCD(isp) ((struct isp_pcisoftc *)isp)->pci_dev struct isp_pcisoftc { struct ispsoftc pci_isp; pci_chipset_tag_t pci_pc; @@ -332,39 +366,7 @@ struct cfattach isp_pci_ca = { sizeof (struct isp_pcisoftc), isp_pci_probe, isp_pci_attach }; -#ifdef DEBUG -const char vstring[] = - "QLogic ISP Driver, NetBSD (pci) Platform Version %d.%d Core Version %d.%d"; -#endif - -const struct pci_matchid ispdev[] = { -#ifndef ISP_DISABLE_1020_SUPPORT - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1020 }, -#endif -#ifndef ISP_DISABLE_1080_SUPPORT - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1080 }, - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1240 }, - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1280 }, -#endif -#ifndef ISP_DISABLE_12160_SUPPORT - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP10160 }, - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP12160 }, -#endif -#ifndef ISP_DISABLE_2100_SUPPORT - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2100 }, -#endif -#ifndef ISP_DISABLE_2200_SUPPORT - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2200 }, -#endif -#ifndef ISP_DISABLE_2300_SUPPORT - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2300 }, - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2312 }, - { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP6312 }, -#endif - { 0, 0 } -}; - -static int +int isp_pci_probe(struct device *parent, void *match, void *aux) { struct pci_attach_args *pa = aux; @@ -386,7 +388,7 @@ isp_pci_probe(struct device *parent, void *match, void *aux) } -static void +void isp_pci_attach(struct device *parent, struct device *self, void *aux) { #ifdef DEBUG @@ -395,7 +397,7 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) static const char nomem[] = ": no mem for sdparam table\n"; u_int32_t data, rev, linesz = PCI_DFLT_LNSZ; struct pci_attach_args *pa = aux; - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) self; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)self; struct ispsoftc *isp = &pcs->pci_isp; bus_space_tag_t st, iot, memt; bus_space_handle_t sh, ioh, memh; @@ -487,8 +489,8 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) printf("\n"); #endif - pcs->pci_st = st; - pcs->pci_sh = sh; + pcs->pci_st = isp->isp_bus_tag = st; + pcs->pci_sh = isp->isp_bus_handle = sh; pcs->pci_pc = pa->pa_pc; pcs->pci_tag = pa->pa_tag; pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; @@ -497,8 +499,7 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0xff; -#ifndef ISP_DISABLE_1020_SUPPORT - if (pa->pa_id == PCI_QLOGIC_ISP) { + if (pa->pa_id == PCI_QLOGIC_ISP1020) { isp->isp_mdvec = &mdvec; isp->isp_type = ISP_HA_SCSI_UNKNOWN; isp->isp_param = malloc(sizeof(sdparam), M_DEVBUF, @@ -508,8 +509,6 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) return; } } -#endif -#ifndef ISP_DISABLE_1080_SUPPORT if (pa->pa_id == PCI_QLOGIC_ISP1080) { isp->isp_mdvec = &mdvec_1080; isp->isp_type = ISP_HA_SCSI_1080; @@ -546,8 +545,6 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; } -#endif -#ifndef ISP_DISABLE_12160_SUPPORT if (pa->pa_id == PCI_QLOGIC_ISP10160) { isp->isp_mdvec = &mdvec_12160; isp->isp_type = ISP_HA_SCSI_10160; @@ -572,8 +569,6 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; } -#endif -#ifndef ISP_DISABLE_2100_SUPPORT if (pa->pa_id == PCI_QLOGIC_ISP2100) { isp->isp_mdvec = &mdvec_2100; isp->isp_type = ISP_HA_FC_2100; @@ -595,8 +590,6 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) linesz = 1; } } -#endif -#ifndef ISP_DISABLE_2200_SUPPORT if (pa->pa_id == PCI_QLOGIC_ISP2200) { isp->isp_mdvec = &mdvec_2200; isp->isp_type = ISP_HA_FC_2200; @@ -621,18 +614,38 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) } #endif } -#endif -#ifndef ISP_DISABLE_2300_SUPPORT - if (pa->pa_id == PCI_QLOGIC_ISP2300 || - pa->pa_id == PCI_QLOGIC_ISP2312 || + if (pa->pa_id == PCI_QLOGIC_ISP2300) { + isp->isp_mdvec = &mdvec_2300; + isp->isp_type = ISP_HA_FC_2300; + isp->isp_param = malloc(sizeof(fcparam), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (isp->isp_param == NULL) { + printf(nomem); + return; + } + pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = + PCI_MBOX_REGS2300_OFF; + } + if (pa->pa_id == PCI_QLOGIC_ISP2312 || pa->pa_id == PCI_QLOGIC_ISP6312) { isp->isp_mdvec = &mdvec_2300; - if (pa->pa_id == PCI_QLOGIC_ISP2300) { - isp->isp_type = ISP_HA_FC_2300; - } else { - isp->isp_type = ISP_HA_FC_2312; - isp->isp_port = pa->pa_function; + isp->isp_type = ISP_HA_FC_2312; + isp->isp_port = pa->pa_function; + isp->isp_param = malloc(sizeof(fcparam), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (isp->isp_param == NULL) { + printf(nomem); + return; } + pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = + PCI_MBOX_REGS2300_OFF; + data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG); + } + if (pa->pa_id == PCI_QLOGIC_ISP2322 || + pa->pa_id == PCI_QLOGIC_ISP6322) { + isp->isp_mdvec = &mdvec_2300; + isp->isp_type = ISP_HA_FC_2322; + isp->isp_port = pa->pa_function; isp->isp_param = malloc(sizeof(fcparam), M_DEVBUF, M_NOWAIT | M_ZERO); if (isp->isp_param == NULL) { @@ -643,7 +656,20 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) PCI_MBOX_REGS2300_OFF; data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG); } -#endif + if (pa->pa_id == PCI_QLOGIC_ISP2422 || + pa->pa_id == PCI_QLOGIC_ISP2432) { + isp->isp_mdvec = &mdvec_2400; + isp->isp_type = ISP_HA_FC_2400; + isp->isp_port = pa->pa_function; + isp->isp_param = malloc(sizeof(fcparam), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (isp->isp_param == NULL) { + printf(nomem); + return; + } + pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = + PCI_MBOX_REGS2400_OFF; + } /* * Set up logging levels. */ @@ -739,7 +765,7 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) free(isp->isp_param, M_DEVBUF); return; } - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { isp_uninit(isp); @@ -762,19 +788,22 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) #define IspVirt2Off(a, x) \ (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ - _BLK_REG_SHFT] + ((x) & 0xff)) + _BLK_REG_SHFT] + ((x) & 0xfff)) #define BXR2(pcs, off) \ bus_space_read_2(pcs->pci_st, pcs->pci_sh, off) #define BXW2(pcs, off, v) \ bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v) +#define BXR4(pcs, off) \ + bus_space_read_4(pcs->pci_st, pcs->pci_sh, off) +#define BXW4(pcs, off, v) \ + bus_space_write_4(pcs->pci_st, pcs->pci_sh, off, v) - -static INLINE int +int isp_pci_rd_debounced(struct ispsoftc *isp, int off, u_int16_t *rp) { - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - u_int16_t val0, val1; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; + u_int32_t val0, val1; int i = 0; do { @@ -788,11 +817,11 @@ isp_pci_rd_debounced(struct ispsoftc *isp, int off, u_int16_t *rp) return (0); } -static int -isp_pci_rd_isr(struct ispsoftc *isp, u_int16_t *isrp, +int +isp_pci_rd_isr(struct ispsoftc *isp, u_int32_t *isrp, u_int16_t *semap, u_int16_t *mbp) { - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; u_int16_t isr, sema; if (IS_2100(isp)) { @@ -825,20 +854,19 @@ isp_pci_rd_isr(struct ispsoftc *isp, u_int16_t *isrp, return (1); } -#ifndef ISP_DISABLE_2300_SUPPORT -static int -isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int16_t *isrp, +int +isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int32_t *isrp, u_int16_t *semap, u_int16_t *mbox0p) { - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; + u_int32_t hccr; u_int32_t r2hisr; if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR)) & BIU2100_ISR_RISC_INT)) { *isrp = 0; return (0); } - r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh, - IspVirt2Off(pcs, BIU_R2HSTSLO)); + r2hisr = BXR4(pcs, IspVirt2Off(isp, BIU_R2HSTSLO)); isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); if ((r2hisr & BIU_R2HST_INTR) == 0) { *isrp = 0; @@ -875,16 +903,26 @@ isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int16_t *isrp, *semap = 0; return (1); default: + hccr = ISP_READ(isp, HCCR); + if (hccr & HCCR_PAUSE) { + ISP_WRITE(isp, HCCR, HCCR_RESET); + isp_prt(isp, ISP_LOGERR, + "RISC paused at interrupt (%x->%x)", hccr, + ISP_READ(isp, HCCR)); + ISP_WRITE(isp, BIU_ICR, 0); + } else { + isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", + r2hisr); + } return (0); } } -#endif -static u_int16_t +u_int32_t isp_pci_rd_reg(struct ispsoftc *isp, int regoff) { u_int16_t rv; - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; int oldconf = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { @@ -894,18 +932,57 @@ isp_pci_rd_reg(struct ispsoftc *isp, int regoff) oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } rv = BXR2(pcs, IspVirt2Off(isp, regoff)); if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); } + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); return (rv); } -static void -isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val) +int +isp_pci_rd_isr_2400(ispsoftc_t *isp, uint32_t *isrp, + uint16_t *semap, uint16_t *mbox0p) { - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; + uint32_t r2hisr; + + r2hisr = BXR4(pcs, IspVirt2Off(isp, BIU2400_R2HSTSLO)); + isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); + if ((r2hisr & BIU2400_R2HST_INTR) == 0) { + *isrp = 0; + return (0); + } + switch (r2hisr & BIU2400_R2HST_ISTAT_MASK) { + case ISP2400R2HST_ROM_MBX_OK: + case ISP2400R2HST_ROM_MBX_FAIL: + case ISP2400R2HST_MBX_OK: + case ISP2400R2HST_MBX_FAIL: + case ISP2400R2HST_ASYNC_EVENT: + *isrp = r2hisr & 0xffff; + *mbox0p = (r2hisr >> 16); + *semap = 1; + return (1); + case ISP2400R2HST_RSPQ_UPDATE: + case ISP2400R2HST_ATIO_RSPQ_UPDATE: + case ISP2400R2HST_ATIO_RQST_UPDATE: + *isrp = r2hisr & 0xffff; + *mbox0p = 0; + *semap = 0; + return (1); + default: + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); + isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); + return (0); + } +} + +void +isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int32_t val) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; int oldconf = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { @@ -915,23 +992,26 @@ isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val) oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } BXW2(pcs, IspVirt2Off(isp, regoff), val); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2); if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } + } -#if !(defined(ISP_DISABLE_1080_SUPPORT) && defined(ISP_DISABLE_12160_SUPPORT)) -static u_int16_t +u_int32_t isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff) { - u_int16_t rv, oc = 0; - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; + u_int32_t rv, oc = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { - u_int16_t tc; + u_int32_t tc; /* * We will assume that someone has paused the RISC processor. */ @@ -942,27 +1022,30 @@ isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff) else tc |= BIU_PCI1080_CONF1_SXP0; BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc | BIU_PCI1080_CONF1_DMA); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } rv = BXR2(pcs, IspVirt2Off(isp, regoff)); if (oc) { BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } return (rv); } -static void -isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val) +void +isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int32_t val) { - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; int oc = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { - u_int16_t tc; + u_int32_t tc; /* * We will assume that someone has paused the RISC processor. */ @@ -973,26 +1056,155 @@ isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val) else tc |= BIU_PCI1080_CONF1_SXP0; BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc | BIU_PCI1080_CONF1_DMA); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } BXW2(pcs, IspVirt2Off(isp, regoff), val); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2); if (oc) { BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); } } -#endif -static int +uint32_t +isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; + uint32_t rv; + int block = regoff & _BLK_REG_MASK; + + switch (block) { + case BIU_BLOCK: + break; + case MBOX_BLOCK: + return (BXR2(pcs, IspVirt2Off(isp, regoff))); + case SXP_BLOCK: + isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff); + return (0xffffffff); + case RISC_BLOCK: + isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff); + return (0xffffffff); + case DMA_BLOCK: + isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff); + return (0xffffffff); + default: + isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff); + return (0xffffffff); + } + + + switch (regoff) { + case BIU2400_FLASH_ADDR: + case BIU2400_FLASH_DATA: + case BIU2400_ICR: + case BIU2400_ISR: + case BIU2400_CSR: + case BIU2400_REQINP: + case BIU2400_REQOUTP: + case BIU2400_RSPINP: + case BIU2400_RSPOUTP: + case BIU2400_PRI_RQINP: + case BIU2400_PRI_RSPINP: + case BIU2400_ATIO_RSPINP: + case BIU2400_ATIO_REQINP: + case BIU2400_HCCR: + case BIU2400_GPIOD: + case BIU2400_GPIOE: + case BIU2400_HSEMA: + rv = BXR4(pcs, IspVirt2Off(isp, regoff)); + break; + case BIU2400_R2HSTSLO: + rv = BXR4(pcs, IspVirt2Off(isp, regoff)); + break; + case BIU2400_R2HSTSHI: + rv = BXR4(pcs, IspVirt2Off(isp, regoff)) >> 16; + break; + default: + isp_prt(isp, ISP_LOGERR, + "isp_pci_rd_reg_2400: unknown offset %x", regoff); + rv = 0xffffffff; + break; + } + return (rv); +} + +void +isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; + int block = regoff & _BLK_REG_MASK; + + switch (block) { + case BIU_BLOCK: + break; + case MBOX_BLOCK: + BXW2(pcs, IspVirt2Off(isp, regoff), val); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2); + return; + case SXP_BLOCK: + isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff); + return; + case RISC_BLOCK: + isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff); + return; + case DMA_BLOCK: + isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff); + return; + default: + isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x", + regoff); + break; + } + + switch (regoff) { + case BIU2400_FLASH_ADDR: + case BIU2400_FLASH_DATA: + case BIU2400_ICR: + case BIU2400_ISR: + case BIU2400_CSR: + case BIU2400_REQINP: + case BIU2400_REQOUTP: + case BIU2400_RSPINP: + case BIU2400_RSPOUTP: + case BIU2400_PRI_RQINP: + case BIU2400_PRI_RSPINP: + case BIU2400_ATIO_RSPINP: + case BIU2400_ATIO_REQINP: + case BIU2400_HCCR: + case BIU2400_GPIOD: + case BIU2400_GPIOE: + case BIU2400_HSEMA: + BXW4(pcs, IspVirt2Off(isp, regoff), val); + MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 4); + break; + default: + isp_prt(isp, ISP_LOGERR, + "isp_pci_wr_reg_2400: bad offset 0x%x", regoff); + break; + } +} + + +struct imush { + ispsoftc_t *isp; + int error; +}; + + +int isp_pci_mbxdma(struct ispsoftc *isp) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; bus_dma_tag_t dmat = isp->isp_dmatag; bus_dma_segment_t sg; + bus_addr_t addr; bus_size_t len; - fcparam *fcp; + caddr_t base; int rs, i; if (isp->isp_rquest_dma) /* been here before? */ @@ -1033,62 +1245,48 @@ isp_pci_mbxdma(struct ispsoftc *isp) } /* - * Allocate and map the request queue. + * Allocate and map the request, result queues, plus FC scratch area. */ len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); + len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); + if (IS_FC(isp)) { + len += ISP2100_SCRLEN; + } + if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs, BUS_DMA_NOWAIT) || bus_dmamem_map(isp->isp_dmatag, &sg, rs, len, - (caddr_t *)&isp->isp_rquest, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { + &base, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { goto dmafail; } if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT, - &isp->isp_rqdmap) || bus_dmamap_load(dmat, isp->isp_rqdmap, - (caddr_t)isp->isp_rquest, len, NULL, + &isp->isp_cdmap) || bus_dmamap_load(dmat, isp->isp_cdmap, + base, len, NULL, BUS_DMA_NOWAIT)) { goto dmafail; } - isp->isp_rquest_dma = isp->isp_rqdmap->dm_segs[0].ds_addr; - /* - * Allocate and map the result queue. - */ - len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); - if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs, - BUS_DMA_NOWAIT) || - bus_dmamem_map(dmat, &sg, rs, len, (caddr_t *)&isp->isp_result, - BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { - goto dmafail; - } - if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT, - &isp->isp_rsdmap) || bus_dmamap_load(isp->isp_dmatag, - isp->isp_rsdmap, (caddr_t)isp->isp_result, len, NULL, - BUS_DMA_NOWAIT)) { - goto dmafail; - } - isp->isp_result_dma = isp->isp_rsdmap->dm_segs[0].ds_addr; + addr = isp->isp_cdmap->dm_segs[0].ds_addr; + isp->isp_rquest_dma = addr; + addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); + isp->isp_result_dma = addr; - if (IS_SCSI(isp)) { - return (0); - } + if (IS_FC(isp)) { + addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); + FCPARAM(isp)->isp_scdma = addr; - fcp = isp->isp_param; - len = ISP2100_SCRLEN; - if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs, - BUS_DMA_NOWAIT) || - bus_dmamem_map(dmat, &sg, rs, len, (caddr_t *)&fcp->isp_scratch, - BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { - goto dmafail; } - if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT, - &isp->isp_scdmap) || bus_dmamap_load(dmat, - isp->isp_scdmap, (caddr_t)fcp->isp_scratch, len, NULL, - BUS_DMA_NOWAIT)) { - goto dmafail; + + isp->isp_rquest = base; + base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); + isp->isp_result = base; + if (IS_FC(isp)) { + base += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); + FCPARAM(isp)->isp_scratch = base; } - fcp->isp_scdma = isp->isp_scdmap->dm_segs[0].ds_addr; return (0); + dmafail: isp_prt(isp, ISP_LOGERR, "mailbox dma setup failure"); for (i = 0; i < isp->isp_maxcmds; i++) { @@ -1101,17 +1299,17 @@ dmafail: return (1); } -static int +int isp_pci_dmasetup(struct ispsoftc *isp, XS_T *xs, ispreq_t *rq, - u_int16_t *nxtip, u_int16_t optr) + u_int32_t *nxtip, u_int32_t optr) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; bus_dmamap_t dmap; - u_int16_t starti = isp->isp_reqidx, nxti = *nxtip; + u_int16_t nxti = *nxtip; ispreq_t *qep; int segcnt, seg, error, ovseg, seglim, drq; - qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, starti); + qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx); dmap = pcs->pci_xfer_dmap[isp_handle_index(rq->req_handle)]; if (xs->datalen == 0) { rq->req_seg_count = 1; @@ -1222,17 +1420,37 @@ mbxsync: (ispextreq_t *)qep); break; case RQSTYPE_T2RQS: - isp_put_request_t2(isp, (ispreqt2_t *) rq, (ispreqt2_t *) qep); + if (FCPARAM(isp)->isp_2klogin) { + isp_put_request_t2e(isp, + (ispreqt2e_t *) rq, (ispreqt2e_t *) qep); + } else { + isp_put_request_t2(isp, + (ispreqt2_t *) rq, (ispreqt2_t *) qep); + } + break; + case RQSTYPE_T3RQS: + if (FCPARAM(isp)->isp_2klogin) { + isp_put_request_t3e(isp, + (ispreqt3e_t *) rq, (ispreqt3e_t *) qep); + break; + } + /* FALLTHROUGH */ + case RQSTYPE_A64: + isp_put_request_t3(isp, (ispreqt3_t *) rq, (ispreqt3_t *) qep); + break; + case RQSTYPE_T7RQS: + isp_put_request_t7(isp, (ispreqt7_t *) rq, (ispreqt7_t *) qep); break; } *nxtip = nxti; return (CMD_QUEUED); } -static int +int isp_pci_intr(void *arg) { - u_int16_t isr, sema, mbox; + u_int32_t isr; + u_int16_t sema, mbox; struct ispsoftc *isp = (struct ispsoftc *)arg; isp->isp_intcnt++; @@ -1247,8 +1465,8 @@ isp_pci_intr(void *arg) } } -static void -isp_pci_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle) +void +isp_pci_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int32_t handle) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; bus_dmamap_t dmap = pcs->pci_xfer_dmap[isp_handle_index(handle)]; @@ -1258,22 +1476,39 @@ isp_pci_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle) bus_dmamap_unload(isp->isp_dmatag, dmap); } -static void +void +isp_pci_reset0(ispsoftc_t *isp) +{ + ISP_DISABLE_INTS(isp); +} + +void isp_pci_reset1(struct ispsoftc *isp) { - /* Make sure the BIOS is disabled */ - isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); - if (isp->isp_osinfo.no_mbox_ints == 0) { - ENABLE_INTS(isp); + if (!IS_24XX(isp)) { + /* Make sure the BIOS is disabled */ + isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); } + /* and enable interrupts */ + ISP_ENABLE_INTS(isp); } -static void +void isp_pci_dumpregs(struct ispsoftc *isp, const char *msg) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; if (msg) isp_prt(isp, ISP_LOGERR, "%s", msg); + if (IS_SCSI(isp)) + isp_prt(isp, ISP_LOGERR, " biu_conf1=%x", + ISP_READ(isp, BIU_CONF1)); + else + isp_prt(isp, ISP_LOGERR, " biu_csr=%x", + ISP_READ(isp, BIU2100_CSR)); + isp_prt(isp, ISP_LOGERR, " biu_icr=%x biu_isr=%x biu_sema=%x ", + ISP_READ(isp, BIU_ICR), ISP_READ(isp, BIU_ISR), + ISP_READ(isp, BIU_SEMA)); + isp_prt(isp, ISP_LOGERR, "risc_hccr=%x\n", ISP_READ(isp, HCCR)); isp_prt(isp, ISP_LOGERR, "PCI Status Command/Status=%x\n", pci_conf_read(pcs->pci_pc, pcs->pci_tag, PCI_COMMAND_STATUS_REG)); } diff --git a/sys/dev/sbus/isp_sbus.c b/sys/dev/sbus/isp_sbus.c index 1d5007770cd..a92dfaebc20 100644 --- a/sys/dev/sbus/isp_sbus.c +++ b/sys/dev/sbus/isp_sbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_sbus.c,v 1.12 2008/06/01 15:49:25 kettenis Exp $ */ +/* $OpenBSD: isp_sbus.c,v 1.13 2009/06/24 11:00:53 krw Exp $ */ /* $NetBSD: isp_sbus.c,v 1.46 2001/09/26 20:53:14 eeh Exp $ */ /* @@ -79,13 +79,13 @@ static int isp_sbus_intr(void *); static int -isp_sbus_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); -static u_int16_t isp_sbus_rd_reg(struct ispsoftc *, int); -static void isp_sbus_wr_reg (struct ispsoftc *, int, u_int16_t); +isp_sbus_rd_isr(struct ispsoftc *, u_int32_t *, u_int16_t *, u_int16_t *); +static u_int32_t isp_sbus_rd_reg(struct ispsoftc *, int); +static void isp_sbus_wr_reg (struct ispsoftc *, int, u_int32_t); static int isp_sbus_mbxdma(struct ispsoftc *); -static int isp_sbus_dmasetup(struct ispsoftc *, XS_T *, ispreq_t *, u_int16_t *, - u_int16_t); -static void isp_sbus_dmateardown(struct ispsoftc *, XS_T *, u_int16_t); +static int isp_sbus_dmasetup(struct ispsoftc *, XS_T *, ispreq_t *, u_int32_t *, + u_int32_t); +static void isp_sbus_dmateardown(struct ispsoftc *, XS_T *, u_int32_t); #ifndef ISP_1000_RISC_CODE #define ISP_1000_RISC_CODE NULL @@ -283,7 +283,7 @@ isp_sbus_attach(struct device *parent, struct device *self, void *aux) ISP_UNLOCK(isp); return; } - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { isp_uninit(isp); @@ -306,7 +306,8 @@ isp_sbus_attach(struct device *parent, struct device *self, void *aux) static int isp_sbus_intr(void *arg) { - u_int16_t isr, sema, mbox; + u_int32_t isr; + u_int16_t sema, mbox; struct ispsoftc *isp = arg; isp->isp_intcnt++; @@ -329,7 +330,7 @@ isp_sbus_intr(void *arg) bus_space_read_2(sbc->sbus_bustag, sbc->sbus_reg, off) static int -isp_sbus_rd_isr(struct ispsoftc *isp, u_int16_t *isrp, +isp_sbus_rd_isr(struct ispsoftc *isp, u_int32_t *isrp, u_int16_t *semap, u_int16_t *mbp) { struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; @@ -350,7 +351,7 @@ isp_sbus_rd_isr(struct ispsoftc *isp, u_int16_t *isrp, return (1); } -static u_int16_t +static u_int32_t isp_sbus_rd_reg(struct ispsoftc *isp, int regoff) { struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; @@ -360,7 +361,7 @@ isp_sbus_rd_reg(struct ispsoftc *isp, int regoff) } static void -isp_sbus_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val) +isp_sbus_wr_reg(struct ispsoftc *isp, int regoff, u_int32_t val) { struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; @@ -372,10 +373,12 @@ static int isp_sbus_mbxdma(struct ispsoftc *isp) { struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; - bus_dma_segment_t reqseg, rspseg; - int reqrs, rsprs, i, progress; - size_t n; + bus_dma_segment_t seg; + bus_addr_t addr; bus_size_t len; + caddr_t base; + size_t n; + int rs, i, progress; if (isp->isp_rquest_dma) return (0); @@ -420,81 +423,51 @@ isp_sbus_mbxdma(struct ispsoftc *isp) */ progress = 0; len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); - if (bus_dmamem_alloc(isp->isp_dmatag, len, 0, 0, &reqseg, 1, &reqrs, + len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); + if (bus_dmamem_alloc(isp->isp_dmatag, len, 0, 0, &seg, 1, &rs, BUS_DMA_NOWAIT)) { goto dmafail; } progress++; - if (bus_dmamem_map(isp->isp_dmatag, &reqseg, reqrs, len, - (caddr_t *)&isp->isp_rquest, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { + if (bus_dmamem_map(isp->isp_dmatag, &seg, rs, len, + &base, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { goto dmafail; } progress++; if (bus_dmamap_create(isp->isp_dmatag, len, 1, len, 0, BUS_DMA_NOWAIT, - &isp->isp_rqdmap) != 0) { - goto dmafail; - } - progress++; - if (bus_dmamap_load(isp->isp_dmatag, isp->isp_rqdmap, - isp->isp_rquest, len, NULL, BUS_DMA_NOWAIT) != 0) { - goto dmafail; - } - progress++; - isp->isp_rquest_dma = isp->isp_rqdmap->dm_segs[0].ds_addr; - - len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); - if (bus_dmamem_alloc(isp->isp_dmatag, len, 0, 0, &rspseg, 1, &rsprs, - BUS_DMA_NOWAIT)) { - goto dmafail; - } - progress++; - if (bus_dmamem_map(isp->isp_dmatag, &rspseg, rsprs, len, - (caddr_t *)&isp->isp_result, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { + &isp->isp_cdmap) != 0) { goto dmafail; } progress++; - if (bus_dmamap_create(isp->isp_dmatag, len, 1, len, 0, BUS_DMA_NOWAIT, - &isp->isp_rsdmap) != 0) { + if (bus_dmamap_load(isp->isp_dmatag, isp->isp_cdmap, + base, len, NULL, BUS_DMA_NOWAIT) != 0) { goto dmafail; } progress++; - if (bus_dmamap_load(isp->isp_dmatag, isp->isp_rsdmap, - isp->isp_result, len, NULL, BUS_DMA_NOWAIT) != 0) { - goto dmafail; - } - isp->isp_result_dma = isp->isp_rsdmap->dm_segs[0].ds_addr; - + addr = isp->isp_cdmap->dm_segs[0].ds_addr; + isp->isp_rquest_dma = addr; + addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); + isp->isp_result_dma = addr; + + isp->isp_rquest = base; + base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); + isp->isp_result = base; return (0); dmafail: isp_prt(isp, ISP_LOGERR, "Mailbox DMA Setup Failure"); - if (progress >= 8) { - bus_dmamap_unload(isp->isp_dmatag, isp->isp_rsdmap); - } - if (progress >= 7) { - bus_dmamap_destroy(isp->isp_dmatag, isp->isp_rsdmap); - } - if (progress >= 6) { - bus_dmamem_unmap(isp->isp_dmatag, - isp->isp_result, ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp))); - } - if (progress >= 5) { - bus_dmamem_free(isp->isp_dmatag, &rspseg, rsprs); - } - if (progress >= 4) { - bus_dmamap_unload(isp->isp_dmatag, isp->isp_rqdmap); + bus_dmamap_unload(isp->isp_dmatag, isp->isp_cdmap); } if (progress >= 3) { - bus_dmamap_destroy(isp->isp_dmatag, isp->isp_rqdmap); + bus_dmamap_destroy(isp->isp_dmatag, isp->isp_cdmap); } if (progress >= 2) { - bus_dmamem_unmap(isp->isp_dmatag, - isp->isp_rquest, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp))); + bus_dmamem_unmap(isp->isp_dmatag, isp->isp_rquest, len); } if (progress >= 1) { - bus_dmamem_free(isp->isp_dmatag, &reqseg, reqrs); + bus_dmamem_free(isp->isp_dmatag, &seg, rs); } for (i = 0; i < isp->isp_maxcmds; i++) { @@ -514,7 +487,7 @@ dmafail: static int isp_sbus_dmasetup(struct ispsoftc *isp, XS_T *xs, ispreq_t *rq, - u_int16_t *nxtip, u_int16_t optr) + u_int32_t *nxtip, u_int32_t optr) { struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; bus_dmamap_t dmap; @@ -587,7 +560,7 @@ mbxsync: } static void -isp_sbus_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle) +isp_sbus_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int32_t handle) { struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; bus_dmamap_t dmap; |