]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/isp/isp.c
ping(8): Fix a mandoc related issue
[FreeBSD/FreeBSD.git] / sys / dev / isp / isp.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  *  Copyright (c) 2009-2020 Alexander Motin <mav@FreeBSD.org>
5  *  Copyright (c) 1997-2009 by Matthew Jacob
6  *  All rights reserved.
7  *
8  *  Redistribution and use in source and binary forms, with or without
9  *  modification, are permitted provided that the following conditions
10  *  are met:
11  *
12  *  1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *  2. Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *
18  *  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  *  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  *  SUCH DAMAGE.
29  *
30  */
31
32 /*
33  * Machine and OS Independent (well, as best as possible)
34  * code for the Qlogic ISP SCSI and FC-SCSI adapters.
35  */
36
37 /*
38  * Inspiration and ideas about this driver are from Erik Moe's Linux driver
39  * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some
40  * ideas dredged from the Solaris driver.
41  */
42
43 /*
44  * Include header file appropriate for platform we're building on.
45  */
46 #ifdef  __NetBSD__
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD$");
49 #include <dev/ic/isp_netbsd.h>
50 #endif
51 #ifdef  __FreeBSD__
52 #include <sys/cdefs.h>
53 __FBSDID("$FreeBSD$");
54 #include <dev/isp/isp_freebsd.h>
55 #endif
56 #ifdef  __OpenBSD__
57 #include <dev/ic/isp_openbsd.h>
58 #endif
59 #ifdef  __linux__
60 #include "isp_linux.h"
61 #endif
62 #ifdef  __svr4__
63 #include "isp_solaris.h"
64 #endif
65
66 /*
67  * Local static data
68  */
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";
73
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
91 };
92
93 /*
94  * Local function prototypes.
95  */
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 *);
119
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 *);
125
126 static void
127 isp_change_fw_state(ispsoftc_t *isp, int chan, int state)
128 {
129         fcparam *fcp = FCPARAM(isp, chan);
130
131         if (fcp->isp_fwstate == state)
132                 return;
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;
137 }
138
139 /*
140  * Reset Hardware.
141  *
142  * Hit the chip over the head, download new f/w if available and set it running.
143  *
144  * Locking done elsewhere.
145  */
146
147 void
148 isp_reset(ispsoftc_t *isp, int do_load_defaults)
149 {
150         mbreg_t mbs;
151         char *buf;
152         uint64_t fwt;
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";
157
158         isp->isp_state = ISP_NILSTATE;
159         ISP_DISABLE_INTS(isp);
160
161         /*
162          * Put the board into PAUSE mode (so we can read the SXP registers
163          * or write FPM/FBM registers).
164          */
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);
168
169         switch (isp->isp_type) {
170         case ISP_HA_FC_2400:
171                 btype = "2422";
172                 break;
173         case ISP_HA_FC_2500:
174                 btype = "2532";
175                 break;
176         case ISP_HA_FC_2600:
177                 btype = "2600";
178                 break;
179         case ISP_HA_FC_2700:
180                 btype = "2700";
181                 break;
182         default:
183                 break;
184         }
185
186         /*
187          * Stop DMA and wait for it to stop.
188          */
189         ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
190         for (loops = 0; loops < 100000; loops++) {
191                 ISP_DELAY(10);
192                 val = ISP_READ(isp, BIU2400_CSR);
193                 if ((val & BIU2400_DMA_ACTIVE) == 0) {
194                         break;
195                 }
196         }
197         if (val & BIU2400_DMA_ACTIVE)
198                 isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
199
200         /*
201          * Hold it in SOFT_RESET and STOP state for 100us.
202          */
203         ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
204         ISP_DELAY(100);
205         for (loops = 0; loops < 10000; loops++) {
206                 ISP_DELAY(5);
207                 val = ISP_READ(isp, OUTMAILBOX0);
208                 if (val != 0x4)
209                         break;
210         }
211         switch (val) {
212         case 0x0:
213                 break;
214         case 0x4:
215                 isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
216                 return;
217         case 0xf:
218                 isp_prt(isp, ISP_LOGERR, "Board configuration error.");
219                 return;
220         default:
221                 isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
222                 return;
223         }
224
225         /*
226          * Reset RISC Processor
227          */
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);
231
232         /*
233          * Post-RISC Reset stuff.
234          */
235         for (loops = 0; loops < 10000; loops++) {
236                 ISP_DELAY(5);
237                 val = ISP_READ(isp, OUTMAILBOX0);
238                 if (val != 0x4)
239                         break;
240         }
241         switch (val) {
242         case 0x0:
243                 break;
244         case 0x4:
245                 isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
246                 return;
247         case 0xf:
248                 isp_prt(isp, ISP_LOGERR, "Board configuration error.");
249                 return;
250         default:
251                 isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
252                 return;
253         }
254
255         isp->isp_reqidx = isp->isp_reqodx = 0;
256         isp->isp_resodx = 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);
262         if (!IS_26XX(isp)) {
263                 ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
264                 ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
265         }
266         ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
267         ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
268
269         /*
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.
273          */
274
275         /*
276          * Do some sanity checking by running a NOP command.
277          * If it succeeds, the ROM firmware is now running.
278          */
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]);
283                 return;
284         }
285
286         /*
287          * Do some operational tests
288          */
289         {
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,
299                 };
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];
304                 }
305                 isp_mboxcmd(isp, &mbs);
306                 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
307                         return;
308                 }
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]);
312                                 return;
313                         }
314                 }
315         }
316
317         /*
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.
325          */
326         if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
327                 dodnld = 0;
328         } else {
329
330                 /*
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.
334                  */
335                 if (ISP_MBOXDMASETUP(isp) != 0) {
336                         isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
337                         return;
338                 }
339         }
340
341         code_org = ISP_CODE_ORG_2400;
342         loaded_fw = 0;
343         if (dodnld) {
344                 const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
345                 uint32_t la, wi, wl;
346
347                 /*
348                  * Keep loading until we run out of f/w.
349                  */
350                 code_org = ptr[2];      /* 1st load address is our start addr */
351                 for (;;) {
352                         isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
353
354                         wi = 0;
355                         la = ptr[2];
356                         wl = ptr[3];
357                         while (wi < ptr[3]) {
358                                 uint32_t *cp;
359                                 uint32_t nw;
360
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);
367                                 mbs.param[1] = la;
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;
371                                 mbs.param[5] = nw;
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");
379                                         return;
380                                 }
381                                 la += nw;
382                                 wi += nw;
383                                 wl -= nw;
384                         }
385
386                         if (ptr[1] == 0) {
387                                 break;
388                         }
389                         ptr += ptr[3];
390                 }
391                 loaded_fw = 1;
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);
395                 mbs.ibitm = 0x01;
396                 mbs.obitm = 0x07;
397                 isp_mboxcmd(isp, &mbs);
398                 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
399                         isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
400                         return;
401                 }
402         } else {
403                 isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
404         }
405
406         /*
407          * If we loaded firmware, verify its checksum
408          */
409         if (loaded_fw) {
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);
416                         return;
417                 }
418         }
419
420         /*
421          * Now start it rolling.
422          *
423          * If we didn't actually download f/w,
424          * we still need to (re)start it.
425          */
426         MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000);
427         mbs.param[1] = code_org >> 16;
428         mbs.param[2] = code_org;
429         if (!IS_26XX(isp))
430                 mbs.param[3] = loaded_fw ? 0 : 1;
431         isp_mboxcmd(isp, &mbs);
432         if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
433                 return;
434
435         /*
436          * Ask the chip for the current firmware version.
437          * This should prove that the new firmware is working.
438          */
439         MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 5000000);
440         isp_mboxcmd(isp, &mbs);
441         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
442                 return;
443         }
444
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) {
451                 isp->isp_fwattr |=
452                     (((uint64_t) mbs.param[16]) << 32) |
453                     (((uint64_t) mbs.param[17]) << 48);
454         }
455
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]);
458
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);
465         }
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);
469         }
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);
473         }
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);
477         }
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);
481         }
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);
485         }
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);
489         }
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);
493         }
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);
497         }
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);
501         }
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);
505         }
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);
509         }
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);
514         }
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);
518         }
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);
522         }
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);
526         }
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);
530         }
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);
534         }
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);
538         }
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);
542         }
543         if (fwt) {
544                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (unknown 0x%08x%08x)", buf,
545                     (uint32_t) (fwt >> 32), (uint32_t) fwt);
546         }
547         isp_prt(isp, ISP_LOGCONFIG, "%s", buf);
548
549         /*
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.
553          */
554         MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
555         isp_mboxcmd(isp, &mbs);
556         if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
557                 return;
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);
560
561         /*
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
564          * work for them).
565          */
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);
570                         isp->isp_nchan = 1;
571                 } else if (!ISP_CAP_VP0(isp)) {
572                         isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID "
573                             "feature properly without VP0_Decoupling");
574                         isp->isp_nchan = 1;
575                 }
576         }
577
578         /*
579          * Final DMA setup after we got isp_maxcmds.
580          */
581         if (ISP_MBOXDMASETUP(isp) != 0) {
582                 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
583                 return;
584         }
585
586         /*
587          * Setup interrupts.
588          */
589         if (ISP_IRQSETUP(isp) != 0) {
590                 isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ");
591                 return;
592         }
593         ISP_ENABLE_INTS(isp);
594
595         for (i = 0; i < isp->isp_nchan; i++)
596                 isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
597
598         isp->isp_state = ISP_RESETSTATE;
599
600         /*
601          * We get some default values established. As a side
602          * effect, NVRAM is read here (unless overriden by
603          * a configuration flag).
604          */
605         if (do_load_defaults) {
606                 for (i = 0; i < isp->isp_nchan; i++)
607                         isp_setdfltfcparm(isp, i);
608         }
609 }
610
611 /*
612  * Clean firmware shutdown.
613  */
614 static int
615 isp_stop(ispsoftc_t *isp)
616 {
617         mbreg_t mbs;
618
619         isp->isp_state = ISP_NILSTATE;
620         MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000);
621         mbs.param[1] = 0;
622         mbs.param[2] = 0;
623         mbs.param[3] = 0;
624         mbs.param[4] = 0;
625         mbs.param[5] = 0;
626         mbs.param[6] = 0;
627         mbs.param[7] = 0;
628         mbs.param[8] = 0;
629         isp_mboxcmd(isp, &mbs);
630         return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]);
631 }
632
633 /*
634  * Hardware shutdown.
635  */
636 void
637 isp_shutdown(ispsoftc_t *isp)
638 {
639
640         if (isp->isp_state >= ISP_RESETSTATE)
641                 isp_stop(isp);
642         ISP_DISABLE_INTS(isp);
643         ISP_WRITE(isp, BIU2400_ICR, 0);
644         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
645 }
646
647 /*
648  * Initialize Parameters of Hardware to a known state.
649  *
650  * Locks are held before coming here.
651  */
652 void
653 isp_init(ispsoftc_t *isp)
654 {
655         fcparam *fcp;
656         isp_icb_2400_t local, *icbp = &local;
657         mbreg_t mbs;
658         int chan;
659         int ownloopid = 0;
660
661         /*
662          * Check to see whether all channels have *some* kind of role
663          */
664         for (chan = 0; chan < isp->isp_nchan; chan++) {
665                 fcp = FCPARAM(isp, chan);
666                 if (fcp->role != ISP_ROLE_NONE) {
667                         break;
668                 }
669         }
670         if (chan == isp->isp_nchan) {
671                 isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan);
672                 return;
673         }
674
675         isp->isp_state = ISP_INITSTATE;
676
677         /*
678          * Start with channel 0.
679          */
680         fcp = FCPARAM(isp, 0);
681
682         /*
683          * Turn on LIP F8 async event (1)
684          */
685         MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
686         mbs.param[1] = 1;
687         isp_mboxcmd(isp, &mbs);
688         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
689                 return;
690         }
691
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;
699         } else {
700                 if (fcp->role & ISP_ROLE_TARGET)
701                         icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
702                 else
703                         icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
704                 if (fcp->role & ISP_ROLE_INITIATOR)
705                         icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
706                 else
707                         icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
708         }
709
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;
715         }
716
717         if (!IS_26XX(isp))
718                 icbp->icb_execthrottle = 0xffff;
719
720 #ifdef  ISP_TARGET_MODE
721         /*
722          * Set target exchange count. Take half if we are supporting both roles.
723          */
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);
727                 else
728                         icbp->icb_xchgcnt = isp->isp_maxcmds;
729         }
730 #endif
731
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;
736                 ownloopid = 0;
737         }
738
739         if (ownloopid)
740                 icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
741
742         if (isp->isp_confopts & ISP_CFG_NOFCTAPE) {
743                 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
744         }
745         if (isp->isp_confopts & ISP_CFG_FCTAPE) {
746                 icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE;
747         }
748
749         for (chan = 0; chan < isp->isp_nchan; chan++) {
750                 if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE)
751                         FCPARAM(isp, chan)->fctape_enabled = 1;
752                 else
753                         FCPARAM(isp, chan)->fctape_enabled = 0;
754         }
755
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;
760                 break;
761         case ISP_CFG_NPORT_ONLY:
762                 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
763                 icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
764                 break;
765         case ISP_CFG_NPORT:
766                 /* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */
767         case ISP_CFG_LPORT:
768                 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
769                 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
770                 break;
771         default:
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:
777                         break;
778                 default:
779                         icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
780                         icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
781                 }
782                 break;
783         }
784
785         switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
786         case ICB2400_OPT2_ZIO:
787         case ICB2400_OPT2_ZIO1:
788                 icbp->icb_idelaytimer = 0;
789                 break;
790         case 0:
791                 break;
792         default:
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;
795                 break;
796         }
797
798         if (IS_26XX(isp)) {
799                 /* Use handshake to reduce global lock congestion. */
800                 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR;
801                 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA;
802         }
803
804         if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) {
805                 icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24;
806         }
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;
825         } else {
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:
832                         break;
833                 case ICB2400_OPT3_RATE_2GB:
834                         if (isp->isp_type <= ISP_HA_FC_2500)
835                                 break;
836                         /*FALLTHROUGH*/
837                 case ICB2400_OPT3_RATE_1GB:
838                         if (isp->isp_type <= ISP_HA_FC_2400)
839                                 break;
840                         /*FALLTHROUGH*/
841                 default:
842                         icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
843                         icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
844                         break;
845                 }
846         }
847         if (ownloopid == 0) {
848                 icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
849         }
850         icbp->icb_logintime = ICB_LOGIN_TOV;
851
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)));
862         } else {
863                 isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
864                 return;
865         }
866         icbp->icb_rspnsin = isp->isp_resodx;
867         icbp->icb_rqstout = isp->isp_reqidx;
868         icbp->icb_retry_count = fcp->isp_retry_count;
869
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);
873                 return;
874         }
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",
878                     icbp->icb_rsltqlen);
879                 return;
880         }
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);
885
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);
890
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);
897                 return;
898         }
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));
905 #endif
906
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;
911         }
912
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);
914
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));
918
919         if (FC_SCRATCH_ACQUIRE(isp, 0)) {
920                 isp_prt(isp, ISP_LOGERR, sacq);
921                 return;
922         }
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);
928         }
929
930         /*
931          * Now fill in information about any additional channels
932          */
933         if (isp->isp_nchan > 1) {
934                 isp_icb_2400_vpinfo_t vpinfo, *vdst;
935                 vp_port_info_t pi, *pdst;
936                 size_t amt = 0;
937                 uint8_t *off;
938
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;
943                         chan = 0;
944                 } else {
945                         vpinfo.vp_count = isp->isp_nchan - 1;
946                         chan = 1;
947                 }
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++) {
954                         fcparam *fcp2;
955
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;
969                                 }
970
971                         }
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);
977                         else
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;
982                 }
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);
987                 }
988         }
989
990         /*
991          * Init the firmware
992          */
993         MBSINIT(&mbs, 0, MBLOGALL, 30000000);
994         if (isp->isp_nchan > 1) {
995                 mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
996         } else {
997                 mbs.param[0] = MBOX_INIT_FIRMWARE;
998         }
999         mbs.param[1] = 0;
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);
1008
1009         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1010                 return;
1011         }
1012
1013         /*
1014          * Whatever happens, we're now committed to being here.
1015          */
1016         isp->isp_state = ISP_RUNSTATE;
1017 }
1018
1019 static int
1020 isp_fc_enable_vp(ispsoftc_t *isp, int chan)
1021 {
1022         fcparam *fcp = FCPARAM(isp, chan);
1023         vp_modify_t vp;
1024         int retval;
1025
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;
1030         vp.vp_mod_cnt = 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;
1043         }
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);
1046
1047         retval = isp_exec_entry_queue(isp, &vp, &vp, 5);
1048         if (retval != 0) {
1049                 isp_prt(isp, ISP_LOGERR, "%s: VP_MODIFY of chan %d error %d",
1050                     __func__, chan, retval);
1051                 return (retval);
1052         }
1053
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);
1058                 return (EIO);
1059         }
1060         return (0);
1061 }
1062
1063 static int
1064 isp_fc_disable_vp(ispsoftc_t *isp, int chan)
1065 {
1066         vp_ctrl_info_t vp;
1067         int retval;
1068
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;
1075         } else {
1076                 vp.vp_ctrl_status = 0;
1077                 chan--; /* VP0 can not be controlled in this case. */
1078         }
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);
1082
1083         retval = isp_exec_entry_queue(isp, &vp, &vp, 5);
1084         if (retval != 0) {
1085                 isp_prt(isp, ISP_LOGERR, "%s: VP_CTRL of chan %d error %d",
1086                     __func__, chan, retval);
1087                 return (retval);
1088         }
1089
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);
1095                 return (EIO);
1096         }
1097         return (0);
1098 }
1099
1100 static int
1101 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
1102 {
1103         fcparam *fcp = FCPARAM(isp, chan);
1104         int i, was, res = 0;
1105
1106         if (chan >= isp->isp_nchan) {
1107                 isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan);
1108                 return (ENXIO);
1109         }
1110         if (fcp->role == new_role)
1111                 return (0);
1112         for (was = 0, i = 0; i < isp->isp_nchan; i++) {
1113                 if (FCPARAM(isp, i)->role != ISP_ROLE_NONE)
1114                         was++;
1115         }
1116         if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) {
1117                 fcp->role = new_role;
1118                 return (isp_reinit(isp, 0));
1119         }
1120         if (fcp->role != ISP_ROLE_NONE) {
1121                 res = isp_fc_disable_vp(isp, chan);
1122                 isp_clear_portdb(isp, chan);
1123         }
1124         fcp->role = new_role;
1125         if (fcp->role != ISP_ROLE_NONE)
1126                 res = isp_fc_enable_vp(isp, chan);
1127         return (res);
1128 }
1129
1130 static void
1131 isp_clear_portdb(ispsoftc_t *isp, int chan)
1132 {
1133         fcparam *fcp = FCPARAM(isp, chan);
1134         fcportdb_t *lp;
1135         int i;
1136
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);
1145                         break;
1146                 case FC_PORTDB_STATE_NIL:
1147                 case FC_PORTDB_STATE_NEW:
1148                         lp->state = FC_PORTDB_STATE_NIL;
1149                         break;
1150                 case FC_PORTDB_STATE_ZOMBIE:
1151                         break;
1152                 default:
1153                         panic("Don't know how to clear state %d\n", lp->state);
1154                 }
1155         }
1156 }
1157
1158 static void
1159 isp_mark_portdb(ispsoftc_t *isp, int chan)
1160 {
1161         fcparam *fcp = FCPARAM(isp, chan);
1162         fcportdb_t *lp;
1163         int i;
1164
1165         for (i = 0; i < MAX_FC_TARG; i++) {
1166                 lp = &fcp->portdb[i];
1167                 if (lp->state == FC_PORTDB_STATE_NIL)
1168                         continue;
1169                 if (lp->portid >= DOMAIN_CONTROLLER_BASE &&
1170                     lp->portid <= DOMAIN_CONTROLLER_END)
1171                         continue;
1172                 fcp->portdb[i].probational = 1;
1173         }
1174 }
1175
1176 /*
1177  * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
1178  * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
1179  */
1180 static int
1181 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags)
1182 {
1183         isp_plogx_t pl;
1184         uint32_t sst, parm1;
1185         int retval, lev;
1186         const char *msg;
1187         char buf[64];
1188
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);
1192
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;
1201
1202         retval = isp_exec_entry_queue(isp, &pl, &pl, 3 * ICB_LOGIN_TOV);
1203         if (retval != 0) {
1204                 isp_prt(isp, ISP_LOGERR, "%s: PLOGX of chan %d error %d",
1205                     __func__, chan, retval);
1206                 return (retval);
1207         }
1208
1209         if (pl.plogx_status == PLOGX_STATUS_OK) {
1210                 return (0);
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);
1215                 return (-1);
1216         }
1217
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);
1220
1221         retval = -1;
1222         lev = ISP_LOGERR;
1223         msg = NULL;
1224
1225         switch (sst) {
1226         case PLOGX_IOCBERR_NOLINK:
1227                 msg = "no link";
1228                 break;
1229         case PLOGX_IOCBERR_NOIOCB:
1230                 msg = "no IOCB buffer";
1231                 break;
1232         case PLOGX_IOCBERR_NOXGHG:
1233                 msg = "no Exchange Control Block";
1234                 break;
1235         case PLOGX_IOCBERR_FAILED:
1236                 ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff);
1237                 msg = buf;
1238                 break;
1239         case PLOGX_IOCBERR_NOFABRIC:
1240                 msg = "no fabric";
1241                 break;
1242         case PLOGX_IOCBERR_NOTREADY:
1243                 msg = "firmware not ready";
1244                 break;
1245         case PLOGX_IOCBERR_NOLOGIN:
1246                 ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1);
1247                 msg = buf;
1248                 retval = MBOX_NOT_LOGGED_IN;
1249                 break;
1250         case PLOGX_IOCBERR_REJECT:
1251                 ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
1252                 msg = buf;
1253                 break;
1254         case PLOGX_IOCBERR_NOPCB:
1255                 msg = "no PCB allocated";
1256                 break;
1257         case PLOGX_IOCBERR_EINVAL:
1258                 ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1);
1259                 msg = buf;
1260                 break;
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);
1264                 msg = buf;
1265                 retval = MBOX_PORT_ID_USED | (parm1 << 16);
1266                 break;
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);
1270                 msg = buf;
1271                 retval = MBOX_LOOP_ID_USED;
1272                 break;
1273         case PLOGX_IOCBERR_NOHANDLE:
1274                 msg = "no handle allocated";
1275                 break;
1276         case PLOGX_IOCBERR_NOFLOGI:
1277                 msg = "no FLOGI_ACC";
1278                 break;
1279         default:
1280                 ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags);
1281                 msg = buf;
1282                 break;
1283         }
1284         if (msg) {
1285                 isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
1286                     chan, portid, handle, msg);
1287         }
1288         return (retval);
1289 }
1290
1291 static int
1292 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb)
1293 {
1294         mbreg_t mbs;
1295         union {
1296                 isp_pdb_24xx_t bill;
1297         } un;
1298
1299         MBSINIT(&mbs, MBOX_GET_PORT_DB,
1300             MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000);
1301         mbs.ibits = (1 << 9)|(1 << 10);
1302         mbs.param[1] = id;
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);
1309
1310         isp_mboxcmd(isp, &mbs);
1311         if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
1312                 return (mbs.param[0] | (mbs.param[1] << 16));
1313
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);
1326
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]);
1330         }
1331         return (0);
1332 }
1333
1334 static int
1335 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop)
1336 {
1337         fcparam *fcp = FCPARAM(isp, chan);
1338         mbreg_t mbs;
1339         isp_pnhle_24xx_t el4, *elp4;
1340         int i, j;
1341         uint32_t p;
1342
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);
1352                 return (-1);
1353         }
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));
1359         }
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))
1366                         continue;
1367                 handles[j++] = el4.pnhle_handle;
1368         }
1369         *num = j;
1370         FC_SCRATCH_RELEASE(isp, chan);
1371         return (0);
1372 }
1373
1374 static void
1375 isp_dump_chip_portdb(ispsoftc_t *isp, int chan)
1376 {
1377         isp_pdb_t pdb;
1378         uint16_t nphdl;
1379
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)) {
1383                         continue;
1384                 }
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]);
1390         }
1391 }
1392
1393 static uint64_t
1394 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename)
1395 {
1396         uint64_t wwn = INI_NONE;
1397         mbreg_t mbs;
1398
1399         MBSINIT(&mbs, MBOX_GET_PORT_NAME,
1400             MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
1401         mbs.param[1] = nphdl;
1402         if (nodename)
1403                 mbs.param[10] = 1;
1404         mbs.param[9] = chan;
1405         isp_mboxcmd(isp, &mbs);
1406         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1407                 return (wwn);
1408         }
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)));
1417         return (wwn);
1418 }
1419
1420 /*
1421  * Make sure we have good FC link.
1422  */
1423
1424 static int
1425 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
1426 {
1427         mbreg_t mbs;
1428         int i, r, topo;
1429         fcparam *fcp;
1430         isp_pdb_t pdb;
1431         NANOTIME_T hra, hrb;
1432
1433         fcp = FCPARAM(isp, chan);
1434
1435         if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1436                 return (-1);
1437         if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
1438                 return (0);
1439
1440         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
1441
1442         /*
1443          * Wait up to N microseconds for F/W to go to a ready state.
1444          */
1445         GET_NANOTIME(&hra);
1446         while (1) {
1447                 isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
1448                 if (fcp->isp_fwstate == FW_READY) {
1449                         break;
1450                 }
1451                 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1452                         goto abort;
1453                 GET_NANOTIME(&hrb);
1454                 if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
1455                         break;
1456                 ISP_SLEEP(isp, 1000);
1457         }
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));
1462                 return (-1);
1463         }
1464
1465         /*
1466          * Get our Loop ID and Port ID.
1467          */
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) {
1472                 return (-1);
1473         }
1474
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);
1480
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;
1485
1486                 for (i = 0; alpa_map[i]; i++) {
1487                         if (alpa_map[i] == alpa)
1488                                 break;
1489                 }
1490                 if (alpa_map[i])
1491                         fcp->isp_loopid = i;
1492         }
1493
1494 #if 0
1495         fcp->isp_loopstate = LOOP_HAVE_ADDR;
1496 #endif
1497         fcp->isp_loopstate = LOOP_TESTING_LINK;
1498
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;
1505                         goto not_on_fabric;
1506                 }
1507
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)
1512                         goto abort;
1513                 if (r != 0)
1514                         goto not_on_fabric;
1515                 r = isp_register_fc4_features_24xx(isp, chan);
1516                 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1517                         goto abort;
1518                 if (r != 0)
1519                         goto not_on_fabric;
1520                 r = isp_register_port_name_24xx(isp, chan);
1521                 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1522                         goto abort;
1523                 if (r != 0)
1524                         goto not_on_fabric;
1525                 isp_register_node_name_24xx(isp, chan);
1526                 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1527                         goto abort;
1528         }
1529
1530 not_on_fabric:
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;
1552         }
1553
1554         if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
1555 abort:
1556                 isp_prt(isp, ISP_LOG_SANCFG,
1557                     "Chan %d FC link test aborted", chan);
1558                 return (1);
1559         }
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,
1567             fcp->isp_loopid);
1568         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
1569         return (0);
1570 }
1571
1572 /*
1573  * Complete the synchronization of our Port Database.
1574  *
1575  * At this point, we've scanned the local loop (if any) and the fabric
1576  * and performed fabric logins on all new devices.
1577  *
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
1581  * devices.
1582  */
1583 static int
1584 isp_pdb_sync(ispsoftc_t *isp, int chan)
1585 {
1586         fcparam *fcp = FCPARAM(isp, chan);
1587         fcportdb_t *lp;
1588         uint16_t dbidx;
1589
1590         if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
1591                 return (-1);
1592         if (fcp->isp_loopstate >= LOOP_READY)
1593                 return (0);
1594
1595         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
1596
1597         fcp->isp_loopstate = LOOP_SYNCING_PDB;
1598
1599         for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
1600                 lp = &fcp->portdb[dbidx];
1601
1602                 if (lp->state == FC_PORTDB_STATE_NIL)
1603                         continue;
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,
1612                                     lp->portid,
1613                                     PLOGX_FLG_CMD_LOGO |
1614                                     PLOGX_FLG_IMPLICIT |
1615                                     PLOGX_FLG_FREE_NPHDL);
1616                         }
1617                         /*
1618                          * Note that we might come out of this with our state
1619                          * set to FC_PORTDB_STATE_ZOMBIE.
1620                          */
1621                         break;
1622                 case FC_PORTDB_STATE_NEW:
1623                         lp->state = FC_PORTDB_STATE_VALID;
1624                         isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
1625                         break;
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;
1632                         break;
1633                 case FC_PORTDB_STATE_VALID:
1634                         isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
1635                         break;
1636                 case FC_PORTDB_STATE_ZOMBIE:
1637                         break;
1638                 default:
1639                         isp_prt(isp, ISP_LOGWARN,
1640                             "isp_pdb_sync: state %d for idx %d",
1641                             lp->state, dbidx);
1642                         isp_dump_portdb(isp, chan);
1643                 }
1644         }
1645
1646         if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
1647                 isp_prt(isp, ISP_LOG_SANCFG,
1648                     "Chan %d FC PDB sync aborted", chan);
1649                 return (1);
1650         }
1651
1652         fcp->isp_loopstate = LOOP_READY;
1653         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
1654         return (0);
1655 }
1656
1657 static void
1658 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
1659 {
1660         fcportdb_t *lp;
1661         uint64_t wwnn, wwpn;
1662
1663         MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
1664         MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
1665
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);
1674                         return;
1675                 }
1676                 lp->probational = 0;
1677                 lp->node_wwn = wwnn;
1678
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);
1690                         return;
1691                 }
1692
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);
1702                 return;
1703         }
1704
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);
1708                 return;
1709         }
1710
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);
1722 }
1723
1724 /*
1725  * Scan local loop for devices.
1726  */
1727 static int
1728 isp_scan_loop(ispsoftc_t *isp, int chan)
1729 {
1730         fcparam *fcp = FCPARAM(isp, chan);
1731         int idx, lim, r;
1732         isp_pdb_t pdb;
1733         uint16_t *handles;
1734         uint16_t handle;
1735
1736         if (fcp->isp_loopstate < LOOP_LTEST_DONE)
1737                 return (-1);
1738         if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
1739                 return (0);
1740
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;
1747                 return (0);
1748         }
1749
1750         handles = (uint16_t *)fcp->isp_scanscratch;
1751         lim = ISP_FC_SCRLEN / 2;
1752         r = isp_gethandles(isp, chan, handles, &lim, 1);
1753         if (r != 0) {
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);
1758                 return (-1);
1759         }
1760
1761         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
1762             chan, lim);
1763
1764         /*
1765          * Run through the list and get the port database info for each one.
1766          */
1767         isp_mark_portdb(isp, chan);
1768         for (idx = 0; idx < lim; idx++) {
1769                 handle = handles[idx];
1770
1771                 /*
1772                  * Don't scan "special" ids.
1773                  */
1774                 if (handle >= NPH_RESERVED)
1775                         continue;
1776
1777                 /*
1778                  * Get the port database entity for this index.
1779                  */
1780                 r = isp_getpdb(isp, chan, handle, &pdb);
1781                 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
1782 abort:
1783                         isp_prt(isp, ISP_LOG_SANCFG,
1784                             "Chan %d FC loop scan aborted", chan);
1785                         return (1);
1786                 }
1787                 if (r != 0) {
1788                         isp_prt(isp, ISP_LOGDEBUG1,
1789                             "Chan %d FC Scan Loop handle %d returned %x",
1790                             chan, handle, r);
1791                         continue;
1792                 }
1793
1794                 isp_pdb_add_update(isp, chan, &pdb);
1795         }
1796         if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
1797                 goto abort;
1798         fcp->isp_loopstate = LOOP_LSCAN_DONE;
1799         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
1800         return (0);
1801 }
1802
1803 static int
1804 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
1805 {
1806         fcparam *fcp = FCPARAM(isp, chan);
1807         isp_ct_pt_t pt;
1808         int retval;
1809
1810         if (isp->isp_dblev & ISP_LOGDEBUG1)
1811                 isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch);
1812
1813         /*
1814          * Build a Passthrough IOCB in memory.
1815          */
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;
1820         pt.ctp_cmd_cnt = 1;
1821         pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
1822         pt.ctp_time = 10;
1823         pt.ctp_rsp_cnt = 1;
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;
1832
1833         retval = isp_exec_entry_queue(isp, &pt, &pt, 2 * pt.ctp_time);
1834         if (retval != 0) {
1835                 isp_prt(isp, ISP_LOGERR, "%s: CTP of chan %d error %d",
1836                     __func__, chan, retval);
1837                 return (retval);
1838         }
1839
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);
1844                 return (-1);
1845         }
1846
1847         if (isp->isp_dblev & ISP_LOGDEBUG1)
1848                 isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch);
1849
1850         return (0);
1851 }
1852
1853 /*
1854  * Scan the fabric for devices and add them to our port database.
1855  *
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).
1858  *
1859  * We use CT Pass-through IOCB.
1860  */
1861 #define GIDLEN  ISP_FC_SCRLEN
1862 #define NGENT   ((GIDLEN - 16) >> 2)
1863
1864 static int
1865 isp_gid_pt(ispsoftc_t *isp, int chan)
1866 {
1867         fcparam *fcp = FCPARAM(isp, chan);
1868         ct_hdr_t ct;
1869         uint8_t *scp = fcp->isp_scratch;
1870
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);
1874                 return (-1);
1875         }
1876
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 */
1889
1890         if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) {
1891                 FC_SCRATCH_RELEASE(isp, chan);
1892                 return (-1);
1893         }
1894
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);
1898         return (0);
1899 }
1900
1901 static int
1902 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid)
1903 {
1904         fcparam *fcp = FCPARAM(isp, chan);
1905         ct_hdr_t ct;
1906         uint32_t *rp;
1907         uint8_t *scp = fcp->isp_scratch;
1908         sns_gff_id_rsp_t rsp;
1909         int i, res = -1;
1910
1911         if (!fcp->isp_use_gff_id)       /* User may block GFF_ID use. */
1912                 return (res);
1913
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);
1917                 return (res);
1918         }
1919
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);
1930
1931         if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
1932             SNS_GFF_ID_RESP_SIZE)) {
1933                 FC_SCRATCH_RELEASE(isp, chan);
1934                 return (res);
1935         }
1936
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) {
1941                                 res = 0;
1942                                 break;
1943                         }
1944                 }
1945                 if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >>
1946                     ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
1947                         res = 1;
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)
1951                         res = 1;
1952         }
1953         FC_SCRATCH_RELEASE(isp, chan);
1954         isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res);
1955         return (res);
1956 }
1957
1958 static int
1959 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid)
1960 {
1961         fcparam *fcp = FCPARAM(isp, chan);
1962         ct_hdr_t ct;
1963         uint32_t *rp;
1964         uint8_t *scp = fcp->isp_scratch;
1965         sns_gft_id_rsp_t rsp;
1966         int i, res = -1;
1967
1968         if (!fcp->isp_use_gft_id)       /* User may block GFT_ID use. */
1969                 return (res);
1970
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);
1974                 return (res);
1975         }
1976
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);
1987
1988         if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
1989             SNS_GFT_ID_RESP_SIZE)) {
1990                 FC_SCRATCH_RELEASE(isp, chan);
1991                 return (res);
1992         }
1993
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) {
1998                                 res = 0;
1999                                 break;
2000                         }
2001                 }
2002                 if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >>
2003                     (FC4_SCSI % 32)) & 0x01) != 0)
2004                         res = 1;
2005         }
2006         FC_SCRATCH_RELEASE(isp, chan);
2007         isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res);
2008         return (res);
2009 }
2010
2011 static int
2012 isp_scan_fabric(ispsoftc_t *isp, int chan)
2013 {
2014         fcparam *fcp = FCPARAM(isp, chan);
2015         fcportdb_t *lp;
2016         uint32_t portid;
2017         isp_pdb_t pdb;
2018         int portidx, portlim, r;
2019         sns_gid_xx_rsp_t *rs;
2020
2021         if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
2022                 return (-1);
2023         if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
2024                 return (0);
2025
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);
2032                 return (0);
2033         }
2034
2035         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
2036 abort:
2037                 FC_SCRATCH_RELEASE(isp, chan);
2038                 isp_prt(isp, ISP_LOG_SANCFG,
2039                     "Chan %d FC fabric scan aborted", chan);
2040                 return (1);
2041         }
2042
2043         /*
2044          * Make sure we still are logged into the fabric controller.
2045          */
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);
2049         }
2050         if (r) {
2051                 fcp->isp_loopstate = LOOP_LTEST_DONE;
2052 fail:
2053                 isp_prt(isp, ISP_LOG_SANCFG,
2054                     "Chan %d FC fabric scan done (bad)", chan);
2055                 return (-1);
2056         }
2057
2058         /* Get list of port IDs from SNS. */
2059         r = isp_gid_pt(isp, chan);
2060         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2061                 goto abort;
2062         if (r > 0) {
2063                 fcp->isp_loopstate = LOOP_FSCAN_DONE;
2064                 return (-1);
2065         } else if (r < 0) {
2066                 fcp->isp_loopstate = LOOP_LTEST_DONE;   /* try again */
2067                 return (-1);
2068         }
2069
2070         rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch;
2071         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2072                 goto abort;
2073         if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) {
2074                 int level;
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;
2080                 } else {
2081                         level = ISP_LOGWARN;
2082                 }
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;
2088                 return (-1);
2089         }
2090
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)
2094                         break;
2095         }
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");
2099         }
2100         portlim = portidx + 1;
2101         isp_prt(isp, ISP_LOG_SANCFG,
2102             "Chan %d Got %d ports back from name server", chan, portlim);
2103
2104         /* Go through the list and remove duplicate port ids. */
2105         for (portidx = 0; portidx < portlim; portidx++) {
2106                 int npidx;
2107
2108                 portid =
2109                     ((rs->snscb_ports[portidx].portid[0]) << 16) |
2110                     ((rs->snscb_ports[portidx].portid[1]) << 8) |
2111                     ((rs->snscb_ports[portidx].portid[2]));
2112
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) {
2119                                 break;
2120                         }
2121                 }
2122
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);
2128                 }
2129         }
2130
2131         /*
2132          * We now have a list of Port IDs for all FC4 SCSI devices
2133          * that the Fabric Name server knows about.
2134          *
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.
2138          *
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.
2144          */
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);
2152                 if (portid == 0) {
2153                         isp_prt(isp, ISP_LOG_SANCFG,
2154                             "Chan %d Port at idx %d is zero",
2155                             chan, portidx);
2156                         continue;
2157                 }
2158                 if (portid == fcp->isp_portid) {
2159                         isp_prt(isp, ISP_LOG_SANCFG,
2160                             "Chan %d Port 0x%06x is our", chan, portid);
2161                         continue;
2162                 }
2163
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);
2172                                 goto fail;
2173                         }
2174
2175                         if (lp->state == FC_PORTDB_STATE_ZOMBIE)
2176                                 goto relogin;
2177
2178                         /*
2179                          * See if we're still logged into it.
2180                          *
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).
2185                          *
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).
2192                          */
2193                         r = isp_getpdb(isp, chan, lp->handle, &pdb);
2194                         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2195                                 goto abort;
2196                         if (r != 0) {
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);
2201                                 goto relogin;
2202                         }
2203
2204                         isp_pdb_add_update(isp, chan, &pdb);
2205                         continue;
2206                 }
2207
2208 relogin:
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);
2212                         continue;
2213                 }
2214
2215                 r = isp_gff_id(isp, chan, portid);
2216                 if (r == 0) {
2217                         isp_prt(isp, ISP_LOG_SANCFG,
2218                             "Chan %d Port 0x%06x is not an FCP target", chan, portid);
2219                         continue;
2220                 }
2221                 if (r < 0)
2222                         r = isp_gft_id(isp, chan, portid);
2223                 if (r == 0) {
2224                         isp_prt(isp, ISP_LOG_SANCFG,
2225                             "Chan %d Port 0x%06x is not FCP", chan, portid);
2226                         continue;
2227                 }
2228
2229                 if (isp_login_device(isp, chan, portid, &pdb,
2230                     &FCPARAM(isp, 0)->isp_lasthdl)) {
2231                         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2232                                 goto abort;
2233                         continue;
2234                 }
2235
2236                 isp_pdb_add_update(isp, chan, &pdb);
2237         }
2238
2239         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2240                 goto abort;
2241         fcp->isp_loopstate = LOOP_FSCAN_DONE;
2242         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
2243         return (0);
2244 }
2245
2246 /*
2247  * Find an unused handle and try and use to login to a port.
2248  */
2249 static int
2250 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
2251 {
2252         int i, r;
2253         uint16_t handle;
2254
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)
2258                         return (-1);
2259
2260                 /* Check if this handle is free. */
2261                 r = isp_getpdb(isp, chan, handle, p);
2262                 if (r == 0) {
2263                         if (p->portid != portid) {
2264                                 /* This handle is busy, try next one. */
2265                                 handle = isp_next_handle(isp, ohp);
2266                                 continue;
2267                         }
2268                         break;
2269                 }
2270                 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2271                         return (-1);
2272
2273                 /*
2274                  * Now try and log into the device
2275                  */
2276                 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2277                 if (r == 0) {
2278                         break;
2279                 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
2280                         /*
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).
2284                          */
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);
2287                         }
2288                         if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2289                                 return (-1);
2290                         r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2291                         if (r != 0)
2292                                 i = NPH_MAX_2K;
2293                         break;
2294                 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
2295                         /* Try the next handle. */
2296                         handle = isp_next_handle(isp, ohp);
2297                 } else {
2298                         /* Give up. */
2299                         i = NPH_MAX_2K;
2300                         break;
2301                 }
2302         }
2303
2304         if (i == NPH_MAX_2K) {
2305                 isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid);
2306                 return (-1);
2307         }
2308
2309         /*
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
2313          */
2314         r = isp_getpdb(isp, chan, handle, p);
2315         if (r != 0) {
2316                 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
2317                 return (-1);
2318         }
2319
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);
2323                 return (-1);
2324         }
2325         return (0);
2326 }
2327
2328 static int
2329 isp_register_fc4_type(ispsoftc_t *isp, int chan)
2330 {
2331         fcparam *fcp = FCPARAM(isp, chan);
2332         rft_id_t rp;
2333         ct_hdr_t *ct = &rp.rftid_hdr;
2334         uint8_t *scp = fcp->isp_scratch;
2335
2336         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2337                 isp_prt(isp, ISP_LOGERR, sacq);
2338                 return (-1);
2339         }
2340
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);
2353
2354         if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2355                 FC_SCRATCH_RELEASE(isp, chan);
2356                 return (-1);
2357         }
2358
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);
2363                 return (-1);
2364         } else if (ct->ct_cmd_resp == LS_ACC) {
2365                 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan);
2366         } else {
2367                 isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp);
2368                 return (-1);
2369         }
2370         return (0);
2371 }
2372
2373 static int
2374 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
2375 {
2376         fcparam *fcp = FCPARAM(isp, chan);
2377         ct_hdr_t *ct;
2378         rff_id_t rp;
2379         uint8_t *scp = fcp->isp_scratch;
2380
2381         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2382                 isp_prt(isp, ISP_LOGERR, sacq);
2383                 return (-1);
2384         }
2385
2386         /*
2387          * Build the CT header and command in memory.
2388          */
2389         ISP_MEMZERO(&rp, sizeof(rp));
2390         ct = &rp.rffid_hdr;
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);
2408
2409         if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2410                 FC_SCRATCH_RELEASE(isp, chan);
2411                 return (-1);
2412         }
2413
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);
2419                 return (-1);
2420         } else if (ct->ct_cmd_resp == LS_ACC) {
2421                 isp_prt(isp, ISP_LOG_SANCFG,
2422                     "Chan %d Register FC4 Features accepted", chan);
2423         } else {
2424                 isp_prt(isp, ISP_LOGWARN,
2425                     "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
2426                 return (-1);
2427         }
2428         return (0);
2429 }
2430
2431 static int
2432 isp_register_port_name_24xx(ispsoftc_t *isp, int chan)
2433 {
2434         fcparam *fcp = FCPARAM(isp, chan);
2435         ct_hdr_t *ct;
2436         rspn_id_t rp;
2437         uint8_t *scp = fcp->isp_scratch;
2438         int len;
2439
2440         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2441                 isp_prt(isp, ISP_LOGERR, sacq);
2442                 return (-1);
2443         }
2444
2445         /*
2446          * Build the CT header and command in memory.
2447          */
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));
2465         if (chan != 0) {
2466                 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2467                     "/%d", chan);
2468         }
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);
2472
2473         if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2474                 FC_SCRATCH_RELEASE(isp, chan);
2475                 return (-1);
2476         }
2477
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);
2483                 return (-1);
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);
2487         } else {
2488                 isp_prt(isp, ISP_LOGWARN,
2489                     "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp);
2490                 return (-1);
2491         }
2492         return (0);
2493 }
2494
2495 static int
2496 isp_register_node_name_24xx(ispsoftc_t *isp, int chan)
2497 {
2498         fcparam *fcp = FCPARAM(isp, chan);
2499         ct_hdr_t *ct;
2500         rsnn_nn_t rp;
2501         uint8_t *scp = fcp->isp_scratch;
2502         int len;
2503
2504         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2505                 isp_prt(isp, ISP_LOGERR, sacq);
2506                 return (-1);
2507         }
2508
2509         /*
2510          * Build the CT header and command in memory.
2511          */
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);
2528
2529         if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2530                 FC_SCRATCH_RELEASE(isp, chan);
2531                 return (-1);
2532         }
2533
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);
2539                 return (-1);
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);
2543         } else {
2544                 isp_prt(isp, ISP_LOGWARN,
2545                     "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp);
2546                 return (-1);
2547         }
2548         return (0);
2549 }
2550
2551 static uint16_t
2552 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
2553 {
2554         fcparam *fcp;
2555         int i, chan, wrap;
2556         uint16_t handle;
2557
2558         handle = *ohp;
2559         wrap = 0;
2560
2561 next:
2562         if (handle == NIL_HANDLE) {
2563                 handle = 0;
2564         } else {
2565                 handle++;
2566                 if (handle > NPH_RESERVED - 1) {
2567                         if (++wrap >= 2) {
2568                                 isp_prt(isp, ISP_LOGERR, "Out of port handles!");
2569                                 return (NIL_HANDLE);
2570                         }
2571                         handle = 0;
2572                 }
2573         }
2574         for (chan = 0; chan < isp->isp_nchan; chan++) {
2575                 fcp = FCPARAM(isp, chan);
2576                 if (fcp->role == ISP_ROLE_NONE)
2577                         continue;
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)
2581                                 goto next;
2582                 }
2583         }
2584         *ohp = handle;
2585         return (handle);
2586 }
2587
2588 /*
2589  * Start a command. Locking is assumed done in the caller.
2590  */
2591
2592 int
2593 isp_start(XS_T *xs)
2594 {
2595         ispsoftc_t *isp;
2596         fcparam *fcp;
2597         uint32_t cdblen;
2598         ispreqt7_t local, *reqp = &local;
2599         void *qep;
2600         fcportdb_t *lp;
2601         int target, dmaresult;
2602
2603         XS_INITERR(xs);
2604         isp = XS_ISP(xs);
2605
2606         /*
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).
2611          */
2612
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);
2617         }
2618
2619         /*
2620          * Translate the target to device handle as appropriate, checking
2621          * for correct device state as well.
2622          */
2623         target = XS_TGT(xs);
2624         fcp = FCPARAM(isp, XS_CHANNEL(xs));
2625
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);
2632         }
2633
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);
2638         }
2639
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);
2646         }
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);
2652         }
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);
2658         }
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);
2665         }
2666
2667  start_again:
2668
2669         qep = isp_getrqentry(isp);
2670         if (qep == NULL) {
2671                 isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow");
2672                 XS_SETERR(xs, HBA_BOTCH);
2673                 return (CMD_EAGAIN);
2674         }
2675         XS_SETERR(xs, HBA_NOERROR);
2676
2677         /*
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.
2681          */
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);
2692                 goto start_again;
2693         }
2694
2695         /*
2696          * NB: we do not support long CDBs (yet)
2697          */
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);
2703         }
2704
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)));
2710         if (XS_XFRIN(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;
2714         if (XS_TAG_P(xs))
2715                 reqp->req_task_attribute = XS_TAG_TYPE(xs);
2716         else
2717                 reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE;
2718         reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) &
2719              FCP_CMND_PRIO_MASK;
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);
2727                 }
2728         }
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));
2734
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);
2741         }
2742
2743         /*
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.
2746          *
2747          * The callee is responsible for adding all requests at this point.
2748          */
2749         dmaresult = ISP_DMASETUP(isp, xs, reqp);
2750         if (dmaresult != 0) {
2751                 isp_destroy_handle(isp, reqp->req_handle);
2752                 /*
2753                  * dmasetup sets actual error in packet, and
2754                  * return what we were given to return.
2755                  */
2756                 return (dmaresult);
2757         }
2758         isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
2759         return (0);
2760 }
2761
2762 /*
2763  * isp control
2764  * Locks (ints blocked) assumed held.
2765  */
2766
2767 int
2768 isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
2769 {
2770         fcparam *fcp;
2771         fcportdb_t *lp;
2772         XS_T *xs;
2773         mbreg_t *mbr;
2774         int chan, tgt;
2775         uint32_t handle;
2776         va_list ap;
2777         uint8_t local[QENTRY_LEN];
2778
2779         switch (ctl) {
2780         case ISPCTL_RESET_BUS:
2781                 /*
2782                  * Issue a bus reset.
2783                  */
2784                 isp_prt(isp, ISP_LOGERR, "BUS RESET NOT IMPLEMENTED");
2785                 break;
2786
2787         case ISPCTL_RESET_DEV:
2788         {
2789                 isp24xx_tmf_t *tmf;
2790                 isp24xx_statusreq_t *sp;
2791
2792                 va_start(ap, ctl);
2793                 chan = va_arg(ap, int);
2794                 tgt = va_arg(ap, int);
2795                 va_end(ap);
2796                 fcp = FCPARAM(isp, chan);
2797
2798                 if (tgt < 0 || tgt >= MAX_FC_TARG) {
2799                         isp_prt(isp, ISP_LOGWARN, "Chan %d trying to reset bad target %d", chan, tgt);
2800                         break;
2801                 }
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);
2805                         break;
2806                 }
2807
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;
2813                 tmf->tmf_delay = 2;
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);
2821
2822                 sp = (isp24xx_statusreq_t *) local;
2823                 if (isp_exec_entry_mbox(isp, tmf, sp, 2 * tmf->tmf_timeout))
2824                         break;
2825
2826                 if (sp->req_completion_status == 0)
2827                         return (0);
2828                 isp_prt(isp, ISP_LOGWARN, "Chan %d reset of target %d returned 0x%x", chan, tgt, sp->req_completion_status);
2829                 break;
2830         }
2831         case ISPCTL_ABORT_CMD:
2832         {
2833                 isp24xx_abrt_t *ab = (isp24xx_abrt_t *)&local;
2834
2835                 va_start(ap, ctl);
2836                 xs = va_arg(ap, XS_T *);
2837                 va_end(ap);
2838
2839                 tgt = XS_TGT(xs);
2840                 chan = XS_CHANNEL(xs);
2841
2842                 handle = isp_find_handle(isp, xs);
2843                 if (handle == 0) {
2844                         isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort");
2845                         break;
2846                 }
2847
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);
2851                         break;
2852                 }
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);
2856                         break;
2857                 }
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);
2867
2868                 if (isp_exec_entry_mbox(isp, ab, ab, 5))
2869                         break;
2870
2871                 if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY)
2872                         return (0);
2873                 isp_prt(isp, ISP_LOGWARN, "Chan %d handle %d abort returned 0x%x", chan, tgt, ab->abrt_nphdl);
2874         }
2875         case ISPCTL_FCLINK_TEST:
2876         {
2877                 int usdelay;
2878
2879                 va_start(ap, ctl);
2880                 chan = va_arg(ap, int);
2881                 usdelay = va_arg(ap, int);
2882                 va_end(ap);
2883                 if (usdelay == 0)
2884                         usdelay = 250000;
2885                 return (isp_fclink_test(isp, chan, usdelay));
2886         }
2887         case ISPCTL_SCAN_FABRIC:
2888
2889                 va_start(ap, ctl);
2890                 chan = va_arg(ap, int);
2891                 va_end(ap);
2892                 return (isp_scan_fabric(isp, chan));
2893
2894         case ISPCTL_SCAN_LOOP:
2895
2896                 va_start(ap, ctl);
2897                 chan = va_arg(ap, int);
2898                 va_end(ap);
2899                 return (isp_scan_loop(isp, chan));
2900
2901         case ISPCTL_PDB_SYNC:
2902
2903                 va_start(ap, ctl);
2904                 chan = va_arg(ap, int);
2905                 va_end(ap);
2906                 return (isp_pdb_sync(isp, chan));
2907
2908         case ISPCTL_SEND_LIP:
2909                 break;
2910
2911         case ISPCTL_GET_PDB:
2912         {
2913                 isp_pdb_t *pdb;
2914                 va_start(ap, ctl);
2915                 chan = va_arg(ap, int);
2916                 tgt = va_arg(ap, int);
2917                 pdb = va_arg(ap, isp_pdb_t *);
2918                 va_end(ap);
2919                 return (isp_getpdb(isp, chan, tgt, pdb));
2920         }
2921         case ISPCTL_GET_NAMES:
2922         {
2923                 uint64_t *wwnn, *wwnp;
2924                 va_start(ap, ctl);
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 *);
2929                 va_end(ap);
2930                 if (wwnn == NULL && wwnp == NULL) {
2931                         break;
2932                 }
2933                 if (wwnn) {
2934                         *wwnn = isp_get_wwn(isp, chan, tgt, 1);
2935                         if (*wwnn == INI_NONE) {
2936                                 break;
2937                         }
2938                 }
2939                 if (wwnp) {
2940                         *wwnp = isp_get_wwn(isp, chan, tgt, 0);
2941                         if (*wwnp == INI_NONE) {
2942                                 break;
2943                         }
2944                 }
2945                 return (0);
2946         }
2947         case ISPCTL_RUN_MBOXCMD:
2948         {
2949                 va_start(ap, ctl);
2950                 mbr = va_arg(ap, mbreg_t *);
2951                 va_end(ap);
2952                 isp_mboxcmd(isp, mbr);
2953                 return (0);
2954         }
2955         case ISPCTL_PLOGX:
2956         {
2957                 isp_plcmd_t *p;
2958                 int r;
2959
2960                 va_start(ap, ctl);
2961                 p = va_arg(ap, isp_plcmd_t *);
2962                 va_end(ap);
2963
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));
2966                 }
2967                 do {
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;
2972                                 r = 0;
2973                                 break;
2974                         }
2975                 } while ((r & 0xffff) == MBOX_LOOP_ID_USED);
2976                 return (r);
2977         }
2978         case ISPCTL_CHANGE_ROLE:
2979         {
2980                 int role;
2981
2982                 va_start(ap, ctl);
2983                 chan = va_arg(ap, int);
2984                 role = va_arg(ap, int);
2985                 va_end(ap);
2986                 return (isp_fc_change_role(isp, chan, role));
2987         }
2988         default:
2989                 isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
2990                 break;
2991
2992         }
2993         return (-1);
2994 }
2995
2996 /*
2997  * Interrupt Service Routine(s).
2998  *
2999  * External (OS) framework has done the appropriate locking,
3000  * and the locking will be held throughout this function.
3001  */
3002
3003 #ifdef  ISP_TARGET_MODE
3004 void
3005 isp_intr_atioq(ispsoftc_t *isp)
3006 {
3007         void *addr;
3008         uint32_t iptr, optr, oop;
3009
3010         iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
3011         optr = isp->isp_atioodx;
3012         while (optr != iptr) {
3013                 oop = optr;
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:
3018                 case RQSTYPE_ATIO:
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));
3023                         break;
3024                 case RQSTYPE_RPT_ID_ACQ:        /* Can be set to ATIO queue.*/
3025                 default:
3026                         isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
3027                         break;
3028                 }
3029                 optr = ISP_NXT_QENTRY(oop, ATIO_QUEUE_LEN(isp));
3030         }
3031         if (isp->isp_atioodx != optr) {
3032                 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
3033                 isp->isp_atioodx = optr;
3034         }
3035 }
3036 #endif
3037
3038 void
3039 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0)
3040 {
3041         int i, obits;
3042
3043         if (!isp->isp_mboxbsy) {
3044                 isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0);
3045                 return;
3046         }
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)
3051                         continue;
3052                 isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
3053         }
3054         isp->isp_mboxbsy = 0;
3055 }
3056
3057 void
3058 isp_intr_respq(ispsoftc_t *isp)
3059 {
3060         XS_T *xs, *cont_xs;
3061         uint8_t qe[QENTRY_LEN];
3062         isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe;
3063         ispstatus_cont_t *scp = (ispstatus_cont_t *)qe;
3064         isphdr_t *hp;
3065         uint8_t *resp, *snsp, etype;
3066         uint16_t scsi_status;
3067         uint32_t iptr, cont = 0, cptr, optr, rlen, slen, sptr, totslen;
3068
3069         /*
3070          * We can't be getting this now.
3071          */
3072         if (isp->isp_state != ISP_RUNSTATE) {
3073                 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready");
3074                 return;
3075         }
3076
3077         iptr = ISP_READ(isp, BIU2400_RSPINP);
3078         optr = isp->isp_resodx;
3079         while (optr != iptr) {
3080                 sptr = cptr = optr;
3081                 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
3082                 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
3083
3084                 /*
3085                  * Synchronize our view of this response queue entry.
3086                  */
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);
3091
3092                 /*
3093                  * Log IOCBs rejected by the firmware.  We can't really do
3094                  * much more about them, since it just should not happen.
3095                  */
3096                 if (sp->req_header.rqs_flags & RQSFLAG_BADTYPE) {
3097                         isp_print_qentry(isp, "invalid entry type", cptr, hp);
3098                         continue;
3099                 }
3100                 if (sp->req_header.rqs_flags & RQSFLAG_BADPARAM) {
3101                         isp_print_qentry(isp, "invalid entry parameter", cptr, hp);
3102                         continue;
3103                 }
3104                 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
3105                         isp_print_qentry(isp, "invalid entry count", cptr, hp);
3106                         continue;
3107                 }
3108                 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
3109                         isp_print_qentry(isp, "invalid entry order", cptr, hp);
3110                         continue;
3111                 }
3112
3113                 etype = sp->req_header.rqs_entry_type;
3114
3115                 /* We expected Status Continuation, but got different IOCB. */
3116                 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
3117                         cont = 0;
3118                         isp_done(cont_xs);
3119                 }
3120
3121                 if (isp_handle_control(isp, hp)) {
3122                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
3123                         continue;
3124                 }
3125
3126                 switch (etype) {
3127                 case RQSTYPE_RESPONSE:
3128                         isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp);
3129                         break;
3130                 case RQSTYPE_MARKER:
3131                         isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
3132                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
3133                         continue;
3134                 case RQSTYPE_STATUS_CONT:
3135                         isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
3136                         if (cont > 0) {
3137                                 slen = min(cont, sizeof(scp->req_sense_data));
3138                                 XS_SENSE_APPEND(cont_xs, scp->req_sense_data, slen);
3139                                 cont -= slen;
3140                                 if (cont == 0) {
3141                                         isp_done(cont_xs);
3142                                 } else {
3143                                         isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3144                                             "Expecting Status Continuations for %u bytes",
3145                                             cont);
3146                                 }
3147                         } else {
3148                                 isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
3149                         }
3150                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
3151                         continue;
3152 #ifdef  ISP_TARGET_MODE
3153                 case RQSTYPE_NOTIFY_ACK:        /* Can be set to ATIO queue. */
3154                 case RQSTYPE_CTIO7:
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);
3163                         }
3164                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
3165                         optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
3166                         continue;
3167 #endif
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 */
3171                         continue;
3172                 default:
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 */
3176                         continue;
3177                 }
3178
3179                 xs = isp_find_xs(isp, sp->req_handle);
3180                 if (xs == NULL) {
3181                         /*
3182                          * Only whine if this isn't the expected fallout of
3183                          * aborting the command or resetting the target.
3184                          */
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 */
3190                         continue;
3191                 }
3192
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;
3198                         snsp += rlen;
3199                 }
3200                 if (scsi_status & RQCS_SV) {
3201                         totslen = sp->req_sense_len;
3202                         slen = MIN(totslen, sizeof(sp->req_rsp_sense) - rlen);
3203                 }
3204                 *XS_STSP(xs) = scsi_status & 0xff;
3205                 if (scsi_status & RQCS_RESID)
3206                         XS_SET_RESID(xs, sp->req_fcp_residual);
3207                 else
3208                         XS_SET_RESID(xs, 0);
3209
3210                 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
3211                         const char *ptr;
3212                         char lb[64];
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",
3220                             NULL,
3221                             NULL,
3222                             "Task Management function succeeded",
3223                             "Task Management function incorrect logical unit number",
3224                         };
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);
3229                                 ptr = lb;
3230                         } else {
3231                                 ptr = rnames[code];
3232                         }
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);
3239                 }
3240                 isp_parse_status_24xx(isp, sp, xs);
3241                 if (slen > 0) {
3242                         XS_SAVE_SENSE(xs, snsp, slen);
3243                         if (totslen > slen) {
3244                                 cont = totslen - slen;
3245                                 cont_xs = xs;
3246                                 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3247                                     "Expecting Status Continuations for %u bytes",
3248                                     cont);
3249                         }
3250                 }
3251
3252                 ISP_DMAFREE(isp, xs);
3253                 isp_destroy_handle(isp, sp->req_handle);
3254                 ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
3255
3256                 /* Complete command if we expect no Status Continuations. */
3257                 if (cont == 0)
3258                         isp_done(xs);
3259         }
3260
3261         /* We haven't received all Status Continuations, but that is it. */
3262         if (cont > 0)
3263                 isp_done(cont_xs);
3264
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;
3269         }
3270 }
3271
3272
3273 void
3274 isp_intr_async(ispsoftc_t *isp, uint16_t mbox)
3275 {
3276         fcparam *fcp;
3277         uint16_t chan;
3278
3279         isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
3280
3281         switch (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);
3287                 }
3288                 /*
3289                  * Were we waiting for a mailbox command to complete?
3290                  * If so, it's dead, so wake up the waiter.
3291                  */
3292                 if (isp->isp_mboxbsy) {
3293                         isp->isp_obits = 1;
3294                         isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
3295                         isp->isp_mboxbsy = 0;
3296                 }
3297                 /*
3298                  * It's up to the handler for isp_async to reinit stuff and
3299                  * restart the firmware
3300                  */
3301                 isp_async(isp, ISPASYNC_FW_CRASH);
3302                 break;
3303
3304         case ASYNC_RQS_XFER_ERR:
3305                 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
3306                 break;
3307
3308         case ASYNC_RSP_XFER_ERR:
3309                 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
3310                 break;
3311
3312         case ASYNC_ATIO_XFER_ERR:
3313                 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
3314                 break;
3315
3316         case ASYNC_LIP_OCCURRED:
3317         case ASYNC_LIP_NOS_OLS_RECV:
3318         case ASYNC_LIP_ERROR:
3319         case ASYNC_PTPMODE:
3320                 /*
3321                  * These are broadcast events that have to be sent across
3322                  * all active channels.
3323                  */
3324                 for (chan = 0; chan < isp->isp_nchan; chan++) {
3325                         fcp = FCPARAM(isp, chan);
3326                         int topo = fcp->isp_topo;
3327
3328                         if (fcp->role == ISP_ROLE_NONE)
3329                                 continue;
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);
3336 #endif
3337                         /*
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.
3343                          */
3344                         if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
3345                                 int i, j;
3346                                 for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) {
3347                                         XS_T *xs;
3348                                         isp_hdl_t *hdp;
3349
3350                                         hdp = &isp->isp_xflist[i];
3351                                         if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
3352                                                 continue;
3353                                         }
3354                                         xs = hdp->cmd;
3355                                         if (XS_CHANNEL(xs) != chan) {
3356                                                 continue;
3357                                         }
3358                                         j++;
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);
3365                                 }
3366                                 if (j) {
3367                                         isp_prt(isp, ISP_LOGERR, lipd, chan, j);
3368                                 }
3369                         }
3370                 }
3371                 break;
3372
3373         case ASYNC_LOOP_UP:
3374                 /*
3375                  * This is a broadcast event that has to be sent across
3376                  * all active channels.
3377                  */
3378                 for (chan = 0; chan < isp->isp_nchan; chan++) {
3379                         fcp = FCPARAM(isp, chan);
3380                         if (fcp->role == ISP_ROLE_NONE)
3381                                 continue;
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);
3389 #endif
3390                 }
3391                 break;
3392
3393         case ASYNC_LOOP_DOWN:
3394                 /*
3395                  * This is a broadcast event that has to be sent across
3396                  * all active channels.
3397                  */
3398                 for (chan = 0; chan < isp->isp_nchan; chan++) {
3399                         fcp = FCPARAM(isp, chan);
3400                         if (fcp->role == ISP_ROLE_NONE)
3401                                 continue;
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);
3408 #endif
3409                 }
3410                 break;
3411
3412         case ASYNC_LOOP_RESET:
3413                 /*
3414                  * This is a broadcast event that has to be sent across
3415                  * all active channels.
3416                  */
3417                 for (chan = 0; chan < isp->isp_nchan; chan++) {
3418                         fcp = FCPARAM(isp, chan);
3419                         if (fcp->role == ISP_ROLE_NONE)
3420                                 continue;
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);
3427 #endif
3428                 }
3429                 break;
3430
3431         case ASYNC_PDB_CHANGED:
3432         {
3433                 int echan, nphdl, nlstate, reason;
3434
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) {
3441                                 chan = 0;
3442                                 echan = isp->isp_nchan - 1;
3443                         } else if (chan >= isp->isp_nchan) {
3444                                 break;
3445                         } else {
3446                                 echan = chan;
3447                         }
3448                 } else {
3449                         chan = echan = 0;
3450                 }
3451                 for (; chan <= echan; chan++) {
3452                         fcp = FCPARAM(isp, chan);
3453                         if (fcp->role == ISP_ROLE_NONE)
3454                                 continue;
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)
3459                                         continue;
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);
3465                 }
3466                 break;
3467         }
3468         case ASYNC_CHANGE_NOTIFY:
3469         {
3470                 int portid;
3471
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)
3477                                 break;
3478                 } else {
3479                         chan = 0;
3480                 }
3481                 fcp = FCPARAM(isp, chan);
3482                 if (fcp->role == ISP_ROLE_NONE)
3483                         break;
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);
3490                 break;
3491         }
3492         case ASYNC_ERR_LOGGING_DISABLED:
3493                 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)",
3494                     ISP_READ(isp, OUTMAILBOX1));
3495                 break;
3496         case ASYNC_P2P_INIT_ERR:
3497                 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)",
3498                     ISP_READ(isp, OUTMAILBOX1));
3499                 break;
3500         case ASYNC_RCV_ERR:
3501                 isp_prt(isp, ISP_LOGWARN, "Receive Error");
3502                 break;
3503         case ASYNC_RJT_SENT:    /* same as ASYNC_QFULL_SENT */
3504                 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
3505                 break;
3506         case ASYNC_FW_RESTART_COMPLETE:
3507                 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete");
3508                 break;
3509         case ASYNC_TEMPERATURE_ALERT:
3510                 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)",
3511                     ISP_READ(isp, OUTMAILBOX1));
3512                 break;
3513         case ASYNC_INTER_DRIVER_COMP:
3514                 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication complete");
3515                 break;
3516         case ASYNC_INTER_DRIVER_NOTIFY:
3517                 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication notification");
3518                 break;
3519         case ASYNC_INTER_DRIVER_TIME_EXT:
3520                 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication time extended");
3521                 break;
3522         case ASYNC_TRANSCEIVER_INSERTION:
3523                 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)",
3524                     ISP_READ(isp, OUTMAILBOX1));
3525                 break;
3526         case ASYNC_TRANSCEIVER_REMOVAL:
3527                 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal");
3528                 break;
3529         case ASYNC_NIC_FW_STATE_CHANGE:
3530                 isp_prt(isp, ISP_LOGDEBUG0, "NIC Firmware State Change");
3531                 break;
3532         case ASYNC_AUTOLOAD_FW_COMPLETE:
3533                 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete");
3534                 break;
3535         case ASYNC_AUTOLOAD_FW_FAILURE:
3536                 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure");
3537                 break;
3538         default:
3539                 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
3540                 break;
3541         }
3542 }
3543
3544 /*
3545  * Handle completions with control handles by waking up waiting threads.
3546  */
3547 static int
3548 isp_handle_control(ispsoftc_t *isp, isphdr_t *hp)
3549 {
3550         uint32_t hdl;
3551         void *ptr;
3552
3553         switch (hp->rqs_entry_type) {
3554         case RQSTYPE_RESPONSE:
3555         case RQSTYPE_MARKER:
3556         case RQSTYPE_NOTIFY_ACK:
3557         case RQSTYPE_CTIO7:
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:
3563         case RQSTYPE_MBOX:
3564         case RQSTYPE_LOGIN:
3565         case RQSTYPE_ELS_PASSTHRU:
3566                 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
3567                 if (ISP_H2HT(hdl) != ISP_HANDLE_CTRL)
3568                         break;
3569                 ptr = isp_find_xs(isp, hdl);
3570                 if (ptr != NULL) {
3571                         isp_destroy_handle(isp, hdl);
3572                         memcpy(ptr, hp, QENTRY_LEN);
3573                         wakeup(ptr);
3574                 }
3575                 return (1);
3576         }
3577         return (0);
3578 }
3579
3580 static void
3581 isp_handle_rpt_id_acq(ispsoftc_t *isp, isphdr_t *hp)
3582 {
3583         fcparam *fcp;
3584         isp_ridacq_t rid;
3585         int chan, c;
3586         uint32_t portid;
3587
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)
3595                                 continue;
3596                         c = (chan == 0) ? 127 : (chan - 1);
3597                         if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
3598                             chan == 0) {
3599                                 fcp->isp_loopstate = LOOP_HAVE_LINK;
3600                                 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3601                                     chan, ISPASYNC_CHANGE_OTHER);
3602                         } else {
3603                                 fcp->isp_loopstate = LOOP_NIL;
3604                                 isp_async(isp, ISPASYNC_LOOP_DOWN,
3605                                     chan);
3606                         }
3607                 }
3608         } else {
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);
3617                 } else {
3618                         fcp->isp_loopstate = LOOP_NIL;
3619                         isp_async(isp, ISPASYNC_LOOP_DOWN,
3620                             rid.ridacq_vp_index);
3621                 }
3622         }
3623 }
3624
3625 static void
3626 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs)
3627 {
3628         int ru_marked, sv_marked;
3629         int chan = XS_CHANNEL(xs);
3630
3631         switch (sp->req_completion_status) {
3632         case RQCS_COMPLETE:
3633                 return;
3634
3635         case RQCS_DMA_ERROR:
3636                 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error");
3637                 if (XS_NOERR(xs))
3638                         XS_SETERR(xs, HBA_BOTCH);
3639                 break;
3640
3641         case RQCS_TRANSPORT_ERROR:
3642                 isp_xs_prt(isp, xs,  ISP_LOGERR, "Transport Error");
3643                 if (XS_NOERR(xs))
3644                         XS_SETERR(xs, HBA_BOTCH);
3645                 break;
3646
3647         case RQCS_RESET_OCCURRED:
3648                 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command");
3649                 FCPARAM(isp, chan)->sendmarker = 1;
3650                 if (XS_NOERR(xs))
3651                         XS_SETERR(xs, HBA_BUSRESET);
3652                 return;
3653
3654         case RQCS_ABORTED:
3655                 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted");
3656                 FCPARAM(isp, chan)->sendmarker = 1;
3657                 if (XS_NOERR(xs))
3658                         XS_SETERR(xs, HBA_ABORTED);
3659                 return;
3660
3661         case RQCS_TIMEOUT:
3662                 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out");
3663                 if (XS_NOERR(xs))
3664                         XS_SETERR(xs, HBA_CMDTIMEOUT);
3665                 return;
3666
3667         case RQCS_DATA_OVERRUN:
3668                 XS_SET_RESID(xs, sp->req_resid);
3669                 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun");
3670                 if (XS_NOERR(xs))
3671                         XS_SETERR(xs, HBA_DATAOVR);
3672                 return;
3673
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));
3676                 if (XS_NOERR(xs))
3677                         XS_SETERR(xs, HBA_BOTCH);
3678                 return;
3679
3680         case RQCS_TABORT:       /* aborted by target */
3681                 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs));
3682                 if (XS_NOERR(xs))
3683                         XS_SETERR(xs, HBA_ABORTED);
3684                 return;
3685
3686         case RQCS_DATA_UNDERRUN:
3687                 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
3688                 /*
3689                  * We can get an underrun w/o things being marked
3690                  * if we got a non-zero status.
3691                  */
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");
3696                         if (XS_NOERR(xs))
3697                                 XS_SETERR(xs, HBA_BOTCH);
3698                         return;
3699                 }
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);
3702                 return;
3703
3704         case RQCS_PORT_UNAVAILABLE:
3705                 /*
3706                  * No such port on the loop. Moral equivalent of SELTIMEO
3707                  */
3708         case RQCS_PORT_LOGGED_OUT:
3709         {
3710                 const char *reason;
3711                 uint8_t sts = sp->req_completion_status & 0xff;
3712                 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
3713                 fcportdb_t *lp;
3714
3715                 /*
3716                  * It was there (maybe)- treat as a selection timeout.
3717                  */
3718                 if (sts == RQCS_PORT_UNAVAILABLE) {
3719                         reason = "unavailable";
3720                 } else {
3721                         reason = "logout";
3722                 }
3723
3724                 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
3725                     chan, reason, XS_TGT(xs));
3726
3727                 /* XXX: Should we trigger rescan or FW announce change? */
3728
3729                 if (XS_NOERR(xs)) {
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);
3734                         } else
3735                                 XS_SETERR(xs, HBA_SELTIMEOUT);
3736                 }
3737                 return;
3738         }
3739         case RQCS_PORT_CHANGED:
3740                 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan);
3741                 if (XS_NOERR(xs)) {
3742                         *XS_STSP(xs) = SCSI_BUSY;
3743                         XS_SETERR(xs, HBA_TGTBSY);
3744                 }
3745                 return;
3746
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);
3749                 if (XS_NOERR(xs)) {
3750                         *XS_STSP(xs) = SCSI_BUSY;
3751                         XS_SETERR(xs, HBA_TGTBSY);
3752                 }
3753                 return;
3754
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);
3757                 if (XS_NOERR(xs)) {
3758                         *XS_STSP(xs) = SCSI_BUSY;
3759                         XS_SETERR(xs, HBA_TGTBSY);
3760                 }
3761                 return;
3762
3763         default:
3764                 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan);
3765                 break;
3766         }
3767         if (XS_NOERR(xs))
3768                 XS_SETERR(xs, HBA_BOTCH);
3769 }
3770
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]))
3773
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 */
3905 };
3906 #define MAX_FC_OPCODE   0x7e
3907 /*
3908  * Footnotes
3909  *
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.
3914  */
3915
3916 static const char *fc_mbcmd_names[] = {
3917         "NO-OP",                        /* 00h */
3918         "LOAD RAM",
3919         "EXEC FIRMWARE",
3920         "DUMP RAM",
3921         "WRITE RAM WORD",
3922         "READ RAM WORD",
3923         "MAILBOX REG TEST",
3924         "VERIFY CHECKSUM",
3925         "ABOUT FIRMWARE",
3926         "LOAD RAM (2100)",
3927         "DUMP RAM",
3928         "LOAD RISC RAM",
3929         "DUMP RISC RAM",
3930         "WRITE RAM WORD EXTENDED",
3931         "CHECK FIRMWARE",
3932         "READ RAM WORD EXTENDED",
3933         "INIT REQUEST QUEUE",           /* 10h */
3934         "INIT RESULT QUEUE",
3935         "EXECUTE IOCB",
3936         "WAKE UP",
3937         "STOP FIRMWARE",
3938         "ABORT",
3939         "ABORT DEVICE",
3940         "ABORT TARGET",
3941         "BUS RESET",
3942         "STOP QUEUE",
3943         "START QUEUE",
3944         "SINGLE STEP QUEUE",
3945         "ABORT QUEUE",
3946         "GET DEV QUEUE STATUS",
3947         NULL,
3948         "GET FIRMWARE STATUS",
3949         "GET LOOP ID",                  /* 20h */
3950         NULL,
3951         "GET TIMEOUT PARAMS",
3952         NULL,
3953         NULL,
3954         NULL,
3955         NULL,
3956         NULL,
3957         "GET FIRMWARE OPTIONS",
3958         "GET PORT QUEUE PARAMS",
3959         "GENERATE SYSTEM ERROR",
3960         NULL,
3961         NULL,
3962         NULL,
3963         NULL,
3964         NULL,
3965         "WRITE SFP",                    /* 30h */
3966         "READ SFP",
3967         "SET TIMEOUT PARAMS",
3968         NULL,
3969         NULL,
3970         NULL,
3971         NULL,
3972         NULL,
3973         "SET FIRMWARE OPTIONS",
3974         "SET PORT QUEUE PARAMS",
3975         NULL,
3976         "SET FC LED CONF",
3977         NULL,
3978         "RESTART NIC FIRMWARE",
3979         "ACCESS CONTROL",
3980         NULL,
3981         "LOOP PORT BYPASS",             /* 40h */
3982         "LOOP PORT ENABLE",
3983         "GET RESOURCE COUNT",
3984         "REQUEST NON PARTICIPATING MODE",
3985         "DIAGNOSTIC ECHO TEST",
3986         "DIAGNOSTIC LOOPBACK",
3987         NULL,
3988         "GET PORT DATABASE ENHANCED",
3989         "INIT FIRMWARE MULTI ID",
3990         "GET VP DATABASE",
3991         "GET VP DATABASE ENTRY",
3992         NULL,
3993         NULL,
3994         NULL,
3995         NULL,
3996         NULL,
3997         "GET FCF LIST",                 /* 50h */
3998         "GET DCBX PARAMETERS",
3999         NULL,
4000         "HOST MEMORY COPY",
4001         "EXECUTE IOCB A64",
4002         NULL,
4003         NULL,
4004         "SEND RNID",
4005         NULL,
4006         "SET PARAMETERS",
4007         "GET PARAMETERS",
4008         "DRIVER HEARTBEAT",
4009         "FIRMWARE HEARTBEAT",
4010         "GET/SET DATA RATE",
4011         "SEND RNFT",
4012         NULL,
4013         "INIT FIRMWARE",                /* 60h */
4014         "GET INIT CONTROL BLOCK",
4015         "INIT LIP",
4016         "GET FC-AL POSITION MAP",
4017         "GET PORT DATABASE",
4018         "CLEAR ACA",
4019         "TARGET RESET",
4020         "CLEAR TASK SET",
4021         "ABORT TASK SET",
4022         "GET FW STATE",
4023         "GET PORT NAME",
4024         "GET LINK STATUS",
4025         "INIT LIP RESET",
4026         "GET LINK STATS & PRIVATE DATA CNTS",
4027         "SEND SNS",
4028         "FABRIC LOGIN",
4029         "SEND CHANGE REQUEST",          /* 70h */
4030         "FABRIC LOGOUT",
4031         "INIT LIP LOGIN",
4032         NULL,
4033         "LOGIN LOOP PORT",
4034         "GET PORT/NODE NAME LIST",
4035         "SET VENDOR ID",
4036         "INITIALIZE IP MAILBOX",
4037         NULL,
4038         NULL,
4039         "GET XGMAC STATS",
4040         NULL,
4041         "GET ID LIST",
4042         "SEND LFA",
4043         "LUN RESET"
4044 };
4045
4046 static void
4047 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
4048 {
4049         const char *cname, *xname, *sname;
4050         char tname[16], mname[16];
4051         unsigned int ibits, obits, box, opcode, t, to;
4052
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);
4057                 return;
4058         }
4059         cname = fc_mbcmd_names[opcode];
4060         ibits = ISP_FC_IBITS(opcode);
4061         obits = ISP_FC_OBITS(opcode);
4062         if (cname == NULL) {
4063                 cname = tname;
4064                 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
4065         }
4066         isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname);
4067
4068         /*
4069          * Pick up any additional bits that the caller might have set.
4070          */
4071         ibits |= mbp->ibits;
4072         obits |= mbp->obits;
4073
4074         /*
4075          * Mask any bits that the caller wants us to mask
4076          */
4077         ibits &= mbp->ibitm;
4078         obits &= mbp->obitm;
4079
4080
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);
4084                 return;
4085         }
4086
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,
4090                             mbp->param[box]);
4091                         ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
4092                 }
4093                 isp->isp_mboxtmp[box] = mbp->param[box] = 0;
4094         }
4095
4096         isp->isp_obits = obits;
4097         isp->isp_mboxbsy = 1;
4098
4099         /*
4100          * Set Host Interrupt condition so that RISC will pick up mailbox regs.
4101          */
4102         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
4103
4104         /*
4105          * While we haven't finished the command, spin our wheels here.
4106          */
4107         to = (mbp->timeout == 0) ? MBCMD_DEFAULT_TIMEOUT : mbp->timeout;
4108         for (t = 0; t < to; t += 100) {
4109                 if (!isp->isp_mboxbsy)
4110                         break;
4111                 ISP_RUN_ISR(isp);
4112                 if (!isp->isp_mboxbsy)
4113                         break;
4114                 ISP_DELAY(100);
4115         }
4116
4117         /*
4118          * Did the command time out?
4119          */
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;
4125                 goto out;
4126         }
4127
4128         /*
4129          * Copy back output registers.
4130          */
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,
4135                             mbp->param[box]);
4136                 }
4137         }
4138
4139 out:
4140         if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE)
4141                 return;
4142
4143         if ((mbp->param[0] & 0xbfe0) == 0 &&
4144             (mbp->logval & MBLOGMASK(mbp->param[0])) == 0)
4145                 return;
4146
4147         xname = NULL;
4148         sname = "";
4149         switch (mbp->param[0]) {
4150         case MBOX_INVALID_COMMAND:
4151                 xname = "INVALID COMMAND";
4152                 break;
4153         case MBOX_HOST_INTERFACE_ERROR:
4154                 xname = "HOST INTERFACE ERROR";
4155                 break;
4156         case MBOX_TEST_FAILED:
4157                 xname = "TEST FAILED";
4158                 break;
4159         case MBOX_COMMAND_ERROR:
4160                 xname = "COMMAND ERROR";
4161                 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x",
4162                     mbp->param[1]);
4163                 sname = mname;
4164                 break;
4165         case MBOX_COMMAND_PARAM_ERROR:
4166                 xname = "COMMAND PARAMETER ERROR";
4167                 break;
4168         case MBOX_PORT_ID_USED:
4169                 xname = "PORT ID ALREADY IN USE";
4170                 break;
4171         case MBOX_LOOP_ID_USED:
4172                 xname = "LOOP ID ALREADY IN USE";
4173                 break;
4174         case MBOX_ALL_IDS_USED:
4175                 xname = "ALL LOOP IDS IN USE";
4176                 break;
4177         case MBOX_NOT_LOGGED_IN:
4178                 xname = "NOT LOGGED IN";
4179                 break;
4180         case MBOX_LINK_DOWN_ERROR:
4181                 xname = "LINK DOWN ERROR";
4182                 break;
4183         case MBOX_LOOPBACK_ERROR:
4184                 xname = "LOOPBACK ERROR";
4185                 break;
4186         case MBOX_CHECKSUM_ERROR:
4187                 xname = "CHECKSUM ERROR";
4188                 break;
4189         case MBOX_INVALID_PRODUCT_KEY:
4190                 xname = "INVALID PRODUCT KEY";
4191                 break;
4192         case MBOX_REGS_BUSY:
4193                 xname = "REGISTERS BUSY";
4194                 break;
4195         case MBOX_TIMEOUT:
4196                 xname = "TIMEOUT";
4197                 break;
4198         default:
4199                 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
4200                 xname = mname;
4201                 break;
4202         }
4203         if (xname) {
4204                 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)",
4205                     cname, xname, sname);
4206         }
4207 }
4208
4209 static int
4210 isp_fw_state(ispsoftc_t *isp, int chan)
4211 {
4212         mbreg_t mbs;
4213
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]);
4218         return (FW_ERROR);
4219 }
4220
4221 static void
4222 isp_setdfltfcparm(ispsoftc_t *isp, int chan)
4223 {
4224         fcparam *fcp = FCPARAM(isp, chan);
4225
4226         /*
4227          * Establish some default parameters.
4228          */
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;
4240
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;
4248
4249         /*
4250          * Now try and read NVRAM unless told to not do so.
4251          * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
4252          */
4253         if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
4254                 int i, j = 0;
4255                 /*
4256                  * Give a couple of tries at reading NVRAM.
4257                  */
4258                 for (i = 0; i < 2; i++) {
4259                         j = isp_read_nvram(isp, chan);
4260                         if (j == 0) {
4261                                 break;
4262                         }
4263                 }
4264                 if (j) {
4265                         isp->isp_confopts |= ISP_CFG_NONVRAM;
4266                 }
4267         }
4268
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]);
4275 }
4276
4277 /*
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.
4281  */
4282
4283 int
4284 isp_reinit(ispsoftc_t *isp, int do_load_defaults)
4285 {
4286         int i, res = 0;
4287
4288         if (isp->isp_state > ISP_RESETSTATE)
4289                 isp_stop(isp);
4290         if (isp->isp_state != ISP_RESETSTATE)
4291                 isp_reset(isp, do_load_defaults);
4292         if (isp->isp_state != ISP_RESETSTATE) {
4293                 res = EIO;
4294                 isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
4295                 goto cleanup;
4296         }
4297
4298         isp_init(isp);
4299         if (isp->isp_state > ISP_RESETSTATE &&
4300             isp->isp_state != ISP_RUNSTATE) {
4301                 res = EIO;
4302                 isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
4303                 ISP_DISABLE_INTS(isp);
4304         }
4305
4306 cleanup:
4307         isp_clear_commands(isp);
4308         for (i = 0; i < isp->isp_nchan; i++)
4309                 isp_clear_portdb(isp, i);
4310         return (res);
4311 }
4312
4313 /*
4314  * NVRAM Routines
4315  */
4316 static int
4317 isp_read_nvram(ispsoftc_t *isp, int bus)
4318 {
4319
4320         return (isp_read_nvram_2400(isp));
4321 }
4322
4323 static int
4324 isp_read_nvram_2400(ispsoftc_t *isp)
4325 {
4326         int retval = 0;
4327         uint32_t addr, csum, lwrds, *dptr;
4328         uint8_t nvram_data[ISP2400_NVRAM_SIZE];
4329
4330         if (isp->isp_port) {
4331                 addr = ISP2400_NVRAM_PORT1_ADDR;
4332         } else {
4333                 addr = ISP2400_NVRAM_PORT0_ADDR;
4334         }
4335
4336         dptr = (uint32_t *) nvram_data;
4337         for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4338                 isp_rd_2400_nvram(isp, addr++, dptr++);
4339         }
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]);
4344                 retval = -1;
4345                 goto out;
4346         }
4347         dptr = (uint32_t *) nvram_data;
4348         for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4349                 uint32_t tmp;
4350                 ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
4351                 csum += tmp;
4352         }
4353         if (csum != 0) {
4354                 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
4355                 retval = -1;
4356                 goto out;
4357         }
4358         isp_parse_nvram_2400(isp, nvram_data);
4359 out:
4360         return (retval);
4361 }
4362
4363 static void
4364 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
4365 {
4366         int loops = 0;
4367         uint32_t base = 0x7ffe0000;
4368         uint32_t tmp = 0;
4369
4370         if (IS_26XX(isp)) {
4371                 base = 0x7fe7c000;      /* XXX: Observation, may be wrong. */
4372         } else if (IS_25XX(isp)) {
4373                 base = 0x7ff00000 | 0x48000;
4374         }
4375         ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
4376         for (loops = 0; loops < 5000; loops++) {
4377                 ISP_DELAY(10);
4378                 tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
4379                 if ((tmp & (1U << 31)) != 0) {
4380                         break;
4381                 }
4382         }
4383         if (tmp & (1U << 31)) {
4384                 *rp = ISP_READ(isp, BIU2400_FLASH_DATA);
4385                 ISP_SWIZZLE_NVRAM_LONG(isp, rp);
4386         } else {
4387                 *rp = 0xffffffff;
4388         }
4389 }
4390
4391 static void
4392 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
4393 {
4394         fcparam *fcp = FCPARAM(isp, 0);
4395         uint64_t wwn;
4396
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));
4410
4411         wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
4412         fcp->isp_wwpn_nvram = wwn;
4413
4414         wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
4415         if (wwn) {
4416                 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
4417                         wwn = 0;
4418                 }
4419         }
4420         if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
4421                 wwn = fcp->isp_wwpn_nvram;
4422                 wwn &= ~((uint64_t) 0xfff << 48);
4423         }
4424         fcp->isp_wwnn_nvram = wwn;
4425
4426         if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
4427                 DEFAULT_FRAMESIZE(isp) =
4428                     ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
4429         }
4430         if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
4431                 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
4432         }
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);
4436 }