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 *); 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 isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds); 583 584 /* 585 * If we don't have Multi-ID f/w loaded, we need to restrict channels to one. 586 * Only make this check for non-SCSI cards (I'm not sure firmware attributes 587 * work for them). 588 */ 589 if (isp->isp_nchan > 1) { 590 if (!ISP_CAP_MULTI_ID(isp)) { 591 isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, " 592 "only can enable 1 of %d channels", isp->isp_nchan); 593 isp->isp_nchan = 1; 594 } else if (!ISP_CAP_VP0(isp)) { 595 isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID " 596 "feature properly without VP0_Decoupling"); 597 isp->isp_nchan = 1; 598 } 599 } 600 601 /* 602 * Final DMA setup after we got isp_maxcmds. 603 */ 604 if (ISP_MBOXDMASETUP(isp) != 0) { 605 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); 606 return; 607 } 608 609 /* 610 * Setup interrupts. 611 */ 612 if (ISP_IRQSETUP(isp) != 0) { 613 isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ"); 614 return; 615 } 616 ISP_ENABLE_INTS(isp); 617 618 for (i = 0; i < isp->isp_nchan; i++) 619 isp_change_fw_state(isp, i, FW_CONFIG_WAIT); 620 621 isp->isp_state = ISP_RESETSTATE; 622 623 /* 624 * We get some default values established. As a side 625 * effect, NVRAM is read here (unless overriden by 626 * a configuration flag). 627 */ 628 if (do_load_defaults) { 629 for (i = 0; i < isp->isp_nchan; i++) 630 isp_setdfltfcparm(isp, i); 631 } 632 } 633 634 /* 635 * Clean firmware shutdown. 636 */ 637 static int 638 isp_stop(ispsoftc_t *isp) 639 { 640 mbreg_t mbs; 641 642 isp->isp_state = ISP_NILSTATE; 643 MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000); 644 mbs.param[1] = 0; 645 mbs.param[2] = 0; 646 mbs.param[3] = 0; 647 mbs.param[4] = 0; 648 mbs.param[5] = 0; 649 mbs.param[6] = 0; 650 mbs.param[7] = 0; 651 mbs.param[8] = 0; 652 isp_mboxcmd(isp, &mbs); 653 return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]); 654 } 655 656 /* 657 * Hardware shutdown. 658 */ 659 void 660 isp_shutdown(ispsoftc_t *isp) 661 { 662 663 if (isp->isp_state >= ISP_RESETSTATE) 664 isp_stop(isp); 665 ISP_DISABLE_INTS(isp); 666 ISP_WRITE(isp, BIU2400_ICR, 0); 667 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); 668 } 669 670 /* 671 * Initialize Parameters of Hardware to a known state. 672 * 673 * Locks are held before coming here. 674 */ 675 void 676 isp_init(ispsoftc_t *isp) 677 { 678 fcparam *fcp; 679 isp_icb_2400_t local, *icbp = &local; 680 mbreg_t mbs; 681 int chan; 682 int ownloopid = 0; 683 684 /* 685 * Check to see whether all channels have *some* kind of role 686 */ 687 for (chan = 0; chan < isp->isp_nchan; chan++) { 688 fcp = FCPARAM(isp, chan); 689 if (fcp->role != ISP_ROLE_NONE) { 690 break; 691 } 692 } 693 if (chan == isp->isp_nchan) { 694 isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan); 695 return; 696 } 697 698 isp->isp_state = ISP_INITSTATE; 699 700 /* 701 * Start with channel 0. 702 */ 703 fcp = FCPARAM(isp, 0); 704 705 /* 706 * Turn on LIP F8 async event (1) 707 */ 708 MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0); 709 mbs.param[1] = 1; 710 isp_mboxcmd(isp, &mbs); 711 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 712 return; 713 } 714 715 ISP_MEMZERO(icbp, sizeof (*icbp)); 716 icbp->icb_fwoptions1 = fcp->isp_fwoptions; 717 icbp->icb_fwoptions2 = fcp->isp_xfwoptions; 718 icbp->icb_fwoptions3 = fcp->isp_zfwoptions; 719 if (isp->isp_nchan > 1 && ISP_CAP_VP0(isp)) { 720 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE; 721 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE; 722 } else { 723 if (fcp->role & ISP_ROLE_TARGET) 724 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE; 725 else 726 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE; 727 if (fcp->role & ISP_ROLE_INITIATOR) 728 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE; 729 else 730 icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE; 731 } 732 733 icbp->icb_version = ICB_VERSION1; 734 icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp); 735 if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { 736 isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN); 737 icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN; 738 } 739 740 icbp->icb_execthrottle = DEFAULT_EXEC_THROTTLE(isp); 741 if (icbp->icb_execthrottle < 1 && !IS_26XX(isp)) { 742 isp_prt(isp, ISP_LOGERR, "bad execution throttle of %d- using %d", DEFAULT_EXEC_THROTTLE(isp), ICB_DFLT_THROTTLE); 743 icbp->icb_execthrottle = ICB_DFLT_THROTTLE; 744 } 745 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 icbp->icb_xchgcnt = isp->isp_maxcmds; 751 if ((icbp->icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE) == 0) 752 icbp->icb_xchgcnt >>= 1; 753 } 754 755 756 ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0; 757 icbp->icb_hardaddr = fcp->isp_loopid; 758 if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) { 759 icbp->icb_hardaddr = 0; 760 ownloopid = 0; 761 } 762 763 if (ownloopid) 764 icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS; 765 766 if (isp->isp_confopts & ISP_CFG_NOFCTAPE) { 767 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE; 768 } 769 if (isp->isp_confopts & ISP_CFG_FCTAPE) { 770 icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE; 771 } 772 773 for (chan = 0; chan < isp->isp_nchan; chan++) { 774 if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE) 775 FCPARAM(isp, chan)->fctape_enabled = 1; 776 else 777 FCPARAM(isp, chan)->fctape_enabled = 0; 778 } 779 780 switch (isp->isp_confopts & ISP_CFG_PORT_PREF) { 781 case ISP_CFG_LPORT_ONLY: 782 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; 783 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY; 784 break; 785 case ISP_CFG_NPORT_ONLY: 786 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; 787 icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY; 788 break; 789 case ISP_CFG_NPORT: 790 /* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */ 791 case ISP_CFG_LPORT: 792 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; 793 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP; 794 break; 795 default: 796 /* Let NVRAM settings define it if they are sane */ 797 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK) { 798 case ICB2400_OPT2_LOOP_ONLY: 799 case ICB2400_OPT2_PTP_ONLY: 800 case ICB2400_OPT2_LOOP_2_PTP: 801 break; 802 default: 803 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; 804 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP; 805 } 806 break; 807 } 808 809 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) { 810 case ICB2400_OPT2_ZIO: 811 case ICB2400_OPT2_ZIO1: 812 icbp->icb_idelaytimer = 0; 813 break; 814 case 0: 815 break; 816 default: 817 isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK); 818 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK; 819 break; 820 } 821 822 if (IS_26XX(isp)) { 823 /* Use handshake to reduce global lock congestion. */ 824 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR; 825 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA; 826 } 827 828 if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) { 829 icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24; 830 } 831 if (isp->isp_confopts & ISP_CFG_1GB) { 832 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 833 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB; 834 } else if (isp->isp_confopts & ISP_CFG_2GB) { 835 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 836 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB; 837 } else if (isp->isp_confopts & ISP_CFG_4GB) { 838 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 839 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB; 840 } else if (isp->isp_confopts & ISP_CFG_8GB) { 841 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 842 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB; 843 } else if (isp->isp_confopts & ISP_CFG_16GB) { 844 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 845 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB; 846 } else if (isp->isp_confopts & ISP_CFG_32GB) { 847 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 848 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB; 849 } else { 850 switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) { 851 case ICB2400_OPT3_RATE_4GB: 852 case ICB2400_OPT3_RATE_8GB: 853 case ICB2400_OPT3_RATE_16GB: 854 case ICB2400_OPT3_RATE_32GB: 855 case ICB2400_OPT3_RATE_AUTO: 856 break; 857 case ICB2400_OPT3_RATE_2GB: 858 if (isp->isp_type <= ISP_HA_FC_2500) 859 break; 860 /*FALLTHROUGH*/ 861 case ICB2400_OPT3_RATE_1GB: 862 if (isp->isp_type <= ISP_HA_FC_2400) 863 break; 864 /*FALLTHROUGH*/ 865 default: 866 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; 867 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO; 868 break; 869 } 870 } 871 if (ownloopid == 0) { 872 icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID; 873 } 874 icbp->icb_logintime = ICB_LOGIN_TOV; 875 876 if (fcp->isp_wwnn && fcp->isp_wwpn) { 877 icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS; 878 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn); 879 MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn); 880 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)), 881 ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn))); 882 } else if (fcp->isp_wwpn) { 883 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS; 884 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn); 885 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))); 886 } else { 887 isp_prt(isp, ISP_LOGERR, "No valid WWNs to use"); 888 return; 889 } 890 icbp->icb_retry_count = fcp->isp_retry_count; 891 892 icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp); 893 if (icbp->icb_rqstqlen < 8) { 894 isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen); 895 return; 896 } 897 icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp); 898 if (icbp->icb_rsltqlen < 8) { 899 isp_prt(isp, ISP_LOGERR, "bad result queue length %d", 900 icbp->icb_rsltqlen); 901 return; 902 } 903 icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma); 904 icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma); 905 icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma); 906 icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma); 907 908 icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma); 909 icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma); 910 icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma); 911 icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma); 912 913 #ifdef ISP_TARGET_MODE 914 /* unconditionally set up the ATIO queue if we support target mode */ 915 icbp->icb_atioqlen = RESULT_QUEUE_LEN(isp); 916 if (icbp->icb_atioqlen < 8) { 917 isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen); 918 return; 919 } 920 icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma); 921 icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma); 922 icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma); 923 icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma); 924 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma), 925 DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma)); 926 #endif 927 928 if (ISP_CAP_MSIX(isp) && isp->isp_nirq >= 2) { 929 icbp->icb_msixresp = 1; 930 if (IS_26XX(isp) && isp->isp_nirq >= 3) 931 icbp->icb_msixatio = 2; 932 } 933 934 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); 935 936 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), 937 DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma), 938 DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma)); 939 940 if (FC_SCRATCH_ACQUIRE(isp, 0)) { 941 isp_prt(isp, ISP_LOGERR, sacq); 942 return; 943 } 944 ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN); 945 isp_put_icb_2400(isp, icbp, fcp->isp_scratch); 946 if (isp->isp_dblev & ISP_LOGDEBUG1) { 947 isp_print_bytes(isp, "isp_init", 948 sizeof (*icbp), fcp->isp_scratch); 949 } 950 951 /* 952 * Now fill in information about any additional channels 953 */ 954 if (isp->isp_nchan > 1) { 955 isp_icb_2400_vpinfo_t vpinfo, *vdst; 956 vp_port_info_t pi, *pdst; 957 size_t amt = 0; 958 uint8_t *off; 959 960 vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA; 961 if (ISP_CAP_VP0(isp)) { 962 vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE; 963 vpinfo.vp_count = isp->isp_nchan; 964 chan = 0; 965 } else { 966 vpinfo.vp_count = isp->isp_nchan - 1; 967 chan = 1; 968 } 969 off = fcp->isp_scratch; 970 off += ICB2400_VPINFO_OFF; 971 vdst = (isp_icb_2400_vpinfo_t *) off; 972 isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst); 973 amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t); 974 for (; chan < isp->isp_nchan; chan++) { 975 fcparam *fcp2; 976 977 ISP_MEMZERO(&pi, sizeof (pi)); 978 fcp2 = FCPARAM(isp, chan); 979 if (fcp2->role != ISP_ROLE_NONE) { 980 pi.vp_port_options = ICB2400_VPOPT_ENABLED | 981 ICB2400_VPOPT_ENA_SNSLOGIN; 982 if (fcp2->role & ISP_ROLE_INITIATOR) 983 pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE; 984 if ((fcp2->role & ISP_ROLE_TARGET) == 0) 985 pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE; 986 if (fcp2->isp_loopid < LOCAL_LOOP_LIM) { 987 pi.vp_port_loopid = fcp2->isp_loopid; 988 if (isp->isp_confopts & ISP_CFG_OWNLOOPID) 989 pi.vp_port_options |= ICB2400_VPOPT_HARD_ADDRESS; 990 } 991 992 } 993 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn); 994 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn); 995 off = fcp->isp_scratch; 996 if (ISP_CAP_VP0(isp)) 997 off += ICB2400_VPINFO_PORT_OFF(chan); 998 else 999 off += ICB2400_VPINFO_PORT_OFF(chan - 1); 1000 pdst = (vp_port_info_t *) off; 1001 isp_put_vp_port_info(isp, &pi, pdst); 1002 amt += ICB2400_VPOPT_WRITE_SIZE; 1003 } 1004 if (isp->isp_dblev & ISP_LOGDEBUG1) { 1005 isp_print_bytes(isp, "isp_init", 1006 amt - ICB2400_VPINFO_OFF, 1007 (char *)fcp->isp_scratch + ICB2400_VPINFO_OFF); 1008 } 1009 } 1010 1011 /* 1012 * Init the firmware 1013 */ 1014 MBSINIT(&mbs, 0, MBLOGALL, 30000000); 1015 if (isp->isp_nchan > 1) { 1016 mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID; 1017 } else { 1018 mbs.param[0] = MBOX_INIT_FIRMWARE; 1019 } 1020 mbs.param[1] = 0; 1021 mbs.param[2] = DMA_WD1(fcp->isp_scdma); 1022 mbs.param[3] = DMA_WD0(fcp->isp_scdma); 1023 mbs.param[6] = DMA_WD3(fcp->isp_scdma); 1024 mbs.param[7] = DMA_WD2(fcp->isp_scdma); 1025 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)); 1026 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp), 0); 1027 isp_mboxcmd(isp, &mbs); 1028 FC_SCRATCH_RELEASE(isp, 0); 1029 1030 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 1031 return; 1032 } 1033 isp->isp_reqidx = 0; 1034 isp->isp_reqodx = 0; 1035 isp->isp_residx = 0; 1036 isp->isp_resodx = 0; 1037 isp->isp_atioodx = 0; 1038 1039 /* 1040 * Whatever happens, we're now committed to being here. 1041 */ 1042 isp->isp_state = ISP_RUNSTATE; 1043 } 1044 1045 static int 1046 isp_fc_enable_vp(ispsoftc_t *isp, int chan) 1047 { 1048 fcparam *fcp = FCPARAM(isp, chan); 1049 vp_modify_t vp; 1050 void *reqp; 1051 uint8_t resp[QENTRY_LEN]; 1052 1053 /* Build a VP MODIFY command in memory */ 1054 ISP_MEMZERO(&vp, sizeof(vp)); 1055 vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY; 1056 vp.vp_mod_hdr.rqs_entry_count = 1; 1057 vp.vp_mod_cnt = 1; 1058 vp.vp_mod_idx0 = chan; 1059 vp.vp_mod_cmd = VP_MODIFY_ENA; 1060 vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED | 1061 ICB2400_VPOPT_ENA_SNSLOGIN; 1062 if (fcp->role & ISP_ROLE_INITIATOR) 1063 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE; 1064 if ((fcp->role & ISP_ROLE_TARGET) == 0) 1065 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE; 1066 if (fcp->isp_loopid < LOCAL_LOOP_LIM) { 1067 vp.vp_mod_ports[0].loopid = fcp->isp_loopid; 1068 if (isp->isp_confopts & ISP_CFG_OWNLOOPID) 1069 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS; 1070 } 1071 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn); 1072 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn); 1073 1074 /* Prepare space for response in memory */ 1075 memset(resp, 0xff, sizeof(resp)); 1076 vp.vp_mod_hdl = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); 1077 if (vp.vp_mod_hdl == 0) { 1078 isp_prt(isp, ISP_LOGERR, 1079 "%s: VP_MODIFY of Chan %d out of handles", __func__, chan); 1080 return (EIO); 1081 } 1082 1083 /* Send request and wait for response. */ 1084 reqp = isp_getrqentry(isp); 1085 if (reqp == NULL) { 1086 isp_prt(isp, ISP_LOGERR, 1087 "%s: VP_MODIFY of Chan %d out of rqent", __func__, chan); 1088 isp_destroy_handle(isp, vp.vp_mod_hdl); 1089 return (EIO); 1090 } 1091 isp_put_vp_modify(isp, &vp, (vp_modify_t *)reqp); 1092 if (isp->isp_dblev & ISP_LOGDEBUG1) 1093 isp_print_bytes(isp, "IOCB VP_MODIFY", QENTRY_LEN, reqp); 1094 ISP_SYNC_REQUEST(isp); 1095 if (msleep(resp, &isp->isp_lock, 0, "VP_MODIFY", 5*hz) == EWOULDBLOCK) { 1096 isp_prt(isp, ISP_LOGERR, 1097 "%s: VP_MODIFY of Chan %d timed out", __func__, chan); 1098 isp_destroy_handle(isp, vp.vp_mod_hdl); 1099 return (EIO); 1100 } 1101 if (isp->isp_dblev & ISP_LOGDEBUG1) 1102 isp_print_bytes(isp, "IOCB VP_MODIFY response", QENTRY_LEN, resp); 1103 isp_get_vp_modify(isp, (vp_modify_t *)resp, &vp); 1104 1105 if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) { 1106 isp_prt(isp, ISP_LOGERR, 1107 "%s: VP_MODIFY of Chan %d failed with flags %x status %d", 1108 __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status); 1109 return (EIO); 1110 } 1111 return (0); 1112 } 1113 1114 static int 1115 isp_fc_disable_vp(ispsoftc_t *isp, int chan) 1116 { 1117 vp_ctrl_info_t vp; 1118 void *reqp; 1119 uint8_t resp[QENTRY_LEN]; 1120 1121 /* Build a VP CTRL command in memory */ 1122 ISP_MEMZERO(&vp, sizeof(vp)); 1123 vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL; 1124 vp.vp_ctrl_hdr.rqs_entry_count = 1; 1125 if (ISP_CAP_VP0(isp)) { 1126 vp.vp_ctrl_status = 1; 1127 } else { 1128 vp.vp_ctrl_status = 0; 1129 chan--; /* VP0 can not be controlled in this case. */ 1130 } 1131 vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL; 1132 vp.vp_ctrl_vp_count = 1; 1133 vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16); 1134 1135 /* Prepare space for response in memory */ 1136 memset(resp, 0xff, sizeof(resp)); 1137 vp.vp_ctrl_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); 1138 if (vp.vp_ctrl_handle == 0) { 1139 isp_prt(isp, ISP_LOGERR, 1140 "%s: VP_CTRL of Chan %d out of handles", __func__, chan); 1141 return (EIO); 1142 } 1143 1144 /* Send request and wait for response. */ 1145 reqp = isp_getrqentry(isp); 1146 if (reqp == NULL) { 1147 isp_prt(isp, ISP_LOGERR, 1148 "%s: VP_CTRL of Chan %d out of rqent", __func__, chan); 1149 isp_destroy_handle(isp, vp.vp_ctrl_handle); 1150 return (EIO); 1151 } 1152 isp_put_vp_ctrl_info(isp, &vp, (vp_ctrl_info_t *)reqp); 1153 if (isp->isp_dblev & ISP_LOGDEBUG1) 1154 isp_print_bytes(isp, "IOCB VP_CTRL", QENTRY_LEN, reqp); 1155 ISP_SYNC_REQUEST(isp); 1156 if (msleep(resp, &isp->isp_lock, 0, "VP_CTRL", 5*hz) == EWOULDBLOCK) { 1157 isp_prt(isp, ISP_LOGERR, 1158 "%s: VP_CTRL of Chan %d timed out", __func__, chan); 1159 isp_destroy_handle(isp, vp.vp_ctrl_handle); 1160 return (EIO); 1161 } 1162 if (isp->isp_dblev & ISP_LOGDEBUG1) 1163 isp_print_bytes(isp, "IOCB VP_CTRL response", QENTRY_LEN, resp); 1164 isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)resp, &vp); 1165 1166 if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) { 1167 isp_prt(isp, ISP_LOGERR, 1168 "%s: VP_CTRL of Chan %d failed with flags %x status %d %d", 1169 __func__, chan, vp.vp_ctrl_hdr.rqs_flags, 1170 vp.vp_ctrl_status, vp.vp_ctrl_index_fail); 1171 return (EIO); 1172 } 1173 return (0); 1174 } 1175 1176 static int 1177 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role) 1178 { 1179 fcparam *fcp = FCPARAM(isp, chan); 1180 int i, was, res = 0; 1181 1182 if (chan >= isp->isp_nchan) { 1183 isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan); 1184 return (ENXIO); 1185 } 1186 if (fcp->role == new_role) 1187 return (0); 1188 for (was = 0, i = 0; i < isp->isp_nchan; i++) { 1189 if (FCPARAM(isp, i)->role != ISP_ROLE_NONE) 1190 was++; 1191 } 1192 if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) { 1193 fcp->role = new_role; 1194 return (isp_reinit(isp, 0)); 1195 } 1196 if (fcp->role != ISP_ROLE_NONE) { 1197 res = isp_fc_disable_vp(isp, chan); 1198 isp_clear_portdb(isp, chan); 1199 } 1200 fcp->role = new_role; 1201 if (fcp->role != ISP_ROLE_NONE) 1202 res = isp_fc_enable_vp(isp, chan); 1203 return (res); 1204 } 1205 1206 static void 1207 isp_clear_portdb(ispsoftc_t *isp, int chan) 1208 { 1209 fcparam *fcp = FCPARAM(isp, chan); 1210 fcportdb_t *lp; 1211 int i; 1212 1213 for (i = 0; i < MAX_FC_TARG; i++) { 1214 lp = &fcp->portdb[i]; 1215 switch (lp->state) { 1216 case FC_PORTDB_STATE_DEAD: 1217 case FC_PORTDB_STATE_CHANGED: 1218 case FC_PORTDB_STATE_VALID: 1219 lp->state = FC_PORTDB_STATE_NIL; 1220 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); 1221 break; 1222 case FC_PORTDB_STATE_NIL: 1223 case FC_PORTDB_STATE_NEW: 1224 lp->state = FC_PORTDB_STATE_NIL; 1225 break; 1226 case FC_PORTDB_STATE_ZOMBIE: 1227 break; 1228 default: 1229 panic("Don't know how to clear state %d\n", lp->state); 1230 } 1231 } 1232 } 1233 1234 static void 1235 isp_mark_portdb(ispsoftc_t *isp, int chan) 1236 { 1237 fcparam *fcp = FCPARAM(isp, chan); 1238 fcportdb_t *lp; 1239 int i; 1240 1241 for (i = 0; i < MAX_FC_TARG; i++) { 1242 lp = &fcp->portdb[i]; 1243 if (lp->state == FC_PORTDB_STATE_NIL) 1244 continue; 1245 if (lp->portid >= DOMAIN_CONTROLLER_BASE && 1246 lp->portid <= DOMAIN_CONTROLLER_END) 1247 continue; 1248 fcp->portdb[i].probational = 1; 1249 } 1250 } 1251 1252 /* 1253 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards 1254 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards. 1255 */ 1256 static int 1257 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags) 1258 { 1259 isp_plogx_t pl; 1260 void *reqp; 1261 uint8_t resp[QENTRY_LEN]; 1262 uint32_t sst, parm1; 1263 int rval, lev; 1264 const char *msg; 1265 char buf[64]; 1266 1267 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x", 1268 chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ? 1269 "Login":"Logout", portid, handle); 1270 1271 ISP_MEMZERO(&pl, sizeof(pl)); 1272 pl.plogx_header.rqs_entry_count = 1; 1273 pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN; 1274 pl.plogx_nphdl = handle; 1275 pl.plogx_vphdl = chan; 1276 pl.plogx_portlo = portid; 1277 pl.plogx_rspsz_porthi = (portid >> 16) & 0xff; 1278 pl.plogx_flags = flags; 1279 1280 /* Prepare space for response in memory */ 1281 memset(resp, 0xff, sizeof(resp)); 1282 pl.plogx_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); 1283 if (pl.plogx_handle == 0) { 1284 isp_prt(isp, ISP_LOGERR, 1285 "%s: PLOGX of Chan %d out of handles", __func__, chan); 1286 return (-1); 1287 } 1288 1289 /* Send request and wait for response. */ 1290 reqp = isp_getrqentry(isp); 1291 if (reqp == NULL) { 1292 isp_prt(isp, ISP_LOGERR, 1293 "%s: PLOGX of Chan %d out of rqent", __func__, chan); 1294 isp_destroy_handle(isp, pl.plogx_handle); 1295 return (-1); 1296 } 1297 isp_put_plogx(isp, &pl, (isp_plogx_t *)reqp); 1298 if (isp->isp_dblev & ISP_LOGDEBUG1) 1299 isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, reqp); 1300 FCPARAM(isp, chan)->isp_login_hdl = handle; 1301 ISP_SYNC_REQUEST(isp); 1302 if (msleep(resp, &isp->isp_lock, 0, "PLOGX", 3 * ICB_LOGIN_TOV * hz) 1303 == EWOULDBLOCK) { 1304 isp_prt(isp, ISP_LOGERR, 1305 "%s: PLOGX of Chan %d timed out", __func__, chan); 1306 isp_destroy_handle(isp, pl.plogx_handle); 1307 return (-1); 1308 } 1309 FCPARAM(isp, chan)->isp_login_hdl = NIL_HANDLE; 1310 if (isp->isp_dblev & ISP_LOGDEBUG1) 1311 isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, resp); 1312 isp_get_plogx(isp, (isp_plogx_t *)resp, &pl); 1313 1314 if (pl.plogx_status == PLOGX_STATUS_OK) { 1315 return (0); 1316 } else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) { 1317 isp_prt(isp, ISP_LOGWARN, 1318 "status 0x%x on port login IOCB channel %d", 1319 pl.plogx_status, chan); 1320 return (-1); 1321 } 1322 1323 sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16); 1324 parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16); 1325 1326 rval = -1; 1327 lev = ISP_LOGERR; 1328 msg = NULL; 1329 1330 switch (sst) { 1331 case PLOGX_IOCBERR_NOLINK: 1332 msg = "no link"; 1333 break; 1334 case PLOGX_IOCBERR_NOIOCB: 1335 msg = "no IOCB buffer"; 1336 break; 1337 case PLOGX_IOCBERR_NOXGHG: 1338 msg = "no Exchange Control Block"; 1339 break; 1340 case PLOGX_IOCBERR_FAILED: 1341 ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff); 1342 msg = buf; 1343 break; 1344 case PLOGX_IOCBERR_NOFABRIC: 1345 msg = "no fabric"; 1346 break; 1347 case PLOGX_IOCBERR_NOTREADY: 1348 msg = "firmware not ready"; 1349 break; 1350 case PLOGX_IOCBERR_NOLOGIN: 1351 ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1); 1352 msg = buf; 1353 rval = MBOX_NOT_LOGGED_IN; 1354 break; 1355 case PLOGX_IOCBERR_REJECT: 1356 ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1); 1357 msg = buf; 1358 break; 1359 case PLOGX_IOCBERR_NOPCB: 1360 msg = "no PCB allocated"; 1361 break; 1362 case PLOGX_IOCBERR_EINVAL: 1363 ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1); 1364 msg = buf; 1365 break; 1366 case PLOGX_IOCBERR_PORTUSED: 1367 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1; 1368 ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1); 1369 msg = buf; 1370 rval = MBOX_PORT_ID_USED | (parm1 << 16); 1371 break; 1372 case PLOGX_IOCBERR_HNDLUSED: 1373 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1; 1374 ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1); 1375 msg = buf; 1376 rval = MBOX_LOOP_ID_USED; 1377 break; 1378 case PLOGX_IOCBERR_NOHANDLE: 1379 msg = "no handle allocated"; 1380 break; 1381 case PLOGX_IOCBERR_NOFLOGI: 1382 msg = "no FLOGI_ACC"; 1383 break; 1384 default: 1385 ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags); 1386 msg = buf; 1387 break; 1388 } 1389 if (msg) { 1390 isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s", 1391 chan, portid, handle, msg); 1392 } 1393 return (rval); 1394 } 1395 1396 static int 1397 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb) 1398 { 1399 mbreg_t mbs; 1400 union { 1401 isp_pdb_24xx_t bill; 1402 } un; 1403 1404 MBSINIT(&mbs, MBOX_GET_PORT_DB, 1405 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000); 1406 mbs.ibits = (1 << 9)|(1 << 10); 1407 mbs.param[1] = id; 1408 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma); 1409 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma); 1410 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma); 1411 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma); 1412 mbs.param[9] = chan; 1413 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, sizeof(un), chan); 1414 1415 isp_mboxcmd(isp, &mbs); 1416 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) 1417 return (mbs.param[0] | (mbs.param[1] << 16)); 1418 1419 MEMORYBARRIER(isp, SYNC_IFORCPU, 0, sizeof(un), chan); 1420 isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill); 1421 pdb->handle = un.bill.pdb_handle; 1422 pdb->prli_word0 = un.bill.pdb_prli_svc0; 1423 pdb->prli_word3 = un.bill.pdb_prli_svc3; 1424 pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits); 1425 ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8); 1426 ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8); 1427 isp_prt(isp, ISP_LOGDEBUG0, 1428 "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x", 1429 chan, id, pdb->portid, un.bill.pdb_flags, 1430 un.bill.pdb_curstate, un.bill.pdb_laststate); 1431 1432 if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) { 1433 mbs.param[0] = MBOX_NOT_LOGGED_IN; 1434 return (mbs.param[0]); 1435 } 1436 return (0); 1437 } 1438 1439 static int 1440 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop) 1441 { 1442 fcparam *fcp = FCPARAM(isp, chan); 1443 mbreg_t mbs; 1444 isp_pnhle_24xx_t el4, *elp4; 1445 int i, j; 1446 uint32_t p; 1447 1448 MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL, 250000); 1449 mbs.param[2] = DMA_WD1(fcp->isp_scdma); 1450 mbs.param[3] = DMA_WD0(fcp->isp_scdma); 1451 mbs.param[6] = DMA_WD3(fcp->isp_scdma); 1452 mbs.param[7] = DMA_WD2(fcp->isp_scdma); 1453 mbs.param[8] = ISP_FC_SCRLEN; 1454 mbs.param[9] = chan; 1455 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 1456 isp_prt(isp, ISP_LOGERR, sacq); 1457 return (-1); 1458 } 1459 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan); 1460 isp_mboxcmd(isp, &mbs); 1461 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 1462 FC_SCRATCH_RELEASE(isp, chan); 1463 return (mbs.param[0] | (mbs.param[1] << 16)); 1464 } 1465 MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan); 1466 elp4 = fcp->isp_scratch; 1467 for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) { 1468 isp_get_pnhle_24xx(isp, &elp4[i], &el4); 1469 p = el4.pnhle_port_id_lo | (el4.pnhle_port_id_hi << 16); 1470 if (loop && (p >> 8) != (fcp->isp_portid >> 8)) 1471 continue; 1472 handles[j++] = el4.pnhle_handle; 1473 } 1474 *num = j; 1475 FC_SCRATCH_RELEASE(isp, chan); 1476 return (0); 1477 } 1478 1479 static void 1480 isp_dump_chip_portdb(ispsoftc_t *isp, int chan) 1481 { 1482 isp_pdb_t pdb; 1483 uint16_t nphdl; 1484 1485 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan); 1486 for (nphdl = 0; nphdl != NPH_MAX_2K; nphdl++) { 1487 if (isp_getpdb(isp, chan, nphdl, &pdb)) { 1488 continue; 1489 } 1490 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x " 1491 "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x", 1492 chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1], 1493 pdb.portname[2], pdb.portname[3], pdb.portname[4], 1494 pdb.portname[5], pdb.portname[6], pdb.portname[7]); 1495 } 1496 } 1497 1498 static uint64_t 1499 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename) 1500 { 1501 uint64_t wwn = INI_NONE; 1502 mbreg_t mbs; 1503 1504 MBSINIT(&mbs, MBOX_GET_PORT_NAME, 1505 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000); 1506 mbs.param[1] = nphdl; 1507 if (nodename) 1508 mbs.param[10] = 1; 1509 mbs.param[9] = chan; 1510 isp_mboxcmd(isp, &mbs); 1511 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 1512 return (wwn); 1513 } 1514 wwn = (((uint64_t)(mbs.param[2] >> 8)) << 56) | 1515 (((uint64_t)(mbs.param[2] & 0xff))<< 48) | 1516 (((uint64_t)(mbs.param[3] >> 8)) << 40) | 1517 (((uint64_t)(mbs.param[3] & 0xff))<< 32) | 1518 (((uint64_t)(mbs.param[6] >> 8)) << 24) | 1519 (((uint64_t)(mbs.param[6] & 0xff))<< 16) | 1520 (((uint64_t)(mbs.param[7] >> 8)) << 8) | 1521 (((uint64_t)(mbs.param[7] & 0xff))); 1522 return (wwn); 1523 } 1524 1525 /* 1526 * Make sure we have good FC link. 1527 */ 1528 1529 static int 1530 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) 1531 { 1532 mbreg_t mbs; 1533 int i, r, topo; 1534 fcparam *fcp; 1535 isp_pdb_t pdb; 1536 NANOTIME_T hra, hrb; 1537 1538 fcp = FCPARAM(isp, chan); 1539 1540 if (fcp->isp_loopstate < LOOP_HAVE_LINK) 1541 return (-1); 1542 if (fcp->isp_loopstate >= LOOP_LTEST_DONE) 1543 return (0); 1544 1545 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan); 1546 1547 /* 1548 * Wait up to N microseconds for F/W to go to a ready state. 1549 */ 1550 GET_NANOTIME(&hra); 1551 while (1) { 1552 isp_change_fw_state(isp, chan, isp_fw_state(isp, chan)); 1553 if (fcp->isp_fwstate == FW_READY) { 1554 break; 1555 } 1556 if (fcp->isp_loopstate < LOOP_HAVE_LINK) 1557 goto abort; 1558 GET_NANOTIME(&hrb); 1559 if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay)) 1560 break; 1561 ISP_SLEEP(isp, 1000); 1562 } 1563 if (fcp->isp_fwstate != FW_READY) { 1564 isp_prt(isp, ISP_LOG_SANCFG, 1565 "Chan %d Firmware is not ready (%s)", 1566 chan, isp_fc_fw_statename(fcp->isp_fwstate)); 1567 return (-1); 1568 } 1569 1570 /* 1571 * Get our Loop ID and Port ID. 1572 */ 1573 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0); 1574 mbs.param[9] = chan; 1575 isp_mboxcmd(isp, &mbs); 1576 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 1577 return (-1); 1578 } 1579 1580 topo = (int) mbs.param[6]; 1581 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) 1582 topo = TOPO_PTP_STUB; 1583 fcp->isp_topo = topo; 1584 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16); 1585 1586 if (!TOPO_IS_FABRIC(fcp->isp_topo)) { 1587 fcp->isp_loopid = mbs.param[1] & 0xff; 1588 } else if (fcp->isp_topo != TOPO_F_PORT) { 1589 uint8_t alpa = fcp->isp_portid; 1590 1591 for (i = 0; alpa_map[i]; i++) { 1592 if (alpa_map[i] == alpa) 1593 break; 1594 } 1595 if (alpa_map[i]) 1596 fcp->isp_loopid = i; 1597 } 1598 1599 #if 0 1600 fcp->isp_loopstate = LOOP_HAVE_ADDR; 1601 #endif 1602 fcp->isp_loopstate = LOOP_TESTING_LINK; 1603 1604 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { 1605 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb); 1606 if (r != 0 || pdb.portid == 0) { 1607 isp_prt(isp, ISP_LOGWARN, 1608 "fabric topology, but cannot get info about fabric controller (0x%x)", r); 1609 fcp->isp_topo = TOPO_PTP_STUB; 1610 goto not_on_fabric; 1611 } 1612 1613 fcp->isp_fabric_params = mbs.param[7]; 1614 fcp->isp_sns_hdl = NPH_SNS_ID; 1615 r = isp_register_fc4_type(isp, chan); 1616 if (fcp->isp_loopstate < LOOP_TESTING_LINK) 1617 goto abort; 1618 if (r != 0) 1619 goto not_on_fabric; 1620 r = isp_register_fc4_features_24xx(isp, chan); 1621 if (fcp->isp_loopstate < LOOP_TESTING_LINK) 1622 goto abort; 1623 if (r != 0) 1624 goto not_on_fabric; 1625 r = isp_register_port_name_24xx(isp, chan); 1626 if (fcp->isp_loopstate < LOOP_TESTING_LINK) 1627 goto abort; 1628 if (r != 0) 1629 goto not_on_fabric; 1630 isp_register_node_name_24xx(isp, chan); 1631 if (fcp->isp_loopstate < LOOP_TESTING_LINK) 1632 goto abort; 1633 } 1634 1635 not_on_fabric: 1636 /* Get link speed. */ 1637 fcp->isp_gbspeed = 1; 1638 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000); 1639 mbs.param[1] = MBGSD_GET_RATE; 1640 /* mbs.param[2] undefined if we're just getting rate */ 1641 isp_mboxcmd(isp, &mbs); 1642 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { 1643 if (mbs.param[1] == MBGSD_10GB) 1644 fcp->isp_gbspeed = 10; 1645 else if (mbs.param[1] == MBGSD_32GB) 1646 fcp->isp_gbspeed = 32; 1647 else if (mbs.param[1] == MBGSD_16GB) 1648 fcp->isp_gbspeed = 16; 1649 else if (mbs.param[1] == MBGSD_8GB) 1650 fcp->isp_gbspeed = 8; 1651 else if (mbs.param[1] == MBGSD_4GB) 1652 fcp->isp_gbspeed = 4; 1653 else if (mbs.param[1] == MBGSD_2GB) 1654 fcp->isp_gbspeed = 2; 1655 else if (mbs.param[1] == MBGSD_1GB) 1656 fcp->isp_gbspeed = 1; 1657 } 1658 1659 if (fcp->isp_loopstate < LOOP_TESTING_LINK) { 1660 abort: 1661 isp_prt(isp, ISP_LOG_SANCFG, 1662 "Chan %d FC link test aborted", chan); 1663 return (1); 1664 } 1665 fcp->isp_loopstate = LOOP_LTEST_DONE; 1666 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, 1667 "Chan %d WWPN %016jx WWNN %016jx", 1668 chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn); 1669 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, 1670 "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x", 1671 chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid, 1672 fcp->isp_loopid); 1673 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan); 1674 return (0); 1675 } 1676 1677 /* 1678 * Complete the synchronization of our Port Database. 1679 * 1680 * At this point, we've scanned the local loop (if any) and the fabric 1681 * and performed fabric logins on all new devices. 1682 * 1683 * Our task here is to go through our port database removing any entities 1684 * that are still marked probational (issuing PLOGO for ones which we had 1685 * PLOGI'd into) or are dead, and notifying upper layers about new/changed 1686 * devices. 1687 */ 1688 static int 1689 isp_pdb_sync(ispsoftc_t *isp, int chan) 1690 { 1691 fcparam *fcp = FCPARAM(isp, chan); 1692 fcportdb_t *lp; 1693 uint16_t dbidx; 1694 1695 if (fcp->isp_loopstate < LOOP_FSCAN_DONE) 1696 return (-1); 1697 if (fcp->isp_loopstate >= LOOP_READY) 1698 return (0); 1699 1700 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan); 1701 1702 fcp->isp_loopstate = LOOP_SYNCING_PDB; 1703 1704 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { 1705 lp = &fcp->portdb[dbidx]; 1706 1707 if (lp->state == FC_PORTDB_STATE_NIL) 1708 continue; 1709 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE) 1710 lp->state = FC_PORTDB_STATE_DEAD; 1711 switch (lp->state) { 1712 case FC_PORTDB_STATE_DEAD: 1713 lp->state = FC_PORTDB_STATE_NIL; 1714 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); 1715 if ((lp->portid & 0xffff00) != 0) { 1716 (void) isp_plogx(isp, chan, lp->handle, 1717 lp->portid, 1718 PLOGX_FLG_CMD_LOGO | 1719 PLOGX_FLG_IMPLICIT | 1720 PLOGX_FLG_FREE_NPHDL); 1721 } 1722 /* 1723 * Note that we might come out of this with our state 1724 * set to FC_PORTDB_STATE_ZOMBIE. 1725 */ 1726 break; 1727 case FC_PORTDB_STATE_NEW: 1728 lp->state = FC_PORTDB_STATE_VALID; 1729 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp); 1730 break; 1731 case FC_PORTDB_STATE_CHANGED: 1732 lp->state = FC_PORTDB_STATE_VALID; 1733 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp); 1734 lp->portid = lp->new_portid; 1735 lp->prli_word0 = lp->new_prli_word0; 1736 lp->prli_word3 = lp->new_prli_word3; 1737 break; 1738 case FC_PORTDB_STATE_VALID: 1739 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp); 1740 break; 1741 case FC_PORTDB_STATE_ZOMBIE: 1742 break; 1743 default: 1744 isp_prt(isp, ISP_LOGWARN, 1745 "isp_pdb_sync: state %d for idx %d", 1746 lp->state, dbidx); 1747 isp_dump_portdb(isp, chan); 1748 } 1749 } 1750 1751 if (fcp->isp_loopstate < LOOP_SYNCING_PDB) { 1752 isp_prt(isp, ISP_LOG_SANCFG, 1753 "Chan %d FC PDB sync aborted", chan); 1754 return (1); 1755 } 1756 1757 fcp->isp_loopstate = LOOP_READY; 1758 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan); 1759 return (0); 1760 } 1761 1762 static void 1763 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb) 1764 { 1765 fcportdb_t *lp; 1766 uint64_t wwnn, wwpn; 1767 1768 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename); 1769 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname); 1770 1771 /* Search port database for the same WWPN. */ 1772 if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) { 1773 if (!lp->probational) { 1774 isp_prt(isp, ISP_LOGERR, 1775 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)", 1776 chan, lp->portid, lp->handle, 1777 FC_PORTDB_TGT(isp, chan, lp), lp->state); 1778 isp_dump_portdb(isp, chan); 1779 return; 1780 } 1781 lp->probational = 0; 1782 lp->node_wwn = wwnn; 1783 1784 /* Old device, nothing new. */ 1785 if (lp->portid == pdb->portid && 1786 lp->handle == pdb->handle && 1787 lp->prli_word3 == pdb->prli_word3 && 1788 ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) == 1789 (lp->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR))) { 1790 if (lp->state != FC_PORTDB_STATE_NEW) 1791 lp->state = FC_PORTDB_STATE_VALID; 1792 isp_prt(isp, ISP_LOG_SANCFG, 1793 "Chan %d Port 0x%06x@0x%04x is valid", 1794 chan, pdb->portid, pdb->handle); 1795 return; 1796 } 1797 1798 /* Something has changed. */ 1799 lp->state = FC_PORTDB_STATE_CHANGED; 1800 lp->handle = pdb->handle; 1801 lp->new_portid = pdb->portid; 1802 lp->new_prli_word0 = pdb->prli_word0; 1803 lp->new_prli_word3 = pdb->prli_word3; 1804 isp_prt(isp, ISP_LOG_SANCFG, 1805 "Chan %d Port 0x%06x@0x%04x is changed", 1806 chan, pdb->portid, pdb->handle); 1807 return; 1808 } 1809 1810 /* It seems like a new port. Find an empty slot for it. */ 1811 if (!isp_find_pdb_empty(isp, chan, &lp)) { 1812 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan); 1813 return; 1814 } 1815 1816 ISP_MEMZERO(lp, sizeof (fcportdb_t)); 1817 lp->probational = 0; 1818 lp->state = FC_PORTDB_STATE_NEW; 1819 lp->portid = lp->new_portid = pdb->portid; 1820 lp->prli_word0 = lp->new_prli_word0 = pdb->prli_word0; 1821 lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3; 1822 lp->handle = pdb->handle; 1823 lp->port_wwn = wwpn; 1824 lp->node_wwn = wwnn; 1825 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new", 1826 chan, pdb->portid, pdb->handle); 1827 } 1828 1829 /* 1830 * Scan local loop for devices. 1831 */ 1832 static int 1833 isp_scan_loop(ispsoftc_t *isp, int chan) 1834 { 1835 fcparam *fcp = FCPARAM(isp, chan); 1836 int idx, lim, r; 1837 isp_pdb_t pdb; 1838 uint16_t *handles; 1839 uint16_t handle; 1840 1841 if (fcp->isp_loopstate < LOOP_LTEST_DONE) 1842 return (-1); 1843 if (fcp->isp_loopstate >= LOOP_LSCAN_DONE) 1844 return (0); 1845 1846 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan); 1847 fcp->isp_loopstate = LOOP_SCANNING_LOOP; 1848 if (TOPO_IS_FABRIC(fcp->isp_topo)) { 1849 isp_prt(isp, ISP_LOG_SANCFG, 1850 "Chan %d FC loop scan done (no loop)", chan); 1851 fcp->isp_loopstate = LOOP_LSCAN_DONE; 1852 return (0); 1853 } 1854 1855 handles = (uint16_t *)fcp->isp_scanscratch; 1856 lim = ISP_FC_SCRLEN / 2; 1857 r = isp_gethandles(isp, chan, handles, &lim, 1); 1858 if (r != 0) { 1859 isp_prt(isp, ISP_LOG_SANCFG, 1860 "Chan %d Getting list of handles failed with %x", chan, r); 1861 isp_prt(isp, ISP_LOG_SANCFG, 1862 "Chan %d FC loop scan done (bad)", chan); 1863 return (-1); 1864 } 1865 1866 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles", 1867 chan, lim); 1868 1869 /* 1870 * Run through the list and get the port database info for each one. 1871 */ 1872 isp_mark_portdb(isp, chan); 1873 for (idx = 0; idx < lim; idx++) { 1874 handle = handles[idx]; 1875 1876 /* 1877 * Don't scan "special" ids. 1878 */ 1879 if (handle >= NPH_RESERVED) 1880 continue; 1881 1882 /* 1883 * Get the port database entity for this index. 1884 */ 1885 r = isp_getpdb(isp, chan, handle, &pdb); 1886 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { 1887 abort: 1888 isp_prt(isp, ISP_LOG_SANCFG, 1889 "Chan %d FC loop scan aborted", chan); 1890 return (1); 1891 } 1892 if (r != 0) { 1893 isp_prt(isp, ISP_LOGDEBUG1, 1894 "Chan %d FC Scan Loop handle %d returned %x", 1895 chan, handle, r); 1896 continue; 1897 } 1898 1899 isp_pdb_add_update(isp, chan, &pdb); 1900 } 1901 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) 1902 goto abort; 1903 fcp->isp_loopstate = LOOP_LSCAN_DONE; 1904 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan); 1905 return (0); 1906 } 1907 1908 static int 1909 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt) 1910 { 1911 fcparam *fcp = FCPARAM(isp, chan); 1912 isp_ct_pt_t pt; 1913 void *reqp; 1914 uint8_t resp[QENTRY_LEN]; 1915 1916 if (isp->isp_dblev & ISP_LOGDEBUG1) 1917 isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch); 1918 1919 /* 1920 * Build a Passthrough IOCB in memory. 1921 */ 1922 ISP_MEMZERO(&pt, sizeof(pt)); 1923 pt.ctp_header.rqs_entry_count = 1; 1924 pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU; 1925 pt.ctp_nphdl = fcp->isp_sns_hdl; 1926 pt.ctp_cmd_cnt = 1; 1927 pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan); 1928 pt.ctp_time = 10; 1929 pt.ctp_rsp_cnt = 1; 1930 pt.ctp_rsp_bcnt = rsp_bcnt; 1931 pt.ctp_cmd_bcnt = cmd_bcnt; 1932 pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma); 1933 pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma); 1934 pt.ctp_dataseg[0].ds_count = cmd_bcnt; 1935 pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma); 1936 pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma); 1937 pt.ctp_dataseg[1].ds_count = rsp_bcnt; 1938 1939 /* Prepare space for response in memory */ 1940 memset(resp, 0xff, sizeof(resp)); 1941 pt.ctp_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); 1942 if (pt.ctp_handle == 0) { 1943 isp_prt(isp, ISP_LOGERR, 1944 "%s: CTP of Chan %d out of handles", __func__, chan); 1945 return (-1); 1946 } 1947 1948 /* Send request and wait for response. */ 1949 reqp = isp_getrqentry(isp); 1950 if (reqp == NULL) { 1951 isp_prt(isp, ISP_LOGERR, 1952 "%s: CTP of Chan %d out of rqent", __func__, chan); 1953 isp_destroy_handle(isp, pt.ctp_handle); 1954 return (-1); 1955 } 1956 isp_put_ct_pt(isp, &pt, (isp_ct_pt_t *)reqp); 1957 if (isp->isp_dblev & ISP_LOGDEBUG1) 1958 isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, reqp); 1959 ISP_SYNC_REQUEST(isp); 1960 if (msleep(resp, &isp->isp_lock, 0, "CTP", pt.ctp_time*hz) == EWOULDBLOCK) { 1961 isp_prt(isp, ISP_LOGERR, 1962 "%s: CTP of Chan %d timed out", __func__, chan); 1963 isp_destroy_handle(isp, pt.ctp_handle); 1964 return (-1); 1965 } 1966 if (isp->isp_dblev & ISP_LOGDEBUG1) 1967 isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, resp); 1968 1969 isp_get_ct_pt(isp, (isp_ct_pt_t *)resp, &pt); 1970 if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) { 1971 isp_prt(isp, ISP_LOGWARN, 1972 "Chan %d CT pass-through returned 0x%x", 1973 chan, pt.ctp_status); 1974 return (-1); 1975 } 1976 1977 if (isp->isp_dblev & ISP_LOGDEBUG1) 1978 isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch); 1979 1980 return (0); 1981 } 1982 1983 /* 1984 * Scan the fabric for devices and add them to our port database. 1985 * 1986 * Use the GID_PT command to get list of all Nx_Port IDs SNS knows. 1987 * Use GFF_ID and GFT_ID to check port type (FCP) and features (target). 1988 * 1989 * We use CT Pass-through IOCB. 1990 */ 1991 #define GIDLEN ISP_FC_SCRLEN 1992 #define NGENT ((GIDLEN - 16) >> 2) 1993 1994 static int 1995 isp_gid_pt(ispsoftc_t *isp, int chan) 1996 { 1997 fcparam *fcp = FCPARAM(isp, chan); 1998 ct_hdr_t ct; 1999 uint8_t *scp = fcp->isp_scratch; 2000 2001 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan); 2002 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2003 isp_prt(isp, ISP_LOGERR, sacq); 2004 return (-1); 2005 } 2006 2007 /* Build the CT command and execute via pass-through. */ 2008 ISP_MEMZERO(&ct, sizeof (ct)); 2009 ct.ct_revision = CT_REVISION; 2010 ct.ct_fcs_type = CT_FC_TYPE_FC; 2011 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2012 ct.ct_cmd_resp = SNS_GID_PT; 2013 ct.ct_bcnt_resid = (GIDLEN - 16) >> 2; 2014 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp); 2015 scp[sizeof(ct)] = 0x7f; /* Port Type = Nx_Port */ 2016 scp[sizeof(ct)+1] = 0; /* Domain_ID = any */ 2017 scp[sizeof(ct)+2] = 0; /* Area_ID = any */ 2018 scp[sizeof(ct)+3] = 0; /* Flags = no Area_ID */ 2019 2020 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) { 2021 FC_SCRATCH_RELEASE(isp, chan); 2022 return (-1); 2023 } 2024 2025 isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp, 2026 (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT); 2027 FC_SCRATCH_RELEASE(isp, chan); 2028 return (0); 2029 } 2030 2031 static int 2032 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid) 2033 { 2034 fcparam *fcp = FCPARAM(isp, chan); 2035 ct_hdr_t ct; 2036 uint32_t *rp; 2037 uint8_t *scp = fcp->isp_scratch; 2038 sns_gff_id_rsp_t rsp; 2039 int i, res = -1; 2040 2041 if (!fcp->isp_use_gff_id) /* User may block GFF_ID use. */ 2042 return (res); 2043 2044 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan); 2045 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2046 isp_prt(isp, ISP_LOGERR, sacq); 2047 return (res); 2048 } 2049 2050 /* Build the CT command and execute via pass-through. */ 2051 ISP_MEMZERO(&ct, sizeof (ct)); 2052 ct.ct_revision = CT_REVISION; 2053 ct.ct_fcs_type = CT_FC_TYPE_FC; 2054 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2055 ct.ct_cmd_resp = SNS_GFF_ID; 2056 ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4; 2057 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp); 2058 rp = (uint32_t *) &scp[sizeof(ct)]; 2059 ISP_IOZPUT_32(isp, portid, rp); 2060 2061 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), 2062 SNS_GFF_ID_RESP_SIZE)) { 2063 FC_SCRATCH_RELEASE(isp, chan); 2064 return (res); 2065 } 2066 2067 isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp); 2068 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) { 2069 for (i = 0; i < 32; i++) { 2070 if (rsp.snscb_fc4_features[i] != 0) { 2071 res = 0; 2072 break; 2073 } 2074 } 2075 if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >> 2076 ((FC4_SCSI % 8) * 4)) & 0x01) != 0) 2077 res = 1; 2078 /* Workaround for broken Brocade firmware. */ 2079 if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >> 2080 ((FC4_SCSI % 8) * 4)) & 0x01) != 0) 2081 res = 1; 2082 } 2083 FC_SCRATCH_RELEASE(isp, chan); 2084 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res); 2085 return (res); 2086 } 2087 2088 static int 2089 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid) 2090 { 2091 fcparam *fcp = FCPARAM(isp, chan); 2092 ct_hdr_t ct; 2093 uint32_t *rp; 2094 uint8_t *scp = fcp->isp_scratch; 2095 sns_gft_id_rsp_t rsp; 2096 int i, res = -1; 2097 2098 if (!fcp->isp_use_gft_id) /* User may block GFT_ID use. */ 2099 return (res); 2100 2101 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan); 2102 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2103 isp_prt(isp, ISP_LOGERR, sacq); 2104 return (res); 2105 } 2106 2107 /* Build the CT command and execute via pass-through. */ 2108 ISP_MEMZERO(&ct, sizeof (ct)); 2109 ct.ct_revision = CT_REVISION; 2110 ct.ct_fcs_type = CT_FC_TYPE_FC; 2111 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2112 ct.ct_cmd_resp = SNS_GFT_ID; 2113 ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4; 2114 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp); 2115 rp = (uint32_t *) &scp[sizeof(ct)]; 2116 ISP_IOZPUT_32(isp, portid, rp); 2117 2118 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), 2119 SNS_GFT_ID_RESP_SIZE)) { 2120 FC_SCRATCH_RELEASE(isp, chan); 2121 return (res); 2122 } 2123 2124 isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp); 2125 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) { 2126 for (i = 0; i < 8; i++) { 2127 if (rsp.snscb_fc4_types[i] != 0) { 2128 res = 0; 2129 break; 2130 } 2131 } 2132 if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >> 2133 (FC4_SCSI % 32)) & 0x01) != 0) 2134 res = 1; 2135 } 2136 FC_SCRATCH_RELEASE(isp, chan); 2137 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res); 2138 return (res); 2139 } 2140 2141 static int 2142 isp_scan_fabric(ispsoftc_t *isp, int chan) 2143 { 2144 fcparam *fcp = FCPARAM(isp, chan); 2145 fcportdb_t *lp; 2146 uint32_t portid; 2147 isp_pdb_t pdb; 2148 int portidx, portlim, r; 2149 sns_gid_xx_rsp_t *rs; 2150 2151 if (fcp->isp_loopstate < LOOP_LSCAN_DONE) 2152 return (-1); 2153 if (fcp->isp_loopstate >= LOOP_FSCAN_DONE) 2154 return (0); 2155 2156 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan); 2157 fcp->isp_loopstate = LOOP_SCANNING_FABRIC; 2158 if (!TOPO_IS_FABRIC(fcp->isp_topo)) { 2159 fcp->isp_loopstate = LOOP_FSCAN_DONE; 2160 isp_prt(isp, ISP_LOG_SANCFG, 2161 "Chan %d FC fabric scan done (no fabric)", chan); 2162 return (0); 2163 } 2164 2165 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { 2166 abort: 2167 FC_SCRATCH_RELEASE(isp, chan); 2168 isp_prt(isp, ISP_LOG_SANCFG, 2169 "Chan %d FC fabric scan aborted", chan); 2170 return (1); 2171 } 2172 2173 /* 2174 * Make sure we still are logged into the fabric controller. 2175 */ 2176 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb); 2177 if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) { 2178 isp_dump_chip_portdb(isp, chan); 2179 } 2180 if (r) { 2181 fcp->isp_loopstate = LOOP_LTEST_DONE; 2182 fail: 2183 isp_prt(isp, ISP_LOG_SANCFG, 2184 "Chan %d FC fabric scan done (bad)", chan); 2185 return (-1); 2186 } 2187 2188 /* Get list of port IDs from SNS. */ 2189 r = isp_gid_pt(isp, chan); 2190 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2191 goto abort; 2192 if (r > 0) { 2193 fcp->isp_loopstate = LOOP_FSCAN_DONE; 2194 return (-1); 2195 } else if (r < 0) { 2196 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */ 2197 return (-1); 2198 } 2199 2200 rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch; 2201 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2202 goto abort; 2203 if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) { 2204 int level; 2205 /* FC-4 Type and Port Type not registered are not errors. */ 2206 if (rs->snscb_cthdr.ct_reason == 9 && 2207 (rs->snscb_cthdr.ct_explanation == 0x07 || 2208 rs->snscb_cthdr.ct_explanation == 0x0a)) { 2209 level = ISP_LOG_SANCFG; 2210 } else { 2211 level = ISP_LOGWARN; 2212 } 2213 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT" 2214 " (Reason=0x%x Expl=0x%x)", chan, 2215 rs->snscb_cthdr.ct_reason, 2216 rs->snscb_cthdr.ct_explanation); 2217 fcp->isp_loopstate = LOOP_FSCAN_DONE; 2218 return (-1); 2219 } 2220 2221 /* Check our buffer was big enough to get the full list. */ 2222 for (portidx = 0; portidx < NGENT-1; portidx++) { 2223 if (rs->snscb_ports[portidx].control & 0x80) 2224 break; 2225 } 2226 if ((rs->snscb_ports[portidx].control & 0x80) == 0) { 2227 isp_prt(isp, ISP_LOGWARN, 2228 "fabric too big for scratch area: increase ISP_FC_SCRLEN"); 2229 } 2230 portlim = portidx + 1; 2231 isp_prt(isp, ISP_LOG_SANCFG, 2232 "Chan %d Got %d ports back from name server", chan, portlim); 2233 2234 /* Go through the list and remove duplicate port ids. */ 2235 for (portidx = 0; portidx < portlim; portidx++) { 2236 int npidx; 2237 2238 portid = 2239 ((rs->snscb_ports[portidx].portid[0]) << 16) | 2240 ((rs->snscb_ports[portidx].portid[1]) << 8) | 2241 ((rs->snscb_ports[portidx].portid[2])); 2242 2243 for (npidx = portidx + 1; npidx < portlim; npidx++) { 2244 uint32_t new_portid = 2245 ((rs->snscb_ports[npidx].portid[0]) << 16) | 2246 ((rs->snscb_ports[npidx].portid[1]) << 8) | 2247 ((rs->snscb_ports[npidx].portid[2])); 2248 if (new_portid == portid) { 2249 break; 2250 } 2251 } 2252 2253 if (npidx < portlim) { 2254 rs->snscb_ports[npidx].portid[0] = 0; 2255 rs->snscb_ports[npidx].portid[1] = 0; 2256 rs->snscb_ports[npidx].portid[2] = 0; 2257 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid); 2258 } 2259 } 2260 2261 /* 2262 * We now have a list of Port IDs for all FC4 SCSI devices 2263 * that the Fabric Name server knows about. 2264 * 2265 * For each entry on this list go through our port database looking 2266 * for probational entries- if we find one, then an old entry is 2267 * maybe still this one. We get some information to find out. 2268 * 2269 * Otherwise, it's a new fabric device, and we log into it 2270 * (unconditionally). After searching the entire database 2271 * again to make sure that we never ever ever ever have more 2272 * than one entry that has the same PortID or the same 2273 * WWNN/WWPN duple, we enter the device into our database. 2274 */ 2275 isp_mark_portdb(isp, chan); 2276 for (portidx = 0; portidx < portlim; portidx++) { 2277 portid = ((rs->snscb_ports[portidx].portid[0]) << 16) | 2278 ((rs->snscb_ports[portidx].portid[1]) << 8) | 2279 ((rs->snscb_ports[portidx].portid[2])); 2280 isp_prt(isp, ISP_LOG_SANCFG, 2281 "Chan %d Checking fabric port 0x%06x", chan, portid); 2282 if (portid == 0) { 2283 isp_prt(isp, ISP_LOG_SANCFG, 2284 "Chan %d Port at idx %d is zero", 2285 chan, portidx); 2286 continue; 2287 } 2288 if (portid == fcp->isp_portid) { 2289 isp_prt(isp, ISP_LOG_SANCFG, 2290 "Chan %d Port 0x%06x is our", chan, portid); 2291 continue; 2292 } 2293 2294 /* Now search the entire port database for the same portid. */ 2295 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) { 2296 if (!lp->probational) { 2297 isp_prt(isp, ISP_LOGERR, 2298 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)", 2299 chan, lp->portid, lp->handle, 2300 FC_PORTDB_TGT(isp, chan, lp), lp->state); 2301 isp_dump_portdb(isp, chan); 2302 goto fail; 2303 } 2304 2305 if (lp->state == FC_PORTDB_STATE_ZOMBIE) 2306 goto relogin; 2307 2308 /* 2309 * See if we're still logged into it. 2310 * 2311 * If we aren't, mark it as a dead device and 2312 * leave the new portid in the database entry 2313 * for somebody further along to decide what to 2314 * do (policy choice). 2315 * 2316 * If we are, check to see if it's the same 2317 * device still (it should be). If for some 2318 * reason it isn't, mark it as a changed device 2319 * and leave the new portid and role in the 2320 * database entry for somebody further along to 2321 * decide what to do (policy choice). 2322 */ 2323 r = isp_getpdb(isp, chan, lp->handle, &pdb); 2324 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2325 goto abort; 2326 if (r != 0) { 2327 lp->state = FC_PORTDB_STATE_DEAD; 2328 isp_prt(isp, ISP_LOG_SANCFG, 2329 "Chan %d Port 0x%06x handle 0x%x is dead (%d)", 2330 chan, portid, lp->handle, r); 2331 goto relogin; 2332 } 2333 2334 isp_pdb_add_update(isp, chan, &pdb); 2335 continue; 2336 } 2337 2338 relogin: 2339 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) { 2340 isp_prt(isp, ISP_LOG_SANCFG, 2341 "Chan %d Port 0x%06x is not logged in", chan, portid); 2342 continue; 2343 } 2344 2345 r = isp_gff_id(isp, chan, portid); 2346 if (r == 0) { 2347 isp_prt(isp, ISP_LOG_SANCFG, 2348 "Chan %d Port 0x%06x is not an FCP target", chan, portid); 2349 continue; 2350 } 2351 if (r < 0) 2352 r = isp_gft_id(isp, chan, portid); 2353 if (r == 0) { 2354 isp_prt(isp, ISP_LOG_SANCFG, 2355 "Chan %d Port 0x%06x is not FCP", chan, portid); 2356 continue; 2357 } 2358 2359 if (isp_login_device(isp, chan, portid, &pdb, 2360 &FCPARAM(isp, 0)->isp_lasthdl)) { 2361 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2362 goto abort; 2363 continue; 2364 } 2365 2366 isp_pdb_add_update(isp, chan, &pdb); 2367 } 2368 2369 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) 2370 goto abort; 2371 fcp->isp_loopstate = LOOP_FSCAN_DONE; 2372 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan); 2373 return (0); 2374 } 2375 2376 /* 2377 * Find an unused handle and try and use to login to a port. 2378 */ 2379 static int 2380 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp) 2381 { 2382 int i, r; 2383 uint16_t handle; 2384 2385 handle = isp_next_handle(isp, ohp); 2386 for (i = 0; i < NPH_MAX_2K; i++) { 2387 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) 2388 return (-1); 2389 2390 /* Check if this handle is free. */ 2391 r = isp_getpdb(isp, chan, handle, p); 2392 if (r == 0) { 2393 if (p->portid != portid) { 2394 /* This handle is busy, try next one. */ 2395 handle = isp_next_handle(isp, ohp); 2396 continue; 2397 } 2398 break; 2399 } 2400 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) 2401 return (-1); 2402 2403 /* 2404 * Now try and log into the device 2405 */ 2406 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI); 2407 if (r == 0) { 2408 break; 2409 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) { 2410 /* 2411 * If we get here, then the firmwware still thinks we're logged into this device, but with a different 2412 * handle. We need to break that association. We used to try and just substitute the handle, but then 2413 * failed to get any data via isp_getpdb (below). 2414 */ 2415 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) { 2416 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16); 2417 } 2418 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) 2419 return (-1); 2420 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI); 2421 if (r != 0) 2422 i = NPH_MAX_2K; 2423 break; 2424 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) { 2425 /* Try the next handle. */ 2426 handle = isp_next_handle(isp, ohp); 2427 } else { 2428 /* Give up. */ 2429 i = NPH_MAX_2K; 2430 break; 2431 } 2432 } 2433 2434 if (i == NPH_MAX_2K) { 2435 isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid); 2436 return (-1); 2437 } 2438 2439 /* 2440 * If we successfully logged into it, get the PDB for it 2441 * so we can crosscheck that it is still what we think it 2442 * is and that we also have the role it plays 2443 */ 2444 r = isp_getpdb(isp, chan, handle, p); 2445 if (r != 0) { 2446 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle); 2447 return (-1); 2448 } 2449 2450 if (p->handle != handle || p->portid != portid) { 2451 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)", 2452 chan, portid, handle, p->portid, p->handle); 2453 return (-1); 2454 } 2455 return (0); 2456 } 2457 2458 static int 2459 isp_register_fc4_type(ispsoftc_t *isp, int chan) 2460 { 2461 fcparam *fcp = FCPARAM(isp, chan); 2462 rft_id_t rp; 2463 ct_hdr_t *ct = &rp.rftid_hdr; 2464 uint8_t *scp = fcp->isp_scratch; 2465 2466 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2467 isp_prt(isp, ISP_LOGERR, sacq); 2468 return (-1); 2469 } 2470 2471 /* Build the CT command and execute via pass-through. */ 2472 ISP_MEMZERO(&rp, sizeof(rp)); 2473 ct->ct_revision = CT_REVISION; 2474 ct->ct_fcs_type = CT_FC_TYPE_FC; 2475 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2476 ct->ct_cmd_resp = SNS_RFT_ID; 2477 ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2; 2478 rp.rftid_portid[0] = fcp->isp_portid >> 16; 2479 rp.rftid_portid[1] = fcp->isp_portid >> 8; 2480 rp.rftid_portid[2] = fcp->isp_portid; 2481 rp.rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f); 2482 isp_put_rft_id(isp, &rp, (rft_id_t *)scp); 2483 2484 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) { 2485 FC_SCRATCH_RELEASE(isp, chan); 2486 return (-1); 2487 } 2488 2489 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); 2490 FC_SCRATCH_RELEASE(isp, chan); 2491 if (ct->ct_cmd_resp == LS_RJT) { 2492 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "Chan %d Register FC4 Type rejected", chan); 2493 return (-1); 2494 } else if (ct->ct_cmd_resp == LS_ACC) { 2495 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan); 2496 } else { 2497 isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp); 2498 return (-1); 2499 } 2500 return (0); 2501 } 2502 2503 static int 2504 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan) 2505 { 2506 fcparam *fcp = FCPARAM(isp, chan); 2507 ct_hdr_t *ct; 2508 rff_id_t rp; 2509 uint8_t *scp = fcp->isp_scratch; 2510 2511 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2512 isp_prt(isp, ISP_LOGERR, sacq); 2513 return (-1); 2514 } 2515 2516 /* 2517 * Build the CT header and command in memory. 2518 */ 2519 ISP_MEMZERO(&rp, sizeof(rp)); 2520 ct = &rp.rffid_hdr; 2521 ct->ct_revision = CT_REVISION; 2522 ct->ct_fcs_type = CT_FC_TYPE_FC; 2523 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2524 ct->ct_cmd_resp = SNS_RFF_ID; 2525 ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2; 2526 rp.rffid_portid[0] = fcp->isp_portid >> 16; 2527 rp.rffid_portid[1] = fcp->isp_portid >> 8; 2528 rp.rffid_portid[2] = fcp->isp_portid; 2529 rp.rffid_fc4features = 0; 2530 if (fcp->role & ISP_ROLE_TARGET) 2531 rp.rffid_fc4features |= 1; 2532 if (fcp->role & ISP_ROLE_INITIATOR) 2533 rp.rffid_fc4features |= 2; 2534 rp.rffid_fc4type = FC4_SCSI; 2535 isp_put_rff_id(isp, &rp, (rff_id_t *)scp); 2536 if (isp->isp_dblev & ISP_LOGDEBUG1) 2537 isp_print_bytes(isp, "CT request", sizeof(rft_id_t), scp); 2538 2539 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) { 2540 FC_SCRATCH_RELEASE(isp, chan); 2541 return (-1); 2542 } 2543 2544 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); 2545 FC_SCRATCH_RELEASE(isp, chan); 2546 if (ct->ct_cmd_resp == LS_RJT) { 2547 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, 2548 "Chan %d Register FC4 Features rejected", chan); 2549 return (-1); 2550 } else if (ct->ct_cmd_resp == LS_ACC) { 2551 isp_prt(isp, ISP_LOG_SANCFG, 2552 "Chan %d Register FC4 Features accepted", chan); 2553 } else { 2554 isp_prt(isp, ISP_LOGWARN, 2555 "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp); 2556 return (-1); 2557 } 2558 return (0); 2559 } 2560 2561 static int 2562 isp_register_port_name_24xx(ispsoftc_t *isp, int chan) 2563 { 2564 fcparam *fcp = FCPARAM(isp, chan); 2565 ct_hdr_t *ct; 2566 rspn_id_t rp; 2567 uint8_t *scp = fcp->isp_scratch; 2568 int len; 2569 2570 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2571 isp_prt(isp, ISP_LOGERR, sacq); 2572 return (-1); 2573 } 2574 2575 /* 2576 * Build the CT header and command in memory. 2577 */ 2578 ISP_MEMZERO(&rp, sizeof(rp)); 2579 ct = &rp.rspnid_hdr; 2580 ct->ct_revision = CT_REVISION; 2581 ct->ct_fcs_type = CT_FC_TYPE_FC; 2582 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2583 ct->ct_cmd_resp = SNS_RSPN_ID; 2584 rp.rspnid_portid[0] = fcp->isp_portid >> 16; 2585 rp.rspnid_portid[1] = fcp->isp_portid >> 8; 2586 rp.rspnid_portid[2] = fcp->isp_portid; 2587 rp.rspnid_length = 0; 2588 len = offsetof(rspn_id_t, rspnid_name); 2589 mtx_lock(&prison0.pr_mtx); 2590 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length], 2591 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD"); 2592 mtx_unlock(&prison0.pr_mtx); 2593 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length], 2594 ":%s", device_get_nameunit(isp->isp_dev)); 2595 if (chan != 0) { 2596 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length], 2597 "/%d", chan); 2598 } 2599 len += rp.rspnid_length; 2600 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2; 2601 isp_put_rspn_id(isp, &rp, (rspn_id_t *)scp); 2602 2603 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) { 2604 FC_SCRATCH_RELEASE(isp, chan); 2605 return (-1); 2606 } 2607 2608 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); 2609 FC_SCRATCH_RELEASE(isp, chan); 2610 if (ct->ct_cmd_resp == LS_RJT) { 2611 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, 2612 "Chan %d Register Symbolic Port Name rejected", chan); 2613 return (-1); 2614 } else if (ct->ct_cmd_resp == LS_ACC) { 2615 isp_prt(isp, ISP_LOG_SANCFG, 2616 "Chan %d Register Symbolic Port Name accepted", chan); 2617 } else { 2618 isp_prt(isp, ISP_LOGWARN, 2619 "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp); 2620 return (-1); 2621 } 2622 return (0); 2623 } 2624 2625 static int 2626 isp_register_node_name_24xx(ispsoftc_t *isp, int chan) 2627 { 2628 fcparam *fcp = FCPARAM(isp, chan); 2629 ct_hdr_t *ct; 2630 rsnn_nn_t rp; 2631 uint8_t *scp = fcp->isp_scratch; 2632 int len; 2633 2634 if (FC_SCRATCH_ACQUIRE(isp, chan)) { 2635 isp_prt(isp, ISP_LOGERR, sacq); 2636 return (-1); 2637 } 2638 2639 /* 2640 * Build the CT header and command in memory. 2641 */ 2642 ISP_MEMZERO(&rp, sizeof(rp)); 2643 ct = &rp.rsnnnn_hdr; 2644 ct->ct_revision = CT_REVISION; 2645 ct->ct_fcs_type = CT_FC_TYPE_FC; 2646 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; 2647 ct->ct_cmd_resp = SNS_RSNN_NN; 2648 MAKE_NODE_NAME_FROM_WWN(rp.rsnnnn_nodename, fcp->isp_wwnn); 2649 rp.rsnnnn_length = 0; 2650 len = offsetof(rsnn_nn_t, rsnnnn_name); 2651 mtx_lock(&prison0.pr_mtx); 2652 rp.rsnnnn_length += sprintf(&scp[len + rp.rsnnnn_length], 2653 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD"); 2654 mtx_unlock(&prison0.pr_mtx); 2655 len += rp.rsnnnn_length; 2656 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2; 2657 isp_put_rsnn_nn(isp, &rp, (rsnn_nn_t *)scp); 2658 2659 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) { 2660 FC_SCRATCH_RELEASE(isp, chan); 2661 return (-1); 2662 } 2663 2664 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); 2665 FC_SCRATCH_RELEASE(isp, chan); 2666 if (ct->ct_cmd_resp == LS_RJT) { 2667 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, 2668 "Chan %d Register Symbolic Node Name rejected", chan); 2669 return (-1); 2670 } else if (ct->ct_cmd_resp == LS_ACC) { 2671 isp_prt(isp, ISP_LOG_SANCFG, 2672 "Chan %d Register Symbolic Node Name accepted", chan); 2673 } else { 2674 isp_prt(isp, ISP_LOGWARN, 2675 "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp); 2676 return (-1); 2677 } 2678 return (0); 2679 } 2680 2681 static uint16_t 2682 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp) 2683 { 2684 fcparam *fcp; 2685 int i, chan, wrap; 2686 uint16_t handle; 2687 2688 handle = *ohp; 2689 wrap = 0; 2690 2691 next: 2692 if (handle == NIL_HANDLE) { 2693 handle = 0; 2694 } else { 2695 handle++; 2696 if (handle > NPH_RESERVED - 1) { 2697 if (++wrap >= 2) { 2698 isp_prt(isp, ISP_LOGERR, "Out of port handles!"); 2699 return (NIL_HANDLE); 2700 } 2701 handle = 0; 2702 } 2703 } 2704 for (chan = 0; chan < isp->isp_nchan; chan++) { 2705 fcp = FCPARAM(isp, chan); 2706 if (fcp->role == ISP_ROLE_NONE) 2707 continue; 2708 for (i = 0; i < MAX_FC_TARG; i++) { 2709 if (fcp->portdb[i].state != FC_PORTDB_STATE_NIL && 2710 fcp->portdb[i].handle == handle) 2711 goto next; 2712 } 2713 } 2714 *ohp = handle; 2715 return (handle); 2716 } 2717 2718 /* 2719 * Start a command. Locking is assumed done in the caller. 2720 */ 2721 2722 int 2723 isp_start(XS_T *xs) 2724 { 2725 ispsoftc_t *isp; 2726 fcparam *fcp; 2727 uint32_t cdblen; 2728 ispreqt7_t local, *reqp = &local; 2729 void *qep; 2730 fcportdb_t *lp; 2731 int target, dmaresult; 2732 2733 XS_INITERR(xs); 2734 isp = XS_ISP(xs); 2735 2736 /* 2737 * Check command CDB length, etc.. We really are limited to 16 bytes 2738 * for Fibre Channel, but can do up to 44 bytes in parallel SCSI, 2739 * but probably only if we're running fairly new firmware (we'll 2740 * let the old f/w choke on an extended command queue entry). 2741 */ 2742 2743 if (XS_CDBLEN(xs) > 16 || XS_CDBLEN(xs) == 0) { 2744 isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff); 2745 XS_SETERR(xs, HBA_REQINVAL); 2746 return (CMD_COMPLETE); 2747 } 2748 2749 /* 2750 * Translate the target to device handle as appropriate, checking 2751 * for correct device state as well. 2752 */ 2753 target = XS_TGT(xs); 2754 fcp = FCPARAM(isp, XS_CHANNEL(xs)); 2755 2756 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) { 2757 isp_prt(isp, ISP_LOG_WARN1, 2758 "%d.%d.%jx I am not an initiator", 2759 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs)); 2760 XS_SETERR(xs, HBA_SELTIMEOUT); 2761 return (CMD_COMPLETE); 2762 } 2763 2764 if (isp->isp_state != ISP_RUNSTATE) { 2765 isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE"); 2766 XS_SETERR(xs, HBA_BOTCH); 2767 return (CMD_COMPLETE); 2768 } 2769 2770 isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target); 2771 lp = &fcp->portdb[target]; 2772 if (target < 0 || target >= MAX_FC_TARG || 2773 lp->is_target == 0) { 2774 XS_SETERR(xs, HBA_SELTIMEOUT); 2775 return (CMD_COMPLETE); 2776 } 2777 if (fcp->isp_loopstate != LOOP_READY) { 2778 isp_prt(isp, ISP_LOGDEBUG1, 2779 "%d.%d.%jx loop is not ready", 2780 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs)); 2781 return (CMD_RQLATER); 2782 } 2783 if (lp->state == FC_PORTDB_STATE_ZOMBIE) { 2784 isp_prt(isp, ISP_LOGDEBUG1, 2785 "%d.%d.%jx target zombie", 2786 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs)); 2787 return (CMD_RQLATER); 2788 } 2789 if (lp->state != FC_PORTDB_STATE_VALID) { 2790 isp_prt(isp, ISP_LOGDEBUG1, 2791 "%d.%d.%jx bad db port state 0x%x", 2792 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs), lp->state); 2793 XS_SETERR(xs, HBA_SELTIMEOUT); 2794 return (CMD_COMPLETE); 2795 } 2796 2797 start_again: 2798 2799 qep = isp_getrqentry(isp); 2800 if (qep == NULL) { 2801 isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow"); 2802 XS_SETERR(xs, HBA_BOTCH); 2803 return (CMD_EAGAIN); 2804 } 2805 XS_SETERR(xs, HBA_NOERROR); 2806 2807 /* 2808 * Now see if we need to synchronize the ISP with respect to anything. 2809 * We do dual duty here (cough) for synchronizing for buses other 2810 * than which we got here to send a command to. 2811 */ 2812 ISP_MEMZERO(reqp, QENTRY_LEN); 2813 if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) { 2814 isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp; 2815 m->mrk_header.rqs_entry_count = 1; 2816 m->mrk_header.rqs_entry_type = RQSTYPE_MARKER; 2817 m->mrk_modifier = SYNC_ALL; 2818 m->mrk_vphdl = XS_CHANNEL(xs); 2819 isp_put_marker_24xx(isp, m, qep); 2820 ISP_SYNC_REQUEST(isp); 2821 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0); 2822 goto start_again; 2823 } 2824 2825 reqp->req_header.rqs_entry_count = 1; 2826 reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS; 2827 2828 /* 2829 * Set task attributes 2830 */ 2831 if (XS_TAG_P(xs)) 2832 reqp->req_task_attribute = XS_TAG_TYPE(xs); 2833 else 2834 reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE; 2835 reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) & 2836 FCP_CMND_PRIO_MASK; 2837 2838 /* 2839 * NB: we do not support long CDBs (yet) 2840 */ 2841 cdblen = XS_CDBLEN(xs); 2842 2843 if (cdblen > sizeof (reqp->req_cdb)) { 2844 isp_prt(isp, ISP_LOGERR, "Command Length %u too long for this chip", cdblen); 2845 XS_SETERR(xs, HBA_REQINVAL); 2846 return (CMD_COMPLETE); 2847 } 2848 2849 reqp->req_nphdl = lp->handle; 2850 reqp->req_tidlo = lp->portid; 2851 reqp->req_tidhi = lp->portid >> 16; 2852 reqp->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs)); 2853 be64enc(reqp->req_lun, CAM_EXTLUN_BYTE_SWIZZLE(XS_LUN(xs))); 2854 if (FCPARAM(isp, XS_CHANNEL(xs))->fctape_enabled && (lp->prli_word3 & PRLI_WD3_RETRY)) { 2855 if (FCP_NEXT_CRN(isp, &reqp->req_crn, xs)) { 2856 isp_prt(isp, ISP_LOG_WARN1, 2857 "%d.%d.%jx cannot generate next CRN", 2858 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs)); 2859 XS_SETERR(xs, HBA_BOTCH); 2860 return (CMD_EAGAIN); 2861 } 2862 } 2863 reqp->req_time = XS_TIME(xs); 2864 ISP_MEMCPY(reqp->req_cdb, XS_CDBP(xs), cdblen); 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 != CMD_QUEUED) { 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 (CMD_QUEUED); 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 break; 3185 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/ 3186 default: 3187 isp_print_qentry(isp, "?ATIOQ entry?", oop, addr); 3188 break; 3189 } 3190 optr = ISP_NXT_QENTRY(oop, RESULT_QUEUE_LEN(isp)); 3191 } 3192 if (isp->isp_atioodx != optr) { 3193 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr); 3194 isp->isp_atioodx = optr; 3195 } 3196 } 3197 #endif 3198 3199 void 3200 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0) 3201 { 3202 int i, obits; 3203 3204 if (!isp->isp_mboxbsy) { 3205 isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0); 3206 return; 3207 } 3208 obits = isp->isp_obits; 3209 isp->isp_mboxtmp[0] = mbox0; 3210 for (i = 1; i < ISP_NMBOX(isp); i++) { 3211 if ((obits & (1 << i)) == 0) 3212 continue; 3213 isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i)); 3214 } 3215 MBOX_NOTIFY_COMPLETE(isp); 3216 } 3217 3218 void 3219 isp_intr_respq(ispsoftc_t *isp) 3220 { 3221 XS_T *xs, *cont_xs; 3222 uint8_t qe[QENTRY_LEN]; 3223 isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe; 3224 isphdr_t *hp; 3225 uint8_t *resp, *snsp; 3226 int buddaboom, completion_status, cont = 0, etype, i; 3227 int req_status_flags, req_state_flags, scsi_status; 3228 uint32_t iptr, cptr, optr, rlen, slen, sptr, totslen, resid; 3229 3230 /* 3231 * We can't be getting this now. 3232 */ 3233 if (isp->isp_state != ISP_RUNSTATE) { 3234 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready"); 3235 return; 3236 } 3237 3238 iptr = ISP_READ(isp, BIU2400_RSPINP); 3239 isp->isp_residx = iptr; 3240 3241 optr = isp->isp_resodx; 3242 while (optr != iptr) { 3243 sptr = cptr = optr; 3244 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr); 3245 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp)); 3246 3247 /* 3248 * Synchronize our view of this response queue entry. 3249 */ 3250 MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1); 3251 if (isp->isp_dblev & ISP_LOGDEBUG1) 3252 isp_print_qentry(isp, "Response Queue Entry", cptr, hp); 3253 isp_get_hdr(isp, hp, &sp->req_header); 3254 etype = sp->req_header.rqs_entry_type; 3255 3256 /* We expected Status Continuation, but got different IOCB. */ 3257 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) { 3258 cont = 0; 3259 isp_done(cont_xs); 3260 } 3261 3262 if (etype == RQSTYPE_RESPONSE) { 3263 isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp); 3264 scsi_status = sp->req_scsi_status; 3265 completion_status = sp->req_completion_status; 3266 req_status_flags = 0; 3267 if ((scsi_status & 0xff) != 0) 3268 req_state_flags = RQSF_GOT_STATUS; 3269 else 3270 req_state_flags = 0; 3271 resid = sp->req_resid; 3272 } else if (etype == RQSTYPE_STATUS_CONT) { 3273 ispstatus_cont_t *scp = (ispstatus_cont_t *)qe; 3274 isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp); 3275 if (cont > 0) { 3276 i = min(cont, sizeof(scp->req_sense_data)); 3277 XS_SENSE_APPEND(cont_xs, scp->req_sense_data, i); 3278 cont -= i; 3279 if (cont == 0) { 3280 isp_done(cont_xs); 3281 } else { 3282 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN, 3283 "Expecting Status Continuations for %u bytes", 3284 cont); 3285 } 3286 } else { 3287 isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response"); 3288 } 3289 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3290 continue; 3291 } else if (isp_handle_other_response(isp, etype, hp, &cptr)) { 3292 /* More then one IOCB could be consumed. */ 3293 while (sptr != cptr) { 3294 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3295 sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp)); 3296 hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr); 3297 } 3298 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3299 optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp)); 3300 continue; 3301 } else { 3302 /* We don't know what was this -- log and skip. */ 3303 isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr); 3304 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3305 continue; 3306 } 3307 3308 buddaboom = 0; 3309 if (sp->req_header.rqs_flags & RQSFLAG_MASK) { 3310 if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) { 3311 isp_print_qentry(isp, "unexpected continuation segment", 3312 cptr, hp); 3313 continue; 3314 } 3315 if (sp->req_header.rqs_flags & RQSFLAG_FULL) { 3316 isp_prt(isp, ISP_LOG_WARN1, "internal queues full"); 3317 /* 3318 * We'll synthesize a QUEUE FULL message below. 3319 */ 3320 } 3321 if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) { 3322 isp_print_qentry(isp, "bad header flag", 3323 cptr, hp); 3324 buddaboom++; 3325 } 3326 if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) { 3327 isp_print_qentry(isp, "bad request packet", 3328 cptr, hp); 3329 buddaboom++; 3330 } 3331 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) { 3332 isp_print_qentry(isp, "invalid entry count", 3333 cptr, hp); 3334 buddaboom++; 3335 } 3336 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) { 3337 isp_print_qentry(isp, "invalid IOCB ordering", 3338 cptr, hp); 3339 continue; 3340 } 3341 } 3342 3343 xs = isp_find_xs(isp, sp->req_handle); 3344 if (xs == NULL) { 3345 uint8_t ts = completion_status & 0xff; 3346 /* 3347 * Only whine if this isn't the expected fallout of 3348 * aborting the command or resetting the target. 3349 */ 3350 if (etype != RQSTYPE_RESPONSE) { 3351 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype); 3352 } else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED) { 3353 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts); 3354 } 3355 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3356 continue; 3357 } 3358 if (req_status_flags & RQSTF_BUS_RESET) { 3359 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx bus was reset", 3360 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs)); 3361 XS_SETERR(xs, HBA_BUSRESET); 3362 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1); 3363 } 3364 if (buddaboom) { 3365 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx buddaboom", 3366 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs)); 3367 XS_SETERR(xs, HBA_BOTCH); 3368 } 3369 3370 resp = snsp = NULL; 3371 rlen = slen = totslen = 0; 3372 if ((scsi_status & (RQCS_RV|RQCS_SV)) != 0) { 3373 resp = sp->req_rsp_sense; 3374 rlen = sp->req_response_len; 3375 } 3376 if ((scsi_status & RQCS_SV) != 0) { 3377 /* 3378 * Fibre Channel F/W doesn't say we got status 3379 * if there's Sense Data instead. I guess they 3380 * think it goes w/o saying. 3381 */ 3382 req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE; 3383 snsp = sp->req_rsp_sense + rlen; 3384 totslen = sp->req_sense_len; 3385 slen = sizeof(sp->req_rsp_sense) - rlen; 3386 } 3387 if (slen > totslen) 3388 slen = totslen; 3389 if (req_state_flags & RQSF_GOT_STATUS) 3390 *XS_STSP(xs) = scsi_status & 0xff; 3391 3392 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) { 3393 const char *ptr; 3394 char lb[64]; 3395 const char *rnames[10] = { 3396 "Task Management function complete", 3397 "FCP_DATA length different than FCP_BURST_LEN", 3398 "FCP_CMND fields invalid", 3399 "FCP_DATA parameter mismatch with FCP_DATA_RO", 3400 "Task Management function rejected", 3401 "Task Management function failed", 3402 NULL, 3403 NULL, 3404 "Task Management function succeeded", 3405 "Task Management function incorrect logical unit number", 3406 }; 3407 uint8_t code = resp[FCP_RSPNS_CODE_OFFSET]; 3408 if (code >= 10 || rnames[code] == NULL) { 3409 ISP_SNPRINTF(lb, sizeof(lb), 3410 "Unknown FCP Response Code 0x%x", code); 3411 ptr = lb; 3412 } else { 3413 ptr = rnames[code]; 3414 } 3415 isp_xs_prt(isp, xs, ISP_LOGWARN, 3416 "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x", 3417 rlen, ptr, XS_CDBP(xs)[0] & 0xff); 3418 if (code != 0 && code != 8) 3419 XS_SETERR(xs, HBA_BOTCH); 3420 } 3421 isp_parse_status_24xx(isp, sp, xs, &resid); 3422 if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) && 3423 (*XS_STSP(xs) == SCSI_BUSY)) 3424 XS_SETERR(xs, HBA_TGTBSY); 3425 if (req_status_flags & RQSF_XFER_COMPLETE) { 3426 XS_SET_RESID(xs, 0); 3427 } else if (scsi_status & RQCS_RESID) { 3428 XS_SET_RESID(xs, resid); 3429 } else { 3430 XS_SET_RESID(xs, 0); 3431 } 3432 if (slen > 0) { 3433 XS_SAVE_SENSE(xs, snsp, slen); 3434 if (totslen > slen) { 3435 cont = totslen - slen; 3436 cont_xs = xs; 3437 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN, 3438 "Expecting Status Continuations for %u bytes", 3439 cont); 3440 } 3441 } 3442 isp_prt(isp, ISP_LOGDEBUG2, "asked for %lu got raw resid %lu settled for %lu", 3443 (u_long)XS_XFRLEN(xs), (u_long)resid, (u_long)XS_GET_RESID(xs)); 3444 3445 if (XS_XFRLEN(xs)) 3446 ISP_DMAFREE(isp, xs, sp->req_handle); 3447 isp_destroy_handle(isp, sp->req_handle); 3448 3449 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3450 3451 /* Complete command if we expect no Status Continuations. */ 3452 if (cont == 0) 3453 isp_done(xs); 3454 } 3455 3456 /* We haven't received all Status Continuations, but that is it. */ 3457 if (cont > 0) 3458 isp_done(cont_xs); 3459 3460 /* If we processed any IOCBs, let ISP know about it. */ 3461 if (optr != isp->isp_resodx) { 3462 ISP_WRITE(isp, BIU2400_RSPOUTP, optr); 3463 isp->isp_resodx = optr; 3464 } 3465 } 3466 3467 3468 void 3469 isp_intr_async(ispsoftc_t *isp, uint16_t mbox) 3470 { 3471 fcparam *fcp; 3472 uint16_t chan; 3473 3474 isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox); 3475 3476 switch (mbox) { 3477 case ASYNC_SYSTEM_ERROR: 3478 isp->isp_state = ISP_CRASHED; 3479 for (chan = 0; chan < isp->isp_nchan; chan++) { 3480 FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL; 3481 isp_change_fw_state(isp, chan, FW_CONFIG_WAIT); 3482 } 3483 /* 3484 * Were we waiting for a mailbox command to complete? 3485 * If so, it's dead, so wake up the waiter. 3486 */ 3487 if (isp->isp_mboxbsy) { 3488 isp->isp_obits = 1; 3489 isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR; 3490 MBOX_NOTIFY_COMPLETE(isp); 3491 } 3492 /* 3493 * It's up to the handler for isp_async to reinit stuff and 3494 * restart the firmware 3495 */ 3496 isp_async(isp, ISPASYNC_FW_CRASH); 3497 break; 3498 3499 case ASYNC_RQS_XFER_ERR: 3500 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error"); 3501 break; 3502 3503 case ASYNC_RSP_XFER_ERR: 3504 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error"); 3505 break; 3506 3507 case ASYNC_ATIO_XFER_ERR: 3508 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error"); 3509 break; 3510 3511 case ASYNC_LIP_OCCURRED: 3512 case ASYNC_LIP_NOS_OLS_RECV: 3513 case ASYNC_LIP_ERROR: 3514 case ASYNC_PTPMODE: 3515 /* 3516 * These are broadcast events that have to be sent across 3517 * all active channels. 3518 */ 3519 for (chan = 0; chan < isp->isp_nchan; chan++) { 3520 fcp = FCPARAM(isp, chan); 3521 int topo = fcp->isp_topo; 3522 3523 if (fcp->role == ISP_ROLE_NONE) 3524 continue; 3525 if (fcp->isp_loopstate > LOOP_HAVE_LINK) 3526 fcp->isp_loopstate = LOOP_HAVE_LINK; 3527 ISP_SET_SENDMARKER(isp, chan, 1); 3528 isp_async(isp, ISPASYNC_LIP, chan); 3529 #ifdef ISP_TARGET_MODE 3530 isp_target_async(isp, chan, mbox); 3531 #endif 3532 /* 3533 * We've had problems with data corruption occurring on 3534 * commands that complete (with no apparent error) after 3535 * we receive a LIP. This has been observed mostly on 3536 * Local Loop topologies. To be safe, let's just mark 3537 * all active initiator commands as dead. 3538 */ 3539 if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) { 3540 int i, j; 3541 for (i = j = 0; i < isp->isp_maxcmds; i++) { 3542 XS_T *xs; 3543 isp_hdl_t *hdp; 3544 3545 hdp = &isp->isp_xflist[i]; 3546 if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) { 3547 continue; 3548 } 3549 xs = hdp->cmd; 3550 if (XS_CHANNEL(xs) != chan) { 3551 continue; 3552 } 3553 j++; 3554 isp_prt(isp, ISP_LOG_WARN1, 3555 "%d.%d.%jx bus reset set at %s:%u", 3556 XS_CHANNEL(xs), XS_TGT(xs), 3557 (uintmax_t)XS_LUN(xs), 3558 __func__, __LINE__); 3559 XS_SETERR(xs, HBA_BUSRESET); 3560 } 3561 if (j) { 3562 isp_prt(isp, ISP_LOGERR, lipd, chan, j); 3563 } 3564 } 3565 } 3566 break; 3567 3568 case ASYNC_LOOP_UP: 3569 /* 3570 * This is a broadcast event that has to be sent across 3571 * all active channels. 3572 */ 3573 for (chan = 0; chan < isp->isp_nchan; chan++) { 3574 fcp = FCPARAM(isp, chan); 3575 if (fcp->role == ISP_ROLE_NONE) 3576 continue; 3577 fcp->isp_linkstate = 1; 3578 if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3579 fcp->isp_loopstate = LOOP_HAVE_LINK; 3580 ISP_SET_SENDMARKER(isp, chan, 1); 3581 isp_async(isp, ISPASYNC_LOOP_UP, chan); 3582 #ifdef ISP_TARGET_MODE 3583 isp_target_async(isp, chan, mbox); 3584 #endif 3585 } 3586 break; 3587 3588 case ASYNC_LOOP_DOWN: 3589 /* 3590 * This is a broadcast event that has to be sent across 3591 * all active channels. 3592 */ 3593 for (chan = 0; chan < isp->isp_nchan; chan++) { 3594 fcp = FCPARAM(isp, chan); 3595 if (fcp->role == ISP_ROLE_NONE) 3596 continue; 3597 ISP_SET_SENDMARKER(isp, chan, 1); 3598 fcp->isp_linkstate = 0; 3599 fcp->isp_loopstate = LOOP_NIL; 3600 isp_async(isp, ISPASYNC_LOOP_DOWN, chan); 3601 #ifdef ISP_TARGET_MODE 3602 isp_target_async(isp, chan, mbox); 3603 #endif 3604 } 3605 break; 3606 3607 case ASYNC_LOOP_RESET: 3608 /* 3609 * This is a broadcast event that has to be sent across 3610 * all active channels. 3611 */ 3612 for (chan = 0; chan < isp->isp_nchan; chan++) { 3613 fcp = FCPARAM(isp, chan); 3614 if (fcp->role == ISP_ROLE_NONE) 3615 continue; 3616 ISP_SET_SENDMARKER(isp, chan, 1); 3617 if (fcp->isp_loopstate > LOOP_HAVE_LINK) 3618 fcp->isp_loopstate = LOOP_HAVE_LINK; 3619 isp_async(isp, ISPASYNC_LOOP_RESET, chan); 3620 #ifdef ISP_TARGET_MODE 3621 isp_target_async(isp, chan, mbox); 3622 #endif 3623 } 3624 break; 3625 3626 case ASYNC_PDB_CHANGED: 3627 { 3628 int echan, nphdl, nlstate, reason; 3629 3630 nphdl = ISP_READ(isp, OUTMAILBOX1); 3631 nlstate = ISP_READ(isp, OUTMAILBOX2); 3632 reason = ISP_READ(isp, OUTMAILBOX3) >> 8; 3633 if (ISP_CAP_MULTI_ID(isp)) { 3634 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; 3635 if (chan == 0xff || nphdl == NIL_HANDLE) { 3636 chan = 0; 3637 echan = isp->isp_nchan - 1; 3638 } else if (chan >= isp->isp_nchan) { 3639 break; 3640 } else { 3641 echan = chan; 3642 } 3643 } else { 3644 chan = echan = 0; 3645 } 3646 for (; chan <= echan; chan++) { 3647 fcp = FCPARAM(isp, chan); 3648 if (fcp->role == ISP_ROLE_NONE) 3649 continue; 3650 if (fcp->isp_loopstate > LOOP_LTEST_DONE) { 3651 if (nphdl != NIL_HANDLE && 3652 nphdl == fcp->isp_login_hdl && 3653 reason == PDB24XX_AE_OPN_2) 3654 continue; 3655 fcp->isp_loopstate = LOOP_LTEST_DONE; 3656 } else if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3657 fcp->isp_loopstate = LOOP_HAVE_LINK; 3658 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, 3659 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason); 3660 } 3661 break; 3662 } 3663 case ASYNC_CHANGE_NOTIFY: 3664 { 3665 int portid; 3666 3667 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) | 3668 ISP_READ(isp, OUTMAILBOX2); 3669 if (ISP_CAP_MULTI_ID(isp)) { 3670 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; 3671 if (chan >= isp->isp_nchan) 3672 break; 3673 } else { 3674 chan = 0; 3675 } 3676 fcp = FCPARAM(isp, chan); 3677 if (fcp->role == ISP_ROLE_NONE) 3678 break; 3679 if (fcp->isp_loopstate > LOOP_LTEST_DONE) 3680 fcp->isp_loopstate = LOOP_LTEST_DONE; 3681 else if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3682 fcp->isp_loopstate = LOOP_HAVE_LINK; 3683 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, 3684 ISPASYNC_CHANGE_SNS, portid); 3685 break; 3686 } 3687 case ASYNC_ERR_LOGGING_DISABLED: 3688 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)", 3689 ISP_READ(isp, OUTMAILBOX1)); 3690 break; 3691 case ASYNC_P2P_INIT_ERR: 3692 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)", 3693 ISP_READ(isp, OUTMAILBOX1)); 3694 break; 3695 case ASYNC_RCV_ERR: 3696 isp_prt(isp, ISP_LOGWARN, "Receive Error"); 3697 break; 3698 case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */ 3699 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent"); 3700 break; 3701 case ASYNC_FW_RESTART_COMPLETE: 3702 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete"); 3703 break; 3704 case ASYNC_TEMPERATURE_ALERT: 3705 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)", 3706 ISP_READ(isp, OUTMAILBOX1)); 3707 break; 3708 case ASYNC_TRANSCEIVER_INSERTION: 3709 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)", 3710 ISP_READ(isp, OUTMAILBOX1)); 3711 break; 3712 case ASYNC_TRANSCEIVER_REMOVAL: 3713 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal"); 3714 break; 3715 case ASYNC_AUTOLOAD_FW_COMPLETE: 3716 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete"); 3717 break; 3718 case ASYNC_AUTOLOAD_FW_FAILURE: 3719 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure"); 3720 break; 3721 default: 3722 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox); 3723 break; 3724 } 3725 } 3726 3727 /* 3728 * Handle other response entries. A pointer to the request queue output 3729 * index is here in case we want to eat several entries at once, although 3730 * this is not used currently. 3731 */ 3732 3733 static int 3734 isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *optrp) 3735 { 3736 isp_ridacq_t rid; 3737 int chan, c; 3738 uint32_t hdl, portid; 3739 void *ptr; 3740 3741 switch (type) { 3742 case RQSTYPE_MARKER: 3743 isp_prt(isp, ISP_LOG_WARN1, "Marker Response"); 3744 return (1); 3745 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/ 3746 isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid); 3747 portid = (uint32_t)rid.ridacq_vp_port_hi << 16 | 3748 rid.ridacq_vp_port_lo; 3749 if (rid.ridacq_format == 0) { 3750 for (chan = 0; chan < isp->isp_nchan; chan++) { 3751 fcparam *fcp = FCPARAM(isp, chan); 3752 if (fcp->role == ISP_ROLE_NONE) 3753 continue; 3754 c = (chan == 0) ? 127 : (chan - 1); 3755 if (rid.ridacq_map[c / 16] & (1 << (c % 16)) || 3756 chan == 0) { 3757 fcp->isp_loopstate = LOOP_HAVE_LINK; 3758 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 3759 chan, ISPASYNC_CHANGE_OTHER); 3760 } else { 3761 fcp->isp_loopstate = LOOP_NIL; 3762 isp_async(isp, ISPASYNC_LOOP_DOWN, 3763 chan); 3764 } 3765 } 3766 } else { 3767 fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index); 3768 if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE || 3769 rid.ridacq_vp_status == RIDACQ_STS_CHANGED) { 3770 fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7; 3771 fcp->isp_portid = portid; 3772 fcp->isp_loopstate = LOOP_HAVE_ADDR; 3773 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 3774 rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER); 3775 } else { 3776 fcp->isp_loopstate = LOOP_NIL; 3777 isp_async(isp, ISPASYNC_LOOP_DOWN, 3778 rid.ridacq_vp_index); 3779 } 3780 } 3781 return (1); 3782 case RQSTYPE_CT_PASSTHRU: 3783 case RQSTYPE_VP_MODIFY: 3784 case RQSTYPE_VP_CTRL: 3785 case RQSTYPE_LOGIN: 3786 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl); 3787 ptr = isp_find_xs(isp, hdl); 3788 if (ptr != NULL) { 3789 isp_destroy_handle(isp, hdl); 3790 memcpy(ptr, hp, QENTRY_LEN); 3791 wakeup(ptr); 3792 } 3793 return (1); 3794 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue. */ 3795 case RQSTYPE_CTIO7: 3796 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue. */ 3797 case RQSTYPE_ABTS_RSP: 3798 #ifdef ISP_TARGET_MODE 3799 return (isp_target_notify(isp, hp, optrp)); 3800 #endif 3801 /* FALLTHROUGH */ 3802 default: 3803 return (0); 3804 } 3805 } 3806 3807 static void 3808 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs, uint32_t *rp) 3809 { 3810 int ru_marked, sv_marked; 3811 int chan = XS_CHANNEL(xs); 3812 3813 switch (sp->req_completion_status) { 3814 case RQCS_COMPLETE: 3815 if (XS_NOERR(xs)) { 3816 XS_SETERR(xs, HBA_NOERROR); 3817 } 3818 return; 3819 3820 case RQCS_DMA_ERROR: 3821 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error"); 3822 break; 3823 3824 case RQCS_TRANSPORT_ERROR: 3825 isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error"); 3826 break; 3827 3828 case RQCS_RESET_OCCURRED: 3829 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command"); 3830 FCPARAM(isp, chan)->sendmarker = 1; 3831 if (XS_NOERR(xs)) { 3832 XS_SETERR(xs, HBA_BUSRESET); 3833 } 3834 return; 3835 3836 case RQCS_ABORTED: 3837 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted"); 3838 FCPARAM(isp, chan)->sendmarker = 1; 3839 if (XS_NOERR(xs)) { 3840 XS_SETERR(xs, HBA_ABORTED); 3841 } 3842 return; 3843 3844 case RQCS_TIMEOUT: 3845 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out"); 3846 if (XS_NOERR(xs)) { 3847 XS_SETERR(xs, HBA_CMDTIMEOUT); 3848 } 3849 return; 3850 3851 case RQCS_DATA_OVERRUN: 3852 XS_SET_RESID(xs, sp->req_resid); 3853 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun"); 3854 if (XS_NOERR(xs)) { 3855 XS_SETERR(xs, HBA_DATAOVR); 3856 } 3857 return; 3858 3859 case RQCS_24XX_DRE: /* data reassembly error */ 3860 isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs)); 3861 if (XS_NOERR(xs)) { 3862 XS_SETERR(xs, HBA_ABORTED); 3863 } 3864 *rp = XS_XFRLEN(xs); 3865 return; 3866 3867 case RQCS_24XX_TABORT: /* aborted by target */ 3868 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs)); 3869 if (XS_NOERR(xs)) { 3870 XS_SETERR(xs, HBA_ABORTED); 3871 } 3872 return; 3873 3874 case RQCS_DATA_UNDERRUN: 3875 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0; 3876 /* 3877 * We can get an underrun w/o things being marked 3878 * if we got a non-zero status. 3879 */ 3880 sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0; 3881 if ((ru_marked == 0 && sv_marked == 0) || 3882 (sp->req_resid > XS_XFRLEN(xs))) { 3883 isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked"); 3884 if (XS_NOERR(xs)) { 3885 XS_SETERR(xs, HBA_BOTCH); 3886 } 3887 return; 3888 } 3889 XS_SET_RESID(xs, sp->req_resid); 3890 isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff); 3891 if (XS_NOERR(xs)) { 3892 XS_SETERR(xs, HBA_NOERROR); 3893 } 3894 return; 3895 3896 case RQCS_PORT_UNAVAILABLE: 3897 /* 3898 * No such port on the loop. Moral equivalent of SELTIMEO 3899 */ 3900 case RQCS_PORT_LOGGED_OUT: 3901 { 3902 const char *reason; 3903 uint8_t sts = sp->req_completion_status & 0xff; 3904 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs)); 3905 fcportdb_t *lp; 3906 3907 /* 3908 * It was there (maybe)- treat as a selection timeout. 3909 */ 3910 if (sts == RQCS_PORT_UNAVAILABLE) { 3911 reason = "unavailable"; 3912 } else { 3913 reason = "logout"; 3914 } 3915 3916 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d", 3917 chan, reason, XS_TGT(xs)); 3918 3919 /* XXX: Should we trigger rescan or FW announce change? */ 3920 3921 if (XS_NOERR(xs)) { 3922 lp = &fcp->portdb[XS_TGT(xs)]; 3923 if (lp->state == FC_PORTDB_STATE_ZOMBIE) { 3924 *XS_STSP(xs) = SCSI_BUSY; 3925 XS_SETERR(xs, HBA_TGTBSY); 3926 } else 3927 XS_SETERR(xs, HBA_SELTIMEOUT); 3928 } 3929 return; 3930 } 3931 case RQCS_PORT_CHANGED: 3932 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan); 3933 if (XS_NOERR(xs)) { 3934 *XS_STSP(xs) = SCSI_BUSY; 3935 XS_SETERR(xs, HBA_TGTBSY); 3936 } 3937 return; 3938 3939 case RQCS_24XX_ENOMEM: /* f/w resource unavailable */ 3940 isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan); 3941 if (XS_NOERR(xs)) { 3942 *XS_STSP(xs) = SCSI_BUSY; 3943 XS_SETERR(xs, HBA_TGTBSY); 3944 } 3945 return; 3946 3947 case RQCS_24XX_TMO: /* task management overrun */ 3948 isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan); 3949 if (XS_NOERR(xs)) { 3950 *XS_STSP(xs) = SCSI_BUSY; 3951 XS_SETERR(xs, HBA_TGTBSY); 3952 } 3953 return; 3954 3955 default: 3956 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan); 3957 break; 3958 } 3959 if (XS_NOERR(xs)) { 3960 XS_SETERR(xs, HBA_BOTCH); 3961 } 3962 } 3963 3964 #define ISP_FC_IBITS(op) ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3])) 3965 #define ISP_FC_OBITS(op) ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7])) 3966 3967 #define ISP_FC_OPMAP(in0, out0) 0, 0, 0, in0, 0, 0, 0, out0 3968 #define ISP_FC_OPMAP_HALF(in1, in0, out1, out0) 0, 0, in1, in0, 0, 0, out1, out0 3969 #define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0) in3, in2, in1, in0, out3, out2, out1, out0 3970 static const uint32_t mbpfc[] = { 3971 ISP_FC_OPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ 3972 ISP_FC_OPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ 3973 ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f), /* 0x02: MBOX_EXEC_FIRMWARE */ 3974 ISP_FC_OPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */ 3975 ISP_FC_OPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ 3976 ISP_FC_OPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ 3977 ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */ 3978 ISP_FC_OPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ 3979 ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f), /* 0x08: MBOX_ABOUT_FIRMWARE */ 3980 ISP_FC_OPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */ 3981 ISP_FC_OPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */ 3982 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */ 3983 ISP_FC_OPMAP(0x00, 0x00), /* 0x0c: */ 3984 ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */ 3985 ISP_FC_OPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ 3986 ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */ 3987 ISP_FC_OPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */ 3988 ISP_FC_OPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */ 3989 ISP_FC_OPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */ 3990 ISP_FC_OPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */ 3991 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03), /* 0x14: MBOX_STOP_FIRMWARE */ 3992 ISP_FC_OPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */ 3993 ISP_FC_OPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */ 3994 ISP_FC_OPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */ 3995 ISP_FC_OPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */ 3996 ISP_FC_OPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */ 3997 ISP_FC_OPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */ 3998 ISP_FC_OPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ 3999 ISP_FC_OPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */ 4000 ISP_FC_OPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ 4001 ISP_FC_OPMAP(0x00, 0x00), /* 0x1e: */ 4002 ISP_FC_OPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ 4003 ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf), /* 0x20: MBOX_GET_LOOP_ID */ 4004 ISP_FC_OPMAP(0x00, 0x00), /* 0x21: */ 4005 ISP_FC_OPMAP(0x03, 0x4b), /* 0x22: MBOX_GET_TIMEOUT_PARAMS */ 4006 ISP_FC_OPMAP(0x00, 0x00), /* 0x23: */ 4007 ISP_FC_OPMAP(0x00, 0x00), /* 0x24: */ 4008 ISP_FC_OPMAP(0x00, 0x00), /* 0x25: */ 4009 ISP_FC_OPMAP(0x00, 0x00), /* 0x26: */ 4010 ISP_FC_OPMAP(0x00, 0x00), /* 0x27: */ 4011 ISP_FC_OPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */ 4012 ISP_FC_OPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */ 4013 ISP_FC_OPMAP(0x00, 0x00), /* 0x2a: */ 4014 ISP_FC_OPMAP(0x00, 0x00), /* 0x2b: */ 4015 ISP_FC_OPMAP(0x00, 0x00), /* 0x2c: */ 4016 ISP_FC_OPMAP(0x00, 0x00), /* 0x2d: */ 4017 ISP_FC_OPMAP(0x00, 0x00), /* 0x2e: */ 4018 ISP_FC_OPMAP(0x00, 0x00), /* 0x2f: */ 4019 ISP_FC_OPMAP(0x00, 0x00), /* 0x30: */ 4020 ISP_FC_OPMAP(0x00, 0x00), /* 0x31: */ 4021 ISP_FC_OPMAP(0x4b, 0x4b), /* 0x32: MBOX_SET_TIMEOUT_PARAMS */ 4022 ISP_FC_OPMAP(0x00, 0x00), /* 0x33: */ 4023 ISP_FC_OPMAP(0x00, 0x00), /* 0x34: */ 4024 ISP_FC_OPMAP(0x00, 0x00), /* 0x35: */ 4025 ISP_FC_OPMAP(0x00, 0x00), /* 0x36: */ 4026 ISP_FC_OPMAP(0x00, 0x00), /* 0x37: */ 4027 ISP_FC_OPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */ 4028 ISP_FC_OPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */ 4029 ISP_FC_OPMAP(0x00, 0x00), /* 0x3a: */ 4030 ISP_FC_OPMAP(0x00, 0x00), /* 0x3b: */ 4031 ISP_FC_OPMAP(0x00, 0x00), /* 0x3c: */ 4032 ISP_FC_OPMAP(0x00, 0x00), /* 0x3d: */ 4033 ISP_FC_OPMAP(0x00, 0x00), /* 0x3e: */ 4034 ISP_FC_OPMAP(0x00, 0x00), /* 0x3f: */ 4035 ISP_FC_OPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */ 4036 ISP_FC_OPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */ 4037 ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf), /* 0x42: MBOX_GET_RESOURCE_COUNT */ 4038 ISP_FC_OPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */ 4039 ISP_FC_OPMAP(0x00, 0x00), /* 0x44: */ 4040 ISP_FC_OPMAP(0x00, 0x00), /* 0x45: */ 4041 ISP_FC_OPMAP(0x00, 0x00), /* 0x46: */ 4042 ISP_FC_OPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */ 4043 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */ 4044 ISP_FC_OPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */ 4045 ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */ 4046 ISP_FC_OPMAP(0x00, 0x00), /* 0x4b: */ 4047 ISP_FC_OPMAP(0x00, 0x00), /* 0x4c: */ 4048 ISP_FC_OPMAP(0x00, 0x00), /* 0x4d: */ 4049 ISP_FC_OPMAP(0x00, 0x00), /* 0x4e: */ 4050 ISP_FC_OPMAP(0x00, 0x00), /* 0x4f: */ 4051 ISP_FC_OPMAP(0x00, 0x00), /* 0x50: */ 4052 ISP_FC_OPMAP(0x00, 0x00), /* 0x51: */ 4053 ISP_FC_OPMAP(0x00, 0x00), /* 0x52: */ 4054 ISP_FC_OPMAP(0x00, 0x00), /* 0x53: */ 4055 ISP_FC_OPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */ 4056 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */ 4057 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */ 4058 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */ 4059 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */ 4060 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */ 4061 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */ 4062 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */ 4063 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */ 4064 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */ 4065 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */ 4066 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */ 4067 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */ 4068 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */ 4069 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ 4070 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ 4071 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */ 4072 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */ 4073 ISP_FC_OPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */ 4074 ISP_FC_OPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */ 4075 ISP_FC_OPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */ 4076 ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f), /* 0x69: MBOX_GET_FW_STATE */ 4077 ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */ 4078 ISP_FC_OPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */ 4079 ISP_FC_OPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */ 4080 ISP_FC_OPMAP(0x00, 0x00), /* 0x6d: */ 4081 ISP_FC_OPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */ 4082 ISP_FC_OPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */ 4083 ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03), /* 0x70: MBOX_SEND_CHANGE_REQUEST */ 4084 ISP_FC_OPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */ 4085 ISP_FC_OPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */ 4086 ISP_FC_OPMAP(0x00, 0x00), /* 0x73: */ 4087 ISP_FC_OPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */ 4088 ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07), /* 0x75: GET PORT/NODE NAME LIST */ 4089 ISP_FC_OPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */ 4090 ISP_FC_OPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */ 4091 ISP_FC_OPMAP(0x00, 0x00), /* 0x78: */ 4092 ISP_FC_OPMAP(0x00, 0x00), /* 0x79: */ 4093 ISP_FC_OPMAP(0x00, 0x00), /* 0x7a: */ 4094 ISP_FC_OPMAP(0x00, 0x00), /* 0x7b: */ 4095 ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07), /* 0x7c: Get ID List */ 4096 ISP_FC_OPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */ 4097 ISP_FC_OPMAP(0x0f, 0x01) /* 0x7e: LUN RESET */ 4098 }; 4099 #define MAX_FC_OPCODE 0x7e 4100 /* 4101 * Footnotes 4102 * 4103 * (1): this sets bits 21..16 in mailbox register #8, which we nominally 4104 * do not access at this time in the core driver. The caller is 4105 * responsible for setting this register first (Gross!). The assumption 4106 * is that we won't overflow. 4107 */ 4108 4109 static const char *fc_mbcmd_names[] = { 4110 "NO-OP", /* 00h */ 4111 "LOAD RAM", 4112 "EXEC FIRMWARE", 4113 "DUMP RAM", 4114 "WRITE RAM WORD", 4115 "READ RAM WORD", 4116 "MAILBOX REG TEST", 4117 "VERIFY CHECKSUM", 4118 "ABOUT FIRMWARE", 4119 "LOAD RAM (2100)", 4120 "DUMP RAM", 4121 "LOAD RISC RAM", 4122 "DUMP RISC RAM", 4123 "WRITE RAM WORD EXTENDED", 4124 "CHECK FIRMWARE", 4125 "READ RAM WORD EXTENDED", 4126 "INIT REQUEST QUEUE", /* 10h */ 4127 "INIT RESULT QUEUE", 4128 "EXECUTE IOCB", 4129 "WAKE UP", 4130 "STOP FIRMWARE", 4131 "ABORT", 4132 "ABORT DEVICE", 4133 "ABORT TARGET", 4134 "BUS RESET", 4135 "STOP QUEUE", 4136 "START QUEUE", 4137 "SINGLE STEP QUEUE", 4138 "ABORT QUEUE", 4139 "GET DEV QUEUE STATUS", 4140 NULL, 4141 "GET FIRMWARE STATUS", 4142 "GET LOOP ID", /* 20h */ 4143 NULL, 4144 "GET TIMEOUT PARAMS", 4145 NULL, 4146 NULL, 4147 NULL, 4148 NULL, 4149 NULL, 4150 "GET FIRMWARE OPTIONS", 4151 "GET PORT QUEUE PARAMS", 4152 "GENERATE SYSTEM ERROR", 4153 NULL, 4154 NULL, 4155 NULL, 4156 NULL, 4157 NULL, 4158 "WRITE SFP", /* 30h */ 4159 "READ SFP", 4160 "SET TIMEOUT PARAMS", 4161 NULL, 4162 NULL, 4163 NULL, 4164 NULL, 4165 NULL, 4166 "SET FIRMWARE OPTIONS", 4167 "SET PORT QUEUE PARAMS", 4168 NULL, 4169 "SET FC LED CONF", 4170 NULL, 4171 "RESTART NIC FIRMWARE", 4172 "ACCESS CONTROL", 4173 NULL, 4174 "LOOP PORT BYPASS", /* 40h */ 4175 "LOOP PORT ENABLE", 4176 "GET RESOURCE COUNT", 4177 "REQUEST NON PARTICIPATING MODE", 4178 "DIAGNOSTIC ECHO TEST", 4179 "DIAGNOSTIC LOOPBACK", 4180 NULL, 4181 "GET PORT DATABASE ENHANCED", 4182 "INIT FIRMWARE MULTI ID", 4183 "GET VP DATABASE", 4184 "GET VP DATABASE ENTRY", 4185 NULL, 4186 NULL, 4187 NULL, 4188 NULL, 4189 NULL, 4190 "GET FCF LIST", /* 50h */ 4191 "GET DCBX PARAMETERS", 4192 NULL, 4193 "HOST MEMORY COPY", 4194 "EXECUTE IOCB A64", 4195 NULL, 4196 NULL, 4197 "SEND RNID", 4198 NULL, 4199 "SET PARAMETERS", 4200 "GET PARAMETERS", 4201 "DRIVER HEARTBEAT", 4202 "FIRMWARE HEARTBEAT", 4203 "GET/SET DATA RATE", 4204 "SEND RNFT", 4205 NULL, 4206 "INIT FIRMWARE", /* 60h */ 4207 "GET INIT CONTROL BLOCK", 4208 "INIT LIP", 4209 "GET FC-AL POSITION MAP", 4210 "GET PORT DATABASE", 4211 "CLEAR ACA", 4212 "TARGET RESET", 4213 "CLEAR TASK SET", 4214 "ABORT TASK SET", 4215 "GET FW STATE", 4216 "GET PORT NAME", 4217 "GET LINK STATUS", 4218 "INIT LIP RESET", 4219 "GET LINK STATS & PRIVATE DATA CNTS", 4220 "SEND SNS", 4221 "FABRIC LOGIN", 4222 "SEND CHANGE REQUEST", /* 70h */ 4223 "FABRIC LOGOUT", 4224 "INIT LIP LOGIN", 4225 NULL, 4226 "LOGIN LOOP PORT", 4227 "GET PORT/NODE NAME LIST", 4228 "SET VENDOR ID", 4229 "INITIALIZE IP MAILBOX", 4230 NULL, 4231 NULL, 4232 "GET XGMAC STATS", 4233 NULL, 4234 "GET ID LIST", 4235 "SEND LFA", 4236 "LUN RESET" 4237 }; 4238 4239 static void 4240 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp) 4241 { 4242 const char *cname, *xname, *sname; 4243 char tname[16], mname[16]; 4244 unsigned int ibits, obits, box, opcode; 4245 4246 opcode = mbp->param[0]; 4247 if (opcode > MAX_FC_OPCODE) { 4248 mbp->param[0] = MBOX_INVALID_COMMAND; 4249 isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode); 4250 return; 4251 } 4252 cname = fc_mbcmd_names[opcode]; 4253 ibits = ISP_FC_IBITS(opcode); 4254 obits = ISP_FC_OBITS(opcode); 4255 if (cname == NULL) { 4256 cname = tname; 4257 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode); 4258 } 4259 isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname); 4260 4261 /* 4262 * Pick up any additional bits that the caller might have set. 4263 */ 4264 ibits |= mbp->ibits; 4265 obits |= mbp->obits; 4266 4267 /* 4268 * Mask any bits that the caller wants us to mask 4269 */ 4270 ibits &= mbp->ibitm; 4271 obits &= mbp->obitm; 4272 4273 4274 if (ibits == 0 && obits == 0) { 4275 mbp->param[0] = MBOX_COMMAND_PARAM_ERROR; 4276 isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode); 4277 return; 4278 } 4279 4280 /* 4281 * Get exclusive usage of mailbox registers. 4282 */ 4283 if (MBOX_ACQUIRE(isp)) { 4284 mbp->param[0] = MBOX_REGS_BUSY; 4285 goto out; 4286 } 4287 4288 for (box = 0; box < ISP_NMBOX(isp); box++) { 4289 if (ibits & (1 << box)) { 4290 isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box, 4291 mbp->param[box]); 4292 ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); 4293 } 4294 isp->isp_mboxtmp[box] = mbp->param[box] = 0; 4295 } 4296 4297 isp->isp_lastmbxcmd = opcode; 4298 4299 /* 4300 * We assume that we can't overwrite a previous command. 4301 */ 4302 isp->isp_obits = obits; 4303 isp->isp_mboxbsy = 1; 4304 4305 /* 4306 * Set Host Interrupt condition so that RISC will pick up mailbox regs. 4307 */ 4308 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT); 4309 4310 /* 4311 * While we haven't finished the command, spin our wheels here. 4312 */ 4313 MBOX_WAIT_COMPLETE(isp, mbp); 4314 4315 /* 4316 * Did the command time out? 4317 */ 4318 if (mbp->param[0] == MBOX_TIMEOUT) { 4319 isp->isp_mboxbsy = 0; 4320 MBOX_RELEASE(isp); 4321 goto out; 4322 } 4323 4324 /* 4325 * Copy back output registers. 4326 */ 4327 for (box = 0; box < ISP_NMBOX(isp); box++) { 4328 if (obits & (1 << box)) { 4329 mbp->param[box] = isp->isp_mboxtmp[box]; 4330 isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box, 4331 mbp->param[box]); 4332 } 4333 } 4334 4335 isp->isp_mboxbsy = 0; 4336 MBOX_RELEASE(isp); 4337 out: 4338 if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE) 4339 return; 4340 4341 if ((mbp->param[0] & 0xbfe0) == 0 && 4342 (mbp->logval & MBLOGMASK(mbp->param[0])) == 0) 4343 return; 4344 4345 xname = NULL; 4346 sname = ""; 4347 switch (mbp->param[0]) { 4348 case MBOX_INVALID_COMMAND: 4349 xname = "INVALID COMMAND"; 4350 break; 4351 case MBOX_HOST_INTERFACE_ERROR: 4352 xname = "HOST INTERFACE ERROR"; 4353 break; 4354 case MBOX_TEST_FAILED: 4355 xname = "TEST FAILED"; 4356 break; 4357 case MBOX_COMMAND_ERROR: 4358 xname = "COMMAND ERROR"; 4359 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x", 4360 mbp->param[1]); 4361 sname = mname; 4362 break; 4363 case MBOX_COMMAND_PARAM_ERROR: 4364 xname = "COMMAND PARAMETER ERROR"; 4365 break; 4366 case MBOX_PORT_ID_USED: 4367 xname = "PORT ID ALREADY IN USE"; 4368 break; 4369 case MBOX_LOOP_ID_USED: 4370 xname = "LOOP ID ALREADY IN USE"; 4371 break; 4372 case MBOX_ALL_IDS_USED: 4373 xname = "ALL LOOP IDS IN USE"; 4374 break; 4375 case MBOX_NOT_LOGGED_IN: 4376 xname = "NOT LOGGED IN"; 4377 break; 4378 case MBOX_LINK_DOWN_ERROR: 4379 xname = "LINK DOWN ERROR"; 4380 break; 4381 case MBOX_LOOPBACK_ERROR: 4382 xname = "LOOPBACK ERROR"; 4383 break; 4384 case MBOX_CHECKSUM_ERROR: 4385 xname = "CHECKSUM ERROR"; 4386 break; 4387 case MBOX_INVALID_PRODUCT_KEY: 4388 xname = "INVALID PRODUCT KEY"; 4389 break; 4390 case MBOX_REGS_BUSY: 4391 xname = "REGISTERS BUSY"; 4392 break; 4393 case MBOX_TIMEOUT: 4394 xname = "TIMEOUT"; 4395 break; 4396 default: 4397 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]); 4398 xname = mname; 4399 break; 4400 } 4401 if (xname) { 4402 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)", 4403 cname, xname, sname); 4404 } 4405 } 4406 4407 static int 4408 isp_fw_state(ispsoftc_t *isp, int chan) 4409 { 4410 mbreg_t mbs; 4411 4412 MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0); 4413 isp_mboxcmd(isp, &mbs); 4414 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) 4415 return (mbs.param[1]); 4416 return (FW_ERROR); 4417 } 4418 4419 static void 4420 isp_setdfltfcparm(ispsoftc_t *isp, int chan) 4421 { 4422 fcparam *fcp = FCPARAM(isp, chan); 4423 4424 /* 4425 * Establish some default parameters. 4426 */ 4427 fcp->role = DEFAULT_ROLE(isp, chan); 4428 fcp->isp_maxalloc = ICB_DFLT_ALLOC; 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 exchg_cnt %d 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_EXCHANGE_COUNT(nvram_data), 4603 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data)); 4604 isp_prt(isp, ISP_LOGDEBUG0, 4605 "NVRAM execthr %d loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", 4606 ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data), 4607 ISP2400_NVRAM_HARDLOOPID(nvram_data), 4608 ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data), 4609 ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data), 4610 ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data)); 4611 4612 wwn = ISP2400_NVRAM_PORT_NAME(nvram_data); 4613 fcp->isp_wwpn_nvram = wwn; 4614 4615 wwn = ISP2400_NVRAM_NODE_NAME(nvram_data); 4616 if (wwn) { 4617 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) { 4618 wwn = 0; 4619 } 4620 } 4621 if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) { 4622 wwn = fcp->isp_wwpn_nvram; 4623 wwn &= ~((uint64_t) 0xfff << 48); 4624 } 4625 fcp->isp_wwnn_nvram = wwn; 4626 4627 if (ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data)) { 4628 fcp->isp_maxalloc = ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data); 4629 } 4630 if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) { 4631 DEFAULT_FRAMESIZE(isp) = 4632 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data); 4633 } 4634 if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { 4635 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data); 4636 } 4637 if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) { 4638 DEFAULT_EXEC_THROTTLE(isp) = 4639 ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data); 4640 } 4641 fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data); 4642 fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data); 4643 fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data); 4644 } 4645