diff options
Diffstat (limited to 'sys/dev/ic')
-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 |
9 files changed, 2217 insertions, 1846 deletions
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 */ |