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