1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2009-2020 Alexander Motin <mav@FreeBSD.org> 5 * Copyright (c) 1997-2009 by Matthew Jacob 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 /* 33 * Machine and OS Independent (well, as best as possible) 34 * code for the Qlogic ISP SCSI and FC-SCSI adapters. 35 */ 36 37 /* 38 * Inspiration and ideas about this driver are from Erik Moe's Linux driver 39 * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some 40 * ideas dredged from the Solaris driver. 41 */ 42 43 /* 44 * Include header file appropriate for platform we're building on. 45 */ 46 #ifdef __NetBSD__ 47 #include <sys/cdefs.h> 48 __KERNEL_RCSID(0, "$NetBSD$"); 49 #include <dev/ic/isp_netbsd.h> 50 #endif 51 #ifdef __FreeBSD__ 52 #include <sys/cdefs.h> 53 __FBSDID("$FreeBSD$"); 54 #include <dev/isp/isp_freebsd.h> 55 #endif 56 #ifdef __OpenBSD__ 57 #include <dev/ic/isp_openbsd.h> 58 #endif 59 #ifdef __linux__ 60 #include "isp_linux.h" 61 #endif 62 #ifdef __svr4__ 63 #include "isp_solaris.h" 64 #endif 65 66 /* 67 * General defines 68 */ 69 #define MBOX_DELAY_COUNT 1000000 / 100 70 71 /* 72 * Local static data 73 */ 74 static const char notresp[] = "Unknown IOCB in RESPONSE Queue (type 0x%x) @ idx %d (next %d)"; 75 static const char bun[] = "bad underrun (count %d, resid %d, status %s)"; 76 static const char lipd[] = "Chan %d LIP destroyed %d active commands"; 77 static const char sacq[] = "unable to acquire scratch area"; 78 79 static const uint8_t alpa_map[] = { 80 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 81 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 82 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, 83 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3, 84 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 85 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 86 0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 87 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73, 88 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 89 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56, 90 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 91 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 92 0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 93 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26, 94 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 95 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00 96 }; 97 98 /* 99 * Local function prototypes. 100 */ 101 static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t *, uint16_t); 102 static void isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, uint32_t *); 103 static void isp_clear_portdb(ispsoftc_t *, int); 104 static void isp_mark_portdb(ispsoftc_t *, int); 105 static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int); 106 static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *); 107 static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int); 108 static void isp_dump_chip_portdb(ispsoftc_t *, int); 109 static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int); 110 static int isp_fclink_test(ispsoftc_t *, int, int); 111 static int isp_pdb_sync(ispsoftc_t *, int); 112 static int isp_scan_loop(ispsoftc_t *, int); 113 static int isp_gid_pt(ispsoftc_t *, int); 114 static int isp_scan_fabric(ispsoftc_t *, int); 115 static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *); 116 static int isp_register_fc4_type(ispsoftc_t *, int); 117 static int isp_register_fc4_features_24xx(ispsoftc_t *, int); 118 static int isp_register_port_name_24xx(ispsoftc_t *, int); 119 static int isp_register_node_name_24xx(ispsoftc_t *, int); 120 static uint16_t isp_next_handle(ispsoftc_t *, uint16_t *); 121 static int isp_fw_state(ispsoftc_t *, int); 122 static void isp_mboxcmd(ispsoftc_t *, mbreg_t *); 123 124 static void isp_setdfltfcparm(ispsoftc_t *, int); 125 static int isp_read_nvram(ispsoftc_t *, int); 126 static int isp_read_nvram_2400(ispsoftc_t *); 127 static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *); 128 static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *); 129 130 static void 131 isp_change_fw_state(ispsoftc_t *isp, int chan, int state) 132 { 133 fcparam *fcp = FCPARAM(isp, chan); 134 135 if (fcp->isp_fwstate == state) 136 return; 137 isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG, 138 "Chan %d Firmware state <%s->%s>", chan, 139 isp_fc_fw_statename(fcp->isp_fwstate), isp_fc_fw_statename(state)); 140 fcp->isp_fwstate = state; 141 } 142 143 /* 144 * Reset Hardware. 145 * 146 * Hit the chip over the head, download new f/w if available and set it running. 147 * 148 * Locking done elsewhere. 149 */ 150 151 void 152 isp_reset(ispsoftc_t *isp, int do_load_defaults) 153 { 154 mbreg_t mbs; 155 char *buf; 156 uint64_t fwt; 157 uint32_t code_org, val; 158 int loops, i, dodnld = 1; 159 const char *btype = "????"; 160 static const char dcrc[] = "Downloaded RISC Code Checksum Failure"; 161 162 isp->isp_state = ISP_NILSTATE; 163 ISP_DISABLE_INTS(isp); 164 165 /* 166 * Put the board into PAUSE mode (so we can read the SXP registers 167 * or write FPM/FBM registers). 168 */ 169 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT); 170 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); 171 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); 172 173 switch (isp->isp_type) { 174 case ISP_HA_FC_2400: 175 btype = "2422"; 176 break; 177 case ISP_HA_FC_2500: 178 btype = "2532"; 179 break; 180 case ISP_HA_FC_2600: 181 btype = "2600"; 182 break; 183 case ISP_HA_FC_2700: 184 btype = "2700"; 185 break; 186 default: 187 break; 188 } 189 190 /* 191 * Hit the chip over the head with hammer, 192 * and give it a chance to recover. 193 */ 194 195 /* 196 * Stop DMA and wait for it to stop. 197 */ 198 ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4)); 199 for (val = loops = 0; loops < 30000; loops++) { 200 ISP_DELAY(10); 201 val = ISP_READ(isp, BIU2400_CSR); 202 if ((val & BIU2400_DMA_ACTIVE) == 0) { 203 break; 204 } 205 } 206 if (val & BIU2400_DMA_ACTIVE) { 207 isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset"); 208 return; 209 } 210 /* 211 * Hold it in SOFT_RESET and STOP state for 100us. 212 */ 213 ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4)); 214 ISP_DELAY(100); 215 for (loops = 0; loops < 10000; loops++) { 216 ISP_DELAY(5); 217 val = ISP_READ(isp, OUTMAILBOX0); 218 } 219 for (val = loops = 0; loops < 500000; loops ++) { 220 val = ISP_READ(isp, BIU2400_CSR); 221 if ((val & BIU2400_SOFT_RESET) == 0) { 222 break; 223 } 224 } 225 if (val & BIU2400_SOFT_RESET) { 226 isp_prt(isp, ISP_LOGERR, "Failed to come out of reset"); 227 return; 228 } 229 230 /* 231 * Wait for ISP to be ready to go... 232 */ 233 loops = MBOX_DELAY_COUNT; 234 for (;;) { 235 if (ISP_READ(isp, OUTMAILBOX0) == 0) 236 break; 237 ISP_DELAY(100); 238 if (--loops < 0) { 239 ISP_DUMPREGS(isp, "chip reset timed out"); 240 return; 241 } 242 } 243 244 /* 245 * Reset RISC Processor 246 */ 247 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET); 248 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE); 249 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET); 250 251 /* 252 * Post-RISC Reset stuff. 253 */ 254 for (val = loops = 0; loops < 5000000; loops++) { 255 ISP_DELAY(5); 256 val = ISP_READ(isp, OUTMAILBOX0); 257 if (val == 0) { 258 break; 259 } 260 } 261 if (val != 0) { 262 isp_prt(isp, ISP_LOGERR, "reset didn't clear"); 263 return; 264 } 265 266 ISP_WRITE(isp, BIU2400_REQINP, 0); 267 ISP_WRITE(isp, BIU2400_REQOUTP, 0); 268 ISP_WRITE(isp, BIU2400_RSPINP, 0); 269 ISP_WRITE(isp, BIU2400_RSPOUTP, 0); 270 if (!IS_26XX(isp)) { 271 ISP_WRITE(isp, BIU2400_PRI_REQINP, 0); 272 ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0); 273 } 274 ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0); 275 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0); 276 277 /* 278 * Wait for everything to finish firing up. 279 */ 280 loops = MBOX_DELAY_COUNT; 281 while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) { 282 ISP_DELAY(100); 283 if (--loops < 0) { 284 isp_prt(isp, ISP_LOGERR, "MBOX_BUSY never cleared on reset"); 285 return; 286 } 287 } 288 289 /* 290 * Up until this point we've done everything by just reading or 291 * setting registers. From this point on we rely on at least *some* 292 * kind of firmware running in the card. 293 */ 294 295 /* 296 * Do some sanity checking by running a NOP command. 297 * If it succeeds, the ROM firmware is now running. 298 */ 299 MBSINIT(&mbs, MBOX_NO_OP, MBLOGALL, 0); 300 isp_mboxcmd(isp, &mbs); 301 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 302 isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]); 303 return; 304 } 305 306 /* 307 * Do some operational tests 308 */ 309 { 310 static const uint16_t patterns[MAX_MAILBOX] = { 311 0x0000, 0xdead, 0xbeef, 0xffff, 312 0xa5a5, 0x5a5a, 0x7f7f, 0x7ff7, 313 0x3421, 0xabcd, 0xdcba, 0xfeef, 314 0xbead, 0xdebe, 0x2222, 0x3333, 315 0x5555, 0x6666, 0x7777, 0xaaaa, 316 0xffff, 0xdddd, 0x9999, 0x1fbc, 317 0x6666, 0x6677, 0x1122, 0x33ff, 318 0x0000, 0x0001, 0x1000, 0x1010, 319 }; 320 int nmbox = ISP_NMBOX(isp); 321 MBSINIT(&mbs, MBOX_MAILBOX_REG_TEST, MBLOGALL, 0); 322 for (i = 1; i < nmbox; i++) { 323 mbs.param[i] = patterns[i]; 324 } 325 isp_mboxcmd(isp, &mbs); 326 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 327 return; 328 } 329 for (i = 1; i < nmbox; i++) { 330 if (mbs.param[i] != patterns[i]) { 331 isp_prt(isp, ISP_LOGERR, "Register Test Failed at Register %d: should have 0x%04x but got 0x%04x", i, patterns[i], mbs.param[i]); 332 return; 333 } 334 } 335 } 336 337 /* 338 * Download new Firmware, unless requested not to do so. 339 * This is made slightly trickier in some cases where the 340 * firmware of the ROM revision is newer than the revision 341 * compiled into the driver. So, where we used to compare 342 * versions of our f/w and the ROM f/w, now we just see 343 * whether we have f/w at all and whether a config flag 344 * has disabled our download. 345 */ 346 if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) { 347 dodnld = 0; 348 } else { 349 350 /* 351 * Set up DMA for the request and response queues. 352 * We do this now so we can use the request queue 353 * for dma to load firmware from. 354 */ 355 if (ISP_MBOXDMASETUP(isp) != 0) { 356 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); 357 return; 358 } 359 } 360 361 code_org = ISP_CODE_ORG_2400; 362 isp->isp_loaded_fw = 0; 363 if (dodnld) { 364 const uint32_t *ptr = isp->isp_mdvec->dv_ispfw; 365 uint32_t la, wi, wl; 366 367 /* 368 * Keep loading until we run out of f/w. 369 */ 370 code_org = ptr[2]; /* 1st load address is our start addr */ 371 for (;;) { 372 isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]); 373 374 wi = 0; 375 la = ptr[2]; 376 wl = ptr[3]; 377 while (wi < ptr[3]) { 378 uint32_t *cp; 379 uint32_t nw; 380 381 nw = min(wl, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) / 4); 382 cp = isp->isp_rquest; 383 for (i = 0; i < nw; i++) 384 ISP_IOXPUT_32(isp, ptr[wi + i], &cp[i]); 385 MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), -1); 386 MBSINIT(&mbs, MBOX_LOAD_RISC_RAM, MBLOGALL, 0); 387 mbs.param[1] = la; 388 mbs.param[2] = DMA_WD1(isp->isp_rquest_dma); 389 mbs.param[3] = DMA_WD0(isp->isp_rquest_dma); 390 mbs.param[4] = nw >> 16; 391 mbs.param[5] = nw; 392 mbs.param[6] = DMA_WD3(isp->isp_rquest_dma); 393 mbs.param[7] = DMA_WD2(isp->isp_rquest_dma); 394 mbs.param[8] = la >> 16; 395 isp_prt(isp, ISP_LOGDEBUG0, "LOAD RISC RAM %u words at load address 0x%x", nw, la); 396 isp_mboxcmd(isp, &mbs); 397 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 398 isp_prt(isp, ISP_LOGERR, "F/W download failed"); 399 return; 400 } 401 la += nw; 402 wi += nw; 403 wl -= nw; 404 } 405 406 if (ptr[1] == 0) { 407 break; 408 } 409 ptr += ptr[3]; 410 } 411 isp->isp_loaded_fw = 1; 412 } else if (IS_26XX(isp)) { 413 isp_prt(isp, ISP_LOGDEBUG1, "loading firmware from flash"); 414 MBSINIT(&mbs, MBOX_LOAD_FLASH_FIRMWARE, MBLOGALL, 5000000); 415 mbs.ibitm = 0x01; 416 mbs.obitm = 0x07; 417 isp_mboxcmd(isp, &mbs); 418 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 419 isp_prt(isp, ISP_LOGERR, "Flash F/W load failed"); 420 return; 421 } 422 } else { 423 isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download"); 424 } 425 426 /* 427 * If we loaded firmware, verify its checksum 428 */ 429 if (isp->isp_loaded_fw) { 430 MBSINIT(&mbs, MBOX_VERIFY_CHECKSUM, MBLOGNONE, 0); 431 mbs.param[1] = code_org >> 16; 432 mbs.param[2] = code_org; 433 isp_mboxcmd(isp, &mbs); 434 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 435 isp_prt(isp, ISP_LOGERR, dcrc); 436 return; 437 } 438 } 439 440 /* 441 * Now start it rolling. 442 * 443 * If we didn't actually download f/w, 444 * we still need to (re)start it. 445 */ 446 MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000); 447 if (IS_26XX(isp)) { 448 mbs.param[1] = code_org >> 16; 449 mbs.param[2] = code_org; 450 } else { 451 mbs.param[1] = code_org >> 16; 452 mbs.param[2] = code_org; 453 if (isp->isp_loaded_fw) 454 mbs.param[3] = 0; 455 else 456 mbs.param[3] = 1; 457 } 458 isp_mboxcmd(isp, &mbs); 459 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) 460 return; 461 462 /* 463 * Ask the chip for the current firmware version. 464 * This should prove that the new firmware is working. 465 */ 466 MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 5000000); 467 isp_mboxcmd(isp, &mbs); 468 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 469 return; 470 } 471 472 isp->isp_fwrev[0] = mbs.param[1]; 473 isp->isp_fwrev[1] = mbs.param[2]; 474 isp->isp_fwrev[2] = mbs.param[3]; 475 isp->isp_fwattr = mbs.param[6]; 476 isp->isp_fwattr |= ((uint64_t) mbs.param[15]) << 16; 477 if (isp->isp_fwattr & ISP2400_FW_ATTR_EXTNDED) { 478 isp->isp_fwattr |= 479 (((uint64_t) mbs.param[16]) << 32) | 480 (((uint64_t) mbs.param[17]) << 48); 481 } 482 483 isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d", 484 btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]); 485 486 fwt = isp->isp_fwattr; 487 buf = FCPARAM(isp, 0)->isp_scanscratch; 488 ISP_SNPRINTF(buf, ISP_FC_SCRLEN, "Attributes:"); 489 if (fwt & ISP2400_FW_ATTR_CLASS2) { 490 fwt ^=ISP2400_FW_ATTR_CLASS2; 491 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s Class2", buf); 492 } 493 if (fwt & ISP2400_FW_ATTR_IP) { 494 fwt ^=ISP2400_FW_ATTR_IP; 495 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s IP", buf); 496 } 497 if (fwt & ISP2400_FW_ATTR_MULTIID) { 498 fwt ^=ISP2400_FW_ATTR_MULTIID; 499 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MultiID", buf); 500 } 501 if (fwt & ISP2400_FW_ATTR_SB2) { 502 fwt ^=ISP2400_FW_ATTR_SB2; 503 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SB2", buf); 504 } 505 if (fwt & ISP2400_FW_ATTR_T10CRC) { 506 fwt ^=ISP2400_FW_ATTR_T10CRC; 507 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s T10CRC", buf); 508 } 509 if (fwt & ISP2400_FW_ATTR_VI) { 510 fwt ^=ISP2400_FW_ATTR_VI; 511 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VI", buf); 512 } 513 if (fwt & ISP2400_FW_ATTR_MQ) { 514 fwt ^=ISP2400_FW_ATTR_MQ; 515 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MQ", buf); 516 } 517 if (fwt & ISP2400_FW_ATTR_MSIX) { 518 fwt ^=ISP2400_FW_ATTR_MSIX; 519 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MSIX", buf); 520 } 521 if (fwt & ISP2400_FW_ATTR_FCOE) { 522 fwt ^=ISP2400_FW_ATTR_FCOE; 523 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s FCOE", buf); 524 } 525 if (fwt & ISP2400_FW_ATTR_VP0) { 526 fwt ^= ISP2400_FW_ATTR_VP0; 527 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VP0_Decoupling", buf); 528 } 529 if (fwt & ISP2400_FW_ATTR_EXPFW) { 530 fwt ^= ISP2400_FW_ATTR_EXPFW; 531 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (Experimental)", buf); 532 } 533 if (fwt & ISP2400_FW_ATTR_HOTFW) { 534 fwt ^= ISP2400_FW_ATTR_HOTFW; 535 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s HotFW", buf); 536 } 537 fwt &= ~ISP2400_FW_ATTR_EXTNDED; 538 if (fwt & ISP2400_FW_ATTR_EXTVP) { 539 fwt ^= ISP2400_FW_ATTR_EXTVP; 540 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ExtVP", buf); 541 } 542 if (fwt & ISP2400_FW_ATTR_VN2VN) { 543 fwt ^= ISP2400_FW_ATTR_VN2VN; 544 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VN2VN", buf); 545 } 546 if (fwt & ISP2400_FW_ATTR_EXMOFF) { 547 fwt ^= ISP2400_FW_ATTR_EXMOFF; 548 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s EXMOFF", buf); 549 } 550 if (fwt & ISP2400_FW_ATTR_NPMOFF) { 551 fwt ^= ISP2400_FW_ATTR_NPMOFF; 552 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s NPMOFF", buf); 553 } 554 if (fwt & ISP2400_FW_ATTR_DIFCHOP) { 555 fwt ^= ISP2400_FW_ATTR_DIFCHOP; 556 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s DIFCHOP", buf); 557 } 558 if (fwt & ISP2400_FW_ATTR_SRIOV) { 559 fwt ^= ISP2400_FW_ATTR_SRIOV; 560 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SRIOV", buf); 561 } 562 if (fwt & ISP2400_FW_ATTR_ASICTMP) { 563 fwt ^= ISP2400_FW_ATTR_ASICTMP; 564 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ASICTMP", buf); 565 } 566 if (fwt & ISP2400_FW_ATTR_ATIOMQ) { 567 fwt ^= ISP2400_FW_ATTR_ATIOMQ; 568 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ATIOMQ", buf); 569 } 570 if (fwt) { 571 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (unknown 0x%08x%08x)", buf, 572 (uint32_t) (fwt >> 32), (uint32_t) fwt); 573 } 574 isp_prt(isp, ISP_LOGCONFIG, "%s", buf); 575 576 MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0); 577 isp_mboxcmd(isp, &mbs); 578 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 579 return; 580 } 581 isp->isp_maxcmds = mbs.param[3]; 582 /* Limit to the maximum of our hardcoded handle format (16K now). */ 583 isp->isp_maxcmds = MIN(isp->isp_maxcmds, ISP_HANDLE_MAX - ISP_HANDLE_RESERVE); 584 isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds); 585 586 /* 587 * If we don't have Multi-ID f/w loaded, we need to restrict channels to one. 588 * Only make this check for non-SCSI cards (I'm not sure firmware attributes 589 * work for them). 590 */ 591 if (isp->isp_nchan > 1) { 592 if (!ISP_CAP_MULTI_ID(isp)) { 593 isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, " 594 "only can enable 1 of %d channels", isp->isp_nchan); 595 isp->isp_nchan = 1; 596 } else if (!ISP_CAP_VP0(isp)) { 597 isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID " 598 "feature properly without VP0_Decoupling"); 599 isp->isp_nchan = 1; 600 } 601 } 602 603 /* 604 * Final DMA setup after we got isp_maxcmds. 605 */ 606 if (ISP_MBOXDMASETUP(isp) != 0) { 607 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); 608 return; 609 } 610 611 /* 612 * Setup interrupts. 613 */ 614 if (ISP_IRQSETUP(isp) != 0) { 615 isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ"); 616 return; 617 } 618 ISP_ENABLE_INTS(isp); 619 620 for (i = 0; i < isp->isp_nchan; i++) 621 isp_change_fw_state(isp, i, FW_CONFIG_WAIT); 622 623 isp->isp_state = ISP_RESETSTATE; 624 625 /* 626 * We get some default values established. As a side 627 * effect, NVRAM is read here (unless overriden by 628 * a configuration flag). 629 */ 630 if (do_load_defaults) { 631 for (i = 0; i < isp->isp_nchan; i++) 632 isp_setdfltfcparm(isp, i); 633 } 634 } 635 636 /* 637 * Clean firmware shutdown. 638 */ 639 static int 640 isp_stop(ispsoftc_t *isp) 641 { 642 mbreg_t mbs; 643 644 isp->isp_state = ISP_NILSTATE; 645 MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000); 646 mbs.param[1] = 0; 647 mbs.param[2] = 0; 648 mbs.param[3] = 0; 649 mbs.param[4] = 0; 650 mbs.param[5] = 0; 651 mbs.param[6] = 0; 652 mbs.param[7] = 0; 653 mbs.param[8] = 0; 654 isp_mboxcmd(isp, &mbs); 655 return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]); 656 } 657 658 /* 659 * Hardware shutdown. 660 */ 661 void 662 isp_shutdown(ispsoftc_t *isp) 663 { 664 665 if (isp->isp_state >= ISP_RESETSTATE) 666 isp_stop(isp); 667 ISP_DISABLE_INTS(isp); 668 ISP_WRITE(isp, BIU2400_ICR, 0); 669 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); 670 } 671 672 /* 673 * Initialize Parameters of Hardware to a known state. 674 * 675 * Locks are held before coming here. 676 */ 677 void 678 isp_init(ispsoftc_t *isp) 679 { 680 fcparam *fcp; 681 isp_icb_2400_t local, *icbp = &local; 682 mbreg_t mbs; 683 int chan; 684 int ownloopid = 0; 685 686 /* 687 * Check to see whether all channels have *some* kind of role 688 */ 689 for (chan = 0; chan < isp->isp_nchan; chan++) { 690 fcp = FCPARAM(isp, chan); 691 if (fcp->role != ISP_ROLE_NONE) { 692 break; 693 } 694 } 695 if (chan == isp->isp_nchan) { 696 isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan); 697 return; 698 } 699 700 isp->isp_state = ISP_INITSTATE; 701 702 /* 703 * Start with channel 0. 704 */ 705 fcp = FCPARAM(isp, 0); 706 707 /* 708 * Turn on LIP F8 async event (1) 709 */ 710 MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0); 711 mbs.param[1] = 1; 712 isp_mboxcmd(isp, &mbs); 713 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 714 return; 715 } 716 717 ISP_MEMZERO(icbp, sizeof (*icbp)); 718 icbp->icb_fwoptions1 = fcp->isp_fwoptions; 719 icbp->icb_fwoptions2 = fcp->isp_xfwoptions; 720 icbp->icb_fwoptions3 = fcp->isp_zfwoptions; 721 if (isp->isp_nchan > 1 && ISP_CAP_VP0(isp)) { 722 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE; 723 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE; 724 } else { 725 if (fcp->role & ISP_ROLE_TARGET) 726 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE; 727 else 728 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE; 729 if (fcp->role & ISP_ROLE_INITIATOR) 730 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE; 731 else 732 icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE; 733 } 734 735 icbp->icb_version = ICB_VERSION1; 736 icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp); 737 if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { 738 isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN); 739 icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN; 740 } 741 742 if (!IS_26XX(isp)) 743 icbp->icb_execthrottle = 0xffff; 744 745 #ifdef ISP_TARGET_MODE 746 /* 747 * Set target exchange count. Take half if we are supporting both roles. 748 */ 749 if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) { 750 if ((icbp->icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE) == 0) 751 icbp->icb_xchgcnt = MIN(isp->isp_maxcmds / 2, ATPDPSIZE); 752 else 753 icbp->icb_xchgcnt = isp->isp_maxcmds; 754 } 755 #endif 756 757 ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0; 758 icbp->icb_hardaddr = fcp->isp_loopid; 759 if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) { 760 icbp->icb_hardaddr = 0; 761 ownloopid = 0; 762 } 763 764 if (ownloopid) 765 icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS; 766 767 if (isp->isp_confopts & ISP_CFG_NOFCTAPE) { 768 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE; 769 } 770 if (isp->isp_confopts & ISP_CFG_FCTAPE) { 771 icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE; 772 } 773 774 for (chan = 0; chan < isp->isp_nchan; chan++) { 775 if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE) 776 FCPARAM(isp, chan)->fctape_enabled = 1; 777 else 778 FCPARAM(isp, chan)->fctape_enabled = 0; 779 } 780 781 switch (isp->isp_confopts & ISP_CFG_PORT_PREF) { 782 case ISP_CFG_LPORT_ONLY: 783 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; 784 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY; 785 break; 786 case ISP_CFG_NPORT_ONLY: 787 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; 788 icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY; 789 break; 790 case ISP_CFG_NPORT: 791 /* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */ 792 case ISP_CFG_LPORT: 793 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; 794 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP; 795 break; 796 default: 797 /* Let NVRAM settings define it if they are sane */ 798 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK) { 799 case ICB2400_OPT2_LOOP_ONLY: 800 case ICB2400_OPT2_PTP_ONLY: 801 case ICB2400_OPT2_LOOP_2_PTP: 802 break; 803 default: 804 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; 805 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP; 806 } 807 break; 808 } 809 810 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) { 811 case ICB2400_OPT2_ZIO: 812 case ICB2400_OPT2_ZIO1: 813 icbp->icb_idelaytimer = 0; 814 break; 815 case 0: 816 break; 817 default: 818 isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK); 819 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK; 820 break; 821 } 822 823 if (IS_26XX(isp)) { 824 /* Use handshake to reduce global lock congestion. */ 825 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR; 826 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA; 827 } 828 829 if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) { 830 icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24; 831 } 832 if (isp->isp_confopts & ISP_CFG_1GB) { 833 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 834 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB; 835 } else if (isp->isp_confopts & ISP_CFG_2GB) { 836 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 837 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB; 838 } else if (isp->isp_confopts & ISP_CFG_4GB) { 839 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 840 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB; 841 } else if (isp->isp_confopts & ISP_CFG_8GB) { 842 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 843 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB; 844 } else if (isp->isp_confopts & ISP_CFG_16GB) { 845 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 846 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB; 847 } else if (isp->isp_confopts & ISP_CFG_32GB) { 848 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 849 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB; 850 } else { 851 switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) { 852 case ICB2400_OPT3_RATE_4GB: 853 case ICB2400_OPT3_RATE_8GB: 854 case ICB2400_OPT3_RATE_16GB: 855 case ICB2400_OPT3_RATE_32GB: 856 case ICB2400_OPT3_RATE_AUTO: 857 break; 858 case ICB2400_OPT3_RATE_2GB: 859 if (isp->isp_type <= ISP_HA_FC_2500) 860 break; 861 /*FALLTHROUGH*/ 862 case ICB2400_OPT3_RATE_1GB: 863 if (isp->isp_type <= ISP_HA_FC_2400) 864 break; 865 /*FALLTHROUGH*/ 866 default: 867 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 868 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO; 869 break; 870 } 871 } 872 if (ownloopid == 0) { 873 icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID; 874 } 875 icbp->icb_logintime = ICB_LOGIN_TOV; 876 877 if (fcp->isp_wwnn && fcp->isp_wwpn) { 878 icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS; 879 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn); 880 MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn); 881 isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node 0x%08x%08x Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwnn >> 32)), ((uint32_t) (fcp->isp_wwnn)), 882 ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn))); 883 } else if (fcp->isp_wwpn) { 884 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS; 885 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn); 886 isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node to be same as Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn))); 887 } else { 888 isp_prt(isp, ISP_LOGERR, "No valid WWNs to use"); 889 return; 890 } 891 icbp->icb_retry_count = fcp->isp_retry_count; 892 893 icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp); 894 if (icbp->icb_rqstqlen < 8) { 895 isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen); 896 return; 897 } 898 icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp); 899 if (icbp->icb_rsltqlen < 8) { 900 isp_prt(isp, ISP_LOGERR, "bad result queue length %d", 901 icbp->icb_rsltqlen); 902 return; 903 } 904 icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma); 905 icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma); 906 icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma); 907 icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma); 908 909 icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma); 910 icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma); 911 icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma); 912 icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma); 913 914 #ifdef ISP_TARGET_MODE 915 /* unconditionally set up the ATIO queue if we support target mode */ 916 icbp->icb_atioqlen = ATIO_QUEUE_LEN(isp); 917 if (icbp->icb_atioqlen < 8) { 918 isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen); 919 return; 920 } 921 icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma); 922 icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma); 923 icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma); 924 icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma); 925 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma), 926 DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma)); 927 #endif 928 929 if (ISP_CAP_MSIX(isp) && isp->isp_nirq >= 2) { 930 icbp->icb_msixresp = 1; 931 if (IS_26XX(isp) && isp->isp_nirq >= 3) 932 icbp->icb_msixatio = 2; 933 } 934 935 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3); 936 937 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x", DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma), 938 DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma), 939 DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma)); 940 941 if (FC_SCRATCH_ACQUIRE(isp, 0)) { 942 isp_prt(isp, ISP_LOGERR, sacq); 943 return; 944 } 945 ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN); 946 isp_put_icb_2400(isp, icbp, fcp->isp_scratch); 947 if (isp->isp_dblev & ISP_LOGDEBUG1) { 948 isp_print_bytes(isp, "isp_init", 949 sizeof (*icbp), fcp->isp_scratch); 950 } 951 952 /* 953 * Now fill in information about any additional channels 954 */ 955 if (isp->isp_nchan > 1) { 956 isp_icb_2400_vpinfo_t vpinfo, *vdst; 957 vp_port_info_t pi, *pdst; 958 size_t amt = 0; 959 uint8_t *off; 960 961 vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA; 962 if (ISP_CAP_VP0(isp)) { 963 vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE; 964 vpinfo.vp_count = isp->isp_nchan; 965 chan = 0; 966 } else { 967 vpinfo.vp_count = isp->isp_nchan - 1; 968 chan = 1; 969 } 970 off = fcp->isp_scratch; 971 off += ICB2400_VPINFO_OFF; 972 vdst = (isp_icb_2400_vpinfo_t *) off; 973 isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst); 974 amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t); 975 for (; chan < isp->isp_nchan; chan++) { 976 fcparam *fcp2; 977 978 ISP_MEMZERO(&pi, sizeof (pi)); 979 fcp2 = FCPARAM(isp, chan); 980 if (fcp2->role != ISP_ROLE_NONE) { 981 pi.vp_port_options = ICB2400_VPOPT_ENABLED | 982 ICB2400_VPOPT_ENA_SNSLOGIN; 983 if (fcp2->role & ISP_ROLE_INITIATOR) 984 pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE; 985 if ((fcp2->role & ISP_ROLE_TARGET) == 0) 986 pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE; 987 if (fcp2->isp_loopid < LOCAL_LOOP_LIM) { 988 pi.vp_port_loopid = fcp2->isp_loopid; 989 if (isp->isp_confopts & ISP_CFG_OWNLOOPID) 990 pi.vp_port_options |= ICB2400_VPOPT_HARD_ADDRESS; 991 } 992 993 } 994 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn); 995 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn); 996 off = fcp->isp_scratch; 997 if (ISP_CAP_VP0(isp)) 998 off += ICB2400_VPINFO_PORT_OFF(chan); 999 else 1000 off += ICB2400_VPINFO_PORT_OFF(chan - 1); 1001 pdst = (vp_port_info_t *) off; 1002 isp_put_vp_port_info(isp, &pi, pdst); 1003 amt += ICB2400_VPOPT_WRITE_SIZE; 1004 } 1005 if (isp->isp_dblev & ISP_LOGDEBUG1) { 1006 isp_print_bytes(isp, "isp_init", 1007 amt - ICB2400_VPINFO_OFF, 1008 (char *)fcp->isp_scratch + ICB2400_VPINFO_OFF); 1009 } 1010 } 1011 1012 /* 1013 * Init the firmware 1014 */ 1015 MBSINIT(&mbs, 0, MBLOGALL, 30000000); 1016 if (isp->isp_nchan > 1) { 1017 mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID; 1018 } else { 1019 mbs.param[0] = MBOX_INIT_FIRMWARE; 1020 } 1021 mbs.param[1] = 0; 1022 mbs.param[2] = DMA_WD1(fcp->isp_scdma); 1023 mbs.param[3] = DMA_WD0(fcp->isp_scdma); 1024 mbs.param[6] = DMA_WD3(fcp->isp_scdma); 1025 mbs.param[7] = DMA_WD2(fcp->isp_scdma); 1026 isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x", DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma), DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma)); 1027 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp), 0); 1028 isp_mboxcmd(isp, &mbs); 1029 FC_SCRATCH_RELEASE(isp, 0); 1030 1031 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 1032 return; 1033 } 1034 isp->isp_reqidx = 0; 1035 isp->isp_reqodx = 0; 1036 isp->isp_residx = 0; 1037 isp->isp_resodx = 0; 1038 isp->isp_atioodx = 0; 1039 1040 /* 1041 * Whatever happens, we're now committed to being here. 1042 */ 1043 isp->isp_state = ISP_RUNSTATE; 1044 } 1045 1046 static int 1047 isp_fc_enable_vp(ispsoftc_t *isp, int chan) 1048 { 1049 fcparam *fcp = FCPARAM(isp, chan); 1050 vp_modify_t vp; 1051 void *reqp; 1052 uint8_t resp[QENTRY_LEN]; 1053 1054 /* Build a VP MODIFY command in memory */ 1055 ISP_MEMZERO(&vp, sizeof(vp)); 1056 vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY; 1057 vp.vp_mod_hdr.rqs_entry_count = 1; 1058 vp.vp_mod_cnt = 1; 1059 vp.vp_mod_idx0 = chan; 1060 vp.vp_mod_cmd = VP_MODIFY_ENA; 1061 vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED | 1062 ICB2400_VPOPT_ENA_SNSLOGIN; 1063 if (fcp->role & ISP_ROLE_INITIATOR) 1064 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE; 1065 if ((fcp->role & ISP_ROLE_TARGET) == 0) 1066 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE; 1067 if (fcp->isp_loopid < LOCAL_LOOP_LIM) { 1068 vp.vp_mod_ports[0].loopid = fcp->isp_loopid; 1069 if (isp->isp_confopts & ISP_CFG_OWNLOOPID) 1070 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS; 1071 } 1072 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn); 1073 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn); 1074 1075 /* Prepare space for response in memory */ 1076 memset(resp, 0xff, sizeof(resp)); 1077 vp.vp_mod_hdl = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); 1078 if (vp.vp_mod_hdl == 0) { 1079 isp_prt(isp, ISP_LOGERR, 1080 "%s: VP_MODIFY of Chan %d out of handles", __func__, chan); 1081 return (EIO); 1082 } 1083 1084 /* Send request and wait for response. */ 1085 reqp = isp_getrqentry(isp); 1086 if (reqp == NULL) { 1087 isp_prt(isp, ISP_LOGERR, 1088 "%s: VP_MODIFY of Chan %d out of rqent", __func__, chan); 1089 isp_destroy_handle(isp, vp.vp_mod_hdl); 1090 return (EIO); 1091 } 1092 isp_put_vp_modify(isp, &vp, (vp_modify_t *)reqp); 1093 if (isp->isp_dblev & ISP_LOGDEBUG1) 1094 isp_print_bytes(isp, "IOCB VP_MODIFY", QENTRY_LEN, reqp); 1095 ISP_SYNC_REQUEST(isp); 1096 if (msleep(resp, &isp->isp_lock, 0, "VP_MODIFY", 5*hz) == EWOULDBLOCK) { 1097 isp_prt(isp, ISP_LOGERR, 1098 "%s: VP_MODIFY of Chan %d timed out", __func__, chan); 1099 isp_destroy_handle(isp, vp.vp_mod_hdl); 1100 return (EIO); 1101 } 1102 if (isp->isp_dblev & ISP_LOGDEBUG1) 1103 isp_print_bytes(isp, "IOCB VP_MODIFY response", QENTRY_LEN, resp); 1104 isp_get_vp_modify(isp, (vp_modify_t *)resp, &vp); 1105 1106 if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) { 1107 isp_prt(isp, ISP_LOGERR, 1108 "%s: VP_MODIFY of Chan %d failed with flags %x status %d", 1109 __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status); 1110 return (EIO); 1111 } 1112 return (0); 1113 } 1114 1115 static int 1116 isp_fc_disable_vp(ispsoftc_t *isp, int chan) 1117 { 1118 vp_ctrl_info_t vp; 1119 void *reqp; 1120 uint8_t resp[QENTRY_LEN]; 1121 1122 /* Build a VP CTRL command in memory */ 1123 ISP_MEMZERO(&vp, sizeof(vp)); 1124 vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL; 1125 vp.vp_ctrl_hdr.rqs_entry_count = 1; 1126 if (ISP_CAP_VP0(isp)) { 1127 vp.vp_ctrl_status = 1; 1128 } else { 1129 vp.vp_ctrl_status = 0; 1130 chan--; /* VP0 can not be controlled in this case. */ 1131 } 1132 vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL; 1133 vp.vp_ctrl_vp_count = 1; 1134 vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16); 1135 1136 /* Prepare space for response in memory */ 1137 memset(resp, 0xff, sizeof(resp)); 1138 vp.vp_ctrl_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); 1139 if (vp.vp_ctrl_handle == 0) { 1140 isp_prt(isp, ISP_LOGERR, 1141 "%s: VP_CTRL of Chan %d out of handles", __func__, chan); 1142 return (EIO); 1143 } 1144 1145 /* Send request and wait for response. */ 1146 reqp = isp_getrqentry(isp); 1147 if (reqp == NULL) { 1148 isp_prt(isp, ISP_LOGERR, 1149 "%s: VP_CTRL of Chan %d out of rqent", __func__, chan); 1150 isp_destroy_handle(isp, vp.vp_ctrl_handle); 1151 return (EIO); 1152 } 1153 isp_put_vp_ctrl_info(isp, &vp, (vp_ctrl_info_t *)reqp); 1154 if (isp->isp_dblev & ISP_LOGDEBUG1) 1155 isp_print_bytes(isp, "IOCB VP_CTRL", QENTRY_LEN, reqp); 1156 ISP_SYNC_REQUEST(isp); 1157 if (msleep(resp, &isp->isp_lock, 0, "VP_CTRL", 5*hz) == EWOULDBLOCK) { 1158 isp_prt(isp, ISP_LOGERR, 1159 "%s: VP_CTRL of Chan %d timed out", __func__, chan); 1160 isp_destroy_handle(isp, vp.vp_ctrl_handle); 1161 return (EIO); 1162 } 1163 if (isp->isp_dblev & ISP_LOGDEBUG1) 1164 isp_print_bytes(isp, "IOCB VP_CTRL response", QENTRY_LEN, resp); 1165 isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)resp, &vp); 1166 1167 if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) { 1168 isp_prt(isp, ISP_LOGERR, 1169 "%s: VP_CTRL of Chan %d failed with flags %x status %d %d", 1170 __func__, chan, vp.vp_ctrl_hdr.rqs_flags, 1171 vp.vp_ctrl_status, vp.vp_ctrl_index_fail); 1172 return (EIO); 1173 } 1174 return (0); 1175 } 1176 1177 static int 1178 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role) 1179 { 1180 fcparam *fcp = FCPARAM(isp, chan); 1181 int i, was, res = 0; 1182 1183 if (chan >= isp->isp_nchan) { 1184 isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan); 1185 return (ENXIO); 1186 } 1187 if (fcp->role == new_role) 1188 return (0); 1189 for (was = 0, i = 0; i < isp->isp_nchan; i++) { 1190 if (FCPARAM(isp, i)->role != ISP_ROLE_NONE) 1191 was++; 1192 } 1193 if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) { 1194 fcp->role = new_role; 1195 return (isp_reinit(isp, 0)); 1196 } 1197 if (fcp->role != ISP_ROLE_NONE) { 1198 res = isp_fc_disable_vp(isp, chan); 1199 isp_clear_portdb(isp, chan); 1200 } 1201 fcp->role = new_role; 1202 if (fcp->role != ISP_ROLE_NONE) 1203 res = isp_fc_enable_vp(isp, chan); 1204 return (res); 1205 } 1206 1207 static void 1208 isp_clear_portdb(ispsoftc_t *isp, int chan) 1209 { 1210 fcparam *fcp = FCPARAM(isp, chan); 1211 fcportdb_t *lp; 1212 int i; 1213 1214 for (i = 0; i < MAX_FC_TARG; i++) { 1215 lp = &fcp->portdb[i]; 1216 switch (lp->state) { 1217 case FC_PORTDB_STATE_DEAD: 1218 case FC_PORTDB_STATE_CHANGED: 1219 case FC_PORTDB_STATE_VALID: 1220 lp->state = FC_PORTDB_STATE_NIL; 1221 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); 1222 break; 1223 case FC_PORTDB_STATE_NIL: 1224 case FC_PORTDB_STATE_NEW: 1225 lp->state = FC_PORTDB_STATE_NIL; 1226 break; 1227 case FC_PORTDB_STATE_ZOMBIE: 1228 break; 1229 default: 1230 panic("Don't know how to clear state %d\n", lp->state); 1231 } 1232 } 1233 } 1234 1235 static void 1236 isp_mark_portdb(ispsoftc_t *isp, int chan) 1237 { 1238 fcparam *fcp = FCPARAM(isp, chan); 1239 fcportdb_t *lp; 1240 int i; 1241 1242 for (i = 0; i < MAX_FC_TARG; i++) { 1243 lp = &fcp->portdb[i]; 1244 if (lp->state == FC_PORTDB_STATE_NIL) 1245 continue; 1246 if (lp->portid >= DOMAIN_CONTROLLER_BASE && 1247 lp->portid <= DOMAIN_CONTROLLER_END) 1248 continue; 1249 fcp->portdb[i].probational = 1; 1250 } 1251 } 1252 1253 /* 1254 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards 1255 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards. 1256 */ 1257 static int 1258 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags) 1259 { 1260 isp_plogx_t pl; 1261 void *reqp; 1262 uint8_t resp[QENTRY_LEN]; 1263 uint32_t sst, parm1; 1264 int rval, lev; 1265 const char *msg; 1266 char buf[64]; 1267 1268 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x", 1269 chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ? 1270 "Login":"Logout", portid, handle); 1271 1272 ISP_MEMZERO(&pl, sizeof(pl)); 1273 pl.plogx_header.rqs_entry_count = 1; 1274 pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN; 1275 pl.plogx_nphdl = handle; 1276 pl.plogx_vphdl = chan; 1277 pl.plogx_portlo = portid; 1278 pl.plogx_rspsz_porthi = (portid >> 16) & 0xff; 1279 pl.plogx_flags = flags; 1280 1281 /* Prepare space for response in memory */ 1282 memset(resp, 0xff, sizeof(resp)); 1283 pl.plogx_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); 1284 if (pl.plogx_handle == 0) { 1285 isp_prt(isp, ISP_LOGERR, 1286 "%s: PLOGX of Chan %d out of handles", __func__, chan); 1287 return (-1); 1288 } 1289 1290 /* Send request and wait for response. */ 1291 reqp = isp_getrqentry(isp); 1292 if (reqp == NULL) { 1293 isp_prt(isp, ISP_LOGERR, 1294 "%s: PLOGX of Chan %d out of rqent", __func__, chan); 1295 isp_destroy_handle(isp, pl.plogx_handle); 1296 return (-1); 1297 } 1298 isp_put_plogx(isp, &pl, (isp_plogx_t *)reqp); 1299 if (isp->isp_dblev & ISP_LOGDEBUG1) 1300 isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, reqp); 1301 FCPARAM(isp, chan)->isp_login_hdl = handle; 1302 ISP_SYNC_REQUEST(isp); 1303 if (msleep(resp, &isp->isp_lock, 0, "PLOGX", 3 * ICB_LOGIN_TOV * hz) 1304 == EWOULDBLOCK) { 1305 isp_prt(isp, ISP_LOGERR, 1306 "%s: PLOGX of Chan %d timed out", __func__, chan); 1307 isp_destroy_handle(isp, pl.plogx_handle); 1308 return (-1); 1309 } 1310 FCPARAM(isp, chan)->isp_login_hdl = NIL_HANDLE; 1311 if (isp->isp_dblev & ISP_LOGDEBUG1) 1312 isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, resp); 1313 isp_get_plogx(isp, (isp_plogx_t *)resp, &pl); 1314 1315 if (pl.plogx_status == PLOGX_STATUS_OK) { 1316 return (0); 1317 } else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) { 1318 isp_prt(isp, ISP_LOGWARN, 1319 "status 0x%x on port login IOCB channel %d", 1320 pl.plogx_status, chan); 1321 return (-1); 1322 } 1323 1324 sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16); 1325 parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16); 1326 1327 rval = -1; 1328 lev = ISP_LOGERR; 1329 msg = NULL; 1330 1331 switch (sst) { 1332 case PLOGX_IOCBERR_NOLINK: 1333 msg = "no link"; 1334 break; 1335 case PLOGX_IOCBERR_NOIOCB: 1336 msg = "no IOCB buffer"; 1337 break; 1338 case PLOGX_IOCBERR_NOXGHG: 1339 msg = "no Exchange Control Block"; 1340 break; 1341 case PLOGX_IOCBERR_FAILED: 1342 ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff); 1343 msg = buf; 1344 break; 1345 case PLOGX_IOCBERR_NOFABRIC: 1346 msg = "no fabric"; 1347 break; 1348 case PLOGX_IOCBERR_NOTREADY: 1349 msg = "firmware not ready"; 1350 break; 1351 case PLOGX_IOCBERR_NOLOGIN: 1352 ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1); 1353 msg = buf; 1354 rval = MBOX_NOT_LOGGED_IN; 1355 break; 1356 case PLOGX_IOCBERR_REJECT: 1357 ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1); 1358 msg = buf; 1359 break; 1360 case PLOGX_IOCBERR_NOPCB: 1361 msg = "no PCB allocated"; 1362 break; 1363 case PLOGX_IOCBERR_EINVAL: 1364 ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1); 1365 msg = buf; 1366 break; 1367 case PLOGX_IOCBERR_PORTUSED: 1368 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1; 1369 ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1); 1370 msg = buf; 1371 rval = MBOX_PORT_ID_USED | (parm1 << 16); 1372 break; 1373 case PLOGX_IOCBERR_HNDLUSED: 1374 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1; 1375 ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1); 1376 msg = buf; 1377 rval = MBOX_LOOP_ID_USED; 1378 break; 1379 case PLOGX_IOCBERR_NOHANDLE: 1380 msg = "no handle allocated"; 1381 break; 1382 case PLOGX_IOCBERR_NOFLOGI: 1383 msg = "no FLOGI_ACC"; 1384 break; 1385 default: 1386 ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags); 1387 msg = buf; 1388 break; 1389 } 1390 if (msg) { 1391 isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s", 1392 chan, portid, handle, msg); 1393 } 1394 return (rval); 1395 } 1396 1397 static int 1398 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb) 1399 { 1400 mbreg_t mbs; 1401 union { 1402 isp_pdb_24xx_t bill; 1403 } un; 1404 1405 MBSINIT(&mbs, MBOX_GET_PORT_DB, 1406 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000); 1407 mbs.ibits = (1 << 9)|(1 << 10); 1408 mbs.param[1] = id; 1409 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma); 1410 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma); 1411 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma); 1412 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma); 1413 mbs.param[9] = chan; 1414 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, sizeof(un), chan); 1415 1416 isp_mboxcmd(isp, &mbs); 1417 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) 1418 return (mbs.param[0] | (mbs.param[1] << 16)); 1419 1420 MEMORYBARRIER(isp, SYNC_IFORCPU, 0, sizeof(un), chan); 1421 isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill); 1422 pdb->handle = un.bill.pdb_handle; 1423 pdb->prli_word0 = un.bill.pdb_prli_svc0; 1424 pdb->prli_word3 = un.bill.pdb_prli_svc3; 1425 pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits); 1426 ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8); 1427 ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8); 1428 isp_prt(isp, ISP_LOGDEBUG0, 1429 "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x", 1430 chan, id, pdb->portid, un.bill.pdb_flags, 1431 un.bill.pdb_curstate, un.bill.pdb_laststate); 1432 1433 if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) { 1434 mbs.param[0] = MBOX_NOT_LOGGED_IN; 1435 return (mbs.param[0]); 1436 } 1437 return (0); 1438 } 1439 1440 static int 1441 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop) 1442 { 1443 fcparam *fcp = FCPARAM(isp, chan); 1444 mbreg_t mbs; 1445 isp_pnhle_24xx_t el4, *elp4; 1446 int i, j; 1447 uint32_t p; 1448 1449 MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL, 250000); 1450 mbs.param[2] = DMA_WD1(fcp->isp_scdma); 1451 mbs.param[3] = DMA_WD0(fcp->isp_scdma); 1452 mbs.param[6] = DMA_WD3(fcp->isp_scdma); 1453 mbs.param[7] = DMA_WD2(fcp->isp_scdma); 1454 mbs.param[8] = ISP_FC_SCRLEN; 1455 mbs.param[9] = chan; 1456 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 1457 isp_prt(isp, ISP_LOGERR, sacq); 1458 return (-1); 1459 } 1460 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan); 1461 isp_mboxcmd(isp, &mbs); 1462 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 1463 FC_SCRATCH_RELEASE(isp, chan); 1464 return (mbs.param[0] | (mbs.param[1] << 16)); 1465 } 1466 MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan); 1467 elp4 = fcp->isp_scratch; 1468 for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) { 1469 isp_get_pnhle_24xx(isp, &elp4[i], &el4); 1470 p = el4.pnhle_port_id_lo | (el4.pnhle_port_id_hi << 16); 1471 if (loop && (p >> 8) != (fcp->isp_portid >> 8)) 1472 continue; 1473 handles[j++] = el4.pnhle_handle; 1474 } 1475 *num = j; 1476 FC_SCRATCH_RELEASE(isp, chan); 1477 return (0); 1478 } 1479 1480 static void 1481 isp_dump_chip_portdb(ispsoftc_t *isp, int chan) 1482 { 1483 isp_pdb_t pdb; 1484 uint16_t nphdl; 1485 1486 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan); 1487 for (nphdl = 0; nphdl != NPH_MAX_2K; nphdl++) { 1488 if (isp_getpdb(isp, chan, nphdl, &pdb)) { 1489 continue; 1490 } 1491 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x " 1492 "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x", 1493 chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1], 1494 pdb.portname[2], pdb.portname[3], pdb.portname[4], 1495 pdb.portname[5], pdb.portname[6], pdb.portname[7]); 1496 } 1497 } 1498 1499 static uint64_t 1500 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename) 1501 { 1502 uint64_t wwn = INI_NONE; 1503 mbreg_t mbs; 1504 1505 MBSINIT(&mbs, MBOX_GET_PORT_NAME, 1506 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000); 1507 mbs.param[1] = nphdl; 1508 if (nodename) 1509 mbs.param[10] = 1; 1510 mbs.param[9] = chan; 1511 isp_mboxcmd(isp, &mbs); 1512 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 1513 return (wwn); 1514 } 1515 wwn = (((uint64_t)(mbs.param[2] >> 8)) << 56) | 1516 (((uint64_t)(mbs.param[2] & 0xff))<< 48) | 1517 (((uint64_t)(mbs.param[3] >> 8)) << 40) | 1518 (((uint64_t)(mbs.param[3] & 0xff))<< 32) | 1519 (((uint64_t)(mbs.param[6] >> 8)) << 24) | 1520 (((uint64_t)(mbs.param[6] & 0xff))<< 16) | 1521 (((uint64_t)(mbs.param[7] >> 8)) << 8) | 1522 (((uint64_t)(mbs.param[7] & 0xff))); 1523 return (wwn); 1524 } 1525 1526 /* 1527 * Make sure we have good FC link. 1528 */ 1529 1530 static int 1531 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) 1532 { 1533 mbreg_t mbs; 1534 int i, r, topo; 1535 fcparam *fcp; 1536 isp_pdb_t pdb; 1537 NANOTIME_T hra, hrb; 1538 1539 fcp = FCPARAM(isp, chan); 1540 1541 if (fcp->isp_loopstate < LOOP_HAVE_LINK) 1542 return (-1); 1543 if (fcp->isp_loopstate >= LOOP_LTEST_DONE) 1544 return (0); 1545 1546 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan); 1547 1548 /* 1549 * Wait up to N microseconds for F/W to go to a ready state. 1550 */ 1551 GET_NANOTIME(&hra); 1552 while (1) { 1553 isp_change_fw_state(isp, chan, isp_fw_state(isp, chan)); 1554 if (fcp->isp_fwstate == FW_READY) { 1555 break; 1556 } 1557 if (fcp->isp_loopstate < LOOP_HAVE_LINK) 1558 goto abort; 1559 GET_NANOTIME(&hrb); 1560 if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay)) 1561 break; 1562 ISP_SLEEP(isp, 1000); 1563 } 1564 if (fcp->isp_fwstate != FW_READY) { 1565 isp_prt(isp, ISP_LOG_SANCFG, 1566 "Chan %d Firmware is not ready (%s)", 1567 chan, isp_fc_fw_statename(fcp->isp_fwstate)); 1568 return (-1); 1569 } 1570 1571 /* 1572 * Get our Loop ID and Port ID. 1573 */ 1574 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0); 1575 mbs.param[9] = chan; 1576 isp_mboxcmd(isp, &mbs); 1577 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 1578 return (-1); 1579 } 1580 1581 topo = (int) mbs.param[6]; 1582 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) 1583 topo = TOPO_PTP_STUB; 1584 fcp->isp_topo = topo; 1585 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16); 1586 1587 if (!TOPO_IS_FABRIC(fcp->isp_topo)) { 1588 fcp->isp_loopid = mbs.param[1] & 0xff; 1589 } else if (fcp->isp_topo != TOPO_F_PORT) { 1590 uint8_t alpa = fcp->isp_portid; 1591 1592 for (i = 0; alpa_map[i]; i++) { 1593 if (alpa_map[i] == alpa) 1594 break; 1595 } 1596 if (alpa_map[i]) 1597 fcp->isp_loopid = i; 1598 } 1599 1600 #if 0 1601 fcp->isp_loopstate = LOOP_HAVE_ADDR; 1602 #endif 1603 fcp->isp_loopstate = LOOP_TESTING_LINK; 1604 1605 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { 1606 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb); 1607 if (r != 0 || pdb.portid == 0) { 1608 isp_prt(isp, ISP_LOGWARN, 1609 "fabric topology, but cannot get info about fabric controller (0x%x)", r); 1610 fcp->isp_topo = TOPO_PTP_STUB; 1611 goto not_on_fabric; 1612 } 1613 1614 fcp->isp_fabric_params = mbs.param[7]; 1615 fcp->isp_sns_hdl = NPH_SNS_ID; 1616 r = isp_register_fc4_type(isp, chan); 1617 if (fcp->isp_loopstate < LOOP_TESTING_LINK) 1618 goto abort; 1619 if (r != 0) 1620 goto not_on_fabric; 1621 r = isp_register_fc4_features_24xx(isp, chan); 1622 if (fcp->isp_loopstate < LOOP_TESTING_LINK) 1623 goto abort; 1624 if (r != 0) 1625 goto not_on_fabric; 1626 r = isp_register_port_name_24xx(isp, chan); 1627 if (fcp->isp_loopstate < LOOP_TESTING_LINK) 1628 goto abort; 1629 if (r != 0) 1630 goto not_on_fabric; 1631 isp_register_node_name_24xx(isp, chan); 1632 if (fcp->isp_loopstate < LOOP_TESTING_LINK) 1633 goto abort; 1634 } 1635 1636 not_on_fabric: 1637 /* Get link speed. */ 1638 fcp->isp_gbspeed = 1; 1639 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000); 1640 mbs.param[1] = MBGSD_GET_RATE; 1641 /* mbs.param[2] undefined if we're just getting rate */ 1642 isp_mboxcmd(isp, &mbs); 1643 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { 1644 if (mbs.param[1] == MBGSD_10GB) 1645 fcp->isp_gbspeed = 10; 1646 else if (mbs.param[1] == MBGSD_32GB) 1647 fcp->isp_gbspeed = 32; 1648 else if (mbs.param[1] == MBGSD_16GB) 1649 fcp->isp_gbspeed = 16; 1650 else if (mbs.param[1] == MBGSD_8GB) 1651 fcp->isp_gbspeed = 8; 1652 else if (mbs.param[1] == MBGSD_4GB) 1653 fcp->isp_gbspeed = 4; 1654 else if (mbs.param[1] == MBGSD_2GB) 1655 fcp->isp_gbspeed = 2; 1656 else if (mbs.param[1] == MBGSD_1GB) 1657 fcp->isp_gbspeed = 1; 1658 } 1659 1660 if (fcp->isp_loopstate < LOOP_TESTING_LINK) { 1661 abort: 1662 isp_prt(isp, ISP_LOG_SANCFG, 1663 "Chan %d FC link test aborted", chan); 1664 return (1); 1665 } 1666 fcp->isp_loopstate = LOOP_LTEST_DONE; 1667 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, 1668 "Chan %d WWPN %016jx WWNN %016jx", 1669 chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn); 1670 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, 1671 "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x", 1672 chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid, 1673 fcp->isp_loopid); 1674 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan); 1675 return (0); 1676 } 1677 1678 /* 1679 * Complete the synchronization of our Port Database. 1680 * 1681 * At this point, we've scanned the local loop (if any) and the fabric 1682 * and performed fabric logins on all new devices. 1683 * 1684 * Our task here is to go through our port database removing any entities 1685 * that are still marked probational (issuing PLOGO for ones which we had 1686 * PLOGI'd into) or are dead, and notifying upper layers about new/changed 1687 * devices. 1688 */ 1689 static int 1690 isp_pdb_sync(ispsoftc_t *isp, int chan) 1691 { 1692 fcparam *fcp = FCPARAM(isp, chan); 1693 fcportdb_t *lp; 1694 uint16_t dbidx; 1695 1696 if (fcp->isp_loopstate < LOOP_FSCAN_DONE) 1697 return (-1); 1698 if (fcp->isp_loopstate >= LOOP_READY) 1699 return (0); 1700 1701 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan); 1702 1703 fcp->isp_loopstate = LOOP_SYNCING_PDB; 1704 1705 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { 1706 lp = &fcp->portdb[dbidx]; 1707 1708 if (lp->state == FC_PORTDB_STATE_NIL) 1709 continue; 1710 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE) 1711 lp->state = FC_PORTDB_STATE_DEAD; 1712 switch (lp->state) { 1713 case FC_PORTDB_STATE_DEAD: 1714 lp->state = FC_PORTDB_STATE_NIL; 1715 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); 1716 if ((lp->portid & 0xffff00) != 0) { 1717 (void) isp_plogx(isp, chan, lp->handle, 1718 lp->portid, 1719 PLOGX_FLG_CMD_LOGO | 1720 PLOGX_FLG_IMPLICIT | 1721 PLOGX_FLG_FREE_NPHDL); 1722 } 1723 /* 1724 * Note that we might come out of this with our state 1725 * set to FC_PORTDB_STATE_ZOMBIE. 1726 */ 1727 break; 1728 case FC_PORTDB_STATE_NEW: 1729 lp->state = FC_PORTDB_STATE_VALID; 1730 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp); 1731 break; 1732 case FC_PORTDB_STATE_CHANGED: 1733 lp->state = FC_PORTDB_STATE_VALID; 1734 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp); 1735 lp->portid = lp->new_portid; 1736 lp->prli_word0 = lp->new_prli_word0; 1737 lp->prli_word3 = lp->new_prli_word3; 1738 break; 1739 case FC_PORTDB_STATE_VALID: 1740 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp); 1741 break; 1742 case FC_PORTDB_STATE_ZOMBIE: 1743 break; 1744 default: 1745 isp_prt(isp, ISP_LOGWARN, 1746 "isp_pdb_sync: state %d for idx %d", 1747 lp->state, dbidx); 1748 isp_dump_portdb(isp, chan); 1749 } 1750 } 1751 1752 if (fcp->isp_loopstate < LOOP_SYNCING_PDB) { 1753 isp_prt(isp, ISP_LOG_SANCFG, 1754 "Chan %d FC PDB sync aborted", chan); 1755 return (1); 1756 } 1757 1758 fcp->isp_loopstate = LOOP_READY; 1759 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan); 1760 return (0); 1761 } 1762 1763 static void 1764 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb) 1765 { 1766 fcportdb_t *lp; 1767 uint64_t wwnn, wwpn; 1768 1769 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename); 1770 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname); 1771 1772 /* Search port database for the same WWPN. */ 1773 if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) { 1774 if (!lp->probational) { 1775 isp_prt(isp, ISP_LOGERR, 1776 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)", 1777 chan, lp->portid, lp->handle, 1778 FC_PORTDB_TGT(isp, chan, lp), lp->state); 1779 isp_dump_portdb(isp, chan); 1780 return; 1781 } 1782 lp->probational = 0; 1783 lp->node_wwn = wwnn; 1784 1785 /* Old device, nothing new. */ 1786 if (lp->portid == pdb->portid && 1787 lp->handle == pdb->handle && 1788 lp->prli_word3 == pdb->prli_word3 && 1789 ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) == 1790 (lp->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR))) { 1791 if (lp->state != FC_PORTDB_STATE_NEW) 1792 lp->state = FC_PORTDB_STATE_VALID; 1793 isp_prt(isp, ISP_LOG_SANCFG, 1794 "Chan %d Port 0x%06x@0x%04x is valid", 1795 chan, pdb->portid, pdb->handle); 1796 return; 1797 } 1798 1799 /* Something has changed. */ 1800 lp->state = FC_PORTDB_STATE_CHANGED; 1801 lp->handle = pdb->handle; 1802 lp->new_portid = pdb->portid; 1803 lp->new_prli_word0 = pdb->prli_word0; 1804 lp->new_prli_word3 = pdb->prli_word3; 1805 isp_prt(isp, ISP_LOG_SANCFG, 1806 "Chan %d Port 0x%06x@0x%04x is changed", 1807 chan, pdb->portid, pdb->handle); 1808 return; 1809 } 1810 1811 /* It seems like a new port. Find an empty slot for it. */ 1812 if (!isp_find_pdb_empty(isp, chan, &lp)) { 1813 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan); 1814 return; 1815 } 1816 1817 ISP_MEMZERO(lp, sizeof (fcportdb_t)); 1818 lp->probational = 0; 1819 lp->state = FC_PORTDB_STATE_NEW; 1820 lp->portid = lp->new_portid = pdb->portid; 1821 lp->prli_word0 = lp->new_prli_word0 = pdb->prli_word0; 1822 lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3; 1823 lp->handle = pdb->handle; 1824 lp->port_wwn = wwpn; 1825 lp->node_wwn = wwnn; 1826 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new", 1827 chan, pdb->portid, pdb->handle); 1828 } 1829 1830 /* 1831 * Scan local loop for devices. 1832 */ 1833 static int 1834 isp_scan_loop(ispsoftc_t *isp, int chan) 1835 { 1836 fcparam *fcp = FCPARAM(isp, chan); 1837 int idx, lim, r; 1838 isp_pdb_t pdb; 1839 uint16_t *handles; 1840 uint16_t handle; 1841 1842 if (fcp->isp_loopstate < LOOP_LTEST_DONE) 1843 return (-1); 1844 if (fcp->isp_loopstate >= LOOP_LSCAN_DONE) 1845 return (0); 1846 1847 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan); 1848 fcp->isp_loopstate = LOOP_SCANNING_LOOP; 1849 if (TOPO_IS_FABRIC(fcp->isp_topo)) { 1850 isp_prt(isp, ISP_LOG_SANCFG, 1851 "Chan %d FC loop scan done (no loop)", chan); 1852 fcp->isp_loopstate = LOOP_LSCAN_DONE; 1853 return (0); 1854 } 1855 1856 handles = (uint16_t *)fcp->isp_scanscratch; 1857 lim = ISP_FC_SCRLEN / 2; 1858 r = isp_gethandles(isp, chan, handles, &lim, 1); 1859 if (r != 0) { 1860 isp_prt(isp, ISP_LOG_SANCFG, 1861 "Chan %d Getting list of handles failed with %x", chan, r); 1862 isp_prt(isp, ISP_LOG_SANCFG, 1863 "Chan %d FC loop scan done (bad)", chan); 1864 return (-1); 1865 } 1866 1867 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles", 1868 chan, lim); 1869 1870 /* 1871 * Run through the list and get the port database info for each one. 1872 */ 1873 isp_mark_portdb(isp, chan); 1874 for (idx = 0; idx < lim; idx++) { 1875 handle = handles[idx]; 1876 1877 /* 1878 * Don't scan "special" ids. 1879 */ 1880 if (handle >= NPH_RESERVED) 1881 continue; 1882 1883 /* 1884 * Get the port database entity for this index. 1885 */ 1886 r = isp_getpdb(isp, chan, handle, &pdb); 1887 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { 1888 abort: 1889 isp_prt(isp, ISP_LOG_SANCFG, 1890 "Chan %d FC loop scan aborted", chan); 1891 return (1); 1892 } 1893 if (r != 0) { 1894 isp_prt(isp, ISP_LOGDEBUG1, 1895 "Chan %d FC Scan Loop handle %d returned %x", 1896 chan, handle, r); 1897 continue; 1898 } 1899 1900 isp_pdb_add_update(isp, chan, &pdb); 1901 } 1902 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) 1903 goto abort; 1904 fcp->isp_loopstate = LOOP_LSCAN_DONE; 1905 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan); 1906 return (0); 1907 } 1908 1909 static int 1910 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt) 1911 { 1912 fcparam *fcp = FCPARAM(isp, chan); 1913 isp_ct_pt_t pt; 1914 void *reqp; 1915 uint8_t resp[QENTRY_LEN]; 1916 1917 if (isp->isp_dblev & ISP_LOGDEBUG1) 1918 isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch); 1919 1920 /* 1921 * Build a Passthrough IOCB in memory. 1922 */ 1923 ISP_MEMZERO(&pt, sizeof(pt)); 1924 pt.ctp_header.rqs_entry_count = 1; 1925 pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU; 1926 pt.ctp_nphdl = fcp->isp_sns_hdl; 1927 pt.ctp_cmd_cnt = 1; 1928 pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan); 1929 pt.ctp_time = 10; 1930 pt.ctp_rsp_cnt = 1; 1931 pt.ctp_rsp_bcnt = rsp_bcnt; 1932 pt.ctp_cmd_bcnt = cmd_bcnt; 1933 pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma); 1934 pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma); 1935 pt.ctp_dataseg[0].ds_count = cmd_bcnt; 1936 pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma); 1937 pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma); 1938 pt.ctp_dataseg[1].ds_count = rsp_bcnt; 1939 1940 /* Prepare space for response in memory */ 1941 memset(resp, 0xff, sizeof(resp)); 1942 pt.ctp_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); 1943 if (pt.ctp_handle == 0) { 1944 isp_prt(isp, ISP_LOGERR, 1945 "%s: CTP of Chan %d out of handles", __func__, chan); 1946 return (-1); 1947 } 1948 1949 /* Send request and wait for response. */ 1950 reqp = isp_getrqentry(isp); 1951 if (reqp == NULL) { 1952 isp_prt(isp, ISP_LOGERR, 1953 "%s: CTP of Chan %d out of rqent", __func__, chan); 1954 isp_destroy_handle(isp, pt.ctp_handle); 1955 return (-1); 1956 } 1957 isp_put_ct_pt(isp, &pt, (isp_ct_pt_t *)reqp); 1958 if (isp->isp_dblev & ISP_LOGDEBUG1) 1959 isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, reqp); 1960 ISP_SYNC_REQUEST(isp); 1961 if (msleep(resp, &isp->isp_lock, 0, "CTP", pt.ctp_time*hz) == EWOULDBLOCK) { 1962 isp_prt(isp, ISP_LOGERR, 1963 "%s: CTP of Chan %d timed out", __func__, chan); 1964 isp_destroy_handle(isp, pt.ctp_handle); 1965 return (-1); 1966 } 1967 if (isp->isp_dblev & ISP_LOGDEBUG1) 1968 isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, resp); 1969 1970 isp_get_ct_pt(isp, (isp_ct_pt_t *)resp, &pt); 1971 if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) { 1972 isp_prt(isp, ISP_LOGWARN, 1973 "Chan %d CT pass-through returned 0x%x", 1974 chan, pt.ctp_status); 1975 return (-1); 1976 } 1977 1978 if (isp->isp_dblev & ISP_LOGDEBUG1) 1979 isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch); 1980 1981 return (0); 1982 } 1983 1984 /* 1985 * Scan the fabric for devices and add them to our port database. 1986 * 1987 * Use the GID_PT command to get list of all Nx_Port IDs SNS knows. 1988 * Use GFF_ID and GFT_ID to check port type (FCP) and features (target). 1989 * 1990 * We use CT Pass-through IOCB. 1991 */ 1992 #define GIDLEN ISP_FC_SCRLEN 1993 #define NGENT ((GIDLEN - 16) >> 2) 1994 1995 static int 1996 isp_gid_pt(ispsoftc_t *isp, int chan) 1997 { 1998 fcparam *fcp = FCPARAM(isp, chan); 1999 ct_hdr_t ct; 2000 uint8_t *scp = fcp->isp_scratch; 2001 2002 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan); 2003 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2004 isp_prt(isp, ISP_LOGERR, sacq); 2005 return (-1); 2006 } 2007 2008 /* Build the CT command and execute via pass-through. */ 2009 ISP_MEMZERO(&ct, sizeof (ct)); 2010 ct.ct_revision = CT_REVISION; 2011 ct.ct_fcs_type = CT_FC_TYPE_FC; 2012 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2013 ct.ct_cmd_resp = SNS_GID_PT; 2014 ct.ct_bcnt_resid = (GIDLEN - 16) >> 2; 2015 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp); 2016 scp[sizeof(ct)] = 0x7f; /* Port Type = Nx_Port */ 2017 scp[sizeof(ct)+1] = 0; /* Domain_ID = any */ 2018 scp[sizeof(ct)+2] = 0; /* Area_ID = any */ 2019 scp[sizeof(ct)+3] = 0; /* Flags = no Area_ID */ 2020 2021 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) { 2022 FC_SCRATCH_RELEASE(isp, chan); 2023 return (-1); 2024 } 2025 2026 isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp, 2027 (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT); 2028 FC_SCRATCH_RELEASE(isp, chan); 2029 return (0); 2030 } 2031 2032 static int 2033 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid) 2034 { 2035 fcparam *fcp = FCPARAM(isp, chan); 2036 ct_hdr_t ct; 2037 uint32_t *rp; 2038 uint8_t *scp = fcp->isp_scratch; 2039 sns_gff_id_rsp_t rsp; 2040 int i, res = -1; 2041 2042 if (!fcp->isp_use_gff_id) /* User may block GFF_ID use. */ 2043 return (res); 2044 2045 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan); 2046 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2047 isp_prt(isp, ISP_LOGERR, sacq); 2048 return (res); 2049 } 2050 2051 /* Build the CT command and execute via pass-through. */ 2052 ISP_MEMZERO(&ct, sizeof (ct)); 2053 ct.ct_revision = CT_REVISION; 2054 ct.ct_fcs_type = CT_FC_TYPE_FC; 2055 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2056 ct.ct_cmd_resp = SNS_GFF_ID; 2057 ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4; 2058 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp); 2059 rp = (uint32_t *) &scp[sizeof(ct)]; 2060 ISP_IOZPUT_32(isp, portid, rp); 2061 2062 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), 2063 SNS_GFF_ID_RESP_SIZE)) { 2064 FC_SCRATCH_RELEASE(isp, chan); 2065 return (res); 2066 } 2067 2068 isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp); 2069 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) { 2070 for (i = 0; i < 32; i++) { 2071 if (rsp.snscb_fc4_features[i] != 0) { 2072 res = 0; 2073 break; 2074 } 2075 } 2076 if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >> 2077 ((FC4_SCSI % 8) * 4)) & 0x01) != 0) 2078 res = 1; 2079 /* Workaround for broken Brocade firmware. */ 2080 if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >> 2081 ((FC4_SCSI % 8) * 4)) & 0x01) != 0) 2082 res = 1; 2083 } 2084 FC_SCRATCH_RELEASE(isp, chan); 2085 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res); 2086 return (res); 2087 } 2088 2089 static int 2090 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid) 2091 { 2092 fcparam *fcp = FCPARAM(isp, chan); 2093 ct_hdr_t ct; 2094 uint32_t *rp; 2095 uint8_t *scp = fcp->isp_scratch; 2096 sns_gft_id_rsp_t rsp; 2097 int i, res = -1; 2098 2099 if (!fcp->isp_use_gft_id) /* User may block GFT_ID use. */ 2100 return (res); 2101 2102 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan); 2103 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2104 isp_prt(isp, ISP_LOGERR, sacq); 2105 return (res); 2106 } 2107 2108 /* Build the CT command and execute via pass-through. */ 2109 ISP_MEMZERO(&ct, sizeof (ct)); 2110 ct.ct_revision = CT_REVISION; 2111 ct.ct_fcs_type = CT_FC_TYPE_FC; 2112 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2113 ct.ct_cmd_resp = SNS_GFT_ID; 2114 ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4; 2115 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp); 2116 rp = (uint32_t *) &scp[sizeof(ct)]; 2117 ISP_IOZPUT_32(isp, portid, rp); 2118 2119 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), 2120 SNS_GFT_ID_RESP_SIZE)) { 2121 FC_SCRATCH_RELEASE(isp, chan); 2122 return (res); 2123 } 2124 2125 isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp); 2126 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) { 2127 for (i = 0; i < 8; i++) { 2128 if (rsp.snscb_fc4_types[i] != 0) { 2129 res = 0; 2130 break; 2131 } 2132 } 2133 if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >> 2134 (FC4_SCSI % 32)) & 0x01) != 0) 2135 res = 1; 2136 } 2137 FC_SCRATCH_RELEASE(isp, chan); 2138 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res); 2139 return (res); 2140 } 2141 2142 static int 2143 isp_scan_fabric(ispsoftc_t *isp, int chan) 2144 { 2145 fcparam *fcp = FCPARAM(isp, chan); 2146 fcportdb_t *lp; 2147 uint32_t portid; 2148 isp_pdb_t pdb; 2149 int portidx, portlim, r; 2150 sns_gid_xx_rsp_t *rs; 2151 2152 if (fcp->isp_loopstate < LOOP_LSCAN_DONE) 2153 return (-1); 2154 if (fcp->isp_loopstate >= LOOP_FSCAN_DONE) 2155 return (0); 2156 2157 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan); 2158 fcp->isp_loopstate = LOOP_SCANNING_FABRIC; 2159 if (!TOPO_IS_FABRIC(fcp->isp_topo)) { 2160 fcp->isp_loopstate = LOOP_FSCAN_DONE; 2161 isp_prt(isp, ISP_LOG_SANCFG, 2162 "Chan %d FC fabric scan done (no fabric)", chan); 2163 return (0); 2164 } 2165 2166 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { 2167 abort: 2168 FC_SCRATCH_RELEASE(isp, chan); 2169 isp_prt(isp, ISP_LOG_SANCFG, 2170 "Chan %d FC fabric scan aborted", chan); 2171 return (1); 2172 } 2173 2174 /* 2175 * Make sure we still are logged into the fabric controller. 2176 */ 2177 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb); 2178 if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) { 2179 isp_dump_chip_portdb(isp, chan); 2180 } 2181 if (r) { 2182 fcp->isp_loopstate = LOOP_LTEST_DONE; 2183 fail: 2184 isp_prt(isp, ISP_LOG_SANCFG, 2185 "Chan %d FC fabric scan done (bad)", chan); 2186 return (-1); 2187 } 2188 2189 /* Get list of port IDs from SNS. */ 2190 r = isp_gid_pt(isp, chan); 2191 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2192 goto abort; 2193 if (r > 0) { 2194 fcp->isp_loopstate = LOOP_FSCAN_DONE; 2195 return (-1); 2196 } else if (r < 0) { 2197 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */ 2198 return (-1); 2199 } 2200 2201 rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch; 2202 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2203 goto abort; 2204 if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) { 2205 int level; 2206 /* FC-4 Type and Port Type not registered are not errors. */ 2207 if (rs->snscb_cthdr.ct_reason == 9 && 2208 (rs->snscb_cthdr.ct_explanation == 0x07 || 2209 rs->snscb_cthdr.ct_explanation == 0x0a)) { 2210 level = ISP_LOG_SANCFG; 2211 } else { 2212 level = ISP_LOGWARN; 2213 } 2214 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT" 2215 " (Reason=0x%x Expl=0x%x)", chan, 2216 rs->snscb_cthdr.ct_reason, 2217 rs->snscb_cthdr.ct_explanation); 2218 fcp->isp_loopstate = LOOP_FSCAN_DONE; 2219 return (-1); 2220 } 2221 2222 /* Check our buffer was big enough to get the full list. */ 2223 for (portidx = 0; portidx < NGENT-1; portidx++) { 2224 if (rs->snscb_ports[portidx].control & 0x80) 2225 break; 2226 } 2227 if ((rs->snscb_ports[portidx].control & 0x80) == 0) { 2228 isp_prt(isp, ISP_LOGWARN, 2229 "fabric too big for scratch area: increase ISP_FC_SCRLEN"); 2230 } 2231 portlim = portidx + 1; 2232 isp_prt(isp, ISP_LOG_SANCFG, 2233 "Chan %d Got %d ports back from name server", chan, portlim); 2234 2235 /* Go through the list and remove duplicate port ids. */ 2236 for (portidx = 0; portidx < portlim; portidx++) { 2237 int npidx; 2238 2239 portid = 2240 ((rs->snscb_ports[portidx].portid[0]) << 16) | 2241 ((rs->snscb_ports[portidx].portid[1]) << 8) | 2242 ((rs->snscb_ports[portidx].portid[2])); 2243 2244 for (npidx = portidx + 1; npidx < portlim; npidx++) { 2245 uint32_t new_portid = 2246 ((rs->snscb_ports[npidx].portid[0]) << 16) | 2247 ((rs->snscb_ports[npidx].portid[1]) << 8) | 2248 ((rs->snscb_ports[npidx].portid[2])); 2249 if (new_portid == portid) { 2250 break; 2251 } 2252 } 2253 2254 if (npidx < portlim) { 2255 rs->snscb_ports[npidx].portid[0] = 0; 2256 rs->snscb_ports[npidx].portid[1] = 0; 2257 rs->snscb_ports[npidx].portid[2] = 0; 2258 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid); 2259 } 2260 } 2261 2262 /* 2263 * We now have a list of Port IDs for all FC4 SCSI devices 2264 * that the Fabric Name server knows about. 2265 * 2266 * For each entry on this list go through our port database looking 2267 * for probational entries- if we find one, then an old entry is 2268 * maybe still this one. We get some information to find out. 2269 * 2270 * Otherwise, it's a new fabric device, and we log into it 2271 * (unconditionally). After searching the entire database 2272 * again to make sure that we never ever ever ever have more 2273 * than one entry that has the same PortID or the same 2274 * WWNN/WWPN duple, we enter the device into our database. 2275 */ 2276 isp_mark_portdb(isp, chan); 2277 for (portidx = 0; portidx < portlim; portidx++) { 2278 portid = ((rs->snscb_ports[portidx].portid[0]) << 16) | 2279 ((rs->snscb_ports[portidx].portid[1]) << 8) | 2280 ((rs->snscb_ports[portidx].portid[2])); 2281 isp_prt(isp, ISP_LOG_SANCFG, 2282 "Chan %d Checking fabric port 0x%06x", chan, portid); 2283 if (portid == 0) { 2284 isp_prt(isp, ISP_LOG_SANCFG, 2285 "Chan %d Port at idx %d is zero", 2286 chan, portidx); 2287 continue; 2288 } 2289 if (portid == fcp->isp_portid) { 2290 isp_prt(isp, ISP_LOG_SANCFG, 2291 "Chan %d Port 0x%06x is our", chan, portid); 2292 continue; 2293 } 2294 2295 /* Now search the entire port database for the same portid. */ 2296 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) { 2297 if (!lp->probational) { 2298 isp_prt(isp, ISP_LOGERR, 2299 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)", 2300 chan, lp->portid, lp->handle, 2301 FC_PORTDB_TGT(isp, chan, lp), lp->state); 2302 isp_dump_portdb(isp, chan); 2303 goto fail; 2304 } 2305 2306 if (lp->state == FC_PORTDB_STATE_ZOMBIE) 2307 goto relogin; 2308 2309 /* 2310 * See if we're still logged into it. 2311 * 2312 * If we aren't, mark it as a dead device and 2313 * leave the new portid in the database entry 2314 * for somebody further along to decide what to 2315 * do (policy choice). 2316 * 2317 * If we are, check to see if it's the same 2318 * device still (it should be). If for some 2319 * reason it isn't, mark it as a changed device 2320 * and leave the new portid and role in the 2321 * database entry for somebody further along to 2322 * decide what to do (policy choice). 2323 */ 2324 r = isp_getpdb(isp, chan, lp->handle, &pdb); 2325 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2326 goto abort; 2327 if (r != 0) { 2328 lp->state = FC_PORTDB_STATE_DEAD; 2329 isp_prt(isp, ISP_LOG_SANCFG, 2330 "Chan %d Port 0x%06x handle 0x%x is dead (%d)", 2331 chan, portid, lp->handle, r); 2332 goto relogin; 2333 } 2334 2335 isp_pdb_add_update(isp, chan, &pdb); 2336 continue; 2337 } 2338 2339 relogin: 2340 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) { 2341 isp_prt(isp, ISP_LOG_SANCFG, 2342 "Chan %d Port 0x%06x is not logged in", chan, portid); 2343 continue; 2344 } 2345 2346 r = isp_gff_id(isp, chan, portid); 2347 if (r == 0) { 2348 isp_prt(isp, ISP_LOG_SANCFG, 2349 "Chan %d Port 0x%06x is not an FCP target", chan, portid); 2350 continue; 2351 } 2352 if (r < 0) 2353 r = isp_gft_id(isp, chan, portid); 2354 if (r == 0) { 2355 isp_prt(isp, ISP_LOG_SANCFG, 2356 "Chan %d Port 0x%06x is not FCP", chan, portid); 2357 continue; 2358 } 2359 2360 if (isp_login_device(isp, chan, portid, &pdb, 2361 &FCPARAM(isp, 0)->isp_lasthdl)) { 2362 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2363 goto abort; 2364 continue; 2365 } 2366 2367 isp_pdb_add_update(isp, chan, &pdb); 2368 } 2369 2370 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2371 goto abort; 2372 fcp->isp_loopstate = LOOP_FSCAN_DONE; 2373 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan); 2374 return (0); 2375 } 2376 2377 /* 2378 * Find an unused handle and try and use to login to a port. 2379 */ 2380 static int 2381 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp) 2382 { 2383 int i, r; 2384 uint16_t handle; 2385 2386 handle = isp_next_handle(isp, ohp); 2387 for (i = 0; i < NPH_MAX_2K; i++) { 2388 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) 2389 return (-1); 2390 2391 /* Check if this handle is free. */ 2392 r = isp_getpdb(isp, chan, handle, p); 2393 if (r == 0) { 2394 if (p->portid != portid) { 2395 /* This handle is busy, try next one. */ 2396 handle = isp_next_handle(isp, ohp); 2397 continue; 2398 } 2399 break; 2400 } 2401 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) 2402 return (-1); 2403 2404 /* 2405 * Now try and log into the device 2406 */ 2407 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI); 2408 if (r == 0) { 2409 break; 2410 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) { 2411 /* 2412 * If we get here, then the firmwware still thinks we're logged into this device, but with a different 2413 * handle. We need to break that association. We used to try and just substitute the handle, but then 2414 * failed to get any data via isp_getpdb (below). 2415 */ 2416 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) { 2417 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16); 2418 } 2419 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) 2420 return (-1); 2421 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI); 2422 if (r != 0) 2423 i = NPH_MAX_2K; 2424 break; 2425 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) { 2426 /* Try the next handle. */ 2427 handle = isp_next_handle(isp, ohp); 2428 } else { 2429 /* Give up. */ 2430 i = NPH_MAX_2K; 2431 break; 2432 } 2433 } 2434 2435 if (i == NPH_MAX_2K) { 2436 isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid); 2437 return (-1); 2438 } 2439 2440 /* 2441 * If we successfully logged into it, get the PDB for it 2442 * so we can crosscheck that it is still what we think it 2443 * is and that we also have the role it plays 2444 */ 2445 r = isp_getpdb(isp, chan, handle, p); 2446 if (r != 0) { 2447 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle); 2448 return (-1); 2449 } 2450 2451 if (p->handle != handle || p->portid != portid) { 2452 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)", 2453 chan, portid, handle, p->portid, p->handle); 2454 return (-1); 2455 } 2456 return (0); 2457 } 2458 2459 static int 2460 isp_register_fc4_type(ispsoftc_t *isp, int chan) 2461 { 2462 fcparam *fcp = FCPARAM(isp, chan); 2463 rft_id_t rp; 2464 ct_hdr_t *ct = &rp.rftid_hdr; 2465 uint8_t *scp = fcp->isp_scratch; 2466 2467 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2468 isp_prt(isp, ISP_LOGERR, sacq); 2469 return (-1); 2470 } 2471 2472 /* Build the CT command and execute via pass-through. */ 2473 ISP_MEMZERO(&rp, sizeof(rp)); 2474 ct->ct_revision = CT_REVISION; 2475 ct->ct_fcs_type = CT_FC_TYPE_FC; 2476 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2477 ct->ct_cmd_resp = SNS_RFT_ID; 2478 ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2; 2479 rp.rftid_portid[0] = fcp->isp_portid >> 16; 2480 rp.rftid_portid[1] = fcp->isp_portid >> 8; 2481 rp.rftid_portid[2] = fcp->isp_portid; 2482 rp.rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f); 2483 isp_put_rft_id(isp, &rp, (rft_id_t *)scp); 2484 2485 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) { 2486 FC_SCRATCH_RELEASE(isp, chan); 2487 return (-1); 2488 } 2489 2490 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); 2491 FC_SCRATCH_RELEASE(isp, chan); 2492 if (ct->ct_cmd_resp == LS_RJT) { 2493 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "Chan %d Register FC4 Type rejected", chan); 2494 return (-1); 2495 } else if (ct->ct_cmd_resp == LS_ACC) { 2496 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan); 2497 } else { 2498 isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp); 2499 return (-1); 2500 } 2501 return (0); 2502 } 2503 2504 static int 2505 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan) 2506 { 2507 fcparam *fcp = FCPARAM(isp, chan); 2508 ct_hdr_t *ct; 2509 rff_id_t rp; 2510 uint8_t *scp = fcp->isp_scratch; 2511 2512 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2513 isp_prt(isp, ISP_LOGERR, sacq); 2514 return (-1); 2515 } 2516 2517 /* 2518 * Build the CT header and command in memory. 2519 */ 2520 ISP_MEMZERO(&rp, sizeof(rp)); 2521 ct = &rp.rffid_hdr; 2522 ct->ct_revision = CT_REVISION; 2523 ct->ct_fcs_type = CT_FC_TYPE_FC; 2524 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2525 ct->ct_cmd_resp = SNS_RFF_ID; 2526 ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2; 2527 rp.rffid_portid[0] = fcp->isp_portid >> 16; 2528 rp.rffid_portid[1] = fcp->isp_portid >> 8; 2529 rp.rffid_portid[2] = fcp->isp_portid; 2530 rp.rffid_fc4features = 0; 2531 if (fcp->role & ISP_ROLE_TARGET) 2532 rp.rffid_fc4features |= 1; 2533 if (fcp->role & ISP_ROLE_INITIATOR) 2534 rp.rffid_fc4features |= 2; 2535 rp.rffid_fc4type = FC4_SCSI; 2536 isp_put_rff_id(isp, &rp, (rff_id_t *)scp); 2537 if (isp->isp_dblev & ISP_LOGDEBUG1) 2538 isp_print_bytes(isp, "CT request", sizeof(rft_id_t), scp); 2539 2540 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) { 2541 FC_SCRATCH_RELEASE(isp, chan); 2542 return (-1); 2543 } 2544 2545 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); 2546 FC_SCRATCH_RELEASE(isp, chan); 2547 if (ct->ct_cmd_resp == LS_RJT) { 2548 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, 2549 "Chan %d Register FC4 Features rejected", chan); 2550 return (-1); 2551 } else if (ct->ct_cmd_resp == LS_ACC) { 2552 isp_prt(isp, ISP_LOG_SANCFG, 2553 "Chan %d Register FC4 Features accepted", chan); 2554 } else { 2555 isp_prt(isp, ISP_LOGWARN, 2556 "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp); 2557 return (-1); 2558 } 2559 return (0); 2560 } 2561 2562 static int 2563 isp_register_port_name_24xx(ispsoftc_t *isp, int chan) 2564 { 2565 fcparam *fcp = FCPARAM(isp, chan); 2566 ct_hdr_t *ct; 2567 rspn_id_t rp; 2568 uint8_t *scp = fcp->isp_scratch; 2569 int len; 2570 2571 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2572 isp_prt(isp, ISP_LOGERR, sacq); 2573 return (-1); 2574 } 2575 2576 /* 2577 * Build the CT header and command in memory. 2578 */ 2579 ISP_MEMZERO(&rp, sizeof(rp)); 2580 ct = &rp.rspnid_hdr; 2581 ct->ct_revision = CT_REVISION; 2582 ct->ct_fcs_type = CT_FC_TYPE_FC; 2583 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2584 ct->ct_cmd_resp = SNS_RSPN_ID; 2585 rp.rspnid_portid[0] = fcp->isp_portid >> 16; 2586 rp.rspnid_portid[1] = fcp->isp_portid >> 8; 2587 rp.rspnid_portid[2] = fcp->isp_portid; 2588 rp.rspnid_length = 0; 2589 len = offsetof(rspn_id_t, rspnid_name); 2590 mtx_lock(&prison0.pr_mtx); 2591 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length], 2592 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD"); 2593 mtx_unlock(&prison0.pr_mtx); 2594 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length], 2595 ":%s", device_get_nameunit(isp->isp_dev)); 2596 if (chan != 0) { 2597 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length], 2598 "/%d", chan); 2599 } 2600 len += rp.rspnid_length; 2601 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2; 2602 isp_put_rspn_id(isp, &rp, (rspn_id_t *)scp); 2603 2604 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) { 2605 FC_SCRATCH_RELEASE(isp, chan); 2606 return (-1); 2607 } 2608 2609 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); 2610 FC_SCRATCH_RELEASE(isp, chan); 2611 if (ct->ct_cmd_resp == LS_RJT) { 2612 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, 2613 "Chan %d Register Symbolic Port Name rejected", chan); 2614 return (-1); 2615 } else if (ct->ct_cmd_resp == LS_ACC) { 2616 isp_prt(isp, ISP_LOG_SANCFG, 2617 "Chan %d Register Symbolic Port Name accepted", chan); 2618 } else { 2619 isp_prt(isp, ISP_LOGWARN, 2620 "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp); 2621 return (-1); 2622 } 2623 return (0); 2624 } 2625 2626 static int 2627 isp_register_node_name_24xx(ispsoftc_t *isp, int chan) 2628 { 2629 fcparam *fcp = FCPARAM(isp, chan); 2630 ct_hdr_t *ct; 2631 rsnn_nn_t rp; 2632 uint8_t *scp = fcp->isp_scratch; 2633 int len; 2634 2635 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2636 isp_prt(isp, ISP_LOGERR, sacq); 2637 return (-1); 2638 } 2639 2640 /* 2641 * Build the CT header and command in memory. 2642 */ 2643 ISP_MEMZERO(&rp, sizeof(rp)); 2644 ct = &rp.rsnnnn_hdr; 2645 ct->ct_revision = CT_REVISION; 2646 ct->ct_fcs_type = CT_FC_TYPE_FC; 2647 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2648 ct->ct_cmd_resp = SNS_RSNN_NN; 2649 MAKE_NODE_NAME_FROM_WWN(rp.rsnnnn_nodename, fcp->isp_wwnn); 2650 rp.rsnnnn_length = 0; 2651 len = offsetof(rsnn_nn_t, rsnnnn_name); 2652 mtx_lock(&prison0.pr_mtx); 2653 rp.rsnnnn_length += sprintf(&scp[len + rp.rsnnnn_length], 2654 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD"); 2655 mtx_unlock(&prison0.pr_mtx); 2656 len += rp.rsnnnn_length; 2657 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2; 2658 isp_put_rsnn_nn(isp, &rp, (rsnn_nn_t *)scp); 2659 2660 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) { 2661 FC_SCRATCH_RELEASE(isp, chan); 2662 return (-1); 2663 } 2664 2665 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); 2666 FC_SCRATCH_RELEASE(isp, chan); 2667 if (ct->ct_cmd_resp == LS_RJT) { 2668 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, 2669 "Chan %d Register Symbolic Node Name rejected", chan); 2670 return (-1); 2671 } else if (ct->ct_cmd_resp == LS_ACC) { 2672 isp_prt(isp, ISP_LOG_SANCFG, 2673 "Chan %d Register Symbolic Node Name accepted", chan); 2674 } else { 2675 isp_prt(isp, ISP_LOGWARN, 2676 "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp); 2677 return (-1); 2678 } 2679 return (0); 2680 } 2681 2682 static uint16_t 2683 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp) 2684 { 2685 fcparam *fcp; 2686 int i, chan, wrap; 2687 uint16_t handle; 2688 2689 handle = *ohp; 2690 wrap = 0; 2691 2692 next: 2693 if (handle == NIL_HANDLE) { 2694 handle = 0; 2695 } else { 2696 handle++; 2697 if (handle > NPH_RESERVED - 1) { 2698 if (++wrap >= 2) { 2699 isp_prt(isp, ISP_LOGERR, "Out of port handles!"); 2700 return (NIL_HANDLE); 2701 } 2702 handle = 0; 2703 } 2704 } 2705 for (chan = 0; chan < isp->isp_nchan; chan++) { 2706 fcp = FCPARAM(isp, chan); 2707 if (fcp->role == ISP_ROLE_NONE) 2708 continue; 2709 for (i = 0; i < MAX_FC_TARG; i++) { 2710 if (fcp->portdb[i].state != FC_PORTDB_STATE_NIL && 2711 fcp->portdb[i].handle == handle) 2712 goto next; 2713 } 2714 } 2715 *ohp = handle; 2716 return (handle); 2717 } 2718 2719 /* 2720 * Start a command. Locking is assumed done in the caller. 2721 */ 2722 2723 int 2724 isp_start(XS_T *xs) 2725 { 2726 ispsoftc_t *isp; 2727 fcparam *fcp; 2728 uint32_t cdblen; 2729 ispreqt7_t local, *reqp = &local; 2730 void *qep; 2731 fcportdb_t *lp; 2732 int target, dmaresult; 2733 2734 XS_INITERR(xs); 2735 isp = XS_ISP(xs); 2736 2737 /* 2738 * Check command CDB length, etc.. We really are limited to 16 bytes 2739 * for Fibre Channel, but can do up to 44 bytes in parallel SCSI, 2740 * but probably only if we're running fairly new firmware (we'll 2741 * let the old f/w choke on an extended command queue entry). 2742 */ 2743 2744 if (XS_CDBLEN(xs) > 16 || XS_CDBLEN(xs) == 0) { 2745 isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff); 2746 XS_SETERR(xs, HBA_REQINVAL); 2747 return (CMD_COMPLETE); 2748 } 2749 2750 /* 2751 * Translate the target to device handle as appropriate, checking 2752 * for correct device state as well. 2753 */ 2754 target = XS_TGT(xs); 2755 fcp = FCPARAM(isp, XS_CHANNEL(xs)); 2756 2757 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) { 2758 isp_prt(isp, ISP_LOG_WARN1, 2759 "%d.%d.%jx I am not an initiator", 2760 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs)); 2761 XS_SETERR(xs, HBA_SELTIMEOUT); 2762 return (CMD_COMPLETE); 2763 } 2764 2765 if (isp->isp_state != ISP_RUNSTATE) { 2766 isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE"); 2767 XS_SETERR(xs, HBA_BOTCH); 2768 return (CMD_COMPLETE); 2769 } 2770 2771 isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target); 2772 lp = &fcp->portdb[target]; 2773 if (target < 0 || target >= MAX_FC_TARG || 2774 lp->is_target == 0) { 2775 XS_SETERR(xs, HBA_SELTIMEOUT); 2776 return (CMD_COMPLETE); 2777 } 2778 if (fcp->isp_loopstate != LOOP_READY) { 2779 isp_prt(isp, ISP_LOGDEBUG1, 2780 "%d.%d.%jx loop is not ready", 2781 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs)); 2782 return (CMD_RQLATER); 2783 } 2784 if (lp->state == FC_PORTDB_STATE_ZOMBIE) { 2785 isp_prt(isp, ISP_LOGDEBUG1, 2786 "%d.%d.%jx target zombie", 2787 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs)); 2788 return (CMD_RQLATER); 2789 } 2790 if (lp->state != FC_PORTDB_STATE_VALID) { 2791 isp_prt(isp, ISP_LOGDEBUG1, 2792 "%d.%d.%jx bad db port state 0x%x", 2793 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs), lp->state); 2794 XS_SETERR(xs, HBA_SELTIMEOUT); 2795 return (CMD_COMPLETE); 2796 } 2797 2798 start_again: 2799 2800 qep = isp_getrqentry(isp); 2801 if (qep == NULL) { 2802 isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow"); 2803 XS_SETERR(xs, HBA_BOTCH); 2804 return (CMD_EAGAIN); 2805 } 2806 XS_SETERR(xs, HBA_NOERROR); 2807 2808 /* 2809 * Now see if we need to synchronize the ISP with respect to anything. 2810 * We do dual duty here (cough) for synchronizing for buses other 2811 * than which we got here to send a command to. 2812 */ 2813 ISP_MEMZERO(reqp, QENTRY_LEN); 2814 if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) { 2815 isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp; 2816 m->mrk_header.rqs_entry_count = 1; 2817 m->mrk_header.rqs_entry_type = RQSTYPE_MARKER; 2818 m->mrk_modifier = SYNC_ALL; 2819 m->mrk_vphdl = XS_CHANNEL(xs); 2820 isp_put_marker_24xx(isp, m, qep); 2821 ISP_SYNC_REQUEST(isp); 2822 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0); 2823 goto start_again; 2824 } 2825 2826 /* 2827 * NB: we do not support long CDBs (yet) 2828 */ 2829 cdblen = XS_CDBLEN(xs); 2830 if (cdblen > sizeof (reqp->req_cdb)) { 2831 isp_prt(isp, ISP_LOGERR, "Command Length %u too long for this chip", cdblen); 2832 XS_SETERR(xs, HBA_REQINVAL); 2833 return (CMD_COMPLETE); 2834 } 2835 2836 reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS; 2837 reqp->req_header.rqs_entry_count = 1; 2838 reqp->req_nphdl = lp->handle; 2839 reqp->req_time = XS_TIME(xs); 2840 be64enc(reqp->req_lun, CAM_EXTLUN_BYTE_SWIZZLE(XS_LUN(xs))); 2841 if (XS_XFRIN(xs)) 2842 reqp->req_alen_datadir = FCP_CMND_DATA_READ; 2843 else if (XS_XFROUT(xs)) 2844 reqp->req_alen_datadir = FCP_CMND_DATA_WRITE; 2845 if (XS_TAG_P(xs)) 2846 reqp->req_task_attribute = XS_TAG_TYPE(xs); 2847 else 2848 reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE; 2849 reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) & 2850 FCP_CMND_PRIO_MASK; 2851 if (FCPARAM(isp, XS_CHANNEL(xs))->fctape_enabled && (lp->prli_word3 & PRLI_WD3_RETRY)) { 2852 if (FCP_NEXT_CRN(isp, &reqp->req_crn, xs)) { 2853 isp_prt(isp, ISP_LOG_WARN1, 2854 "%d.%d.%jx cannot generate next CRN", 2855 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs)); 2856 XS_SETERR(xs, HBA_BOTCH); 2857 return (CMD_EAGAIN); 2858 } 2859 } 2860 ISP_MEMCPY(reqp->req_cdb, XS_CDBP(xs), cdblen); 2861 reqp->req_dl = XS_XFRLEN(xs); 2862 reqp->req_tidlo = lp->portid; 2863 reqp->req_tidhi = lp->portid >> 16; 2864 reqp->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs)); 2865 2866 /* Whew. Thankfully the same for type 7 requests */ 2867 reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR); 2868 if (reqp->req_handle == 0) { 2869 isp_prt(isp, ISP_LOG_WARN1, "out of xflist pointers"); 2870 XS_SETERR(xs, HBA_BOTCH); 2871 return (CMD_EAGAIN); 2872 } 2873 2874 /* 2875 * Set up DMA and/or do any platform dependent swizzling of the request entry 2876 * so that the Qlogic F/W understands what is being asked of it. 2877 * 2878 * The callee is responsible for adding all requests at this point. 2879 */ 2880 dmaresult = ISP_DMASETUP(isp, xs, reqp); 2881 if (dmaresult != 0) { 2882 isp_destroy_handle(isp, reqp->req_handle); 2883 /* 2884 * dmasetup sets actual error in packet, and 2885 * return what we were given to return. 2886 */ 2887 return (dmaresult); 2888 } 2889 isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs)); 2890 return (0); 2891 } 2892 2893 /* 2894 * isp control 2895 * Locks (ints blocked) assumed held. 2896 */ 2897 2898 int 2899 isp_control(ispsoftc_t *isp, ispctl_t ctl, ...) 2900 { 2901 fcparam *fcp; 2902 fcportdb_t *lp; 2903 XS_T *xs; 2904 mbreg_t mbs; 2905 int chan, tgt; 2906 uint32_t handle; 2907 va_list ap; 2908 uint8_t local[QENTRY_LEN]; 2909 2910 switch (ctl) { 2911 case ISPCTL_RESET_BUS: 2912 /* 2913 * Issue a bus reset. 2914 */ 2915 isp_prt(isp, ISP_LOGERR, "BUS RESET NOT IMPLEMENTED"); 2916 break; 2917 2918 case ISPCTL_RESET_DEV: 2919 { 2920 isp24xx_tmf_t *tmf; 2921 isp24xx_statusreq_t *sp; 2922 2923 va_start(ap, ctl); 2924 chan = va_arg(ap, int); 2925 tgt = va_arg(ap, int); 2926 va_end(ap); 2927 fcp = FCPARAM(isp, chan); 2928 2929 if (tgt < 0 || tgt >= MAX_FC_TARG) { 2930 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to reset bad target %d", chan, tgt); 2931 break; 2932 } 2933 lp = &fcp->portdb[tgt]; 2934 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) { 2935 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt); 2936 break; 2937 } 2938 2939 tmf = (isp24xx_tmf_t *) local; 2940 ISP_MEMZERO(tmf, QENTRY_LEN); 2941 tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT; 2942 tmf->tmf_header.rqs_entry_count = 1; 2943 tmf->tmf_nphdl = lp->handle; 2944 tmf->tmf_delay = 2; 2945 tmf->tmf_timeout = 4; 2946 tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET; 2947 tmf->tmf_tidlo = lp->portid; 2948 tmf->tmf_tidhi = lp->portid >> 16; 2949 tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan); 2950 isp_put_24xx_tmf(isp, tmf, isp->isp_iocb); 2951 if (isp->isp_dblev & ISP_LOGDEBUG1) 2952 isp_print_bytes(isp, "TMF IOCB request", QENTRY_LEN, isp->isp_iocb); 2953 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, QENTRY_LEN, chan); 2954 fcp->sendmarker = 1; 2955 2956 isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid); 2957 MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 2958 MBCMD_DEFAULT_TIMEOUT + tmf->tmf_timeout * 1000000); 2959 mbs.param[1] = QENTRY_LEN; 2960 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma); 2961 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma); 2962 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma); 2963 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma); 2964 isp_mboxcmd(isp, &mbs); 2965 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) 2966 break; 2967 2968 MEMORYBARRIER(isp, SYNC_IFORCPU, QENTRY_LEN, QENTRY_LEN, chan); 2969 if (isp->isp_dblev & ISP_LOGDEBUG1) 2970 isp_print_bytes(isp, "TMF IOCB response", QENTRY_LEN, &((isp24xx_statusreq_t *)isp->isp_iocb)[1]); 2971 sp = (isp24xx_statusreq_t *) local; 2972 isp_get_24xx_response(isp, &((isp24xx_statusreq_t *)isp->isp_iocb)[1], sp); 2973 if (sp->req_completion_status == 0) { 2974 return (0); 2975 } 2976 isp_prt(isp, ISP_LOGWARN, "Chan %d reset of target %d returned 0x%x", chan, tgt, sp->req_completion_status); 2977 break; 2978 } 2979 case ISPCTL_ABORT_CMD: 2980 { 2981 isp24xx_abrt_t *ab = (isp24xx_abrt_t *)&local; 2982 2983 va_start(ap, ctl); 2984 xs = va_arg(ap, XS_T *); 2985 va_end(ap); 2986 2987 tgt = XS_TGT(xs); 2988 chan = XS_CHANNEL(xs); 2989 2990 handle = isp_find_handle(isp, xs); 2991 if (handle == 0) { 2992 isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort"); 2993 break; 2994 } 2995 2996 fcp = FCPARAM(isp, chan); 2997 if (tgt < 0 || tgt >= MAX_FC_TARG) { 2998 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to abort bad target %d", chan, tgt); 2999 break; 3000 } 3001 lp = &fcp->portdb[tgt]; 3002 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) { 3003 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt); 3004 break; 3005 } 3006 isp_prt(isp, ISP_LOGALL, "Chan %d Abort Cmd for N-Port 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid); 3007 ISP_MEMZERO(ab, QENTRY_LEN); 3008 ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO; 3009 ab->abrt_header.rqs_entry_count = 1; 3010 ab->abrt_handle = lp->handle; 3011 ab->abrt_cmd_handle = handle; 3012 ab->abrt_tidlo = lp->portid; 3013 ab->abrt_tidhi = lp->portid >> 16; 3014 ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan); 3015 isp_put_24xx_abrt(isp, ab, isp->isp_iocb); 3016 if (isp->isp_dblev & ISP_LOGDEBUG1) 3017 isp_print_bytes(isp, "AB IOCB quest", QENTRY_LEN, isp->isp_iocb); 3018 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, 2 * QENTRY_LEN, chan); 3019 3020 ISP_MEMZERO(&mbs, sizeof (mbs)); 3021 MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000); 3022 mbs.param[1] = QENTRY_LEN; 3023 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma); 3024 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma); 3025 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma); 3026 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma); 3027 3028 isp_mboxcmd(isp, &mbs); 3029 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) 3030 break; 3031 3032 MEMORYBARRIER(isp, SYNC_IFORCPU, QENTRY_LEN, QENTRY_LEN, chan); 3033 if (isp->isp_dblev & ISP_LOGDEBUG1) 3034 isp_print_bytes(isp, "AB IOCB response", QENTRY_LEN, &((isp24xx_abrt_t *)isp->isp_iocb)[1]); 3035 isp_get_24xx_abrt(isp, &((isp24xx_abrt_t *)isp->isp_iocb)[1], ab); 3036 if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY) { 3037 return (0); 3038 } 3039 isp_prt(isp, ISP_LOGWARN, "Chan %d handle %d abort returned 0x%x", chan, tgt, ab->abrt_nphdl); 3040 } 3041 case ISPCTL_FCLINK_TEST: 3042 { 3043 int usdelay; 3044 3045 va_start(ap, ctl); 3046 chan = va_arg(ap, int); 3047 usdelay = va_arg(ap, int); 3048 va_end(ap); 3049 if (usdelay == 0) 3050 usdelay = 250000; 3051 return (isp_fclink_test(isp, chan, usdelay)); 3052 } 3053 case ISPCTL_SCAN_FABRIC: 3054 3055 va_start(ap, ctl); 3056 chan = va_arg(ap, int); 3057 va_end(ap); 3058 return (isp_scan_fabric(isp, chan)); 3059 3060 case ISPCTL_SCAN_LOOP: 3061 3062 va_start(ap, ctl); 3063 chan = va_arg(ap, int); 3064 va_end(ap); 3065 return (isp_scan_loop(isp, chan)); 3066 3067 case ISPCTL_PDB_SYNC: 3068 3069 va_start(ap, ctl); 3070 chan = va_arg(ap, int); 3071 va_end(ap); 3072 return (isp_pdb_sync(isp, chan)); 3073 3074 case ISPCTL_SEND_LIP: 3075 break; 3076 3077 case ISPCTL_GET_PDB: 3078 { 3079 isp_pdb_t *pdb; 3080 va_start(ap, ctl); 3081 chan = va_arg(ap, int); 3082 tgt = va_arg(ap, int); 3083 pdb = va_arg(ap, isp_pdb_t *); 3084 va_end(ap); 3085 return (isp_getpdb(isp, chan, tgt, pdb)); 3086 } 3087 case ISPCTL_GET_NAMES: 3088 { 3089 uint64_t *wwnn, *wwnp; 3090 va_start(ap, ctl); 3091 chan = va_arg(ap, int); 3092 tgt = va_arg(ap, int); 3093 wwnn = va_arg(ap, uint64_t *); 3094 wwnp = va_arg(ap, uint64_t *); 3095 va_end(ap); 3096 if (wwnn == NULL && wwnp == NULL) { 3097 break; 3098 } 3099 if (wwnn) { 3100 *wwnn = isp_get_wwn(isp, chan, tgt, 1); 3101 if (*wwnn == INI_NONE) { 3102 break; 3103 } 3104 } 3105 if (wwnp) { 3106 *wwnp = isp_get_wwn(isp, chan, tgt, 0); 3107 if (*wwnp == INI_NONE) { 3108 break; 3109 } 3110 } 3111 return (0); 3112 } 3113 case ISPCTL_PLOGX: 3114 { 3115 isp_plcmd_t *p; 3116 int r; 3117 3118 va_start(ap, ctl); 3119 p = va_arg(ap, isp_plcmd_t *); 3120 va_end(ap); 3121 3122 if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) { 3123 return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags)); 3124 } 3125 do { 3126 isp_next_handle(isp, &p->handle); 3127 r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags); 3128 if ((r & 0xffff) == MBOX_PORT_ID_USED) { 3129 p->handle = r >> 16; 3130 r = 0; 3131 break; 3132 } 3133 } while ((r & 0xffff) == MBOX_LOOP_ID_USED); 3134 return (r); 3135 } 3136 case ISPCTL_CHANGE_ROLE: 3137 { 3138 int role; 3139 3140 va_start(ap, ctl); 3141 chan = va_arg(ap, int); 3142 role = va_arg(ap, int); 3143 va_end(ap); 3144 return (isp_fc_change_role(isp, chan, role)); 3145 } 3146 default: 3147 isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl); 3148 break; 3149 3150 } 3151 return (-1); 3152 } 3153 3154 /* 3155 * Interrupt Service Routine(s). 3156 * 3157 * External (OS) framework has done the appropriate locking, 3158 * and the locking will be held throughout this function. 3159 */ 3160 3161 #ifdef ISP_TARGET_MODE 3162 void 3163 isp_intr_atioq(ispsoftc_t *isp) 3164 { 3165 uint8_t qe[QENTRY_LEN]; 3166 isphdr_t *hp; 3167 void *addr; 3168 uint32_t iptr, optr, oop; 3169 3170 iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP); 3171 optr = isp->isp_atioodx; 3172 while (optr != iptr) { 3173 oop = optr; 3174 MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN, -1); 3175 addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop); 3176 isp_get_hdr(isp, addr, (isphdr_t *)qe); 3177 hp = (isphdr_t *)qe; 3178 switch (hp->rqs_entry_type) { 3179 case RQSTYPE_NOTIFY: 3180 case RQSTYPE_ATIO: 3181 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue.*/ 3182 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue.*/ 3183 (void) isp_target_notify(isp, addr, &oop, 3184 ATIO_QUEUE_LEN(isp)); 3185 break; 3186 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/ 3187 default: 3188 isp_print_qentry(isp, "?ATIOQ entry?", oop, addr); 3189 break; 3190 } 3191 optr = ISP_NXT_QENTRY(oop, ATIO_QUEUE_LEN(isp)); 3192 } 3193 if (isp->isp_atioodx != optr) { 3194 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr); 3195 isp->isp_atioodx = optr; 3196 } 3197 } 3198 #endif 3199 3200 void 3201 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0) 3202 { 3203 int i, obits; 3204 3205 if (!isp->isp_mboxbsy) { 3206 isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0); 3207 return; 3208 } 3209 obits = isp->isp_obits; 3210 isp->isp_mboxtmp[0] = mbox0; 3211 for (i = 1; i < ISP_NMBOX(isp); i++) { 3212 if ((obits & (1 << i)) == 0) 3213 continue; 3214 isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i)); 3215 } 3216 MBOX_NOTIFY_COMPLETE(isp); 3217 } 3218 3219 void 3220 isp_intr_respq(ispsoftc_t *isp) 3221 { 3222 XS_T *xs, *cont_xs; 3223 uint8_t qe[QENTRY_LEN]; 3224 isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe; 3225 isphdr_t *hp; 3226 uint8_t *resp, *snsp; 3227 int buddaboom, completion_status, cont = 0, etype, i; 3228 int req_status_flags, req_state_flags, scsi_status; 3229 uint32_t iptr, cptr, optr, rlen, slen, sptr, totslen, resid; 3230 3231 /* 3232 * We can't be getting this now. 3233 */ 3234 if (isp->isp_state != ISP_RUNSTATE) { 3235 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready"); 3236 return; 3237 } 3238 3239 iptr = ISP_READ(isp, BIU2400_RSPINP); 3240 isp->isp_residx = iptr; 3241 3242 optr = isp->isp_resodx; 3243 while (optr != iptr) { 3244 sptr = cptr = optr; 3245 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr); 3246 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp)); 3247 3248 /* 3249 * Synchronize our view of this response queue entry. 3250 */ 3251 MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1); 3252 if (isp->isp_dblev & ISP_LOGDEBUG1) 3253 isp_print_qentry(isp, "Response Queue Entry", cptr, hp); 3254 isp_get_hdr(isp, hp, &sp->req_header); 3255 etype = sp->req_header.rqs_entry_type; 3256 3257 /* We expected Status Continuation, but got different IOCB. */ 3258 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) { 3259 cont = 0; 3260 isp_done(cont_xs); 3261 } 3262 3263 if (etype == RQSTYPE_RESPONSE) { 3264 isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp); 3265 scsi_status = sp->req_scsi_status; 3266 completion_status = sp->req_completion_status; 3267 req_status_flags = 0; 3268 if ((scsi_status & 0xff) != 0) 3269 req_state_flags = RQSF_GOT_STATUS; 3270 else 3271 req_state_flags = 0; 3272 resid = sp->req_resid; 3273 } else if (etype == RQSTYPE_STATUS_CONT) { 3274 ispstatus_cont_t *scp = (ispstatus_cont_t *)qe; 3275 isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp); 3276 if (cont > 0) { 3277 i = min(cont, sizeof(scp->req_sense_data)); 3278 XS_SENSE_APPEND(cont_xs, scp->req_sense_data, i); 3279 cont -= i; 3280 if (cont == 0) { 3281 isp_done(cont_xs); 3282 } else { 3283 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN, 3284 "Expecting Status Continuations for %u bytes", 3285 cont); 3286 } 3287 } else { 3288 isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response"); 3289 } 3290 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3291 continue; 3292 } else if (isp_handle_other_response(isp, etype, hp, 3293 &cptr, RESULT_QUEUE_LEN(isp))) { 3294 /* More then one IOCB could be consumed. */ 3295 while (sptr != cptr) { 3296 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3297 sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp)); 3298 hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr); 3299 } 3300 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3301 optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp)); 3302 continue; 3303 } else { 3304 /* We don't know what was this -- log and skip. */ 3305 isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr); 3306 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3307 continue; 3308 } 3309 3310 buddaboom = 0; 3311 if (sp->req_header.rqs_flags & RQSFLAG_MASK) { 3312 if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) { 3313 isp_print_qentry(isp, "unexpected continuation segment", 3314 cptr, hp); 3315 continue; 3316 } 3317 if (sp->req_header.rqs_flags & RQSFLAG_FULL) { 3318 isp_prt(isp, ISP_LOG_WARN1, "internal queues full"); 3319 /* 3320 * We'll synthesize a QUEUE FULL message below. 3321 */ 3322 } 3323 if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) { 3324 isp_print_qentry(isp, "bad header flag", 3325 cptr, hp); 3326 buddaboom++; 3327 } 3328 if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) { 3329 isp_print_qentry(isp, "bad request packet", 3330 cptr, hp); 3331 buddaboom++; 3332 } 3333 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) { 3334 isp_print_qentry(isp, "invalid entry count", 3335 cptr, hp); 3336 buddaboom++; 3337 } 3338 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) { 3339 isp_print_qentry(isp, "invalid IOCB ordering", 3340 cptr, hp); 3341 continue; 3342 } 3343 } 3344 3345 xs = isp_find_xs(isp, sp->req_handle); 3346 if (xs == NULL) { 3347 uint8_t ts = completion_status & 0xff; 3348 /* 3349 * Only whine if this isn't the expected fallout of 3350 * aborting the command or resetting the target. 3351 */ 3352 if (etype != RQSTYPE_RESPONSE) { 3353 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype); 3354 } else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED) { 3355 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts); 3356 } 3357 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3358 continue; 3359 } 3360 if (req_status_flags & RQSTF_BUS_RESET) { 3361 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx bus was reset", 3362 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs)); 3363 XS_SETERR(xs, HBA_BUSRESET); 3364 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1); 3365 } 3366 if (buddaboom) { 3367 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx buddaboom", 3368 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs)); 3369 XS_SETERR(xs, HBA_BOTCH); 3370 } 3371 3372 resp = snsp = NULL; 3373 rlen = slen = totslen = 0; 3374 if ((scsi_status & (RQCS_RV|RQCS_SV)) != 0) { 3375 resp = sp->req_rsp_sense; 3376 rlen = sp->req_response_len; 3377 } 3378 if ((scsi_status & RQCS_SV) != 0) { 3379 /* 3380 * Fibre Channel F/W doesn't say we got status 3381 * if there's Sense Data instead. I guess they 3382 * think it goes w/o saying. 3383 */ 3384 req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE; 3385 snsp = sp->req_rsp_sense + rlen; 3386 totslen = sp->req_sense_len; 3387 slen = sizeof(sp->req_rsp_sense) - rlen; 3388 } 3389 if (slen > totslen) 3390 slen = totslen; 3391 if (req_state_flags & RQSF_GOT_STATUS) 3392 *XS_STSP(xs) = scsi_status & 0xff; 3393 3394 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) { 3395 const char *ptr; 3396 char lb[64]; 3397 const char *rnames[10] = { 3398 "Task Management function complete", 3399 "FCP_DATA length different than FCP_BURST_LEN", 3400 "FCP_CMND fields invalid", 3401 "FCP_DATA parameter mismatch with FCP_DATA_RO", 3402 "Task Management function rejected", 3403 "Task Management function failed", 3404 NULL, 3405 NULL, 3406 "Task Management function succeeded", 3407 "Task Management function incorrect logical unit number", 3408 }; 3409 uint8_t code = resp[FCP_RSPNS_CODE_OFFSET]; 3410 if (code >= 10 || rnames[code] == NULL) { 3411 ISP_SNPRINTF(lb, sizeof(lb), 3412 "Unknown FCP Response Code 0x%x", code); 3413 ptr = lb; 3414 } else { 3415 ptr = rnames[code]; 3416 } 3417 isp_xs_prt(isp, xs, ISP_LOGWARN, 3418 "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x", 3419 rlen, ptr, XS_CDBP(xs)[0] & 0xff); 3420 if (code != 0 && code != 8) 3421 XS_SETERR(xs, HBA_BOTCH); 3422 } 3423 isp_parse_status_24xx(isp, sp, xs, &resid); 3424 if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) && 3425 (*XS_STSP(xs) == SCSI_BUSY)) 3426 XS_SETERR(xs, HBA_TGTBSY); 3427 if (req_status_flags & RQSF_XFER_COMPLETE) { 3428 XS_SET_RESID(xs, 0); 3429 } else if (scsi_status & RQCS_RESID) { 3430 XS_SET_RESID(xs, resid); 3431 } else { 3432 XS_SET_RESID(xs, 0); 3433 } 3434 if (slen > 0) { 3435 XS_SAVE_SENSE(xs, snsp, slen); 3436 if (totslen > slen) { 3437 cont = totslen - slen; 3438 cont_xs = xs; 3439 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN, 3440 "Expecting Status Continuations for %u bytes", 3441 cont); 3442 } 3443 } 3444 isp_prt(isp, ISP_LOGDEBUG2, "asked for %lu got raw resid %lu settled for %lu", 3445 (u_long)XS_XFRLEN(xs), (u_long)resid, (u_long)XS_GET_RESID(xs)); 3446 3447 ISP_DMAFREE(isp, xs); 3448 isp_destroy_handle(isp, sp->req_handle); 3449 3450 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3451 3452 /* Complete command if we expect no Status Continuations. */ 3453 if (cont == 0) 3454 isp_done(xs); 3455 } 3456 3457 /* We haven't received all Status Continuations, but that is it. */ 3458 if (cont > 0) 3459 isp_done(cont_xs); 3460 3461 /* If we processed any IOCBs, let ISP know about it. */ 3462 if (optr != isp->isp_resodx) { 3463 ISP_WRITE(isp, BIU2400_RSPOUTP, optr); 3464 isp->isp_resodx = optr; 3465 } 3466 } 3467 3468 3469 void 3470 isp_intr_async(ispsoftc_t *isp, uint16_t mbox) 3471 { 3472 fcparam *fcp; 3473 uint16_t chan; 3474 3475 isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox); 3476 3477 switch (mbox) { 3478 case ASYNC_SYSTEM_ERROR: 3479 isp->isp_state = ISP_CRASHED; 3480 for (chan = 0; chan < isp->isp_nchan; chan++) { 3481 FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL; 3482 isp_change_fw_state(isp, chan, FW_CONFIG_WAIT); 3483 } 3484 /* 3485 * Were we waiting for a mailbox command to complete? 3486 * If so, it's dead, so wake up the waiter. 3487 */ 3488 if (isp->isp_mboxbsy) { 3489 isp->isp_obits = 1; 3490 isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR; 3491 MBOX_NOTIFY_COMPLETE(isp); 3492 } 3493 /* 3494 * It's up to the handler for isp_async to reinit stuff and 3495 * restart the firmware 3496 */ 3497 isp_async(isp, ISPASYNC_FW_CRASH); 3498 break; 3499 3500 case ASYNC_RQS_XFER_ERR: 3501 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error"); 3502 break; 3503 3504 case ASYNC_RSP_XFER_ERR: 3505 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error"); 3506 break; 3507 3508 case ASYNC_ATIO_XFER_ERR: 3509 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error"); 3510 break; 3511 3512 case ASYNC_LIP_OCCURRED: 3513 case ASYNC_LIP_NOS_OLS_RECV: 3514 case ASYNC_LIP_ERROR: 3515 case ASYNC_PTPMODE: 3516 /* 3517 * These are broadcast events that have to be sent across 3518 * all active channels. 3519 */ 3520 for (chan = 0; chan < isp->isp_nchan; chan++) { 3521 fcp = FCPARAM(isp, chan); 3522 int topo = fcp->isp_topo; 3523 3524 if (fcp->role == ISP_ROLE_NONE) 3525 continue; 3526 if (fcp->isp_loopstate > LOOP_HAVE_LINK) 3527 fcp->isp_loopstate = LOOP_HAVE_LINK; 3528 ISP_SET_SENDMARKER(isp, chan, 1); 3529 isp_async(isp, ISPASYNC_LIP, chan); 3530 #ifdef ISP_TARGET_MODE 3531 isp_target_async(isp, chan, mbox); 3532 #endif 3533 /* 3534 * We've had problems with data corruption occurring on 3535 * commands that complete (with no apparent error) after 3536 * we receive a LIP. This has been observed mostly on 3537 * Local Loop topologies. To be safe, let's just mark 3538 * all active initiator commands as dead. 3539 */ 3540 if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) { 3541 int i, j; 3542 for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) { 3543 XS_T *xs; 3544 isp_hdl_t *hdp; 3545 3546 hdp = &isp->isp_xflist[i]; 3547 if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) { 3548 continue; 3549 } 3550 xs = hdp->cmd; 3551 if (XS_CHANNEL(xs) != chan) { 3552 continue; 3553 } 3554 j++; 3555 isp_prt(isp, ISP_LOG_WARN1, 3556 "%d.%d.%jx bus reset set at %s:%u", 3557 XS_CHANNEL(xs), XS_TGT(xs), 3558 (uintmax_t)XS_LUN(xs), 3559 __func__, __LINE__); 3560 XS_SETERR(xs, HBA_BUSRESET); 3561 } 3562 if (j) { 3563 isp_prt(isp, ISP_LOGERR, lipd, chan, j); 3564 } 3565 } 3566 } 3567 break; 3568 3569 case ASYNC_LOOP_UP: 3570 /* 3571 * This is a broadcast event that has to be sent across 3572 * all active channels. 3573 */ 3574 for (chan = 0; chan < isp->isp_nchan; chan++) { 3575 fcp = FCPARAM(isp, chan); 3576 if (fcp->role == ISP_ROLE_NONE) 3577 continue; 3578 fcp->isp_linkstate = 1; 3579 if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3580 fcp->isp_loopstate = LOOP_HAVE_LINK; 3581 ISP_SET_SENDMARKER(isp, chan, 1); 3582 isp_async(isp, ISPASYNC_LOOP_UP, chan); 3583 #ifdef ISP_TARGET_MODE 3584 isp_target_async(isp, chan, mbox); 3585 #endif 3586 } 3587 break; 3588 3589 case ASYNC_LOOP_DOWN: 3590 /* 3591 * This is a broadcast event that has to be sent across 3592 * all active channels. 3593 */ 3594 for (chan = 0; chan < isp->isp_nchan; chan++) { 3595 fcp = FCPARAM(isp, chan); 3596 if (fcp->role == ISP_ROLE_NONE) 3597 continue; 3598 ISP_SET_SENDMARKER(isp, chan, 1); 3599 fcp->isp_linkstate = 0; 3600 fcp->isp_loopstate = LOOP_NIL; 3601 isp_async(isp, ISPASYNC_LOOP_DOWN, chan); 3602 #ifdef ISP_TARGET_MODE 3603 isp_target_async(isp, chan, mbox); 3604 #endif 3605 } 3606 break; 3607 3608 case ASYNC_LOOP_RESET: 3609 /* 3610 * This is a broadcast event that has to be sent across 3611 * all active channels. 3612 */ 3613 for (chan = 0; chan < isp->isp_nchan; chan++) { 3614 fcp = FCPARAM(isp, chan); 3615 if (fcp->role == ISP_ROLE_NONE) 3616 continue; 3617 ISP_SET_SENDMARKER(isp, chan, 1); 3618 if (fcp->isp_loopstate > LOOP_HAVE_LINK) 3619 fcp->isp_loopstate = LOOP_HAVE_LINK; 3620 isp_async(isp, ISPASYNC_LOOP_RESET, chan); 3621 #ifdef ISP_TARGET_MODE 3622 isp_target_async(isp, chan, mbox); 3623 #endif 3624 } 3625 break; 3626 3627 case ASYNC_PDB_CHANGED: 3628 { 3629 int echan, nphdl, nlstate, reason; 3630 3631 nphdl = ISP_READ(isp, OUTMAILBOX1); 3632 nlstate = ISP_READ(isp, OUTMAILBOX2); 3633 reason = ISP_READ(isp, OUTMAILBOX3) >> 8; 3634 if (ISP_CAP_MULTI_ID(isp)) { 3635 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; 3636 if (chan == 0xff || nphdl == NIL_HANDLE) { 3637 chan = 0; 3638 echan = isp->isp_nchan - 1; 3639 } else if (chan >= isp->isp_nchan) { 3640 break; 3641 } else { 3642 echan = chan; 3643 } 3644 } else { 3645 chan = echan = 0; 3646 } 3647 for (; chan <= echan; chan++) { 3648 fcp = FCPARAM(isp, chan); 3649 if (fcp->role == ISP_ROLE_NONE) 3650 continue; 3651 if (fcp->isp_loopstate > LOOP_LTEST_DONE) { 3652 if (nphdl != NIL_HANDLE && 3653 nphdl == fcp->isp_login_hdl && 3654 reason == PDB24XX_AE_OPN_2) 3655 continue; 3656 fcp->isp_loopstate = LOOP_LTEST_DONE; 3657 } else if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3658 fcp->isp_loopstate = LOOP_HAVE_LINK; 3659 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, 3660 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason); 3661 } 3662 break; 3663 } 3664 case ASYNC_CHANGE_NOTIFY: 3665 { 3666 int portid; 3667 3668 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) | 3669 ISP_READ(isp, OUTMAILBOX2); 3670 if (ISP_CAP_MULTI_ID(isp)) { 3671 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; 3672 if (chan >= isp->isp_nchan) 3673 break; 3674 } else { 3675 chan = 0; 3676 } 3677 fcp = FCPARAM(isp, chan); 3678 if (fcp->role == ISP_ROLE_NONE) 3679 break; 3680 if (fcp->isp_loopstate > LOOP_LTEST_DONE) 3681 fcp->isp_loopstate = LOOP_LTEST_DONE; 3682 else if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3683 fcp->isp_loopstate = LOOP_HAVE_LINK; 3684 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, 3685 ISPASYNC_CHANGE_SNS, portid); 3686 break; 3687 } 3688 case ASYNC_ERR_LOGGING_DISABLED: 3689 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)", 3690 ISP_READ(isp, OUTMAILBOX1)); 3691 break; 3692 case ASYNC_P2P_INIT_ERR: 3693 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)", 3694 ISP_READ(isp, OUTMAILBOX1)); 3695 break; 3696 case ASYNC_RCV_ERR: 3697 isp_prt(isp, ISP_LOGWARN, "Receive Error"); 3698 break; 3699 case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */ 3700 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent"); 3701 break; 3702 case ASYNC_FW_RESTART_COMPLETE: 3703 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete"); 3704 break; 3705 case ASYNC_TEMPERATURE_ALERT: 3706 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)", 3707 ISP_READ(isp, OUTMAILBOX1)); 3708 break; 3709 case ASYNC_TRANSCEIVER_INSERTION: 3710 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)", 3711 ISP_READ(isp, OUTMAILBOX1)); 3712 break; 3713 case ASYNC_TRANSCEIVER_REMOVAL: 3714 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal"); 3715 break; 3716 case ASYNC_AUTOLOAD_FW_COMPLETE: 3717 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete"); 3718 break; 3719 case ASYNC_AUTOLOAD_FW_FAILURE: 3720 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure"); 3721 break; 3722 default: 3723 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox); 3724 break; 3725 } 3726 } 3727 3728 /* 3729 * Handle other response entries. A pointer to the request queue output 3730 * index is here in case we want to eat several entries at once, although 3731 * this is not used currently. 3732 */ 3733 3734 static int 3735 isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *optrp, uint16_t ql) 3736 { 3737 isp_ridacq_t rid; 3738 int chan, c; 3739 uint32_t hdl, portid; 3740 void *ptr; 3741 3742 switch (type) { 3743 case RQSTYPE_MARKER: 3744 isp_prt(isp, ISP_LOG_WARN1, "Marker Response"); 3745 return (1); 3746 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/ 3747 isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid); 3748 portid = (uint32_t)rid.ridacq_vp_port_hi << 16 | 3749 rid.ridacq_vp_port_lo; 3750 if (rid.ridacq_format == 0) { 3751 for (chan = 0; chan < isp->isp_nchan; chan++) { 3752 fcparam *fcp = FCPARAM(isp, chan); 3753 if (fcp->role == ISP_ROLE_NONE) 3754 continue; 3755 c = (chan == 0) ? 127 : (chan - 1); 3756 if (rid.ridacq_map[c / 16] & (1 << (c % 16)) || 3757 chan == 0) { 3758 fcp->isp_loopstate = LOOP_HAVE_LINK; 3759 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 3760 chan, ISPASYNC_CHANGE_OTHER); 3761 } else { 3762 fcp->isp_loopstate = LOOP_NIL; 3763 isp_async(isp, ISPASYNC_LOOP_DOWN, 3764 chan); 3765 } 3766 } 3767 } else { 3768 fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index); 3769 if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE || 3770 rid.ridacq_vp_status == RIDACQ_STS_CHANGED) { 3771 fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7; 3772 fcp->isp_portid = portid; 3773 fcp->isp_loopstate = LOOP_HAVE_ADDR; 3774 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 3775 rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER); 3776 } else { 3777 fcp->isp_loopstate = LOOP_NIL; 3778 isp_async(isp, ISPASYNC_LOOP_DOWN, 3779 rid.ridacq_vp_index); 3780 } 3781 } 3782 return (1); 3783 case RQSTYPE_CT_PASSTHRU: 3784 case RQSTYPE_VP_MODIFY: 3785 case RQSTYPE_VP_CTRL: 3786 case RQSTYPE_LOGIN: 3787 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl); 3788 ptr = isp_find_xs(isp, hdl); 3789 if (ptr != NULL) { 3790 isp_destroy_handle(isp, hdl); 3791 memcpy(ptr, hp, QENTRY_LEN); 3792 wakeup(ptr); 3793 } 3794 return (1); 3795 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue. */ 3796 case RQSTYPE_CTIO7: 3797 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue. */ 3798 case RQSTYPE_ABTS_RSP: 3799 #ifdef ISP_TARGET_MODE 3800 return (isp_target_notify(isp, hp, optrp, ql)); 3801 #endif 3802 /* FALLTHROUGH */ 3803 default: 3804 return (0); 3805 } 3806 } 3807 3808 static void 3809 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs, uint32_t *rp) 3810 { 3811 int ru_marked, sv_marked; 3812 int chan = XS_CHANNEL(xs); 3813 3814 switch (sp->req_completion_status) { 3815 case RQCS_COMPLETE: 3816 if (XS_NOERR(xs)) { 3817 XS_SETERR(xs, HBA_NOERROR); 3818 } 3819 return; 3820 3821 case RQCS_DMA_ERROR: 3822 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error"); 3823 break; 3824 3825 case RQCS_TRANSPORT_ERROR: 3826 isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error"); 3827 break; 3828 3829 case RQCS_RESET_OCCURRED: 3830 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command"); 3831 FCPARAM(isp, chan)->sendmarker = 1; 3832 if (XS_NOERR(xs)) { 3833 XS_SETERR(xs, HBA_BUSRESET); 3834 } 3835 return; 3836 3837 case RQCS_ABORTED: 3838 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted"); 3839 FCPARAM(isp, chan)->sendmarker = 1; 3840 if (XS_NOERR(xs)) { 3841 XS_SETERR(xs, HBA_ABORTED); 3842 } 3843 return; 3844 3845 case RQCS_TIMEOUT: 3846 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out"); 3847 if (XS_NOERR(xs)) { 3848 XS_SETERR(xs, HBA_CMDTIMEOUT); 3849 } 3850 return; 3851 3852 case RQCS_DATA_OVERRUN: 3853 XS_SET_RESID(xs, sp->req_resid); 3854 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun"); 3855 if (XS_NOERR(xs)) { 3856 XS_SETERR(xs, HBA_DATAOVR); 3857 } 3858 return; 3859 3860 case RQCS_24XX_DRE: /* data reassembly error */ 3861 isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs)); 3862 if (XS_NOERR(xs)) { 3863 XS_SETERR(xs, HBA_ABORTED); 3864 } 3865 *rp = XS_XFRLEN(xs); 3866 return; 3867 3868 case RQCS_24XX_TABORT: /* aborted by target */ 3869 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs)); 3870 if (XS_NOERR(xs)) { 3871 XS_SETERR(xs, HBA_ABORTED); 3872 } 3873 return; 3874 3875 case RQCS_DATA_UNDERRUN: 3876 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0; 3877 /* 3878 * We can get an underrun w/o things being marked 3879 * if we got a non-zero status. 3880 */ 3881 sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0; 3882 if ((ru_marked == 0 && sv_marked == 0) || 3883 (sp->req_resid > XS_XFRLEN(xs))) { 3884 isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked"); 3885 if (XS_NOERR(xs)) { 3886 XS_SETERR(xs, HBA_BOTCH); 3887 } 3888 return; 3889 } 3890 XS_SET_RESID(xs, sp->req_resid); 3891 isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff); 3892 if (XS_NOERR(xs)) { 3893 XS_SETERR(xs, HBA_NOERROR); 3894 } 3895 return; 3896 3897 case RQCS_PORT_UNAVAILABLE: 3898 /* 3899 * No such port on the loop. Moral equivalent of SELTIMEO 3900 */ 3901 case RQCS_PORT_LOGGED_OUT: 3902 { 3903 const char *reason; 3904 uint8_t sts = sp->req_completion_status & 0xff; 3905 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs)); 3906 fcportdb_t *lp; 3907 3908 /* 3909 * It was there (maybe)- treat as a selection timeout. 3910 */ 3911 if (sts == RQCS_PORT_UNAVAILABLE) { 3912 reason = "unavailable"; 3913 } else { 3914 reason = "logout"; 3915 } 3916 3917 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d", 3918 chan, reason, XS_TGT(xs)); 3919 3920 /* XXX: Should we trigger rescan or FW announce change? */ 3921 3922 if (XS_NOERR(xs)) { 3923 lp = &fcp->portdb[XS_TGT(xs)]; 3924 if (lp->state == FC_PORTDB_STATE_ZOMBIE) { 3925 *XS_STSP(xs) = SCSI_BUSY; 3926 XS_SETERR(xs, HBA_TGTBSY); 3927 } else 3928 XS_SETERR(xs, HBA_SELTIMEOUT); 3929 } 3930 return; 3931 } 3932 case RQCS_PORT_CHANGED: 3933 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan); 3934 if (XS_NOERR(xs)) { 3935 *XS_STSP(xs) = SCSI_BUSY; 3936 XS_SETERR(xs, HBA_TGTBSY); 3937 } 3938 return; 3939 3940 case RQCS_24XX_ENOMEM: /* f/w resource unavailable */ 3941 isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan); 3942 if (XS_NOERR(xs)) { 3943 *XS_STSP(xs) = SCSI_BUSY; 3944 XS_SETERR(xs, HBA_TGTBSY); 3945 } 3946 return; 3947 3948 case RQCS_24XX_TMO: /* task management overrun */ 3949 isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan); 3950 if (XS_NOERR(xs)) { 3951 *XS_STSP(xs) = SCSI_BUSY; 3952 XS_SETERR(xs, HBA_TGTBSY); 3953 } 3954 return; 3955 3956 default: 3957 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan); 3958 break; 3959 } 3960 if (XS_NOERR(xs)) { 3961 XS_SETERR(xs, HBA_BOTCH); 3962 } 3963 } 3964 3965 #define ISP_FC_IBITS(op) ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3])) 3966 #define ISP_FC_OBITS(op) ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7])) 3967 3968 #define ISP_FC_OPMAP(in0, out0) 0, 0, 0, in0, 0, 0, 0, out0 3969 #define ISP_FC_OPMAP_HALF(in1, in0, out1, out0) 0, 0, in1, in0, 0, 0, out1, out0 3970 #define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0) in3, in2, in1, in0, out3, out2, out1, out0 3971 static const uint32_t mbpfc[] = { 3972 ISP_FC_OPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ 3973 ISP_FC_OPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ 3974 ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f), /* 0x02: MBOX_EXEC_FIRMWARE */ 3975 ISP_FC_OPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */ 3976 ISP_FC_OPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ 3977 ISP_FC_OPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ 3978 ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */ 3979 ISP_FC_OPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ 3980 ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f), /* 0x08: MBOX_ABOUT_FIRMWARE */ 3981 ISP_FC_OPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */ 3982 ISP_FC_OPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */ 3983 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */ 3984 ISP_FC_OPMAP(0x00, 0x00), /* 0x0c: */ 3985 ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */ 3986 ISP_FC_OPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ 3987 ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */ 3988 ISP_FC_OPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */ 3989 ISP_FC_OPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */ 3990 ISP_FC_OPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */ 3991 ISP_FC_OPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */ 3992 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03), /* 0x14: MBOX_STOP_FIRMWARE */ 3993 ISP_FC_OPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */ 3994 ISP_FC_OPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */ 3995 ISP_FC_OPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */ 3996 ISP_FC_OPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */ 3997 ISP_FC_OPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */ 3998 ISP_FC_OPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */ 3999 ISP_FC_OPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ 4000 ISP_FC_OPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */ 4001 ISP_FC_OPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ 4002 ISP_FC_OPMAP(0x00, 0x00), /* 0x1e: */ 4003 ISP_FC_OPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ 4004 ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf), /* 0x20: MBOX_GET_LOOP_ID */ 4005 ISP_FC_OPMAP(0x00, 0x00), /* 0x21: */ 4006 ISP_FC_OPMAP(0x03, 0x4b), /* 0x22: MBOX_GET_TIMEOUT_PARAMS */ 4007 ISP_FC_OPMAP(0x00, 0x00), /* 0x23: */ 4008 ISP_FC_OPMAP(0x00, 0x00), /* 0x24: */ 4009 ISP_FC_OPMAP(0x00, 0x00), /* 0x25: */ 4010 ISP_FC_OPMAP(0x00, 0x00), /* 0x26: */ 4011 ISP_FC_OPMAP(0x00, 0x00), /* 0x27: */ 4012 ISP_FC_OPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */ 4013 ISP_FC_OPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */ 4014 ISP_FC_OPMAP(0x00, 0x00), /* 0x2a: */ 4015 ISP_FC_OPMAP(0x00, 0x00), /* 0x2b: */ 4016 ISP_FC_OPMAP(0x00, 0x00), /* 0x2c: */ 4017 ISP_FC_OPMAP(0x00, 0x00), /* 0x2d: */ 4018 ISP_FC_OPMAP(0x00, 0x00), /* 0x2e: */ 4019 ISP_FC_OPMAP(0x00, 0x00), /* 0x2f: */ 4020 ISP_FC_OPMAP(0x00, 0x00), /* 0x30: */ 4021 ISP_FC_OPMAP(0x00, 0x00), /* 0x31: */ 4022 ISP_FC_OPMAP(0x4b, 0x4b), /* 0x32: MBOX_SET_TIMEOUT_PARAMS */ 4023 ISP_FC_OPMAP(0x00, 0x00), /* 0x33: */ 4024 ISP_FC_OPMAP(0x00, 0x00), /* 0x34: */ 4025 ISP_FC_OPMAP(0x00, 0x00), /* 0x35: */ 4026 ISP_FC_OPMAP(0x00, 0x00), /* 0x36: */ 4027 ISP_FC_OPMAP(0x00, 0x00), /* 0x37: */ 4028 ISP_FC_OPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */ 4029 ISP_FC_OPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */ 4030 ISP_FC_OPMAP(0x00, 0x00), /* 0x3a: */ 4031 ISP_FC_OPMAP(0x00, 0x00), /* 0x3b: */ 4032 ISP_FC_OPMAP(0x00, 0x00), /* 0x3c: */ 4033 ISP_FC_OPMAP(0x00, 0x00), /* 0x3d: */ 4034 ISP_FC_OPMAP(0x00, 0x00), /* 0x3e: */ 4035 ISP_FC_OPMAP(0x00, 0x00), /* 0x3f: */ 4036 ISP_FC_OPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */ 4037 ISP_FC_OPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */ 4038 ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf), /* 0x42: MBOX_GET_RESOURCE_COUNT */ 4039 ISP_FC_OPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */ 4040 ISP_FC_OPMAP(0x00, 0x00), /* 0x44: */ 4041 ISP_FC_OPMAP(0x00, 0x00), /* 0x45: */ 4042 ISP_FC_OPMAP(0x00, 0x00), /* 0x46: */ 4043 ISP_FC_OPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */ 4044 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */ 4045 ISP_FC_OPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */ 4046 ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */ 4047 ISP_FC_OPMAP(0x00, 0x00), /* 0x4b: */ 4048 ISP_FC_OPMAP(0x00, 0x00), /* 0x4c: */ 4049 ISP_FC_OPMAP(0x00, 0x00), /* 0x4d: */ 4050 ISP_FC_OPMAP(0x00, 0x00), /* 0x4e: */ 4051 ISP_FC_OPMAP(0x00, 0x00), /* 0x4f: */ 4052 ISP_FC_OPMAP(0x00, 0x00), /* 0x50: */ 4053 ISP_FC_OPMAP(0x00, 0x00), /* 0x51: */ 4054 ISP_FC_OPMAP(0x00, 0x00), /* 0x52: */ 4055 ISP_FC_OPMAP(0x00, 0x00), /* 0x53: */ 4056 ISP_FC_OPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */ 4057 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */ 4058 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */ 4059 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */ 4060 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */ 4061 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */ 4062 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */ 4063 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */ 4064 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */ 4065 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */ 4066 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */ 4067 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */ 4068 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */ 4069 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */ 4070 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ 4071 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ 4072 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */ 4073 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */ 4074 ISP_FC_OPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */ 4075 ISP_FC_OPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */ 4076 ISP_FC_OPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */ 4077 ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f), /* 0x69: MBOX_GET_FW_STATE */ 4078 ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */ 4079 ISP_FC_OPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */ 4080 ISP_FC_OPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */ 4081 ISP_FC_OPMAP(0x00, 0x00), /* 0x6d: */ 4082 ISP_FC_OPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */ 4083 ISP_FC_OPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */ 4084 ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03), /* 0x70: MBOX_SEND_CHANGE_REQUEST */ 4085 ISP_FC_OPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */ 4086 ISP_FC_OPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */ 4087 ISP_FC_OPMAP(0x00, 0x00), /* 0x73: */ 4088 ISP_FC_OPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */ 4089 ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07), /* 0x75: GET PORT/NODE NAME LIST */ 4090 ISP_FC_OPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */ 4091 ISP_FC_OPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */ 4092 ISP_FC_OPMAP(0x00, 0x00), /* 0x78: */ 4093 ISP_FC_OPMAP(0x00, 0x00), /* 0x79: */ 4094 ISP_FC_OPMAP(0x00, 0x00), /* 0x7a: */ 4095 ISP_FC_OPMAP(0x00, 0x00), /* 0x7b: */ 4096 ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07), /* 0x7c: Get ID List */ 4097 ISP_FC_OPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */ 4098 ISP_FC_OPMAP(0x0f, 0x01) /* 0x7e: LUN RESET */ 4099 }; 4100 #define MAX_FC_OPCODE 0x7e 4101 /* 4102 * Footnotes 4103 * 4104 * (1): this sets bits 21..16 in mailbox register #8, which we nominally 4105 * do not access at this time in the core driver. The caller is 4106 * responsible for setting this register first (Gross!). The assumption 4107 * is that we won't overflow. 4108 */ 4109 4110 static const char *fc_mbcmd_names[] = { 4111 "NO-OP", /* 00h */ 4112 "LOAD RAM", 4113 "EXEC FIRMWARE", 4114 "DUMP RAM", 4115 "WRITE RAM WORD", 4116 "READ RAM WORD", 4117 "MAILBOX REG TEST", 4118 "VERIFY CHECKSUM", 4119 "ABOUT FIRMWARE", 4120 "LOAD RAM (2100)", 4121 "DUMP RAM", 4122 "LOAD RISC RAM", 4123 "DUMP RISC RAM", 4124 "WRITE RAM WORD EXTENDED", 4125 "CHECK FIRMWARE", 4126 "READ RAM WORD EXTENDED", 4127 "INIT REQUEST QUEUE", /* 10h */ 4128 "INIT RESULT QUEUE", 4129 "EXECUTE IOCB", 4130 "WAKE UP", 4131 "STOP FIRMWARE", 4132 "ABORT", 4133 "ABORT DEVICE", 4134 "ABORT TARGET", 4135 "BUS RESET", 4136 "STOP QUEUE", 4137 "START QUEUE", 4138 "SINGLE STEP QUEUE", 4139 "ABORT QUEUE", 4140 "GET DEV QUEUE STATUS", 4141 NULL, 4142 "GET FIRMWARE STATUS", 4143 "GET LOOP ID", /* 20h */ 4144 NULL, 4145 "GET TIMEOUT PARAMS", 4146 NULL, 4147 NULL, 4148 NULL, 4149 NULL, 4150 NULL, 4151 "GET FIRMWARE OPTIONS", 4152 "GET PORT QUEUE PARAMS", 4153 "GENERATE SYSTEM ERROR", 4154 NULL, 4155 NULL, 4156 NULL, 4157 NULL, 4158 NULL, 4159 "WRITE SFP", /* 30h */ 4160 "READ SFP", 4161 "SET TIMEOUT PARAMS", 4162 NULL, 4163 NULL, 4164 NULL, 4165 NULL, 4166 NULL, 4167 "SET FIRMWARE OPTIONS", 4168 "SET PORT QUEUE PARAMS", 4169 NULL, 4170 "SET FC LED CONF", 4171 NULL, 4172 "RESTART NIC FIRMWARE", 4173 "ACCESS CONTROL", 4174 NULL, 4175 "LOOP PORT BYPASS", /* 40h */ 4176 "LOOP PORT ENABLE", 4177 "GET RESOURCE COUNT", 4178 "REQUEST NON PARTICIPATING MODE", 4179 "DIAGNOSTIC ECHO TEST", 4180 "DIAGNOSTIC LOOPBACK", 4181 NULL, 4182 "GET PORT DATABASE ENHANCED", 4183 "INIT FIRMWARE MULTI ID", 4184 "GET VP DATABASE", 4185 "GET VP DATABASE ENTRY", 4186 NULL, 4187 NULL, 4188 NULL, 4189 NULL, 4190 NULL, 4191 "GET FCF LIST", /* 50h */ 4192 "GET DCBX PARAMETERS", 4193 NULL, 4194 "HOST MEMORY COPY", 4195 "EXECUTE IOCB A64", 4196 NULL, 4197 NULL, 4198 "SEND RNID", 4199 NULL, 4200 "SET PARAMETERS", 4201 "GET PARAMETERS", 4202 "DRIVER HEARTBEAT", 4203 "FIRMWARE HEARTBEAT", 4204 "GET/SET DATA RATE", 4205 "SEND RNFT", 4206 NULL, 4207 "INIT FIRMWARE", /* 60h */ 4208 "GET INIT CONTROL BLOCK", 4209 "INIT LIP", 4210 "GET FC-AL POSITION MAP", 4211 "GET PORT DATABASE", 4212 "CLEAR ACA", 4213 "TARGET RESET", 4214 "CLEAR TASK SET", 4215 "ABORT TASK SET", 4216 "GET FW STATE", 4217 "GET PORT NAME", 4218 "GET LINK STATUS", 4219 "INIT LIP RESET", 4220 "GET LINK STATS & PRIVATE DATA CNTS", 4221 "SEND SNS", 4222 "FABRIC LOGIN", 4223 "SEND CHANGE REQUEST", /* 70h */ 4224 "FABRIC LOGOUT", 4225 "INIT LIP LOGIN", 4226 NULL, 4227 "LOGIN LOOP PORT", 4228 "GET PORT/NODE NAME LIST", 4229 "SET VENDOR ID", 4230 "INITIALIZE IP MAILBOX", 4231 NULL, 4232 NULL, 4233 "GET XGMAC STATS", 4234 NULL, 4235 "GET ID LIST", 4236 "SEND LFA", 4237 "LUN RESET" 4238 }; 4239 4240 static void 4241 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp) 4242 { 4243 const char *cname, *xname, *sname; 4244 char tname[16], mname[16]; 4245 unsigned int ibits, obits, box, opcode; 4246 4247 opcode = mbp->param[0]; 4248 if (opcode > MAX_FC_OPCODE) { 4249 mbp->param[0] = MBOX_INVALID_COMMAND; 4250 isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode); 4251 return; 4252 } 4253 cname = fc_mbcmd_names[opcode]; 4254 ibits = ISP_FC_IBITS(opcode); 4255 obits = ISP_FC_OBITS(opcode); 4256 if (cname == NULL) { 4257 cname = tname; 4258 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode); 4259 } 4260 isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname); 4261 4262 /* 4263 * Pick up any additional bits that the caller might have set. 4264 */ 4265 ibits |= mbp->ibits; 4266 obits |= mbp->obits; 4267 4268 /* 4269 * Mask any bits that the caller wants us to mask 4270 */ 4271 ibits &= mbp->ibitm; 4272 obits &= mbp->obitm; 4273 4274 4275 if (ibits == 0 && obits == 0) { 4276 mbp->param[0] = MBOX_COMMAND_PARAM_ERROR; 4277 isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode); 4278 return; 4279 } 4280 4281 /* 4282 * Get exclusive usage of mailbox registers. 4283 */ 4284 if (MBOX_ACQUIRE(isp)) { 4285 mbp->param[0] = MBOX_REGS_BUSY; 4286 goto out; 4287 } 4288 4289 for (box = 0; box < ISP_NMBOX(isp); box++) { 4290 if (ibits & (1 << box)) { 4291 isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box, 4292 mbp->param[box]); 4293 ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); 4294 } 4295 isp->isp_mboxtmp[box] = mbp->param[box] = 0; 4296 } 4297 4298 isp->isp_lastmbxcmd = opcode; 4299 4300 /* 4301 * We assume that we can't overwrite a previous command. 4302 */ 4303 isp->isp_obits = obits; 4304 isp->isp_mboxbsy = 1; 4305 4306 /* 4307 * Set Host Interrupt condition so that RISC will pick up mailbox regs. 4308 */ 4309 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT); 4310 4311 /* 4312 * While we haven't finished the command, spin our wheels here. 4313 */ 4314 MBOX_WAIT_COMPLETE(isp, mbp); 4315 4316 /* 4317 * Did the command time out? 4318 */ 4319 if (mbp->param[0] == MBOX_TIMEOUT) { 4320 isp->isp_mboxbsy = 0; 4321 MBOX_RELEASE(isp); 4322 goto out; 4323 } 4324 4325 /* 4326 * Copy back output registers. 4327 */ 4328 for (box = 0; box < ISP_NMBOX(isp); box++) { 4329 if (obits & (1 << box)) { 4330 mbp->param[box] = isp->isp_mboxtmp[box]; 4331 isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box, 4332 mbp->param[box]); 4333 } 4334 } 4335 4336 isp->isp_mboxbsy = 0; 4337 MBOX_RELEASE(isp); 4338 out: 4339 if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE) 4340 return; 4341 4342 if ((mbp->param[0] & 0xbfe0) == 0 && 4343 (mbp->logval & MBLOGMASK(mbp->param[0])) == 0) 4344 return; 4345 4346 xname = NULL; 4347 sname = ""; 4348 switch (mbp->param[0]) { 4349 case MBOX_INVALID_COMMAND: 4350 xname = "INVALID COMMAND"; 4351 break; 4352 case MBOX_HOST_INTERFACE_ERROR: 4353 xname = "HOST INTERFACE ERROR"; 4354 break; 4355 case MBOX_TEST_FAILED: 4356 xname = "TEST FAILED"; 4357 break; 4358 case MBOX_COMMAND_ERROR: 4359 xname = "COMMAND ERROR"; 4360 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x", 4361 mbp->param[1]); 4362 sname = mname; 4363 break; 4364 case MBOX_COMMAND_PARAM_ERROR: 4365 xname = "COMMAND PARAMETER ERROR"; 4366 break; 4367 case MBOX_PORT_ID_USED: 4368 xname = "PORT ID ALREADY IN USE"; 4369 break; 4370 case MBOX_LOOP_ID_USED: 4371 xname = "LOOP ID ALREADY IN USE"; 4372 break; 4373 case MBOX_ALL_IDS_USED: 4374 xname = "ALL LOOP IDS IN USE"; 4375 break; 4376 case MBOX_NOT_LOGGED_IN: 4377 xname = "NOT LOGGED IN"; 4378 break; 4379 case MBOX_LINK_DOWN_ERROR: 4380 xname = "LINK DOWN ERROR"; 4381 break; 4382 case MBOX_LOOPBACK_ERROR: 4383 xname = "LOOPBACK ERROR"; 4384 break; 4385 case MBOX_CHECKSUM_ERROR: 4386 xname = "CHECKSUM ERROR"; 4387 break; 4388 case MBOX_INVALID_PRODUCT_KEY: 4389 xname = "INVALID PRODUCT KEY"; 4390 break; 4391 case MBOX_REGS_BUSY: 4392 xname = "REGISTERS BUSY"; 4393 break; 4394 case MBOX_TIMEOUT: 4395 xname = "TIMEOUT"; 4396 break; 4397 default: 4398 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]); 4399 xname = mname; 4400 break; 4401 } 4402 if (xname) { 4403 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)", 4404 cname, xname, sname); 4405 } 4406 } 4407 4408 static int 4409 isp_fw_state(ispsoftc_t *isp, int chan) 4410 { 4411 mbreg_t mbs; 4412 4413 MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0); 4414 isp_mboxcmd(isp, &mbs); 4415 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) 4416 return (mbs.param[1]); 4417 return (FW_ERROR); 4418 } 4419 4420 static void 4421 isp_setdfltfcparm(ispsoftc_t *isp, int chan) 4422 { 4423 fcparam *fcp = FCPARAM(isp, chan); 4424 4425 /* 4426 * Establish some default parameters. 4427 */ 4428 fcp->role = DEFAULT_ROLE(isp, chan); 4429 fcp->isp_retry_delay = ICB_DFLT_RDELAY; 4430 fcp->isp_retry_count = ICB_DFLT_RCOUNT; 4431 fcp->isp_loopid = DEFAULT_LOOPID(isp, chan); 4432 fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan); 4433 fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan); 4434 fcp->isp_fwoptions = 0; 4435 fcp->isp_xfwoptions = 0; 4436 fcp->isp_zfwoptions = 0; 4437 fcp->isp_lasthdl = NIL_HANDLE; 4438 fcp->isp_login_hdl = NIL_HANDLE; 4439 4440 fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS; 4441 fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS; 4442 if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) 4443 fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX; 4444 fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS; 4445 fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP; 4446 fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO; 4447 4448 /* 4449 * Now try and read NVRAM unless told to not do so. 4450 * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram. 4451 */ 4452 if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { 4453 int i, j = 0; 4454 /* 4455 * Give a couple of tries at reading NVRAM. 4456 */ 4457 for (i = 0; i < 2; i++) { 4458 j = isp_read_nvram(isp, chan); 4459 if (j == 0) { 4460 break; 4461 } 4462 } 4463 if (j) { 4464 isp->isp_confopts |= ISP_CFG_NONVRAM; 4465 } 4466 } 4467 4468 fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan); 4469 fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan); 4470 isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s", 4471 chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn), 4472 (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn), 4473 isp_class3_roles[fcp->role]); 4474 } 4475 4476 /* 4477 * Re-initialize the ISP and complete all orphaned commands 4478 * with a 'botched' notice. The reset/init routines should 4479 * not disturb an already active list of commands. 4480 */ 4481 4482 int 4483 isp_reinit(ispsoftc_t *isp, int do_load_defaults) 4484 { 4485 int i, res = 0; 4486 4487 if (isp->isp_state > ISP_RESETSTATE) 4488 isp_stop(isp); 4489 if (isp->isp_state != ISP_RESETSTATE) 4490 isp_reset(isp, do_load_defaults); 4491 if (isp->isp_state != ISP_RESETSTATE) { 4492 res = EIO; 4493 isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__); 4494 goto cleanup; 4495 } 4496 4497 isp_init(isp); 4498 if (isp->isp_state > ISP_RESETSTATE && 4499 isp->isp_state != ISP_RUNSTATE) { 4500 res = EIO; 4501 isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__); 4502 ISP_DISABLE_INTS(isp); 4503 } 4504 4505 cleanup: 4506 isp_clear_commands(isp); 4507 for (i = 0; i < isp->isp_nchan; i++) 4508 isp_clear_portdb(isp, i); 4509 return (res); 4510 } 4511 4512 /* 4513 * NVRAM Routines 4514 */ 4515 static int 4516 isp_read_nvram(ispsoftc_t *isp, int bus) 4517 { 4518 4519 return (isp_read_nvram_2400(isp)); 4520 } 4521 4522 static int 4523 isp_read_nvram_2400(ispsoftc_t *isp) 4524 { 4525 int retval = 0; 4526 uint32_t addr, csum, lwrds, *dptr; 4527 uint8_t nvram_data[ISP2400_NVRAM_SIZE]; 4528 4529 if (isp->isp_port) { 4530 addr = ISP2400_NVRAM_PORT1_ADDR; 4531 } else { 4532 addr = ISP2400_NVRAM_PORT0_ADDR; 4533 } 4534 4535 dptr = (uint32_t *) nvram_data; 4536 for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) { 4537 isp_rd_2400_nvram(isp, addr++, dptr++); 4538 } 4539 if (nvram_data[0] != 'I' || nvram_data[1] != 'S' || 4540 nvram_data[2] != 'P') { 4541 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)", 4542 nvram_data[0], nvram_data[1], nvram_data[2]); 4543 retval = -1; 4544 goto out; 4545 } 4546 dptr = (uint32_t *) nvram_data; 4547 for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) { 4548 uint32_t tmp; 4549 ISP_IOXGET_32(isp, &dptr[lwrds], tmp); 4550 csum += tmp; 4551 } 4552 if (csum != 0) { 4553 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum"); 4554 retval = -1; 4555 goto out; 4556 } 4557 isp_parse_nvram_2400(isp, nvram_data); 4558 out: 4559 return (retval); 4560 } 4561 4562 static void 4563 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp) 4564 { 4565 int loops = 0; 4566 uint32_t base = 0x7ffe0000; 4567 uint32_t tmp = 0; 4568 4569 if (IS_26XX(isp)) { 4570 base = 0x7fe7c000; /* XXX: Observation, may be wrong. */ 4571 } else if (IS_25XX(isp)) { 4572 base = 0x7ff00000 | 0x48000; 4573 } 4574 ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr); 4575 for (loops = 0; loops < 5000; loops++) { 4576 ISP_DELAY(10); 4577 tmp = ISP_READ(isp, BIU2400_FLASH_ADDR); 4578 if ((tmp & (1U << 31)) != 0) { 4579 break; 4580 } 4581 } 4582 if (tmp & (1U << 31)) { 4583 *rp = ISP_READ(isp, BIU2400_FLASH_DATA); 4584 ISP_SWIZZLE_NVRAM_LONG(isp, rp); 4585 } else { 4586 *rp = 0xffffffff; 4587 } 4588 } 4589 4590 static void 4591 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data) 4592 { 4593 fcparam *fcp = FCPARAM(isp, 0); 4594 uint64_t wwn; 4595 4596 isp_prt(isp, ISP_LOGDEBUG0, 4597 "NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d", 4598 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32), 4599 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)), 4600 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32), 4601 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)), 4602 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data)); 4603 isp_prt(isp, ISP_LOGDEBUG0, 4604 "NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", 4605 ISP2400_NVRAM_HARDLOOPID(nvram_data), 4606 ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data), 4607 ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data), 4608 ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data)); 4609 4610 wwn = ISP2400_NVRAM_PORT_NAME(nvram_data); 4611 fcp->isp_wwpn_nvram = wwn; 4612 4613 wwn = ISP2400_NVRAM_NODE_NAME(nvram_data); 4614 if (wwn) { 4615 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) { 4616 wwn = 0; 4617 } 4618 } 4619 if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) { 4620 wwn = fcp->isp_wwpn_nvram; 4621 wwn &= ~((uint64_t) 0xfff << 48); 4622 } 4623 fcp->isp_wwnn_nvram = wwn; 4624 4625 if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) { 4626 DEFAULT_FRAMESIZE(isp) = 4627 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data); 4628 } 4629 if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { 4630 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data); 4631 } 4632 fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data); 4633 fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data); 4634 fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data); 4635 } 4636