diff options
author | mjacob <mjacob@cvs.openbsd.org> | 2000-10-16 01:02:02 +0000 |
---|---|---|
committer | mjacob <mjacob@cvs.openbsd.org> | 2000-10-16 01:02:02 +0000 |
commit | 9cc1567806c1cd21079fd2d4304cb9d473812767 (patch) | |
tree | 8bcdc7f9b6ff007ecad40d121f805f84f32678bc | |
parent | 72cbdc846bedac2befb88855f176a7bbc835f811 (diff) |
Update OpenBSD with respect to Solaris/FreeBSD/NetBSD/Linux versions.
Major rewrite of a lot of internals- far too many to list. Cleaner
locking, more paramaterization, an isp_prt logging function that
handles debugging as well as error printouts. We also should no
longer hang if there is no Loop for Fibre Channel when booting.
The file ispvar.h now contains a list of all platform required macros
and explanation as to what they're for. This should make maintenance
easier.
-rw-r--r-- | sys/arch/sparc/dev/isp_sbus.c | 75 | ||||
-rw-r--r-- | sys/dev/ic/isp.c | 2409 | ||||
-rw-r--r-- | sys/dev/ic/isp_inline.h | 180 | ||||
-rw-r--r-- | sys/dev/ic/isp_openbsd.c | 446 | ||||
-rw-r--r-- | sys/dev/ic/isp_openbsd.h | 409 | ||||
-rw-r--r-- | sys/dev/ic/isp_target.c | 257 | ||||
-rw-r--r-- | sys/dev/ic/isp_target.h | 24 | ||||
-rw-r--r-- | sys/dev/ic/ispmbox.h | 59 | ||||
-rw-r--r-- | sys/dev/ic/ispreg.h | 13 | ||||
-rw-r--r-- | sys/dev/ic/ispvar.h | 266 | ||||
-rw-r--r-- | sys/dev/pci/isp_pci.c | 93 |
11 files changed, 2326 insertions, 1905 deletions
diff --git a/sys/arch/sparc/dev/isp_sbus.c b/sys/arch/sparc/dev/isp_sbus.c index ff68bc24892..410c3eb9b97 100644 --- a/sys/arch/sparc/dev/isp_sbus.c +++ b/sys/arch/sparc/dev/isp_sbus.c @@ -1,10 +1,8 @@ -/* $OpenBSD: isp_sbus.c,v 1.12 2000/07/06 05:25:15 mjacob Exp $ */ -/* release_03_25_99 */ +/* $OpenBSD: isp_sbus.c,v 1.13 2000/10/16 01:01:57 mjacob Exp $ */ /* * SBus specific probe and attach routines for Qlogic ISP SCSI adapters. * - * Copyright (c) 1997 by Matthew Jacob - * NASA AMES Research Center + * Copyright (c) 1997, 2000 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -13,10 +11,8 @@ * 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 @@ -47,7 +43,9 @@ #include <sparc/sparc/cpuvar.h> #include <dev/ic/isp_openbsd.h> +#if defined(ISP_COMPILE_FW) || defined(ISP_COMPILE_1000_FW) #include <dev/microcode/isp/asm_sbus.h> +#endif static u_int16_t isp_sbus_rd_reg __P((struct ispsoftc *, int)); static void isp_sbus_wr_reg __P((struct ispsoftc *, int, u_int16_t)); @@ -56,13 +54,11 @@ static int isp_sbus_dmasetup __P((struct ispsoftc *, struct scsi_xfer *, ispreq_t *, u_int16_t *, u_int16_t)); static void isp_sbus_dmateardown __P((struct ispsoftc *, struct scsi_xfer *, u_int32_t)); +static int isp_sbus_intr __P((void *)); #ifndef ISP_1000_RISC_CODE #define ISP_1000_RISC_CODE NULL #endif -#ifndef ISP_CODE_ORG -#define ISP_CODE_ORG 0x1000 -#endif static struct ispmdvec mdvec = { isp_sbus_rd_reg, @@ -73,8 +69,8 @@ static struct ispmdvec mdvec = { NULL, NULL, NULL, - ISP_1000_RISC_CODE, 0, ISP_CODE_ORG, 0, - BIU_BURST_ENABLE + ISP_1000_RISC_CODE, + BIU_BURST_ENABLE|BIU_SBUS_CONF1_FIFO_32 }; struct isp_sbussoftc { @@ -142,7 +138,6 @@ isp_sbus_attach(parent, self, aux) struct bootpath *bp; struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) self; struct ispsoftc *isp = &sbc->sbus_isp; - ISP_LOCKVAL_DECL; if (ca->ca_ra.ra_nintr != 1) { printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr); @@ -214,16 +209,36 @@ isp_sbus_attach(parent, self, aux) sbc->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; /* Establish interrupt channel */ - sbc->sbus_ih.ih_fun = (void *) isp_intr; + sbc->sbus_ih.ih_fun = (void *) isp_sbus_intr; sbc->sbus_ih.ih_arg = sbc; intr_establish(sbc->sbus_pri, &sbc->sbus_ih); + /* + * Set up logging levels. + */ +#ifdef ISP_LOGDEFAULT + isp->isp_dblev = ISP_LOGDEFAULT; +#else + isp->isp_dblev = ISP_LOGCONFIG|ISP_LOGWARN|ISP_LOGERR; +#ifdef SCSIDEBUG + isp->isp_dblev |= ISP_LOGDEBUG1|ISP_LOGDEBUG2; +#endif +#ifdef DEBUG + isp->isp_dblev |= ISP_LOGDEBUG0; +#endif +#ifdef DIAGNOSTIC + isp->isp_dblev |= ISP_LOGINFO; +#endif +#endif + + isp->isp_osinfo.no_mbox_ints = 1; ISP_LOCK(isp); isp_reset(isp); if (isp->isp_state != ISP_RESETSTATE) { ISP_UNLOCK(isp); return; } + ENABLE_INTS(isp); isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { isp_uninit(isp); @@ -231,8 +246,6 @@ isp_sbus_attach(parent, self, aux) return; } - ENABLE_INTS(isp); - /* * do generic attach. */ @@ -299,8 +312,8 @@ isp_sbus_mbxdma(isp) * to be uncached. */ - len = isp->isp_maxcmds * sizeof (ISP_SCSI_XFER_T); - isp->isp_xflist = (ISP_SCSI_XFER_T **) malloc(len, M_DEVBUF, M_WAITOK); + len = isp->isp_maxcmds * sizeof (XS_T); + isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK); if (isp->isp_xflist == NULL) { printf("%s: cannot malloc xflist array\n", isp->isp_name); return (1); @@ -317,7 +330,7 @@ isp_sbus_mbxdma(isp) /* * Allocate and map the request queue. */ - len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); + len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); isp->isp_rquest = (volatile caddr_t)malloc(len, M_DEVBUF, M_NOWAIT); if (isp->isp_rquest == 0) { printf("%s: cannot allocate request queue\n", isp->isp_name); @@ -333,7 +346,7 @@ isp_sbus_mbxdma(isp) /* * Allocate and map the result queue. */ - len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); + len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); isp->isp_result = (volatile caddr_t)malloc(len, M_DEVBUF, M_NOWAIT); if (isp->isp_result == 0) { printf("%s: cannot allocate result queue\n", isp->isp_name); @@ -386,7 +399,7 @@ isp_sbus_dmasetup(isp, xs, rq, iptrp, optr) } if (XS_CDBLEN(xs) > 12) { crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); - *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); + *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN(isp)); if (*iptrp == optr) { printf("%s: Request Queue Overflow++\n", isp->isp_name); if (CPU_ISSUN4M) { @@ -414,7 +427,7 @@ isp_sbus_dmasetup(isp, xs, rq, iptrp, optr) crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; crq->req_dataseg[0].ds_count = xs->datalen; crq->req_dataseg[0].ds_base = (u_int32_t) kdvma; - ISP_SWIZZLE_CONTINUATION(isp, crq); + ISP_SBUSIFY_ISPHDR(isp, &crq->req_header) } else { rq->req_dataseg[0].ds_count = xs->datalen; rq->req_dataseg[0].ds_base = (u_int32_t) kdvma; @@ -448,3 +461,21 @@ isp_sbus_dmateardown(isp, xs, handle) dvma_mapout(kdvma, (vaddr_t) xs->data, xs->datalen); } } + +static int +isp_sbus_intr(arg) + void *arg; +{ + int r; + struct ispsoftc *isp = (struct ispsoftc *)arg; +#if 0 + struct iss_sbussoftc *s = (struct isp_sbussoftc *)isp; + + bus_dmamap_sync(p->pci_dmat, p->pci_result_dmap, BUS_DMASYNC_POSTREAD); +#endif + + isp->isp_osinfo.onintstack = 1; + r = isp_intr(arg); + isp->isp_osinfo.onintstack = 0; + return (r); +} diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c index 23e0c6af910..66c3403a77e 100644 --- a/sys/dev/ic/isp.c +++ b/sys/dev/ic/isp.c @@ -1,10 +1,10 @@ -/* $OpenBSD: isp.c,v 1.16 2000/07/06 05:31:48 mjacob Exp $ */ +/* $OpenBSD: isp.c,v 1.17 2000/10/16 01:01:58 mjacob Exp $ */ /* * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. * - * Copyright (c) 1997, 1998, 1999 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob + * Feral Software * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -13,10 +13,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 @@ -54,6 +51,9 @@ #ifdef __linux__ #include "isp_linux.h" #endif +#ifdef __svr4__ +#include "isp_solaris.h" +#endif /* * General defines @@ -64,7 +64,44 @@ /* * Local static data */ - +static char *warnlun = + "WARNING- cannot determine Expanded LUN capability- limiting to one LUN"; +static char *portshift = + "Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)"; +static char *portdup = + "Target %d duplicates Target %d- killing off both"; +static char *retained = + "Retaining Loop ID 0x%x for Target %d (Port 0x%x)"; +#ifdef ISP2100_FABRIC +static char *lretained = + "Retained login of Target %d (Loop ID 0x%x) Port 0x%x"; +static char *plogout = + "Logging out Target %d at Loop ID 0x%x (Port 0x%x)"; +static char *plogierr = + "Command Error in PLOGI for Port 0x%x (0x%x)"; +static char *nopdb = + "Could not get PDB for Device @ Port 0x%x"; +static char *pdbmfail1 = + "PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)"; +static char *pdbmfail2 = + "PDB Port info for Device @ Port 0x%x does not match up (0x%x)"; +static char *ldumped = + "Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch"; +#endif +static char *notresp = + "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d)"; +static char *xact1 = + "HBA attempted queued transaction with disconnect not set for %d.%d.%d"; +static char *xact2 = + "HBA attempted queued transaction to target routine %d on target %d bus %d"; +static char *xact3 = + "HBA attempted queued cmd for %d.%d.%d when queueing disabled"; +static char *pskip = + "SCSI phase skipped for target %d.%d.%d"; +static char *topology = + "Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'"; +static char *finmsg = + "(%d.%d.%d): FIN dl%d resid%d STS 0x%x SKEY %c XS_ERR=0x%x"; /* * Local function prototypes. */ @@ -72,7 +109,7 @@ static int isp_parse_async __P((struct ispsoftc *, int)); static int isp_handle_other_response __P((struct ispsoftc *, ispstatusreq_t *, u_int16_t *)); static void isp_parse_status -__P((struct ispsoftc *, ispstatusreq_t *, ISP_SCSI_XFER_T *)); +__P((struct ispsoftc *, ispstatusreq_t *, XS_T *)); static void isp_fastpost_complete __P((struct ispsoftc *, u_int32_t)); static void isp_scsi_init __P((struct ispsoftc *)); static void isp_scsi_channel_init __P((struct ispsoftc *, int)); @@ -81,14 +118,14 @@ static void isp_mark_getpdb_all __P((struct ispsoftc *)); static int isp_getpdb __P((struct ispsoftc *, int, isp_pdb_t *)); static u_int64_t isp_get_portname __P((struct ispsoftc *, int, int)); static int isp_fclink_test __P((struct ispsoftc *, int)); +static char *isp2100_fw_statename __P((int)); static int isp_same_lportdb __P((struct lportdb *, struct lportdb *)); static int isp_pdb_sync __P((struct ispsoftc *, int)); #ifdef ISP2100_FABRIC static int isp_scan_fabric __P((struct ispsoftc *)); #endif static void isp_fw_state __P((struct ispsoftc *)); -static void isp_dumpregs __P((struct ispsoftc *, const char *)); -static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *)); +static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *, int)); static void isp_update __P((struct ispsoftc *)); static void isp_update_bus __P((struct ispsoftc *, int)); @@ -100,7 +137,6 @@ static void isp_parse_nvram_1080 __P((struct ispsoftc *, int, u_int8_t *)); static void isp_parse_nvram_12160 __P((struct ispsoftc *, int, u_int8_t *)); static void isp_parse_nvram_2100 __P((struct ispsoftc *, u_int8_t *)); - /* * Reset Hardware. * @@ -118,16 +154,14 @@ isp_reset(isp) isp->isp_state = ISP_NILSTATE; + /* * Basic types (SCSI, FibreChannel and PCI or SBus) * have been set in the MD code. We figure out more * here. - */ - isp->isp_dblev = DFLT_DBLEVEL; - - /* + * * After we've fired this chip up, zero out the conf1 register - * for SCSI adapters and other settings for the 2100. + * for SCSI adapters and do other settings for the 2100. */ /* @@ -140,19 +174,27 @@ isp_reset(isp) */ if ((touched = isp->isp_touched) == 0) { /* - * Just in case it was paused... + * First see whether or not we're sitting in the ISP PROM. + * If we've just been reset, we'll have the string "ISP " + * spread through outgoing mailbox registers 1-3. */ - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); - mbs.param[0] = MBOX_ABOUT_FIRMWARE; - isp_mboxcmd(isp, &mbs); - /* - * If this fails, it probably means we're running - * an old prom, if anything at all... - */ - if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - isp->isp_romfw_rev[0] = mbs.param[1]; - isp->isp_romfw_rev[1] = mbs.param[2]; - isp->isp_romfw_rev[2] = mbs.param[3]; + if (ISP_READ(isp, OUTMAILBOX1) != 0x4953 || + ISP_READ(isp, OUTMAILBOX2) != 0x5020 || + ISP_READ(isp, OUTMAILBOX3) != 0x2020) { + /* + * Just in case it was paused... + */ + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); + mbs.param[0] = MBOX_ABOUT_FIRMWARE; + isp_mboxcmd(isp, &mbs, MBLOGNONE); + /* + * This *shouldn't* fail..... + */ + if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { + isp->isp_romfw_rev[0] = mbs.param[1]; + isp->isp_romfw_rev[1] = mbs.param[2]; + isp->isp_romfw_rev[2] = mbs.param[3]; + } } isp->isp_touched = 1; } @@ -187,7 +229,7 @@ isp_reset(isp) * XXX: Should probably do some bus sensing. */ } else if (IS_ULTRA2(isp)) { - static char *m = "%s: bus %d is in %s Mode\n"; + static char *m = "bus %d is in %s Mode"; u_int16_t l; sdparam *sdp = isp->isp_param; @@ -206,19 +248,19 @@ isp_reset(isp) switch (l) { case ISP1080_LVD_MODE: sdp->isp_lvdmode = 1; - CFGPRINTF(m, isp->isp_name, 0, "LVD"); + isp_prt(isp, ISP_LOGCONFIG, m, 0, "LVD"); break; case ISP1080_HVD_MODE: sdp->isp_diffmode = 1; - CFGPRINTF(m, isp->isp_name, 0, "Differential"); + isp_prt(isp, ISP_LOGCONFIG, m, 0, "Differential"); break; case ISP1080_SE_MODE: sdp->isp_ultramode = 1; - CFGPRINTF(m, isp->isp_name, 0, "Single-Ended"); + isp_prt(isp, ISP_LOGCONFIG, m, 0, "Single-Ended"); break; default: - CFGPRINTF("%s: unknown mode on bus %d (0x%x)\n", - isp->isp_name, 0, l); + isp_prt(isp, ISP_LOGERR, + "unknown mode on bus %d (0x%x)", 0, l); break; } @@ -229,19 +271,21 @@ isp_reset(isp) switch(l) { case ISP1080_LVD_MODE: sdp->isp_lvdmode = 1; - CFGPRINTF(m, isp->isp_name, 1, "LVD"); + isp_prt(isp, ISP_LOGCONFIG, m, 1, "LVD"); break; case ISP1080_HVD_MODE: sdp->isp_diffmode = 1; - CFGPRINTF(m, isp->isp_name, 1, "Differential"); + isp_prt(isp, ISP_LOGCONFIG, + m, 1, "Differential"); break; case ISP1080_SE_MODE: sdp->isp_ultramode = 1; - CFGPRINTF(m, isp->isp_name, 1, "Single-Ended"); + isp_prt(isp, ISP_LOGCONFIG, + m, 1, "Single-Ended"); break; default: - CFGPRINTF("%s: unknown mode on bus %d (0x%x)\n", - isp->isp_name, 1, l); + isp_prt(isp, ISP_LOGERR, + "unknown mode on bus %d (0x%x)", 1, l); break; } } @@ -250,8 +294,7 @@ isp_reset(isp) i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK; switch (i) { default: - PRINTF("%s: unknown chip rev. 0x%x- assuming a 1020\n", - isp->isp_name, i); + isp_prt(isp, ISP_LOGALL, "Unknown Chip Type 0x%x", i); /* FALLTHROUGH */ case 1: revname = "1020"; @@ -294,7 +337,7 @@ isp_reset(isp) * and/or differential mode. */ if (ISP_READ(isp, SXP_PINS_DIFF) & SXP_PINS_DIFF_MODE) { - CFGPRINTF("%s: Differential Mode\n", isp->isp_name); + isp_prt(isp, ISP_LOGCONFIG, "Differential Mode"); sdp->isp_diffmode = 1; } else { sdp->isp_diffmode = 0; @@ -306,7 +349,7 @@ isp_reset(isp) i &= RISC_PSR_PCI_ULTRA; } if (i != 0) { - CFGPRINTF("%s: Ultra Mode Capable\n", isp->isp_name); + isp_prt(isp, ISP_LOGCONFIG, "Ultra Mode Capable"); sdp->isp_ultramode = 1; /* * If we're in Ultra Mode, we have to be 60Mhz clock- @@ -349,15 +392,7 @@ again: /* * A slight delay... */ - SYS_DELAY(100); - -#if 0 - PRINTF("%s: mbox0-5: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", - isp->isp_name, ISP_READ(isp, OUTMAILBOX0), - ISP_READ(isp, OUTMAILBOX1), ISP_READ(isp, OUTMAILBOX2), - ISP_READ(isp, OUTMAILBOX3), ISP_READ(isp, OUTMAILBOX4), - ISP_READ(isp, OUTMAILBOX5)); -#endif + USEC_DELAY(100); /* * Clear data && control DMA engines. @@ -373,7 +408,7 @@ again: /* * A slight delay... */ - SYS_DELAY(100); + USEC_DELAY(100); /* * Clear data && control DMA engines. @@ -398,9 +433,9 @@ again: if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET)) break; } - SYS_DELAY(100); + USEC_DELAY(100); if (--loops < 0) { - isp_dumpregs(isp, "chip reset timed out"); + ISP_DUMPREGS(isp, "chip reset timed out"); return; } } @@ -420,7 +455,7 @@ again: * Reset RISC Processor */ ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); - SYS_DELAY(100); + USEC_DELAY(100); /* * Establish some initial burst rate stuff. @@ -472,10 +507,10 @@ again: */ loops = MBOX_DELAY_COUNT; while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) { - SYS_DELAY(100); + USEC_DELAY(100); if (--loops < 0) { - PRINTF("%s: MBOX_BUSY never cleared on reset\n", - isp->isp_name); + isp_prt(isp, ISP_LOGERR, + "MBOX_BUSY never cleared on reset"); return; } } @@ -490,9 +525,8 @@ again: * Do some sanity checking. */ mbs.param[0] = MBOX_NO_OP; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_dumpregs(isp, "NOP test failed"); return; } @@ -503,16 +537,17 @@ again: mbs.param[3] = 0xffff; mbs.param[4] = 0x1111; mbs.param[5] = 0xa5a5; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_dumpregs(isp, - "Mailbox Register test didn't complete"); return; } if (mbs.param[1] != 0xdead || mbs.param[2] != 0xbeef || mbs.param[3] != 0xffff || mbs.param[4] != 0x1111 || mbs.param[5] != 0xa5a5) { - isp_dumpregs(isp, "Register Test Failed"); + 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], + mbs.param[4], mbs.param[5]); return; } @@ -533,17 +568,15 @@ again: } if (dodnld) { - u_int16_t fwlen = isp->isp_mdvec->dv_fwlen; - if (fwlen == 0) - fwlen = isp->isp_mdvec->dv_ispfw[3]; /* usually here */ + u_int16_t fwlen = isp->isp_mdvec->dv_ispfw[3]; for (i = 0; i < fwlen; i++) { mbs.param[0] = MBOX_WRITE_RAM_WORD; - mbs.param[1] = isp->isp_mdvec->dv_codeorg + i; + mbs.param[1] = ISP_CODE_ORG + i; mbs.param[2] = isp->isp_mdvec->dv_ispfw[i]; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGNONE); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: F/W download failed at word %d\n", - isp->isp_name, i); + isp_prt(isp, ISP_LOGERR, + "F/W download failed at word %d", i); dodnld = 0; goto again; } @@ -553,14 +586,16 @@ again: * Verify that it downloaded correctly. */ mbs.param[0] = MBOX_VERIFY_CHECKSUM; - mbs.param[1] = isp->isp_mdvec->dv_codeorg; - isp_mboxcmd(isp, &mbs); + mbs.param[1] = ISP_CODE_ORG; + isp_mboxcmd(isp, &mbs, MBLOGNONE); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_dumpregs(isp, "ram checksum failure"); + isp_prt(isp, ISP_LOGERR, "Ram Checksum Failure"); return; } + isp->isp_loaded_fw = 1; } else { - IDPRINTF(3, ("%s: skipping f/w download\n", isp->isp_name)); + isp->isp_loaded_fw = 0; + isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download"); } /* @@ -571,13 +606,10 @@ again: */ mbs.param[0] = MBOX_EXEC_FIRMWARE; - if (isp->isp_mdvec->dv_codeorg) - mbs.param[1] = isp->isp_mdvec->dv_codeorg; - else - mbs.param[1] = 0x1000; - isp_mboxcmd(isp, &mbs); + mbs.param[1] = ISP_CODE_ORG; + isp_mboxcmd(isp, &mbs, MBLOGNONE); /* give it a chance to start */ - SYS_DELAY(500); + USEC_DELAY(500); if (IS_SCSI(isp)) { /* @@ -586,26 +618,24 @@ again: if (isp->isp_clock) { mbs.param[0] = MBOX_SET_CLOCK_RATE; mbs.param[1] = isp->isp_clock; - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("failed to set clockrate (0x%x)\n", - mbs.param[0]); - /* but continue */ - } + isp_mboxcmd(isp, &mbs, MBLOGALL); + /* we will try not to care if this fails */ } } + mbs.param[0] = MBOX_ABOUT_FIRMWARE; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("could not get f/w started (0x%x)\n", mbs.param[0]); return; } - CFGPRINTF("%s: Board Revision %s, %s F/W Revision %d.%d.%d\n", - isp->isp_name, revname, dodnld? "loaded" : "resident", - mbs.param[1], mbs.param[2], mbs.param[3]); + isp_prt(isp, ISP_LOGCONFIG, + "Board Revision %s, %s F/W Revision %d.%d.%d", revname, + dodnld? "loaded" : "resident", mbs.param[1], mbs.param[2], + mbs.param[3]); if (IS_FC(isp)) { if (ISP_READ(isp, BIU2100_CSR) & BIU2100_PCI64) { - CFGPRINTF("%s: in 64-Bit PCI slot\n", isp->isp_name); + isp_prt(isp, ISP_LOGCONFIG, + "Installed in 64-Bit PCI slot"); } } @@ -614,27 +644,26 @@ again: isp->isp_fwrev[2] = mbs.param[3]; if (isp->isp_romfw_rev[0] || isp->isp_romfw_rev[1] || isp->isp_romfw_rev[2]) { - CFGPRINTF("%s: Last F/W revision was %d.%d.%d\n", isp->isp_name, + isp_prt(isp, ISP_LOGCONFIG, "Last F/W revision was %d.%d.%d", isp->isp_romfw_rev[0], isp->isp_romfw_rev[1], isp->isp_romfw_rev[2]); } mbs.param[0] = MBOX_GET_FIRMWARE_STATUS; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: could not GET FIRMWARE STATUS\n", isp->isp_name); return; } isp->isp_maxcmds = mbs.param[2]; - CFGPRINTF("%s: %d max I/O commands supported\n", - isp->isp_name, mbs.param[2]); + isp_prt(isp, ISP_LOGINFO, + "%d max I/O commands supported", mbs.param[2]); isp_fw_state(isp); /* * Set up DMA for the request and result mailboxes. */ if (ISP_MBOXDMASETUP(isp) != 0) { - PRINTF("%s: can't setup dma mailboxes\n", isp->isp_name); + isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); return; } isp->isp_state = ISP_RESETSTATE; @@ -671,9 +700,7 @@ again: if (IS_SCSI(isp)) { isp->isp_maxluns = 8; } else { - PRINTF("%s: WARNING- cannot determine Expanded " - "LUN capability- limiting to one LUN\n", - isp->isp_name); + isp_prt(isp, ISP_LOGALL, warnlun); isp->isp_maxluns = 1; } } @@ -697,7 +724,6 @@ isp_init(isp) if (IS_DUALBUS(isp)) { isp_setdfltparm(isp, 1); } - if (IS_FC(isp)) { isp_fibre_init(isp); } else { @@ -723,7 +749,7 @@ isp_scsi_init(isp) /* * If we have fast memory timing enabled, turn it on. */ - if (isp->isp_fast_mttr) { + if (sdp_chan0->isp_fast_mttr) { ISP_WRITE(isp, RISC_MTR, 0x1313); } @@ -737,10 +763,8 @@ isp_scsi_init(isp) mbs.param[6] = sdp_chan1->isp_retry_count; mbs.param[7] = sdp_chan1->isp_retry_delay; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed to set retry count and retry delay\n", - isp->isp_name); return; } @@ -750,10 +774,8 @@ isp_scsi_init(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); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed to set asynchronous data setup time\n", - isp->isp_name); return; } @@ -768,10 +790,10 @@ isp_scsi_init(isp) (sdp_chan1->isp_req_ack_active_neg << 4) | (sdp_chan1->isp_data_line_active_neg << 5); - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGNONE); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed to set active negation state " - "(%d,%d),(%d,%d)\n", isp->isp_name, + isp_prt(isp, ISP_LOGERR, + "failed to set active negation state (%d,%d), (%d,%d)", sdp_chan0->isp_req_ack_active_neg, sdp_chan0->isp_data_line_active_neg, sdp_chan1->isp_req_ack_active_neg, @@ -787,11 +809,10 @@ isp_scsi_init(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); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed to set tag age limit (%d,%d)\n", - isp->isp_name, sdp_chan0->isp_tag_aging, - sdp_chan1->isp_tag_aging); + isp_prt(isp, ISP_LOGERR, "failed to set tag age limit (%d,%d)", + sdp_chan0->isp_tag_aging, sdp_chan1->isp_tag_aging); return; } @@ -801,9 +822,8 @@ isp_scsi_init(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); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed to set selection timeout\n", isp->isp_name); return; } @@ -817,30 +837,27 @@ isp_scsi_init(isp) */ mbs.param[0] = MBOX_INIT_RES_QUEUE; - mbs.param[1] = RESULT_QUEUE_LEN; + mbs.param[1] = RESULT_QUEUE_LEN(isp); mbs.param[2] = DMA_MSW(isp->isp_result_dma); mbs.param[3] = DMA_LSW(isp->isp_result_dma); mbs.param[4] = 0; mbs.param[5] = 0; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: set of response queue failed\n", isp->isp_name); return; } - isp->isp_residx = 0; + isp->isp_residx = mbs.param[5]; mbs.param[0] = MBOX_INIT_REQ_QUEUE; - mbs.param[1] = RQUEST_QUEUE_LEN; + mbs.param[1] = RQUEST_QUEUE_LEN(isp); mbs.param[2] = DMA_MSW(isp->isp_rquest_dma); mbs.param[3] = DMA_LSW(isp->isp_rquest_dma); mbs.param[4] = 0; - mbs.param[5] = 0; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: set of request queue failed\n", isp->isp_name); return; } - isp->isp_reqidx = isp->isp_reqodx = 0; + isp->isp_reqidx = isp->isp_reqodx = mbs.param[4]; /* * Turn on Fast Posting, LVD transitions @@ -859,13 +876,10 @@ isp_scsi_init(isp) mbs.param[1] |= FW_FEATURE_FAST_POST; if (mbs.param[1] != 0) { u_int16_t sfeat = mbs.param[1]; - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: cannot enable FW features (0x%x)\n", - isp->isp_name, sfeat); - } else { - CFGPRINTF("%s: enabled FW features (0x%x)\n", - isp->isp_name, sfeat); + isp_mboxcmd(isp, &mbs, MBLOGALL); + if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGINFO, + "Enabled FW features (0x%x)", sfeat); } } @@ -892,12 +906,12 @@ isp_scsi_channel_init(isp, channel) */ mbs.param[0] = MBOX_SET_INIT_SCSI_ID; mbs.param[1] = (channel << 7) | sdp->isp_initiator_id; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: cannot set initiator id on bus %d to %d\n", - isp->isp_name, channel, sdp->isp_initiator_id); return; } + isp_prt(isp, ISP_LOGINFO, "Initiator ID is %d", sdp->isp_initiator_id); + /* * Set current per-target parameters to a safe minimum. @@ -907,107 +921,71 @@ isp_scsi_channel_init(isp, channel) u_int16_t sdf; if (sdp->isp_devparam[tgt].dev_enable == 0) { - IDPRINTF(2, ("%s: skipping target %d bus %d settings\n", - isp->isp_name, tgt, channel)); continue; } - + sdf = DPARM_SAFE_DFLT; /* - * If we're in LVD mode, then we pretty much should - * only disable tagged queuing. + * It is not quite clear when this changed over so that + * we could force narrow and async for 1000/1020 cards, + * but assume that this is only the case for loaded + * firmware. */ - if (IS_ULTRA2(isp) && sdp->isp_lvdmode) { - sdf = DPARM_DEFAULT & ~DPARM_TQING; - } else { - int rvf = ISP_FW_REVX(isp->isp_fwrev); - sdf = DPARM_SAFE_DFLT; - - /* - * It is not quite clear when this changed over so that - * we could force narrow and async, so assume >= 7.55 - * for i/t F/W and = 4.55 for initiator f/w. - */ - if ((ISP_FW_REV(4, 55, 0) <= rvf && - (ISP_FW_REV(5, 0, 0) > rvf)) || - (ISP_FW_REV(7, 55, 0) <= rvf)) { - sdf |= DPARM_NARROW | DPARM_ASYNC; - } + if (isp->isp_loaded_fw) { + sdf |= DPARM_NARROW | DPARM_ASYNC; } mbs.param[0] = MBOX_SET_TARGET_PARAMS; mbs.param[1] = (tgt << 8) | (channel << 15); mbs.param[2] = sdf; - mbs.param[3] = - (sdp->isp_devparam[tgt].sync_offset << 8) | - (sdp->isp_devparam[tgt].sync_period); - isp_mboxcmd(isp, &mbs); + if ((sdf & DPARM_SYNC) == 0) { + mbs.param[3] = 0; + } else { + mbs.param[3] = + (sdp->isp_devparam[tgt].sync_offset << 8) | + (sdp->isp_devparam[tgt].sync_period); + } + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { sdf = DPARM_SAFE_DFLT; mbs.param[0] = MBOX_SET_TARGET_PARAMS; mbs.param[1] = (tgt << 8) | (channel << 15); mbs.param[2] = sdf; - mbs.param[3] = - (sdp->isp_devparam[tgt].sync_offset << 8) | - (sdp->isp_devparam[tgt].sync_period); - isp_mboxcmd(isp, &mbs); + mbs.param[3] = 0; + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed even to set defaults for " - "target %d\n", isp->isp_name, tgt); continue; } } -#if 0 - /* - * We don't update dev_flags with what we've set - * because that's not the ultimate goal setting. - * If we succeed with the command, we *do* update - * cur_dflags by getting target parameters. - */ - mbs.param[0] = MBOX_GET_TARGET_PARAMS; - mbs.param[1] = (tgt << 8) | (channel << 15); - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - /* - * Urrr.... We'll set cur_dflags to DPARM_SAFE_DFLT so - * we don't try and do tags if tags aren't enabled. - */ - sdp->isp_devparam[tgt].cur_dflags = DPARM_SAFE_DFLT; - } else { - sdp->isp_devparam[tgt].cur_dflags = mbs.param[2]; - sdp->isp_devparam[tgt].cur_offset = mbs.param[3] >> 8; - sdp->isp_devparam[tgt].cur_period = mbs.param[3] & 0xff; - } - IDPRINTF(3, ("%s: set flags 0x%x got 0x%x back for target %d\n", - isp->isp_name, sdf, mbs.param[2], tgt)); - -#else - /* - * We don't update any information because we need to run - * at least one command per target to cause a new state - * to be latched. - */ -#endif /* + * We don't update any information directly from the f/w + * because we need to run at least one command to cause a + * new state to be latched up. So, we just assume that we + * converge to the values we just had set. + * * Ensure that we don't believe tagged queuing is enabled yet. * It turns out that sometimes the ISP just ignores our * attempts to set parameters for devices that it hasn't * seen yet. */ - sdp->isp_devparam[tgt].cur_dflags &= ~DPARM_TQING; - for (lun = 0; lun < isp->isp_maxluns; lun++) { + sdp->isp_devparam[tgt].cur_dflags = sdf & ~DPARM_TQING; + for (lun = 0; lun < (int) isp->isp_maxluns; lun++) { mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS; 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); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed to set device queue " - "parameters for target %d, lun %d\n", - isp->isp_name, tgt, lun); break; } } } + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if (sdp->isp_devparam[tgt].dev_refresh) { + isp->isp_sendmarker |= (1 << channel); + isp->isp_update |= (1 << channel); + break; + } + } } /* @@ -1023,41 +1001,30 @@ isp_fibre_init(isp) isp_icb_t *icbp; mbreg_t mbs; int loopid; + u_int64_t nwwn, pwwn; fcp = isp->isp_param; - /* - * For systems that don't have BIOS methods for which - * we can easily change the NVRAM based loopid, we'll - * override that here. Note that when we initialize - * the firmware we may get back a different loopid than - * we asked for anyway. XXX This is probably not the - * best way to figure this out XXX - */ -#ifndef __i386__ loopid = DEFAULT_LOOPID(isp); -#else - loopid = fcp->isp_loopid; -#endif - icbp = (isp_icb_t *) fcp->isp_scratch; MEMZERO(icbp, sizeof (*icbp)); icbp->icb_version = ICB_VERSION1; -#ifdef ISP_TARGET_MODE - fcp->isp_fwoptions = ICBOPT_TGT_ENABLE; -#else - fcp->isp_fwoptions = 0; -#endif - fcp->isp_fwoptions |= ICBOPT_FAIRNESS; + + /* + * Firmware Options are either retrieved from NVRAM or + * are patched elsewhere. We check them for sanity here + * and make changes based on board revision, but otherwise + * let others decide policy. + */ + /* * 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; } - fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; - fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; + /* * We have to use FULL LOGIN even though it resets the loop too much * because otherwise port database entries don't get updated after @@ -1066,11 +1033,11 @@ isp_fibre_init(isp) if (ISP_FW_REVX(isp->isp_fwrev) < ISP_FW_REV(1, 17, 0)) { fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; } -#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; + + /* + * Insist on Port Database Update Async notifications + */ + fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; /* * We don't set ICBOPT_PORTNAME because we want our @@ -1081,26 +1048,31 @@ isp_fibre_init(isp) icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { - PRINTF("%s: bad frame length (%d) from NVRAM- using %d\n", - isp->isp_name, fcp->isp_maxfrmlen, ICB_DFLT_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_maxalloc = fcp->isp_maxalloc; if (icbp->icb_maxalloc < 1) { - PRINTF("%s: bad maximum allocation (%d)- using 16\n", - isp->isp_name, fcp->isp_maxalloc); + isp_prt(isp, ISP_LOGERR, + "bad maximum allocation (%d)- using 16", fcp->isp_maxalloc); icbp->icb_maxalloc = 16; } icbp->icb_execthrottle = fcp->isp_execthrottle; if (icbp->icb_execthrottle < 1) { - PRINTF("%s: bad execution throttle of %d- using 16\n", - isp->isp_name, fcp->isp_execthrottle); + isp_prt(isp, ISP_LOGERR, + "bad execution throttle of %d- using 16", + fcp->isp_execthrottle); icbp->icb_execthrottle = ICB_DFLT_THROTTLE; } icbp->icb_retry_delay = fcp->isp_retry_delay; icbp->icb_retry_count = fcp->isp_retry_count; icbp->icb_hardaddr = loopid; -#ifdef PRET_A_PORTE + /* + * Right now we just set extended options to prefer point-to-point + * over loop based upon some soft config options. + */ if (IS_2200(isp)) { icbp->icb_fwoptions |= ICBOPT_EXTENDED; /* @@ -1111,21 +1083,31 @@ isp_fibre_init(isp) else icbp->icb_xfwoptions = ICBXOPT_LOOP_2_PTP; } -#endif icbp->icb_logintime = 60; /* 60 second login timeout */ - if (fcp->isp_nodewwn) { - MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_nodewwn); - MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_portwwn); + nwwn = ISP_NODEWWN(isp); + pwwn = ISP_PORTWWN(isp); + if (nwwn && pwwn) { + 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 { + isp_prt(isp, ISP_LOGDEBUG1, "Not using any WWNs"); fcp->isp_fwoptions &= ~(ICBOPT_USE_PORTNAME|ICBOPT_FULL_LOGIN); } - icbp->icb_rqstqlen = RQUEST_QUEUE_LEN; - icbp->icb_rsltqlen = RESULT_QUEUE_LEN; + icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp); + icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp); icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_rquest_dma); icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_rquest_dma); icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_result_dma); icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_result_dma); + isp_prt(isp, ISP_LOGDEBUG1, + "isp_fibre_init: fwoptions 0x%x", fcp->isp_fwoptions); ISP_SWIZZLE_ICB(isp, icbp); /* @@ -1135,29 +1117,18 @@ isp_fibre_init(isp) fcp->isp_fwstate = FW_CONFIG_WAIT; fcp->isp_loopstate = LOOP_NIL; - MemoryBarrier(); - for (;;) { - mbs.param[0] = MBOX_INIT_FIRMWARE; - mbs.param[1] = 0; - mbs.param[2] = DMA_MSW(fcp->isp_scdma); - mbs.param[3] = DMA_LSW(fcp->isp_scdma); - mbs.param[4] = 0; - mbs.param[5] = 0; - mbs.param[6] = 0; - mbs.param[7] = 0; - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: INIT FIRMWARE failed (code 0x%x)\n", - isp->isp_name, mbs.param[0]); - if (mbs.param[0] & 0x8000) { - SYS_DELAY(1000); - continue; - } - return; - } - break; + mbs.param[0] = MBOX_INIT_FIRMWARE; + mbs.param[1] = 0; + mbs.param[2] = DMA_MSW(fcp->isp_scdma); + mbs.param[3] = DMA_LSW(fcp->isp_scdma); + mbs.param[4] = 0; + mbs.param[5] = 0; + mbs.param[6] = 0; + mbs.param[7] = 0; + isp_mboxcmd(isp, &mbs, MBLOGALL); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; } - isp->isp_reqidx = isp->isp_reqodx = 0; isp->isp_residx = 0; isp->isp_sendmarker = 1; @@ -1208,26 +1179,12 @@ isp_getpdb(isp, id, pdbp) */ mbs.param[6] = 0; mbs.param[7] = 0; - isp_mboxcmd(isp, &mbs); - switch (mbs.param[0]) { - case MBOX_COMMAND_COMPLETE: - MemoryBarrier(); + isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); + if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { ISP_UNSWIZZLE_AND_COPY_PDBP(isp, pdbp, fcp->isp_scratch); - break; - case MBOX_HOST_INTERFACE_ERROR: - PRINTF("%s: DMA error getting port database\n", isp->isp_name); - return (-1); - case MBOX_COMMAND_PARAM_ERROR: - /* Not Logged In */ - IDPRINTF(3, ("%s: Param Error on Get Port Database for id %d\n", - isp->isp_name, id)); - return (-1); - default: - PRINTF("%s: error 0x%x getting port database for ID %d\n", - isp->isp_name, mbs.param[0], id); - return (-1); + return (0); } - return (0); + return (-1); } static u_int64_t @@ -1243,7 +1200,7 @@ isp_get_portname(isp, loopid, nodename) mbs.param[1] = loopid << 8; if (nodename) mbs.param[1] |= 1; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { wwn = (((u_int64_t)(mbs.param[2] & 0xff)) << 56) | @@ -1263,9 +1220,9 @@ isp_get_portname(isp, loopid, nodename) */ static int -isp_fclink_test(isp, waitdelay) +isp_fclink_test(isp, usdelay) struct ispsoftc *isp; - int waitdelay; + int usdelay; { static char *toponames[] = { "Private Loop", @@ -1284,21 +1241,69 @@ isp_fclink_test(isp, waitdelay) fcp = isp->isp_param; /* + * XXX: Here is where we would start a 'loop dead' timeout + */ + + /* * Wait up to N microseconds for F/W to go to a ready state. */ lwfs = FW_CONFIG_WAIT; - for (count = 0; count < waitdelay; count += 100) { + count = 0; + while (count < usdelay) { + u_int64_t enano; + u_int32_t wrk; + NANOTIME_T hra, hrb; + + GET_NANOTIME(&hra); isp_fw_state(isp); if (lwfs != fcp->isp_fwstate) { - PRINTF("%s: Firmware State %s -> %s\n", - isp->isp_name, isp2100_fw_statename((int)lwfs), + isp_prt(isp, ISP_LOGINFO, "Firmware State <%s->%s>", + isp2100_fw_statename((int)lwfs), isp2100_fw_statename((int)fcp->isp_fwstate)); lwfs = fcp->isp_fwstate; } if (fcp->isp_fwstate == FW_READY) { break; } - SYS_DELAY(100); /* wait 100 microseconds */ + GET_NANOTIME(&hrb); + + /* + * Get the elapsed time in nanoseconds. + * Always guaranteed to be non-zero. + */ + enano = NANOTIME_SUB(&hrb, &hra); + + /* + * If the elapsed time is less than 1 millisecond, + * delay a period of time up to that millisecond of + * waiting. + */ + isp_prt(isp, ISP_LOGDEBUG3, "usec%d: 0x%lx->0x%lx enano %u", + count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb), + enano); + + /* + * This peculiar code is an attempt to try and avoid + * invoking u_int64_t math support functions for some + * platforms where linkage is a problem. + */ + if (enano < (1000 * 1000)) { + count += 1000; + enano = (1000 * 1000) - enano; + while (enano > (u_int64_t) 4000000000U) { + USEC_DELAY(4000000); + enano -= (u_int64_t) 4000000000U; + } + wrk = enano; + USEC_DELAY(wrk/1000); + } else { + while (enano > (u_int64_t) 4000000000U) { + count += 4000000; + enano -= (u_int64_t) 4000000000U; + } + wrk = enano; + count += (wrk / 1000); + } } /* @@ -1312,9 +1317,8 @@ isp_fclink_test(isp, waitdelay) * Get our Loop ID (if possible). We really need to have it. */ mbs.param[0] = MBOX_GET_LOOP_ID; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: GET LOOP ID failed\n", isp->isp_name); return (-1); } fcp->isp_loopid = mbs.param[1]; @@ -1382,17 +1386,28 @@ isp_fclink_test(isp, waitdelay) fcp->portdb[FL_PORT_ID].valid = 0; } - CFGPRINTF("%s: Loop ID %d, AL_PA 0x%x, Port ID 0x%x Loop State " - "0x%x topology '%s'\n", isp->isp_name, fcp->isp_loopid, - fcp->isp_alpa, fcp->isp_portid, fcp->isp_loopstate, - toponames[fcp->isp_topo]); + isp_prt(isp, ISP_LOGINFO, topology, fcp->isp_loopid, fcp->isp_alpa, + fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]); return (0); } -/* - * Compare two local port db entities and return 1 if they're the same, else 0. - */ +static char * +isp2100_fw_statename(state) + int state; +{ + switch(state) { + case FW_CONFIG_WAIT: return "Config Wait"; + case FW_WAIT_AL_PA: return "Waiting for AL_PA"; + case FW_WAIT_LOGIN: return "Wait Login"; + case FW_READY: return "Ready"; + case FW_LOSS_OF_SYNC: return "Loss Of Sync"; + case FW_ERROR: return "Error"; + case FW_REINIT: return "Re-Init"; + case FW_NON_PART: return "Nonparticipating"; + default: return "?????"; + } +} static int isp_same_lportdb(a, b) @@ -1503,8 +1518,8 @@ isp_pdb_sync(isp, target) if (lim++ < FL_PORT_ID) { continue; } - PRINTF("%s: giving up on synchronizing the port " - "database\n", isp->isp_name); + isp_prt(isp, ISP_LOGWARN, + "giving up on synchronizing the port database"); return (-1); } @@ -1608,9 +1623,8 @@ isp_pdb_sync(isp, target) * just change the actual loop ID we'd use. */ if (fcp->portdb[i].loopid != loopid) { - PRINTF("%s: Target ID %d Loop 0x%x (Port 0x%x) " - "=> Loop 0x%x (Port 0x%x) \n", - isp->isp_name, i, fcp->portdb[i].loopid, + isp_prt(isp, ISP_LOGINFO, portshift, i, + fcp->portdb[i].loopid, fcp->portdb[i].portid, loopid, tport[loopid].portid); } @@ -1628,9 +1642,7 @@ isp_pdb_sync(isp, target) fcp->portdb[j].port_wwn) { continue; } - PRINTF("%s: Target ID %d Duplicates Target ID " - "%d- killing off both\n", - isp->isp_name, j, i); + isp_prt(isp, ISP_LOGWARN, portdup, j, i); /* * Invalidate the 'old' *and* 'new' ones. * This is really harsh and not quite right, @@ -1663,7 +1675,7 @@ isp_pdb_sync(isp, target) } /* "Cannot Happen" */ if (lim == FL_PORT_ID) { - PRINTF("%s: remap overflow?\n", isp->isp_name); + isp_prt(isp, ISP_LOGWARN, "Remap Overflow"); continue; } i = lim; @@ -1759,10 +1771,9 @@ isp_pdb_sync(isp, target) nwwnn == lp->node_wwn && nwwpn == lp->port_wwn && lp->roles == nrole) { lp->loggedin = lp->valid = 1; - IDPRINTF(1, ("%s: retained login of Target %d " - "(Loop 0x%x) Port ID 0x%x\n", - isp->isp_name, (int) (lp - fcp->portdb), - (int) lp->loopid, lp->portid)); + isp_prt(isp, ISP_LOGINFO, lretained, + (int) (lp - fcp->portdb), + (int) lp->loopid, lp->portid); continue; } } @@ -1775,11 +1786,10 @@ isp_pdb_sync(isp, target) mbs.param[1] = lp->loopid << 8; mbs.param[2] = 0; mbs.param[3] = 0; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGNONE); lp->loggedin = 0; - IDPRINTF(1, ("%s: Logging out target %d at Loop ID %d " - "(port id 0x%x)\n", isp->isp_name, - (int) (lp - fcp->portdb), lp->loopid, lp->portid)); + isp_prt(isp, ISP_LOGINFO, plogout, + (int) (lp - fcp->portdb), lp->loopid, lp->portid); } /* @@ -1796,7 +1806,8 @@ isp_pdb_sync(isp, target) /* only issue a PLOGI if not logged in */ mbs.param[1] |= 0x1; } - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL & ~(MBOX_LOOP_ID_USED | + MBOX_PORT_ID_USED | MBOX_COMMAND_ERROR)); switch (mbs.param[0]) { case MBOX_LOOP_ID_USED: /* @@ -1812,11 +1823,9 @@ isp_pdb_sync(isp, target) */ if (mbs.param[1] != 0) { loopid = mbs.param[1]; - IDPRINTF(1, ("%s: Retaining loopid 0x%x" - " for Target %d (port id 0x%x)\n", - isp->isp_name, loopid, - (int) (lp - fcp->portdb), - lp->portid)); + isp_prt(isp, ISP_LOGINFO, retained, + loopid, (int) (lp - fcp->portdb), + lp->portid); } else { loopid = MAX_FC_TARG; break; @@ -1827,9 +1836,8 @@ isp_pdb_sync(isp, target) lp->loopid = loopid; break; case MBOX_COMMAND_ERROR: - PRINTF("%s: command error in PLOGI for port " - " 0x%x (0x%x)\n", isp->isp_name, portid, - mbs.param[1]); + isp_prt(isp, ISP_LOGINFO, plogierr, + portid, mbs.param[1]); /* FALLTHROUGH */ case MBOX_ALL_IDS_USED: /* We're outta IDs */ default: @@ -1851,22 +1859,19 @@ isp_pdb_sync(isp, target) * Make sure we can get the approriate port information. */ if (isp_getpdb(isp, lp->loopid, &pdb) != 0) { - PRINTF("%s: could not get PDB for device@port 0x%x\n", - isp->isp_name, lp->portid); + isp_prt(isp, ISP_LOGWARN, nopdb, lp->portid); goto dump_em; } if (pdb.pdb_loopid != lp->loopid) { - PRINTF("%s: PDB loopid info for device@port 0x%x does " - "not match up (0x%x)\n", isp->isp_name, lp->portid, - pdb.pdb_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)) { - PRINTF("%s: PDB port info for device@port 0x%x does " - "not match up (0x%x)\n", isp->isp_name, lp->portid, - BITS2WORD(pdb.pdb_portid_bits)); + isp_prt(isp, ISP_LOGWARN, pdbmfail2, + lp->portid, BITS2WORD(pdb.pdb_portid_bits)); goto dump_em; } @@ -1901,19 +1906,19 @@ isp_pdb_sync(isp, target) } dump_em: lp->valid = 0; - PRINTF("%s: Target %d (Loop 0x%x) Port ID 0x%x dumped after " - "login\n", isp->isp_name, loopid, lp->loopid, lp->portid); + isp_prt(isp, ISP_LOGINFO, + ldumped, loopid, lp->loopid, lp->portid); mbs.param[0] = MBOX_FABRIC_LOGOUT; mbs.param[1] = lp->loopid << 8; mbs.param[2] = 0; mbs.param[3] = 0; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGNONE); } #endif /* * 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 - * in ispscsicmd. + * in isp_start. */ fcp->loop_seen_once = 1; return (0); @@ -1953,11 +1958,8 @@ isp_scan_fabric(isp) mbs.param[3] = DMA_LSW(fcp->isp_scdma); mbs.param[6] = 0; mbs.param[7] = 0; - MemoryBarrier(); - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - IDPRINTF(1, ("%s: SNS failed (0x%x)\n", isp->isp_name, - mbs.param[0])); return (-1); } ISP_UNSWIZZLE_SNS_RSP(isp, resp, SNS_GAN_RESP_SIZE >> 1); @@ -1984,9 +1986,9 @@ isp_scan_fabric(isp) * Start a command. Locking is assumed done in the caller. */ -int32_t -ispscsicmd(xs) - ISP_SCSI_XFER_T *xs; +int +isp_start(xs) + XS_T *xs; { struct ispsoftc *isp; u_int16_t iptr, optr; @@ -2003,7 +2005,7 @@ ispscsicmd(xs) isp = XS_ISP(xs); if (isp->isp_state != ISP_RUNSTATE) { - PRINTF("%s: adapter not ready\n", isp->isp_name); + isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE"); XS_SETERR(xs, HBA_BOTCH); return (CMD_COMPLETE); } @@ -2016,8 +2018,9 @@ ispscsicmd(xs) */ if (XS_CDBLEN(xs) > (IS_FC(isp)? 16 : 44) || XS_CDBLEN(xs) == 0) { - PRINTF("%s: unsupported cdb length (%d, CDB[0]=0x%x)\n", - isp->isp_name, XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff); + isp_prt(isp, ISP_LOGERR, + "unsupported cdb length (%d, CDB[0]=0x%x)", + XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff); XS_SETERR(xs, HBA_BOTCH); return (CMD_COMPLETE); } @@ -2067,7 +2070,10 @@ ispscsicmd(xs) * until later. */ if (fcp->isp_fwstate != FW_READY) { - if (isp_fclink_test(isp, FC_FW_READY_DELAY)) { + /* + * 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); @@ -2108,6 +2114,11 @@ ispscsicmd(xs) } /* + * XXX: Here's were we would cancel any loop_dead flag + * XXX: also cancel in dead_loop timeout that's running + */ + + /* * Now check whether we should even think about pursuing this. */ lp = &fcp->portdb[target]; @@ -2116,8 +2127,8 @@ ispscsicmd(xs) return (CMD_COMPLETE); } if ((lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT)) == 0) { - IDPRINTF(3, ("%s: target %d is not a target\n", - isp->isp_name, target)); + isp_prt(isp, ISP_LOGDEBUG2, + "Target %d does not have target service", target); XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); } @@ -2136,7 +2147,7 @@ ispscsicmd(xs) } if (isp_getrqentry(isp, &iptr, &optr, (void **) &reqp)) { - IDPRINTF(2, ("%s: Request Queue Overflow\n", isp->isp_name)); + isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow"); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } @@ -2161,12 +2172,11 @@ ispscsicmd(xs) reqp->req_modifier = SYNC_ALL; reqp->req_target = i << 7; /* insert bus number */ ISP_SWIZZLE_REQUEST(isp, reqp); - MemoryBarrier(); ISP_ADD_REQUEST(isp, iptr); if (isp_getrqentry(isp, &iptr, &optr, (void **)&reqp)) { - IDPRINTF(2, ("%s: Request Queue Overflow+\n", - isp->isp_name)); + isp_prt(isp, ISP_LOGDEBUG0, + "Request Queue Overflow+"); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } @@ -2196,9 +2206,13 @@ ispscsicmd(xs) * The Qlogic drivers seem be happy not to use a tag, * but this breaks for some devices (IBM drives). */ - if (XS_CANTAG(xs)) { - t2reqp->req_flags = XS_KINDOF_TAG(xs); + if (XS_TAG_P(xs)) { + t2reqp->req_flags = XS_TAG_TYPE(xs); } else { + /* + * If we don't know what tag to use, use HEAD OF QUEUE + * for Request Sense or Ordered (for safety's sake). + */ if (XS_CDBP(xs)[0] == 0x3) /* REQUEST SENSE */ t2reqp->req_flags = REQFLAG_HTAG; else @@ -2207,8 +2221,8 @@ ispscsicmd(xs) } else { sdparam *sdp = (sdparam *)isp->isp_param; if ((sdp->isp_devparam[target].cur_dflags & DPARM_TQING) && - XS_CANTAG(xs)) { - reqp->req_flags = XS_KINDOF_TAG(xs); + XS_TAG_P(xs)) { + reqp->req_flags = XS_TAG_TYPE(xs); } } reqp->req_target = target | (XS_CHANNEL(xs) << 7); @@ -2235,7 +2249,7 @@ ispscsicmd(xs) reqp->req_time = 5; } if (isp_save_xs(isp, xs, &reqp->req_handle)) { - IDPRINTF(2, ("%s: out of xflist pointers\n", isp->isp_name)); + isp_prt(isp, ISP_LOGDEBUG1, "out of xflist pointers"); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } @@ -2253,10 +2267,9 @@ ispscsicmd(xs) return (i); } XS_SETERR(xs, HBA_NOERROR); - IDPRINTF(5, ("%s(%d.%d.%d): START cmd 0x%x datalen %d\n", - isp->isp_name, XS_CHANNEL(xs), target, XS_LUN(xs), - reqp->req_cdb[0], XS_XFRLEN(xs))); - MemoryBarrier(); + isp_prt(isp, ISP_LOGDEBUG2, + "START cmd for %d.%d.%d cmd 0x%x datalen %d", + XS_CHANNEL(xs), target, XS_LUN(xs), XS_CDBP(xs)[0], XS_XFRLEN(xs)); ISP_ADD_REQUEST(isp, iptr); isp->isp_nactive++; if (isp->isp_sendmarker) @@ -2277,15 +2290,14 @@ isp_control(isp, ctl, arg) ispctl_t ctl; void *arg; { - ISP_SCSI_XFER_T *xs; + XS_T *xs; mbreg_t mbs; int bus, tgt; u_int32_t handle; switch (ctl) { default: - PRINTF("%s: isp_control unknown control op %x\n", - isp->isp_name, ctl); + isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl); break; case ISPCTL_RESET_BUS: @@ -2307,13 +2319,12 @@ isp_control(isp, ctl, arg) bus = 0; } isp->isp_sendmarker |= (1 << bus); - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_dumpregs(isp, "isp_control SCSI bus reset failed"); break; } - CFGPRINTF("%s: driver initiated bus reset of bus %d\n", - isp->isp_name, bus); + isp_prt(isp, ISP_LOGINFO, + "driver initiated bus reset of bus %d", bus); return (0); case ISPCTL_RESET_DEV: @@ -2322,24 +2333,22 @@ isp_control(isp, ctl, arg) mbs.param[0] = MBOX_ABORT_TARGET; mbs.param[1] = (tgt << 8) | (bus << 15); mbs.param[2] = 3; /* 'delay', in seconds */ - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: isp_control MBOX_RESET_DEV failure (code " - "%x)\n", isp->isp_name, mbs.param[0]); break; } - PRINTF("%s: Target %d on Bus %d Reset Succeeded\n", - isp->isp_name, tgt, bus); + isp_prt(isp, ISP_LOGINFO, + "Target %d on Bus %d Reset Succeeded", tgt, bus); isp->isp_sendmarker |= (1 << bus); return (0); case ISPCTL_ABORT_CMD: - xs = (ISP_SCSI_XFER_T *) arg; + xs = (XS_T *) arg; tgt = XS_TGT(xs); handle = isp_find_handle(isp, xs); if (handle == 0) { - PRINTF("%s: isp_control- cannot find command to abort " - "in active list\n", isp->isp_name); + isp_prt(isp, ISP_LOGWARN, + "cannot find handle for command to abort"); break; } bus = XS_CHANNEL(xs); @@ -2359,21 +2368,15 @@ isp_control(isp, ctl, arg) } mbs.param[3] = handle >> 16; mbs.param[2] = handle & 0xffff; - isp_mboxcmd(isp, &mbs); - switch (mbs.param[0]) { - case MBOX_COMMAND_COMPLETE: - IDPRINTF(1, - ("%s: command (handle 0x%x) for %d.%d.%d aborted\n", - isp->isp_name, handle, bus, tgt, XS_LUN(xs))); - /* FALLTHROUGH */ - case MBOX_COMMAND_ERROR: - break; - default: - PRINTF("%s: command (handle 0x%x) abort failed (%x)\n", - isp->isp_name, handle, mbs.param[0]); - break; + isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_ERROR); + if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { + return (0); } - return (0); + /* + * XXX: Look for command in the REQUEST QUEUE. That is, + * XXX: It hasen't been picked up by firmware yet. + */ + break; case ISPCTL_UPDATE_PARAMS: isp_update(isp); @@ -2381,7 +2384,8 @@ isp_control(isp, ctl, arg) case ISPCTL_FCLINK_TEST: if (IS_FC(isp)) { - return (isp_fclink_test(isp, FC_FW_READY_DELAY)); + int usdelay = (arg)? *((int *) arg) : 250000; + return (isp_fclink_test(isp, usdelay)); } break; @@ -2390,22 +2394,46 @@ isp_control(isp, ctl, arg) return (isp_pdb_sync(isp, -1)); } break; - #ifdef ISP_TARGET_MODE case ISPCTL_TOGGLE_TMODE: + { + int ena = *(int *)arg; if (IS_SCSI(isp)) { - int ena = *(int *)arg; mbs.param[0] = MBOX_ENABLE_TARGET_MODE; mbs.param[1] = (ena)? ENABLE_TARGET_FLAG : 0; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: cannot %sable target mode (0x%x)\n", - isp->isp_name, ena? "en" : "dis", - mbs.param[0]); break; } + } else { + fcparam *fcp = isp->isp_param; + /* + * We assume somebody has quiesced this bus. + */ + if (ena) { + if (fcp->isp_fwoptions & ICBOPT_TGT_ENABLE) { + return (0); + } + fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE; + } else { + if (!(fcp->isp_fwoptions & ICBOPT_TGT_ENABLE)) { + return (0); + } + fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE; + } + isp->isp_state = ISP_NILSTATE; + isp_reset(isp); + if (isp->isp_state != ISP_RESETSTATE) { + break; + } + isp_init(isp); + if (isp->isp_state != ISP_INITSTATE) { + break; + } + isp->isp_state = ISP_RUNSTATE; } return (0); + } #endif } return (-1); @@ -2418,12 +2446,18 @@ isp_control(isp, ctl, arg) * and the locking will be held throughout this function. */ +/* + * Limit our stack depth by sticking with the max likely number + * of completions on a request queue at any one time. + */ +#define MAX_REQUESTQ_COMPLETIONS 32 + int isp_intr(arg) void *arg; { - ISP_SCSI_XFER_T *complist[RESULT_QUEUE_LEN], *xs; struct ispsoftc *isp = arg; + XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs; u_int16_t iptr, optr, isr, sema, junk; int i, nlooked = 0, ndone = 0; @@ -2434,8 +2468,8 @@ isp_intr(arg) junk = ISP_READ(isp, BIU_ISR); } while (isr != junk && ++i < 1000); if (isr != junk) { - PRINTF("%s: isr unsteady (%x, %x)\n", - isp->isp_name, isr, junk); + isp_prt(isp, ISP_LOGWARN, + "isr unsteady (%x, %x)", isr, junk); } i = 0; do { @@ -2443,14 +2477,14 @@ isp_intr(arg) junk = ISP_READ(isp, BIU_SEMA); } while (sema != junk && ++i < 1000); if (sema != junk) { - PRINTF("%s: sema unsteady (%x, %x)\n", - isp->isp_name, sema, junk); + isp_prt(isp, ISP_LOGWARN, + "sema unsteady (%x, %x)", sema, junk); } } else { isr = ISP_READ(isp, BIU_ISR); sema = ISP_READ(isp, BIU_SEMA); } - IDPRINTF(5, ("%s: isp_intr isr %x sem %x\n", isp->isp_name, isr, sema)); + isp_prt(isp, ISP_LOGDEBUG3, "isp_intr isr %x sem %x", isr, sema); isr &= INT_PENDING_MASK(isp); sema &= BIU_SEMA_LOCK; if (isr == 0 && sema == 0) { @@ -2467,8 +2501,8 @@ isp_intr(arg) junk = ISP_READ(isp, OUTMAILBOX0);; } while (junk != mbox && ++i < 1000); if (mbox != junk) { - PRINTF("%s: mailbox0 unsteady (%x, %x)\n", - isp->isp_name, mbox, junk); + isp_prt(isp, ISP_LOGWARN, + "mailbox0 unsteady (%x, %x)", mbox, junk); ISP_WRITE(isp, BIU_SEMA, 0); ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); return (1); @@ -2489,13 +2523,13 @@ isp_intr(arg) } MBOX_NOTIFY_COMPLETE(isp); } else { - PRINTF("%s: Command Mbox 0x%x\n", - isp->isp_name, mbox); + isp_prt(isp, ISP_LOGWARN, + "Mbox Command Async (0x%x) with no waiters", + mbox); } } else { u_int32_t fhandle = isp_parse_async(isp, (int) mbox); - IDPRINTF(4, ("%s: Async Mbox 0x%x\n", - isp->isp_name, mbox)); + isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox); if (fhandle > 0) { isp_fastpost_complete(isp, fhandle); } @@ -2511,8 +2545,8 @@ isp_intr(arg) * We can't be getting this now. */ if (isp->isp_state != ISP_RUNSTATE) { - PRINTF("%s: interrupt (isr=%x, sema=%x) when not ready\n", - isp->isp_name, isr, sema); + isp_prt(isp, ISP_LOGWARN, + "interrupt (isr=%x, sema=%x) when not ready", isr, sema); ISP_WRITE(isp, INMAILBOX5, ISP_READ(isp, OUTMAILBOX5)); ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); ISP_WRITE(isp, BIU_SEMA, 0); @@ -2533,8 +2567,8 @@ isp_intr(arg) if (iptr != junk) { ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - PRINTF("%s: mailbox5 unsteady (%x, %x)\n", - isp->isp_name, iptr, junk); + isp_prt(isp, ISP_LOGWARN, + "mailbox5 unsteady (%x, %x)", iptr, junk); return (1); } } else { @@ -2556,8 +2590,9 @@ isp_intr(arg) * effects), but that didn't stop this from occurring. */ junk = ISP_READ(isp, BIU_ISR); - IDPRINTF(2, ("%s: null intr- isr %x (%x) iptr %x optr %x\n", - isp->isp_name, isr, junk, iptr, optr)); + isp_prt(isp, ISP_LOGDEBUG2, + "bogus intr- isr %x (%x) iptr %x optr %x", + isr, junk, iptr, optr); } while (optr != iptr) { @@ -2567,17 +2602,17 @@ isp_intr(arg) sp = (ispstatusreq_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr); oop = optr; - optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN); + optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp)); nlooked++; - MemoryBarrier(); /* * Do any appropriate unswizzling of what the Qlogic f/w has * written into memory so it makes sense to us. This is a - * per-platform thing. + * per-platform thing. Also includes any memory barriers. */ - ISP_UNSWIZZLE_RESPONSE(isp, sp); + ISP_UNSWIZZLE_RESPONSE(isp, sp, oop); if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) { if (isp_handle_other_response(isp, sp, &optr) == 0) { + MEMZERO(sp, sizeof (isphdr_t)); continue; } /* @@ -2586,10 +2621,9 @@ isp_intr(arg) * not, something bad has happened. */ if (sp->req_header.rqs_entry_type != RQSTYPE_REQUEST) { - PRINTF("%s: not RESPONSE in RESPONSE Queue " - "(type 0x%x) @ idx %d (next %d)\n", - isp->isp_name, + isp_prt(isp, ISP_LOGERR, notresp, sp->req_header.rqs_entry_type, oop, optr); + MEMZERO(sp, sizeof (isphdr_t)); continue; } buddaboom = 1; @@ -2599,44 +2633,47 @@ isp_intr(arg) #define _RQS_OFLAGS \ ~(RQSFLAG_CONTINUATION|RQSFLAG_FULL|RQSFLAG_BADHEADER|RQSFLAG_BADPACKET) if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) { - IDPRINTF(4, ("%s: continuation segment\n", - isp->isp_name)); + isp_prt(isp, ISP_LOGWARN, + "continuation segment"); ISP_WRITE(isp, INMAILBOX5, optr); continue; } if (sp->req_header.rqs_flags & RQSFLAG_FULL) { - IDPRINTF(2, ("%s: internal queues full\n", - isp->isp_name)); + isp_prt(isp, ISP_LOGDEBUG1, + "internal queues full"); /* * We'll synthesize a QUEUE FULL message below. */ } if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) { - PRINTF("%s: bad header\n", isp->isp_name); + isp_prt(isp, ISP_LOGERR, "bad header flag"); buddaboom++; } if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) { - PRINTF("%s: bad request packet\n", - isp->isp_name); + isp_prt(isp, ISP_LOGERR, "bad request packet"); buddaboom++; } if (sp->req_header.rqs_flags & _RQS_OFLAGS) { - PRINTF("%s: unknown flags in response (0x%x)\n", - isp->isp_name, sp->req_header.rqs_flags); + 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) { - PRINTF("%s: bad request handle %d\n", isp->isp_name, - sp->req_handle); + MEMZERO(sp, sizeof (isphdr_t)); + isp_prt(isp, ISP_LOGERR, + "bad request handle %d", sp->req_handle); ISP_WRITE(isp, INMAILBOX5, optr); continue; } xs = isp_find_xs(isp, sp->req_handle); if (xs == NULL) { - PRINTF("%s: NULL xs in xflist (handle 0x%x)\n", - isp->isp_name, sp->req_handle); + MEMZERO(sp, sizeof (isphdr_t)); + isp_prt(isp, ISP_LOGERR, + "cannot find handle 0x%x in xflist", + sp->req_handle); ISP_WRITE(isp, INMAILBOX5, optr); continue; } @@ -2647,92 +2684,119 @@ isp_intr(arg) if (buddaboom) { XS_SETERR(xs, HBA_BOTCH); } - XS_STS(xs) = sp->req_scsi_status & 0xff; - if (IS_SCSI(isp)) { - if (sp->req_state_flags & RQSF_GOT_SENSE) { - MEMCPY(XS_SNSP(xs), sp->req_sense_data, - XS_SNSLEN(xs)); - XS_SNS_IS_VALID(xs); - } + + if (IS_FC(isp) && (sp->req_scsi_status & RQCS_SV)) { /* - * A new synchronous rate was negotiated for this - * target. Mark state such that we'll go look up - * that which has changed later. + * 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. */ - if (sp->req_status_flags & RQSTF_NEGOTIATION) { - sdparam *sdp = isp->isp_param; - sdp += XS_CHANNEL(xs); - sdp->isp_devparam[XS_TGT(xs)].dev_refresh = 1; - isp->isp_update |= (1 << XS_CHANNEL(xs)); - } - } else { - if (sp->req_scsi_status & RQCS_SV) { - int amt = min(XS_SNSLEN(xs), sp->req_sense_len); - MEMCPY(XS_SNSP(xs), sp->req_sense_data, amt); - XS_SNS_IS_VALID(xs); - sp->req_state_flags |= RQSF_GOT_SENSE; - } else if (XS_STS(xs) == SCSI_CHECK) { - IDPRINTF(2, - ("%s: check condition with no sense data\n", - isp->isp_name)); - } + sp->req_state_flags |= RQSF_GOT_STATUS; } - if (XS_NOERR(xs) && XS_STS(xs) == SCSI_BUSY) { - XS_SETERR(xs, HBA_TGTBSY); + if (sp->req_state_flags & RQSF_GOT_STATUS) { + *XS_STSP(xs) = sp->req_scsi_status & 0xff; } - if (sp->req_header.rqs_entry_type == RQSTYPE_RESPONSE) { - if (XS_NOERR(xs)) { - if (sp->req_completion_status != RQCS_COMPLETE) { - isp_parse_status(isp, sp, xs); - } else { - XS_SETERR(xs, HBA_NOERROR); - } + switch (sp->req_header.rqs_entry_type) { + case RQSTYPE_RESPONSE: + XS_SET_STATE_STAT(isp, xs, sp); + isp_parse_status(isp, sp, xs); + 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); + } + /* + * 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) { + int t = XS_TGT(xs); + sdparam *sdp = isp->isp_param; + sdp += XS_CHANNEL(xs); + sdp->isp_devparam[t].dev_refresh = 1; + isp->isp_update |= + (1 << XS_CHANNEL(xs)); + } + } else { + if (sp->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 { + 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); + } } - } else if (sp->req_header.rqs_entry_type == RQSTYPE_REQUEST) { + isp_prt(isp, ISP_LOGDEBUG2, "asked for %d got resid %d", + XS_XFRLEN(xs), sp->req_resid); + break; + case RQSTYPE_REQUEST: if (sp->req_header.rqs_flags & RQSFLAG_FULL) { /* * Force Queue Full status. */ - XS_STS(xs) = SCSI_QFULL; + *XS_STSP(xs) = SCSI_QFULL; XS_SETERR(xs, HBA_NOERROR); } else if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BOTCH); } - } else { - PRINTF("%s: unhandled respose queue type 0x%x\n", - isp->isp_name, sp->req_header.rqs_entry_type); + XS_RESID(xs) = XS_XFRLEN(xs); + break; + default: + isp_prt(isp, ISP_LOGWARN, + "unhandled respose queue type 0x%x", + sp->req_header.rqs_entry_type); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BOTCH); } + break; } - if (IS_SCSI(isp)) { - XS_RESID(xs) = sp->req_resid; - } else if (sp->req_scsi_status & RQCS_RU) { - XS_RESID(xs) = sp->req_resid; - IDPRINTF(4, ("%s: cnt %d rsd %d\n", isp->isp_name, - XS_XFRLEN(xs), sp->req_resid)); - } + + /* + * 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 >= 5) || - (isp->isp_dblev > 2 && !XS_NOERR(xs))) { - PRINTF("%s(%d.%d): FIN dl%d resid%d STS %x", - isp->isp_name, XS_TGT(xs), XS_LUN(xs), - XS_XFRLEN(xs), XS_RESID(xs), XS_STS(xs)); + + if (((isp->isp_dblev & (ISP_LOGDEBUG2|ISP_LOGDEBUG3))) || + ((isp->isp_dblev & ISP_LOGDEBUG1) && !XS_NOERR(xs))) { + char skey; if (sp->req_state_flags & RQSF_GOT_SENSE) { - PRINTF(" Skey: %x", XS_SNSKEY(xs)); - if (!(XS_IS_SNS_VALID(xs))) { - PRINTF(" BUT NOT SET"); - } + skey = XS_SNSKEY(xs) & 0xf; + if (skey < 10) + skey += '0'; + else + skey += 'a'; + } else if (*XS_STSP(xs) == SCSI_CHECK) { + skey = '?'; + } else { + skey = '.'; } - PRINTF(" XS_ERR=0x%x\n", (unsigned int) XS_ERR(xs)); + isp_prt(isp, ISP_LOGALL, finmsg, XS_CHANNEL(xs), + XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs), XS_RESID(xs), + *XS_STSP(xs), skey, XS_ERR(xs)); } if (isp->isp_nactive > 0) isp->isp_nactive--; complist[ndone++] = xs; /* defer completion call until later */ + MEMZERO(sp, sizeof (isphdr_t)); + if (ndone == MAX_REQUESTQ_COMPLETIONS) { + break; + } } /* @@ -2749,7 +2813,7 @@ isp_intr(arg) for (i = 0; i < ndone; i++) { xs = complist[i]; if (xs) { - XS_CMD_DONE(xs); + isp_done(xs); } } return (1); @@ -2774,8 +2838,6 @@ isp_parse_async(isp, mbox) } switch (mbox) { - case MBOX_COMMAND_COMPLETE: /* sometimes these show up */ - break; case ASYNC_BUS_RESET: isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE @@ -2785,18 +2847,18 @@ isp_parse_async(isp, mbox) break; case ASYNC_SYSTEM_ERROR: mbox = ISP_READ(isp, OUTMAILBOX1); - PRINTF("%s: Internal FW Error @ RISC Addr 0x%x\n", - isp->isp_name, mbox); - isp_restart(isp); + isp_prt(isp, ISP_LOGERR, + "Internal FW Error @ RISC Addr 0x%x", mbox); + isp_reinit(isp); /* no point continuing after this */ return (-1); case ASYNC_RQS_XFER_ERR: - PRINTF("%s: Request Queue Transfer Error\n", isp->isp_name); + isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error"); break; case ASYNC_RSP_XFER_ERR: - PRINTF("%s: Response Queue Transfer Error\n", isp->isp_name); + isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error"); break; case ASYNC_QWAKEUP: @@ -2809,8 +2871,8 @@ isp_parse_async(isp, mbox) break; case ASYNC_TIMEOUT_RESET: - PRINTF("%s: timeout initiated SCSI bus reset of bus %d\n", - isp->isp_name, bus); + isp_prt(isp, ISP_LOGWARN, + "timeout initiated SCSI bus reset of bus %d\n", bus); isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE isp_target_async(isp, bus, mbox); @@ -2818,7 +2880,7 @@ isp_parse_async(isp, mbox) break; case ASYNC_DEVICE_RESET: - PRINTF("%s: device reset on bus %d\n", isp->isp_name, bus); + isp_prt(isp, ISP_LOGINFO, "device reset on bus %d", bus); isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE isp_target_async(isp, bus, mbox); @@ -2826,50 +2888,49 @@ isp_parse_async(isp, mbox) break; case ASYNC_EXTMSG_UNDERRUN: - PRINTF("%s: extended message underrun\n", isp->isp_name); + isp_prt(isp, ISP_LOGWARN, "extended message underrun"); break; case ASYNC_SCAM_INT: - PRINTF("%s: SCAM interrupt\n", isp->isp_name); + isp_prt(isp, ISP_LOGINFO, "SCAM interrupt"); break; case ASYNC_HUNG_SCSI: - PRINTF("%s: stalled SCSI Bus after DATA Overrun\n", - isp->isp_name); + isp_prt(isp, ISP_LOGERR, + "stalled SCSI Bus after DATA Overrun"); /* XXX: Need to issue SCSI reset at this point */ break; case ASYNC_KILLED_BUS: - PRINTF("%s: SCSI Bus reset after DATA Overrun\n", - isp->isp_name); + isp_prt(isp, ISP_LOGERR, "SCSI Bus reset after DATA Overrun"); break; case ASYNC_BUS_TRANSIT: mbox = ISP_READ(isp, OUTMAILBOX2); switch (mbox & 0x1c00) { case SXP_PINS_LVD_MODE: - PRINTF("%s: Transition to LVD mode\n", isp->isp_name); - ((sdparam *)isp->isp_param)->isp_diffmode = 0; - ((sdparam *)isp->isp_param)->isp_ultramode = 0; - ((sdparam *)isp->isp_param)->isp_lvdmode = 1; + isp_prt(isp, ISP_LOGINFO, "Transition to LVD mode"); + SDPARAM(isp)->isp_diffmode = 0; + SDPARAM(isp)->isp_ultramode = 0; + SDPARAM(isp)->isp_lvdmode = 1; break; case SXP_PINS_HVD_MODE: - PRINTF("%s: Transition to Differential mode\n", - isp->isp_name); - ((sdparam *)isp->isp_param)->isp_diffmode = 1; - ((sdparam *)isp->isp_param)->isp_ultramode = 0; - ((sdparam *)isp->isp_param)->isp_lvdmode = 0; + isp_prt(isp, ISP_LOGINFO, + "Transition to Differential mode"); + SDPARAM(isp)->isp_diffmode = 1; + SDPARAM(isp)->isp_ultramode = 0; + SDPARAM(isp)->isp_lvdmode = 0; break; case SXP_PINS_SE_MODE: - PRINTF("%s: Transition to Single Ended mode\n", - isp->isp_name); - ((sdparam *)isp->isp_param)->isp_diffmode = 0; - ((sdparam *)isp->isp_param)->isp_ultramode = 1; - ((sdparam *)isp->isp_param)->isp_lvdmode = 0; + isp_prt(isp, ISP_LOGINFO, + "Transition to Single Ended mode"); + SDPARAM(isp)->isp_diffmode = 0; + SDPARAM(isp)->isp_ultramode = 1; + SDPARAM(isp)->isp_lvdmode = 0; break; default: - PRINTF("%s: Transition to unknown mode 0x%x\n", - isp->isp_name, mbox); + isp_prt(isp, ISP_LOGWARN, + "Transition to Unknown Mode 0x%x", mbox); break; } /* @@ -2882,23 +2943,32 @@ isp_parse_async(isp, mbox) case ASYNC_CMD_CMPLT: fast_post_handle = (ISP_READ(isp, OUTMAILBOX2) << 16) | ISP_READ(isp, OUTMAILBOX1); - IDPRINTF(4, ("%s: fast post completion of %u\n", isp->isp_name, - fast_post_handle)); + isp_prt(isp, ISP_LOGDEBUG3, "fast post completion of %u", + fast_post_handle); break; case ASYNC_CTIO_DONE: - /* Should only occur when Fast Posting Set for 2100s */ - PRINTF("%s: CTIO done\n", isp->isp_name); +#ifdef ISP_TARGET_MODE + /* + * Bus gets overloaded with the handle. Dual bus + * cards don't put bus# into the handle. + */ + bus = (ISP_READ(isp, OUTMAILBOX2) << 16) | + ISP_READ(isp, OUTMAILBOX1); + isp_target_async(isp, bus, mbox); +#else + isp_prt(isp, ISP_LOGINFO, "Fast Posting CTIO done"); +#endif break; case ASYNC_LIP_OCCURRED: - ((fcparam *) isp->isp_param)->isp_lipseq = + FCPARAM(isp)->isp_lipseq = ISP_READ(isp, OUTMAILBOX1); - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD; + FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; + FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp->isp_sendmarker = 1; isp_mark_getpdb_all(isp); - IDPRINTF(1, ("%s: LIP occurred\n", isp->isp_name)); + isp_prt(isp, ISP_LOGINFO, "LIP occurred"); #ifdef ISP_TARGET_MODE isp_target_async(isp, bus, mbox); #endif @@ -2906,8 +2976,8 @@ isp_parse_async(isp, mbox) case ASYNC_LOOP_UP: isp->isp_sendmarker = 1; - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD; + FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; + FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp_mark_getpdb_all(isp); isp_async(isp, ISPASYNC_LOOP_UP, NULL); #ifdef ISP_TARGET_MODE @@ -2917,8 +2987,8 @@ isp_parse_async(isp, mbox) case ASYNC_LOOP_DOWN: isp->isp_sendmarker = 1; - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL; + FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; + FCPARAM(isp)->isp_loopstate = LOOP_NIL; isp_mark_getpdb_all(isp); isp_async(isp, ISPASYNC_LOOP_DOWN, NULL); #ifdef ISP_TARGET_MODE @@ -2928,10 +2998,10 @@ isp_parse_async(isp, mbox) case ASYNC_LOOP_RESET: isp->isp_sendmarker = 1; - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL; + FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; + FCPARAM(isp)->isp_loopstate = LOOP_NIL; isp_mark_getpdb_all(isp); - PRINTF("%s: Loop RESET\n", isp->isp_name); + isp_prt(isp, ISP_LOGINFO, "Loop RESET"); #ifdef ISP_TARGET_MODE isp_target_async(isp, bus, mbox); #endif @@ -2939,9 +3009,9 @@ isp_parse_async(isp, mbox) case ASYNC_PDB_CHANGED: isp->isp_sendmarker = 1; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD; + FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; isp_mark_getpdb_all(isp); - IDPRINTF(1, ("%s: Port Database Changed\n", isp->isp_name)); + isp_prt(isp, ISP_LOGINFO, "Port Database Changed"); break; case ASYNC_CHANGE_NOTIFY: @@ -2949,54 +3019,52 @@ isp_parse_async(isp, mbox) /* * Not correct, but it will force us to rescan the loop. */ - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD; + FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; isp_async(isp, ISPASYNC_CHANGE_NOTIFY, NULL); break; case ASYNC_PTPMODE: - if (((fcparam *) isp->isp_param)->isp_onfabric) - ((fcparam *) isp->isp_param)->isp_topo = TOPO_N_PORT; + if (FCPARAM(isp)->isp_onfabric) + FCPARAM(isp)->isp_topo = TOPO_N_PORT; else - ((fcparam *) isp->isp_param)->isp_topo = TOPO_F_PORT; + FCPARAM(isp)->isp_topo = TOPO_F_PORT; isp_mark_getpdb_all(isp); isp->isp_sendmarker = 1; - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD; + FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; + FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; #ifdef ISP_TARGET_MODE isp_target_async(isp, bus, mbox); #endif - PRINTF("%s: Point-to-Point mode\n", isp->isp_name); + isp_prt(isp, ISP_LOGINFO, "Point-to-Point mode"); break; case ASYNC_CONNMODE: mbox = ISP_READ(isp, OUTMAILBOX1); switch (mbox) { case ISP_CONN_LOOP: - PRINTF("%s: Point-to-Point -> Loop mode\n", - isp->isp_name); + isp_prt(isp, ISP_LOGINFO, "Point-to-Point->Loop mode"); break; case ISP_CONN_PTP: - PRINTF("%s: Loop -> Point-to-Point mode\n", - isp->isp_name); + isp_prt(isp, ISP_LOGINFO, "Loop->Point-to-Point mode"); break; case ISP_CONN_BADLIP: - PRINTF("%s: Point-to-Point -> Loop mode (1)\n", - isp->isp_name); + isp_prt(isp, ISP_LOGWARN, + "Point-to-Point->Loop mode (1)"); break; case ISP_CONN_FATAL: - PRINTF("%s: FATAL CONNECTION ERROR\n", isp->isp_name); - isp_restart(isp); + isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR"); + isp_reinit(isp); /* no point continuing after this */ return (-1); case ISP_CONN_LOOPBACK: - PRINTF("%s: Looped Back in Point-to-Point mode\n", - isp->isp_name); + isp_prt(isp, ISP_LOGWARN, + "Looped Back in Point-to-Point mode"); } break; default: - PRINTF("%s: unknown async code 0x%x\n", isp->isp_name, mbox); + isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox); break; } return (fast_post_handle); @@ -3015,6 +3083,9 @@ isp_handle_other_response(isp, sp, optrp) u_int16_t *optrp; { switch (sp->req_header.rqs_entry_type) { + case RQSTYPE_STATUS_CONT: + isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response"); + return (0); case RQSTYPE_ATIO: case RQSTYPE_CTIO: case RQSTYPE_ENABLE_LUN: @@ -3028,11 +3099,12 @@ isp_handle_other_response(isp, sp, optrp) #ifdef ISP_TARGET_MODE return (isp_target_notify(isp, sp, optrp)); #else + optrp = optrp; /* FALLTHROUGH */ #endif case RQSTYPE_REQUEST: default: - PRINTF("%s: unhandled response type 0x%x\n", isp->isp_name, + isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x", sp->req_header.rqs_entry_type); return (-1); } @@ -3042,189 +3114,258 @@ static void isp_parse_status(isp, sp, xs) struct ispsoftc *isp; ispstatusreq_t *sp; - ISP_SCSI_XFER_T *xs; + XS_T *xs; { - switch (sp->req_completion_status) { + switch (sp->req_completion_status & 0xff) { case RQCS_COMPLETE: - XS_SETERR(xs, HBA_NOERROR); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_NOERROR); + } return; case RQCS_INCOMPLETE: if ((sp->req_state_flags & RQSF_GOT_TARGET) == 0) { - IDPRINTF(3, ("%s: Selection Timeout for %d.%d.%d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs), - XS_CHANNEL(xs))); - XS_SETERR(xs, HBA_SELTIMEOUT); + isp_prt(isp, ISP_LOGDEBUG1, + "Selection Timeout for %d.%d.%d", + XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + } return; } - PRINTF("%s: command incomplete for %d.%d.%d, state 0x%x\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), + isp_prt(isp, ISP_LOGERR, + "command incomplete for %d.%d.%d, state 0x%x", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), sp->req_state_flags); break; case RQCS_DMA_ERROR: - PRINTF("%s: DMA error for command on %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + 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: - PRINTF("%s: transport error for %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); - isp_prtstst(sp); + { + char buf[172]; + buf[0] = 0; + STRNCAT(buf, "states=>", sizeof buf); + if (sp->req_state_flags & RQSF_GOT_BUS) { + STRNCAT(buf, " GOT_BUS", sizeof buf); + } + if (sp->req_state_flags & RQSF_GOT_TARGET) { + STRNCAT(buf, " GOT_TGT", sizeof buf); + } + if (sp->req_state_flags & RQSF_SENT_CDB) { + STRNCAT(buf, " SENT_CDB", sizeof buf); + } + if (sp->req_state_flags & RQSF_XFRD_DATA) { + STRNCAT(buf, " XFRD_DATA", sizeof buf); + } + if (sp->req_state_flags & RQSF_GOT_STATUS) { + STRNCAT(buf, " GOT_STS", sizeof buf); + } + if (sp->req_state_flags & RQSF_GOT_SENSE) { + STRNCAT(buf, " GOT_SNS", sizeof buf); + } + if (sp->req_state_flags & RQSF_XFER_COMPLETE) { + STRNCAT(buf, " XFR_CMPLT", sizeof buf); + } + STRNCAT(buf, "\nstatus=>", sizeof buf); + if (sp->req_status_flags & RQSTF_DISCONNECT) { + STRNCAT(buf, " Disconnect", sizeof buf); + } + if (sp->req_status_flags & RQSTF_SYNCHRONOUS) { + STRNCAT(buf, " Sync_xfr", sizeof buf); + } + if (sp->req_status_flags & RQSTF_PARITY_ERROR) { + STRNCAT(buf, " Parity", sizeof buf); + } + if (sp->req_status_flags & RQSTF_BUS_RESET) { + STRNCAT(buf, " Bus_Reset", sizeof buf); + } + if (sp->req_status_flags & RQSTF_DEVICE_RESET) { + STRNCAT(buf, " Device_Reset", sizeof buf); + } + if (sp->req_status_flags & RQSTF_ABORTED) { + STRNCAT(buf, " Aborted", sizeof buf); + } + if (sp->req_status_flags & RQSTF_TIMEOUT) { + STRNCAT(buf, " Timeout", sizeof buf); + } + if (sp->req_status_flags & RQSTF_NEGOTIATION) { + STRNCAT(buf, " Negotiation", sizeof buf); + } + 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); break; - + } case RQCS_RESET_OCCURRED: - IDPRINTF(1, ("%s: bus reset destroyed command for %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs))); + 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)); - XS_SETERR(xs, HBA_BUSRESET); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_BUSRESET); + } return; case RQCS_ABORTED: - PRINTF("%s: command aborted for %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + 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)); - XS_SETERR(xs, HBA_ABORTED); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_ABORTED); + } return; case RQCS_TIMEOUT: - IDPRINTF(2, ("%s: command timed out for %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs))); - XS_SETERR(xs, HBA_CMDTIMEOUT); + 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: - if (IS_FC(isp)) { - XS_RESID(xs) = sp->req_resid; - break; + 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); } - PRINTF("%s: data overrun for command on %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); - XS_SETERR(xs, HBA_DATAOVR); return; case RQCS_COMMAND_OVERRUN: - PRINTF("%s: command overrun for command on %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, + "command overrun for command on %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_STATUS_OVERRUN: - PRINTF("%s: status overrun for command on %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, + "status overrun for command on %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_BAD_MESSAGE: - PRINTF("%s: msg not COMMAND COMPLETE after status %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, + "msg not COMMAND COMPLETE after status %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_NO_MESSAGE_OUT: - PRINTF("%s: No MESSAGE OUT phase after selection on %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, + "No MESSAGE OUT phase after selection on %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_EXT_ID_FAILED: - PRINTF("%s: EXTENDED IDENTIFY failed %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, "EXTENDED IDENTIFY failed %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_IDE_MSG_FAILED: - PRINTF("%s: INITIATOR DETECTED ERROR rejected by %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, + "INITIATOR DETECTED ERROR rejected by %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_ABORT_MSG_FAILED: - PRINTF("%s: ABORT OPERATION rejected by %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, "ABORT OPERATION rejected by %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_REJECT_MSG_FAILED: - PRINTF("%s: MESSAGE REJECT rejected by %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, "MESSAGE REJECT rejected by %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_NOP_MSG_FAILED: - PRINTF("%s: NOP rejected by %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, "NOP rejected by %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_PARITY_ERROR_MSG_FAILED: - PRINTF("%s: MESSAGE PARITY ERROR rejected by %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, + "MESSAGE PARITY ERROR rejected by %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_DEVICE_RESET_MSG_FAILED: - PRINTF("%s: BUS DEVICE RESET rejected by %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGWARN, + "BUS DEVICE RESET rejected by %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_ID_MSG_FAILED: - PRINTF("%s: IDENTIFY rejected by %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, "IDENTIFY rejected by %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_UNEXP_BUS_FREE: - PRINTF("%s: %d.%d.%d had an unexpected bus free\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, "%d.%d.%d had an unexpected bus free", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_DATA_UNDERRUN: - if (IS_FC(isp)) { - XS_RESID(xs) = sp->req_resid; + XS_RESID(xs) = sp->req_resid; + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_NOERROR); } - XS_SETERR(xs, HBA_NOERROR); return; case RQCS_XACT_ERR1: - PRINTF("%s: HBA attempted queued transaction with disconnect " - "not set for %d.%d.%d\n", isp->isp_name, XS_CHANNEL(xs), + isp_prt(isp, ISP_LOGERR, xact1, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); break; case RQCS_XACT_ERR2: - PRINTF("%s: HBA attempted queued transaction to target " - "routine %d on target %d, bus %d\n", isp->isp_name, + isp_prt(isp, ISP_LOGERR, xact2, XS_LUN(xs), XS_TGT(xs), XS_CHANNEL(xs)); break; case RQCS_XACT_ERR3: - PRINTF("%s: HBA attempted queued transaction for target %d lun " - "%d on bus %d when queueing disabled\n", isp->isp_name, - XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp_prt(isp, ISP_LOGERR, xact3, XS_TGT(xs), + XS_LUN(xs), XS_CHANNEL(xs)); break; case RQCS_BAD_ENTRY: - PRINTF("%s: invalid IOCB entry type detected\n", isp->isp_name); + isp_prt(isp, ISP_LOGERR, "Invalid IOCB entry type detected"); break; case RQCS_QUEUE_FULL: - IDPRINTF(3, ("%s: internal queues full for target %d lun %d " - "bus %d, status 0x%x\n", isp->isp_name, XS_TGT(xs), - XS_LUN(xs), XS_CHANNEL(xs), XS_STS(xs))); + isp_prt(isp, ISP_LOGDEBUG1, + "internal queues full for %d.%d.%d status 0x%x", XS_TGT(xs), + XS_LUN(xs), XS_CHANNEL(xs), *XS_STSP(xs)); /* * If QFULL or some other status byte is set, then this * isn't an error, per se. */ - if (XS_STS(xs) != 0) { + if (*XS_STSP(xs) != SCSI_GOOD && XS_NOERR(xs)) { XS_SETERR(xs, HBA_NOERROR); return; } break; case RQCS_PHASE_SKIPPED: - PRINTF("%s: SCSI phase skipped (e.g., COMMAND COMPLETE w/o " - "STATUS phase) for target %d lun %d bus %d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp_prt(isp, ISP_LOGERR, pskip, + XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); break; case RQCS_ARQS_FAILED: - PRINTF("%s: Auto Request Sense failed for %d.%d.%d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp_prt(isp, ISP_LOGERR, + "Auto Request Sense failed for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_ARQFAIL); + } return; case RQCS_WIDE_FAILED: - PRINTF("%s: Wide Negotiation failed for %d.%d.%d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp_prt(isp, ISP_LOGERR, + "Wide Negotiation failed for %d.%d.%d", + XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); if (IS_SCSI(isp)) { sdparam *sdp = isp->isp_param; sdp += XS_CHANNEL(xs); @@ -3232,12 +3373,15 @@ isp_parse_status(isp, sp, xs) sdp->isp_devparam[XS_TGT(xs)].dev_update = 1; isp->isp_update |= (1 << XS_CHANNEL(xs)); } - XS_SETERR(xs, HBA_NOERROR); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_NOERROR); + } return; case RQCS_SYNCXFER_FAILED: - PRINTF("%s: SDTR Message failed for target %d.%d.%d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp_prt(isp, ISP_LOGERR, + "SDTR Message failed for target %d.%d.%d", + XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); if (IS_SCSI(isp)) { sdparam *sdp = isp->isp_param; sdp += XS_CHANNEL(xs); @@ -3248,46 +3392,57 @@ isp_parse_status(isp, sp, xs) break; case RQCS_LVD_BUSERR: - PRINTF("%s: Bad LVD condition while talking to %d.%d.%d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp_prt(isp, ISP_LOGERR, + "Bad LVD condition while talking to %d.%d.%d", + XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); break; case RQCS_PORT_UNAVAILABLE: /* * No such port on the loop. Moral equivalent of SELTIMEO */ - IDPRINTF(3, ("%s: Port Unavailable for target %d\n", - isp->isp_name, XS_TGT(xs))); - XS_SETERR(xs, HBA_SELTIMEOUT); + isp_prt(isp, ISP_LOGINFO, + "Port Unavailable for target %d", XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + } return; case RQCS_PORT_LOGGED_OUT: /* * It was there (maybe)- treat as a selection timeout. */ - IDPRINTF(2, ("%s: port logout for target %d\n", - isp->isp_name, XS_TGT(xs))); - XS_SETERR(xs, HBA_SELTIMEOUT); + isp_prt(isp, ISP_LOGINFO, + "port logout for target %d", XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + } return; case RQCS_PORT_CHANGED: - PRINTF("%s: port changed for target %d\n", - isp->isp_name, XS_TGT(xs)); - XS_SETERR(xs, HBA_SELTIMEOUT); + 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: - PRINTF("%s: port busy for target %d\n", - isp->isp_name, XS_TGT(xs)); - XS_SETERR(xs, HBA_TGTBSY); + isp_prt(isp, ISP_LOGWARN, + "port busy for target %d", XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_TGTBSY); + } return; default: - PRINTF("%s: completion status 0x%x\n", - isp->isp_name, sp->req_completion_status); + isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x", + sp->req_completion_status); break; } - XS_SETERR(xs, HBA_BOTCH); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_BOTCH); + } } static void @@ -3295,15 +3450,15 @@ isp_fastpost_complete(isp, fph) struct ispsoftc *isp; u_int32_t fph; { - ISP_SCSI_XFER_T *xs; + XS_T *xs; if (fph < 1) { return; } xs = isp_find_xs(isp, fph); if (xs == NULL) { - PRINTF("%s: command for fast posting handle 0x%x not found\n", - isp->isp_name, fph); + isp_prt(isp, ISP_LOGWARN, + "Command for fast post handle 0x%x not found", fph); return; } isp_destroy_handle(isp, fph); @@ -3313,14 +3468,15 @@ isp_fastpost_complete(isp, fph) * we must believe that SCSI status is zero and * that all data transferred. */ + XS_SET_STATE_STAT(isp, xs, NULL); XS_RESID(xs) = 0; - XS_STS(xs) = 0; + *XS_STSP(xs) = SCSI_GOOD; if (XS_XFRLEN(xs)) { ISP_DMAFREE(isp, xs, fph); } - XS_CMD_DONE(xs); if (isp->isp_nactive) isp->isp_nactive--; + isp_done(xs); } #define HIBYT(x) ((x) >> 0x8) @@ -3423,6 +3579,105 @@ static u_int16_t mbpscsi[] = { ISPOPMAP(0x01, 0x01) /* 0x5d: GET NOST DATA */ }; +#ifndef ISP_STRIPEED +static char *scsi_mbcmd_names[] = { + "NO-OP", + "LOAD RAM", + "EXEC FIRMWARE", + "DUMP RAM", + "WRITE RAM WORD", + "READ RAM WORD", + "MAILBOX REG TEST", + "VERIFY CHECKSUM", + "ABOUT FIRMWARE", + NULL, + NULL, + NULL, + NULL, + NULL, + "CHECK FIRMWARE", + NULL, + "INIT REQUEST QUEUE", + "INIT RESULT QUEUE", + "EXECUTE IOCB", + "WAKE UP", + "STOP FIRMWARE", + "ABORT", + "ABORT DEVICE", + "ABORT TARGET", + "BUS RESET", + "STOP QUEUE", + "START QUEUE", + "SINGLE STEP QUEUE", + "ABORT QUEUE", + "GET DEV QUEUE STATUS", + NULL, + "GET FIRMWARE STATUS", + "GET INIT SCSI ID", + "GET SELECT TIMEOUT", + "GET RETRY COUNT", + "GET TAG AGE LIMIT", + "GET CLOCK RATE", + "GET ACT NEG STATE", + "GET ASYNC DATA SETUP TIME", + "GET PCI PARAMS", + "GET TARGET PARAMS", + "GET DEV QUEUE PARAMS", + "GET RESET DELAY PARAMS", + NULL, + NULL, + NULL, + NULL, + NULL, + "SET INIT SCSI ID", + "SET SELECT TIMEOUT", + "SET RETRY COUNT", + "SET TAG AGE LIMIT", + "SET CLOCK RATE", + "SET ACT NEG STATE", + "SET ASYNC DATA SETUP TIME", + "SET PCI CONTROL PARAMS", + "SET TARGET PARAMS", + "SET DEV QUEUE PARAMS", + "SET RESET DELAY PARAMS", + NULL, + NULL, + NULL, + NULL, + NULL, + "RETURN BIOS BLOCK ADDR", + "WRITE FOUR RAM WORDS", + "EXEC BIOS IOCB", + NULL, + NULL, + "SET SYSTEM PARAMETER", + "GET SYSTEM PARAMETER", + NULL, + "GET SCAM CONFIGURATION", + "SET SCAM CONFIGURATION", + "SET FIRMWARE FEATURES", + "GET FIRMWARE FEATURES", + NULL, + NULL, + NULL, + NULL, + "LOAD RAM A64", + "DUMP RAM A64", + "INITIALIZE REQUEST QUEUE A64", + "INITIALIZE RESPONSE QUEUE A64", + "EXECUTE IOCB A64", + "ENABLE TARGET MODE", + NULL, + NULL, + NULL, + NULL, + "SET DATA OVERRUN RECOVERY MODE", + "GET DATA OVERRUN RECOVERY MODE", + "SET HOST DATA", + "GET NOST DATA", +}; +#endif + static u_int16_t mbpfc[] = { ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ @@ -3553,11 +3808,145 @@ static u_int16_t mbpfc[] = { ISPOPMAP(0x07, 0x01) /* 0x7e: Lun RESET */ }; +#ifndef ISP_STRIPPED +static char *fc_mbcmd_names[] = { + "NO-OP", + "LOAD RAM", + "EXEC FIRMWARE", + "DUMP RAM", + "WRITE RAM WORD", + "READ RAM WORD", + "MAILBOX REG TEST", + "VERIFY CHECKSUM", + "ABOUT FIRMWARE", + "LOAD RAM", + "DUMP RAM", + NULL, + NULL, + NULL, + "CHECK FIRMWARE", + NULL, + "INIT REQUEST QUEUE", + "INIT RESULT QUEUE", + "EXECUTE IOCB", + "WAKE UP", + "STOP FIRMWARE", + "ABORT", + "ABORT DEVICE", + "ABORT TARGET", + "BUS RESET", + "STOP QUEUE", + "START QUEUE", + "SINGLE STEP QUEUE", + "ABORT QUEUE", + "GET DEV QUEUE STATUS", + NULL, + "GET FIRMWARE STATUS", + "GET LOOP ID", + NULL, + "GET RETRY COUNT", + NULL, + NULL, + NULL, + NULL, + NULL, + "GET FIRMWARE OPTIONS", + "GET PORT QUEUE PARAMS", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "SET RETRY COUNT", + NULL, + NULL, + NULL, + NULL, + NULL, + "SET FIRMWARE OPTIONS", + "SET PORT QUEUE PARAMS", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "LOOP PORT BYPASS", + "LOOP PORT ENABLE", + "GET RESOURCE COUNTS", + "REQUEST NON PARTICIPATING MODE", + NULL, + NULL, + NULL, + "GET PORT DATABASE,, ENHANCED", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "EXECUTE IOCB A64", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "INIT FIRMWARE", + NULL, + "INIT LIP", + "GET FC-AL POSITION MAP", + "GET PORT DATABASE", + "CLEAR ACA", + "TARGET RESET", + "CLEAR TASK SET", + "ABORT TASK SET", + "GET FW STATE", + "GET PORT NAME", + "GET LINK STATUS", + "INIT LIP RESET", + NULL, + "SEND SNS", + "FABRIC LOGIN", + "SEND CHANGE REQUEST", + "FABRIC LOGOUT", + "INIT LIP LOGIN", + NULL, + "LOGIN LOOP PORT", + "GET PORT/NODE NAME LIST", + "SET VENDOR ID", + "INITIALIZE IP MAILBOX", + NULL, + NULL, + NULL, + NULL, + "Get ID List", + "SEND LFA", + "Lun RESET" +}; +#endif + static void -isp_mboxcmd(isp, mbp) +isp_mboxcmd(isp, mbp, logmask) struct ispsoftc *isp; mbreg_t *mbp; + int logmask; { + char *cname, *xname, tname[16], mname[16]; unsigned int lim, ibits, obits, box, opcode; u_int16_t *mcp; @@ -3571,7 +3960,7 @@ isp_mboxcmd(isp, mbp) if ((opcode = mbp->param[0]) >= lim) { mbp->param[0] = MBOX_INVALID_COMMAND; - PRINTF("%s: unknown command 0x%x\n", isp->isp_name, opcode); + isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode); return; } @@ -3580,11 +3969,15 @@ isp_mboxcmd(isp, mbp) if (ibits == 0 && obits == 0) { mbp->param[0] = MBOX_COMMAND_PARAM_ERROR; - PRINTF("%s: no parameters for opcode 0x%x\n", isp->isp_name, - opcode); + isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode); return; } + /* + * Get exclusive usage of mailbox registers. + */ + MBOX_ACQUIRE(isp); + for (box = 0; box < MAX_MAILBOX; box++) { if (ibits & (1 << box)) { ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); @@ -3605,7 +3998,7 @@ isp_mboxcmd(isp, mbp) /* * Give the f/w a chance to pick this up. */ - SYS_DELAY(250); + USEC_DELAY(250); /* @@ -3622,180 +4015,84 @@ isp_mboxcmd(isp, mbp) } } + MBOX_RELEASE(isp); + + if (logmask == 0 || opcode == MBOX_EXEC_FIRMWARE) { + return; + } +#ifdef ISP_STRIPPED + cname = NULL; +#else + cname = (IS_FC(isp))? fc_mbcmd_names[opcode] : scsi_mbcmd_names[opcode]; +#endif + if (cname == NULL) { + SNPRINTF(cname, sizeof tname, "opcode %x", opcode); + } + /* * Just to be chatty here... */ + xname = NULL; switch (mbp->param[0]) { case MBOX_COMMAND_COMPLETE: break; case MBOX_INVALID_COMMAND: - IDPRINTF(2, ("%s: mbox cmd %x failed with INVALID_COMMAND\n", - isp->isp_name, opcode)); + if (logmask & MBLOGMASK(MBOX_COMMAND_COMPLETE)) + xname = "INVALID COMMAND"; break; case MBOX_HOST_INTERFACE_ERROR: - PRINTF("%s: mbox cmd %x failed with HOST_INTERFACE_ERROR\n", - isp->isp_name, opcode); + if (logmask & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR)) + xname = "HOST INTERFACE ERROR"; break; case MBOX_TEST_FAILED: - PRINTF("%s: mbox cmd %x failed with TEST_FAILED\n", - isp->isp_name, opcode); + if (logmask & MBLOGMASK(MBOX_TEST_FAILED)) + xname = "TEST FAILED"; break; case MBOX_COMMAND_ERROR: - if (opcode != MBOX_ABOUT_FIRMWARE) - PRINTF("%s: mbox cmd %x failed with COMMAND_ERROR\n", - isp->isp_name, opcode); + if (logmask & MBLOGMASK(MBOX_COMMAND_ERROR)) + xname = "COMMAND ERROR"; break; case MBOX_COMMAND_PARAM_ERROR: - switch (opcode) { - case MBOX_GET_PORT_DB: - case MBOX_GET_PORT_NAME: - case MBOX_GET_DEV_QUEUE_PARAMS: - break; - default: - PRINTF("%s: mbox cmd %x failed with " - "COMMAND_PARAM_ERROR\n", isp->isp_name, opcode); - } + if (logmask & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR)) + xname = "COMMAND PARAMETER ERROR"; break; - case MBOX_LOOP_ID_USED: + if (logmask & MBLOGMASK(MBOX_LOOP_ID_USED)) + xname = "LOOP ID ALREADY IN USE"; + break; case MBOX_PORT_ID_USED: + if (logmask & MBLOGMASK(MBOX_PORT_ID_USED)) + xname = "PORT ID ALREADY IN USE"; + break; case MBOX_ALL_IDS_USED: + if (logmask & MBLOGMASK(MBOX_ALL_IDS_USED)) + xname = "ALL LOOP IDS IN USE"; + break; + case 0: /* special case */ + xname = "TIMEOUT"; break; - default: - /* - * The expected return of EXEC_FIRMWARE is zero. - */ - if ((opcode == MBOX_EXEC_FIRMWARE && mbp->param[0] != 0) || - (opcode != MBOX_EXEC_FIRMWARE)) { - PRINTF("%s: mbox cmd %x failed with error %x\n", - isp->isp_name, opcode, mbp->param[0]); - } + SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]); + xname = mname; break; } -} - -void -isp_lostcmd(isp, xs) - struct ispsoftc *isp; - ISP_SCSI_XFER_T *xs; -{ - mbreg_t mbs; - - mbs.param[0] = MBOX_GET_FIRMWARE_STATUS; - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_dumpregs(isp, "couldn't GET FIRMWARE STATUS"); - return; - } - if (mbs.param[1]) { - PRINTF("%s: %d commands on completion queue\n", - isp->isp_name, mbs.param[1]); - } - if (XS_NULL(xs)) - return; - - mbs.param[0] = MBOX_GET_DEV_QUEUE_STATUS; - mbs.param[1] = (XS_TGT(xs) << 8) | XS_LUN(xs); /* XXX: WHICH BUS? */ - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_dumpregs(isp, "couldn't GET DEVICE QUEUE STATUS"); - return; - } - PRINTF("%s: lost command for target %d lun %d, %d active of %d, " - "Queue State: %x\n", isp->isp_name, XS_TGT(xs), - XS_LUN(xs), mbs.param[2], mbs.param[3], mbs.param[1]); - - isp_dumpregs(isp, "lost command"); - /* - * XXX: Need to try and do something to recover. - */ -} - -static void -isp_dumpregs(isp, msg) - struct ispsoftc *isp; - const char *msg; -{ - PRINTF("%s: %s\n", isp->isp_name, msg); - if (IS_SCSI(isp)) - PRINTF(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1)); - else - PRINTF(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR)); - PRINTF(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR), - ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA)); - PRINTF("risc_hccr=%x\n", ISP_READ(isp, HCCR)); - - - if (IS_SCSI(isp)) { - ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); - PRINTF(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n", - ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS), - ISP_READ(isp, CDMA_FIFO_STS)); - PRINTF(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n", - ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS), - ISP_READ(isp, DDMA_FIFO_STS)); - PRINTF(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n", - ISP_READ(isp, SXP_INTERRUPT), - ISP_READ(isp, SXP_GROSS_ERR), - ISP_READ(isp, SXP_PINS_CTRL)); - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); - } - PRINTF(" mbox regs: %x %x %x %x %x\n", - ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1), - ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3), - ISP_READ(isp, OUTMAILBOX4)); - ISP_DUMPREGS(isp); + if (xname) + isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s)", + cname, xname); } static void isp_fw_state(isp) struct ispsoftc *isp; { - mbreg_t mbs; if (IS_FC(isp)) { - int once = 0; + mbreg_t mbs; fcparam *fcp = isp->isp_param; -again: + mbs.param[0] = MBOX_GET_FW_STATE; - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - IDPRINTF(1, ("%s: isp_fw_state 0x%x\n", isp->isp_name, - mbs.param[0])); - switch (mbs.param[0]) { - case ASYNC_PDB_CHANGED: - if (once++ < 10) { - goto again; - } - fcp->isp_fwstate = FW_CONFIG_WAIT; - fcp->isp_loopstate = LOOP_PDB_RCVD; - goto again; - case ASYNC_LIP_OCCURRED: - fcp->isp_lipseq = mbs.param[1]; - /* FALLTHROUGH */ - case ASYNC_LOOP_UP: - fcp->isp_fwstate = FW_CONFIG_WAIT; - fcp->isp_loopstate = LOOP_LIP_RCVD; - if (once++ < 10) { - goto again; - } - break; - case ASYNC_LOOP_RESET: - case ASYNC_LOOP_DOWN: - fcp->isp_fwstate = FW_CONFIG_WAIT; - fcp->isp_loopstate = LOOP_NIL; - /* FALLTHROUGH */ - case ASYNC_CHANGE_NOTIFY: - if (once++ < 10) { - goto again; - } - break; - } - PRINTF("%s: GET FIRMWARE STATE failed (0x%x)\n", - isp->isp_name, mbs.param[0]); - return; - } - fcp->isp_fwstate = mbs.param[1]; + isp_mboxcmd(isp, &mbs, MBLOGALL); + if (mbs.param[0] == MBOX_COMMAND_COMPLETE) + fcp->isp_fwstate = mbs.param[1]; } } @@ -3803,13 +4100,13 @@ static void isp_update(isp) struct ispsoftc *isp; { - int bus; + int bus, upmask; - for (bus = 0; isp->isp_update != 0; bus++) { - if (isp->isp_update & (1 << bus)) { + for (bus = 0, upmask = isp->isp_update; upmask != 0; bus++) { + if (upmask & (1 << bus)) { isp_update_bus(isp, bus); - isp->isp_update ^= (1 << bus); } + upmask &= ~(1 << bus); } } @@ -3822,10 +4119,13 @@ isp_update_bus(isp, bus) mbreg_t mbs; sdparam *sdp; + isp->isp_update &= ~(1 << bus); if (IS_FC(isp)) { + /* + * There are no 'per-bus' settings for Fibre Channel. + */ return; } - sdp = isp->isp_param; sdp += bus; @@ -3834,35 +4134,57 @@ isp_update_bus(isp, bus) int get; if (sdp->isp_devparam[tgt].dev_enable == 0) { - IDPRINTF(2, ("%s: skipping target %d bus %d update\n", - isp->isp_name, tgt, bus)); + sdp->isp_devparam[tgt].dev_update = 0; + sdp->isp_devparam[tgt].dev_refresh = 0; + isp_prt(isp, ISP_LOGDEBUG1, + "skipping target %d bus %d update", tgt, bus); continue; } - /* * If the goal is to update the status of the device, * take what's in dev_flags and try and set the device * toward that. Otherwise, if we're just refreshing the * current device state, get the current parameters. */ - if (sdp->isp_devparam[tgt].dev_update) { + + /* + * Refresh overrides set + */ + 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 dev_flags has "Renegotiate on Error" + * on and "Freeze Queue on Error" off. + */ + sdp->isp_devparam[tgt].dev_flags |= DPARM_RENEG; + sdp->isp_devparam[tgt].dev_flags &= ~DPARM_QFRZ; + mbs.param[2] = sdp->isp_devparam[tgt].dev_flags; + /* - * Insist that PARITY must be enabled if SYNC - * is enabled. + * Insist that PARITY must be enabled + * if SYNC or WIDE is enabled. */ - if (mbs.param[2] & DPARM_SYNC) { + if ((mbs.param[2] & (DPARM_SYNC|DPARM_WIDE)) != 0) { mbs.param[2] |= DPARM_PARITY; } - mbs.param[3] = - (sdp->isp_devparam[tgt].sync_offset << 8) | - (sdp->isp_devparam[tgt].sync_period); - sdp->isp_devparam[tgt].dev_update = 0; + + if ((mbs.param[2] & DPARM_SYNC) == 0) { + mbs.param[3] = 0; + } else { + mbs.param[3] = + (sdp->isp_devparam[tgt].sync_offset << 8) | + (sdp->isp_devparam[tgt].sync_period); + } /* * A command completion later that has - * RQSTF_NEGOTIATION set will cause - * the dev_refresh/announce cycle. + * RQSTF_NEGOTIATION set canl cause + * the dev_refresh/announce cycle also. + & * * Note: It is really important to update our current * flags with at least the state of TAG capabilities- @@ -3873,27 +4195,18 @@ isp_update_bus(isp, bus) sdp->isp_devparam[tgt].cur_dflags &= ~DPARM_TQING; sdp->isp_devparam[tgt].cur_dflags |= (sdp->isp_devparam[tgt].dev_flags & DPARM_TQING); + isp_prt(isp, ISP_LOGDEBUG2, + "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; - IDPRINTF(3, ("%s: bus %d set tgt %d flags 0x%x off 0x%x" - " period 0x%x\n", isp->isp_name, bus, tgt, - mbs.param[2], mbs.param[3] >> 8, - mbs.param[3] & 0xff)); get = 0; - } else if (sdp->isp_devparam[tgt].dev_refresh) { - mbs.param[0] = MBOX_GET_TARGET_PARAMS; - sdp->isp_devparam[tgt].dev_refresh = 0; - get = 1; } else { continue; } mbs.param[1] = (bus << 15) | (tgt << 8) ; - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: failed to %cet SCSI parameters for " - "target %d\n", isp->isp_name, (get)? 'g' : 's', - tgt); - continue; - } + isp_mboxcmd(isp, &mbs, MBLOGALL); if (get == 0) { isp->isp_sendmarker |= (1 << bus); continue; @@ -3907,6 +4220,14 @@ isp_update_bus(isp, bus) get = (bus << 16) | tgt; (void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get); } + + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if (sdp->isp_devparam[tgt].dev_update || + sdp->isp_devparam[tgt].dev_refresh) { + isp->isp_update |= (1 << bus); + break; + } + } } static void @@ -3927,26 +4248,37 @@ isp_setdfltparm(isp, channel) fcp->isp_gotdparms = 1; fcp->isp_maxfrmlen = ICB_DFLT_FRMLEN; fcp->isp_maxalloc = ICB_DFLT_ALLOC; - fcp->isp_execthrottle = ICB_DFLT_THROTTLE; + fcp->isp_execthrottle = ISP_EXEC_THROTTLE; 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_WWN(isp); - if ((fcp->isp_nodewwn >> 60) == 2) { - fcp->isp_nodewwn &= ~((u_int64_t) 0xfff << 48); - fcp->isp_portwwn = fcp->isp_nodewwn | - (((u_int64_t)(isp->isp_unit+1)) << 48); - } else { - fcp->isp_portwwn = fcp->isp_nodewwn; - } + 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 */ if ((isp->isp_confopts & (ISP_CFG_NONVRAM|ISP_CFG_OWNWWN)) || (isp_read_nvram(isp))) { - PRINTF("%s: Node WWN 0x%08x%08x, Port WWN 0x%08x%08x\n", - isp->isp_name, (u_int32_t) (fcp->isp_nodewwn >> 32), + isp_prt(isp, ISP_LOGINFO, + "Node WWN 0x%08x%08x, Port WWN 0x%08x%08x", + (u_int32_t) (fcp->isp_nodewwn >> 32), (u_int32_t) (fcp->isp_nodewwn & 0xffffffff), (u_int32_t) (fcp->isp_portwwn >> 32), (u_int32_t) (fcp->isp_portwwn & 0xffffffff)); @@ -3982,9 +4314,8 @@ isp_setdfltparm(isp, channel) */ if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { mbs.param[0] = MBOX_GET_ACT_NEG_STATE; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - IDPRINTF(2, ("could not GET ACT NEG STATE\n")); sdp->isp_req_ack_active_neg = 1; sdp->isp_data_line_active_neg = 1; } else { @@ -3998,10 +4329,12 @@ isp_setdfltparm(isp, channel) sdp->isp_data_line_active_neg = 1; } - IDPRINTF(3, ("%s: defaulting bus %d REQ/ACK Active Negation is %d\n", - isp->isp_name, channel, sdp->isp_req_ack_active_neg)); - IDPRINTF(3, ("%s: defaulting bus %d DATA Active Negation is %d\n", - isp->isp_name, channel, sdp->isp_data_line_active_neg)); + isp_prt(isp, ISP_LOGDEBUG1, + "defaulting bus %d REQ/ACK Active Negation is %d", + channel, sdp->isp_req_ack_active_neg); + isp_prt(isp, ISP_LOGDEBUG1, + "defaulting bus %d DATA Active Negation is %d", + channel, sdp->isp_data_line_active_neg); /* * The trick here is to establish a default for the default (honk!) @@ -4028,16 +4361,26 @@ isp_setdfltparm(isp, channel) ISP_10M_SYNCPARMS >> 8; sdp->isp_devparam[tgt].sync_period = ISP_10M_SYNCPARMS & 0xff; + } else if (IS_ULTRA3(isp)) { + sdp->isp_devparam[tgt].sync_offset = + ISP_80M_SYNCPARMS >> 8; + sdp->isp_devparam[tgt].sync_period = + ISP_80M_SYNCPARMS & 0xff; } else if (IS_ULTRA2(isp)) { sdp->isp_devparam[tgt].sync_offset = ISP_40M_SYNCPARMS >> 8; sdp->isp_devparam[tgt].sync_period = ISP_40M_SYNCPARMS & 0xff; - } else { + } else if (IS_1240(isp)) { sdp->isp_devparam[tgt].sync_offset = ISP_20M_SYNCPARMS >> 8; sdp->isp_devparam[tgt].sync_period = ISP_20M_SYNCPARMS & 0xff; + } else { + sdp->isp_devparam[tgt].sync_offset = + ISP_20M_SYNCPARMS_1040 >> 8; + sdp->isp_devparam[tgt].sync_period = + ISP_20M_SYNCPARMS_1040 & 0xff; } /* @@ -4048,7 +4391,7 @@ isp_setdfltparm(isp, channel) mbs.param[0] = MBOX_GET_TARGET_PARAMS; mbs.param[1] = tgt << 8; - isp_mboxcmd(isp, &mbs); + isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { continue; } @@ -4084,11 +4427,11 @@ isp_setdfltparm(isp, channel) ISP_10M_SYNCPARMS & 0xff; } } - IDPRINTF(3, ("%s: bus %d tgt %d flags %x offset %x period %x\n", - isp->isp_name, channel, tgt, - sdp->isp_devparam[tgt].dev_flags, + isp_prt(isp, ISP_LOGDEBUG1, + "Initial bus %d tgt %d flags %x offset %x period %x", + channel, tgt, sdp->isp_devparam[tgt].dev_flags, sdp->isp_devparam[tgt].sync_offset, - sdp->isp_devparam[tgt].sync_period)); + sdp->isp_devparam[tgt].sync_period); } /* @@ -4097,22 +4440,21 @@ isp_setdfltparm(isp, channel) sdp->isp_cmd_dma_burst_enable = 1; sdp->isp_data_dma_burst_enabl = 1; sdp->isp_fifo_threshold = 0; - sdp->isp_initiator_id = 7; - /* XXXX This is probably based upon clock XXXX */ + sdp->isp_initiator_id = DEFAULT_IID(isp); if (isp->isp_type >= ISP_HA_SCSI_1040) { sdp->isp_async_data_setup = 9; } else { sdp->isp_async_data_setup = 6; } sdp->isp_selection_timeout = 250; - sdp->isp_max_queue_depth = MAXISPREQUEST; + sdp->isp_max_queue_depth = MAXISPREQUEST(isp); sdp->isp_tag_aging = 8; sdp->isp_bus_reset_delay = 3; sdp->isp_retry_count = 2; sdp->isp_retry_delay = 2; for (tgt = 0; tgt < MAX_TARGETS; tgt++) { - sdp->isp_devparam[tgt].exc_throttle = 16; + sdp->isp_devparam[tgt].exc_throttle = ISP_EXEC_THROTTLE; sdp->isp_devparam[tgt].dev_enable = 1; } } @@ -4126,10 +4468,10 @@ isp_setdfltparm(isp, channel) */ void -isp_restart(isp) +isp_reinit(isp) struct ispsoftc *isp; { - ISP_SCSI_XFER_T *xs; + XS_T *xs; u_int32_t handle; isp_reset(isp); @@ -4140,11 +4482,11 @@ isp_restart(isp) } } if (isp->isp_state != ISP_RUNSTATE) { - PRINTF("%s: isp_restart cannot restart ISP\n", isp->isp_name); + isp_prt(isp, ISP_LOGERR, "isp_reinit cannot restart ISP"); } isp->isp_nactive = 0; - for (handle = 1; handle <= (int) isp->isp_maxcmds; handle++) { + for (handle = 1; (int) handle <= isp->isp_maxcmds; handle++) { xs = isp_find_xs(isp, handle); if (xs == NULL) { continue; @@ -4157,7 +4499,7 @@ isp_restart(isp) XS_RESID(xs) = 0; } XS_SETERR(xs, HBA_BUSRESET); - XS_CMD_DONE(xs); + isp_done(xs); } } @@ -4198,9 +4540,9 @@ isp_read_nvram(isp) if (nvram_data[0] != 'I' || nvram_data[1] != 'S' || nvram_data[2] != 'P') { if (isp->isp_bustype != ISP_BT_SBUS) { - PRINTF("%s: invalid NVRAM header (%x,%x,%x,%x)\n", - isp->isp_name, nvram_data[0], nvram_data[1], - nvram_data[2], nvram_data[3]); + isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header"); + isp_prt(isp, ISP_LOGDEBUG0, "%x %x %x", + nvram_data[0], nvram_data[1], nvram_data[2]); } return (-1); } @@ -4211,11 +4553,11 @@ isp_read_nvram(isp) csum += nvram_data[i]; } if (csum != 0) { - PRINTF("%s: invalid NVRAM checksum\n", isp->isp_name); + isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum"); return (-1); } if (ISP_NVRAM_VERSION(nvram_data) < minversion) { - PRINTF("%s: version %d NVRAM not understood\n", isp->isp_name, + isp_prt(isp, ISP_LOGWARN, "version %d NVRAM not understood", ISP_NVRAM_VERSION(nvram_data)); return (-1); } @@ -4233,7 +4575,6 @@ isp_read_nvram(isp) } else { isp_parse_nvram_2100(isp, nvram_data); } - IDPRINTF(3, ("%s: NVRAM is valid\n", isp->isp_name)); return (0); #undef nvram_data #undef nvram_words @@ -4249,9 +4590,9 @@ isp_rdnvram_word(isp, wo, rp) u_int16_t bit, rqst; ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT); - SYS_DELAY(2); + USEC_DELAY(2); ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK); - SYS_DELAY(2); + USEC_DELAY(2); if (IS_FC(isp)) { wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1); @@ -4277,11 +4618,11 @@ isp_rdnvram_word(isp, wo, rp) bit = BIU_NVRAM_SELECT; } ISP_WRITE(isp, BIU_NVRAM, bit); - SYS_DELAY(2); + USEC_DELAY(2); ISP_WRITE(isp, BIU_NVRAM, bit | BIU_NVRAM_CLOCK); - SYS_DELAY(2); + USEC_DELAY(2); ISP_WRITE(isp, BIU_NVRAM, bit); - SYS_DELAY(2); + USEC_DELAY(2); } /* * Now read the result back in (bits come back in MSB format). @@ -4291,20 +4632,18 @@ isp_rdnvram_word(isp, wo, rp) u_int16_t rv; *rp <<= 1; ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK); - SYS_DELAY(2); + USEC_DELAY(2); rv = ISP_READ(isp, BIU_NVRAM); if (rv & BIU_NVRAM_DATAIN) { *rp |= 1; } - SYS_DELAY(2); + USEC_DELAY(2); ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT); - SYS_DELAY(2); + USEC_DELAY(2); } ISP_WRITE(isp, BIU_NVRAM, 0); - SYS_DELAY(2); -#if BYTE_ORDER == BIG_ENDIAN - *rp = ((*rp >> 8) | ((*rp & 0xff) << 8)); -#endif + USEC_DELAY(2); + ISP_SWIZZLE_NVRAM_WORD(isp, rp); } static void @@ -4313,8 +4652,6 @@ isp_parse_nvram_1020(isp, nvram_data) u_int8_t *nvram_data; { int i; - static char *tru = "true"; - static char *not = "false"; sdparam *sdp = (sdparam *) isp->isp_param; sdp->isp_fifo_threshold = @@ -4367,36 +4704,7 @@ isp_parse_nvram_1020(isp, nvram_data) sdp->isp_max_queue_depth = ISP_NVRAM_MAX_QUEUE_DEPTH(nvram_data); - isp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data); - if (isp->isp_dblev > 2) { - PRINTF("%s: NVRAM values:\n", isp->isp_name); - PRINTF(" Fifo Threshold = 0x%x\n", - sdp->isp_fifo_threshold); - PRINTF(" Bus Reset Delay = %d\n", - sdp->isp_bus_reset_delay); - PRINTF(" Retry Count = %d\n", - sdp->isp_retry_count); - PRINTF(" Retry Delay = %d\n", - sdp->isp_retry_delay); - PRINTF(" Tag Age Limit = %d\n", - sdp->isp_tag_aging); - PRINTF(" Selection Timeout = %d\n", - sdp->isp_selection_timeout); - PRINTF(" Max Queue Depth = %d\n", - sdp->isp_max_queue_depth); - PRINTF(" Async Data Setup = 0x%x\n", - sdp->isp_async_data_setup); - PRINTF(" REQ/ACK Active Negation = %s\n", - sdp->isp_req_ack_active_neg? tru : not); - PRINTF(" Data Line Active Negation = %s\n", - sdp->isp_data_line_active_neg? tru : not); - PRINTF(" Data DMA Burst Enable = %s\n", - sdp->isp_data_dma_burst_enabl? tru : not); - PRINTF(" Cmd DMA Burst Enable = %s\n", - sdp->isp_cmd_dma_burst_enable? tru : not); - PRINTF(" Fast MTTR = %s\n", - isp->isp_fast_mttr? tru : not); - } + sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data); for (i = 0; i < MAX_TARGETS; i++) { sdp->isp_devparam[i].dev_enable = ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, i); @@ -4413,12 +4721,10 @@ isp_parse_nvram_1020(isp, nvram_data) * be a shorter period than this. */ if (sdp->isp_devparam[i].sync_period < 0x19) { - sdp->isp_devparam[i].sync_period = - 0x19; + sdp->isp_devparam[i].sync_period = 0x19; } if (sdp->isp_devparam[i].sync_offset > 0xc) { - sdp->isp_devparam[i].sync_offset = - 0x0c; + sdp->isp_devparam[i].sync_offset = 0x0c; } } else { if (sdp->isp_devparam[i].sync_offset > 0x8) { @@ -4428,15 +4734,7 @@ isp_parse_nvram_1020(isp, nvram_data) sdp->isp_devparam[i].dev_flags = 0; if (ISP_NVRAM_TGT_RENEG(nvram_data, i)) sdp->isp_devparam[i].dev_flags |= DPARM_RENEG; - if (ISP_NVRAM_TGT_QFRZ(nvram_data, i)) { - PRINTF("%s: not supporting QFRZ option for " - "target %d\n", isp->isp_name, i); - } sdp->isp_devparam[i].dev_flags |= DPARM_ARQ; - if (ISP_NVRAM_TGT_ARQ(nvram_data, i) == 0) { - PRINTF("%s: not disabling ARQ option for " - "target %d\n", isp->isp_name, i); - } if (ISP_NVRAM_TGT_TQING(nvram_data, i)) sdp->isp_devparam[i].dev_flags |= DPARM_TQING; if (ISP_NVRAM_TGT_SYNC(nvram_data, i)) @@ -4448,15 +4746,6 @@ isp_parse_nvram_1020(isp, nvram_data) if (ISP_NVRAM_TGT_DISC(nvram_data, i)) sdp->isp_devparam[i].dev_flags |= DPARM_DISC; sdp->isp_devparam[i].cur_dflags = 0; /* we don't know */ - if (isp->isp_dblev > 2) { - PRINTF(" Target %d: Enabled %d Throttle %d " - "Offset %d Period %d Flags 0x%x\n", i, - sdp->isp_devparam[i].dev_enable, - sdp->isp_devparam[i].exc_throttle, - sdp->isp_devparam[i].sync_offset, - sdp->isp_devparam[i].sync_period, - sdp->isp_devparam[i].dev_flags); - } } } @@ -4466,8 +4755,6 @@ isp_parse_nvram_1080(isp, bus, nvram_data) int bus; u_int8_t *nvram_data; { - static char *tru = "true"; - static char *not = "false"; int i; sdparam *sdp = (sdparam *) isp->isp_param; sdp += bus; @@ -4511,34 +4798,6 @@ isp_parse_nvram_1080(isp, bus, nvram_data) sdp->isp_max_queue_depth = ISP1080_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus); - if (isp->isp_dblev >= 3) { - PRINTF("%s: ISP1080 bus %d NVRAM values:\n", - isp->isp_name, bus); - PRINTF(" Initiator ID = %d\n", - sdp->isp_initiator_id); - PRINTF(" Fifo Threshold = 0x%x\n", - sdp->isp_fifo_threshold); - PRINTF(" Bus Reset Delay = %d\n", - sdp->isp_bus_reset_delay); - PRINTF(" Retry Count = %d\n", - sdp->isp_retry_count); - PRINTF(" Retry Delay = %d\n", - sdp->isp_retry_delay); - PRINTF(" Tag Age Limit = %d\n", - sdp->isp_tag_aging); - PRINTF(" Selection Timeout = %d\n", - sdp->isp_selection_timeout); - PRINTF(" Max Queue Depth = %d\n", - sdp->isp_max_queue_depth); - PRINTF(" Async Data Setup = 0x%x\n", - sdp->isp_async_data_setup); - PRINTF(" REQ/ACK Active Negation = %s\n", - sdp->isp_req_ack_active_neg? tru : not); - PRINTF(" Data Line Active Negation = %s\n", - sdp->isp_data_line_active_neg? tru : not); - PRINTF(" Cmd DMA Burst Enable = %s\n", - sdp->isp_cmd_dma_burst_enable? tru : not); - } for (i = 0; i < MAX_TARGETS; i++) { sdp->isp_devparam[i].dev_enable = ISP1080_NVRAM_TGT_DEVICE_ENABLE(nvram_data, i, bus); @@ -4551,17 +4810,7 @@ isp_parse_nvram_1080(isp, bus, nvram_data) sdp->isp_devparam[i].dev_flags = 0; if (ISP1080_NVRAM_TGT_RENEG(nvram_data, i, bus)) sdp->isp_devparam[i].dev_flags |= DPARM_RENEG; - if (ISP1080_NVRAM_TGT_QFRZ(nvram_data, i, bus)) { - PRINTF("%s: not supporting QFRZ option " - "for target %d bus %d\n", - isp->isp_name, i, bus); - } sdp->isp_devparam[i].dev_flags |= DPARM_ARQ; - if (ISP1080_NVRAM_TGT_ARQ(nvram_data, i, bus) == 0) { - PRINTF("%s: not disabling ARQ option " - "for target %d bus %d\n", - isp->isp_name, i, bus); - } if (ISP1080_NVRAM_TGT_TQING(nvram_data, i, bus)) sdp->isp_devparam[i].dev_flags |= DPARM_TQING; if (ISP1080_NVRAM_TGT_SYNC(nvram_data, i, bus)) @@ -4573,16 +4822,6 @@ isp_parse_nvram_1080(isp, bus, nvram_data) if (ISP1080_NVRAM_TGT_DISC(nvram_data, i, bus)) sdp->isp_devparam[i].dev_flags |= DPARM_DISC; sdp->isp_devparam[i].cur_dflags = 0; - if (isp->isp_dblev >= 3) { - PRINTF(" Target %d: Ena %d Throttle " - "%d Offset %d Period %d Flags " - "0x%x\n", i, - sdp->isp_devparam[i].dev_enable, - sdp->isp_devparam[i].exc_throttle, - sdp->isp_devparam[i].sync_offset, - sdp->isp_devparam[i].sync_period, - sdp->isp_devparam[i].dev_flags); - } } } @@ -4592,8 +4831,6 @@ isp_parse_nvram_12160(isp, bus, nvram_data) int bus; u_int8_t *nvram_data; { - static char *tru = "true"; - static char *not = "false"; sdparam *sdp = (sdparam *) isp->isp_param; int i; @@ -4638,35 +4875,6 @@ isp_parse_nvram_12160(isp, bus, nvram_data) sdp->isp_max_queue_depth = ISP12160_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus); - if (isp->isp_dblev >= 3) { - PRINTF("%s: ISP12160 bus %d NVRAM values:\n", - isp->isp_name, bus); - PRINTF(" Initiator ID = %d\n", - sdp->isp_initiator_id); - PRINTF(" Fifo Threshold = 0x%x\n", - sdp->isp_fifo_threshold); - PRINTF(" Bus Reset Delay = %d\n", - sdp->isp_bus_reset_delay); - PRINTF(" Retry Count = %d\n", - sdp->isp_retry_count); - PRINTF(" Retry Delay = %d\n", - sdp->isp_retry_delay); - PRINTF(" Tag Age Limit = %d\n", - sdp->isp_tag_aging); - PRINTF(" Selection Timeout = %d\n", - sdp->isp_selection_timeout); - PRINTF(" Max Queue Depth = %d\n", - sdp->isp_max_queue_depth); - PRINTF(" Async Data Setup = 0x%x\n", - sdp->isp_async_data_setup); - PRINTF(" REQ/ACK Active Negation = %s\n", - sdp->isp_req_ack_active_neg? tru : not); - PRINTF(" Data Line Active Negation = %s\n", - sdp->isp_data_line_active_neg? tru : not); - PRINTF(" Cmd DMA Burst Enable = %s\n", - sdp->isp_cmd_dma_burst_enable? tru : not); - } - for (i = 0; i < MAX_TARGETS; i++) { sdp->isp_devparam[i].dev_enable = ISP12160_NVRAM_TGT_DEVICE_ENABLE(nvram_data, i, bus); @@ -4679,15 +4887,7 @@ isp_parse_nvram_12160(isp, bus, nvram_data) sdp->isp_devparam[i].dev_flags = 0; if (ISP12160_NVRAM_TGT_RENEG(nvram_data, i, bus)) sdp->isp_devparam[i].dev_flags |= DPARM_RENEG; - if (ISP12160_NVRAM_TGT_QFRZ(nvram_data, i, bus)) { - PRINTF("%s: not supporting QFRZ option " - "for target %d bus %d\n", isp->isp_name, i, bus); - } sdp->isp_devparam[i].dev_flags |= DPARM_ARQ; - if (ISP12160_NVRAM_TGT_ARQ(nvram_data, i, bus) == 0) { - PRINTF("%s: not disabling ARQ option " - "for target %d bus %d\n", isp->isp_name, i, bus); - } if (ISP12160_NVRAM_TGT_TQING(nvram_data, i, bus)) sdp->isp_devparam[i].dev_flags |= DPARM_TQING; if (ISP12160_NVRAM_TGT_SYNC(nvram_data, i, bus)) @@ -4699,15 +4899,6 @@ isp_parse_nvram_12160(isp, bus, nvram_data) if (ISP12160_NVRAM_TGT_DISC(nvram_data, i, bus)) sdp->isp_devparam[i].dev_flags |= DPARM_DISC; sdp->isp_devparam[i].cur_dflags = 0; - if (isp->isp_dblev >= 3) { - PRINTF(" Target %d: Ena %d Throttle %d Offset %d " - "Period %d Flags 0x%x\n", i, - sdp->isp_devparam[i].dev_enable, - sdp->isp_devparam[i].exc_throttle, - sdp->isp_devparam[i].sync_offset, - sdp->isp_devparam[i].sync_period, - sdp->isp_devparam[i].dev_flags); - } } } @@ -4717,54 +4908,63 @@ isp_parse_nvram_2100(isp, nvram_data) u_int8_t *nvram_data; { fcparam *fcp = (fcparam *) isp->isp_param; - union { - struct { -#if BYTE_ORDER == BIG_ENDIAN - u_int32_t hi32; - u_int32_t lo32; -#else - u_int32_t lo32; - u_int32_t hi32; -#endif - } wd; - u_int64_t full64; - } wwnstore; + u_int64_t wwn; /* - * There is supposed to be WWNN storage as distinct - * from WWPN storage in NVRAM, but it doesn't appear - * to be used sanely. + * There is NVRAM storage for both Port and Node entities- + * but the Node entity appears to be unused on all the cards + * 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 + * 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. */ + wwn = ISP2100_NVRAM_PORT_NAME(nvram_data); + if (wwn) { + isp_prt(isp, ISP_LOGCONFIG, "NVRAM Port WWN 0x%08x%08x", + (u_int32_t) (wwn >> 32), (u_int32_t) (wwn & 0xffffffff)); + if ((wwn >> 60) == 0) { + wwn |= (((u_int64_t) 2)<< 60); + } + } + fcp->isp_portwwn = wwn; + wwn = ISP2100_NVRAM_NODE_NAME(nvram_data); + if (wwn) { + isp_prt(isp, ISP_LOGCONFIG, "NVRAM Node WWN 0x%08x%08x", + (u_int32_t) (wwn >> 32), (u_int32_t) (wwn & 0xffffffff)); + if ((wwn >> 60) == 0) { + wwn |= (((u_int64_t) 2)<< 60); + } + } + fcp->isp_nodewwn = wwn; - wwnstore.full64 = ISP2100_NVRAM_PORT_NAME(nvram_data); - if (wwnstore.full64 != 0LL) { - switch ((int) (wwnstore.full64 >> 60)) { - case 0: - /* - * Broken cards with nothing in the top nibble. - * Pah. - */ - wwnstore.full64 |= (2LL << 60); - /* FALLTHROUGH */ - case 2: - fcp->isp_portwwn = wwnstore.full64; - fcp->isp_nodewwn = wwnstore.full64; - fcp->isp_nodewwn &= ~((0xfffLL) << 48); - if (fcp->isp_nodewwn == fcp->isp_portwwn) { - fcp->isp_portwwn |= - (((u_int64_t)(isp->isp_unit+1)) << 48); - } - break; - default: - fcp->isp_portwwn = wwnstore.full64; - fcp->isp_nodewwn = wwnstore.full64; + /* + * 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; + } + + /* + * 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); + } + if ((fcp->isp_portwwn & (((u_int64_t) 0xfff) << 48)) == 0 && + (fcp->isp_portwwn >> 60) == 2) { + fcp->isp_portwwn |= ((u_int64_t) 1 << 56); } } - CFGPRINTF("%s: Node WWN 0x%08x%08x, Port WWN 0x%08x%08x\n", - isp->isp_name, (u_int32_t) (fcp->isp_nodewwn >> 32), - (u_int32_t) (fcp->isp_nodewwn & 0xffffffff), - (u_int32_t) (fcp->isp_portwwn >> 32), - (u_int32_t) (fcp->isp_portwwn & 0xffffffff)); fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); @@ -4779,23 +4979,6 @@ isp_parse_nvram_2100(isp, nvram_data) fcp->isp_execthrottle = ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data); fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data); - if (isp->isp_dblev > 2) { - PRINTF("%s: NVRAM values:\n", isp->isp_name); - PRINTF(" Max IOCB Allocation = %d\n", - fcp->isp_maxalloc); - PRINTF(" Max Frame Length = %d\n", - fcp->isp_maxfrmlen); - PRINTF(" Execution Throttle = %d\n", - fcp->isp_execthrottle); - PRINTF(" Retry Count = %d\n", - fcp->isp_retry_count); - PRINTF(" Retry Delay = %d\n", - fcp->isp_retry_delay); - PRINTF(" Hard Loop ID = %d\n", - fcp->isp_loopid); - PRINTF(" Options = 0x%x\n", - fcp->isp_fwoptions); - PRINTF(" HBA Options = 0x%x\n", - ISP2100_NVRAM_HBA_OPTIONS(nvram_data)); - } + isp_prt(isp, ISP_LOGDEBUG0, + "fwoptions from nvram are 0x%x", fcp->isp_fwoptions); } diff --git a/sys/dev/ic/isp_inline.h b/sys/dev/ic/isp_inline.h index 08dbbbbfc4b..00eea381150 100644 --- a/sys/dev/ic/isp_inline.h +++ b/sys/dev/ic/isp_inline.h @@ -1,13 +1,11 @@ -/* $OpenBSD: isp_inline.h,v 1.4 2000/07/06 05:31:48 mjacob Exp $ */ +/* $OpenBSD: isp_inline.h,v 1.5 2000/10/16 01:01:59 mjacob Exp $ */ /* - * Qlogic Inline Functions + * Qlogic Host Adapter Inline Functions * - *--------------------------------------- - * Copyright (c) 1999 by Matthew Jacob + * Copyright (c) 1999, 2000 by Matthew Jacob * Feral Software * 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 @@ -15,10 +13,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 @@ -37,109 +32,6 @@ #ifndef _ISP_INLINE_H #define _ISP_INLINE_H -static INLINE void isp_prtstst __P((ispstatusreq_t *)); -static INLINE char *isp2100_fw_statename __P((int)); -static INLINE char *isp2100_pdb_statename __P((int)); - - -static INLINE void -isp_prtstst(sp) - ispstatusreq_t *sp; -{ - char buf[172]; - buf[0] = 0; - STRNCAT(buf, "states=>", sizeof buf); - if (sp->req_state_flags & RQSF_GOT_BUS) { - STRNCAT(buf, " GOT_BUS", sizeof buf); - } - if (sp->req_state_flags & RQSF_GOT_TARGET) { - STRNCAT(buf, " GOT_TGT", sizeof buf); - } - if (sp->req_state_flags & RQSF_SENT_CDB) { - STRNCAT(buf, " SENT_CDB", sizeof buf); - } - if (sp->req_state_flags & RQSF_XFRD_DATA) { - STRNCAT(buf, " XFRD_DATA", sizeof buf); - } - if (sp->req_state_flags & RQSF_GOT_STATUS) { - STRNCAT(buf, " GOT_STS", sizeof buf); - } - if (sp->req_state_flags & RQSF_GOT_SENSE) { - STRNCAT(buf, " GOT_SNS", sizeof buf); - } - if (sp->req_state_flags & RQSF_XFER_COMPLETE) { - STRNCAT(buf, " XFR_CMPLT", sizeof buf); - } - STRNCAT(buf, "\nstatus=>", sizeof buf); - if (sp->req_status_flags & RQSTF_DISCONNECT) { - STRNCAT(buf, " Disconnect", sizeof buf); - } - if (sp->req_status_flags & RQSTF_SYNCHRONOUS) { - STRNCAT(buf, " Sync_xfr", sizeof buf); - } - if (sp->req_status_flags & RQSTF_PARITY_ERROR) { - STRNCAT(buf, " Parity", sizeof buf); - } - if (sp->req_status_flags & RQSTF_BUS_RESET) { - STRNCAT(buf, " Bus_Reset", sizeof buf); - } - if (sp->req_status_flags & RQSTF_DEVICE_RESET) { - STRNCAT(buf, " Device_Reset", sizeof buf); - } - if (sp->req_status_flags & RQSTF_ABORTED) { - STRNCAT(buf, " Aborted", sizeof buf); - } - if (sp->req_status_flags & RQSTF_TIMEOUT) { - STRNCAT(buf, " Timeout", sizeof buf); - } - if (sp->req_status_flags & RQSTF_NEGOTIATION) { - STRNCAT(buf, " Negotiation", sizeof buf); - } - PRINTF(buf, "%s\n", buf); -} - -static INLINE char * -isp2100_fw_statename(state) - int state; -{ - static char buf[16]; - switch(state) { - case FW_CONFIG_WAIT: return "Config Wait"; - case FW_WAIT_AL_PA: return "Waiting for AL_PA"; - case FW_WAIT_LOGIN: return "Wait Login"; - case FW_READY: return "Ready"; - case FW_LOSS_OF_SYNC: return "Loss Of Sync"; - case FW_ERROR: return "Error"; - case FW_REINIT: return "Re-Init"; - case FW_NON_PART: return "Nonparticipating"; - default: - sprintf(buf, "0x%x", state); - return buf; - } -} - -static INLINE char *isp2100_pdb_statename(int pdb_state) -{ - static char buf[16]; - switch(pdb_state) { - case PDB_STATE_DISCOVERY: return "Port Discovery"; - case PDB_STATE_WDISC_ACK: return "Waiting Port Discovery ACK"; - case PDB_STATE_PLOGI: return "Port Login"; - case PDB_STATE_PLOGI_ACK: return "Wait Port Login ACK"; - case PDB_STATE_PRLI: return "Process Login"; - case PDB_STATE_PRLI_ACK: return "Wait Process Login ACK"; - case PDB_STATE_LOGGED_IN: return "Logged In"; - case PDB_STATE_PORT_UNAVAIL: return "Port Unavailable"; - case PDB_STATE_PRLO: return "Process Logout"; - case PDB_STATE_PRLO_ACK: return "Wait Process Logout ACK"; - case PDB_STATE_PLOGO: return "Port Logout"; - case PDB_STATE_PLOG_ACK: return "Wait Port Logout ACK"; - default: - sprintf(buf, "0x%x", pdb_state); - return buf; - } -} - /* * Handle Functions. * For each outstanding command there will be a non-zero handle. @@ -148,13 +40,13 @@ static INLINE char *isp2100_pdb_statename(int pdb_state) */ static INLINE int -isp_save_xs __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t *)); +isp_save_xs __P((struct ispsoftc *, XS_T *, u_int32_t *)); -static INLINE ISP_SCSI_XFER_T * +static INLINE XS_T * isp_find_xs __P((struct ispsoftc *, u_int32_t)); static INLINE u_int32_t -isp_find_handle __P((struct ispsoftc *, ISP_SCSI_XFER_T *)); +isp_find_handle __P((struct ispsoftc *, XS_T *)); static INLINE int isp_handle_index __P((u_int32_t)); @@ -163,12 +55,12 @@ static INLINE void isp_destroy_handle __P((struct ispsoftc *, u_int32_t)); static INLINE void -isp_remove_handle __P((struct ispsoftc *, ISP_SCSI_XFER_T *)); +isp_remove_handle __P((struct ispsoftc *, XS_T *)); static INLINE int isp_save_xs(isp, xs, handlep) struct ispsoftc *isp; - ISP_SCSI_XFER_T *xs; + XS_T *xs; u_int32_t *handlep; { int i, j; @@ -188,11 +80,11 @@ isp_save_xs(isp, xs, handlep) *handlep = j+1; if (++j == isp->isp_maxcmds) j = 0; - isp->isp_lasthdls = j; + isp->isp_lasthdls = (u_int16_t)j; return (0); } -static INLINE ISP_SCSI_XFER_T * +static INLINE XS_T * isp_find_xs(isp, handle) struct ispsoftc *isp; u_int32_t handle; @@ -207,7 +99,7 @@ isp_find_xs(isp, handle) static INLINE u_int32_t isp_find_handle(isp, xs) struct ispsoftc *isp; - ISP_SCSI_XFER_T *xs; + XS_T *xs; { int i; if (xs != NULL) { @@ -240,7 +132,7 @@ isp_destroy_handle(isp, handle) static INLINE void isp_remove_handle(isp, xs) struct ispsoftc *isp; - ISP_SCSI_XFER_T *xs; + XS_T *xs; { isp_destroy_handle(isp, isp_find_handle(isp, xs)); } @@ -260,7 +152,7 @@ isp_getrqentry(isp, iptrp, optrp, resultp) optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4); iptr = isp->isp_reqidx; *resultp = ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); - iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN); + iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN(isp)); if (iptr == optr) { return (1); } @@ -274,6 +166,8 @@ isp_getrqentry(isp, iptrp, optrp, resultp) static INLINE void isp_print_qentry __P((struct ispsoftc *, char *, int, void *)); + +#define TBA (4 * (((QENTRY_LEN >> 2) * 3) + 1) + 1) static INLINE void isp_print_qentry(isp, msg, idx, arg) struct ispsoftc *isp; @@ -281,14 +175,48 @@ isp_print_qentry(isp, msg, idx, arg) int idx; void *arg; { + char buf[TBA]; int amt, i, j; u_int8_t *ptr = arg; - PRINTF("%s %s index %d:\n", isp->isp_name, msg, idx); - for (amt = i = 0; i < 4; i++) { + + for (buf[0] = 0, amt = i = 0; i < 4; i++) { + buf[0] = 0; for (j = 0; j < (QENTRY_LEN >> 2); j++) { - PRINTF(" %02x", ptr[amt++] & 0xff); + SNPRINTF(buf, TBA, "%s %02x", buf, ptr[amt++] & 0xff); + } + STRNCAT(buf, "\n", TBA); + } + isp_prt(isp, ISP_LOGALL, "%s index %d:%s", msg, idx, buf); +} + +static INLINE void +isp_print_bytes __P((struct ispsoftc *, char *, int, void *)); + +static INLINE void +isp_print_bytes(isp, msg, amt, arg) + struct ispsoftc *isp; + char *msg; + int amt; + void *arg; +{ + char buf[128]; + u_int8_t *ptr = arg; + int off; + + if (msg) + isp_prt(isp, ISP_LOGALL, "%s:", msg); + off = 0; + buf[0] = 0; + while (off < amt) { + int j, to; + to = off; + for (j = 0; j < 16; j++) { + SNPRINTF(buf, 128, "%s %02x", buf, ptr[off++] & 0xff); + if (off == amt) + break; } - PRINTF("\n"); + isp_prt(isp, ISP_LOGALL, "0x%08x:%s", to, buf); + buf[0] = 0; } } #endif /* _ISP_INLINE_H */ diff --git a/sys/dev/ic/isp_openbsd.c b/sys/dev/ic/isp_openbsd.c index 900af61ac92..914bafb0fcf 100644 --- a/sys/dev/ic/isp_openbsd.c +++ b/sys/dev/ic/isp_openbsd.c @@ -1,12 +1,9 @@ -/* $OpenBSD: isp_openbsd.c,v 1.11 2000/07/07 19:00:47 mjacob Exp $ */ +/* $OpenBSD: isp_openbsd.c,v 1.12 2000/10/16 01:02:00 mjacob Exp $ */ /* * Platform (OpenBSD) dependent common attachment code for Qlogic adapters. * - *--------------------------------------- - * Copyright (c) 1999 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (c) 1999, 2000 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 +11,8 @@ * 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 @@ -34,7 +29,6 @@ * * The author may be reached via electronic communications at * - * mjacob@nas.nasa.gov * mjacob@feral.com * * or, via United States Postal Address @@ -48,17 +42,6 @@ #include <dev/ic/isp_openbsd.h> -static void ispminphys __P((struct buf *)); -static int32_t ispcmd_slow __P((ISP_SCSI_XFER_T *)); -static int32_t ispcmd __P((ISP_SCSI_XFER_T *)); - -static struct scsi_device isp_dev = { NULL, NULL, NULL, NULL }; - -static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int)); -static void isp_wdog __P((void *)); -static void isp_requeue(void *); -static void isp_internal_restart(void *); - /* * Set a timeout for the watchdogging of a command. * @@ -77,6 +60,17 @@ static void isp_internal_restart(void *); */ #define _XT(xs) ((((xs)->timeout/1000) * hz) + (3 * hz)) +static void ispminphys __P((struct buf *)); +static int32_t ispcmd_slow __P((XS_T *)); +static int32_t ispcmd __P((XS_T *)); + +static struct scsi_device isp_dev = { NULL, NULL, NULL, NULL }; + +static int isp_polled_cmd __P((struct ispsoftc *, XS_T *)); +static void isp_wdog __P((void *)); +static void isp_requeue(void *); +static void isp_internal_restart(void *); + struct cfdriver isp_cd = { NULL, "isp", DV_DULL }; @@ -139,11 +133,13 @@ isp_attach(isp) */ if (IS_SCSI(isp)) { int bus = 0; + ISP_LOCK(isp); (void) isp_control(isp, ISPCTL_RESET_BUS, &bus); if (IS_DUALBUS(isp)) { bus++; (void) isp_control(isp, ISPCTL_RESET_BUS, &bus); } + ISP_UNLOCK(isp); /* * wait for the bus to settle. */ @@ -151,39 +147,37 @@ isp_attach(isp) isp->isp_name); delay(4 * 1000000); } else { - int i, j; + int defid; fcparam *fcp = isp->isp_param; + delay(2 * 1000000); + defid = MAX_FC_TARG; + ISP_LOCK(isp); /* - * wait for the loop to settle. + * We probably won't have clock interrupts running, + * so we'll be really short (smoke test, really) + * at this time. */ - printf("%s: waiting 2 seconds for loop reset settling\n", - isp->isp_name); - delay(2 * 1000000); - for (j = 0; j < 5; j++) { - for (i = 0; i < 5; i++) { - if (isp_control(isp, ISPCTL_FCLINK_TEST, NULL)) - continue; - /* - * Wait extra time to see if the f/w - * eventually completed an FLOGI that - * will allow us to know we're on a - * fabric. - */ - if (fcp->isp_onfabric == 0) { - delay(1 * 1000000); - continue; - } - break; - } + if (isp_control(isp, ISPCTL_FCLINK_TEST, NULL)) { + (void) isp_control(isp, ISPCTL_PDB_SYNC, NULL); if (fcp->isp_fwstate == FW_READY && fcp->isp_loopstate >= LOOP_PDB_RCVD) { - break; + defid = fcp->isp_loopid; } } + ISP_UNLOCK(isp); lptr->adapter_target = fcp->isp_loopid; } /* + * After this point, we *could* be doing the new configuration + * schema which allows interrups, so we can do tsleep/wakeup + * for mailbox stuff at that point. + */ +#if 0 + isp->isp_osinfo.no_mbox_ints = 0; +#endif + + /* * And attach children (if any). */ config_found((void *)isp, lptr, scsiprint); @@ -216,7 +210,7 @@ ispminphys(bp) static int32_t ispcmd_slow(xs) - ISP_SCSI_XFER_T *xs; + XS_T *xs; { sdparam *sdp; int tgt, chan; @@ -289,8 +283,6 @@ ispcmd_slow(xs) } } if (chan == (IS_12X0(isp)? 2 : 1)) { - CFGPRINTF("%s: allowing sync/wide negotiation and " - "tag usage\n", isp->isp_name); isp->isp_osinfo._adapter.scsipi_cmd = ispcmd; if (IS_12X0(isp)) isp->isp_update |= 2; @@ -301,11 +293,10 @@ ispcmd_slow(xs) static int32_t ispcmd(xs) - ISP_SCSI_XFER_T *xs; + XS_T *xs; { struct ispsoftc *isp; int result; - int s; /* * Make sure that there's *some* kind of sane setting. @@ -315,13 +306,13 @@ ispcmd(xs) isp = XS_ISP(xs); - s = splbio(); + ISP_LOCK(isp); if (isp->isp_state < ISP_RUNSTATE) { DISABLE_INTS(isp); isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { ENABLE_INTS(isp); - (void) splx(s); + ISP_UNLOCK(isp); XS_SETERR(xs, HBA_BOTCH); return (CMD_COMPLETE); } @@ -333,10 +324,10 @@ ispcmd(xs) * Check for queue blockage... */ if (isp->isp_osinfo.blocked) { - IDPRINTF(2, ("%s: blocked\n", isp->isp_name)); + isp_prt(isp, ISP_LOGDEBUG2, "blocked"); if (xs->flags & SCSI_POLL) { xs->error = XS_DRIVER_STUFFUP; - splx(s); + ISP_UNLOCK(isp); return (TRY_AGAIN_LATER); } if (isp->isp_osinfo.wqf != NULL) { @@ -346,35 +337,66 @@ ispcmd(xs) } isp->isp_osinfo.wqt = xs; xs->free_list.le_next = NULL; - splx(s); + ISP_UNLOCK(isp); return (SUCCESSFULLY_QUEUED); } - result = ispscsicmd(xs); - if ((xs->flags & SCSI_POLL) == 0) { - switch (result) { - case CMD_QUEUED: - result = SUCCESSFULLY_QUEUED; - if (xs->timeout) { - timeout_add(&xs->stimeout, _XT(xs)); - } - break; - case CMD_EAGAIN: - result = TRY_AGAIN_LATER; - break; - case CMD_RQLATER: - result = SUCCESSFULLY_QUEUED; - timeout_set(&xs->stimeout, isp_requeue, xs); - timeout_add(&xs->stimeout, hz); - break; - case CMD_COMPLETE: - result = COMPLETE; - break; - } - (void) splx(s); + if (xs->flags & SCSI_POLL) { + volatile u_int8_t ombi = isp->isp_osinfo.no_mbox_ints; + isp->isp_osinfo.no_mbox_ints = 1; + result = isp_polled_cmd(isp, xs); + isp->isp_osinfo.no_mbox_ints = ombi; + ISP_UNLOCK(isp); return (result); } + result = isp_start(xs); + +#if 0 +{ + static int na[16] = { 0 }; + if (na[isp->isp_unit] < isp->isp_nactive) { + isp_prt(isp, ISP_LOGALL, "active hiwater %d", isp->isp_nactive); + na[isp->isp_unit] = isp->isp_nactive; + } +} +#endif + + switch (result) { + case CMD_QUEUED: + result = SUCCESSFULLY_QUEUED; + if (xs->timeout) { + timeout_add(&xs->stimeout, _XT(xs)); + } + break; + case CMD_EAGAIN: +#if 0 + result = TRY_AGAIN_LATER; + break; +#endif + case CMD_RQLATER: + result = SUCCESSFULLY_QUEUED; + timeout_set(&xs->stimeout, isp_requeue, xs); + timeout_add(&xs->stimeout, hz); + break; + case CMD_COMPLETE: + result = COMPLETE; + break; + } + ISP_UNLOCK(isp); + return (result); +} + +static int +isp_polled_cmd(isp, xs) + struct ispsoftc *isp; + XS_T *xs; +{ + int result; + int infinite = 0, mswait; + + result = isp_start(xs); + switch (result) { case CMD_QUEUED: result = SUCCESSFULLY_QUEUED; @@ -392,33 +414,45 @@ ispcmd(xs) } + if (result != SUCCESSFULLY_QUEUED) { + return (result); + } + /* - * We can't use interrupts so poll on completion. + * If we can't use interrupts, poll on completion. */ - if (result == SUCCESSFULLY_QUEUED) { - if (isp_poll(isp, xs, xs->timeout)) { - /* - * If no other error occurred but we didn't finish, - * something bad happened. - */ - if (XS_CMD_DONE_P(xs) == 0) { - if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) { - isp_restart(isp); - } - if (XS_NOERR(xs)) { - XS_SETERR(xs, HBA_BOTCH); - } + if ((mswait = XS_TIME(xs)) == 0) + infinite = 1; + + while (mswait || infinite) { + if (isp_intr((void *)isp)) { + if (XS_CMD_DONE_P(xs)) { + break; } } - result = COMPLETE; + USEC_DELAY(1000); + mswait -= 1; + } + + /* + * If no other error occurred but we didn't finish, + * something bad happened. + */ + if (XS_CMD_DONE_P(xs) == 0) { + if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) { + isp_reinit(isp); + } + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_BOTCH); + } } - (void) splx(s); + result = COMPLETE; return (result); } void isp_done(xs) - ISP_SCSI_XFER_T *xs; + XS_T *xs; { XS_CMD_S_DONE(xs); if (XS_CMD_WDOG_P(xs) == 0) { @@ -427,65 +461,45 @@ isp_done(xs) } if (XS_CMD_GRACE_P(xs)) { struct ispsoftc *isp = XS_ISP(xs); - PRINTF("%s: finished command on borrowed time\n", - isp->isp_name); + isp_prt(isp, ISP_LOGDEBUG1, + "finished command on borrowed time"); } XS_CMD_S_CLEAR(xs); scsi_done(xs); } } -static int -isp_poll(isp, xs, mswait) - struct ispsoftc *isp; - ISP_SCSI_XFER_T *xs; - int mswait; -{ - - while (mswait) { - /* Try the interrupt handling routine */ - (void)isp_intr((void *)isp); - - /* See if the xs is now done */ - if (XS_CMD_DONE_P(xs)) { - return (0); - } - delay(1000); /* wait one millisecond */ - mswait--; - } - return (1); -} - - static void isp_wdog(arg) void *arg; { - ISP_SCSI_XFER_T *xs = arg; + XS_T *xs = arg; struct ispsoftc *isp = XS_ISP(xs); u_int32_t handle; - int s = splbio(); /* * We've decided this command is dead. Make sure we're not trying * to kill a command that's already dead by getting it's handle and * and seeing whether it's still alive. */ + ISP_LOCK(isp); handle = isp_find_handle(isp, xs); if (handle) { u_int16_t r, r1, i; if (XS_CMD_DONE_P(xs)) { - PRINTF("%s: watchdog found done cmd (handle 0x%x)\n", - isp->isp_name, handle); - (void) splx(s); + isp_prt(isp, ISP_LOGDEBUG1, + "watchdog found done cmd (handle 0x%x)", + handle); + ISP_UNLOCK(isp); return; } if (XS_CMD_WDOG_P(xs)) { - PRINTF("%s: recursive watchdog (handle 0x%x)\n", - isp->isp_name, handle); - (void) splx(s); + isp_prt(isp, ISP_LOGDEBUG1, + "recursive watchdog (handle 0x%x)", + handle); + ISP_UNLOCK(isp); return; } @@ -494,13 +508,13 @@ isp_wdog(arg) i = 0; do { r = ISP_READ(isp, BIU_ISR); - SYS_DELAY(1); + USEC_DELAY(1); r1 = ISP_READ(isp, BIU_ISR); } while (r != r1 && ++i < 1000); if (INT_PENDING(isp, r) && isp_intr(isp) && XS_CMD_DONE_P(xs)) { - IDPRINTF(1, ("%s: watchdog cleanup (%x, %x)\n", - isp->isp_name, handle, r)); + isp_prt(isp, ISP_LOGDEBUG1, "watchdog cleanup (%x, %x)", + isp->isp_name, handle, r); XS_CMD_C_WDOG(xs); isp_done(xs); } else if (XS_CMD_GRACE_P(xs)) { @@ -516,8 +530,7 @@ isp_wdog(arg) if (XS_XFRLEN(xs)) { ISP_DMAFREE(isp, xs, handle); } - printf("%s: watchdog timeout (%x, %x)\n", - isp->isp_name, handle, r); + printf("%s: watchdog timeout (%x, %x)\n", handle, r); isp_destroy_handle(isp, handle); XS_SETERR(xs, XS_TIMEOUT); XS_CMD_S_CLEAR(xs); @@ -526,13 +539,13 @@ isp_wdog(arg) u_int16_t iptr, optr; ispreq_t *mp; - IDPRINTF(2, ("%s: possible command timeout (%x, %x)\n", - isp->isp_name, handle, r)); + isp_prt(isp, ISP_LOGDEBUG2, + "possible command timeout (%x, %x)", handle, r); XS_CMD_C_WDOG(xs); timeout_add(&xs->stimeout, _XT(xs)); if (isp_getrqentry(isp, &iptr, &optr, (void **) &mp)) { - (void) splx(s); + ISP_UNLOCK(isp); return; } XS_CMD_S_GRACE(xs); @@ -542,13 +555,12 @@ isp_wdog(arg) mp->req_modifier = SYNC_ALL; mp->req_target = XS_CHANNEL(xs) << 7; ISP_SWIZZLE_REQUEST(isp, mp); - MemoryBarrier(); ISP_ADD_REQUEST(isp, iptr); } } else if (isp->isp_dblev) { - PRINTF("%s: watchdog with no command\n", isp->isp_name); + isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command"); } - (void) splx(s); + ISP_UNLOCK(isp); } /* @@ -562,13 +574,13 @@ void isp_uninit(isp) struct ispsoftc *isp; { - int s = splbio(); + ISP_LOCK(isp); /* * Leave with interrupts disabled. */ DISABLE_INTS(isp); - splx(s); + ISP_UNLOCK(isp); } /* @@ -579,7 +591,7 @@ isp_requeue(void *arg) { struct scsi_xfer *xs = arg; struct ispsoftc *isp = XS_ISP(xs); - int s = splbio(); + ISP_LOCK(isp); switch (ispcmd_slow(xs)) { case SUCCESSFULLY_QUEUED: printf("%s: isp_command_reque: queued %d.%d\n", @@ -592,15 +604,17 @@ isp_requeue(void *arg) case TRY_AGAIN_LATER: printf("%s: EAGAIN for %d.%d\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs)); - /* FALLTHROUGH */ + timeout_set(&xs->stimeout, isp_requeue, xs); + timeout_add(&xs->stimeout, hz); + break; case COMPLETE: /* can only be an error */ if (XS_NOERR(xs)) XS_SETERR(xs, XS_DRIVER_STUFFUP); - XS_CMD_DONE(xs); + XS_CMD_S_DONE(xs); break; } - (void) splx(s); + ISP_UNLOCK(isp); } /* @@ -611,23 +625,21 @@ static void isp_internal_restart(void *arg) { struct ispsoftc *isp = arg; - int result, nrestarted = 0, s; + int result, nrestarted = 0; - s = splbio(); + ISP_LOCK(isp); if (isp->isp_osinfo.blocked == 0) { struct scsi_xfer *xs; while ((xs = isp->isp_osinfo.wqf) != NULL) { isp->isp_osinfo.wqf = xs->free_list.le_next; xs->free_list.le_next = NULL; - DISABLE_INTS(isp); - result = ispscsicmd(xs); - ENABLE_INTS(isp); + result = isp_start(xs); if (result != CMD_QUEUED) { printf("%s: botched command restart (0x%x)\n", isp->isp_name, result); if (XS_NOERR(xs)) XS_SETERR(xs, XS_DRIVER_STUFFUP); - XS_CMD_DONE(xs); + XS_CMD_S_DONE(xs); } else if (xs->timeout) { timeout_add(&xs->stimeout, _XT(xs)); } @@ -635,7 +647,7 @@ isp_internal_restart(void *arg) } printf("%s: requeued %d commands\n", isp->isp_name, nrestarted); } - (void) splx(s); + ISP_UNLOCK(isp); } int @@ -645,7 +657,7 @@ isp_async(isp, cmd, arg) void *arg; { int bus, tgt; - int s = splbio(); + switch (cmd) { case ISPASYNC_NEW_TGT_PARAMS: if (IS_SCSI(isp) && isp->isp_dblev) { @@ -657,11 +669,17 @@ isp_async(isp, cmd, arg) bus = (tgt >> 16) & 0xffff; tgt &= 0xffff; sdp += bus; - flags = sdp->isp_devparam[tgt].cur_dflags; period = sdp->isp_devparam[tgt].cur_period; + if ((flags & DPARM_SYNC) && period && (sdp->isp_devparam[tgt].cur_offset) != 0) { + /* + * There's some ambiguity about our negotiated speed + * if we haven't detected LVD mode correctly (which + * seems to happen, unfortunately). If we're in LVD + * mode, then different rules apply about speed. + */ if (sdp->isp_lvdmode || period < 0xc) { switch (period) { case 0x9: @@ -688,25 +706,26 @@ isp_async(isp, cmd, arg) } switch (flags & (DPARM_WIDE|DPARM_TQING)) { case DPARM_WIDE: - wt = ", 16 bit wide\n"; + wt = ", 16 bit wide"; break; case DPARM_TQING: - wt = ", Tagged Queueing Enabled\n"; + wt = ", Tagged Queueing Enabled"; break; case DPARM_WIDE|DPARM_TQING: - wt = ", 16 bit wide, Tagged Queueing Enabled\n"; + wt = ", 16 bit wide, Tagged Queueing Enabled"; break; default: - wt = "\n"; + wt = " "; break; } if (mhz) { - CFGPRINTF("%s: Bus %d Target %d at %dMHz Max " - "Offset %d%s", isp->isp_name, bus, tgt, mhz, - sdp->isp_devparam[tgt].cur_offset, wt); + isp_prt(isp, ISP_LOGINFO, + "Bus %d Target %d at %dMHz Max Offset %d%s", + bus, tgt, mhz, sdp->isp_devparam[tgt].cur_offset, + wt); } else { - CFGPRINTF("%s: Bus %d Target %d Async Mode%s", - isp->isp_name, bus, tgt, wt); + isp_prt(isp, ISP_LOGINFO, + "Bus %d Target %d Async Mode%s", bus, tgt, wt); } break; } @@ -715,7 +734,7 @@ isp_async(isp, cmd, arg) bus = *((int *) arg); else bus = 0; - printf("%s: SCSI bus %d reset detected\n", isp->isp_name, bus); + isp_prt(isp, ISP_LOGINFO, "SCSI bus %d reset detected", bus); break; case ISPASYNC_LOOP_DOWN: /* @@ -723,18 +742,18 @@ isp_async(isp, cmd, arg) * of commands we are firing off that are sure to die. */ isp->isp_osinfo.blocked = 1; - printf("%s: Loop DOWN\n", isp->isp_name); + isp_prt(isp, ISP_LOGINFO, "Loop DOWN"); break; case ISPASYNC_LOOP_UP: isp->isp_osinfo.blocked = 0; timeout_set(&isp->isp_osinfo.rqt, isp_internal_restart, isp); timeout_add(&isp->isp_osinfo.rqt, 1); - printf("%s: Loop UP\n", isp->isp_name); + isp_prt(isp, ISP_LOGINFO, "Loop UP"); break; case ISPASYNC_PDB_CHANGED: if (IS_FC(isp) && isp->isp_dblev) { - const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x " - "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n"; + 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" }; @@ -748,7 +767,7 @@ isp_async(isp, cmd, arg) } else { ptr = "disappeared"; } - printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid, + isp_prt(isp, ISP_LOGINFO, fmt, tgt, lp->loopid, lp->portid, roles[lp->roles & 0x3], ptr, (u_int32_t) (lp->port_wwn >> 32), (u_int32_t) (lp->port_wwn & 0xffffffffLL), @@ -756,25 +775,24 @@ isp_async(isp, cmd, arg) (u_int32_t) (lp->node_wwn & 0xffffffffLL)); break; } +#ifdef ISP2100_FABRIC case ISPASYNC_CHANGE_NOTIFY: - printf("%s: Name Server Database Changed\n", isp->isp_name); + isp_prt(isp, ISP_LOGINFO, "Name Server Database Changed"); break; case ISPASYNC_FABRIC_DEV: { int target; struct lportdb *lp; - char *pt; - sns_ganrsp_t *resp = (sns_ganrsp_t *) arg; + sns_scrsp_t *resp = (sns_scrsp_t *) arg; u_int32_t portid; - u_int64_t wwpn, wwnn; + u_int64_t wwn; fcparam *fcp = isp->isp_param; portid = (((u_int32_t) resp->snscb_port_id[0]) << 16) | (((u_int32_t) resp->snscb_port_id[1]) << 8) | (((u_int32_t) resp->snscb_port_id[2])); - - wwpn = + wwn = (((u_int64_t)resp->snscb_portname[0]) << 56) | (((u_int64_t)resp->snscb_portname[1]) << 48) | (((u_int64_t)resp->snscb_portname[2]) << 40) | @@ -784,60 +802,14 @@ isp_async(isp, cmd, arg) (((u_int64_t)resp->snscb_portname[6]) << 8) | (((u_int64_t)resp->snscb_portname[7])); - wwnn = - (((u_int64_t)resp->snscb_nodename[0]) << 56) | - (((u_int64_t)resp->snscb_nodename[1]) << 48) | - (((u_int64_t)resp->snscb_nodename[2]) << 40) | - (((u_int64_t)resp->snscb_nodename[3]) << 32) | - (((u_int64_t)resp->snscb_nodename[4]) << 24) | - (((u_int64_t)resp->snscb_nodename[5]) << 16) | - (((u_int64_t)resp->snscb_nodename[6]) << 8) | - (((u_int64_t)resp->snscb_nodename[7])); - if (portid == 0 || wwpn == 0) { - break; - } + isp_prt(isp, ISP_LOGINFO, + "Fabric Device (Type 0x%x)@PortID 0x%x WWN 0x%08x%08x", + resp->snscb_port_type, portid, ((u_int32_t)(wwn >> 32)), + ((u_int32_t)(wwn & 0xffffffff))); - switch (resp->snscb_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; - } - CFGPRINTF("%s: %s @ 0x%x, Node 0x%08x%08x Port %08x%08x\n", - isp->isp_name, pt, portid, - ((u_int32_t) (wwnn >> 32)), ((u_int32_t) wwnn), - ((u_int32_t) (wwpn >> 32)), ((u_int32_t) wwpn)); -#if 0 - if ((resp->snscb_fc4_types[1] & 0x1) == 0) { - printf("Types 0..3: 0x%x 0x%x 0x%x 0x%x\n", - resp->snscb_fc4_types[0], resp->snscb_fc4_types[1], - resp->snscb_fc4_types[3], resp->snscb_fc4_types[3]); - break; - } -#endif for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) { lp = &fcp->portdb[target]; - if (lp->port_wwn == wwpn && lp->node_wwn == wwnn) + if (lp->port_wwn == wwn) break; } if (target < MAX_FC_TARG) { @@ -849,18 +821,38 @@ isp_async(isp, cmd, arg) break; } if (target == MAX_FC_TARG) { - printf("%s: no more space for fabric devices\n", - isp->isp_name); - break; + isp_prt(isp, ISP_LOGWARN, + "no more space for fabric devices"); + return (-1); } - lp->node_wwn = wwnn; - lp->port_wwn = wwpn; + lp->port_wwn = lp->node_wwn = wwn; lp->portid = portid; break; } +#endif default: break; } - (void) splx(s); return (0); } + +void +#ifdef __STDC__ +isp_prt(struct ispsoftc *isp, int level, const char *fmt, ...) +#else +isp_log(isp, fmt, va_alist) + struct ispsoftc *isp; + char *fmt; + va_dcl; +#endif +{ + va_list ap; + if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) { + return; + } + printf("%s: ", isp->isp_name); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); +} diff --git a/sys/dev/ic/isp_openbsd.h b/sys/dev/ic/isp_openbsd.h index 89f34fb2633..1d8d2c511ae 100644 --- a/sys/dev/ic/isp_openbsd.h +++ b/sys/dev/ic/isp_openbsd.h @@ -1,39 +1,30 @@ -/* $OpenBSD: isp_openbsd.h,v 1.9 2000/07/06 05:31:48 mjacob Exp $ */ +/* $OpenBSD: isp_openbsd.h,v 1.10 2000/10/16 01:02:00 mjacob Exp $ */ /* * OpenBSD Specific definitions for the Qlogic ISP Host Adapter - * - *--------------------------------------- - * Copyright (c) 1999 by Matthew Jacob - * NASA/Ames Research Center + */ +/* + * Copyright (C) 1999, 2000 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 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 - * 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. + * notice, 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 ``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 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. */ - #ifndef _ISP_OPENBSD_H #define _ISP_OPENBSD_H @@ -50,7 +41,6 @@ #include <sys/user.h> #include <sys/queue.h> - #include <scsi/scsi_all.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> @@ -62,117 +52,199 @@ #include <vm/vm_param.h> #include <vm/pmap.h> -#define ISP_PLATFORM_VERSION_MAJOR 0 -#define ISP_PLATFORM_VERSION_MINOR 10 -#define ISP_SCSI_XFER_T struct scsi_xfer +#define ISP_PLATFORM_VERSION_MAJOR 1 +#define ISP_PLATFORM_VERSION_MINOR 0 + struct isposinfo { struct device _dev; struct scsi_link _link[2]; struct scsi_adapter _adapter; - int blocked; + int splsaved; + int mboxwaiting; + u_int32_t islocked; + u_int32_t onintstack; + unsigned int : 30, + no_mbox_ints : 1, + blocked : 1; union { - int _seed; + u_int64_t _wwn; u_int16_t _discovered[2]; } un; -#define seed un._seed #define discovered un._discovered struct scsi_xfer *wqf, *wqt; struct timeout rqt; }; -#define MBOX_WAIT_COMPLETE(isp) \ - { \ - int j; \ - for (j = 0; j < 60 * 2000; j++) { \ - if (isp_intr(isp) == 0) { \ - SYS_DELAY(500); \ - } \ - if (isp->isp_mboxbsy == 0) \ - break; \ - } \ - if (isp->isp_mboxbsy != 0) \ - printf("%s: mailbox timeout\n", isp->isp_name); \ - } +/* + * Required Macros/Defines + */ -#define MBOX_NOTIFY_COMPLETE(isp) isp->isp_mboxbsy = 0 +#define INLINE inline -#define MAXISPREQUEST 256 #define ISP2100_FABRIC 1 #define ISP2100_SCRLEN 0x400 -#include <dev/ic/ispreg.h> -#include <dev/ic/ispvar.h> -#include <dev/ic/ispmbox.h> +#define MEMZERO bzero +#define MEMCPY(dst, src, amt) bcopy((src), (dst), (amt)) +#define SNPRINTF snprintf +#define STRNCAT strncat +#define USEC_DELAY(x) delay(x) -#define IDPRINTF(lev, x) if (isp->isp_dblev >= lev) printf x -#define PRINTF printf +#define NANOTIME_T struct timeval +#define GET_NANOTIME microtime +#define GET_NANOSEC(x) (((x)->tv_sec * 1000000 + (x)->tv_usec) * 1000) +#define NANOTIME_SUB isp_microtime_sub -#define MEMZERO bzero -#define MEMCPY(dst, src, count) bcopy((src), (dst), (count)) +#define MAXISPREQUEST(isp) 256 #ifdef __alpha__ -#define MemoryBarrier alpha_mb +#define MEMORYBARRIER(isp, type, offset, size) alpha_mb() #else -#define MemoryBarrier() +#define MEMORYBARRIER(isp, type, offset, size) #endif -#define DMA_MSW(x) (((x) >> 16) & 0xffff) -#define DMA_LSW(x) (((x) & 0xffff)) - -#if defined(SCSIDEBUG) -#define DFLT_DBLEVEL 3 -#define CFGPRINTF printf -#elif defined(DEBUG) -#define DFLT_DBLEVEL 2 -#define CFGPRINTF printf -#elif defined(DIAGNOSTIC) -#define DFLT_DBLEVEL 1 -#define CFGPRINTF if (0) printf -#else -#define DFLT_DBLEVEL 0 -#define CFGPRINTF if (0) printf -#endif +#define MBOX_ACQUIRE(isp) +#define MBOX_WAIT_COMPLETE isp_wait_complete + +#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 ISP_LOCKVAL_DECL int isp_spl_save -#define ISP_ILOCKVAL_DECL ISP_LOCKVAL_DECL -#define ISP_LOCK(x) isp_spl_save = splbio() -#define ISP_UNLOCK(x) (void) splx(isp_spl_save) -#define ISP_ILOCK ISP_LOCK -#define ISP_IUNLOCK ISP_UNLOCK +#define MBOX_RELEASE(isp) +#ifndef SCSI_GOOD +#define SCSI_GOOD 0x0 +#endif +#ifndef SCSI_CHECK +#define SCSI_CHECK 0x2 +#endif +#ifndef SCSI_BUSY +#define SCSI_BUSY 0x8 +#endif +#ifndef SCSI_QFULL +#define SCSI_QFULL 0x28 +#endif -#define XS_NULL(xs) xs == NULL || xs->sc_link == NULL +#define XS_T struct scsi_xfer +#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) #define XS_TGT(xs) ((int) (xs)->sc_link->target) -#define XS_RESID(xs) (xs)->resid -#define XS_CHANNEL(xs) (((xs)->sc_link->flags & SDEV_2NDBUS)? 1 : 0) -#define XS_XFRLEN(xs) (xs)->datalen -#define XS_CDBLEN(xs) (xs)->cmdlen #define XS_CDBP(xs) ((caddr_t) (xs)->cmd) -#define XS_STS(xs) (xs)->status +#define XS_CDBLEN(xs) (xs)->cmdlen +#define XS_XFRLEN(xs) (xs)->datalen #define XS_TIME(xs) (xs)->timeout +#define XS_RESID(xs) (xs)->resid +#define XS_STSP(xs) (&(xs)->status) #define XS_SNSP(xs) (&(xs)->sense) #define XS_SNSLEN(xs) (sizeof (xs)->sense) #define XS_SNSKEY(xs) ((xs)->sense.flags) +#define XS_TAG_P(xs) (((xs)->flags & SCSI_POLL) != 0) +#define XS_TAG_TYPE(xs) REQFLAG_STAG + +#define XS_SETERR(xs, v) (xs)->error = v + +# define HBA_NOERROR XS_NOERROR +# define HBA_BOTCH XS_DRIVER_STUFFUP +# define HBA_CMDTIMEOUT XS_TIMEOUT +# define HBA_SELTIMEOUT XS_SELTIMEOUT +# define HBA_TGTBSY XS_BUSY +# define HBA_BUSRESET XS_RESET +# define HBA_ABORTED XS_DRIVER_STUFFUP +# define HBA_DATAOVR XS_DRIVER_STUFFUP +# define HBA_ARQFAIL XS_DRIVER_STUFFUP + +#define XS_ERR(xs) (xs)->error + +#define XS_NOERR(xs) (xs)->error == XS_NOERROR -#define HBA_NOERROR XS_NOERROR -#define HBA_BOTCH XS_DRIVER_STUFFUP -#define HBA_CMDTIMEOUT XS_TIMEOUT -#define HBA_SELTIMEOUT XS_SELTIMEOUT -#define HBA_TGTBSY XS_BUSY -#ifdef XS_RESET -#define HBA_BUSRESET XS_RESET +#define XS_INITERR(xs) (xs)->error = 0, XS_CMD_S_CLEAR(xs) + +#define XS_SAVE_SENSE(xs, sp) \ + bcopy(sp->req_sense_data, &(xs)->sense, \ + imin(XS_SNSLEN(xs), sp->req_sense_len)) + +#define XS_SET_STATE_STAT(a, b, c) + +#define DEFAULT_IID(x) 7 +#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_UNSWIZZLE_AND_COPY_PDBP(isp, dest, src) \ + if((void *)src != (void *)dest) bcopy(src, dest, sizeof (isp_pdb_t)) +#define ISP_SWIZZLE_ICB(a, b) +#ifdef __sparc__ +#define ISP_SWIZZLE_REQUEST(a, b) \ + ISP_SBUSIFY_ISPHDR(a, &(b)->req_header); \ + ISP_SBUSIFY_ISPREQ(a, b) +#define ISP_UNSWIZZLE_RESPONSE(a, b, c) \ + ISP_SBUSIFY_ISPHDR(a, &(b)->req_header) +#else +#define ISP_SWIZZLE_REQUEST(a, b) +#define ISP_UNSWIZZLE_RESPONSE(a, b, c) +#endif +#define ISP_SWIZZLE_SNS_REQ(a, b) +#define ISP_UNSWIZZLE_SNS_RSP(a, b, c) +#ifdef __sparc__ +#define ISP_SWIZZLE_NVRAM_WORD(isp, rp) \ + { \ + u_int16_t tmp = *rp >> 8; \ + tmp |= ((*rp & 0xff) << 8); \ + *rp = tmp; \ + } #else -#define HBA_BUSRESET XS_DRIVER_STUFFUP +#define ISP_SWIZZLE_NVRAM_WORD(isp, rp) #endif -#define HBA_ABORTED XS_DRIVER_STUFFUP -#define HBA_DATAOVR XS_DRIVER_STUFFUP -#define HBA_ARQFAIL XS_DRIVER_STUFFUP -#define XS_SNS_IS_VALID(xs) (xs)->error = XS_SENSE -#define XS_IS_SNS_VALID(xs) ((xs)->error == XS_SENSE) +/* + * Includes of common header files + */ + +#include <dev/ic/ispreg.h> +#include <dev/ic/ispvar.h> +#include <dev/ic/ispmbox.h> + +/* + * isp_osinfo definitions, extensions and shorthand. + */ +#define isp_name isp_osinfo._dev.dv_xname +#define isp_unit isp_osinfo._dev.dv_unit + +/* + * Driver prototypes.. + */ +void isp_attach __P((struct ispsoftc *)); +void isp_uninit __P((struct ispsoftc *)); + +static inline void isp_lock __P((struct ispsoftc *)); +static inline void isp_unlock __P((struct ispsoftc *)); +static inline char *strncat __P((char *, const char *, size_t)); +static inline u_int64_t +isp_microtime_sub __P((struct timeval *, struct timeval *)); +static void isp_wait_complete __P((struct ispsoftc *)); + +/* + * Driver wide data... + */ + +/* + * Locking macros... + */ +#define ISP_LOCK isp_lock +#define ISP_UNLOCK isp_unlock +#define ISP_ILOCK(x) isp_lock(x); isp->isp_osinfo.onintstack++ +#define ISP_IUNLOCK(x) isp->isp_osinfo.onintstack--; isp_unlock(x) + +/* + * Platform private flags + */ #define XS_PSTS_INWDOG 0x10000 #define XS_PSTS_GRACE 0x20000 @@ -192,68 +264,36 @@ struct isposinfo { #define XS_CMD_S_CLEAR(xs) (xs)->flags &= ~XS_PSTS_ALL -#define XS_INITERR(xs) (xs)->error = 0, XS_CMD_S_CLEAR(xs) -#define XS_SETERR(xs, v) (xs)->error = v -#define XS_ERR(xs) (xs)->error -#define XS_NOERR(xs) (xs)->error == XS_NOERROR - -#define XS_CMD_DONE isp_done - /* - * We use whether or not we're a polled command to decide about tagging. + * Platform specific 'inline' or support functions */ -#define XS_CANTAG(xs) (((xs)->flags & SCSI_POLL) != 0) - -/* - * This is our default tag (ordered). - */ -#define XS_KINDOF_TAG(xs) REQFLAG_OTAG - -#define CMD_COMPLETE 100 -#define CMD_EAGAIN 101 -#define CMD_QUEUED 102 -#define CMD_RQLATER 103 - -#define isp_name isp_osinfo._dev.dv_xname -#define isp_unit isp_osinfo._dev.dv_unit - -#define SCSI_QFULL 0x28 - -#define SYS_DELAY(x) delay(x) - -#define WATCH_INTERVAL 30 - -#define FC_FW_READY_DELAY (5 * 1000000) -#define DEFAULT_LOOPID(x) 107 -#define DEFAULT_WWN(x) (0x1000b00d00000000LL + (x)->isp_osinfo.seed) - -extern void isp_attach __P((struct ispsoftc *)); -extern void isp_uninit __P((struct ispsoftc *)); -extern void isp_done __P((ISP_SCSI_XFER_T *)); - +static inline void +isp_lock(isp) + struct ispsoftc *isp; +{ + int s = splbio(); + if (isp->isp_osinfo.islocked++ == 0) { + isp->isp_osinfo.splsaved = s; + } else { + splx(s); + } +} -#define ISP_UNSWIZZLE_AND_COPY_PDBP(isp, dest, src) \ - bcopy(src, dest, sizeof (isp_pdb_t)) -#define ISP_SWIZZLE_ICB(a, b) -#ifdef __sparc__ -#define ISP_SWIZZLE_CONTINUATION(a, b) ISP_SBUSIFY_ISPHDR(a, &(b)->req_header) -#define ISP_SWIZZLE_REQUEST(a, b) \ - ISP_SBUSIFY_ISPHDR(a, &(b)->req_header); \ - ISP_SBUSIFY_ISPREQ(a, b) -#define ISP_UNSWIZZLE_RESPONSE(a, b) \ - ISP_SBUSIFY_ISPHDR(a, &(b)->req_header) -#else -#define ISP_SWIZZLE_CONTINUATION(a, b) -#define ISP_SWIZZLE_REQUEST(a, b) -#define ISP_UNSWIZZLE_RESPONSE(a, b) -#endif -#define ISP_SWIZZLE_SNS_REQ(a, b) -#define ISP_UNSWIZZLE_SNS_RSP(a, b, c) +static inline void +isp_unlock(isp) + struct ispsoftc *isp; +{ + if (isp->isp_osinfo.islocked-- <= 1) { + isp->isp_osinfo.islocked = 0; + splx(isp->isp_osinfo.splsaved); + } +} -#define STRNCAT strncat -static inline char *strncat(char *, const char *, size_t); static inline char * -strncat(char *d, const char *s, size_t c) +strncat(d, s, c) + char *d; + const char *s; + size_t c; { char *t = d; @@ -270,8 +310,63 @@ strncat(char *d, const char *s, size_t c) return (t); } +static inline u_int64_t +isp_microtime_sub(b, a) + struct timeval *b; + struct timeval *a; +{ + struct timeval x; + u_int64_t elapsed; + timersub(b, a, &x); + elapsed = GET_NANOSEC(&x); + if (elapsed == 0) + elapsed++; + return (elapsed); +} + +static inline void +isp_wait_complete(isp) + struct ispsoftc *isp; +{ + if (isp->isp_osinfo.onintstack || isp->isp_osinfo.no_mbox_ints) { + int usecs = 0; + while (usecs < 2 * 1000000) { + (void) isp_intr(isp); + if (isp->isp_mboxbsy == 0) { + break; + } + USEC_DELAY(500); + usecs += 500; + } + if (isp->isp_mboxbsy != 0) { + isp_prt(isp, ISP_LOGWARN, "Mailbox Cmd (poll) Timeout"); + } + } else { + int rv = 0; + isp->isp_osinfo.mboxwaiting = 1; + while (isp->isp_osinfo.mboxwaiting && rv == 0) { + static struct timeval fivesec = { 5, 0 }; + int timo; + struct timeval tv; + microtime(&tv); + timeradd(&tv, &fivesec, &tv); + if ((timo = hzto(&tv)) == 0) { + timo = 1; + } + rv = tsleep(&isp->isp_osinfo.mboxwaiting, + PRIBIO, "isp_mboxcmd", timo); + } + if (rv == EWOULDBLOCK) { + isp->isp_mboxbsy = 0; + isp->isp_osinfo.mboxwaiting = 0; + isp_prt(isp, ISP_LOGWARN, "Mailbox Cmd (intr) Timeout"); + } + } +} -#define INLINE inline +/* + * Common inline functions + */ #include <dev/ic/isp_inline.h> -#endif /* _ISP_OPENBSD_H */ +#endif /* _ISP_NETBSD_H */ diff --git a/sys/dev/ic/isp_target.c b/sys/dev/ic/isp_target.c index d6b7fd14b9e..4718c2b6f61 100644 --- a/sys/dev/ic/isp_target.c +++ b/sys/dev/ic/isp_target.c @@ -1,8 +1,8 @@ -/* $OpenBSD: isp_target.c,v 1.2 2000/07/06 05:31:48 mjacob Exp $ */ +/* $OpenBSD: isp_target.c,v 1.3 2000/10/16 01:02:00 mjacob Exp $ */ /* * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters. * - * Copyright (c) 1999 by Matthew Jacob + * Copyright (c) 1999, 2000 by Matthew Jacob * All rights reserved. * mjacob@feral.com * @@ -12,10 +12,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 @@ -49,7 +46,10 @@ #endif #ifdef ISP_TARGET_MODE -int isp_tdebug = 0; +static char *atiocope = + "ATIO returned for lun %d because it was in the middle of Bus Device Reset"; +static char *atior = + "ATIO returned for lun %d from initiator %d because a Bus Reset occurred"; static void isp_got_msg __P((struct ispsoftc *, int, in_entry_t *)); static void isp_got_msg_fc __P((struct ispsoftc *, int, in_fcentry_t *)); @@ -179,8 +179,8 @@ isp_target_notify(isp, vptr, optrp) inotp->in_iid &= ~0x80; } } - ITDEBUG(2, ("isp_target_notify: Immediate Notify, " - "status=0x%x seqid=0x%x\n", status, seqid)); + isp_prt(isp, ISP_LOGTDEBUG1, + "Immediate Notify, status=0x%x seqid=0x%x", status, seqid); switch (status) { case IN_RESET: (void) isp_async(isp, ISPASYNC_BUS_RESET, &bus); @@ -194,26 +194,29 @@ isp_target_notify(isp, vptr, optrp) } break; case IN_RSRC_UNAVAIL: - PRINTF("%s: Firmware out of ATIOs\n", isp->isp_name); + isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs"); break; case IN_ABORT_TASK: - PRINTF("%s: Abort Task for Initiator %d RX_ID 0x%x\n", - isp->isp_name, inot_fcp->in_iid, seqid); + isp_prt(isp, ISP_LOGWARN, + "Abort Task for Initiator %d RX_ID 0x%x", + inot_fcp->in_iid, seqid); break; case IN_PORT_LOGOUT: - PRINTF("%s: Port Logout for Initiator %d RX_ID 0x%x\n", - isp->isp_name, inot_fcp->in_iid, seqid); + isp_prt(isp, ISP_LOGWARN, + "Port Logout for Initiator %d RX_ID 0x%x", + inot_fcp->in_iid, seqid); break; case IN_PORT_CHANGED: - PRINTF("%s: Port Changed for Initiator %d RX_ID 0x%x\n", - isp->isp_name, inot_fcp->in_iid, seqid); + isp_prt(isp, ISP_LOGWARN, + "Port Changed for Initiator %d RX_ID 0x%x", + inot_fcp->in_iid, seqid); break; case IN_GLOBAL_LOGO: - PRINTF("%s: All ports logged out\n", isp->isp_name); + isp_prt(isp, ISP_LOGWARN, "All ports logged out"); break; default: - PRINTF("%s: bad status (0x%x) in isp_target_notify\n", - isp->isp_name, status); + isp_prt(isp, ISP_LOGERR, + "bad status (0x%x) in isp_target_notify", status); break; } isp_notify_ack(isp, vptr); @@ -225,18 +228,19 @@ isp_target_notify(isp, vptr, optrp) * Immediate Notify entry for some asynchronous event. */ if (IS_FC(isp)) { - ITDEBUG(2, ("%s: Notify Ack status=0x%x seqid 0x%x\n", - isp->isp_name, nack_fcp->na_status, - nack_fcp->na_seqid)); + isp_prt(isp, ISP_LOGTDEBUG1, + "Notify Ack status=0x%x seqid 0x%x", + nack_fcp->na_status, nack_fcp->na_seqid); } else { - ITDEBUG(2, ("%s: Notify Ack event 0x%x status=0x%x " - "seqid 0x%x\n", isp->isp_name, nackp->na_event, - nackp->na_status, nackp->na_seqid)); + isp_prt(isp, ISP_LOGTDEBUG1, + "Notify Ack event 0x%x status=0x%x seqid 0x%x", + nackp->na_event, nackp->na_status, nackp->na_seqid); } break; default: - PRINTF("%s: Unknown entry type 0x%x in isp_target_notify", - isp->isp_name, hdrp->rqs_entry_type); + isp_prt(isp, ISP_LOGERR, + "Unknown entry type 0x%x in isp_target_notify", + hdrp->rqs_entry_type); rval = -1; break; } @@ -310,8 +314,8 @@ isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque) } if (isp_getrqentry(isp, &iptr, &optr, &outp)) { - PRINTF("%s: Request Queue Overflow in isp_lun_cmd\n", - isp->isp_name); + isp_prt(isp, ISP_LOGWARN, + "Request Queue Overflow in isp_lun_cmd"); return (-1); } ISP_SWIZ_ENABLE_LUN(isp, outp, &el); @@ -331,8 +335,8 @@ isp_target_put_entry(isp, ap) u_int8_t etype = ((isphdr_t *) ap)->rqs_entry_type; if (isp_getrqentry(isp, &iptr, &optr, &outp)) { - PRINTF("%s: Request Queue Overflow in isp_target_put_entry " - "for type 0x%x\n", isp->isp_name, etype); + isp_prt(isp, ISP_LOGWARN, + "Request Queue Overflow in isp_target_put_entry"); return (-1); } switch (etype) { @@ -349,8 +353,8 @@ isp_target_put_entry(isp, ap) ISP_SWIZ_CTIO2(isp, outp, ap); break; default: - PRINTF("%s: Unknown type 0x%x in isp_put_entry\n", - isp->isp_name, etype); + isp_prt(isp, ISP_LOGERR, + "Unknown type 0x%x in isp_put_entry", etype); return (-1); } @@ -518,22 +522,21 @@ isp_target_async(isp, bus, event) */ MEMZERO(&msg, sizeof msg); if (IS_FC(isp)) { - msg.nt_iid = - ((fcparam *)isp->isp_param)->isp_loopid; + msg.nt_iid = FCPARAM(isp)->isp_loopid; } else { - msg.nt_iid = - ((sdparam *)isp->isp_param)->isp_initiator_id; + msg.nt_iid = SDPARAM(isp)->isp_initiator_id; } msg.nt_bus = bus; msg.nt_msg[0] = MSG_BUS_DEV_RESET; (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg); break; default: - PRINTF("%s: isp_target_async: unknown event 0x%x\n", - isp->isp_name, event); + isp_prt(isp, ISP_LOGERR, + "isp_target_async: unknown event 0x%x", event); break; } - isp_notify_ack(isp, NULL); + if (isp->isp_state == ISP_RUNSTATE) + isp_notify_ack(isp, NULL); } @@ -566,8 +569,8 @@ isp_got_msg(isp, bus, inp) MEMCPY(msg.nt_msg, inp->in_msg, IN_MSGLEN); (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg); } else { - PRINTF("%s: unknown immediate notify status 0x%x\n", - isp->isp_name, inp->in_status); + isp_prt(isp, ISP_LOGERR, + "unknown immediate notify status 0x%x", inp->in_status); } } @@ -580,12 +583,12 @@ isp_got_msg_fc(isp, bus, inp) int bus; in_fcentry_t *inp; { - static char *f1 = "%s: %s from iid %d lun %d seq 0x%x\n"; + static char *f1 = "%s from iid %d lun %d seq 0x%x"; static char *f2 = - "%s: unknown %s 0x%x lun %d iid %d task flags 0x%x seq 0x%x\n"; + "unknown %s 0x%x lun %d iid %d task flags 0x%x seq 0x%x\n"; if (inp->in_status != IN_MSG_RECEIVED) { - PRINTF(f2, isp->isp_name, "immediate notify status", + isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", inp->in_status, inp->in_lun, inp->in_iid, inp->in_task_flags, inp->in_seqid); } else { @@ -602,28 +605,28 @@ isp_got_msg_fc(isp, bus, inp) msg.nt_tagval = inp->in_seqid; if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK) { - PRINTF(f1, isp->isp_name, "ABORT TASK", + isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK", inp->in_iid, inp->in_lun, inp->in_seqid); msg.nt_msg[0] = MSG_ABORT_TAG; } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { - PRINTF(f1, isp->isp_name, "CLEAR TASK SET", + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", inp->in_iid, inp->in_lun, inp->in_seqid); msg.nt_msg[0] = MSG_CLEAR_QUEUE; } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { - PRINTF(f1, isp->isp_name, "TARGET RESET", + isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", inp->in_iid, inp->in_lun, inp->in_seqid); msg.nt_msg[0] = MSG_BUS_DEV_RESET; } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { - PRINTF(f1, isp->isp_name, "CLEAR ACA", + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", inp->in_iid, inp->in_lun, inp->in_seqid); /* ???? */ msg.nt_msg[0] = MSG_REL_RECOVERY; } else if (inp->in_task_flags & TASK_FLAGS_TERMINATE_TASK) { - PRINTF(f1, isp->isp_name, "TERMINATE TASK", + isp_prt(isp, ISP_LOGINFO, f1, "TERMINATE TASK", inp->in_iid, inp->in_lun, inp->in_seqid); msg.nt_msg[0] = MSG_TERM_IO_PROC; } else { - PRINTF(f2, isp->isp_name, "task flag", + isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, inp->in_lun, inp->in_iid, inp->in_task_flags, inp->in_seqid); } @@ -643,8 +646,8 @@ isp_notify_ack(isp, arg) void *outp; if (isp_getrqentry(isp, &iptr, &optr, &outp)) { - PRINTF("%s: Request Queue Overflow For isp_notify_ack\n", - isp->isp_name); + isp_prt(isp, ISP_LOGWARN, + "Request Queue Overflow For isp_notify_ack"); return; } @@ -720,8 +723,8 @@ isp_handle_atio(isp, aep) /* * ATIO rejected by the firmware due to disabled lun. */ - PRINTF("%s: rejected ATIO for disabled lun %d\n", - isp->isp_name, lun); + isp_prt(isp, ISP_LOGERR, + "rejected ATIO for disabled lun %d", lun); break; case AT_NOCAP: /* @@ -729,8 +732,9 @@ isp_handle_atio(isp, aep) * We sent an ATIO that overflowed the firmware's * command resource count. */ - PRINTF("%s: rejected ATIO for lun %d because of command count" - " overflow\n", isp->isp_name, lun); + isp_prt(isp, ISP_LOGERR, + "rejected ATIO for lun %d because of command count" + " overflow", lun); break; case AT_BDR_MSG: @@ -743,9 +747,7 @@ isp_handle_atio(isp, aep) * not increment it. Therefore we should never get * this status here. */ - PRINTF("%s: ATIO returned for lun %d because it was in the " - " middle of coping with a Bus Device Reset\n", - isp->isp_name, lun); + isp_prt(isp, ISP_LOGERR, atiocope, lun); break; case AT_CDB: /* Got a CDB */ @@ -765,15 +767,14 @@ isp_handle_atio(isp, aep) * Ignore it because the async event will clear things * up for us. */ - PRINTF("%s: ATIO returned for lun %d from initiator %d because" - " a Bus Reset occurred\n", isp->isp_name, lun, - aep->at_iid); + isp_prt(isp, ISP_LOGWARN, atior, lun, aep->at_iid); break; default: - PRINTF("%s: Unknown ATIO status 0x%x from initiator %d for lun" - " %d\n", isp->isp_name, aep->at_status, aep->at_iid, lun); + isp_prt(isp, ISP_LOGERR, + "Unknown ATIO status 0x%x from initiator %d for lun %d", + aep->at_status, aep->at_iid, lun); (void) isp_target_put_atio(isp, aep->at_iid, aep->at_tgt, lun, aep->at_tag_type, aep->at_tag_val); break; @@ -810,8 +811,8 @@ isp_handle_atio2(isp, aep) /* * ATIO rejected by the firmware due to disabled lun. */ - PRINTF("%s: rejected ATIO2 for disabled lun %d\n", - isp->isp_name, lun); + isp_prt(isp, ISP_LOGERR, + "rejected ATIO2 for disabled lun %d", lun); break; case AT_NOCAP: /* @@ -819,8 +820,8 @@ isp_handle_atio2(isp, aep) * We sent an ATIO that overflowed the firmware's * command resource count. */ - PRINTF("%s: rejected ATIO2 for lun %d because of command count" - " overflow\n", isp->isp_name, lun); + isp_prt(isp, ISP_LOGERR, + "rejected ATIO2 for lun %d- command count overflow", lun); break; case AT_BDR_MSG: @@ -833,9 +834,7 @@ isp_handle_atio2(isp, aep) * not increment it. Therefore we should never get * this status here. */ - PRINTF("%s: ATIO2 returned for lun %d because it was in the " - " middle of coping with a Bus Device Reset\n", - isp->isp_name, lun); + isp_prt(isp, ISP_LOGERR, atiocope, lun); break; case AT_CDB: /* Got a CDB */ @@ -854,15 +853,14 @@ isp_handle_atio2(isp, aep) * Ignore it because the async event will clear things * up for us. */ - PRINTF("%s: ATIO2 returned for lun %d from initiator %d because" - " a Bus Reset occurred\n", isp->isp_name, lun, - aep->at_iid); + isp_prt(isp, ISP_LOGERR, atior, lun, aep->at_iid); break; default: - PRINTF("%s: Unknown ATIO2 status 0x%x from initiator %d for lun" - " %d\n", isp->isp_name, aep->at_status, aep->at_iid, lun); + isp_prt(isp, ISP_LOGERR, + "Unknown ATIO2 status 0x%x from initiator %d for lun %d", + aep->at_status, aep->at_iid, lun); (void) isp_target_put_atio(isp, aep->at_iid, 0, lun, 0, 0); break; } @@ -873,16 +871,16 @@ isp_handle_ctio(isp, ct) struct ispsoftc *isp; ct_entry_t *ct; { - ISP_SCSI_XFER_T *xs; - int pl = 0; + XS_T *xs; + int pl = ISP_LOGTDEBUG2; char *fmsg = NULL; if (ct->ct_reserved) { xs = isp_find_xs(isp, ct->ct_reserved); if (xs == NULL) - pl = 0; + pl = ISP_LOGALL; } else { - pl = 2; + pl = ISP_LOGTDEBUG1; xs = NULL; } @@ -902,8 +900,8 @@ isp_handle_ctio(isp, ct) /* * Nothing to do in this case. */ - IDPRINTF(pl, ("%s:CTIO- iid %d disconnected OK\n", - isp->isp_name, ct->ct_iid)); + isp_prt(isp, pl, "CTIO- iid %d disconnected OK", + ct->ct_iid); return; } break; @@ -933,7 +931,7 @@ isp_handle_ctio(isp, ct) if (fmsg == NULL) fmsg = "ABORT TASK sent by Initiator"; - PRINTF("%s: CTIO destroyed by %s\n", isp->isp_name, fmsg); + isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg); break; case CT_INVAL: @@ -941,8 +939,9 @@ isp_handle_ctio(isp, ct) * CTIO rejected by the firmware due to disabled lun. * "Cannot Happen". */ - PRINTF("%s: Firmware rejected CTIO for disabled lun %d\n", - isp->isp_name, ct->ct_lun); + isp_prt(isp, ISP_LOGERR, + "Firmware rejected CTIO for disabled lun %d", + ct->ct_lun); break; case CT_NOPATH: @@ -952,8 +951,9 @@ isp_handle_ctio(isp, ct) * we tried to access the bus while a non-disconnecting * command is in process. */ - PRINTF("%s: Firmware rejected CTIO for bad nexus %d/%d/%d\n", - isp->isp_name, ct->ct_iid, ct->ct_tgt, ct->ct_lun); + isp_prt(isp, ISP_LOGERR, + "Firmware rejected CTIO for bad nexus %d/%d/%d", + ct->ct_iid, ct->ct_tgt, ct->ct_lun); break; case CT_RSELTMO: @@ -962,7 +962,7 @@ isp_handle_ctio(isp, ct) case CT_TIMEOUT: if (fmsg == NULL) fmsg = "Command"; - PRINTF("%s: Firmware timed out on %s\n", isp->isp_name, fmsg); + isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); break; case CT_ERR: @@ -980,7 +980,7 @@ isp_handle_ctio(isp, ct) if (fmsg == NULL) fmsg = "unacknowledged Immediate Notify pending"; - PRINTF("%s: CTIO returned by f/w- %s\n", isp->isp_name, fmsg); + isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); #if 0 if (status & SENSEVALID) { bcopy((caddr_t) (cep + CTIO_SENSE_OFFSET), @@ -991,7 +991,7 @@ isp_handle_ctio(isp, ct) #endif break; default: - PRINTF("%s: Unknown CTIO status 0x%x\n", isp->isp_name, + isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", ct->ct_status & ~QLTM_SVALID); break; } @@ -1006,19 +1006,16 @@ isp_handle_ctio(isp, ct) */ if (ct->ct_reserved == 0) { if ((ct->ct_flags & CT_SENDSTATUS) == 0) { - IDPRINTF(pl, - ("%s: intermediate CTIO completed ok\n", - isp->isp_name)); + isp_prt(isp, pl, + "intermediate CTIO completed ok"); } else { - IDPRINTF(pl, - ("%s: unmonitored CTIO completed ok\n", - isp->isp_name)); + isp_prt(isp, pl, + "unmonitored CTIO completed ok"); } } else { - IDPRINTF(pl, - ("%s: NO xs for CTIO (handle 0x%x) status 0x%x\n", - isp->isp_name, ct->ct_reserved, - ct->ct_status & ~QLTM_SVALID)); + isp_prt(isp, pl, + "NO xs for CTIO (handle 0x%x) status 0x%x", + ct->ct_reserved, ct->ct_status & ~QLTM_SVALID); } } else { if (ct->ct_flags & CT_SENDSTATUS) { @@ -1030,15 +1027,13 @@ isp_handle_ctio(isp, ct) * only there can we do the appropriate command * complete thread synchronization. */ - IDPRINTF(pl, - ("%s:status CTIO complete\n", isp->isp_name)); + isp_prt(isp, pl, "status CTIO complete"); } else { /* * Final CTIO completed. Release DMA resources and * notify platform dependent layers. */ - IDPRINTF(pl, - ("%s: data CTIO complete\n", isp->isp_name)); + isp_prt(isp, pl, "data CTIO complete"); ISP_DMAFREE(isp, xs, ct->ct_reserved); } (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); @@ -1053,16 +1048,16 @@ isp_handle_ctio2(isp, ct) struct ispsoftc *isp; ct2_entry_t *ct; { - ISP_SCSI_XFER_T *xs; - int pl = 3; + XS_T *xs; + int pl = ISP_LOGTDEBUG2; char *fmsg = NULL; if (ct->ct_reserved) { xs = isp_find_xs(isp, ct->ct_reserved); if (xs == NULL) - pl = 0; + pl = ISP_LOGALL; } else { - pl = 2; + pl = ISP_LOGTDEBUG1; xs = NULL; } @@ -1102,14 +1097,14 @@ isp_handle_ctio2(isp, ct) if (fmsg == NULL) fmsg = "ABORT TASK sent by Initiator"; - PRINTF("%s: CTIO2 destroyed by %s\n", isp->isp_name, fmsg); + isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s", fmsg); break; case CT_INVAL: /* * CTIO rejected by the firmware - invalid data direction. */ - PRINTF("%s: CTIO2 had wrong data directiond\n", isp->isp_name); + isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data directiond"); break; case CT_NOPATH: @@ -1119,8 +1114,9 @@ isp_handle_ctio2(isp, ct) * we tried to access the bus while a non-disconnecting * command is in process. */ - PRINTF("%s: Firmware rejected CTIO2 for bad nexus %d->%d\n", - isp->isp_name, ct->ct_iid, ct->ct_lun); + isp_prt(isp, ISP_LOGERR, + "Firmware rejected CTIO2 for bad nexus %d->%d", + ct->ct_iid, ct->ct_lun); break; case CT_RSELTMO: @@ -1129,7 +1125,7 @@ isp_handle_ctio2(isp, ct) case CT_TIMEOUT: if (fmsg == NULL) fmsg = "Command"; - PRINTF("%s: Firmware timed out on %s\n", isp->isp_name, fmsg); + isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); break; case CT_ERR: @@ -1154,7 +1150,7 @@ isp_handle_ctio2(isp, ct) if (fmsg == NULL) fmsg = "unacknowledged Immediate Notify pending"; - PRINTF("%s: CTIO returned by f/w- %s\n", isp->isp_name, fmsg); + isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); #if 0 if (status & SENSEVALID) { bcopy((caddr_t) (cep + CTIO_SENSE_OFFSET), @@ -1170,13 +1166,13 @@ isp_handle_ctio2(isp, ct) * CTIO rejected by the firmware because an invalid RX_ID. * Just print a message. */ - PRINTF("%s: CTIO2 completed with Invalid RX_ID 0x%x\n", - isp->isp_name, ct->ct_rxid); + isp_prt(isp, ISP_LOGERR, + "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid); break; default: - IDPRINTF(pl, ("%s: Unknown CTIO status 0x%x\n", isp->isp_name, - ct->ct_status & ~QLTM_SVALID)); + isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", + ct->ct_status & ~QLTM_SVALID); break; } @@ -1190,19 +1186,16 @@ isp_handle_ctio2(isp, ct) */ if (ct->ct_reserved == 0) { if ((ct->ct_flags & CT_SENDSTATUS) == 0) { - IDPRINTF(pl, - ("%s: intermediate CTIO completed ok\n", - isp->isp_name)); + isp_prt(isp, pl, + "intermediate CTIO completed ok"); } else { - IDPRINTF(pl, - ("%s: unmonitored CTIO completed ok\n", - isp->isp_name)); + isp_prt(isp, pl, + "unmonitored CTIO completed ok"); } } else { - IDPRINTF(pl, - ("%s: NO xs for CTIO (handle 0x%x) status 0x%x\n", - isp->isp_name, ct->ct_reserved, - ct->ct_status & ~QLTM_SVALID)); + isp_prt(isp, pl, + "NO xs for CTIO (handle 0x%x) status 0x%x", + ct->ct_reserved, ct->ct_status & ~QLTM_SVALID); } } else { if (ct->ct_flags & CT_SENDSTATUS) { @@ -1214,15 +1207,13 @@ isp_handle_ctio2(isp, ct) * only there can we do the appropriate command * complete thread synchronization. */ - IDPRINTF(pl, - ("%s: status CTIO complete\n", isp->isp_name)); + isp_prt(isp, pl, "status CTIO complete"); } else { /* * Final CTIO completed. Release DMA resources and * notify platform dependent layers. */ - IDPRINTF(pl, - ("%s: data CTIO complete\n", isp->isp_name)); + isp_prt(isp, pl, "data CTIO complete"); ISP_DMAFREE(isp, xs, ct->ct_reserved); } (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); diff --git a/sys/dev/ic/isp_target.h b/sys/dev/ic/isp_target.h index 725a9dfb2e7..03c4e3135dc 100644 --- a/sys/dev/ic/isp_target.h +++ b/sys/dev/ic/isp_target.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_target.h,v 1.2 2000/07/06 05:31:48 mjacob Exp $ */ +/* $OpenBSD: isp_target.h,v 1.3 2000/10/16 01:02:00 mjacob Exp $ */ /* * Qlogic Target Mode Structure and Flag Definitions * @@ -7,7 +7,7 @@ * pms@psconsult.com * All rights reserved. * - * Additional Copyright (c) 1999 + * Additional Copyright (c) 1999< 2000 * Matthew Jacob * mjacob@feral.com * All rights reserved. @@ -19,10 +19,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 @@ -129,6 +126,7 @@ typedef struct { /* * Values for the in_status field */ +#define IN_REJECT 0x0D /* Message Reject message received */ #define IN_RESET 0x0E /* Bus Reset occurred */ #define IN_NO_RCAP 0x16 /* requested capability not available */ #define IN_IDE_RECEIVED 0x33 /* Initiator Detected Error msg received */ @@ -138,6 +136,7 @@ typedef struct { #define IN_PORT_LOGOUT 0x29 /* port has logged out (FC) */ #define IN_PORT_CHANGED 0x2A /* port changed */ #define IN_GLOBAL_LOGO 0x2E /* all ports logged out */ +#define IN_NO_NEXUS 0x3B /* Nexus not established */ /* * Values for the in_task_flags field- should only get one at a time! @@ -323,6 +322,7 @@ typedef struct { #define CT_NO_DATA 0x000000C0 /* bits 6&7, Data direction */ #define CT_CCINCR 0x00000100 /* bit 8, autoincrement atio count */ #define CT_DATAMASK 0x000000C0 /* bits 6&7, Data direction */ +#define CT_INISYNCWIDE 0x00004000 /* bit 14, Do Sync/Wide Negotiation */ #define CT_NODISC 0x00008000 /* bit 15, Disconnects disabled */ #define CT_DSDP 0x01000000 /* bit 24, Disable Save Data Pointers */ #define CT_SENDRDP 0x04000000 /* bit 26, Send Restore Pointers msg */ @@ -341,12 +341,15 @@ typedef struct { #define CT_RSELTMO 0x0A /* reselection timeout after 2 tries */ #define CT_TIMEOUT 0x0B /* timed out */ #define CT_RESET 0x0E /* SCSI Bus Reset occurred */ +#define CT_PARITY 0x0F /* Uncorrectable Parity Error */ +#define CT_PANIC 0x13 /* Unrecoverable Error */ #define CT_PHASE_ERROR 0x14 /* Bus phase sequence error */ #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_LOGOUT 0x29 /* port logout */ #define CT_PORTCHANGED 0x2A /* port changed */ +#define CT_IDE 0x33 /* Initiator Detected Error */ #define CT_NOACK 0x35 /* Outstanding Immed. Notify. entry */ /* @@ -502,7 +505,7 @@ typedef struct { #define ISP_SWIZ_CTIO(isp, dest, vsrc) \ { \ - ct_entry_t *source = (ct_entry-t *) vsrc; \ + ct_entry_t *source = (ct_entry_t *) vsrc; \ ct_entry_t *local, *vdst; \ if ((void *)dest == (void *)vsrc) { \ MEMCPY(vsrc, &local, sizeof (ct_entry_t)); \ @@ -605,11 +608,8 @@ typedef struct { * Debug macros */ -extern int isp_tdebug; #define ISP_TDQE(isp, msg, idx, arg) \ - if (isp_tdebug > 3) isp_print_qentry(isp, msg, idx, arg) - -#define ITDEBUG(level, msg) if (isp_tdebug >= level) PRINTF msg + if (isp->isp_dblev & ISP_LOGTDEBUG2) isp_print_qentry(isp, msg, idx, arg) /* * The functions below are target mode functions that @@ -624,7 +624,7 @@ int isp_target_notify __P((struct ispsoftc *, void *, u_int16_t *)); /* * Enable/Disable/Modify a logical unit. */ -#define DFLT_CMD_CNT (RESULT_QUEUE_LEN >> 1) +#define DFLT_CMD_CNT 32 /* XX */ #define DFLT_INOTIFY (4) int isp_lun_cmd __P((struct ispsoftc *, int, int, int, int, u_int32_t)); diff --git a/sys/dev/ic/ispmbox.h b/sys/dev/ic/ispmbox.h index 1d298dbd751..0186e830b52 100644 --- a/sys/dev/ic/ispmbox.h +++ b/sys/dev/ic/ispmbox.h @@ -1,12 +1,9 @@ -/* $OpenBSD: ispmbox.h,v 1.9 2000/07/06 05:31:49 mjacob Exp $ */ +/* $OpenBSD: ispmbox.h,v 1.10 2000/10/16 01:02:01 mjacob Exp $ */ /* * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters. * - *--------------------------------------- - * Copyright (c) 1997, 1998, 1999 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (c) 1997, 1998, 1999, 2000 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 +11,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 @@ -160,6 +154,9 @@ typedef struct { #define MBOX_LOOP_ID_USED 0x4008 #define MBOX_ALL_IDS_USED 0x4009 #define MBOX_NOT_LOGGED_IN 0x400A +#define MBLOGALL 0x000f +#define MBLOGNONE 0x0000 +#define MBLOGMASK(x) ((x) & 0xf) /* * Asynchronous event status codes @@ -371,7 +368,7 @@ typedef struct { #define req_response_len req_time /* FC only */ u_int16_t req_sense_len; u_int32_t req_resid; - u_int8_t _res1[8]; + u_int8_t req_response[8]; /* FC only */ u_int8_t req_sense_data[32]; } ispstatusreq_t; @@ -381,20 +378,25 @@ typedef struct { */ #define RQCS_RU 0x800 /* Residual Under */ #define RQCS_RO 0x400 /* Residual Over */ +#define RQCS_RESID (RQCS_RU|RQCS_RO) #define RQCS_SV 0x200 /* Sense Length Valid */ -#define RQCS_RV 0x100 /* Residual Valid */ +#define RQCS_RV 0x100 /* FCP Response Length Valid */ /* * Completion Status Codes. */ #define RQCS_COMPLETE 0x0000 -#define RQCS_INCOMPLETE 0x0001 #define RQCS_DMA_ERROR 0x0002 -#define RQCS_TRANSPORT_ERROR 0x0003 #define RQCS_RESET_OCCURRED 0x0004 #define RQCS_ABORTED 0x0005 #define RQCS_TIMEOUT 0x0006 #define RQCS_DATA_OVERRUN 0x0007 +#define RQCS_DATA_UNDERRUN 0x0015 +#define RQCS_QUEUE_FULL 0x001C + +/* 1X00 Only Completion Codes */ +#define RQCS_INCOMPLETE 0x0001 +#define RQCS_TRANSPORT_ERROR 0x0003 #define RQCS_COMMAND_OVERRUN 0x0008 #define RQCS_STATUS_OVERRUN 0x0009 #define RQCS_BAD_MESSAGE 0x000a @@ -408,26 +410,24 @@ typedef struct { #define RQCS_DEVICE_RESET_MSG_FAILED 0x0012 #define RQCS_ID_MSG_FAILED 0x0013 #define RQCS_UNEXP_BUS_FREE 0x0014 -#define RQCS_DATA_UNDERRUN 0x0015 #define RQCS_XACT_ERR1 0x0018 #define RQCS_XACT_ERR2 0x0019 #define RQCS_XACT_ERR3 0x001A #define RQCS_BAD_ENTRY 0x001B -#define RQCS_QUEUE_FULL 0x001C #define RQCS_PHASE_SKIPPED 0x001D #define RQCS_ARQS_FAILED 0x001E #define RQCS_WIDE_FAILED 0x001F #define RQCS_SYNCXFER_FAILED 0x0020 #define RQCS_LVD_BUSERR 0x0021 -/* 2100 Only Completion Codes */ +/* 2X00 Only Completion Codes */ #define RQCS_PORT_UNAVAILABLE 0x0028 #define RQCS_PORT_LOGGED_OUT 0x0029 #define RQCS_PORT_CHANGED 0x002A #define RQCS_PORT_BUSY 0x002B /* - * State Flags (not applicable to 2100) + * 1X00 specific State Flags */ #define RQSF_GOT_BUS 0x0100 #define RQSF_GOT_TARGET 0x0200 @@ -438,7 +438,7 @@ typedef struct { #define RQSF_XFER_COMPLETE 0x4000 /* - * Status Flags (not applicable to 2100) + * 1X00 Status Flags */ #define RQSTF_DISCONNECT 0x0001 #define RQSTF_SYNCHRONOUS 0x0002 @@ -450,6 +450,29 @@ typedef struct { #define RQSTF_NEGOTIATION 0x0080 /* + * 2X00 specific state flags + */ +/* RQSF_SENT_CDB */ +/* RQSF_XFRD_DATA */ +/* RQSF_GOT_STATUS */ +/* RQSF_XFER_COMPLETE */ + +/* + * 2X00 specific status flags + */ +/* RQSTF_ABORTED */ +/* RQSTF_TIMEOUT */ +#define RQSTF_DMA_ERROR 0x0080 +#define RQSTF_LOGOUT 0x2000 + +/* + * Miscellaneous + */ +#ifndef ISP_EXEC_THROTTLE +#define ISP_EXEC_THROTTLE 16 +#endif + +/* * FC (ISP2100) specific data structures */ diff --git a/sys/dev/ic/ispreg.h b/sys/dev/ic/ispreg.h index bacf424cb8f..ab985321f61 100644 --- a/sys/dev/ic/ispreg.h +++ b/sys/dev/ic/ispreg.h @@ -1,10 +1,9 @@ -/* $OpenBSD: ispreg.h,v 1.8 2000/07/06 05:31:49 mjacob Exp $ */ +/* $OpenBSD: ispreg.h,v 1.9 2000/10/16 01:02:01 mjacob Exp $ */ /* * Machine Independent (well, as best as possible) register * definitions for Qlogic ISP SCSI adapters. * - * Copyright (c) 1997, 1998, 1999 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -13,10 +12,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 @@ -79,6 +75,9 @@ #define ISP1080_DMA_REGS_OFF 0x60 #define DMA_REGS_OFF 0x00 /* same as BIU block */ +#define SBUS_REGSIZE 0x450 +#define PCI_REGSIZE 0x100 + /* * NB: The *_BLOCK definitions have no specific hardware meaning. * They serve simply to note to the MD layer which block of diff --git a/sys/dev/ic/ispvar.h b/sys/dev/ic/ispvar.h index b87c8e8d1e1..c0daaa3ab6b 100644 --- a/sys/dev/ic/ispvar.h +++ b/sys/dev/ic/ispvar.h @@ -1,22 +1,17 @@ -/* $OpenBSD: ispvar.h,v 1.11 2000/07/06 05:31:49 mjacob Exp $ */ +/* $OpenBSD: ispvar.h,v 1.12 2000/10/16 01:02:01 mjacob Exp $ */ /* * Soft Definitions for for Qlogic ISP SCSI adapters. * - *--------------------------------------- - * Copyright (c) 1997, 1998, 1999 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (c) 1997, 1998, 1999, 2000 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 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 @@ -58,8 +53,8 @@ #endif #endif -#define ISP_CORE_VERSION_MAJOR 1 -#define ISP_CORE_VERSION_MINOR 16 +#define ISP_CORE_VERSION_MAJOR 2 +#define ISP_CORE_VERSION_MINOR 0 /* * Vector for bus specific code to provide specific services. @@ -70,23 +65,20 @@ struct ispmdvec { void (*dv_wr_reg) __P((struct ispsoftc *, int, u_int16_t)); int (*dv_mbxdma) __P((struct ispsoftc *)); int (*dv_dmaset) __P((struct ispsoftc *, - ISP_SCSI_XFER_T *, ispreq_t *, u_int16_t *, u_int16_t)); + XS_T *, ispreq_t *, u_int16_t *, u_int16_t)); void (*dv_dmaclr) - __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t)); + __P((struct ispsoftc *, XS_T *, u_int32_t)); void (*dv_reset0) __P((struct ispsoftc *)); void (*dv_reset1) __P((struct ispsoftc *)); - void (*dv_dregs) __P((struct ispsoftc *)); + void (*dv_dregs) __P((struct ispsoftc *, const char *)); const u_int16_t *dv_ispfw; /* ptr to f/w */ - u_int16_t dv_fwlen; /* length of f/w */ - u_int16_t dv_codeorg; /* code ORG for f/w */ - u_int32_t dv_fwrev; /* f/w revision */ - /* - * Initial values for conf1 register - */ u_int16_t dv_conf1; u_int16_t dv_clock; /* clock frequency */ }; +/* + * Overall parameters + */ #define MAX_TARGETS 16 #ifdef ISP2100_FABRIC #define MAX_FC_TARG 256 @@ -99,7 +91,8 @@ struct ispmdvec { /* - * Macros to read, write ISP registers through bus specific code. + * Macros to access ISP registers through bus specific layers- + * mostly wrappers to vector through the mdvec structure. */ #define ISP_READ(isp, reg) \ @@ -122,8 +115,8 @@ struct ispmdvec { if ((isp)->isp_mdvec->dv_reset0) (*(isp)->isp_mdvec->dv_reset0)((isp)) #define ISP_RESET1(isp) \ if ((isp)->isp_mdvec->dv_reset1) (*(isp)->isp_mdvec->dv_reset1)((isp)) -#define ISP_DUMPREGS(isp) \ - if ((isp)->isp_mdvec->dv_dregs) (*(isp)->isp_mdvec->dv_dregs)((isp)) +#define ISP_DUMPREGS(isp, m) \ + if ((isp)->isp_mdvec->dv_dregs) (*(isp)->isp_mdvec->dv_dregs)((isp),(m)) #define ISP_SETBITS(isp, reg, val) \ (*(isp)->isp_mdvec->dv_wr_reg)((isp), (reg), ISP_READ((isp), (reg)) | (val)) @@ -131,25 +124,41 @@ struct ispmdvec { #define ISP_CLRBITS(isp, reg, val) \ (*(isp)->isp_mdvec->dv_wr_reg)((isp), (reg), ISP_READ((isp), (reg)) & ~(val)) -/* this is the size of a queue entry (request and response) */ +/* + * The MEMORYBARRIER macro is defined per platform (to provide synchronization + * on Request and Response Queues, Scratch DMA areas, and Registers) + * + * Defined Memory Barrier Synchronization Types + */ +#define SYNC_REQUEST 0 /* request queue synchronization */ +#define SYNC_RESULT 1 /* result queue synchronization */ +#define SYNC_SFORDEV 2 /* scratch, sync for ISP */ +#define SYNC_SFORCPU 3 /* scratch, sync for CPU */ +#define SYNC_REG 4 /* for registers */ + +/* + * Request/Response Queue defines and macros. + * The maximum is defined per platform (and can be based on board type). + */ +/* This is the size of a queue entry (request and response) */ #define QENTRY_LEN 64 -/* both request and result queue length must be a power of two */ -#define RQUEST_QUEUE_LEN MAXISPREQUEST -/* I've seen wierdnesses with the result queue < 64 */ -#if MAXISPREQUEST > 64 -#define RESULT_QUEUE_LEN (MAXISPREQUEST/2) -#else -#define RESULT_QUEUE_LEN MAXISPREQUEST -#endif +/* Both request and result queue length must be a power of two */ +#define RQUEST_QUEUE_LEN(x) MAXISPREQUEST(x) +#define RESULT_QUEUE_LEN(x) \ + (((MAXISPREQUEST(x) >> 2) < 64)? 64 : MAXISPREQUEST(x) >> 2) #define ISP_QUEUE_ENTRY(q, idx) ((q) + ((idx) * QENTRY_LEN)) #define ISP_QUEUE_SIZE(n) ((n) * QENTRY_LEN) #define ISP_NXT_QENTRY(idx, qlen) (((idx) + 1) & ((qlen)-1)) -#define ISP_QAVAIL(in, out, qlen) \ +#define ISP_QFREE(in, out, qlen) \ ((in == out)? (qlen - 1) : ((in > out)? \ ((qlen - 1) - (in - out)) : (out - in - 1))) +#define ISP_QAVAIL(isp) \ + ISP_QFREE(isp->isp_reqidx, isp->isp_reqodx, RQUEST_QUEUE_LEN(isp)) #define ISP_ADD_REQUEST(isp, iptr) \ - ISP_WRITE(isp, INMAILBOX4, iptr), isp->isp_reqidx = iptr + MEMORYBARRIER(isp, SYNC_REQUEST, iptr, QENTRY_LEN); \ + ISP_WRITE(isp, INMAILBOX4, iptr); \ + isp->isp_reqidx = iptr /* * SCSI Specific Host Adapter Parameters- per bus, per target @@ -165,7 +174,7 @@ typedef struct { isp_ultramode : 1, isp_diffmode : 1, isp_lvdmode : 1, - : 1, + isp_fast_mttr : 1, /* fast sram */ isp_initiator_id : 4, isp_async_data_setup : 4; u_int16_t isp_selection_timeout; @@ -200,15 +209,18 @@ typedef struct { #define DPARM_ARQ 0x0400 #define DPARM_QFRZ 0x0200 #define DPARM_RENEG 0x0100 -#define DPARM_NARROW 0x0080 /* Possibly only available with >= 7.55 fw */ -#define DPARM_ASYNC 0x0040 /* Possibly only available with >= 7.55 fw */ +#define DPARM_NARROW 0x0080 +#define DPARM_ASYNC 0x0040 +#define DPARM_PPR 0x0020 #define DPARM_DEFAULT (0xFF00 & ~DPARM_QFRZ) #define DPARM_SAFE_DFLT (DPARM_DEFAULT & ~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING)) /* technically, not really correct, as they need to be rated based upon clock */ -#define ISP_40M_SYNCPARMS 0x080a -#define ISP_20M_SYNCPARMS 0x080c +#define ISP_80M_SYNCPARMS 0x0c09 +#define ISP_40M_SYNCPARMS 0x0c0a +#define ISP_20M_SYNCPARMS 0x0c0c +#define ISP_20M_SYNCPARMS_1040 0x080c #define ISP_10M_SYNCPARMS 0x0c19 #define ISP_08M_SYNCPARMS 0x0c25 #define ISP_05M_SYNCPARMS 0x0c32 @@ -293,7 +305,7 @@ typedef struct { /* * Soft Structure per host adapter */ -struct ispsoftc { +typedef struct ispsoftc { /* * Platform (OS) specific data */ @@ -317,12 +329,12 @@ struct ispsoftc { u_int8_t isp_revision; /* HBA Chip H/W Revision */ u_int32_t isp_maxluns; /* maximum luns supported */ - u_int32_t : 4, + u_int32_t isp_touched : 1, /* board ever seen? */ - isp_fast_mttr : 1, /* fast sram */ - isp_bustype : 1, /* SBus or PCI */ : 1, - isp_dblev : 8, /* debug level */ + isp_bustype : 1, /* SBus or PCI */ + isp_loaded_fw : 1, /* loaded firmware */ + isp_dblev : 12, /* debug log mask */ isp_clock : 8, /* input clock */ isp_confopts : 8; /* config options */ @@ -346,7 +358,7 @@ struct ispsoftc { /* * Active commands are stored here, indexed by handle functions. */ - ISP_SCSI_XFER_T **isp_xflist; + XS_T **isp_xflist; /* * request/result queue pointers and dma handles for them. @@ -355,13 +367,13 @@ struct ispsoftc { caddr_t isp_result; u_int32_t isp_rquest_dma; u_int32_t isp_result_dma; -}; +} ispsoftc_t; #define SDPARAM(isp) ((sdparam *) (isp)->isp_param) #define FCPARAM(isp) ((fcparam *) (isp)->isp_param) /* - * ISP States + * ISP Driver Run States */ #define ISP_NILSTATE 0 #define ISP_RESETSTATE 1 @@ -377,6 +389,10 @@ struct ispsoftc { #define ISP_CFG_OWNWWN 0x02 /* override NVRAM wwn */ #define ISP_CFG_NPORT 0x04 /* try to force N- instead of L-Port */ +/* + * Firmware related defines + */ +#define ISP_CODE_ORG 0x1000 /* default f/w code start */ #define ISP_FW_REV(maj, min, mic) ((maj << 24) | (min << 16) | mic) #define ISP_FW_REVX(xp) ((xp[0]<<24) | (xp[1] << 16) | xp[2]) @@ -420,9 +436,14 @@ struct ispsoftc { #define IS_2100(isp) (isp->isp_type == ISP_HA_FC_2100) #define IS_2200(isp) (isp->isp_type == ISP_HA_FC_2200) +/* + * DMA cookie macros + */ +#define DMA_MSW(x) (((x) >> 16) & 0xffff) +#define DMA_LSW(x) (((x) & 0xffff)) /* - * Function Prototypes + * Core System Function Prototypes */ /* @@ -439,7 +460,7 @@ void isp_init __P((struct ispsoftc *)); /* * Reset the ISP and call completion for any orphaned commands. */ -void isp_restart __P((struct ispsoftc *)); +void isp_reinit __P((struct ispsoftc *)); /* * Interrupt Service Routine @@ -447,9 +468,19 @@ void isp_restart __P((struct ispsoftc *)); int isp_intr __P((void *)); /* - * Command Entry Point + * Command Entry Point- Platform Dependent layers call into this */ -int32_t ispscsicmd __P((ISP_SCSI_XFER_T *)); +int isp_start __P((XS_T *)); +/* these values are what isp_start returns */ +#define CMD_COMPLETE 101 /* command completed */ +#define CMD_EAGAIN 102 /* busy- maybe retry later */ +#define CMD_QUEUED 103 /* command has been queued for execution */ +#define CMD_RQLATER 104 /* requeue this command later */ + +/* + * Command Completion Point- Core layers call out from this with completed cmds + */ +void isp_done __P((XS_T *)); /* * Platform Dependent to External to Internal Control Function @@ -492,8 +523,137 @@ typedef enum { int isp_async __P((struct ispsoftc *, ispasync_t, void *)); /* - * lost command routine (XXXX IN TRANSITION XXXX) + * Platform Dependent Error and Debug Printout */ -void isp_lostcmd __P((struct ispsoftc *, ISP_SCSI_XFER_T *)); +void isp_prt __P((struct ispsoftc *, int level, const char *, ...)); +#define ISP_LOGALL 0x0 /* log always */ +#define ISP_LOGCONFIG 0x1 /* log configuration messages */ +#define ISP_LOGINFO 0x2 /* log informational messages */ +#define ISP_LOGWARN 0x4 /* log warning messages */ +#define ISP_LOGERR 0x8 /* log error messages */ +#define ISP_LOGDEBUG0 0x10 /* log simple debug messages */ +#define ISP_LOGDEBUG1 0x20 /* log intermediate debug messages */ +#define ISP_LOGDEBUG2 0x40 /* log most debug messages */ +#define ISP_LOGDEBUG3 0x100 /* log high frequency debug messages */ +#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) */ +/* + * Each Platform provides it's own isposinfo substructure of the ispsoftc + * defined above. + * + * Each platform must also provide the following macros/defines: + * + * + * INLINE - platform specific define for 'inline' functions + * + * ISP2100_FABRIC - defines whether FABRIC support is enabled + * ISP2100_SCRLEN - length for the Fibre Channel scratch DMA area + * + * MEMZERO(dst, src) platform zeroing function + * MEMCPY(dst, src, count) platform copying function + * SNPRINTF(buf, bufsize, fmt, ...) snprintf + * STRNCAT(dstbuf, size, srcbuf) strncat + * USEC_DELAY(usecs) microsecond spindelay function + * + * NANOTIME_T nanosecond time type + * + * GET_NANOTIME(NANOTIME_T *) get current nanotime. + * + * GET_NANOSEC(NANOTIME_T *) get u_int64_t from NANOTIME_T + * + * NANOTIME_SUB(NANOTIME_T *, NANOTIME_T *) + * subtract two NANOTIME_T values + * + * + * MAXISPREQUEST(struct ispsoftc *) maximum request queue size + * for this particular board type + * + * MEMORYBARRIER(struct ispsoftc *, barrier_type, offset, size) + * + * Function/Macro the provides memory synchronization on + * various objects so that the ISP's and the system's view + * 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_NOTIFY_COMPLETE(struct ispsoftc *) notification of mbox cmd donee + * MBOX_RELEASE(struct ispsoftc *) release lock on mailbox regs + * + * + * SCSI_GOOD SCSI 'Good' Status + * SCSI_CHECK SCSI 'Check Condition' Status + * SCSI_BUSY SCSI 'Busy' Status + * SCSI_QFULL SCSI 'Queue Full' Status + * + * XS_T Platform SCSI transaction type (i.e., command for HBA) + * 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 "" + * XS_LUN(xs) gets the lun "" + * XS_CDBP(xs) gets a pointer to the scsi CDB "" + * XS_CDBLEN(xs) gets the CDB's length "" + * XS_XFRLEN(xs) gets the associated data transfer length "" + * XS_TIME(xs) gets the time (in milliseconds) for this command + * XS_RESID(xs) gets the current residual count + * XS_STSP(xs) gets a pointer to the SCSI status byte "" + * XS_SNSP(xs) gets a pointer to the associate sense data + * XS_SNSLEN(xs) gets the length of sense data storage + * XS_SNSKEY(xs) dereferences XS_SNSP to get the current stored Sense Key + * XS_TAG_P(xs) predicate of whether this command should be tagged + * XS_TAG_TYPE(xs) which type of tag to use + * XS_SETERR(xs) set error state + * + * HBA_NOERROR command has no erros + * HBA_BOTCH hba botched something + * HBA_CMDTIMEOUT command timed out + * HBA_SELTIMEOUT selection timed out (also port logouts for FC) + * HBA_TGTBSY target returned a BUSY status + * HBA_BUSRESET bus reset destroyed command + * HBA_ABORTED command was aborted (by request) + * HBA_DATAOVR a data overrun was detected + * HBA_ARQFAIL Automatic Request Sense failed + * + * XS_ERR(xs) return current error state + * XS_NOERR(xs) there is no error currently set + * XS_INITERR(xs) initialize error state + * + * XS_SAVE_SENSE(xs, sp) 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 + * These establish reasonable defaults for each platform. + * These must be available independent of card NVRAM and are + * to be used should NVRAM not be readable. + * + * ISP_NODEWWN(struct ispsoftc *) FC Node WWN to use + * 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 + * 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 + * used when sending the Qlogic f/w the Initialization Control + * Block. + * + * (XXX these do endian specific transformations- in transition XXX) + * ISP_SWIZZLE_ICB + * ISP_UNSWIZZLE_AND_COPY_PDBP + * ISP_SWIZZLE_CONTINUATION + * ISP_SWIZZLE_REQUEST + * ISP_UNSWIZZLE_RESPONSE + * ISP_SWIZZLE_SNS_REQ + * ISP_UNSWIZZLE_SNS_RSP + * ISP_SWIZZLE_NVRAM_WORD + * + * + */ #endif /* _ISPVAR_H */ diff --git a/sys/dev/pci/isp_pci.c b/sys/dev/pci/isp_pci.c index a5ac338f90d..36173fed7b2 100644 --- a/sys/dev/pci/isp_pci.c +++ b/sys/dev/pci/isp_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_pci.c,v 1.12 2000/07/06 05:11:26 mjacob Exp $ */ +/* $OpenBSD: isp_pci.c,v 1.13 2000/10/16 01:01:58 mjacob Exp $ */ /* * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. * @@ -52,7 +52,7 @@ static int isp_pci_dmasetup __P((struct ispsoftc *, struct scsi_xfer *, static void isp_pci_dmateardown __P((struct ispsoftc *, struct scsi_xfer *, u_int32_t)); static void isp_pci_reset1 __P((struct ispsoftc *)); -static void isp_pci_dumpregs __P((struct ispsoftc *)); +static void isp_pci_dumpregs __P((struct ispsoftc *, const char *)); static int isp_pci_intr __P((void *)); #ifndef ISP_CODE_ORG @@ -112,7 +112,7 @@ static struct ispmdvec mdvec = { NULL, isp_pci_reset1, isp_pci_dumpregs, - ISP_1040_RISC_CODE, 0, ISP_CODE_ORG, 0, + ISP_1040_RISC_CODE, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 }; #endif @@ -127,7 +127,7 @@ static struct ispmdvec mdvec_1080 = { NULL, isp_pci_reset1, isp_pci_dumpregs, - ISP_1080_RISC_CODE, 0, ISP_CODE_ORG, 0, + ISP_1080_RISC_CODE, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 }; #endif @@ -142,7 +142,7 @@ static struct ispmdvec mdvec_12160 = { NULL, isp_pci_reset1, isp_pci_dumpregs, - ISP_12160_RISC_CODE, 0, ISP_CODE_ORG, 0, + ISP_12160_RISC_CODE, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 }; #endif @@ -157,7 +157,7 @@ static struct ispmdvec mdvec_2100 = { NULL, isp_pci_reset1, isp_pci_dumpregs, - ISP_2100_RISC_CODE, 0, ISP_CODE_ORG + ISP_2100_RISC_CODE }; #endif @@ -171,7 +171,7 @@ static struct ispmdvec mdvec_2200 = { NULL, isp_pci_reset1, isp_pci_dumpregs, - ISP_2200_RISC_CODE, 0, ISP_CODE_ORG + ISP_2200_RISC_CODE }; #endif @@ -318,7 +318,7 @@ isp_pci_attach(parent, self, aux) bus_space_handle_t sh, ioh, memh; pci_intr_handle_t ih; const char *intrstr; - int ioh_valid, memh_valid, i, s; + int ioh_valid, memh_valid, i; bus_addr_t iobase, mbase; bus_size_t iosize, msize; @@ -533,6 +533,23 @@ isp_pci_attach(parent, self, aux) data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCIR_ROMADDR); data &= ~1; pci_conf_write(pa->pa_pc, pa->pa_tag, PCIR_ROMADDR, data); + /* + * Set up logging levels. + */ +#ifdef ISP_LOGDEFAULT + isp->isp_dblev = ISP_LOGDEFAULT; +#else + isp->isp_dblev = ISP_LOGCONFIG|ISP_LOGWARN|ISP_LOGERR; +#ifdef SCSIDEBUG + isp->isp_dblev |= ISP_LOGDEBUG1|ISP_LOGDEBUG2; +#endif +#ifdef DEBUG + isp->isp_dblev |= ISP_LOGDEBUG0; +#endif +#ifdef DIAGNOSTIC + isp->isp_dblev |= ISP_LOGINFO; +#endif +#endif #ifdef DEBUG if (oneshot) { @@ -563,32 +580,24 @@ isp_pci_attach(parent, self, aux) printf("%s: interrupting at %s\n", isp->isp_name, intrstr); if (IS_FC(isp)) { - long foo; - /* - * This isn't very random, but it's the best we can do for - * the real edge case of cards that don't have WWNs. - */ - foo = (long) isp; - foo >>= 4; - foo &= 0x7; - while (version[foo]) - isp->isp_osinfo.seed += (int) version[foo++]; - isp->isp_osinfo.seed <<= 8; - isp->isp_osinfo.seed += (isp->isp_osinfo._dev.dv_unit + 1); + DEFAULT_NODEWWN(isp) = 0x400000007F000002; + DEFAULT_PORTWWN(isp) = 0x400000007F000002; } - s = splbio(); + isp->isp_osinfo.no_mbox_ints = 1; + ISP_LOCK(isp); isp_reset(isp); if (isp->isp_state != ISP_RESETSTATE) { free(isp->isp_param, M_DEVBUF); - (void) splx(s); + ISP_UNLOCK(isp); return; } + ENABLE_INTS(isp); isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { isp_uninit(isp); + ISP_UNLOCK(isp); free(isp->isp_param, M_DEVBUF); - (void) splx(s); return; } @@ -601,13 +610,12 @@ isp_pci_attach(parent, self, aux) &pcs->pci_xfer_dmap[i])) { printf("%s: can't create dma maps\n", isp->isp_name); isp_uninit(isp); + ISP_UNLOCK(isp); free(isp->isp_param, M_DEVBUF); - (void) splx(s); return; } } - ENABLE_INTS(isp); /* * Do Generic attach now. @@ -615,9 +623,11 @@ isp_pci_attach(parent, self, aux) isp_attach(isp); if (isp->isp_state != ISP_RUNSTATE) { isp_uninit(isp); + ISP_UNLOCK(isp); free(isp->isp_param, M_DEVBUF); + } else { + ISP_UNLOCK(isp); } - (void) splx(s); } static u_int16_t @@ -772,8 +782,8 @@ isp_pci_mbxdma(isp) if (isp->isp_rquest_dma) /* been here before? */ return (0); - len = isp->isp_maxcmds * sizeof (ISP_SCSI_XFER_T); - isp->isp_xflist = (ISP_SCSI_XFER_T **) malloc(len, M_DEVBUF, M_WAITOK); + len = isp->isp_maxcmds * sizeof (XS_T); + isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK); if (isp->isp_xflist == NULL) { printf("%s: cannot malloc xflist array\n", isp->isp_name); return (1); @@ -789,7 +799,7 @@ isp_pci_mbxdma(isp) /* * Allocate and map the request queue. */ - len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); + len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); if (bus_dmamem_alloc(pci->pci_dmat, len, NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT) || bus_dmamem_map(pci->pci_dmat, &seg, rseg, len, (caddr_t *)&isp->isp_rquest, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) @@ -805,7 +815,7 @@ isp_pci_mbxdma(isp) /* * Allocate and map the result queue. */ - len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); + len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); if (bus_dmamem_alloc(pci->pci_dmat, len, NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT) || bus_dmamem_map(pci->pci_dmat, &seg, rseg, len, (caddr_t *)&isp->isp_result, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) @@ -904,7 +914,7 @@ isp_pci_dmasetup(isp, xs, rq, iptrp, optr) do { crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); - *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); + *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN(isp)); if (*iptrp == optr) { printf("%s: Request Queue Overflow++\n", isp->isp_name); bus_dmamap_unload(pci->pci_dmat, dmap); @@ -940,10 +950,16 @@ static int isp_pci_intr(arg) void *arg; { - struct isp_pcisoftc *pci = (struct isp_pcisoftc *)arg; - bus_dmamap_sync(pci->pci_dmat, pci->pci_result_dmap, - BUS_DMASYNC_POSTREAD); - return (isp_intr(arg)); + int r; + struct ispsoftc *isp = (struct ispsoftc *)arg; + struct isp_pcisoftc *p = (struct isp_pcisoftc *)isp; + + bus_dmamap_sync(p->pci_dmat, p->pci_result_dmap, BUS_DMASYNC_POSTREAD); + + isp->isp_osinfo.onintstack = 1; + r = isp_intr(arg); + isp->isp_osinfo.onintstack = 0; + return (r); } static void @@ -968,10 +984,13 @@ isp_pci_reset1(isp) } static void -isp_pci_dumpregs(isp) +isp_pci_dumpregs(isp, msg) struct ispsoftc *isp; + const char *msg; { struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; - printf("%s: PCI Status Command/Status=%x\n", pci->pci_isp.isp_name, + if (msg) + isp_prt(isp, ISP_LOGERR, "%s", msg); + isp_prt(isp, ISP_LOGERR, "PCI Status Command/Status=%x\n", pci_conf_read(pci->pci_pc, pci->pci_tag, PCI_COMMAND_STATUS_REG)); } |