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