2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2009-2020 Alexander Motin <mav@FreeBSD.org>
5 * Copyright (c) 1997-2009 by Matthew Jacob
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Machine and OS Independent (well, as best as possible)
34 * code for the Qlogic ISP SCSI and FC-SCSI adapters.
38 * Inspiration and ideas about this driver are from Erik Moe's Linux driver
39 * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some
40 * ideas dredged from the Solaris driver.
44 * Include header file appropriate for platform we're building on.
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD$");
49 #include <dev/ic/isp_netbsd.h>
52 #include <sys/cdefs.h>
53 __FBSDID("$FreeBSD$");
54 #include <dev/isp/isp_freebsd.h>
57 #include <dev/ic/isp_openbsd.h>
60 #include "isp_linux.h"
63 #include "isp_solaris.h"
69 static const char notresp[] = "Unknown IOCB in RESPONSE Queue (type 0x%x) @ idx %d (next %d)";
70 static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
71 static const char lipd[] = "Chan %d LIP destroyed %d active commands";
72 static const char sacq[] = "unable to acquire scratch area";
74 static const uint8_t alpa_map[] = {
75 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
76 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
77 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,
78 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
79 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
80 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
81 0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81,
82 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
83 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69,
84 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
85 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c,
86 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
87 0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
88 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
89 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
90 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
94 * Local function prototypes.
96 static int isp_handle_control(ispsoftc_t *, isphdr_t *);
97 static void isp_handle_rpt_id_acq(ispsoftc_t *, isphdr_t *);
98 static void isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *);
99 static void isp_clear_portdb(ispsoftc_t *, int);
100 static void isp_mark_portdb(ispsoftc_t *, int);
101 static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int);
102 static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *);
103 static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int);
104 static void isp_dump_chip_portdb(ispsoftc_t *, int);
105 static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
106 static int isp_fclink_test(ispsoftc_t *, int, int);
107 static int isp_pdb_sync(ispsoftc_t *, int);
108 static int isp_scan_loop(ispsoftc_t *, int);
109 static int isp_gid_pt(ispsoftc_t *, int);
110 static int isp_scan_fabric(ispsoftc_t *, int);
111 static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
112 static int isp_register_fc4_type(ispsoftc_t *, int);
113 static int isp_register_fc4_features_24xx(ispsoftc_t *, int);
114 static int isp_register_port_name_24xx(ispsoftc_t *, int);
115 static int isp_register_node_name_24xx(ispsoftc_t *, int);
116 static uint16_t isp_next_handle(ispsoftc_t *, uint16_t *);
117 static int isp_fw_state(ispsoftc_t *, int);
118 static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
120 static void isp_setdfltfcparm(ispsoftc_t *, int);
121 static int isp_read_nvram(ispsoftc_t *, int);
122 static int isp_read_nvram_2400(ispsoftc_t *);
123 static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *);
124 static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
127 isp_change_fw_state(ispsoftc_t *isp, int chan, int state)
129 fcparam *fcp = FCPARAM(isp, chan);
131 if (fcp->isp_fwstate == state)
133 isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG,
134 "Chan %d Firmware state <%s->%s>", chan,
135 isp_fc_fw_statename(fcp->isp_fwstate), isp_fc_fw_statename(state));
136 fcp->isp_fwstate = state;
142 * Hit the chip over the head, download new f/w if available and set it running.
144 * Locking done elsewhere.
148 isp_reset(ispsoftc_t *isp, int do_load_defaults)
153 uint32_t code_org, val;
154 int loaded_fw, loops, i, dodnld = 1;
155 const char *btype = "????";
156 static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
158 isp->isp_state = ISP_NILSTATE;
159 ISP_DISABLE_INTS(isp);
162 * Put the board into PAUSE mode (so we can read the SXP registers
163 * or write FPM/FBM registers).
165 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT);
166 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
167 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
169 switch (isp->isp_type) {
187 * Stop DMA and wait for it to stop.
189 ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
190 for (loops = 0; loops < 100000; loops++) {
192 val = ISP_READ(isp, BIU2400_CSR);
193 if ((val & BIU2400_DMA_ACTIVE) == 0) {
197 if (val & BIU2400_DMA_ACTIVE)
198 isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
201 * Hold it in SOFT_RESET and STOP state for 100us.
203 ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
205 for (loops = 0; loops < 10000; loops++) {
207 val = ISP_READ(isp, OUTMAILBOX0);
215 isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
218 isp_prt(isp, ISP_LOGERR, "Board configuration error.");
221 isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
226 * Reset RISC Processor
228 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
229 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE);
230 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET);
233 * Post-RISC Reset stuff.
235 for (loops = 0; loops < 10000; loops++) {
237 val = ISP_READ(isp, OUTMAILBOX0);
245 isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
248 isp_prt(isp, ISP_LOGERR, "Board configuration error.");
251 isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
255 isp->isp_reqidx = isp->isp_reqodx = 0;
257 isp->isp_atioodx = 0;
258 ISP_WRITE(isp, BIU2400_REQINP, 0);
259 ISP_WRITE(isp, BIU2400_REQOUTP, 0);
260 ISP_WRITE(isp, BIU2400_RSPINP, 0);
261 ISP_WRITE(isp, BIU2400_RSPOUTP, 0);
263 ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
264 ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
266 ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
267 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
270 * Up until this point we've done everything by just reading or
271 * setting registers. From this point on we rely on at least *some*
272 * kind of firmware running in the card.
276 * Do some sanity checking by running a NOP command.
277 * If it succeeds, the ROM firmware is now running.
279 MBSINIT(&mbs, MBOX_NO_OP, MBLOGALL, 0);
280 isp_mboxcmd(isp, &mbs);
281 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
282 isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]);
287 * Do some operational tests
290 static const uint16_t patterns[MAX_MAILBOX] = {
291 0x0000, 0xdead, 0xbeef, 0xffff,
292 0xa5a5, 0x5a5a, 0x7f7f, 0x7ff7,
293 0x3421, 0xabcd, 0xdcba, 0xfeef,
294 0xbead, 0xdebe, 0x2222, 0x3333,
295 0x5555, 0x6666, 0x7777, 0xaaaa,
296 0xffff, 0xdddd, 0x9999, 0x1fbc,
297 0x6666, 0x6677, 0x1122, 0x33ff,
298 0x0000, 0x0001, 0x1000, 0x1010,
300 int nmbox = ISP_NMBOX(isp);
301 MBSINIT(&mbs, MBOX_MAILBOX_REG_TEST, MBLOGALL, 0);
302 for (i = 1; i < nmbox; i++) {
303 mbs.param[i] = patterns[i];
305 isp_mboxcmd(isp, &mbs);
306 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
309 for (i = 1; i < nmbox; i++) {
310 if (mbs.param[i] != patterns[i]) {
311 isp_prt(isp, ISP_LOGERR, "Register Test Failed at Register %d: should have 0x%04x but got 0x%04x", i, patterns[i], mbs.param[i]);
318 * Download new Firmware, unless requested not to do so.
319 * This is made slightly trickier in some cases where the
320 * firmware of the ROM revision is newer than the revision
321 * compiled into the driver. So, where we used to compare
322 * versions of our f/w and the ROM f/w, now we just see
323 * whether we have f/w at all and whether a config flag
324 * has disabled our download.
326 if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
331 * Set up DMA for the request and response queues.
332 * We do this now so we can use the request queue
333 * for dma to load firmware from.
335 if (ISP_MBOXDMASETUP(isp) != 0) {
336 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
341 code_org = ISP_CODE_ORG_2400;
344 const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
348 * Keep loading until we run out of f/w.
350 code_org = ptr[2]; /* 1st load address is our start addr */
352 isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
357 while (wi < ptr[3]) {
361 nw = min(wl, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) / 4);
362 cp = isp->isp_rquest;
363 for (i = 0; i < nw; i++)
364 ISP_IOXPUT_32(isp, ptr[wi + i], &cp[i]);
365 MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), -1);
366 MBSINIT(&mbs, MBOX_LOAD_RISC_RAM, MBLOGALL, 0);
368 mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
369 mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
370 mbs.param[4] = nw >> 16;
372 mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
373 mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
374 mbs.param[8] = la >> 16;
375 isp_prt(isp, ISP_LOGDEBUG0, "LOAD RISC RAM %u words at load address 0x%x", nw, la);
376 isp_mboxcmd(isp, &mbs);
377 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
378 isp_prt(isp, ISP_LOGERR, "F/W download failed");
392 } else if (IS_26XX(isp)) {
393 isp_prt(isp, ISP_LOGDEBUG1, "loading firmware from flash");
394 MBSINIT(&mbs, MBOX_LOAD_FLASH_FIRMWARE, MBLOGALL, 5000000);
397 isp_mboxcmd(isp, &mbs);
398 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
399 isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
403 isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
407 * If we loaded firmware, verify its checksum
410 MBSINIT(&mbs, MBOX_VERIFY_CHECKSUM, MBLOGNONE, 0);
411 mbs.param[1] = code_org >> 16;
412 mbs.param[2] = code_org;
413 isp_mboxcmd(isp, &mbs);
414 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
415 isp_prt(isp, ISP_LOGERR, dcrc);
421 * Now start it rolling.
423 * If we didn't actually download f/w,
424 * we still need to (re)start it.
426 MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000);
427 mbs.param[1] = code_org >> 16;
428 mbs.param[2] = code_org;
430 mbs.param[3] = loaded_fw ? 0 : 1;
431 isp_mboxcmd(isp, &mbs);
432 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
436 * Ask the chip for the current firmware version.
437 * This should prove that the new firmware is working.
439 MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 5000000);
440 isp_mboxcmd(isp, &mbs);
441 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
445 isp->isp_fwrev[0] = mbs.param[1];
446 isp->isp_fwrev[1] = mbs.param[2];
447 isp->isp_fwrev[2] = mbs.param[3];
448 isp->isp_fwattr = mbs.param[6];
449 isp->isp_fwattr |= ((uint64_t) mbs.param[15]) << 16;
450 if (isp->isp_fwattr & ISP2400_FW_ATTR_EXTNDED) {
452 (((uint64_t) mbs.param[16]) << 32) |
453 (((uint64_t) mbs.param[17]) << 48);
456 isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
457 btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
459 fwt = isp->isp_fwattr;
460 buf = FCPARAM(isp, 0)->isp_scanscratch;
461 ISP_SNPRINTF(buf, ISP_FC_SCRLEN, "Attributes:");
462 if (fwt & ISP2400_FW_ATTR_CLASS2) {
463 fwt ^=ISP2400_FW_ATTR_CLASS2;
464 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s Class2", buf);
466 if (fwt & ISP2400_FW_ATTR_IP) {
467 fwt ^=ISP2400_FW_ATTR_IP;
468 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s IP", buf);
470 if (fwt & ISP2400_FW_ATTR_MULTIID) {
471 fwt ^=ISP2400_FW_ATTR_MULTIID;
472 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MultiID", buf);
474 if (fwt & ISP2400_FW_ATTR_SB2) {
475 fwt ^=ISP2400_FW_ATTR_SB2;
476 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SB2", buf);
478 if (fwt & ISP2400_FW_ATTR_T10CRC) {
479 fwt ^=ISP2400_FW_ATTR_T10CRC;
480 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s T10CRC", buf);
482 if (fwt & ISP2400_FW_ATTR_VI) {
483 fwt ^=ISP2400_FW_ATTR_VI;
484 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VI", buf);
486 if (fwt & ISP2400_FW_ATTR_MQ) {
487 fwt ^=ISP2400_FW_ATTR_MQ;
488 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MQ", buf);
490 if (fwt & ISP2400_FW_ATTR_MSIX) {
491 fwt ^=ISP2400_FW_ATTR_MSIX;
492 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MSIX", buf);
494 if (fwt & ISP2400_FW_ATTR_FCOE) {
495 fwt ^=ISP2400_FW_ATTR_FCOE;
496 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s FCOE", buf);
498 if (fwt & ISP2400_FW_ATTR_VP0) {
499 fwt ^= ISP2400_FW_ATTR_VP0;
500 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VP0_Decoupling", buf);
502 if (fwt & ISP2400_FW_ATTR_EXPFW) {
503 fwt ^= ISP2400_FW_ATTR_EXPFW;
504 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (Experimental)", buf);
506 if (fwt & ISP2400_FW_ATTR_HOTFW) {
507 fwt ^= ISP2400_FW_ATTR_HOTFW;
508 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s HotFW", buf);
510 fwt &= ~ISP2400_FW_ATTR_EXTNDED;
511 if (fwt & ISP2400_FW_ATTR_EXTVP) {
512 fwt ^= ISP2400_FW_ATTR_EXTVP;
513 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ExtVP", buf);
515 if (fwt & ISP2400_FW_ATTR_VN2VN) {
516 fwt ^= ISP2400_FW_ATTR_VN2VN;
517 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VN2VN", buf);
519 if (fwt & ISP2400_FW_ATTR_EXMOFF) {
520 fwt ^= ISP2400_FW_ATTR_EXMOFF;
521 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s EXMOFF", buf);
523 if (fwt & ISP2400_FW_ATTR_NPMOFF) {
524 fwt ^= ISP2400_FW_ATTR_NPMOFF;
525 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s NPMOFF", buf);
527 if (fwt & ISP2400_FW_ATTR_DIFCHOP) {
528 fwt ^= ISP2400_FW_ATTR_DIFCHOP;
529 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s DIFCHOP", buf);
531 if (fwt & ISP2400_FW_ATTR_SRIOV) {
532 fwt ^= ISP2400_FW_ATTR_SRIOV;
533 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SRIOV", buf);
535 if (fwt & ISP2400_FW_ATTR_ASICTMP) {
536 fwt ^= ISP2400_FW_ATTR_ASICTMP;
537 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ASICTMP", buf);
539 if (fwt & ISP2400_FW_ATTR_ATIOMQ) {
540 fwt ^= ISP2400_FW_ATTR_ATIOMQ;
541 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ATIOMQ", buf);
544 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (unknown 0x%08x%08x)", buf,
545 (uint32_t) (fwt >> 32), (uint32_t) fwt);
547 isp_prt(isp, ISP_LOGCONFIG, "%s", buf);
550 * For the maximum number of commands take free exchange control block
551 * buffer count reported by firmware, limiting it to the maximum of our
552 * hardcoded handle format (16K now) minus some management reserve.
554 MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
555 isp_mboxcmd(isp, &mbs);
556 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
558 isp->isp_maxcmds = MIN(mbs.param[3], ISP_HANDLE_MAX - ISP_HANDLE_RESERVE);
559 isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
562 * If we don't have Multi-ID f/w loaded, we need to restrict channels to one.
563 * Only make this check for non-SCSI cards (I'm not sure firmware attributes
566 if (isp->isp_nchan > 1) {
567 if (!ISP_CAP_MULTI_ID(isp)) {
568 isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, "
569 "only can enable 1 of %d channels", isp->isp_nchan);
571 } else if (!ISP_CAP_VP0(isp)) {
572 isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID "
573 "feature properly without VP0_Decoupling");
579 * Final DMA setup after we got isp_maxcmds.
581 if (ISP_MBOXDMASETUP(isp) != 0) {
582 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
589 if (ISP_IRQSETUP(isp) != 0) {
590 isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ");
593 ISP_ENABLE_INTS(isp);
595 for (i = 0; i < isp->isp_nchan; i++)
596 isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
598 isp->isp_state = ISP_RESETSTATE;
601 * We get some default values established. As a side
602 * effect, NVRAM is read here (unless overriden by
603 * a configuration flag).
605 if (do_load_defaults) {
606 for (i = 0; i < isp->isp_nchan; i++)
607 isp_setdfltfcparm(isp, i);
612 * Clean firmware shutdown.
615 isp_stop(ispsoftc_t *isp)
619 isp->isp_state = ISP_NILSTATE;
620 MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000);
629 isp_mboxcmd(isp, &mbs);
630 return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]);
637 isp_shutdown(ispsoftc_t *isp)
640 if (isp->isp_state >= ISP_RESETSTATE)
642 ISP_DISABLE_INTS(isp);
643 ISP_WRITE(isp, BIU2400_ICR, 0);
644 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
648 * Initialize Parameters of Hardware to a known state.
650 * Locks are held before coming here.
653 isp_init(ispsoftc_t *isp)
656 isp_icb_2400_t local, *icbp = &local;
662 * Check to see whether all channels have *some* kind of role
664 for (chan = 0; chan < isp->isp_nchan; chan++) {
665 fcp = FCPARAM(isp, chan);
666 if (fcp->role != ISP_ROLE_NONE) {
670 if (chan == isp->isp_nchan) {
671 isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan);
675 isp->isp_state = ISP_INITSTATE;
678 * Start with channel 0.
680 fcp = FCPARAM(isp, 0);
683 * Turn on LIP F8 async event (1)
685 MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
687 isp_mboxcmd(isp, &mbs);
688 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
692 ISP_MEMZERO(icbp, sizeof (*icbp));
693 icbp->icb_fwoptions1 = fcp->isp_fwoptions;
694 icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
695 icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
696 if (isp->isp_nchan > 1 && ISP_CAP_VP0(isp)) {
697 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
698 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
700 if (fcp->role & ISP_ROLE_TARGET)
701 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
703 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
704 if (fcp->role & ISP_ROLE_INITIATOR)
705 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
707 icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
710 icbp->icb_version = ICB_VERSION1;
711 icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
712 if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
713 isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
714 icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
718 icbp->icb_execthrottle = 0xffff;
720 #ifdef ISP_TARGET_MODE
722 * Set target exchange count. Take half if we are supporting both roles.
724 if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) {
725 if ((icbp->icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE) == 0)
726 icbp->icb_xchgcnt = MIN(isp->isp_maxcmds / 2, ATPDPSIZE);
728 icbp->icb_xchgcnt = isp->isp_maxcmds;
732 ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
733 icbp->icb_hardaddr = fcp->isp_loopid;
734 if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
735 icbp->icb_hardaddr = 0;
740 icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
742 if (isp->isp_confopts & ISP_CFG_NOFCTAPE) {
743 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
745 if (isp->isp_confopts & ISP_CFG_FCTAPE) {
746 icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE;
749 for (chan = 0; chan < isp->isp_nchan; chan++) {
750 if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE)
751 FCPARAM(isp, chan)->fctape_enabled = 1;
753 FCPARAM(isp, chan)->fctape_enabled = 0;
756 switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
757 case ISP_CFG_LPORT_ONLY:
758 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
759 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY;
761 case ISP_CFG_NPORT_ONLY:
762 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
763 icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
766 /* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */
768 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
769 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
772 /* Let NVRAM settings define it if they are sane */
773 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK) {
774 case ICB2400_OPT2_LOOP_ONLY:
775 case ICB2400_OPT2_PTP_ONLY:
776 case ICB2400_OPT2_LOOP_2_PTP:
779 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
780 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
785 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
786 case ICB2400_OPT2_ZIO:
787 case ICB2400_OPT2_ZIO1:
788 icbp->icb_idelaytimer = 0;
793 isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
794 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
799 /* Use handshake to reduce global lock congestion. */
800 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR;
801 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA;
804 if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) {
805 icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24;
807 if (isp->isp_confopts & ISP_CFG_1GB) {
808 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
809 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB;
810 } else if (isp->isp_confopts & ISP_CFG_2GB) {
811 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
812 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB;
813 } else if (isp->isp_confopts & ISP_CFG_4GB) {
814 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
815 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB;
816 } else if (isp->isp_confopts & ISP_CFG_8GB) {
817 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
818 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB;
819 } else if (isp->isp_confopts & ISP_CFG_16GB) {
820 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
821 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB;
822 } else if (isp->isp_confopts & ISP_CFG_32GB) {
823 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
824 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB;
826 switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) {
827 case ICB2400_OPT3_RATE_4GB:
828 case ICB2400_OPT3_RATE_8GB:
829 case ICB2400_OPT3_RATE_16GB:
830 case ICB2400_OPT3_RATE_32GB:
831 case ICB2400_OPT3_RATE_AUTO:
833 case ICB2400_OPT3_RATE_2GB:
834 if (isp->isp_type <= ISP_HA_FC_2500)
837 case ICB2400_OPT3_RATE_1GB:
838 if (isp->isp_type <= ISP_HA_FC_2400)
842 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
843 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
847 if (ownloopid == 0) {
848 icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
850 icbp->icb_logintime = ICB_LOGIN_TOV;
852 if (fcp->isp_wwnn && fcp->isp_wwpn) {
853 icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
854 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
855 MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
856 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)),
857 ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
858 } else if (fcp->isp_wwpn) {
859 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
860 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
861 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)));
863 isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
866 icbp->icb_rspnsin = isp->isp_resodx;
867 icbp->icb_rqstout = isp->isp_reqidx;
868 icbp->icb_retry_count = fcp->isp_retry_count;
870 icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
871 if (icbp->icb_rqstqlen < 8) {
872 isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen);
875 icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
876 if (icbp->icb_rsltqlen < 8) {
877 isp_prt(isp, ISP_LOGERR, "bad result queue length %d",
881 icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
882 icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
883 icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
884 icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
886 icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
887 icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
888 icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
889 icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
891 #ifdef ISP_TARGET_MODE
892 /* unconditionally set up the ATIO queue if we support target mode */
893 icbp->icb_atio_in = isp->isp_atioodx;
894 icbp->icb_atioqlen = ATIO_QUEUE_LEN(isp);
895 if (icbp->icb_atioqlen < 8) {
896 isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen);
899 icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
900 icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
901 icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
902 icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
903 isp_prt(isp, ISP_LOGDEBUG0, "isp_init: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
904 DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
907 if (ISP_CAP_MSIX(isp) && isp->isp_nirq >= 2) {
908 icbp->icb_msixresp = 1;
909 if (IS_26XX(isp) && isp->isp_nirq >= 3)
910 icbp->icb_msixatio = 2;
913 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);
915 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),
916 DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
917 DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
919 if (FC_SCRATCH_ACQUIRE(isp, 0)) {
920 isp_prt(isp, ISP_LOGERR, sacq);
923 ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
924 isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
925 if (isp->isp_dblev & ISP_LOGDEBUG1) {
926 isp_print_bytes(isp, "isp_init",
927 sizeof (*icbp), fcp->isp_scratch);
931 * Now fill in information about any additional channels
933 if (isp->isp_nchan > 1) {
934 isp_icb_2400_vpinfo_t vpinfo, *vdst;
935 vp_port_info_t pi, *pdst;
939 vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA;
940 if (ISP_CAP_VP0(isp)) {
941 vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE;
942 vpinfo.vp_count = isp->isp_nchan;
945 vpinfo.vp_count = isp->isp_nchan - 1;
948 off = fcp->isp_scratch;
949 off += ICB2400_VPINFO_OFF;
950 vdst = (isp_icb_2400_vpinfo_t *) off;
951 isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst);
952 amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t);
953 for (; chan < isp->isp_nchan; chan++) {
956 ISP_MEMZERO(&pi, sizeof (pi));
957 fcp2 = FCPARAM(isp, chan);
958 if (fcp2->role != ISP_ROLE_NONE) {
959 pi.vp_port_options = ICB2400_VPOPT_ENABLED |
960 ICB2400_VPOPT_ENA_SNSLOGIN;
961 if (fcp2->role & ISP_ROLE_INITIATOR)
962 pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
963 if ((fcp2->role & ISP_ROLE_TARGET) == 0)
964 pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE;
965 if (fcp2->isp_loopid < LOCAL_LOOP_LIM) {
966 pi.vp_port_loopid = fcp2->isp_loopid;
967 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
968 pi.vp_port_options |= ICB2400_VPOPT_HARD_ADDRESS;
972 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn);
973 MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn);
974 off = fcp->isp_scratch;
975 if (ISP_CAP_VP0(isp))
976 off += ICB2400_VPINFO_PORT_OFF(chan);
978 off += ICB2400_VPINFO_PORT_OFF(chan - 1);
979 pdst = (vp_port_info_t *) off;
980 isp_put_vp_port_info(isp, &pi, pdst);
981 amt += ICB2400_VPOPT_WRITE_SIZE;
983 if (isp->isp_dblev & ISP_LOGDEBUG1) {
984 isp_print_bytes(isp, "isp_init",
985 amt - ICB2400_VPINFO_OFF,
986 (char *)fcp->isp_scratch + ICB2400_VPINFO_OFF);
993 MBSINIT(&mbs, 0, MBLOGALL, 30000000);
994 if (isp->isp_nchan > 1) {
995 mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
997 mbs.param[0] = MBOX_INIT_FIRMWARE;
1000 mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1001 mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1002 mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1003 mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1004 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));
1005 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp), 0);
1006 isp_mboxcmd(isp, &mbs);
1007 FC_SCRATCH_RELEASE(isp, 0);
1009 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1014 * Whatever happens, we're now committed to being here.
1016 isp->isp_state = ISP_RUNSTATE;
1020 isp_fc_enable_vp(ispsoftc_t *isp, int chan)
1022 fcparam *fcp = FCPARAM(isp, chan);
1026 /* Build a VP MODIFY command in memory */
1027 ISP_MEMZERO(&vp, sizeof(vp));
1028 vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
1029 vp.vp_mod_hdr.rqs_entry_count = 1;
1031 vp.vp_mod_idx0 = chan;
1032 vp.vp_mod_cmd = VP_MODIFY_ENA;
1033 vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
1034 ICB2400_VPOPT_ENA_SNSLOGIN;
1035 if (fcp->role & ISP_ROLE_INITIATOR)
1036 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
1037 if ((fcp->role & ISP_ROLE_TARGET) == 0)
1038 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
1039 if (fcp->isp_loopid < LOCAL_LOOP_LIM) {
1040 vp.vp_mod_ports[0].loopid = fcp->isp_loopid;
1041 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
1042 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS;
1044 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn);
1045 MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn);
1047 retval = isp_exec_entry_queue(isp, &vp, &vp, 5);
1049 isp_prt(isp, ISP_LOGERR, "%s: VP_MODIFY of chan %d error %d",
1050 __func__, chan, retval);
1054 if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) {
1055 isp_prt(isp, ISP_LOGERR,
1056 "%s: VP_MODIFY of Chan %d failed with flags %x status %d",
1057 __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status);
1064 isp_fc_disable_vp(ispsoftc_t *isp, int chan)
1069 /* Build a VP CTRL command in memory */
1070 ISP_MEMZERO(&vp, sizeof(vp));
1071 vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
1072 vp.vp_ctrl_hdr.rqs_entry_count = 1;
1073 if (ISP_CAP_VP0(isp)) {
1074 vp.vp_ctrl_status = 1;
1076 vp.vp_ctrl_status = 0;
1077 chan--; /* VP0 can not be controlled in this case. */
1079 vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
1080 vp.vp_ctrl_vp_count = 1;
1081 vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
1083 retval = isp_exec_entry_queue(isp, &vp, &vp, 5);
1085 isp_prt(isp, ISP_LOGERR, "%s: VP_CTRL of chan %d error %d",
1086 __func__, chan, retval);
1090 if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) {
1091 isp_prt(isp, ISP_LOGERR,
1092 "%s: VP_CTRL of Chan %d failed with flags %x status %d %d",
1093 __func__, chan, vp.vp_ctrl_hdr.rqs_flags,
1094 vp.vp_ctrl_status, vp.vp_ctrl_index_fail);
1101 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
1103 fcparam *fcp = FCPARAM(isp, chan);
1104 int i, was, res = 0;
1106 if (chan >= isp->isp_nchan) {
1107 isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan);
1110 if (fcp->role == new_role)
1112 for (was = 0, i = 0; i < isp->isp_nchan; i++) {
1113 if (FCPARAM(isp, i)->role != ISP_ROLE_NONE)
1116 if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) {
1117 fcp->role = new_role;
1118 return (isp_reinit(isp, 0));
1120 if (fcp->role != ISP_ROLE_NONE) {
1121 res = isp_fc_disable_vp(isp, chan);
1122 isp_clear_portdb(isp, chan);
1124 fcp->role = new_role;
1125 if (fcp->role != ISP_ROLE_NONE)
1126 res = isp_fc_enable_vp(isp, chan);
1131 isp_clear_portdb(ispsoftc_t *isp, int chan)
1133 fcparam *fcp = FCPARAM(isp, chan);
1137 for (i = 0; i < MAX_FC_TARG; i++) {
1138 lp = &fcp->portdb[i];
1139 switch (lp->state) {
1140 case FC_PORTDB_STATE_DEAD:
1141 case FC_PORTDB_STATE_CHANGED:
1142 case FC_PORTDB_STATE_VALID:
1143 lp->state = FC_PORTDB_STATE_NIL;
1144 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1146 case FC_PORTDB_STATE_NIL:
1147 case FC_PORTDB_STATE_NEW:
1148 lp->state = FC_PORTDB_STATE_NIL;
1150 case FC_PORTDB_STATE_ZOMBIE:
1153 panic("Don't know how to clear state %d\n", lp->state);
1159 isp_mark_portdb(ispsoftc_t *isp, int chan)
1161 fcparam *fcp = FCPARAM(isp, chan);
1165 for (i = 0; i < MAX_FC_TARG; i++) {
1166 lp = &fcp->portdb[i];
1167 if (lp->state == FC_PORTDB_STATE_NIL)
1169 if (lp->portid >= DOMAIN_CONTROLLER_BASE &&
1170 lp->portid <= DOMAIN_CONTROLLER_END)
1172 fcp->portdb[i].probational = 1;
1177 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
1178 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
1181 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags)
1184 uint32_t sst, parm1;
1189 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x",
1190 chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ?
1191 "Login":"Logout", portid, handle);
1193 ISP_MEMZERO(&pl, sizeof(pl));
1194 pl.plogx_header.rqs_entry_count = 1;
1195 pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
1196 pl.plogx_nphdl = handle;
1197 pl.plogx_vphdl = chan;
1198 pl.plogx_portlo = portid;
1199 pl.plogx_rspsz_porthi = (portid >> 16) & 0xff;
1200 pl.plogx_flags = flags;
1202 retval = isp_exec_entry_queue(isp, &pl, &pl, 3 * ICB_LOGIN_TOV);
1204 isp_prt(isp, ISP_LOGERR, "%s: PLOGX of chan %d error %d",
1205 __func__, chan, retval);
1209 if (pl.plogx_status == PLOGX_STATUS_OK) {
1211 } else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) {
1212 isp_prt(isp, ISP_LOGWARN,
1213 "status 0x%x on port login IOCB channel %d",
1214 pl.plogx_status, chan);
1218 sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16);
1219 parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16);
1226 case PLOGX_IOCBERR_NOLINK:
1229 case PLOGX_IOCBERR_NOIOCB:
1230 msg = "no IOCB buffer";
1232 case PLOGX_IOCBERR_NOXGHG:
1233 msg = "no Exchange Control Block";
1235 case PLOGX_IOCBERR_FAILED:
1236 ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff);
1239 case PLOGX_IOCBERR_NOFABRIC:
1242 case PLOGX_IOCBERR_NOTREADY:
1243 msg = "firmware not ready";
1245 case PLOGX_IOCBERR_NOLOGIN:
1246 ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1);
1248 retval = MBOX_NOT_LOGGED_IN;
1250 case PLOGX_IOCBERR_REJECT:
1251 ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
1254 case PLOGX_IOCBERR_NOPCB:
1255 msg = "no PCB allocated";
1257 case PLOGX_IOCBERR_EINVAL:
1258 ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1);
1261 case PLOGX_IOCBERR_PORTUSED:
1262 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1263 ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1);
1265 retval = MBOX_PORT_ID_USED | (parm1 << 16);
1267 case PLOGX_IOCBERR_HNDLUSED:
1268 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1269 ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1);
1271 retval = MBOX_LOOP_ID_USED;
1273 case PLOGX_IOCBERR_NOHANDLE:
1274 msg = "no handle allocated";
1276 case PLOGX_IOCBERR_NOFLOGI:
1277 msg = "no FLOGI_ACC";
1280 ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags);
1285 isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
1286 chan, portid, handle, msg);
1292 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb)
1296 isp_pdb_24xx_t bill;
1299 MBSINIT(&mbs, MBOX_GET_PORT_DB,
1300 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000);
1301 mbs.ibits = (1 << 9)|(1 << 10);
1303 mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
1304 mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
1305 mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
1306 mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
1307 mbs.param[9] = chan;
1308 MEMORYBARRIER(isp, SYNC_IFORDEV, 0, sizeof(un), chan);
1310 isp_mboxcmd(isp, &mbs);
1311 if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
1312 return (mbs.param[0] | (mbs.param[1] << 16));
1314 MEMORYBARRIER(isp, SYNC_IFORCPU, 0, sizeof(un), chan);
1315 isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill);
1316 pdb->handle = un.bill.pdb_handle;
1317 pdb->prli_word0 = un.bill.pdb_prli_svc0;
1318 pdb->prli_word3 = un.bill.pdb_prli_svc3;
1319 pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
1320 ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
1321 ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
1322 isp_prt(isp, ISP_LOGDEBUG0,
1323 "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x",
1324 chan, id, pdb->portid, un.bill.pdb_flags,
1325 un.bill.pdb_curstate, un.bill.pdb_laststate);
1327 if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
1328 mbs.param[0] = MBOX_NOT_LOGGED_IN;
1329 return (mbs.param[0]);
1335 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop)
1337 fcparam *fcp = FCPARAM(isp, chan);
1339 isp_pnhle_24xx_t el4, *elp4;
1343 MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL, 250000);
1344 mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1345 mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1346 mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1347 mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1348 mbs.param[8] = ISP_FC_SCRLEN;
1349 mbs.param[9] = chan;
1350 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1351 isp_prt(isp, ISP_LOGERR, sacq);
1354 MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan);
1355 isp_mboxcmd(isp, &mbs);
1356 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1357 FC_SCRATCH_RELEASE(isp, chan);
1358 return (mbs.param[0] | (mbs.param[1] << 16));
1360 MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan);
1361 elp4 = fcp->isp_scratch;
1362 for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) {
1363 isp_get_pnhle_24xx(isp, &elp4[i], &el4);
1364 p = el4.pnhle_port_id_lo | (el4.pnhle_port_id_hi << 16);
1365 if (loop && (p >> 8) != (fcp->isp_portid >> 8))
1367 handles[j++] = el4.pnhle_handle;
1370 FC_SCRATCH_RELEASE(isp, chan);
1375 isp_dump_chip_portdb(ispsoftc_t *isp, int chan)
1380 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan);
1381 for (nphdl = 0; nphdl != NPH_MAX_2K; nphdl++) {
1382 if (isp_getpdb(isp, chan, nphdl, &pdb)) {
1385 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x "
1386 "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
1387 chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1],
1388 pdb.portname[2], pdb.portname[3], pdb.portname[4],
1389 pdb.portname[5], pdb.portname[6], pdb.portname[7]);
1394 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename)
1396 uint64_t wwn = INI_NONE;
1399 MBSINIT(&mbs, MBOX_GET_PORT_NAME,
1400 MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
1401 mbs.param[1] = nphdl;
1404 mbs.param[9] = chan;
1405 isp_mboxcmd(isp, &mbs);
1406 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1409 wwn = (((uint64_t)(mbs.param[2] >> 8)) << 56) |
1410 (((uint64_t)(mbs.param[2] & 0xff))<< 48) |
1411 (((uint64_t)(mbs.param[3] >> 8)) << 40) |
1412 (((uint64_t)(mbs.param[3] & 0xff))<< 32) |
1413 (((uint64_t)(mbs.param[6] >> 8)) << 24) |
1414 (((uint64_t)(mbs.param[6] & 0xff))<< 16) |
1415 (((uint64_t)(mbs.param[7] >> 8)) << 8) |
1416 (((uint64_t)(mbs.param[7] & 0xff)));
1421 * Make sure we have good FC link.
1425 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
1431 NANOTIME_T hra, hrb;
1433 fcp = FCPARAM(isp, chan);
1435 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1437 if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
1440 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
1443 * Wait up to N microseconds for F/W to go to a ready state.
1447 isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
1448 if (fcp->isp_fwstate == FW_READY) {
1451 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1454 if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
1456 ISP_SLEEP(isp, 1000);
1458 if (fcp->isp_fwstate != FW_READY) {
1459 isp_prt(isp, ISP_LOG_SANCFG,
1460 "Chan %d Firmware is not ready (%s)",
1461 chan, isp_fc_fw_statename(fcp->isp_fwstate));
1466 * Get our Loop ID and Port ID.
1468 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
1469 mbs.param[9] = chan;
1470 isp_mboxcmd(isp, &mbs);
1471 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1475 topo = (int) mbs.param[6];
1476 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
1477 topo = TOPO_PTP_STUB;
1478 fcp->isp_topo = topo;
1479 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
1481 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
1482 fcp->isp_loopid = mbs.param[1] & 0xff;
1483 } else if (fcp->isp_topo != TOPO_F_PORT) {
1484 uint8_t alpa = fcp->isp_portid;
1486 for (i = 0; alpa_map[i]; i++) {
1487 if (alpa_map[i] == alpa)
1491 fcp->isp_loopid = i;
1495 fcp->isp_loopstate = LOOP_HAVE_ADDR;
1497 fcp->isp_loopstate = LOOP_TESTING_LINK;
1499 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
1500 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
1501 if (r != 0 || pdb.portid == 0) {
1502 isp_prt(isp, ISP_LOGWARN,
1503 "fabric topology, but cannot get info about fabric controller (0x%x)", r);
1504 fcp->isp_topo = TOPO_PTP_STUB;
1508 fcp->isp_fabric_params = mbs.param[7];
1509 fcp->isp_sns_hdl = NPH_SNS_ID;
1510 r = isp_register_fc4_type(isp, chan);
1511 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1515 r = isp_register_fc4_features_24xx(isp, chan);
1516 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1520 r = isp_register_port_name_24xx(isp, chan);
1521 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1525 isp_register_node_name_24xx(isp, chan);
1526 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1531 /* Get link speed. */
1532 fcp->isp_gbspeed = 1;
1533 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
1534 mbs.param[1] = MBGSD_GET_RATE;
1535 /* mbs.param[2] undefined if we're just getting rate */
1536 isp_mboxcmd(isp, &mbs);
1537 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
1538 if (mbs.param[1] == MBGSD_10GB)
1539 fcp->isp_gbspeed = 10;
1540 else if (mbs.param[1] == MBGSD_32GB)
1541 fcp->isp_gbspeed = 32;
1542 else if (mbs.param[1] == MBGSD_16GB)
1543 fcp->isp_gbspeed = 16;
1544 else if (mbs.param[1] == MBGSD_8GB)
1545 fcp->isp_gbspeed = 8;
1546 else if (mbs.param[1] == MBGSD_4GB)
1547 fcp->isp_gbspeed = 4;
1548 else if (mbs.param[1] == MBGSD_2GB)
1549 fcp->isp_gbspeed = 2;
1550 else if (mbs.param[1] == MBGSD_1GB)
1551 fcp->isp_gbspeed = 1;
1554 if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
1556 isp_prt(isp, ISP_LOG_SANCFG,
1557 "Chan %d FC link test aborted", chan);
1560 fcp->isp_loopstate = LOOP_LTEST_DONE;
1561 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1562 "Chan %d WWPN %016jx WWNN %016jx",
1563 chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn);
1564 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1565 "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x",
1566 chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid,
1568 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
1573 * Complete the synchronization of our Port Database.
1575 * At this point, we've scanned the local loop (if any) and the fabric
1576 * and performed fabric logins on all new devices.
1578 * Our task here is to go through our port database removing any entities
1579 * that are still marked probational (issuing PLOGO for ones which we had
1580 * PLOGI'd into) or are dead, and notifying upper layers about new/changed
1584 isp_pdb_sync(ispsoftc_t *isp, int chan)
1586 fcparam *fcp = FCPARAM(isp, chan);
1590 if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
1592 if (fcp->isp_loopstate >= LOOP_READY)
1595 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
1597 fcp->isp_loopstate = LOOP_SYNCING_PDB;
1599 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
1600 lp = &fcp->portdb[dbidx];
1602 if (lp->state == FC_PORTDB_STATE_NIL)
1604 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE)
1605 lp->state = FC_PORTDB_STATE_DEAD;
1606 switch (lp->state) {
1607 case FC_PORTDB_STATE_DEAD:
1608 lp->state = FC_PORTDB_STATE_NIL;
1609 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1610 if ((lp->portid & 0xffff00) != 0) {
1611 (void) isp_plogx(isp, chan, lp->handle,
1613 PLOGX_FLG_CMD_LOGO |
1614 PLOGX_FLG_IMPLICIT |
1615 PLOGX_FLG_FREE_NPHDL);
1618 * Note that we might come out of this with our state
1619 * set to FC_PORTDB_STATE_ZOMBIE.
1622 case FC_PORTDB_STATE_NEW:
1623 lp->state = FC_PORTDB_STATE_VALID;
1624 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
1626 case FC_PORTDB_STATE_CHANGED:
1627 lp->state = FC_PORTDB_STATE_VALID;
1628 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
1629 lp->portid = lp->new_portid;
1630 lp->prli_word0 = lp->new_prli_word0;
1631 lp->prli_word3 = lp->new_prli_word3;
1633 case FC_PORTDB_STATE_VALID:
1634 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
1636 case FC_PORTDB_STATE_ZOMBIE:
1639 isp_prt(isp, ISP_LOGWARN,
1640 "isp_pdb_sync: state %d for idx %d",
1642 isp_dump_portdb(isp, chan);
1646 if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
1647 isp_prt(isp, ISP_LOG_SANCFG,
1648 "Chan %d FC PDB sync aborted", chan);
1652 fcp->isp_loopstate = LOOP_READY;
1653 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
1658 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
1661 uint64_t wwnn, wwpn;
1663 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
1664 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
1666 /* Search port database for the same WWPN. */
1667 if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) {
1668 if (!lp->probational) {
1669 isp_prt(isp, ISP_LOGERR,
1670 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
1671 chan, lp->portid, lp->handle,
1672 FC_PORTDB_TGT(isp, chan, lp), lp->state);
1673 isp_dump_portdb(isp, chan);
1676 lp->probational = 0;
1677 lp->node_wwn = wwnn;
1679 /* Old device, nothing new. */
1680 if (lp->portid == pdb->portid &&
1681 lp->handle == pdb->handle &&
1682 lp->prli_word3 == pdb->prli_word3 &&
1683 ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) ==
1684 (lp->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR))) {
1685 if (lp->state != FC_PORTDB_STATE_NEW)
1686 lp->state = FC_PORTDB_STATE_VALID;
1687 isp_prt(isp, ISP_LOG_SANCFG,
1688 "Chan %d Port 0x%06x@0x%04x is valid",
1689 chan, pdb->portid, pdb->handle);
1693 /* Something has changed. */
1694 lp->state = FC_PORTDB_STATE_CHANGED;
1695 lp->handle = pdb->handle;
1696 lp->new_portid = pdb->portid;
1697 lp->new_prli_word0 = pdb->prli_word0;
1698 lp->new_prli_word3 = pdb->prli_word3;
1699 isp_prt(isp, ISP_LOG_SANCFG,
1700 "Chan %d Port 0x%06x@0x%04x is changed",
1701 chan, pdb->portid, pdb->handle);
1705 /* It seems like a new port. Find an empty slot for it. */
1706 if (!isp_find_pdb_empty(isp, chan, &lp)) {
1707 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan);
1711 ISP_MEMZERO(lp, sizeof (fcportdb_t));
1712 lp->probational = 0;
1713 lp->state = FC_PORTDB_STATE_NEW;
1714 lp->portid = lp->new_portid = pdb->portid;
1715 lp->prli_word0 = lp->new_prli_word0 = pdb->prli_word0;
1716 lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3;
1717 lp->handle = pdb->handle;
1718 lp->port_wwn = wwpn;
1719 lp->node_wwn = wwnn;
1720 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new",
1721 chan, pdb->portid, pdb->handle);
1725 * Scan local loop for devices.
1728 isp_scan_loop(ispsoftc_t *isp, int chan)
1730 fcparam *fcp = FCPARAM(isp, chan);
1736 if (fcp->isp_loopstate < LOOP_LTEST_DONE)
1738 if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
1741 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
1742 fcp->isp_loopstate = LOOP_SCANNING_LOOP;
1743 if (TOPO_IS_FABRIC(fcp->isp_topo)) {
1744 isp_prt(isp, ISP_LOG_SANCFG,
1745 "Chan %d FC loop scan done (no loop)", chan);
1746 fcp->isp_loopstate = LOOP_LSCAN_DONE;
1750 handles = (uint16_t *)fcp->isp_scanscratch;
1751 lim = ISP_FC_SCRLEN / 2;
1752 r = isp_gethandles(isp, chan, handles, &lim, 1);
1754 isp_prt(isp, ISP_LOG_SANCFG,
1755 "Chan %d Getting list of handles failed with %x", chan, r);
1756 isp_prt(isp, ISP_LOG_SANCFG,
1757 "Chan %d FC loop scan done (bad)", chan);
1761 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
1765 * Run through the list and get the port database info for each one.
1767 isp_mark_portdb(isp, chan);
1768 for (idx = 0; idx < lim; idx++) {
1769 handle = handles[idx];
1772 * Don't scan "special" ids.
1774 if (handle >= NPH_RESERVED)
1778 * Get the port database entity for this index.
1780 r = isp_getpdb(isp, chan, handle, &pdb);
1781 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
1783 isp_prt(isp, ISP_LOG_SANCFG,
1784 "Chan %d FC loop scan aborted", chan);
1788 isp_prt(isp, ISP_LOGDEBUG1,
1789 "Chan %d FC Scan Loop handle %d returned %x",
1794 isp_pdb_add_update(isp, chan, &pdb);
1796 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
1798 fcp->isp_loopstate = LOOP_LSCAN_DONE;
1799 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
1804 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
1806 fcparam *fcp = FCPARAM(isp, chan);
1810 if (isp->isp_dblev & ISP_LOGDEBUG1)
1811 isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch);
1814 * Build a Passthrough IOCB in memory.
1816 ISP_MEMZERO(&pt, sizeof(pt));
1817 pt.ctp_header.rqs_entry_count = 1;
1818 pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
1819 pt.ctp_nphdl = fcp->isp_sns_hdl;
1821 pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
1824 pt.ctp_rsp_bcnt = rsp_bcnt;
1825 pt.ctp_cmd_bcnt = cmd_bcnt;
1826 pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma);
1827 pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma);
1828 pt.ctp_dataseg[0].ds_count = cmd_bcnt;
1829 pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
1830 pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
1831 pt.ctp_dataseg[1].ds_count = rsp_bcnt;
1833 retval = isp_exec_entry_queue(isp, &pt, &pt, 2 * pt.ctp_time);
1835 isp_prt(isp, ISP_LOGERR, "%s: CTP of chan %d error %d",
1836 __func__, chan, retval);
1840 if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
1841 isp_prt(isp, ISP_LOGWARN,
1842 "Chan %d CT pass-through returned 0x%x",
1843 chan, pt.ctp_status);
1847 if (isp->isp_dblev & ISP_LOGDEBUG1)
1848 isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch);
1854 * Scan the fabric for devices and add them to our port database.
1856 * Use the GID_PT command to get list of all Nx_Port IDs SNS knows.
1857 * Use GFF_ID and GFT_ID to check port type (FCP) and features (target).
1859 * We use CT Pass-through IOCB.
1861 #define GIDLEN ISP_FC_SCRLEN
1862 #define NGENT ((GIDLEN - 16) >> 2)
1865 isp_gid_pt(ispsoftc_t *isp, int chan)
1867 fcparam *fcp = FCPARAM(isp, chan);
1869 uint8_t *scp = fcp->isp_scratch;
1871 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan);
1872 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1873 isp_prt(isp, ISP_LOGERR, sacq);
1877 /* Build the CT command and execute via pass-through. */
1878 ISP_MEMZERO(&ct, sizeof (ct));
1879 ct.ct_revision = CT_REVISION;
1880 ct.ct_fcs_type = CT_FC_TYPE_FC;
1881 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
1882 ct.ct_cmd_resp = SNS_GID_PT;
1883 ct.ct_bcnt_resid = (GIDLEN - 16) >> 2;
1884 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
1885 scp[sizeof(ct)] = 0x7f; /* Port Type = Nx_Port */
1886 scp[sizeof(ct)+1] = 0; /* Domain_ID = any */
1887 scp[sizeof(ct)+2] = 0; /* Area_ID = any */
1888 scp[sizeof(ct)+3] = 0; /* Flags = no Area_ID */
1890 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) {
1891 FC_SCRATCH_RELEASE(isp, chan);
1895 isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp,
1896 (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT);
1897 FC_SCRATCH_RELEASE(isp, chan);
1902 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid)
1904 fcparam *fcp = FCPARAM(isp, chan);
1907 uint8_t *scp = fcp->isp_scratch;
1908 sns_gff_id_rsp_t rsp;
1911 if (!fcp->isp_use_gff_id) /* User may block GFF_ID use. */
1914 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan);
1915 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1916 isp_prt(isp, ISP_LOGERR, sacq);
1920 /* Build the CT command and execute via pass-through. */
1921 ISP_MEMZERO(&ct, sizeof (ct));
1922 ct.ct_revision = CT_REVISION;
1923 ct.ct_fcs_type = CT_FC_TYPE_FC;
1924 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
1925 ct.ct_cmd_resp = SNS_GFF_ID;
1926 ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4;
1927 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
1928 rp = (uint32_t *) &scp[sizeof(ct)];
1929 ISP_IOZPUT_32(isp, portid, rp);
1931 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
1932 SNS_GFF_ID_RESP_SIZE)) {
1933 FC_SCRATCH_RELEASE(isp, chan);
1937 isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp);
1938 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
1939 for (i = 0; i < 32; i++) {
1940 if (rsp.snscb_fc4_features[i] != 0) {
1945 if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >>
1946 ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
1948 /* Workaround for broken Brocade firmware. */
1949 if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >>
1950 ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
1953 FC_SCRATCH_RELEASE(isp, chan);
1954 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res);
1959 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid)
1961 fcparam *fcp = FCPARAM(isp, chan);
1964 uint8_t *scp = fcp->isp_scratch;
1965 sns_gft_id_rsp_t rsp;
1968 if (!fcp->isp_use_gft_id) /* User may block GFT_ID use. */
1971 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan);
1972 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1973 isp_prt(isp, ISP_LOGERR, sacq);
1977 /* Build the CT command and execute via pass-through. */
1978 ISP_MEMZERO(&ct, sizeof (ct));
1979 ct.ct_revision = CT_REVISION;
1980 ct.ct_fcs_type = CT_FC_TYPE_FC;
1981 ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
1982 ct.ct_cmd_resp = SNS_GFT_ID;
1983 ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4;
1984 isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
1985 rp = (uint32_t *) &scp[sizeof(ct)];
1986 ISP_IOZPUT_32(isp, portid, rp);
1988 if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
1989 SNS_GFT_ID_RESP_SIZE)) {
1990 FC_SCRATCH_RELEASE(isp, chan);
1994 isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp);
1995 if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
1996 for (i = 0; i < 8; i++) {
1997 if (rsp.snscb_fc4_types[i] != 0) {
2002 if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >>
2003 (FC4_SCSI % 32)) & 0x01) != 0)
2006 FC_SCRATCH_RELEASE(isp, chan);
2007 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res);
2012 isp_scan_fabric(ispsoftc_t *isp, int chan)
2014 fcparam *fcp = FCPARAM(isp, chan);
2018 int portidx, portlim, r;
2019 sns_gid_xx_rsp_t *rs;
2021 if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
2023 if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
2026 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
2027 fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
2028 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
2029 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2030 isp_prt(isp, ISP_LOG_SANCFG,
2031 "Chan %d FC fabric scan done (no fabric)", chan);
2035 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
2037 FC_SCRATCH_RELEASE(isp, chan);
2038 isp_prt(isp, ISP_LOG_SANCFG,
2039 "Chan %d FC fabric scan aborted", chan);
2044 * Make sure we still are logged into the fabric controller.
2046 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
2047 if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) {
2048 isp_dump_chip_portdb(isp, chan);
2051 fcp->isp_loopstate = LOOP_LTEST_DONE;
2053 isp_prt(isp, ISP_LOG_SANCFG,
2054 "Chan %d FC fabric scan done (bad)", chan);
2058 /* Get list of port IDs from SNS. */
2059 r = isp_gid_pt(isp, chan);
2060 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2063 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2066 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
2070 rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch;
2071 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2073 if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) {
2075 /* FC-4 Type and Port Type not registered are not errors. */
2076 if (rs->snscb_cthdr.ct_reason == 9 &&
2077 (rs->snscb_cthdr.ct_explanation == 0x07 ||
2078 rs->snscb_cthdr.ct_explanation == 0x0a)) {
2079 level = ISP_LOG_SANCFG;
2081 level = ISP_LOGWARN;
2083 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT"
2084 " (Reason=0x%x Expl=0x%x)", chan,
2085 rs->snscb_cthdr.ct_reason,
2086 rs->snscb_cthdr.ct_explanation);
2087 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2091 /* Check our buffer was big enough to get the full list. */
2092 for (portidx = 0; portidx < NGENT-1; portidx++) {
2093 if (rs->snscb_ports[portidx].control & 0x80)
2096 if ((rs->snscb_ports[portidx].control & 0x80) == 0) {
2097 isp_prt(isp, ISP_LOGWARN,
2098 "fabric too big for scratch area: increase ISP_FC_SCRLEN");
2100 portlim = portidx + 1;
2101 isp_prt(isp, ISP_LOG_SANCFG,
2102 "Chan %d Got %d ports back from name server", chan, portlim);
2104 /* Go through the list and remove duplicate port ids. */
2105 for (portidx = 0; portidx < portlim; portidx++) {
2109 ((rs->snscb_ports[portidx].portid[0]) << 16) |
2110 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2111 ((rs->snscb_ports[portidx].portid[2]));
2113 for (npidx = portidx + 1; npidx < portlim; npidx++) {
2114 uint32_t new_portid =
2115 ((rs->snscb_ports[npidx].portid[0]) << 16) |
2116 ((rs->snscb_ports[npidx].portid[1]) << 8) |
2117 ((rs->snscb_ports[npidx].portid[2]));
2118 if (new_portid == portid) {
2123 if (npidx < portlim) {
2124 rs->snscb_ports[npidx].portid[0] = 0;
2125 rs->snscb_ports[npidx].portid[1] = 0;
2126 rs->snscb_ports[npidx].portid[2] = 0;
2127 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid);
2132 * We now have a list of Port IDs for all FC4 SCSI devices
2133 * that the Fabric Name server knows about.
2135 * For each entry on this list go through our port database looking
2136 * for probational entries- if we find one, then an old entry is
2137 * maybe still this one. We get some information to find out.
2139 * Otherwise, it's a new fabric device, and we log into it
2140 * (unconditionally). After searching the entire database
2141 * again to make sure that we never ever ever ever have more
2142 * than one entry that has the same PortID or the same
2143 * WWNN/WWPN duple, we enter the device into our database.
2145 isp_mark_portdb(isp, chan);
2146 for (portidx = 0; portidx < portlim; portidx++) {
2147 portid = ((rs->snscb_ports[portidx].portid[0]) << 16) |
2148 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2149 ((rs->snscb_ports[portidx].portid[2]));
2150 isp_prt(isp, ISP_LOG_SANCFG,
2151 "Chan %d Checking fabric port 0x%06x", chan, portid);
2153 isp_prt(isp, ISP_LOG_SANCFG,
2154 "Chan %d Port at idx %d is zero",
2158 if (portid == fcp->isp_portid) {
2159 isp_prt(isp, ISP_LOG_SANCFG,
2160 "Chan %d Port 0x%06x is our", chan, portid);
2164 /* Now search the entire port database for the same portid. */
2165 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) {
2166 if (!lp->probational) {
2167 isp_prt(isp, ISP_LOGERR,
2168 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
2169 chan, lp->portid, lp->handle,
2170 FC_PORTDB_TGT(isp, chan, lp), lp->state);
2171 isp_dump_portdb(isp, chan);
2175 if (lp->state == FC_PORTDB_STATE_ZOMBIE)
2179 * See if we're still logged into it.
2181 * If we aren't, mark it as a dead device and
2182 * leave the new portid in the database entry
2183 * for somebody further along to decide what to
2184 * do (policy choice).
2186 * If we are, check to see if it's the same
2187 * device still (it should be). If for some
2188 * reason it isn't, mark it as a changed device
2189 * and leave the new portid and role in the
2190 * database entry for somebody further along to
2191 * decide what to do (policy choice).
2193 r = isp_getpdb(isp, chan, lp->handle, &pdb);
2194 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2197 lp->state = FC_PORTDB_STATE_DEAD;
2198 isp_prt(isp, ISP_LOG_SANCFG,
2199 "Chan %d Port 0x%06x handle 0x%x is dead (%d)",
2200 chan, portid, lp->handle, r);
2204 isp_pdb_add_update(isp, chan, &pdb);
2209 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2210 isp_prt(isp, ISP_LOG_SANCFG,
2211 "Chan %d Port 0x%06x is not logged in", chan, portid);
2215 r = isp_gff_id(isp, chan, portid);
2217 isp_prt(isp, ISP_LOG_SANCFG,
2218 "Chan %d Port 0x%06x is not an FCP target", chan, portid);
2222 r = isp_gft_id(isp, chan, portid);
2224 isp_prt(isp, ISP_LOG_SANCFG,
2225 "Chan %d Port 0x%06x is not FCP", chan, portid);
2229 if (isp_login_device(isp, chan, portid, &pdb,
2230 &FCPARAM(isp, 0)->isp_lasthdl)) {
2231 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2236 isp_pdb_add_update(isp, chan, &pdb);
2239 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2241 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2242 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
2247 * Find an unused handle and try and use to login to a port.
2250 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
2255 handle = isp_next_handle(isp, ohp);
2256 for (i = 0; i < NPH_MAX_2K; i++) {
2257 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2260 /* Check if this handle is free. */
2261 r = isp_getpdb(isp, chan, handle, p);
2263 if (p->portid != portid) {
2264 /* This handle is busy, try next one. */
2265 handle = isp_next_handle(isp, ohp);
2270 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2274 * Now try and log into the device
2276 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2279 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
2281 * If we get here, then the firmwware still thinks we're logged into this device, but with a different
2282 * handle. We need to break that association. We used to try and just substitute the handle, but then
2283 * failed to get any data via isp_getpdb (below).
2285 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) {
2286 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
2288 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2290 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2294 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
2295 /* Try the next handle. */
2296 handle = isp_next_handle(isp, ohp);
2304 if (i == NPH_MAX_2K) {
2305 isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid);
2310 * If we successfully logged into it, get the PDB for it
2311 * so we can crosscheck that it is still what we think it
2312 * is and that we also have the role it plays
2314 r = isp_getpdb(isp, chan, handle, p);
2316 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
2320 if (p->handle != handle || p->portid != portid) {
2321 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
2322 chan, portid, handle, p->portid, p->handle);
2329 isp_register_fc4_type(ispsoftc_t *isp, int chan)
2331 fcparam *fcp = FCPARAM(isp, chan);
2333 ct_hdr_t *ct = &rp.rftid_hdr;
2334 uint8_t *scp = fcp->isp_scratch;
2336 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2337 isp_prt(isp, ISP_LOGERR, sacq);
2341 /* Build the CT command and execute via pass-through. */
2342 ISP_MEMZERO(&rp, sizeof(rp));
2343 ct->ct_revision = CT_REVISION;
2344 ct->ct_fcs_type = CT_FC_TYPE_FC;
2345 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2346 ct->ct_cmd_resp = SNS_RFT_ID;
2347 ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2;
2348 rp.rftid_portid[0] = fcp->isp_portid >> 16;
2349 rp.rftid_portid[1] = fcp->isp_portid >> 8;
2350 rp.rftid_portid[2] = fcp->isp_portid;
2351 rp.rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
2352 isp_put_rft_id(isp, &rp, (rft_id_t *)scp);
2354 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2355 FC_SCRATCH_RELEASE(isp, chan);
2359 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2360 FC_SCRATCH_RELEASE(isp, chan);
2361 if (ct->ct_cmd_resp == LS_RJT) {
2362 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "Chan %d Register FC4 Type rejected", chan);
2364 } else if (ct->ct_cmd_resp == LS_ACC) {
2365 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan);
2367 isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp);
2374 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
2376 fcparam *fcp = FCPARAM(isp, chan);
2379 uint8_t *scp = fcp->isp_scratch;
2381 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2382 isp_prt(isp, ISP_LOGERR, sacq);
2387 * Build the CT header and command in memory.
2389 ISP_MEMZERO(&rp, sizeof(rp));
2391 ct->ct_revision = CT_REVISION;
2392 ct->ct_fcs_type = CT_FC_TYPE_FC;
2393 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2394 ct->ct_cmd_resp = SNS_RFF_ID;
2395 ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2;
2396 rp.rffid_portid[0] = fcp->isp_portid >> 16;
2397 rp.rffid_portid[1] = fcp->isp_portid >> 8;
2398 rp.rffid_portid[2] = fcp->isp_portid;
2399 rp.rffid_fc4features = 0;
2400 if (fcp->role & ISP_ROLE_TARGET)
2401 rp.rffid_fc4features |= 1;
2402 if (fcp->role & ISP_ROLE_INITIATOR)
2403 rp.rffid_fc4features |= 2;
2404 rp.rffid_fc4type = FC4_SCSI;
2405 isp_put_rff_id(isp, &rp, (rff_id_t *)scp);
2406 if (isp->isp_dblev & ISP_LOGDEBUG1)
2407 isp_print_bytes(isp, "CT request", sizeof(rft_id_t), scp);
2409 if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2410 FC_SCRATCH_RELEASE(isp, chan);
2414 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2415 FC_SCRATCH_RELEASE(isp, chan);
2416 if (ct->ct_cmd_resp == LS_RJT) {
2417 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2418 "Chan %d Register FC4 Features rejected", chan);
2420 } else if (ct->ct_cmd_resp == LS_ACC) {
2421 isp_prt(isp, ISP_LOG_SANCFG,
2422 "Chan %d Register FC4 Features accepted", chan);
2424 isp_prt(isp, ISP_LOGWARN,
2425 "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
2432 isp_register_port_name_24xx(ispsoftc_t *isp, int chan)
2434 fcparam *fcp = FCPARAM(isp, chan);
2437 uint8_t *scp = fcp->isp_scratch;
2440 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2441 isp_prt(isp, ISP_LOGERR, sacq);
2446 * Build the CT header and command in memory.
2448 ISP_MEMZERO(&rp, sizeof(rp));
2449 ct = &rp.rspnid_hdr;
2450 ct->ct_revision = CT_REVISION;
2451 ct->ct_fcs_type = CT_FC_TYPE_FC;
2452 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2453 ct->ct_cmd_resp = SNS_RSPN_ID;
2454 rp.rspnid_portid[0] = fcp->isp_portid >> 16;
2455 rp.rspnid_portid[1] = fcp->isp_portid >> 8;
2456 rp.rspnid_portid[2] = fcp->isp_portid;
2457 rp.rspnid_length = 0;
2458 len = offsetof(rspn_id_t, rspnid_name);
2459 mtx_lock(&prison0.pr_mtx);
2460 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2461 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2462 mtx_unlock(&prison0.pr_mtx);
2463 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2464 ":%s", device_get_nameunit(isp->isp_dev));
2466 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2469 len += rp.rspnid_length;
2470 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2471 isp_put_rspn_id(isp, &rp, (rspn_id_t *)scp);
2473 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2474 FC_SCRATCH_RELEASE(isp, chan);
2478 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2479 FC_SCRATCH_RELEASE(isp, chan);
2480 if (ct->ct_cmd_resp == LS_RJT) {
2481 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2482 "Chan %d Register Symbolic Port Name rejected", chan);
2484 } else if (ct->ct_cmd_resp == LS_ACC) {
2485 isp_prt(isp, ISP_LOG_SANCFG,
2486 "Chan %d Register Symbolic Port Name accepted", chan);
2488 isp_prt(isp, ISP_LOGWARN,
2489 "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp);
2496 isp_register_node_name_24xx(ispsoftc_t *isp, int chan)
2498 fcparam *fcp = FCPARAM(isp, chan);
2501 uint8_t *scp = fcp->isp_scratch;
2504 if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2505 isp_prt(isp, ISP_LOGERR, sacq);
2510 * Build the CT header and command in memory.
2512 ISP_MEMZERO(&rp, sizeof(rp));
2513 ct = &rp.rsnnnn_hdr;
2514 ct->ct_revision = CT_REVISION;
2515 ct->ct_fcs_type = CT_FC_TYPE_FC;
2516 ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2517 ct->ct_cmd_resp = SNS_RSNN_NN;
2518 MAKE_NODE_NAME_FROM_WWN(rp.rsnnnn_nodename, fcp->isp_wwnn);
2519 rp.rsnnnn_length = 0;
2520 len = offsetof(rsnn_nn_t, rsnnnn_name);
2521 mtx_lock(&prison0.pr_mtx);
2522 rp.rsnnnn_length += sprintf(&scp[len + rp.rsnnnn_length],
2523 "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2524 mtx_unlock(&prison0.pr_mtx);
2525 len += rp.rsnnnn_length;
2526 ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2527 isp_put_rsnn_nn(isp, &rp, (rsnn_nn_t *)scp);
2529 if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2530 FC_SCRATCH_RELEASE(isp, chan);
2534 isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2535 FC_SCRATCH_RELEASE(isp, chan);
2536 if (ct->ct_cmd_resp == LS_RJT) {
2537 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2538 "Chan %d Register Symbolic Node Name rejected", chan);
2540 } else if (ct->ct_cmd_resp == LS_ACC) {
2541 isp_prt(isp, ISP_LOG_SANCFG,
2542 "Chan %d Register Symbolic Node Name accepted", chan);
2544 isp_prt(isp, ISP_LOGWARN,
2545 "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp);
2552 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
2562 if (handle == NIL_HANDLE) {
2566 if (handle > NPH_RESERVED - 1) {
2568 isp_prt(isp, ISP_LOGERR, "Out of port handles!");
2569 return (NIL_HANDLE);
2574 for (chan = 0; chan < isp->isp_nchan; chan++) {
2575 fcp = FCPARAM(isp, chan);
2576 if (fcp->role == ISP_ROLE_NONE)
2578 for (i = 0; i < MAX_FC_TARG; i++) {
2579 if (fcp->portdb[i].state != FC_PORTDB_STATE_NIL &&
2580 fcp->portdb[i].handle == handle)
2589 * Start a command. Locking is assumed done in the caller.
2598 ispreqt7_t local, *reqp = &local;
2601 int target, dmaresult;
2607 * Check command CDB length, etc.. We really are limited to 16 bytes
2608 * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
2609 * but probably only if we're running fairly new firmware (we'll
2610 * let the old f/w choke on an extended command queue entry).
2613 if (XS_CDBLEN(xs) > 16 || XS_CDBLEN(xs) == 0) {
2614 isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
2615 XS_SETERR(xs, HBA_REQINVAL);
2616 return (CMD_COMPLETE);
2620 * Translate the target to device handle as appropriate, checking
2621 * for correct device state as well.
2623 target = XS_TGT(xs);
2624 fcp = FCPARAM(isp, XS_CHANNEL(xs));
2626 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2627 isp_prt(isp, ISP_LOG_WARN1,
2628 "%d.%d.%jx I am not an initiator",
2629 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2630 XS_SETERR(xs, HBA_SELTIMEOUT);
2631 return (CMD_COMPLETE);
2634 if (isp->isp_state != ISP_RUNSTATE) {
2635 isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
2636 XS_SETERR(xs, HBA_BOTCH);
2637 return (CMD_COMPLETE);
2640 isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target);
2641 lp = &fcp->portdb[target];
2642 if (target < 0 || target >= MAX_FC_TARG ||
2643 lp->is_target == 0) {
2644 XS_SETERR(xs, HBA_SELTIMEOUT);
2645 return (CMD_COMPLETE);
2647 if (fcp->isp_loopstate != LOOP_READY) {
2648 isp_prt(isp, ISP_LOGDEBUG1,
2649 "%d.%d.%jx loop is not ready",
2650 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2651 return (CMD_RQLATER);
2653 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
2654 isp_prt(isp, ISP_LOGDEBUG1,
2655 "%d.%d.%jx target zombie",
2656 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2657 return (CMD_RQLATER);
2659 if (lp->state != FC_PORTDB_STATE_VALID) {
2660 isp_prt(isp, ISP_LOGDEBUG1,
2661 "%d.%d.%jx bad db port state 0x%x",
2662 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs), lp->state);
2663 XS_SETERR(xs, HBA_SELTIMEOUT);
2664 return (CMD_COMPLETE);
2669 qep = isp_getrqentry(isp);
2671 isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow");
2672 XS_SETERR(xs, HBA_BOTCH);
2673 return (CMD_EAGAIN);
2675 XS_SETERR(xs, HBA_NOERROR);
2678 * Now see if we need to synchronize the ISP with respect to anything.
2679 * We do dual duty here (cough) for synchronizing for buses other
2680 * than which we got here to send a command to.
2682 ISP_MEMZERO(reqp, QENTRY_LEN);
2683 if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
2684 isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
2685 m->mrk_header.rqs_entry_count = 1;
2686 m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
2687 m->mrk_modifier = SYNC_ALL;
2688 m->mrk_vphdl = XS_CHANNEL(xs);
2689 isp_put_marker_24xx(isp, m, qep);
2690 ISP_SYNC_REQUEST(isp);
2691 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
2696 * NB: we do not support long CDBs (yet)
2698 cdblen = XS_CDBLEN(xs);
2699 if (cdblen > sizeof (reqp->req_cdb)) {
2700 isp_prt(isp, ISP_LOGERR, "Command Length %u too long for this chip", cdblen);
2701 XS_SETERR(xs, HBA_REQINVAL);
2702 return (CMD_COMPLETE);
2705 reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
2706 reqp->req_header.rqs_entry_count = 1;
2707 reqp->req_nphdl = lp->handle;
2708 reqp->req_time = XS_TIME(xs);
2709 be64enc(reqp->req_lun, CAM_EXTLUN_BYTE_SWIZZLE(XS_LUN(xs)));
2711 reqp->req_alen_datadir = FCP_CMND_DATA_READ;
2712 else if (XS_XFROUT(xs))
2713 reqp->req_alen_datadir = FCP_CMND_DATA_WRITE;
2715 reqp->req_task_attribute = XS_TAG_TYPE(xs);
2717 reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE;
2718 reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) &
2720 if (FCPARAM(isp, XS_CHANNEL(xs))->fctape_enabled && (lp->prli_word3 & PRLI_WD3_RETRY)) {
2721 if (FCP_NEXT_CRN(isp, &reqp->req_crn, xs)) {
2722 isp_prt(isp, ISP_LOG_WARN1,
2723 "%d.%d.%jx cannot generate next CRN",
2724 XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2725 XS_SETERR(xs, HBA_BOTCH);
2726 return (CMD_EAGAIN);
2729 ISP_MEMCPY(reqp->req_cdb, XS_CDBP(xs), cdblen);
2730 reqp->req_dl = XS_XFRLEN(xs);
2731 reqp->req_tidlo = lp->portid;
2732 reqp->req_tidhi = lp->portid >> 16;
2733 reqp->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs));
2735 /* Whew. Thankfully the same for type 7 requests */
2736 reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR);
2737 if (reqp->req_handle == 0) {
2738 isp_prt(isp, ISP_LOG_WARN1, "out of xflist pointers");
2739 XS_SETERR(xs, HBA_BOTCH);
2740 return (CMD_EAGAIN);
2744 * Set up DMA and/or do any platform dependent swizzling of the request entry
2745 * so that the Qlogic F/W understands what is being asked of it.
2747 * The callee is responsible for adding all requests at this point.
2749 dmaresult = ISP_DMASETUP(isp, xs, reqp);
2750 if (dmaresult != 0) {
2751 isp_destroy_handle(isp, reqp->req_handle);
2753 * dmasetup sets actual error in packet, and
2754 * return what we were given to return.
2758 isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
2764 * Locks (ints blocked) assumed held.
2768 isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
2777 uint8_t local[QENTRY_LEN];
2780 case ISPCTL_RESET_BUS:
2782 * Issue a bus reset.
2784 isp_prt(isp, ISP_LOGERR, "BUS RESET NOT IMPLEMENTED");
2787 case ISPCTL_RESET_DEV:
2790 isp24xx_statusreq_t *sp;
2793 chan = va_arg(ap, int);
2794 tgt = va_arg(ap, int);
2796 fcp = FCPARAM(isp, chan);
2798 if (tgt < 0 || tgt >= MAX_FC_TARG) {
2799 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to reset bad target %d", chan, tgt);
2802 lp = &fcp->portdb[tgt];
2803 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
2804 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
2808 tmf = (isp24xx_tmf_t *) local;
2809 ISP_MEMZERO(tmf, QENTRY_LEN);
2810 tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
2811 tmf->tmf_header.rqs_entry_count = 1;
2812 tmf->tmf_nphdl = lp->handle;
2814 tmf->tmf_timeout = 4;
2815 tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
2816 tmf->tmf_tidlo = lp->portid;
2817 tmf->tmf_tidhi = lp->portid >> 16;
2818 tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
2819 fcp->sendmarker = 1;
2820 isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
2822 sp = (isp24xx_statusreq_t *) local;
2823 if (isp_exec_entry_mbox(isp, tmf, sp, 2 * tmf->tmf_timeout))
2826 if (sp->req_completion_status == 0)
2828 isp_prt(isp, ISP_LOGWARN, "Chan %d reset of target %d returned 0x%x", chan, tgt, sp->req_completion_status);
2831 case ISPCTL_ABORT_CMD:
2833 isp24xx_abrt_t *ab = (isp24xx_abrt_t *)&local;
2836 xs = va_arg(ap, XS_T *);
2840 chan = XS_CHANNEL(xs);
2842 handle = isp_find_handle(isp, xs);
2844 isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort");
2848 fcp = FCPARAM(isp, chan);
2849 if (tgt < 0 || tgt >= MAX_FC_TARG) {
2850 isp_prt(isp, ISP_LOGWARN, "Chan %d trying to abort bad target %d", chan, tgt);
2853 lp = &fcp->portdb[tgt];
2854 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
2855 isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
2858 isp_prt(isp, ISP_LOGALL, "Chan %d Abort Cmd for N-Port 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
2859 ISP_MEMZERO(ab, QENTRY_LEN);
2860 ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO;
2861 ab->abrt_header.rqs_entry_count = 1;
2862 ab->abrt_handle = lp->handle;
2863 ab->abrt_cmd_handle = handle;
2864 ab->abrt_tidlo = lp->portid;
2865 ab->abrt_tidhi = lp->portid >> 16;
2866 ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan);
2868 if (isp_exec_entry_mbox(isp, ab, ab, 5))
2871 if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY)
2873 isp_prt(isp, ISP_LOGWARN, "Chan %d handle %d abort returned 0x%x", chan, tgt, ab->abrt_nphdl);
2875 case ISPCTL_FCLINK_TEST:
2880 chan = va_arg(ap, int);
2881 usdelay = va_arg(ap, int);
2885 return (isp_fclink_test(isp, chan, usdelay));
2887 case ISPCTL_SCAN_FABRIC:
2890 chan = va_arg(ap, int);
2892 return (isp_scan_fabric(isp, chan));
2894 case ISPCTL_SCAN_LOOP:
2897 chan = va_arg(ap, int);
2899 return (isp_scan_loop(isp, chan));
2901 case ISPCTL_PDB_SYNC:
2904 chan = va_arg(ap, int);
2906 return (isp_pdb_sync(isp, chan));
2908 case ISPCTL_SEND_LIP:
2911 case ISPCTL_GET_PDB:
2915 chan = va_arg(ap, int);
2916 tgt = va_arg(ap, int);
2917 pdb = va_arg(ap, isp_pdb_t *);
2919 return (isp_getpdb(isp, chan, tgt, pdb));
2921 case ISPCTL_GET_NAMES:
2923 uint64_t *wwnn, *wwnp;
2925 chan = va_arg(ap, int);
2926 tgt = va_arg(ap, int);
2927 wwnn = va_arg(ap, uint64_t *);
2928 wwnp = va_arg(ap, uint64_t *);
2930 if (wwnn == NULL && wwnp == NULL) {
2934 *wwnn = isp_get_wwn(isp, chan, tgt, 1);
2935 if (*wwnn == INI_NONE) {
2940 *wwnp = isp_get_wwn(isp, chan, tgt, 0);
2941 if (*wwnp == INI_NONE) {
2947 case ISPCTL_RUN_MBOXCMD:
2950 mbr = va_arg(ap, mbreg_t *);
2952 isp_mboxcmd(isp, mbr);
2961 p = va_arg(ap, isp_plcmd_t *);
2964 if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
2965 return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags));
2968 isp_next_handle(isp, &p->handle);
2969 r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags);
2970 if ((r & 0xffff) == MBOX_PORT_ID_USED) {
2971 p->handle = r >> 16;
2975 } while ((r & 0xffff) == MBOX_LOOP_ID_USED);
2978 case ISPCTL_CHANGE_ROLE:
2983 chan = va_arg(ap, int);
2984 role = va_arg(ap, int);
2986 return (isp_fc_change_role(isp, chan, role));
2989 isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
2997 * Interrupt Service Routine(s).
2999 * External (OS) framework has done the appropriate locking,
3000 * and the locking will be held throughout this function.
3003 #ifdef ISP_TARGET_MODE
3005 isp_intr_atioq(ispsoftc_t *isp)
3008 uint32_t iptr, optr, oop;
3010 iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
3011 optr = isp->isp_atioodx;
3012 while (optr != iptr) {
3014 MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN, -1);
3015 addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop);
3016 switch (((isphdr_t *)addr)->rqs_entry_type) {
3017 case RQSTYPE_NOTIFY:
3019 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue.*/
3020 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue.*/
3021 (void) isp_target_notify(isp, addr, &oop,
3022 ATIO_QUEUE_LEN(isp));
3024 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/
3026 isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
3029 optr = ISP_NXT_QENTRY(oop, ATIO_QUEUE_LEN(isp));
3031 if (isp->isp_atioodx != optr) {
3032 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
3033 isp->isp_atioodx = optr;
3039 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0)
3043 if (!isp->isp_mboxbsy) {
3044 isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0);
3047 obits = isp->isp_obits;
3048 isp->isp_mboxtmp[0] = mbox0;
3049 for (i = 1; i < ISP_NMBOX(isp); i++) {
3050 if ((obits & (1 << i)) == 0)
3052 isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
3054 isp->isp_mboxbsy = 0;
3058 isp_intr_respq(ispsoftc_t *isp)
3061 uint8_t qe[QENTRY_LEN];
3062 isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe;
3063 ispstatus_cont_t *scp = (ispstatus_cont_t *)qe;
3065 uint8_t *resp, *snsp, etype;
3066 uint16_t scsi_status;
3067 uint32_t iptr, cont = 0, cptr, optr, rlen, slen, sptr, totslen;
3070 * We can't be getting this now.
3072 if (isp->isp_state != ISP_RUNSTATE) {
3073 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready");
3077 iptr = ISP_READ(isp, BIU2400_RSPINP);
3078 optr = isp->isp_resodx;
3079 while (optr != iptr) {
3081 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
3082 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
3085 * Synchronize our view of this response queue entry.
3087 MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1);
3088 if (isp->isp_dblev & ISP_LOGDEBUG1)
3089 isp_print_qentry(isp, "Response Queue Entry", cptr, hp);
3090 isp_get_hdr(isp, hp, &sp->req_header);
3093 * Log IOCBs rejected by the firmware. We can't really do
3094 * much more about them, since it just should not happen.
3096 if (sp->req_header.rqs_flags & RQSFLAG_BADTYPE) {
3097 isp_print_qentry(isp, "invalid entry type", cptr, hp);
3100 if (sp->req_header.rqs_flags & RQSFLAG_BADPARAM) {
3101 isp_print_qentry(isp, "invalid entry parameter", cptr, hp);
3104 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
3105 isp_print_qentry(isp, "invalid entry count", cptr, hp);
3108 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
3109 isp_print_qentry(isp, "invalid entry order", cptr, hp);
3113 etype = sp->req_header.rqs_entry_type;
3115 /* We expected Status Continuation, but got different IOCB. */
3116 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
3121 if (isp_handle_control(isp, hp)) {
3122 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3127 case RQSTYPE_RESPONSE:
3128 isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp);
3130 case RQSTYPE_MARKER:
3131 isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
3132 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3134 case RQSTYPE_STATUS_CONT:
3135 isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
3137 slen = min(cont, sizeof(scp->req_sense_data));
3138 XS_SENSE_APPEND(cont_xs, scp->req_sense_data, slen);
3143 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3144 "Expecting Status Continuations for %u bytes",
3148 isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
3150 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3152 #ifdef ISP_TARGET_MODE
3153 case RQSTYPE_NOTIFY_ACK: /* Can be set to ATIO queue. */
3155 case RQSTYPE_ABTS_RCVD: /* Can be set to ATIO queue. */
3156 case RQSTYPE_ABTS_RSP:
3157 isp_target_notify(isp, hp, &cptr, RESULT_QUEUE_LEN(isp));
3158 /* More then one IOCB could be consumed. */
3159 while (sptr != cptr) {
3160 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3161 sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp));
3162 hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr);
3164 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3165 optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
3168 case RQSTYPE_RPT_ID_ACQ: /* Can be set to ATIO queue.*/
3169 isp_handle_rpt_id_acq(isp, hp);
3170 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3173 /* We don't know what was this -- log and skip. */
3174 isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr);
3175 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3179 xs = isp_find_xs(isp, sp->req_handle);
3182 * Only whine if this isn't the expected fallout of
3183 * aborting the command or resetting the target.
3185 if (sp->req_completion_status != RQCS_ABORTED &&
3186 sp->req_completion_status != RQCS_RESET_OCCURRED)
3187 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)",
3188 sp->req_handle, sp->req_completion_status);
3189 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3193 resp = snsp = sp->req_rsp_sense;
3194 rlen = slen = totslen = 0;
3195 scsi_status = sp->req_scsi_status;
3196 if (scsi_status & RQCS_RV) {
3197 rlen = sp->req_response_len;
3200 if (scsi_status & RQCS_SV) {
3201 totslen = sp->req_sense_len;
3202 slen = MIN(totslen, sizeof(sp->req_rsp_sense) - rlen);
3204 *XS_STSP(xs) = scsi_status & 0xff;
3205 if (scsi_status & RQCS_RESID)
3206 XS_SET_RESID(xs, sp->req_fcp_residual);
3208 XS_SET_RESID(xs, 0);
3210 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
3213 const char *rnames[10] = {
3214 "Task Management function complete",
3215 "FCP_DATA length different than FCP_BURST_LEN",
3216 "FCP_CMND fields invalid",
3217 "FCP_DATA parameter mismatch with FCP_DATA_RO",
3218 "Task Management function rejected",
3219 "Task Management function failed",
3222 "Task Management function succeeded",
3223 "Task Management function incorrect logical unit number",
3225 uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
3226 if (code >= nitems(rnames) || rnames[code] == NULL) {
3227 ISP_SNPRINTF(lb, sizeof(lb),
3228 "Unknown FCP Response Code 0x%x", code);
3233 isp_xs_prt(isp, xs, ISP_LOGWARN,
3234 "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
3235 rlen, ptr, XS_CDBP(xs)[0] & 0xff);
3236 if (code != FCP_RSPNS_TMF_DONE &&
3237 code != FCP_RSPNS_TMF_SUCCEEDED)
3238 XS_SETERR(xs, HBA_BOTCH);
3240 isp_parse_status_24xx(isp, sp, xs);
3242 XS_SAVE_SENSE(xs, snsp, slen);
3243 if (totslen > slen) {
3244 cont = totslen - slen;
3246 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3247 "Expecting Status Continuations for %u bytes",
3252 ISP_DMAFREE(isp, xs);
3253 isp_destroy_handle(isp, sp->req_handle);
3254 ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
3256 /* Complete command if we expect no Status Continuations. */
3261 /* We haven't received all Status Continuations, but that is it. */
3265 /* If we processed any IOCBs, let ISP know about it. */
3266 if (optr != isp->isp_resodx) {
3267 ISP_WRITE(isp, BIU2400_RSPOUTP, optr);
3268 isp->isp_resodx = optr;
3274 isp_intr_async(ispsoftc_t *isp, uint16_t mbox)
3279 isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
3282 case ASYNC_SYSTEM_ERROR:
3283 isp->isp_state = ISP_CRASHED;
3284 for (chan = 0; chan < isp->isp_nchan; chan++) {
3285 FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
3286 isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
3289 * Were we waiting for a mailbox command to complete?
3290 * If so, it's dead, so wake up the waiter.
3292 if (isp->isp_mboxbsy) {
3294 isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
3295 isp->isp_mboxbsy = 0;
3298 * It's up to the handler for isp_async to reinit stuff and
3299 * restart the firmware
3301 isp_async(isp, ISPASYNC_FW_CRASH);
3304 case ASYNC_RQS_XFER_ERR:
3305 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
3308 case ASYNC_RSP_XFER_ERR:
3309 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
3312 case ASYNC_ATIO_XFER_ERR:
3313 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
3316 case ASYNC_LIP_OCCURRED:
3317 case ASYNC_LIP_NOS_OLS_RECV:
3318 case ASYNC_LIP_ERROR:
3321 * These are broadcast events that have to be sent across
3322 * all active channels.
3324 for (chan = 0; chan < isp->isp_nchan; chan++) {
3325 fcp = FCPARAM(isp, chan);
3326 int topo = fcp->isp_topo;
3328 if (fcp->role == ISP_ROLE_NONE)
3330 if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3331 fcp->isp_loopstate = LOOP_HAVE_LINK;
3332 ISP_SET_SENDMARKER(isp, chan, 1);
3333 isp_async(isp, ISPASYNC_LIP, chan);
3334 #ifdef ISP_TARGET_MODE
3335 isp_target_async(isp, chan, mbox);
3338 * We've had problems with data corruption occurring on
3339 * commands that complete (with no apparent error) after
3340 * we receive a LIP. This has been observed mostly on
3341 * Local Loop topologies. To be safe, let's just mark
3342 * all active initiator commands as dead.
3344 if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
3346 for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) {
3350 hdp = &isp->isp_xflist[i];
3351 if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
3355 if (XS_CHANNEL(xs) != chan) {
3359 isp_prt(isp, ISP_LOG_WARN1,
3360 "%d.%d.%jx bus reset set at %s:%u",
3361 XS_CHANNEL(xs), XS_TGT(xs),
3362 (uintmax_t)XS_LUN(xs),
3363 __func__, __LINE__);
3364 XS_SETERR(xs, HBA_BUSRESET);
3367 isp_prt(isp, ISP_LOGERR, lipd, chan, j);
3375 * This is a broadcast event that has to be sent across
3376 * all active channels.
3378 for (chan = 0; chan < isp->isp_nchan; chan++) {
3379 fcp = FCPARAM(isp, chan);
3380 if (fcp->role == ISP_ROLE_NONE)
3382 fcp->isp_linkstate = 1;
3383 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3384 fcp->isp_loopstate = LOOP_HAVE_LINK;
3385 ISP_SET_SENDMARKER(isp, chan, 1);
3386 isp_async(isp, ISPASYNC_LOOP_UP, chan);
3387 #ifdef ISP_TARGET_MODE
3388 isp_target_async(isp, chan, mbox);
3393 case ASYNC_LOOP_DOWN:
3395 * This is a broadcast event that has to be sent across
3396 * all active channels.
3398 for (chan = 0; chan < isp->isp_nchan; chan++) {
3399 fcp = FCPARAM(isp, chan);
3400 if (fcp->role == ISP_ROLE_NONE)
3402 ISP_SET_SENDMARKER(isp, chan, 1);
3403 fcp->isp_linkstate = 0;
3404 fcp->isp_loopstate = LOOP_NIL;
3405 isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
3406 #ifdef ISP_TARGET_MODE
3407 isp_target_async(isp, chan, mbox);
3412 case ASYNC_LOOP_RESET:
3414 * This is a broadcast event that has to be sent across
3415 * all active channels.
3417 for (chan = 0; chan < isp->isp_nchan; chan++) {
3418 fcp = FCPARAM(isp, chan);
3419 if (fcp->role == ISP_ROLE_NONE)
3421 ISP_SET_SENDMARKER(isp, chan, 1);
3422 if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3423 fcp->isp_loopstate = LOOP_HAVE_LINK;
3424 isp_async(isp, ISPASYNC_LOOP_RESET, chan);
3425 #ifdef ISP_TARGET_MODE
3426 isp_target_async(isp, chan, mbox);
3431 case ASYNC_PDB_CHANGED:
3433 int echan, nphdl, nlstate, reason;
3435 nphdl = ISP_READ(isp, OUTMAILBOX1);
3436 nlstate = ISP_READ(isp, OUTMAILBOX2);
3437 reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
3438 if (ISP_CAP_MULTI_ID(isp)) {
3439 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3440 if (chan == 0xff || nphdl == NIL_HANDLE) {
3442 echan = isp->isp_nchan - 1;
3443 } else if (chan >= isp->isp_nchan) {
3451 for (; chan <= echan; chan++) {
3452 fcp = FCPARAM(isp, chan);
3453 if (fcp->role == ISP_ROLE_NONE)
3455 if (fcp->isp_loopstate > LOOP_LTEST_DONE) {
3456 if (nphdl != NIL_HANDLE &&
3457 nphdl == fcp->isp_login_hdl &&
3458 reason == PDB24XX_AE_OPN_2)
3460 fcp->isp_loopstate = LOOP_LTEST_DONE;
3461 } else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3462 fcp->isp_loopstate = LOOP_HAVE_LINK;
3463 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3464 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
3468 case ASYNC_CHANGE_NOTIFY:
3472 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) |
3473 ISP_READ(isp, OUTMAILBOX2);
3474 if (ISP_CAP_MULTI_ID(isp)) {
3475 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3476 if (chan >= isp->isp_nchan)
3481 fcp = FCPARAM(isp, chan);
3482 if (fcp->role == ISP_ROLE_NONE)
3484 if (fcp->isp_loopstate > LOOP_LTEST_DONE)
3485 fcp->isp_loopstate = LOOP_LTEST_DONE;
3486 else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3487 fcp->isp_loopstate = LOOP_HAVE_LINK;
3488 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3489 ISPASYNC_CHANGE_SNS, portid);
3492 case ASYNC_ERR_LOGGING_DISABLED:
3493 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)",
3494 ISP_READ(isp, OUTMAILBOX1));
3496 case ASYNC_P2P_INIT_ERR:
3497 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)",
3498 ISP_READ(isp, OUTMAILBOX1));
3501 isp_prt(isp, ISP_LOGWARN, "Receive Error");
3503 case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */
3504 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
3506 case ASYNC_FW_RESTART_COMPLETE:
3507 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete");
3509 case ASYNC_TEMPERATURE_ALERT:
3510 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)",
3511 ISP_READ(isp, OUTMAILBOX1));
3513 case ASYNC_INTER_DRIVER_COMP:
3514 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication complete");
3516 case ASYNC_INTER_DRIVER_NOTIFY:
3517 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication notification");
3519 case ASYNC_INTER_DRIVER_TIME_EXT:
3520 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication time extended");
3522 case ASYNC_TRANSCEIVER_INSERTION:
3523 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)",
3524 ISP_READ(isp, OUTMAILBOX1));
3526 case ASYNC_TRANSCEIVER_REMOVAL:
3527 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal");
3529 case ASYNC_NIC_FW_STATE_CHANGE:
3530 isp_prt(isp, ISP_LOGDEBUG0, "NIC Firmware State Change");
3532 case ASYNC_AUTOLOAD_FW_COMPLETE:
3533 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete");
3535 case ASYNC_AUTOLOAD_FW_FAILURE:
3536 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure");
3539 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
3545 * Handle completions with control handles by waking up waiting threads.
3548 isp_handle_control(ispsoftc_t *isp, isphdr_t *hp)
3553 switch (hp->rqs_entry_type) {
3554 case RQSTYPE_RESPONSE:
3555 case RQSTYPE_MARKER:
3556 case RQSTYPE_NOTIFY_ACK:
3558 case RQSTYPE_TSK_MGMT:
3559 case RQSTYPE_CT_PASSTHRU:
3560 case RQSTYPE_VP_MODIFY:
3561 case RQSTYPE_VP_CTRL:
3562 case RQSTYPE_ABORT_IO:
3565 case RQSTYPE_ELS_PASSTHRU:
3566 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
3567 if (ISP_H2HT(hdl) != ISP_HANDLE_CTRL)
3569 ptr = isp_find_xs(isp, hdl);
3571 isp_destroy_handle(isp, hdl);
3572 memcpy(ptr, hp, QENTRY_LEN);
3581 isp_handle_rpt_id_acq(ispsoftc_t *isp, isphdr_t *hp)
3588 isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
3589 portid = (uint32_t)rid.ridacq_vp_port_hi << 16 |
3590 rid.ridacq_vp_port_lo;
3591 if (rid.ridacq_format == 0) {
3592 for (chan = 0; chan < isp->isp_nchan; chan++) {
3593 fcp = FCPARAM(isp, chan);
3594 if (fcp->role == ISP_ROLE_NONE)
3596 c = (chan == 0) ? 127 : (chan - 1);
3597 if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
3599 fcp->isp_loopstate = LOOP_HAVE_LINK;
3600 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3601 chan, ISPASYNC_CHANGE_OTHER);
3603 fcp->isp_loopstate = LOOP_NIL;
3604 isp_async(isp, ISPASYNC_LOOP_DOWN,
3609 fcp = FCPARAM(isp, rid.ridacq_vp_index);
3610 if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
3611 rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
3612 fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7;
3613 fcp->isp_portid = portid;
3614 fcp->isp_loopstate = LOOP_HAVE_ADDR;
3615 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3616 rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
3618 fcp->isp_loopstate = LOOP_NIL;
3619 isp_async(isp, ISPASYNC_LOOP_DOWN,
3620 rid.ridacq_vp_index);
3626 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs)
3628 int ru_marked, sv_marked;
3629 int chan = XS_CHANNEL(xs);
3631 switch (sp->req_completion_status) {
3635 case RQCS_DMA_ERROR:
3636 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error");
3638 XS_SETERR(xs, HBA_BOTCH);
3641 case RQCS_TRANSPORT_ERROR:
3642 isp_xs_prt(isp, xs, ISP_LOGERR, "Transport Error");
3644 XS_SETERR(xs, HBA_BOTCH);
3647 case RQCS_RESET_OCCURRED:
3648 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command");
3649 FCPARAM(isp, chan)->sendmarker = 1;
3651 XS_SETERR(xs, HBA_BUSRESET);
3655 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted");
3656 FCPARAM(isp, chan)->sendmarker = 1;
3658 XS_SETERR(xs, HBA_ABORTED);
3662 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out");
3664 XS_SETERR(xs, HBA_CMDTIMEOUT);
3667 case RQCS_DATA_OVERRUN:
3668 XS_SET_RESID(xs, sp->req_resid);
3669 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun");
3671 XS_SETERR(xs, HBA_DATAOVR);
3674 case RQCS_DRE: /* data reassembly error */
3675 isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs));
3677 XS_SETERR(xs, HBA_BOTCH);
3680 case RQCS_TABORT: /* aborted by target */
3681 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs));
3683 XS_SETERR(xs, HBA_ABORTED);
3686 case RQCS_DATA_UNDERRUN:
3687 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
3689 * We can get an underrun w/o things being marked
3690 * if we got a non-zero status.
3692 sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
3693 if ((ru_marked == 0 && sv_marked == 0) ||
3694 (sp->req_resid > XS_XFRLEN(xs))) {
3695 isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked");
3697 XS_SETERR(xs, HBA_BOTCH);
3700 XS_SET_RESID(xs, sp->req_resid);
3701 isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff);
3704 case RQCS_PORT_UNAVAILABLE:
3706 * No such port on the loop. Moral equivalent of SELTIMEO
3708 case RQCS_PORT_LOGGED_OUT:
3711 uint8_t sts = sp->req_completion_status & 0xff;
3712 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
3716 * It was there (maybe)- treat as a selection timeout.
3718 if (sts == RQCS_PORT_UNAVAILABLE) {
3719 reason = "unavailable";
3724 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
3725 chan, reason, XS_TGT(xs));
3727 /* XXX: Should we trigger rescan or FW announce change? */
3730 lp = &fcp->portdb[XS_TGT(xs)];
3731 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
3732 *XS_STSP(xs) = SCSI_BUSY;
3733 XS_SETERR(xs, HBA_TGTBSY);
3735 XS_SETERR(xs, HBA_SELTIMEOUT);
3739 case RQCS_PORT_CHANGED:
3740 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan);
3742 *XS_STSP(xs) = SCSI_BUSY;
3743 XS_SETERR(xs, HBA_TGTBSY);
3747 case RQCS_ENOMEM: /* f/w resource unavailable */
3748 isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan);
3750 *XS_STSP(xs) = SCSI_BUSY;
3751 XS_SETERR(xs, HBA_TGTBSY);
3755 case RQCS_TMO: /* task management overrun */
3756 isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan);
3758 *XS_STSP(xs) = SCSI_BUSY;
3759 XS_SETERR(xs, HBA_TGTBSY);
3764 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan);
3768 XS_SETERR(xs, HBA_BOTCH);
3771 #define ISP_FC_IBITS(op) ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3]))
3772 #define ISP_FC_OBITS(op) ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7]))
3774 #define ISP_FC_OPMAP(in0, out0) 0, 0, 0, in0, 0, 0, 0, out0
3775 #define ISP_FC_OPMAP_HALF(in1, in0, out1, out0) 0, 0, in1, in0, 0, 0, out1, out0
3776 #define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0) in3, in2, in1, in0, out3, out2, out1, out0
3777 static const uint32_t mbpfc[] = {
3778 ISP_FC_OPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
3779 ISP_FC_OPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
3780 ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f), /* 0x02: MBOX_EXEC_FIRMWARE */
3781 ISP_FC_OPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */
3782 ISP_FC_OPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
3783 ISP_FC_OPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
3784 ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */
3785 ISP_FC_OPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
3786 ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f), /* 0x08: MBOX_ABOUT_FIRMWARE */
3787 ISP_FC_OPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */
3788 ISP_FC_OPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
3789 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */
3790 ISP_FC_OPMAP(0x00, 0x00), /* 0x0c: */
3791 ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
3792 ISP_FC_OPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
3793 ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
3794 ISP_FC_OPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
3795 ISP_FC_OPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
3796 ISP_FC_OPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
3797 ISP_FC_OPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
3798 ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03), /* 0x14: MBOX_STOP_FIRMWARE */
3799 ISP_FC_OPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */
3800 ISP_FC_OPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */
3801 ISP_FC_OPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */
3802 ISP_FC_OPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */
3803 ISP_FC_OPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */
3804 ISP_FC_OPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */
3805 ISP_FC_OPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
3806 ISP_FC_OPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */
3807 ISP_FC_OPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
3808 ISP_FC_OPMAP(0x00, 0x00), /* 0x1e: */
3809 ISP_FC_OPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
3810 ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf), /* 0x20: MBOX_GET_LOOP_ID */
3811 ISP_FC_OPMAP(0x00, 0x00), /* 0x21: */
3812 ISP_FC_OPMAP(0x03, 0x4b), /* 0x22: MBOX_GET_TIMEOUT_PARAMS */
3813 ISP_FC_OPMAP(0x00, 0x00), /* 0x23: */
3814 ISP_FC_OPMAP(0x00, 0x00), /* 0x24: */
3815 ISP_FC_OPMAP(0x00, 0x00), /* 0x25: */
3816 ISP_FC_OPMAP(0x00, 0x00), /* 0x26: */
3817 ISP_FC_OPMAP(0x00, 0x00), /* 0x27: */
3818 ISP_FC_OPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
3819 ISP_FC_OPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
3820 ISP_FC_OPMAP(0x00, 0x00), /* 0x2a: */
3821 ISP_FC_OPMAP(0x00, 0x00), /* 0x2b: */
3822 ISP_FC_OPMAP(0x00, 0x00), /* 0x2c: */
3823 ISP_FC_OPMAP(0x00, 0x00), /* 0x2d: */
3824 ISP_FC_OPMAP(0x00, 0x00), /* 0x2e: */
3825 ISP_FC_OPMAP(0x00, 0x00), /* 0x2f: */
3826 ISP_FC_OPMAP(0x00, 0x00), /* 0x30: */
3827 ISP_FC_OPMAP(0x00, 0x00), /* 0x31: */
3828 ISP_FC_OPMAP(0x4b, 0x4b), /* 0x32: MBOX_SET_TIMEOUT_PARAMS */
3829 ISP_FC_OPMAP(0x00, 0x00), /* 0x33: */
3830 ISP_FC_OPMAP(0x00, 0x00), /* 0x34: */
3831 ISP_FC_OPMAP(0x00, 0x00), /* 0x35: */
3832 ISP_FC_OPMAP(0x00, 0x00), /* 0x36: */
3833 ISP_FC_OPMAP(0x00, 0x00), /* 0x37: */
3834 ISP_FC_OPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
3835 ISP_FC_OPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
3836 ISP_FC_OPMAP(0x00, 0x00), /* 0x3a: */
3837 ISP_FC_OPMAP(0x00, 0x00), /* 0x3b: */
3838 ISP_FC_OPMAP(0x00, 0x00), /* 0x3c: */
3839 ISP_FC_OPMAP(0x00, 0x00), /* 0x3d: */
3840 ISP_FC_OPMAP(0x00, 0x00), /* 0x3e: */
3841 ISP_FC_OPMAP(0x00, 0x00), /* 0x3f: */
3842 ISP_FC_OPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */
3843 ISP_FC_OPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */
3844 ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf), /* 0x42: MBOX_GET_RESOURCE_COUNT */
3845 ISP_FC_OPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */
3846 ISP_FC_OPMAP(0x00, 0x00), /* 0x44: */
3847 ISP_FC_OPMAP(0x00, 0x00), /* 0x45: */
3848 ISP_FC_OPMAP(0x00, 0x00), /* 0x46: */
3849 ISP_FC_OPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */
3850 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
3851 ISP_FC_OPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */
3852 ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
3853 ISP_FC_OPMAP(0x00, 0x00), /* 0x4b: */
3854 ISP_FC_OPMAP(0x00, 0x00), /* 0x4c: */
3855 ISP_FC_OPMAP(0x00, 0x00), /* 0x4d: */
3856 ISP_FC_OPMAP(0x00, 0x00), /* 0x4e: */
3857 ISP_FC_OPMAP(0x00, 0x00), /* 0x4f: */
3858 ISP_FC_OPMAP(0x00, 0x00), /* 0x50: */
3859 ISP_FC_OPMAP(0x00, 0x00), /* 0x51: */
3860 ISP_FC_OPMAP(0x00, 0x00), /* 0x52: */
3861 ISP_FC_OPMAP(0x00, 0x00), /* 0x53: */
3862 ISP_FC_OPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
3863 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */
3864 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */
3865 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */
3866 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */
3867 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */
3868 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */
3869 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
3870 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
3871 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */
3872 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */
3873 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */
3874 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */
3875 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */
3876 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */
3877 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
3878 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
3879 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */
3880 ISP_FC_OPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */
3881 ISP_FC_OPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */
3882 ISP_FC_OPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */
3883 ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f), /* 0x69: MBOX_GET_FW_STATE */
3884 ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */
3885 ISP_FC_OPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */
3886 ISP_FC_OPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */
3887 ISP_FC_OPMAP(0x00, 0x00), /* 0x6d: */
3888 ISP_FC_OPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */
3889 ISP_FC_OPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */
3890 ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03), /* 0x70: MBOX_SEND_CHANGE_REQUEST */
3891 ISP_FC_OPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */
3892 ISP_FC_OPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */
3893 ISP_FC_OPMAP(0x00, 0x00), /* 0x73: */
3894 ISP_FC_OPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */
3895 ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07), /* 0x75: GET PORT/NODE NAME LIST */
3896 ISP_FC_OPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */
3897 ISP_FC_OPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */
3898 ISP_FC_OPMAP(0x00, 0x00), /* 0x78: */
3899 ISP_FC_OPMAP(0x00, 0x00), /* 0x79: */
3900 ISP_FC_OPMAP(0x00, 0x00), /* 0x7a: */
3901 ISP_FC_OPMAP(0x00, 0x00), /* 0x7b: */
3902 ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07), /* 0x7c: Get ID List */
3903 ISP_FC_OPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */
3904 ISP_FC_OPMAP(0x0f, 0x01) /* 0x7e: LUN RESET */
3906 #define MAX_FC_OPCODE 0x7e
3910 * (1): this sets bits 21..16 in mailbox register #8, which we nominally
3911 * do not access at this time in the core driver. The caller is
3912 * responsible for setting this register first (Gross!). The assumption
3913 * is that we won't overflow.
3916 static const char *fc_mbcmd_names[] = {
3930 "WRITE RAM WORD EXTENDED",
3932 "READ RAM WORD EXTENDED",
3933 "INIT REQUEST QUEUE", /* 10h */
3934 "INIT RESULT QUEUE",
3944 "SINGLE STEP QUEUE",
3946 "GET DEV QUEUE STATUS",
3948 "GET FIRMWARE STATUS",
3949 "GET LOOP ID", /* 20h */
3951 "GET TIMEOUT PARAMS",
3957 "GET FIRMWARE OPTIONS",
3958 "GET PORT QUEUE PARAMS",
3959 "GENERATE SYSTEM ERROR",
3965 "WRITE SFP", /* 30h */
3967 "SET TIMEOUT PARAMS",
3973 "SET FIRMWARE OPTIONS",
3974 "SET PORT QUEUE PARAMS",
3978 "RESTART NIC FIRMWARE",
3981 "LOOP PORT BYPASS", /* 40h */
3983 "GET RESOURCE COUNT",
3984 "REQUEST NON PARTICIPATING MODE",
3985 "DIAGNOSTIC ECHO TEST",
3986 "DIAGNOSTIC LOOPBACK",
3988 "GET PORT DATABASE ENHANCED",
3989 "INIT FIRMWARE MULTI ID",
3991 "GET VP DATABASE ENTRY",
3997 "GET FCF LIST", /* 50h */
3998 "GET DCBX PARAMETERS",
4009 "FIRMWARE HEARTBEAT",
4010 "GET/SET DATA RATE",
4013 "INIT FIRMWARE", /* 60h */
4014 "GET INIT CONTROL BLOCK",
4016 "GET FC-AL POSITION MAP",
4017 "GET PORT DATABASE",
4026 "GET LINK STATS & PRIVATE DATA CNTS",
4029 "SEND CHANGE REQUEST", /* 70h */
4034 "GET PORT/NODE NAME LIST",
4036 "INITIALIZE IP MAILBOX",
4047 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
4049 const char *cname, *xname, *sname;
4050 char tname[16], mname[16];
4051 unsigned int ibits, obits, box, opcode, t, to;
4053 opcode = mbp->param[0];
4054 if (opcode > MAX_FC_OPCODE) {
4055 mbp->param[0] = MBOX_INVALID_COMMAND;
4056 isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
4059 cname = fc_mbcmd_names[opcode];
4060 ibits = ISP_FC_IBITS(opcode);
4061 obits = ISP_FC_OBITS(opcode);
4062 if (cname == NULL) {
4064 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
4066 isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname);
4069 * Pick up any additional bits that the caller might have set.
4071 ibits |= mbp->ibits;
4072 obits |= mbp->obits;
4075 * Mask any bits that the caller wants us to mask
4077 ibits &= mbp->ibitm;
4078 obits &= mbp->obitm;
4081 if (ibits == 0 && obits == 0) {
4082 mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
4083 isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
4087 for (box = 0; box < ISP_NMBOX(isp); box++) {
4088 if (ibits & (1 << box)) {
4089 isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
4091 ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
4093 isp->isp_mboxtmp[box] = mbp->param[box] = 0;
4096 isp->isp_obits = obits;
4097 isp->isp_mboxbsy = 1;
4100 * Set Host Interrupt condition so that RISC will pick up mailbox regs.
4102 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
4105 * While we haven't finished the command, spin our wheels here.
4107 to = (mbp->timeout == 0) ? MBCMD_DEFAULT_TIMEOUT : mbp->timeout;
4108 for (t = 0; t < to; t += 100) {
4109 if (!isp->isp_mboxbsy)
4112 if (!isp->isp_mboxbsy)
4118 * Did the command time out?
4120 if (isp->isp_mboxbsy) {
4121 isp->isp_mboxbsy = 0;
4122 isp_prt(isp, ISP_LOGWARN, "Mailbox Command (0x%x) Timeout (%uus) (%s:%d)",
4123 opcode, to, mbp->func, mbp->lineno);
4124 mbp->param[0] = MBOX_TIMEOUT;
4129 * Copy back output registers.
4131 for (box = 0; box < ISP_NMBOX(isp); box++) {
4132 if (obits & (1 << box)) {
4133 mbp->param[box] = isp->isp_mboxtmp[box];
4134 isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
4140 if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE)
4143 if ((mbp->param[0] & 0xbfe0) == 0 &&
4144 (mbp->logval & MBLOGMASK(mbp->param[0])) == 0)
4149 switch (mbp->param[0]) {
4150 case MBOX_INVALID_COMMAND:
4151 xname = "INVALID COMMAND";
4153 case MBOX_HOST_INTERFACE_ERROR:
4154 xname = "HOST INTERFACE ERROR";
4156 case MBOX_TEST_FAILED:
4157 xname = "TEST FAILED";
4159 case MBOX_COMMAND_ERROR:
4160 xname = "COMMAND ERROR";
4161 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x",
4165 case MBOX_COMMAND_PARAM_ERROR:
4166 xname = "COMMAND PARAMETER ERROR";
4168 case MBOX_PORT_ID_USED:
4169 xname = "PORT ID ALREADY IN USE";
4171 case MBOX_LOOP_ID_USED:
4172 xname = "LOOP ID ALREADY IN USE";
4174 case MBOX_ALL_IDS_USED:
4175 xname = "ALL LOOP IDS IN USE";
4177 case MBOX_NOT_LOGGED_IN:
4178 xname = "NOT LOGGED IN";
4180 case MBOX_LINK_DOWN_ERROR:
4181 xname = "LINK DOWN ERROR";
4183 case MBOX_LOOPBACK_ERROR:
4184 xname = "LOOPBACK ERROR";
4186 case MBOX_CHECKSUM_ERROR:
4187 xname = "CHECKSUM ERROR";
4189 case MBOX_INVALID_PRODUCT_KEY:
4190 xname = "INVALID PRODUCT KEY";
4192 case MBOX_REGS_BUSY:
4193 xname = "REGISTERS BUSY";
4199 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
4204 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)",
4205 cname, xname, sname);
4210 isp_fw_state(ispsoftc_t *isp, int chan)
4214 MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
4215 isp_mboxcmd(isp, &mbs);
4216 if (mbs.param[0] == MBOX_COMMAND_COMPLETE)
4217 return (mbs.param[1]);
4222 isp_setdfltfcparm(ispsoftc_t *isp, int chan)
4224 fcparam *fcp = FCPARAM(isp, chan);
4227 * Establish some default parameters.
4229 fcp->role = DEFAULT_ROLE(isp, chan);
4230 fcp->isp_retry_delay = ICB_DFLT_RDELAY;
4231 fcp->isp_retry_count = ICB_DFLT_RCOUNT;
4232 fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
4233 fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
4234 fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
4235 fcp->isp_fwoptions = 0;
4236 fcp->isp_xfwoptions = 0;
4237 fcp->isp_zfwoptions = 0;
4238 fcp->isp_lasthdl = NIL_HANDLE;
4239 fcp->isp_login_hdl = NIL_HANDLE;
4241 fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
4242 fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
4243 if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
4244 fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
4245 fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
4246 fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP;
4247 fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO;
4250 * Now try and read NVRAM unless told to not do so.
4251 * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
4253 if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
4256 * Give a couple of tries at reading NVRAM.
4258 for (i = 0; i < 2; i++) {
4259 j = isp_read_nvram(isp, chan);
4265 isp->isp_confopts |= ISP_CFG_NONVRAM;
4269 fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
4270 fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
4271 isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
4272 chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
4273 (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
4274 isp_class3_roles[fcp->role]);
4278 * Re-initialize the ISP and complete all orphaned commands
4279 * with a 'botched' notice. The reset/init routines should
4280 * not disturb an already active list of commands.
4284 isp_reinit(ispsoftc_t *isp, int do_load_defaults)
4288 if (isp->isp_state > ISP_RESETSTATE)
4290 if (isp->isp_state != ISP_RESETSTATE)
4291 isp_reset(isp, do_load_defaults);
4292 if (isp->isp_state != ISP_RESETSTATE) {
4294 isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
4299 if (isp->isp_state > ISP_RESETSTATE &&
4300 isp->isp_state != ISP_RUNSTATE) {
4302 isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
4303 ISP_DISABLE_INTS(isp);
4307 isp_clear_commands(isp);
4308 for (i = 0; i < isp->isp_nchan; i++)
4309 isp_clear_portdb(isp, i);
4317 isp_read_nvram(ispsoftc_t *isp, int bus)
4320 return (isp_read_nvram_2400(isp));
4324 isp_read_nvram_2400(ispsoftc_t *isp)
4327 uint32_t addr, csum, lwrds, *dptr;
4328 uint8_t nvram_data[ISP2400_NVRAM_SIZE];
4330 if (isp->isp_port) {
4331 addr = ISP2400_NVRAM_PORT1_ADDR;
4333 addr = ISP2400_NVRAM_PORT0_ADDR;
4336 dptr = (uint32_t *) nvram_data;
4337 for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4338 isp_rd_2400_nvram(isp, addr++, dptr++);
4340 if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
4341 nvram_data[2] != 'P') {
4342 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)",
4343 nvram_data[0], nvram_data[1], nvram_data[2]);
4347 dptr = (uint32_t *) nvram_data;
4348 for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4350 ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
4354 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
4358 isp_parse_nvram_2400(isp, nvram_data);
4364 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
4367 uint32_t base = 0x7ffe0000;
4371 base = 0x7fe7c000; /* XXX: Observation, may be wrong. */
4372 } else if (IS_25XX(isp)) {
4373 base = 0x7ff00000 | 0x48000;
4375 ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
4376 for (loops = 0; loops < 5000; loops++) {
4378 tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
4379 if ((tmp & (1U << 31)) != 0) {
4383 if (tmp & (1U << 31)) {
4384 *rp = ISP_READ(isp, BIU2400_FLASH_DATA);
4385 ISP_SWIZZLE_NVRAM_LONG(isp, rp);
4392 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
4394 fcparam *fcp = FCPARAM(isp, 0);
4397 isp_prt(isp, ISP_LOGDEBUG0,
4398 "NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d",
4399 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
4400 (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
4401 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
4402 (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
4403 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
4404 isp_prt(isp, ISP_LOGDEBUG0,
4405 "NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
4406 ISP2400_NVRAM_HARDLOOPID(nvram_data),
4407 ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
4408 ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
4409 ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
4411 wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
4412 fcp->isp_wwpn_nvram = wwn;
4414 wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
4416 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
4420 if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
4421 wwn = fcp->isp_wwpn_nvram;
4422 wwn &= ~((uint64_t) 0xfff << 48);
4424 fcp->isp_wwnn_nvram = wwn;
4426 if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
4427 DEFAULT_FRAMESIZE(isp) =
4428 ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
4430 if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
4431 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
4433 fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
4434 fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
4435 fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);