2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2009-2020 Alexander Motin <mav@FreeBSD.org>
5 * Copyright (c) 1997-2009 by Matthew Jacob
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
33 * Machine and OS Independent (well, as best as possible)
34 * code for the Qlogic ISP SCSI and FC-SCSI adapters.
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.
44 * Include header file appropriate for platform we're building on.
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD$");
49 #include <dev/ic/isp_netbsd.h>
52 #include <sys/cdefs.h>
53 __FBSDID("$FreeBSD$");
54 #include <dev/isp/isp_freebsd.h>
57 #include <dev/ic/isp_openbsd.h>
60 #include "isp_linux.h"
63 #include "isp_solaris.h"
69 static const char notresp[] = "Unknown IOCB in RESPONSE Queue (type 0x%x) @ idx %d (next %d)";
70 static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
71 static const char lipd[] = "Chan %d LIP destroyed %d active commands";
72 static const char sacq[] = "unable to acquire scratch area";
74 static const uint8_t alpa_map[] = {
75 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
76 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
77 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,
78 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
79 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
80 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
81 0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81,
82 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
83 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69,
84 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
85 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c,
86 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
87 0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
88 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
89 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
90 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
94 * Local function prototypes.
96 static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t *, uint16_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 *);
119 static void isp_setdfltfcparm(ispsoftc_t *, int);
120 static int isp_read_nvram(ispsoftc_t *, int);
121 static int isp_read_nvram_2400(ispsoftc_t *);
122 static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *);
123 static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
126 isp_change_fw_state(ispsoftc_t *isp, int chan, int state)
128 fcparam *fcp = FCPARAM(isp, chan);
130 if (fcp->isp_fwstate == state)
132 isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG,
133 "Chan %d Firmware state <%s->%s>", chan,
134 isp_fc_fw_statename(fcp->isp_fwstate), isp_fc_fw_statename(state));
135 fcp->isp_fwstate = state;
141 * Hit the chip over the head, download new f/w if available and set it running.
143 * Locking done elsewhere.
147 isp_reset(ispsoftc_t *isp, int do_load_defaults)
152 uint32_t code_org, val;
153 int loaded_fw, loops, i, dodnld = 1;
154 const char *btype = "????";
155 static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
157 isp->isp_state = ISP_NILSTATE;
158 ISP_DISABLE_INTS(isp);
161 * Put the board into PAUSE mode (so we can read the SXP registers
162 * or write FPM/FBM registers).
164 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT);
165 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
166 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
168 switch (isp->isp_type) {
186 * Stop DMA and wait for it to stop.
188 ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
189 for (loops = 0; loops < 100000; loops++) {
191 val = ISP_READ(isp, BIU2400_CSR);
192 if ((val & BIU2400_DMA_ACTIVE) == 0) {
196 if (val & BIU2400_DMA_ACTIVE)
197 isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
200 * Hold it in SOFT_RESET and STOP state for 100us.
202 ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
204 for (loops = 0; loops < 10000; loops++) {
206 val = ISP_READ(isp, OUTMAILBOX0);
214 isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
217 isp_prt(isp, ISP_LOGERR, "Board configuration error.");
220 isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
225 * Reset RISC Processor
227 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
228 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE);
229 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET);
232 * Post-RISC Reset stuff.
234 for (loops = 0; loops < 10000; loops++) {
236 val = ISP_READ(isp, OUTMAILBOX0);
244 isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
247 isp_prt(isp, ISP_LOGERR, "Board configuration error.");
250 isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
254 isp->isp_reqidx = isp->isp_reqodx = 0;
256 isp->isp_atioodx = 0;
257 ISP_WRITE(isp, BIU2400_REQINP, 0);
258 ISP_WRITE(isp, BIU2400_REQOUTP, 0);
259 ISP_WRITE(isp, BIU2400_RSPINP, 0);
260 ISP_WRITE(isp, BIU2400_RSPOUTP, 0);
262 ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
263 ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
265 ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
266 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
269 * Up until this point we've done everything by just reading or
270 * setting registers. From this point on we rely on at least *some*
271 * kind of firmware running in the card.
275 * Do some sanity checking by running a NOP command.
276 * If it succeeds, the ROM firmware is now running.
278 MBSINIT(&mbs, MBOX_NO_OP, MBLOGALL, 0);
279 isp_mboxcmd(isp, &mbs);
280 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
281 isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]);
286 * Do some operational tests
289 static const uint16_t patterns[MAX_MAILBOX] = {
290 0x0000, 0xdead, 0xbeef, 0xffff,
291 0xa5a5, 0x5a5a, 0x7f7f, 0x7ff7,
292 0x3421, 0xabcd, 0xdcba, 0xfeef,
293 0xbead, 0xdebe, 0x2222, 0x3333,
294 0x5555, 0x6666, 0x7777, 0xaaaa,
295 0xffff, 0xdddd, 0x9999, 0x1fbc,
296 0x6666, 0x6677, 0x1122, 0x33ff,
297 0x0000, 0x0001, 0x1000, 0x1010,
299 int nmbox = ISP_NMBOX(isp);
300 MBSINIT(&mbs, MBOX_MAILBOX_REG_TEST, MBLOGALL, 0);
301 for (i = 1; i < nmbox; i++) {
302 mbs.param[i] = patterns[i];
304 isp_mboxcmd(isp, &mbs);
305 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
308 for (i = 1; i < nmbox; i++) {
309 if (mbs.param[i] != patterns[i]) {
310 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]);
317 * Download new Firmware, unless requested not to do so.
318 * This is made slightly trickier in some cases where the
319 * firmware of the ROM revision is newer than the revision
320 * compiled into the driver. So, where we used to compare
321 * versions of our f/w and the ROM f/w, now we just see
322 * whether we have f/w at all and whether a config flag
323 * has disabled our download.
325 if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
330 * Set up DMA for the request and response queues.
331 * We do this now so we can use the request queue
332 * for dma to load firmware from.
334 if (ISP_MBOXDMASETUP(isp) != 0) {
335 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
340 code_org = ISP_CODE_ORG_2400;
343 const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
347 * Keep loading until we run out of f/w.
349 code_org = ptr[2]; /* 1st load address is our start addr */
351 isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
356 while (wi < ptr[3]) {
360 nw = min(wl, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) / 4);
361 cp = isp->isp_rquest;
362 for (i = 0; i < nw; i++)
363 ISP_IOXPUT_32(isp, ptr[wi + i], &cp[i]);
364 MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), -1);
365 MBSINIT(&mbs, MBOX_LOAD_RISC_RAM, MBLOGALL, 0);
367 mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
368 mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
369 mbs.param[4] = nw >> 16;
371 mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
372 mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
373 mbs.param[8] = la >> 16;
374 isp_prt(isp, ISP_LOGDEBUG0, "LOAD RISC RAM %u words at load address 0x%x", nw, la);
375 isp_mboxcmd(isp, &mbs);
376 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
377 isp_prt(isp, ISP_LOGERR, "F/W download failed");
391 } else if (IS_26XX(isp)) {
392 isp_prt(isp, ISP_LOGDEBUG1, "loading firmware from flash");
393 MBSINIT(&mbs, MBOX_LOAD_FLASH_FIRMWARE, MBLOGALL, 5000000);
396 isp_mboxcmd(isp, &mbs);
397 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
398 isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
402 isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
406 * If we loaded firmware, verify its checksum
409 MBSINIT(&mbs, MBOX_VERIFY_CHECKSUM, MBLOGNONE, 0);
410 mbs.param[1] = code_org >> 16;
411 mbs.param[2] = code_org;
412 isp_mboxcmd(isp, &mbs);
413 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
414 isp_prt(isp, ISP_LOGERR, dcrc);
420 * Now start it rolling.
422 * If we didn't actually download f/w,
423 * we still need to (re)start it.
425 MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000);
426 mbs.param[1] = code_org >> 16;
427 mbs.param[2] = code_org;
429 mbs.param[3] = loaded_fw ? 0 : 1;
430 isp_mboxcmd(isp, &mbs);
431 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
435 * Ask the chip for the current firmware version.
436 * This should prove that the new firmware is working.
438 MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 5000000);
439 isp_mboxcmd(isp, &mbs);
440 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
444 isp->isp_fwrev[0] = mbs.param[1];
445 isp->isp_fwrev[1] = mbs.param[2];
446 isp->isp_fwrev[2] = mbs.param[3];
447 isp->isp_fwattr = mbs.param[6];
448 isp->isp_fwattr |= ((uint64_t) mbs.param[15]) << 16;
449 if (isp->isp_fwattr & ISP2400_FW_ATTR_EXTNDED) {
451 (((uint64_t) mbs.param[16]) << 32) |
452 (((uint64_t) mbs.param[17]) << 48);
455 isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
456 btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
458 fwt = isp->isp_fwattr;
459 buf = FCPARAM(isp, 0)->isp_scanscratch;
460 ISP_SNPRINTF(buf, ISP_FC_SCRLEN, "Attributes:");
461 if (fwt & ISP2400_FW_ATTR_CLASS2) {
462 fwt ^=ISP2400_FW_ATTR_CLASS2;
463 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s Class2", buf);
465 if (fwt & ISP2400_FW_ATTR_IP) {
466 fwt ^=ISP2400_FW_ATTR_IP;
467 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s IP", buf);
469 if (fwt & ISP2400_FW_ATTR_MULTIID) {
470 fwt ^=ISP2400_FW_ATTR_MULTIID;
471 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MultiID", buf);
473 if (fwt & ISP2400_FW_ATTR_SB2) {
474 fwt ^=ISP2400_FW_ATTR_SB2;
475 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SB2", buf);
477 if (fwt & ISP2400_FW_ATTR_T10CRC) {
478 fwt ^=ISP2400_FW_ATTR_T10CRC;
479 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s T10CRC", buf);
481 if (fwt & ISP2400_FW_ATTR_VI) {
482 fwt ^=ISP2400_FW_ATTR_VI;
483 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VI", buf);
485 if (fwt & ISP2400_FW_ATTR_MQ) {
486 fwt ^=ISP2400_FW_ATTR_MQ;
487 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MQ", buf);
489 if (fwt & ISP2400_FW_ATTR_MSIX) {
490 fwt ^=ISP2400_FW_ATTR_MSIX;
491 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MSIX", buf);
493 if (fwt & ISP2400_FW_ATTR_FCOE) {
494 fwt ^=ISP2400_FW_ATTR_FCOE;
495 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s FCOE", buf);
497 if (fwt & ISP2400_FW_ATTR_VP0) {
498 fwt ^= ISP2400_FW_ATTR_VP0;
499 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VP0_Decoupling", buf);
501 if (fwt & ISP2400_FW_ATTR_EXPFW) {
502 fwt ^= ISP2400_FW_ATTR_EXPFW;
503 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (Experimental)", buf);
505 if (fwt & ISP2400_FW_ATTR_HOTFW) {
506 fwt ^= ISP2400_FW_ATTR_HOTFW;
507 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s HotFW", buf);
509 fwt &= ~ISP2400_FW_ATTR_EXTNDED;
510 if (fwt & ISP2400_FW_ATTR_EXTVP) {
511 fwt ^= ISP2400_FW_ATTR_EXTVP;
512 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ExtVP", buf);
514 if (fwt & ISP2400_FW_ATTR_VN2VN) {
515 fwt ^= ISP2400_FW_ATTR_VN2VN;
516 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VN2VN", buf);
518 if (fwt & ISP2400_FW_ATTR_EXMOFF) {
519 fwt ^= ISP2400_FW_ATTR_EXMOFF;
520 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s EXMOFF", buf);
522 if (fwt & ISP2400_FW_ATTR_NPMOFF) {
523 fwt ^= ISP2400_FW_ATTR_NPMOFF;
524 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s NPMOFF", buf);
526 if (fwt & ISP2400_FW_ATTR_DIFCHOP) {
527 fwt ^= ISP2400_FW_ATTR_DIFCHOP;
528 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s DIFCHOP", buf);
530 if (fwt & ISP2400_FW_ATTR_SRIOV) {
531 fwt ^= ISP2400_FW_ATTR_SRIOV;
532 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SRIOV", buf);
534 if (fwt & ISP2400_FW_ATTR_ASICTMP) {
535 fwt ^= ISP2400_FW_ATTR_ASICTMP;
536 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ASICTMP", buf);
538 if (fwt & ISP2400_FW_ATTR_ATIOMQ) {
539 fwt ^= ISP2400_FW_ATTR_ATIOMQ;
540 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ATIOMQ", buf);
543 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (unknown 0x%08x%08x)", buf,
544 (uint32_t) (fwt >> 32), (uint32_t) fwt);
546 isp_prt(isp, ISP_LOGCONFIG, "%s", buf);
549 * For the maximum number of commands take free exchange control block
550 * buffer count reported by firmware, limiting it to the maximum of our
551 * hardcoded handle format (16K now) minus some management reserve.
553 MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
554 isp_mboxcmd(isp, &mbs);
555 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
557 isp->isp_maxcmds = MIN(mbs.param[3], ISP_HANDLE_MAX - ISP_HANDLE_RESERVE);
558 isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
561 * If we don't have Multi-ID f/w loaded, we need to restrict channels to one.
562 * Only make this check for non-SCSI cards (I'm not sure firmware attributes
565 if (isp->isp_nchan > 1) {
566 if (!ISP_CAP_MULTI_ID(isp)) {
567 isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, "
568 "only can enable 1 of %d channels", isp->isp_nchan);
570 } else if (!ISP_CAP_VP0(isp)) {
571 isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID "
572 "feature properly without VP0_Decoupling");
578 * Final DMA setup after we got isp_maxcmds.
580 if (ISP_MBOXDMASETUP(isp) != 0) {
581 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
588 if (ISP_IRQSETUP(isp) != 0) {
589 isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ");
592 ISP_ENABLE_INTS(isp);
594 for (i = 0; i < isp->isp_nchan; i++)
595 isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
597 isp->isp_state = ISP_RESETSTATE;
600 * We get some default values established. As a side
601 * effect, NVRAM is read here (unless overriden by
602 * a configuration flag).
604 if (do_load_defaults) {
605 for (i = 0; i < isp->isp_nchan; i++)
606 isp_setdfltfcparm(isp, i);
611 * Clean firmware shutdown.
614 isp_stop(ispsoftc_t *isp)
618 isp->isp_state = ISP_NILSTATE;
619 MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000);
628 isp_mboxcmd(isp, &mbs);
629 return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]);
636 isp_shutdown(ispsoftc_t *isp)
639 if (isp->isp_state >= ISP_RESETSTATE)
641 ISP_DISABLE_INTS(isp);
642 ISP_WRITE(isp, BIU2400_ICR, 0);
643 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
647 * Initialize Parameters of Hardware to a known state.
649 * Locks are held before coming here.
652 isp_init(ispsoftc_t *isp)
655 isp_icb_2400_t local, *icbp = &local;
661 * Check to see whether all channels have *some* kind of role
663 for (chan = 0; chan < isp->isp_nchan; chan++) {
664 fcp = FCPARAM(isp, chan);
665 if (fcp->role != ISP_ROLE_NONE) {
669 if (chan == isp->isp_nchan) {
670 isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan);
674 isp->isp_state = ISP_INITSTATE;
677 * Start with channel 0.
679 fcp = FCPARAM(isp, 0);
682 * Turn on LIP F8 async event (1)
684 MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
686 isp_mboxcmd(isp, &mbs);
687 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
691 ISP_MEMZERO(icbp, sizeof (*icbp));
692 icbp->icb_fwoptions1 = fcp->isp_fwoptions;
693 icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
694 icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
695 if (isp->isp_nchan > 1 && ISP_CAP_VP0(isp)) {
696 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
697 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
699 if (fcp->role & ISP_ROLE_TARGET)
700 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
702 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
703 if (fcp->role & ISP_ROLE_INITIATOR)
704 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
706 icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
709 icbp->icb_version = ICB_VERSION1;
710 icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
711 if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
712 isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
713 icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
717 icbp->icb_execthrottle = 0xffff;
719 #ifdef ISP_TARGET_MODE
721 * Set target exchange count. Take half if we are supporting both roles.
723 if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) {
724 if ((icbp->icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE) == 0)
725 icbp->icb_xchgcnt = MIN(isp->isp_maxcmds / 2, ATPDPSIZE);
727 icbp->icb_xchgcnt = isp->isp_maxcmds;
731 ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
732 icbp->icb_hardaddr = fcp->isp_loopid;
733 if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
734 icbp->icb_hardaddr = 0;
739 icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
741 if (isp->isp_confopts & ISP_CFG_NOFCTAPE) {
742 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
744 if (isp->isp_confopts & ISP_CFG_FCTAPE) {
745 icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE;
748 for (chan = 0; chan < isp->isp_nchan; chan++) {
749 if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE)
750 FCPARAM(isp, chan)->fctape_enabled = 1;
752 FCPARAM(isp, chan)->fctape_enabled = 0;
755 switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
756 case ISP_CFG_LPORT_ONLY:
757 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
758 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY;
760 case ISP_CFG_NPORT_ONLY:
761 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
762 icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
765 /* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */
767 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
768 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
771 /* Let NVRAM settings define it if they are sane */
772 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK) {
773 case ICB2400_OPT2_LOOP_ONLY:
774 case ICB2400_OPT2_PTP_ONLY:
775 case ICB2400_OPT2_LOOP_2_PTP:
778 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
779 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
784 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
785 case ICB2400_OPT2_ZIO:
786 case ICB2400_OPT2_ZIO1:
787 icbp->icb_idelaytimer = 0;
792 isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
793 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
798 /* Use handshake to reduce global lock congestion. */
799 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR;
800 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA;
803 if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) {
804 icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24;
806 if (isp->isp_confopts & ISP_CFG_1GB) {
807 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
808 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB;
809 } else if (isp->isp_confopts & ISP_CFG_2GB) {
810 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
811 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB;
812 } else if (isp->isp_confopts & ISP_CFG_4GB) {
813 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
814 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB;
815 } else if (isp->isp_confopts & ISP_CFG_8GB) {
816 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
817 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB;
818 } else if (isp->isp_confopts & ISP_CFG_16GB) {
819 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
820 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB;
821 } else if (isp->isp_confopts & ISP_CFG_32GB) {
822 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
823 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB;
825 switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) {
826 case ICB2400_OPT3_RATE_4GB:
827 case ICB2400_OPT3_RATE_8GB:
828 case ICB2400_OPT3_RATE_16GB:
829 case ICB2400_OPT3_RATE_32GB:
830 case ICB2400_OPT3_RATE_AUTO:
832 case ICB2400_OPT3_RATE_2GB:
833 if (isp->isp_type <= ISP_HA_FC_2500)
836 case ICB2400_OPT3_RATE_1GB:
837 if (isp->isp_type <= ISP_HA_FC_2400)
841 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
842 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
846 if (ownloopid == 0) {
847 icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
849 icbp->icb_logintime = ICB_LOGIN_TOV;
851 if (fcp->isp_wwnn && fcp->isp_wwpn) {
852 icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
853 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
854 MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
855 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)),
856 ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
857 } else if (fcp->isp_wwpn) {
858 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
859 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
860 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)));
862 isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
865 icbp->icb_rspnsin = isp->isp_resodx;
866 icbp->icb_rqstout = isp->isp_reqidx;
867 icbp->icb_retry_count = fcp->isp_retry_count;
869 icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
870 if (icbp->icb_rqstqlen < 8) {
871 isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen);
874 icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
875 if (icbp->icb_rsltqlen < 8) {
876 isp_prt(isp, ISP_LOGERR, "bad result queue length %d",
880 icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
881 icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
882 icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
883 icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
885 icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
886 icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
887 icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
888 icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
890 #ifdef ISP_TARGET_MODE
891 /* unconditionally set up the ATIO queue if we support target mode */
892 icbp->icb_atio_in = isp->isp_atioodx;
893 icbp->icb_atioqlen = ATIO_QUEUE_LEN(isp);
894 if (icbp->icb_atioqlen < 8) {
895 isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen);
898 icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
899 icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
900 icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
901 icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
902 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
903 DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
906 if (ISP_CAP_MSIX(isp) && isp->isp_nirq >= 2) {
907 icbp->icb_msixresp = 1;
908 if (IS_26XX(isp) && isp->isp_nirq >= 3)
909 icbp->icb_msixatio = 2;
912 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);
914 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),
915 DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
916 DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
918 if (FC_SCRATCH_ACQUIRE(isp, 0)) {
919 isp_prt(isp, ISP_LOGERR, sacq);
922 ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
923 isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
924 if (isp->isp_dblev & ISP_LOGDEBUG1) {
925 isp_print_bytes(isp, "isp_init",
926 sizeof (*icbp), fcp->isp_scratch);
930 * Now fill in information about any additional channels
932 if (isp->isp_nchan > 1) {
933 isp_icb_2400_vpinfo_t vpinfo, *vdst;
934 vp_port_info_t pi, *pdst;
938 vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA;
939 if (ISP_CAP_VP0(isp)) {
940 vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE;
941 vpinfo.vp_count = isp->isp_nchan;
944 vpinfo.vp_count = isp->isp_nchan - 1;
947 off = fcp->isp_scratch;
948 off += ICB2400_VPINFO_OFF;
949 vdst = (isp_icb_2400_vpinfo_t *) off;
950 isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst);
951 amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t);
952 for (; chan < isp->isp_nchan; chan++) {
955 ISP_MEMZERO(&pi, sizeof (pi));
956 fcp2 = FCPARAM(isp, chan);
957 if (fcp2->role != ISP_ROLE_NONE) {
958 pi.vp_port_options = ICB2400_VPOPT_ENABLED |
959 ICB2400_VPOPT_ENA_SNSLOGIN;
960 if (fcp2->role & ISP_ROLE_INITIATOR)
961 pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
962 if ((fcp2->role & ISP_ROLE_TARGET) == 0)
963 pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE;
964 if (fcp2->isp_loopid < LOCAL_LOOP_LIM) {
965 pi.vp_port_loopid = fcp2->isp_loopid;
966 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
967 pi.vp_port_options |= ICB2400_VPOPT_HARD_ADDRESS;
971 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn);
972 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn);
973 off = fcp->isp_scratch;
974 if (ISP_CAP_VP0(isp))
975 off += ICB2400_VPINFO_PORT_OFF(chan);
977 off += ICB2400_VPINFO_PORT_OFF(chan - 1);
978 pdst = (vp_port_info_t *) off;
979 isp_put_vp_port_info(isp, &pi, pdst);
980 amt += ICB2400_VPOPT_WRITE_SIZE;
982 if (isp->isp_dblev & ISP_LOGDEBUG1) {
983 isp_print_bytes(isp, "isp_init",
984 amt - ICB2400_VPINFO_OFF,
985 (char *)fcp->isp_scratch + ICB2400_VPINFO_OFF);
992 MBSINIT(&mbs, 0, MBLOGALL, 30000000);
993 if (isp->isp_nchan > 1) {
994 mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
996 mbs.param[0] = MBOX_INIT_FIRMWARE;
999 mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1000 mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1001 mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1002 mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1003 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));
1004 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp), 0);
1005 isp_mboxcmd(isp, &mbs);
1006 FC_SCRATCH_RELEASE(isp, 0);
1008 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1013 * Whatever happens, we're now committed to being here.
1015 isp->isp_state = ISP_RUNSTATE;
1019 isp_fc_enable_vp(ispsoftc_t *isp, int chan)
1021 fcparam *fcp = FCPARAM(isp, chan);
1024 uint8_t resp[QENTRY_LEN];
1026 /* Build a VP MODIFY command in memory */
1027 ISP_MEMZERO(&vp, sizeof(vp));
1028 vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
1029 vp.vp_mod_hdr.rqs_entry_count = 1;
1031 vp.vp_mod_idx0 = chan;
1032 vp.vp_mod_cmd = VP_MODIFY_ENA;
1033 vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
1034 ICB2400_VPOPT_ENA_SNSLOGIN;
1035 if (fcp->role & ISP_ROLE_INITIATOR)
1036 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
1037 if ((fcp->role & ISP_ROLE_TARGET) == 0)
1038 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
1039 if (fcp->isp_loopid < LOCAL_LOOP_LIM) {
1040 vp.vp_mod_ports[0].loopid = fcp->isp_loopid;
1041 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
1042 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS;
1044 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn);
1045 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn);
1047 /* Prepare space for response in memory */
1048 memset(resp, 0xff, sizeof(resp));
1049 vp.vp_mod_hdl = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1050 if (vp.vp_mod_hdl == 0) {
1051 isp_prt(isp, ISP_LOGERR,
1052 "%s: VP_MODIFY of Chan %d out of handles", __func__, chan);
1056 /* Send request and wait for response. */
1057 reqp = isp_getrqentry(isp);
1059 isp_prt(isp, ISP_LOGERR,
1060 "%s: VP_MODIFY of Chan %d out of rqent", __func__, chan);
1061 isp_destroy_handle(isp, vp.vp_mod_hdl);
1064 isp_put_vp_modify(isp, &vp, (vp_modify_t *)reqp);
1065 if (isp->isp_dblev & ISP_LOGDEBUG1)
1066 isp_print_bytes(isp, "IOCB VP_MODIFY", QENTRY_LEN, reqp);
1067 ISP_SYNC_REQUEST(isp);
1068 if (msleep(resp, &isp->isp_lock, 0, "VP_MODIFY", 5*hz) == EWOULDBLOCK) {
1069 isp_prt(isp, ISP_LOGERR,
1070 "%s: VP_MODIFY of Chan %d timed out", __func__, chan);
1071 isp_destroy_handle(isp, vp.vp_mod_hdl);
1074 if (isp->isp_dblev & ISP_LOGDEBUG1)
1075 isp_print_bytes(isp, "IOCB VP_MODIFY response", QENTRY_LEN, resp);
1076 isp_get_vp_modify(isp, (vp_modify_t *)resp, &vp);
1078 if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) {
1079 isp_prt(isp, ISP_LOGERR,
1080 "%s: VP_MODIFY of Chan %d failed with flags %x status %d",
1081 __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status);
1088 isp_fc_disable_vp(ispsoftc_t *isp, int chan)
1092 uint8_t resp[QENTRY_LEN];
1094 /* Build a VP CTRL command in memory */
1095 ISP_MEMZERO(&vp, sizeof(vp));
1096 vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
1097 vp.vp_ctrl_hdr.rqs_entry_count = 1;
1098 if (ISP_CAP_VP0(isp)) {
1099 vp.vp_ctrl_status = 1;
1101 vp.vp_ctrl_status = 0;
1102 chan--; /* VP0 can not be controlled in this case. */
1104 vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
1105 vp.vp_ctrl_vp_count = 1;
1106 vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
1108 /* Prepare space for response in memory */
1109 memset(resp, 0xff, sizeof(resp));
1110 vp.vp_ctrl_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1111 if (vp.vp_ctrl_handle == 0) {
1112 isp_prt(isp, ISP_LOGERR,
1113 "%s: VP_CTRL of Chan %d out of handles", __func__, chan);
1117 /* Send request and wait for response. */
1118 reqp = isp_getrqentry(isp);
1120 isp_prt(isp, ISP_LOGERR,
1121 "%s: VP_CTRL of Chan %d out of rqent", __func__, chan);
1122 isp_destroy_handle(isp, vp.vp_ctrl_handle);
1125 isp_put_vp_ctrl_info(isp, &vp, (vp_ctrl_info_t *)reqp);
1126 if (isp->isp_dblev & ISP_LOGDEBUG1)
1127 isp_print_bytes(isp, "IOCB VP_CTRL", QENTRY_LEN, reqp);
1128 ISP_SYNC_REQUEST(isp);
1129 if (msleep(resp, &isp->isp_lock, 0, "VP_CTRL", 5*hz) == EWOULDBLOCK) {
1130 isp_prt(isp, ISP_LOGERR,
1131 "%s: VP_CTRL of Chan %d timed out", __func__, chan);
1132 isp_destroy_handle(isp, vp.vp_ctrl_handle);
1135 if (isp->isp_dblev & ISP_LOGDEBUG1)
1136 isp_print_bytes(isp, "IOCB VP_CTRL response", QENTRY_LEN, resp);
1137 isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)resp, &vp);
1139 if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) {
1140 isp_prt(isp, ISP_LOGERR,
1141 "%s: VP_CTRL of Chan %d failed with flags %x status %d %d",
1142 __func__, chan, vp.vp_ctrl_hdr.rqs_flags,
1143 vp.vp_ctrl_status, vp.vp_ctrl_index_fail);
1150 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
1152 fcparam *fcp = FCPARAM(isp, chan);
1153 int i, was, res = 0;
1155 if (chan >= isp->isp_nchan) {
1156 isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan);
1159 if (fcp->role == new_role)
1161 for (was = 0, i = 0; i < isp->isp_nchan; i++) {
1162 if (FCPARAM(isp, i)->role != ISP_ROLE_NONE)
1165 if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) {
1166 fcp->role = new_role;
1167 return (isp_reinit(isp, 0));
1169 if (fcp->role != ISP_ROLE_NONE) {
1170 res = isp_fc_disable_vp(isp, chan);
1171 isp_clear_portdb(isp, chan);
1173 fcp->role = new_role;
1174 if (fcp->role != ISP_ROLE_NONE)
1175 res = isp_fc_enable_vp(isp, chan);
1180 isp_clear_portdb(ispsoftc_t *isp, int chan)
1182 fcparam *fcp = FCPARAM(isp, chan);
1186 for (i = 0; i < MAX_FC_TARG; i++) {
1187 lp = &fcp->portdb[i];
1188 switch (lp->state) {
1189 case FC_PORTDB_STATE_DEAD:
1190 case FC_PORTDB_STATE_CHANGED:
1191 case FC_PORTDB_STATE_VALID:
1192 lp->state = FC_PORTDB_STATE_NIL;
1193 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1195 case FC_PORTDB_STATE_NIL:
1196 case FC_PORTDB_STATE_NEW:
1197 lp->state = FC_PORTDB_STATE_NIL;
1199 case FC_PORTDB_STATE_ZOMBIE:
1202 panic("Don't know how to clear state %d\n", lp->state);
1208 isp_mark_portdb(ispsoftc_t *isp, int chan)
1210 fcparam *fcp = FCPARAM(isp, chan);
1214 for (i = 0; i < MAX_FC_TARG; i++) {
1215 lp = &fcp->portdb[i];
1216 if (lp->state == FC_PORTDB_STATE_NIL)
1218 if (lp->portid >= DOMAIN_CONTROLLER_BASE &&
1219 lp->portid <= DOMAIN_CONTROLLER_END)
1221 fcp->portdb[i].probational = 1;
1226 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
1227 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
1230 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags)
1234 uint8_t resp[QENTRY_LEN];
1235 uint32_t sst, parm1;
1240 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x",
1241 chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ?
1242 "Login":"Logout", portid, handle);
1244 ISP_MEMZERO(&pl, sizeof(pl));
1245 pl.plogx_header.rqs_entry_count = 1;
1246 pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
1247 pl.plogx_nphdl = handle;
1248 pl.plogx_vphdl = chan;
1249 pl.plogx_portlo = portid;
1250 pl.plogx_rspsz_porthi = (portid >> 16) & 0xff;
1251 pl.plogx_flags = flags;
1253 /* Prepare space for response in memory */
1254 memset(resp, 0xff, sizeof(resp));
1255 pl.plogx_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1256 if (pl.plogx_handle == 0) {
1257 isp_prt(isp, ISP_LOGERR,
1258 "%s: PLOGX of Chan %d out of handles", __func__, chan);
1262 /* Send request and wait for response. */
1263 reqp = isp_getrqentry(isp);
1265 isp_prt(isp, ISP_LOGERR,
1266 "%s: PLOGX of Chan %d out of rqent", __func__, chan);
1267 isp_destroy_handle(isp, pl.plogx_handle);
1270 isp_put_plogx(isp, &pl, (isp_plogx_t *)reqp);
1271 if (isp->isp_dblev & ISP_LOGDEBUG1)
1272 isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, reqp);
1273 FCPARAM(isp, chan)->isp_login_hdl = handle;
1274 ISP_SYNC_REQUEST(isp);
1275 if (msleep(resp, &isp->isp_lock, 0, "PLOGX", 3 * ICB_LOGIN_TOV * hz)
1277 isp_prt(isp, ISP_LOGERR,
1278 "%s: PLOGX of Chan %d timed out", __func__, chan);
1279 isp_destroy_handle(isp, pl.plogx_handle);
1282 FCPARAM(isp, chan)->isp_login_hdl = NIL_HANDLE;
1283 if (isp->isp_dblev & ISP_LOGDEBUG1)
1284 isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, resp);
1285 isp_get_plogx(isp, (isp_plogx_t *)resp, &pl);
1287 if (pl.plogx_status == PLOGX_STATUS_OK) {
1289 } else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) {
1290 isp_prt(isp, ISP_LOGWARN,
1291 "status 0x%x on port login IOCB channel %d",
1292 pl.plogx_status, chan);
1296 sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16);
1297 parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16);
1304 case PLOGX_IOCBERR_NOLINK:
1307 case PLOGX_IOCBERR_NOIOCB:
1308 msg = "no IOCB buffer";
1310 case PLOGX_IOCBERR_NOXGHG:
1311 msg = "no Exchange Control Block";
1313 case PLOGX_IOCBERR_FAILED:
1314 ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff);
1317 case PLOGX_IOCBERR_NOFABRIC:
1320 case PLOGX_IOCBERR_NOTREADY:
1321 msg = "firmware not ready";
1323 case PLOGX_IOCBERR_NOLOGIN:
1324 ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1);
1326 rval = MBOX_NOT_LOGGED_IN;
1328 case PLOGX_IOCBERR_REJECT:
1329 ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
1332 case PLOGX_IOCBERR_NOPCB:
1333 msg = "no PCB allocated";
1335 case PLOGX_IOCBERR_EINVAL:
1336 ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1);
1339 case PLOGX_IOCBERR_PORTUSED:
1340 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1341 ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1);
1343 rval = MBOX_PORT_ID_USED | (parm1 << 16);
1345 case PLOGX_IOCBERR_HNDLUSED:
1346 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1347 ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1);
1349 rval = MBOX_LOOP_ID_USED;
1351 case PLOGX_IOCBERR_NOHANDLE:
1352 msg = "no handle allocated";
1354 case PLOGX_IOCBERR_NOFLOGI:
1355 msg = "no FLOGI_ACC";
1358 ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags);
1363 isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
1364 chan, portid, handle, msg);
1370 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb)
1374 isp_pdb_24xx_t bill;
1377 MBSINIT(&mbs, MBOX_GET_PORT_DB,
1378 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000);
1379 mbs.ibits = (1 << 9)|(1 << 10);
1381 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
1382 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
1383 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
1384 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
1385 mbs.param[9] = chan;
1386 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, sizeof(un), chan);
1388 isp_mboxcmd(isp, &mbs);
1389 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
1390 return (mbs.param[0] | (mbs.param[1] << 16));
1392 MEMORYBARRIER(isp, SYNC_IFORCPU, 0, sizeof(un), chan);
1393 isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill);
1394 pdb->handle = un.bill.pdb_handle;
1395 pdb->prli_word0 = un.bill.pdb_prli_svc0;
1396 pdb->prli_word3 = un.bill.pdb_prli_svc3;
1397 pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
1398 ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
1399 ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
1400 isp_prt(isp, ISP_LOGDEBUG0,
1401 "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x",
1402 chan, id, pdb->portid, un.bill.pdb_flags,
1403 un.bill.pdb_curstate, un.bill.pdb_laststate);
1405 if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
1406 mbs.param[0] = MBOX_NOT_LOGGED_IN;
1407 return (mbs.param[0]);
1413 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop)
1415 fcparam *fcp = FCPARAM(isp, chan);
1417 isp_pnhle_24xx_t el4, *elp4;
1421 MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL, 250000);
1422 mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1423 mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1424 mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1425 mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1426 mbs.param[8] = ISP_FC_SCRLEN;
1427 mbs.param[9] = chan;
1428 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1429 isp_prt(isp, ISP_LOGERR, sacq);
1432 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan);
1433 isp_mboxcmd(isp, &mbs);
1434 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1435 FC_SCRATCH_RELEASE(isp, chan);
1436 return (mbs.param[0] | (mbs.param[1] << 16));
1438 MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan);
1439 elp4 = fcp->isp_scratch;
1440 for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) {
1441 isp_get_pnhle_24xx(isp, &elp4[i], &el4);
1442 p = el4.pnhle_port_id_lo | (el4.pnhle_port_id_hi << 16);
1443 if (loop && (p >> 8) != (fcp->isp_portid >> 8))
1445 handles[j++] = el4.pnhle_handle;
1448 FC_SCRATCH_RELEASE(isp, chan);
1453 isp_dump_chip_portdb(ispsoftc_t *isp, int chan)
1458 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan);
1459 for (nphdl = 0; nphdl != NPH_MAX_2K; nphdl++) {
1460 if (isp_getpdb(isp, chan, nphdl, &pdb)) {
1463 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x "
1464 "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
1465 chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1],
1466 pdb.portname[2], pdb.portname[3], pdb.portname[4],
1467 pdb.portname[5], pdb.portname[6], pdb.portname[7]);
1472 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename)
1474 uint64_t wwn = INI_NONE;
1477 MBSINIT(&mbs, MBOX_GET_PORT_NAME,
1478 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
1479 mbs.param[1] = nphdl;
1482 mbs.param[9] = chan;
1483 isp_mboxcmd(isp, &mbs);
1484 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1487 wwn = (((uint64_t)(mbs.param[2] >> 8)) << 56) |
1488 (((uint64_t)(mbs.param[2] & 0xff))<< 48) |
1489 (((uint64_t)(mbs.param[3] >> 8)) << 40) |
1490 (((uint64_t)(mbs.param[3] & 0xff))<< 32) |
1491 (((uint64_t)(mbs.param[6] >> 8)) << 24) |
1492 (((uint64_t)(mbs.param[6] & 0xff))<< 16) |
1493 (((uint64_t)(mbs.param[7] >> 8)) << 8) |
1494 (((uint64_t)(mbs.param[7] & 0xff)));
1499 * Make sure we have good FC link.
1503 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
1509 NANOTIME_T hra, hrb;
1511 fcp = FCPARAM(isp, chan);
1513 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1515 if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
1518 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
1521 * Wait up to N microseconds for F/W to go to a ready state.
1525 isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
1526 if (fcp->isp_fwstate == FW_READY) {
1529 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1532 if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
1534 ISP_SLEEP(isp, 1000);
1536 if (fcp->isp_fwstate != FW_READY) {
1537 isp_prt(isp, ISP_LOG_SANCFG,
1538 "Chan %d Firmware is not ready (%s)",
1539 chan, isp_fc_fw_statename(fcp->isp_fwstate));
1544 * Get our Loop ID and Port ID.
1546 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
1547 mbs.param[9] = chan;
1548 isp_mboxcmd(isp, &mbs);
1549 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1553 topo = (int) mbs.param[6];
1554 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
1555 topo = TOPO_PTP_STUB;
1556 fcp->isp_topo = topo;
1557 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
1559 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
1560 fcp->isp_loopid = mbs.param[1] & 0xff;
1561 } else if (fcp->isp_topo != TOPO_F_PORT) {
1562 uint8_t alpa = fcp->isp_portid;
1564 for (i = 0; alpa_map[i]; i++) {
1565 if (alpa_map[i] == alpa)
1569 fcp->isp_loopid = i;
1573 fcp->isp_loopstate = LOOP_HAVE_ADDR;
1575 fcp->isp_loopstate = LOOP_TESTING_LINK;
1577 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
1578 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
1579 if (r != 0 || pdb.portid == 0) {
1580 isp_prt(isp, ISP_LOGWARN,
1581 "fabric topology, but cannot get info about fabric controller (0x%x)", r);
1582 fcp->isp_topo = TOPO_PTP_STUB;
1586 fcp->isp_fabric_params = mbs.param[7];
1587 fcp->isp_sns_hdl = NPH_SNS_ID;
1588 r = isp_register_fc4_type(isp, chan);
1589 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1593 r = isp_register_fc4_features_24xx(isp, chan);
1594 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1598 r = isp_register_port_name_24xx(isp, chan);
1599 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1603 isp_register_node_name_24xx(isp, chan);
1604 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1609 /* Get link speed. */
1610 fcp->isp_gbspeed = 1;
1611 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
1612 mbs.param[1] = MBGSD_GET_RATE;
1613 /* mbs.param[2] undefined if we're just getting rate */
1614 isp_mboxcmd(isp, &mbs);
1615 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
1616 if (mbs.param[1] == MBGSD_10GB)
1617 fcp->isp_gbspeed = 10;
1618 else if (mbs.param[1] == MBGSD_32GB)
1619 fcp->isp_gbspeed = 32;
1620 else if (mbs.param[1] == MBGSD_16GB)
1621 fcp->isp_gbspeed = 16;
1622 else if (mbs.param[1] == MBGSD_8GB)
1623 fcp->isp_gbspeed = 8;
1624 else if (mbs.param[1] == MBGSD_4GB)
1625 fcp->isp_gbspeed = 4;
1626 else if (mbs.param[1] == MBGSD_2GB)
1627 fcp->isp_gbspeed = 2;
1628 else if (mbs.param[1] == MBGSD_1GB)
1629 fcp->isp_gbspeed = 1;
1632 if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
1634 isp_prt(isp, ISP_LOG_SANCFG,
1635 "Chan %d FC link test aborted", chan);
1638 fcp->isp_loopstate = LOOP_LTEST_DONE;
1639 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1640 "Chan %d WWPN %016jx WWNN %016jx",
1641 chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn);
1642 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1643 "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x",
1644 chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid,
1646 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
1651 * Complete the synchronization of our Port Database.
1653 * At this point, we've scanned the local loop (if any) and the fabric
1654 * and performed fabric logins on all new devices.
1656 * Our task here is to go through our port database removing any entities
1657 * that are still marked probational (issuing PLOGO for ones which we had
1658 * PLOGI'd into) or are dead, and notifying upper layers about new/changed
1662 isp_pdb_sync(ispsoftc_t *isp, int chan)
1664 fcparam *fcp = FCPARAM(isp, chan);
1668 if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
1670 if (fcp->isp_loopstate >= LOOP_READY)
1673 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
1675 fcp->isp_loopstate = LOOP_SYNCING_PDB;
1677 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
1678 lp = &fcp->portdb[dbidx];
1680 if (lp->state == FC_PORTDB_STATE_NIL)
1682 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE)
1683 lp->state = FC_PORTDB_STATE_DEAD;
1684 switch (lp->state) {
1685 case FC_PORTDB_STATE_DEAD:
1686 lp->state = FC_PORTDB_STATE_NIL;
1687 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1688 if ((lp->portid & 0xffff00) != 0) {
1689 (void) isp_plogx(isp, chan, lp->handle,
1691 PLOGX_FLG_CMD_LOGO |
1692 PLOGX_FLG_IMPLICIT |
1693 PLOGX_FLG_FREE_NPHDL);
1696 * Note that we might come out of this with our state
1697 * set to FC_PORTDB_STATE_ZOMBIE.
1700 case FC_PORTDB_STATE_NEW:
1701 lp->state = FC_PORTDB_STATE_VALID;
1702 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
1704 case FC_PORTDB_STATE_CHANGED:
1705 lp->state = FC_PORTDB_STATE_VALID;
1706 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
1707 lp->portid = lp->new_portid;
1708 lp->prli_word0 = lp->new_prli_word0;
1709 lp->prli_word3 = lp->new_prli_word3;
1711 case FC_PORTDB_STATE_VALID:
1712 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
1714 case FC_PORTDB_STATE_ZOMBIE:
1717 isp_prt(isp, ISP_LOGWARN,
1718 "isp_pdb_sync: state %d for idx %d",
1720 isp_dump_portdb(isp, chan);
1724 if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
1725 isp_prt(isp, ISP_LOG_SANCFG,
1726 "Chan %d FC PDB sync aborted", chan);
1730 fcp->isp_loopstate = LOOP_READY;
1731 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
1736 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
1739 uint64_t wwnn, wwpn;
1741 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
1742 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
1744 /* Search port database for the same WWPN. */
1745 if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) {
1746 if (!lp->probational) {
1747 isp_prt(isp, ISP_LOGERR,
1748 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
1749 chan, lp->portid, lp->handle,
1750 FC_PORTDB_TGT(isp, chan, lp), lp->state);
1751 isp_dump_portdb(isp, chan);
1754 lp->probational = 0;
1755 lp->node_wwn = wwnn;
1757 /* Old device, nothing new. */
1758 if (lp->portid == pdb->portid &&
1759 lp->handle == pdb->handle &&
1760 lp->prli_word3 == pdb->prli_word3 &&
1761 ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) ==
1762 (lp->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR))) {
1763 if (lp->state != FC_PORTDB_STATE_NEW)
1764 lp->state = FC_PORTDB_STATE_VALID;
1765 isp_prt(isp, ISP_LOG_SANCFG,
1766 "Chan %d Port 0x%06x@0x%04x is valid",
1767 chan, pdb->portid, pdb->handle);
1771 /* Something has changed. */
1772 lp->state = FC_PORTDB_STATE_CHANGED;
1773 lp->handle = pdb->handle;
1774 lp->new_portid = pdb->portid;
1775 lp->new_prli_word0 = pdb->prli_word0;
1776 lp->new_prli_word3 = pdb->prli_word3;
1777 isp_prt(isp, ISP_LOG_SANCFG,
1778 "Chan %d Port 0x%06x@0x%04x is changed",
1779 chan, pdb->portid, pdb->handle);
1783 /* It seems like a new port. Find an empty slot for it. */
1784 if (!isp_find_pdb_empty(isp, chan, &lp)) {
1785 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan);
1789 ISP_MEMZERO(lp, sizeof (fcportdb_t));
1790 lp->probational = 0;
1791 lp->state = FC_PORTDB_STATE_NEW;
1792 lp->portid = lp->new_portid = pdb->portid;
1793 lp->prli_word0 = lp->new_prli_word0 = pdb->prli_word0;
1794 lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3;
1795 lp->handle = pdb->handle;
1796 lp->port_wwn = wwpn;
1797 lp->node_wwn = wwnn;
1798 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new",
1799 chan, pdb->portid, pdb->handle);
1803 * Scan local loop for devices.
1806 isp_scan_loop(ispsoftc_t *isp, int chan)
1808 fcparam *fcp = FCPARAM(isp, chan);
1814 if (fcp->isp_loopstate < LOOP_LTEST_DONE)
1816 if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
1819 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
1820 fcp->isp_loopstate = LOOP_SCANNING_LOOP;
1821 if (TOPO_IS_FABRIC(fcp->isp_topo)) {
1822 isp_prt(isp, ISP_LOG_SANCFG,
1823 "Chan %d FC loop scan done (no loop)", chan);
1824 fcp->isp_loopstate = LOOP_LSCAN_DONE;
1828 handles = (uint16_t *)fcp->isp_scanscratch;
1829 lim = ISP_FC_SCRLEN / 2;
1830 r = isp_gethandles(isp, chan, handles, &lim, 1);
1832 isp_prt(isp, ISP_LOG_SANCFG,
1833 "Chan %d Getting list of handles failed with %x", chan, r);
1834 isp_prt(isp, ISP_LOG_SANCFG,
1835 "Chan %d FC loop scan done (bad)", chan);
1839 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
1843 * Run through the list and get the port database info for each one.
1845 isp_mark_portdb(isp, chan);
1846 for (idx = 0; idx < lim; idx++) {
1847 handle = handles[idx];
1850 * Don't scan "special" ids.
1852 if (handle >= NPH_RESERVED)
1856 * Get the port database entity for this index.
1858 r = isp_getpdb(isp, chan, handle, &pdb);
1859 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
1861 isp_prt(isp, ISP_LOG_SANCFG,
1862 "Chan %d FC loop scan aborted", chan);
1866 isp_prt(isp, ISP_LOGDEBUG1,
1867 "Chan %d FC Scan Loop handle %d returned %x",
1872 isp_pdb_add_update(isp, chan, &pdb);
1874 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
1876 fcp->isp_loopstate = LOOP_LSCAN_DONE;
1877 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
1882 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
1884 fcparam *fcp = FCPARAM(isp, chan);
1887 uint8_t resp[QENTRY_LEN];
1889 if (isp->isp_dblev & ISP_LOGDEBUG1)
1890 isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch);
1893 * Build a Passthrough IOCB in memory.
1895 ISP_MEMZERO(&pt, sizeof(pt));
1896 pt.ctp_header.rqs_entry_count = 1;
1897 pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
1898 pt.ctp_nphdl = fcp->isp_sns_hdl;
1900 pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
1903 pt.ctp_rsp_bcnt = rsp_bcnt;
1904 pt.ctp_cmd_bcnt = cmd_bcnt;
1905 pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma);
1906 pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma);
1907 pt.ctp_dataseg[0].ds_count = cmd_bcnt;
1908 pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
1909 pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
1910 pt.ctp_dataseg[1].ds_count = rsp_bcnt;
1912 /* Prepare space for response in memory */
1913 memset(resp, 0xff, sizeof(resp));
1914 pt.ctp_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1915 if (pt.ctp_handle == 0) {
1916 isp_prt(isp, ISP_LOGERR,
1917 "%s: CTP of Chan %d out of handles", __func__, chan);
1921 /* Send request and wait for response. */
1922 reqp = isp_getrqentry(isp);
1924 isp_prt(isp, ISP_LOGERR,
1925 "%s: CTP of Chan %d out of rqent", __func__, chan);
1926 isp_destroy_handle(isp, pt.ctp_handle);
1929 isp_put_ct_pt(isp, &pt, (isp_ct_pt_t *)reqp);
1930 if (isp->isp_dblev & ISP_LOGDEBUG1)
1931 isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, reqp);
1932 ISP_SYNC_REQUEST(isp);
1933 if (msleep(resp, &isp->isp_lock, 0, "CTP", pt.ctp_time*hz) == EWOULDBLOCK) {
1934 isp_prt(isp, ISP_LOGERR,
1935 "%s: CTP of Chan %d timed out", __func__, chan);
1936 isp_destroy_handle(isp, pt.ctp_handle);
1939 if (isp->isp_dblev & ISP_LOGDEBUG1)
1940 isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, resp);
1942 isp_get_ct_pt(isp, (isp_ct_pt_t *)resp, &pt);
1943 if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
1944 isp_prt(isp, ISP_LOGWARN,
1945 "Chan %d CT pass-through returned 0x%x",
1946 chan, pt.ctp_status);
1950 if (isp->isp_dblev & ISP_LOGDEBUG1)
1951 isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch);
1957 * Scan the fabric for devices and add them to our port database.
1959 * Use the GID_PT command to get list of all Nx_Port IDs SNS knows.
1960 * Use GFF_ID and GFT_ID to check port type (FCP) and features (target).
1962 * We use CT Pass-through IOCB.
1964 #define GIDLEN ISP_FC_SCRLEN
1965 #define NGENT ((GIDLEN - 16) >> 2)
1968 isp_gid_pt(ispsoftc_t *isp, int chan)
1970 fcparam *fcp = FCPARAM(isp, chan);
1972 uint8_t *scp = fcp->isp_scratch;
1974 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan);
1975 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1976 isp_prt(isp, ISP_LOGERR, sacq);
1980 /* Build the CT command and execute via pass-through. */
1981 ISP_MEMZERO(&ct, sizeof (ct));
1982 ct.ct_revision = CT_REVISION;
1983 ct.ct_fcs_type = CT_FC_TYPE_FC;
1984 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
1985 ct.ct_cmd_resp = SNS_GID_PT;
1986 ct.ct_bcnt_resid = (GIDLEN - 16) >> 2;
1987 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
1988 scp[sizeof(ct)] = 0x7f; /* Port Type = Nx_Port */
1989 scp[sizeof(ct)+1] = 0; /* Domain_ID = any */
1990 scp[sizeof(ct)+2] = 0; /* Area_ID = any */
1991 scp[sizeof(ct)+3] = 0; /* Flags = no Area_ID */
1993 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) {
1994 FC_SCRATCH_RELEASE(isp, chan);
1998 isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp,
1999 (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT);
2000 FC_SCRATCH_RELEASE(isp, chan);
2005 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid)
2007 fcparam *fcp = FCPARAM(isp, chan);
2010 uint8_t *scp = fcp->isp_scratch;
2011 sns_gff_id_rsp_t rsp;
2014 if (!fcp->isp_use_gff_id) /* User may block GFF_ID use. */
2017 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan);
2018 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2019 isp_prt(isp, ISP_LOGERR, sacq);
2023 /* Build the CT command and execute via pass-through. */
2024 ISP_MEMZERO(&ct, sizeof (ct));
2025 ct.ct_revision = CT_REVISION;
2026 ct.ct_fcs_type = CT_FC_TYPE_FC;
2027 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2028 ct.ct_cmd_resp = SNS_GFF_ID;
2029 ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4;
2030 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2031 rp = (uint32_t *) &scp[sizeof(ct)];
2032 ISP_IOZPUT_32(isp, portid, rp);
2034 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
2035 SNS_GFF_ID_RESP_SIZE)) {
2036 FC_SCRATCH_RELEASE(isp, chan);
2040 isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp);
2041 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
2042 for (i = 0; i < 32; i++) {
2043 if (rsp.snscb_fc4_features[i] != 0) {
2048 if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >>
2049 ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
2051 /* Workaround for broken Brocade firmware. */
2052 if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >>
2053 ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
2056 FC_SCRATCH_RELEASE(isp, chan);
2057 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res);
2062 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid)
2064 fcparam *fcp = FCPARAM(isp, chan);
2067 uint8_t *scp = fcp->isp_scratch;
2068 sns_gft_id_rsp_t rsp;
2071 if (!fcp->isp_use_gft_id) /* User may block GFT_ID use. */
2074 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan);
2075 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2076 isp_prt(isp, ISP_LOGERR, sacq);
2080 /* Build the CT command and execute via pass-through. */
2081 ISP_MEMZERO(&ct, sizeof (ct));
2082 ct.ct_revision = CT_REVISION;
2083 ct.ct_fcs_type = CT_FC_TYPE_FC;
2084 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2085 ct.ct_cmd_resp = SNS_GFT_ID;
2086 ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4;
2087 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2088 rp = (uint32_t *) &scp[sizeof(ct)];
2089 ISP_IOZPUT_32(isp, portid, rp);
2091 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
2092 SNS_GFT_ID_RESP_SIZE)) {
2093 FC_SCRATCH_RELEASE(isp, chan);
2097 isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp);
2098 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
2099 for (i = 0; i < 8; i++) {
2100 if (rsp.snscb_fc4_types[i] != 0) {
2105 if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >>
2106 (FC4_SCSI % 32)) & 0x01) != 0)
2109 FC_SCRATCH_RELEASE(isp, chan);
2110 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res);
2115 isp_scan_fabric(ispsoftc_t *isp, int chan)
2117 fcparam *fcp = FCPARAM(isp, chan);
2121 int portidx, portlim, r;
2122 sns_gid_xx_rsp_t *rs;
2124 if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
2126 if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
2129 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
2130 fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
2131 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
2132 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2133 isp_prt(isp, ISP_LOG_SANCFG,
2134 "Chan %d FC fabric scan done (no fabric)", chan);
2138 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
2140 FC_SCRATCH_RELEASE(isp, chan);
2141 isp_prt(isp, ISP_LOG_SANCFG,
2142 "Chan %d FC fabric scan aborted", chan);
2147 * Make sure we still are logged into the fabric controller.
2149 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
2150 if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) {
2151 isp_dump_chip_portdb(isp, chan);
2154 fcp->isp_loopstate = LOOP_LTEST_DONE;
2156 isp_prt(isp, ISP_LOG_SANCFG,
2157 "Chan %d FC fabric scan done (bad)", chan);
2161 /* Get list of port IDs from SNS. */
2162 r = isp_gid_pt(isp, chan);
2163 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2166 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2169 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
2173 rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch;
2174 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2176 if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) {
2178 /* FC-4 Type and Port Type not registered are not errors. */
2179 if (rs->snscb_cthdr.ct_reason == 9 &&
2180 (rs->snscb_cthdr.ct_explanation == 0x07 ||
2181 rs->snscb_cthdr.ct_explanation == 0x0a)) {
2182 level = ISP_LOG_SANCFG;
2184 level = ISP_LOGWARN;
2186 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT"
2187 " (Reason=0x%x Expl=0x%x)", chan,
2188 rs->snscb_cthdr.ct_reason,
2189 rs->snscb_cthdr.ct_explanation);
2190 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2194 /* Check our buffer was big enough to get the full list. */
2195 for (portidx = 0; portidx < NGENT-1; portidx++) {
2196 if (rs->snscb_ports[portidx].control & 0x80)
2199 if ((rs->snscb_ports[portidx].control & 0x80) == 0) {
2200 isp_prt(isp, ISP_LOGWARN,
2201 "fabric too big for scratch area: increase ISP_FC_SCRLEN");
2203 portlim = portidx + 1;
2204 isp_prt(isp, ISP_LOG_SANCFG,
2205 "Chan %d Got %d ports back from name server", chan, portlim);
2207 /* Go through the list and remove duplicate port ids. */
2208 for (portidx = 0; portidx < portlim; portidx++) {
2212 ((rs->snscb_ports[portidx].portid[0]) << 16) |
2213 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2214 ((rs->snscb_ports[portidx].portid[2]));
2216 for (npidx = portidx + 1; npidx < portlim; npidx++) {
2217 uint32_t new_portid =
2218 ((rs->snscb_ports[npidx].portid[0]) << 16) |
2219 ((rs->snscb_ports[npidx].portid[1]) << 8) |
2220 ((rs->snscb_ports[npidx].portid[2]));
2221 if (new_portid == portid) {
2226 if (npidx < portlim) {
2227 rs->snscb_ports[npidx].portid[0] = 0;
2228 rs->snscb_ports[npidx].portid[1] = 0;
2229 rs->snscb_ports[npidx].portid[2] = 0;
2230 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid);
2235 * We now have a list of Port IDs for all FC4 SCSI devices
2236 * that the Fabric Name server knows about.
2238 * For each entry on this list go through our port database looking
2239 * for probational entries- if we find one, then an old entry is
2240 * maybe still this one. We get some information to find out.
2242 * Otherwise, it's a new fabric device, and we log into it
2243 * (unconditionally). After searching the entire database
2244 * again to make sure that we never ever ever ever have more
2245 * than one entry that has the same PortID or the same
2246 * WWNN/WWPN duple, we enter the device into our database.
2248 isp_mark_portdb(isp, chan);
2249 for (portidx = 0; portidx < portlim; portidx++) {
2250 portid = ((rs->snscb_ports[portidx].portid[0]) << 16) |
2251 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2252 ((rs->snscb_ports[portidx].portid[2]));
2253 isp_prt(isp, ISP_LOG_SANCFG,
2254 "Chan %d Checking fabric port 0x%06x", chan, portid);
2256 isp_prt(isp, ISP_LOG_SANCFG,
2257 "Chan %d Port at idx %d is zero",
2261 if (portid == fcp->isp_portid) {
2262 isp_prt(isp, ISP_LOG_SANCFG,
2263 "Chan %d Port 0x%06x is our", chan, portid);
2267 /* Now search the entire port database for the same portid. */
2268 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) {
2269 if (!lp->probational) {
2270 isp_prt(isp, ISP_LOGERR,
2271 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
2272 chan, lp->portid, lp->handle,
2273 FC_PORTDB_TGT(isp, chan, lp), lp->state);
2274 isp_dump_portdb(isp, chan);
2278 if (lp->state == FC_PORTDB_STATE_ZOMBIE)
2282 * See if we're still logged into it.
2284 * If we aren't, mark it as a dead device and
2285 * leave the new portid in the database entry
2286 * for somebody further along to decide what to
2287 * do (policy choice).
2289 * If we are, check to see if it's the same
2290 * device still (it should be). If for some
2291 * reason it isn't, mark it as a changed device
2292 * and leave the new portid and role in the
2293 * database entry for somebody further along to
2294 * decide what to do (policy choice).
2296 r = isp_getpdb(isp, chan, lp->handle, &pdb);
2297 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2300 lp->state = FC_PORTDB_STATE_DEAD;
2301 isp_prt(isp, ISP_LOG_SANCFG,
2302 "Chan %d Port 0x%06x handle 0x%x is dead (%d)",
2303 chan, portid, lp->handle, r);
2307 isp_pdb_add_update(isp, chan, &pdb);
2312 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2313 isp_prt(isp, ISP_LOG_SANCFG,
2314 "Chan %d Port 0x%06x is not logged in", chan, portid);
2318 r = isp_gff_id(isp, chan, portid);
2320 isp_prt(isp, ISP_LOG_SANCFG,
2321 "Chan %d Port 0x%06x is not an FCP target", chan, portid);
2325 r = isp_gft_id(isp, chan, portid);
2327 isp_prt(isp, ISP_LOG_SANCFG,
2328 "Chan %d Port 0x%06x is not FCP", chan, portid);
2332 if (isp_login_device(isp, chan, portid, &pdb,
2333 &FCPARAM(isp, 0)->isp_lasthdl)) {
2334 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2339 isp_pdb_add_update(isp, chan, &pdb);
2342 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2344 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2345 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
2350 * Find an unused handle and try and use to login to a port.
2353 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
2358 handle = isp_next_handle(isp, ohp);
2359 for (i = 0; i < NPH_MAX_2K; i++) {
2360 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2363 /* Check if this handle is free. */
2364 r = isp_getpdb(isp, chan, handle, p);
2366 if (p->portid != portid) {
2367 /* This handle is busy, try next one. */
2368 handle = isp_next_handle(isp, ohp);
2373 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2377 * Now try and log into the device
2379 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2382 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
2384 * If we get here, then the firmwware still thinks we're logged into this device, but with a different
2385 * handle. We need to break that association. We used to try and just substitute the handle, but then
2386 * failed to get any data via isp_getpdb (below).
2388 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) {
2389 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
2391 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2393 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2397 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
2398 /* Try the next handle. */
2399 handle = isp_next_handle(isp, ohp);
2407 if (i == NPH_MAX_2K) {
2408 isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid);
2413 * If we successfully logged into it, get the PDB for it
2414 * so we can crosscheck that it is still what we think it
2415 * is and that we also have the role it plays
2417 r = isp_getpdb(isp, chan, handle, p);
2419 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
2423 if (p->handle != handle || p->portid != portid) {
2424 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
2425 chan, portid, handle, p->portid, p->handle);
2432 isp_register_fc4_type(ispsoftc_t *isp, int chan)
2434 fcparam *fcp = FCPARAM(isp, chan);
2436 ct_hdr_t *ct = &rp.rftid_hdr;
2437 uint8_t *scp = fcp->isp_scratch;
2439 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2440 isp_prt(isp, ISP_LOGERR, sacq);
2444 /* Build the CT command and execute via pass-through. */
2445 ISP_MEMZERO(&rp, sizeof(rp));
2446 ct->ct_revision = CT_REVISION;
2447 ct->ct_fcs_type = CT_FC_TYPE_FC;
2448 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2449 ct->ct_cmd_resp = SNS_RFT_ID;
2450 ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2;
2451 rp.rftid_portid[0] = fcp->isp_portid >> 16;
2452 rp.rftid_portid[1] = fcp->isp_portid >> 8;
2453 rp.rftid_portid[2] = fcp->isp_portid;
2454 rp.rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
2455 isp_put_rft_id(isp, &rp, (rft_id_t *)scp);
2457 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2458 FC_SCRATCH_RELEASE(isp, chan);
2462 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2463 FC_SCRATCH_RELEASE(isp, chan);
2464 if (ct->ct_cmd_resp == LS_RJT) {
2465 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "Chan %d Register FC4 Type rejected", chan);
2467 } else if (ct->ct_cmd_resp == LS_ACC) {
2468 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan);
2470 isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp);
2477 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
2479 fcparam *fcp = FCPARAM(isp, chan);
2482 uint8_t *scp = fcp->isp_scratch;
2484 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2485 isp_prt(isp, ISP_LOGERR, sacq);
2490 * Build the CT header and command in memory.
2492 ISP_MEMZERO(&rp, sizeof(rp));
2494 ct->ct_revision = CT_REVISION;
2495 ct->ct_fcs_type = CT_FC_TYPE_FC;
2496 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2497 ct->ct_cmd_resp = SNS_RFF_ID;
2498 ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2;
2499 rp.rffid_portid[0] = fcp->isp_portid >> 16;
2500 rp.rffid_portid[1] = fcp->isp_portid >> 8;
2501 rp.rffid_portid[2] = fcp->isp_portid;
2502 rp.rffid_fc4features = 0;
2503 if (fcp->role & ISP_ROLE_TARGET)
2504 rp.rffid_fc4features |= 1;
2505 if (fcp->role & ISP_ROLE_INITIATOR)
2506 rp.rffid_fc4features |= 2;
2507 rp.rffid_fc4type = FC4_SCSI;
2508 isp_put_rff_id(isp, &rp, (rff_id_t *)scp);
2509 if (isp->isp_dblev & ISP_LOGDEBUG1)
2510 isp_print_bytes(isp, "CT request", sizeof(rft_id_t), scp);
2512 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2513 FC_SCRATCH_RELEASE(isp, chan);
2517 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2518 FC_SCRATCH_RELEASE(isp, chan);
2519 if (ct->ct_cmd_resp == LS_RJT) {
2520 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2521 "Chan %d Register FC4 Features rejected", chan);
2523 } else if (ct->ct_cmd_resp == LS_ACC) {
2524 isp_prt(isp, ISP_LOG_SANCFG,
2525 "Chan %d Register FC4 Features accepted", chan);
2527 isp_prt(isp, ISP_LOGWARN,
2528 "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
2535 isp_register_port_name_24xx(ispsoftc_t *isp, int chan)
2537 fcparam *fcp = FCPARAM(isp, chan);
2540 uint8_t *scp = fcp->isp_scratch;
2543 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2544 isp_prt(isp, ISP_LOGERR, sacq);
2549 * Build the CT header and command in memory.
2551 ISP_MEMZERO(&rp, sizeof(rp));
2552 ct = &rp.rspnid_hdr;
2553 ct->ct_revision = CT_REVISION;
2554 ct->ct_fcs_type = CT_FC_TYPE_FC;
2555 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2556 ct->ct_cmd_resp = SNS_RSPN_ID;
2557 rp.rspnid_portid[0] = fcp->isp_portid >> 16;
2558 rp.rspnid_portid[1] = fcp->isp_portid >> 8;
2559 rp.rspnid_portid[2] = fcp->isp_portid;
2560 rp.rspnid_length = 0;
2561 len = offsetof(rspn_id_t, rspnid_name);
2562 mtx_lock(&prison0.pr_mtx);
2563 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2564 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2565 mtx_unlock(&prison0.pr_mtx);
2566 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2567 ":%s", device_get_nameunit(isp->isp_dev));
2569 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2572 len += rp.rspnid_length;
2573 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2574 isp_put_rspn_id(isp, &rp, (rspn_id_t *)scp);
2576 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2577 FC_SCRATCH_RELEASE(isp, chan);
2581 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2582 FC_SCRATCH_RELEASE(isp, chan);
2583 if (ct->ct_cmd_resp == LS_RJT) {
2584 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2585 "Chan %d Register Symbolic Port Name rejected", chan);
2587 } else if (ct->ct_cmd_resp == LS_ACC) {
2588 isp_prt(isp, ISP_LOG_SANCFG,
2589 "Chan %d Register Symbolic Port Name accepted", chan);
2591 isp_prt(isp, ISP_LOGWARN,
2592 "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp);
2599 isp_register_node_name_24xx(ispsoftc_t *isp, int chan)
2601 fcparam *fcp = FCPARAM(isp, chan);
2604 uint8_t *scp = fcp->isp_scratch;
2607 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2608 isp_prt(isp, ISP_LOGERR, sacq);
2613 * Build the CT header and command in memory.
2615 ISP_MEMZERO(&rp, sizeof(rp));
2616 ct = &rp.rsnnnn_hdr;
2617 ct->ct_revision = CT_REVISION;
2618 ct->ct_fcs_type = CT_FC_TYPE_FC;
2619 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2620 ct->ct_cmd_resp = SNS_RSNN_NN;
2621 MAKE_NODE_NAME_FROM_WWN(rp.rsnnnn_nodename, fcp->isp_wwnn);
2622 rp.rsnnnn_length = 0;
2623 len = offsetof(rsnn_nn_t, rsnnnn_name);
2624 mtx_lock(&prison0.pr_mtx);
2625 rp.rsnnnn_length += sprintf(&scp[len + rp.rsnnnn_length],
2626 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2627 mtx_unlock(&prison0.pr_mtx);
2628 len += rp.rsnnnn_length;
2629 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2630 isp_put_rsnn_nn(isp, &rp, (rsnn_nn_t *)scp);
2632 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2633 FC_SCRATCH_RELEASE(isp, chan);
2637 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2638 FC_SCRATCH_RELEASE(isp, chan);
2639 if (ct->ct_cmd_resp == LS_RJT) {
2640 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2641 "Chan %d Register Symbolic Node Name rejected", chan);
2643 } else if (ct->ct_cmd_resp == LS_ACC) {
2644 isp_prt(isp, ISP_LOG_SANCFG,
2645 "Chan %d Register Symbolic Node Name accepted", chan);
2647 isp_prt(isp, ISP_LOGWARN,
2648 "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp);
2655 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
2665 if (handle == NIL_HANDLE) {
2669 if (handle > NPH_RESERVED - 1) {
2671 isp_prt(isp, ISP_LOGERR, "Out of port handles!");
2672 return (NIL_HANDLE);
2677 for (chan = 0; chan < isp->isp_nchan; chan++) {
2678 fcp = FCPARAM(isp, chan);
2679 if (fcp->role == ISP_ROLE_NONE)
2681 for (i = 0; i < MAX_FC_TARG; i++) {
2682 if (fcp->portdb[i].state != FC_PORTDB_STATE_NIL &&
2683 fcp->portdb[i].handle == handle)
2692 * Start a command. Locking is assumed done in the caller.
2701 ispreqt7_t local, *reqp = &local;
2704 int target, dmaresult;
2710 * Check command CDB length, etc.. We really are limited to 16 bytes
2711 * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
2712 * but probably only if we're running fairly new firmware (we'll
2713 * let the old f/w choke on an extended command queue entry).
2716 if (XS_CDBLEN(xs) > 16 || XS_CDBLEN(xs) == 0) {
2717 isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
2718 XS_SETERR(xs, HBA_REQINVAL);
2719 return (CMD_COMPLETE);
2723 * Translate the target to device handle as appropriate, checking
2724 * for correct device state as well.
2726 target = XS_TGT(xs);
2727 fcp = FCPARAM(isp, XS_CHANNEL(xs));
2729 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2730 isp_prt(isp, ISP_LOG_WARN1,
2731 "%d.%d.%jx I am not an initiator",
2732 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2733 XS_SETERR(xs, HBA_SELTIMEOUT);
2734 return (CMD_COMPLETE);
2737 if (isp->isp_state != ISP_RUNSTATE) {
2738 isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
2739 XS_SETERR(xs, HBA_BOTCH);
2740 return (CMD_COMPLETE);
2743 isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target);
2744 lp = &fcp->portdb[target];
2745 if (target < 0 || target >= MAX_FC_TARG ||
2746 lp->is_target == 0) {
2747 XS_SETERR(xs, HBA_SELTIMEOUT);
2748 return (CMD_COMPLETE);
2750 if (fcp->isp_loopstate != LOOP_READY) {
2751 isp_prt(isp, ISP_LOGDEBUG1,
2752 "%d.%d.%jx loop is not ready",
2753 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2754 return (CMD_RQLATER);
2756 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
2757 isp_prt(isp, ISP_LOGDEBUG1,
2758 "%d.%d.%jx target zombie",
2759 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2760 return (CMD_RQLATER);
2762 if (lp->state != FC_PORTDB_STATE_VALID) {
2763 isp_prt(isp, ISP_LOGDEBUG1,
2764 "%d.%d.%jx bad db port state 0x%x",
2765 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs), lp->state);
2766 XS_SETERR(xs, HBA_SELTIMEOUT);
2767 return (CMD_COMPLETE);
2772 qep = isp_getrqentry(isp);
2774 isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow");
2775 XS_SETERR(xs, HBA_BOTCH);
2776 return (CMD_EAGAIN);
2778 XS_SETERR(xs, HBA_NOERROR);
2781 * Now see if we need to synchronize the ISP with respect to anything.
2782 * We do dual duty here (cough) for synchronizing for buses other
2783 * than which we got here to send a command to.
2785 ISP_MEMZERO(reqp, QENTRY_LEN);
2786 if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
2787 isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
2788 m->mrk_header.rqs_entry_count = 1;
2789 m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
2790 m->mrk_modifier = SYNC_ALL;
2791 m->mrk_vphdl = XS_CHANNEL(xs);
2792 isp_put_marker_24xx(isp, m, qep);
2793 ISP_SYNC_REQUEST(isp);
2794 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
2799 * NB: we do not support long CDBs (yet)
2801 cdblen = XS_CDBLEN(xs);
2802 if (cdblen > sizeof (reqp->req_cdb)) {
2803 isp_prt(isp, ISP_LOGERR, "Command Length %u too long for this chip", cdblen);
2804 XS_SETERR(xs, HBA_REQINVAL);
2805 return (CMD_COMPLETE);
2808 reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
2809 reqp->req_header.rqs_entry_count = 1;
2810 reqp->req_nphdl = lp->handle;
2811 reqp->req_time = XS_TIME(xs);
2812 be64enc(reqp->req_lun, CAM_EXTLUN_BYTE_SWIZZLE(XS_LUN(xs)));
2814 reqp->req_alen_datadir = FCP_CMND_DATA_READ;
2815 else if (XS_XFROUT(xs))
2816 reqp->req_alen_datadir = FCP_CMND_DATA_WRITE;
2818 reqp->req_task_attribute = XS_TAG_TYPE(xs);
2820 reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE;
2821 reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) &
2823 if (FCPARAM(isp, XS_CHANNEL(xs))->fctape_enabled && (lp->prli_word3 & PRLI_WD3_RETRY)) {
2824 if (FCP_NEXT_CRN(isp, &reqp->req_crn, xs)) {
2825 isp_prt(isp, ISP_LOG_WARN1,
2826 "%d.%d.%jx cannot generate next CRN",
2827 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2828 XS_SETERR(xs, HBA_BOTCH);
2829 return (CMD_EAGAIN);
2832 ISP_MEMCPY(reqp->req_cdb, XS_CDBP(xs), cdblen);
2833 reqp->req_dl = XS_XFRLEN(xs);
2834 reqp->req_tidlo = lp->portid;
2835 reqp->req_tidhi = lp->portid >> 16;
2836 reqp->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs));
2838 /* Whew. Thankfully the same for type 7 requests */
2839 reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR);
2840 if (reqp->req_handle == 0) {
2841 isp_prt(isp, ISP_LOG_WARN1, "out of xflist pointers");
2842 XS_SETERR(xs, HBA_BOTCH);
2843 return (CMD_EAGAIN);
2847 * Set up DMA and/or do any platform dependent swizzling of the request entry
2848 * so that the Qlogic F/W understands what is being asked of it.
2850 * The callee is responsible for adding all requests at this point.
2852 dmaresult = ISP_DMASETUP(isp, xs, reqp);
2853 if (dmaresult != 0) {
2854 isp_destroy_handle(isp, reqp->req_handle);
2856 * dmasetup sets actual error in packet, and
2857 * return what we were given to return.
2861 isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
2867 * Locks (ints blocked) assumed held.
2871 isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
2880 uint8_t local[QENTRY_LEN];
2883 case ISPCTL_RESET_BUS:
2885 * Issue a bus reset.
2887 isp_prt(isp, ISP_LOGERR, "BUS RESET NOT IMPLEMENTED");
2890 case ISPCTL_RESET_DEV:
2893 isp24xx_statusreq_t *sp;
2896 chan = va_arg(ap, int);
2897 tgt = va_arg(ap, int);
2899 fcp = FCPARAM(isp, chan);
2901 if (tgt < 0 || tgt >= MAX_FC_TARG) {
2902 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to reset bad target %d", chan, tgt);
2905 lp = &fcp->portdb[tgt];
2906 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
2907 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
2911 tmf = (isp24xx_tmf_t *) local;
2912 ISP_MEMZERO(tmf, QENTRY_LEN);
2913 tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
2914 tmf->tmf_header.rqs_entry_count = 1;
2915 tmf->tmf_nphdl = lp->handle;
2917 tmf->tmf_timeout = 4;
2918 tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
2919 tmf->tmf_tidlo = lp->portid;
2920 tmf->tmf_tidhi = lp->portid >> 16;
2921 tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
2922 isp_put_24xx_tmf(isp, tmf, isp->isp_iocb);
2923 if (isp->isp_dblev & ISP_LOGDEBUG1)
2924 isp_print_bytes(isp, "TMF IOCB request", QENTRY_LEN, isp->isp_iocb);
2925 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, QENTRY_LEN, chan);
2926 fcp->sendmarker = 1;
2928 isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
2929 MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL,
2930 MBCMD_DEFAULT_TIMEOUT + tmf->tmf_timeout * 1000000);
2931 mbs.param[1] = QENTRY_LEN;
2932 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
2933 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
2934 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
2935 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
2936 isp_mboxcmd(isp, &mbs);
2937 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
2940 MEMORYBARRIER(isp, SYNC_IFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
2941 if (isp->isp_dblev & ISP_LOGDEBUG1)
2942 isp_print_bytes(isp, "TMF IOCB response", QENTRY_LEN, &((isp24xx_statusreq_t *)isp->isp_iocb)[1]);
2943 sp = (isp24xx_statusreq_t *) local;
2944 isp_get_24xx_response(isp, &((isp24xx_statusreq_t *)isp->isp_iocb)[1], sp);
2945 if (sp->req_completion_status == 0) {
2948 isp_prt(isp, ISP_LOGWARN, "Chan %d reset of target %d returned 0x%x", chan, tgt, sp->req_completion_status);
2951 case ISPCTL_ABORT_CMD:
2953 isp24xx_abrt_t *ab = (isp24xx_abrt_t *)&local;
2956 xs = va_arg(ap, XS_T *);
2960 chan = XS_CHANNEL(xs);
2962 handle = isp_find_handle(isp, xs);
2964 isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort");
2968 fcp = FCPARAM(isp, chan);
2969 if (tgt < 0 || tgt >= MAX_FC_TARG) {
2970 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to abort bad target %d", chan, tgt);
2973 lp = &fcp->portdb[tgt];
2974 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
2975 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
2978 isp_prt(isp, ISP_LOGALL, "Chan %d Abort Cmd for N-Port 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
2979 ISP_MEMZERO(ab, QENTRY_LEN);
2980 ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO;
2981 ab->abrt_header.rqs_entry_count = 1;
2982 ab->abrt_handle = lp->handle;
2983 ab->abrt_cmd_handle = handle;
2984 ab->abrt_tidlo = lp->portid;
2985 ab->abrt_tidhi = lp->portid >> 16;
2986 ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan);
2987 isp_put_24xx_abrt(isp, ab, isp->isp_iocb);
2988 if (isp->isp_dblev & ISP_LOGDEBUG1)
2989 isp_print_bytes(isp, "AB IOCB quest", QENTRY_LEN, isp->isp_iocb);
2990 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, 2 * QENTRY_LEN, chan);
2992 ISP_MEMZERO(&mbs, sizeof (mbs));
2993 MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
2994 mbs.param[1] = QENTRY_LEN;
2995 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
2996 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
2997 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
2998 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
3000 isp_mboxcmd(isp, &mbs);
3001 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
3004 MEMORYBARRIER(isp, SYNC_IFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
3005 if (isp->isp_dblev & ISP_LOGDEBUG1)
3006 isp_print_bytes(isp, "AB IOCB response", QENTRY_LEN, &((isp24xx_abrt_t *)isp->isp_iocb)[1]);
3007 isp_get_24xx_abrt(isp, &((isp24xx_abrt_t *)isp->isp_iocb)[1], ab);
3008 if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY) {
3011 isp_prt(isp, ISP_LOGWARN, "Chan %d handle %d abort returned 0x%x", chan, tgt, ab->abrt_nphdl);
3013 case ISPCTL_FCLINK_TEST:
3018 chan = va_arg(ap, int);
3019 usdelay = va_arg(ap, int);
3023 return (isp_fclink_test(isp, chan, usdelay));
3025 case ISPCTL_SCAN_FABRIC:
3028 chan = va_arg(ap, int);
3030 return (isp_scan_fabric(isp, chan));
3032 case ISPCTL_SCAN_LOOP:
3035 chan = va_arg(ap, int);
3037 return (isp_scan_loop(isp, chan));
3039 case ISPCTL_PDB_SYNC:
3042 chan = va_arg(ap, int);
3044 return (isp_pdb_sync(isp, chan));
3046 case ISPCTL_SEND_LIP:
3049 case ISPCTL_GET_PDB:
3053 chan = va_arg(ap, int);
3054 tgt = va_arg(ap, int);
3055 pdb = va_arg(ap, isp_pdb_t *);
3057 return (isp_getpdb(isp, chan, tgt, pdb));
3059 case ISPCTL_GET_NAMES:
3061 uint64_t *wwnn, *wwnp;
3063 chan = va_arg(ap, int);
3064 tgt = va_arg(ap, int);
3065 wwnn = va_arg(ap, uint64_t *);
3066 wwnp = va_arg(ap, uint64_t *);
3068 if (wwnn == NULL && wwnp == NULL) {
3072 *wwnn = isp_get_wwn(isp, chan, tgt, 1);
3073 if (*wwnn == INI_NONE) {
3078 *wwnp = isp_get_wwn(isp, chan, tgt, 0);
3079 if (*wwnp == INI_NONE) {
3091 p = va_arg(ap, isp_plcmd_t *);
3094 if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
3095 return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags));
3098 isp_next_handle(isp, &p->handle);
3099 r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags);
3100 if ((r & 0xffff) == MBOX_PORT_ID_USED) {
3101 p->handle = r >> 16;
3105 } while ((r & 0xffff) == MBOX_LOOP_ID_USED);
3108 case ISPCTL_CHANGE_ROLE:
3113 chan = va_arg(ap, int);
3114 role = va_arg(ap, int);
3116 return (isp_fc_change_role(isp, chan, role));
3119 isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
3127 * Interrupt Service Routine(s).
3129 * External (OS) framework has done the appropriate locking,
3130 * and the locking will be held throughout this function.
3133 #ifdef ISP_TARGET_MODE
3135 isp_intr_atioq(ispsoftc_t *isp)
3137 uint8_t qe[QENTRY_LEN];
3140 uint32_t iptr, optr, oop;
3142 iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
3143 optr = isp->isp_atioodx;
3144 while (optr != iptr) {
3146 MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN, -1);
3147 addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop);
3148 isp_get_hdr(isp, addr, (isphdr_t *)qe);
3149 hp = (isphdr_t *)qe;
3150 switch (hp->rqs_entry_type) {
3151 case RQSTYPE_NOTIFY:
3153 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue.*/
3154 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue.*/
3155 (void) isp_target_notify(isp, addr, &oop,
3156 ATIO_QUEUE_LEN(isp));
3158 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/
3160 isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
3163 optr = ISP_NXT_QENTRY(oop, ATIO_QUEUE_LEN(isp));
3165 if (isp->isp_atioodx != optr) {
3166 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
3167 isp->isp_atioodx = optr;
3173 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0)
3177 if (!isp->isp_mboxbsy) {
3178 isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0);
3181 obits = isp->isp_obits;
3182 isp->isp_mboxtmp[0] = mbox0;
3183 for (i = 1; i < ISP_NMBOX(isp); i++) {
3184 if ((obits & (1 << i)) == 0)
3186 isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
3188 isp->isp_mboxbsy = 0;
3192 isp_intr_respq(ispsoftc_t *isp)
3195 uint8_t qe[QENTRY_LEN];
3196 isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe;
3197 ispstatus_cont_t *scp = (ispstatus_cont_t *)qe;
3199 uint8_t *resp, *snsp, etype;
3200 uint16_t scsi_status;
3201 uint32_t iptr, cont = 0, cptr, optr, rlen, slen, sptr, totslen;
3204 * We can't be getting this now.
3206 if (isp->isp_state != ISP_RUNSTATE) {
3207 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready");
3211 iptr = ISP_READ(isp, BIU2400_RSPINP);
3212 optr = isp->isp_resodx;
3213 while (optr != iptr) {
3215 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
3216 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
3219 * Synchronize our view of this response queue entry.
3221 MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1);
3222 if (isp->isp_dblev & ISP_LOGDEBUG1)
3223 isp_print_qentry(isp, "Response Queue Entry", cptr, hp);
3224 isp_get_hdr(isp, hp, &sp->req_header);
3227 * Log IOCBs rejected by the firmware. We can't really do
3228 * much more about them, since it just should not happen.
3230 if (sp->req_header.rqs_flags & RQSFLAG_BADTYPE) {
3231 isp_print_qentry(isp, "invalid entry type", cptr, hp);
3234 if (sp->req_header.rqs_flags & RQSFLAG_BADPARAM) {
3235 isp_print_qentry(isp, "invalid entry parameter", cptr, hp);
3238 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
3239 isp_print_qentry(isp, "invalid entry count", cptr, hp);
3242 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
3243 isp_print_qentry(isp, "invalid entry order", cptr, hp);
3247 etype = sp->req_header.rqs_entry_type;
3249 /* We expected Status Continuation, but got different IOCB. */
3250 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
3255 if (etype == RQSTYPE_RESPONSE) {
3256 isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp);
3258 } else if (etype == RQSTYPE_STATUS_CONT) {
3259 isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
3261 slen = min(cont, sizeof(scp->req_sense_data));
3262 XS_SENSE_APPEND(cont_xs, scp->req_sense_data, slen);
3267 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3268 "Expecting Status Continuations for %u bytes",
3272 isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
3274 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3276 } else if (isp_handle_other_response(isp, etype, hp,
3277 &cptr, RESULT_QUEUE_LEN(isp))) {
3278 /* More then one IOCB could be consumed. */
3279 while (sptr != cptr) {
3280 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3281 sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp));
3282 hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr);
3284 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3285 optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
3288 /* We don't know what was this -- log and skip. */
3289 isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr);
3290 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3294 xs = isp_find_xs(isp, sp->req_handle);
3297 * Only whine if this isn't the expected fallout of
3298 * aborting the command or resetting the target.
3300 if (sp->req_completion_status != RQCS_ABORTED &&
3301 sp->req_completion_status != RQCS_RESET_OCCURRED)
3302 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)",
3303 sp->req_handle, sp->req_completion_status);
3304 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3308 resp = snsp = sp->req_rsp_sense;
3309 rlen = slen = totslen = 0;
3310 scsi_status = sp->req_scsi_status;
3311 if (scsi_status & RQCS_RV) {
3312 rlen = sp->req_response_len;
3315 if (scsi_status & RQCS_SV) {
3316 totslen = sp->req_sense_len;
3317 slen = MIN(totslen, sizeof(sp->req_rsp_sense) - rlen);
3319 *XS_STSP(xs) = scsi_status & 0xff;
3320 if (scsi_status & RQCS_RESID)
3321 XS_SET_RESID(xs, sp->req_fcp_residual);
3323 XS_SET_RESID(xs, 0);
3325 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
3328 const char *rnames[10] = {
3329 "Task Management function complete",
3330 "FCP_DATA length different than FCP_BURST_LEN",
3331 "FCP_CMND fields invalid",
3332 "FCP_DATA parameter mismatch with FCP_DATA_RO",
3333 "Task Management function rejected",
3334 "Task Management function failed",
3337 "Task Management function succeeded",
3338 "Task Management function incorrect logical unit number",
3340 uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
3341 if (code >= nitems(rnames) || rnames[code] == NULL) {
3342 ISP_SNPRINTF(lb, sizeof(lb),
3343 "Unknown FCP Response Code 0x%x", code);
3348 isp_xs_prt(isp, xs, ISP_LOGWARN,
3349 "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
3350 rlen, ptr, XS_CDBP(xs)[0] & 0xff);
3351 if (code != FCP_RSPNS_TMF_DONE &&
3352 code != FCP_RSPNS_TMF_SUCCEEDED)
3353 XS_SETERR(xs, HBA_BOTCH);
3355 isp_parse_status_24xx(isp, sp, xs);
3357 XS_SAVE_SENSE(xs, snsp, slen);
3358 if (totslen > slen) {
3359 cont = totslen - slen;
3361 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3362 "Expecting Status Continuations for %u bytes",
3367 ISP_DMAFREE(isp, xs);
3368 isp_destroy_handle(isp, sp->req_handle);
3369 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3371 /* Complete command if we expect no Status Continuations. */
3376 /* We haven't received all Status Continuations, but that is it. */
3380 /* If we processed any IOCBs, let ISP know about it. */
3381 if (optr != isp->isp_resodx) {
3382 ISP_WRITE(isp, BIU2400_RSPOUTP, optr);
3383 isp->isp_resodx = optr;
3389 isp_intr_async(ispsoftc_t *isp, uint16_t mbox)
3394 isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
3397 case ASYNC_SYSTEM_ERROR:
3398 isp->isp_state = ISP_CRASHED;
3399 for (chan = 0; chan < isp->isp_nchan; chan++) {
3400 FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
3401 isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
3404 * Were we waiting for a mailbox command to complete?
3405 * If so, it's dead, so wake up the waiter.
3407 if (isp->isp_mboxbsy) {
3409 isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
3410 isp->isp_mboxbsy = 0;
3413 * It's up to the handler for isp_async to reinit stuff and
3414 * restart the firmware
3416 isp_async(isp, ISPASYNC_FW_CRASH);
3419 case ASYNC_RQS_XFER_ERR:
3420 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
3423 case ASYNC_RSP_XFER_ERR:
3424 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
3427 case ASYNC_ATIO_XFER_ERR:
3428 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
3431 case ASYNC_LIP_OCCURRED:
3432 case ASYNC_LIP_NOS_OLS_RECV:
3433 case ASYNC_LIP_ERROR:
3436 * These are broadcast events that have to be sent across
3437 * all active channels.
3439 for (chan = 0; chan < isp->isp_nchan; chan++) {
3440 fcp = FCPARAM(isp, chan);
3441 int topo = fcp->isp_topo;
3443 if (fcp->role == ISP_ROLE_NONE)
3445 if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3446 fcp->isp_loopstate = LOOP_HAVE_LINK;
3447 ISP_SET_SENDMARKER(isp, chan, 1);
3448 isp_async(isp, ISPASYNC_LIP, chan);
3449 #ifdef ISP_TARGET_MODE
3450 isp_target_async(isp, chan, mbox);
3453 * We've had problems with data corruption occurring on
3454 * commands that complete (with no apparent error) after
3455 * we receive a LIP. This has been observed mostly on
3456 * Local Loop topologies. To be safe, let's just mark
3457 * all active initiator commands as dead.
3459 if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
3461 for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) {
3465 hdp = &isp->isp_xflist[i];
3466 if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
3470 if (XS_CHANNEL(xs) != chan) {
3474 isp_prt(isp, ISP_LOG_WARN1,
3475 "%d.%d.%jx bus reset set at %s:%u",
3476 XS_CHANNEL(xs), XS_TGT(xs),
3477 (uintmax_t)XS_LUN(xs),
3478 __func__, __LINE__);
3479 XS_SETERR(xs, HBA_BUSRESET);
3482 isp_prt(isp, ISP_LOGERR, lipd, chan, j);
3490 * This is a broadcast event that has to be sent across
3491 * all active channels.
3493 for (chan = 0; chan < isp->isp_nchan; chan++) {
3494 fcp = FCPARAM(isp, chan);
3495 if (fcp->role == ISP_ROLE_NONE)
3497 fcp->isp_linkstate = 1;
3498 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3499 fcp->isp_loopstate = LOOP_HAVE_LINK;
3500 ISP_SET_SENDMARKER(isp, chan, 1);
3501 isp_async(isp, ISPASYNC_LOOP_UP, chan);
3502 #ifdef ISP_TARGET_MODE
3503 isp_target_async(isp, chan, mbox);
3508 case ASYNC_LOOP_DOWN:
3510 * This is a broadcast event that has to be sent across
3511 * all active channels.
3513 for (chan = 0; chan < isp->isp_nchan; chan++) {
3514 fcp = FCPARAM(isp, chan);
3515 if (fcp->role == ISP_ROLE_NONE)
3517 ISP_SET_SENDMARKER(isp, chan, 1);
3518 fcp->isp_linkstate = 0;
3519 fcp->isp_loopstate = LOOP_NIL;
3520 isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
3521 #ifdef ISP_TARGET_MODE
3522 isp_target_async(isp, chan, mbox);
3527 case ASYNC_LOOP_RESET:
3529 * This is a broadcast event that has to be sent across
3530 * all active channels.
3532 for (chan = 0; chan < isp->isp_nchan; chan++) {
3533 fcp = FCPARAM(isp, chan);
3534 if (fcp->role == ISP_ROLE_NONE)
3536 ISP_SET_SENDMARKER(isp, chan, 1);
3537 if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3538 fcp->isp_loopstate = LOOP_HAVE_LINK;
3539 isp_async(isp, ISPASYNC_LOOP_RESET, chan);
3540 #ifdef ISP_TARGET_MODE
3541 isp_target_async(isp, chan, mbox);
3546 case ASYNC_PDB_CHANGED:
3548 int echan, nphdl, nlstate, reason;
3550 nphdl = ISP_READ(isp, OUTMAILBOX1);
3551 nlstate = ISP_READ(isp, OUTMAILBOX2);
3552 reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
3553 if (ISP_CAP_MULTI_ID(isp)) {
3554 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3555 if (chan == 0xff || nphdl == NIL_HANDLE) {
3557 echan = isp->isp_nchan - 1;
3558 } else if (chan >= isp->isp_nchan) {
3566 for (; chan <= echan; chan++) {
3567 fcp = FCPARAM(isp, chan);
3568 if (fcp->role == ISP_ROLE_NONE)
3570 if (fcp->isp_loopstate > LOOP_LTEST_DONE) {
3571 if (nphdl != NIL_HANDLE &&
3572 nphdl == fcp->isp_login_hdl &&
3573 reason == PDB24XX_AE_OPN_2)
3575 fcp->isp_loopstate = LOOP_LTEST_DONE;
3576 } else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3577 fcp->isp_loopstate = LOOP_HAVE_LINK;
3578 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3579 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
3583 case ASYNC_CHANGE_NOTIFY:
3587 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) |
3588 ISP_READ(isp, OUTMAILBOX2);
3589 if (ISP_CAP_MULTI_ID(isp)) {
3590 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3591 if (chan >= isp->isp_nchan)
3596 fcp = FCPARAM(isp, chan);
3597 if (fcp->role == ISP_ROLE_NONE)
3599 if (fcp->isp_loopstate > LOOP_LTEST_DONE)
3600 fcp->isp_loopstate = LOOP_LTEST_DONE;
3601 else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3602 fcp->isp_loopstate = LOOP_HAVE_LINK;
3603 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3604 ISPASYNC_CHANGE_SNS, portid);
3607 case ASYNC_ERR_LOGGING_DISABLED:
3608 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)",
3609 ISP_READ(isp, OUTMAILBOX1));
3611 case ASYNC_P2P_INIT_ERR:
3612 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)",
3613 ISP_READ(isp, OUTMAILBOX1));
3616 isp_prt(isp, ISP_LOGWARN, "Receive Error");
3618 case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */
3619 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
3621 case ASYNC_FW_RESTART_COMPLETE:
3622 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete");
3624 case ASYNC_TEMPERATURE_ALERT:
3625 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)",
3626 ISP_READ(isp, OUTMAILBOX1));
3628 case ASYNC_INTER_DRIVER_COMP:
3629 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication complete");
3631 case ASYNC_INTER_DRIVER_NOTIFY:
3632 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication notification");
3634 case ASYNC_INTER_DRIVER_TIME_EXT:
3635 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication time extended");
3637 case ASYNC_TRANSCEIVER_INSERTION:
3638 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)",
3639 ISP_READ(isp, OUTMAILBOX1));
3641 case ASYNC_TRANSCEIVER_REMOVAL:
3642 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal");
3644 case ASYNC_NIC_FW_STATE_CHANGE:
3645 isp_prt(isp, ISP_LOGDEBUG0, "NIC Firmware State Change");
3647 case ASYNC_AUTOLOAD_FW_COMPLETE:
3648 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete");
3650 case ASYNC_AUTOLOAD_FW_FAILURE:
3651 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure");
3654 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
3660 * Handle other response entries. A pointer to the request queue output
3661 * index is here in case we want to eat several entries at once, although
3662 * this is not used currently.
3666 isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *optrp, uint16_t ql)
3670 uint32_t hdl, portid;
3674 case RQSTYPE_MARKER:
3675 isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
3677 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/
3678 isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
3679 portid = (uint32_t)rid.ridacq_vp_port_hi << 16 |
3680 rid.ridacq_vp_port_lo;
3681 if (rid.ridacq_format == 0) {
3682 for (chan = 0; chan < isp->isp_nchan; chan++) {
3683 fcparam *fcp = FCPARAM(isp, chan);
3684 if (fcp->role == ISP_ROLE_NONE)
3686 c = (chan == 0) ? 127 : (chan - 1);
3687 if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
3689 fcp->isp_loopstate = LOOP_HAVE_LINK;
3690 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3691 chan, ISPASYNC_CHANGE_OTHER);
3693 fcp->isp_loopstate = LOOP_NIL;
3694 isp_async(isp, ISPASYNC_LOOP_DOWN,
3699 fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index);
3700 if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
3701 rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
3702 fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7;
3703 fcp->isp_portid = portid;
3704 fcp->isp_loopstate = LOOP_HAVE_ADDR;
3705 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3706 rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
3708 fcp->isp_loopstate = LOOP_NIL;
3709 isp_async(isp, ISPASYNC_LOOP_DOWN,
3710 rid.ridacq_vp_index);
3714 case RQSTYPE_CT_PASSTHRU:
3715 case RQSTYPE_VP_MODIFY:
3716 case RQSTYPE_VP_CTRL:
3718 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
3719 ptr = isp_find_xs(isp, hdl);
3721 isp_destroy_handle(isp, hdl);
3722 memcpy(ptr, hp, QENTRY_LEN);
3726 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue. */
3728 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue. */
3729 case RQSTYPE_ABTS_RSP:
3730 #ifdef ISP_TARGET_MODE
3731 return (isp_target_notify(isp, hp, optrp, ql));
3740 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs)
3742 int ru_marked, sv_marked;
3743 int chan = XS_CHANNEL(xs);
3745 switch (sp->req_completion_status) {
3749 case RQCS_DMA_ERROR:
3750 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error");
3752 XS_SETERR(xs, HBA_BOTCH);
3755 case RQCS_TRANSPORT_ERROR:
3756 isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error");
3758 XS_SETERR(xs, HBA_BOTCH);
3761 case RQCS_RESET_OCCURRED:
3762 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command");
3763 FCPARAM(isp, chan)->sendmarker = 1;
3765 XS_SETERR(xs, HBA_BUSRESET);
3769 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted");
3770 FCPARAM(isp, chan)->sendmarker = 1;
3772 XS_SETERR(xs, HBA_ABORTED);
3776 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out");
3778 XS_SETERR(xs, HBA_CMDTIMEOUT);
3781 case RQCS_DATA_OVERRUN:
3782 XS_SET_RESID(xs, sp->req_resid);
3783 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun");
3785 XS_SETERR(xs, HBA_DATAOVR);
3788 case RQCS_DRE: /* data reassembly error */
3789 isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs));
3791 XS_SETERR(xs, HBA_BOTCH);
3794 case RQCS_TABORT: /* aborted by target */
3795 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs));
3797 XS_SETERR(xs, HBA_ABORTED);
3800 case RQCS_DATA_UNDERRUN:
3801 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
3803 * We can get an underrun w/o things being marked
3804 * if we got a non-zero status.
3806 sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
3807 if ((ru_marked == 0 && sv_marked == 0) ||
3808 (sp->req_resid > XS_XFRLEN(xs))) {
3809 isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked");
3811 XS_SETERR(xs, HBA_BOTCH);
3814 XS_SET_RESID(xs, sp->req_resid);
3815 isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff);
3818 case RQCS_PORT_UNAVAILABLE:
3820 * No such port on the loop. Moral equivalent of SELTIMEO
3822 case RQCS_PORT_LOGGED_OUT:
3825 uint8_t sts = sp->req_completion_status & 0xff;
3826 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
3830 * It was there (maybe)- treat as a selection timeout.
3832 if (sts == RQCS_PORT_UNAVAILABLE) {
3833 reason = "unavailable";
3838 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
3839 chan, reason, XS_TGT(xs));
3841 /* XXX: Should we trigger rescan or FW announce change? */
3844 lp = &fcp->portdb[XS_TGT(xs)];
3845 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
3846 *XS_STSP(xs) = SCSI_BUSY;
3847 XS_SETERR(xs, HBA_TGTBSY);
3849 XS_SETERR(xs, HBA_SELTIMEOUT);
3853 case RQCS_PORT_CHANGED:
3854 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan);
3856 *XS_STSP(xs) = SCSI_BUSY;
3857 XS_SETERR(xs, HBA_TGTBSY);
3861 case RQCS_ENOMEM: /* f/w resource unavailable */
3862 isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan);
3864 *XS_STSP(xs) = SCSI_BUSY;
3865 XS_SETERR(xs, HBA_TGTBSY);
3869 case RQCS_TMO: /* task management overrun */
3870 isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan);
3872 *XS_STSP(xs) = SCSI_BUSY;
3873 XS_SETERR(xs, HBA_TGTBSY);
3878 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan);
3882 XS_SETERR(xs, HBA_BOTCH);
3885 #define ISP_FC_IBITS(op) ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3]))
3886 #define ISP_FC_OBITS(op) ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7]))
3888 #define ISP_FC_OPMAP(in0, out0) 0, 0, 0, in0, 0, 0, 0, out0
3889 #define ISP_FC_OPMAP_HALF(in1, in0, out1, out0) 0, 0, in1, in0, 0, 0, out1, out0
3890 #define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0) in3, in2, in1, in0, out3, out2, out1, out0
3891 static const uint32_t mbpfc[] = {
3892 ISP_FC_OPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
3893 ISP_FC_OPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
3894 ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f), /* 0x02: MBOX_EXEC_FIRMWARE */
3895 ISP_FC_OPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */
3896 ISP_FC_OPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
3897 ISP_FC_OPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
3898 ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */
3899 ISP_FC_OPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
3900 ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f), /* 0x08: MBOX_ABOUT_FIRMWARE */
3901 ISP_FC_OPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */
3902 ISP_FC_OPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
3903 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */
3904 ISP_FC_OPMAP(0x00, 0x00), /* 0x0c: */
3905 ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
3906 ISP_FC_OPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
3907 ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
3908 ISP_FC_OPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
3909 ISP_FC_OPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
3910 ISP_FC_OPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
3911 ISP_FC_OPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
3912 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03), /* 0x14: MBOX_STOP_FIRMWARE */
3913 ISP_FC_OPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */
3914 ISP_FC_OPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */
3915 ISP_FC_OPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */
3916 ISP_FC_OPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */
3917 ISP_FC_OPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */
3918 ISP_FC_OPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */
3919 ISP_FC_OPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
3920 ISP_FC_OPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */
3921 ISP_FC_OPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
3922 ISP_FC_OPMAP(0x00, 0x00), /* 0x1e: */
3923 ISP_FC_OPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
3924 ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf), /* 0x20: MBOX_GET_LOOP_ID */
3925 ISP_FC_OPMAP(0x00, 0x00), /* 0x21: */
3926 ISP_FC_OPMAP(0x03, 0x4b), /* 0x22: MBOX_GET_TIMEOUT_PARAMS */
3927 ISP_FC_OPMAP(0x00, 0x00), /* 0x23: */
3928 ISP_FC_OPMAP(0x00, 0x00), /* 0x24: */
3929 ISP_FC_OPMAP(0x00, 0x00), /* 0x25: */
3930 ISP_FC_OPMAP(0x00, 0x00), /* 0x26: */
3931 ISP_FC_OPMAP(0x00, 0x00), /* 0x27: */
3932 ISP_FC_OPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
3933 ISP_FC_OPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
3934 ISP_FC_OPMAP(0x00, 0x00), /* 0x2a: */
3935 ISP_FC_OPMAP(0x00, 0x00), /* 0x2b: */
3936 ISP_FC_OPMAP(0x00, 0x00), /* 0x2c: */
3937 ISP_FC_OPMAP(0x00, 0x00), /* 0x2d: */
3938 ISP_FC_OPMAP(0x00, 0x00), /* 0x2e: */
3939 ISP_FC_OPMAP(0x00, 0x00), /* 0x2f: */
3940 ISP_FC_OPMAP(0x00, 0x00), /* 0x30: */
3941 ISP_FC_OPMAP(0x00, 0x00), /* 0x31: */
3942 ISP_FC_OPMAP(0x4b, 0x4b), /* 0x32: MBOX_SET_TIMEOUT_PARAMS */
3943 ISP_FC_OPMAP(0x00, 0x00), /* 0x33: */
3944 ISP_FC_OPMAP(0x00, 0x00), /* 0x34: */
3945 ISP_FC_OPMAP(0x00, 0x00), /* 0x35: */
3946 ISP_FC_OPMAP(0x00, 0x00), /* 0x36: */
3947 ISP_FC_OPMAP(0x00, 0x00), /* 0x37: */
3948 ISP_FC_OPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
3949 ISP_FC_OPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
3950 ISP_FC_OPMAP(0x00, 0x00), /* 0x3a: */
3951 ISP_FC_OPMAP(0x00, 0x00), /* 0x3b: */
3952 ISP_FC_OPMAP(0x00, 0x00), /* 0x3c: */
3953 ISP_FC_OPMAP(0x00, 0x00), /* 0x3d: */
3954 ISP_FC_OPMAP(0x00, 0x00), /* 0x3e: */
3955 ISP_FC_OPMAP(0x00, 0x00), /* 0x3f: */
3956 ISP_FC_OPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */
3957 ISP_FC_OPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */
3958 ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf), /* 0x42: MBOX_GET_RESOURCE_COUNT */
3959 ISP_FC_OPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */
3960 ISP_FC_OPMAP(0x00, 0x00), /* 0x44: */
3961 ISP_FC_OPMAP(0x00, 0x00), /* 0x45: */
3962 ISP_FC_OPMAP(0x00, 0x00), /* 0x46: */
3963 ISP_FC_OPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */
3964 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
3965 ISP_FC_OPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */
3966 ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
3967 ISP_FC_OPMAP(0x00, 0x00), /* 0x4b: */
3968 ISP_FC_OPMAP(0x00, 0x00), /* 0x4c: */
3969 ISP_FC_OPMAP(0x00, 0x00), /* 0x4d: */
3970 ISP_FC_OPMAP(0x00, 0x00), /* 0x4e: */
3971 ISP_FC_OPMAP(0x00, 0x00), /* 0x4f: */
3972 ISP_FC_OPMAP(0x00, 0x00), /* 0x50: */
3973 ISP_FC_OPMAP(0x00, 0x00), /* 0x51: */
3974 ISP_FC_OPMAP(0x00, 0x00), /* 0x52: */
3975 ISP_FC_OPMAP(0x00, 0x00), /* 0x53: */
3976 ISP_FC_OPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
3977 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */
3978 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */
3979 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */
3980 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */
3981 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */
3982 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */
3983 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
3984 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
3985 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */
3986 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */
3987 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */
3988 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */
3989 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */
3990 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */
3991 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
3992 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
3993 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */
3994 ISP_FC_OPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */
3995 ISP_FC_OPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */
3996 ISP_FC_OPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */
3997 ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f), /* 0x69: MBOX_GET_FW_STATE */
3998 ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */
3999 ISP_FC_OPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */
4000 ISP_FC_OPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */
4001 ISP_FC_OPMAP(0x00, 0x00), /* 0x6d: */
4002 ISP_FC_OPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */
4003 ISP_FC_OPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */
4004 ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03), /* 0x70: MBOX_SEND_CHANGE_REQUEST */
4005 ISP_FC_OPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */
4006 ISP_FC_OPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */
4007 ISP_FC_OPMAP(0x00, 0x00), /* 0x73: */
4008 ISP_FC_OPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */
4009 ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07), /* 0x75: GET PORT/NODE NAME LIST */
4010 ISP_FC_OPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */
4011 ISP_FC_OPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */
4012 ISP_FC_OPMAP(0x00, 0x00), /* 0x78: */
4013 ISP_FC_OPMAP(0x00, 0x00), /* 0x79: */
4014 ISP_FC_OPMAP(0x00, 0x00), /* 0x7a: */
4015 ISP_FC_OPMAP(0x00, 0x00), /* 0x7b: */
4016 ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07), /* 0x7c: Get ID List */
4017 ISP_FC_OPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */
4018 ISP_FC_OPMAP(0x0f, 0x01) /* 0x7e: LUN RESET */
4020 #define MAX_FC_OPCODE 0x7e
4024 * (1): this sets bits 21..16 in mailbox register #8, which we nominally
4025 * do not access at this time in the core driver. The caller is
4026 * responsible for setting this register first (Gross!). The assumption
4027 * is that we won't overflow.
4030 static const char *fc_mbcmd_names[] = {
4044 "WRITE RAM WORD EXTENDED",
4046 "READ RAM WORD EXTENDED",
4047 "INIT REQUEST QUEUE", /* 10h */
4048 "INIT RESULT QUEUE",
4058 "SINGLE STEP QUEUE",
4060 "GET DEV QUEUE STATUS",
4062 "GET FIRMWARE STATUS",
4063 "GET LOOP ID", /* 20h */
4065 "GET TIMEOUT PARAMS",
4071 "GET FIRMWARE OPTIONS",
4072 "GET PORT QUEUE PARAMS",
4073 "GENERATE SYSTEM ERROR",
4079 "WRITE SFP", /* 30h */
4081 "SET TIMEOUT PARAMS",
4087 "SET FIRMWARE OPTIONS",
4088 "SET PORT QUEUE PARAMS",
4092 "RESTART NIC FIRMWARE",
4095 "LOOP PORT BYPASS", /* 40h */
4097 "GET RESOURCE COUNT",
4098 "REQUEST NON PARTICIPATING MODE",
4099 "DIAGNOSTIC ECHO TEST",
4100 "DIAGNOSTIC LOOPBACK",
4102 "GET PORT DATABASE ENHANCED",
4103 "INIT FIRMWARE MULTI ID",
4105 "GET VP DATABASE ENTRY",
4111 "GET FCF LIST", /* 50h */
4112 "GET DCBX PARAMETERS",
4123 "FIRMWARE HEARTBEAT",
4124 "GET/SET DATA RATE",
4127 "INIT FIRMWARE", /* 60h */
4128 "GET INIT CONTROL BLOCK",
4130 "GET FC-AL POSITION MAP",
4131 "GET PORT DATABASE",
4140 "GET LINK STATS & PRIVATE DATA CNTS",
4143 "SEND CHANGE REQUEST", /* 70h */
4148 "GET PORT/NODE NAME LIST",
4150 "INITIALIZE IP MAILBOX",
4161 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
4163 const char *cname, *xname, *sname;
4164 char tname[16], mname[16];
4165 unsigned int ibits, obits, box, opcode, t, to;
4167 opcode = mbp->param[0];
4168 if (opcode > MAX_FC_OPCODE) {
4169 mbp->param[0] = MBOX_INVALID_COMMAND;
4170 isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
4173 cname = fc_mbcmd_names[opcode];
4174 ibits = ISP_FC_IBITS(opcode);
4175 obits = ISP_FC_OBITS(opcode);
4176 if (cname == NULL) {
4178 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
4180 isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname);
4183 * Pick up any additional bits that the caller might have set.
4185 ibits |= mbp->ibits;
4186 obits |= mbp->obits;
4189 * Mask any bits that the caller wants us to mask
4191 ibits &= mbp->ibitm;
4192 obits &= mbp->obitm;
4195 if (ibits == 0 && obits == 0) {
4196 mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
4197 isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
4201 for (box = 0; box < ISP_NMBOX(isp); box++) {
4202 if (ibits & (1 << box)) {
4203 isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
4205 ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
4207 isp->isp_mboxtmp[box] = mbp->param[box] = 0;
4210 isp->isp_obits = obits;
4211 isp->isp_mboxbsy = 1;
4214 * Set Host Interrupt condition so that RISC will pick up mailbox regs.
4216 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
4219 * While we haven't finished the command, spin our wheels here.
4221 to = (mbp->timeout == 0) ? MBCMD_DEFAULT_TIMEOUT : mbp->timeout;
4222 for (t = 0; t < to; t += 100) {
4223 if (!isp->isp_mboxbsy)
4226 if (!isp->isp_mboxbsy)
4232 * Did the command time out?
4234 if (isp->isp_mboxbsy) {
4235 isp->isp_mboxbsy = 0;
4236 isp_prt(isp, ISP_LOGWARN, "Mailbox Command (0x%x) Timeout (%uus) (%s:%d)",
4237 opcode, to, mbp->func, mbp->lineno);
4238 mbp->param[0] = MBOX_TIMEOUT;
4243 * Copy back output registers.
4245 for (box = 0; box < ISP_NMBOX(isp); box++) {
4246 if (obits & (1 << box)) {
4247 mbp->param[box] = isp->isp_mboxtmp[box];
4248 isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
4254 if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE)
4257 if ((mbp->param[0] & 0xbfe0) == 0 &&
4258 (mbp->logval & MBLOGMASK(mbp->param[0])) == 0)
4263 switch (mbp->param[0]) {
4264 case MBOX_INVALID_COMMAND:
4265 xname = "INVALID COMMAND";
4267 case MBOX_HOST_INTERFACE_ERROR:
4268 xname = "HOST INTERFACE ERROR";
4270 case MBOX_TEST_FAILED:
4271 xname = "TEST FAILED";
4273 case MBOX_COMMAND_ERROR:
4274 xname = "COMMAND ERROR";
4275 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x",
4279 case MBOX_COMMAND_PARAM_ERROR:
4280 xname = "COMMAND PARAMETER ERROR";
4282 case MBOX_PORT_ID_USED:
4283 xname = "PORT ID ALREADY IN USE";
4285 case MBOX_LOOP_ID_USED:
4286 xname = "LOOP ID ALREADY IN USE";
4288 case MBOX_ALL_IDS_USED:
4289 xname = "ALL LOOP IDS IN USE";
4291 case MBOX_NOT_LOGGED_IN:
4292 xname = "NOT LOGGED IN";
4294 case MBOX_LINK_DOWN_ERROR:
4295 xname = "LINK DOWN ERROR";
4297 case MBOX_LOOPBACK_ERROR:
4298 xname = "LOOPBACK ERROR";
4300 case MBOX_CHECKSUM_ERROR:
4301 xname = "CHECKSUM ERROR";
4303 case MBOX_INVALID_PRODUCT_KEY:
4304 xname = "INVALID PRODUCT KEY";
4306 case MBOX_REGS_BUSY:
4307 xname = "REGISTERS BUSY";
4313 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
4318 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)",
4319 cname, xname, sname);
4324 isp_fw_state(ispsoftc_t *isp, int chan)
4328 MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
4329 isp_mboxcmd(isp, &mbs);
4330 if (mbs.param[0] == MBOX_COMMAND_COMPLETE)
4331 return (mbs.param[1]);
4336 isp_setdfltfcparm(ispsoftc_t *isp, int chan)
4338 fcparam *fcp = FCPARAM(isp, chan);
4341 * Establish some default parameters.
4343 fcp->role = DEFAULT_ROLE(isp, chan);
4344 fcp->isp_retry_delay = ICB_DFLT_RDELAY;
4345 fcp->isp_retry_count = ICB_DFLT_RCOUNT;
4346 fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
4347 fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
4348 fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
4349 fcp->isp_fwoptions = 0;
4350 fcp->isp_xfwoptions = 0;
4351 fcp->isp_zfwoptions = 0;
4352 fcp->isp_lasthdl = NIL_HANDLE;
4353 fcp->isp_login_hdl = NIL_HANDLE;
4355 fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
4356 fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
4357 if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
4358 fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
4359 fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
4360 fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP;
4361 fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO;
4364 * Now try and read NVRAM unless told to not do so.
4365 * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
4367 if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
4370 * Give a couple of tries at reading NVRAM.
4372 for (i = 0; i < 2; i++) {
4373 j = isp_read_nvram(isp, chan);
4379 isp->isp_confopts |= ISP_CFG_NONVRAM;
4383 fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
4384 fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
4385 isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
4386 chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
4387 (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
4388 isp_class3_roles[fcp->role]);
4392 * Re-initialize the ISP and complete all orphaned commands
4393 * with a 'botched' notice. The reset/init routines should
4394 * not disturb an already active list of commands.
4398 isp_reinit(ispsoftc_t *isp, int do_load_defaults)
4402 if (isp->isp_state > ISP_RESETSTATE)
4404 if (isp->isp_state != ISP_RESETSTATE)
4405 isp_reset(isp, do_load_defaults);
4406 if (isp->isp_state != ISP_RESETSTATE) {
4408 isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
4413 if (isp->isp_state > ISP_RESETSTATE &&
4414 isp->isp_state != ISP_RUNSTATE) {
4416 isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
4417 ISP_DISABLE_INTS(isp);
4421 isp_clear_commands(isp);
4422 for (i = 0; i < isp->isp_nchan; i++)
4423 isp_clear_portdb(isp, i);
4431 isp_read_nvram(ispsoftc_t *isp, int bus)
4434 return (isp_read_nvram_2400(isp));
4438 isp_read_nvram_2400(ispsoftc_t *isp)
4441 uint32_t addr, csum, lwrds, *dptr;
4442 uint8_t nvram_data[ISP2400_NVRAM_SIZE];
4444 if (isp->isp_port) {
4445 addr = ISP2400_NVRAM_PORT1_ADDR;
4447 addr = ISP2400_NVRAM_PORT0_ADDR;
4450 dptr = (uint32_t *) nvram_data;
4451 for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4452 isp_rd_2400_nvram(isp, addr++, dptr++);
4454 if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
4455 nvram_data[2] != 'P') {
4456 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)",
4457 nvram_data[0], nvram_data[1], nvram_data[2]);
4461 dptr = (uint32_t *) nvram_data;
4462 for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4464 ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
4468 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
4472 isp_parse_nvram_2400(isp, nvram_data);
4478 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
4481 uint32_t base = 0x7ffe0000;
4485 base = 0x7fe7c000; /* XXX: Observation, may be wrong. */
4486 } else if (IS_25XX(isp)) {
4487 base = 0x7ff00000 | 0x48000;
4489 ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
4490 for (loops = 0; loops < 5000; loops++) {
4492 tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
4493 if ((tmp & (1U << 31)) != 0) {
4497 if (tmp & (1U << 31)) {
4498 *rp = ISP_READ(isp, BIU2400_FLASH_DATA);
4499 ISP_SWIZZLE_NVRAM_LONG(isp, rp);
4506 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
4508 fcparam *fcp = FCPARAM(isp, 0);
4511 isp_prt(isp, ISP_LOGDEBUG0,
4512 "NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d",
4513 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
4514 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
4515 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
4516 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
4517 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
4518 isp_prt(isp, ISP_LOGDEBUG0,
4519 "NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
4520 ISP2400_NVRAM_HARDLOOPID(nvram_data),
4521 ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
4522 ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
4523 ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
4525 wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
4526 fcp->isp_wwpn_nvram = wwn;
4528 wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
4530 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
4534 if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
4535 wwn = fcp->isp_wwpn_nvram;
4536 wwn &= ~((uint64_t) 0xfff << 48);
4538 fcp->isp_wwnn_nvram = wwn;
4540 if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
4541 DEFAULT_FRAMESIZE(isp) =
4542 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
4544 if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
4545 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
4547 fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
4548 fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
4549 fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);