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 #define MBOX_DELAY_COUNT 1000000 / 100
74 static const char notresp[] = "Unknown IOCB in RESPONSE Queue (type 0x%x) @ idx %d (next %d)";
75 static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
76 static const char lipd[] = "Chan %d LIP destroyed %d active commands";
77 static const char sacq[] = "unable to acquire scratch area";
79 static const uint8_t alpa_map[] = {
80 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
81 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
82 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,
83 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
84 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
85 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
86 0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81,
87 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
88 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69,
89 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
90 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c,
91 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
92 0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
93 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
94 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
95 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
99 * Local function prototypes.
101 static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t *, uint16_t);
102 static void isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, uint32_t *);
103 static void isp_clear_portdb(ispsoftc_t *, int);
104 static void isp_mark_portdb(ispsoftc_t *, int);
105 static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int);
106 static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *);
107 static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int);
108 static void isp_dump_chip_portdb(ispsoftc_t *, int);
109 static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
110 static int isp_fclink_test(ispsoftc_t *, int, int);
111 static int isp_pdb_sync(ispsoftc_t *, int);
112 static int isp_scan_loop(ispsoftc_t *, int);
113 static int isp_gid_pt(ispsoftc_t *, int);
114 static int isp_scan_fabric(ispsoftc_t *, int);
115 static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
116 static int isp_register_fc4_type(ispsoftc_t *, int);
117 static int isp_register_fc4_features_24xx(ispsoftc_t *, int);
118 static int isp_register_port_name_24xx(ispsoftc_t *, int);
119 static int isp_register_node_name_24xx(ispsoftc_t *, int);
120 static uint16_t isp_next_handle(ispsoftc_t *, uint16_t *);
121 static int isp_fw_state(ispsoftc_t *, int);
122 static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
124 static void isp_setdfltfcparm(ispsoftc_t *, int);
125 static int isp_read_nvram(ispsoftc_t *, int);
126 static int isp_read_nvram_2400(ispsoftc_t *);
127 static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *);
128 static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
131 isp_change_fw_state(ispsoftc_t *isp, int chan, int state)
133 fcparam *fcp = FCPARAM(isp, chan);
135 if (fcp->isp_fwstate == state)
137 isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG,
138 "Chan %d Firmware state <%s->%s>", chan,
139 isp_fc_fw_statename(fcp->isp_fwstate), isp_fc_fw_statename(state));
140 fcp->isp_fwstate = state;
146 * Hit the chip over the head, download new f/w if available and set it running.
148 * Locking done elsewhere.
152 isp_reset(ispsoftc_t *isp, int do_load_defaults)
157 uint32_t code_org, val;
158 int loops, i, dodnld = 1;
159 const char *btype = "????";
160 static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
162 isp->isp_state = ISP_NILSTATE;
163 ISP_DISABLE_INTS(isp);
166 * Put the board into PAUSE mode (so we can read the SXP registers
167 * or write FPM/FBM registers).
169 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT);
170 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
171 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
173 switch (isp->isp_type) {
191 * Hit the chip over the head with hammer,
192 * and give it a chance to recover.
196 * Stop DMA and wait for it to stop.
198 ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
199 for (val = loops = 0; loops < 30000; loops++) {
201 val = ISP_READ(isp, BIU2400_CSR);
202 if ((val & BIU2400_DMA_ACTIVE) == 0) {
206 if (val & BIU2400_DMA_ACTIVE) {
207 isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
211 * Hold it in SOFT_RESET and STOP state for 100us.
213 ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
215 for (loops = 0; loops < 10000; loops++) {
217 val = ISP_READ(isp, OUTMAILBOX0);
219 for (val = loops = 0; loops < 500000; loops ++) {
220 val = ISP_READ(isp, BIU2400_CSR);
221 if ((val & BIU2400_SOFT_RESET) == 0) {
225 if (val & BIU2400_SOFT_RESET) {
226 isp_prt(isp, ISP_LOGERR, "Failed to come out of reset");
231 * Wait for ISP to be ready to go...
233 loops = MBOX_DELAY_COUNT;
235 if (ISP_READ(isp, OUTMAILBOX0) == 0)
239 ISP_DUMPREGS(isp, "chip reset timed out");
245 * Reset RISC Processor
247 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
248 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE);
249 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET);
252 * Post-RISC Reset stuff.
254 for (val = loops = 0; loops < 5000000; loops++) {
256 val = ISP_READ(isp, OUTMAILBOX0);
262 isp_prt(isp, ISP_LOGERR, "reset didn't clear");
266 isp->isp_reqidx = isp->isp_reqodx = 0;
268 isp->isp_atioodx = 0;
269 ISP_WRITE(isp, BIU2400_REQINP, 0);
270 ISP_WRITE(isp, BIU2400_REQOUTP, 0);
271 ISP_WRITE(isp, BIU2400_RSPINP, 0);
272 ISP_WRITE(isp, BIU2400_RSPOUTP, 0);
274 ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
275 ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
277 ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
278 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
281 * Wait for everything to finish firing up.
283 loops = MBOX_DELAY_COUNT;
284 while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) {
287 isp_prt(isp, ISP_LOGERR, "MBOX_BUSY never cleared on reset");
293 * Up until this point we've done everything by just reading or
294 * setting registers. From this point on we rely on at least *some*
295 * kind of firmware running in the card.
299 * Do some sanity checking by running a NOP command.
300 * If it succeeds, the ROM firmware is now running.
302 MBSINIT(&mbs, MBOX_NO_OP, MBLOGALL, 0);
303 isp_mboxcmd(isp, &mbs);
304 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
305 isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]);
310 * Do some operational tests
313 static const uint16_t patterns[MAX_MAILBOX] = {
314 0x0000, 0xdead, 0xbeef, 0xffff,
315 0xa5a5, 0x5a5a, 0x7f7f, 0x7ff7,
316 0x3421, 0xabcd, 0xdcba, 0xfeef,
317 0xbead, 0xdebe, 0x2222, 0x3333,
318 0x5555, 0x6666, 0x7777, 0xaaaa,
319 0xffff, 0xdddd, 0x9999, 0x1fbc,
320 0x6666, 0x6677, 0x1122, 0x33ff,
321 0x0000, 0x0001, 0x1000, 0x1010,
323 int nmbox = ISP_NMBOX(isp);
324 MBSINIT(&mbs, MBOX_MAILBOX_REG_TEST, MBLOGALL, 0);
325 for (i = 1; i < nmbox; i++) {
326 mbs.param[i] = patterns[i];
328 isp_mboxcmd(isp, &mbs);
329 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
332 for (i = 1; i < nmbox; i++) {
333 if (mbs.param[i] != patterns[i]) {
334 isp_prt(isp, ISP_LOGERR, "Register Test Failed at Register %d: should have 0x%04x but got 0x%04x", i, patterns[i], mbs.param[i]);
341 * Download new Firmware, unless requested not to do so.
342 * This is made slightly trickier in some cases where the
343 * firmware of the ROM revision is newer than the revision
344 * compiled into the driver. So, where we used to compare
345 * versions of our f/w and the ROM f/w, now we just see
346 * whether we have f/w at all and whether a config flag
347 * has disabled our download.
349 if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
354 * Set up DMA for the request and response queues.
355 * We do this now so we can use the request queue
356 * for dma to load firmware from.
358 if (ISP_MBOXDMASETUP(isp) != 0) {
359 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
364 code_org = ISP_CODE_ORG_2400;
365 isp->isp_loaded_fw = 0;
367 const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
371 * Keep loading until we run out of f/w.
373 code_org = ptr[2]; /* 1st load address is our start addr */
375 isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
380 while (wi < ptr[3]) {
384 nw = min(wl, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) / 4);
385 cp = isp->isp_rquest;
386 for (i = 0; i < nw; i++)
387 ISP_IOXPUT_32(isp, ptr[wi + i], &cp[i]);
388 MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), -1);
389 MBSINIT(&mbs, MBOX_LOAD_RISC_RAM, MBLOGALL, 0);
391 mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
392 mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
393 mbs.param[4] = nw >> 16;
395 mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
396 mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
397 mbs.param[8] = la >> 16;
398 isp_prt(isp, ISP_LOGDEBUG0, "LOAD RISC RAM %u words at load address 0x%x", nw, la);
399 isp_mboxcmd(isp, &mbs);
400 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
401 isp_prt(isp, ISP_LOGERR, "F/W download failed");
414 isp->isp_loaded_fw = 1;
415 } else if (IS_26XX(isp)) {
416 isp_prt(isp, ISP_LOGDEBUG1, "loading firmware from flash");
417 MBSINIT(&mbs, MBOX_LOAD_FLASH_FIRMWARE, MBLOGALL, 5000000);
420 isp_mboxcmd(isp, &mbs);
421 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
422 isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
426 isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
430 * If we loaded firmware, verify its checksum
432 if (isp->isp_loaded_fw) {
433 MBSINIT(&mbs, MBOX_VERIFY_CHECKSUM, MBLOGNONE, 0);
434 mbs.param[1] = code_org >> 16;
435 mbs.param[2] = code_org;
436 isp_mboxcmd(isp, &mbs);
437 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
438 isp_prt(isp, ISP_LOGERR, dcrc);
444 * Now start it rolling.
446 * If we didn't actually download f/w,
447 * we still need to (re)start it.
449 MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000);
451 mbs.param[1] = code_org >> 16;
452 mbs.param[2] = code_org;
454 mbs.param[1] = code_org >> 16;
455 mbs.param[2] = code_org;
456 if (isp->isp_loaded_fw)
461 isp_mboxcmd(isp, &mbs);
462 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
466 * Ask the chip for the current firmware version.
467 * This should prove that the new firmware is working.
469 MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 5000000);
470 isp_mboxcmd(isp, &mbs);
471 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
475 isp->isp_fwrev[0] = mbs.param[1];
476 isp->isp_fwrev[1] = mbs.param[2];
477 isp->isp_fwrev[2] = mbs.param[3];
478 isp->isp_fwattr = mbs.param[6];
479 isp->isp_fwattr |= ((uint64_t) mbs.param[15]) << 16;
480 if (isp->isp_fwattr & ISP2400_FW_ATTR_EXTNDED) {
482 (((uint64_t) mbs.param[16]) << 32) |
483 (((uint64_t) mbs.param[17]) << 48);
486 isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
487 btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
489 fwt = isp->isp_fwattr;
490 buf = FCPARAM(isp, 0)->isp_scanscratch;
491 ISP_SNPRINTF(buf, ISP_FC_SCRLEN, "Attributes:");
492 if (fwt & ISP2400_FW_ATTR_CLASS2) {
493 fwt ^=ISP2400_FW_ATTR_CLASS2;
494 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s Class2", buf);
496 if (fwt & ISP2400_FW_ATTR_IP) {
497 fwt ^=ISP2400_FW_ATTR_IP;
498 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s IP", buf);
500 if (fwt & ISP2400_FW_ATTR_MULTIID) {
501 fwt ^=ISP2400_FW_ATTR_MULTIID;
502 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MultiID", buf);
504 if (fwt & ISP2400_FW_ATTR_SB2) {
505 fwt ^=ISP2400_FW_ATTR_SB2;
506 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SB2", buf);
508 if (fwt & ISP2400_FW_ATTR_T10CRC) {
509 fwt ^=ISP2400_FW_ATTR_T10CRC;
510 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s T10CRC", buf);
512 if (fwt & ISP2400_FW_ATTR_VI) {
513 fwt ^=ISP2400_FW_ATTR_VI;
514 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VI", buf);
516 if (fwt & ISP2400_FW_ATTR_MQ) {
517 fwt ^=ISP2400_FW_ATTR_MQ;
518 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MQ", buf);
520 if (fwt & ISP2400_FW_ATTR_MSIX) {
521 fwt ^=ISP2400_FW_ATTR_MSIX;
522 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MSIX", buf);
524 if (fwt & ISP2400_FW_ATTR_FCOE) {
525 fwt ^=ISP2400_FW_ATTR_FCOE;
526 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s FCOE", buf);
528 if (fwt & ISP2400_FW_ATTR_VP0) {
529 fwt ^= ISP2400_FW_ATTR_VP0;
530 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VP0_Decoupling", buf);
532 if (fwt & ISP2400_FW_ATTR_EXPFW) {
533 fwt ^= ISP2400_FW_ATTR_EXPFW;
534 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (Experimental)", buf);
536 if (fwt & ISP2400_FW_ATTR_HOTFW) {
537 fwt ^= ISP2400_FW_ATTR_HOTFW;
538 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s HotFW", buf);
540 fwt &= ~ISP2400_FW_ATTR_EXTNDED;
541 if (fwt & ISP2400_FW_ATTR_EXTVP) {
542 fwt ^= ISP2400_FW_ATTR_EXTVP;
543 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ExtVP", buf);
545 if (fwt & ISP2400_FW_ATTR_VN2VN) {
546 fwt ^= ISP2400_FW_ATTR_VN2VN;
547 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VN2VN", buf);
549 if (fwt & ISP2400_FW_ATTR_EXMOFF) {
550 fwt ^= ISP2400_FW_ATTR_EXMOFF;
551 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s EXMOFF", buf);
553 if (fwt & ISP2400_FW_ATTR_NPMOFF) {
554 fwt ^= ISP2400_FW_ATTR_NPMOFF;
555 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s NPMOFF", buf);
557 if (fwt & ISP2400_FW_ATTR_DIFCHOP) {
558 fwt ^= ISP2400_FW_ATTR_DIFCHOP;
559 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s DIFCHOP", buf);
561 if (fwt & ISP2400_FW_ATTR_SRIOV) {
562 fwt ^= ISP2400_FW_ATTR_SRIOV;
563 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SRIOV", buf);
565 if (fwt & ISP2400_FW_ATTR_ASICTMP) {
566 fwt ^= ISP2400_FW_ATTR_ASICTMP;
567 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ASICTMP", buf);
569 if (fwt & ISP2400_FW_ATTR_ATIOMQ) {
570 fwt ^= ISP2400_FW_ATTR_ATIOMQ;
571 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ATIOMQ", buf);
574 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (unknown 0x%08x%08x)", buf,
575 (uint32_t) (fwt >> 32), (uint32_t) fwt);
577 isp_prt(isp, ISP_LOGCONFIG, "%s", buf);
580 * For the maximum number of commands take free exchange control block
581 * buffer count reported by firmware, limiting it to the maximum of our
582 * hardcoded handle format (16K now) minus some management reserve.
584 MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
585 isp_mboxcmd(isp, &mbs);
586 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
588 isp->isp_maxcmds = MIN(mbs.param[3], ISP_HANDLE_MAX - ISP_HANDLE_RESERVE);
589 isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
592 * If we don't have Multi-ID f/w loaded, we need to restrict channels to one.
593 * Only make this check for non-SCSI cards (I'm not sure firmware attributes
596 if (isp->isp_nchan > 1) {
597 if (!ISP_CAP_MULTI_ID(isp)) {
598 isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, "
599 "only can enable 1 of %d channels", isp->isp_nchan);
601 } else if (!ISP_CAP_VP0(isp)) {
602 isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID "
603 "feature properly without VP0_Decoupling");
609 * Final DMA setup after we got isp_maxcmds.
611 if (ISP_MBOXDMASETUP(isp) != 0) {
612 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
619 if (ISP_IRQSETUP(isp) != 0) {
620 isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ");
623 ISP_ENABLE_INTS(isp);
625 for (i = 0; i < isp->isp_nchan; i++)
626 isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
628 isp->isp_state = ISP_RESETSTATE;
631 * We get some default values established. As a side
632 * effect, NVRAM is read here (unless overriden by
633 * a configuration flag).
635 if (do_load_defaults) {
636 for (i = 0; i < isp->isp_nchan; i++)
637 isp_setdfltfcparm(isp, i);
642 * Clean firmware shutdown.
645 isp_stop(ispsoftc_t *isp)
649 isp->isp_state = ISP_NILSTATE;
650 MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000);
659 isp_mboxcmd(isp, &mbs);
660 return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]);
667 isp_shutdown(ispsoftc_t *isp)
670 if (isp->isp_state >= ISP_RESETSTATE)
672 ISP_DISABLE_INTS(isp);
673 ISP_WRITE(isp, BIU2400_ICR, 0);
674 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
678 * Initialize Parameters of Hardware to a known state.
680 * Locks are held before coming here.
683 isp_init(ispsoftc_t *isp)
686 isp_icb_2400_t local, *icbp = &local;
692 * Check to see whether all channels have *some* kind of role
694 for (chan = 0; chan < isp->isp_nchan; chan++) {
695 fcp = FCPARAM(isp, chan);
696 if (fcp->role != ISP_ROLE_NONE) {
700 if (chan == isp->isp_nchan) {
701 isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan);
705 isp->isp_state = ISP_INITSTATE;
708 * Start with channel 0.
710 fcp = FCPARAM(isp, 0);
713 * Turn on LIP F8 async event (1)
715 MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
717 isp_mboxcmd(isp, &mbs);
718 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
722 ISP_MEMZERO(icbp, sizeof (*icbp));
723 icbp->icb_fwoptions1 = fcp->isp_fwoptions;
724 icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
725 icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
726 if (isp->isp_nchan > 1 && ISP_CAP_VP0(isp)) {
727 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
728 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
730 if (fcp->role & ISP_ROLE_TARGET)
731 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
733 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
734 if (fcp->role & ISP_ROLE_INITIATOR)
735 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
737 icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
740 icbp->icb_version = ICB_VERSION1;
741 icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
742 if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
743 isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
744 icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
748 icbp->icb_execthrottle = 0xffff;
750 #ifdef ISP_TARGET_MODE
752 * Set target exchange count. Take half if we are supporting both roles.
754 if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) {
755 if ((icbp->icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE) == 0)
756 icbp->icb_xchgcnt = MIN(isp->isp_maxcmds / 2, ATPDPSIZE);
758 icbp->icb_xchgcnt = isp->isp_maxcmds;
762 ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
763 icbp->icb_hardaddr = fcp->isp_loopid;
764 if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
765 icbp->icb_hardaddr = 0;
770 icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
772 if (isp->isp_confopts & ISP_CFG_NOFCTAPE) {
773 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
775 if (isp->isp_confopts & ISP_CFG_FCTAPE) {
776 icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE;
779 for (chan = 0; chan < isp->isp_nchan; chan++) {
780 if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE)
781 FCPARAM(isp, chan)->fctape_enabled = 1;
783 FCPARAM(isp, chan)->fctape_enabled = 0;
786 switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
787 case ISP_CFG_LPORT_ONLY:
788 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
789 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY;
791 case ISP_CFG_NPORT_ONLY:
792 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
793 icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
796 /* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */
798 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
799 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
802 /* Let NVRAM settings define it if they are sane */
803 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK) {
804 case ICB2400_OPT2_LOOP_ONLY:
805 case ICB2400_OPT2_PTP_ONLY:
806 case ICB2400_OPT2_LOOP_2_PTP:
809 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
810 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
815 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
816 case ICB2400_OPT2_ZIO:
817 case ICB2400_OPT2_ZIO1:
818 icbp->icb_idelaytimer = 0;
823 isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
824 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
829 /* Use handshake to reduce global lock congestion. */
830 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR;
831 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA;
834 if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) {
835 icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24;
837 if (isp->isp_confopts & ISP_CFG_1GB) {
838 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
839 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB;
840 } else if (isp->isp_confopts & ISP_CFG_2GB) {
841 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
842 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB;
843 } else if (isp->isp_confopts & ISP_CFG_4GB) {
844 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
845 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB;
846 } else if (isp->isp_confopts & ISP_CFG_8GB) {
847 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
848 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB;
849 } else if (isp->isp_confopts & ISP_CFG_16GB) {
850 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
851 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB;
852 } else if (isp->isp_confopts & ISP_CFG_32GB) {
853 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
854 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB;
856 switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) {
857 case ICB2400_OPT3_RATE_4GB:
858 case ICB2400_OPT3_RATE_8GB:
859 case ICB2400_OPT3_RATE_16GB:
860 case ICB2400_OPT3_RATE_32GB:
861 case ICB2400_OPT3_RATE_AUTO:
863 case ICB2400_OPT3_RATE_2GB:
864 if (isp->isp_type <= ISP_HA_FC_2500)
867 case ICB2400_OPT3_RATE_1GB:
868 if (isp->isp_type <= ISP_HA_FC_2400)
872 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
873 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
877 if (ownloopid == 0) {
878 icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
880 icbp->icb_logintime = ICB_LOGIN_TOV;
882 if (fcp->isp_wwnn && fcp->isp_wwpn) {
883 icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
884 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
885 MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
886 isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node 0x%08x%08x Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwnn >> 32)), ((uint32_t) (fcp->isp_wwnn)),
887 ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
888 } else if (fcp->isp_wwpn) {
889 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
890 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
891 isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node to be same as Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
893 isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
896 icbp->icb_rspnsin = isp->isp_resodx;
897 icbp->icb_rqstout = isp->isp_reqidx;
898 icbp->icb_retry_count = fcp->isp_retry_count;
900 icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
901 if (icbp->icb_rqstqlen < 8) {
902 isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen);
905 icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
906 if (icbp->icb_rsltqlen < 8) {
907 isp_prt(isp, ISP_LOGERR, "bad result queue length %d",
911 icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
912 icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
913 icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
914 icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
916 icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
917 icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
918 icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
919 icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
921 #ifdef ISP_TARGET_MODE
922 /* unconditionally set up the ATIO queue if we support target mode */
923 icbp->icb_atio_in = isp->isp_atioodx;
924 icbp->icb_atioqlen = ATIO_QUEUE_LEN(isp);
925 if (icbp->icb_atioqlen < 8) {
926 isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen);
929 icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
930 icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
931 icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
932 icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
933 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
934 DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
937 if (ISP_CAP_MSIX(isp) && isp->isp_nirq >= 2) {
938 icbp->icb_msixresp = 1;
939 if (IS_26XX(isp) && isp->isp_nirq >= 3)
940 icbp->icb_msixatio = 2;
943 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3);
945 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x", DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma),
946 DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
947 DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
949 if (FC_SCRATCH_ACQUIRE(isp, 0)) {
950 isp_prt(isp, ISP_LOGERR, sacq);
953 ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
954 isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
955 if (isp->isp_dblev & ISP_LOGDEBUG1) {
956 isp_print_bytes(isp, "isp_init",
957 sizeof (*icbp), fcp->isp_scratch);
961 * Now fill in information about any additional channels
963 if (isp->isp_nchan > 1) {
964 isp_icb_2400_vpinfo_t vpinfo, *vdst;
965 vp_port_info_t pi, *pdst;
969 vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA;
970 if (ISP_CAP_VP0(isp)) {
971 vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE;
972 vpinfo.vp_count = isp->isp_nchan;
975 vpinfo.vp_count = isp->isp_nchan - 1;
978 off = fcp->isp_scratch;
979 off += ICB2400_VPINFO_OFF;
980 vdst = (isp_icb_2400_vpinfo_t *) off;
981 isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst);
982 amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t);
983 for (; chan < isp->isp_nchan; chan++) {
986 ISP_MEMZERO(&pi, sizeof (pi));
987 fcp2 = FCPARAM(isp, chan);
988 if (fcp2->role != ISP_ROLE_NONE) {
989 pi.vp_port_options = ICB2400_VPOPT_ENABLED |
990 ICB2400_VPOPT_ENA_SNSLOGIN;
991 if (fcp2->role & ISP_ROLE_INITIATOR)
992 pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
993 if ((fcp2->role & ISP_ROLE_TARGET) == 0)
994 pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE;
995 if (fcp2->isp_loopid < LOCAL_LOOP_LIM) {
996 pi.vp_port_loopid = fcp2->isp_loopid;
997 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
998 pi.vp_port_options |= ICB2400_VPOPT_HARD_ADDRESS;
1002 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn);
1003 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn);
1004 off = fcp->isp_scratch;
1005 if (ISP_CAP_VP0(isp))
1006 off += ICB2400_VPINFO_PORT_OFF(chan);
1008 off += ICB2400_VPINFO_PORT_OFF(chan - 1);
1009 pdst = (vp_port_info_t *) off;
1010 isp_put_vp_port_info(isp, &pi, pdst);
1011 amt += ICB2400_VPOPT_WRITE_SIZE;
1013 if (isp->isp_dblev & ISP_LOGDEBUG1) {
1014 isp_print_bytes(isp, "isp_init",
1015 amt - ICB2400_VPINFO_OFF,
1016 (char *)fcp->isp_scratch + ICB2400_VPINFO_OFF);
1023 MBSINIT(&mbs, 0, MBLOGALL, 30000000);
1024 if (isp->isp_nchan > 1) {
1025 mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
1027 mbs.param[0] = MBOX_INIT_FIRMWARE;
1030 mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1031 mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1032 mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1033 mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1034 isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x", DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma), DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma));
1035 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp), 0);
1036 isp_mboxcmd(isp, &mbs);
1037 FC_SCRATCH_RELEASE(isp, 0);
1039 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1044 * Whatever happens, we're now committed to being here.
1046 isp->isp_state = ISP_RUNSTATE;
1050 isp_fc_enable_vp(ispsoftc_t *isp, int chan)
1052 fcparam *fcp = FCPARAM(isp, chan);
1055 uint8_t resp[QENTRY_LEN];
1057 /* Build a VP MODIFY command in memory */
1058 ISP_MEMZERO(&vp, sizeof(vp));
1059 vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
1060 vp.vp_mod_hdr.rqs_entry_count = 1;
1062 vp.vp_mod_idx0 = chan;
1063 vp.vp_mod_cmd = VP_MODIFY_ENA;
1064 vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
1065 ICB2400_VPOPT_ENA_SNSLOGIN;
1066 if (fcp->role & ISP_ROLE_INITIATOR)
1067 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
1068 if ((fcp->role & ISP_ROLE_TARGET) == 0)
1069 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
1070 if (fcp->isp_loopid < LOCAL_LOOP_LIM) {
1071 vp.vp_mod_ports[0].loopid = fcp->isp_loopid;
1072 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
1073 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS;
1075 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn);
1076 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn);
1078 /* Prepare space for response in memory */
1079 memset(resp, 0xff, sizeof(resp));
1080 vp.vp_mod_hdl = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1081 if (vp.vp_mod_hdl == 0) {
1082 isp_prt(isp, ISP_LOGERR,
1083 "%s: VP_MODIFY of Chan %d out of handles", __func__, chan);
1087 /* Send request and wait for response. */
1088 reqp = isp_getrqentry(isp);
1090 isp_prt(isp, ISP_LOGERR,
1091 "%s: VP_MODIFY of Chan %d out of rqent", __func__, chan);
1092 isp_destroy_handle(isp, vp.vp_mod_hdl);
1095 isp_put_vp_modify(isp, &vp, (vp_modify_t *)reqp);
1096 if (isp->isp_dblev & ISP_LOGDEBUG1)
1097 isp_print_bytes(isp, "IOCB VP_MODIFY", QENTRY_LEN, reqp);
1098 ISP_SYNC_REQUEST(isp);
1099 if (msleep(resp, &isp->isp_lock, 0, "VP_MODIFY", 5*hz) == EWOULDBLOCK) {
1100 isp_prt(isp, ISP_LOGERR,
1101 "%s: VP_MODIFY of Chan %d timed out", __func__, chan);
1102 isp_destroy_handle(isp, vp.vp_mod_hdl);
1105 if (isp->isp_dblev & ISP_LOGDEBUG1)
1106 isp_print_bytes(isp, "IOCB VP_MODIFY response", QENTRY_LEN, resp);
1107 isp_get_vp_modify(isp, (vp_modify_t *)resp, &vp);
1109 if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) {
1110 isp_prt(isp, ISP_LOGERR,
1111 "%s: VP_MODIFY of Chan %d failed with flags %x status %d",
1112 __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status);
1119 isp_fc_disable_vp(ispsoftc_t *isp, int chan)
1123 uint8_t resp[QENTRY_LEN];
1125 /* Build a VP CTRL command in memory */
1126 ISP_MEMZERO(&vp, sizeof(vp));
1127 vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
1128 vp.vp_ctrl_hdr.rqs_entry_count = 1;
1129 if (ISP_CAP_VP0(isp)) {
1130 vp.vp_ctrl_status = 1;
1132 vp.vp_ctrl_status = 0;
1133 chan--; /* VP0 can not be controlled in this case. */
1135 vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
1136 vp.vp_ctrl_vp_count = 1;
1137 vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
1139 /* Prepare space for response in memory */
1140 memset(resp, 0xff, sizeof(resp));
1141 vp.vp_ctrl_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1142 if (vp.vp_ctrl_handle == 0) {
1143 isp_prt(isp, ISP_LOGERR,
1144 "%s: VP_CTRL of Chan %d out of handles", __func__, chan);
1148 /* Send request and wait for response. */
1149 reqp = isp_getrqentry(isp);
1151 isp_prt(isp, ISP_LOGERR,
1152 "%s: VP_CTRL of Chan %d out of rqent", __func__, chan);
1153 isp_destroy_handle(isp, vp.vp_ctrl_handle);
1156 isp_put_vp_ctrl_info(isp, &vp, (vp_ctrl_info_t *)reqp);
1157 if (isp->isp_dblev & ISP_LOGDEBUG1)
1158 isp_print_bytes(isp, "IOCB VP_CTRL", QENTRY_LEN, reqp);
1159 ISP_SYNC_REQUEST(isp);
1160 if (msleep(resp, &isp->isp_lock, 0, "VP_CTRL", 5*hz) == EWOULDBLOCK) {
1161 isp_prt(isp, ISP_LOGERR,
1162 "%s: VP_CTRL of Chan %d timed out", __func__, chan);
1163 isp_destroy_handle(isp, vp.vp_ctrl_handle);
1166 if (isp->isp_dblev & ISP_LOGDEBUG1)
1167 isp_print_bytes(isp, "IOCB VP_CTRL response", QENTRY_LEN, resp);
1168 isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)resp, &vp);
1170 if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) {
1171 isp_prt(isp, ISP_LOGERR,
1172 "%s: VP_CTRL of Chan %d failed with flags %x status %d %d",
1173 __func__, chan, vp.vp_ctrl_hdr.rqs_flags,
1174 vp.vp_ctrl_status, vp.vp_ctrl_index_fail);
1181 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
1183 fcparam *fcp = FCPARAM(isp, chan);
1184 int i, was, res = 0;
1186 if (chan >= isp->isp_nchan) {
1187 isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan);
1190 if (fcp->role == new_role)
1192 for (was = 0, i = 0; i < isp->isp_nchan; i++) {
1193 if (FCPARAM(isp, i)->role != ISP_ROLE_NONE)
1196 if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) {
1197 fcp->role = new_role;
1198 return (isp_reinit(isp, 0));
1200 if (fcp->role != ISP_ROLE_NONE) {
1201 res = isp_fc_disable_vp(isp, chan);
1202 isp_clear_portdb(isp, chan);
1204 fcp->role = new_role;
1205 if (fcp->role != ISP_ROLE_NONE)
1206 res = isp_fc_enable_vp(isp, chan);
1211 isp_clear_portdb(ispsoftc_t *isp, int chan)
1213 fcparam *fcp = FCPARAM(isp, chan);
1217 for (i = 0; i < MAX_FC_TARG; i++) {
1218 lp = &fcp->portdb[i];
1219 switch (lp->state) {
1220 case FC_PORTDB_STATE_DEAD:
1221 case FC_PORTDB_STATE_CHANGED:
1222 case FC_PORTDB_STATE_VALID:
1223 lp->state = FC_PORTDB_STATE_NIL;
1224 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1226 case FC_PORTDB_STATE_NIL:
1227 case FC_PORTDB_STATE_NEW:
1228 lp->state = FC_PORTDB_STATE_NIL;
1230 case FC_PORTDB_STATE_ZOMBIE:
1233 panic("Don't know how to clear state %d\n", lp->state);
1239 isp_mark_portdb(ispsoftc_t *isp, int chan)
1241 fcparam *fcp = FCPARAM(isp, chan);
1245 for (i = 0; i < MAX_FC_TARG; i++) {
1246 lp = &fcp->portdb[i];
1247 if (lp->state == FC_PORTDB_STATE_NIL)
1249 if (lp->portid >= DOMAIN_CONTROLLER_BASE &&
1250 lp->portid <= DOMAIN_CONTROLLER_END)
1252 fcp->portdb[i].probational = 1;
1257 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
1258 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
1261 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags)
1265 uint8_t resp[QENTRY_LEN];
1266 uint32_t sst, parm1;
1271 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x",
1272 chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ?
1273 "Login":"Logout", portid, handle);
1275 ISP_MEMZERO(&pl, sizeof(pl));
1276 pl.plogx_header.rqs_entry_count = 1;
1277 pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
1278 pl.plogx_nphdl = handle;
1279 pl.plogx_vphdl = chan;
1280 pl.plogx_portlo = portid;
1281 pl.plogx_rspsz_porthi = (portid >> 16) & 0xff;
1282 pl.plogx_flags = flags;
1284 /* Prepare space for response in memory */
1285 memset(resp, 0xff, sizeof(resp));
1286 pl.plogx_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1287 if (pl.plogx_handle == 0) {
1288 isp_prt(isp, ISP_LOGERR,
1289 "%s: PLOGX of Chan %d out of handles", __func__, chan);
1293 /* Send request and wait for response. */
1294 reqp = isp_getrqentry(isp);
1296 isp_prt(isp, ISP_LOGERR,
1297 "%s: PLOGX of Chan %d out of rqent", __func__, chan);
1298 isp_destroy_handle(isp, pl.plogx_handle);
1301 isp_put_plogx(isp, &pl, (isp_plogx_t *)reqp);
1302 if (isp->isp_dblev & ISP_LOGDEBUG1)
1303 isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, reqp);
1304 FCPARAM(isp, chan)->isp_login_hdl = handle;
1305 ISP_SYNC_REQUEST(isp);
1306 if (msleep(resp, &isp->isp_lock, 0, "PLOGX", 3 * ICB_LOGIN_TOV * hz)
1308 isp_prt(isp, ISP_LOGERR,
1309 "%s: PLOGX of Chan %d timed out", __func__, chan);
1310 isp_destroy_handle(isp, pl.plogx_handle);
1313 FCPARAM(isp, chan)->isp_login_hdl = NIL_HANDLE;
1314 if (isp->isp_dblev & ISP_LOGDEBUG1)
1315 isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, resp);
1316 isp_get_plogx(isp, (isp_plogx_t *)resp, &pl);
1318 if (pl.plogx_status == PLOGX_STATUS_OK) {
1320 } else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) {
1321 isp_prt(isp, ISP_LOGWARN,
1322 "status 0x%x on port login IOCB channel %d",
1323 pl.plogx_status, chan);
1327 sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16);
1328 parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16);
1335 case PLOGX_IOCBERR_NOLINK:
1338 case PLOGX_IOCBERR_NOIOCB:
1339 msg = "no IOCB buffer";
1341 case PLOGX_IOCBERR_NOXGHG:
1342 msg = "no Exchange Control Block";
1344 case PLOGX_IOCBERR_FAILED:
1345 ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff);
1348 case PLOGX_IOCBERR_NOFABRIC:
1351 case PLOGX_IOCBERR_NOTREADY:
1352 msg = "firmware not ready";
1354 case PLOGX_IOCBERR_NOLOGIN:
1355 ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1);
1357 rval = MBOX_NOT_LOGGED_IN;
1359 case PLOGX_IOCBERR_REJECT:
1360 ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
1363 case PLOGX_IOCBERR_NOPCB:
1364 msg = "no PCB allocated";
1366 case PLOGX_IOCBERR_EINVAL:
1367 ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1);
1370 case PLOGX_IOCBERR_PORTUSED:
1371 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1372 ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1);
1374 rval = MBOX_PORT_ID_USED | (parm1 << 16);
1376 case PLOGX_IOCBERR_HNDLUSED:
1377 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1378 ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1);
1380 rval = MBOX_LOOP_ID_USED;
1382 case PLOGX_IOCBERR_NOHANDLE:
1383 msg = "no handle allocated";
1385 case PLOGX_IOCBERR_NOFLOGI:
1386 msg = "no FLOGI_ACC";
1389 ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags);
1394 isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
1395 chan, portid, handle, msg);
1401 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb)
1405 isp_pdb_24xx_t bill;
1408 MBSINIT(&mbs, MBOX_GET_PORT_DB,
1409 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000);
1410 mbs.ibits = (1 << 9)|(1 << 10);
1412 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
1413 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
1414 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
1415 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
1416 mbs.param[9] = chan;
1417 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, sizeof(un), chan);
1419 isp_mboxcmd(isp, &mbs);
1420 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
1421 return (mbs.param[0] | (mbs.param[1] << 16));
1423 MEMORYBARRIER(isp, SYNC_IFORCPU, 0, sizeof(un), chan);
1424 isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill);
1425 pdb->handle = un.bill.pdb_handle;
1426 pdb->prli_word0 = un.bill.pdb_prli_svc0;
1427 pdb->prli_word3 = un.bill.pdb_prli_svc3;
1428 pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
1429 ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
1430 ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
1431 isp_prt(isp, ISP_LOGDEBUG0,
1432 "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x",
1433 chan, id, pdb->portid, un.bill.pdb_flags,
1434 un.bill.pdb_curstate, un.bill.pdb_laststate);
1436 if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
1437 mbs.param[0] = MBOX_NOT_LOGGED_IN;
1438 return (mbs.param[0]);
1444 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop)
1446 fcparam *fcp = FCPARAM(isp, chan);
1448 isp_pnhle_24xx_t el4, *elp4;
1452 MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL, 250000);
1453 mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1454 mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1455 mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1456 mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1457 mbs.param[8] = ISP_FC_SCRLEN;
1458 mbs.param[9] = chan;
1459 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1460 isp_prt(isp, ISP_LOGERR, sacq);
1463 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan);
1464 isp_mboxcmd(isp, &mbs);
1465 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1466 FC_SCRATCH_RELEASE(isp, chan);
1467 return (mbs.param[0] | (mbs.param[1] << 16));
1469 MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan);
1470 elp4 = fcp->isp_scratch;
1471 for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) {
1472 isp_get_pnhle_24xx(isp, &elp4[i], &el4);
1473 p = el4.pnhle_port_id_lo | (el4.pnhle_port_id_hi << 16);
1474 if (loop && (p >> 8) != (fcp->isp_portid >> 8))
1476 handles[j++] = el4.pnhle_handle;
1479 FC_SCRATCH_RELEASE(isp, chan);
1484 isp_dump_chip_portdb(ispsoftc_t *isp, int chan)
1489 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan);
1490 for (nphdl = 0; nphdl != NPH_MAX_2K; nphdl++) {
1491 if (isp_getpdb(isp, chan, nphdl, &pdb)) {
1494 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x "
1495 "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
1496 chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1],
1497 pdb.portname[2], pdb.portname[3], pdb.portname[4],
1498 pdb.portname[5], pdb.portname[6], pdb.portname[7]);
1503 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename)
1505 uint64_t wwn = INI_NONE;
1508 MBSINIT(&mbs, MBOX_GET_PORT_NAME,
1509 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
1510 mbs.param[1] = nphdl;
1513 mbs.param[9] = chan;
1514 isp_mboxcmd(isp, &mbs);
1515 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1518 wwn = (((uint64_t)(mbs.param[2] >> 8)) << 56) |
1519 (((uint64_t)(mbs.param[2] & 0xff))<< 48) |
1520 (((uint64_t)(mbs.param[3] >> 8)) << 40) |
1521 (((uint64_t)(mbs.param[3] & 0xff))<< 32) |
1522 (((uint64_t)(mbs.param[6] >> 8)) << 24) |
1523 (((uint64_t)(mbs.param[6] & 0xff))<< 16) |
1524 (((uint64_t)(mbs.param[7] >> 8)) << 8) |
1525 (((uint64_t)(mbs.param[7] & 0xff)));
1530 * Make sure we have good FC link.
1534 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
1540 NANOTIME_T hra, hrb;
1542 fcp = FCPARAM(isp, chan);
1544 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1546 if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
1549 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
1552 * Wait up to N microseconds for F/W to go to a ready state.
1556 isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
1557 if (fcp->isp_fwstate == FW_READY) {
1560 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1563 if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
1565 ISP_SLEEP(isp, 1000);
1567 if (fcp->isp_fwstate != FW_READY) {
1568 isp_prt(isp, ISP_LOG_SANCFG,
1569 "Chan %d Firmware is not ready (%s)",
1570 chan, isp_fc_fw_statename(fcp->isp_fwstate));
1575 * Get our Loop ID and Port ID.
1577 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
1578 mbs.param[9] = chan;
1579 isp_mboxcmd(isp, &mbs);
1580 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1584 topo = (int) mbs.param[6];
1585 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
1586 topo = TOPO_PTP_STUB;
1587 fcp->isp_topo = topo;
1588 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
1590 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
1591 fcp->isp_loopid = mbs.param[1] & 0xff;
1592 } else if (fcp->isp_topo != TOPO_F_PORT) {
1593 uint8_t alpa = fcp->isp_portid;
1595 for (i = 0; alpa_map[i]; i++) {
1596 if (alpa_map[i] == alpa)
1600 fcp->isp_loopid = i;
1604 fcp->isp_loopstate = LOOP_HAVE_ADDR;
1606 fcp->isp_loopstate = LOOP_TESTING_LINK;
1608 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
1609 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
1610 if (r != 0 || pdb.portid == 0) {
1611 isp_prt(isp, ISP_LOGWARN,
1612 "fabric topology, but cannot get info about fabric controller (0x%x)", r);
1613 fcp->isp_topo = TOPO_PTP_STUB;
1617 fcp->isp_fabric_params = mbs.param[7];
1618 fcp->isp_sns_hdl = NPH_SNS_ID;
1619 r = isp_register_fc4_type(isp, chan);
1620 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1624 r = isp_register_fc4_features_24xx(isp, chan);
1625 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1629 r = isp_register_port_name_24xx(isp, chan);
1630 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1634 isp_register_node_name_24xx(isp, chan);
1635 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1640 /* Get link speed. */
1641 fcp->isp_gbspeed = 1;
1642 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
1643 mbs.param[1] = MBGSD_GET_RATE;
1644 /* mbs.param[2] undefined if we're just getting rate */
1645 isp_mboxcmd(isp, &mbs);
1646 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
1647 if (mbs.param[1] == MBGSD_10GB)
1648 fcp->isp_gbspeed = 10;
1649 else if (mbs.param[1] == MBGSD_32GB)
1650 fcp->isp_gbspeed = 32;
1651 else if (mbs.param[1] == MBGSD_16GB)
1652 fcp->isp_gbspeed = 16;
1653 else if (mbs.param[1] == MBGSD_8GB)
1654 fcp->isp_gbspeed = 8;
1655 else if (mbs.param[1] == MBGSD_4GB)
1656 fcp->isp_gbspeed = 4;
1657 else if (mbs.param[1] == MBGSD_2GB)
1658 fcp->isp_gbspeed = 2;
1659 else if (mbs.param[1] == MBGSD_1GB)
1660 fcp->isp_gbspeed = 1;
1663 if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
1665 isp_prt(isp, ISP_LOG_SANCFG,
1666 "Chan %d FC link test aborted", chan);
1669 fcp->isp_loopstate = LOOP_LTEST_DONE;
1670 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1671 "Chan %d WWPN %016jx WWNN %016jx",
1672 chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn);
1673 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1674 "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x",
1675 chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid,
1677 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
1682 * Complete the synchronization of our Port Database.
1684 * At this point, we've scanned the local loop (if any) and the fabric
1685 * and performed fabric logins on all new devices.
1687 * Our task here is to go through our port database removing any entities
1688 * that are still marked probational (issuing PLOGO for ones which we had
1689 * PLOGI'd into) or are dead, and notifying upper layers about new/changed
1693 isp_pdb_sync(ispsoftc_t *isp, int chan)
1695 fcparam *fcp = FCPARAM(isp, chan);
1699 if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
1701 if (fcp->isp_loopstate >= LOOP_READY)
1704 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
1706 fcp->isp_loopstate = LOOP_SYNCING_PDB;
1708 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
1709 lp = &fcp->portdb[dbidx];
1711 if (lp->state == FC_PORTDB_STATE_NIL)
1713 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE)
1714 lp->state = FC_PORTDB_STATE_DEAD;
1715 switch (lp->state) {
1716 case FC_PORTDB_STATE_DEAD:
1717 lp->state = FC_PORTDB_STATE_NIL;
1718 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1719 if ((lp->portid & 0xffff00) != 0) {
1720 (void) isp_plogx(isp, chan, lp->handle,
1722 PLOGX_FLG_CMD_LOGO |
1723 PLOGX_FLG_IMPLICIT |
1724 PLOGX_FLG_FREE_NPHDL);
1727 * Note that we might come out of this with our state
1728 * set to FC_PORTDB_STATE_ZOMBIE.
1731 case FC_PORTDB_STATE_NEW:
1732 lp->state = FC_PORTDB_STATE_VALID;
1733 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
1735 case FC_PORTDB_STATE_CHANGED:
1736 lp->state = FC_PORTDB_STATE_VALID;
1737 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
1738 lp->portid = lp->new_portid;
1739 lp->prli_word0 = lp->new_prli_word0;
1740 lp->prli_word3 = lp->new_prli_word3;
1742 case FC_PORTDB_STATE_VALID:
1743 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
1745 case FC_PORTDB_STATE_ZOMBIE:
1748 isp_prt(isp, ISP_LOGWARN,
1749 "isp_pdb_sync: state %d for idx %d",
1751 isp_dump_portdb(isp, chan);
1755 if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
1756 isp_prt(isp, ISP_LOG_SANCFG,
1757 "Chan %d FC PDB sync aborted", chan);
1761 fcp->isp_loopstate = LOOP_READY;
1762 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
1767 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
1770 uint64_t wwnn, wwpn;
1772 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
1773 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
1775 /* Search port database for the same WWPN. */
1776 if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) {
1777 if (!lp->probational) {
1778 isp_prt(isp, ISP_LOGERR,
1779 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
1780 chan, lp->portid, lp->handle,
1781 FC_PORTDB_TGT(isp, chan, lp), lp->state);
1782 isp_dump_portdb(isp, chan);
1785 lp->probational = 0;
1786 lp->node_wwn = wwnn;
1788 /* Old device, nothing new. */
1789 if (lp->portid == pdb->portid &&
1790 lp->handle == pdb->handle &&
1791 lp->prli_word3 == pdb->prli_word3 &&
1792 ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) ==
1793 (lp->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR))) {
1794 if (lp->state != FC_PORTDB_STATE_NEW)
1795 lp->state = FC_PORTDB_STATE_VALID;
1796 isp_prt(isp, ISP_LOG_SANCFG,
1797 "Chan %d Port 0x%06x@0x%04x is valid",
1798 chan, pdb->portid, pdb->handle);
1802 /* Something has changed. */
1803 lp->state = FC_PORTDB_STATE_CHANGED;
1804 lp->handle = pdb->handle;
1805 lp->new_portid = pdb->portid;
1806 lp->new_prli_word0 = pdb->prli_word0;
1807 lp->new_prli_word3 = pdb->prli_word3;
1808 isp_prt(isp, ISP_LOG_SANCFG,
1809 "Chan %d Port 0x%06x@0x%04x is changed",
1810 chan, pdb->portid, pdb->handle);
1814 /* It seems like a new port. Find an empty slot for it. */
1815 if (!isp_find_pdb_empty(isp, chan, &lp)) {
1816 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan);
1820 ISP_MEMZERO(lp, sizeof (fcportdb_t));
1821 lp->probational = 0;
1822 lp->state = FC_PORTDB_STATE_NEW;
1823 lp->portid = lp->new_portid = pdb->portid;
1824 lp->prli_word0 = lp->new_prli_word0 = pdb->prli_word0;
1825 lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3;
1826 lp->handle = pdb->handle;
1827 lp->port_wwn = wwpn;
1828 lp->node_wwn = wwnn;
1829 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new",
1830 chan, pdb->portid, pdb->handle);
1834 * Scan local loop for devices.
1837 isp_scan_loop(ispsoftc_t *isp, int chan)
1839 fcparam *fcp = FCPARAM(isp, chan);
1845 if (fcp->isp_loopstate < LOOP_LTEST_DONE)
1847 if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
1850 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
1851 fcp->isp_loopstate = LOOP_SCANNING_LOOP;
1852 if (TOPO_IS_FABRIC(fcp->isp_topo)) {
1853 isp_prt(isp, ISP_LOG_SANCFG,
1854 "Chan %d FC loop scan done (no loop)", chan);
1855 fcp->isp_loopstate = LOOP_LSCAN_DONE;
1859 handles = (uint16_t *)fcp->isp_scanscratch;
1860 lim = ISP_FC_SCRLEN / 2;
1861 r = isp_gethandles(isp, chan, handles, &lim, 1);
1863 isp_prt(isp, ISP_LOG_SANCFG,
1864 "Chan %d Getting list of handles failed with %x", chan, r);
1865 isp_prt(isp, ISP_LOG_SANCFG,
1866 "Chan %d FC loop scan done (bad)", chan);
1870 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
1874 * Run through the list and get the port database info for each one.
1876 isp_mark_portdb(isp, chan);
1877 for (idx = 0; idx < lim; idx++) {
1878 handle = handles[idx];
1881 * Don't scan "special" ids.
1883 if (handle >= NPH_RESERVED)
1887 * Get the port database entity for this index.
1889 r = isp_getpdb(isp, chan, handle, &pdb);
1890 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
1892 isp_prt(isp, ISP_LOG_SANCFG,
1893 "Chan %d FC loop scan aborted", chan);
1897 isp_prt(isp, ISP_LOGDEBUG1,
1898 "Chan %d FC Scan Loop handle %d returned %x",
1903 isp_pdb_add_update(isp, chan, &pdb);
1905 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
1907 fcp->isp_loopstate = LOOP_LSCAN_DONE;
1908 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
1913 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
1915 fcparam *fcp = FCPARAM(isp, chan);
1918 uint8_t resp[QENTRY_LEN];
1920 if (isp->isp_dblev & ISP_LOGDEBUG1)
1921 isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch);
1924 * Build a Passthrough IOCB in memory.
1926 ISP_MEMZERO(&pt, sizeof(pt));
1927 pt.ctp_header.rqs_entry_count = 1;
1928 pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
1929 pt.ctp_nphdl = fcp->isp_sns_hdl;
1931 pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
1934 pt.ctp_rsp_bcnt = rsp_bcnt;
1935 pt.ctp_cmd_bcnt = cmd_bcnt;
1936 pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma);
1937 pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma);
1938 pt.ctp_dataseg[0].ds_count = cmd_bcnt;
1939 pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
1940 pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
1941 pt.ctp_dataseg[1].ds_count = rsp_bcnt;
1943 /* Prepare space for response in memory */
1944 memset(resp, 0xff, sizeof(resp));
1945 pt.ctp_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1946 if (pt.ctp_handle == 0) {
1947 isp_prt(isp, ISP_LOGERR,
1948 "%s: CTP of Chan %d out of handles", __func__, chan);
1952 /* Send request and wait for response. */
1953 reqp = isp_getrqentry(isp);
1955 isp_prt(isp, ISP_LOGERR,
1956 "%s: CTP of Chan %d out of rqent", __func__, chan);
1957 isp_destroy_handle(isp, pt.ctp_handle);
1960 isp_put_ct_pt(isp, &pt, (isp_ct_pt_t *)reqp);
1961 if (isp->isp_dblev & ISP_LOGDEBUG1)
1962 isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, reqp);
1963 ISP_SYNC_REQUEST(isp);
1964 if (msleep(resp, &isp->isp_lock, 0, "CTP", pt.ctp_time*hz) == EWOULDBLOCK) {
1965 isp_prt(isp, ISP_LOGERR,
1966 "%s: CTP of Chan %d timed out", __func__, chan);
1967 isp_destroy_handle(isp, pt.ctp_handle);
1970 if (isp->isp_dblev & ISP_LOGDEBUG1)
1971 isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, resp);
1973 isp_get_ct_pt(isp, (isp_ct_pt_t *)resp, &pt);
1974 if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
1975 isp_prt(isp, ISP_LOGWARN,
1976 "Chan %d CT pass-through returned 0x%x",
1977 chan, pt.ctp_status);
1981 if (isp->isp_dblev & ISP_LOGDEBUG1)
1982 isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch);
1988 * Scan the fabric for devices and add them to our port database.
1990 * Use the GID_PT command to get list of all Nx_Port IDs SNS knows.
1991 * Use GFF_ID and GFT_ID to check port type (FCP) and features (target).
1993 * We use CT Pass-through IOCB.
1995 #define GIDLEN ISP_FC_SCRLEN
1996 #define NGENT ((GIDLEN - 16) >> 2)
1999 isp_gid_pt(ispsoftc_t *isp, int chan)
2001 fcparam *fcp = FCPARAM(isp, chan);
2003 uint8_t *scp = fcp->isp_scratch;
2005 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan);
2006 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2007 isp_prt(isp, ISP_LOGERR, sacq);
2011 /* Build the CT command and execute via pass-through. */
2012 ISP_MEMZERO(&ct, sizeof (ct));
2013 ct.ct_revision = CT_REVISION;
2014 ct.ct_fcs_type = CT_FC_TYPE_FC;
2015 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2016 ct.ct_cmd_resp = SNS_GID_PT;
2017 ct.ct_bcnt_resid = (GIDLEN - 16) >> 2;
2018 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2019 scp[sizeof(ct)] = 0x7f; /* Port Type = Nx_Port */
2020 scp[sizeof(ct)+1] = 0; /* Domain_ID = any */
2021 scp[sizeof(ct)+2] = 0; /* Area_ID = any */
2022 scp[sizeof(ct)+3] = 0; /* Flags = no Area_ID */
2024 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) {
2025 FC_SCRATCH_RELEASE(isp, chan);
2029 isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp,
2030 (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT);
2031 FC_SCRATCH_RELEASE(isp, chan);
2036 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid)
2038 fcparam *fcp = FCPARAM(isp, chan);
2041 uint8_t *scp = fcp->isp_scratch;
2042 sns_gff_id_rsp_t rsp;
2045 if (!fcp->isp_use_gff_id) /* User may block GFF_ID use. */
2048 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan);
2049 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2050 isp_prt(isp, ISP_LOGERR, sacq);
2054 /* Build the CT command and execute via pass-through. */
2055 ISP_MEMZERO(&ct, sizeof (ct));
2056 ct.ct_revision = CT_REVISION;
2057 ct.ct_fcs_type = CT_FC_TYPE_FC;
2058 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2059 ct.ct_cmd_resp = SNS_GFF_ID;
2060 ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4;
2061 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2062 rp = (uint32_t *) &scp[sizeof(ct)];
2063 ISP_IOZPUT_32(isp, portid, rp);
2065 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
2066 SNS_GFF_ID_RESP_SIZE)) {
2067 FC_SCRATCH_RELEASE(isp, chan);
2071 isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp);
2072 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
2073 for (i = 0; i < 32; i++) {
2074 if (rsp.snscb_fc4_features[i] != 0) {
2079 if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >>
2080 ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
2082 /* Workaround for broken Brocade firmware. */
2083 if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >>
2084 ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
2087 FC_SCRATCH_RELEASE(isp, chan);
2088 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res);
2093 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid)
2095 fcparam *fcp = FCPARAM(isp, chan);
2098 uint8_t *scp = fcp->isp_scratch;
2099 sns_gft_id_rsp_t rsp;
2102 if (!fcp->isp_use_gft_id) /* User may block GFT_ID use. */
2105 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan);
2106 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2107 isp_prt(isp, ISP_LOGERR, sacq);
2111 /* Build the CT command and execute via pass-through. */
2112 ISP_MEMZERO(&ct, sizeof (ct));
2113 ct.ct_revision = CT_REVISION;
2114 ct.ct_fcs_type = CT_FC_TYPE_FC;
2115 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2116 ct.ct_cmd_resp = SNS_GFT_ID;
2117 ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4;
2118 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2119 rp = (uint32_t *) &scp[sizeof(ct)];
2120 ISP_IOZPUT_32(isp, portid, rp);
2122 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
2123 SNS_GFT_ID_RESP_SIZE)) {
2124 FC_SCRATCH_RELEASE(isp, chan);
2128 isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp);
2129 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
2130 for (i = 0; i < 8; i++) {
2131 if (rsp.snscb_fc4_types[i] != 0) {
2136 if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >>
2137 (FC4_SCSI % 32)) & 0x01) != 0)
2140 FC_SCRATCH_RELEASE(isp, chan);
2141 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res);
2146 isp_scan_fabric(ispsoftc_t *isp, int chan)
2148 fcparam *fcp = FCPARAM(isp, chan);
2152 int portidx, portlim, r;
2153 sns_gid_xx_rsp_t *rs;
2155 if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
2157 if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
2160 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
2161 fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
2162 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
2163 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2164 isp_prt(isp, ISP_LOG_SANCFG,
2165 "Chan %d FC fabric scan done (no fabric)", chan);
2169 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
2171 FC_SCRATCH_RELEASE(isp, chan);
2172 isp_prt(isp, ISP_LOG_SANCFG,
2173 "Chan %d FC fabric scan aborted", chan);
2178 * Make sure we still are logged into the fabric controller.
2180 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
2181 if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) {
2182 isp_dump_chip_portdb(isp, chan);
2185 fcp->isp_loopstate = LOOP_LTEST_DONE;
2187 isp_prt(isp, ISP_LOG_SANCFG,
2188 "Chan %d FC fabric scan done (bad)", chan);
2192 /* Get list of port IDs from SNS. */
2193 r = isp_gid_pt(isp, chan);
2194 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2197 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2200 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
2204 rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch;
2205 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2207 if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) {
2209 /* FC-4 Type and Port Type not registered are not errors. */
2210 if (rs->snscb_cthdr.ct_reason == 9 &&
2211 (rs->snscb_cthdr.ct_explanation == 0x07 ||
2212 rs->snscb_cthdr.ct_explanation == 0x0a)) {
2213 level = ISP_LOG_SANCFG;
2215 level = ISP_LOGWARN;
2217 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT"
2218 " (Reason=0x%x Expl=0x%x)", chan,
2219 rs->snscb_cthdr.ct_reason,
2220 rs->snscb_cthdr.ct_explanation);
2221 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2225 /* Check our buffer was big enough to get the full list. */
2226 for (portidx = 0; portidx < NGENT-1; portidx++) {
2227 if (rs->snscb_ports[portidx].control & 0x80)
2230 if ((rs->snscb_ports[portidx].control & 0x80) == 0) {
2231 isp_prt(isp, ISP_LOGWARN,
2232 "fabric too big for scratch area: increase ISP_FC_SCRLEN");
2234 portlim = portidx + 1;
2235 isp_prt(isp, ISP_LOG_SANCFG,
2236 "Chan %d Got %d ports back from name server", chan, portlim);
2238 /* Go through the list and remove duplicate port ids. */
2239 for (portidx = 0; portidx < portlim; portidx++) {
2243 ((rs->snscb_ports[portidx].portid[0]) << 16) |
2244 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2245 ((rs->snscb_ports[portidx].portid[2]));
2247 for (npidx = portidx + 1; npidx < portlim; npidx++) {
2248 uint32_t new_portid =
2249 ((rs->snscb_ports[npidx].portid[0]) << 16) |
2250 ((rs->snscb_ports[npidx].portid[1]) << 8) |
2251 ((rs->snscb_ports[npidx].portid[2]));
2252 if (new_portid == portid) {
2257 if (npidx < portlim) {
2258 rs->snscb_ports[npidx].portid[0] = 0;
2259 rs->snscb_ports[npidx].portid[1] = 0;
2260 rs->snscb_ports[npidx].portid[2] = 0;
2261 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid);
2266 * We now have a list of Port IDs for all FC4 SCSI devices
2267 * that the Fabric Name server knows about.
2269 * For each entry on this list go through our port database looking
2270 * for probational entries- if we find one, then an old entry is
2271 * maybe still this one. We get some information to find out.
2273 * Otherwise, it's a new fabric device, and we log into it
2274 * (unconditionally). After searching the entire database
2275 * again to make sure that we never ever ever ever have more
2276 * than one entry that has the same PortID or the same
2277 * WWNN/WWPN duple, we enter the device into our database.
2279 isp_mark_portdb(isp, chan);
2280 for (portidx = 0; portidx < portlim; portidx++) {
2281 portid = ((rs->snscb_ports[portidx].portid[0]) << 16) |
2282 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2283 ((rs->snscb_ports[portidx].portid[2]));
2284 isp_prt(isp, ISP_LOG_SANCFG,
2285 "Chan %d Checking fabric port 0x%06x", chan, portid);
2287 isp_prt(isp, ISP_LOG_SANCFG,
2288 "Chan %d Port at idx %d is zero",
2292 if (portid == fcp->isp_portid) {
2293 isp_prt(isp, ISP_LOG_SANCFG,
2294 "Chan %d Port 0x%06x is our", chan, portid);
2298 /* Now search the entire port database for the same portid. */
2299 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) {
2300 if (!lp->probational) {
2301 isp_prt(isp, ISP_LOGERR,
2302 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
2303 chan, lp->portid, lp->handle,
2304 FC_PORTDB_TGT(isp, chan, lp), lp->state);
2305 isp_dump_portdb(isp, chan);
2309 if (lp->state == FC_PORTDB_STATE_ZOMBIE)
2313 * See if we're still logged into it.
2315 * If we aren't, mark it as a dead device and
2316 * leave the new portid in the database entry
2317 * for somebody further along to decide what to
2318 * do (policy choice).
2320 * If we are, check to see if it's the same
2321 * device still (it should be). If for some
2322 * reason it isn't, mark it as a changed device
2323 * and leave the new portid and role in the
2324 * database entry for somebody further along to
2325 * decide what to do (policy choice).
2327 r = isp_getpdb(isp, chan, lp->handle, &pdb);
2328 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2331 lp->state = FC_PORTDB_STATE_DEAD;
2332 isp_prt(isp, ISP_LOG_SANCFG,
2333 "Chan %d Port 0x%06x handle 0x%x is dead (%d)",
2334 chan, portid, lp->handle, r);
2338 isp_pdb_add_update(isp, chan, &pdb);
2343 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2344 isp_prt(isp, ISP_LOG_SANCFG,
2345 "Chan %d Port 0x%06x is not logged in", chan, portid);
2349 r = isp_gff_id(isp, chan, portid);
2351 isp_prt(isp, ISP_LOG_SANCFG,
2352 "Chan %d Port 0x%06x is not an FCP target", chan, portid);
2356 r = isp_gft_id(isp, chan, portid);
2358 isp_prt(isp, ISP_LOG_SANCFG,
2359 "Chan %d Port 0x%06x is not FCP", chan, portid);
2363 if (isp_login_device(isp, chan, portid, &pdb,
2364 &FCPARAM(isp, 0)->isp_lasthdl)) {
2365 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2370 isp_pdb_add_update(isp, chan, &pdb);
2373 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2375 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2376 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
2381 * Find an unused handle and try and use to login to a port.
2384 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
2389 handle = isp_next_handle(isp, ohp);
2390 for (i = 0; i < NPH_MAX_2K; i++) {
2391 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2394 /* Check if this handle is free. */
2395 r = isp_getpdb(isp, chan, handle, p);
2397 if (p->portid != portid) {
2398 /* This handle is busy, try next one. */
2399 handle = isp_next_handle(isp, ohp);
2404 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2408 * Now try and log into the device
2410 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2413 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
2415 * If we get here, then the firmwware still thinks we're logged into this device, but with a different
2416 * handle. We need to break that association. We used to try and just substitute the handle, but then
2417 * failed to get any data via isp_getpdb (below).
2419 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) {
2420 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
2422 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2424 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2428 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
2429 /* Try the next handle. */
2430 handle = isp_next_handle(isp, ohp);
2438 if (i == NPH_MAX_2K) {
2439 isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid);
2444 * If we successfully logged into it, get the PDB for it
2445 * so we can crosscheck that it is still what we think it
2446 * is and that we also have the role it plays
2448 r = isp_getpdb(isp, chan, handle, p);
2450 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
2454 if (p->handle != handle || p->portid != portid) {
2455 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
2456 chan, portid, handle, p->portid, p->handle);
2463 isp_register_fc4_type(ispsoftc_t *isp, int chan)
2465 fcparam *fcp = FCPARAM(isp, chan);
2467 ct_hdr_t *ct = &rp.rftid_hdr;
2468 uint8_t *scp = fcp->isp_scratch;
2470 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2471 isp_prt(isp, ISP_LOGERR, sacq);
2475 /* Build the CT command and execute via pass-through. */
2476 ISP_MEMZERO(&rp, sizeof(rp));
2477 ct->ct_revision = CT_REVISION;
2478 ct->ct_fcs_type = CT_FC_TYPE_FC;
2479 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2480 ct->ct_cmd_resp = SNS_RFT_ID;
2481 ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2;
2482 rp.rftid_portid[0] = fcp->isp_portid >> 16;
2483 rp.rftid_portid[1] = fcp->isp_portid >> 8;
2484 rp.rftid_portid[2] = fcp->isp_portid;
2485 rp.rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
2486 isp_put_rft_id(isp, &rp, (rft_id_t *)scp);
2488 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2489 FC_SCRATCH_RELEASE(isp, chan);
2493 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2494 FC_SCRATCH_RELEASE(isp, chan);
2495 if (ct->ct_cmd_resp == LS_RJT) {
2496 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "Chan %d Register FC4 Type rejected", chan);
2498 } else if (ct->ct_cmd_resp == LS_ACC) {
2499 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan);
2501 isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp);
2508 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
2510 fcparam *fcp = FCPARAM(isp, chan);
2513 uint8_t *scp = fcp->isp_scratch;
2515 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2516 isp_prt(isp, ISP_LOGERR, sacq);
2521 * Build the CT header and command in memory.
2523 ISP_MEMZERO(&rp, sizeof(rp));
2525 ct->ct_revision = CT_REVISION;
2526 ct->ct_fcs_type = CT_FC_TYPE_FC;
2527 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2528 ct->ct_cmd_resp = SNS_RFF_ID;
2529 ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2;
2530 rp.rffid_portid[0] = fcp->isp_portid >> 16;
2531 rp.rffid_portid[1] = fcp->isp_portid >> 8;
2532 rp.rffid_portid[2] = fcp->isp_portid;
2533 rp.rffid_fc4features = 0;
2534 if (fcp->role & ISP_ROLE_TARGET)
2535 rp.rffid_fc4features |= 1;
2536 if (fcp->role & ISP_ROLE_INITIATOR)
2537 rp.rffid_fc4features |= 2;
2538 rp.rffid_fc4type = FC4_SCSI;
2539 isp_put_rff_id(isp, &rp, (rff_id_t *)scp);
2540 if (isp->isp_dblev & ISP_LOGDEBUG1)
2541 isp_print_bytes(isp, "CT request", sizeof(rft_id_t), scp);
2543 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2544 FC_SCRATCH_RELEASE(isp, chan);
2548 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2549 FC_SCRATCH_RELEASE(isp, chan);
2550 if (ct->ct_cmd_resp == LS_RJT) {
2551 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2552 "Chan %d Register FC4 Features rejected", chan);
2554 } else if (ct->ct_cmd_resp == LS_ACC) {
2555 isp_prt(isp, ISP_LOG_SANCFG,
2556 "Chan %d Register FC4 Features accepted", chan);
2558 isp_prt(isp, ISP_LOGWARN,
2559 "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
2566 isp_register_port_name_24xx(ispsoftc_t *isp, int chan)
2568 fcparam *fcp = FCPARAM(isp, chan);
2571 uint8_t *scp = fcp->isp_scratch;
2574 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2575 isp_prt(isp, ISP_LOGERR, sacq);
2580 * Build the CT header and command in memory.
2582 ISP_MEMZERO(&rp, sizeof(rp));
2583 ct = &rp.rspnid_hdr;
2584 ct->ct_revision = CT_REVISION;
2585 ct->ct_fcs_type = CT_FC_TYPE_FC;
2586 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2587 ct->ct_cmd_resp = SNS_RSPN_ID;
2588 rp.rspnid_portid[0] = fcp->isp_portid >> 16;
2589 rp.rspnid_portid[1] = fcp->isp_portid >> 8;
2590 rp.rspnid_portid[2] = fcp->isp_portid;
2591 rp.rspnid_length = 0;
2592 len = offsetof(rspn_id_t, rspnid_name);
2593 mtx_lock(&prison0.pr_mtx);
2594 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2595 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2596 mtx_unlock(&prison0.pr_mtx);
2597 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2598 ":%s", device_get_nameunit(isp->isp_dev));
2600 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2603 len += rp.rspnid_length;
2604 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2605 isp_put_rspn_id(isp, &rp, (rspn_id_t *)scp);
2607 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2608 FC_SCRATCH_RELEASE(isp, chan);
2612 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2613 FC_SCRATCH_RELEASE(isp, chan);
2614 if (ct->ct_cmd_resp == LS_RJT) {
2615 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2616 "Chan %d Register Symbolic Port Name rejected", chan);
2618 } else if (ct->ct_cmd_resp == LS_ACC) {
2619 isp_prt(isp, ISP_LOG_SANCFG,
2620 "Chan %d Register Symbolic Port Name accepted", chan);
2622 isp_prt(isp, ISP_LOGWARN,
2623 "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp);
2630 isp_register_node_name_24xx(ispsoftc_t *isp, int chan)
2632 fcparam *fcp = FCPARAM(isp, chan);
2635 uint8_t *scp = fcp->isp_scratch;
2638 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2639 isp_prt(isp, ISP_LOGERR, sacq);
2644 * Build the CT header and command in memory.
2646 ISP_MEMZERO(&rp, sizeof(rp));
2647 ct = &rp.rsnnnn_hdr;
2648 ct->ct_revision = CT_REVISION;
2649 ct->ct_fcs_type = CT_FC_TYPE_FC;
2650 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2651 ct->ct_cmd_resp = SNS_RSNN_NN;
2652 MAKE_NODE_NAME_FROM_WWN(rp.rsnnnn_nodename, fcp->isp_wwnn);
2653 rp.rsnnnn_length = 0;
2654 len = offsetof(rsnn_nn_t, rsnnnn_name);
2655 mtx_lock(&prison0.pr_mtx);
2656 rp.rsnnnn_length += sprintf(&scp[len + rp.rsnnnn_length],
2657 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2658 mtx_unlock(&prison0.pr_mtx);
2659 len += rp.rsnnnn_length;
2660 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2661 isp_put_rsnn_nn(isp, &rp, (rsnn_nn_t *)scp);
2663 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2664 FC_SCRATCH_RELEASE(isp, chan);
2668 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2669 FC_SCRATCH_RELEASE(isp, chan);
2670 if (ct->ct_cmd_resp == LS_RJT) {
2671 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2672 "Chan %d Register Symbolic Node Name rejected", chan);
2674 } else if (ct->ct_cmd_resp == LS_ACC) {
2675 isp_prt(isp, ISP_LOG_SANCFG,
2676 "Chan %d Register Symbolic Node Name accepted", chan);
2678 isp_prt(isp, ISP_LOGWARN,
2679 "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp);
2686 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
2696 if (handle == NIL_HANDLE) {
2700 if (handle > NPH_RESERVED - 1) {
2702 isp_prt(isp, ISP_LOGERR, "Out of port handles!");
2703 return (NIL_HANDLE);
2708 for (chan = 0; chan < isp->isp_nchan; chan++) {
2709 fcp = FCPARAM(isp, chan);
2710 if (fcp->role == ISP_ROLE_NONE)
2712 for (i = 0; i < MAX_FC_TARG; i++) {
2713 if (fcp->portdb[i].state != FC_PORTDB_STATE_NIL &&
2714 fcp->portdb[i].handle == handle)
2723 * Start a command. Locking is assumed done in the caller.
2732 ispreqt7_t local, *reqp = &local;
2735 int target, dmaresult;
2741 * Check command CDB length, etc.. We really are limited to 16 bytes
2742 * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
2743 * but probably only if we're running fairly new firmware (we'll
2744 * let the old f/w choke on an extended command queue entry).
2747 if (XS_CDBLEN(xs) > 16 || XS_CDBLEN(xs) == 0) {
2748 isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
2749 XS_SETERR(xs, HBA_REQINVAL);
2750 return (CMD_COMPLETE);
2754 * Translate the target to device handle as appropriate, checking
2755 * for correct device state as well.
2757 target = XS_TGT(xs);
2758 fcp = FCPARAM(isp, XS_CHANNEL(xs));
2760 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2761 isp_prt(isp, ISP_LOG_WARN1,
2762 "%d.%d.%jx I am not an initiator",
2763 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2764 XS_SETERR(xs, HBA_SELTIMEOUT);
2765 return (CMD_COMPLETE);
2768 if (isp->isp_state != ISP_RUNSTATE) {
2769 isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
2770 XS_SETERR(xs, HBA_BOTCH);
2771 return (CMD_COMPLETE);
2774 isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target);
2775 lp = &fcp->portdb[target];
2776 if (target < 0 || target >= MAX_FC_TARG ||
2777 lp->is_target == 0) {
2778 XS_SETERR(xs, HBA_SELTIMEOUT);
2779 return (CMD_COMPLETE);
2781 if (fcp->isp_loopstate != LOOP_READY) {
2782 isp_prt(isp, ISP_LOGDEBUG1,
2783 "%d.%d.%jx loop is not ready",
2784 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2785 return (CMD_RQLATER);
2787 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
2788 isp_prt(isp, ISP_LOGDEBUG1,
2789 "%d.%d.%jx target zombie",
2790 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2791 return (CMD_RQLATER);
2793 if (lp->state != FC_PORTDB_STATE_VALID) {
2794 isp_prt(isp, ISP_LOGDEBUG1,
2795 "%d.%d.%jx bad db port state 0x%x",
2796 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs), lp->state);
2797 XS_SETERR(xs, HBA_SELTIMEOUT);
2798 return (CMD_COMPLETE);
2803 qep = isp_getrqentry(isp);
2805 isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow");
2806 XS_SETERR(xs, HBA_BOTCH);
2807 return (CMD_EAGAIN);
2809 XS_SETERR(xs, HBA_NOERROR);
2812 * Now see if we need to synchronize the ISP with respect to anything.
2813 * We do dual duty here (cough) for synchronizing for buses other
2814 * than which we got here to send a command to.
2816 ISP_MEMZERO(reqp, QENTRY_LEN);
2817 if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
2818 isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
2819 m->mrk_header.rqs_entry_count = 1;
2820 m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
2821 m->mrk_modifier = SYNC_ALL;
2822 m->mrk_vphdl = XS_CHANNEL(xs);
2823 isp_put_marker_24xx(isp, m, qep);
2824 ISP_SYNC_REQUEST(isp);
2825 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
2830 * NB: we do not support long CDBs (yet)
2832 cdblen = XS_CDBLEN(xs);
2833 if (cdblen > sizeof (reqp->req_cdb)) {
2834 isp_prt(isp, ISP_LOGERR, "Command Length %u too long for this chip", cdblen);
2835 XS_SETERR(xs, HBA_REQINVAL);
2836 return (CMD_COMPLETE);
2839 reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
2840 reqp->req_header.rqs_entry_count = 1;
2841 reqp->req_nphdl = lp->handle;
2842 reqp->req_time = XS_TIME(xs);
2843 be64enc(reqp->req_lun, CAM_EXTLUN_BYTE_SWIZZLE(XS_LUN(xs)));
2845 reqp->req_alen_datadir = FCP_CMND_DATA_READ;
2846 else if (XS_XFROUT(xs))
2847 reqp->req_alen_datadir = FCP_CMND_DATA_WRITE;
2849 reqp->req_task_attribute = XS_TAG_TYPE(xs);
2851 reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE;
2852 reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) &
2854 if (FCPARAM(isp, XS_CHANNEL(xs))->fctape_enabled && (lp->prli_word3 & PRLI_WD3_RETRY)) {
2855 if (FCP_NEXT_CRN(isp, &reqp->req_crn, xs)) {
2856 isp_prt(isp, ISP_LOG_WARN1,
2857 "%d.%d.%jx cannot generate next CRN",
2858 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2859 XS_SETERR(xs, HBA_BOTCH);
2860 return (CMD_EAGAIN);
2863 ISP_MEMCPY(reqp->req_cdb, XS_CDBP(xs), cdblen);
2864 reqp->req_dl = XS_XFRLEN(xs);
2865 reqp->req_tidlo = lp->portid;
2866 reqp->req_tidhi = lp->portid >> 16;
2867 reqp->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs));
2869 /* Whew. Thankfully the same for type 7 requests */
2870 reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR);
2871 if (reqp->req_handle == 0) {
2872 isp_prt(isp, ISP_LOG_WARN1, "out of xflist pointers");
2873 XS_SETERR(xs, HBA_BOTCH);
2874 return (CMD_EAGAIN);
2878 * Set up DMA and/or do any platform dependent swizzling of the request entry
2879 * so that the Qlogic F/W understands what is being asked of it.
2881 * The callee is responsible for adding all requests at this point.
2883 dmaresult = ISP_DMASETUP(isp, xs, reqp);
2884 if (dmaresult != 0) {
2885 isp_destroy_handle(isp, reqp->req_handle);
2887 * dmasetup sets actual error in packet, and
2888 * return what we were given to return.
2892 isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
2898 * Locks (ints blocked) assumed held.
2902 isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
2911 uint8_t local[QENTRY_LEN];
2914 case ISPCTL_RESET_BUS:
2916 * Issue a bus reset.
2918 isp_prt(isp, ISP_LOGERR, "BUS RESET NOT IMPLEMENTED");
2921 case ISPCTL_RESET_DEV:
2924 isp24xx_statusreq_t *sp;
2927 chan = va_arg(ap, int);
2928 tgt = va_arg(ap, int);
2930 fcp = FCPARAM(isp, chan);
2932 if (tgt < 0 || tgt >= MAX_FC_TARG) {
2933 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to reset bad target %d", chan, tgt);
2936 lp = &fcp->portdb[tgt];
2937 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
2938 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
2942 tmf = (isp24xx_tmf_t *) local;
2943 ISP_MEMZERO(tmf, QENTRY_LEN);
2944 tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
2945 tmf->tmf_header.rqs_entry_count = 1;
2946 tmf->tmf_nphdl = lp->handle;
2948 tmf->tmf_timeout = 4;
2949 tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
2950 tmf->tmf_tidlo = lp->portid;
2951 tmf->tmf_tidhi = lp->portid >> 16;
2952 tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
2953 isp_put_24xx_tmf(isp, tmf, isp->isp_iocb);
2954 if (isp->isp_dblev & ISP_LOGDEBUG1)
2955 isp_print_bytes(isp, "TMF IOCB request", QENTRY_LEN, isp->isp_iocb);
2956 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, QENTRY_LEN, chan);
2957 fcp->sendmarker = 1;
2959 isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
2960 MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL,
2961 MBCMD_DEFAULT_TIMEOUT + tmf->tmf_timeout * 1000000);
2962 mbs.param[1] = QENTRY_LEN;
2963 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
2964 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
2965 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
2966 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
2967 isp_mboxcmd(isp, &mbs);
2968 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
2971 MEMORYBARRIER(isp, SYNC_IFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
2972 if (isp->isp_dblev & ISP_LOGDEBUG1)
2973 isp_print_bytes(isp, "TMF IOCB response", QENTRY_LEN, &((isp24xx_statusreq_t *)isp->isp_iocb)[1]);
2974 sp = (isp24xx_statusreq_t *) local;
2975 isp_get_24xx_response(isp, &((isp24xx_statusreq_t *)isp->isp_iocb)[1], sp);
2976 if (sp->req_completion_status == 0) {
2979 isp_prt(isp, ISP_LOGWARN, "Chan %d reset of target %d returned 0x%x", chan, tgt, sp->req_completion_status);
2982 case ISPCTL_ABORT_CMD:
2984 isp24xx_abrt_t *ab = (isp24xx_abrt_t *)&local;
2987 xs = va_arg(ap, XS_T *);
2991 chan = XS_CHANNEL(xs);
2993 handle = isp_find_handle(isp, xs);
2995 isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort");
2999 fcp = FCPARAM(isp, chan);
3000 if (tgt < 0 || tgt >= MAX_FC_TARG) {
3001 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to abort bad target %d", chan, tgt);
3004 lp = &fcp->portdb[tgt];
3005 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
3006 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
3009 isp_prt(isp, ISP_LOGALL, "Chan %d Abort Cmd for N-Port 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
3010 ISP_MEMZERO(ab, QENTRY_LEN);
3011 ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO;
3012 ab->abrt_header.rqs_entry_count = 1;
3013 ab->abrt_handle = lp->handle;
3014 ab->abrt_cmd_handle = handle;
3015 ab->abrt_tidlo = lp->portid;
3016 ab->abrt_tidhi = lp->portid >> 16;
3017 ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan);
3018 isp_put_24xx_abrt(isp, ab, isp->isp_iocb);
3019 if (isp->isp_dblev & ISP_LOGDEBUG1)
3020 isp_print_bytes(isp, "AB IOCB quest", QENTRY_LEN, isp->isp_iocb);
3021 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, 2 * QENTRY_LEN, chan);
3023 ISP_MEMZERO(&mbs, sizeof (mbs));
3024 MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
3025 mbs.param[1] = QENTRY_LEN;
3026 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
3027 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
3028 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
3029 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
3031 isp_mboxcmd(isp, &mbs);
3032 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
3035 MEMORYBARRIER(isp, SYNC_IFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
3036 if (isp->isp_dblev & ISP_LOGDEBUG1)
3037 isp_print_bytes(isp, "AB IOCB response", QENTRY_LEN, &((isp24xx_abrt_t *)isp->isp_iocb)[1]);
3038 isp_get_24xx_abrt(isp, &((isp24xx_abrt_t *)isp->isp_iocb)[1], ab);
3039 if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY) {
3042 isp_prt(isp, ISP_LOGWARN, "Chan %d handle %d abort returned 0x%x", chan, tgt, ab->abrt_nphdl);
3044 case ISPCTL_FCLINK_TEST:
3049 chan = va_arg(ap, int);
3050 usdelay = va_arg(ap, int);
3054 return (isp_fclink_test(isp, chan, usdelay));
3056 case ISPCTL_SCAN_FABRIC:
3059 chan = va_arg(ap, int);
3061 return (isp_scan_fabric(isp, chan));
3063 case ISPCTL_SCAN_LOOP:
3066 chan = va_arg(ap, int);
3068 return (isp_scan_loop(isp, chan));
3070 case ISPCTL_PDB_SYNC:
3073 chan = va_arg(ap, int);
3075 return (isp_pdb_sync(isp, chan));
3077 case ISPCTL_SEND_LIP:
3080 case ISPCTL_GET_PDB:
3084 chan = va_arg(ap, int);
3085 tgt = va_arg(ap, int);
3086 pdb = va_arg(ap, isp_pdb_t *);
3088 return (isp_getpdb(isp, chan, tgt, pdb));
3090 case ISPCTL_GET_NAMES:
3092 uint64_t *wwnn, *wwnp;
3094 chan = va_arg(ap, int);
3095 tgt = va_arg(ap, int);
3096 wwnn = va_arg(ap, uint64_t *);
3097 wwnp = va_arg(ap, uint64_t *);
3099 if (wwnn == NULL && wwnp == NULL) {
3103 *wwnn = isp_get_wwn(isp, chan, tgt, 1);
3104 if (*wwnn == INI_NONE) {
3109 *wwnp = isp_get_wwn(isp, chan, tgt, 0);
3110 if (*wwnp == INI_NONE) {
3122 p = va_arg(ap, isp_plcmd_t *);
3125 if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
3126 return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags));
3129 isp_next_handle(isp, &p->handle);
3130 r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags);
3131 if ((r & 0xffff) == MBOX_PORT_ID_USED) {
3132 p->handle = r >> 16;
3136 } while ((r & 0xffff) == MBOX_LOOP_ID_USED);
3139 case ISPCTL_CHANGE_ROLE:
3144 chan = va_arg(ap, int);
3145 role = va_arg(ap, int);
3147 return (isp_fc_change_role(isp, chan, role));
3150 isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
3158 * Interrupt Service Routine(s).
3160 * External (OS) framework has done the appropriate locking,
3161 * and the locking will be held throughout this function.
3164 #ifdef ISP_TARGET_MODE
3166 isp_intr_atioq(ispsoftc_t *isp)
3168 uint8_t qe[QENTRY_LEN];
3171 uint32_t iptr, optr, oop;
3173 iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
3174 optr = isp->isp_atioodx;
3175 while (optr != iptr) {
3177 MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN, -1);
3178 addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop);
3179 isp_get_hdr(isp, addr, (isphdr_t *)qe);
3180 hp = (isphdr_t *)qe;
3181 switch (hp->rqs_entry_type) {
3182 case RQSTYPE_NOTIFY:
3184 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue.*/
3185 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue.*/
3186 (void) isp_target_notify(isp, addr, &oop,
3187 ATIO_QUEUE_LEN(isp));
3189 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/
3191 isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
3194 optr = ISP_NXT_QENTRY(oop, ATIO_QUEUE_LEN(isp));
3196 if (isp->isp_atioodx != optr) {
3197 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
3198 isp->isp_atioodx = optr;
3204 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0)
3208 if (!isp->isp_mboxbsy) {
3209 isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0);
3212 obits = isp->isp_obits;
3213 isp->isp_mboxtmp[0] = mbox0;
3214 for (i = 1; i < ISP_NMBOX(isp); i++) {
3215 if ((obits & (1 << i)) == 0)
3217 isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
3219 isp->isp_mboxbsy = 0;
3223 isp_intr_respq(ispsoftc_t *isp)
3226 uint8_t qe[QENTRY_LEN];
3227 isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe;
3228 ispstatus_cont_t *scp = (ispstatus_cont_t *)qe;
3230 uint8_t *resp, *snsp;
3231 int buddaboom, completion_status, cont = 0, etype, i;
3232 int req_status_flags, req_state_flags, scsi_status;
3233 uint32_t iptr, cptr, optr, rlen, slen, sptr, totslen, resid;
3236 * We can't be getting this now.
3238 if (isp->isp_state != ISP_RUNSTATE) {
3239 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready");
3243 iptr = ISP_READ(isp, BIU2400_RSPINP);
3244 optr = isp->isp_resodx;
3245 while (optr != iptr) {
3247 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
3248 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
3251 * Synchronize our view of this response queue entry.
3253 MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1);
3254 if (isp->isp_dblev & ISP_LOGDEBUG1)
3255 isp_print_qentry(isp, "Response Queue Entry", cptr, hp);
3256 isp_get_hdr(isp, hp, &sp->req_header);
3257 etype = sp->req_header.rqs_entry_type;
3259 /* We expected Status Continuation, but got different IOCB. */
3260 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
3265 if (etype == RQSTYPE_RESPONSE) {
3266 isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp);
3267 scsi_status = sp->req_scsi_status;
3268 completion_status = sp->req_completion_status;
3269 req_status_flags = 0;
3270 if ((scsi_status & 0xff) != 0)
3271 req_state_flags = RQSF_GOT_STATUS;
3273 req_state_flags = 0;
3274 resid = sp->req_resid;
3275 } else if (etype == RQSTYPE_STATUS_CONT) {
3276 isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
3278 i = min(cont, sizeof(scp->req_sense_data));
3279 XS_SENSE_APPEND(cont_xs, scp->req_sense_data, i);
3284 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3285 "Expecting Status Continuations for %u bytes",
3289 isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
3291 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3293 } else if (isp_handle_other_response(isp, etype, hp,
3294 &cptr, RESULT_QUEUE_LEN(isp))) {
3295 /* More then one IOCB could be consumed. */
3296 while (sptr != cptr) {
3297 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3298 sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp));
3299 hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr);
3301 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3302 optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
3305 /* We don't know what was this -- log and skip. */
3306 isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr);
3307 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3312 if (sp->req_header.rqs_flags & RQSFLAG_MASK) {
3313 if (sp->req_header.rqs_flags & RQSFLAG_BADTYPE) {
3314 isp_print_qentry(isp, "invalid entry type",
3318 if (sp->req_header.rqs_flags & RQSFLAG_BADPARAM) {
3319 isp_print_qentry(isp, "invalid entry parameter",
3323 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
3324 isp_print_qentry(isp, "invalid entry count",
3328 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
3329 isp_print_qentry(isp, "invalid entry order",
3335 xs = isp_find_xs(isp, sp->req_handle);
3337 uint8_t ts = completion_status & 0xff;
3339 * Only whine if this isn't the expected fallout of
3340 * aborting the command or resetting the target.
3342 if (etype != RQSTYPE_RESPONSE) {
3343 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype);
3344 } else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED) {
3345 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts);
3347 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3350 if (req_status_flags & RQSTF_BUS_RESET) {
3351 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx bus was reset",
3352 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs));
3353 XS_SETERR(xs, HBA_BUSRESET);
3354 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1);
3357 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx buddaboom",
3358 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs));
3359 XS_SETERR(xs, HBA_BOTCH);
3363 rlen = slen = totslen = 0;
3364 if ((scsi_status & (RQCS_RV|RQCS_SV)) != 0) {
3365 resp = sp->req_rsp_sense;
3366 rlen = sp->req_response_len;
3368 if ((scsi_status & RQCS_SV) != 0) {
3370 * Fibre Channel F/W doesn't say we got status
3371 * if there's Sense Data instead. I guess they
3372 * think it goes w/o saying.
3374 req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE;
3375 snsp = sp->req_rsp_sense + rlen;
3376 totslen = sp->req_sense_len;
3377 slen = sizeof(sp->req_rsp_sense) - rlen;
3381 if (req_state_flags & RQSF_GOT_STATUS)
3382 *XS_STSP(xs) = scsi_status & 0xff;
3384 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
3387 const char *rnames[10] = {
3388 "Task Management function complete",
3389 "FCP_DATA length different than FCP_BURST_LEN",
3390 "FCP_CMND fields invalid",
3391 "FCP_DATA parameter mismatch with FCP_DATA_RO",
3392 "Task Management function rejected",
3393 "Task Management function failed",
3396 "Task Management function succeeded",
3397 "Task Management function incorrect logical unit number",
3399 uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
3400 if (code >= 10 || rnames[code] == NULL) {
3401 ISP_SNPRINTF(lb, sizeof(lb),
3402 "Unknown FCP Response Code 0x%x", code);
3407 isp_xs_prt(isp, xs, ISP_LOGWARN,
3408 "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
3409 rlen, ptr, XS_CDBP(xs)[0] & 0xff);
3410 if (code != 0 && code != 8)
3411 XS_SETERR(xs, HBA_BOTCH);
3413 isp_parse_status_24xx(isp, sp, xs, &resid);
3414 if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) &&
3415 (*XS_STSP(xs) == SCSI_BUSY))
3416 XS_SETERR(xs, HBA_TGTBSY);
3417 if (req_status_flags & RQSF_XFER_COMPLETE) {
3418 XS_SET_RESID(xs, 0);
3419 } else if (scsi_status & RQCS_RESID) {
3420 XS_SET_RESID(xs, resid);
3422 XS_SET_RESID(xs, 0);
3425 XS_SAVE_SENSE(xs, snsp, slen);
3426 if (totslen > slen) {
3427 cont = totslen - slen;
3429 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3430 "Expecting Status Continuations for %u bytes",
3434 isp_prt(isp, ISP_LOGDEBUG2, "asked for %lu got raw resid %lu settled for %lu",
3435 (u_long)XS_XFRLEN(xs), (u_long)resid, (u_long)XS_GET_RESID(xs));
3437 ISP_DMAFREE(isp, xs);
3438 isp_destroy_handle(isp, sp->req_handle);
3440 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3442 /* Complete command if we expect no Status Continuations. */
3447 /* We haven't received all Status Continuations, but that is it. */
3451 /* If we processed any IOCBs, let ISP know about it. */
3452 if (optr != isp->isp_resodx) {
3453 ISP_WRITE(isp, BIU2400_RSPOUTP, optr);
3454 isp->isp_resodx = optr;
3460 isp_intr_async(ispsoftc_t *isp, uint16_t mbox)
3465 isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
3468 case ASYNC_SYSTEM_ERROR:
3469 isp->isp_state = ISP_CRASHED;
3470 for (chan = 0; chan < isp->isp_nchan; chan++) {
3471 FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
3472 isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
3475 * Were we waiting for a mailbox command to complete?
3476 * If so, it's dead, so wake up the waiter.
3478 if (isp->isp_mboxbsy) {
3480 isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
3481 isp->isp_mboxbsy = 0;
3484 * It's up to the handler for isp_async to reinit stuff and
3485 * restart the firmware
3487 isp_async(isp, ISPASYNC_FW_CRASH);
3490 case ASYNC_RQS_XFER_ERR:
3491 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
3494 case ASYNC_RSP_XFER_ERR:
3495 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
3498 case ASYNC_ATIO_XFER_ERR:
3499 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
3502 case ASYNC_LIP_OCCURRED:
3503 case ASYNC_LIP_NOS_OLS_RECV:
3504 case ASYNC_LIP_ERROR:
3507 * These are broadcast events that have to be sent across
3508 * all active channels.
3510 for (chan = 0; chan < isp->isp_nchan; chan++) {
3511 fcp = FCPARAM(isp, chan);
3512 int topo = fcp->isp_topo;
3514 if (fcp->role == ISP_ROLE_NONE)
3516 if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3517 fcp->isp_loopstate = LOOP_HAVE_LINK;
3518 ISP_SET_SENDMARKER(isp, chan, 1);
3519 isp_async(isp, ISPASYNC_LIP, chan);
3520 #ifdef ISP_TARGET_MODE
3521 isp_target_async(isp, chan, mbox);
3524 * We've had problems with data corruption occurring on
3525 * commands that complete (with no apparent error) after
3526 * we receive a LIP. This has been observed mostly on
3527 * Local Loop topologies. To be safe, let's just mark
3528 * all active initiator commands as dead.
3530 if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
3532 for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) {
3536 hdp = &isp->isp_xflist[i];
3537 if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
3541 if (XS_CHANNEL(xs) != chan) {
3545 isp_prt(isp, ISP_LOG_WARN1,
3546 "%d.%d.%jx bus reset set at %s:%u",
3547 XS_CHANNEL(xs), XS_TGT(xs),
3548 (uintmax_t)XS_LUN(xs),
3549 __func__, __LINE__);
3550 XS_SETERR(xs, HBA_BUSRESET);
3553 isp_prt(isp, ISP_LOGERR, lipd, chan, j);
3561 * This is a broadcast event that has to be sent across
3562 * all active channels.
3564 for (chan = 0; chan < isp->isp_nchan; chan++) {
3565 fcp = FCPARAM(isp, chan);
3566 if (fcp->role == ISP_ROLE_NONE)
3568 fcp->isp_linkstate = 1;
3569 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3570 fcp->isp_loopstate = LOOP_HAVE_LINK;
3571 ISP_SET_SENDMARKER(isp, chan, 1);
3572 isp_async(isp, ISPASYNC_LOOP_UP, chan);
3573 #ifdef ISP_TARGET_MODE
3574 isp_target_async(isp, chan, mbox);
3579 case ASYNC_LOOP_DOWN:
3581 * This is a broadcast event that has to be sent across
3582 * all active channels.
3584 for (chan = 0; chan < isp->isp_nchan; chan++) {
3585 fcp = FCPARAM(isp, chan);
3586 if (fcp->role == ISP_ROLE_NONE)
3588 ISP_SET_SENDMARKER(isp, chan, 1);
3589 fcp->isp_linkstate = 0;
3590 fcp->isp_loopstate = LOOP_NIL;
3591 isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
3592 #ifdef ISP_TARGET_MODE
3593 isp_target_async(isp, chan, mbox);
3598 case ASYNC_LOOP_RESET:
3600 * This is a broadcast event that has to be sent across
3601 * all active channels.
3603 for (chan = 0; chan < isp->isp_nchan; chan++) {
3604 fcp = FCPARAM(isp, chan);
3605 if (fcp->role == ISP_ROLE_NONE)
3607 ISP_SET_SENDMARKER(isp, chan, 1);
3608 if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3609 fcp->isp_loopstate = LOOP_HAVE_LINK;
3610 isp_async(isp, ISPASYNC_LOOP_RESET, chan);
3611 #ifdef ISP_TARGET_MODE
3612 isp_target_async(isp, chan, mbox);
3617 case ASYNC_PDB_CHANGED:
3619 int echan, nphdl, nlstate, reason;
3621 nphdl = ISP_READ(isp, OUTMAILBOX1);
3622 nlstate = ISP_READ(isp, OUTMAILBOX2);
3623 reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
3624 if (ISP_CAP_MULTI_ID(isp)) {
3625 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3626 if (chan == 0xff || nphdl == NIL_HANDLE) {
3628 echan = isp->isp_nchan - 1;
3629 } else if (chan >= isp->isp_nchan) {
3637 for (; chan <= echan; chan++) {
3638 fcp = FCPARAM(isp, chan);
3639 if (fcp->role == ISP_ROLE_NONE)
3641 if (fcp->isp_loopstate > LOOP_LTEST_DONE) {
3642 if (nphdl != NIL_HANDLE &&
3643 nphdl == fcp->isp_login_hdl &&
3644 reason == PDB24XX_AE_OPN_2)
3646 fcp->isp_loopstate = LOOP_LTEST_DONE;
3647 } else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3648 fcp->isp_loopstate = LOOP_HAVE_LINK;
3649 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3650 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
3654 case ASYNC_CHANGE_NOTIFY:
3658 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) |
3659 ISP_READ(isp, OUTMAILBOX2);
3660 if (ISP_CAP_MULTI_ID(isp)) {
3661 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3662 if (chan >= isp->isp_nchan)
3667 fcp = FCPARAM(isp, chan);
3668 if (fcp->role == ISP_ROLE_NONE)
3670 if (fcp->isp_loopstate > LOOP_LTEST_DONE)
3671 fcp->isp_loopstate = LOOP_LTEST_DONE;
3672 else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3673 fcp->isp_loopstate = LOOP_HAVE_LINK;
3674 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3675 ISPASYNC_CHANGE_SNS, portid);
3678 case ASYNC_ERR_LOGGING_DISABLED:
3679 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)",
3680 ISP_READ(isp, OUTMAILBOX1));
3682 case ASYNC_P2P_INIT_ERR:
3683 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)",
3684 ISP_READ(isp, OUTMAILBOX1));
3687 isp_prt(isp, ISP_LOGWARN, "Receive Error");
3689 case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */
3690 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
3692 case ASYNC_FW_RESTART_COMPLETE:
3693 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete");
3695 case ASYNC_TEMPERATURE_ALERT:
3696 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)",
3697 ISP_READ(isp, OUTMAILBOX1));
3699 case ASYNC_INTER_DRIVER_COMP:
3700 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication complete");
3702 case ASYNC_INTER_DRIVER_NOTIFY:
3703 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication notification");
3705 case ASYNC_INTER_DRIVER_TIME_EXT:
3706 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication time extended");
3708 case ASYNC_TRANSCEIVER_INSERTION:
3709 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)",
3710 ISP_READ(isp, OUTMAILBOX1));
3712 case ASYNC_TRANSCEIVER_REMOVAL:
3713 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal");
3715 case ASYNC_NIC_FW_STATE_CHANGE:
3716 isp_prt(isp, ISP_LOGDEBUG0, "NIC Firmware State Change");
3718 case ASYNC_AUTOLOAD_FW_COMPLETE:
3719 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete");
3721 case ASYNC_AUTOLOAD_FW_FAILURE:
3722 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure");
3725 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
3731 * Handle other response entries. A pointer to the request queue output
3732 * index is here in case we want to eat several entries at once, although
3733 * this is not used currently.
3737 isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *optrp, uint16_t ql)
3741 uint32_t hdl, portid;
3745 case RQSTYPE_MARKER:
3746 isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
3748 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/
3749 isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
3750 portid = (uint32_t)rid.ridacq_vp_port_hi << 16 |
3751 rid.ridacq_vp_port_lo;
3752 if (rid.ridacq_format == 0) {
3753 for (chan = 0; chan < isp->isp_nchan; chan++) {
3754 fcparam *fcp = FCPARAM(isp, chan);
3755 if (fcp->role == ISP_ROLE_NONE)
3757 c = (chan == 0) ? 127 : (chan - 1);
3758 if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
3760 fcp->isp_loopstate = LOOP_HAVE_LINK;
3761 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3762 chan, ISPASYNC_CHANGE_OTHER);
3764 fcp->isp_loopstate = LOOP_NIL;
3765 isp_async(isp, ISPASYNC_LOOP_DOWN,
3770 fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index);
3771 if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
3772 rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
3773 fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7;
3774 fcp->isp_portid = portid;
3775 fcp->isp_loopstate = LOOP_HAVE_ADDR;
3776 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3777 rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
3779 fcp->isp_loopstate = LOOP_NIL;
3780 isp_async(isp, ISPASYNC_LOOP_DOWN,
3781 rid.ridacq_vp_index);
3785 case RQSTYPE_CT_PASSTHRU:
3786 case RQSTYPE_VP_MODIFY:
3787 case RQSTYPE_VP_CTRL:
3789 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
3790 ptr = isp_find_xs(isp, hdl);
3792 isp_destroy_handle(isp, hdl);
3793 memcpy(ptr, hp, QENTRY_LEN);
3797 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue. */
3799 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue. */
3800 case RQSTYPE_ABTS_RSP:
3801 #ifdef ISP_TARGET_MODE
3802 return (isp_target_notify(isp, hp, optrp, ql));
3811 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs, uint32_t *rp)
3813 int ru_marked, sv_marked;
3814 int chan = XS_CHANNEL(xs);
3816 switch (sp->req_completion_status) {
3819 XS_SETERR(xs, HBA_NOERROR);
3823 case RQCS_DMA_ERROR:
3824 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error");
3827 case RQCS_TRANSPORT_ERROR:
3828 isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error");
3831 case RQCS_RESET_OCCURRED:
3832 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command");
3833 FCPARAM(isp, chan)->sendmarker = 1;
3835 XS_SETERR(xs, HBA_BUSRESET);
3840 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted");
3841 FCPARAM(isp, chan)->sendmarker = 1;
3843 XS_SETERR(xs, HBA_ABORTED);
3848 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out");
3850 XS_SETERR(xs, HBA_CMDTIMEOUT);
3854 case RQCS_DATA_OVERRUN:
3855 XS_SET_RESID(xs, sp->req_resid);
3856 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun");
3858 XS_SETERR(xs, HBA_DATAOVR);
3862 case RQCS_24XX_DRE: /* data reassembly error */
3863 isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs));
3865 XS_SETERR(xs, HBA_ABORTED);
3867 *rp = XS_XFRLEN(xs);
3870 case RQCS_24XX_TABORT: /* aborted by target */
3871 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs));
3873 XS_SETERR(xs, HBA_ABORTED);
3877 case RQCS_DATA_UNDERRUN:
3878 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
3880 * We can get an underrun w/o things being marked
3881 * if we got a non-zero status.
3883 sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
3884 if ((ru_marked == 0 && sv_marked == 0) ||
3885 (sp->req_resid > XS_XFRLEN(xs))) {
3886 isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked");
3888 XS_SETERR(xs, HBA_BOTCH);
3892 XS_SET_RESID(xs, sp->req_resid);
3893 isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff);
3895 XS_SETERR(xs, HBA_NOERROR);
3899 case RQCS_PORT_UNAVAILABLE:
3901 * No such port on the loop. Moral equivalent of SELTIMEO
3903 case RQCS_PORT_LOGGED_OUT:
3906 uint8_t sts = sp->req_completion_status & 0xff;
3907 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
3911 * It was there (maybe)- treat as a selection timeout.
3913 if (sts == RQCS_PORT_UNAVAILABLE) {
3914 reason = "unavailable";
3919 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
3920 chan, reason, XS_TGT(xs));
3922 /* XXX: Should we trigger rescan or FW announce change? */
3925 lp = &fcp->portdb[XS_TGT(xs)];
3926 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
3927 *XS_STSP(xs) = SCSI_BUSY;
3928 XS_SETERR(xs, HBA_TGTBSY);
3930 XS_SETERR(xs, HBA_SELTIMEOUT);
3934 case RQCS_PORT_CHANGED:
3935 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan);
3937 *XS_STSP(xs) = SCSI_BUSY;
3938 XS_SETERR(xs, HBA_TGTBSY);
3942 case RQCS_24XX_ENOMEM: /* f/w resource unavailable */
3943 isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan);
3945 *XS_STSP(xs) = SCSI_BUSY;
3946 XS_SETERR(xs, HBA_TGTBSY);
3950 case RQCS_24XX_TMO: /* task management overrun */
3951 isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan);
3953 *XS_STSP(xs) = SCSI_BUSY;
3954 XS_SETERR(xs, HBA_TGTBSY);
3959 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan);
3963 XS_SETERR(xs, HBA_BOTCH);
3967 #define ISP_FC_IBITS(op) ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3]))
3968 #define ISP_FC_OBITS(op) ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7]))
3970 #define ISP_FC_OPMAP(in0, out0) 0, 0, 0, in0, 0, 0, 0, out0
3971 #define ISP_FC_OPMAP_HALF(in1, in0, out1, out0) 0, 0, in1, in0, 0, 0, out1, out0
3972 #define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0) in3, in2, in1, in0, out3, out2, out1, out0
3973 static const uint32_t mbpfc[] = {
3974 ISP_FC_OPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
3975 ISP_FC_OPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
3976 ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f), /* 0x02: MBOX_EXEC_FIRMWARE */
3977 ISP_FC_OPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */
3978 ISP_FC_OPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
3979 ISP_FC_OPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
3980 ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */
3981 ISP_FC_OPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
3982 ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f), /* 0x08: MBOX_ABOUT_FIRMWARE */
3983 ISP_FC_OPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */
3984 ISP_FC_OPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
3985 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */
3986 ISP_FC_OPMAP(0x00, 0x00), /* 0x0c: */
3987 ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
3988 ISP_FC_OPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
3989 ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
3990 ISP_FC_OPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
3991 ISP_FC_OPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
3992 ISP_FC_OPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
3993 ISP_FC_OPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
3994 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03), /* 0x14: MBOX_STOP_FIRMWARE */
3995 ISP_FC_OPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */
3996 ISP_FC_OPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */
3997 ISP_FC_OPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */
3998 ISP_FC_OPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */
3999 ISP_FC_OPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */
4000 ISP_FC_OPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */
4001 ISP_FC_OPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
4002 ISP_FC_OPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */
4003 ISP_FC_OPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
4004 ISP_FC_OPMAP(0x00, 0x00), /* 0x1e: */
4005 ISP_FC_OPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
4006 ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf), /* 0x20: MBOX_GET_LOOP_ID */
4007 ISP_FC_OPMAP(0x00, 0x00), /* 0x21: */
4008 ISP_FC_OPMAP(0x03, 0x4b), /* 0x22: MBOX_GET_TIMEOUT_PARAMS */
4009 ISP_FC_OPMAP(0x00, 0x00), /* 0x23: */
4010 ISP_FC_OPMAP(0x00, 0x00), /* 0x24: */
4011 ISP_FC_OPMAP(0x00, 0x00), /* 0x25: */
4012 ISP_FC_OPMAP(0x00, 0x00), /* 0x26: */
4013 ISP_FC_OPMAP(0x00, 0x00), /* 0x27: */
4014 ISP_FC_OPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
4015 ISP_FC_OPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
4016 ISP_FC_OPMAP(0x00, 0x00), /* 0x2a: */
4017 ISP_FC_OPMAP(0x00, 0x00), /* 0x2b: */
4018 ISP_FC_OPMAP(0x00, 0x00), /* 0x2c: */
4019 ISP_FC_OPMAP(0x00, 0x00), /* 0x2d: */
4020 ISP_FC_OPMAP(0x00, 0x00), /* 0x2e: */
4021 ISP_FC_OPMAP(0x00, 0x00), /* 0x2f: */
4022 ISP_FC_OPMAP(0x00, 0x00), /* 0x30: */
4023 ISP_FC_OPMAP(0x00, 0x00), /* 0x31: */
4024 ISP_FC_OPMAP(0x4b, 0x4b), /* 0x32: MBOX_SET_TIMEOUT_PARAMS */
4025 ISP_FC_OPMAP(0x00, 0x00), /* 0x33: */
4026 ISP_FC_OPMAP(0x00, 0x00), /* 0x34: */
4027 ISP_FC_OPMAP(0x00, 0x00), /* 0x35: */
4028 ISP_FC_OPMAP(0x00, 0x00), /* 0x36: */
4029 ISP_FC_OPMAP(0x00, 0x00), /* 0x37: */
4030 ISP_FC_OPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
4031 ISP_FC_OPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
4032 ISP_FC_OPMAP(0x00, 0x00), /* 0x3a: */
4033 ISP_FC_OPMAP(0x00, 0x00), /* 0x3b: */
4034 ISP_FC_OPMAP(0x00, 0x00), /* 0x3c: */
4035 ISP_FC_OPMAP(0x00, 0x00), /* 0x3d: */
4036 ISP_FC_OPMAP(0x00, 0x00), /* 0x3e: */
4037 ISP_FC_OPMAP(0x00, 0x00), /* 0x3f: */
4038 ISP_FC_OPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */
4039 ISP_FC_OPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */
4040 ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf), /* 0x42: MBOX_GET_RESOURCE_COUNT */
4041 ISP_FC_OPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */
4042 ISP_FC_OPMAP(0x00, 0x00), /* 0x44: */
4043 ISP_FC_OPMAP(0x00, 0x00), /* 0x45: */
4044 ISP_FC_OPMAP(0x00, 0x00), /* 0x46: */
4045 ISP_FC_OPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */
4046 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
4047 ISP_FC_OPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */
4048 ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
4049 ISP_FC_OPMAP(0x00, 0x00), /* 0x4b: */
4050 ISP_FC_OPMAP(0x00, 0x00), /* 0x4c: */
4051 ISP_FC_OPMAP(0x00, 0x00), /* 0x4d: */
4052 ISP_FC_OPMAP(0x00, 0x00), /* 0x4e: */
4053 ISP_FC_OPMAP(0x00, 0x00), /* 0x4f: */
4054 ISP_FC_OPMAP(0x00, 0x00), /* 0x50: */
4055 ISP_FC_OPMAP(0x00, 0x00), /* 0x51: */
4056 ISP_FC_OPMAP(0x00, 0x00), /* 0x52: */
4057 ISP_FC_OPMAP(0x00, 0x00), /* 0x53: */
4058 ISP_FC_OPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
4059 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */
4060 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */
4061 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */
4062 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */
4063 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */
4064 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */
4065 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
4066 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
4067 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */
4068 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */
4069 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */
4070 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */
4071 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */
4072 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */
4073 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
4074 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
4075 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */
4076 ISP_FC_OPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */
4077 ISP_FC_OPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */
4078 ISP_FC_OPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */
4079 ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f), /* 0x69: MBOX_GET_FW_STATE */
4080 ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */
4081 ISP_FC_OPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */
4082 ISP_FC_OPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */
4083 ISP_FC_OPMAP(0x00, 0x00), /* 0x6d: */
4084 ISP_FC_OPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */
4085 ISP_FC_OPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */
4086 ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03), /* 0x70: MBOX_SEND_CHANGE_REQUEST */
4087 ISP_FC_OPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */
4088 ISP_FC_OPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */
4089 ISP_FC_OPMAP(0x00, 0x00), /* 0x73: */
4090 ISP_FC_OPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */
4091 ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07), /* 0x75: GET PORT/NODE NAME LIST */
4092 ISP_FC_OPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */
4093 ISP_FC_OPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */
4094 ISP_FC_OPMAP(0x00, 0x00), /* 0x78: */
4095 ISP_FC_OPMAP(0x00, 0x00), /* 0x79: */
4096 ISP_FC_OPMAP(0x00, 0x00), /* 0x7a: */
4097 ISP_FC_OPMAP(0x00, 0x00), /* 0x7b: */
4098 ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07), /* 0x7c: Get ID List */
4099 ISP_FC_OPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */
4100 ISP_FC_OPMAP(0x0f, 0x01) /* 0x7e: LUN RESET */
4102 #define MAX_FC_OPCODE 0x7e
4106 * (1): this sets bits 21..16 in mailbox register #8, which we nominally
4107 * do not access at this time in the core driver. The caller is
4108 * responsible for setting this register first (Gross!). The assumption
4109 * is that we won't overflow.
4112 static const char *fc_mbcmd_names[] = {
4126 "WRITE RAM WORD EXTENDED",
4128 "READ RAM WORD EXTENDED",
4129 "INIT REQUEST QUEUE", /* 10h */
4130 "INIT RESULT QUEUE",
4140 "SINGLE STEP QUEUE",
4142 "GET DEV QUEUE STATUS",
4144 "GET FIRMWARE STATUS",
4145 "GET LOOP ID", /* 20h */
4147 "GET TIMEOUT PARAMS",
4153 "GET FIRMWARE OPTIONS",
4154 "GET PORT QUEUE PARAMS",
4155 "GENERATE SYSTEM ERROR",
4161 "WRITE SFP", /* 30h */
4163 "SET TIMEOUT PARAMS",
4169 "SET FIRMWARE OPTIONS",
4170 "SET PORT QUEUE PARAMS",
4174 "RESTART NIC FIRMWARE",
4177 "LOOP PORT BYPASS", /* 40h */
4179 "GET RESOURCE COUNT",
4180 "REQUEST NON PARTICIPATING MODE",
4181 "DIAGNOSTIC ECHO TEST",
4182 "DIAGNOSTIC LOOPBACK",
4184 "GET PORT DATABASE ENHANCED",
4185 "INIT FIRMWARE MULTI ID",
4187 "GET VP DATABASE ENTRY",
4193 "GET FCF LIST", /* 50h */
4194 "GET DCBX PARAMETERS",
4205 "FIRMWARE HEARTBEAT",
4206 "GET/SET DATA RATE",
4209 "INIT FIRMWARE", /* 60h */
4210 "GET INIT CONTROL BLOCK",
4212 "GET FC-AL POSITION MAP",
4213 "GET PORT DATABASE",
4222 "GET LINK STATS & PRIVATE DATA CNTS",
4225 "SEND CHANGE REQUEST", /* 70h */
4230 "GET PORT/NODE NAME LIST",
4232 "INITIALIZE IP MAILBOX",
4243 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
4245 const char *cname, *xname, *sname;
4246 char tname[16], mname[16];
4247 unsigned int ibits, obits, box, opcode, t, to;
4249 opcode = mbp->param[0];
4250 if (opcode > MAX_FC_OPCODE) {
4251 mbp->param[0] = MBOX_INVALID_COMMAND;
4252 isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
4255 cname = fc_mbcmd_names[opcode];
4256 ibits = ISP_FC_IBITS(opcode);
4257 obits = ISP_FC_OBITS(opcode);
4258 if (cname == NULL) {
4260 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
4262 isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname);
4265 * Pick up any additional bits that the caller might have set.
4267 ibits |= mbp->ibits;
4268 obits |= mbp->obits;
4271 * Mask any bits that the caller wants us to mask
4273 ibits &= mbp->ibitm;
4274 obits &= mbp->obitm;
4277 if (ibits == 0 && obits == 0) {
4278 mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
4279 isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
4283 for (box = 0; box < ISP_NMBOX(isp); box++) {
4284 if (ibits & (1 << box)) {
4285 isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
4287 ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
4289 isp->isp_mboxtmp[box] = mbp->param[box] = 0;
4292 isp->isp_lastmbxcmd = opcode;
4293 isp->isp_obits = obits;
4294 isp->isp_mboxbsy = 1;
4297 * Set Host Interrupt condition so that RISC will pick up mailbox regs.
4299 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
4302 * While we haven't finished the command, spin our wheels here.
4304 to = (mbp->timeout == 0) ? MBCMD_DEFAULT_TIMEOUT : mbp->timeout;
4305 for (t = 0; t < to; t += 100) {
4306 if (!isp->isp_mboxbsy)
4309 if (!isp->isp_mboxbsy)
4315 * Did the command time out?
4317 if (isp->isp_mboxbsy) {
4318 isp->isp_mboxbsy = 0;
4319 isp_prt(isp, ISP_LOGWARN, "Mailbox Command (0x%x) Timeout (%uus) (%s:%d)",
4320 isp->isp_lastmbxcmd, to, mbp->func, mbp->lineno);
4321 mbp->param[0] = MBOX_TIMEOUT;
4326 * Copy back output registers.
4328 for (box = 0; box < ISP_NMBOX(isp); box++) {
4329 if (obits & (1 << box)) {
4330 mbp->param[box] = isp->isp_mboxtmp[box];
4331 isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
4337 if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE)
4340 if ((mbp->param[0] & 0xbfe0) == 0 &&
4341 (mbp->logval & MBLOGMASK(mbp->param[0])) == 0)
4346 switch (mbp->param[0]) {
4347 case MBOX_INVALID_COMMAND:
4348 xname = "INVALID COMMAND";
4350 case MBOX_HOST_INTERFACE_ERROR:
4351 xname = "HOST INTERFACE ERROR";
4353 case MBOX_TEST_FAILED:
4354 xname = "TEST FAILED";
4356 case MBOX_COMMAND_ERROR:
4357 xname = "COMMAND ERROR";
4358 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x",
4362 case MBOX_COMMAND_PARAM_ERROR:
4363 xname = "COMMAND PARAMETER ERROR";
4365 case MBOX_PORT_ID_USED:
4366 xname = "PORT ID ALREADY IN USE";
4368 case MBOX_LOOP_ID_USED:
4369 xname = "LOOP ID ALREADY IN USE";
4371 case MBOX_ALL_IDS_USED:
4372 xname = "ALL LOOP IDS IN USE";
4374 case MBOX_NOT_LOGGED_IN:
4375 xname = "NOT LOGGED IN";
4377 case MBOX_LINK_DOWN_ERROR:
4378 xname = "LINK DOWN ERROR";
4380 case MBOX_LOOPBACK_ERROR:
4381 xname = "LOOPBACK ERROR";
4383 case MBOX_CHECKSUM_ERROR:
4384 xname = "CHECKSUM ERROR";
4386 case MBOX_INVALID_PRODUCT_KEY:
4387 xname = "INVALID PRODUCT KEY";
4389 case MBOX_REGS_BUSY:
4390 xname = "REGISTERS BUSY";
4396 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
4401 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)",
4402 cname, xname, sname);
4407 isp_fw_state(ispsoftc_t *isp, int chan)
4411 MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
4412 isp_mboxcmd(isp, &mbs);
4413 if (mbs.param[0] == MBOX_COMMAND_COMPLETE)
4414 return (mbs.param[1]);
4419 isp_setdfltfcparm(ispsoftc_t *isp, int chan)
4421 fcparam *fcp = FCPARAM(isp, chan);
4424 * Establish some default parameters.
4426 fcp->role = DEFAULT_ROLE(isp, chan);
4427 fcp->isp_retry_delay = ICB_DFLT_RDELAY;
4428 fcp->isp_retry_count = ICB_DFLT_RCOUNT;
4429 fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
4430 fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
4431 fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
4432 fcp->isp_fwoptions = 0;
4433 fcp->isp_xfwoptions = 0;
4434 fcp->isp_zfwoptions = 0;
4435 fcp->isp_lasthdl = NIL_HANDLE;
4436 fcp->isp_login_hdl = NIL_HANDLE;
4438 fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
4439 fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
4440 if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
4441 fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
4442 fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
4443 fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP;
4444 fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO;
4447 * Now try and read NVRAM unless told to not do so.
4448 * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
4450 if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
4453 * Give a couple of tries at reading NVRAM.
4455 for (i = 0; i < 2; i++) {
4456 j = isp_read_nvram(isp, chan);
4462 isp->isp_confopts |= ISP_CFG_NONVRAM;
4466 fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
4467 fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
4468 isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
4469 chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
4470 (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
4471 isp_class3_roles[fcp->role]);
4475 * Re-initialize the ISP and complete all orphaned commands
4476 * with a 'botched' notice. The reset/init routines should
4477 * not disturb an already active list of commands.
4481 isp_reinit(ispsoftc_t *isp, int do_load_defaults)
4485 if (isp->isp_state > ISP_RESETSTATE)
4487 if (isp->isp_state != ISP_RESETSTATE)
4488 isp_reset(isp, do_load_defaults);
4489 if (isp->isp_state != ISP_RESETSTATE) {
4491 isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
4496 if (isp->isp_state > ISP_RESETSTATE &&
4497 isp->isp_state != ISP_RUNSTATE) {
4499 isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
4500 ISP_DISABLE_INTS(isp);
4504 isp_clear_commands(isp);
4505 for (i = 0; i < isp->isp_nchan; i++)
4506 isp_clear_portdb(isp, i);
4514 isp_read_nvram(ispsoftc_t *isp, int bus)
4517 return (isp_read_nvram_2400(isp));
4521 isp_read_nvram_2400(ispsoftc_t *isp)
4524 uint32_t addr, csum, lwrds, *dptr;
4525 uint8_t nvram_data[ISP2400_NVRAM_SIZE];
4527 if (isp->isp_port) {
4528 addr = ISP2400_NVRAM_PORT1_ADDR;
4530 addr = ISP2400_NVRAM_PORT0_ADDR;
4533 dptr = (uint32_t *) nvram_data;
4534 for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4535 isp_rd_2400_nvram(isp, addr++, dptr++);
4537 if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
4538 nvram_data[2] != 'P') {
4539 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)",
4540 nvram_data[0], nvram_data[1], nvram_data[2]);
4544 dptr = (uint32_t *) nvram_data;
4545 for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4547 ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
4551 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
4555 isp_parse_nvram_2400(isp, nvram_data);
4561 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
4564 uint32_t base = 0x7ffe0000;
4568 base = 0x7fe7c000; /* XXX: Observation, may be wrong. */
4569 } else if (IS_25XX(isp)) {
4570 base = 0x7ff00000 | 0x48000;
4572 ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
4573 for (loops = 0; loops < 5000; loops++) {
4575 tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
4576 if ((tmp & (1U << 31)) != 0) {
4580 if (tmp & (1U << 31)) {
4581 *rp = ISP_READ(isp, BIU2400_FLASH_DATA);
4582 ISP_SWIZZLE_NVRAM_LONG(isp, rp);
4589 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
4591 fcparam *fcp = FCPARAM(isp, 0);
4594 isp_prt(isp, ISP_LOGDEBUG0,
4595 "NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d",
4596 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
4597 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
4598 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
4599 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
4600 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
4601 isp_prt(isp, ISP_LOGDEBUG0,
4602 "NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
4603 ISP2400_NVRAM_HARDLOOPID(nvram_data),
4604 ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
4605 ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
4606 ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
4608 wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
4609 fcp->isp_wwpn_nvram = wwn;
4611 wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
4613 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
4617 if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
4618 wwn = fcp->isp_wwpn_nvram;
4619 wwn &= ~((uint64_t) 0xfff << 48);
4621 fcp->isp_wwnn_nvram = wwn;
4623 if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
4624 DEFAULT_FRAMESIZE(isp) =
4625 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
4627 if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
4628 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
4630 fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
4631 fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
4632 fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);