Annotation of sys/dev/ic/isp.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: isp.c,v 1.39 2007/05/23 01:32:25 ray Exp $ */
! 2: /*
! 3: * Machine and OS Independent (well, as best as possible)
! 4: * code for the Qlogic ISP SCSI adapters.
! 5: *
! 6: * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob
! 7: * Feral Software
! 8: * All rights reserved.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice immediately at the beginning of the file, without modification,
! 15: * this list of conditions, and the following disclaimer.
! 16: * 2. The name of the author may not be used to endorse or promote products
! 17: * derived from this software without specific prior written permission.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 22: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
! 23: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 29: * SUCH DAMAGE.
! 30: */
! 31:
! 32: /*
! 33: * Inspiration and ideas about this driver are from Erik Moe's Linux driver
! 34: * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some
! 35: * ideas dredged from the Solaris driver.
! 36: */
! 37:
! 38: /*
! 39: * Include header file appropriate for platform we're building on.
! 40: */
! 41:
! 42: #ifdef __NetBSD__
! 43: #include <dev/ic/isp_netbsd.h>
! 44: #endif
! 45: #ifdef __FreeBSD__
! 46: #include <dev/isp/isp_freebsd.h>
! 47: #endif
! 48: #ifdef __OpenBSD__
! 49: #include <dev/ic/isp_openbsd.h>
! 50: #endif
! 51: #ifdef __linux__
! 52: #include "isp_linux.h"
! 53: #endif
! 54: #ifdef __svr4__
! 55: #include "isp_solaris.h"
! 56: #endif
! 57:
! 58: /*
! 59: * General defines
! 60: */
! 61:
! 62: #define MBOX_DELAY_COUNT 1000000 / 100
! 63:
! 64: /*
! 65: * Local static data
! 66: */
! 67: static const char portshift[] =
! 68: "Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)";
! 69: static const char portdup[] =
! 70: "Target %d duplicates Target %d- killing off both";
! 71: static const char retained[] =
! 72: "Retaining Loop ID 0x%x for Target %d (Port 0x%x)";
! 73: static const char lretained[] =
! 74: "Retained login of Target %d (Loop ID 0x%x) Port 0x%x";
! 75: static const char plogout[] =
! 76: "Logging out Target %d at Loop ID 0x%x (Port 0x%x)";
! 77: static const char plogierr[] =
! 78: "Command Error in PLOGI for Port 0x%x (0x%x)";
! 79: static const char nopdb[] =
! 80: "Could not get PDB for Device @ Port 0x%x";
! 81: static const char pdbmfail1[] =
! 82: "PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)";
! 83: static const char pdbmfail2[] =
! 84: "PDB Port info for Device @ Port 0x%x does not match up (0x%x)";
! 85: static const char ldumped[] =
! 86: "Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch";
! 87: static const char notresp[] =
! 88: "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
! 89: static const char xact1[] =
! 90: "HBA attempted queued transaction with disconnect not set for %d.%d.%d";
! 91: static const char xact2[] =
! 92: "HBA attempted queued transaction to target routine %d on target %d bus %d";
! 93: static const char xact3[] =
! 94: "HBA attempted queued cmd for %d.%d.%d when queueing disabled";
! 95: static const char pskip[] =
! 96: "SCSI phase skipped for target %d.%d.%d";
! 97: static const char topology[] =
! 98: "Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'";
! 99: static const char swrej[] =
! 100: "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x";
! 101: static const char finmsg[] =
! 102: "(%d.%d.%d): FIN dl%d resid %lu STS 0x%x SKEY %c XS_ERR=0x%x";
! 103: static const char sc0[] =
! 104: "%s CHAN %d FTHRSH %d IID %d RESETD %d RETRYC %d RETRYD %d ASD 0x%x";
! 105: static const char sc1[] =
! 106: "%s RAAN 0x%x DLAN 0x%x DDMAB 0x%x CDMAB 0x%x SELTIME %d MQD %d";
! 107: static const char sc2[] = "%s CHAN %d TGT %d FLAGS 0x%x 0x%x/0x%x";
! 108: static const char sc3[] = "Generated";
! 109: static const char sc4[] = "NVRAM";
! 110: static const char bun[] =
! 111: "bad underrun for %d.%d (count %d, resid %d, status %s)";
! 112:
! 113: /*
! 114: * Local function prototypes.
! 115: */
! 116: static int isp_parse_async(struct ispsoftc *, u_int16_t);
! 117: static int isp_handle_other_response(struct ispsoftc *, int, isphdr_t *,
! 118: u_int16_t *);
! 119: static void
! 120: isp_parse_status(struct ispsoftc *, ispstatusreq_t *, XS_T *);
! 121: static void isp_fastpost_complete(struct ispsoftc *, u_int16_t);
! 122: static int isp_mbox_continue(struct ispsoftc *);
! 123: static void isp_scsi_init(struct ispsoftc *);
! 124: static void isp_scsi_channel_init(struct ispsoftc *, int);
! 125: static void isp_fibre_init(struct ispsoftc *);
! 126: static void isp_mark_getpdb_all(struct ispsoftc *);
! 127: static int isp_getmap(struct ispsoftc *, fcpos_map_t *);
! 128: static int isp_getpdb(struct ispsoftc *, int, isp_pdb_t *);
! 129: static u_int64_t isp_get_portname(struct ispsoftc *, int, int);
! 130: static int isp_fclink_test(struct ispsoftc *, int);
! 131: static char *isp2100_fw_statename(int);
! 132: static int isp_pdb_sync(struct ispsoftc *);
! 133: static int isp_scan_loop(struct ispsoftc *);
! 134: static int isp_fabric_mbox_cmd(struct ispsoftc *, mbreg_t *);
! 135: static int isp_scan_fabric(struct ispsoftc *, int);
! 136: static void isp_register_fc4_type(struct ispsoftc *);
! 137: static void isp_fw_state(struct ispsoftc *);
! 138: static void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *, int);
! 139: static void isp_mboxcmd(struct ispsoftc *, mbreg_t *, int);
! 140:
! 141: static void isp_update(struct ispsoftc *);
! 142: static void isp_update_bus(struct ispsoftc *, int);
! 143: static void isp_setdfltparm(struct ispsoftc *, int);
! 144: static int isp_read_nvram(struct ispsoftc *);
! 145: static void isp_rdnvram_word(struct ispsoftc *, int, u_int16_t *);
! 146: static void isp_parse_nvram_1020(struct ispsoftc *, u_int8_t *);
! 147: static void isp_parse_nvram_1080(struct ispsoftc *, int, u_int8_t *);
! 148: static void isp_parse_nvram_12160(struct ispsoftc *, int, u_int8_t *);
! 149: static void isp_parse_nvram_2100(struct ispsoftc *, u_int8_t *);
! 150:
! 151: /*
! 152: * Reset Hardware.
! 153: *
! 154: * Hit the chip over the head, download new f/w if available and set it running.
! 155: *
! 156: * Locking done elsewhere.
! 157: */
! 158:
! 159: void
! 160: isp_reset(struct ispsoftc *isp)
! 161: {
! 162: mbreg_t mbs;
! 163: u_int16_t code_org;
! 164: int loops, i, dodnld = 1;
! 165: char *btype = "????";
! 166:
! 167: isp->isp_state = ISP_NILSTATE;
! 168:
! 169: /*
! 170: * Basic types (SCSI, FibreChannel and PCI or SBus)
! 171: * have been set in the MD code. We figure out more
! 172: * here. Possibly more refined types based upon PCI
! 173: * identification. Chip revision has been gathered.
! 174: *
! 175: * After we've fired this chip up, zero out the conf1 register
! 176: * for SCSI adapters and do other settings for the 2100.
! 177: */
! 178:
! 179: /*
! 180: * Get the current running firmware revision out of the
! 181: * chip before we hit it over the head (if this is our
! 182: * first time through). Note that we store this as the
! 183: * 'ROM' firmware revision- which it may not be. In any
! 184: * case, we don't really use this yet, but we may in
! 185: * the future.
! 186: */
! 187: if (isp->isp_touched == 0) {
! 188: /*
! 189: * First see whether or not we're sitting in the ISP PROM.
! 190: * If we've just been reset, we'll have the string "ISP "
! 191: * spread through outgoing mailbox registers 1-3. We do
! 192: * this for PCI cards because otherwise we really don't
! 193: * know what state the card is in and we could hang if
! 194: * we try this command otherwise.
! 195: *
! 196: * For SBus cards, we just do this because they almost
! 197: * certainly will be running firmware by now.
! 198: */
! 199: if (ISP_READ(isp, OUTMAILBOX1) != 0x4953 ||
! 200: ISP_READ(isp, OUTMAILBOX2) != 0x5020 ||
! 201: ISP_READ(isp, OUTMAILBOX3) != 0x2020) {
! 202: /*
! 203: * Just in case it was paused...
! 204: */
! 205: ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
! 206: mbs.param[0] = MBOX_ABOUT_FIRMWARE;
! 207: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 208: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 209: isp->isp_romfw_rev[0] = mbs.param[1];
! 210: isp->isp_romfw_rev[1] = mbs.param[2];
! 211: isp->isp_romfw_rev[2] = mbs.param[3];
! 212: }
! 213: }
! 214: isp->isp_touched = 1;
! 215: }
! 216:
! 217: DISABLE_INTS(isp);
! 218:
! 219: /*
! 220: * Set up default request/response queue in-pointer/out-pointer
! 221: * register indices.
! 222: */
! 223: if (IS_23XX(isp)) {
! 224: isp->isp_rqstinrp = BIU_REQINP;
! 225: isp->isp_rqstoutrp = BIU_REQOUTP;
! 226: isp->isp_respinrp = BIU_RSPINP;
! 227: isp->isp_respoutrp = BIU_RSPOUTP;
! 228: } else {
! 229: isp->isp_rqstinrp = INMAILBOX4;
! 230: isp->isp_rqstoutrp = OUTMAILBOX4;
! 231: isp->isp_respinrp = OUTMAILBOX5;
! 232: isp->isp_respoutrp = INMAILBOX5;
! 233: }
! 234:
! 235: /*
! 236: * Put the board into PAUSE mode (so we can read the SXP registers
! 237: * or write FPM/FBM registers).
! 238: */
! 239: ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
! 240:
! 241: if (IS_FC(isp)) {
! 242: switch (isp->isp_type) {
! 243: case ISP_HA_FC_2100:
! 244: btype = "2100";
! 245: break;
! 246: case ISP_HA_FC_2200:
! 247: btype = "2200";
! 248: break;
! 249: case ISP_HA_FC_2300:
! 250: btype = "2300";
! 251: break;
! 252: case ISP_HA_FC_2312:
! 253: btype = "2312";
! 254: break;
! 255: default:
! 256: break;
! 257: }
! 258: /*
! 259: * While we're paused, reset the FPM module and FBM fifos.
! 260: */
! 261: ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
! 262: ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
! 263: ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
! 264: ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
! 265: ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
! 266: } else if (IS_1240(isp)) {
! 267: sdparam *sdp = isp->isp_param;
! 268: btype = "1240";
! 269: isp->isp_clock = 60;
! 270: sdp->isp_ultramode = 1;
! 271: sdp++;
! 272: sdp->isp_ultramode = 1;
! 273: /*
! 274: * XXX: Should probably do some bus sensing.
! 275: */
! 276: } else if (IS_ULTRA2(isp)) {
! 277: static const char m[] = "bus %d is in %s Mode";
! 278: u_int16_t l;
! 279: sdparam *sdp = isp->isp_param;
! 280:
! 281: isp->isp_clock = 100;
! 282:
! 283: if (IS_1280(isp))
! 284: btype = "1280";
! 285: else if (IS_1080(isp))
! 286: btype = "1080";
! 287: else if (IS_10160(isp))
! 288: btype = "10160";
! 289: else if (IS_12160(isp))
! 290: btype = "12160";
! 291: else
! 292: btype = "<UNKLVD>";
! 293:
! 294: l = ISP_READ(isp, SXP_PINS_DIFF) & ISP1080_MODE_MASK;
! 295: switch (l) {
! 296: case ISP1080_LVD_MODE:
! 297: sdp->isp_lvdmode = 1;
! 298: isp_prt(isp, ISP_LOGCONFIG, m, 0, "LVD");
! 299: break;
! 300: case ISP1080_HVD_MODE:
! 301: sdp->isp_diffmode = 1;
! 302: isp_prt(isp, ISP_LOGCONFIG, m, 0, "Differential");
! 303: break;
! 304: case ISP1080_SE_MODE:
! 305: sdp->isp_ultramode = 1;
! 306: isp_prt(isp, ISP_LOGCONFIG, m, 0, "Single-Ended");
! 307: break;
! 308: default:
! 309: isp_prt(isp, ISP_LOGERR,
! 310: "unknown mode on bus %d (0x%x)", 0, l);
! 311: break;
! 312: }
! 313:
! 314: if (IS_DUALBUS(isp)) {
! 315: sdp++;
! 316: l = ISP_READ(isp, SXP_PINS_DIFF|SXP_BANK1_SELECT);
! 317: l &= ISP1080_MODE_MASK;
! 318: switch(l) {
! 319: case ISP1080_LVD_MODE:
! 320: sdp->isp_lvdmode = 1;
! 321: isp_prt(isp, ISP_LOGCONFIG, m, 1, "LVD");
! 322: break;
! 323: case ISP1080_HVD_MODE:
! 324: sdp->isp_diffmode = 1;
! 325: isp_prt(isp, ISP_LOGCONFIG,
! 326: m, 1, "Differential");
! 327: break;
! 328: case ISP1080_SE_MODE:
! 329: sdp->isp_ultramode = 1;
! 330: isp_prt(isp, ISP_LOGCONFIG,
! 331: m, 1, "Single-Ended");
! 332: break;
! 333: default:
! 334: isp_prt(isp, ISP_LOGERR,
! 335: "unknown mode on bus %d (0x%x)", 1, l);
! 336: break;
! 337: }
! 338: }
! 339: } else {
! 340: sdparam *sdp = isp->isp_param;
! 341: i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
! 342: switch (i) {
! 343: default:
! 344: isp_prt(isp, ISP_LOGALL, "Unknown Chip Type 0x%x", i);
! 345: /* FALLTHROUGH */
! 346: case 1:
! 347: btype = "1020";
! 348: isp->isp_type = ISP_HA_SCSI_1020;
! 349: isp->isp_clock = 40;
! 350: break;
! 351: case 2:
! 352: /*
! 353: * Some 1020A chips are Ultra Capable, but don't
! 354: * run the clock rate up for that unless told to
! 355: * do so by the Ultra Capable bits being set.
! 356: */
! 357: btype = "1020A";
! 358: isp->isp_type = ISP_HA_SCSI_1020A;
! 359: isp->isp_clock = 40;
! 360: break;
! 361: case 3:
! 362: btype = "1040";
! 363: isp->isp_type = ISP_HA_SCSI_1040;
! 364: isp->isp_clock = 60;
! 365: break;
! 366: case 4:
! 367: btype = "1040A";
! 368: isp->isp_type = ISP_HA_SCSI_1040A;
! 369: isp->isp_clock = 60;
! 370: break;
! 371: case 5:
! 372: btype = "1040B";
! 373: isp->isp_type = ISP_HA_SCSI_1040B;
! 374: isp->isp_clock = 60;
! 375: break;
! 376: case 6:
! 377: btype = "1040C";
! 378: isp->isp_type = ISP_HA_SCSI_1040C;
! 379: isp->isp_clock = 60;
! 380: break;
! 381: }
! 382: /*
! 383: * Now, while we're at it, gather info about ultra
! 384: * and/or differential mode.
! 385: */
! 386: if (ISP_READ(isp, SXP_PINS_DIFF) & SXP_PINS_DIFF_MODE) {
! 387: isp_prt(isp, ISP_LOGCONFIG, "Differential Mode");
! 388: sdp->isp_diffmode = 1;
! 389: } else {
! 390: sdp->isp_diffmode = 0;
! 391: }
! 392: i = ISP_READ(isp, RISC_PSR);
! 393: if (isp->isp_bustype == ISP_BT_SBUS) {
! 394: i &= RISC_PSR_SBUS_ULTRA;
! 395: } else {
! 396: i &= RISC_PSR_PCI_ULTRA;
! 397: }
! 398: if (i != 0) {
! 399: isp_prt(isp, ISP_LOGCONFIG, "Ultra Mode Capable");
! 400: sdp->isp_ultramode = 1;
! 401: /*
! 402: * If we're in Ultra Mode, we have to be 60MHz clock-
! 403: * even for the SBus version.
! 404: */
! 405: isp->isp_clock = 60;
! 406: } else {
! 407: sdp->isp_ultramode = 0;
! 408: /*
! 409: * Clock is known. Gronk.
! 410: */
! 411: }
! 412:
! 413: /*
! 414: * Machine dependent clock (if set) overrides
! 415: * our generic determinations.
! 416: */
! 417: if (isp->isp_mdvec->dv_clock) {
! 418: if (isp->isp_mdvec->dv_clock < isp->isp_clock) {
! 419: isp->isp_clock = isp->isp_mdvec->dv_clock;
! 420: }
! 421: }
! 422:
! 423: }
! 424:
! 425: /*
! 426: * Clear instrumentation
! 427: */
! 428: isp->isp_intcnt = isp->isp_intbogus = 0;
! 429:
! 430: /*
! 431: * Do MD specific pre initialization
! 432: */
! 433: ISP_RESET0(isp);
! 434:
! 435: again:
! 436:
! 437: /*
! 438: * Hit the chip over the head with hammer,
! 439: * and give the ISP a chance to recover.
! 440: */
! 441:
! 442: if (IS_SCSI(isp)) {
! 443: ISP_WRITE(isp, BIU_ICR, BIU_ICR_SOFT_RESET);
! 444: /*
! 445: * A slight delay...
! 446: */
! 447: USEC_DELAY(100);
! 448:
! 449: /*
! 450: * Clear data && control DMA engines.
! 451: */
! 452: ISP_WRITE(isp, CDMA_CONTROL,
! 453: DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
! 454: ISP_WRITE(isp, DDMA_CONTROL,
! 455: DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
! 456:
! 457:
! 458: } else {
! 459: ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
! 460: /*
! 461: * A slight delay...
! 462: */
! 463: USEC_DELAY(100);
! 464:
! 465: /*
! 466: * Clear data && control DMA engines.
! 467: */
! 468: ISP_WRITE(isp, CDMA2100_CONTROL,
! 469: DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
! 470: ISP_WRITE(isp, TDMA2100_CONTROL,
! 471: DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
! 472: ISP_WRITE(isp, RDMA2100_CONTROL,
! 473: DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
! 474: }
! 475:
! 476: /*
! 477: * Wait for ISP to be ready to go...
! 478: */
! 479: loops = MBOX_DELAY_COUNT;
! 480: for (;;) {
! 481: if (IS_SCSI(isp)) {
! 482: if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET))
! 483: break;
! 484: } else {
! 485: if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET))
! 486: break;
! 487: }
! 488: USEC_DELAY(100);
! 489: if (--loops < 0) {
! 490: ISP_DUMPREGS(isp, "chip reset timed out");
! 491: return;
! 492: }
! 493: }
! 494:
! 495: /*
! 496: * After we've fired this chip up, zero out the conf1 register
! 497: * for SCSI adapters and other settings for the 2100.
! 498: */
! 499:
! 500: if (IS_SCSI(isp)) {
! 501: ISP_WRITE(isp, BIU_CONF1, 0);
! 502: } else {
! 503: ISP_WRITE(isp, BIU2100_CSR, 0);
! 504: }
! 505:
! 506: /*
! 507: * Reset RISC Processor
! 508: */
! 509: ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
! 510: USEC_DELAY(100);
! 511: /* Clear semaphore register (just to be sure) */
! 512: ISP_WRITE(isp, BIU_SEMA, 0);
! 513:
! 514: /*
! 515: * Establish some initial burst rate stuff.
! 516: * (only for the 1XX0 boards). This really should
! 517: * be done later after fetching from NVRAM.
! 518: */
! 519: if (IS_SCSI(isp)) {
! 520: u_int16_t tmp = isp->isp_mdvec->dv_conf1;
! 521: /*
! 522: * Busted FIFO. Turn off all but burst enables.
! 523: */
! 524: if (isp->isp_type == ISP_HA_SCSI_1040A) {
! 525: tmp &= BIU_BURST_ENABLE;
! 526: }
! 527: ISP_SETBITS(isp, BIU_CONF1, tmp);
! 528: if (tmp & BIU_BURST_ENABLE) {
! 529: ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST);
! 530: ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST);
! 531: }
! 532: #ifdef PTI_CARDS
! 533: if (((sdparam *) isp->isp_param)->isp_ultramode) {
! 534: while (ISP_READ(isp, RISC_MTR) != 0x1313) {
! 535: ISP_WRITE(isp, RISC_MTR, 0x1313);
! 536: ISP_WRITE(isp, HCCR, HCCR_CMD_STEP);
! 537: }
! 538: } else {
! 539: ISP_WRITE(isp, RISC_MTR, 0x1212);
! 540: }
! 541: /*
! 542: * PTI specific register
! 543: */
! 544: ISP_WRITE(isp, RISC_EMB, DUAL_BANK)
! 545: #else
! 546: ISP_WRITE(isp, RISC_MTR, 0x1212);
! 547: #endif
! 548: } else {
! 549: ISP_WRITE(isp, RISC_MTR2100, 0x1212);
! 550: if (IS_2200(isp) || IS_23XX(isp)) {
! 551: ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE);
! 552: }
! 553: }
! 554:
! 555: ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); /* release paused processor */
! 556:
! 557: /*
! 558: * Do MD specific post initialization
! 559: */
! 560: ISP_RESET1(isp);
! 561:
! 562: /*
! 563: * Wait for everything to finish firing up.
! 564: *
! 565: * Avoid doing this on the 2312 because you can generate a PCI
! 566: * parity error (chip breakage).
! 567: */
! 568: if (IS_23XX(isp)) {
! 569: USEC_DELAY(5);
! 570: } else {
! 571: loops = MBOX_DELAY_COUNT;
! 572: while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) {
! 573: USEC_DELAY(100);
! 574: if (--loops < 0) {
! 575: isp_prt(isp, ISP_LOGERR,
! 576: "MBOX_BUSY never cleared on reset");
! 577: return;
! 578: }
! 579: }
! 580: }
! 581:
! 582: /*
! 583: * Up until this point we've done everything by just reading or
! 584: * setting registers. From this point on we rely on at least *some*
! 585: * kind of firmware running in the card.
! 586: */
! 587:
! 588: /*
! 589: * Do some sanity checking.
! 590: */
! 591: mbs.param[0] = MBOX_NO_OP;
! 592: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 593: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 594: return;
! 595: }
! 596:
! 597: if (IS_SCSI(isp)) {
! 598: mbs.param[0] = MBOX_MAILBOX_REG_TEST;
! 599: mbs.param[1] = 0xdead;
! 600: mbs.param[2] = 0xbeef;
! 601: mbs.param[3] = 0xffff;
! 602: mbs.param[4] = 0x1111;
! 603: mbs.param[5] = 0xa5a5;
! 604: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 605: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 606: return;
! 607: }
! 608: if (mbs.param[1] != 0xdead || mbs.param[2] != 0xbeef ||
! 609: mbs.param[3] != 0xffff || mbs.param[4] != 0x1111 ||
! 610: mbs.param[5] != 0xa5a5) {
! 611: isp_prt(isp, ISP_LOGERR,
! 612: "Register Test Failed (0x%x 0x%x 0x%x 0x%x 0x%x)",
! 613: mbs.param[1], mbs.param[2], mbs.param[3],
! 614: mbs.param[4], mbs.param[5]);
! 615: return;
! 616: }
! 617:
! 618: }
! 619:
! 620: /*
! 621: * Download new Firmware, unless requested not to do so.
! 622: * This is made slightly trickier in some cases where the
! 623: * firmware of the ROM revision is newer than the revision
! 624: * compiled into the driver. So, where we used to compare
! 625: * versions of our f/w and the ROM f/w, now we just see
! 626: * whether we have f/w at all and whether a config flag
! 627: * has disabled our download.
! 628: */
! 629: if ((isp->isp_mdvec->dv_ispfw == NULL) ||
! 630: (isp->isp_confopts & ISP_CFG_NORELOAD)) {
! 631: dodnld = 0;
! 632: }
! 633:
! 634: if (IS_23XX(isp))
! 635: code_org = ISP_CODE_ORG_2300;
! 636: else
! 637: code_org = ISP_CODE_ORG;
! 638:
! 639: if (dodnld) {
! 640: isp->isp_mbxworkp = (void *) &isp->isp_mdvec->dv_ispfw[1];
! 641: isp->isp_mbxwrk0 = isp->isp_mdvec->dv_ispfw[3] - 1;
! 642: isp->isp_mbxwrk1 = code_org + 1;
! 643: mbs.param[0] = MBOX_WRITE_RAM_WORD;
! 644: mbs.param[1] = code_org;
! 645: mbs.param[2] = isp->isp_mdvec->dv_ispfw[0];
! 646: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 647: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 648: isp_prt(isp, ISP_LOGERR,
! 649: "F/W download failed at word %d",
! 650: isp->isp_mbxwrk1 - code_org);
! 651: dodnld = 0;
! 652: goto again;
! 653: }
! 654: /*
! 655: * Verify that it downloaded correctly.
! 656: */
! 657: mbs.param[0] = MBOX_VERIFY_CHECKSUM;
! 658: mbs.param[1] = code_org;
! 659: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 660: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 661: isp_prt(isp, ISP_LOGERR, "Ram Checksum Failure");
! 662: return;
! 663: }
! 664: isp->isp_loaded_fw = 1;
! 665: } else {
! 666: isp->isp_loaded_fw = 0;
! 667: isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
! 668: }
! 669:
! 670: /*
! 671: * Now start it rolling.
! 672: *
! 673: * If we didn't actually download f/w,
! 674: * we still need to (re)start it.
! 675: */
! 676:
! 677:
! 678: mbs.param[0] = MBOX_EXEC_FIRMWARE;
! 679: mbs.param[1] = code_org;
! 680: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 681: /*
! 682: * Give it a chance to start.
! 683: */
! 684: USEC_DELAY(500);
! 685:
! 686: if (IS_SCSI(isp)) {
! 687: /*
! 688: * Set CLOCK RATE, but only if asked to.
! 689: */
! 690: if (isp->isp_clock) {
! 691: mbs.param[0] = MBOX_SET_CLOCK_RATE;
! 692: mbs.param[1] = isp->isp_clock;
! 693: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 694: /* we will try not to care if this fails */
! 695: }
! 696: }
! 697:
! 698: mbs.param[0] = MBOX_ABOUT_FIRMWARE;
! 699: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 700: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 701: return;
! 702: }
! 703:
! 704: /*
! 705: * The SBus firmware that we are using apparently does not return
! 706: * major, minor, micro revisions in the mailbox registers, which
! 707: * is really, really, annoying.
! 708: */
! 709: if (ISP_SBUS_SUPPORTED && isp->isp_bustype == ISP_BT_SBUS) {
! 710: if (dodnld) {
! 711: #ifdef ISP_TARGET_MODE
! 712: isp->isp_fwrev[0] = 7;
! 713: isp->isp_fwrev[1] = 55;
! 714: #else
! 715: isp->isp_fwrev[0] = 1;
! 716: isp->isp_fwrev[1] = 37;
! 717: #endif
! 718: isp->isp_fwrev[2] = 0;
! 719: }
! 720: } else {
! 721: isp->isp_fwrev[0] = mbs.param[1];
! 722: isp->isp_fwrev[1] = mbs.param[2];
! 723: isp->isp_fwrev[2] = mbs.param[3];
! 724: }
! 725: isp_prt(isp, ISP_LOGCONFIG,
! 726: "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
! 727: btype, isp->isp_revision, dodnld? "loaded" : "resident",
! 728: isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
! 729:
! 730: if (IS_FC(isp)) {
! 731: /*
! 732: * We do not believe firmware attributes for 2100 code less
! 733: * than 1.17.0, unless it's the firmware we specifically
! 734: * are loading.
! 735: *
! 736: * Note that all 22XX and 23XX f/w is greater than 1.X.0.
! 737: */
! 738: if (!(ISP_FW_NEWER_THAN(isp, 1, 17, 0))) {
! 739: #ifdef USE_SMALLER_2100_FIRMWARE
! 740: FCPARAM(isp)->isp_fwattr = ISP_FW_ATTR_SCCLUN;
! 741: #else
! 742: FCPARAM(isp)->isp_fwattr = 0;
! 743: #endif
! 744: } else {
! 745: FCPARAM(isp)->isp_fwattr = mbs.param[6];
! 746: isp_prt(isp, ISP_LOGDEBUG0,
! 747: "Firmware Attributes = 0x%x", mbs.param[6]);
! 748: }
! 749: if (ISP_READ(isp, BIU2100_CSR) & BIU2100_PCI64) {
! 750: isp_prt(isp, ISP_LOGCONFIG,
! 751: "Installed in 64-Bit PCI slot");
! 752: }
! 753: }
! 754:
! 755: if (isp->isp_romfw_rev[0] || isp->isp_romfw_rev[1] ||
! 756: isp->isp_romfw_rev[2]) {
! 757: isp_prt(isp, ISP_LOGCONFIG, "Last F/W revision was %d.%d.%d",
! 758: isp->isp_romfw_rev[0], isp->isp_romfw_rev[1],
! 759: isp->isp_romfw_rev[2]);
! 760: }
! 761:
! 762: mbs.param[0] = MBOX_GET_FIRMWARE_STATUS;
! 763: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 764: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 765: return;
! 766: }
! 767: isp->isp_maxcmds = mbs.param[2];
! 768: isp_prt(isp, ISP_LOGINFO,
! 769: "%d max I/O commands supported", mbs.param[2]);
! 770: isp_fw_state(isp);
! 771:
! 772: /*
! 773: * Set up DMA for the request and result mailboxes.
! 774: */
! 775: if (ISP_MBOXDMASETUP(isp) != 0) {
! 776: isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
! 777: return;
! 778: }
! 779: isp->isp_state = ISP_RESETSTATE;
! 780:
! 781: /*
! 782: * Okay- now that we have new firmware running, we now (re)set our
! 783: * notion of how many luns we support. This is somewhat tricky because
! 784: * if we haven't loaded firmware, we sometimes do not have an easy way
! 785: * of knowing how many luns we support.
! 786: *
! 787: * Expanded lun firmware gives you 32 luns for SCSI cards and
! 788: * 16384 luns for Fibre Channel cards.
! 789: *
! 790: * It turns out that even for QLogic 2100s with ROM 1.10 and above
! 791: * we do get a firmware attributes word returned in mailbox register 6.
! 792: *
! 793: * Because the lun is in a different position in the Request Queue
! 794: * Entry structure for Fibre Channel with expanded lun firmware, we
! 795: * can only support one lun (lun zero) when we don't know what kind
! 796: * of firmware we're running.
! 797: */
! 798: if (IS_SCSI(isp)) {
! 799: if (dodnld) {
! 800: if (IS_ULTRA2(isp) || IS_ULTRA3(isp)) {
! 801: isp->isp_maxluns = 32;
! 802: } else {
! 803: isp->isp_maxluns = 8;
! 804: }
! 805: } else {
! 806: isp->isp_maxluns = 8;
! 807: }
! 808: } else {
! 809: if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
! 810: isp->isp_maxluns = 16384;
! 811: } else {
! 812: isp->isp_maxluns = 16;
! 813: }
! 814: }
! 815: }
! 816:
! 817: /*
! 818: * Initialize Parameters of Hardware to a known state.
! 819: *
! 820: * Locks are held before coming here.
! 821: */
! 822:
! 823: void
! 824: isp_init(struct ispsoftc *isp)
! 825: {
! 826: /*
! 827: * Must do this first to get defaults established.
! 828: */
! 829: isp_setdfltparm(isp, 0);
! 830: if (IS_DUALBUS(isp)) {
! 831: isp_setdfltparm(isp, 1);
! 832: }
! 833: if (IS_FC(isp)) {
! 834: isp_fibre_init(isp);
! 835: } else {
! 836: isp_scsi_init(isp);
! 837: }
! 838: }
! 839:
! 840: static void
! 841: isp_scsi_init(struct ispsoftc *isp)
! 842: {
! 843: sdparam *sdp_chan0, *sdp_chan1;
! 844: mbreg_t mbs;
! 845:
! 846: sdp_chan0 = isp->isp_param;
! 847: sdp_chan1 = sdp_chan0;
! 848: if (IS_DUALBUS(isp)) {
! 849: sdp_chan1++;
! 850: }
! 851:
! 852: /*
! 853: * If we have no role (neither target nor initiator), return.
! 854: */
! 855: if (isp->isp_role == ISP_ROLE_NONE) {
! 856: return;
! 857: }
! 858:
! 859: /* First do overall per-card settings. */
! 860:
! 861: /*
! 862: * If we have fast memory timing enabled, turn it on.
! 863: */
! 864: if (sdp_chan0->isp_fast_mttr) {
! 865: ISP_WRITE(isp, RISC_MTR, 0x1313);
! 866: }
! 867:
! 868: /*
! 869: * Set Retry Delay and Count.
! 870: * You set both channels at the same time.
! 871: */
! 872: mbs.param[0] = MBOX_SET_RETRY_COUNT;
! 873: mbs.param[1] = sdp_chan0->isp_retry_count;
! 874: mbs.param[2] = sdp_chan0->isp_retry_delay;
! 875: mbs.param[6] = sdp_chan1->isp_retry_count;
! 876: mbs.param[7] = sdp_chan1->isp_retry_delay;
! 877:
! 878: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 879: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 880: return;
! 881: }
! 882:
! 883: /*
! 884: * Set ASYNC DATA SETUP time. This is very important.
! 885: */
! 886: mbs.param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME;
! 887: mbs.param[1] = sdp_chan0->isp_async_data_setup;
! 888: mbs.param[2] = sdp_chan1->isp_async_data_setup;
! 889: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 890: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 891: return;
! 892: }
! 893:
! 894: /*
! 895: * Set ACTIVE Negation State.
! 896: */
! 897: mbs.param[0] = MBOX_SET_ACT_NEG_STATE;
! 898: mbs.param[1] =
! 899: (sdp_chan0->isp_req_ack_active_neg << 4) |
! 900: (sdp_chan0->isp_data_line_active_neg << 5);
! 901: mbs.param[2] =
! 902: (sdp_chan1->isp_req_ack_active_neg << 4) |
! 903: (sdp_chan1->isp_data_line_active_neg << 5);
! 904:
! 905: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 906: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 907: isp_prt(isp, ISP_LOGERR,
! 908: "failed to set active negation state (%d,%d), (%d,%d)",
! 909: sdp_chan0->isp_req_ack_active_neg,
! 910: sdp_chan0->isp_data_line_active_neg,
! 911: sdp_chan1->isp_req_ack_active_neg,
! 912: sdp_chan1->isp_data_line_active_neg);
! 913: /*
! 914: * But don't return.
! 915: */
! 916: }
! 917:
! 918: /*
! 919: * Set the Tag Aging limit
! 920: */
! 921: mbs.param[0] = MBOX_SET_TAG_AGE_LIMIT;
! 922: mbs.param[1] = sdp_chan0->isp_tag_aging;
! 923: mbs.param[2] = sdp_chan1->isp_tag_aging;
! 924: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 925: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 926: isp_prt(isp, ISP_LOGERR, "failed to set tag age limit (%d,%d)",
! 927: sdp_chan0->isp_tag_aging, sdp_chan1->isp_tag_aging);
! 928: return;
! 929: }
! 930:
! 931: /*
! 932: * Set selection timeout.
! 933: */
! 934: mbs.param[0] = MBOX_SET_SELECT_TIMEOUT;
! 935: mbs.param[1] = sdp_chan0->isp_selection_timeout;
! 936: mbs.param[2] = sdp_chan1->isp_selection_timeout;
! 937: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 938: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 939: return;
! 940: }
! 941:
! 942: /* now do per-channel settings */
! 943: isp_scsi_channel_init(isp, 0);
! 944: if (IS_DUALBUS(isp))
! 945: isp_scsi_channel_init(isp, 1);
! 946:
! 947: /*
! 948: * Now enable request/response queues
! 949: */
! 950:
! 951: if (IS_ULTRA2(isp) || IS_1240(isp)) {
! 952: mbs.param[0] = MBOX_INIT_RES_QUEUE_A64;
! 953: mbs.param[1] = RESULT_QUEUE_LEN(isp);
! 954: mbs.param[2] = DMA_WD1(isp->isp_result_dma);
! 955: mbs.param[3] = DMA_WD0(isp->isp_result_dma);
! 956: mbs.param[4] = 0;
! 957: mbs.param[6] = DMA_WD3(isp->isp_result_dma);
! 958: mbs.param[7] = DMA_WD2(isp->isp_result_dma);
! 959: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 960: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 961: return;
! 962: }
! 963: isp->isp_residx = mbs.param[5];
! 964:
! 965: mbs.param[0] = MBOX_INIT_REQ_QUEUE_A64;
! 966: mbs.param[1] = RQUEST_QUEUE_LEN(isp);
! 967: mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
! 968: mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
! 969: mbs.param[5] = 0;
! 970: mbs.param[6] = DMA_WD3(isp->isp_result_dma);
! 971: mbs.param[7] = DMA_WD2(isp->isp_result_dma);
! 972: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 973: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 974: return;
! 975: }
! 976: isp->isp_reqidx = isp->isp_reqodx = mbs.param[4];
! 977: } else {
! 978: mbs.param[0] = MBOX_INIT_RES_QUEUE;
! 979: mbs.param[1] = RESULT_QUEUE_LEN(isp);
! 980: mbs.param[2] = DMA_WD1(isp->isp_result_dma);
! 981: mbs.param[3] = DMA_WD0(isp->isp_result_dma);
! 982: mbs.param[4] = 0;
! 983: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 984: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 985: return;
! 986: }
! 987: isp->isp_residx = mbs.param[5];
! 988:
! 989: mbs.param[0] = MBOX_INIT_REQ_QUEUE;
! 990: mbs.param[1] = RQUEST_QUEUE_LEN(isp);
! 991: mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
! 992: mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
! 993: mbs.param[5] = 0;
! 994: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 995: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 996: return;
! 997: }
! 998: isp->isp_reqidx = isp->isp_reqodx = mbs.param[4];
! 999: }
! 1000:
! 1001: /*
! 1002: * Turn on Fast Posting, LVD transitions
! 1003: *
! 1004: * Ultra2 F/W always has had fast posting (and LVD transitions)
! 1005: *
! 1006: * Ultra and older (i.e., SBus) cards may not. It's just safer
! 1007: * to assume not for them.
! 1008: */
! 1009:
! 1010: mbs.param[0] = MBOX_SET_FW_FEATURES;
! 1011: mbs.param[1] = 0;
! 1012: if (IS_ULTRA2(isp))
! 1013: mbs.param[1] |= FW_FEATURE_LVD_NOTIFY;
! 1014: #ifndef ISP_NO_RIO
! 1015: if (IS_ULTRA2(isp) || IS_1240(isp))
! 1016: mbs.param[1] |= FW_FEATURE_RIO_16BIT;
! 1017: #else
! 1018: #ifndef ISP_NO_FASTPOST
! 1019: if (IS_ULTRA2(isp) || IS_1240(isp))
! 1020: mbs.param[1] |= FW_FEATURE_FAST_POST;
! 1021: #endif
! 1022: #endif
! 1023: if (mbs.param[1] != 0) {
! 1024: u_int16_t sfeat = mbs.param[1];
! 1025: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 1026: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 1027: isp_prt(isp, ISP_LOGINFO,
! 1028: "Enabled FW features (0x%x)", sfeat);
! 1029: }
! 1030: }
! 1031:
! 1032: /*
! 1033: * Let the outer layers decide whether to issue a SCSI bus reset.
! 1034: */
! 1035: isp->isp_state = ISP_INITSTATE;
! 1036: }
! 1037:
! 1038: static void
! 1039: isp_scsi_channel_init(struct ispsoftc *isp, int channel)
! 1040: {
! 1041: sdparam *sdp;
! 1042: mbreg_t mbs;
! 1043: int tgt;
! 1044:
! 1045: sdp = isp->isp_param;
! 1046: sdp += channel;
! 1047:
! 1048: /*
! 1049: * Set (possibly new) Initiator ID.
! 1050: */
! 1051: mbs.param[0] = MBOX_SET_INIT_SCSI_ID;
! 1052: mbs.param[1] = (channel << 7) | sdp->isp_initiator_id;
! 1053: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 1054: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 1055: return;
! 1056: }
! 1057: isp_prt(isp, ISP_LOGINFO, "Initiator ID is %d on Channel %d",
! 1058: sdp->isp_initiator_id, channel);
! 1059:
! 1060:
! 1061: /*
! 1062: * Set current per-target parameters to an initial safe minimum.
! 1063: */
! 1064: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 1065: int lun;
! 1066: u_int16_t sdf;
! 1067:
! 1068: if (sdp->isp_devparam[tgt].dev_enable == 0) {
! 1069: continue;
! 1070: }
! 1071: #ifndef ISP_TARGET_MODE
! 1072: sdf = sdp->isp_devparam[tgt].goal_flags;
! 1073: sdf &= DPARM_SAFE_DFLT;
! 1074: /*
! 1075: * It is not quite clear when this changed over so that
! 1076: * we could force narrow and async for 1000/1020 cards,
! 1077: * but assume that this is only the case for loaded
! 1078: * firmware.
! 1079: */
! 1080: if (isp->isp_loaded_fw) {
! 1081: sdf |= DPARM_NARROW | DPARM_ASYNC;
! 1082: }
! 1083: #else
! 1084: /*
! 1085: * The !$*!)$!$)* f/w uses the same index into some
! 1086: * internal table to decide how to respond to negotiations,
! 1087: * so if we've said "let's be safe" for ID X, and ID X
! 1088: * selects *us*, the negotiations will back to 'safe'
! 1089: * (as in narrow/async). What the f/w *should* do is
! 1090: * use the initiator id settings to decide how to respond.
! 1091: */
! 1092: sdp->isp_devparam[tgt].goal_flags = sdf = DPARM_DEFAULT;
! 1093: #endif
! 1094: mbs.param[0] = MBOX_SET_TARGET_PARAMS;
! 1095: mbs.param[1] = (channel << 15) | (tgt << 8);
! 1096: mbs.param[2] = sdf;
! 1097: if ((sdf & DPARM_SYNC) == 0) {
! 1098: mbs.param[3] = 0;
! 1099: } else {
! 1100: mbs.param[3] =
! 1101: (sdp->isp_devparam[tgt].goal_offset << 8) |
! 1102: (sdp->isp_devparam[tgt].goal_period);
! 1103: }
! 1104: isp_prt(isp, ISP_LOGDEBUG0,
! 1105: "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x",
! 1106: channel, tgt, mbs.param[2], mbs.param[3] >> 8,
! 1107: mbs.param[3] & 0xff);
! 1108: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 1109: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 1110: sdf = DPARM_SAFE_DFLT;
! 1111: mbs.param[0] = MBOX_SET_TARGET_PARAMS;
! 1112: mbs.param[1] = (tgt << 8) | (channel << 15);
! 1113: mbs.param[2] = sdf;
! 1114: mbs.param[3] = 0;
! 1115: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 1116: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 1117: continue;
! 1118: }
! 1119: }
! 1120:
! 1121: /*
! 1122: * We don't update any information directly from the f/w
! 1123: * because we need to run at least one command to cause a
! 1124: * new state to be latched up. So, we just assume that we
! 1125: * converge to the values we just had set.
! 1126: *
! 1127: * Ensure that we don't believe tagged queuing is enabled yet.
! 1128: * It turns out that sometimes the ISP just ignores our
! 1129: * attempts to set parameters for devices that it hasn't
! 1130: * seen yet.
! 1131: */
! 1132: sdp->isp_devparam[tgt].actv_flags = sdf & ~DPARM_TQING;
! 1133: for (lun = 0; lun < (int) isp->isp_maxluns; lun++) {
! 1134: mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS;
! 1135: mbs.param[1] = (channel << 15) | (tgt << 8) | lun;
! 1136: mbs.param[2] = sdp->isp_max_queue_depth;
! 1137: mbs.param[3] = sdp->isp_devparam[tgt].exc_throttle;
! 1138: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 1139: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 1140: break;
! 1141: }
! 1142: }
! 1143: }
! 1144: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 1145: if (sdp->isp_devparam[tgt].dev_refresh) {
! 1146: isp->isp_sendmarker |= (1 << channel);
! 1147: isp->isp_update |= (1 << channel);
! 1148: break;
! 1149: }
! 1150: }
! 1151: }
! 1152:
! 1153: /*
! 1154: * Fibre Channel specific initialization.
! 1155: *
! 1156: * Locks are held before coming here.
! 1157: */
! 1158: static void
! 1159: isp_fibre_init(struct ispsoftc *isp)
! 1160: {
! 1161: fcparam *fcp;
! 1162: isp_icb_t local, *icbp = &local;
! 1163: mbreg_t mbs;
! 1164: int loopid;
! 1165: u_int64_t nwwn, pwwn;
! 1166:
! 1167: fcp = isp->isp_param;
! 1168:
! 1169: /*
! 1170: * Do this *before* initializing the firmware.
! 1171: */
! 1172: isp_mark_getpdb_all(isp);
! 1173: fcp->isp_fwstate = FW_CONFIG_WAIT;
! 1174: fcp->isp_loopstate = LOOP_NIL;
! 1175:
! 1176: /*
! 1177: * If we have no role (neither target nor initiator), return.
! 1178: */
! 1179: if (isp->isp_role == ISP_ROLE_NONE) {
! 1180: return;
! 1181: }
! 1182:
! 1183: loopid = fcp->isp_loopid;
! 1184: MEMZERO(icbp, sizeof (*icbp));
! 1185: icbp->icb_version = ICB_VERSION1;
! 1186:
! 1187: /*
! 1188: * Firmware Options are either retrieved from NVRAM or
! 1189: * are patched elsewhere. We check them for sanity here
! 1190: * and make changes based on board revision, but otherwise
! 1191: * let others decide policy.
! 1192: */
! 1193:
! 1194: /*
! 1195: * If this is a 2100 < revision 5, we have to turn off FAIRNESS.
! 1196: */
! 1197: if ((isp->isp_type == ISP_HA_FC_2100) && isp->isp_revision < 5) {
! 1198: fcp->isp_fwoptions &= ~ICBOPT_FAIRNESS;
! 1199: }
! 1200:
! 1201: /*
! 1202: * We have to use FULL LOGIN even though it resets the loop too much
! 1203: * because otherwise port database entries don't get updated after
! 1204: * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0.
! 1205: */
! 1206: if (!ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
! 1207: fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;
! 1208: }
! 1209:
! 1210: /*
! 1211: * Insist on Port Database Update Async notifications
! 1212: */
! 1213: fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
! 1214:
! 1215: /*
! 1216: * Make sure that target role reflects into fwoptions.
! 1217: */
! 1218: if (isp->isp_role & ISP_ROLE_TARGET) {
! 1219: fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE;
! 1220: } else {
! 1221: fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE;
! 1222: }
! 1223:
! 1224: /*
! 1225: * Propagate all of this into the ICB structure.
! 1226: */
! 1227: icbp->icb_fwoptions = fcp->isp_fwoptions;
! 1228: icbp->icb_maxfrmlen = fcp->isp_maxfrmlen;
! 1229: if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN ||
! 1230: icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
! 1231: isp_prt(isp, ISP_LOGERR,
! 1232: "bad frame length (%d) from NVRAM- using %d",
! 1233: fcp->isp_maxfrmlen, ICB_DFLT_FRMLEN);
! 1234: icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
! 1235: }
! 1236: icbp->icb_maxalloc = fcp->isp_maxalloc;
! 1237: if (icbp->icb_maxalloc < 1) {
! 1238: isp_prt(isp, ISP_LOGERR,
! 1239: "bad maximum allocation (%d)- using 16", fcp->isp_maxalloc);
! 1240: icbp->icb_maxalloc = 16;
! 1241: }
! 1242: icbp->icb_execthrottle = fcp->isp_execthrottle;
! 1243: if (icbp->icb_execthrottle < 1) {
! 1244: isp_prt(isp, ISP_LOGERR,
! 1245: "bad execution throttle of %d- using 16",
! 1246: fcp->isp_execthrottle);
! 1247: icbp->icb_execthrottle = ICB_DFLT_THROTTLE;
! 1248: }
! 1249: icbp->icb_retry_delay = fcp->isp_retry_delay;
! 1250: icbp->icb_retry_count = fcp->isp_retry_count;
! 1251: icbp->icb_hardaddr = loopid;
! 1252: /*
! 1253: * Right now we just set extended options to prefer point-to-point
! 1254: * over loop based upon some soft config options.
! 1255: *
! 1256: * NB: for the 2300, ICBOPT_EXTENDED is required.
! 1257: */
! 1258: if (IS_2200(isp) || IS_23XX(isp)) {
! 1259: icbp->icb_fwoptions |= ICBOPT_EXTENDED;
! 1260: /*
! 1261: * Prefer or force Point-To-Point instead Loop?
! 1262: */
! 1263: switch(isp->isp_confopts & ISP_CFG_PORT_PREF) {
! 1264: case ISP_CFG_NPORT:
! 1265: icbp->icb_xfwoptions |= ICBXOPT_PTP_2_LOOP;
! 1266: break;
! 1267: case ISP_CFG_NPORT_ONLY:
! 1268: icbp->icb_xfwoptions |= ICBXOPT_PTP_ONLY;
! 1269: break;
! 1270: case ISP_CFG_LPORT_ONLY:
! 1271: icbp->icb_xfwoptions |= ICBXOPT_LOOP_ONLY;
! 1272: break;
! 1273: default:
! 1274: icbp->icb_xfwoptions |= ICBXOPT_LOOP_2_PTP;
! 1275: break;
! 1276: }
! 1277: if (IS_23XX(isp)) {
! 1278: /*
! 1279: * QLogic recommends that FAST Posting be turned
! 1280: * off for 23XX cards and instead allow the HBA
! 1281: * to write response queue entries and interrupt
! 1282: * after a delay (ZIO).
! 1283: *
! 1284: * If we set ZIO, it will disable fast posting,
! 1285: * so we don't need to clear it in fwoptions.
! 1286: */
! 1287: icbp->icb_xfwoptions |= ICBXOPT_ZIO;
! 1288: #if 0
! 1289: /*
! 1290: * Values, in 100us increments. The default
! 1291: * is 2 (200us) if a value 0 (default) is
! 1292: * selected.
! 1293: */
! 1294: icbp->icb_idelaytimer = 2;
! 1295: #endif
! 1296:
! 1297: if (isp->isp_confopts & ISP_CFG_ONEGB) {
! 1298: icbp->icb_zfwoptions |= ICBZOPT_RATE_ONEGB;
! 1299: } else if (isp->isp_confopts & ISP_CFG_TWOGB) {
! 1300: icbp->icb_zfwoptions |= ICBZOPT_RATE_TWOGB;
! 1301: } else {
! 1302: icbp->icb_zfwoptions |= ICBZOPT_RATE_AUTO;
! 1303: }
! 1304: }
! 1305: }
! 1306:
! 1307: #ifndef ISP_NO_RIO_FC
! 1308: /*
! 1309: * RIO seems to be enabled in 2100s for fw >= 1.17.0.
! 1310: *
! 1311: * I've had some questionable problems with RIO on 2200.
! 1312: * More specifically, on a 2204 I had problems with RIO
! 1313: * on a Linux system where I was dropping commands right
! 1314: * and left. It's not clear to me what the actual problem
! 1315: * was.
! 1316: *
! 1317: * 23XX Cards do not support RIO. Instead they support ZIO.
! 1318: */
! 1319: #if 0
! 1320: if (!IS_23XX(isp) && ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
! 1321: icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;
! 1322: icbp->icb_racctimer = 4;
! 1323: icbp->icb_idelaytimer = 8;
! 1324: }
! 1325: #endif
! 1326: #endif
! 1327:
! 1328: /*
! 1329: * For 22XX > 2.1.26 && 23XX, set someoptions.
! 1330: * XXX: Probably okay for newer 2100 f/w too.
! 1331: */
! 1332: if (ISP_FW_NEWER_THAN(isp, 2, 26, 0)) {
! 1333: /*
! 1334: * Turn on LIP F8 async event (1)
! 1335: * Turn on generate AE 8013 on all LIP Resets (2)
! 1336: * Disable LIP F7 switching (8)
! 1337: */
! 1338: mbs.param[0] = MBOX_SET_FIRMWARE_OPTIONS;
! 1339: mbs.param[1] = 0xb;
! 1340: mbs.param[2] = 0;
! 1341: mbs.param[3] = 0;
! 1342: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 1343: }
! 1344: icbp->icb_logintime = 30; /* 30 second login timeout */
! 1345:
! 1346: if (IS_23XX(isp)) {
! 1347: ISP_WRITE(isp, isp->isp_rqstinrp, 0);
! 1348: ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
! 1349: ISP_WRITE(isp, isp->isp_respinrp, 0);
! 1350: ISP_WRITE(isp, isp->isp_respoutrp, 0);
! 1351: }
! 1352:
! 1353: nwwn = ISP_NODEWWN(isp);
! 1354: pwwn = ISP_PORTWWN(isp);
! 1355: if (nwwn && pwwn) {
! 1356: icbp->icb_fwoptions |= ICBOPT_BOTH_WWNS;
! 1357: MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, nwwn);
! 1358: MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
! 1359: isp_prt(isp, ISP_LOGDEBUG1,
! 1360: "Setting ICB Node 0x%08x%08x Port 0x%08x%08x",
! 1361: ((u_int32_t) (nwwn >> 32)),
! 1362: ((u_int32_t) (nwwn & 0xffffffff)),
! 1363: ((u_int32_t) (pwwn >> 32)),
! 1364: ((u_int32_t) (pwwn & 0xffffffff)));
! 1365: } else {
! 1366: isp_prt(isp, ISP_LOGDEBUG1, "Not using any WWNs");
! 1367: icbp->icb_fwoptions &= ~(ICBOPT_BOTH_WWNS|ICBOPT_FULL_LOGIN);
! 1368: }
! 1369: icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
! 1370: icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
! 1371: icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
! 1372: icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
! 1373: icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
! 1374: icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
! 1375: icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
! 1376: icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
! 1377: icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
! 1378: icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
! 1379: isp_prt(isp, ISP_LOGDEBUG0,
! 1380: "isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x",
! 1381: icbp->icb_fwoptions, icbp->icb_xfwoptions, icbp->icb_zfwoptions);
! 1382:
! 1383: FC_SCRATCH_ACQUIRE(isp);
! 1384: isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch);
! 1385:
! 1386: /*
! 1387: * Init the firmware
! 1388: */
! 1389: mbs.param[0] = MBOX_INIT_FIRMWARE;
! 1390: mbs.param[1] = 0;
! 1391: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 1392: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 1393: mbs.param[4] = 0;
! 1394: mbs.param[5] = 0;
! 1395: mbs.param[6] = DMA_WD3(fcp->isp_scdma);
! 1396: mbs.param[7] = DMA_WD2(fcp->isp_scdma);
! 1397: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 1398: FC_SCRATCH_RELEASE(isp);
! 1399: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 1400: return;
! 1401: }
! 1402: isp->isp_reqidx = isp->isp_reqodx = 0;
! 1403: isp->isp_residx = 0;
! 1404: isp->isp_sendmarker = 1;
! 1405:
! 1406: /*
! 1407: * Whatever happens, we're now committed to being here.
! 1408: */
! 1409: isp->isp_state = ISP_INITSTATE;
! 1410: }
! 1411:
! 1412: /*
! 1413: * Fibre Channel Support- get the port database for the id.
! 1414: *
! 1415: * Locks are held before coming here. Return 0 if success,
! 1416: * else failure.
! 1417: */
! 1418:
! 1419: static int
! 1420: isp_getmap(struct ispsoftc *isp, fcpos_map_t *map)
! 1421: {
! 1422: fcparam *fcp = (fcparam *) isp->isp_param;
! 1423: mbreg_t mbs;
! 1424:
! 1425: mbs.param[0] = MBOX_GET_FC_AL_POSITION_MAP;
! 1426: mbs.param[1] = 0;
! 1427: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 1428: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 1429: /*
! 1430: * Unneeded. For the 2100, except for initializing f/w, registers
! 1431: * 4/5 have to not be written to.
! 1432: * mbs.param[4] = 0;
! 1433: * mbs.param[5] = 0;
! 1434: *
! 1435: */
! 1436: mbs.param[6] = 0;
! 1437: mbs.param[7] = 0;
! 1438: FC_SCRATCH_ACQUIRE(isp);
! 1439: isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
! 1440: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 1441: MEMCPY(map, fcp->isp_scratch, sizeof (fcpos_map_t));
! 1442: map->fwmap = mbs.param[1] != 0;
! 1443: FC_SCRATCH_RELEASE(isp);
! 1444: return (0);
! 1445: }
! 1446: FC_SCRATCH_RELEASE(isp);
! 1447: return (-1);
! 1448: }
! 1449:
! 1450: static void
! 1451: isp_mark_getpdb_all(struct ispsoftc *isp)
! 1452: {
! 1453: fcparam *fcp = (fcparam *) isp->isp_param;
! 1454: int i;
! 1455: for (i = 0; i < MAX_FC_TARG; i++) {
! 1456: fcp->portdb[i].valid = fcp->portdb[i].fabric_dev = 0;
! 1457: }
! 1458: }
! 1459:
! 1460: static int
! 1461: isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp)
! 1462: {
! 1463: fcparam *fcp = (fcparam *) isp->isp_param;
! 1464: mbreg_t mbs;
! 1465:
! 1466: mbs.param[0] = MBOX_GET_PORT_DB;
! 1467: mbs.param[1] = id << 8;
! 1468: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 1469: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 1470: /*
! 1471: * Unneeded. For the 2100, except for initializing f/w, registers
! 1472: * 4/5 have to not be written to.
! 1473: * mbs.param[4] = 0;
! 1474: * mbs.param[5] = 0;
! 1475: *
! 1476: */
! 1477: mbs.param[6] = DMA_WD3(fcp->isp_scdma);
! 1478: mbs.param[7] = DMA_WD2(fcp->isp_scdma);
! 1479: FC_SCRATCH_ACQUIRE(isp);
! 1480: isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
! 1481: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 1482: isp_get_pdb(isp, (isp_pdb_t *)fcp->isp_scratch, pdbp);
! 1483: FC_SCRATCH_RELEASE(isp);
! 1484: return (0);
! 1485: }
! 1486: FC_SCRATCH_RELEASE(isp);
! 1487: return (-1);
! 1488: }
! 1489:
! 1490: static u_int64_t
! 1491: isp_get_portname(struct ispsoftc *isp, int loopid, int nodename)
! 1492: {
! 1493: u_int64_t wwn = 0;
! 1494: mbreg_t mbs;
! 1495:
! 1496: mbs.param[0] = MBOX_GET_PORT_NAME;
! 1497: mbs.param[1] = loopid << 8;
! 1498: if (nodename)
! 1499: mbs.param[1] |= 1;
! 1500: isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
! 1501: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 1502: wwn =
! 1503: (((u_int64_t)(mbs.param[2] & 0xff)) << 56) |
! 1504: (((u_int64_t)(mbs.param[2] >> 8)) << 48) |
! 1505: (((u_int64_t)(mbs.param[3] & 0xff)) << 40) |
! 1506: (((u_int64_t)(mbs.param[3] >> 8)) << 32) |
! 1507: (((u_int64_t)(mbs.param[6] & 0xff)) << 24) |
! 1508: (((u_int64_t)(mbs.param[6] >> 8)) << 16) |
! 1509: (((u_int64_t)(mbs.param[7] & 0xff)) << 8) |
! 1510: (((u_int64_t)(mbs.param[7] >> 8)));
! 1511: }
! 1512: return (wwn);
! 1513: }
! 1514:
! 1515: /*
! 1516: * Make sure we have good FC link and know our Loop ID.
! 1517: */
! 1518:
! 1519: static int
! 1520: isp_fclink_test(struct ispsoftc *isp, int usdelay)
! 1521: {
! 1522: static char *toponames[] = {
! 1523: "Private Loop",
! 1524: "FL Port",
! 1525: "N-Port to N-Port",
! 1526: "F Port",
! 1527: "F Port (no FLOGI_ACC response)"
! 1528: };
! 1529: mbreg_t mbs;
! 1530: int count, check_for_fabric;
! 1531: u_int8_t lwfs;
! 1532: fcparam *fcp;
! 1533: struct lportdb *lp;
! 1534: isp_pdb_t pdb;
! 1535:
! 1536: fcp = isp->isp_param;
! 1537:
! 1538: /*
! 1539: * XXX: Here is where we would start a 'loop dead' timeout
! 1540: */
! 1541:
! 1542: /*
! 1543: * Wait up to N microseconds for F/W to go to a ready state.
! 1544: */
! 1545: lwfs = FW_CONFIG_WAIT;
! 1546: count = 0;
! 1547: while (count < usdelay) {
! 1548: u_int64_t enano;
! 1549: u_int32_t wrk;
! 1550: NANOTIME_T hra, hrb;
! 1551:
! 1552: GET_NANOTIME(&hra);
! 1553: isp_fw_state(isp);
! 1554: if (lwfs != fcp->isp_fwstate) {
! 1555: isp_prt(isp, ISP_LOGINFO, "Firmware State <%s->%s>",
! 1556: isp2100_fw_statename((int)lwfs),
! 1557: isp2100_fw_statename((int)fcp->isp_fwstate));
! 1558: lwfs = fcp->isp_fwstate;
! 1559: }
! 1560: if (fcp->isp_fwstate == FW_READY) {
! 1561: break;
! 1562: }
! 1563: GET_NANOTIME(&hrb);
! 1564:
! 1565: /*
! 1566: * Get the elapsed time in nanoseconds.
! 1567: * Always guaranteed to be non-zero.
! 1568: */
! 1569: enano = NANOTIME_SUB(&hrb, &hra);
! 1570:
! 1571: isp_prt(isp, ISP_LOGDEBUG1,
! 1572: "usec%d: 0x%lx->0x%lx enano 0x%x%08x",
! 1573: count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb),
! 1574: (u_int32_t)(enano >> 32), (u_int32_t)(enano & 0xffffffff));
! 1575:
! 1576: /*
! 1577: * If the elapsed time is less than 1 millisecond,
! 1578: * delay a period of time up to that millisecond of
! 1579: * waiting.
! 1580: *
! 1581: * This peculiar code is an attempt to try and avoid
! 1582: * invoking u_int64_t math support functions for some
! 1583: * platforms where linkage is a problem.
! 1584: */
! 1585: if (enano < (1000 * 1000)) {
! 1586: count += 1000;
! 1587: enano = (1000 * 1000) - enano;
! 1588: while (enano > (u_int64_t) 4000000000U) {
! 1589: USEC_SLEEP(isp, 4000000);
! 1590: enano -= (u_int64_t) 4000000000U;
! 1591: }
! 1592: wrk = enano;
! 1593: wrk /= 1000;
! 1594: USEC_SLEEP(isp, wrk);
! 1595: } else {
! 1596: while (enano > (u_int64_t) 4000000000U) {
! 1597: count += 4000000;
! 1598: enano -= (u_int64_t) 4000000000U;
! 1599: }
! 1600: wrk = enano;
! 1601: count += (wrk / 1000);
! 1602: }
! 1603: }
! 1604:
! 1605: /*
! 1606: * If we haven't gone to 'ready' state, return.
! 1607: */
! 1608: if (fcp->isp_fwstate != FW_READY) {
! 1609: return (-1);
! 1610: }
! 1611:
! 1612: /*
! 1613: * Get our Loop ID (if possible). We really need to have it.
! 1614: */
! 1615: mbs.param[0] = MBOX_GET_LOOP_ID;
! 1616: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 1617: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 1618: return (-1);
! 1619: }
! 1620: fcp->isp_loopid = mbs.param[1];
! 1621: if (IS_2200(isp) || IS_23XX(isp)) {
! 1622: int topo = (int) mbs.param[6];
! 1623: if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
! 1624: topo = TOPO_PTP_STUB;
! 1625: fcp->isp_topo = topo;
! 1626: } else {
! 1627: fcp->isp_topo = TOPO_NL_PORT;
! 1628: }
! 1629: fcp->isp_portid = fcp->isp_alpa = mbs.param[2] & 0xff;
! 1630:
! 1631: /*
! 1632: * Check to see if we're on a fabric by trying to see if we
! 1633: * can talk to the fabric name server. This can be a bit
! 1634: * tricky because if we're a 2100, we should check always
! 1635: * (in case we're connected to a server doing aliasing).
! 1636: */
! 1637: fcp->isp_onfabric = 0;
! 1638:
! 1639: if (IS_2100(isp)) {
! 1640: /*
! 1641: * Don't bother with fabric if we are using really old
! 1642: * 2100 firmware. It's just not worth it.
! 1643: */
! 1644: if (ISP_FW_NEWER_THAN(isp, 1, 15, 37)) {
! 1645: check_for_fabric = 1;
! 1646: } else {
! 1647: check_for_fabric = 0;
! 1648: }
! 1649: } else if (fcp->isp_topo == TOPO_FL_PORT ||
! 1650: fcp->isp_topo == TOPO_F_PORT) {
! 1651: check_for_fabric = 1;
! 1652: } else
! 1653: check_for_fabric = 0;
! 1654:
! 1655: if (check_for_fabric && isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) {
! 1656: int loopid = FL_PORT_ID;
! 1657: if (IS_2100(isp)) {
! 1658: fcp->isp_topo = TOPO_FL_PORT;
! 1659: }
! 1660:
! 1661: if (BITS2WORD(pdb.pdb_portid_bits) == 0) {
! 1662: /*
! 1663: * Crock.
! 1664: */
! 1665: fcp->isp_topo = TOPO_NL_PORT;
! 1666: goto not_on_fabric;
! 1667: }
! 1668: fcp->isp_portid = mbs.param[2] | ((int) mbs.param[3] << 16);
! 1669:
! 1670: /*
! 1671: * Save the Fabric controller's port database entry.
! 1672: */
! 1673: lp = &fcp->portdb[loopid];
! 1674: lp->node_wwn =
! 1675: (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
! 1676: (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
! 1677: (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
! 1678: (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
! 1679: (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
! 1680: (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
! 1681: (((u_int64_t)pdb.pdb_nodename[6]) << 8) |
! 1682: (((u_int64_t)pdb.pdb_nodename[7]));
! 1683: lp->port_wwn =
! 1684: (((u_int64_t)pdb.pdb_portname[0]) << 56) |
! 1685: (((u_int64_t)pdb.pdb_portname[1]) << 48) |
! 1686: (((u_int64_t)pdb.pdb_portname[2]) << 40) |
! 1687: (((u_int64_t)pdb.pdb_portname[3]) << 32) |
! 1688: (((u_int64_t)pdb.pdb_portname[4]) << 24) |
! 1689: (((u_int64_t)pdb.pdb_portname[5]) << 16) |
! 1690: (((u_int64_t)pdb.pdb_portname[6]) << 8) |
! 1691: (((u_int64_t)pdb.pdb_portname[7]));
! 1692: lp->roles =
! 1693: (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
! 1694: lp->portid = BITS2WORD(pdb.pdb_portid_bits);
! 1695: lp->loopid = pdb.pdb_loopid;
! 1696: lp->loggedin = lp->valid = 1;
! 1697: fcp->isp_onfabric = 1;
! 1698: (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
! 1699: isp_register_fc4_type(isp);
! 1700: } else {
! 1701: not_on_fabric:
! 1702: fcp->isp_onfabric = 0;
! 1703: fcp->portdb[FL_PORT_ID].valid = 0;
! 1704: }
! 1705:
! 1706: fcp->isp_gbspeed = 1;
! 1707: if (IS_23XX(isp)) {
! 1708: mbs.param[0] = MBOX_GET_SET_DATA_RATE;
! 1709: mbs.param[1] = MBGSD_GET_RATE;
! 1710: /* mbs.param[2] undefined if we're just getting rate */
! 1711: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 1712: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 1713: if (mbs.param[1] == MBGSD_TWOGB) {
! 1714: isp_prt(isp, ISP_LOGINFO, "2Gb link speed/s");
! 1715: fcp->isp_gbspeed = 2;
! 1716: }
! 1717: }
! 1718: }
! 1719:
! 1720: isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid, fcp->isp_alpa,
! 1721: fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]);
! 1722:
! 1723: /*
! 1724: * Announce ourselves, too. This involves synthesizing an entry.
! 1725: */
! 1726: if (fcp->isp_iid_set == 0) {
! 1727: fcp->isp_iid_set = 1;
! 1728: fcp->isp_iid = fcp->isp_loopid;
! 1729: lp = &fcp->portdb[fcp->isp_iid];
! 1730: } else {
! 1731: lp = &fcp->portdb[fcp->isp_iid];
! 1732: if (fcp->isp_portid != lp->portid ||
! 1733: fcp->isp_loopid != lp->loopid ||
! 1734: fcp->isp_nodewwn != ISP_NODEWWN(isp) ||
! 1735: fcp->isp_portwwn != ISP_PORTWWN(isp)) {
! 1736: lp->valid = 0;
! 1737: count = fcp->isp_iid;
! 1738: (void) isp_async(isp, ISPASYNC_PROMENADE, &count);
! 1739: }
! 1740: }
! 1741: lp->loopid = fcp->isp_loopid;
! 1742: lp->portid = fcp->isp_portid;
! 1743: lp->node_wwn = ISP_NODEWWN(isp);
! 1744: lp->port_wwn = ISP_PORTWWN(isp);
! 1745: switch (isp->isp_role) {
! 1746: case ISP_ROLE_NONE:
! 1747: lp->roles = 0;
! 1748: break;
! 1749: case ISP_ROLE_TARGET:
! 1750: lp->roles = SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT;
! 1751: break;
! 1752: case ISP_ROLE_INITIATOR:
! 1753: lp->roles = SVC3_INI_ROLE >> SVC3_ROLE_SHIFT;
! 1754: break;
! 1755: case ISP_ROLE_BOTH:
! 1756: lp->roles = (SVC3_INI_ROLE|SVC3_TGT_ROLE) >> SVC3_ROLE_SHIFT;
! 1757: break;
! 1758: }
! 1759: lp->loggedin = lp->valid = 1;
! 1760: count = fcp->isp_iid;
! 1761: (void) isp_async(isp, ISPASYNC_PROMENADE, &count);
! 1762: return (0);
! 1763: }
! 1764:
! 1765: static char *
! 1766: isp2100_fw_statename(int state)
! 1767: {
! 1768: switch(state) {
! 1769: case FW_CONFIG_WAIT: return "Config Wait";
! 1770: case FW_WAIT_AL_PA: return "Waiting for AL_PA";
! 1771: case FW_WAIT_LOGIN: return "Wait Login";
! 1772: case FW_READY: return "Ready";
! 1773: case FW_LOSS_OF_SYNC: return "Loss Of Sync";
! 1774: case FW_ERROR: return "Error";
! 1775: case FW_REINIT: return "Re-Init";
! 1776: case FW_NON_PART: return "Nonparticipating";
! 1777: default: return "?????";
! 1778: }
! 1779: }
! 1780:
! 1781: /*
! 1782: * Synchronize our soft copy of the port database with what the f/w thinks
! 1783: * (with a view toward possibly for a specific target....)
! 1784: */
! 1785:
! 1786: static int
! 1787: isp_pdb_sync(struct ispsoftc *isp)
! 1788: {
! 1789: struct lportdb *lp;
! 1790: fcparam *fcp = isp->isp_param;
! 1791: isp_pdb_t pdb;
! 1792: int loopid, base, lim;
! 1793:
! 1794: /*
! 1795: * Make sure we're okay for doing this right now.
! 1796: */
! 1797: if (fcp->isp_loopstate != LOOP_PDB_RCVD &&
! 1798: fcp->isp_loopstate != LOOP_FSCAN_DONE &&
! 1799: fcp->isp_loopstate != LOOP_LSCAN_DONE) {
! 1800: return (-1);
! 1801: }
! 1802:
! 1803: if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT ||
! 1804: fcp->isp_topo == TOPO_N_PORT) {
! 1805: if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
! 1806: if (isp_scan_loop(isp) != 0) {
! 1807: return (-1);
! 1808: }
! 1809: }
! 1810: }
! 1811: fcp->isp_loopstate = LOOP_SYNCING_PDB;
! 1812:
! 1813: /*
! 1814: * If we get this far, we've settled our differences with the f/w
! 1815: * (for local loop device) and we can say that the loop state is ready.
! 1816: */
! 1817:
! 1818: if (fcp->isp_topo == TOPO_NL_PORT) {
! 1819: fcp->loop_seen_once = 1;
! 1820: fcp->isp_loopstate = LOOP_READY;
! 1821: return (0);
! 1822: }
! 1823:
! 1824: /*
! 1825: * Find all Fabric Entities that didn't make it from one scan to the
! 1826: * next and let the world know they went away. Scan the whole database.
! 1827: */
! 1828: for (lp = &fcp->portdb[0]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
! 1829: if (lp->was_fabric_dev && lp->fabric_dev == 0) {
! 1830: loopid = lp - fcp->portdb;
! 1831: lp->valid = 0; /* should already be set */
! 1832: (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
! 1833: MEMZERO((void *) lp, sizeof (*lp));
! 1834: continue;
! 1835: }
! 1836: lp->was_fabric_dev = lp->fabric_dev;
! 1837: }
! 1838:
! 1839: if (fcp->isp_topo == TOPO_FL_PORT)
! 1840: base = FC_SNS_ID+1;
! 1841: else
! 1842: base = 0;
! 1843:
! 1844: if (fcp->isp_topo == TOPO_N_PORT)
! 1845: lim = 1;
! 1846: else
! 1847: lim = MAX_FC_TARG;
! 1848:
! 1849: /*
! 1850: * Now log in any fabric devices that the outer layer has
! 1851: * left for us to see. This seems the most sane policy
! 1852: * for the moment.
! 1853: */
! 1854: for (lp = &fcp->portdb[base]; lp < &fcp->portdb[lim]; lp++) {
! 1855: u_int32_t portid;
! 1856: mbreg_t mbs;
! 1857:
! 1858: loopid = lp - fcp->portdb;
! 1859: if (loopid >= FL_PORT_ID && loopid <= FC_SNS_ID) {
! 1860: continue;
! 1861: }
! 1862:
! 1863: /*
! 1864: * Anything here?
! 1865: */
! 1866: if (lp->port_wwn == 0) {
! 1867: continue;
! 1868: }
! 1869:
! 1870: /*
! 1871: * Don't try to log into yourself.
! 1872: */
! 1873: if ((portid = lp->portid) == fcp->isp_portid) {
! 1874: continue;
! 1875: }
! 1876:
! 1877:
! 1878: /*
! 1879: * If we'd been logged in- see if we still are and we haven't
! 1880: * changed. If so, no need to log ourselves out, etc..
! 1881: *
! 1882: * Unfortunately, our charming Qlogic f/w has decided to
! 1883: * return a valid port database entry for a fabric device
! 1884: * that has, in fact, gone away. And it hangs trying to
! 1885: * log it out.
! 1886: */
! 1887: if (lp->loggedin && lp->force_logout == 0 &&
! 1888: isp_getpdb(isp, lp->loopid, &pdb) == 0) {
! 1889: int nrole;
! 1890: u_int64_t nwwnn, nwwpn;
! 1891: nwwnn =
! 1892: (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
! 1893: (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
! 1894: (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
! 1895: (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
! 1896: (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
! 1897: (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
! 1898: (((u_int64_t)pdb.pdb_nodename[6]) << 8) |
! 1899: (((u_int64_t)pdb.pdb_nodename[7]));
! 1900: nwwpn =
! 1901: (((u_int64_t)pdb.pdb_portname[0]) << 56) |
! 1902: (((u_int64_t)pdb.pdb_portname[1]) << 48) |
! 1903: (((u_int64_t)pdb.pdb_portname[2]) << 40) |
! 1904: (((u_int64_t)pdb.pdb_portname[3]) << 32) |
! 1905: (((u_int64_t)pdb.pdb_portname[4]) << 24) |
! 1906: (((u_int64_t)pdb.pdb_portname[5]) << 16) |
! 1907: (((u_int64_t)pdb.pdb_portname[6]) << 8) |
! 1908: (((u_int64_t)pdb.pdb_portname[7]));
! 1909: nrole = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >>
! 1910: SVC3_ROLE_SHIFT;
! 1911: if (pdb.pdb_loopid == lp->loopid && lp->portid ==
! 1912: (u_int32_t) BITS2WORD(pdb.pdb_portid_bits) &&
! 1913: nwwnn == lp->node_wwn && nwwpn == lp->port_wwn &&
! 1914: lp->roles == nrole && lp->force_logout == 0) {
! 1915: lp->loggedin = lp->valid = 1;
! 1916: isp_prt(isp, ISP_LOGCONFIG, lretained,
! 1917: (int) (lp - fcp->portdb),
! 1918: (int) lp->loopid, lp->portid);
! 1919: continue;
! 1920: }
! 1921: }
! 1922:
! 1923: if (fcp->isp_fwstate != FW_READY ||
! 1924: fcp->isp_loopstate != LOOP_SYNCING_PDB) {
! 1925: return (-1);
! 1926: }
! 1927:
! 1928: /*
! 1929: * Force a logout if we were logged in.
! 1930: */
! 1931: if (lp->loggedin) {
! 1932: if (lp->force_logout ||
! 1933: isp_getpdb(isp, lp->loopid, &pdb) == 0) {
! 1934: mbs.param[0] = MBOX_FABRIC_LOGOUT;
! 1935: mbs.param[1] = lp->loopid << 8;
! 1936: mbs.param[2] = 0;
! 1937: mbs.param[3] = 0;
! 1938: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 1939: isp_prt(isp, ISP_LOGINFO, plogout,
! 1940: (int) (lp - fcp->portdb), lp->loopid,
! 1941: lp->portid);
! 1942: }
! 1943: lp->force_logout = lp->loggedin = 0;
! 1944: if (fcp->isp_fwstate != FW_READY ||
! 1945: fcp->isp_loopstate != LOOP_SYNCING_PDB) {
! 1946: return (-1);
! 1947: }
! 1948: }
! 1949:
! 1950: /*
! 1951: * And log in....
! 1952: */
! 1953: loopid = lp - fcp->portdb;
! 1954: lp->loopid = FL_PORT_ID;
! 1955: do {
! 1956: mbs.param[0] = MBOX_FABRIC_LOGIN;
! 1957: mbs.param[1] = loopid << 8;
! 1958: mbs.param[2] = portid >> 16;
! 1959: mbs.param[3] = portid & 0xffff;
! 1960: isp_mboxcmd(isp, &mbs, MBLOGALL & ~(MBOX_LOOP_ID_USED |
! 1961: MBOX_PORT_ID_USED | MBOX_COMMAND_ERROR));
! 1962: if (fcp->isp_fwstate != FW_READY ||
! 1963: fcp->isp_loopstate != LOOP_SYNCING_PDB) {
! 1964: return (-1);
! 1965: }
! 1966: switch (mbs.param[0]) {
! 1967: case MBOX_LOOP_ID_USED:
! 1968: /*
! 1969: * Try the next available loop id.
! 1970: */
! 1971: loopid++;
! 1972: break;
! 1973: case MBOX_PORT_ID_USED:
! 1974: /*
! 1975: * This port is already logged in.
! 1976: * Snaffle the loop id it's using if it's
! 1977: * nonzero, otherwise we're hosed.
! 1978: */
! 1979: if (mbs.param[1] != 0) {
! 1980: loopid = mbs.param[1];
! 1981: isp_prt(isp, ISP_LOGINFO, retained,
! 1982: loopid, (int) (lp - fcp->portdb),
! 1983: lp->portid);
! 1984: } else {
! 1985: loopid = MAX_FC_TARG;
! 1986: break;
! 1987: }
! 1988: /* FALLTHROUGH */
! 1989: case MBOX_COMMAND_COMPLETE:
! 1990: lp->loggedin = 1;
! 1991: lp->loopid = loopid;
! 1992: break;
! 1993: case MBOX_COMMAND_ERROR:
! 1994: isp_prt(isp, ISP_LOGINFO, plogierr,
! 1995: portid, mbs.param[1]);
! 1996: /* FALLTHROUGH */
! 1997: case MBOX_ALL_IDS_USED: /* We're outta IDs */
! 1998: default:
! 1999: loopid = MAX_FC_TARG;
! 2000: break;
! 2001: }
! 2002: } while (lp->loopid == FL_PORT_ID && loopid < MAX_FC_TARG);
! 2003:
! 2004: /*
! 2005: * If we get here and we haven't set a Loop ID,
! 2006: * we failed to log into this device.
! 2007: */
! 2008:
! 2009: if (lp->loopid == FL_PORT_ID) {
! 2010: lp->loopid = 0;
! 2011: continue;
! 2012: }
! 2013:
! 2014: /*
! 2015: * Make sure we can get the appropriate port information.
! 2016: */
! 2017: if (isp_getpdb(isp, lp->loopid, &pdb) != 0) {
! 2018: isp_prt(isp, ISP_LOGWARN, nopdb, lp->portid);
! 2019: goto dump_em;
! 2020: }
! 2021:
! 2022: if (fcp->isp_fwstate != FW_READY ||
! 2023: fcp->isp_loopstate != LOOP_SYNCING_PDB) {
! 2024: return (-1);
! 2025: }
! 2026:
! 2027: if (pdb.pdb_loopid != lp->loopid) {
! 2028: isp_prt(isp, ISP_LOGWARN, pdbmfail1,
! 2029: lp->portid, pdb.pdb_loopid);
! 2030: goto dump_em;
! 2031: }
! 2032:
! 2033: if (lp->portid != (u_int32_t) BITS2WORD(pdb.pdb_portid_bits)) {
! 2034: isp_prt(isp, ISP_LOGWARN, pdbmfail2,
! 2035: lp->portid, BITS2WORD(pdb.pdb_portid_bits));
! 2036: goto dump_em;
! 2037: }
! 2038:
! 2039: lp->roles =
! 2040: (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
! 2041: lp->node_wwn =
! 2042: (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
! 2043: (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
! 2044: (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
! 2045: (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
! 2046: (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
! 2047: (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
! 2048: (((u_int64_t)pdb.pdb_nodename[6]) << 8) |
! 2049: (((u_int64_t)pdb.pdb_nodename[7]));
! 2050: lp->port_wwn =
! 2051: (((u_int64_t)pdb.pdb_portname[0]) << 56) |
! 2052: (((u_int64_t)pdb.pdb_portname[1]) << 48) |
! 2053: (((u_int64_t)pdb.pdb_portname[2]) << 40) |
! 2054: (((u_int64_t)pdb.pdb_portname[3]) << 32) |
! 2055: (((u_int64_t)pdb.pdb_portname[4]) << 24) |
! 2056: (((u_int64_t)pdb.pdb_portname[5]) << 16) |
! 2057: (((u_int64_t)pdb.pdb_portname[6]) << 8) |
! 2058: (((u_int64_t)pdb.pdb_portname[7]));
! 2059: /*
! 2060: * Check to make sure this all makes sense.
! 2061: */
! 2062: if (lp->node_wwn && lp->port_wwn) {
! 2063: lp->valid = 1;
! 2064: loopid = lp - fcp->portdb;
! 2065: (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
! 2066: continue;
! 2067: }
! 2068: dump_em:
! 2069: lp->valid = 0;
! 2070: isp_prt(isp, ISP_LOGINFO,
! 2071: ldumped, loopid, lp->loopid, lp->portid);
! 2072: mbs.param[0] = MBOX_FABRIC_LOGOUT;
! 2073: mbs.param[1] = lp->loopid << 8;
! 2074: mbs.param[2] = 0;
! 2075: mbs.param[3] = 0;
! 2076: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 2077: if (fcp->isp_fwstate != FW_READY ||
! 2078: fcp->isp_loopstate != LOOP_SYNCING_PDB) {
! 2079: return (-1);
! 2080: }
! 2081: }
! 2082: /*
! 2083: * If we get here, we've for sure seen not only a valid loop
! 2084: * but know what is or isn't on it, so mark this for usage
! 2085: * in isp_start.
! 2086: */
! 2087: fcp->loop_seen_once = 1;
! 2088: fcp->isp_loopstate = LOOP_READY;
! 2089: return (0);
! 2090: }
! 2091:
! 2092: static int
! 2093: isp_scan_loop(struct ispsoftc *isp)
! 2094: {
! 2095: struct lportdb *lp;
! 2096: fcparam *fcp = isp->isp_param;
! 2097: isp_pdb_t pdb;
! 2098: int loopid, lim, hival;
! 2099:
! 2100: switch (fcp->isp_topo) {
! 2101: case TOPO_NL_PORT:
! 2102: hival = FL_PORT_ID;
! 2103: break;
! 2104: case TOPO_N_PORT:
! 2105: hival = 2;
! 2106: break;
! 2107: case TOPO_FL_PORT:
! 2108: hival = FC_PORT_ID;
! 2109: break;
! 2110: default:
! 2111: fcp->isp_loopstate = LOOP_LSCAN_DONE;
! 2112: return (0);
! 2113: }
! 2114: fcp->isp_loopstate = LOOP_SCANNING_LOOP;
! 2115:
! 2116: /*
! 2117: * make sure the temp port database is clean...
! 2118: */
! 2119: MEMZERO((void *)fcp->tport, sizeof (fcp->tport));
! 2120:
! 2121: /*
! 2122: * Run through the local loop ports and get port database info
! 2123: * for each loop ID.
! 2124: *
! 2125: * There's a somewhat unexplained situation where the f/w passes back
! 2126: * the wrong database entity- if that happens, just restart (up to
! 2127: * FL_PORT_ID times).
! 2128: */
! 2129: for (lim = loopid = 0; loopid < hival; loopid++) {
! 2130: lp = &fcp->tport[loopid];
! 2131:
! 2132: /*
! 2133: * Don't even try for ourselves...
! 2134: */
! 2135: if (loopid == fcp->isp_loopid)
! 2136: continue;
! 2137:
! 2138: lp->node_wwn = isp_get_portname(isp, loopid, 1);
! 2139: if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
! 2140: return (-1);
! 2141: if (lp->node_wwn == 0)
! 2142: continue;
! 2143: lp->port_wwn = isp_get_portname(isp, loopid, 0);
! 2144: if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
! 2145: return (-1);
! 2146: if (lp->port_wwn == 0) {
! 2147: lp->node_wwn = 0;
! 2148: continue;
! 2149: }
! 2150:
! 2151: /*
! 2152: * Get an entry....
! 2153: */
! 2154: if (isp_getpdb(isp, loopid, &pdb) != 0) {
! 2155: if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
! 2156: return (-1);
! 2157: continue;
! 2158: }
! 2159: if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
! 2160: return (-1);
! 2161: }
! 2162:
! 2163: /*
! 2164: * If the returned database element doesn't match what we
! 2165: * asked for, restart the process entirely (up to a point...).
! 2166: */
! 2167: if (pdb.pdb_loopid != loopid) {
! 2168: loopid = 0;
! 2169: if (lim++ < hival) {
! 2170: continue;
! 2171: }
! 2172: isp_prt(isp, ISP_LOGWARN,
! 2173: "giving up on synchronizing the port database");
! 2174: return (-1);
! 2175: }
! 2176:
! 2177: /*
! 2178: * Save the pertinent info locally.
! 2179: */
! 2180: lp->node_wwn =
! 2181: (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
! 2182: (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
! 2183: (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
! 2184: (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
! 2185: (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
! 2186: (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
! 2187: (((u_int64_t)pdb.pdb_nodename[6]) << 8) |
! 2188: (((u_int64_t)pdb.pdb_nodename[7]));
! 2189: lp->port_wwn =
! 2190: (((u_int64_t)pdb.pdb_portname[0]) << 56) |
! 2191: (((u_int64_t)pdb.pdb_portname[1]) << 48) |
! 2192: (((u_int64_t)pdb.pdb_portname[2]) << 40) |
! 2193: (((u_int64_t)pdb.pdb_portname[3]) << 32) |
! 2194: (((u_int64_t)pdb.pdb_portname[4]) << 24) |
! 2195: (((u_int64_t)pdb.pdb_portname[5]) << 16) |
! 2196: (((u_int64_t)pdb.pdb_portname[6]) << 8) |
! 2197: (((u_int64_t)pdb.pdb_portname[7]));
! 2198: lp->roles =
! 2199: (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
! 2200: lp->portid = BITS2WORD(pdb.pdb_portid_bits);
! 2201: lp->loopid = pdb.pdb_loopid;
! 2202: }
! 2203:
! 2204: /*
! 2205: * Mark all of the permanent local loop database entries as invalid
! 2206: * (except our own entry).
! 2207: */
! 2208: for (loopid = 0; loopid < hival; loopid++) {
! 2209: if (loopid == fcp->isp_iid) {
! 2210: fcp->portdb[loopid].valid = 1;
! 2211: fcp->portdb[loopid].loopid = fcp->isp_loopid;
! 2212: continue;
! 2213: }
! 2214: fcp->portdb[loopid].valid = 0;
! 2215: }
! 2216:
! 2217: /*
! 2218: * Now merge our local copy of the port database into our saved copy.
! 2219: * Notify the outer layers of new devices arriving.
! 2220: */
! 2221: for (loopid = 0; loopid < hival; loopid++) {
! 2222: int i;
! 2223:
! 2224: /*
! 2225: * If we don't have a non-zero Port WWN, we're not here.
! 2226: */
! 2227: if (fcp->tport[loopid].port_wwn == 0) {
! 2228: continue;
! 2229: }
! 2230:
! 2231: /*
! 2232: * Skip ourselves.
! 2233: */
! 2234: if (loopid == fcp->isp_iid) {
! 2235: continue;
! 2236: }
! 2237:
! 2238: /*
! 2239: * For the purposes of deciding whether this is the
! 2240: * 'same' device or not, we only search for an identical
! 2241: * Port WWN. Node WWNs may or may not be the same as
! 2242: * the Port WWN, and there may be multiple different
! 2243: * Port WWNs with the same Node WWN. It would be chaos
! 2244: * to have multiple identical Port WWNs, so we don't
! 2245: * allow that.
! 2246: */
! 2247:
! 2248: for (i = 0; i < hival; i++) {
! 2249: int j;
! 2250: if (fcp->portdb[i].port_wwn == 0)
! 2251: continue;
! 2252: if (fcp->portdb[i].port_wwn !=
! 2253: fcp->tport[loopid].port_wwn)
! 2254: continue;
! 2255: /*
! 2256: * We found this WWN elsewhere- it's changed
! 2257: * loopids then. We don't change its actual
! 2258: * position in our cached port database- we
! 2259: * just change the actual loop ID we'd use.
! 2260: */
! 2261: if (fcp->portdb[i].loopid != loopid) {
! 2262: isp_prt(isp, ISP_LOGINFO, portshift, i,
! 2263: fcp->portdb[i].loopid,
! 2264: fcp->portdb[i].portid, loopid,
! 2265: fcp->tport[loopid].portid);
! 2266: }
! 2267: fcp->portdb[i].portid = fcp->tport[loopid].portid;
! 2268: fcp->portdb[i].loopid = loopid;
! 2269: fcp->portdb[i].valid = 1;
! 2270: fcp->portdb[i].roles = fcp->tport[loopid].roles;
! 2271:
! 2272: /*
! 2273: * Now make sure this Port WWN doesn't exist elsewhere
! 2274: * in the port database.
! 2275: */
! 2276: for (j = i+1; j < hival; j++) {
! 2277: if (fcp->portdb[i].port_wwn !=
! 2278: fcp->portdb[j].port_wwn) {
! 2279: continue;
! 2280: }
! 2281: isp_prt(isp, ISP_LOGWARN, portdup, j, i);
! 2282: /*
! 2283: * Invalidate the 'old' *and* 'new' ones.
! 2284: * This is really harsh and not quite right,
! 2285: * but if this happens, we really don't know
! 2286: * who is what at this point.
! 2287: */
! 2288: fcp->portdb[i].valid = 0;
! 2289: fcp->portdb[j].valid = 0;
! 2290: }
! 2291: break;
! 2292: }
! 2293:
! 2294: /*
! 2295: * If we didn't traverse the entire port database,
! 2296: * then we found (and remapped) an existing entry.
! 2297: * No need to notify anyone- go for the next one.
! 2298: */
! 2299: if (i < hival) {
! 2300: isp_prt(isp, ISP_LOGINFO, retained,
! 2301: fcp->portdb[i].loopid, i, fcp->portdb[i].portid);
! 2302: continue;
! 2303: }
! 2304:
! 2305: /*
! 2306: * We've not found this Port WWN anywhere. It's a new entry.
! 2307: * See if we can leave it where it is (with target == loopid).
! 2308: */
! 2309: if (fcp->portdb[loopid].port_wwn != 0) {
! 2310: for (lim = 0; lim < hival; lim++) {
! 2311: if (fcp->portdb[lim].port_wwn == 0)
! 2312: break;
! 2313: }
! 2314: /* "Cannot Happen" */
! 2315: if (lim == hival) {
! 2316: isp_prt(isp, ISP_LOGWARN, "Remap Overflow");
! 2317: continue;
! 2318: }
! 2319: i = lim;
! 2320: } else {
! 2321: i = loopid;
! 2322: }
! 2323:
! 2324: /*
! 2325: * NB: The actual loopid we use here is loopid- we may
! 2326: * in fact be at a completely different index (target).
! 2327: */
! 2328: fcp->portdb[i].loopid = loopid;
! 2329: fcp->portdb[i].port_wwn = fcp->tport[loopid].port_wwn;
! 2330: fcp->portdb[i].node_wwn = fcp->tport[loopid].node_wwn;
! 2331: fcp->portdb[i].roles = fcp->tport[loopid].roles;
! 2332: fcp->portdb[i].portid = fcp->tport[loopid].portid;
! 2333: fcp->portdb[i].valid = 1;
! 2334:
! 2335: /*
! 2336: * Tell the outside world we've arrived.
! 2337: */
! 2338: (void) isp_async(isp, ISPASYNC_PROMENADE, &i);
! 2339: }
! 2340:
! 2341: /*
! 2342: * Now find all previously used targets that are now invalid and
! 2343: * notify the outer layers that they're gone.
! 2344: */
! 2345: for (lp = &fcp->portdb[0]; lp < &fcp->portdb[hival]; lp++) {
! 2346: if (lp->valid || lp->port_wwn == 0) {
! 2347: continue;
! 2348: }
! 2349:
! 2350: /*
! 2351: * Tell the outside world we've gone
! 2352: * away and erase our pdb entry.
! 2353: *
! 2354: */
! 2355: loopid = lp - fcp->portdb;
! 2356: (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
! 2357: MEMZERO((void *) lp, sizeof (*lp));
! 2358: }
! 2359: fcp->isp_loopstate = LOOP_LSCAN_DONE;
! 2360: return (0);
! 2361: }
! 2362:
! 2363:
! 2364: static int
! 2365: isp_fabric_mbox_cmd(struct ispsoftc *isp, mbreg_t *mbp)
! 2366: {
! 2367: isp_mboxcmd(isp, mbp, MBLOGNONE);
! 2368: if (mbp->param[0] != MBOX_COMMAND_COMPLETE) {
! 2369: if (FCPARAM(isp)->isp_loopstate == LOOP_SCANNING_FABRIC) {
! 2370: FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
! 2371: }
! 2372: if (mbp->param[0] == MBOX_COMMAND_ERROR) {
! 2373: char tbuf[16];
! 2374: char *m;
! 2375: switch (mbp->param[1]) {
! 2376: case 1:
! 2377: m = "No Loop";
! 2378: break;
! 2379: case 2:
! 2380: m = "Failed to allocate IOCB buffer";
! 2381: break;
! 2382: case 3:
! 2383: m = "Failed to allocate XCB buffer";
! 2384: break;
! 2385: case 4:
! 2386: m = "timeout or transmit failed";
! 2387: break;
! 2388: case 5:
! 2389: m = "no fabric loop";
! 2390: break;
! 2391: case 6:
! 2392: m = "remote device not a target";
! 2393: break;
! 2394: default:
! 2395: SNPRINTF(tbuf, sizeof tbuf, "%x",
! 2396: mbp->param[1]);
! 2397: m = tbuf;
! 2398: break;
! 2399: }
! 2400: isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m);
! 2401: }
! 2402: return (-1);
! 2403: }
! 2404:
! 2405: if (FCPARAM(isp)->isp_fwstate != FW_READY ||
! 2406: FCPARAM(isp)->isp_loopstate < LOOP_SCANNING_FABRIC) {
! 2407: return (-1);
! 2408: }
! 2409: return(0);
! 2410: }
! 2411:
! 2412: #ifdef ISP_USE_GA_NXT
! 2413: static int
! 2414: isp_scan_fabric(struct ispsoftc *isp, int ftype)
! 2415: {
! 2416: fcparam *fcp = isp->isp_param;
! 2417: u_int32_t portid, first_portid, last_portid;
! 2418: int hicap, last_port_same;
! 2419:
! 2420: if (fcp->isp_onfabric == 0) {
! 2421: fcp->isp_loopstate = LOOP_FSCAN_DONE;
! 2422: return (0);
! 2423: }
! 2424:
! 2425: FC_SCRATCH_ACQUIRE(isp);
! 2426:
! 2427: /*
! 2428: * Since Port IDs are 24 bits, we can check against having seen
! 2429: * anything yet with this value.
! 2430: */
! 2431: last_port_same = 0;
! 2432: last_portid = 0xffffffff; /* not a port */
! 2433: first_portid = portid = fcp->isp_portid;
! 2434: fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
! 2435:
! 2436: for (hicap = 0; hicap < GA_NXT_MAX; hicap++) {
! 2437: mbreg_t mbs;
! 2438: sns_screq_t *rq;
! 2439: sns_ga_nxt_rsp_t *rs0, *rs1;
! 2440: struct lportdb lcl;
! 2441: u_int8_t sc[SNS_GA_NXT_RESP_SIZE];
! 2442:
! 2443: rq = (sns_screq_t *)sc;
! 2444: MEMZERO((void *) rq, SNS_GA_NXT_REQ_SIZE);
! 2445: rq->snscb_rblen = SNS_GA_NXT_RESP_SIZE >> 1;
! 2446: rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+0x100);
! 2447: rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+0x100);
! 2448: rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+0x100);
! 2449: rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+0x100);
! 2450: rq->snscb_sblen = 6;
! 2451: rq->snscb_data[0] = SNS_GA_NXT;
! 2452: rq->snscb_data[4] = portid & 0xffff;
! 2453: rq->snscb_data[5] = (portid >> 16) & 0xff;
! 2454: isp_put_sns_request(isp, rq, (sns_screq_t *) fcp->isp_scratch);
! 2455: MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GA_NXT_REQ_SIZE);
! 2456: mbs.param[0] = MBOX_SEND_SNS;
! 2457: mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1;
! 2458: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 2459: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 2460: /*
! 2461: * Leave 4 and 5 alone
! 2462: */
! 2463: mbs.param[6] = DMA_WD3(fcp->isp_scdma);
! 2464: mbs.param[7] = DMA_WD2(fcp->isp_scdma);
! 2465: if (isp_fabric_mbox_cmd(isp, &mbs)) {
! 2466: if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
! 2467: fcp->isp_loopstate = LOOP_PDB_RCVD;
! 2468: }
! 2469: FC_SCRATCH_RELEASE(isp);
! 2470: return (-1);
! 2471: }
! 2472: MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GA_NXT_RESP_SIZE);
! 2473: rs1 = (sns_ga_nxt_rsp_t *) sc;
! 2474: rs0 = (sns_ga_nxt_rsp_t *) ((u_int8_t *)fcp->isp_scratch+0x100);
! 2475: isp_get_ga_nxt_response(isp, rs0, rs1);
! 2476: if (rs1->snscb_cthdr.ct_response != FS_ACC) {
! 2477: int level;
! 2478: if (rs1->snscb_cthdr.ct_reason == 9 &&
! 2479: rs1->snscb_cthdr.ct_explanation == 7)
! 2480: level = ISP_LOGDEBUG0;
! 2481: else
! 2482: level = ISP_LOGWARN;
! 2483: isp_prt(isp, level, swrej, "GA_NXT",
! 2484: rs1->snscb_cthdr.ct_reason,
! 2485: rs1->snscb_cthdr.ct_explanation, portid);
! 2486: FC_SCRATCH_RELEASE(isp);
! 2487: fcp->isp_loopstate = LOOP_FSCAN_DONE;
! 2488: return (0);
! 2489: }
! 2490: portid =
! 2491: (((u_int32_t) rs1->snscb_port_id[0]) << 16) |
! 2492: (((u_int32_t) rs1->snscb_port_id[1]) << 8) |
! 2493: (((u_int32_t) rs1->snscb_port_id[2]));
! 2494:
! 2495: /*
! 2496: * XXX: We should check to make sure that this entry
! 2497: * XXX: supports the type(s) we are interested in.
! 2498: */
! 2499: /*
! 2500: * Okay, we now have information about a fabric object.
! 2501: * If it is the type we're interested in, tell the outer layers
! 2502: * about it. The outer layer needs to know: Port ID, WWNN,
! 2503: * WWPN, FC4 type, and port type.
! 2504: *
! 2505: * The lportdb structure is adequate for this.
! 2506: */
! 2507: MEMZERO(&lcl, sizeof (lcl));
! 2508: lcl.port_type = rs1->snscb_port_type;
! 2509: lcl.fc4_type = ftype;
! 2510: lcl.portid = portid;
! 2511: lcl.node_wwn =
! 2512: (((u_int64_t)rs1->snscb_nodename[0]) << 56) |
! 2513: (((u_int64_t)rs1->snscb_nodename[1]) << 48) |
! 2514: (((u_int64_t)rs1->snscb_nodename[2]) << 40) |
! 2515: (((u_int64_t)rs1->snscb_nodename[3]) << 32) |
! 2516: (((u_int64_t)rs1->snscb_nodename[4]) << 24) |
! 2517: (((u_int64_t)rs1->snscb_nodename[5]) << 16) |
! 2518: (((u_int64_t)rs1->snscb_nodename[6]) << 8) |
! 2519: (((u_int64_t)rs1->snscb_nodename[7]));
! 2520: lcl.port_wwn =
! 2521: (((u_int64_t)rs1->snscb_portname[0]) << 56) |
! 2522: (((u_int64_t)rs1->snscb_portname[1]) << 48) |
! 2523: (((u_int64_t)rs1->snscb_portname[2]) << 40) |
! 2524: (((u_int64_t)rs1->snscb_portname[3]) << 32) |
! 2525: (((u_int64_t)rs1->snscb_portname[4]) << 24) |
! 2526: (((u_int64_t)rs1->snscb_portname[5]) << 16) |
! 2527: (((u_int64_t)rs1->snscb_portname[6]) << 8) |
! 2528: (((u_int64_t)rs1->snscb_portname[7]));
! 2529:
! 2530: /*
! 2531: * Does this fabric object support the type we want?
! 2532: * If not, skip it.
! 2533: */
! 2534: if (rs1->snscb_fc4_types[ftype >> 5] & (1 << (ftype & 0x1f))) {
! 2535: if (first_portid == portid) {
! 2536: lcl.last_fabric_dev = 1;
! 2537: } else {
! 2538: lcl.last_fabric_dev = 0;
! 2539: }
! 2540: (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
! 2541: } else {
! 2542: isp_prt(isp, ISP_LOGDEBUG0,
! 2543: "PortID 0x%x doesn't support FC4 type 0x%x",
! 2544: portid, ftype);
! 2545: }
! 2546: if (first_portid == portid) {
! 2547: fcp->isp_loopstate = LOOP_FSCAN_DONE;
! 2548: FC_SCRATCH_RELEASE(isp);
! 2549: return (0);
! 2550: }
! 2551: if (portid == last_portid) {
! 2552: if (last_port_same++ > 20) {
! 2553: isp_prt(isp, ISP_LOGWARN,
! 2554: "tangled fabric database detected");
! 2555: break;
! 2556: }
! 2557: } else {
! 2558: last_port_same = 0 ;
! 2559: last_portid = portid;
! 2560: }
! 2561: }
! 2562: FC_SCRATCH_RELEASE(isp);
! 2563: if (hicap >= GA_NXT_MAX) {
! 2564: isp_prt(isp, ISP_LOGWARN, "fabric too big (> %d)", GA_NXT_MAX);
! 2565: }
! 2566: fcp->isp_loopstate = LOOP_FSCAN_DONE;
! 2567: return (0);
! 2568: }
! 2569: #else
! 2570: #define GIDLEN ((ISP2100_SCRLEN >> 1) + 16)
! 2571: #define NGENT ((GIDLEN - 16) >> 2)
! 2572:
! 2573: #define IGPOFF (ISP2100_SCRLEN - GIDLEN)
! 2574: #define GXOFF (256)
! 2575:
! 2576: static int
! 2577: isp_scan_fabric(struct ispsoftc *isp, int ftype)
! 2578: {
! 2579: fcparam *fcp = FCPARAM(isp);
! 2580: mbreg_t mbs;
! 2581: int i;
! 2582: sns_gid_ft_req_t *rq;
! 2583: sns_gid_ft_rsp_t *rs0, *rs1;
! 2584:
! 2585: if (fcp->isp_onfabric == 0) {
! 2586: fcp->isp_loopstate = LOOP_FSCAN_DONE;
! 2587: return (0);
! 2588: }
! 2589:
! 2590: FC_SCRATCH_ACQUIRE(isp);
! 2591: fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
! 2592:
! 2593: rq = (sns_gid_ft_req_t *)fcp->tport;
! 2594: MEMZERO((void *) rq, SNS_GID_FT_REQ_SIZE);
! 2595: rq->snscb_rblen = GIDLEN >> 1;
! 2596: rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+IGPOFF);
! 2597: rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+IGPOFF);
! 2598: rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+IGPOFF);
! 2599: rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+IGPOFF);
! 2600: rq->snscb_sblen = 6;
! 2601: rq->snscb_cmd = SNS_GID_FT;
! 2602: rq->snscb_mword_div_2 = NGENT;
! 2603: rq->snscb_fc4_type = ftype;
! 2604: isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *) fcp->isp_scratch);
! 2605: MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE);
! 2606: mbs.param[0] = MBOX_SEND_SNS;
! 2607: mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1;
! 2608: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 2609: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 2610:
! 2611: /*
! 2612: * Leave 4 and 5 alone
! 2613: */
! 2614: mbs.param[6] = DMA_WD3(fcp->isp_scdma);
! 2615: mbs.param[7] = DMA_WD2(fcp->isp_scdma);
! 2616: if (isp_fabric_mbox_cmd(isp, &mbs)) {
! 2617: if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
! 2618: fcp->isp_loopstate = LOOP_PDB_RCVD;
! 2619: }
! 2620: FC_SCRATCH_RELEASE(isp);
! 2621: return (-1);
! 2622: }
! 2623: if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
! 2624: FC_SCRATCH_RELEASE(isp);
! 2625: return (-1);
! 2626: }
! 2627: MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN);
! 2628: rs1 = (sns_gid_ft_rsp_t *) fcp->tport;
! 2629: rs0 = (sns_gid_ft_rsp_t *) ((u_int8_t *)fcp->isp_scratch+IGPOFF);
! 2630: isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
! 2631: if (rs1->snscb_cthdr.ct_response != FS_ACC) {
! 2632: int level;
! 2633: if (rs1->snscb_cthdr.ct_reason == 9 &&
! 2634: rs1->snscb_cthdr.ct_explanation == 7)
! 2635: level = ISP_LOGDEBUG0;
! 2636: else
! 2637: level = ISP_LOGWARN;
! 2638: isp_prt(isp, level, swrej, "GID_FT",
! 2639: rs1->snscb_cthdr.ct_reason,
! 2640: rs1->snscb_cthdr.ct_explanation, 0);
! 2641: FC_SCRATCH_RELEASE(isp);
! 2642: fcp->isp_loopstate = LOOP_FSCAN_DONE;
! 2643: return (0);
! 2644: }
! 2645:
! 2646: /*
! 2647: * Okay, we now have a list of Port IDs for this class of device.
! 2648: * Go through the list and for each one get the WWPN/WWNN for it
! 2649: * and tell the outer layers about it. The outer layer needs to
! 2650: * know: Port ID, WWNN, WWPN, FC4 type, and (possibly) port type.
! 2651: *
! 2652: * The lportdb structure is adequate for this.
! 2653: */
! 2654: i = -1;
! 2655: do {
! 2656: sns_gxn_id_req_t grqbuf, *gq = &grqbuf;
! 2657: sns_gxn_id_rsp_t *gs0, grsbuf, *gs1 = &grsbuf;
! 2658: struct lportdb lcl;
! 2659: #if 0
! 2660: sns_gff_id_rsp_t *fs0, ffsbuf, *fs1 = &ffsbuf;
! 2661: #endif
! 2662:
! 2663: i++;
! 2664: MEMZERO(&lcl, sizeof (lcl));
! 2665: lcl.fc4_type = ftype;
! 2666: lcl.portid =
! 2667: (((u_int32_t) rs1->snscb_ports[i].portid[0]) << 16) |
! 2668: (((u_int32_t) rs1->snscb_ports[i].portid[1]) << 8) |
! 2669: (((u_int32_t) rs1->snscb_ports[i].portid[2]));
! 2670:
! 2671: MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
! 2672: gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
! 2673: gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
! 2674: gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
! 2675: gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
! 2676: gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
! 2677: gq->snscb_sblen = 6;
! 2678: gq->snscb_cmd = SNS_GPN_ID;
! 2679: gq->snscb_portid = lcl.portid;
! 2680: isp_put_gxn_id_request(isp, gq,
! 2681: (sns_gxn_id_req_t *) fcp->isp_scratch);
! 2682: MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
! 2683: mbs.param[0] = MBOX_SEND_SNS;
! 2684: mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
! 2685: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 2686: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 2687: /*
! 2688: * Leave 4 and 5 alone
! 2689: */
! 2690: mbs.param[6] = DMA_WD3(fcp->isp_scdma);
! 2691: mbs.param[7] = DMA_WD2(fcp->isp_scdma);
! 2692: if (isp_fabric_mbox_cmd(isp, &mbs)) {
! 2693: if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
! 2694: fcp->isp_loopstate = LOOP_PDB_RCVD;
! 2695: }
! 2696: FC_SCRATCH_RELEASE(isp);
! 2697: return (-1);
! 2698: }
! 2699: if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
! 2700: FC_SCRATCH_RELEASE(isp);
! 2701: return (-1);
! 2702: }
! 2703: MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
! 2704: gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
! 2705: isp_get_gxn_id_response(isp, gs0, gs1);
! 2706: if (gs1->snscb_cthdr.ct_response != FS_ACC) {
! 2707: isp_prt(isp, ISP_LOGWARN, swrej, "GPN_ID",
! 2708: gs1->snscb_cthdr.ct_reason,
! 2709: gs1->snscb_cthdr.ct_explanation, lcl.portid);
! 2710: if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
! 2711: FC_SCRATCH_RELEASE(isp);
! 2712: return (-1);
! 2713: }
! 2714: continue;
! 2715: }
! 2716: lcl.port_wwn =
! 2717: (((u_int64_t)gs1->snscb_wwn[0]) << 56) |
! 2718: (((u_int64_t)gs1->snscb_wwn[1]) << 48) |
! 2719: (((u_int64_t)gs1->snscb_wwn[2]) << 40) |
! 2720: (((u_int64_t)gs1->snscb_wwn[3]) << 32) |
! 2721: (((u_int64_t)gs1->snscb_wwn[4]) << 24) |
! 2722: (((u_int64_t)gs1->snscb_wwn[5]) << 16) |
! 2723: (((u_int64_t)gs1->snscb_wwn[6]) << 8) |
! 2724: (((u_int64_t)gs1->snscb_wwn[7]));
! 2725:
! 2726: MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
! 2727: gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
! 2728: gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
! 2729: gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
! 2730: gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
! 2731: gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
! 2732: gq->snscb_sblen = 6;
! 2733: gq->snscb_cmd = SNS_GNN_ID;
! 2734: gq->snscb_portid = lcl.portid;
! 2735: isp_put_gxn_id_request(isp, gq,
! 2736: (sns_gxn_id_req_t *) fcp->isp_scratch);
! 2737: MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
! 2738: mbs.param[0] = MBOX_SEND_SNS;
! 2739: mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
! 2740: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 2741: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 2742: /*
! 2743: * Leave 4 and 5 alone
! 2744: */
! 2745: mbs.param[6] = DMA_WD3(fcp->isp_scdma);
! 2746: mbs.param[7] = DMA_WD2(fcp->isp_scdma);
! 2747: if (isp_fabric_mbox_cmd(isp, &mbs)) {
! 2748: if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
! 2749: fcp->isp_loopstate = LOOP_PDB_RCVD;
! 2750: }
! 2751: FC_SCRATCH_RELEASE(isp);
! 2752: return (-1);
! 2753: }
! 2754: if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
! 2755: FC_SCRATCH_RELEASE(isp);
! 2756: return (-1);
! 2757: }
! 2758: MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
! 2759: gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
! 2760: isp_get_gxn_id_response(isp, gs0, gs1);
! 2761: if (gs1->snscb_cthdr.ct_response != FS_ACC) {
! 2762: isp_prt(isp, ISP_LOGWARN, swrej, "GNN_ID",
! 2763: gs1->snscb_cthdr.ct_reason,
! 2764: gs1->snscb_cthdr.ct_explanation, lcl.portid);
! 2765: if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
! 2766: FC_SCRATCH_RELEASE(isp);
! 2767: return (-1);
! 2768: }
! 2769: continue;
! 2770: }
! 2771: lcl.node_wwn =
! 2772: (((u_int64_t)gs1->snscb_wwn[0]) << 56) |
! 2773: (((u_int64_t)gs1->snscb_wwn[1]) << 48) |
! 2774: (((u_int64_t)gs1->snscb_wwn[2]) << 40) |
! 2775: (((u_int64_t)gs1->snscb_wwn[3]) << 32) |
! 2776: (((u_int64_t)gs1->snscb_wwn[4]) << 24) |
! 2777: (((u_int64_t)gs1->snscb_wwn[5]) << 16) |
! 2778: (((u_int64_t)gs1->snscb_wwn[6]) << 8) |
! 2779: (((u_int64_t)gs1->snscb_wwn[7]));
! 2780:
! 2781: /*
! 2782: * The QLogic f/w is bouncing this with a parameter error.
! 2783: */
! 2784: #if 0
! 2785: /*
! 2786: * Try and get FC4 Features (FC-GS-3 only).
! 2787: * We can use the sns_gxn_id_req_t for this request.
! 2788: */
! 2789: MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
! 2790: gq->snscb_rblen = SNS_GFF_ID_RESP_SIZE >> 1;
! 2791: gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
! 2792: gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
! 2793: gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
! 2794: gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
! 2795: gq->snscb_sblen = 6;
! 2796: gq->snscb_cmd = SNS_GFF_ID;
! 2797: gq->snscb_portid = lcl.portid;
! 2798: isp_put_gxn_id_request(isp, gq,
! 2799: (sns_gxn_id_req_t *) fcp->isp_scratch);
! 2800: MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
! 2801: mbs.param[0] = MBOX_SEND_SNS;
! 2802: mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
! 2803: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 2804: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 2805: /*
! 2806: * Leave 4 and 5 alone
! 2807: */
! 2808: mbs.param[6] = DMA_WD3(fcp->isp_scdma);
! 2809: mbs.param[7] = DMA_WD2(fcp->isp_scdma);
! 2810: if (isp_fabric_mbox_cmd(isp, &mbs)) {
! 2811: if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
! 2812: fcp->isp_loopstate = LOOP_PDB_RCVD;
! 2813: }
! 2814: FC_SCRATCH_RELEASE(isp);
! 2815: return (-1);
! 2816: }
! 2817: if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
! 2818: FC_SCRATCH_RELEASE(isp);
! 2819: return (-1);
! 2820: }
! 2821: MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GFF_ID_RESP_SIZE);
! 2822: fs0 = (sns_gff_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
! 2823: isp_get_gff_id_response(isp, fs0, fs1);
! 2824: if (fs1->snscb_cthdr.ct_response != FS_ACC) {
! 2825: isp_prt(isp, /* ISP_LOGDEBUG0 */ ISP_LOGWARN,
! 2826: swrej, "GFF_ID",
! 2827: fs1->snscb_cthdr.ct_reason,
! 2828: fs1->snscb_cthdr.ct_explanation, lcl.portid);
! 2829: if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
! 2830: FC_SCRATCH_RELEASE(isp);
! 2831: return (-1);
! 2832: }
! 2833: } else {
! 2834: int index = (ftype >> 3);
! 2835: int bshft = (ftype & 0x7) * 4;
! 2836: int fc4_fval =
! 2837: (fs1->snscb_fc4_features[index] >> bshft) & 0xf;
! 2838: if (fc4_fval & 0x1) {
! 2839: lcl.roles |=
! 2840: (SVC3_INI_ROLE >> SVC3_ROLE_SHIFT);
! 2841: }
! 2842: if (fc4_fval & 0x2) {
! 2843: lcl.roles |=
! 2844: (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
! 2845: }
! 2846: }
! 2847: #endif
! 2848:
! 2849: /*
! 2850: * If we really want to know what kind of port type this is,
! 2851: * we have to run another CT command. Otherwise, we'll leave
! 2852: * it as undefined.
! 2853: *
! 2854: lcl.port_type = 0;
! 2855: */
! 2856: if (rs1->snscb_ports[i].control & 0x80) {
! 2857: lcl.last_fabric_dev = 1;
! 2858: } else {
! 2859: lcl.last_fabric_dev = 0;
! 2860: }
! 2861: (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
! 2862:
! 2863: } while ((rs1->snscb_ports[i].control & 0x80) == 0 && i < NGENT-1);
! 2864:
! 2865: /*
! 2866: * If we're not at the last entry, our list isn't big enough.
! 2867: */
! 2868: if ((rs1->snscb_ports[i].control & 0x80) == 0) {
! 2869: isp_prt(isp, ISP_LOGWARN, "fabric too big for scratch area");
! 2870: }
! 2871:
! 2872: FC_SCRATCH_RELEASE(isp);
! 2873: fcp->isp_loopstate = LOOP_FSCAN_DONE;
! 2874: return (0);
! 2875: }
! 2876: #endif
! 2877:
! 2878: static void
! 2879: isp_register_fc4_type(struct ispsoftc *isp)
! 2880: {
! 2881: fcparam *fcp = isp->isp_param;
! 2882: u_int8_t local[SNS_RFT_ID_REQ_SIZE];
! 2883: sns_screq_t *reqp = (sns_screq_t *) local;
! 2884: mbreg_t mbs;
! 2885:
! 2886: MEMZERO((void *) reqp, SNS_RFT_ID_REQ_SIZE);
! 2887: reqp->snscb_rblen = SNS_RFT_ID_RESP_SIZE >> 1;
! 2888: reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100);
! 2889: reqp->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + 0x100);
! 2890: reqp->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + 0x100);
! 2891: reqp->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + 0x100);
! 2892: reqp->snscb_sblen = 22;
! 2893: reqp->snscb_data[0] = SNS_RFT_ID;
! 2894: reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
! 2895: reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff;
! 2896: reqp->snscb_data[6] = (1 << FC4_SCSI);
! 2897: #if 0
! 2898: reqp->snscb_data[6] |= (1 << FC4_IP); /* ISO/IEC 8802-2 LLC/SNAP */
! 2899: #endif
! 2900: FC_SCRATCH_ACQUIRE(isp);
! 2901: isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch);
! 2902: mbs.param[0] = MBOX_SEND_SNS;
! 2903: mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1;
! 2904: mbs.param[2] = DMA_WD1(fcp->isp_scdma);
! 2905: mbs.param[3] = DMA_WD0(fcp->isp_scdma);
! 2906: /*
! 2907: * Leave 4 and 5 alone
! 2908: */
! 2909: mbs.param[6] = DMA_WD3(fcp->isp_scdma);
! 2910: mbs.param[7] = DMA_WD2(fcp->isp_scdma);
! 2911: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 2912: FC_SCRATCH_RELEASE(isp);
! 2913: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 2914: isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded");
! 2915: }
! 2916: }
! 2917:
! 2918: /*
! 2919: * Start a command. Locking is assumed done in the caller.
! 2920: */
! 2921:
! 2922: int
! 2923: isp_start(XS_T *xs)
! 2924: {
! 2925: struct ispsoftc *isp;
! 2926: u_int16_t nxti, optr, handle;
! 2927: u_int8_t local[QENTRY_LEN];
! 2928: ispreq_t *reqp, *qep;
! 2929: int target, i;
! 2930:
! 2931: XS_INITERR(xs);
! 2932: isp = XS_ISP(xs);
! 2933:
! 2934: /*
! 2935: * Check to make sure we're supporting initiator role.
! 2936: */
! 2937: if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
! 2938: XS_SETERR(xs, HBA_SELTIMEOUT);
! 2939: return (CMD_COMPLETE);
! 2940: }
! 2941:
! 2942: /*
! 2943: * Now make sure we're running.
! 2944: */
! 2945:
! 2946: if (isp->isp_state != ISP_RUNSTATE) {
! 2947: isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
! 2948: XS_SETERR(xs, HBA_BOTCH);
! 2949: return (CMD_COMPLETE);
! 2950: }
! 2951:
! 2952: /*
! 2953: * Check command CDB length, etc.. We really are limited to 16 bytes
! 2954: * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
! 2955: * but probably only if we're running fairly new firmware (we'll
! 2956: * let the old f/w choke on an extended command queue entry).
! 2957: */
! 2958:
! 2959: if (XS_CDBLEN(xs) > (IS_FC(isp)? 16 : 44) || XS_CDBLEN(xs) == 0) {
! 2960: isp_prt(isp, ISP_LOGERR,
! 2961: "unsupported cdb length (%d, CDB[0]=0x%x)",
! 2962: XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
! 2963: XS_SETERR(xs, HBA_BOTCH);
! 2964: return (CMD_COMPLETE);
! 2965: }
! 2966:
! 2967: /*
! 2968: * Check to see whether we have good firmware state still or
! 2969: * need to refresh our port database for this target.
! 2970: */
! 2971: target = XS_TGT(xs);
! 2972: if (IS_FC(isp)) {
! 2973: fcparam *fcp = isp->isp_param;
! 2974: struct lportdb *lp;
! 2975: #ifdef HANDLE_LOOPSTATE_IN_OUTER_LAYERS
! 2976: if (fcp->isp_fwstate != FW_READY ||
! 2977: fcp->isp_loopstate != LOOP_READY) {
! 2978: return (CMD_RQLATER);
! 2979: }
! 2980:
! 2981: /*
! 2982: * If we're not on a Fabric, we can't have a target
! 2983: * above FL_PORT_ID-1.
! 2984: *
! 2985: * If we're on a fabric and *not* connected as an F-port,
! 2986: * we can't have a target less than FC_SNS_ID+1. This
! 2987: * keeps us from having to sort out the difference between
! 2988: * local public loop devices and those which we might get
! 2989: * from a switch's database.
! 2990: */
! 2991: if (fcp->isp_onfabric == 0) {
! 2992: if (target >= FL_PORT_ID) {
! 2993: XS_SETERR(xs, HBA_SELTIMEOUT);
! 2994: return (CMD_COMPLETE);
! 2995: }
! 2996: } else {
! 2997: if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
! 2998: XS_SETERR(xs, HBA_SELTIMEOUT);
! 2999: return (CMD_COMPLETE);
! 3000: }
! 3001: /*
! 3002: * We used to exclude having local loop ports
! 3003: * at the same time that we have fabric ports.
! 3004: * That is, we used to exclude having ports
! 3005: * at < FL_PORT_ID if we're FL-port.
! 3006: *
! 3007: * That's wrong. The only thing that could be
! 3008: * dicey is if the switch you're connected to
! 3009: * has these local loop ports appear on the
! 3010: * fabric and we somehow attach them twice.
! 3011: */
! 3012: }
! 3013: #else
! 3014: /*
! 3015: * Check for f/w being in ready state. If the f/w
! 3016: * isn't in ready state, then we don't know our
! 3017: * loop ID and the f/w hasn't completed logging
! 3018: * into all targets on the loop. If this is the
! 3019: * case, then bounce the command. We pretend this is
! 3020: * a SELECTION TIMEOUT error if we've never gone to
! 3021: * FW_READY state at all- in this case we may not
! 3022: * be hooked to a loop at all and we shouldn't hang
! 3023: * the machine for this. Otherwise, defer this command
! 3024: * until later.
! 3025: */
! 3026: if (fcp->isp_fwstate != FW_READY) {
! 3027: /*
! 3028: * Give ourselves at most a 250ms delay.
! 3029: */
! 3030: if (isp_fclink_test(isp, 250000)) {
! 3031: XS_SETERR(xs, HBA_SELTIMEOUT);
! 3032: if (fcp->loop_seen_once) {
! 3033: return (CMD_RQLATER);
! 3034: } else {
! 3035: return (CMD_COMPLETE);
! 3036: }
! 3037: }
! 3038: }
! 3039:
! 3040: /*
! 3041: * If we're not on a Fabric, we can't have a target
! 3042: * above FL_PORT_ID-1.
! 3043: *
! 3044: * If we're on a fabric and *not* connected as an F-port,
! 3045: * we can't have a target less than FC_SNS_ID+1. This
! 3046: * keeps us from having to sort out the difference between
! 3047: * local public loop devices and those which we might get
! 3048: * from a switch's database.
! 3049: */
! 3050: if (fcp->isp_onfabric == 0) {
! 3051: if (target >= FL_PORT_ID) {
! 3052: XS_SETERR(xs, HBA_SELTIMEOUT);
! 3053: return (CMD_COMPLETE);
! 3054: }
! 3055: } else {
! 3056: if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
! 3057: XS_SETERR(xs, HBA_SELTIMEOUT);
! 3058: return (CMD_COMPLETE);
! 3059: }
! 3060: if (fcp->isp_topo != TOPO_F_PORT &&
! 3061: target < FL_PORT_ID) {
! 3062: XS_SETERR(xs, HBA_SELTIMEOUT);
! 3063: return (CMD_COMPLETE);
! 3064: }
! 3065: }
! 3066:
! 3067: /*
! 3068: * If our loop state is such that we haven't yet received
! 3069: * a "Port Database Changed" notification (after a LIP or
! 3070: * a Loop Reset or firmware initialization), then defer
! 3071: * sending commands for a little while, but only if we've
! 3072: * seen a valid loop at one point (otherwise we can get
! 3073: * stuck at initialization time).
! 3074: */
! 3075: if (fcp->isp_loopstate < LOOP_PDB_RCVD) {
! 3076: XS_SETERR(xs, HBA_SELTIMEOUT);
! 3077: if (fcp->loop_seen_once) {
! 3078: return (CMD_RQLATER);
! 3079: } else {
! 3080: return (CMD_COMPLETE);
! 3081: }
! 3082: }
! 3083:
! 3084: /*
! 3085: * If we're in the middle of loop or fabric scanning
! 3086: * or merging the port databases, retry this command later.
! 3087: */
! 3088: if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC ||
! 3089: fcp->isp_loopstate == LOOP_SCANNING_LOOP ||
! 3090: fcp->isp_loopstate == LOOP_SYNCING_PDB) {
! 3091: return (CMD_RQLATER);
! 3092: }
! 3093:
! 3094: /*
! 3095: * If our loop state is now such that we've just now
! 3096: * received a Port Database Change notification, then
! 3097: * we have to go off and (re)scan the fabric. We back
! 3098: * out and try again later if this doesn't work.
! 3099: */
! 3100: if (fcp->isp_loopstate == LOOP_PDB_RCVD && fcp->isp_onfabric) {
! 3101: if (isp_scan_fabric(isp, FC4_SCSI)) {
! 3102: return (CMD_RQLATER);
! 3103: }
! 3104: if (fcp->isp_fwstate != FW_READY ||
! 3105: fcp->isp_loopstate < LOOP_FSCAN_DONE) {
! 3106: return (CMD_RQLATER);
! 3107: }
! 3108: }
! 3109:
! 3110: /*
! 3111: * If our loop state is now such that we've just now
! 3112: * received a Port Database Change notification, then
! 3113: * we have to go off and (re)synchronize our port
! 3114: * database.
! 3115: */
! 3116: if (fcp->isp_loopstate < LOOP_READY) {
! 3117: if (isp_pdb_sync(isp)) {
! 3118: return (CMD_RQLATER);
! 3119: }
! 3120: if (fcp->isp_fwstate != FW_READY ||
! 3121: fcp->isp_loopstate != LOOP_READY) {
! 3122: return (CMD_RQLATER);
! 3123: }
! 3124: }
! 3125:
! 3126: /*
! 3127: * XXX: Here's were we would cancel any loop_dead flag
! 3128: * XXX: also cancel in dead_loop timeout that's running
! 3129: */
! 3130: #endif
! 3131:
! 3132: /*
! 3133: * Now check whether we should even think about pursuing this.
! 3134: */
! 3135: lp = &fcp->portdb[target];
! 3136: if (lp->valid == 0) {
! 3137: XS_SETERR(xs, HBA_SELTIMEOUT);
! 3138: return (CMD_COMPLETE);
! 3139: }
! 3140: if ((lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT)) == 0) {
! 3141: isp_prt(isp, ISP_LOGDEBUG2,
! 3142: "Target %d does not have target service", target);
! 3143: XS_SETERR(xs, HBA_SELTIMEOUT);
! 3144: return (CMD_COMPLETE);
! 3145: }
! 3146: /*
! 3147: * Now turn target into what the actual Loop ID is.
! 3148: */
! 3149: target = lp->loopid;
! 3150: xs->sc_link->node_wwn = lp->node_wwn;
! 3151: xs->sc_link->port_wwn = lp->port_wwn;
! 3152:
! 3153: }
! 3154:
! 3155: /*
! 3156: * Next check to see if any HBA or Device
! 3157: * parameters need to be updated.
! 3158: */
! 3159: if (isp->isp_update != 0) {
! 3160: isp_update(isp);
! 3161: }
! 3162:
! 3163: if (isp_getrqentry(isp, &nxti, &optr, (void *)&qep)) {
! 3164: isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow");
! 3165: XS_SETERR(xs, HBA_BOTCH);
! 3166: return (CMD_EAGAIN);
! 3167: }
! 3168:
! 3169: /*
! 3170: * Now see if we need to synchronize the ISP with respect to anything.
! 3171: * We do dual duty here (cough) for synchronizing for busses other
! 3172: * than which we got here to send a command to.
! 3173: */
! 3174: reqp = (ispreq_t *) local;
! 3175: if (isp->isp_sendmarker) {
! 3176: u_int8_t n = (IS_DUALBUS(isp)? 2: 1);
! 3177: /*
! 3178: * Check ports to send markers for...
! 3179: */
! 3180: for (i = 0; i < n; i++) {
! 3181: if ((isp->isp_sendmarker & (1 << i)) == 0) {
! 3182: continue;
! 3183: }
! 3184: MEMZERO((void *) reqp, QENTRY_LEN);
! 3185: reqp->req_header.rqs_entry_count = 1;
! 3186: reqp->req_header.rqs_entry_type = RQSTYPE_MARKER;
! 3187: reqp->req_modifier = SYNC_ALL;
! 3188: reqp->req_target = i << 7; /* insert bus number */
! 3189: isp_put_request(isp, reqp, qep);
! 3190: ISP_ADD_REQUEST(isp, nxti);
! 3191: isp->isp_sendmarker &= ~(1 << i);
! 3192: if (isp_getrqentry(isp, &nxti, &optr, (void *) &qep)) {
! 3193: isp_prt(isp, ISP_LOGDEBUG0,
! 3194: "Request Queue Overflow+");
! 3195: XS_SETERR(xs, HBA_BOTCH);
! 3196: return (CMD_EAGAIN);
! 3197: }
! 3198: }
! 3199: }
! 3200:
! 3201: MEMZERO((void *)reqp, QENTRY_LEN);
! 3202: reqp->req_header.rqs_entry_count = 1;
! 3203: if (IS_FC(isp)) {
! 3204: reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
! 3205: } else {
! 3206: if (XS_CDBLEN(xs) > 12)
! 3207: reqp->req_header.rqs_entry_type = RQSTYPE_CMDONLY;
! 3208: else
! 3209: reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST;
! 3210: }
! 3211: /* reqp->req_header.rqs_flags = 0; */
! 3212: /* reqp->req_header.rqs_seqno = 0; */
! 3213: if (IS_FC(isp)) {
! 3214: /*
! 3215: * See comment in isp_intr
! 3216: */
! 3217: /* XS_RESID(xs) = 0; */
! 3218:
! 3219: /*
! 3220: * Fibre Channel always requires some kind of tag.
! 3221: * The Qlogic drivers seem be happy not to use a tag,
! 3222: * but this breaks for some devices (IBM drives).
! 3223: */
! 3224: if (XS_TAG_P(xs)) {
! 3225: ((ispreqt2_t *)reqp)->req_flags = XS_TAG_TYPE(xs);
! 3226: } else {
! 3227: /*
! 3228: * If we don't know what tag to use, use HEAD OF QUEUE
! 3229: * for Request Sense or Simple.
! 3230: */
! 3231: if (XS_CDBP(xs)[0] == 0x3) /* REQUEST SENSE */
! 3232: ((ispreqt2_t *)reqp)->req_flags = REQFLAG_HTAG;
! 3233: else
! 3234: ((ispreqt2_t *)reqp)->req_flags = REQFLAG_STAG;
! 3235: }
! 3236: } else {
! 3237: sdparam *sdp = (sdparam *)isp->isp_param;
! 3238: sdp += XS_CHANNEL(xs);
! 3239: if ((sdp->isp_devparam[target].actv_flags & DPARM_TQING) &&
! 3240: XS_TAG_P(xs)) {
! 3241: reqp->req_flags = XS_TAG_TYPE(xs);
! 3242: }
! 3243: }
! 3244: reqp->req_target = target | (XS_CHANNEL(xs) << 7);
! 3245: if (IS_SCSI(isp)) {
! 3246: reqp->req_lun_trn = XS_LUN(xs);
! 3247: reqp->req_cdblen = XS_CDBLEN(xs);
! 3248: } else {
! 3249: if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)
! 3250: ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs);
! 3251: else
! 3252: ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs);
! 3253: }
! 3254: MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs));
! 3255:
! 3256: reqp->req_time = XS_TIME(xs) / 1000;
! 3257: if (reqp->req_time == 0 && XS_TIME(xs)) {
! 3258: reqp->req_time = 1;
! 3259: }
! 3260:
! 3261: if (isp_save_xs(isp, xs, &handle)) {
! 3262: isp_prt(isp, ISP_LOGDEBUG0, "out of xflist pointers");
! 3263: XS_SETERR(xs, HBA_BOTCH);
! 3264: return (CMD_EAGAIN);
! 3265: }
! 3266: reqp->req_handle = handle;
! 3267:
! 3268: /*
! 3269: * Set up DMA and/or do any bus swizzling of the request entry
! 3270: * so that the Qlogic F/W understands what is being asked of it.
! 3271: */
! 3272: i = ISP_DMASETUP(isp, xs, reqp, &nxti, optr);
! 3273: if (i != CMD_QUEUED) {
! 3274: isp_destroy_handle(isp, handle);
! 3275: /*
! 3276: * dmasetup sets actual error in packet, and
! 3277: * return what we were given to return.
! 3278: */
! 3279: return (i);
! 3280: }
! 3281: XS_SETERR(xs, HBA_NOERROR);
! 3282: isp_prt(isp, ISP_LOGDEBUG2,
! 3283: "START cmd for %d.%d.%d cmd 0x%x datalen %ld",
! 3284: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0],
! 3285: (long) XS_XFRLEN(xs));
! 3286: ISP_ADD_REQUEST(isp, nxti);
! 3287: isp->isp_nactive++;
! 3288: return (CMD_QUEUED);
! 3289: }
! 3290:
! 3291: /*
! 3292: * isp control
! 3293: * Locks (ints blocked) assumed held.
! 3294: */
! 3295:
! 3296: int
! 3297: isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg)
! 3298: {
! 3299: XS_T *xs;
! 3300: mbreg_t mbs;
! 3301: int bus, tgt;
! 3302: u_int16_t handle;
! 3303:
! 3304: switch (ctl) {
! 3305: default:
! 3306: isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
! 3307: break;
! 3308:
! 3309: case ISPCTL_RESET_BUS:
! 3310: /*
! 3311: * Issue a bus reset.
! 3312: */
! 3313: mbs.param[0] = MBOX_BUS_RESET;
! 3314: mbs.param[2] = 0;
! 3315: if (IS_SCSI(isp)) {
! 3316: mbs.param[1] =
! 3317: ((sdparam *) isp->isp_param)->isp_bus_reset_delay;
! 3318: if (mbs.param[1] < 2)
! 3319: mbs.param[1] = 2;
! 3320: bus = *((int *) arg);
! 3321: if (IS_DUALBUS(isp))
! 3322: mbs.param[2] = bus;
! 3323: } else {
! 3324: mbs.param[1] = 10;
! 3325: bus = 0;
! 3326: }
! 3327: isp->isp_sendmarker |= (1 << bus);
! 3328: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 3329: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 3330: break;
! 3331: }
! 3332: isp_prt(isp, ISP_LOGINFO,
! 3333: "driver initiated bus reset of bus %d", bus);
! 3334: return (0);
! 3335:
! 3336: case ISPCTL_RESET_DEV:
! 3337: tgt = (*((int *) arg)) & 0xffff;
! 3338: bus = (*((int *) arg)) >> 16;
! 3339: mbs.param[0] = MBOX_ABORT_TARGET;
! 3340: mbs.param[1] = (tgt << 8) | (bus << 15);
! 3341: mbs.param[2] = 3; /* 'delay', in seconds */
! 3342: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 3343: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 3344: break;
! 3345: }
! 3346: isp_prt(isp, ISP_LOGINFO,
! 3347: "Target %d on Bus %d Reset Succeeded", tgt, bus);
! 3348: isp->isp_sendmarker |= (1 << bus);
! 3349: return (0);
! 3350:
! 3351: case ISPCTL_ABORT_CMD:
! 3352: xs = (XS_T *) arg;
! 3353: tgt = XS_TGT(xs);
! 3354: handle = isp_find_handle(isp, xs);
! 3355: if (handle == 0) {
! 3356: isp_prt(isp, ISP_LOGWARN,
! 3357: "cannot find handle for command to abort");
! 3358: break;
! 3359: }
! 3360: bus = XS_CHANNEL(xs);
! 3361: mbs.param[0] = MBOX_ABORT;
! 3362: if (IS_FC(isp)) {
! 3363: if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
! 3364: mbs.param[1] = tgt << 8;
! 3365: mbs.param[4] = 0;
! 3366: mbs.param[5] = 0;
! 3367: mbs.param[6] = XS_LUN(xs);
! 3368: } else {
! 3369: mbs.param[1] = tgt << 8 | XS_LUN(xs);
! 3370: }
! 3371: } else {
! 3372: mbs.param[1] =
! 3373: (bus << 15) | (XS_TGT(xs) << 8) | XS_LUN(xs);
! 3374: }
! 3375: mbs.param[3] = 0;
! 3376: mbs.param[2] = handle;
! 3377: isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_ERROR);
! 3378: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 3379: return (0);
! 3380: }
! 3381: /*
! 3382: * XXX: Look for command in the REQUEST QUEUE. That is,
! 3383: * XXX: It hasn't been picked up by firmware yet.
! 3384: */
! 3385: break;
! 3386:
! 3387: case ISPCTL_UPDATE_PARAMS:
! 3388:
! 3389: isp_update(isp);
! 3390: return (0);
! 3391:
! 3392: case ISPCTL_FCLINK_TEST:
! 3393:
! 3394: if (IS_FC(isp)) {
! 3395: int usdelay = (arg)? *((int *) arg) : 250000;
! 3396: return (isp_fclink_test(isp, usdelay));
! 3397: }
! 3398: break;
! 3399:
! 3400: case ISPCTL_SCAN_FABRIC:
! 3401:
! 3402: if (IS_FC(isp)) {
! 3403: int ftype = (arg)? *((int *) arg) : FC4_SCSI;
! 3404: return (isp_scan_fabric(isp, ftype));
! 3405: }
! 3406: break;
! 3407:
! 3408: case ISPCTL_SCAN_LOOP:
! 3409:
! 3410: if (IS_FC(isp)) {
! 3411: return (isp_scan_loop(isp));
! 3412: }
! 3413: break;
! 3414:
! 3415: case ISPCTL_PDB_SYNC:
! 3416:
! 3417: if (IS_FC(isp)) {
! 3418: return (isp_pdb_sync(isp));
! 3419: }
! 3420: break;
! 3421:
! 3422: case ISPCTL_SEND_LIP:
! 3423:
! 3424: if (IS_FC(isp)) {
! 3425: mbs.param[0] = MBOX_INIT_LIP;
! 3426: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 3427: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 3428: return (0);
! 3429: }
! 3430: }
! 3431: break;
! 3432:
! 3433: case ISPCTL_GET_POSMAP:
! 3434:
! 3435: if (IS_FC(isp) && arg) {
! 3436: return (isp_getmap(isp, arg));
! 3437: }
! 3438: break;
! 3439:
! 3440: case ISPCTL_RUN_MBOXCMD:
! 3441:
! 3442: isp_mboxcmd(isp, arg, MBLOGALL);
! 3443: return(0);
! 3444:
! 3445: #ifdef ISP_TARGET_MODE
! 3446: case ISPCTL_TOGGLE_TMODE:
! 3447: {
! 3448:
! 3449: /*
! 3450: * We don't check/set against role here- that's the
! 3451: * responsibility for the outer layer to coordinate.
! 3452: */
! 3453: if (IS_SCSI(isp)) {
! 3454: int param = *(int *)arg;
! 3455: mbs.param[0] = MBOX_ENABLE_TARGET_MODE;
! 3456: mbs.param[1] = param & 0xffff;
! 3457: mbs.param[2] = param >> 16;
! 3458: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 3459: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 3460: break;
! 3461: }
! 3462: }
! 3463: return (0);
! 3464: }
! 3465: #endif
! 3466: }
! 3467: return (-1);
! 3468: }
! 3469:
! 3470: /*
! 3471: * Interrupt Service Routine(s).
! 3472: *
! 3473: * External (OS) framework has done the appropriate locking,
! 3474: * and the locking will be held throughout this function.
! 3475: */
! 3476:
! 3477: /*
! 3478: * Limit our stack depth by sticking with the max likely number
! 3479: * of completions on a request queue at any one time.
! 3480: */
! 3481: #ifndef MAX_REQUESTQ_COMPLETIONS
! 3482: #define MAX_REQUESTQ_COMPLETIONS 64
! 3483: #endif
! 3484:
! 3485: void
! 3486: isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
! 3487: {
! 3488: XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs;
! 3489: u_int16_t iptr, optr, junk;
! 3490: int i, nlooked = 0, ndone = 0;
! 3491:
! 3492: again:
! 3493: /*
! 3494: * Is this a mailbox related interrupt?
! 3495: * The mailbox semaphore will be nonzero if so.
! 3496: */
! 3497: if (sema) {
! 3498: if (mbox & 0x4000) {
! 3499: isp->isp_intmboxc++;
! 3500: if (isp->isp_mboxbsy) {
! 3501: int i = 0, obits = isp->isp_obits;
! 3502: isp->isp_mboxtmp[i++] = mbox;
! 3503: for (i = 1; i < MAX_MAILBOX; i++) {
! 3504: if ((obits & (1 << i)) == 0) {
! 3505: continue;
! 3506: }
! 3507: isp->isp_mboxtmp[i] =
! 3508: ISP_READ(isp, MBOX_OFF(i));
! 3509: }
! 3510: if (isp->isp_mbxwrk0) {
! 3511: if (isp_mbox_continue(isp) == 0) {
! 3512: return;
! 3513: }
! 3514: }
! 3515: MBOX_NOTIFY_COMPLETE(isp);
! 3516: } else {
! 3517: isp_prt(isp, ISP_LOGWARN,
! 3518: "Mbox Command Async (0x%x) with no waiters",
! 3519: mbox);
! 3520: }
! 3521: } else if (isp_parse_async(isp, mbox) < 0) {
! 3522: return;
! 3523: }
! 3524: if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) ||
! 3525: isp->isp_state != ISP_RUNSTATE) {
! 3526: ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
! 3527: ISP_WRITE(isp, BIU_SEMA, 0);
! 3528: return;
! 3529: }
! 3530: }
! 3531:
! 3532: /*
! 3533: * We can't be getting this now.
! 3534: */
! 3535: if (isp->isp_state != ISP_RUNSTATE) {
! 3536: isp_prt(isp, ISP_LOGWARN,
! 3537: "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema);
! 3538: /*
! 3539: * Thank you very much! *Burrrp*!
! 3540: */
! 3541: WRITE_RESPONSE_QUEUE_OUT_POINTER(isp,
! 3542: READ_RESPONSE_QUEUE_IN_POINTER(isp));
! 3543:
! 3544: ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
! 3545: ISP_WRITE(isp, BIU_SEMA, 0);
! 3546: return;
! 3547: }
! 3548:
! 3549: /*
! 3550: * Get the current Response Queue Out Pointer.
! 3551: *
! 3552: * If we're a 2300, we can ask what hardware what it thinks.
! 3553: */
! 3554: if (IS_23XX(isp)) {
! 3555: optr = ISP_READ(isp, isp->isp_respoutrp);
! 3556: /*
! 3557: * Debug: to be taken out eventually
! 3558: */
! 3559: if (isp->isp_residx != optr) {
! 3560: isp_prt(isp, ISP_LOGWARN, "optr %x soft optr %x",
! 3561: optr, isp->isp_residx);
! 3562: }
! 3563: } else {
! 3564: optr = isp->isp_residx;
! 3565: }
! 3566:
! 3567: /*
! 3568: * You *must* read the Response Queue In Pointer
! 3569: * prior to clearing the RISC interrupt.
! 3570: *
! 3571: * Debounce the 2300 if revision less than 2.
! 3572: */
! 3573: if (IS_2100(isp) || (IS_2300(isp) && isp->isp_revision < 2)) {
! 3574: i = 0;
! 3575: do {
! 3576: iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
! 3577: junk = READ_RESPONSE_QUEUE_IN_POINTER(isp);
! 3578: } while (junk != iptr && ++i < 1000);
! 3579:
! 3580: if (iptr != junk) {
! 3581: ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
! 3582: isp_prt(isp, ISP_LOGWARN,
! 3583: "Response Queue Out Pointer Unstable (%x, %x)",
! 3584: iptr, junk);
! 3585: return;
! 3586: }
! 3587: } else {
! 3588: iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
! 3589: }
! 3590: isp->isp_resodx = iptr;
! 3591:
! 3592:
! 3593: if (optr == iptr && sema == 0) {
! 3594: /*
! 3595: * There are a lot of these- reasons unknown- mostly on
! 3596: * faster Alpha machines.
! 3597: *
! 3598: * I tried delaying after writing HCCR_CMD_CLEAR_RISC_INT to
! 3599: * make sure the old interrupt went away (to avoid 'ringing'
! 3600: * effects), but that didn't stop this from occurring.
! 3601: */
! 3602: if (IS_23XX(isp)) {
! 3603: USEC_DELAY(100);
! 3604: iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
! 3605: junk = ISP_READ(isp, BIU_R2HSTSLO);
! 3606: } else {
! 3607: junk = ISP_READ(isp, BIU_ISR);
! 3608: }
! 3609: if (optr == iptr) {
! 3610: if (IS_23XX(isp)) {
! 3611: ;
! 3612: } else {
! 3613: sema = ISP_READ(isp, BIU_SEMA);
! 3614: mbox = ISP_READ(isp, OUTMAILBOX0);
! 3615: if ((sema & 0x3) && (mbox & 0x8000)) {
! 3616: goto again;
! 3617: }
! 3618: }
! 3619: isp->isp_intbogus++;
! 3620: isp_prt(isp, ISP_LOGDEBUG1,
! 3621: "bogus intr- isr %x (%x) iptr %x optr %x",
! 3622: isr, junk, iptr, optr);
! 3623: }
! 3624: }
! 3625: isp->isp_resodx = iptr;
! 3626: ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
! 3627: ISP_WRITE(isp, BIU_SEMA, 0);
! 3628:
! 3629: if (isp->isp_rspbsy) {
! 3630: return;
! 3631: }
! 3632: isp->isp_rspbsy = 1;
! 3633:
! 3634: while (optr != iptr) {
! 3635: ispstatusreq_t local, *sp = &local;
! 3636: isphdr_t *hp;
! 3637: int type;
! 3638: u_int16_t oop;
! 3639: int buddaboom = 0;
! 3640:
! 3641: hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr);
! 3642: oop = optr;
! 3643: optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
! 3644: nlooked++;
! 3645: /*
! 3646: * Synchronize our view of this response queue entry.
! 3647: */
! 3648: MEMORYBARRIER(isp, SYNC_RESULT, oop, QENTRY_LEN);
! 3649:
! 3650: type = isp_get_response_type(isp, hp);
! 3651:
! 3652: if (type == RQSTYPE_RESPONSE) {
! 3653: isp_get_response(isp, (ispstatusreq_t *) hp, sp);
! 3654: } else if (type == RQSTYPE_RIO2) {
! 3655: isp_rio2_t rio;
! 3656: isp_get_rio2(isp, (isp_rio2_t *) hp, &rio);
! 3657: for (i = 0; i < rio.req_header.rqs_seqno; i++) {
! 3658: isp_fastpost_complete(isp, rio.req_handles[i]);
! 3659: }
! 3660: if (isp->isp_fpcchiwater < rio.req_header.rqs_seqno)
! 3661: isp->isp_fpcchiwater = rio.req_header.rqs_seqno;
! 3662: MEMZERO(hp, QENTRY_LEN); /* PERF */
! 3663: continue;
! 3664: } else {
! 3665: /*
! 3666: * Somebody reachable via isp_handle_other_response
! 3667: * may have updated the response queue pointers for
! 3668: * us, so we reload our goal index.
! 3669: */
! 3670: if (isp_handle_other_response(isp, type, hp, &optr)) {
! 3671: iptr = isp->isp_resodx;
! 3672: MEMZERO(hp, QENTRY_LEN); /* PERF */
! 3673: continue;
! 3674: }
! 3675:
! 3676: /*
! 3677: * After this point, we'll just look at the header as
! 3678: * we don't know how to deal with the rest of the
! 3679: * response.
! 3680: */
! 3681: isp_get_response(isp, (ispstatusreq_t *) hp, sp);
! 3682:
! 3683: /*
! 3684: * It really has to be a bounced request just copied
! 3685: * from the request queue to the response queue. If
! 3686: * not, something bad has happened.
! 3687: */
! 3688: if (sp->req_header.rqs_entry_type != RQSTYPE_REQUEST) {
! 3689: isp_prt(isp, ISP_LOGERR, notresp,
! 3690: sp->req_header.rqs_entry_type, oop, optr,
! 3691: nlooked);
! 3692: if (isp->isp_dblev & ISP_LOGDEBUG0) {
! 3693: isp_print_bytes(isp, "Queue Entry",
! 3694: QENTRY_LEN, sp);
! 3695: }
! 3696: MEMZERO(hp, QENTRY_LEN); /* PERF */
! 3697: continue;
! 3698: }
! 3699: buddaboom = 1;
! 3700: }
! 3701:
! 3702: if (sp->req_header.rqs_flags & 0xf) {
! 3703: #define _RQS_OFLAGS \
! 3704: ~(RQSFLAG_CONTINUATION|RQSFLAG_FULL|RQSFLAG_BADHEADER|RQSFLAG_BADPACKET)
! 3705: if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {
! 3706: isp_prt(isp, ISP_LOGWARN,
! 3707: "continuation segment");
! 3708: WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
! 3709: continue;
! 3710: }
! 3711: if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
! 3712: isp_prt(isp, ISP_LOGDEBUG1,
! 3713: "internal queues full");
! 3714: /*
! 3715: * We'll synthesize a QUEUE FULL message below.
! 3716: */
! 3717: }
! 3718: if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) {
! 3719: isp_prt(isp, ISP_LOGERR, "bad header flag");
! 3720: buddaboom++;
! 3721: }
! 3722: if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) {
! 3723: isp_prt(isp, ISP_LOGERR, "bad request packet");
! 3724: buddaboom++;
! 3725: }
! 3726: if (sp->req_header.rqs_flags & _RQS_OFLAGS) {
! 3727: isp_prt(isp, ISP_LOGERR,
! 3728: "unknown flags (0x%x) in response",
! 3729: sp->req_header.rqs_flags);
! 3730: buddaboom++;
! 3731: }
! 3732: #undef _RQS_OFLAGS
! 3733: }
! 3734: if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) {
! 3735: MEMZERO(hp, QENTRY_LEN); /* PERF */
! 3736: isp_prt(isp, ISP_LOGERR,
! 3737: "bad request handle %d (type 0x%x, flags 0x%x)",
! 3738: sp->req_handle, sp->req_header.rqs_entry_type,
! 3739: sp->req_header.rqs_flags);
! 3740: WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
! 3741: continue;
! 3742: }
! 3743: xs = isp_find_xs(isp, sp->req_handle);
! 3744: if (xs == NULL) {
! 3745: u_int8_t ts = sp->req_completion_status & 0xff;
! 3746: MEMZERO(hp, QENTRY_LEN); /* PERF */
! 3747: /*
! 3748: * Only whine if this isn't the expected fallout of
! 3749: * aborting the command.
! 3750: */
! 3751: if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) {
! 3752: isp_prt(isp, ISP_LOGERR,
! 3753: "cannot find handle 0x%x (type 0x%x)",
! 3754: sp->req_handle,
! 3755: sp->req_header.rqs_entry_type);
! 3756: } else if (ts != RQCS_ABORTED) {
! 3757: isp_prt(isp, ISP_LOGERR,
! 3758: "cannot find handle 0x%x (status 0x%x)",
! 3759: sp->req_handle, ts);
! 3760: }
! 3761: WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
! 3762: continue;
! 3763: }
! 3764: isp_destroy_handle(isp, sp->req_handle);
! 3765: if (sp->req_status_flags & RQSTF_BUS_RESET) {
! 3766: XS_SETERR(xs, HBA_BUSRESET);
! 3767: isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
! 3768: }
! 3769: if (buddaboom) {
! 3770: XS_SETERR(xs, HBA_BOTCH);
! 3771: }
! 3772:
! 3773: if (IS_FC(isp) && (sp->req_scsi_status & RQCS_SV)) {
! 3774: /*
! 3775: * Fibre Channel F/W doesn't say we got status
! 3776: * if there's Sense Data instead. I guess they
! 3777: * think it goes w/o saying.
! 3778: */
! 3779: sp->req_state_flags |= RQSF_GOT_STATUS;
! 3780: }
! 3781: if (sp->req_state_flags & RQSF_GOT_STATUS) {
! 3782: *XS_STSP(xs) = sp->req_scsi_status & 0xff;
! 3783: }
! 3784:
! 3785: switch (sp->req_header.rqs_entry_type) {
! 3786: case RQSTYPE_RESPONSE:
! 3787: XS_SET_STATE_STAT(isp, xs, sp);
! 3788: isp_parse_status(isp, sp, xs);
! 3789: if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) &&
! 3790: (*XS_STSP(xs) == SCSI_BUSY)) {
! 3791: XS_SETERR(xs, HBA_TGTBSY);
! 3792: }
! 3793: if (IS_SCSI(isp)) {
! 3794: XS_RESID(xs) = sp->req_resid;
! 3795: if ((sp->req_state_flags & RQSF_GOT_STATUS) &&
! 3796: (*XS_STSP(xs) == SCSI_CHECK) &&
! 3797: (sp->req_state_flags & RQSF_GOT_SENSE)) {
! 3798: XS_SAVE_SENSE(xs, sp);
! 3799: }
! 3800: /*
! 3801: * A new synchronous rate was negotiated for
! 3802: * this target. Mark state such that we'll go
! 3803: * look up that which has changed later.
! 3804: */
! 3805: if (sp->req_status_flags & RQSTF_NEGOTIATION) {
! 3806: int t = XS_TGT(xs);
! 3807: sdparam *sdp = isp->isp_param;
! 3808: sdp += XS_CHANNEL(xs);
! 3809: sdp->isp_devparam[t].dev_refresh = 1;
! 3810: isp->isp_update |=
! 3811: (1 << XS_CHANNEL(xs));
! 3812: }
! 3813: } else {
! 3814: if (sp->req_status_flags & RQSF_XFER_COMPLETE) {
! 3815: XS_RESID(xs) = 0;
! 3816: } else if (sp->req_scsi_status & RQCS_RESID) {
! 3817: XS_RESID(xs) = sp->req_resid;
! 3818: } else {
! 3819: XS_RESID(xs) = 0;
! 3820: }
! 3821: if ((sp->req_state_flags & RQSF_GOT_STATUS) &&
! 3822: (*XS_STSP(xs) == SCSI_CHECK) &&
! 3823: (sp->req_scsi_status & RQCS_SV)) {
! 3824: XS_SAVE_SENSE(xs, sp);
! 3825: /* solely for the benefit of debug */
! 3826: sp->req_state_flags |= RQSF_GOT_SENSE;
! 3827: }
! 3828: }
! 3829: isp_prt(isp, ISP_LOGDEBUG2,
! 3830: "asked for %ld got resid %ld", (long) XS_XFRLEN(xs),
! 3831: (long) sp->req_resid);
! 3832: break;
! 3833: case RQSTYPE_REQUEST:
! 3834: if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
! 3835: /*
! 3836: * Force Queue Full status.
! 3837: */
! 3838: *XS_STSP(xs) = SCSI_QFULL;
! 3839: XS_SETERR(xs, HBA_NOERROR);
! 3840: } else if (XS_NOERR(xs)) {
! 3841: /*
! 3842: * ????
! 3843: */
! 3844: isp_prt(isp, ISP_LOGDEBUG0,
! 3845: "Request Queue Entry bounced back");
! 3846: XS_SETERR(xs, HBA_BOTCH);
! 3847: }
! 3848: XS_RESID(xs) = XS_XFRLEN(xs);
! 3849: break;
! 3850: default:
! 3851: isp_prt(isp, ISP_LOGWARN,
! 3852: "unhandled response queue type 0x%x",
! 3853: sp->req_header.rqs_entry_type);
! 3854: if (XS_NOERR(xs)) {
! 3855: XS_SETERR(xs, HBA_BOTCH);
! 3856: }
! 3857: break;
! 3858: }
! 3859:
! 3860: /*
! 3861: * Free any dma resources. As a side effect, this may
! 3862: * also do any cache flushing necessary for data coherence. */
! 3863: if (XS_XFRLEN(xs)) {
! 3864: ISP_DMAFREE(isp, xs, sp->req_handle);
! 3865: }
! 3866:
! 3867: if (((isp->isp_dblev & (ISP_LOGDEBUG2|ISP_LOGDEBUG3))) ||
! 3868: ((isp->isp_dblev & ISP_LOGDEBUG1) && ((!XS_NOERR(xs)) ||
! 3869: (*XS_STSP(xs) != SCSI_GOOD)))) {
! 3870: char skey;
! 3871: if (sp->req_state_flags & RQSF_GOT_SENSE) {
! 3872: skey = XS_SNSKEY(xs) & 0xf;
! 3873: if (skey < 10)
! 3874: skey += '0';
! 3875: else
! 3876: skey += 'a' - 10;
! 3877: } else if (*XS_STSP(xs) == SCSI_CHECK) {
! 3878: skey = '?';
! 3879: } else {
! 3880: skey = '.';
! 3881: }
! 3882: isp_prt(isp, ISP_LOGALL, finmsg, XS_CHANNEL(xs),
! 3883: XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs),
! 3884: (ulong)XS_RESID(xs),
! 3885: *XS_STSP(xs), skey, XS_ERR(xs));
! 3886: }
! 3887:
! 3888: if (isp->isp_nactive > 0)
! 3889: isp->isp_nactive--;
! 3890: complist[ndone++] = xs; /* defer completion call until later */
! 3891: MEMZERO(hp, QENTRY_LEN); /* PERF */
! 3892: if (ndone == MAX_REQUESTQ_COMPLETIONS) {
! 3893: break;
! 3894: }
! 3895: }
! 3896:
! 3897: /*
! 3898: * If we looked at any commands, then it's valid to find out
! 3899: * what the outpointer is. It also is a trigger to update the
! 3900: * ISP's notion of what we've seen so far.
! 3901: */
! 3902: if (nlooked) {
! 3903: WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
! 3904: /*
! 3905: * While we're at it, read the request queue out pointer.
! 3906: */
! 3907: isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp);
! 3908: if (isp->isp_rscchiwater < ndone)
! 3909: isp->isp_rscchiwater = ndone;
! 3910: }
! 3911:
! 3912: isp->isp_residx = optr;
! 3913: isp->isp_rspbsy = 0;
! 3914: for (i = 0; i < ndone; i++) {
! 3915: xs = complist[i];
! 3916: if (xs) {
! 3917: isp->isp_rsltccmplt++;
! 3918: isp_done(xs);
! 3919: }
! 3920: }
! 3921: }
! 3922:
! 3923: /*
! 3924: * Support routines.
! 3925: */
! 3926:
! 3927: static int
! 3928: isp_parse_async(struct ispsoftc *isp, u_int16_t mbox)
! 3929: {
! 3930: int rval = 0;
! 3931: int bus;
! 3932:
! 3933: if (IS_DUALBUS(isp)) {
! 3934: bus = ISP_READ(isp, OUTMAILBOX6);
! 3935: } else {
! 3936: bus = 0;
! 3937: }
! 3938: isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
! 3939:
! 3940: switch (mbox) {
! 3941: case ASYNC_BUS_RESET:
! 3942: isp->isp_sendmarker |= (1 << bus);
! 3943: #ifdef ISP_TARGET_MODE
! 3944: if (isp_target_async(isp, bus, mbox))
! 3945: rval = -1;
! 3946: #endif
! 3947: isp_async(isp, ISPASYNC_BUS_RESET, &bus);
! 3948: break;
! 3949: case ASYNC_SYSTEM_ERROR:
! 3950: #ifdef ISP_FW_CRASH_DUMP
! 3951: /*
! 3952: * If we have crash dumps enabled, it's up to the handler
! 3953: * for isp_async to reinit stuff and restart the firmware
! 3954: * after performing the crash dump. The reason we do things
! 3955: * this way is that we may need to activate a kernel thread
! 3956: * to do all the crash dump goop.
! 3957: */
! 3958: isp_async(isp, ISPASYNC_FW_CRASH, NULL);
! 3959: #else
! 3960: isp_async(isp, ISPASYNC_FW_CRASH, NULL);
! 3961: isp_reinit(isp);
! 3962: isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
! 3963: #endif
! 3964: rval = -1;
! 3965: break;
! 3966:
! 3967: case ASYNC_RQS_XFER_ERR:
! 3968: isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
! 3969: break;
! 3970:
! 3971: case ASYNC_RSP_XFER_ERR:
! 3972: isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
! 3973: break;
! 3974:
! 3975: case ASYNC_QWAKEUP:
! 3976: /*
! 3977: * We've just been notified that the Queue has woken up.
! 3978: * We don't need to be chatty about this- just unlatch things
! 3979: * and move on.
! 3980: */
! 3981: mbox = READ_REQUEST_QUEUE_OUT_POINTER(isp);
! 3982: break;
! 3983:
! 3984: case ASYNC_TIMEOUT_RESET:
! 3985: isp_prt(isp, ISP_LOGWARN,
! 3986: "timeout initiated SCSI bus reset of bus %d", bus);
! 3987: isp->isp_sendmarker |= (1 << bus);
! 3988: #ifdef ISP_TARGET_MODE
! 3989: if (isp_target_async(isp, bus, mbox))
! 3990: rval = -1;
! 3991: #endif
! 3992: break;
! 3993:
! 3994: case ASYNC_DEVICE_RESET:
! 3995: isp_prt(isp, ISP_LOGINFO, "device reset on bus %d", bus);
! 3996: isp->isp_sendmarker |= (1 << bus);
! 3997: #ifdef ISP_TARGET_MODE
! 3998: if (isp_target_async(isp, bus, mbox))
! 3999: rval = -1;
! 4000: #endif
! 4001: break;
! 4002:
! 4003: case ASYNC_EXTMSG_UNDERRUN:
! 4004: isp_prt(isp, ISP_LOGWARN, "extended message underrun");
! 4005: break;
! 4006:
! 4007: case ASYNC_SCAM_INT:
! 4008: isp_prt(isp, ISP_LOGINFO, "SCAM interrupt");
! 4009: break;
! 4010:
! 4011: case ASYNC_HUNG_SCSI:
! 4012: isp_prt(isp, ISP_LOGERR,
! 4013: "stalled SCSI Bus after DATA Overrun");
! 4014: /* XXX: Need to issue SCSI reset at this point */
! 4015: break;
! 4016:
! 4017: case ASYNC_KILLED_BUS:
! 4018: isp_prt(isp, ISP_LOGERR, "SCSI Bus reset after DATA Overrun");
! 4019: break;
! 4020:
! 4021: case ASYNC_BUS_TRANSIT:
! 4022: mbox = ISP_READ(isp, OUTMAILBOX2);
! 4023: switch (mbox & 0x1c00) {
! 4024: case SXP_PINS_LVD_MODE:
! 4025: isp_prt(isp, ISP_LOGINFO, "Transition to LVD mode");
! 4026: SDPARAM(isp)->isp_diffmode = 0;
! 4027: SDPARAM(isp)->isp_ultramode = 0;
! 4028: SDPARAM(isp)->isp_lvdmode = 1;
! 4029: break;
! 4030: case SXP_PINS_HVD_MODE:
! 4031: isp_prt(isp, ISP_LOGINFO,
! 4032: "Transition to Differential mode");
! 4033: SDPARAM(isp)->isp_diffmode = 1;
! 4034: SDPARAM(isp)->isp_ultramode = 0;
! 4035: SDPARAM(isp)->isp_lvdmode = 0;
! 4036: break;
! 4037: case SXP_PINS_SE_MODE:
! 4038: isp_prt(isp, ISP_LOGINFO,
! 4039: "Transition to Single Ended mode");
! 4040: SDPARAM(isp)->isp_diffmode = 0;
! 4041: SDPARAM(isp)->isp_ultramode = 1;
! 4042: SDPARAM(isp)->isp_lvdmode = 0;
! 4043: break;
! 4044: default:
! 4045: isp_prt(isp, ISP_LOGWARN,
! 4046: "Transition to Unknown Mode 0x%x", mbox);
! 4047: break;
! 4048: }
! 4049: /*
! 4050: * XXX: Set up to renegotiate again!
! 4051: */
! 4052: /* Can only be for a 1080... */
! 4053: isp->isp_sendmarker |= (1 << bus);
! 4054: break;
! 4055:
! 4056: /*
! 4057: * We can use bus, which will always be zero for FC cards,
! 4058: * as a mailbox pattern accumulator to be checked below.
! 4059: */
! 4060: case ASYNC_RIO5:
! 4061: bus = 0x1ce; /* outgoing mailbox regs 1-3, 6-7 */
! 4062: break;
! 4063:
! 4064: case ASYNC_RIO4:
! 4065: bus = 0x14e; /* outgoing mailbox regs 1-3, 6 */
! 4066: break;
! 4067:
! 4068: case ASYNC_RIO3:
! 4069: bus = 0x10e; /* outgoing mailbox regs 1-3 */
! 4070: break;
! 4071:
! 4072: case ASYNC_RIO2:
! 4073: bus = 0x106; /* outgoing mailbox regs 1-2 */
! 4074: break;
! 4075:
! 4076: case ASYNC_RIO1:
! 4077: case ASYNC_CMD_CMPLT:
! 4078: bus = 0x102; /* outgoing mailbox regs 1 */
! 4079: break;
! 4080:
! 4081: case ASYNC_RIO_RESP:
! 4082: return (rval);
! 4083:
! 4084: case ASYNC_CTIO_DONE:
! 4085: {
! 4086: #ifdef ISP_TARGET_MODE
! 4087: int handle =
! 4088: (ISP_READ(isp, OUTMAILBOX2) << 16) |
! 4089: (ISP_READ(isp, OUTMAILBOX1));
! 4090: if (isp_target_async(isp, handle, mbox))
! 4091: rval = -1;
! 4092: #else
! 4093: isp_prt(isp, ISP_LOGINFO, "Fast Posting CTIO done");
! 4094: #endif
! 4095: isp->isp_fphccmplt++; /* count it as a fast posting intr */
! 4096: break;
! 4097: }
! 4098: case ASYNC_LIP_F8:
! 4099: case ASYNC_LIP_OCCURRED:
! 4100: FCPARAM(isp)->isp_lipseq =
! 4101: ISP_READ(isp, OUTMAILBOX1);
! 4102: FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
! 4103: FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
! 4104: isp->isp_sendmarker = 1;
! 4105: isp_mark_getpdb_all(isp);
! 4106: isp_async(isp, ISPASYNC_LIP, NULL);
! 4107: #ifdef ISP_TARGET_MODE
! 4108: if (isp_target_async(isp, bus, mbox))
! 4109: rval = -1;
! 4110: #endif
! 4111: /*
! 4112: * We've had problems with data corruption occurring on
! 4113: * commands that complete (with no apparent error) after
! 4114: * we receive a LIP. This has been observed mostly on
! 4115: * Local Loop topologies. To be safe, let's just mark
! 4116: * all active commands as dead.
! 4117: */
! 4118: if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
! 4119: FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
! 4120: int i, j;
! 4121: for (i = j = 0; i < isp->isp_maxcmds; i++) {
! 4122: XS_T *xs;
! 4123: xs = isp->isp_xflist[i];
! 4124: if (xs != NULL) {
! 4125: j++;
! 4126: XS_SETERR(xs, HBA_BUSRESET);
! 4127: }
! 4128: }
! 4129: if (j) {
! 4130: isp_prt(isp, ISP_LOGERR,
! 4131: "LIP destroyed %d active commands", j);
! 4132: }
! 4133: }
! 4134: break;
! 4135:
! 4136: case ASYNC_LOOP_UP:
! 4137: isp->isp_sendmarker = 1;
! 4138: FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
! 4139: FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
! 4140: isp_mark_getpdb_all(isp);
! 4141: isp_async(isp, ISPASYNC_LOOP_UP, NULL);
! 4142: #ifdef ISP_TARGET_MODE
! 4143: if (isp_target_async(isp, bus, mbox))
! 4144: rval = -1;
! 4145: #endif
! 4146: break;
! 4147:
! 4148: case ASYNC_LOOP_DOWN:
! 4149: isp->isp_sendmarker = 1;
! 4150: FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
! 4151: FCPARAM(isp)->isp_loopstate = LOOP_NIL;
! 4152: isp_mark_getpdb_all(isp);
! 4153: isp_async(isp, ISPASYNC_LOOP_DOWN, NULL);
! 4154: #ifdef ISP_TARGET_MODE
! 4155: if (isp_target_async(isp, bus, mbox))
! 4156: rval = -1;
! 4157: #endif
! 4158: break;
! 4159:
! 4160: case ASYNC_LOOP_RESET:
! 4161: isp->isp_sendmarker = 1;
! 4162: FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
! 4163: FCPARAM(isp)->isp_loopstate = LOOP_NIL;
! 4164: isp_mark_getpdb_all(isp);
! 4165: isp_async(isp, ISPASYNC_LOOP_RESET, NULL);
! 4166: #ifdef ISP_TARGET_MODE
! 4167: if (isp_target_async(isp, bus, mbox))
! 4168: rval = -1;
! 4169: #endif
! 4170: break;
! 4171:
! 4172: case ASYNC_PDB_CHANGED:
! 4173: isp->isp_sendmarker = 1;
! 4174: FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
! 4175: isp_mark_getpdb_all(isp);
! 4176: isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_PDB);
! 4177: break;
! 4178:
! 4179: case ASYNC_CHANGE_NOTIFY:
! 4180: /*
! 4181: * Not correct, but it will force us to rescan the loop.
! 4182: */
! 4183: FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
! 4184: isp_mark_getpdb_all(isp);
! 4185: isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_SNS);
! 4186: break;
! 4187:
! 4188: case ASYNC_PTPMODE:
! 4189: if (FCPARAM(isp)->isp_onfabric)
! 4190: FCPARAM(isp)->isp_topo = TOPO_F_PORT;
! 4191: else
! 4192: FCPARAM(isp)->isp_topo = TOPO_N_PORT;
! 4193: isp_mark_getpdb_all(isp);
! 4194: isp->isp_sendmarker = 1;
! 4195: FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
! 4196: FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
! 4197: isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
! 4198: #ifdef ISP_TARGET_MODE
! 4199: if (isp_target_async(isp, bus, mbox))
! 4200: rval = -1;
! 4201: #endif
! 4202: isp_prt(isp, ISP_LOGINFO, "Point-to-Point mode");
! 4203: break;
! 4204:
! 4205: case ASYNC_CONNMODE:
! 4206: mbox = ISP_READ(isp, OUTMAILBOX1);
! 4207: isp_mark_getpdb_all(isp);
! 4208: switch (mbox) {
! 4209: case ISP_CONN_LOOP:
! 4210: isp_prt(isp, ISP_LOGINFO,
! 4211: "Point-to-Point -> Loop mode");
! 4212: break;
! 4213: case ISP_CONN_PTP:
! 4214: isp_prt(isp, ISP_LOGINFO,
! 4215: "Loop -> Point-to-Point mode");
! 4216: break;
! 4217: case ISP_CONN_BADLIP:
! 4218: isp_prt(isp, ISP_LOGWARN,
! 4219: "Point-to-Point -> Loop mode (BAD LIP)");
! 4220: break;
! 4221: case ISP_CONN_FATAL:
! 4222: isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR");
! 4223: #ifdef ISP_FW_CRASH_DUMP
! 4224: isp_async(isp, ISPASYNC_FW_CRASH, NULL);
! 4225: #else
! 4226: isp_async(isp, ISPASYNC_FW_CRASH, NULL);
! 4227: isp_reinit(isp);
! 4228: isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
! 4229: #endif
! 4230: return (-1);
! 4231: case ISP_CONN_LOOPBACK:
! 4232: isp_prt(isp, ISP_LOGWARN,
! 4233: "Looped Back in Point-to-Point mode");
! 4234: break;
! 4235: default:
! 4236: isp_prt(isp, ISP_LOGWARN,
! 4237: "Unknown connection mode (0x%x)", mbox);
! 4238: break;
! 4239: }
! 4240: isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
! 4241: isp->isp_sendmarker = 1;
! 4242: FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
! 4243: FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
! 4244: break;
! 4245:
! 4246: default:
! 4247: isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
! 4248: break;
! 4249: }
! 4250:
! 4251: if (bus & 0x100) {
! 4252: int i, nh;
! 4253: u_int16_t handles[5];
! 4254:
! 4255: for (nh = 0, i = 1; i < MAX_MAILBOX; i++) {
! 4256: if ((bus & (1 << i)) == 0) {
! 4257: continue;
! 4258: }
! 4259: handles[nh++] = ISP_READ(isp, MBOX_OFF(i));
! 4260: }
! 4261: for (i = 0; i < nh; i++) {
! 4262: isp_fastpost_complete(isp, handles[i]);
! 4263: isp_prt(isp, ISP_LOGDEBUG3,
! 4264: "fast post completion of %u", handles[i]);
! 4265: }
! 4266: if (isp->isp_fpcchiwater < nh)
! 4267: isp->isp_fpcchiwater = nh;
! 4268: } else {
! 4269: isp->isp_intoasync++;
! 4270: }
! 4271: return (rval);
! 4272: }
! 4273:
! 4274: /*
! 4275: * Handle other response entries. A pointer to the request queue output
! 4276: * index is here in case we want to eat several entries at once, although
! 4277: * this is not used currently.
! 4278: */
! 4279:
! 4280: static int
! 4281: isp_handle_other_response(struct ispsoftc *isp, int type,
! 4282: isphdr_t *hp, u_int16_t *optrp)
! 4283: {
! 4284: switch (type) {
! 4285: case RQSTYPE_STATUS_CONT:
! 4286: isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response");
! 4287: return (1);
! 4288: case RQSTYPE_ATIO:
! 4289: case RQSTYPE_CTIO:
! 4290: case RQSTYPE_ENABLE_LUN:
! 4291: case RQSTYPE_MODIFY_LUN:
! 4292: case RQSTYPE_NOTIFY:
! 4293: case RQSTYPE_NOTIFY_ACK:
! 4294: case RQSTYPE_CTIO1:
! 4295: case RQSTYPE_ATIO2:
! 4296: case RQSTYPE_CTIO2:
! 4297: case RQSTYPE_CTIO3:
! 4298: isp->isp_rsltccmplt++; /* count as a response completion */
! 4299: #ifdef ISP_TARGET_MODE
! 4300: if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)) {
! 4301: return (1);
! 4302: }
! 4303: #endif
! 4304: /* FALLTHROUGH */
! 4305: case RQSTYPE_REQUEST:
! 4306: default:
! 4307: if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, hp)) {
! 4308: return (1);
! 4309: }
! 4310: isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x",
! 4311: isp_get_response_type(isp, hp));
! 4312: return (0);
! 4313: }
! 4314: }
! 4315:
! 4316: static void
! 4317: isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
! 4318: {
! 4319: switch (sp->req_completion_status & 0xff) {
! 4320: case RQCS_COMPLETE:
! 4321: if (XS_NOERR(xs)) {
! 4322: XS_SETERR(xs, HBA_NOERROR);
! 4323: }
! 4324: return;
! 4325:
! 4326: case RQCS_INCOMPLETE:
! 4327: if ((sp->req_state_flags & RQSF_GOT_TARGET) == 0) {
! 4328: isp_prt(isp, ISP_LOGDEBUG1,
! 4329: "Selection Timeout for %d.%d.%d",
! 4330: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4331: if (XS_NOERR(xs)) {
! 4332: XS_SETERR(xs, HBA_SELTIMEOUT);
! 4333: }
! 4334: return;
! 4335: }
! 4336: isp_prt(isp, ISP_LOGERR,
! 4337: "command incomplete for %d.%d.%d, state 0x%x",
! 4338: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs),
! 4339: sp->req_state_flags);
! 4340: break;
! 4341:
! 4342: case RQCS_DMA_ERROR:
! 4343: isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d",
! 4344: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4345: break;
! 4346:
! 4347: case RQCS_TRANSPORT_ERROR:
! 4348: {
! 4349: char buf[172];
! 4350: SNPRINTF(buf, sizeof (buf), "states=>");
! 4351: if (sp->req_state_flags & RQSF_GOT_BUS) {
! 4352: SNPRINTF(buf, sizeof (buf), "%s GOT_BUS", buf);
! 4353: }
! 4354: if (sp->req_state_flags & RQSF_GOT_TARGET) {
! 4355: SNPRINTF(buf, sizeof (buf), "%s GOT_TGT", buf);
! 4356: }
! 4357: if (sp->req_state_flags & RQSF_SENT_CDB) {
! 4358: SNPRINTF(buf, sizeof (buf), "%s SENT_CDB", buf);
! 4359: }
! 4360: if (sp->req_state_flags & RQSF_XFRD_DATA) {
! 4361: SNPRINTF(buf, sizeof (buf), "%s XFRD_DATA", buf);
! 4362: }
! 4363: if (sp->req_state_flags & RQSF_GOT_STATUS) {
! 4364: SNPRINTF(buf, sizeof (buf), "%s GOT_STS", buf);
! 4365: }
! 4366: if (sp->req_state_flags & RQSF_GOT_SENSE) {
! 4367: SNPRINTF(buf, sizeof (buf), "%s GOT_SNS", buf);
! 4368: }
! 4369: if (sp->req_state_flags & RQSF_XFER_COMPLETE) {
! 4370: SNPRINTF(buf, sizeof (buf), "%s XFR_CMPLT", buf);
! 4371: }
! 4372: SNPRINTF(buf, sizeof (buf), "%s\nstatus=>", buf);
! 4373: if (sp->req_status_flags & RQSTF_DISCONNECT) {
! 4374: SNPRINTF(buf, sizeof (buf), "%s Disconnect", buf);
! 4375: }
! 4376: if (sp->req_status_flags & RQSTF_SYNCHRONOUS) {
! 4377: SNPRINTF(buf, sizeof (buf), "%s Sync_xfr", buf);
! 4378: }
! 4379: if (sp->req_status_flags & RQSTF_PARITY_ERROR) {
! 4380: SNPRINTF(buf, sizeof (buf), "%s Parity", buf);
! 4381: }
! 4382: if (sp->req_status_flags & RQSTF_BUS_RESET) {
! 4383: SNPRINTF(buf, sizeof (buf), "%s Bus_Reset", buf);
! 4384: }
! 4385: if (sp->req_status_flags & RQSTF_DEVICE_RESET) {
! 4386: SNPRINTF(buf, sizeof (buf), "%s Device_Reset", buf);
! 4387: }
! 4388: if (sp->req_status_flags & RQSTF_ABORTED) {
! 4389: SNPRINTF(buf, sizeof (buf), "%s Aborted", buf);
! 4390: }
! 4391: if (sp->req_status_flags & RQSTF_TIMEOUT) {
! 4392: SNPRINTF(buf, sizeof (buf), "%s Timeout", buf);
! 4393: }
! 4394: if (sp->req_status_flags & RQSTF_NEGOTIATION) {
! 4395: SNPRINTF(buf, sizeof (buf), "%s Negotiation", buf);
! 4396: }
! 4397: isp_prt(isp, ISP_LOGERR, "%s", buf);
! 4398: isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d:\n%s",
! 4399: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), buf);
! 4400: break;
! 4401: }
! 4402: case RQCS_RESET_OCCURRED:
! 4403: isp_prt(isp, ISP_LOGWARN,
! 4404: "bus reset destroyed command for %d.%d.%d",
! 4405: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4406: isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
! 4407: if (XS_NOERR(xs)) {
! 4408: XS_SETERR(xs, HBA_BUSRESET);
! 4409: }
! 4410: return;
! 4411:
! 4412: case RQCS_ABORTED:
! 4413: isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d",
! 4414: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4415: isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
! 4416: if (XS_NOERR(xs)) {
! 4417: XS_SETERR(xs, HBA_ABORTED);
! 4418: }
! 4419: return;
! 4420:
! 4421: case RQCS_TIMEOUT:
! 4422: isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d",
! 4423: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4424: /*
! 4425: * Check to see if we logged out the device.
! 4426: */
! 4427: if (IS_FC(isp)) {
! 4428: if ((sp->req_completion_status & RQSTF_LOGOUT) &&
! 4429: FCPARAM(isp)->portdb[XS_TGT(xs)].valid &&
! 4430: FCPARAM(isp)->portdb[XS_TGT(xs)].fabric_dev) {
! 4431: FCPARAM(isp)->portdb[XS_TGT(xs)].relogin = 1;
! 4432: }
! 4433: }
! 4434: if (XS_NOERR(xs)) {
! 4435: XS_SETERR(xs, HBA_CMDTIMEOUT);
! 4436: }
! 4437: return;
! 4438:
! 4439: case RQCS_DATA_OVERRUN:
! 4440: XS_RESID(xs) = sp->req_resid;
! 4441: isp_prt(isp, ISP_LOGERR, "data overrun for command on %d.%d.%d",
! 4442: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4443: if (XS_NOERR(xs)) {
! 4444: XS_SETERR(xs, HBA_DATAOVR);
! 4445: }
! 4446: return;
! 4447:
! 4448: case RQCS_COMMAND_OVERRUN:
! 4449: isp_prt(isp, ISP_LOGERR,
! 4450: "command overrun for command on %d.%d.%d",
! 4451: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4452: break;
! 4453:
! 4454: case RQCS_STATUS_OVERRUN:
! 4455: isp_prt(isp, ISP_LOGERR,
! 4456: "status overrun for command on %d.%d.%d",
! 4457: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4458: break;
! 4459:
! 4460: case RQCS_BAD_MESSAGE:
! 4461: isp_prt(isp, ISP_LOGERR,
! 4462: "msg not COMMAND COMPLETE after status %d.%d.%d",
! 4463: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4464: break;
! 4465:
! 4466: case RQCS_NO_MESSAGE_OUT:
! 4467: isp_prt(isp, ISP_LOGERR,
! 4468: "No MESSAGE OUT phase after selection on %d.%d.%d",
! 4469: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4470: break;
! 4471:
! 4472: case RQCS_EXT_ID_FAILED:
! 4473: isp_prt(isp, ISP_LOGERR, "EXTENDED IDENTIFY failed %d.%d.%d",
! 4474: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4475: break;
! 4476:
! 4477: case RQCS_IDE_MSG_FAILED:
! 4478: isp_prt(isp, ISP_LOGERR,
! 4479: "INITIATOR DETECTED ERROR rejected by %d.%d.%d",
! 4480: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4481: break;
! 4482:
! 4483: case RQCS_ABORT_MSG_FAILED:
! 4484: isp_prt(isp, ISP_LOGERR, "ABORT OPERATION rejected by %d.%d.%d",
! 4485: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4486: break;
! 4487:
! 4488: case RQCS_REJECT_MSG_FAILED:
! 4489: isp_prt(isp, ISP_LOGERR, "MESSAGE REJECT rejected by %d.%d.%d",
! 4490: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4491: break;
! 4492:
! 4493: case RQCS_NOP_MSG_FAILED:
! 4494: isp_prt(isp, ISP_LOGERR, "NOP rejected by %d.%d.%d",
! 4495: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4496: break;
! 4497:
! 4498: case RQCS_PARITY_ERROR_MSG_FAILED:
! 4499: isp_prt(isp, ISP_LOGERR,
! 4500: "MESSAGE PARITY ERROR rejected by %d.%d.%d",
! 4501: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4502: break;
! 4503:
! 4504: case RQCS_DEVICE_RESET_MSG_FAILED:
! 4505: isp_prt(isp, ISP_LOGWARN,
! 4506: "BUS DEVICE RESET rejected by %d.%d.%d",
! 4507: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4508: break;
! 4509:
! 4510: case RQCS_ID_MSG_FAILED:
! 4511: isp_prt(isp, ISP_LOGERR, "IDENTIFY rejected by %d.%d.%d",
! 4512: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4513: break;
! 4514:
! 4515: case RQCS_UNEXP_BUS_FREE:
! 4516: isp_prt(isp, ISP_LOGERR, "%d.%d.%d had an unexpected bus free",
! 4517: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4518: break;
! 4519:
! 4520: case RQCS_DATA_UNDERRUN:
! 4521: {
! 4522: if (IS_FC(isp)) {
! 4523: int ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
! 4524: if (!ru_marked || sp->req_resid > XS_XFRLEN(xs)) {
! 4525: isp_prt(isp, ISP_LOGWARN, bun, XS_TGT(xs),
! 4526: XS_LUN(xs), XS_XFRLEN(xs), sp->req_resid,
! 4527: (ru_marked)? "marked" : "not marked");
! 4528: if (XS_NOERR(xs)) {
! 4529: XS_SETERR(xs, HBA_BOTCH);
! 4530: }
! 4531: return;
! 4532: }
! 4533: }
! 4534: XS_RESID(xs) = sp->req_resid;
! 4535: if (XS_NOERR(xs)) {
! 4536: XS_SETERR(xs, HBA_NOERROR);
! 4537: }
! 4538: return;
! 4539: }
! 4540:
! 4541: case RQCS_XACT_ERR1:
! 4542: isp_prt(isp, ISP_LOGERR, xact1, XS_CHANNEL(xs),
! 4543: XS_TGT(xs), XS_LUN(xs));
! 4544: break;
! 4545:
! 4546: case RQCS_XACT_ERR2:
! 4547: isp_prt(isp, ISP_LOGERR, xact2,
! 4548: XS_LUN(xs), XS_TGT(xs), XS_CHANNEL(xs));
! 4549: break;
! 4550:
! 4551: case RQCS_XACT_ERR3:
! 4552: isp_prt(isp, ISP_LOGERR, xact3,
! 4553: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4554: break;
! 4555:
! 4556: case RQCS_BAD_ENTRY:
! 4557: isp_prt(isp, ISP_LOGERR, "Invalid IOCB entry type detected");
! 4558: break;
! 4559:
! 4560: case RQCS_QUEUE_FULL:
! 4561: isp_prt(isp, ISP_LOGDEBUG0,
! 4562: "internal queues full for %d.%d.%d status 0x%x",
! 4563: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), *XS_STSP(xs));
! 4564:
! 4565: /*
! 4566: * If QFULL or some other status byte is set, then this
! 4567: * isn't an error, per se.
! 4568: *
! 4569: * Unfortunately, some QLogic f/w writers have, in
! 4570: * some cases, ommitted to *set* status to QFULL.
! 4571: *
! 4572:
! 4573: if (*XS_STSP(xs) != SCSI_GOOD && XS_NOERR(xs)) {
! 4574: XS_SETERR(xs, HBA_NOERROR);
! 4575: return;
! 4576: }
! 4577:
! 4578: *
! 4579: *
! 4580: */
! 4581:
! 4582: *XS_STSP(xs) = SCSI_QFULL;
! 4583: XS_SETERR(xs, HBA_NOERROR);
! 4584: return;
! 4585:
! 4586: case RQCS_PHASE_SKIPPED:
! 4587: isp_prt(isp, ISP_LOGERR, pskip, XS_CHANNEL(xs),
! 4588: XS_TGT(xs), XS_LUN(xs));
! 4589: break;
! 4590:
! 4591: case RQCS_ARQS_FAILED:
! 4592: isp_prt(isp, ISP_LOGERR,
! 4593: "Auto Request Sense failed for %d.%d.%d",
! 4594: XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
! 4595: if (XS_NOERR(xs)) {
! 4596: XS_SETERR(xs, HBA_ARQFAIL);
! 4597: }
! 4598: return;
! 4599:
! 4600: case RQCS_WIDE_FAILED:
! 4601: isp_prt(isp, ISP_LOGERR,
! 4602: "Wide Negotiation failed for %d.%d.%d",
! 4603: XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
! 4604: if (IS_SCSI(isp)) {
! 4605: sdparam *sdp = isp->isp_param;
! 4606: sdp += XS_CHANNEL(xs);
! 4607: sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_WIDE;
! 4608: sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
! 4609: isp->isp_update |= (1 << XS_CHANNEL(xs));
! 4610: }
! 4611: if (XS_NOERR(xs)) {
! 4612: XS_SETERR(xs, HBA_NOERROR);
! 4613: }
! 4614: return;
! 4615:
! 4616: case RQCS_SYNCXFER_FAILED:
! 4617: isp_prt(isp, ISP_LOGERR,
! 4618: "SDTR Message failed for target %d.%d.%d",
! 4619: XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
! 4620: if (IS_SCSI(isp)) {
! 4621: sdparam *sdp = isp->isp_param;
! 4622: sdp += XS_CHANNEL(xs);
! 4623: sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_SYNC;
! 4624: sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
! 4625: isp->isp_update |= (1 << XS_CHANNEL(xs));
! 4626: }
! 4627: break;
! 4628:
! 4629: case RQCS_LVD_BUSERR:
! 4630: isp_prt(isp, ISP_LOGERR,
! 4631: "Bad LVD condition while talking to %d.%d.%d",
! 4632: XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
! 4633: break;
! 4634:
! 4635: case RQCS_PORT_UNAVAILABLE:
! 4636: /*
! 4637: * No such port on the loop. Moral equivalent of SELTIMEO
! 4638: */
! 4639: case RQCS_PORT_LOGGED_OUT:
! 4640: /*
! 4641: * It was there (maybe)- treat as a selection timeout.
! 4642: */
! 4643: if ((sp->req_completion_status & 0xff) == RQCS_PORT_UNAVAILABLE)
! 4644: isp_prt(isp, ISP_LOGINFO,
! 4645: "port unavailable for target %d", XS_TGT(xs));
! 4646: else
! 4647: isp_prt(isp, ISP_LOGINFO,
! 4648: "port logout for target %d", XS_TGT(xs));
! 4649: /*
! 4650: * If we're on a local loop, force a LIP (which is overkill)
! 4651: * to force a re-login of this unit. If we're on fabric,
! 4652: * then we'll have to relogin as a matter of course.
! 4653: */
! 4654: if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
! 4655: FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
! 4656: mbreg_t mbs;
! 4657: mbs.param[0] = MBOX_INIT_LIP;
! 4658: isp_mboxcmd_qnw(isp, &mbs, 1);
! 4659: }
! 4660:
! 4661: /*
! 4662: * Probably overkill.
! 4663: */
! 4664: isp->isp_sendmarker = 1;
! 4665: FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
! 4666: isp_mark_getpdb_all(isp);
! 4667: isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
! 4668: if (XS_NOERR(xs)) {
! 4669: XS_SETERR(xs, HBA_SELTIMEOUT);
! 4670: }
! 4671: return;
! 4672:
! 4673: case RQCS_PORT_CHANGED:
! 4674: isp_prt(isp, ISP_LOGWARN,
! 4675: "port changed for target %d", XS_TGT(xs));
! 4676: if (XS_NOERR(xs)) {
! 4677: XS_SETERR(xs, HBA_SELTIMEOUT);
! 4678: }
! 4679: return;
! 4680:
! 4681: case RQCS_PORT_BUSY:
! 4682: isp_prt(isp, ISP_LOGWARN,
! 4683: "port busy for target %d", XS_TGT(xs));
! 4684: if (XS_NOERR(xs)) {
! 4685: XS_SETERR(xs, HBA_TGTBSY);
! 4686: }
! 4687: return;
! 4688:
! 4689: default:
! 4690: isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x",
! 4691: sp->req_completion_status);
! 4692: break;
! 4693: }
! 4694: if (XS_NOERR(xs)) {
! 4695: XS_SETERR(xs, HBA_BOTCH);
! 4696: }
! 4697: }
! 4698:
! 4699: static void
! 4700: isp_fastpost_complete(struct ispsoftc *isp, u_int16_t fph)
! 4701: {
! 4702: XS_T *xs;
! 4703:
! 4704: if (fph == 0) {
! 4705: return;
! 4706: }
! 4707: xs = isp_find_xs(isp, fph);
! 4708: if (xs == NULL) {
! 4709: isp_prt(isp, ISP_LOGWARN,
! 4710: "Command for fast post handle 0x%x not found", fph);
! 4711: return;
! 4712: }
! 4713: isp_destroy_handle(isp, fph);
! 4714:
! 4715: /*
! 4716: * Since we don't have a result queue entry item,
! 4717: * we must believe that SCSI status is zero and
! 4718: * that all data transferred.
! 4719: */
! 4720: XS_SET_STATE_STAT(isp, xs, NULL);
! 4721: XS_RESID(xs) = 0;
! 4722: *XS_STSP(xs) = SCSI_GOOD;
! 4723: if (XS_XFRLEN(xs)) {
! 4724: ISP_DMAFREE(isp, xs, fph);
! 4725: }
! 4726: if (isp->isp_nactive)
! 4727: isp->isp_nactive--;
! 4728: isp->isp_fphccmplt++;
! 4729: isp_done(xs);
! 4730: }
! 4731:
! 4732: static int
! 4733: isp_mbox_continue(struct ispsoftc *isp)
! 4734: {
! 4735: mbreg_t mbs;
! 4736: u_int16_t *ptr;
! 4737:
! 4738: switch (isp->isp_lastmbxcmd) {
! 4739: case MBOX_WRITE_RAM_WORD:
! 4740: case MBOX_READ_RAM_WORD:
! 4741: case MBOX_READ_RAM_WORD_EXTENDED:
! 4742: break;
! 4743: default:
! 4744: return (1);
! 4745: }
! 4746: if (isp->isp_mboxtmp[0] != MBOX_COMMAND_COMPLETE) {
! 4747: isp->isp_mbxwrk0 = 0;
! 4748: return (-1);
! 4749: }
! 4750:
! 4751:
! 4752: /*
! 4753: * Clear the previous interrupt.
! 4754: */
! 4755: ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
! 4756: ISP_WRITE(isp, BIU_SEMA, 0);
! 4757:
! 4758: /*
! 4759: * Continue with next word.
! 4760: */
! 4761: ptr = isp->isp_mbxworkp;
! 4762: switch (isp->isp_lastmbxcmd) {
! 4763: case MBOX_WRITE_RAM_WORD:
! 4764: mbs.param[2] = *ptr++;
! 4765: mbs.param[1] = isp->isp_mbxwrk1++;
! 4766: break;
! 4767: case MBOX_READ_RAM_WORD:
! 4768: case MBOX_READ_RAM_WORD_EXTENDED:
! 4769: *ptr++ = isp->isp_mboxtmp[2];
! 4770: mbs.param[1] = isp->isp_mbxwrk1++;
! 4771: break;
! 4772: }
! 4773: isp->isp_mbxworkp = ptr;
! 4774: mbs.param[0] = isp->isp_lastmbxcmd;
! 4775: isp->isp_mbxwrk0 -= 1;
! 4776: isp_mboxcmd_qnw(isp, &mbs, 0);
! 4777: return (0);
! 4778: }
! 4779:
! 4780:
! 4781: #define HIBYT(x) ((x) >> 0x8)
! 4782: #define LOBYT(x) ((x) & 0xff)
! 4783: #define ISPOPMAP(a, b) (((a) << 8) | (b))
! 4784: static const u_int16_t mbpscsi[] = {
! 4785: ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
! 4786: ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
! 4787: ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */
! 4788: ISPOPMAP(0x1f, 0x01), /* 0x03: MBOX_DUMP_RAM */
! 4789: ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
! 4790: ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
! 4791: ISPOPMAP(0x3f, 0x3f), /* 0x06: MBOX_MAILBOX_REG_TEST */
! 4792: ISPOPMAP(0x03, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
! 4793: ISPOPMAP(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */
! 4794: ISPOPMAP(0x00, 0x00), /* 0x09: */
! 4795: ISPOPMAP(0x00, 0x00), /* 0x0a: */
! 4796: ISPOPMAP(0x00, 0x00), /* 0x0b: */
! 4797: ISPOPMAP(0x00, 0x00), /* 0x0c: */
! 4798: ISPOPMAP(0x00, 0x00), /* 0x0d: */
! 4799: ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
! 4800: ISPOPMAP(0x00, 0x00), /* 0x0f: */
! 4801: ISPOPMAP(0x1f, 0x1f), /* 0x10: MBOX_INIT_REQ_QUEUE */
! 4802: ISPOPMAP(0x3f, 0x3f), /* 0x11: MBOX_INIT_RES_QUEUE */
! 4803: ISPOPMAP(0x0f, 0x0f), /* 0x12: MBOX_EXECUTE_IOCB */
! 4804: ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
! 4805: ISPOPMAP(0x01, 0x3f), /* 0x14: MBOX_STOP_FIRMWARE */
! 4806: ISPOPMAP(0x0f, 0x0f), /* 0x15: MBOX_ABORT */
! 4807: ISPOPMAP(0x03, 0x03), /* 0x16: MBOX_ABORT_DEVICE */
! 4808: ISPOPMAP(0x07, 0x07), /* 0x17: MBOX_ABORT_TARGET */
! 4809: ISPOPMAP(0x07, 0x07), /* 0x18: MBOX_BUS_RESET */
! 4810: ISPOPMAP(0x03, 0x07), /* 0x19: MBOX_STOP_QUEUE */
! 4811: ISPOPMAP(0x03, 0x07), /* 0x1a: MBOX_START_QUEUE */
! 4812: ISPOPMAP(0x03, 0x07), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
! 4813: ISPOPMAP(0x03, 0x07), /* 0x1c: MBOX_ABORT_QUEUE */
! 4814: ISPOPMAP(0x03, 0x4f), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
! 4815: ISPOPMAP(0x00, 0x00), /* 0x1e: */
! 4816: ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
! 4817: ISPOPMAP(0x01, 0x07), /* 0x20: MBOX_GET_INIT_SCSI_ID */
! 4818: ISPOPMAP(0x01, 0x07), /* 0x21: MBOX_GET_SELECT_TIMEOUT */
! 4819: ISPOPMAP(0x01, 0xc7), /* 0x22: MBOX_GET_RETRY_COUNT */
! 4820: ISPOPMAP(0x01, 0x07), /* 0x23: MBOX_GET_TAG_AGE_LIMIT */
! 4821: ISPOPMAP(0x01, 0x03), /* 0x24: MBOX_GET_CLOCK_RATE */
! 4822: ISPOPMAP(0x01, 0x07), /* 0x25: MBOX_GET_ACT_NEG_STATE */
! 4823: ISPOPMAP(0x01, 0x07), /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */
! 4824: ISPOPMAP(0x01, 0x07), /* 0x27: MBOX_GET_PCI_PARAMS */
! 4825: ISPOPMAP(0x03, 0x4f), /* 0x28: MBOX_GET_TARGET_PARAMS */
! 4826: ISPOPMAP(0x03, 0x0f), /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */
! 4827: ISPOPMAP(0x01, 0x07), /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */
! 4828: ISPOPMAP(0x00, 0x00), /* 0x2b: */
! 4829: ISPOPMAP(0x00, 0x00), /* 0x2c: */
! 4830: ISPOPMAP(0x00, 0x00), /* 0x2d: */
! 4831: ISPOPMAP(0x00, 0x00), /* 0x2e: */
! 4832: ISPOPMAP(0x00, 0x00), /* 0x2f: */
! 4833: ISPOPMAP(0x03, 0x03), /* 0x30: MBOX_SET_INIT_SCSI_ID */
! 4834: ISPOPMAP(0x07, 0x07), /* 0x31: MBOX_SET_SELECT_TIMEOUT */
! 4835: ISPOPMAP(0xc7, 0xc7), /* 0x32: MBOX_SET_RETRY_COUNT */
! 4836: ISPOPMAP(0x07, 0x07), /* 0x33: MBOX_SET_TAG_AGE_LIMIT */
! 4837: ISPOPMAP(0x03, 0x03), /* 0x34: MBOX_SET_CLOCK_RATE */
! 4838: ISPOPMAP(0x07, 0x07), /* 0x35: MBOX_SET_ACT_NEG_STATE */
! 4839: ISPOPMAP(0x07, 0x07), /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */
! 4840: ISPOPMAP(0x07, 0x07), /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */
! 4841: ISPOPMAP(0x4f, 0x4f), /* 0x38: MBOX_SET_TARGET_PARAMS */
! 4842: ISPOPMAP(0x0f, 0x0f), /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */
! 4843: ISPOPMAP(0x07, 0x07), /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */
! 4844: ISPOPMAP(0x00, 0x00), /* 0x3b: */
! 4845: ISPOPMAP(0x00, 0x00), /* 0x3c: */
! 4846: ISPOPMAP(0x00, 0x00), /* 0x3d: */
! 4847: ISPOPMAP(0x00, 0x00), /* 0x3e: */
! 4848: ISPOPMAP(0x00, 0x00), /* 0x3f: */
! 4849: ISPOPMAP(0x01, 0x03), /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */
! 4850: ISPOPMAP(0x3f, 0x01), /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */
! 4851: ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_EXEC_BIOS_IOCB */
! 4852: ISPOPMAP(0x00, 0x00), /* 0x43: */
! 4853: ISPOPMAP(0x00, 0x00), /* 0x44: */
! 4854: ISPOPMAP(0x03, 0x03), /* 0x45: SET SYSTEM PARAMETER */
! 4855: ISPOPMAP(0x01, 0x03), /* 0x46: GET SYSTEM PARAMETER */
! 4856: ISPOPMAP(0x00, 0x00), /* 0x47: */
! 4857: ISPOPMAP(0x01, 0xcf), /* 0x48: GET SCAM CONFIGURATION */
! 4858: ISPOPMAP(0xcf, 0xcf), /* 0x49: SET SCAM CONFIGURATION */
! 4859: ISPOPMAP(0x03, 0x03), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */
! 4860: ISPOPMAP(0x01, 0x03), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */
! 4861: ISPOPMAP(0x00, 0x00), /* 0x4c: */
! 4862: ISPOPMAP(0x00, 0x00), /* 0x4d: */
! 4863: ISPOPMAP(0x00, 0x00), /* 0x4e: */
! 4864: ISPOPMAP(0x00, 0x00), /* 0x4f: */
! 4865: ISPOPMAP(0xdf, 0xdf), /* 0x50: LOAD RAM A64 */
! 4866: ISPOPMAP(0xdf, 0xdf), /* 0x51: DUMP RAM A64 */
! 4867: ISPOPMAP(0xdf, 0xff), /* 0x52: INITIALIZE REQUEST QUEUE A64 */
! 4868: ISPOPMAP(0xef, 0xff), /* 0x53: INITIALIZE RESPONSE QUEUE A64 */
! 4869: ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
! 4870: ISPOPMAP(0x07, 0x01), /* 0x55: ENABLE TARGET MODE */
! 4871: ISPOPMAP(0x03, 0x0f), /* 0x56: GET TARGET STATUS */
! 4872: ISPOPMAP(0x00, 0x00), /* 0x57: */
! 4873: ISPOPMAP(0x00, 0x00), /* 0x58: */
! 4874: ISPOPMAP(0x00, 0x00), /* 0x59: */
! 4875: ISPOPMAP(0x03, 0x03), /* 0x5a: SET DATA OVERRUN RECOVERY MODE */
! 4876: ISPOPMAP(0x01, 0x03), /* 0x5b: GET DATA OVERRUN RECOVERY MODE */
! 4877: ISPOPMAP(0x0f, 0x0f), /* 0x5c: SET HOST DATA */
! 4878: ISPOPMAP(0x01, 0x01) /* 0x5d: GET NOST DATA */
! 4879: };
! 4880:
! 4881: #ifdef SMALL_KERNEL
! 4882: #define ISP_STRIPPED
! 4883: #endif
! 4884:
! 4885: #ifndef ISP_STRIPPED
! 4886: static char *scsi_mbcmd_names[] = {
! 4887: "NO-OP",
! 4888: "LOAD RAM",
! 4889: "EXEC FIRMWARE",
! 4890: "DUMP RAM",
! 4891: "WRITE RAM WORD",
! 4892: "READ RAM WORD",
! 4893: "MAILBOX REG TEST",
! 4894: "VERIFY CHECKSUM",
! 4895: "ABOUT FIRMWARE",
! 4896: NULL,
! 4897: NULL,
! 4898: NULL,
! 4899: NULL,
! 4900: NULL,
! 4901: "CHECK FIRMWARE",
! 4902: NULL,
! 4903: "INIT REQUEST QUEUE",
! 4904: "INIT RESULT QUEUE",
! 4905: "EXECUTE IOCB",
! 4906: "WAKE UP",
! 4907: "STOP FIRMWARE",
! 4908: "ABORT",
! 4909: "ABORT DEVICE",
! 4910: "ABORT TARGET",
! 4911: "BUS RESET",
! 4912: "STOP QUEUE",
! 4913: "START QUEUE",
! 4914: "SINGLE STEP QUEUE",
! 4915: "ABORT QUEUE",
! 4916: "GET DEV QUEUE STATUS",
! 4917: NULL,
! 4918: "GET FIRMWARE STATUS",
! 4919: "GET INIT SCSI ID",
! 4920: "GET SELECT TIMEOUT",
! 4921: "GET RETRY COUNT",
! 4922: "GET TAG AGE LIMIT",
! 4923: "GET CLOCK RATE",
! 4924: "GET ACT NEG STATE",
! 4925: "GET ASYNC DATA SETUP TIME",
! 4926: "GET PCI PARAMS",
! 4927: "GET TARGET PARAMS",
! 4928: "GET DEV QUEUE PARAMS",
! 4929: "GET RESET DELAY PARAMS",
! 4930: NULL,
! 4931: NULL,
! 4932: NULL,
! 4933: NULL,
! 4934: NULL,
! 4935: "SET INIT SCSI ID",
! 4936: "SET SELECT TIMEOUT",
! 4937: "SET RETRY COUNT",
! 4938: "SET TAG AGE LIMIT",
! 4939: "SET CLOCK RATE",
! 4940: "SET ACT NEG STATE",
! 4941: "SET ASYNC DATA SETUP TIME",
! 4942: "SET PCI CONTROL PARAMS",
! 4943: "SET TARGET PARAMS",
! 4944: "SET DEV QUEUE PARAMS",
! 4945: "SET RESET DELAY PARAMS",
! 4946: NULL,
! 4947: NULL,
! 4948: NULL,
! 4949: NULL,
! 4950: NULL,
! 4951: "RETURN BIOS BLOCK ADDR",
! 4952: "WRITE FOUR RAM WORDS",
! 4953: "EXEC BIOS IOCB",
! 4954: NULL,
! 4955: NULL,
! 4956: "SET SYSTEM PARAMETER",
! 4957: "GET SYSTEM PARAMETER",
! 4958: NULL,
! 4959: "GET SCAM CONFIGURATION",
! 4960: "SET SCAM CONFIGURATION",
! 4961: "SET FIRMWARE FEATURES",
! 4962: "GET FIRMWARE FEATURES",
! 4963: NULL,
! 4964: NULL,
! 4965: NULL,
! 4966: NULL,
! 4967: "LOAD RAM A64",
! 4968: "DUMP RAM A64",
! 4969: "INITIALIZE REQUEST QUEUE A64",
! 4970: "INITIALIZE RESPONSE QUEUE A64",
! 4971: "EXECUTE IOCB A64",
! 4972: "ENABLE TARGET MODE",
! 4973: "GET TARGET MODE STATE",
! 4974: NULL,
! 4975: NULL,
! 4976: NULL,
! 4977: "SET DATA OVERRUN RECOVERY MODE",
! 4978: "GET DATA OVERRUN RECOVERY MODE",
! 4979: "SET HOST DATA",
! 4980: "GET NOST DATA",
! 4981: };
! 4982: #endif
! 4983:
! 4984: static const u_int16_t mbpfc[] = {
! 4985: ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
! 4986: ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
! 4987: ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */
! 4988: ISPOPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */
! 4989: ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
! 4990: ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
! 4991: ISPOPMAP(0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */
! 4992: ISPOPMAP(0x03, 0x05), /* 0x07: MBOX_VERIFY_CHECKSUM */
! 4993: ISPOPMAP(0x01, 0x4f), /* 0x08: MBOX_ABOUT_FIRMWARE */
! 4994: ISPOPMAP(0xdf, 0x01), /* 0x09: LOAD RAM */
! 4995: ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
! 4996: ISPOPMAP(0x00, 0x00), /* 0x0b: */
! 4997: ISPOPMAP(0x00, 0x00), /* 0x0c: */
! 4998: ISPOPMAP(0x00, 0x00), /* 0x0d: */
! 4999: ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
! 5000: ISPOPMAP(0x03, 0x07), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED(1) */
! 5001: ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
! 5002: ISPOPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
! 5003: ISPOPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
! 5004: ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
! 5005: ISPOPMAP(0x01, 0xff), /* 0x14: MBOX_STOP_FIRMWARE */
! 5006: ISPOPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */
! 5007: ISPOPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */
! 5008: ISPOPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */
! 5009: ISPOPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */
! 5010: ISPOPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */
! 5011: ISPOPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */
! 5012: ISPOPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
! 5013: ISPOPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */
! 5014: ISPOPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
! 5015: ISPOPMAP(0x00, 0x00), /* 0x1e: */
! 5016: ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
! 5017: ISPOPMAP(0x01, 0x4f), /* 0x20: MBOX_GET_LOOP_ID */
! 5018: ISPOPMAP(0x00, 0x00), /* 0x21: */
! 5019: ISPOPMAP(0x01, 0x07), /* 0x22: MBOX_GET_RETRY_COUNT */
! 5020: ISPOPMAP(0x00, 0x00), /* 0x23: */
! 5021: ISPOPMAP(0x00, 0x00), /* 0x24: */
! 5022: ISPOPMAP(0x00, 0x00), /* 0x25: */
! 5023: ISPOPMAP(0x00, 0x00), /* 0x26: */
! 5024: ISPOPMAP(0x00, 0x00), /* 0x27: */
! 5025: ISPOPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
! 5026: ISPOPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
! 5027: ISPOPMAP(0x00, 0x00), /* 0x2a: */
! 5028: ISPOPMAP(0x00, 0x00), /* 0x2b: */
! 5029: ISPOPMAP(0x00, 0x00), /* 0x2c: */
! 5030: ISPOPMAP(0x00, 0x00), /* 0x2d: */
! 5031: ISPOPMAP(0x00, 0x00), /* 0x2e: */
! 5032: ISPOPMAP(0x00, 0x00), /* 0x2f: */
! 5033: ISPOPMAP(0x00, 0x00), /* 0x30: */
! 5034: ISPOPMAP(0x00, 0x00), /* 0x31: */
! 5035: ISPOPMAP(0x07, 0x07), /* 0x32: MBOX_SET_RETRY_COUNT */
! 5036: ISPOPMAP(0x00, 0x00), /* 0x33: */
! 5037: ISPOPMAP(0x00, 0x00), /* 0x34: */
! 5038: ISPOPMAP(0x00, 0x00), /* 0x35: */
! 5039: ISPOPMAP(0x00, 0x00), /* 0x36: */
! 5040: ISPOPMAP(0x00, 0x00), /* 0x37: */
! 5041: ISPOPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
! 5042: ISPOPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
! 5043: ISPOPMAP(0x00, 0x00), /* 0x3a: */
! 5044: ISPOPMAP(0x00, 0x00), /* 0x3b: */
! 5045: ISPOPMAP(0x00, 0x00), /* 0x3c: */
! 5046: ISPOPMAP(0x00, 0x00), /* 0x3d: */
! 5047: ISPOPMAP(0x00, 0x00), /* 0x3e: */
! 5048: ISPOPMAP(0x00, 0x00), /* 0x3f: */
! 5049: ISPOPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */
! 5050: ISPOPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */
! 5051: ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_GET_RESOURCE_COUNTS */
! 5052: ISPOPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_NON_PARTICIPATING_MODE */
! 5053: ISPOPMAP(0x00, 0x00), /* 0x44: */
! 5054: ISPOPMAP(0x00, 0x00), /* 0x45: */
! 5055: ISPOPMAP(0x00, 0x00), /* 0x46: */
! 5056: ISPOPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */
! 5057: ISPOPMAP(0x00, 0x00), /* 0x48: */
! 5058: ISPOPMAP(0x00, 0x00), /* 0x49: */
! 5059: ISPOPMAP(0x00, 0x00), /* 0x4a: */
! 5060: ISPOPMAP(0x00, 0x00), /* 0x4b: */
! 5061: ISPOPMAP(0x00, 0x00), /* 0x4c: */
! 5062: ISPOPMAP(0x00, 0x00), /* 0x4d: */
! 5063: ISPOPMAP(0x00, 0x00), /* 0x4e: */
! 5064: ISPOPMAP(0x00, 0x00), /* 0x4f: */
! 5065: ISPOPMAP(0x00, 0x00), /* 0x50: */
! 5066: ISPOPMAP(0x00, 0x00), /* 0x51: */
! 5067: ISPOPMAP(0x00, 0x00), /* 0x52: */
! 5068: ISPOPMAP(0x00, 0x00), /* 0x53: */
! 5069: ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
! 5070: ISPOPMAP(0x00, 0x00), /* 0x55: */
! 5071: ISPOPMAP(0x00, 0x00), /* 0x56: */
! 5072: ISPOPMAP(0x00, 0x00), /* 0x57: */
! 5073: ISPOPMAP(0x00, 0x00), /* 0x58: */
! 5074: ISPOPMAP(0x00, 0x00), /* 0x59: */
! 5075: ISPOPMAP(0x00, 0x00), /* 0x5a: */
! 5076: ISPOPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
! 5077: ISPOPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
! 5078: ISPOPMAP(0x07, 0x03), /* 0x5d: MBOX_GET_SET_DATA_RATE */
! 5079: ISPOPMAP(0x00, 0x00), /* 0x5e: */
! 5080: ISPOPMAP(0x00, 0x00), /* 0x5f: */
! 5081: ISPOPMAP(0xfd, 0x31), /* 0x60: MBOX_INIT_FIRMWARE */
! 5082: ISPOPMAP(0x00, 0x00), /* 0x61: */
! 5083: ISPOPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */
! 5084: ISPOPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
! 5085: ISPOPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
! 5086: ISPOPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */
! 5087: ISPOPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */
! 5088: ISPOPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */
! 5089: ISPOPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */
! 5090: ISPOPMAP(0x01, 0x07), /* 0x69: MBOX_GET_FW_STATE */
! 5091: ISPOPMAP(0x03, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */
! 5092: ISPOPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */
! 5093: ISPOPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */
! 5094: ISPOPMAP(0x00, 0x00), /* 0x6d: */
! 5095: ISPOPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */
! 5096: ISPOPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */
! 5097: ISPOPMAP(0x03, 0x01), /* 0x70: MBOX_SEND_CHANGE_REQUEST */
! 5098: ISPOPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */
! 5099: ISPOPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */
! 5100: ISPOPMAP(0x00, 0x00), /* 0x73: */
! 5101: ISPOPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */
! 5102: ISPOPMAP(0xcf, 0x03), /* 0x75: GET PORT/NODE NAME LIST */
! 5103: ISPOPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */
! 5104: ISPOPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */
! 5105: ISPOPMAP(0x00, 0x00), /* 0x78: */
! 5106: ISPOPMAP(0x00, 0x00), /* 0x79: */
! 5107: ISPOPMAP(0x00, 0x00), /* 0x7a: */
! 5108: ISPOPMAP(0x00, 0x00), /* 0x7b: */
! 5109: ISPOPMAP(0x4f, 0x03), /* 0x7c: Get ID List */
! 5110: ISPOPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */
! 5111: ISPOPMAP(0x07, 0x01) /* 0x7e: Lun RESET */
! 5112: };
! 5113: /*
! 5114: * Footnotes
! 5115: *
! 5116: * (1): this sets bits 21..16 in mailbox register #8, which we nominally
! 5117: * do not access at this time in the core driver. The caller is
! 5118: * responsible for setting this register first (Gross!).
! 5119: */
! 5120:
! 5121: #ifndef ISP_STRIPPED
! 5122: static char *fc_mbcmd_names[] = {
! 5123: "NO-OP",
! 5124: "LOAD RAM",
! 5125: "EXEC FIRMWARE",
! 5126: "DUMP RAM",
! 5127: "WRITE RAM WORD",
! 5128: "READ RAM WORD",
! 5129: "MAILBOX REG TEST",
! 5130: "VERIFY CHECKSUM",
! 5131: "ABOUT FIRMWARE",
! 5132: "LOAD RAM",
! 5133: "DUMP RAM",
! 5134: NULL,
! 5135: NULL,
! 5136: "READ RAM WORD EXTENDED",
! 5137: "CHECK FIRMWARE",
! 5138: NULL,
! 5139: "INIT REQUEST QUEUE",
! 5140: "INIT RESULT QUEUE",
! 5141: "EXECUTE IOCB",
! 5142: "WAKE UP",
! 5143: "STOP FIRMWARE",
! 5144: "ABORT",
! 5145: "ABORT DEVICE",
! 5146: "ABORT TARGET",
! 5147: "BUS RESET",
! 5148: "STOP QUEUE",
! 5149: "START QUEUE",
! 5150: "SINGLE STEP QUEUE",
! 5151: "ABORT QUEUE",
! 5152: "GET DEV QUEUE STATUS",
! 5153: NULL,
! 5154: "GET FIRMWARE STATUS",
! 5155: "GET LOOP ID",
! 5156: NULL,
! 5157: "GET RETRY COUNT",
! 5158: NULL,
! 5159: NULL,
! 5160: NULL,
! 5161: NULL,
! 5162: NULL,
! 5163: "GET FIRMWARE OPTIONS",
! 5164: "GET PORT QUEUE PARAMS",
! 5165: NULL,
! 5166: NULL,
! 5167: NULL,
! 5168: NULL,
! 5169: NULL,
! 5170: NULL,
! 5171: NULL,
! 5172: NULL,
! 5173: "SET RETRY COUNT",
! 5174: NULL,
! 5175: NULL,
! 5176: NULL,
! 5177: NULL,
! 5178: NULL,
! 5179: "SET FIRMWARE OPTIONS",
! 5180: "SET PORT QUEUE PARAMS",
! 5181: NULL,
! 5182: NULL,
! 5183: NULL,
! 5184: NULL,
! 5185: NULL,
! 5186: NULL,
! 5187: "LOOP PORT BYPASS",
! 5188: "LOOP PORT ENABLE",
! 5189: "GET RESOURCE COUNTS",
! 5190: "REQUEST NON PARTICIPATING MODE",
! 5191: NULL,
! 5192: NULL,
! 5193: NULL,
! 5194: "GET PORT DATABASE,, ENHANCED",
! 5195: NULL,
! 5196: NULL,
! 5197: NULL,
! 5198: NULL,
! 5199: NULL,
! 5200: NULL,
! 5201: NULL,
! 5202: NULL,
! 5203: NULL,
! 5204: NULL,
! 5205: NULL,
! 5206: NULL,
! 5207: "EXECUTE IOCB A64",
! 5208: NULL,
! 5209: NULL,
! 5210: NULL,
! 5211: NULL,
! 5212: NULL,
! 5213: NULL,
! 5214: "DRIVER HEARTBEAT",
! 5215: NULL,
! 5216: "GET/SET DATA RATE",
! 5217: NULL,
! 5218: NULL,
! 5219: "INIT FIRMWARE",
! 5220: NULL,
! 5221: "INIT LIP",
! 5222: "GET FC-AL POSITION MAP",
! 5223: "GET PORT DATABASE",
! 5224: "CLEAR ACA",
! 5225: "TARGET RESET",
! 5226: "CLEAR TASK SET",
! 5227: "ABORT TASK SET",
! 5228: "GET FW STATE",
! 5229: "GET PORT NAME",
! 5230: "GET LINK STATUS",
! 5231: "INIT LIP RESET",
! 5232: NULL,
! 5233: "SEND SNS",
! 5234: "FABRIC LOGIN",
! 5235: "SEND CHANGE REQUEST",
! 5236: "FABRIC LOGOUT",
! 5237: "INIT LIP LOGIN",
! 5238: NULL,
! 5239: "LOGIN LOOP PORT",
! 5240: "GET PORT/NODE NAME LIST",
! 5241: "SET VENDOR ID",
! 5242: "INITIALIZE IP MAILBOX",
! 5243: NULL,
! 5244: NULL,
! 5245: NULL,
! 5246: NULL,
! 5247: "Get ID List",
! 5248: "SEND LFA",
! 5249: "Lun RESET"
! 5250: };
! 5251: #endif
! 5252:
! 5253: static void
! 5254: isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay)
! 5255: {
! 5256: unsigned int lim, ibits, obits, box, opcode;
! 5257: const u_int16_t *mcp;
! 5258:
! 5259: if (IS_FC(isp)) {
! 5260: mcp = mbpfc;
! 5261: lim = (sizeof (mbpfc) / sizeof (mbpfc[0]));
! 5262: } else {
! 5263: mcp = mbpscsi;
! 5264: lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0]));
! 5265: }
! 5266: opcode = mbp->param[0];
! 5267: ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp);
! 5268: obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp);
! 5269: for (box = 0; box < MAX_MAILBOX; box++) {
! 5270: if (ibits & (1 << box)) {
! 5271: ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
! 5272: }
! 5273: if (nodelay == 0) {
! 5274: isp->isp_mboxtmp[box] = mbp->param[box] = 0;
! 5275: }
! 5276: }
! 5277: if (nodelay == 0) {
! 5278: isp->isp_lastmbxcmd = opcode;
! 5279: isp->isp_obits = obits;
! 5280: isp->isp_mboxbsy = 1;
! 5281: }
! 5282: ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
! 5283: /*
! 5284: * Oddly enough, if we're not delaying for an answer,
! 5285: * delay a bit to give the f/w a chance to pick up the
! 5286: * command.
! 5287: */
! 5288: if (nodelay) {
! 5289: USEC_DELAY(1000);
! 5290: }
! 5291: }
! 5292:
! 5293: static void
! 5294: isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask)
! 5295: {
! 5296: char *cname, *xname, tname[16], mname[16];
! 5297: unsigned int lim, ibits, obits, box, opcode;
! 5298: const u_int16_t *mcp;
! 5299:
! 5300: if (IS_FC(isp)) {
! 5301: mcp = mbpfc;
! 5302: lim = (sizeof (mbpfc) / sizeof (mbpfc[0]));
! 5303: } else {
! 5304: mcp = mbpscsi;
! 5305: lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0]));
! 5306: }
! 5307:
! 5308: if ((opcode = mbp->param[0]) >= lim) {
! 5309: mbp->param[0] = MBOX_INVALID_COMMAND;
! 5310: isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
! 5311: return;
! 5312: }
! 5313:
! 5314: ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp);
! 5315: obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp);
! 5316:
! 5317: if (ibits == 0 && obits == 0) {
! 5318: mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
! 5319: isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
! 5320: return;
! 5321: }
! 5322:
! 5323: /*
! 5324: * Get exclusive usage of mailbox registers.
! 5325: */
! 5326: MBOX_ACQUIRE(isp);
! 5327:
! 5328: for (box = 0; box < MAX_MAILBOX; box++) {
! 5329: if (ibits & (1 << box)) {
! 5330: ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
! 5331: }
! 5332: isp->isp_mboxtmp[box] = mbp->param[box] = 0;
! 5333: }
! 5334:
! 5335: isp->isp_lastmbxcmd = opcode;
! 5336:
! 5337: /*
! 5338: * We assume that we can't overwrite a previous command.
! 5339: */
! 5340: isp->isp_obits = obits;
! 5341: isp->isp_mboxbsy = 1;
! 5342:
! 5343: /*
! 5344: * Set Host Interrupt condition so that RISC will pick up mailbox regs.
! 5345: */
! 5346: ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
! 5347:
! 5348: /*
! 5349: * While we haven't finished the command, spin our wheels here.
! 5350: */
! 5351: MBOX_WAIT_COMPLETE(isp);
! 5352:
! 5353: if (isp->isp_mboxbsy) {
! 5354: /*
! 5355: * Command timed out.
! 5356: */
! 5357: isp->isp_mboxbsy = 0;
! 5358: MBOX_RELEASE(isp);
! 5359: return;
! 5360: }
! 5361:
! 5362: /*
! 5363: * Copy back output registers.
! 5364: */
! 5365: for (box = 0; box < MAX_MAILBOX; box++) {
! 5366: if (obits & (1 << box)) {
! 5367: mbp->param[box] = isp->isp_mboxtmp[box];
! 5368: }
! 5369: }
! 5370:
! 5371: MBOX_RELEASE(isp);
! 5372:
! 5373: if (logmask == 0 || opcode == MBOX_EXEC_FIRMWARE) {
! 5374: return;
! 5375: }
! 5376: #ifdef ISP_STRIPPED
! 5377: cname = NULL;
! 5378: #else
! 5379: cname = (IS_FC(isp))? fc_mbcmd_names[opcode] : scsi_mbcmd_names[opcode];
! 5380: #endif
! 5381: if (cname == NULL) {
! 5382: cname = tname;
! 5383: SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
! 5384: }
! 5385:
! 5386: /*
! 5387: * Just to be chatty here...
! 5388: */
! 5389: xname = NULL;
! 5390: switch (mbp->param[0]) {
! 5391: case MBOX_COMMAND_COMPLETE:
! 5392: break;
! 5393: case MBOX_INVALID_COMMAND:
! 5394: if (logmask & MBLOGMASK(MBOX_COMMAND_COMPLETE))
! 5395: xname = "INVALID COMMAND";
! 5396: break;
! 5397: case MBOX_HOST_INTERFACE_ERROR:
! 5398: if (logmask & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR))
! 5399: xname = "HOST INTERFACE ERROR";
! 5400: break;
! 5401: case MBOX_TEST_FAILED:
! 5402: if (logmask & MBLOGMASK(MBOX_TEST_FAILED))
! 5403: xname = "TEST FAILED";
! 5404: break;
! 5405: case MBOX_COMMAND_ERROR:
! 5406: if (logmask & MBLOGMASK(MBOX_COMMAND_ERROR))
! 5407: xname = "COMMAND ERROR";
! 5408: break;
! 5409: case MBOX_COMMAND_PARAM_ERROR:
! 5410: if (logmask & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR))
! 5411: xname = "COMMAND PARAMETER ERROR";
! 5412: break;
! 5413: case MBOX_LOOP_ID_USED:
! 5414: if (logmask & MBLOGMASK(MBOX_LOOP_ID_USED))
! 5415: xname = "LOOP ID ALREADY IN USE";
! 5416: break;
! 5417: case MBOX_PORT_ID_USED:
! 5418: if (logmask & MBLOGMASK(MBOX_PORT_ID_USED))
! 5419: xname = "PORT ID ALREADY IN USE";
! 5420: break;
! 5421: case MBOX_ALL_IDS_USED:
! 5422: if (logmask & MBLOGMASK(MBOX_ALL_IDS_USED))
! 5423: xname = "ALL LOOP IDS IN USE";
! 5424: break;
! 5425: case 0: /* special case */
! 5426: xname = "TIMEOUT";
! 5427: break;
! 5428: default:
! 5429: SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
! 5430: xname = mname;
! 5431: break;
! 5432: }
! 5433: if (xname)
! 5434: isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s)",
! 5435: cname, xname);
! 5436: }
! 5437:
! 5438: static void
! 5439: isp_fw_state(struct ispsoftc *isp)
! 5440: {
! 5441: if (IS_FC(isp)) {
! 5442: mbreg_t mbs;
! 5443: fcparam *fcp = isp->isp_param;
! 5444:
! 5445: mbs.param[0] = MBOX_GET_FW_STATE;
! 5446: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 5447: if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
! 5448: fcp->isp_fwstate = mbs.param[1];
! 5449: }
! 5450: }
! 5451: }
! 5452:
! 5453: static void
! 5454: isp_update(struct ispsoftc *isp)
! 5455: {
! 5456: int bus, upmask;
! 5457:
! 5458: for (bus = 0, upmask = isp->isp_update; upmask != 0; bus++) {
! 5459: if (upmask & (1 << bus)) {
! 5460: isp_update_bus(isp, bus);
! 5461: }
! 5462: upmask &= ~(1 << bus);
! 5463: }
! 5464: }
! 5465:
! 5466: static void
! 5467: isp_update_bus(struct ispsoftc *isp, int bus)
! 5468: {
! 5469: int tgt;
! 5470: mbreg_t mbs;
! 5471: sdparam *sdp;
! 5472:
! 5473: isp->isp_update &= ~(1 << bus);
! 5474: if (IS_FC(isp)) {
! 5475: /*
! 5476: * There are no 'per-bus' settings for Fibre Channel.
! 5477: */
! 5478: return;
! 5479: }
! 5480: sdp = isp->isp_param;
! 5481: sdp += bus;
! 5482:
! 5483: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 5484: u_int16_t flags, period, offset;
! 5485: int get;
! 5486:
! 5487: if (sdp->isp_devparam[tgt].dev_enable == 0) {
! 5488: sdp->isp_devparam[tgt].dev_update = 0;
! 5489: sdp->isp_devparam[tgt].dev_refresh = 0;
! 5490: isp_prt(isp, ISP_LOGDEBUG0,
! 5491: "skipping target %d bus %d update", tgt, bus);
! 5492: continue;
! 5493: }
! 5494: /*
! 5495: * If the goal is to update the status of the device,
! 5496: * take what's in goal_flags and try and set the device
! 5497: * toward that. Otherwise, if we're just refreshing the
! 5498: * current device state, get the current parameters.
! 5499: */
! 5500:
! 5501: /*
! 5502: * Refresh overrides set
! 5503: */
! 5504: if (sdp->isp_devparam[tgt].dev_refresh) {
! 5505: mbs.param[0] = MBOX_GET_TARGET_PARAMS;
! 5506: sdp->isp_devparam[tgt].dev_refresh = 0;
! 5507: get = 1;
! 5508: } else if (sdp->isp_devparam[tgt].dev_update) {
! 5509: mbs.param[0] = MBOX_SET_TARGET_PARAMS;
! 5510: /*
! 5511: * Make sure goal_flags has "Renegotiate on Error"
! 5512: * on and "Freeze Queue on Error" off.
! 5513: */
! 5514: sdp->isp_devparam[tgt].goal_flags |= DPARM_RENEG;
! 5515: sdp->isp_devparam[tgt].goal_flags &= ~DPARM_QFRZ;
! 5516:
! 5517: mbs.param[2] = sdp->isp_devparam[tgt].goal_flags;
! 5518:
! 5519: /*
! 5520: * Insist that PARITY must be enabled
! 5521: * if SYNC or WIDE is enabled.
! 5522: */
! 5523: if ((mbs.param[2] & (DPARM_SYNC|DPARM_WIDE)) != 0) {
! 5524: mbs.param[2] |= DPARM_PARITY;
! 5525: }
! 5526:
! 5527: if ((mbs.param[2] & DPARM_SYNC) == 0) {
! 5528: mbs.param[3] = 0;
! 5529: } else {
! 5530: mbs.param[3] =
! 5531: (sdp->isp_devparam[tgt].goal_offset << 8) |
! 5532: (sdp->isp_devparam[tgt].goal_period);
! 5533: }
! 5534: /*
! 5535: * A command completion later that has
! 5536: * RQSTF_NEGOTIATION set can cause
! 5537: * the dev_refresh/announce cycle also.
! 5538: *
! 5539: * Note: It is really important to update our current
! 5540: * flags with at least the state of TAG capabilities-
! 5541: * otherwise we might try and send a tagged command
! 5542: * when we have it all turned off. So change it here
! 5543: * to say that current already matches goal.
! 5544: */
! 5545: sdp->isp_devparam[tgt].actv_flags &= ~DPARM_TQING;
! 5546: sdp->isp_devparam[tgt].actv_flags |=
! 5547: (sdp->isp_devparam[tgt].goal_flags & DPARM_TQING);
! 5548: isp_prt(isp, ISP_LOGDEBUG0,
! 5549: "bus %d set tgt %d flags 0x%x off 0x%x period 0x%x",
! 5550: bus, tgt, mbs.param[2], mbs.param[3] >> 8,
! 5551: mbs.param[3] & 0xff);
! 5552: sdp->isp_devparam[tgt].dev_update = 0;
! 5553: sdp->isp_devparam[tgt].dev_refresh = 1;
! 5554: get = 0;
! 5555: } else {
! 5556: continue;
! 5557: }
! 5558: mbs.param[1] = (bus << 15) | (tgt << 8);
! 5559: isp_mboxcmd(isp, &mbs, MBLOGALL);
! 5560: if (get == 0) {
! 5561: isp->isp_sendmarker |= (1 << bus);
! 5562: continue;
! 5563: }
! 5564: flags = mbs.param[2];
! 5565: period = mbs.param[3] & 0xff;
! 5566: offset = mbs.param[3] >> 8;
! 5567: sdp->isp_devparam[tgt].actv_flags = flags;
! 5568: sdp->isp_devparam[tgt].actv_period = period;
! 5569: sdp->isp_devparam[tgt].actv_offset = offset;
! 5570: get = (bus << 16) | tgt;
! 5571: (void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get);
! 5572: }
! 5573:
! 5574: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 5575: if (sdp->isp_devparam[tgt].dev_update ||
! 5576: sdp->isp_devparam[tgt].dev_refresh) {
! 5577: isp->isp_update |= (1 << bus);
! 5578: break;
! 5579: }
! 5580: }
! 5581: }
! 5582:
! 5583: #ifndef DEFAULT_FRAMESIZE
! 5584: #define DEFAULT_FRAMESIZE(isp) ICB_DFLT_FRMLEN
! 5585: #endif
! 5586: #ifndef DEFAULT_EXEC_THROTTLE
! 5587: #define DEFAULT_EXEC_THROTTLE(isp) ISP_EXEC_THROTTLE
! 5588: #endif
! 5589:
! 5590: static void
! 5591: isp_setdfltparm(struct ispsoftc *isp, int channel)
! 5592: {
! 5593: int tgt;
! 5594: mbreg_t mbs;
! 5595: sdparam *sdp;
! 5596:
! 5597: if (IS_FC(isp)) {
! 5598: fcparam *fcp = (fcparam *) isp->isp_param;
! 5599: int nvfail;
! 5600:
! 5601: fcp += channel;
! 5602: if (fcp->isp_gotdparms) {
! 5603: return;
! 5604: }
! 5605: fcp->isp_gotdparms = 1;
! 5606: fcp->isp_maxfrmlen = DEFAULT_FRAMESIZE(isp);
! 5607: fcp->isp_maxalloc = ICB_DFLT_ALLOC;
! 5608: fcp->isp_execthrottle = DEFAULT_EXEC_THROTTLE(isp);
! 5609: fcp->isp_retry_delay = ICB_DFLT_RDELAY;
! 5610: fcp->isp_retry_count = ICB_DFLT_RCOUNT;
! 5611: /* Platform specific.... */
! 5612: fcp->isp_loopid = DEFAULT_LOOPID(isp);
! 5613: fcp->isp_nodewwn = DEFAULT_NODEWWN(isp);
! 5614: fcp->isp_portwwn = DEFAULT_PORTWWN(isp);
! 5615: fcp->isp_fwoptions = 0;
! 5616: fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
! 5617: fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
! 5618: fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
! 5619: #ifndef ISP_NO_FASTPOST_FC
! 5620: fcp->isp_fwoptions |= ICBOPT_FAST_POST;
! 5621: #endif
! 5622: if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
! 5623: fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
! 5624:
! 5625: /*
! 5626: * Make sure this is turned off now until we get
! 5627: * extended options from NVRAM
! 5628: */
! 5629: fcp->isp_fwoptions &= ~ICBOPT_EXTENDED;
! 5630:
! 5631: /*
! 5632: * Now try and read NVRAM unless told to not do so.
! 5633: * This will set fcparam's isp_nodewwn && isp_portwwn.
! 5634: */
! 5635: if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
! 5636: nvfail = isp_read_nvram(isp);
! 5637: if (nvfail)
! 5638: isp->isp_confopts |= ISP_CFG_NONVRAM;
! 5639: } else {
! 5640: nvfail = 1;
! 5641: }
! 5642: /*
! 5643: * Set node && port to override platform set defaults
! 5644: * unless the nvram read failed (or none was done),
! 5645: * or the platform code wants to use what had been
! 5646: * set in the defaults.
! 5647: */
! 5648: if (nvfail) {
! 5649: isp->isp_confopts |= ISP_CFG_OWNWWPN|ISP_CFG_OWNWWNN;
! 5650: }
! 5651: if (isp->isp_confopts & ISP_CFG_OWNWWNN) {
! 5652: isp_prt(isp, ISP_LOGCONFIG, "Using Node WWN 0x%08x%08x",
! 5653: (u_int32_t) (DEFAULT_NODEWWN(isp) >> 32),
! 5654: (u_int32_t) (DEFAULT_NODEWWN(isp) & 0xffffffff));
! 5655: ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
! 5656: } else {
! 5657: /*
! 5658: * We always start out with values derived
! 5659: * from NVRAM or our platform default.
! 5660: */
! 5661: ISP_NODEWWN(isp) = fcp->isp_nodewwn;
! 5662: }
! 5663: if (isp->isp_confopts & ISP_CFG_OWNWWPN) {
! 5664: isp_prt(isp, ISP_LOGCONFIG, "Using Port WWN 0x%08x%08x",
! 5665: (u_int32_t) (DEFAULT_PORTWWN(isp) >> 32),
! 5666: (u_int32_t) (DEFAULT_PORTWWN(isp) & 0xffffffff));
! 5667: ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
! 5668: } else {
! 5669: /*
! 5670: * We always start out with values derived
! 5671: * from NVRAM or our platform default.
! 5672: */
! 5673: ISP_PORTWWN(isp) = fcp->isp_portwwn;
! 5674: }
! 5675: return;
! 5676: }
! 5677:
! 5678: sdp = (sdparam *) isp->isp_param;
! 5679: sdp += channel;
! 5680:
! 5681: /*
! 5682: * Been there, done that, got the T-shirt...
! 5683: */
! 5684: if (sdp->isp_gotdparms) {
! 5685: return;
! 5686: }
! 5687: sdp->isp_gotdparms = 1;
! 5688:
! 5689: /*
! 5690: * Establish some default parameters.
! 5691: */
! 5692: sdp->isp_cmd_dma_burst_enable = 0;
! 5693: sdp->isp_data_dma_burst_enabl = 1;
! 5694: sdp->isp_fifo_threshold = 0;
! 5695: sdp->isp_initiator_id = DEFAULT_IID(isp);
! 5696: if (isp->isp_type >= ISP_HA_SCSI_1040) {
! 5697: sdp->isp_async_data_setup = 9;
! 5698: } else {
! 5699: sdp->isp_async_data_setup = 6;
! 5700: }
! 5701: sdp->isp_selection_timeout = 250;
! 5702: sdp->isp_max_queue_depth = MAXISPREQUEST(isp);
! 5703: sdp->isp_tag_aging = 8;
! 5704: sdp->isp_bus_reset_delay = 5;
! 5705: /*
! 5706: * Don't retry selection, busy or queue full automatically- reflect
! 5707: * these back to us.
! 5708: */
! 5709: sdp->isp_retry_count = 0;
! 5710: sdp->isp_retry_delay = 0;
! 5711:
! 5712: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 5713: sdp->isp_devparam[tgt].exc_throttle = ISP_EXEC_THROTTLE;
! 5714: sdp->isp_devparam[tgt].dev_enable = 1;
! 5715: }
! 5716:
! 5717: /*
! 5718: * If we've not been told to avoid reading NVRAM, try and read it.
! 5719: * If we're successful reading it, we can then return because NVRAM
! 5720: * will tell us what the desired settings are. Otherwise, we establish
! 5721: * some reasonable 'fake' nvram and goal defaults.
! 5722: */
! 5723:
! 5724: if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
! 5725: if (isp_read_nvram(isp) == 0) {
! 5726: return;
! 5727: }
! 5728: }
! 5729:
! 5730: /*
! 5731: * Now try and see whether we have specific values for them.
! 5732: */
! 5733: if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
! 5734: mbs.param[0] = MBOX_GET_ACT_NEG_STATE;
! 5735: isp_mboxcmd(isp, &mbs, MBLOGNONE);
! 5736: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 5737: sdp->isp_req_ack_active_neg = 1;
! 5738: sdp->isp_data_line_active_neg = 1;
! 5739: } else {
! 5740: sdp->isp_req_ack_active_neg =
! 5741: (mbs.param[1+channel] >> 4) & 0x1;
! 5742: sdp->isp_data_line_active_neg =
! 5743: (mbs.param[1+channel] >> 5) & 0x1;
! 5744: }
! 5745: }
! 5746:
! 5747: isp_prt(isp, ISP_LOGDEBUG0, sc0, sc3,
! 5748: 0, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
! 5749: sdp->isp_bus_reset_delay, sdp->isp_retry_count,
! 5750: sdp->isp_retry_delay, sdp->isp_async_data_setup);
! 5751: isp_prt(isp, ISP_LOGDEBUG0, sc1, sc3,
! 5752: sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
! 5753: sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
! 5754: sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
! 5755:
! 5756: /*
! 5757: * The trick here is to establish a default for the default (honk!)
! 5758: * state (goal_flags). Then try and get the current status from
! 5759: * the card to fill in the current state. We don't, in fact, set
! 5760: * the default to the SAFE default state- that's not the goal state.
! 5761: */
! 5762: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 5763: u_int8_t off, per;
! 5764: sdp->isp_devparam[tgt].actv_offset = 0;
! 5765: sdp->isp_devparam[tgt].actv_period = 0;
! 5766: sdp->isp_devparam[tgt].actv_flags = 0;
! 5767:
! 5768: sdp->isp_devparam[tgt].goal_flags =
! 5769: sdp->isp_devparam[tgt].nvrm_flags = DPARM_DEFAULT;
! 5770:
! 5771: /*
! 5772: * We default to Wide/Fast for versions less than a 1040
! 5773: * (unless its SBus).
! 5774: */
! 5775: if (IS_ULTRA3(isp)) {
! 5776: off = ISP_80M_SYNCPARMS >> 8;
! 5777: per = ISP_80M_SYNCPARMS & 0xff;
! 5778: } else if (IS_ULTRA2(isp)) {
! 5779: off = ISP_40M_SYNCPARMS >> 8;
! 5780: per = ISP_40M_SYNCPARMS & 0xff;
! 5781: } else if (IS_1240(isp)) {
! 5782: off = ISP_20M_SYNCPARMS >> 8;
! 5783: per = ISP_20M_SYNCPARMS & 0xff;
! 5784: } else if ((isp->isp_bustype == ISP_BT_SBUS &&
! 5785: isp->isp_type < ISP_HA_SCSI_1020A) ||
! 5786: (isp->isp_bustype == ISP_BT_PCI &&
! 5787: isp->isp_type < ISP_HA_SCSI_1040) ||
! 5788: (isp->isp_clock && isp->isp_clock < 60) ||
! 5789: (sdp->isp_ultramode == 0)) {
! 5790: off = ISP_10M_SYNCPARMS >> 8;
! 5791: per = ISP_10M_SYNCPARMS & 0xff;
! 5792: } else {
! 5793: off = ISP_20M_SYNCPARMS_1040 >> 8;
! 5794: per = ISP_20M_SYNCPARMS_1040 & 0xff;
! 5795: }
! 5796: sdp->isp_devparam[tgt].goal_offset =
! 5797: sdp->isp_devparam[tgt].nvrm_offset = off;
! 5798: sdp->isp_devparam[tgt].goal_period =
! 5799: sdp->isp_devparam[tgt].nvrm_period = per;
! 5800:
! 5801: isp_prt(isp, ISP_LOGDEBUG0, sc2, sc3,
! 5802: channel, tgt, sdp->isp_devparam[tgt].nvrm_flags,
! 5803: sdp->isp_devparam[tgt].nvrm_offset,
! 5804: sdp->isp_devparam[tgt].nvrm_period);
! 5805: }
! 5806: }
! 5807:
! 5808: /*
! 5809: * Re-initialize the ISP and complete all orphaned commands
! 5810: * with a 'botched' notice. The reset/init routines should
! 5811: * not disturb an already active list of commands.
! 5812: *
! 5813: * Locks held prior to coming here.
! 5814: */
! 5815:
! 5816: void
! 5817: isp_reinit(struct ispsoftc *isp)
! 5818: {
! 5819: XS_T *xs;
! 5820: u_int16_t handle;
! 5821:
! 5822: isp_reset(isp);
! 5823: if (isp->isp_state != ISP_RESETSTATE) {
! 5824: isp_prt(isp, ISP_LOGERR, "isp_reinit cannot reset card");
! 5825: } else if (isp->isp_role != ISP_ROLE_NONE) {
! 5826: isp_init(isp);
! 5827: if (isp->isp_state == ISP_INITSTATE) {
! 5828: isp->isp_state = ISP_RUNSTATE;
! 5829: }
! 5830: if (isp->isp_state != ISP_RUNSTATE) {
! 5831: isp_prt(isp, ISP_LOGERR,
! 5832: "isp_reinit cannot restart card");
! 5833: }
! 5834: }
! 5835: isp->isp_nactive = 0;
! 5836:
! 5837: for (handle = 1; (int) handle <= isp->isp_maxcmds; handle++) {
! 5838: xs = isp_find_xs(isp, handle);
! 5839: if (xs == NULL) {
! 5840: continue;
! 5841: }
! 5842: isp_destroy_handle(isp, handle);
! 5843: if (XS_XFRLEN(xs)) {
! 5844: ISP_DMAFREE(isp, xs, handle);
! 5845: XS_RESID(xs) = XS_XFRLEN(xs);
! 5846: } else {
! 5847: XS_RESID(xs) = 0;
! 5848: }
! 5849: XS_SETERR(xs, HBA_BUSRESET);
! 5850: isp_done(xs);
! 5851: }
! 5852: }
! 5853:
! 5854: /*
! 5855: * NVRAM Routines
! 5856: */
! 5857: static int
! 5858: isp_read_nvram(struct ispsoftc *isp)
! 5859: {
! 5860: int i, amt;
! 5861: u_int8_t csum, minversion;
! 5862: union {
! 5863: u_int8_t _x[ISP2100_NVRAM_SIZE];
! 5864: u_int16_t _s[ISP2100_NVRAM_SIZE>>1];
! 5865: } _n;
! 5866: #define nvram_data _n._x
! 5867: #define nvram_words _n._s
! 5868:
! 5869: if (IS_FC(isp)) {
! 5870: amt = ISP2100_NVRAM_SIZE;
! 5871: minversion = 1;
! 5872: } else if (IS_ULTRA2(isp)) {
! 5873: amt = ISP1080_NVRAM_SIZE;
! 5874: minversion = 0;
! 5875: } else {
! 5876: amt = ISP_NVRAM_SIZE;
! 5877: minversion = 2;
! 5878: }
! 5879:
! 5880: /*
! 5881: * Just read the first two words first to see if we have a valid
! 5882: * NVRAM to continue reading the rest with.
! 5883: */
! 5884: for (i = 0; i < 2; i++) {
! 5885: isp_rdnvram_word(isp, i, &nvram_words[i]);
! 5886: }
! 5887: if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
! 5888: nvram_data[2] != 'P') {
! 5889: if (isp->isp_bustype != ISP_BT_SBUS) {
! 5890: isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header");
! 5891: isp_prt(isp, ISP_LOGDEBUG0, "%x %x %x",
! 5892: nvram_data[0], nvram_data[1], nvram_data[2]);
! 5893: }
! 5894: return (-1);
! 5895: }
! 5896: for (i = 2; i < amt>>1; i++) {
! 5897: isp_rdnvram_word(isp, i, &nvram_words[i]);
! 5898: }
! 5899: for (csum = 0, i = 0; i < amt; i++) {
! 5900: csum += nvram_data[i];
! 5901: }
! 5902: if (csum != 0) {
! 5903: isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
! 5904: return (-1);
! 5905: }
! 5906: if (ISP_NVRAM_VERSION(nvram_data) < minversion) {
! 5907: isp_prt(isp, ISP_LOGWARN, "version %d NVRAM not understood",
! 5908: ISP_NVRAM_VERSION(nvram_data));
! 5909: return (-1);
! 5910: }
! 5911:
! 5912: if (IS_ULTRA3(isp)) {
! 5913: isp_parse_nvram_12160(isp, 0, nvram_data);
! 5914: if (IS_12160(isp))
! 5915: isp_parse_nvram_12160(isp, 1, nvram_data);
! 5916: } else if (IS_1080(isp)) {
! 5917: isp_parse_nvram_1080(isp, 0, nvram_data);
! 5918: } else if (IS_1280(isp) || IS_1240(isp)) {
! 5919: isp_parse_nvram_1080(isp, 0, nvram_data);
! 5920: isp_parse_nvram_1080(isp, 1, nvram_data);
! 5921: } else if (IS_SCSI(isp)) {
! 5922: isp_parse_nvram_1020(isp, nvram_data);
! 5923: } else {
! 5924: isp_parse_nvram_2100(isp, nvram_data);
! 5925: }
! 5926: return (0);
! 5927: #undef nvram_data
! 5928: #undef nvram_words
! 5929: }
! 5930:
! 5931: static void
! 5932: isp_rdnvram_word(struct ispsoftc *isp, int wo, u_int16_t *rp)
! 5933: {
! 5934: int i, cbits;
! 5935: u_int16_t bit, rqst;
! 5936:
! 5937: ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
! 5938: USEC_DELAY(2);
! 5939: ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
! 5940: USEC_DELAY(2);
! 5941:
! 5942: if (IS_FC(isp)) {
! 5943: wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1);
! 5944: if (IS_2312(isp) && isp->isp_port) {
! 5945: wo += 128;
! 5946: }
! 5947: rqst = (ISP_NVRAM_READ << 8) | wo;
! 5948: cbits = 10;
! 5949: } else if (IS_ULTRA2(isp)) {
! 5950: wo &= ((ISP1080_NVRAM_SIZE >> 1) - 1);
! 5951: rqst = (ISP_NVRAM_READ << 8) | wo;
! 5952: cbits = 10;
! 5953: } else {
! 5954: wo &= ((ISP_NVRAM_SIZE >> 1) - 1);
! 5955: rqst = (ISP_NVRAM_READ << 6) | wo;
! 5956: cbits = 8;
! 5957: }
! 5958:
! 5959: /*
! 5960: * Clock the word select request out...
! 5961: */
! 5962: for (i = cbits; i >= 0; i--) {
! 5963: if ((rqst >> i) & 1) {
! 5964: bit = BIU_NVRAM_SELECT | BIU_NVRAM_DATAOUT;
! 5965: } else {
! 5966: bit = BIU_NVRAM_SELECT;
! 5967: }
! 5968: ISP_WRITE(isp, BIU_NVRAM, bit);
! 5969: USEC_DELAY(2);
! 5970: ISP_WRITE(isp, BIU_NVRAM, bit | BIU_NVRAM_CLOCK);
! 5971: USEC_DELAY(2);
! 5972: ISP_WRITE(isp, BIU_NVRAM, bit);
! 5973: USEC_DELAY(2);
! 5974: }
! 5975: /*
! 5976: * Now read the result back in (bits come back in MSB format).
! 5977: */
! 5978: *rp = 0;
! 5979: for (i = 0; i < 16; i++) {
! 5980: u_int16_t rv;
! 5981: *rp <<= 1;
! 5982: ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
! 5983: USEC_DELAY(2);
! 5984: rv = ISP_READ(isp, BIU_NVRAM);
! 5985: if (rv & BIU_NVRAM_DATAIN) {
! 5986: *rp |= 1;
! 5987: }
! 5988: USEC_DELAY(2);
! 5989: ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
! 5990: USEC_DELAY(2);
! 5991: }
! 5992: ISP_WRITE(isp, BIU_NVRAM, 0);
! 5993: USEC_DELAY(2);
! 5994: ISP_SWIZZLE_NVRAM_WORD(isp, rp);
! 5995: }
! 5996:
! 5997: static void
! 5998: isp_parse_nvram_1020(struct ispsoftc *isp, u_int8_t *nvram_data)
! 5999: {
! 6000: sdparam *sdp = (sdparam *) isp->isp_param;
! 6001: int tgt;
! 6002:
! 6003: sdp->isp_fifo_threshold =
! 6004: ISP_NVRAM_FIFO_THRESHOLD(nvram_data) |
! 6005: (ISP_NVRAM_FIFO_THRESHOLD_128(nvram_data) << 2);
! 6006:
! 6007: if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
! 6008: sdp->isp_initiator_id =
! 6009: ISP_NVRAM_INITIATOR_ID(nvram_data);
! 6010:
! 6011: sdp->isp_bus_reset_delay =
! 6012: ISP_NVRAM_BUS_RESET_DELAY(nvram_data);
! 6013:
! 6014: sdp->isp_retry_count =
! 6015: ISP_NVRAM_BUS_RETRY_COUNT(nvram_data);
! 6016:
! 6017: sdp->isp_retry_delay =
! 6018: ISP_NVRAM_BUS_RETRY_DELAY(nvram_data);
! 6019:
! 6020: sdp->isp_async_data_setup =
! 6021: ISP_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data);
! 6022:
! 6023: if (isp->isp_type >= ISP_HA_SCSI_1040) {
! 6024: if (sdp->isp_async_data_setup < 9) {
! 6025: sdp->isp_async_data_setup = 9;
! 6026: }
! 6027: } else {
! 6028: if (sdp->isp_async_data_setup != 6) {
! 6029: sdp->isp_async_data_setup = 6;
! 6030: }
! 6031: }
! 6032:
! 6033: sdp->isp_req_ack_active_neg =
! 6034: ISP_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data);
! 6035:
! 6036: sdp->isp_data_line_active_neg =
! 6037: ISP_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data);
! 6038:
! 6039: sdp->isp_data_dma_burst_enabl =
! 6040: ISP_NVRAM_DATA_DMA_BURST_ENABLE(nvram_data);
! 6041:
! 6042: sdp->isp_cmd_dma_burst_enable =
! 6043: ISP_NVRAM_CMD_DMA_BURST_ENABLE(nvram_data);
! 6044:
! 6045: sdp->isp_tag_aging =
! 6046: ISP_NVRAM_TAG_AGE_LIMIT(nvram_data);
! 6047:
! 6048: sdp->isp_selection_timeout =
! 6049: ISP_NVRAM_SELECTION_TIMEOUT(nvram_data);
! 6050:
! 6051: sdp->isp_max_queue_depth =
! 6052: ISP_NVRAM_MAX_QUEUE_DEPTH(nvram_data);
! 6053:
! 6054: sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data);
! 6055:
! 6056: isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
! 6057: 0, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
! 6058: sdp->isp_bus_reset_delay, sdp->isp_retry_count,
! 6059: sdp->isp_retry_delay, sdp->isp_async_data_setup);
! 6060: isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
! 6061: sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
! 6062: sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
! 6063: sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
! 6064:
! 6065: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 6066: sdp->isp_devparam[tgt].dev_enable =
! 6067: ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt);
! 6068: sdp->isp_devparam[tgt].exc_throttle =
! 6069: ISP_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt);
! 6070: sdp->isp_devparam[tgt].nvrm_offset =
! 6071: ISP_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt);
! 6072: sdp->isp_devparam[tgt].nvrm_period =
! 6073: ISP_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt);
! 6074: /*
! 6075: * We probably shouldn't lie about this, but it
! 6076: * it makes it much safer if we limit NVRAM values
! 6077: * to sanity.
! 6078: */
! 6079: if (isp->isp_type < ISP_HA_SCSI_1040) {
! 6080: /*
! 6081: * If we're not ultra, we can't possibly
! 6082: * be a shorter period than this.
! 6083: */
! 6084: if (sdp->isp_devparam[tgt].nvrm_period < 0x19) {
! 6085: sdp->isp_devparam[tgt].nvrm_period = 0x19;
! 6086: }
! 6087: if (sdp->isp_devparam[tgt].nvrm_offset > 0xc) {
! 6088: sdp->isp_devparam[tgt].nvrm_offset = 0x0c;
! 6089: }
! 6090: } else {
! 6091: if (sdp->isp_devparam[tgt].nvrm_offset > 0x8) {
! 6092: sdp->isp_devparam[tgt].nvrm_offset = 0x8;
! 6093: }
! 6094: }
! 6095: sdp->isp_devparam[tgt].nvrm_flags = 0;
! 6096: if (ISP_NVRAM_TGT_RENEG(nvram_data, tgt))
! 6097: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
! 6098: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
! 6099: if (ISP_NVRAM_TGT_TQING(nvram_data, tgt))
! 6100: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
! 6101: if (ISP_NVRAM_TGT_SYNC(nvram_data, tgt))
! 6102: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
! 6103: if (ISP_NVRAM_TGT_WIDE(nvram_data, tgt))
! 6104: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
! 6105: if (ISP_NVRAM_TGT_PARITY(nvram_data, tgt))
! 6106: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
! 6107: if (ISP_NVRAM_TGT_DISC(nvram_data, tgt))
! 6108: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
! 6109: sdp->isp_devparam[tgt].actv_flags = 0; /* we don't know */
! 6110: isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
! 6111: 0, tgt, sdp->isp_devparam[tgt].nvrm_flags,
! 6112: sdp->isp_devparam[tgt].nvrm_offset,
! 6113: sdp->isp_devparam[tgt].nvrm_period);
! 6114: sdp->isp_devparam[tgt].goal_offset =
! 6115: sdp->isp_devparam[tgt].nvrm_offset;
! 6116: sdp->isp_devparam[tgt].goal_period =
! 6117: sdp->isp_devparam[tgt].nvrm_period;
! 6118: sdp->isp_devparam[tgt].goal_flags =
! 6119: sdp->isp_devparam[tgt].nvrm_flags;
! 6120: }
! 6121: }
! 6122:
! 6123: static void
! 6124: isp_parse_nvram_1080(struct ispsoftc *isp, int bus, u_int8_t *nvram_data)
! 6125: {
! 6126: sdparam *sdp = (sdparam *) isp->isp_param;
! 6127: int tgt;
! 6128:
! 6129: sdp += bus;
! 6130:
! 6131: sdp->isp_fifo_threshold =
! 6132: ISP1080_NVRAM_FIFO_THRESHOLD(nvram_data);
! 6133:
! 6134: if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
! 6135: sdp->isp_initiator_id =
! 6136: ISP1080_NVRAM_INITIATOR_ID(nvram_data, bus);
! 6137:
! 6138: sdp->isp_bus_reset_delay =
! 6139: ISP1080_NVRAM_BUS_RESET_DELAY(nvram_data, bus);
! 6140:
! 6141: sdp->isp_retry_count =
! 6142: ISP1080_NVRAM_BUS_RETRY_COUNT(nvram_data, bus);
! 6143:
! 6144: sdp->isp_retry_delay =
! 6145: ISP1080_NVRAM_BUS_RETRY_DELAY(nvram_data, bus);
! 6146:
! 6147: sdp->isp_async_data_setup =
! 6148: ISP1080_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data, bus);
! 6149:
! 6150: sdp->isp_req_ack_active_neg =
! 6151: ISP1080_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data, bus);
! 6152:
! 6153: sdp->isp_data_line_active_neg =
! 6154: ISP1080_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data, bus);
! 6155:
! 6156: sdp->isp_data_dma_burst_enabl =
! 6157: ISP1080_NVRAM_BURST_ENABLE(nvram_data);
! 6158:
! 6159: sdp->isp_cmd_dma_burst_enable =
! 6160: ISP1080_NVRAM_BURST_ENABLE(nvram_data);
! 6161:
! 6162: sdp->isp_selection_timeout =
! 6163: ISP1080_NVRAM_SELECTION_TIMEOUT(nvram_data, bus);
! 6164:
! 6165: sdp->isp_max_queue_depth =
! 6166: ISP1080_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus);
! 6167:
! 6168: isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
! 6169: bus, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
! 6170: sdp->isp_bus_reset_delay, sdp->isp_retry_count,
! 6171: sdp->isp_retry_delay, sdp->isp_async_data_setup);
! 6172: isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
! 6173: sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
! 6174: sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
! 6175: sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
! 6176:
! 6177:
! 6178: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 6179: sdp->isp_devparam[tgt].dev_enable =
! 6180: ISP1080_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt, bus);
! 6181: sdp->isp_devparam[tgt].exc_throttle =
! 6182: ISP1080_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt, bus);
! 6183: sdp->isp_devparam[tgt].nvrm_offset =
! 6184: ISP1080_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt, bus);
! 6185: sdp->isp_devparam[tgt].nvrm_period =
! 6186: ISP1080_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt, bus);
! 6187: sdp->isp_devparam[tgt].nvrm_flags = 0;
! 6188: if (ISP1080_NVRAM_TGT_RENEG(nvram_data, tgt, bus))
! 6189: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
! 6190: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
! 6191: if (ISP1080_NVRAM_TGT_TQING(nvram_data, tgt, bus))
! 6192: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
! 6193: if (ISP1080_NVRAM_TGT_SYNC(nvram_data, tgt, bus))
! 6194: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
! 6195: if (ISP1080_NVRAM_TGT_WIDE(nvram_data, tgt, bus))
! 6196: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
! 6197: if (ISP1080_NVRAM_TGT_PARITY(nvram_data, tgt, bus))
! 6198: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
! 6199: if (ISP1080_NVRAM_TGT_DISC(nvram_data, tgt, bus))
! 6200: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
! 6201: sdp->isp_devparam[tgt].actv_flags = 0;
! 6202: isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
! 6203: bus, tgt, sdp->isp_devparam[tgt].nvrm_flags,
! 6204: sdp->isp_devparam[tgt].nvrm_offset,
! 6205: sdp->isp_devparam[tgt].nvrm_period);
! 6206: sdp->isp_devparam[tgt].goal_offset =
! 6207: sdp->isp_devparam[tgt].nvrm_offset;
! 6208: sdp->isp_devparam[tgt].goal_period =
! 6209: sdp->isp_devparam[tgt].nvrm_period;
! 6210: sdp->isp_devparam[tgt].goal_flags =
! 6211: sdp->isp_devparam[tgt].nvrm_flags;
! 6212: }
! 6213: }
! 6214:
! 6215: static void
! 6216: isp_parse_nvram_12160(struct ispsoftc *isp, int bus, u_int8_t *nvram_data)
! 6217: {
! 6218: sdparam *sdp = (sdparam *) isp->isp_param;
! 6219: int tgt;
! 6220:
! 6221: sdp += bus;
! 6222:
! 6223: sdp->isp_fifo_threshold =
! 6224: ISP12160_NVRAM_FIFO_THRESHOLD(nvram_data);
! 6225:
! 6226: if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
! 6227: sdp->isp_initiator_id =
! 6228: ISP12160_NVRAM_INITIATOR_ID(nvram_data, bus);
! 6229:
! 6230: sdp->isp_bus_reset_delay =
! 6231: ISP12160_NVRAM_BUS_RESET_DELAY(nvram_data, bus);
! 6232:
! 6233: sdp->isp_retry_count =
! 6234: ISP12160_NVRAM_BUS_RETRY_COUNT(nvram_data, bus);
! 6235:
! 6236: sdp->isp_retry_delay =
! 6237: ISP12160_NVRAM_BUS_RETRY_DELAY(nvram_data, bus);
! 6238:
! 6239: sdp->isp_async_data_setup =
! 6240: ISP12160_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data, bus);
! 6241:
! 6242: sdp->isp_req_ack_active_neg =
! 6243: ISP12160_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data, bus);
! 6244:
! 6245: sdp->isp_data_line_active_neg =
! 6246: ISP12160_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data, bus);
! 6247:
! 6248: sdp->isp_data_dma_burst_enabl =
! 6249: ISP12160_NVRAM_BURST_ENABLE(nvram_data);
! 6250:
! 6251: sdp->isp_cmd_dma_burst_enable =
! 6252: ISP12160_NVRAM_BURST_ENABLE(nvram_data);
! 6253:
! 6254: sdp->isp_selection_timeout =
! 6255: ISP12160_NVRAM_SELECTION_TIMEOUT(nvram_data, bus);
! 6256:
! 6257: sdp->isp_max_queue_depth =
! 6258: ISP12160_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus);
! 6259:
! 6260: isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
! 6261: bus, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
! 6262: sdp->isp_bus_reset_delay, sdp->isp_retry_count,
! 6263: sdp->isp_retry_delay, sdp->isp_async_data_setup);
! 6264: isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
! 6265: sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
! 6266: sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
! 6267: sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
! 6268:
! 6269: for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
! 6270: sdp->isp_devparam[tgt].dev_enable =
! 6271: ISP12160_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt, bus);
! 6272: sdp->isp_devparam[tgt].exc_throttle =
! 6273: ISP12160_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt, bus);
! 6274: sdp->isp_devparam[tgt].nvrm_offset =
! 6275: ISP12160_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt, bus);
! 6276: sdp->isp_devparam[tgt].nvrm_period =
! 6277: ISP12160_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt, bus);
! 6278: sdp->isp_devparam[tgt].nvrm_flags = 0;
! 6279: if (ISP12160_NVRAM_TGT_RENEG(nvram_data, tgt, bus))
! 6280: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
! 6281: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
! 6282: if (ISP12160_NVRAM_TGT_TQING(nvram_data, tgt, bus))
! 6283: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
! 6284: if (ISP12160_NVRAM_TGT_SYNC(nvram_data, tgt, bus))
! 6285: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
! 6286: if (ISP12160_NVRAM_TGT_WIDE(nvram_data, tgt, bus))
! 6287: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
! 6288: if (ISP12160_NVRAM_TGT_PARITY(nvram_data, tgt, bus))
! 6289: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
! 6290: if (ISP12160_NVRAM_TGT_DISC(nvram_data, tgt, bus))
! 6291: sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
! 6292: sdp->isp_devparam[tgt].actv_flags = 0;
! 6293: isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
! 6294: bus, tgt, sdp->isp_devparam[tgt].nvrm_flags,
! 6295: sdp->isp_devparam[tgt].nvrm_offset,
! 6296: sdp->isp_devparam[tgt].nvrm_period);
! 6297: sdp->isp_devparam[tgt].goal_offset =
! 6298: sdp->isp_devparam[tgt].nvrm_offset;
! 6299: sdp->isp_devparam[tgt].goal_period =
! 6300: sdp->isp_devparam[tgt].nvrm_period;
! 6301: sdp->isp_devparam[tgt].goal_flags =
! 6302: sdp->isp_devparam[tgt].nvrm_flags;
! 6303: }
! 6304: }
! 6305:
! 6306: static void
! 6307: isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data)
! 6308: {
! 6309: fcparam *fcp = (fcparam *) isp->isp_param;
! 6310: u_int64_t wwn;
! 6311:
! 6312: /*
! 6313: * There is NVRAM storage for both Port and Node entities-
! 6314: * but the Node entity appears to be unused on all the cards
! 6315: * I can find. However, we should account for this being set
! 6316: * at some point in the future.
! 6317: *
! 6318: * Qlogic WWNs have an NAA of 2, but usually nothing shows up in
! 6319: * bits 48..60. In the case of the 2202, it appears that they do
! 6320: * use bit 48 to distinguish between the two instances on the card.
! 6321: * The 2204, which I've never seen, *probably* extends this method.
! 6322: */
! 6323: wwn = ISP2100_NVRAM_PORT_NAME(nvram_data);
! 6324: if (wwn) {
! 6325: isp_prt(isp, ISP_LOGCONFIG, "NVRAM Port WWN 0x%08x%08x",
! 6326: (u_int32_t) (wwn >> 32), (u_int32_t) (wwn & 0xffffffff));
! 6327: if ((wwn >> 60) == 0) {
! 6328: wwn |= (((u_int64_t) 2)<< 60);
! 6329: }
! 6330: }
! 6331: fcp->isp_portwwn = wwn;
! 6332: if (IS_2200(isp) || IS_23XX(isp)) {
! 6333: wwn = ISP2200_NVRAM_NODE_NAME(nvram_data);
! 6334: if (wwn) {
! 6335: isp_prt(isp, ISP_LOGCONFIG, "NVRAM Node WWN 0x%08x%08x",
! 6336: (u_int32_t) (wwn >> 32),
! 6337: (u_int32_t) (wwn & 0xffffffff));
! 6338: if ((wwn >> 60) == 0) {
! 6339: wwn |= (((u_int64_t) 2)<< 60);
! 6340: }
! 6341: }
! 6342: } else {
! 6343: wwn &= ~((u_int64_t) 0xfff << 48);
! 6344: }
! 6345: fcp->isp_nodewwn = wwn;
! 6346:
! 6347: /*
! 6348: * Make sure we have both Node and Port as non-zero values.
! 6349: */
! 6350: if (fcp->isp_nodewwn != 0 && fcp->isp_portwwn == 0) {
! 6351: fcp->isp_portwwn = fcp->isp_nodewwn;
! 6352: } else if (fcp->isp_nodewwn == 0 && fcp->isp_portwwn != 0) {
! 6353: fcp->isp_nodewwn = fcp->isp_portwwn;
! 6354: }
! 6355:
! 6356: /*
! 6357: * Make the Node and Port values sane if they're NAA == 2.
! 6358: * This means to clear bits 48..56 for the Node WWN and
! 6359: * make sure that there's some non-zero value in 48..56
! 6360: * for the Port WWN.
! 6361: */
! 6362: if (fcp->isp_nodewwn && fcp->isp_portwwn) {
! 6363: if ((fcp->isp_nodewwn & (((u_int64_t) 0xfff) << 48)) != 0 &&
! 6364: (fcp->isp_nodewwn >> 60) == 2) {
! 6365: fcp->isp_nodewwn &= ~((u_int64_t) 0xfff << 48);
! 6366: }
! 6367: if ((fcp->isp_portwwn & (((u_int64_t) 0xfff) << 48)) == 0 &&
! 6368: (fcp->isp_portwwn >> 60) == 2) {
! 6369: fcp->isp_portwwn |= ((u_int64_t) 1 << 56);
! 6370: }
! 6371: }
! 6372:
! 6373: isp_prt(isp, ISP_LOGDEBUG0,
! 6374: "NVRAM: maxfrmlen %d execthrottle %d fwoptions 0x%x loopid %x",
! 6375: ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data),
! 6376: ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data),
! 6377: ISP2100_NVRAM_OPTIONS(nvram_data),
! 6378: ISP2100_NVRAM_HARDLOOPID(nvram_data));
! 6379:
! 6380: fcp->isp_maxalloc =
! 6381: ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);
! 6382: if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0)
! 6383: fcp->isp_maxfrmlen =
! 6384: ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data);
! 6385: fcp->isp_retry_delay =
! 6386: ISP2100_NVRAM_RETRY_DELAY(nvram_data);
! 6387: fcp->isp_retry_count =
! 6388: ISP2100_NVRAM_RETRY_COUNT(nvram_data);
! 6389: if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
! 6390: fcp->isp_loopid =
! 6391: ISP2100_NVRAM_HARDLOOPID(nvram_data);
! 6392: if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0)
! 6393: fcp->isp_execthrottle =
! 6394: ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data);
! 6395: fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data);
! 6396: }
! 6397:
! 6398: #ifdef ISP_FW_CRASH_DUMP
! 6399: static void isp2200_fw_dump(struct ispsoftc *);
! 6400: static void isp2300_fw_dump(struct ispsoftc *);
! 6401:
! 6402: static void
! 6403: isp2200_fw_dump(struct ispsoftc *isp)
! 6404: {
! 6405: int i, j;
! 6406: mbreg_t mbs;
! 6407: u_int16_t *ptr;
! 6408:
! 6409: ptr = FCPARAM(isp)->isp_dump_data;
! 6410: if (ptr == NULL) {
! 6411: isp_prt(isp, ISP_LOGERR,
! 6412: "No place to dump RISC registers and SRAM");
! 6413: return;
! 6414: }
! 6415: if (*ptr++) {
! 6416: isp_prt(isp, ISP_LOGERR,
! 6417: "dump area for RISC registers and SRAM already used");
! 6418: return;
! 6419: }
! 6420: ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
! 6421: for (i = 0; i < 100; i++) {
! 6422: USEC_DELAY(100);
! 6423: if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
! 6424: break;
! 6425: }
! 6426: }
! 6427: if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
! 6428: /*
! 6429: * PBIU Registers
! 6430: */
! 6431: for (i = 0; i < 8; i++) {
! 6432: *ptr++ = ISP_READ(isp, BIU_BLOCK + (i << 1));
! 6433: }
! 6434:
! 6435: /*
! 6436: * Mailbox Registers
! 6437: */
! 6438: for (i = 0; i < 8; i++) {
! 6439: *ptr++ = ISP_READ(isp, MBOX_BLOCK + (i << 1));
! 6440: }
! 6441:
! 6442: /*
! 6443: * DMA Registers
! 6444: */
! 6445: for (i = 0; i < 48; i++) {
! 6446: *ptr++ = ISP_READ(isp, DMA_BLOCK + 0x20 + (i << 1));
! 6447: }
! 6448:
! 6449: /*
! 6450: * RISC H/W Registers
! 6451: */
! 6452: ISP_WRITE(isp, BIU2100_CSR, 0);
! 6453: for (i = 0; i < 16; i++) {
! 6454: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0xA0 + (i << 1));
! 6455: }
! 6456:
! 6457: /*
! 6458: * RISC GP Registers
! 6459: */
! 6460: for (j = 0; j < 8; j++) {
! 6461: ISP_WRITE(isp, BIU_BLOCK + 0xA4, 0x2000 + (j << 8));
! 6462: for (i = 0; i < 16; i++) {
! 6463: *ptr++ =
! 6464: ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6465: }
! 6466: }
! 6467:
! 6468: /*
! 6469: * Frame Buffer Hardware Registers
! 6470: */
! 6471: ISP_WRITE(isp, BIU2100_CSR, 0x10);
! 6472: for (i = 0; i < 16; i++) {
! 6473: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6474: }
! 6475:
! 6476: /*
! 6477: * Fibre Protocol Module 0 Hardware Registers
! 6478: */
! 6479: ISP_WRITE(isp, BIU2100_CSR, 0x20);
! 6480: for (i = 0; i < 64; i++) {
! 6481: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6482: }
! 6483:
! 6484: /*
! 6485: * Fibre Protocol Module 1 Hardware Registers
! 6486: */
! 6487: ISP_WRITE(isp, BIU2100_CSR, 0x30);
! 6488: for (i = 0; i < 64; i++) {
! 6489: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6490: }
! 6491: } else {
! 6492: isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause");
! 6493: return;
! 6494: }
! 6495: isp_prt(isp, ISP_LOGALL,
! 6496: "isp_fw_dump: RISC registers dumped successfully");
! 6497: ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
! 6498: for (i = 0; i < 100; i++) {
! 6499: USEC_DELAY(100);
! 6500: if (ISP_READ(isp, OUTMAILBOX0) == 0) {
! 6501: break;
! 6502: }
! 6503: }
! 6504: if (ISP_READ(isp, OUTMAILBOX0) != 0) {
! 6505: isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
! 6506: return;
! 6507: }
! 6508: ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
! 6509: for (i = 0; i < 100; i++) {
! 6510: USEC_DELAY(100);
! 6511: if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
! 6512: break;
! 6513: }
! 6514: }
! 6515: if ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
! 6516: isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause After Reset");
! 6517: return;
! 6518: }
! 6519: ISP_WRITE(isp, RISC_EMB, 0xf2);
! 6520: ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
! 6521: for (i = 0; i < 100; i++) {
! 6522: USEC_DELAY(100);
! 6523: if ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
! 6524: break;
! 6525: }
! 6526: }
! 6527: ENABLE_INTS(isp);
! 6528: mbs.param[0] = MBOX_READ_RAM_WORD;
! 6529: mbs.param[1] = 0x1000;
! 6530: isp->isp_mbxworkp = (void *) ptr;
! 6531: isp->isp_mbxwrk0 = 0xefff; /* continuation count */
! 6532: isp->isp_mbxwrk1 = 0x1001; /* next SRAM address */
! 6533: isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
! 6534: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 6535: isp_prt(isp, ISP_LOGWARN,
! 6536: "RAM DUMP FAILED @ WORD %x", isp->isp_mbxwrk1);
! 6537: return;
! 6538: }
! 6539: ptr = isp->isp_mbxworkp; /* finish fetch of final word */
! 6540: *ptr++ = isp->isp_mboxtmp[2];
! 6541: isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped successfully");
! 6542: FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */
! 6543: (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0);
! 6544: }
! 6545:
! 6546: static void
! 6547: isp2300_fw_dump(struct ispsoftc *isp)
! 6548: {
! 6549: int i, j;
! 6550: mbreg_t mbs;
! 6551: u_int16_t *ptr;
! 6552:
! 6553: ptr = FCPARAM(isp)->isp_dump_data;
! 6554: if (ptr == NULL) {
! 6555: isp_prt(isp, ISP_LOGERR,
! 6556: "No place to dump RISC registers and SRAM");
! 6557: return;
! 6558: }
! 6559: if (*ptr++) {
! 6560: isp_prt(isp, ISP_LOGERR,
! 6561: "dump area for RISC registers and SRAM already used");
! 6562: return;
! 6563: }
! 6564: ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
! 6565: for (i = 0; i < 100; i++) {
! 6566: USEC_DELAY(100);
! 6567: if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
! 6568: break;
! 6569: }
! 6570: }
! 6571: if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
! 6572: /*
! 6573: * PBIU registers
! 6574: */
! 6575: for (i = 0; i < 8; i++) {
! 6576: *ptr++ = ISP_READ(isp, BIU_BLOCK + (i << 1));
! 6577: }
! 6578:
! 6579: /*
! 6580: * ReqQ-RspQ-Risc2Host Status registers
! 6581: */
! 6582: for (i = 0; i < 8; i++) {
! 6583: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x10 + (i << 1));
! 6584: }
! 6585:
! 6586: /*
! 6587: * Mailbox Registers
! 6588: */
! 6589: for (i = 0; i < 32; i++) {
! 6590: *ptr++ =
! 6591: ISP_READ(isp, PCI_MBOX_REGS2300_OFF + (i << 1));
! 6592: }
! 6593:
! 6594: /*
! 6595: * Auto Request Response DMA registers
! 6596: */
! 6597: ISP_WRITE(isp, BIU2100_CSR, 0x40);
! 6598: for (i = 0; i < 32; i++) {
! 6599: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6600: }
! 6601:
! 6602: /*
! 6603: * DMA registers
! 6604: */
! 6605: ISP_WRITE(isp, BIU2100_CSR, 0x50);
! 6606: for (i = 0; i < 48; i++) {
! 6607: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6608: }
! 6609:
! 6610: /*
! 6611: * RISC hardware registers
! 6612: */
! 6613: ISP_WRITE(isp, BIU2100_CSR, 0);
! 6614: for (i = 0; i < 16; i++) {
! 6615: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0xA0 + (i << 1));
! 6616: }
! 6617:
! 6618: /*
! 6619: * RISC GP? registers
! 6620: */
! 6621: for (j = 0; j < 8; j++) {
! 6622: ISP_WRITE(isp, BIU_BLOCK + 0xA4, 0x2000 + (j << 9));
! 6623: for (i = 0; i < 16; i++) {
! 6624: *ptr++ =
! 6625: ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6626: }
! 6627: }
! 6628:
! 6629: /*
! 6630: * frame buffer hardware registers
! 6631: */
! 6632: ISP_WRITE(isp, BIU2100_CSR, 0x10);
! 6633: for (i = 0; i < 64; i++) {
! 6634: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6635: }
! 6636:
! 6637: /*
! 6638: * FPM B0 hardware registers
! 6639: */
! 6640: ISP_WRITE(isp, BIU2100_CSR, 0x20);
! 6641: for (i = 0; i < 64; i++) {
! 6642: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6643: }
! 6644:
! 6645: /*
! 6646: * FPM B1 hardware registers
! 6647: */
! 6648: ISP_WRITE(isp, BIU2100_CSR, 0x30);
! 6649: for (i = 0; i < 64; i++) {
! 6650: *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
! 6651: }
! 6652: } else {
! 6653: isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause");
! 6654: return;
! 6655: }
! 6656: isp_prt(isp, ISP_LOGALL,
! 6657: "isp_fw_dump: RISC registers dumped successfully");
! 6658: ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
! 6659: for (i = 0; i < 100; i++) {
! 6660: USEC_DELAY(100);
! 6661: if (ISP_READ(isp, OUTMAILBOX0) == 0) {
! 6662: break;
! 6663: }
! 6664: }
! 6665: if (ISP_READ(isp, OUTMAILBOX0) != 0) {
! 6666: isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
! 6667: return;
! 6668: }
! 6669: ENABLE_INTS(isp);
! 6670: mbs.param[0] = MBOX_READ_RAM_WORD;
! 6671: mbs.param[1] = 0x800;
! 6672: isp->isp_mbxworkp = (void *) ptr;
! 6673: isp->isp_mbxwrk0 = 0xf7ff; /* continuation count */
! 6674: isp->isp_mbxwrk1 = 0x801; /* next SRAM address */
! 6675: isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
! 6676: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 6677: isp_prt(isp, ISP_LOGWARN,
! 6678: "RAM DUMP FAILED @ WORD %x", isp->isp_mbxwrk1);
! 6679: return;
! 6680: }
! 6681: ptr = isp->isp_mbxworkp; /* finish fetch of final word */
! 6682: *ptr++ = isp->isp_mboxtmp[2];
! 6683:
! 6684: /*
! 6685: * We don't have access to mailbox registers 8.. onward
! 6686: * in our 'common' device model- so we have to set it
! 6687: * here and hope it stays the same!
! 6688: */
! 6689: ISP_WRITE(isp, PCI_MBOX_REGS2300_OFF + (8 << 1), 0x1);
! 6690:
! 6691: mbs.param[0] = MBOX_READ_RAM_WORD_EXTENDED;
! 6692: mbs.param[1] = 0;
! 6693: isp->isp_mbxworkp = (void *) ptr;
! 6694: isp->isp_mbxwrk0 = 0xffff; /* continuation count */
! 6695: isp->isp_mbxwrk1 = 0x1; /* next SRAM address */
! 6696: isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
! 6697: if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
! 6698: isp_prt(isp, ISP_LOGWARN,
! 6699: "RAM DUMP FAILED @ WORD %x", 0x10000 + isp->isp_mbxwrk1);
! 6700: return;
! 6701: }
! 6702: ptr = isp->isp_mbxworkp; /* finish final word */
! 6703: *ptr++ = mbs.param[2];
! 6704: isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped successfully");
! 6705: FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */
! 6706: (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0);
! 6707: }
! 6708:
! 6709: void
! 6710: isp_fw_dump(struct ispsoftc *isp)
! 6711: {
! 6712: if (IS_2200(isp))
! 6713: isp2200_fw_dump(isp);
! 6714: else if (IS_23XX(isp))
! 6715: isp2300_fw_dump(isp);
! 6716: }
! 6717: #endif
CVSweb