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 ispstatus_cont_t *scp = (ispstatus_cont_t *)qe; 3229 isphdr_t *hp; 3230 uint8_t *resp, *snsp; 3231 int buddaboom, completion_status, cont = 0, etype, i; 3232 int req_status_flags, req_state_flags, scsi_status; 3233 uint32_t iptr, cptr, optr, rlen, slen, sptr, totslen, resid; 3234 3235 /* 3236 * We can't be getting this now. 3237 */ 3238 if (isp->isp_state != ISP_RUNSTATE) { 3239 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready"); 3240 return; 3241 } 3242 3243 iptr = ISP_READ(isp, BIU2400_RSPINP); 3244 optr = isp->isp_resodx; 3245 while (optr != iptr) { 3246 sptr = cptr = optr; 3247 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr); 3248 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp)); 3249 3250 /* 3251 * Synchronize our view of this response queue entry. 3252 */ 3253 MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1); 3254 if (isp->isp_dblev & ISP_LOGDEBUG1) 3255 isp_print_qentry(isp, "Response Queue Entry", cptr, hp); 3256 isp_get_hdr(isp, hp, &sp->req_header); 3257 etype = sp->req_header.rqs_entry_type; 3258 3259 /* We expected Status Continuation, but got different IOCB. */ 3260 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) { 3261 cont = 0; 3262 isp_done(cont_xs); 3263 } 3264 3265 if (etype == RQSTYPE_RESPONSE) { 3266 isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp); 3267 scsi_status = sp->req_scsi_status; 3268 completion_status = sp->req_completion_status; 3269 req_status_flags = 0; 3270 if ((scsi_status & 0xff) != 0) 3271 req_state_flags = RQSF_GOT_STATUS; 3272 else 3273 req_state_flags = 0; 3274 resid = sp->req_resid; 3275 } else if (etype == RQSTYPE_STATUS_CONT) { 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_BADTYPE) { 3314 isp_print_qentry(isp, "invalid entry type", 3315 cptr, hp); 3316 buddaboom++; 3317 } 3318 if (sp->req_header.rqs_flags & RQSFLAG_BADPARAM) { 3319 isp_print_qentry(isp, "invalid entry parameter", 3320 cptr, hp); 3321 buddaboom++; 3322 } 3323 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) { 3324 isp_print_qentry(isp, "invalid entry count", 3325 cptr, hp); 3326 buddaboom++; 3327 } 3328 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) { 3329 isp_print_qentry(isp, "invalid entry order", 3330 cptr, hp); 3331 continue; 3332 } 3333 } 3334 3335 xs = isp_find_xs(isp, sp->req_handle); 3336 if (xs == NULL) { 3337 uint8_t ts = completion_status & 0xff; 3338 /* 3339 * Only whine if this isn't the expected fallout of 3340 * aborting the command or resetting the target. 3341 */ 3342 if (etype != RQSTYPE_RESPONSE) { 3343 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype); 3344 } else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED) { 3345 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts); 3346 } 3347 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3348 continue; 3349 } 3350 if (req_status_flags & RQSTF_BUS_RESET) { 3351 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx bus was reset", 3352 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs)); 3353 XS_SETERR(xs, HBA_BUSRESET); 3354 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1); 3355 } 3356 if (buddaboom) { 3357 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx buddaboom", 3358 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs)); 3359 XS_SETERR(xs, HBA_BOTCH); 3360 } 3361 3362 resp = snsp = NULL; 3363 rlen = slen = totslen = 0; 3364 if ((scsi_status & (RQCS_RV|RQCS_SV)) != 0) { 3365 resp = sp->req_rsp_sense; 3366 rlen = sp->req_response_len; 3367 } 3368 if ((scsi_status & RQCS_SV) != 0) { 3369 /* 3370 * Fibre Channel F/W doesn't say we got status 3371 * if there's Sense Data instead. I guess they 3372 * think it goes w/o saying. 3373 */ 3374 req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE; 3375 snsp = sp->req_rsp_sense + rlen; 3376 totslen = sp->req_sense_len; 3377 slen = sizeof(sp->req_rsp_sense) - rlen; 3378 } 3379 if (slen > totslen) 3380 slen = totslen; 3381 if (req_state_flags & RQSF_GOT_STATUS) 3382 *XS_STSP(xs) = scsi_status & 0xff; 3383 3384 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) { 3385 const char *ptr; 3386 char lb[64]; 3387 const char *rnames[10] = { 3388 "Task Management function complete", 3389 "FCP_DATA length different than FCP_BURST_LEN", 3390 "FCP_CMND fields invalid", 3391 "FCP_DATA parameter mismatch with FCP_DATA_RO", 3392 "Task Management function rejected", 3393 "Task Management function failed", 3394 NULL, 3395 NULL, 3396 "Task Management function succeeded", 3397 "Task Management function incorrect logical unit number", 3398 }; 3399 uint8_t code = resp[FCP_RSPNS_CODE_OFFSET]; 3400 if (code >= 10 || rnames[code] == NULL) { 3401 ISP_SNPRINTF(lb, sizeof(lb), 3402 "Unknown FCP Response Code 0x%x", code); 3403 ptr = lb; 3404 } else { 3405 ptr = rnames[code]; 3406 } 3407 isp_xs_prt(isp, xs, ISP_LOGWARN, 3408 "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x", 3409 rlen, ptr, XS_CDBP(xs)[0] & 0xff); 3410 if (code != 0 && code != 8) 3411 XS_SETERR(xs, HBA_BOTCH); 3412 } 3413 isp_parse_status_24xx(isp, sp, xs, &resid); 3414 if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) && 3415 (*XS_STSP(xs) == SCSI_BUSY)) 3416 XS_SETERR(xs, HBA_TGTBSY); 3417 if (req_status_flags & RQSF_XFER_COMPLETE) { 3418 XS_SET_RESID(xs, 0); 3419 } else if (scsi_status & RQCS_RESID) { 3420 XS_SET_RESID(xs, resid); 3421 } else { 3422 XS_SET_RESID(xs, 0); 3423 } 3424 if (slen > 0) { 3425 XS_SAVE_SENSE(xs, snsp, slen); 3426 if (totslen > slen) { 3427 cont = totslen - slen; 3428 cont_xs = xs; 3429 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN, 3430 "Expecting Status Continuations for %u bytes", 3431 cont); 3432 } 3433 } 3434 isp_prt(isp, ISP_LOGDEBUG2, "asked for %lu got raw resid %lu settled for %lu", 3435 (u_long)XS_XFRLEN(xs), (u_long)resid, (u_long)XS_GET_RESID(xs)); 3436 3437 ISP_DMAFREE(isp, xs); 3438 isp_destroy_handle(isp, sp->req_handle); 3439 3440 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ 3441 3442 /* Complete command if we expect no Status Continuations. */ 3443 if (cont == 0) 3444 isp_done(xs); 3445 } 3446 3447 /* We haven't received all Status Continuations, but that is it. */ 3448 if (cont > 0) 3449 isp_done(cont_xs); 3450 3451 /* If we processed any IOCBs, let ISP know about it. */ 3452 if (optr != isp->isp_resodx) { 3453 ISP_WRITE(isp, BIU2400_RSPOUTP, optr); 3454 isp->isp_resodx = optr; 3455 } 3456 } 3457 3458 3459 void 3460 isp_intr_async(ispsoftc_t *isp, uint16_t mbox) 3461 { 3462 fcparam *fcp; 3463 uint16_t chan; 3464 3465 isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox); 3466 3467 switch (mbox) { 3468 case ASYNC_SYSTEM_ERROR: 3469 isp->isp_state = ISP_CRASHED; 3470 for (chan = 0; chan < isp->isp_nchan; chan++) { 3471 FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL; 3472 isp_change_fw_state(isp, chan, FW_CONFIG_WAIT); 3473 } 3474 /* 3475 * Were we waiting for a mailbox command to complete? 3476 * If so, it's dead, so wake up the waiter. 3477 */ 3478 if (isp->isp_mboxbsy) { 3479 isp->isp_obits = 1; 3480 isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR; 3481 isp->isp_mboxbsy = 0; 3482 } 3483 /* 3484 * It's up to the handler for isp_async to reinit stuff and 3485 * restart the firmware 3486 */ 3487 isp_async(isp, ISPASYNC_FW_CRASH); 3488 break; 3489 3490 case ASYNC_RQS_XFER_ERR: 3491 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error"); 3492 break; 3493 3494 case ASYNC_RSP_XFER_ERR: 3495 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error"); 3496 break; 3497 3498 case ASYNC_ATIO_XFER_ERR: 3499 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error"); 3500 break; 3501 3502 case ASYNC_LIP_OCCURRED: 3503 case ASYNC_LIP_NOS_OLS_RECV: 3504 case ASYNC_LIP_ERROR: 3505 case ASYNC_PTPMODE: 3506 /* 3507 * These are broadcast events that have to be sent across 3508 * all active channels. 3509 */ 3510 for (chan = 0; chan < isp->isp_nchan; chan++) { 3511 fcp = FCPARAM(isp, chan); 3512 int topo = fcp->isp_topo; 3513 3514 if (fcp->role == ISP_ROLE_NONE) 3515 continue; 3516 if (fcp->isp_loopstate > LOOP_HAVE_LINK) 3517 fcp->isp_loopstate = LOOP_HAVE_LINK; 3518 ISP_SET_SENDMARKER(isp, chan, 1); 3519 isp_async(isp, ISPASYNC_LIP, chan); 3520 #ifdef ISP_TARGET_MODE 3521 isp_target_async(isp, chan, mbox); 3522 #endif 3523 /* 3524 * We've had problems with data corruption occurring on 3525 * commands that complete (with no apparent error) after 3526 * we receive a LIP. This has been observed mostly on 3527 * Local Loop topologies. To be safe, let's just mark 3528 * all active initiator commands as dead. 3529 */ 3530 if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) { 3531 int i, j; 3532 for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) { 3533 XS_T *xs; 3534 isp_hdl_t *hdp; 3535 3536 hdp = &isp->isp_xflist[i]; 3537 if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) { 3538 continue; 3539 } 3540 xs = hdp->cmd; 3541 if (XS_CHANNEL(xs) != chan) { 3542 continue; 3543 } 3544 j++; 3545 isp_prt(isp, ISP_LOG_WARN1, 3546 "%d.%d.%jx bus reset set at %s:%u", 3547 XS_CHANNEL(xs), XS_TGT(xs), 3548 (uintmax_t)XS_LUN(xs), 3549 __func__, __LINE__); 3550 XS_SETERR(xs, HBA_BUSRESET); 3551 } 3552 if (j) { 3553 isp_prt(isp, ISP_LOGERR, lipd, chan, j); 3554 } 3555 } 3556 } 3557 break; 3558 3559 case ASYNC_LOOP_UP: 3560 /* 3561 * This is a broadcast event that has to be sent across 3562 * all active channels. 3563 */ 3564 for (chan = 0; chan < isp->isp_nchan; chan++) { 3565 fcp = FCPARAM(isp, chan); 3566 if (fcp->role == ISP_ROLE_NONE) 3567 continue; 3568 fcp->isp_linkstate = 1; 3569 if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3570 fcp->isp_loopstate = LOOP_HAVE_LINK; 3571 ISP_SET_SENDMARKER(isp, chan, 1); 3572 isp_async(isp, ISPASYNC_LOOP_UP, chan); 3573 #ifdef ISP_TARGET_MODE 3574 isp_target_async(isp, chan, mbox); 3575 #endif 3576 } 3577 break; 3578 3579 case ASYNC_LOOP_DOWN: 3580 /* 3581 * This is a broadcast event that has to be sent across 3582 * all active channels. 3583 */ 3584 for (chan = 0; chan < isp->isp_nchan; chan++) { 3585 fcp = FCPARAM(isp, chan); 3586 if (fcp->role == ISP_ROLE_NONE) 3587 continue; 3588 ISP_SET_SENDMARKER(isp, chan, 1); 3589 fcp->isp_linkstate = 0; 3590 fcp->isp_loopstate = LOOP_NIL; 3591 isp_async(isp, ISPASYNC_LOOP_DOWN, chan); 3592 #ifdef ISP_TARGET_MODE 3593 isp_target_async(isp, chan, mbox); 3594 #endif 3595 } 3596 break; 3597 3598 case ASYNC_LOOP_RESET: 3599 /* 3600 * This is a broadcast event that has to be sent across 3601 * all active channels. 3602 */ 3603 for (chan = 0; chan < isp->isp_nchan; chan++) { 3604 fcp = FCPARAM(isp, chan); 3605 if (fcp->role == ISP_ROLE_NONE) 3606 continue; 3607 ISP_SET_SENDMARKER(isp, chan, 1); 3608 if (fcp->isp_loopstate > LOOP_HAVE_LINK) 3609 fcp->isp_loopstate = LOOP_HAVE_LINK; 3610 isp_async(isp, ISPASYNC_LOOP_RESET, chan); 3611 #ifdef ISP_TARGET_MODE 3612 isp_target_async(isp, chan, mbox); 3613 #endif 3614 } 3615 break; 3616 3617 case ASYNC_PDB_CHANGED: 3618 { 3619 int echan, nphdl, nlstate, reason; 3620 3621 nphdl = ISP_READ(isp, OUTMAILBOX1); 3622 nlstate = ISP_READ(isp, OUTMAILBOX2); 3623 reason = ISP_READ(isp, OUTMAILBOX3) >> 8; 3624 if (ISP_CAP_MULTI_ID(isp)) { 3625 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; 3626 if (chan == 0xff || nphdl == NIL_HANDLE) { 3627 chan = 0; 3628 echan = isp->isp_nchan - 1; 3629 } else if (chan >= isp->isp_nchan) { 3630 break; 3631 } else { 3632 echan = chan; 3633 } 3634 } else { 3635 chan = echan = 0; 3636 } 3637 for (; chan <= echan; chan++) { 3638 fcp = FCPARAM(isp, chan); 3639 if (fcp->role == ISP_ROLE_NONE) 3640 continue; 3641 if (fcp->isp_loopstate > LOOP_LTEST_DONE) { 3642 if (nphdl != NIL_HANDLE && 3643 nphdl == fcp->isp_login_hdl && 3644 reason == PDB24XX_AE_OPN_2) 3645 continue; 3646 fcp->isp_loopstate = LOOP_LTEST_DONE; 3647 } else if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3648 fcp->isp_loopstate = LOOP_HAVE_LINK; 3649 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, 3650 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason); 3651 } 3652 break; 3653 } 3654 case ASYNC_CHANGE_NOTIFY: 3655 { 3656 int portid; 3657 3658 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) | 3659 ISP_READ(isp, OUTMAILBOX2); 3660 if (ISP_CAP_MULTI_ID(isp)) { 3661 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; 3662 if (chan >= isp->isp_nchan) 3663 break; 3664 } else { 3665 chan = 0; 3666 } 3667 fcp = FCPARAM(isp, chan); 3668 if (fcp->role == ISP_ROLE_NONE) 3669 break; 3670 if (fcp->isp_loopstate > LOOP_LTEST_DONE) 3671 fcp->isp_loopstate = LOOP_LTEST_DONE; 3672 else if (fcp->isp_loopstate < LOOP_HAVE_LINK) 3673 fcp->isp_loopstate = LOOP_HAVE_LINK; 3674 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, 3675 ISPASYNC_CHANGE_SNS, portid); 3676 break; 3677 } 3678 case ASYNC_ERR_LOGGING_DISABLED: 3679 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)", 3680 ISP_READ(isp, OUTMAILBOX1)); 3681 break; 3682 case ASYNC_P2P_INIT_ERR: 3683 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)", 3684 ISP_READ(isp, OUTMAILBOX1)); 3685 break; 3686 case ASYNC_RCV_ERR: 3687 isp_prt(isp, ISP_LOGWARN, "Receive Error"); 3688 break; 3689 case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */ 3690 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent"); 3691 break; 3692 case ASYNC_FW_RESTART_COMPLETE: 3693 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete"); 3694 break; 3695 case ASYNC_TEMPERATURE_ALERT: 3696 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)", 3697 ISP_READ(isp, OUTMAILBOX1)); 3698 break; 3699 case ASYNC_TRANSCEIVER_INSERTION: 3700 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)", 3701 ISP_READ(isp, OUTMAILBOX1)); 3702 break; 3703 case ASYNC_TRANSCEIVER_REMOVAL: 3704 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal"); 3705 break; 3706 case ASYNC_AUTOLOAD_FW_COMPLETE: 3707 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete"); 3708 break; 3709 case ASYNC_AUTOLOAD_FW_FAILURE: 3710 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure"); 3711 break; 3712 default: 3713 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox); 3714 break; 3715 } 3716 } 3717 3718 /* 3719 * Handle other response entries. A pointer to the request queue output 3720 * index is here in case we want to eat several entries at once, although 3721 * this is not used currently. 3722 */ 3723 3724 static int 3725 isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *optrp, uint16_t ql) 3726 { 3727 isp_ridacq_t rid; 3728 int chan, c; 3729 uint32_t hdl, portid; 3730 void *ptr; 3731 3732 switch (type) { 3733 case RQSTYPE_MARKER: 3734 isp_prt(isp, ISP_LOG_WARN1, "Marker Response"); 3735 return (1); 3736 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/ 3737 isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid); 3738 portid = (uint32_t)rid.ridacq_vp_port_hi << 16 | 3739 rid.ridacq_vp_port_lo; 3740 if (rid.ridacq_format == 0) { 3741 for (chan = 0; chan < isp->isp_nchan; chan++) { 3742 fcparam *fcp = FCPARAM(isp, chan); 3743 if (fcp->role == ISP_ROLE_NONE) 3744 continue; 3745 c = (chan == 0) ? 127 : (chan - 1); 3746 if (rid.ridacq_map[c / 16] & (1 << (c % 16)) || 3747 chan == 0) { 3748 fcp->isp_loopstate = LOOP_HAVE_LINK; 3749 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 3750 chan, ISPASYNC_CHANGE_OTHER); 3751 } else { 3752 fcp->isp_loopstate = LOOP_NIL; 3753 isp_async(isp, ISPASYNC_LOOP_DOWN, 3754 chan); 3755 } 3756 } 3757 } else { 3758 fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index); 3759 if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE || 3760 rid.ridacq_vp_status == RIDACQ_STS_CHANGED) { 3761 fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7; 3762 fcp->isp_portid = portid; 3763 fcp->isp_loopstate = LOOP_HAVE_ADDR; 3764 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 3765 rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER); 3766 } else { 3767 fcp->isp_loopstate = LOOP_NIL; 3768 isp_async(isp, ISPASYNC_LOOP_DOWN, 3769 rid.ridacq_vp_index); 3770 } 3771 } 3772 return (1); 3773 case RQSTYPE_CT_PASSTHRU: 3774 case RQSTYPE_VP_MODIFY: 3775 case RQSTYPE_VP_CTRL: 3776 case RQSTYPE_LOGIN: 3777 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl); 3778 ptr = isp_find_xs(isp, hdl); 3779 if (ptr != NULL) { 3780 isp_destroy_handle(isp, hdl); 3781 memcpy(ptr, hp, QENTRY_LEN); 3782 wakeup(ptr); 3783 } 3784 return (1); 3785 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue. */ 3786 case RQSTYPE_CTIO7: 3787 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue. */ 3788 case RQSTYPE_ABTS_RSP: 3789 #ifdef ISP_TARGET_MODE 3790 return (isp_target_notify(isp, hp, optrp, ql)); 3791 #endif 3792 /* FALLTHROUGH */ 3793 default: 3794 return (0); 3795 } 3796 } 3797 3798 static void 3799 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs, uint32_t *rp) 3800 { 3801 int ru_marked, sv_marked; 3802 int chan = XS_CHANNEL(xs); 3803 3804 switch (sp->req_completion_status) { 3805 case RQCS_COMPLETE: 3806 if (XS_NOERR(xs)) { 3807 XS_SETERR(xs, HBA_NOERROR); 3808 } 3809 return; 3810 3811 case RQCS_DMA_ERROR: 3812 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error"); 3813 break; 3814 3815 case RQCS_TRANSPORT_ERROR: 3816 isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error"); 3817 break; 3818 3819 case RQCS_RESET_OCCURRED: 3820 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command"); 3821 FCPARAM(isp, chan)->sendmarker = 1; 3822 if (XS_NOERR(xs)) { 3823 XS_SETERR(xs, HBA_BUSRESET); 3824 } 3825 return; 3826 3827 case RQCS_ABORTED: 3828 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted"); 3829 FCPARAM(isp, chan)->sendmarker = 1; 3830 if (XS_NOERR(xs)) { 3831 XS_SETERR(xs, HBA_ABORTED); 3832 } 3833 return; 3834 3835 case RQCS_TIMEOUT: 3836 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out"); 3837 if (XS_NOERR(xs)) { 3838 XS_SETERR(xs, HBA_CMDTIMEOUT); 3839 } 3840 return; 3841 3842 case RQCS_DATA_OVERRUN: 3843 XS_SET_RESID(xs, sp->req_resid); 3844 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun"); 3845 if (XS_NOERR(xs)) { 3846 XS_SETERR(xs, HBA_DATAOVR); 3847 } 3848 return; 3849 3850 case RQCS_24XX_DRE: /* data reassembly error */ 3851 isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs)); 3852 if (XS_NOERR(xs)) { 3853 XS_SETERR(xs, HBA_ABORTED); 3854 } 3855 *rp = XS_XFRLEN(xs); 3856 return; 3857 3858 case RQCS_24XX_TABORT: /* aborted by target */ 3859 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs)); 3860 if (XS_NOERR(xs)) { 3861 XS_SETERR(xs, HBA_ABORTED); 3862 } 3863 return; 3864 3865 case RQCS_DATA_UNDERRUN: 3866 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0; 3867 /* 3868 * We can get an underrun w/o things being marked 3869 * if we got a non-zero status. 3870 */ 3871 sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0; 3872 if ((ru_marked == 0 && sv_marked == 0) || 3873 (sp->req_resid > XS_XFRLEN(xs))) { 3874 isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked"); 3875 if (XS_NOERR(xs)) { 3876 XS_SETERR(xs, HBA_BOTCH); 3877 } 3878 return; 3879 } 3880 XS_SET_RESID(xs, sp->req_resid); 3881 isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff); 3882 if (XS_NOERR(xs)) { 3883 XS_SETERR(xs, HBA_NOERROR); 3884 } 3885 return; 3886 3887 case RQCS_PORT_UNAVAILABLE: 3888 /* 3889 * No such port on the loop. Moral equivalent of SELTIMEO 3890 */ 3891 case RQCS_PORT_LOGGED_OUT: 3892 { 3893 const char *reason; 3894 uint8_t sts = sp->req_completion_status & 0xff; 3895 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs)); 3896 fcportdb_t *lp; 3897 3898 /* 3899 * It was there (maybe)- treat as a selection timeout. 3900 */ 3901 if (sts == RQCS_PORT_UNAVAILABLE) { 3902 reason = "unavailable"; 3903 } else { 3904 reason = "logout"; 3905 } 3906 3907 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d", 3908 chan, reason, XS_TGT(xs)); 3909 3910 /* XXX: Should we trigger rescan or FW announce change? */ 3911 3912 if (XS_NOERR(xs)) { 3913 lp = &fcp->portdb[XS_TGT(xs)]; 3914 if (lp->state == FC_PORTDB_STATE_ZOMBIE) { 3915 *XS_STSP(xs) = SCSI_BUSY; 3916 XS_SETERR(xs, HBA_TGTBSY); 3917 } else 3918 XS_SETERR(xs, HBA_SELTIMEOUT); 3919 } 3920 return; 3921 } 3922 case RQCS_PORT_CHANGED: 3923 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan); 3924 if (XS_NOERR(xs)) { 3925 *XS_STSP(xs) = SCSI_BUSY; 3926 XS_SETERR(xs, HBA_TGTBSY); 3927 } 3928 return; 3929 3930 case RQCS_24XX_ENOMEM: /* f/w resource unavailable */ 3931 isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan); 3932 if (XS_NOERR(xs)) { 3933 *XS_STSP(xs) = SCSI_BUSY; 3934 XS_SETERR(xs, HBA_TGTBSY); 3935 } 3936 return; 3937 3938 case RQCS_24XX_TMO: /* task management overrun */ 3939 isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan); 3940 if (XS_NOERR(xs)) { 3941 *XS_STSP(xs) = SCSI_BUSY; 3942 XS_SETERR(xs, HBA_TGTBSY); 3943 } 3944 return; 3945 3946 default: 3947 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan); 3948 break; 3949 } 3950 if (XS_NOERR(xs)) { 3951 XS_SETERR(xs, HBA_BOTCH); 3952 } 3953 } 3954 3955 #define ISP_FC_IBITS(op) ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3])) 3956 #define ISP_FC_OBITS(op) ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7])) 3957 3958 #define ISP_FC_OPMAP(in0, out0) 0, 0, 0, in0, 0, 0, 0, out0 3959 #define ISP_FC_OPMAP_HALF(in1, in0, out1, out0) 0, 0, in1, in0, 0, 0, out1, out0 3960 #define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0) in3, in2, in1, in0, out3, out2, out1, out0 3961 static const uint32_t mbpfc[] = { 3962 ISP_FC_OPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ 3963 ISP_FC_OPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ 3964 ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f), /* 0x02: MBOX_EXEC_FIRMWARE */ 3965 ISP_FC_OPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */ 3966 ISP_FC_OPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ 3967 ISP_FC_OPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ 3968 ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */ 3969 ISP_FC_OPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ 3970 ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f), /* 0x08: MBOX_ABOUT_FIRMWARE */ 3971 ISP_FC_OPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */ 3972 ISP_FC_OPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */ 3973 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */ 3974 ISP_FC_OPMAP(0x00, 0x00), /* 0x0c: */ 3975 ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */ 3976 ISP_FC_OPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ 3977 ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */ 3978 ISP_FC_OPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */ 3979 ISP_FC_OPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */ 3980 ISP_FC_OPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */ 3981 ISP_FC_OPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */ 3982 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03), /* 0x14: MBOX_STOP_FIRMWARE */ 3983 ISP_FC_OPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */ 3984 ISP_FC_OPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */ 3985 ISP_FC_OPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */ 3986 ISP_FC_OPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */ 3987 ISP_FC_OPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */ 3988 ISP_FC_OPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */ 3989 ISP_FC_OPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ 3990 ISP_FC_OPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */ 3991 ISP_FC_OPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ 3992 ISP_FC_OPMAP(0x00, 0x00), /* 0x1e: */ 3993 ISP_FC_OPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ 3994 ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf), /* 0x20: MBOX_GET_LOOP_ID */ 3995 ISP_FC_OPMAP(0x00, 0x00), /* 0x21: */ 3996 ISP_FC_OPMAP(0x03, 0x4b), /* 0x22: MBOX_GET_TIMEOUT_PARAMS */ 3997 ISP_FC_OPMAP(0x00, 0x00), /* 0x23: */ 3998 ISP_FC_OPMAP(0x00, 0x00), /* 0x24: */ 3999 ISP_FC_OPMAP(0x00, 0x00), /* 0x25: */ 4000 ISP_FC_OPMAP(0x00, 0x00), /* 0x26: */ 4001 ISP_FC_OPMAP(0x00, 0x00), /* 0x27: */ 4002 ISP_FC_OPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */ 4003 ISP_FC_OPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */ 4004 ISP_FC_OPMAP(0x00, 0x00), /* 0x2a: */ 4005 ISP_FC_OPMAP(0x00, 0x00), /* 0x2b: */ 4006 ISP_FC_OPMAP(0x00, 0x00), /* 0x2c: */ 4007 ISP_FC_OPMAP(0x00, 0x00), /* 0x2d: */ 4008 ISP_FC_OPMAP(0x00, 0x00), /* 0x2e: */ 4009 ISP_FC_OPMAP(0x00, 0x00), /* 0x2f: */ 4010 ISP_FC_OPMAP(0x00, 0x00), /* 0x30: */ 4011 ISP_FC_OPMAP(0x00, 0x00), /* 0x31: */ 4012 ISP_FC_OPMAP(0x4b, 0x4b), /* 0x32: MBOX_SET_TIMEOUT_PARAMS */ 4013 ISP_FC_OPMAP(0x00, 0x00), /* 0x33: */ 4014 ISP_FC_OPMAP(0x00, 0x00), /* 0x34: */ 4015 ISP_FC_OPMAP(0x00, 0x00), /* 0x35: */ 4016 ISP_FC_OPMAP(0x00, 0x00), /* 0x36: */ 4017 ISP_FC_OPMAP(0x00, 0x00), /* 0x37: */ 4018 ISP_FC_OPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */ 4019 ISP_FC_OPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */ 4020 ISP_FC_OPMAP(0x00, 0x00), /* 0x3a: */ 4021 ISP_FC_OPMAP(0x00, 0x00), /* 0x3b: */ 4022 ISP_FC_OPMAP(0x00, 0x00), /* 0x3c: */ 4023 ISP_FC_OPMAP(0x00, 0x00), /* 0x3d: */ 4024 ISP_FC_OPMAP(0x00, 0x00), /* 0x3e: */ 4025 ISP_FC_OPMAP(0x00, 0x00), /* 0x3f: */ 4026 ISP_FC_OPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */ 4027 ISP_FC_OPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */ 4028 ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf), /* 0x42: MBOX_GET_RESOURCE_COUNT */ 4029 ISP_FC_OPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */ 4030 ISP_FC_OPMAP(0x00, 0x00), /* 0x44: */ 4031 ISP_FC_OPMAP(0x00, 0x00), /* 0x45: */ 4032 ISP_FC_OPMAP(0x00, 0x00), /* 0x46: */ 4033 ISP_FC_OPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */ 4034 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */ 4035 ISP_FC_OPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */ 4036 ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */ 4037 ISP_FC_OPMAP(0x00, 0x00), /* 0x4b: */ 4038 ISP_FC_OPMAP(0x00, 0x00), /* 0x4c: */ 4039 ISP_FC_OPMAP(0x00, 0x00), /* 0x4d: */ 4040 ISP_FC_OPMAP(0x00, 0x00), /* 0x4e: */ 4041 ISP_FC_OPMAP(0x00, 0x00), /* 0x4f: */ 4042 ISP_FC_OPMAP(0x00, 0x00), /* 0x50: */ 4043 ISP_FC_OPMAP(0x00, 0x00), /* 0x51: */ 4044 ISP_FC_OPMAP(0x00, 0x00), /* 0x52: */ 4045 ISP_FC_OPMAP(0x00, 0x00), /* 0x53: */ 4046 ISP_FC_OPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */ 4047 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */ 4048 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */ 4049 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */ 4050 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */ 4051 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */ 4052 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */ 4053 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */ 4054 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */ 4055 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */ 4056 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */ 4057 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */ 4058 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */ 4059 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */ 4060 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ 4061 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ 4062 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */ 4063 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */ 4064 ISP_FC_OPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */ 4065 ISP_FC_OPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */ 4066 ISP_FC_OPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */ 4067 ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f), /* 0x69: MBOX_GET_FW_STATE */ 4068 ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */ 4069 ISP_FC_OPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */ 4070 ISP_FC_OPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */ 4071 ISP_FC_OPMAP(0x00, 0x00), /* 0x6d: */ 4072 ISP_FC_OPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */ 4073 ISP_FC_OPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */ 4074 ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03), /* 0x70: MBOX_SEND_CHANGE_REQUEST */ 4075 ISP_FC_OPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */ 4076 ISP_FC_OPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */ 4077 ISP_FC_OPMAP(0x00, 0x00), /* 0x73: */ 4078 ISP_FC_OPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */ 4079 ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07), /* 0x75: GET PORT/NODE NAME LIST */ 4080 ISP_FC_OPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */ 4081 ISP_FC_OPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */ 4082 ISP_FC_OPMAP(0x00, 0x00), /* 0x78: */ 4083 ISP_FC_OPMAP(0x00, 0x00), /* 0x79: */ 4084 ISP_FC_OPMAP(0x00, 0x00), /* 0x7a: */ 4085 ISP_FC_OPMAP(0x00, 0x00), /* 0x7b: */ 4086 ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07), /* 0x7c: Get ID List */ 4087 ISP_FC_OPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */ 4088 ISP_FC_OPMAP(0x0f, 0x01) /* 0x7e: LUN RESET */ 4089 }; 4090 #define MAX_FC_OPCODE 0x7e 4091 /* 4092 * Footnotes 4093 * 4094 * (1): this sets bits 21..16 in mailbox register #8, which we nominally 4095 * do not access at this time in the core driver. The caller is 4096 * responsible for setting this register first (Gross!). The assumption 4097 * is that we won't overflow. 4098 */ 4099 4100 static const char *fc_mbcmd_names[] = { 4101 "NO-OP", /* 00h */ 4102 "LOAD RAM", 4103 "EXEC FIRMWARE", 4104 "DUMP RAM", 4105 "WRITE RAM WORD", 4106 "READ RAM WORD", 4107 "MAILBOX REG TEST", 4108 "VERIFY CHECKSUM", 4109 "ABOUT FIRMWARE", 4110 "LOAD RAM (2100)", 4111 "DUMP RAM", 4112 "LOAD RISC RAM", 4113 "DUMP RISC RAM", 4114 "WRITE RAM WORD EXTENDED", 4115 "CHECK FIRMWARE", 4116 "READ RAM WORD EXTENDED", 4117 "INIT REQUEST QUEUE", /* 10h */ 4118 "INIT RESULT QUEUE", 4119 "EXECUTE IOCB", 4120 "WAKE UP", 4121 "STOP FIRMWARE", 4122 "ABORT", 4123 "ABORT DEVICE", 4124 "ABORT TARGET", 4125 "BUS RESET", 4126 "STOP QUEUE", 4127 "START QUEUE", 4128 "SINGLE STEP QUEUE", 4129 "ABORT QUEUE", 4130 "GET DEV QUEUE STATUS", 4131 NULL, 4132 "GET FIRMWARE STATUS", 4133 "GET LOOP ID", /* 20h */ 4134 NULL, 4135 "GET TIMEOUT PARAMS", 4136 NULL, 4137 NULL, 4138 NULL, 4139 NULL, 4140 NULL, 4141 "GET FIRMWARE OPTIONS", 4142 "GET PORT QUEUE PARAMS", 4143 "GENERATE SYSTEM ERROR", 4144 NULL, 4145 NULL, 4146 NULL, 4147 NULL, 4148 NULL, 4149 "WRITE SFP", /* 30h */ 4150 "READ SFP", 4151 "SET TIMEOUT PARAMS", 4152 NULL, 4153 NULL, 4154 NULL, 4155 NULL, 4156 NULL, 4157 "SET FIRMWARE OPTIONS", 4158 "SET PORT QUEUE PARAMS", 4159 NULL, 4160 "SET FC LED CONF", 4161 NULL, 4162 "RESTART NIC FIRMWARE", 4163 "ACCESS CONTROL", 4164 NULL, 4165 "LOOP PORT BYPASS", /* 40h */ 4166 "LOOP PORT ENABLE", 4167 "GET RESOURCE COUNT", 4168 "REQUEST NON PARTICIPATING MODE", 4169 "DIAGNOSTIC ECHO TEST", 4170 "DIAGNOSTIC LOOPBACK", 4171 NULL, 4172 "GET PORT DATABASE ENHANCED", 4173 "INIT FIRMWARE MULTI ID", 4174 "GET VP DATABASE", 4175 "GET VP DATABASE ENTRY", 4176 NULL, 4177 NULL, 4178 NULL, 4179 NULL, 4180 NULL, 4181 "GET FCF LIST", /* 50h */ 4182 "GET DCBX PARAMETERS", 4183 NULL, 4184 "HOST MEMORY COPY", 4185 "EXECUTE IOCB A64", 4186 NULL, 4187 NULL, 4188 "SEND RNID", 4189 NULL, 4190 "SET PARAMETERS", 4191 "GET PARAMETERS", 4192 "DRIVER HEARTBEAT", 4193 "FIRMWARE HEARTBEAT", 4194 "GET/SET DATA RATE", 4195 "SEND RNFT", 4196 NULL, 4197 "INIT FIRMWARE", /* 60h */ 4198 "GET INIT CONTROL BLOCK", 4199 "INIT LIP", 4200 "GET FC-AL POSITION MAP", 4201 "GET PORT DATABASE", 4202 "CLEAR ACA", 4203 "TARGET RESET", 4204 "CLEAR TASK SET", 4205 "ABORT TASK SET", 4206 "GET FW STATE", 4207 "GET PORT NAME", 4208 "GET LINK STATUS", 4209 "INIT LIP RESET", 4210 "GET LINK STATS & PRIVATE DATA CNTS", 4211 "SEND SNS", 4212 "FABRIC LOGIN", 4213 "SEND CHANGE REQUEST", /* 70h */ 4214 "FABRIC LOGOUT", 4215 "INIT LIP LOGIN", 4216 NULL, 4217 "LOGIN LOOP PORT", 4218 "GET PORT/NODE NAME LIST", 4219 "SET VENDOR ID", 4220 "INITIALIZE IP MAILBOX", 4221 NULL, 4222 NULL, 4223 "GET XGMAC STATS", 4224 NULL, 4225 "GET ID LIST", 4226 "SEND LFA", 4227 "LUN RESET" 4228 }; 4229 4230 static void 4231 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp) 4232 { 4233 const char *cname, *xname, *sname; 4234 char tname[16], mname[16]; 4235 unsigned int ibits, obits, box, opcode, t, to; 4236 4237 opcode = mbp->param[0]; 4238 if (opcode > MAX_FC_OPCODE) { 4239 mbp->param[0] = MBOX_INVALID_COMMAND; 4240 isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode); 4241 return; 4242 } 4243 cname = fc_mbcmd_names[opcode]; 4244 ibits = ISP_FC_IBITS(opcode); 4245 obits = ISP_FC_OBITS(opcode); 4246 if (cname == NULL) { 4247 cname = tname; 4248 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode); 4249 } 4250 isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname); 4251 4252 /* 4253 * Pick up any additional bits that the caller might have set. 4254 */ 4255 ibits |= mbp->ibits; 4256 obits |= mbp->obits; 4257 4258 /* 4259 * Mask any bits that the caller wants us to mask 4260 */ 4261 ibits &= mbp->ibitm; 4262 obits &= mbp->obitm; 4263 4264 4265 if (ibits == 0 && obits == 0) { 4266 mbp->param[0] = MBOX_COMMAND_PARAM_ERROR; 4267 isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode); 4268 return; 4269 } 4270 4271 for (box = 0; box < ISP_NMBOX(isp); box++) { 4272 if (ibits & (1 << box)) { 4273 isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box, 4274 mbp->param[box]); 4275 ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); 4276 } 4277 isp->isp_mboxtmp[box] = mbp->param[box] = 0; 4278 } 4279 4280 isp->isp_lastmbxcmd = opcode; 4281 isp->isp_obits = obits; 4282 isp->isp_mboxbsy = 1; 4283 4284 /* 4285 * Set Host Interrupt condition so that RISC will pick up mailbox regs. 4286 */ 4287 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT); 4288 4289 /* 4290 * While we haven't finished the command, spin our wheels here. 4291 */ 4292 to = (mbp->timeout == 0) ? MBCMD_DEFAULT_TIMEOUT : mbp->timeout; 4293 for (t = 0; t < to; t += 100) { 4294 if (!isp->isp_mboxbsy) 4295 break; 4296 ISP_RUN_ISR(isp); 4297 if (!isp->isp_mboxbsy) 4298 break; 4299 ISP_DELAY(100); 4300 } 4301 4302 /* 4303 * Did the command time out? 4304 */ 4305 if (isp->isp_mboxbsy) { 4306 isp->isp_mboxbsy = 0; 4307 isp_prt(isp, ISP_LOGWARN, "Mailbox Command (0x%x) Timeout (%uus) (%s:%d)", 4308 isp->isp_lastmbxcmd, to, mbp->func, mbp->lineno); 4309 mbp->param[0] = MBOX_TIMEOUT; 4310 goto out; 4311 } 4312 4313 /* 4314 * Copy back output registers. 4315 */ 4316 for (box = 0; box < ISP_NMBOX(isp); box++) { 4317 if (obits & (1 << box)) { 4318 mbp->param[box] = isp->isp_mboxtmp[box]; 4319 isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box, 4320 mbp->param[box]); 4321 } 4322 } 4323 4324 out: 4325 if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE) 4326 return; 4327 4328 if ((mbp->param[0] & 0xbfe0) == 0 && 4329 (mbp->logval & MBLOGMASK(mbp->param[0])) == 0) 4330 return; 4331 4332 xname = NULL; 4333 sname = ""; 4334 switch (mbp->param[0]) { 4335 case MBOX_INVALID_COMMAND: 4336 xname = "INVALID COMMAND"; 4337 break; 4338 case MBOX_HOST_INTERFACE_ERROR: 4339 xname = "HOST INTERFACE ERROR"; 4340 break; 4341 case MBOX_TEST_FAILED: 4342 xname = "TEST FAILED"; 4343 break; 4344 case MBOX_COMMAND_ERROR: 4345 xname = "COMMAND ERROR"; 4346 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x", 4347 mbp->param[1]); 4348 sname = mname; 4349 break; 4350 case MBOX_COMMAND_PARAM_ERROR: 4351 xname = "COMMAND PARAMETER ERROR"; 4352 break; 4353 case MBOX_PORT_ID_USED: 4354 xname = "PORT ID ALREADY IN USE"; 4355 break; 4356 case MBOX_LOOP_ID_USED: 4357 xname = "LOOP ID ALREADY IN USE"; 4358 break; 4359 case MBOX_ALL_IDS_USED: 4360 xname = "ALL LOOP IDS IN USE"; 4361 break; 4362 case MBOX_NOT_LOGGED_IN: 4363 xname = "NOT LOGGED IN"; 4364 break; 4365 case MBOX_LINK_DOWN_ERROR: 4366 xname = "LINK DOWN ERROR"; 4367 break; 4368 case MBOX_LOOPBACK_ERROR: 4369 xname = "LOOPBACK ERROR"; 4370 break; 4371 case MBOX_CHECKSUM_ERROR: 4372 xname = "CHECKSUM ERROR"; 4373 break; 4374 case MBOX_INVALID_PRODUCT_KEY: 4375 xname = "INVALID PRODUCT KEY"; 4376 break; 4377 case MBOX_REGS_BUSY: 4378 xname = "REGISTERS BUSY"; 4379 break; 4380 case MBOX_TIMEOUT: 4381 xname = "TIMEOUT"; 4382 break; 4383 default: 4384 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]); 4385 xname = mname; 4386 break; 4387 } 4388 if (xname) { 4389 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)", 4390 cname, xname, sname); 4391 } 4392 } 4393 4394 static int 4395 isp_fw_state(ispsoftc_t *isp, int chan) 4396 { 4397 mbreg_t mbs; 4398 4399 MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0); 4400 isp_mboxcmd(isp, &mbs); 4401 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) 4402 return (mbs.param[1]); 4403 return (FW_ERROR); 4404 } 4405 4406 static void 4407 isp_setdfltfcparm(ispsoftc_t *isp, int chan) 4408 { 4409 fcparam *fcp = FCPARAM(isp, chan); 4410 4411 /* 4412 * Establish some default parameters. 4413 */ 4414 fcp->role = DEFAULT_ROLE(isp, chan); 4415 fcp->isp_retry_delay = ICB_DFLT_RDELAY; 4416 fcp->isp_retry_count = ICB_DFLT_RCOUNT; 4417 fcp->isp_loopid = DEFAULT_LOOPID(isp, chan); 4418 fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan); 4419 fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan); 4420 fcp->isp_fwoptions = 0; 4421 fcp->isp_xfwoptions = 0; 4422 fcp->isp_zfwoptions = 0; 4423 fcp->isp_lasthdl = NIL_HANDLE; 4424 fcp->isp_login_hdl = NIL_HANDLE; 4425 4426 fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS; 4427 fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS; 4428 if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) 4429 fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX; 4430 fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS; 4431 fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP; 4432 fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO; 4433 4434 /* 4435 * Now try and read NVRAM unless told to not do so. 4436 * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram. 4437 */ 4438 if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { 4439 int i, j = 0; 4440 /* 4441 * Give a couple of tries at reading NVRAM. 4442 */ 4443 for (i = 0; i < 2; i++) { 4444 j = isp_read_nvram(isp, chan); 4445 if (j == 0) { 4446 break; 4447 } 4448 } 4449 if (j) { 4450 isp->isp_confopts |= ISP_CFG_NONVRAM; 4451 } 4452 } 4453 4454 fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan); 4455 fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan); 4456 isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s", 4457 chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn), 4458 (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn), 4459 isp_class3_roles[fcp->role]); 4460 } 4461 4462 /* 4463 * Re-initialize the ISP and complete all orphaned commands 4464 * with a 'botched' notice. The reset/init routines should 4465 * not disturb an already active list of commands. 4466 */ 4467 4468 int 4469 isp_reinit(ispsoftc_t *isp, int do_load_defaults) 4470 { 4471 int i, res = 0; 4472 4473 if (isp->isp_state > ISP_RESETSTATE) 4474 isp_stop(isp); 4475 if (isp->isp_state != ISP_RESETSTATE) 4476 isp_reset(isp, do_load_defaults); 4477 if (isp->isp_state != ISP_RESETSTATE) { 4478 res = EIO; 4479 isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__); 4480 goto cleanup; 4481 } 4482 4483 isp_init(isp); 4484 if (isp->isp_state > ISP_RESETSTATE && 4485 isp->isp_state != ISP_RUNSTATE) { 4486 res = EIO; 4487 isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__); 4488 ISP_DISABLE_INTS(isp); 4489 } 4490 4491 cleanup: 4492 isp_clear_commands(isp); 4493 for (i = 0; i < isp->isp_nchan; i++) 4494 isp_clear_portdb(isp, i); 4495 return (res); 4496 } 4497 4498 /* 4499 * NVRAM Routines 4500 */ 4501 static int 4502 isp_read_nvram(ispsoftc_t *isp, int bus) 4503 { 4504 4505 return (isp_read_nvram_2400(isp)); 4506 } 4507 4508 static int 4509 isp_read_nvram_2400(ispsoftc_t *isp) 4510 { 4511 int retval = 0; 4512 uint32_t addr, csum, lwrds, *dptr; 4513 uint8_t nvram_data[ISP2400_NVRAM_SIZE]; 4514 4515 if (isp->isp_port) { 4516 addr = ISP2400_NVRAM_PORT1_ADDR; 4517 } else { 4518 addr = ISP2400_NVRAM_PORT0_ADDR; 4519 } 4520 4521 dptr = (uint32_t *) nvram_data; 4522 for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) { 4523 isp_rd_2400_nvram(isp, addr++, dptr++); 4524 } 4525 if (nvram_data[0] != 'I' || nvram_data[1] != 'S' || 4526 nvram_data[2] != 'P') { 4527 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)", 4528 nvram_data[0], nvram_data[1], nvram_data[2]); 4529 retval = -1; 4530 goto out; 4531 } 4532 dptr = (uint32_t *) nvram_data; 4533 for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) { 4534 uint32_t tmp; 4535 ISP_IOXGET_32(isp, &dptr[lwrds], tmp); 4536 csum += tmp; 4537 } 4538 if (csum != 0) { 4539 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum"); 4540 retval = -1; 4541 goto out; 4542 } 4543 isp_parse_nvram_2400(isp, nvram_data); 4544 out: 4545 return (retval); 4546 } 4547 4548 static void 4549 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp) 4550 { 4551 int loops = 0; 4552 uint32_t base = 0x7ffe0000; 4553 uint32_t tmp = 0; 4554 4555 if (IS_26XX(isp)) { 4556 base = 0x7fe7c000; /* XXX: Observation, may be wrong. */ 4557 } else if (IS_25XX(isp)) { 4558 base = 0x7ff00000 | 0x48000; 4559 } 4560 ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr); 4561 for (loops = 0; loops < 5000; loops++) { 4562 ISP_DELAY(10); 4563 tmp = ISP_READ(isp, BIU2400_FLASH_ADDR); 4564 if ((tmp & (1U << 31)) != 0) { 4565 break; 4566 } 4567 } 4568 if (tmp & (1U << 31)) { 4569 *rp = ISP_READ(isp, BIU2400_FLASH_DATA); 4570 ISP_SWIZZLE_NVRAM_LONG(isp, rp); 4571 } else { 4572 *rp = 0xffffffff; 4573 } 4574 } 4575 4576 static void 4577 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data) 4578 { 4579 fcparam *fcp = FCPARAM(isp, 0); 4580 uint64_t wwn; 4581 4582 isp_prt(isp, ISP_LOGDEBUG0, 4583 "NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d", 4584 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32), 4585 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)), 4586 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32), 4587 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)), 4588 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data)); 4589 isp_prt(isp, ISP_LOGDEBUG0, 4590 "NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", 4591 ISP2400_NVRAM_HARDLOOPID(nvram_data), 4592 ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data), 4593 ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data), 4594 ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data)); 4595 4596 wwn = ISP2400_NVRAM_PORT_NAME(nvram_data); 4597 fcp->isp_wwpn_nvram = wwn; 4598 4599 wwn = ISP2400_NVRAM_NODE_NAME(nvram_data); 4600 if (wwn) { 4601 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) { 4602 wwn = 0; 4603 } 4604 } 4605 if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) { 4606 wwn = fcp->isp_wwpn_nvram; 4607 wwn &= ~((uint64_t) 0xfff << 48); 4608 } 4609 fcp->isp_wwnn_nvram = wwn; 4610 4611 if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) { 4612 DEFAULT_FRAMESIZE(isp) = 4613 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data); 4614 } 4615 if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { 4616 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data); 4617 } 4618 fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data); 4619 fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data); 4620 fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data); 4621 } 4622