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 *);
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_WRITE(isp, BIU2400_REQINP, 0);
267 ISP_WRITE(isp, BIU2400_REQOUTP, 0);
268 ISP_WRITE(isp, BIU2400_RSPINP, 0);
269 ISP_WRITE(isp, BIU2400_RSPOUTP, 0);
271 ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
272 ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
274 ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
275 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
278 * Wait for everything to finish firing up.
280 loops = MBOX_DELAY_COUNT;
281 while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) {
284 isp_prt(isp, ISP_LOGERR, "MBOX_BUSY never cleared on reset");
290 * Up until this point we've done everything by just reading or
291 * setting registers. From this point on we rely on at least *some*
292 * kind of firmware running in the card.
296 * Do some sanity checking by running a NOP command.
297 * If it succeeds, the ROM firmware is now running.
299 MBSINIT(&mbs, MBOX_NO_OP, MBLOGALL, 0);
300 isp_mboxcmd(isp, &mbs);
301 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
302 isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]);
307 * Do some operational tests
310 static const uint16_t patterns[MAX_MAILBOX] = {
311 0x0000, 0xdead, 0xbeef, 0xffff,
312 0xa5a5, 0x5a5a, 0x7f7f, 0x7ff7,
313 0x3421, 0xabcd, 0xdcba, 0xfeef,
314 0xbead, 0xdebe, 0x2222, 0x3333,
315 0x5555, 0x6666, 0x7777, 0xaaaa,
316 0xffff, 0xdddd, 0x9999, 0x1fbc,
317 0x6666, 0x6677, 0x1122, 0x33ff,
318 0x0000, 0x0001, 0x1000, 0x1010,
320 int nmbox = ISP_NMBOX(isp);
321 MBSINIT(&mbs, MBOX_MAILBOX_REG_TEST, MBLOGALL, 0);
322 for (i = 1; i < nmbox; i++) {
323 mbs.param[i] = patterns[i];
325 isp_mboxcmd(isp, &mbs);
326 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
329 for (i = 1; i < nmbox; i++) {
330 if (mbs.param[i] != patterns[i]) {
331 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]);
338 * Download new Firmware, unless requested not to do so.
339 * This is made slightly trickier in some cases where the
340 * firmware of the ROM revision is newer than the revision
341 * compiled into the driver. So, where we used to compare
342 * versions of our f/w and the ROM f/w, now we just see
343 * whether we have f/w at all and whether a config flag
344 * has disabled our download.
346 if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
351 * Set up DMA for the request and response queues.
352 * We do this now so we can use the request queue
353 * for dma to load firmware from.
355 if (ISP_MBOXDMASETUP(isp) != 0) {
356 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
361 code_org = ISP_CODE_ORG_2400;
362 isp->isp_loaded_fw = 0;
364 const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
368 * Keep loading until we run out of f/w.
370 code_org = ptr[2]; /* 1st load address is our start addr */
372 isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
377 while (wi < ptr[3]) {
381 nw = min(wl, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) / 4);
382 cp = isp->isp_rquest;
383 for (i = 0; i < nw; i++)
384 ISP_IOXPUT_32(isp, ptr[wi + i], &cp[i]);
385 MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), -1);
386 MBSINIT(&mbs, MBOX_LOAD_RISC_RAM, MBLOGALL, 0);
388 mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
389 mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
390 mbs.param[4] = nw >> 16;
392 mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
393 mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
394 mbs.param[8] = la >> 16;
395 isp_prt(isp, ISP_LOGDEBUG0, "LOAD RISC RAM %u words at load address 0x%x", nw, la);
396 isp_mboxcmd(isp, &mbs);
397 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
398 isp_prt(isp, ISP_LOGERR, "F/W download failed");
411 isp->isp_loaded_fw = 1;
412 } else if (IS_26XX(isp)) {
413 isp_prt(isp, ISP_LOGDEBUG1, "loading firmware from flash");
414 MBSINIT(&mbs, MBOX_LOAD_FLASH_FIRMWARE, MBLOGALL, 5000000);
417 isp_mboxcmd(isp, &mbs);
418 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
419 isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
423 isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
427 * If we loaded firmware, verify its checksum
429 if (isp->isp_loaded_fw) {
430 MBSINIT(&mbs, MBOX_VERIFY_CHECKSUM, MBLOGNONE, 0);
431 mbs.param[1] = code_org >> 16;
432 mbs.param[2] = code_org;
433 isp_mboxcmd(isp, &mbs);
434 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
435 isp_prt(isp, ISP_LOGERR, dcrc);
441 * Now start it rolling.
443 * If we didn't actually download f/w,
444 * we still need to (re)start it.
446 MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000);
448 mbs.param[1] = code_org >> 16;
449 mbs.param[2] = code_org;
451 mbs.param[1] = code_org >> 16;
452 mbs.param[2] = code_org;
453 if (isp->isp_loaded_fw)
458 isp_mboxcmd(isp, &mbs);
459 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
463 * Ask the chip for the current firmware version.
464 * This should prove that the new firmware is working.
466 MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 5000000);
467 isp_mboxcmd(isp, &mbs);
468 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
472 isp->isp_fwrev[0] = mbs.param[1];
473 isp->isp_fwrev[1] = mbs.param[2];
474 isp->isp_fwrev[2] = mbs.param[3];
475 isp->isp_fwattr = mbs.param[6];
476 isp->isp_fwattr |= ((uint64_t) mbs.param[15]) << 16;
477 if (isp->isp_fwattr & ISP2400_FW_ATTR_EXTNDED) {
479 (((uint64_t) mbs.param[16]) << 32) |
480 (((uint64_t) mbs.param[17]) << 48);
483 isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
484 btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
486 fwt = isp->isp_fwattr;
487 buf = FCPARAM(isp, 0)->isp_scanscratch;
488 ISP_SNPRINTF(buf, ISP_FC_SCRLEN, "Attributes:");
489 if (fwt & ISP2400_FW_ATTR_CLASS2) {
490 fwt ^=ISP2400_FW_ATTR_CLASS2;
491 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s Class2", buf);
493 if (fwt & ISP2400_FW_ATTR_IP) {
494 fwt ^=ISP2400_FW_ATTR_IP;
495 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s IP", buf);
497 if (fwt & ISP2400_FW_ATTR_MULTIID) {
498 fwt ^=ISP2400_FW_ATTR_MULTIID;
499 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MultiID", buf);
501 if (fwt & ISP2400_FW_ATTR_SB2) {
502 fwt ^=ISP2400_FW_ATTR_SB2;
503 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SB2", buf);
505 if (fwt & ISP2400_FW_ATTR_T10CRC) {
506 fwt ^=ISP2400_FW_ATTR_T10CRC;
507 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s T10CRC", buf);
509 if (fwt & ISP2400_FW_ATTR_VI) {
510 fwt ^=ISP2400_FW_ATTR_VI;
511 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VI", buf);
513 if (fwt & ISP2400_FW_ATTR_MQ) {
514 fwt ^=ISP2400_FW_ATTR_MQ;
515 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MQ", buf);
517 if (fwt & ISP2400_FW_ATTR_MSIX) {
518 fwt ^=ISP2400_FW_ATTR_MSIX;
519 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MSIX", buf);
521 if (fwt & ISP2400_FW_ATTR_FCOE) {
522 fwt ^=ISP2400_FW_ATTR_FCOE;
523 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s FCOE", buf);
525 if (fwt & ISP2400_FW_ATTR_VP0) {
526 fwt ^= ISP2400_FW_ATTR_VP0;
527 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VP0_Decoupling", buf);
529 if (fwt & ISP2400_FW_ATTR_EXPFW) {
530 fwt ^= ISP2400_FW_ATTR_EXPFW;
531 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (Experimental)", buf);
533 if (fwt & ISP2400_FW_ATTR_HOTFW) {
534 fwt ^= ISP2400_FW_ATTR_HOTFW;
535 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s HotFW", buf);
537 fwt &= ~ISP2400_FW_ATTR_EXTNDED;
538 if (fwt & ISP2400_FW_ATTR_EXTVP) {
539 fwt ^= ISP2400_FW_ATTR_EXTVP;
540 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ExtVP", buf);
542 if (fwt & ISP2400_FW_ATTR_VN2VN) {
543 fwt ^= ISP2400_FW_ATTR_VN2VN;
544 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VN2VN", buf);
546 if (fwt & ISP2400_FW_ATTR_EXMOFF) {
547 fwt ^= ISP2400_FW_ATTR_EXMOFF;
548 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s EXMOFF", buf);
550 if (fwt & ISP2400_FW_ATTR_NPMOFF) {
551 fwt ^= ISP2400_FW_ATTR_NPMOFF;
552 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s NPMOFF", buf);
554 if (fwt & ISP2400_FW_ATTR_DIFCHOP) {
555 fwt ^= ISP2400_FW_ATTR_DIFCHOP;
556 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s DIFCHOP", buf);
558 if (fwt & ISP2400_FW_ATTR_SRIOV) {
559 fwt ^= ISP2400_FW_ATTR_SRIOV;
560 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SRIOV", buf);
562 if (fwt & ISP2400_FW_ATTR_ASICTMP) {
563 fwt ^= ISP2400_FW_ATTR_ASICTMP;
564 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ASICTMP", buf);
566 if (fwt & ISP2400_FW_ATTR_ATIOMQ) {
567 fwt ^= ISP2400_FW_ATTR_ATIOMQ;
568 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ATIOMQ", buf);
571 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (unknown 0x%08x%08x)", buf,
572 (uint32_t) (fwt >> 32), (uint32_t) fwt);
574 isp_prt(isp, ISP_LOGCONFIG, "%s", buf);
576 MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
577 isp_mboxcmd(isp, &mbs);
578 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
581 isp->isp_maxcmds = mbs.param[3];
582 isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
585 * If we don't have Multi-ID f/w loaded, we need to restrict channels to one.
586 * Only make this check for non-SCSI cards (I'm not sure firmware attributes
589 if (isp->isp_nchan > 1) {
590 if (!ISP_CAP_MULTI_ID(isp)) {
591 isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, "
592 "only can enable 1 of %d channels", isp->isp_nchan);
594 } else if (!ISP_CAP_VP0(isp)) {
595 isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID "
596 "feature properly without VP0_Decoupling");
602 * Final DMA setup after we got isp_maxcmds.
604 if (ISP_MBOXDMASETUP(isp) != 0) {
605 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
612 if (ISP_IRQSETUP(isp) != 0) {
613 isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ");
616 ISP_ENABLE_INTS(isp);
618 for (i = 0; i < isp->isp_nchan; i++)
619 isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
621 isp->isp_state = ISP_RESETSTATE;
624 * We get some default values established. As a side
625 * effect, NVRAM is read here (unless overriden by
626 * a configuration flag).
628 if (do_load_defaults) {
629 for (i = 0; i < isp->isp_nchan; i++)
630 isp_setdfltfcparm(isp, i);
635 * Clean firmware shutdown.
638 isp_stop(ispsoftc_t *isp)
642 isp->isp_state = ISP_NILSTATE;
643 MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000);
652 isp_mboxcmd(isp, &mbs);
653 return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]);
660 isp_shutdown(ispsoftc_t *isp)
663 if (isp->isp_state >= ISP_RESETSTATE)
665 ISP_DISABLE_INTS(isp);
666 ISP_WRITE(isp, BIU2400_ICR, 0);
667 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
671 * Initialize Parameters of Hardware to a known state.
673 * Locks are held before coming here.
676 isp_init(ispsoftc_t *isp)
679 isp_icb_2400_t local, *icbp = &local;
685 * Check to see whether all channels have *some* kind of role
687 for (chan = 0; chan < isp->isp_nchan; chan++) {
688 fcp = FCPARAM(isp, chan);
689 if (fcp->role != ISP_ROLE_NONE) {
693 if (chan == isp->isp_nchan) {
694 isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan);
698 isp->isp_state = ISP_INITSTATE;
701 * Start with channel 0.
703 fcp = FCPARAM(isp, 0);
706 * Turn on LIP F8 async event (1)
708 MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
710 isp_mboxcmd(isp, &mbs);
711 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
715 ISP_MEMZERO(icbp, sizeof (*icbp));
716 icbp->icb_fwoptions1 = fcp->isp_fwoptions;
717 icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
718 icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
719 if (isp->isp_nchan > 1 && ISP_CAP_VP0(isp)) {
720 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
721 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
723 if (fcp->role & ISP_ROLE_TARGET)
724 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
726 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
727 if (fcp->role & ISP_ROLE_INITIATOR)
728 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
730 icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
733 icbp->icb_version = ICB_VERSION1;
734 icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
735 if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
736 isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
737 icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
740 icbp->icb_execthrottle = DEFAULT_EXEC_THROTTLE(isp);
741 if (icbp->icb_execthrottle < 1 && !IS_26XX(isp)) {
742 isp_prt(isp, ISP_LOGERR, "bad execution throttle of %d- using %d", DEFAULT_EXEC_THROTTLE(isp), ICB_DFLT_THROTTLE);
743 icbp->icb_execthrottle = ICB_DFLT_THROTTLE;
747 * Set target exchange count. Take half if we are supporting both roles.
749 if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) {
750 icbp->icb_xchgcnt = isp->isp_maxcmds;
751 if ((icbp->icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE) == 0)
752 icbp->icb_xchgcnt >>= 1;
756 ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
757 icbp->icb_hardaddr = fcp->isp_loopid;
758 if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
759 icbp->icb_hardaddr = 0;
764 icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
766 if (isp->isp_confopts & ISP_CFG_NOFCTAPE) {
767 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
769 if (isp->isp_confopts & ISP_CFG_FCTAPE) {
770 icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE;
773 for (chan = 0; chan < isp->isp_nchan; chan++) {
774 if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE)
775 FCPARAM(isp, chan)->fctape_enabled = 1;
777 FCPARAM(isp, chan)->fctape_enabled = 0;
780 switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
781 case ISP_CFG_LPORT_ONLY:
782 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
783 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY;
785 case ISP_CFG_NPORT_ONLY:
786 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
787 icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
790 /* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */
792 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
793 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
796 /* Let NVRAM settings define it if they are sane */
797 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK) {
798 case ICB2400_OPT2_LOOP_ONLY:
799 case ICB2400_OPT2_PTP_ONLY:
800 case ICB2400_OPT2_LOOP_2_PTP:
803 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
804 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
809 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
810 case ICB2400_OPT2_ZIO:
811 case ICB2400_OPT2_ZIO1:
812 icbp->icb_idelaytimer = 0;
817 isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
818 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
823 /* Use handshake to reduce global lock congestion. */
824 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR;
825 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA;
828 if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) {
829 icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24;
831 if (isp->isp_confopts & ISP_CFG_1GB) {
832 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
833 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB;
834 } else if (isp->isp_confopts & ISP_CFG_2GB) {
835 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
836 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB;
837 } else if (isp->isp_confopts & ISP_CFG_4GB) {
838 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
839 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB;
840 } else if (isp->isp_confopts & ISP_CFG_8GB) {
841 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
842 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB;
843 } else if (isp->isp_confopts & ISP_CFG_16GB) {
844 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
845 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB;
846 } else if (isp->isp_confopts & ISP_CFG_32GB) {
847 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
848 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB;
850 switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) {
851 case ICB2400_OPT3_RATE_4GB:
852 case ICB2400_OPT3_RATE_8GB:
853 case ICB2400_OPT3_RATE_16GB:
854 case ICB2400_OPT3_RATE_32GB:
855 case ICB2400_OPT3_RATE_AUTO:
857 case ICB2400_OPT3_RATE_2GB:
858 if (isp->isp_type <= ISP_HA_FC_2500)
861 case ICB2400_OPT3_RATE_1GB:
862 if (isp->isp_type <= ISP_HA_FC_2400)
866 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
867 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
871 if (ownloopid == 0) {
872 icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
874 icbp->icb_logintime = ICB_LOGIN_TOV;
876 if (fcp->isp_wwnn && fcp->isp_wwpn) {
877 icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
878 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
879 MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
880 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)),
881 ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
882 } else if (fcp->isp_wwpn) {
883 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
884 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
885 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)));
887 isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
890 icbp->icb_retry_count = fcp->isp_retry_count;
892 icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
893 if (icbp->icb_rqstqlen < 8) {
894 isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen);
897 icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
898 if (icbp->icb_rsltqlen < 8) {
899 isp_prt(isp, ISP_LOGERR, "bad result queue length %d",
903 icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
904 icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
905 icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
906 icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
908 icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
909 icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
910 icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
911 icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
913 #ifdef ISP_TARGET_MODE
914 /* unconditionally set up the ATIO queue if we support target mode */
915 icbp->icb_atioqlen = RESULT_QUEUE_LEN(isp);
916 if (icbp->icb_atioqlen < 8) {
917 isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen);
920 icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
921 icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
922 icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
923 icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
924 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
925 DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
928 if (ISP_CAP_MSIX(isp) && isp->isp_nirq >= 2) {
929 icbp->icb_msixresp = 1;
930 if (IS_26XX(isp) && isp->isp_nirq >= 3)
931 icbp->icb_msixatio = 2;
934 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);
936 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),
937 DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
938 DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
940 if (FC_SCRATCH_ACQUIRE(isp, 0)) {
941 isp_prt(isp, ISP_LOGERR, sacq);
944 ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
945 isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
946 if (isp->isp_dblev & ISP_LOGDEBUG1) {
947 isp_print_bytes(isp, "isp_init",
948 sizeof (*icbp), fcp->isp_scratch);
952 * Now fill in information about any additional channels
954 if (isp->isp_nchan > 1) {
955 isp_icb_2400_vpinfo_t vpinfo, *vdst;
956 vp_port_info_t pi, *pdst;
960 vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA;
961 if (ISP_CAP_VP0(isp)) {
962 vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE;
963 vpinfo.vp_count = isp->isp_nchan;
966 vpinfo.vp_count = isp->isp_nchan - 1;
969 off = fcp->isp_scratch;
970 off += ICB2400_VPINFO_OFF;
971 vdst = (isp_icb_2400_vpinfo_t *) off;
972 isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst);
973 amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t);
974 for (; chan < isp->isp_nchan; chan++) {
977 ISP_MEMZERO(&pi, sizeof (pi));
978 fcp2 = FCPARAM(isp, chan);
979 if (fcp2->role != ISP_ROLE_NONE) {
980 pi.vp_port_options = ICB2400_VPOPT_ENABLED |
981 ICB2400_VPOPT_ENA_SNSLOGIN;
982 if (fcp2->role & ISP_ROLE_INITIATOR)
983 pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
984 if ((fcp2->role & ISP_ROLE_TARGET) == 0)
985 pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE;
986 if (fcp2->isp_loopid < LOCAL_LOOP_LIM) {
987 pi.vp_port_loopid = fcp2->isp_loopid;
988 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
989 pi.vp_port_options |= ICB2400_VPOPT_HARD_ADDRESS;
993 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn);
994 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn);
995 off = fcp->isp_scratch;
996 if (ISP_CAP_VP0(isp))
997 off += ICB2400_VPINFO_PORT_OFF(chan);
999 off += ICB2400_VPINFO_PORT_OFF(chan - 1);
1000 pdst = (vp_port_info_t *) off;
1001 isp_put_vp_port_info(isp, &pi, pdst);
1002 amt += ICB2400_VPOPT_WRITE_SIZE;
1004 if (isp->isp_dblev & ISP_LOGDEBUG1) {
1005 isp_print_bytes(isp, "isp_init",
1006 amt - ICB2400_VPINFO_OFF,
1007 (char *)fcp->isp_scratch + ICB2400_VPINFO_OFF);
1014 MBSINIT(&mbs, 0, MBLOGALL, 30000000);
1015 if (isp->isp_nchan > 1) {
1016 mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
1018 mbs.param[0] = MBOX_INIT_FIRMWARE;
1021 mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1022 mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1023 mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1024 mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1025 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));
1026 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp), 0);
1027 isp_mboxcmd(isp, &mbs);
1028 FC_SCRATCH_RELEASE(isp, 0);
1030 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1033 isp->isp_reqidx = 0;
1034 isp->isp_reqodx = 0;
1035 isp->isp_residx = 0;
1036 isp->isp_resodx = 0;
1037 isp->isp_atioodx = 0;
1040 * Whatever happens, we're now committed to being here.
1042 isp->isp_state = ISP_RUNSTATE;
1046 isp_fc_enable_vp(ispsoftc_t *isp, int chan)
1048 fcparam *fcp = FCPARAM(isp, chan);
1051 uint8_t resp[QENTRY_LEN];
1053 /* Build a VP MODIFY command in memory */
1054 ISP_MEMZERO(&vp, sizeof(vp));
1055 vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
1056 vp.vp_mod_hdr.rqs_entry_count = 1;
1058 vp.vp_mod_idx0 = chan;
1059 vp.vp_mod_cmd = VP_MODIFY_ENA;
1060 vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
1061 ICB2400_VPOPT_ENA_SNSLOGIN;
1062 if (fcp->role & ISP_ROLE_INITIATOR)
1063 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
1064 if ((fcp->role & ISP_ROLE_TARGET) == 0)
1065 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
1066 if (fcp->isp_loopid < LOCAL_LOOP_LIM) {
1067 vp.vp_mod_ports[0].loopid = fcp->isp_loopid;
1068 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
1069 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS;
1071 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn);
1072 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn);
1074 /* Prepare space for response in memory */
1075 memset(resp, 0xff, sizeof(resp));
1076 vp.vp_mod_hdl = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1077 if (vp.vp_mod_hdl == 0) {
1078 isp_prt(isp, ISP_LOGERR,
1079 "%s: VP_MODIFY of Chan %d out of handles", __func__, chan);
1083 /* Send request and wait for response. */
1084 reqp = isp_getrqentry(isp);
1086 isp_prt(isp, ISP_LOGERR,
1087 "%s: VP_MODIFY of Chan %d out of rqent", __func__, chan);
1088 isp_destroy_handle(isp, vp.vp_mod_hdl);
1091 isp_put_vp_modify(isp, &vp, (vp_modify_t *)reqp);
1092 if (isp->isp_dblev & ISP_LOGDEBUG1)
1093 isp_print_bytes(isp, "IOCB VP_MODIFY", QENTRY_LEN, reqp);
1094 ISP_SYNC_REQUEST(isp);
1095 if (msleep(resp, &isp->isp_lock, 0, "VP_MODIFY", 5*hz) == EWOULDBLOCK) {
1096 isp_prt(isp, ISP_LOGERR,
1097 "%s: VP_MODIFY of Chan %d timed out", __func__, chan);
1098 isp_destroy_handle(isp, vp.vp_mod_hdl);
1101 if (isp->isp_dblev & ISP_LOGDEBUG1)
1102 isp_print_bytes(isp, "IOCB VP_MODIFY response", QENTRY_LEN, resp);
1103 isp_get_vp_modify(isp, (vp_modify_t *)resp, &vp);
1105 if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) {
1106 isp_prt(isp, ISP_LOGERR,
1107 "%s: VP_MODIFY of Chan %d failed with flags %x status %d",
1108 __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status);
1115 isp_fc_disable_vp(ispsoftc_t *isp, int chan)
1119 uint8_t resp[QENTRY_LEN];
1121 /* Build a VP CTRL command in memory */
1122 ISP_MEMZERO(&vp, sizeof(vp));
1123 vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
1124 vp.vp_ctrl_hdr.rqs_entry_count = 1;
1125 if (ISP_CAP_VP0(isp)) {
1126 vp.vp_ctrl_status = 1;
1128 vp.vp_ctrl_status = 0;
1129 chan--; /* VP0 can not be controlled in this case. */
1131 vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
1132 vp.vp_ctrl_vp_count = 1;
1133 vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
1135 /* Prepare space for response in memory */
1136 memset(resp, 0xff, sizeof(resp));
1137 vp.vp_ctrl_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1138 if (vp.vp_ctrl_handle == 0) {
1139 isp_prt(isp, ISP_LOGERR,
1140 "%s: VP_CTRL of Chan %d out of handles", __func__, chan);
1144 /* Send request and wait for response. */
1145 reqp = isp_getrqentry(isp);
1147 isp_prt(isp, ISP_LOGERR,
1148 "%s: VP_CTRL of Chan %d out of rqent", __func__, chan);
1149 isp_destroy_handle(isp, vp.vp_ctrl_handle);
1152 isp_put_vp_ctrl_info(isp, &vp, (vp_ctrl_info_t *)reqp);
1153 if (isp->isp_dblev & ISP_LOGDEBUG1)
1154 isp_print_bytes(isp, "IOCB VP_CTRL", QENTRY_LEN, reqp);
1155 ISP_SYNC_REQUEST(isp);
1156 if (msleep(resp, &isp->isp_lock, 0, "VP_CTRL", 5*hz) == EWOULDBLOCK) {
1157 isp_prt(isp, ISP_LOGERR,
1158 "%s: VP_CTRL of Chan %d timed out", __func__, chan);
1159 isp_destroy_handle(isp, vp.vp_ctrl_handle);
1162 if (isp->isp_dblev & ISP_LOGDEBUG1)
1163 isp_print_bytes(isp, "IOCB VP_CTRL response", QENTRY_LEN, resp);
1164 isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)resp, &vp);
1166 if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) {
1167 isp_prt(isp, ISP_LOGERR,
1168 "%s: VP_CTRL of Chan %d failed with flags %x status %d %d",
1169 __func__, chan, vp.vp_ctrl_hdr.rqs_flags,
1170 vp.vp_ctrl_status, vp.vp_ctrl_index_fail);
1177 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
1179 fcparam *fcp = FCPARAM(isp, chan);
1180 int i, was, res = 0;
1182 if (chan >= isp->isp_nchan) {
1183 isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan);
1186 if (fcp->role == new_role)
1188 for (was = 0, i = 0; i < isp->isp_nchan; i++) {
1189 if (FCPARAM(isp, i)->role != ISP_ROLE_NONE)
1192 if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) {
1193 fcp->role = new_role;
1194 return (isp_reinit(isp, 0));
1196 if (fcp->role != ISP_ROLE_NONE) {
1197 res = isp_fc_disable_vp(isp, chan);
1198 isp_clear_portdb(isp, chan);
1200 fcp->role = new_role;
1201 if (fcp->role != ISP_ROLE_NONE)
1202 res = isp_fc_enable_vp(isp, chan);
1207 isp_clear_portdb(ispsoftc_t *isp, int chan)
1209 fcparam *fcp = FCPARAM(isp, chan);
1213 for (i = 0; i < MAX_FC_TARG; i++) {
1214 lp = &fcp->portdb[i];
1215 switch (lp->state) {
1216 case FC_PORTDB_STATE_DEAD:
1217 case FC_PORTDB_STATE_CHANGED:
1218 case FC_PORTDB_STATE_VALID:
1219 lp->state = FC_PORTDB_STATE_NIL;
1220 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1222 case FC_PORTDB_STATE_NIL:
1223 case FC_PORTDB_STATE_NEW:
1224 lp->state = FC_PORTDB_STATE_NIL;
1226 case FC_PORTDB_STATE_ZOMBIE:
1229 panic("Don't know how to clear state %d\n", lp->state);
1235 isp_mark_portdb(ispsoftc_t *isp, int chan)
1237 fcparam *fcp = FCPARAM(isp, chan);
1241 for (i = 0; i < MAX_FC_TARG; i++) {
1242 lp = &fcp->portdb[i];
1243 if (lp->state == FC_PORTDB_STATE_NIL)
1245 if (lp->portid >= DOMAIN_CONTROLLER_BASE &&
1246 lp->portid <= DOMAIN_CONTROLLER_END)
1248 fcp->portdb[i].probational = 1;
1253 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
1254 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
1257 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags)
1261 uint8_t resp[QENTRY_LEN];
1262 uint32_t sst, parm1;
1267 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x",
1268 chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ?
1269 "Login":"Logout", portid, handle);
1271 ISP_MEMZERO(&pl, sizeof(pl));
1272 pl.plogx_header.rqs_entry_count = 1;
1273 pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
1274 pl.plogx_nphdl = handle;
1275 pl.plogx_vphdl = chan;
1276 pl.plogx_portlo = portid;
1277 pl.plogx_rspsz_porthi = (portid >> 16) & 0xff;
1278 pl.plogx_flags = flags;
1280 /* Prepare space for response in memory */
1281 memset(resp, 0xff, sizeof(resp));
1282 pl.plogx_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1283 if (pl.plogx_handle == 0) {
1284 isp_prt(isp, ISP_LOGERR,
1285 "%s: PLOGX of Chan %d out of handles", __func__, chan);
1289 /* Send request and wait for response. */
1290 reqp = isp_getrqentry(isp);
1292 isp_prt(isp, ISP_LOGERR,
1293 "%s: PLOGX of Chan %d out of rqent", __func__, chan);
1294 isp_destroy_handle(isp, pl.plogx_handle);
1297 isp_put_plogx(isp, &pl, (isp_plogx_t *)reqp);
1298 if (isp->isp_dblev & ISP_LOGDEBUG1)
1299 isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, reqp);
1300 FCPARAM(isp, chan)->isp_login_hdl = handle;
1301 ISP_SYNC_REQUEST(isp);
1302 if (msleep(resp, &isp->isp_lock, 0, "PLOGX", 3 * ICB_LOGIN_TOV * hz)
1304 isp_prt(isp, ISP_LOGERR,
1305 "%s: PLOGX of Chan %d timed out", __func__, chan);
1306 isp_destroy_handle(isp, pl.plogx_handle);
1309 FCPARAM(isp, chan)->isp_login_hdl = NIL_HANDLE;
1310 if (isp->isp_dblev & ISP_LOGDEBUG1)
1311 isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, resp);
1312 isp_get_plogx(isp, (isp_plogx_t *)resp, &pl);
1314 if (pl.plogx_status == PLOGX_STATUS_OK) {
1316 } else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) {
1317 isp_prt(isp, ISP_LOGWARN,
1318 "status 0x%x on port login IOCB channel %d",
1319 pl.plogx_status, chan);
1323 sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16);
1324 parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16);
1331 case PLOGX_IOCBERR_NOLINK:
1334 case PLOGX_IOCBERR_NOIOCB:
1335 msg = "no IOCB buffer";
1337 case PLOGX_IOCBERR_NOXGHG:
1338 msg = "no Exchange Control Block";
1340 case PLOGX_IOCBERR_FAILED:
1341 ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff);
1344 case PLOGX_IOCBERR_NOFABRIC:
1347 case PLOGX_IOCBERR_NOTREADY:
1348 msg = "firmware not ready";
1350 case PLOGX_IOCBERR_NOLOGIN:
1351 ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1);
1353 rval = MBOX_NOT_LOGGED_IN;
1355 case PLOGX_IOCBERR_REJECT:
1356 ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
1359 case PLOGX_IOCBERR_NOPCB:
1360 msg = "no PCB allocated";
1362 case PLOGX_IOCBERR_EINVAL:
1363 ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1);
1366 case PLOGX_IOCBERR_PORTUSED:
1367 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1368 ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1);
1370 rval = MBOX_PORT_ID_USED | (parm1 << 16);
1372 case PLOGX_IOCBERR_HNDLUSED:
1373 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1374 ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1);
1376 rval = MBOX_LOOP_ID_USED;
1378 case PLOGX_IOCBERR_NOHANDLE:
1379 msg = "no handle allocated";
1381 case PLOGX_IOCBERR_NOFLOGI:
1382 msg = "no FLOGI_ACC";
1385 ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags);
1390 isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
1391 chan, portid, handle, msg);
1397 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb)
1401 isp_pdb_24xx_t bill;
1404 MBSINIT(&mbs, MBOX_GET_PORT_DB,
1405 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000);
1406 mbs.ibits = (1 << 9)|(1 << 10);
1408 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
1409 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
1410 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
1411 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
1412 mbs.param[9] = chan;
1413 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, sizeof(un), chan);
1415 isp_mboxcmd(isp, &mbs);
1416 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
1417 return (mbs.param[0] | (mbs.param[1] << 16));
1419 MEMORYBARRIER(isp, SYNC_IFORCPU, 0, sizeof(un), chan);
1420 isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill);
1421 pdb->handle = un.bill.pdb_handle;
1422 pdb->prli_word0 = un.bill.pdb_prli_svc0;
1423 pdb->prli_word3 = un.bill.pdb_prli_svc3;
1424 pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
1425 ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
1426 ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
1427 isp_prt(isp, ISP_LOGDEBUG0,
1428 "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x",
1429 chan, id, pdb->portid, un.bill.pdb_flags,
1430 un.bill.pdb_curstate, un.bill.pdb_laststate);
1432 if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
1433 mbs.param[0] = MBOX_NOT_LOGGED_IN;
1434 return (mbs.param[0]);
1440 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop)
1442 fcparam *fcp = FCPARAM(isp, chan);
1444 isp_pnhle_24xx_t el4, *elp4;
1448 MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL, 250000);
1449 mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1450 mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1451 mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1452 mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1453 mbs.param[8] = ISP_FC_SCRLEN;
1454 mbs.param[9] = chan;
1455 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1456 isp_prt(isp, ISP_LOGERR, sacq);
1459 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan);
1460 isp_mboxcmd(isp, &mbs);
1461 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1462 FC_SCRATCH_RELEASE(isp, chan);
1463 return (mbs.param[0] | (mbs.param[1] << 16));
1465 MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan);
1466 elp4 = fcp->isp_scratch;
1467 for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) {
1468 isp_get_pnhle_24xx(isp, &elp4[i], &el4);
1469 p = el4.pnhle_port_id_lo | (el4.pnhle_port_id_hi << 16);
1470 if (loop && (p >> 8) != (fcp->isp_portid >> 8))
1472 handles[j++] = el4.pnhle_handle;
1475 FC_SCRATCH_RELEASE(isp, chan);
1480 isp_dump_chip_portdb(ispsoftc_t *isp, int chan)
1485 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan);
1486 for (nphdl = 0; nphdl != NPH_MAX_2K; nphdl++) {
1487 if (isp_getpdb(isp, chan, nphdl, &pdb)) {
1490 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x "
1491 "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
1492 chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1],
1493 pdb.portname[2], pdb.portname[3], pdb.portname[4],
1494 pdb.portname[5], pdb.portname[6], pdb.portname[7]);
1499 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename)
1501 uint64_t wwn = INI_NONE;
1504 MBSINIT(&mbs, MBOX_GET_PORT_NAME,
1505 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
1506 mbs.param[1] = nphdl;
1509 mbs.param[9] = chan;
1510 isp_mboxcmd(isp, &mbs);
1511 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1514 wwn = (((uint64_t)(mbs.param[2] >> 8)) << 56) |
1515 (((uint64_t)(mbs.param[2] & 0xff))<< 48) |
1516 (((uint64_t)(mbs.param[3] >> 8)) << 40) |
1517 (((uint64_t)(mbs.param[3] & 0xff))<< 32) |
1518 (((uint64_t)(mbs.param[6] >> 8)) << 24) |
1519 (((uint64_t)(mbs.param[6] & 0xff))<< 16) |
1520 (((uint64_t)(mbs.param[7] >> 8)) << 8) |
1521 (((uint64_t)(mbs.param[7] & 0xff)));
1526 * Make sure we have good FC link.
1530 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
1536 NANOTIME_T hra, hrb;
1538 fcp = FCPARAM(isp, chan);
1540 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1542 if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
1545 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
1548 * Wait up to N microseconds for F/W to go to a ready state.
1552 isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
1553 if (fcp->isp_fwstate == FW_READY) {
1556 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1559 if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
1561 ISP_SLEEP(isp, 1000);
1563 if (fcp->isp_fwstate != FW_READY) {
1564 isp_prt(isp, ISP_LOG_SANCFG,
1565 "Chan %d Firmware is not ready (%s)",
1566 chan, isp_fc_fw_statename(fcp->isp_fwstate));
1571 * Get our Loop ID and Port ID.
1573 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
1574 mbs.param[9] = chan;
1575 isp_mboxcmd(isp, &mbs);
1576 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1580 topo = (int) mbs.param[6];
1581 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
1582 topo = TOPO_PTP_STUB;
1583 fcp->isp_topo = topo;
1584 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
1586 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
1587 fcp->isp_loopid = mbs.param[1] & 0xff;
1588 } else if (fcp->isp_topo != TOPO_F_PORT) {
1589 uint8_t alpa = fcp->isp_portid;
1591 for (i = 0; alpa_map[i]; i++) {
1592 if (alpa_map[i] == alpa)
1596 fcp->isp_loopid = i;
1600 fcp->isp_loopstate = LOOP_HAVE_ADDR;
1602 fcp->isp_loopstate = LOOP_TESTING_LINK;
1604 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
1605 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
1606 if (r != 0 || pdb.portid == 0) {
1607 isp_prt(isp, ISP_LOGWARN,
1608 "fabric topology, but cannot get info about fabric controller (0x%x)", r);
1609 fcp->isp_topo = TOPO_PTP_STUB;
1613 fcp->isp_fabric_params = mbs.param[7];
1614 fcp->isp_sns_hdl = NPH_SNS_ID;
1615 r = isp_register_fc4_type(isp, chan);
1616 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1620 r = isp_register_fc4_features_24xx(isp, chan);
1621 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1625 r = isp_register_port_name_24xx(isp, chan);
1626 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1630 isp_register_node_name_24xx(isp, chan);
1631 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1636 /* Get link speed. */
1637 fcp->isp_gbspeed = 1;
1638 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
1639 mbs.param[1] = MBGSD_GET_RATE;
1640 /* mbs.param[2] undefined if we're just getting rate */
1641 isp_mboxcmd(isp, &mbs);
1642 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
1643 if (mbs.param[1] == MBGSD_10GB)
1644 fcp->isp_gbspeed = 10;
1645 else if (mbs.param[1] == MBGSD_32GB)
1646 fcp->isp_gbspeed = 32;
1647 else if (mbs.param[1] == MBGSD_16GB)
1648 fcp->isp_gbspeed = 16;
1649 else if (mbs.param[1] == MBGSD_8GB)
1650 fcp->isp_gbspeed = 8;
1651 else if (mbs.param[1] == MBGSD_4GB)
1652 fcp->isp_gbspeed = 4;
1653 else if (mbs.param[1] == MBGSD_2GB)
1654 fcp->isp_gbspeed = 2;
1655 else if (mbs.param[1] == MBGSD_1GB)
1656 fcp->isp_gbspeed = 1;
1659 if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
1661 isp_prt(isp, ISP_LOG_SANCFG,
1662 "Chan %d FC link test aborted", chan);
1665 fcp->isp_loopstate = LOOP_LTEST_DONE;
1666 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1667 "Chan %d WWPN %016jx WWNN %016jx",
1668 chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn);
1669 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1670 "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x",
1671 chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid,
1673 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
1678 * Complete the synchronization of our Port Database.
1680 * At this point, we've scanned the local loop (if any) and the fabric
1681 * and performed fabric logins on all new devices.
1683 * Our task here is to go through our port database removing any entities
1684 * that are still marked probational (issuing PLOGO for ones which we had
1685 * PLOGI'd into) or are dead, and notifying upper layers about new/changed
1689 isp_pdb_sync(ispsoftc_t *isp, int chan)
1691 fcparam *fcp = FCPARAM(isp, chan);
1695 if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
1697 if (fcp->isp_loopstate >= LOOP_READY)
1700 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
1702 fcp->isp_loopstate = LOOP_SYNCING_PDB;
1704 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
1705 lp = &fcp->portdb[dbidx];
1707 if (lp->state == FC_PORTDB_STATE_NIL)
1709 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE)
1710 lp->state = FC_PORTDB_STATE_DEAD;
1711 switch (lp->state) {
1712 case FC_PORTDB_STATE_DEAD:
1713 lp->state = FC_PORTDB_STATE_NIL;
1714 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1715 if ((lp->portid & 0xffff00) != 0) {
1716 (void) isp_plogx(isp, chan, lp->handle,
1718 PLOGX_FLG_CMD_LOGO |
1719 PLOGX_FLG_IMPLICIT |
1720 PLOGX_FLG_FREE_NPHDL);
1723 * Note that we might come out of this with our state
1724 * set to FC_PORTDB_STATE_ZOMBIE.
1727 case FC_PORTDB_STATE_NEW:
1728 lp->state = FC_PORTDB_STATE_VALID;
1729 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
1731 case FC_PORTDB_STATE_CHANGED:
1732 lp->state = FC_PORTDB_STATE_VALID;
1733 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
1734 lp->portid = lp->new_portid;
1735 lp->prli_word0 = lp->new_prli_word0;
1736 lp->prli_word3 = lp->new_prli_word3;
1738 case FC_PORTDB_STATE_VALID:
1739 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
1741 case FC_PORTDB_STATE_ZOMBIE:
1744 isp_prt(isp, ISP_LOGWARN,
1745 "isp_pdb_sync: state %d for idx %d",
1747 isp_dump_portdb(isp, chan);
1751 if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
1752 isp_prt(isp, ISP_LOG_SANCFG,
1753 "Chan %d FC PDB sync aborted", chan);
1757 fcp->isp_loopstate = LOOP_READY;
1758 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
1763 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
1766 uint64_t wwnn, wwpn;
1768 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
1769 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
1771 /* Search port database for the same WWPN. */
1772 if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) {
1773 if (!lp->probational) {
1774 isp_prt(isp, ISP_LOGERR,
1775 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
1776 chan, lp->portid, lp->handle,
1777 FC_PORTDB_TGT(isp, chan, lp), lp->state);
1778 isp_dump_portdb(isp, chan);
1781 lp->probational = 0;
1782 lp->node_wwn = wwnn;
1784 /* Old device, nothing new. */
1785 if (lp->portid == pdb->portid &&
1786 lp->handle == pdb->handle &&
1787 lp->prli_word3 == pdb->prli_word3 &&
1788 ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) ==
1789 (lp->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR))) {
1790 if (lp->state != FC_PORTDB_STATE_NEW)
1791 lp->state = FC_PORTDB_STATE_VALID;
1792 isp_prt(isp, ISP_LOG_SANCFG,
1793 "Chan %d Port 0x%06x@0x%04x is valid",
1794 chan, pdb->portid, pdb->handle);
1798 /* Something has changed. */
1799 lp->state = FC_PORTDB_STATE_CHANGED;
1800 lp->handle = pdb->handle;
1801 lp->new_portid = pdb->portid;
1802 lp->new_prli_word0 = pdb->prli_word0;
1803 lp->new_prli_word3 = pdb->prli_word3;
1804 isp_prt(isp, ISP_LOG_SANCFG,
1805 "Chan %d Port 0x%06x@0x%04x is changed",
1806 chan, pdb->portid, pdb->handle);
1810 /* It seems like a new port. Find an empty slot for it. */
1811 if (!isp_find_pdb_empty(isp, chan, &lp)) {
1812 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan);
1816 ISP_MEMZERO(lp, sizeof (fcportdb_t));
1817 lp->probational = 0;
1818 lp->state = FC_PORTDB_STATE_NEW;
1819 lp->portid = lp->new_portid = pdb->portid;
1820 lp->prli_word0 = lp->new_prli_word0 = pdb->prli_word0;
1821 lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3;
1822 lp->handle = pdb->handle;
1823 lp->port_wwn = wwpn;
1824 lp->node_wwn = wwnn;
1825 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new",
1826 chan, pdb->portid, pdb->handle);
1830 * Scan local loop for devices.
1833 isp_scan_loop(ispsoftc_t *isp, int chan)
1835 fcparam *fcp = FCPARAM(isp, chan);
1841 if (fcp->isp_loopstate < LOOP_LTEST_DONE)
1843 if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
1846 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
1847 fcp->isp_loopstate = LOOP_SCANNING_LOOP;
1848 if (TOPO_IS_FABRIC(fcp->isp_topo)) {
1849 isp_prt(isp, ISP_LOG_SANCFG,
1850 "Chan %d FC loop scan done (no loop)", chan);
1851 fcp->isp_loopstate = LOOP_LSCAN_DONE;
1855 handles = (uint16_t *)fcp->isp_scanscratch;
1856 lim = ISP_FC_SCRLEN / 2;
1857 r = isp_gethandles(isp, chan, handles, &lim, 1);
1859 isp_prt(isp, ISP_LOG_SANCFG,
1860 "Chan %d Getting list of handles failed with %x", chan, r);
1861 isp_prt(isp, ISP_LOG_SANCFG,
1862 "Chan %d FC loop scan done (bad)", chan);
1866 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
1870 * Run through the list and get the port database info for each one.
1872 isp_mark_portdb(isp, chan);
1873 for (idx = 0; idx < lim; idx++) {
1874 handle = handles[idx];
1877 * Don't scan "special" ids.
1879 if (handle >= NPH_RESERVED)
1883 * Get the port database entity for this index.
1885 r = isp_getpdb(isp, chan, handle, &pdb);
1886 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
1888 isp_prt(isp, ISP_LOG_SANCFG,
1889 "Chan %d FC loop scan aborted", chan);
1893 isp_prt(isp, ISP_LOGDEBUG1,
1894 "Chan %d FC Scan Loop handle %d returned %x",
1899 isp_pdb_add_update(isp, chan, &pdb);
1901 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
1903 fcp->isp_loopstate = LOOP_LSCAN_DONE;
1904 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
1909 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
1911 fcparam *fcp = FCPARAM(isp, chan);
1914 uint8_t resp[QENTRY_LEN];
1916 if (isp->isp_dblev & ISP_LOGDEBUG1)
1917 isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch);
1920 * Build a Passthrough IOCB in memory.
1922 ISP_MEMZERO(&pt, sizeof(pt));
1923 pt.ctp_header.rqs_entry_count = 1;
1924 pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
1925 pt.ctp_nphdl = fcp->isp_sns_hdl;
1927 pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
1930 pt.ctp_rsp_bcnt = rsp_bcnt;
1931 pt.ctp_cmd_bcnt = cmd_bcnt;
1932 pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma);
1933 pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma);
1934 pt.ctp_dataseg[0].ds_count = cmd_bcnt;
1935 pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
1936 pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
1937 pt.ctp_dataseg[1].ds_count = rsp_bcnt;
1939 /* Prepare space for response in memory */
1940 memset(resp, 0xff, sizeof(resp));
1941 pt.ctp_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
1942 if (pt.ctp_handle == 0) {
1943 isp_prt(isp, ISP_LOGERR,
1944 "%s: CTP of Chan %d out of handles", __func__, chan);
1948 /* Send request and wait for response. */
1949 reqp = isp_getrqentry(isp);
1951 isp_prt(isp, ISP_LOGERR,
1952 "%s: CTP of Chan %d out of rqent", __func__, chan);
1953 isp_destroy_handle(isp, pt.ctp_handle);
1956 isp_put_ct_pt(isp, &pt, (isp_ct_pt_t *)reqp);
1957 if (isp->isp_dblev & ISP_LOGDEBUG1)
1958 isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, reqp);
1959 ISP_SYNC_REQUEST(isp);
1960 if (msleep(resp, &isp->isp_lock, 0, "CTP", pt.ctp_time*hz) == EWOULDBLOCK) {
1961 isp_prt(isp, ISP_LOGERR,
1962 "%s: CTP of Chan %d timed out", __func__, chan);
1963 isp_destroy_handle(isp, pt.ctp_handle);
1966 if (isp->isp_dblev & ISP_LOGDEBUG1)
1967 isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, resp);
1969 isp_get_ct_pt(isp, (isp_ct_pt_t *)resp, &pt);
1970 if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
1971 isp_prt(isp, ISP_LOGWARN,
1972 "Chan %d CT pass-through returned 0x%x",
1973 chan, pt.ctp_status);
1977 if (isp->isp_dblev & ISP_LOGDEBUG1)
1978 isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch);
1984 * Scan the fabric for devices and add them to our port database.
1986 * Use the GID_PT command to get list of all Nx_Port IDs SNS knows.
1987 * Use GFF_ID and GFT_ID to check port type (FCP) and features (target).
1989 * We use CT Pass-through IOCB.
1991 #define GIDLEN ISP_FC_SCRLEN
1992 #define NGENT ((GIDLEN - 16) >> 2)
1995 isp_gid_pt(ispsoftc_t *isp, int chan)
1997 fcparam *fcp = FCPARAM(isp, chan);
1999 uint8_t *scp = fcp->isp_scratch;
2001 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan);
2002 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2003 isp_prt(isp, ISP_LOGERR, sacq);
2007 /* Build the CT command and execute via pass-through. */
2008 ISP_MEMZERO(&ct, sizeof (ct));
2009 ct.ct_revision = CT_REVISION;
2010 ct.ct_fcs_type = CT_FC_TYPE_FC;
2011 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2012 ct.ct_cmd_resp = SNS_GID_PT;
2013 ct.ct_bcnt_resid = (GIDLEN - 16) >> 2;
2014 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2015 scp[sizeof(ct)] = 0x7f; /* Port Type = Nx_Port */
2016 scp[sizeof(ct)+1] = 0; /* Domain_ID = any */
2017 scp[sizeof(ct)+2] = 0; /* Area_ID = any */
2018 scp[sizeof(ct)+3] = 0; /* Flags = no Area_ID */
2020 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) {
2021 FC_SCRATCH_RELEASE(isp, chan);
2025 isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp,
2026 (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT);
2027 FC_SCRATCH_RELEASE(isp, chan);
2032 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid)
2034 fcparam *fcp = FCPARAM(isp, chan);
2037 uint8_t *scp = fcp->isp_scratch;
2038 sns_gff_id_rsp_t rsp;
2041 if (!fcp->isp_use_gff_id) /* User may block GFF_ID use. */
2044 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan);
2045 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2046 isp_prt(isp, ISP_LOGERR, sacq);
2050 /* Build the CT command and execute via pass-through. */
2051 ISP_MEMZERO(&ct, sizeof (ct));
2052 ct.ct_revision = CT_REVISION;
2053 ct.ct_fcs_type = CT_FC_TYPE_FC;
2054 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2055 ct.ct_cmd_resp = SNS_GFF_ID;
2056 ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4;
2057 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2058 rp = (uint32_t *) &scp[sizeof(ct)];
2059 ISP_IOZPUT_32(isp, portid, rp);
2061 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
2062 SNS_GFF_ID_RESP_SIZE)) {
2063 FC_SCRATCH_RELEASE(isp, chan);
2067 isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp);
2068 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
2069 for (i = 0; i < 32; i++) {
2070 if (rsp.snscb_fc4_features[i] != 0) {
2075 if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >>
2076 ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
2078 /* Workaround for broken Brocade firmware. */
2079 if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >>
2080 ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
2083 FC_SCRATCH_RELEASE(isp, chan);
2084 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res);
2089 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid)
2091 fcparam *fcp = FCPARAM(isp, chan);
2094 uint8_t *scp = fcp->isp_scratch;
2095 sns_gft_id_rsp_t rsp;
2098 if (!fcp->isp_use_gft_id) /* User may block GFT_ID use. */
2101 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan);
2102 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2103 isp_prt(isp, ISP_LOGERR, sacq);
2107 /* Build the CT command and execute via pass-through. */
2108 ISP_MEMZERO(&ct, sizeof (ct));
2109 ct.ct_revision = CT_REVISION;
2110 ct.ct_fcs_type = CT_FC_TYPE_FC;
2111 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2112 ct.ct_cmd_resp = SNS_GFT_ID;
2113 ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4;
2114 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2115 rp = (uint32_t *) &scp[sizeof(ct)];
2116 ISP_IOZPUT_32(isp, portid, rp);
2118 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
2119 SNS_GFT_ID_RESP_SIZE)) {
2120 FC_SCRATCH_RELEASE(isp, chan);
2124 isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp);
2125 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
2126 for (i = 0; i < 8; i++) {
2127 if (rsp.snscb_fc4_types[i] != 0) {
2132 if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >>
2133 (FC4_SCSI % 32)) & 0x01) != 0)
2136 FC_SCRATCH_RELEASE(isp, chan);
2137 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res);
2142 isp_scan_fabric(ispsoftc_t *isp, int chan)
2144 fcparam *fcp = FCPARAM(isp, chan);
2148 int portidx, portlim, r;
2149 sns_gid_xx_rsp_t *rs;
2151 if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
2153 if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
2156 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
2157 fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
2158 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
2159 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2160 isp_prt(isp, ISP_LOG_SANCFG,
2161 "Chan %d FC fabric scan done (no fabric)", chan);
2165 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
2167 FC_SCRATCH_RELEASE(isp, chan);
2168 isp_prt(isp, ISP_LOG_SANCFG,
2169 "Chan %d FC fabric scan aborted", chan);
2174 * Make sure we still are logged into the fabric controller.
2176 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
2177 if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) {
2178 isp_dump_chip_portdb(isp, chan);
2181 fcp->isp_loopstate = LOOP_LTEST_DONE;
2183 isp_prt(isp, ISP_LOG_SANCFG,
2184 "Chan %d FC fabric scan done (bad)", chan);
2188 /* Get list of port IDs from SNS. */
2189 r = isp_gid_pt(isp, chan);
2190 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2193 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2196 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
2200 rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch;
2201 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2203 if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) {
2205 /* FC-4 Type and Port Type not registered are not errors. */
2206 if (rs->snscb_cthdr.ct_reason == 9 &&
2207 (rs->snscb_cthdr.ct_explanation == 0x07 ||
2208 rs->snscb_cthdr.ct_explanation == 0x0a)) {
2209 level = ISP_LOG_SANCFG;
2211 level = ISP_LOGWARN;
2213 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT"
2214 " (Reason=0x%x Expl=0x%x)", chan,
2215 rs->snscb_cthdr.ct_reason,
2216 rs->snscb_cthdr.ct_explanation);
2217 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2221 /* Check our buffer was big enough to get the full list. */
2222 for (portidx = 0; portidx < NGENT-1; portidx++) {
2223 if (rs->snscb_ports[portidx].control & 0x80)
2226 if ((rs->snscb_ports[portidx].control & 0x80) == 0) {
2227 isp_prt(isp, ISP_LOGWARN,
2228 "fabric too big for scratch area: increase ISP_FC_SCRLEN");
2230 portlim = portidx + 1;
2231 isp_prt(isp, ISP_LOG_SANCFG,
2232 "Chan %d Got %d ports back from name server", chan, portlim);
2234 /* Go through the list and remove duplicate port ids. */
2235 for (portidx = 0; portidx < portlim; portidx++) {
2239 ((rs->snscb_ports[portidx].portid[0]) << 16) |
2240 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2241 ((rs->snscb_ports[portidx].portid[2]));
2243 for (npidx = portidx + 1; npidx < portlim; npidx++) {
2244 uint32_t new_portid =
2245 ((rs->snscb_ports[npidx].portid[0]) << 16) |
2246 ((rs->snscb_ports[npidx].portid[1]) << 8) |
2247 ((rs->snscb_ports[npidx].portid[2]));
2248 if (new_portid == portid) {
2253 if (npidx < portlim) {
2254 rs->snscb_ports[npidx].portid[0] = 0;
2255 rs->snscb_ports[npidx].portid[1] = 0;
2256 rs->snscb_ports[npidx].portid[2] = 0;
2257 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid);
2262 * We now have a list of Port IDs for all FC4 SCSI devices
2263 * that the Fabric Name server knows about.
2265 * For each entry on this list go through our port database looking
2266 * for probational entries- if we find one, then an old entry is
2267 * maybe still this one. We get some information to find out.
2269 * Otherwise, it's a new fabric device, and we log into it
2270 * (unconditionally). After searching the entire database
2271 * again to make sure that we never ever ever ever have more
2272 * than one entry that has the same PortID or the same
2273 * WWNN/WWPN duple, we enter the device into our database.
2275 isp_mark_portdb(isp, chan);
2276 for (portidx = 0; portidx < portlim; portidx++) {
2277 portid = ((rs->snscb_ports[portidx].portid[0]) << 16) |
2278 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2279 ((rs->snscb_ports[portidx].portid[2]));
2280 isp_prt(isp, ISP_LOG_SANCFG,
2281 "Chan %d Checking fabric port 0x%06x", chan, portid);
2283 isp_prt(isp, ISP_LOG_SANCFG,
2284 "Chan %d Port at idx %d is zero",
2288 if (portid == fcp->isp_portid) {
2289 isp_prt(isp, ISP_LOG_SANCFG,
2290 "Chan %d Port 0x%06x is our", chan, portid);
2294 /* Now search the entire port database for the same portid. */
2295 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) {
2296 if (!lp->probational) {
2297 isp_prt(isp, ISP_LOGERR,
2298 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
2299 chan, lp->portid, lp->handle,
2300 FC_PORTDB_TGT(isp, chan, lp), lp->state);
2301 isp_dump_portdb(isp, chan);
2305 if (lp->state == FC_PORTDB_STATE_ZOMBIE)
2309 * See if we're still logged into it.
2311 * If we aren't, mark it as a dead device and
2312 * leave the new portid in the database entry
2313 * for somebody further along to decide what to
2314 * do (policy choice).
2316 * If we are, check to see if it's the same
2317 * device still (it should be). If for some
2318 * reason it isn't, mark it as a changed device
2319 * and leave the new portid and role in the
2320 * database entry for somebody further along to
2321 * decide what to do (policy choice).
2323 r = isp_getpdb(isp, chan, lp->handle, &pdb);
2324 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2327 lp->state = FC_PORTDB_STATE_DEAD;
2328 isp_prt(isp, ISP_LOG_SANCFG,
2329 "Chan %d Port 0x%06x handle 0x%x is dead (%d)",
2330 chan, portid, lp->handle, r);
2334 isp_pdb_add_update(isp, chan, &pdb);
2339 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2340 isp_prt(isp, ISP_LOG_SANCFG,
2341 "Chan %d Port 0x%06x is not logged in", chan, portid);
2345 r = isp_gff_id(isp, chan, portid);
2347 isp_prt(isp, ISP_LOG_SANCFG,
2348 "Chan %d Port 0x%06x is not an FCP target", chan, portid);
2352 r = isp_gft_id(isp, chan, portid);
2354 isp_prt(isp, ISP_LOG_SANCFG,
2355 "Chan %d Port 0x%06x is not FCP", chan, portid);
2359 if (isp_login_device(isp, chan, portid, &pdb,
2360 &FCPARAM(isp, 0)->isp_lasthdl)) {
2361 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2366 isp_pdb_add_update(isp, chan, &pdb);
2369 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2371 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2372 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
2377 * Find an unused handle and try and use to login to a port.
2380 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
2385 handle = isp_next_handle(isp, ohp);
2386 for (i = 0; i < NPH_MAX_2K; i++) {
2387 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2390 /* Check if this handle is free. */
2391 r = isp_getpdb(isp, chan, handle, p);
2393 if (p->portid != portid) {
2394 /* This handle is busy, try next one. */
2395 handle = isp_next_handle(isp, ohp);
2400 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2404 * Now try and log into the device
2406 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2409 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
2411 * If we get here, then the firmwware still thinks we're logged into this device, but with a different
2412 * handle. We need to break that association. We used to try and just substitute the handle, but then
2413 * failed to get any data via isp_getpdb (below).
2415 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) {
2416 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
2418 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2420 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2424 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
2425 /* Try the next handle. */
2426 handle = isp_next_handle(isp, ohp);
2434 if (i == NPH_MAX_2K) {
2435 isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid);
2440 * If we successfully logged into it, get the PDB for it
2441 * so we can crosscheck that it is still what we think it
2442 * is and that we also have the role it plays
2444 r = isp_getpdb(isp, chan, handle, p);
2446 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
2450 if (p->handle != handle || p->portid != portid) {
2451 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
2452 chan, portid, handle, p->portid, p->handle);
2459 isp_register_fc4_type(ispsoftc_t *isp, int chan)
2461 fcparam *fcp = FCPARAM(isp, chan);
2463 ct_hdr_t *ct = &rp.rftid_hdr;
2464 uint8_t *scp = fcp->isp_scratch;
2466 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2467 isp_prt(isp, ISP_LOGERR, sacq);
2471 /* Build the CT command and execute via pass-through. */
2472 ISP_MEMZERO(&rp, sizeof(rp));
2473 ct->ct_revision = CT_REVISION;
2474 ct->ct_fcs_type = CT_FC_TYPE_FC;
2475 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2476 ct->ct_cmd_resp = SNS_RFT_ID;
2477 ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2;
2478 rp.rftid_portid[0] = fcp->isp_portid >> 16;
2479 rp.rftid_portid[1] = fcp->isp_portid >> 8;
2480 rp.rftid_portid[2] = fcp->isp_portid;
2481 rp.rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
2482 isp_put_rft_id(isp, &rp, (rft_id_t *)scp);
2484 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2485 FC_SCRATCH_RELEASE(isp, chan);
2489 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2490 FC_SCRATCH_RELEASE(isp, chan);
2491 if (ct->ct_cmd_resp == LS_RJT) {
2492 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "Chan %d Register FC4 Type rejected", chan);
2494 } else if (ct->ct_cmd_resp == LS_ACC) {
2495 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan);
2497 isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp);
2504 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
2506 fcparam *fcp = FCPARAM(isp, chan);
2509 uint8_t *scp = fcp->isp_scratch;
2511 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2512 isp_prt(isp, ISP_LOGERR, sacq);
2517 * Build the CT header and command in memory.
2519 ISP_MEMZERO(&rp, sizeof(rp));
2521 ct->ct_revision = CT_REVISION;
2522 ct->ct_fcs_type = CT_FC_TYPE_FC;
2523 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2524 ct->ct_cmd_resp = SNS_RFF_ID;
2525 ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2;
2526 rp.rffid_portid[0] = fcp->isp_portid >> 16;
2527 rp.rffid_portid[1] = fcp->isp_portid >> 8;
2528 rp.rffid_portid[2] = fcp->isp_portid;
2529 rp.rffid_fc4features = 0;
2530 if (fcp->role & ISP_ROLE_TARGET)
2531 rp.rffid_fc4features |= 1;
2532 if (fcp->role & ISP_ROLE_INITIATOR)
2533 rp.rffid_fc4features |= 2;
2534 rp.rffid_fc4type = FC4_SCSI;
2535 isp_put_rff_id(isp, &rp, (rff_id_t *)scp);
2536 if (isp->isp_dblev & ISP_LOGDEBUG1)
2537 isp_print_bytes(isp, "CT request", sizeof(rft_id_t), scp);
2539 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2540 FC_SCRATCH_RELEASE(isp, chan);
2544 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2545 FC_SCRATCH_RELEASE(isp, chan);
2546 if (ct->ct_cmd_resp == LS_RJT) {
2547 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2548 "Chan %d Register FC4 Features rejected", chan);
2550 } else if (ct->ct_cmd_resp == LS_ACC) {
2551 isp_prt(isp, ISP_LOG_SANCFG,
2552 "Chan %d Register FC4 Features accepted", chan);
2554 isp_prt(isp, ISP_LOGWARN,
2555 "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
2562 isp_register_port_name_24xx(ispsoftc_t *isp, int chan)
2564 fcparam *fcp = FCPARAM(isp, chan);
2567 uint8_t *scp = fcp->isp_scratch;
2570 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2571 isp_prt(isp, ISP_LOGERR, sacq);
2576 * Build the CT header and command in memory.
2578 ISP_MEMZERO(&rp, sizeof(rp));
2579 ct = &rp.rspnid_hdr;
2580 ct->ct_revision = CT_REVISION;
2581 ct->ct_fcs_type = CT_FC_TYPE_FC;
2582 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2583 ct->ct_cmd_resp = SNS_RSPN_ID;
2584 rp.rspnid_portid[0] = fcp->isp_portid >> 16;
2585 rp.rspnid_portid[1] = fcp->isp_portid >> 8;
2586 rp.rspnid_portid[2] = fcp->isp_portid;
2587 rp.rspnid_length = 0;
2588 len = offsetof(rspn_id_t, rspnid_name);
2589 mtx_lock(&prison0.pr_mtx);
2590 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2591 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2592 mtx_unlock(&prison0.pr_mtx);
2593 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2594 ":%s", device_get_nameunit(isp->isp_dev));
2596 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2599 len += rp.rspnid_length;
2600 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2601 isp_put_rspn_id(isp, &rp, (rspn_id_t *)scp);
2603 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2604 FC_SCRATCH_RELEASE(isp, chan);
2608 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2609 FC_SCRATCH_RELEASE(isp, chan);
2610 if (ct->ct_cmd_resp == LS_RJT) {
2611 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2612 "Chan %d Register Symbolic Port Name rejected", chan);
2614 } else if (ct->ct_cmd_resp == LS_ACC) {
2615 isp_prt(isp, ISP_LOG_SANCFG,
2616 "Chan %d Register Symbolic Port Name accepted", chan);
2618 isp_prt(isp, ISP_LOGWARN,
2619 "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp);
2626 isp_register_node_name_24xx(ispsoftc_t *isp, int chan)
2628 fcparam *fcp = FCPARAM(isp, chan);
2631 uint8_t *scp = fcp->isp_scratch;
2634 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2635 isp_prt(isp, ISP_LOGERR, sacq);
2640 * Build the CT header and command in memory.
2642 ISP_MEMZERO(&rp, sizeof(rp));
2643 ct = &rp.rsnnnn_hdr;
2644 ct->ct_revision = CT_REVISION;
2645 ct->ct_fcs_type = CT_FC_TYPE_FC;
2646 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2647 ct->ct_cmd_resp = SNS_RSNN_NN;
2648 MAKE_NODE_NAME_FROM_WWN(rp.rsnnnn_nodename, fcp->isp_wwnn);
2649 rp.rsnnnn_length = 0;
2650 len = offsetof(rsnn_nn_t, rsnnnn_name);
2651 mtx_lock(&prison0.pr_mtx);
2652 rp.rsnnnn_length += sprintf(&scp[len + rp.rsnnnn_length],
2653 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2654 mtx_unlock(&prison0.pr_mtx);
2655 len += rp.rsnnnn_length;
2656 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2657 isp_put_rsnn_nn(isp, &rp, (rsnn_nn_t *)scp);
2659 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2660 FC_SCRATCH_RELEASE(isp, chan);
2664 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2665 FC_SCRATCH_RELEASE(isp, chan);
2666 if (ct->ct_cmd_resp == LS_RJT) {
2667 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2668 "Chan %d Register Symbolic Node Name rejected", chan);
2670 } else if (ct->ct_cmd_resp == LS_ACC) {
2671 isp_prt(isp, ISP_LOG_SANCFG,
2672 "Chan %d Register Symbolic Node Name accepted", chan);
2674 isp_prt(isp, ISP_LOGWARN,
2675 "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp);
2682 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
2692 if (handle == NIL_HANDLE) {
2696 if (handle > NPH_RESERVED - 1) {
2698 isp_prt(isp, ISP_LOGERR, "Out of port handles!");
2699 return (NIL_HANDLE);
2704 for (chan = 0; chan < isp->isp_nchan; chan++) {
2705 fcp = FCPARAM(isp, chan);
2706 if (fcp->role == ISP_ROLE_NONE)
2708 for (i = 0; i < MAX_FC_TARG; i++) {
2709 if (fcp->portdb[i].state != FC_PORTDB_STATE_NIL &&
2710 fcp->portdb[i].handle == handle)
2719 * Start a command. Locking is assumed done in the caller.
2728 ispreqt7_t local, *reqp = &local;
2731 int target, dmaresult;
2737 * Check command CDB length, etc.. We really are limited to 16 bytes
2738 * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
2739 * but probably only if we're running fairly new firmware (we'll
2740 * let the old f/w choke on an extended command queue entry).
2743 if (XS_CDBLEN(xs) > 16 || XS_CDBLEN(xs) == 0) {
2744 isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
2745 XS_SETERR(xs, HBA_REQINVAL);
2746 return (CMD_COMPLETE);
2750 * Translate the target to device handle as appropriate, checking
2751 * for correct device state as well.
2753 target = XS_TGT(xs);
2754 fcp = FCPARAM(isp, XS_CHANNEL(xs));
2756 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2757 isp_prt(isp, ISP_LOG_WARN1,
2758 "%d.%d.%jx I am not an initiator",
2759 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2760 XS_SETERR(xs, HBA_SELTIMEOUT);
2761 return (CMD_COMPLETE);
2764 if (isp->isp_state != ISP_RUNSTATE) {
2765 isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
2766 XS_SETERR(xs, HBA_BOTCH);
2767 return (CMD_COMPLETE);
2770 isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target);
2771 lp = &fcp->portdb[target];
2772 if (target < 0 || target >= MAX_FC_TARG ||
2773 lp->is_target == 0) {
2774 XS_SETERR(xs, HBA_SELTIMEOUT);
2775 return (CMD_COMPLETE);
2777 if (fcp->isp_loopstate != LOOP_READY) {
2778 isp_prt(isp, ISP_LOGDEBUG1,
2779 "%d.%d.%jx loop is not ready",
2780 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2781 return (CMD_RQLATER);
2783 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
2784 isp_prt(isp, ISP_LOGDEBUG1,
2785 "%d.%d.%jx target zombie",
2786 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2787 return (CMD_RQLATER);
2789 if (lp->state != FC_PORTDB_STATE_VALID) {
2790 isp_prt(isp, ISP_LOGDEBUG1,
2791 "%d.%d.%jx bad db port state 0x%x",
2792 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs), lp->state);
2793 XS_SETERR(xs, HBA_SELTIMEOUT);
2794 return (CMD_COMPLETE);
2799 qep = isp_getrqentry(isp);
2801 isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow");
2802 XS_SETERR(xs, HBA_BOTCH);
2803 return (CMD_EAGAIN);
2805 XS_SETERR(xs, HBA_NOERROR);
2808 * Now see if we need to synchronize the ISP with respect to anything.
2809 * We do dual duty here (cough) for synchronizing for buses other
2810 * than which we got here to send a command to.
2812 ISP_MEMZERO(reqp, QENTRY_LEN);
2813 if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
2814 isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
2815 m->mrk_header.rqs_entry_count = 1;
2816 m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
2817 m->mrk_modifier = SYNC_ALL;
2818 m->mrk_vphdl = XS_CHANNEL(xs);
2819 isp_put_marker_24xx(isp, m, qep);
2820 ISP_SYNC_REQUEST(isp);
2821 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
2825 reqp->req_header.rqs_entry_count = 1;
2826 reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
2829 * Set task attributes
2832 reqp->req_task_attribute = XS_TAG_TYPE(xs);
2834 reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE;
2835 reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) &
2839 * NB: we do not support long CDBs (yet)
2841 cdblen = XS_CDBLEN(xs);
2843 if (cdblen > sizeof (reqp->req_cdb)) {
2844 isp_prt(isp, ISP_LOGERR, "Command Length %u too long for this chip", cdblen);
2845 XS_SETERR(xs, HBA_REQINVAL);
2846 return (CMD_COMPLETE);
2849 reqp->req_nphdl = lp->handle;
2850 reqp->req_tidlo = lp->portid;
2851 reqp->req_tidhi = lp->portid >> 16;
2852 reqp->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs));
2853 be64enc(reqp->req_lun, CAM_EXTLUN_BYTE_SWIZZLE(XS_LUN(xs)));
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 reqp->req_time = XS_TIME(xs);
2864 ISP_MEMCPY(reqp->req_cdb, XS_CDBP(xs), cdblen);
2866 /* Whew. Thankfully the same for type 7 requests */
2867 reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR);
2868 if (reqp->req_handle == 0) {
2869 isp_prt(isp, ISP_LOG_WARN1, "out of xflist pointers");
2870 XS_SETERR(xs, HBA_BOTCH);
2871 return (CMD_EAGAIN);
2875 * Set up DMA and/or do any platform dependent swizzling of the request entry
2876 * so that the Qlogic F/W understands what is being asked of it.
2878 * The callee is responsible for adding all requests at this point.
2880 dmaresult = ISP_DMASETUP(isp, xs, reqp);
2881 if (dmaresult != CMD_QUEUED) {
2882 isp_destroy_handle(isp, reqp->req_handle);
2884 * dmasetup sets actual error in packet, and
2885 * return what we were given to return.
2889 isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
2890 return (CMD_QUEUED);
2895 * Locks (ints blocked) assumed held.
2899 isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
2908 uint8_t local[QENTRY_LEN];
2911 case ISPCTL_RESET_BUS:
2913 * Issue a bus reset.
2915 isp_prt(isp, ISP_LOGERR, "BUS RESET NOT IMPLEMENTED");
2918 case ISPCTL_RESET_DEV:
2921 isp24xx_statusreq_t *sp;
2924 chan = va_arg(ap, int);
2925 tgt = va_arg(ap, int);
2927 fcp = FCPARAM(isp, chan);
2929 if (tgt < 0 || tgt >= MAX_FC_TARG) {
2930 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to reset bad target %d", chan, tgt);
2933 lp = &fcp->portdb[tgt];
2934 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
2935 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
2939 tmf = (isp24xx_tmf_t *) local;
2940 ISP_MEMZERO(tmf, QENTRY_LEN);
2941 tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
2942 tmf->tmf_header.rqs_entry_count = 1;
2943 tmf->tmf_nphdl = lp->handle;
2945 tmf->tmf_timeout = 4;
2946 tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
2947 tmf->tmf_tidlo = lp->portid;
2948 tmf->tmf_tidhi = lp->portid >> 16;
2949 tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
2950 isp_put_24xx_tmf(isp, tmf, isp->isp_iocb);
2951 if (isp->isp_dblev & ISP_LOGDEBUG1)
2952 isp_print_bytes(isp, "TMF IOCB request", QENTRY_LEN, isp->isp_iocb);
2953 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, QENTRY_LEN, chan);
2954 fcp->sendmarker = 1;
2956 isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
2957 MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL,
2958 MBCMD_DEFAULT_TIMEOUT + tmf->tmf_timeout * 1000000);
2959 mbs.param[1] = QENTRY_LEN;
2960 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
2961 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
2962 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
2963 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
2964 isp_mboxcmd(isp, &mbs);
2965 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
2968 MEMORYBARRIER(isp, SYNC_IFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
2969 if (isp->isp_dblev & ISP_LOGDEBUG1)
2970 isp_print_bytes(isp, "TMF IOCB response", QENTRY_LEN, &((isp24xx_statusreq_t *)isp->isp_iocb)[1]);
2971 sp = (isp24xx_statusreq_t *) local;
2972 isp_get_24xx_response(isp, &((isp24xx_statusreq_t *)isp->isp_iocb)[1], sp);
2973 if (sp->req_completion_status == 0) {
2976 isp_prt(isp, ISP_LOGWARN, "Chan %d reset of target %d returned 0x%x", chan, tgt, sp->req_completion_status);
2979 case ISPCTL_ABORT_CMD:
2981 isp24xx_abrt_t *ab = (isp24xx_abrt_t *)&local;
2984 xs = va_arg(ap, XS_T *);
2988 chan = XS_CHANNEL(xs);
2990 handle = isp_find_handle(isp, xs);
2992 isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort");
2996 fcp = FCPARAM(isp, chan);
2997 if (tgt < 0 || tgt >= MAX_FC_TARG) {
2998 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to abort bad target %d", chan, tgt);
3001 lp = &fcp->portdb[tgt];
3002 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
3003 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
3006 isp_prt(isp, ISP_LOGALL, "Chan %d Abort Cmd for N-Port 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
3007 ISP_MEMZERO(ab, QENTRY_LEN);
3008 ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO;
3009 ab->abrt_header.rqs_entry_count = 1;
3010 ab->abrt_handle = lp->handle;
3011 ab->abrt_cmd_handle = handle;
3012 ab->abrt_tidlo = lp->portid;
3013 ab->abrt_tidhi = lp->portid >> 16;
3014 ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan);
3015 isp_put_24xx_abrt(isp, ab, isp->isp_iocb);
3016 if (isp->isp_dblev & ISP_LOGDEBUG1)
3017 isp_print_bytes(isp, "AB IOCB quest", QENTRY_LEN, isp->isp_iocb);
3018 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, 2 * QENTRY_LEN, chan);
3020 ISP_MEMZERO(&mbs, sizeof (mbs));
3021 MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
3022 mbs.param[1] = QENTRY_LEN;
3023 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
3024 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
3025 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
3026 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
3028 isp_mboxcmd(isp, &mbs);
3029 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
3032 MEMORYBARRIER(isp, SYNC_IFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
3033 if (isp->isp_dblev & ISP_LOGDEBUG1)
3034 isp_print_bytes(isp, "AB IOCB response", QENTRY_LEN, &((isp24xx_abrt_t *)isp->isp_iocb)[1]);
3035 isp_get_24xx_abrt(isp, &((isp24xx_abrt_t *)isp->isp_iocb)[1], ab);
3036 if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY) {
3039 isp_prt(isp, ISP_LOGWARN, "Chan %d handle %d abort returned 0x%x", chan, tgt, ab->abrt_nphdl);
3041 case ISPCTL_FCLINK_TEST:
3046 chan = va_arg(ap, int);
3047 usdelay = va_arg(ap, int);
3051 return (isp_fclink_test(isp, chan, usdelay));
3053 case ISPCTL_SCAN_FABRIC:
3056 chan = va_arg(ap, int);
3058 return (isp_scan_fabric(isp, chan));
3060 case ISPCTL_SCAN_LOOP:
3063 chan = va_arg(ap, int);
3065 return (isp_scan_loop(isp, chan));
3067 case ISPCTL_PDB_SYNC:
3070 chan = va_arg(ap, int);
3072 return (isp_pdb_sync(isp, chan));
3074 case ISPCTL_SEND_LIP:
3077 case ISPCTL_GET_PDB:
3081 chan = va_arg(ap, int);
3082 tgt = va_arg(ap, int);
3083 pdb = va_arg(ap, isp_pdb_t *);
3085 return (isp_getpdb(isp, chan, tgt, pdb));
3087 case ISPCTL_GET_NAMES:
3089 uint64_t *wwnn, *wwnp;
3091 chan = va_arg(ap, int);
3092 tgt = va_arg(ap, int);
3093 wwnn = va_arg(ap, uint64_t *);
3094 wwnp = va_arg(ap, uint64_t *);
3096 if (wwnn == NULL && wwnp == NULL) {
3100 *wwnn = isp_get_wwn(isp, chan, tgt, 1);
3101 if (*wwnn == INI_NONE) {
3106 *wwnp = isp_get_wwn(isp, chan, tgt, 0);
3107 if (*wwnp == INI_NONE) {
3119 p = va_arg(ap, isp_plcmd_t *);
3122 if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
3123 return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags));
3126 isp_next_handle(isp, &p->handle);
3127 r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags);
3128 if ((r & 0xffff) == MBOX_PORT_ID_USED) {
3129 p->handle = r >> 16;
3133 } while ((r & 0xffff) == MBOX_LOOP_ID_USED);
3136 case ISPCTL_CHANGE_ROLE:
3141 chan = va_arg(ap, int);
3142 role = va_arg(ap, int);
3144 return (isp_fc_change_role(isp, chan, role));
3147 isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
3155 * Interrupt Service Routine(s).
3157 * External (OS) framework has done the appropriate locking,
3158 * and the locking will be held throughout this function.
3161 #ifdef ISP_TARGET_MODE
3163 isp_intr_atioq(ispsoftc_t *isp)
3165 uint8_t qe[QENTRY_LEN];
3168 uint32_t iptr, optr, oop;
3170 iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
3171 optr = isp->isp_atioodx;
3172 while (optr != iptr) {
3174 MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN, -1);
3175 addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop);
3176 isp_get_hdr(isp, addr, (isphdr_t *)qe);
3177 hp = (isphdr_t *)qe;
3178 switch (hp->rqs_entry_type) {
3179 case RQSTYPE_NOTIFY:
3181 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue.*/
3182 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue.*/
3183 (void) isp_target_notify(isp, addr, &oop);
3185 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/
3187 isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
3190 optr = ISP_NXT_QENTRY(oop, RESULT_QUEUE_LEN(isp));
3192 if (isp->isp_atioodx != optr) {
3193 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
3194 isp->isp_atioodx = optr;
3200 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0)
3204 if (!isp->isp_mboxbsy) {
3205 isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0);
3208 obits = isp->isp_obits;
3209 isp->isp_mboxtmp[0] = mbox0;
3210 for (i = 1; i < ISP_NMBOX(isp); i++) {
3211 if ((obits & (1 << i)) == 0)
3213 isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
3215 MBOX_NOTIFY_COMPLETE(isp);
3219 isp_intr_respq(ispsoftc_t *isp)
3222 uint8_t qe[QENTRY_LEN];
3223 isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe;
3225 uint8_t *resp, *snsp;
3226 int buddaboom, completion_status, cont = 0, etype, i;
3227 int req_status_flags, req_state_flags, scsi_status;
3228 uint32_t iptr, cptr, optr, rlen, slen, sptr, totslen, resid;
3231 * We can't be getting this now.
3233 if (isp->isp_state != ISP_RUNSTATE) {
3234 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready");
3238 iptr = ISP_READ(isp, BIU2400_RSPINP);
3239 isp->isp_residx = iptr;
3241 optr = isp->isp_resodx;
3242 while (optr != iptr) {
3244 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
3245 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
3248 * Synchronize our view of this response queue entry.
3250 MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1);
3251 if (isp->isp_dblev & ISP_LOGDEBUG1)
3252 isp_print_qentry(isp, "Response Queue Entry", cptr, hp);
3253 isp_get_hdr(isp, hp, &sp->req_header);
3254 etype = sp->req_header.rqs_entry_type;
3256 /* We expected Status Continuation, but got different IOCB. */
3257 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
3262 if (etype == RQSTYPE_RESPONSE) {
3263 isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp);
3264 scsi_status = sp->req_scsi_status;
3265 completion_status = sp->req_completion_status;
3266 req_status_flags = 0;
3267 if ((scsi_status & 0xff) != 0)
3268 req_state_flags = RQSF_GOT_STATUS;
3270 req_state_flags = 0;
3271 resid = sp->req_resid;
3272 } else if (etype == RQSTYPE_STATUS_CONT) {
3273 ispstatus_cont_t *scp = (ispstatus_cont_t *)qe;
3274 isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
3276 i = min(cont, sizeof(scp->req_sense_data));
3277 XS_SENSE_APPEND(cont_xs, scp->req_sense_data, i);
3282 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3283 "Expecting Status Continuations for %u bytes",
3287 isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
3289 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3291 } else if (isp_handle_other_response(isp, etype, hp, &cptr)) {
3292 /* More then one IOCB could be consumed. */
3293 while (sptr != cptr) {
3294 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3295 sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp));
3296 hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr);
3298 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3299 optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
3302 /* We don't know what was this -- log and skip. */
3303 isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr);
3304 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3309 if (sp->req_header.rqs_flags & RQSFLAG_MASK) {
3310 if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {
3311 isp_print_qentry(isp, "unexpected continuation segment",
3315 if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
3316 isp_prt(isp, ISP_LOG_WARN1, "internal queues full");
3318 * We'll synthesize a QUEUE FULL message below.
3321 if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) {
3322 isp_print_qentry(isp, "bad header flag",
3326 if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) {
3327 isp_print_qentry(isp, "bad request packet",
3331 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
3332 isp_print_qentry(isp, "invalid entry count",
3336 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
3337 isp_print_qentry(isp, "invalid IOCB ordering",
3343 xs = isp_find_xs(isp, sp->req_handle);
3345 uint8_t ts = completion_status & 0xff;
3347 * Only whine if this isn't the expected fallout of
3348 * aborting the command or resetting the target.
3350 if (etype != RQSTYPE_RESPONSE) {
3351 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype);
3352 } else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED) {
3353 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts);
3355 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3358 if (req_status_flags & RQSTF_BUS_RESET) {
3359 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx bus was reset",
3360 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs));
3361 XS_SETERR(xs, HBA_BUSRESET);
3362 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1);
3365 isp_prt(isp, ISP_LOG_WARN1, "%d.%d.%jx buddaboom",
3366 XS_CHANNEL(xs), XS_TGT(xs), (uintmax_t)XS_LUN(xs));
3367 XS_SETERR(xs, HBA_BOTCH);
3371 rlen = slen = totslen = 0;
3372 if ((scsi_status & (RQCS_RV|RQCS_SV)) != 0) {
3373 resp = sp->req_rsp_sense;
3374 rlen = sp->req_response_len;
3376 if ((scsi_status & RQCS_SV) != 0) {
3378 * Fibre Channel F/W doesn't say we got status
3379 * if there's Sense Data instead. I guess they
3380 * think it goes w/o saying.
3382 req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE;
3383 snsp = sp->req_rsp_sense + rlen;
3384 totslen = sp->req_sense_len;
3385 slen = sizeof(sp->req_rsp_sense) - rlen;
3389 if (req_state_flags & RQSF_GOT_STATUS)
3390 *XS_STSP(xs) = scsi_status & 0xff;
3392 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
3395 const char *rnames[10] = {
3396 "Task Management function complete",
3397 "FCP_DATA length different than FCP_BURST_LEN",
3398 "FCP_CMND fields invalid",
3399 "FCP_DATA parameter mismatch with FCP_DATA_RO",
3400 "Task Management function rejected",
3401 "Task Management function failed",
3404 "Task Management function succeeded",
3405 "Task Management function incorrect logical unit number",
3407 uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
3408 if (code >= 10 || rnames[code] == NULL) {
3409 ISP_SNPRINTF(lb, sizeof(lb),
3410 "Unknown FCP Response Code 0x%x", code);
3415 isp_xs_prt(isp, xs, ISP_LOGWARN,
3416 "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
3417 rlen, ptr, XS_CDBP(xs)[0] & 0xff);
3418 if (code != 0 && code != 8)
3419 XS_SETERR(xs, HBA_BOTCH);
3421 isp_parse_status_24xx(isp, sp, xs, &resid);
3422 if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) &&
3423 (*XS_STSP(xs) == SCSI_BUSY))
3424 XS_SETERR(xs, HBA_TGTBSY);
3425 if (req_status_flags & RQSF_XFER_COMPLETE) {
3426 XS_SET_RESID(xs, 0);
3427 } else if (scsi_status & RQCS_RESID) {
3428 XS_SET_RESID(xs, resid);
3430 XS_SET_RESID(xs, 0);
3433 XS_SAVE_SENSE(xs, snsp, slen);
3434 if (totslen > slen) {
3435 cont = totslen - slen;
3437 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3438 "Expecting Status Continuations for %u bytes",
3442 isp_prt(isp, ISP_LOGDEBUG2, "asked for %lu got raw resid %lu settled for %lu",
3443 (u_long)XS_XFRLEN(xs), (u_long)resid, (u_long)XS_GET_RESID(xs));
3446 ISP_DMAFREE(isp, xs, sp->req_handle);
3447 isp_destroy_handle(isp, sp->req_handle);
3449 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3451 /* Complete command if we expect no Status Continuations. */
3456 /* We haven't received all Status Continuations, but that is it. */
3460 /* If we processed any IOCBs, let ISP know about it. */
3461 if (optr != isp->isp_resodx) {
3462 ISP_WRITE(isp, BIU2400_RSPOUTP, optr);
3463 isp->isp_resodx = optr;
3469 isp_intr_async(ispsoftc_t *isp, uint16_t mbox)
3474 isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
3477 case ASYNC_SYSTEM_ERROR:
3478 isp->isp_state = ISP_CRASHED;
3479 for (chan = 0; chan < isp->isp_nchan; chan++) {
3480 FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
3481 isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
3484 * Were we waiting for a mailbox command to complete?
3485 * If so, it's dead, so wake up the waiter.
3487 if (isp->isp_mboxbsy) {
3489 isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
3490 MBOX_NOTIFY_COMPLETE(isp);
3493 * It's up to the handler for isp_async to reinit stuff and
3494 * restart the firmware
3496 isp_async(isp, ISPASYNC_FW_CRASH);
3499 case ASYNC_RQS_XFER_ERR:
3500 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
3503 case ASYNC_RSP_XFER_ERR:
3504 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
3507 case ASYNC_ATIO_XFER_ERR:
3508 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
3511 case ASYNC_LIP_OCCURRED:
3512 case ASYNC_LIP_NOS_OLS_RECV:
3513 case ASYNC_LIP_ERROR:
3516 * These are broadcast events that have to be sent across
3517 * all active channels.
3519 for (chan = 0; chan < isp->isp_nchan; chan++) {
3520 fcp = FCPARAM(isp, chan);
3521 int topo = fcp->isp_topo;
3523 if (fcp->role == ISP_ROLE_NONE)
3525 if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3526 fcp->isp_loopstate = LOOP_HAVE_LINK;
3527 ISP_SET_SENDMARKER(isp, chan, 1);
3528 isp_async(isp, ISPASYNC_LIP, chan);
3529 #ifdef ISP_TARGET_MODE
3530 isp_target_async(isp, chan, mbox);
3533 * We've had problems with data corruption occurring on
3534 * commands that complete (with no apparent error) after
3535 * we receive a LIP. This has been observed mostly on
3536 * Local Loop topologies. To be safe, let's just mark
3537 * all active initiator commands as dead.
3539 if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
3541 for (i = j = 0; i < isp->isp_maxcmds; i++) {
3545 hdp = &isp->isp_xflist[i];
3546 if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
3550 if (XS_CHANNEL(xs) != chan) {
3554 isp_prt(isp, ISP_LOG_WARN1,
3555 "%d.%d.%jx bus reset set at %s:%u",
3556 XS_CHANNEL(xs), XS_TGT(xs),
3557 (uintmax_t)XS_LUN(xs),
3558 __func__, __LINE__);
3559 XS_SETERR(xs, HBA_BUSRESET);
3562 isp_prt(isp, ISP_LOGERR, lipd, chan, j);
3570 * This is a broadcast event that has to be sent across
3571 * all active channels.
3573 for (chan = 0; chan < isp->isp_nchan; chan++) {
3574 fcp = FCPARAM(isp, chan);
3575 if (fcp->role == ISP_ROLE_NONE)
3577 fcp->isp_linkstate = 1;
3578 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3579 fcp->isp_loopstate = LOOP_HAVE_LINK;
3580 ISP_SET_SENDMARKER(isp, chan, 1);
3581 isp_async(isp, ISPASYNC_LOOP_UP, chan);
3582 #ifdef ISP_TARGET_MODE
3583 isp_target_async(isp, chan, mbox);
3588 case ASYNC_LOOP_DOWN:
3590 * This is a broadcast event that has to be sent across
3591 * all active channels.
3593 for (chan = 0; chan < isp->isp_nchan; chan++) {
3594 fcp = FCPARAM(isp, chan);
3595 if (fcp->role == ISP_ROLE_NONE)
3597 ISP_SET_SENDMARKER(isp, chan, 1);
3598 fcp->isp_linkstate = 0;
3599 fcp->isp_loopstate = LOOP_NIL;
3600 isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
3601 #ifdef ISP_TARGET_MODE
3602 isp_target_async(isp, chan, mbox);
3607 case ASYNC_LOOP_RESET:
3609 * This is a broadcast event that has to be sent across
3610 * all active channels.
3612 for (chan = 0; chan < isp->isp_nchan; chan++) {
3613 fcp = FCPARAM(isp, chan);
3614 if (fcp->role == ISP_ROLE_NONE)
3616 ISP_SET_SENDMARKER(isp, chan, 1);
3617 if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3618 fcp->isp_loopstate = LOOP_HAVE_LINK;
3619 isp_async(isp, ISPASYNC_LOOP_RESET, chan);
3620 #ifdef ISP_TARGET_MODE
3621 isp_target_async(isp, chan, mbox);
3626 case ASYNC_PDB_CHANGED:
3628 int echan, nphdl, nlstate, reason;
3630 nphdl = ISP_READ(isp, OUTMAILBOX1);
3631 nlstate = ISP_READ(isp, OUTMAILBOX2);
3632 reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
3633 if (ISP_CAP_MULTI_ID(isp)) {
3634 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3635 if (chan == 0xff || nphdl == NIL_HANDLE) {
3637 echan = isp->isp_nchan - 1;
3638 } else if (chan >= isp->isp_nchan) {
3646 for (; chan <= echan; chan++) {
3647 fcp = FCPARAM(isp, chan);
3648 if (fcp->role == ISP_ROLE_NONE)
3650 if (fcp->isp_loopstate > LOOP_LTEST_DONE) {
3651 if (nphdl != NIL_HANDLE &&
3652 nphdl == fcp->isp_login_hdl &&
3653 reason == PDB24XX_AE_OPN_2)
3655 fcp->isp_loopstate = LOOP_LTEST_DONE;
3656 } else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3657 fcp->isp_loopstate = LOOP_HAVE_LINK;
3658 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3659 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
3663 case ASYNC_CHANGE_NOTIFY:
3667 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) |
3668 ISP_READ(isp, OUTMAILBOX2);
3669 if (ISP_CAP_MULTI_ID(isp)) {
3670 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3671 if (chan >= isp->isp_nchan)
3676 fcp = FCPARAM(isp, chan);
3677 if (fcp->role == ISP_ROLE_NONE)
3679 if (fcp->isp_loopstate > LOOP_LTEST_DONE)
3680 fcp->isp_loopstate = LOOP_LTEST_DONE;
3681 else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3682 fcp->isp_loopstate = LOOP_HAVE_LINK;
3683 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3684 ISPASYNC_CHANGE_SNS, portid);
3687 case ASYNC_ERR_LOGGING_DISABLED:
3688 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)",
3689 ISP_READ(isp, OUTMAILBOX1));
3691 case ASYNC_P2P_INIT_ERR:
3692 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)",
3693 ISP_READ(isp, OUTMAILBOX1));
3696 isp_prt(isp, ISP_LOGWARN, "Receive Error");
3698 case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */
3699 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
3701 case ASYNC_FW_RESTART_COMPLETE:
3702 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete");
3704 case ASYNC_TEMPERATURE_ALERT:
3705 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)",
3706 ISP_READ(isp, OUTMAILBOX1));
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_AUTOLOAD_FW_COMPLETE:
3716 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete");
3718 case ASYNC_AUTOLOAD_FW_FAILURE:
3719 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure");
3722 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
3728 * Handle other response entries. A pointer to the request queue output
3729 * index is here in case we want to eat several entries at once, although
3730 * this is not used currently.
3734 isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *optrp)
3738 uint32_t hdl, portid;
3742 case RQSTYPE_MARKER:
3743 isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
3745 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/
3746 isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
3747 portid = (uint32_t)rid.ridacq_vp_port_hi << 16 |
3748 rid.ridacq_vp_port_lo;
3749 if (rid.ridacq_format == 0) {
3750 for (chan = 0; chan < isp->isp_nchan; chan++) {
3751 fcparam *fcp = FCPARAM(isp, chan);
3752 if (fcp->role == ISP_ROLE_NONE)
3754 c = (chan == 0) ? 127 : (chan - 1);
3755 if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
3757 fcp->isp_loopstate = LOOP_HAVE_LINK;
3758 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3759 chan, ISPASYNC_CHANGE_OTHER);
3761 fcp->isp_loopstate = LOOP_NIL;
3762 isp_async(isp, ISPASYNC_LOOP_DOWN,
3767 fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index);
3768 if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
3769 rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
3770 fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7;
3771 fcp->isp_portid = portid;
3772 fcp->isp_loopstate = LOOP_HAVE_ADDR;
3773 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3774 rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
3776 fcp->isp_loopstate = LOOP_NIL;
3777 isp_async(isp, ISPASYNC_LOOP_DOWN,
3778 rid.ridacq_vp_index);
3782 case RQSTYPE_CT_PASSTHRU:
3783 case RQSTYPE_VP_MODIFY:
3784 case RQSTYPE_VP_CTRL:
3786 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
3787 ptr = isp_find_xs(isp, hdl);
3789 isp_destroy_handle(isp, hdl);
3790 memcpy(ptr, hp, QENTRY_LEN);
3794 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue. */
3796 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue. */
3797 case RQSTYPE_ABTS_RSP:
3798 #ifdef ISP_TARGET_MODE
3799 return (isp_target_notify(isp, hp, optrp));
3808 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs, uint32_t *rp)
3810 int ru_marked, sv_marked;
3811 int chan = XS_CHANNEL(xs);
3813 switch (sp->req_completion_status) {
3816 XS_SETERR(xs, HBA_NOERROR);
3820 case RQCS_DMA_ERROR:
3821 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error");
3824 case RQCS_TRANSPORT_ERROR:
3825 isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error");
3828 case RQCS_RESET_OCCURRED:
3829 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command");
3830 FCPARAM(isp, chan)->sendmarker = 1;
3832 XS_SETERR(xs, HBA_BUSRESET);
3837 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted");
3838 FCPARAM(isp, chan)->sendmarker = 1;
3840 XS_SETERR(xs, HBA_ABORTED);
3845 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out");
3847 XS_SETERR(xs, HBA_CMDTIMEOUT);
3851 case RQCS_DATA_OVERRUN:
3852 XS_SET_RESID(xs, sp->req_resid);
3853 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun");
3855 XS_SETERR(xs, HBA_DATAOVR);
3859 case RQCS_24XX_DRE: /* data reassembly error */
3860 isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs));
3862 XS_SETERR(xs, HBA_ABORTED);
3864 *rp = XS_XFRLEN(xs);
3867 case RQCS_24XX_TABORT: /* aborted by target */
3868 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs));
3870 XS_SETERR(xs, HBA_ABORTED);
3874 case RQCS_DATA_UNDERRUN:
3875 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
3877 * We can get an underrun w/o things being marked
3878 * if we got a non-zero status.
3880 sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
3881 if ((ru_marked == 0 && sv_marked == 0) ||
3882 (sp->req_resid > XS_XFRLEN(xs))) {
3883 isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked");
3885 XS_SETERR(xs, HBA_BOTCH);
3889 XS_SET_RESID(xs, sp->req_resid);
3890 isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff);
3892 XS_SETERR(xs, HBA_NOERROR);
3896 case RQCS_PORT_UNAVAILABLE:
3898 * No such port on the loop. Moral equivalent of SELTIMEO
3900 case RQCS_PORT_LOGGED_OUT:
3903 uint8_t sts = sp->req_completion_status & 0xff;
3904 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
3908 * It was there (maybe)- treat as a selection timeout.
3910 if (sts == RQCS_PORT_UNAVAILABLE) {
3911 reason = "unavailable";
3916 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
3917 chan, reason, XS_TGT(xs));
3919 /* XXX: Should we trigger rescan or FW announce change? */
3922 lp = &fcp->portdb[XS_TGT(xs)];
3923 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
3924 *XS_STSP(xs) = SCSI_BUSY;
3925 XS_SETERR(xs, HBA_TGTBSY);
3927 XS_SETERR(xs, HBA_SELTIMEOUT);
3931 case RQCS_PORT_CHANGED:
3932 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan);
3934 *XS_STSP(xs) = SCSI_BUSY;
3935 XS_SETERR(xs, HBA_TGTBSY);
3939 case RQCS_24XX_ENOMEM: /* f/w resource unavailable */
3940 isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan);
3942 *XS_STSP(xs) = SCSI_BUSY;
3943 XS_SETERR(xs, HBA_TGTBSY);
3947 case RQCS_24XX_TMO: /* task management overrun */
3948 isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan);
3950 *XS_STSP(xs) = SCSI_BUSY;
3951 XS_SETERR(xs, HBA_TGTBSY);
3956 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan);
3960 XS_SETERR(xs, HBA_BOTCH);
3964 #define ISP_FC_IBITS(op) ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3]))
3965 #define ISP_FC_OBITS(op) ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7]))
3967 #define ISP_FC_OPMAP(in0, out0) 0, 0, 0, in0, 0, 0, 0, out0
3968 #define ISP_FC_OPMAP_HALF(in1, in0, out1, out0) 0, 0, in1, in0, 0, 0, out1, out0
3969 #define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0) in3, in2, in1, in0, out3, out2, out1, out0
3970 static const uint32_t mbpfc[] = {
3971 ISP_FC_OPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
3972 ISP_FC_OPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
3973 ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f), /* 0x02: MBOX_EXEC_FIRMWARE */
3974 ISP_FC_OPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */
3975 ISP_FC_OPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
3976 ISP_FC_OPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
3977 ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */
3978 ISP_FC_OPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
3979 ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f), /* 0x08: MBOX_ABOUT_FIRMWARE */
3980 ISP_FC_OPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */
3981 ISP_FC_OPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
3982 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */
3983 ISP_FC_OPMAP(0x00, 0x00), /* 0x0c: */
3984 ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
3985 ISP_FC_OPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
3986 ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
3987 ISP_FC_OPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
3988 ISP_FC_OPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
3989 ISP_FC_OPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
3990 ISP_FC_OPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
3991 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03), /* 0x14: MBOX_STOP_FIRMWARE */
3992 ISP_FC_OPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */
3993 ISP_FC_OPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */
3994 ISP_FC_OPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */
3995 ISP_FC_OPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */
3996 ISP_FC_OPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */
3997 ISP_FC_OPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */
3998 ISP_FC_OPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
3999 ISP_FC_OPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */
4000 ISP_FC_OPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
4001 ISP_FC_OPMAP(0x00, 0x00), /* 0x1e: */
4002 ISP_FC_OPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
4003 ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf), /* 0x20: MBOX_GET_LOOP_ID */
4004 ISP_FC_OPMAP(0x00, 0x00), /* 0x21: */
4005 ISP_FC_OPMAP(0x03, 0x4b), /* 0x22: MBOX_GET_TIMEOUT_PARAMS */
4006 ISP_FC_OPMAP(0x00, 0x00), /* 0x23: */
4007 ISP_FC_OPMAP(0x00, 0x00), /* 0x24: */
4008 ISP_FC_OPMAP(0x00, 0x00), /* 0x25: */
4009 ISP_FC_OPMAP(0x00, 0x00), /* 0x26: */
4010 ISP_FC_OPMAP(0x00, 0x00), /* 0x27: */
4011 ISP_FC_OPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
4012 ISP_FC_OPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
4013 ISP_FC_OPMAP(0x00, 0x00), /* 0x2a: */
4014 ISP_FC_OPMAP(0x00, 0x00), /* 0x2b: */
4015 ISP_FC_OPMAP(0x00, 0x00), /* 0x2c: */
4016 ISP_FC_OPMAP(0x00, 0x00), /* 0x2d: */
4017 ISP_FC_OPMAP(0x00, 0x00), /* 0x2e: */
4018 ISP_FC_OPMAP(0x00, 0x00), /* 0x2f: */
4019 ISP_FC_OPMAP(0x00, 0x00), /* 0x30: */
4020 ISP_FC_OPMAP(0x00, 0x00), /* 0x31: */
4021 ISP_FC_OPMAP(0x4b, 0x4b), /* 0x32: MBOX_SET_TIMEOUT_PARAMS */
4022 ISP_FC_OPMAP(0x00, 0x00), /* 0x33: */
4023 ISP_FC_OPMAP(0x00, 0x00), /* 0x34: */
4024 ISP_FC_OPMAP(0x00, 0x00), /* 0x35: */
4025 ISP_FC_OPMAP(0x00, 0x00), /* 0x36: */
4026 ISP_FC_OPMAP(0x00, 0x00), /* 0x37: */
4027 ISP_FC_OPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
4028 ISP_FC_OPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
4029 ISP_FC_OPMAP(0x00, 0x00), /* 0x3a: */
4030 ISP_FC_OPMAP(0x00, 0x00), /* 0x3b: */
4031 ISP_FC_OPMAP(0x00, 0x00), /* 0x3c: */
4032 ISP_FC_OPMAP(0x00, 0x00), /* 0x3d: */
4033 ISP_FC_OPMAP(0x00, 0x00), /* 0x3e: */
4034 ISP_FC_OPMAP(0x00, 0x00), /* 0x3f: */
4035 ISP_FC_OPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */
4036 ISP_FC_OPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */
4037 ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf), /* 0x42: MBOX_GET_RESOURCE_COUNT */
4038 ISP_FC_OPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */
4039 ISP_FC_OPMAP(0x00, 0x00), /* 0x44: */
4040 ISP_FC_OPMAP(0x00, 0x00), /* 0x45: */
4041 ISP_FC_OPMAP(0x00, 0x00), /* 0x46: */
4042 ISP_FC_OPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */
4043 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
4044 ISP_FC_OPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */
4045 ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
4046 ISP_FC_OPMAP(0x00, 0x00), /* 0x4b: */
4047 ISP_FC_OPMAP(0x00, 0x00), /* 0x4c: */
4048 ISP_FC_OPMAP(0x00, 0x00), /* 0x4d: */
4049 ISP_FC_OPMAP(0x00, 0x00), /* 0x4e: */
4050 ISP_FC_OPMAP(0x00, 0x00), /* 0x4f: */
4051 ISP_FC_OPMAP(0x00, 0x00), /* 0x50: */
4052 ISP_FC_OPMAP(0x00, 0x00), /* 0x51: */
4053 ISP_FC_OPMAP(0x00, 0x00), /* 0x52: */
4054 ISP_FC_OPMAP(0x00, 0x00), /* 0x53: */
4055 ISP_FC_OPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
4056 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */
4057 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */
4058 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */
4059 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */
4060 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */
4061 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */
4062 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
4063 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
4064 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */
4065 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */
4066 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */
4067 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */
4068 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */
4069 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */
4070 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
4071 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
4072 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */
4073 ISP_FC_OPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */
4074 ISP_FC_OPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */
4075 ISP_FC_OPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */
4076 ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f), /* 0x69: MBOX_GET_FW_STATE */
4077 ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */
4078 ISP_FC_OPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */
4079 ISP_FC_OPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */
4080 ISP_FC_OPMAP(0x00, 0x00), /* 0x6d: */
4081 ISP_FC_OPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */
4082 ISP_FC_OPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */
4083 ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03), /* 0x70: MBOX_SEND_CHANGE_REQUEST */
4084 ISP_FC_OPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */
4085 ISP_FC_OPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */
4086 ISP_FC_OPMAP(0x00, 0x00), /* 0x73: */
4087 ISP_FC_OPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */
4088 ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07), /* 0x75: GET PORT/NODE NAME LIST */
4089 ISP_FC_OPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */
4090 ISP_FC_OPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */
4091 ISP_FC_OPMAP(0x00, 0x00), /* 0x78: */
4092 ISP_FC_OPMAP(0x00, 0x00), /* 0x79: */
4093 ISP_FC_OPMAP(0x00, 0x00), /* 0x7a: */
4094 ISP_FC_OPMAP(0x00, 0x00), /* 0x7b: */
4095 ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07), /* 0x7c: Get ID List */
4096 ISP_FC_OPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */
4097 ISP_FC_OPMAP(0x0f, 0x01) /* 0x7e: LUN RESET */
4099 #define MAX_FC_OPCODE 0x7e
4103 * (1): this sets bits 21..16 in mailbox register #8, which we nominally
4104 * do not access at this time in the core driver. The caller is
4105 * responsible for setting this register first (Gross!). The assumption
4106 * is that we won't overflow.
4109 static const char *fc_mbcmd_names[] = {
4123 "WRITE RAM WORD EXTENDED",
4125 "READ RAM WORD EXTENDED",
4126 "INIT REQUEST QUEUE", /* 10h */
4127 "INIT RESULT QUEUE",
4137 "SINGLE STEP QUEUE",
4139 "GET DEV QUEUE STATUS",
4141 "GET FIRMWARE STATUS",
4142 "GET LOOP ID", /* 20h */
4144 "GET TIMEOUT PARAMS",
4150 "GET FIRMWARE OPTIONS",
4151 "GET PORT QUEUE PARAMS",
4152 "GENERATE SYSTEM ERROR",
4158 "WRITE SFP", /* 30h */
4160 "SET TIMEOUT PARAMS",
4166 "SET FIRMWARE OPTIONS",
4167 "SET PORT QUEUE PARAMS",
4171 "RESTART NIC FIRMWARE",
4174 "LOOP PORT BYPASS", /* 40h */
4176 "GET RESOURCE COUNT",
4177 "REQUEST NON PARTICIPATING MODE",
4178 "DIAGNOSTIC ECHO TEST",
4179 "DIAGNOSTIC LOOPBACK",
4181 "GET PORT DATABASE ENHANCED",
4182 "INIT FIRMWARE MULTI ID",
4184 "GET VP DATABASE ENTRY",
4190 "GET FCF LIST", /* 50h */
4191 "GET DCBX PARAMETERS",
4202 "FIRMWARE HEARTBEAT",
4203 "GET/SET DATA RATE",
4206 "INIT FIRMWARE", /* 60h */
4207 "GET INIT CONTROL BLOCK",
4209 "GET FC-AL POSITION MAP",
4210 "GET PORT DATABASE",
4219 "GET LINK STATS & PRIVATE DATA CNTS",
4222 "SEND CHANGE REQUEST", /* 70h */
4227 "GET PORT/NODE NAME LIST",
4229 "INITIALIZE IP MAILBOX",
4240 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
4242 const char *cname, *xname, *sname;
4243 char tname[16], mname[16];
4244 unsigned int ibits, obits, box, opcode;
4246 opcode = mbp->param[0];
4247 if (opcode > MAX_FC_OPCODE) {
4248 mbp->param[0] = MBOX_INVALID_COMMAND;
4249 isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
4252 cname = fc_mbcmd_names[opcode];
4253 ibits = ISP_FC_IBITS(opcode);
4254 obits = ISP_FC_OBITS(opcode);
4255 if (cname == NULL) {
4257 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
4259 isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname);
4262 * Pick up any additional bits that the caller might have set.
4264 ibits |= mbp->ibits;
4265 obits |= mbp->obits;
4268 * Mask any bits that the caller wants us to mask
4270 ibits &= mbp->ibitm;
4271 obits &= mbp->obitm;
4274 if (ibits == 0 && obits == 0) {
4275 mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
4276 isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
4281 * Get exclusive usage of mailbox registers.
4283 if (MBOX_ACQUIRE(isp)) {
4284 mbp->param[0] = MBOX_REGS_BUSY;
4288 for (box = 0; box < ISP_NMBOX(isp); box++) {
4289 if (ibits & (1 << box)) {
4290 isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
4292 ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
4294 isp->isp_mboxtmp[box] = mbp->param[box] = 0;
4297 isp->isp_lastmbxcmd = opcode;
4300 * We assume that we can't overwrite a previous command.
4302 isp->isp_obits = obits;
4303 isp->isp_mboxbsy = 1;
4306 * Set Host Interrupt condition so that RISC will pick up mailbox regs.
4308 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
4311 * While we haven't finished the command, spin our wheels here.
4313 MBOX_WAIT_COMPLETE(isp, mbp);
4316 * Did the command time out?
4318 if (mbp->param[0] == MBOX_TIMEOUT) {
4319 isp->isp_mboxbsy = 0;
4325 * Copy back output registers.
4327 for (box = 0; box < ISP_NMBOX(isp); box++) {
4328 if (obits & (1 << box)) {
4329 mbp->param[box] = isp->isp_mboxtmp[box];
4330 isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
4335 isp->isp_mboxbsy = 0;
4338 if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE)
4341 if ((mbp->param[0] & 0xbfe0) == 0 &&
4342 (mbp->logval & MBLOGMASK(mbp->param[0])) == 0)
4347 switch (mbp->param[0]) {
4348 case MBOX_INVALID_COMMAND:
4349 xname = "INVALID COMMAND";
4351 case MBOX_HOST_INTERFACE_ERROR:
4352 xname = "HOST INTERFACE ERROR";
4354 case MBOX_TEST_FAILED:
4355 xname = "TEST FAILED";
4357 case MBOX_COMMAND_ERROR:
4358 xname = "COMMAND ERROR";
4359 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x",
4363 case MBOX_COMMAND_PARAM_ERROR:
4364 xname = "COMMAND PARAMETER ERROR";
4366 case MBOX_PORT_ID_USED:
4367 xname = "PORT ID ALREADY IN USE";
4369 case MBOX_LOOP_ID_USED:
4370 xname = "LOOP ID ALREADY IN USE";
4372 case MBOX_ALL_IDS_USED:
4373 xname = "ALL LOOP IDS IN USE";
4375 case MBOX_NOT_LOGGED_IN:
4376 xname = "NOT LOGGED IN";
4378 case MBOX_LINK_DOWN_ERROR:
4379 xname = "LINK DOWN ERROR";
4381 case MBOX_LOOPBACK_ERROR:
4382 xname = "LOOPBACK ERROR";
4384 case MBOX_CHECKSUM_ERROR:
4385 xname = "CHECKSUM ERROR";
4387 case MBOX_INVALID_PRODUCT_KEY:
4388 xname = "INVALID PRODUCT KEY";
4390 case MBOX_REGS_BUSY:
4391 xname = "REGISTERS BUSY";
4397 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
4402 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)",
4403 cname, xname, sname);
4408 isp_fw_state(ispsoftc_t *isp, int chan)
4412 MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
4413 isp_mboxcmd(isp, &mbs);
4414 if (mbs.param[0] == MBOX_COMMAND_COMPLETE)
4415 return (mbs.param[1]);
4420 isp_setdfltfcparm(ispsoftc_t *isp, int chan)
4422 fcparam *fcp = FCPARAM(isp, chan);
4425 * Establish some default parameters.
4427 fcp->role = DEFAULT_ROLE(isp, chan);
4428 fcp->isp_maxalloc = ICB_DFLT_ALLOC;
4429 fcp->isp_retry_delay = ICB_DFLT_RDELAY;
4430 fcp->isp_retry_count = ICB_DFLT_RCOUNT;
4431 fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
4432 fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
4433 fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
4434 fcp->isp_fwoptions = 0;
4435 fcp->isp_xfwoptions = 0;
4436 fcp->isp_zfwoptions = 0;
4437 fcp->isp_lasthdl = NIL_HANDLE;
4438 fcp->isp_login_hdl = NIL_HANDLE;
4440 fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
4441 fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
4442 if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
4443 fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
4444 fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
4445 fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP;
4446 fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO;
4449 * Now try and read NVRAM unless told to not do so.
4450 * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
4452 if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
4455 * Give a couple of tries at reading NVRAM.
4457 for (i = 0; i < 2; i++) {
4458 j = isp_read_nvram(isp, chan);
4464 isp->isp_confopts |= ISP_CFG_NONVRAM;
4468 fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
4469 fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
4470 isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
4471 chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
4472 (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
4473 isp_class3_roles[fcp->role]);
4477 * Re-initialize the ISP and complete all orphaned commands
4478 * with a 'botched' notice. The reset/init routines should
4479 * not disturb an already active list of commands.
4483 isp_reinit(ispsoftc_t *isp, int do_load_defaults)
4487 if (isp->isp_state > ISP_RESETSTATE)
4489 if (isp->isp_state != ISP_RESETSTATE)
4490 isp_reset(isp, do_load_defaults);
4491 if (isp->isp_state != ISP_RESETSTATE) {
4493 isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
4498 if (isp->isp_state > ISP_RESETSTATE &&
4499 isp->isp_state != ISP_RUNSTATE) {
4501 isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
4502 ISP_DISABLE_INTS(isp);
4506 isp_clear_commands(isp);
4507 for (i = 0; i < isp->isp_nchan; i++)
4508 isp_clear_portdb(isp, i);
4516 isp_read_nvram(ispsoftc_t *isp, int bus)
4519 return (isp_read_nvram_2400(isp));
4523 isp_read_nvram_2400(ispsoftc_t *isp)
4526 uint32_t addr, csum, lwrds, *dptr;
4527 uint8_t nvram_data[ISP2400_NVRAM_SIZE];
4529 if (isp->isp_port) {
4530 addr = ISP2400_NVRAM_PORT1_ADDR;
4532 addr = ISP2400_NVRAM_PORT0_ADDR;
4535 dptr = (uint32_t *) nvram_data;
4536 for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4537 isp_rd_2400_nvram(isp, addr++, dptr++);
4539 if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
4540 nvram_data[2] != 'P') {
4541 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)",
4542 nvram_data[0], nvram_data[1], nvram_data[2]);
4546 dptr = (uint32_t *) nvram_data;
4547 for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4549 ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
4553 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
4557 isp_parse_nvram_2400(isp, nvram_data);
4563 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
4566 uint32_t base = 0x7ffe0000;
4570 base = 0x7fe7c000; /* XXX: Observation, may be wrong. */
4571 } else if (IS_25XX(isp)) {
4572 base = 0x7ff00000 | 0x48000;
4574 ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
4575 for (loops = 0; loops < 5000; loops++) {
4577 tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
4578 if ((tmp & (1U << 31)) != 0) {
4582 if (tmp & (1U << 31)) {
4583 *rp = ISP_READ(isp, BIU2400_FLASH_DATA);
4584 ISP_SWIZZLE_NVRAM_LONG(isp, rp);
4591 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
4593 fcparam *fcp = FCPARAM(isp, 0);
4596 isp_prt(isp, ISP_LOGDEBUG0,
4597 "NVRAM 0x%08x%08x 0x%08x%08x exchg_cnt %d maxframelen %d",
4598 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
4599 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
4600 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
4601 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
4602 ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data),
4603 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
4604 isp_prt(isp, ISP_LOGDEBUG0,
4605 "NVRAM execthr %d loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
4606 ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data),
4607 ISP2400_NVRAM_HARDLOOPID(nvram_data),
4608 ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
4609 ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
4610 ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
4612 wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
4613 fcp->isp_wwpn_nvram = wwn;
4615 wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
4617 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
4621 if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
4622 wwn = fcp->isp_wwpn_nvram;
4623 wwn &= ~((uint64_t) 0xfff << 48);
4625 fcp->isp_wwnn_nvram = wwn;
4627 if (ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data)) {
4628 fcp->isp_maxalloc = ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data);
4630 if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
4631 DEFAULT_FRAMESIZE(isp) =
4632 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
4634 if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
4635 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
4637 if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) {
4638 DEFAULT_EXEC_THROTTLE(isp) =
4639 ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data);
4641 fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
4642 fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
4643 fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);