isp.c revision 1.120 1 1.120 mjacob /* $NetBSD: isp.c,v 1.120 2010/01/15 20:09:09 mjacob Exp $ */
2 1.1 cgd /*
3 1.54 mjacob * Machine and OS Independent (well, as best as possible)
4 1.54 mjacob * code for the Qlogic ISP SCSI adapters.
5 1.54 mjacob *
6 1.111 mjacob * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
7 1.111 mjacob * All rights reserved.
8 1.111 mjacob *
9 1.111 mjacob * Additional Copyright (C) 2000-2007 by Matthew Jacob
10 1.1 cgd * All rights reserved.
11 1.1 cgd *
12 1.1 cgd * Redistribution and use in source and binary forms, with or without
13 1.1 cgd * modification, are permitted provided that the following conditions
14 1.1 cgd * are met:
15 1.111 mjacob *
16 1.1 cgd * 1. Redistributions of source code must retain the above copyright
17 1.111 mjacob * notice, this list of conditions and the following disclaimer.
18 1.111 mjacob * 2. Redistributions in binary form must reproduce the above copyright
19 1.111 mjacob * notice, this list of conditions and the following disclaimer in the
20 1.111 mjacob * documentation and/or other materials provided with the distribution.
21 1.111 mjacob *
22 1.111 mjacob * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 1.54 mjacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.54 mjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.111 mjacob * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
26 1.111 mjacob * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.54 mjacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.54 mjacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.54 mjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.54 mjacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.54 mjacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.54 mjacob * SUCH DAMAGE.
33 1.1 cgd */
34 1.70 mjacob
35 1.1 cgd /*
36 1.1 cgd * Inspiration and ideas about this driver are from Erik Moe's Linux driver
37 1.23 mjacob * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some
38 1.23 mjacob * ideas dredged from the Solaris driver.
39 1.1 cgd */
40 1.1 cgd
41 1.23 mjacob /*
42 1.23 mjacob * Include header file appropriate for platform we're building on.
43 1.23 mjacob */
44 1.111 mjacob #ifdef __NetBSD__
45 1.85 lukem #include <sys/cdefs.h>
46 1.120 mjacob __KERNEL_RCSID(0, "$NetBSD: isp.c,v 1.120 2010/01/15 20:09:09 mjacob Exp $");
47 1.23 mjacob #include <dev/ic/isp_netbsd.h>
48 1.23 mjacob #endif
49 1.23 mjacob #ifdef __FreeBSD__
50 1.111 mjacob #include <sys/cdefs.h>
51 1.111 mjacob __FBSDID("$FreeBSD$");
52 1.23 mjacob #include <dev/isp/isp_freebsd.h>
53 1.23 mjacob #endif
54 1.33 mjacob #ifdef __OpenBSD__
55 1.33 mjacob #include <dev/ic/isp_openbsd.h>
56 1.33 mjacob #endif
57 1.23 mjacob #ifdef __linux__
58 1.29 mjacob #include "isp_linux.h"
59 1.23 mjacob #endif
60 1.57 mjacob #ifdef __svr4__
61 1.57 mjacob #include "isp_solaris.h"
62 1.57 mjacob #endif
63 1.1 cgd
64 1.23 mjacob /*
65 1.23 mjacob * General defines
66 1.23 mjacob */
67 1.1 cgd
68 1.23 mjacob #define MBOX_DELAY_COUNT 1000000 / 100
69 1.114 mjacob #define ISP_MARK_PORTDB(a, b, c) \
70 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG, \
71 1.114 mjacob "Chan %d ISP_MARK_PORTDB@LINE %d", b, __LINE__); \
72 1.114 mjacob isp_mark_portdb(a, b, c)
73 1.1 cgd
74 1.23 mjacob /*
75 1.27 mjacob * Local static data
76 1.27 mjacob */
77 1.117 mjacob static const char fconf[] = "Chan %d PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)";
78 1.117 mjacob static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
79 1.117 mjacob static const char xact1[] = "HBA attempted queued transaction with disconnect not set for %d.%d.%d";
80 1.117 mjacob static const char xact2[] = "HBA attempted queued transaction to target routine %d on target %d bus %d";
81 1.117 mjacob static const char xact3[] = "HBA attempted queued cmd for %d.%d.%d when queueing disabled";
82 1.117 mjacob static const char pskip[] = "SCSI phase skipped for target %d.%d.%d";
83 1.117 mjacob static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x N-Port Handle %d, Connection '%s'";
84 1.117 mjacob static const char finmsg[] = "%d.%d.%d: FIN dl%d resid %ld STS 0x%x SKEY %c XS_ERR=0x%x";
85 1.79 mjacob static const char sc4[] = "NVRAM";
86 1.117 mjacob static const char bun[] = "bad underrun for %d.%d (count %d, resid %d, status %s)";
87 1.117 mjacob static const char lipd[] = "Chan %d LIP destroyed %d active commands";
88 1.117 mjacob static const char sacq[] = "unable to acquire scratch area";
89 1.114 mjacob
90 1.114 mjacob static const uint8_t alpa_map[] = {
91 1.114 mjacob 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
92 1.114 mjacob 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
93 1.114 mjacob 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,
94 1.114 mjacob 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
95 1.114 mjacob 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
96 1.114 mjacob 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
97 1.114 mjacob 0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81,
98 1.114 mjacob 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
99 1.114 mjacob 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69,
100 1.114 mjacob 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
101 1.114 mjacob 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c,
102 1.114 mjacob 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
103 1.114 mjacob 0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
104 1.114 mjacob 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
105 1.114 mjacob 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
106 1.114 mjacob 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
107 1.114 mjacob };
108 1.79 mjacob
109 1.27 mjacob /*
110 1.25 mjacob * Local function prototypes.
111 1.23 mjacob */
112 1.111 mjacob static int isp_parse_async(ispsoftc_t *, uint16_t);
113 1.117 mjacob static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t *);
114 1.117 mjacob static void isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *); static void
115 1.111 mjacob isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *);
116 1.111 mjacob static void isp_fastpost_complete(ispsoftc_t *, uint16_t);
117 1.111 mjacob static int isp_mbox_continue(ispsoftc_t *);
118 1.111 mjacob static void isp_scsi_init(ispsoftc_t *);
119 1.111 mjacob static void isp_scsi_channel_init(ispsoftc_t *, int);
120 1.111 mjacob static void isp_fibre_init(ispsoftc_t *);
121 1.111 mjacob static void isp_fibre_init_2400(ispsoftc_t *);
122 1.114 mjacob static void isp_mark_portdb(ispsoftc_t *, int, int);
123 1.114 mjacob static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int);
124 1.111 mjacob static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t);
125 1.111 mjacob static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t);
126 1.114 mjacob static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *, int);
127 1.114 mjacob static void isp_dump_chip_portdb(ispsoftc_t *, int, int);
128 1.114 mjacob static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
129 1.114 mjacob static int isp_fclink_test(ispsoftc_t *, int, int);
130 1.114 mjacob static int isp_pdb_sync(ispsoftc_t *, int);
131 1.114 mjacob static int isp_scan_loop(ispsoftc_t *, int);
132 1.114 mjacob static int isp_gid_ft_sns(ispsoftc_t *, int);
133 1.114 mjacob static int isp_gid_ft_ct_passthru(ispsoftc_t *, int);
134 1.114 mjacob static int isp_scan_fabric(ispsoftc_t *, int);
135 1.117 mjacob static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
136 1.114 mjacob static int isp_register_fc4_type(ispsoftc_t *, int);
137 1.114 mjacob static int isp_register_fc4_type_24xx(ispsoftc_t *, int);
138 1.114 mjacob static uint16_t isp_nxt_handle(ispsoftc_t *, int, uint16_t);
139 1.114 mjacob static void isp_fw_state(ispsoftc_t *, int);
140 1.111 mjacob static void isp_mboxcmd_qnw(ispsoftc_t *, mbreg_t *, int);
141 1.111 mjacob static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
142 1.111 mjacob
143 1.114 mjacob static void isp_spi_update(ispsoftc_t *, int);
144 1.114 mjacob static void isp_setdfltsdparm(ispsoftc_t *);
145 1.114 mjacob static void isp_setdfltfcparm(ispsoftc_t *, int);
146 1.114 mjacob static int isp_read_nvram(ispsoftc_t *, int);
147 1.114 mjacob static int isp_read_nvram_2400(ispsoftc_t *, uint8_t *);
148 1.111 mjacob static void isp_rdnvram_word(ispsoftc_t *, int, uint16_t *);
149 1.111 mjacob static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *);
150 1.111 mjacob static void isp_parse_nvram_1020(ispsoftc_t *, uint8_t *);
151 1.111 mjacob static void isp_parse_nvram_1080(ispsoftc_t *, int, uint8_t *);
152 1.111 mjacob static void isp_parse_nvram_12160(ispsoftc_t *, int, uint8_t *);
153 1.111 mjacob static void isp_parse_nvram_2100(ispsoftc_t *, uint8_t *);
154 1.111 mjacob static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
155 1.49 mjacob
156 1.1 cgd /*
157 1.1 cgd * Reset Hardware.
158 1.25 mjacob *
159 1.43 mjacob * Hit the chip over the head, download new f/w if available and set it running.
160 1.25 mjacob *
161 1.24 mjacob * Locking done elsewhere.
162 1.1 cgd */
163 1.79 mjacob
164 1.1 cgd void
165 1.117 mjacob isp_reset(ispsoftc_t *isp, int do_load_defaults)
166 1.1 cgd {
167 1.1 cgd mbreg_t mbs;
168 1.111 mjacob uint32_t code_org, val;
169 1.95 mjacob int loops, i, dodnld = 1;
170 1.117 mjacob const char *btype = "????";
171 1.111 mjacob static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
172 1.1 cgd
173 1.1 cgd isp->isp_state = ISP_NILSTATE;
174 1.114 mjacob if (isp->isp_dead) {
175 1.114 mjacob isp_shutdown(isp);
176 1.114 mjacob ISP_DISABLE_INTS(isp);
177 1.114 mjacob return;
178 1.114 mjacob }
179 1.4 mjacob
180 1.4 mjacob /*
181 1.25 mjacob * Basic types (SCSI, FibreChannel and PCI or SBus)
182 1.25 mjacob * have been set in the MD code. We figure out more
183 1.79 mjacob * here. Possibly more refined types based upon PCI
184 1.79 mjacob * identification. Chip revision has been gathered.
185 1.57 mjacob *
186 1.32 mjacob * After we've fired this chip up, zero out the conf1 register
187 1.57 mjacob * for SCSI adapters and do other settings for the 2100.
188 1.32 mjacob */
189 1.32 mjacob
190 1.114 mjacob ISP_DISABLE_INTS(isp);
191 1.30 mjacob
192 1.111 mjacob /*
193 1.111 mjacob * Pick an initial maxcmds value which will be used
194 1.111 mjacob * to allocate xflist pointer space. It may be changed
195 1.111 mjacob * later by the firmware.
196 1.111 mjacob */
197 1.111 mjacob if (IS_24XX(isp)) {
198 1.111 mjacob isp->isp_maxcmds = 4096;
199 1.111 mjacob } else if (IS_2322(isp)) {
200 1.111 mjacob isp->isp_maxcmds = 2048;
201 1.111 mjacob } else if (IS_23XX(isp) || IS_2200(isp)) {
202 1.111 mjacob isp->isp_maxcmds = 1024;
203 1.111 mjacob } else {
204 1.111 mjacob isp->isp_maxcmds = 512;
205 1.111 mjacob }
206 1.111 mjacob
207 1.111 mjacob /*
208 1.114 mjacob * Set up DMA for the request and response queues.
209 1.111 mjacob *
210 1.111 mjacob * We do this now so we can use the request queue
211 1.114 mjacob * for dma to load firmware from.
212 1.111 mjacob */
213 1.111 mjacob if (ISP_MBOXDMASETUP(isp) != 0) {
214 1.111 mjacob isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
215 1.111 mjacob return;
216 1.111 mjacob }
217 1.111 mjacob
218 1.79 mjacob /*
219 1.79 mjacob * Set up default request/response queue in-pointer/out-pointer
220 1.79 mjacob * register indices.
221 1.79 mjacob */
222 1.111 mjacob if (IS_24XX(isp)) {
223 1.111 mjacob isp->isp_rqstinrp = BIU2400_REQINP;
224 1.111 mjacob isp->isp_rqstoutrp = BIU2400_REQOUTP;
225 1.111 mjacob isp->isp_respinrp = BIU2400_RSPINP;
226 1.111 mjacob isp->isp_respoutrp = BIU2400_RSPOUTP;
227 1.111 mjacob } else if (IS_23XX(isp)) {
228 1.80 mjacob isp->isp_rqstinrp = BIU_REQINP;
229 1.80 mjacob isp->isp_rqstoutrp = BIU_REQOUTP;
230 1.80 mjacob isp->isp_respinrp = BIU_RSPINP;
231 1.80 mjacob isp->isp_respoutrp = BIU_RSPOUTP;
232 1.80 mjacob } else {
233 1.80 mjacob isp->isp_rqstinrp = INMAILBOX4;
234 1.80 mjacob isp->isp_rqstoutrp = OUTMAILBOX4;
235 1.80 mjacob isp->isp_respinrp = OUTMAILBOX5;
236 1.80 mjacob isp->isp_respoutrp = INMAILBOX5;
237 1.80 mjacob }
238 1.35 mjacob
239 1.31 mjacob /*
240 1.70 mjacob * Put the board into PAUSE mode (so we can read the SXP registers
241 1.70 mjacob * or write FPM/FBM registers).
242 1.31 mjacob */
243 1.111 mjacob if (IS_24XX(isp)) {
244 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT);
245 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
246 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
247 1.111 mjacob } else {
248 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
249 1.111 mjacob }
250 1.31 mjacob
251 1.37 mjacob if (IS_FC(isp)) {
252 1.37 mjacob switch (isp->isp_type) {
253 1.37 mjacob case ISP_HA_FC_2100:
254 1.79 mjacob btype = "2100";
255 1.37 mjacob break;
256 1.37 mjacob case ISP_HA_FC_2200:
257 1.79 mjacob btype = "2200";
258 1.37 mjacob break;
259 1.76 mjacob case ISP_HA_FC_2300:
260 1.88 mjacob btype = "2300";
261 1.88 mjacob break;
262 1.87 mjacob case ISP_HA_FC_2312:
263 1.88 mjacob btype = "2312";
264 1.76 mjacob break;
265 1.111 mjacob case ISP_HA_FC_2322:
266 1.111 mjacob btype = "2322";
267 1.111 mjacob break;
268 1.111 mjacob case ISP_HA_FC_2400:
269 1.111 mjacob btype = "2422";
270 1.111 mjacob break;
271 1.117 mjacob case ISP_HA_FC_2500:
272 1.117 mjacob btype = "2532";
273 1.117 mjacob break;
274 1.37 mjacob default:
275 1.37 mjacob break;
276 1.37 mjacob }
277 1.111 mjacob
278 1.111 mjacob if (!IS_24XX(isp)) {
279 1.111 mjacob /*
280 1.111 mjacob * While we're paused, reset the FPM module and FBM
281 1.111 mjacob * fifos.
282 1.111 mjacob */
283 1.111 mjacob ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
284 1.111 mjacob ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
285 1.111 mjacob ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
286 1.111 mjacob ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
287 1.111 mjacob ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
288 1.111 mjacob }
289 1.44 mjacob } else if (IS_1240(isp)) {
290 1.114 mjacob sdparam *sdp;
291 1.114 mjacob
292 1.79 mjacob btype = "1240";
293 1.36 mjacob isp->isp_clock = 60;
294 1.114 mjacob sdp = SDPARAM(isp, 0);
295 1.44 mjacob sdp->isp_ultramode = 1;
296 1.114 mjacob sdp = SDPARAM(isp, 1);
297 1.44 mjacob sdp->isp_ultramode = 1;
298 1.44 mjacob /*
299 1.44 mjacob * XXX: Should probably do some bus sensing.
300 1.44 mjacob */
301 1.117 mjacob } else if (IS_ULTRA3(isp)) {
302 1.117 mjacob sdparam *sdp = isp->isp_param;
303 1.117 mjacob
304 1.117 mjacob isp->isp_clock = 100;
305 1.117 mjacob
306 1.117 mjacob if (IS_10160(isp))
307 1.117 mjacob btype = "10160";
308 1.117 mjacob else if (IS_12160(isp))
309 1.117 mjacob btype = "12160";
310 1.117 mjacob else
311 1.117 mjacob btype = "<UNKLVD>";
312 1.117 mjacob sdp->isp_lvdmode = 1;
313 1.117 mjacob
314 1.117 mjacob if (IS_DUALBUS(isp)) {
315 1.117 mjacob sdp++;
316 1.117 mjacob sdp->isp_lvdmode = 1;
317 1.117 mjacob }
318 1.44 mjacob } else if (IS_ULTRA2(isp)) {
319 1.66 mjacob static const char m[] = "bus %d is in %s Mode";
320 1.111 mjacob uint16_t l;
321 1.114 mjacob sdparam *sdp = SDPARAM(isp, 0);
322 1.44 mjacob
323 1.44 mjacob isp->isp_clock = 100;
324 1.44 mjacob
325 1.49 mjacob if (IS_1280(isp))
326 1.79 mjacob btype = "1280";
327 1.49 mjacob else if (IS_1080(isp))
328 1.79 mjacob btype = "1080";
329 1.49 mjacob else
330 1.79 mjacob btype = "<UNKLVD>";
331 1.49 mjacob
332 1.34 mjacob l = ISP_READ(isp, SXP_PINS_DIFF) & ISP1080_MODE_MASK;
333 1.34 mjacob switch (l) {
334 1.34 mjacob case ISP1080_LVD_MODE:
335 1.34 mjacob sdp->isp_lvdmode = 1;
336 1.57 mjacob isp_prt(isp, ISP_LOGCONFIG, m, 0, "LVD");
337 1.34 mjacob break;
338 1.34 mjacob case ISP1080_HVD_MODE:
339 1.34 mjacob sdp->isp_diffmode = 1;
340 1.57 mjacob isp_prt(isp, ISP_LOGCONFIG, m, 0, "Differential");
341 1.34 mjacob break;
342 1.34 mjacob case ISP1080_SE_MODE:
343 1.34 mjacob sdp->isp_ultramode = 1;
344 1.57 mjacob isp_prt(isp, ISP_LOGCONFIG, m, 0, "Single-Ended");
345 1.34 mjacob break;
346 1.34 mjacob default:
347 1.57 mjacob isp_prt(isp, ISP_LOGERR,
348 1.57 mjacob "unknown mode on bus %d (0x%x)", 0, l);
349 1.34 mjacob break;
350 1.34 mjacob }
351 1.44 mjacob
352 1.49 mjacob if (IS_DUALBUS(isp)) {
353 1.114 mjacob sdp = SDPARAM(isp, 1);
354 1.44 mjacob l = ISP_READ(isp, SXP_PINS_DIFF|SXP_BANK1_SELECT);
355 1.44 mjacob l &= ISP1080_MODE_MASK;
356 1.117 mjacob switch (l) {
357 1.44 mjacob case ISP1080_LVD_MODE:
358 1.44 mjacob sdp->isp_lvdmode = 1;
359 1.57 mjacob isp_prt(isp, ISP_LOGCONFIG, m, 1, "LVD");
360 1.44 mjacob break;
361 1.44 mjacob case ISP1080_HVD_MODE:
362 1.44 mjacob sdp->isp_diffmode = 1;
363 1.57 mjacob isp_prt(isp, ISP_LOGCONFIG,
364 1.57 mjacob m, 1, "Differential");
365 1.44 mjacob break;
366 1.44 mjacob case ISP1080_SE_MODE:
367 1.44 mjacob sdp->isp_ultramode = 1;
368 1.57 mjacob isp_prt(isp, ISP_LOGCONFIG,
369 1.57 mjacob m, 1, "Single-Ended");
370 1.44 mjacob break;
371 1.44 mjacob default:
372 1.57 mjacob isp_prt(isp, ISP_LOGERR,
373 1.57 mjacob "unknown mode on bus %d (0x%x)", 1, l);
374 1.44 mjacob break;
375 1.44 mjacob }
376 1.44 mjacob }
377 1.10 mjacob } else {
378 1.114 mjacob sdparam *sdp = SDPARAM(isp, 0);
379 1.30 mjacob i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
380 1.30 mjacob switch (i) {
381 1.10 mjacob default:
382 1.57 mjacob isp_prt(isp, ISP_LOGALL, "Unknown Chip Type 0x%x", i);
383 1.25 mjacob /* FALLTHROUGH */
384 1.10 mjacob case 1:
385 1.79 mjacob btype = "1020";
386 1.10 mjacob isp->isp_type = ISP_HA_SCSI_1020;
387 1.36 mjacob isp->isp_clock = 40;
388 1.22 mjacob break;
389 1.22 mjacob case 2:
390 1.25 mjacob /*
391 1.25 mjacob * Some 1020A chips are Ultra Capable, but don't
392 1.25 mjacob * run the clock rate up for that unless told to
393 1.25 mjacob * do so by the Ultra Capable bits being set.
394 1.25 mjacob */
395 1.79 mjacob btype = "1020A";
396 1.22 mjacob isp->isp_type = ISP_HA_SCSI_1020A;
397 1.36 mjacob isp->isp_clock = 40;
398 1.10 mjacob break;
399 1.10 mjacob case 3:
400 1.79 mjacob btype = "1040";
401 1.25 mjacob isp->isp_type = ISP_HA_SCSI_1040;
402 1.36 mjacob isp->isp_clock = 60;
403 1.25 mjacob break;
404 1.25 mjacob case 4:
405 1.79 mjacob btype = "1040A";
406 1.10 mjacob isp->isp_type = ISP_HA_SCSI_1040A;
407 1.36 mjacob isp->isp_clock = 60;
408 1.10 mjacob break;
409 1.10 mjacob case 5:
410 1.79 mjacob btype = "1040B";
411 1.10 mjacob isp->isp_type = ISP_HA_SCSI_1040B;
412 1.36 mjacob isp->isp_clock = 60;
413 1.10 mjacob break;
414 1.78 mjacob case 6:
415 1.79 mjacob btype = "1040C";
416 1.35 mjacob isp->isp_type = ISP_HA_SCSI_1040C;
417 1.36 mjacob isp->isp_clock = 60;
418 1.78 mjacob break;
419 1.8 mjacob }
420 1.25 mjacob /*
421 1.31 mjacob * Now, while we're at it, gather info about ultra
422 1.31 mjacob * and/or differential mode.
423 1.25 mjacob */
424 1.31 mjacob if (ISP_READ(isp, SXP_PINS_DIFF) & SXP_PINS_DIFF_MODE) {
425 1.57 mjacob isp_prt(isp, ISP_LOGCONFIG, "Differential Mode");
426 1.31 mjacob sdp->isp_diffmode = 1;
427 1.31 mjacob } else {
428 1.31 mjacob sdp->isp_diffmode = 0;
429 1.31 mjacob }
430 1.31 mjacob i = ISP_READ(isp, RISC_PSR);
431 1.31 mjacob if (isp->isp_bustype == ISP_BT_SBUS) {
432 1.31 mjacob i &= RISC_PSR_SBUS_ULTRA;
433 1.30 mjacob } else {
434 1.31 mjacob i &= RISC_PSR_PCI_ULTRA;
435 1.31 mjacob }
436 1.31 mjacob if (i != 0) {
437 1.57 mjacob isp_prt(isp, ISP_LOGCONFIG, "Ultra Mode Capable");
438 1.31 mjacob sdp->isp_ultramode = 1;
439 1.33 mjacob /*
440 1.101 mjacob * If we're in Ultra Mode, we have to be 60MHz clock-
441 1.33 mjacob * even for the SBus version.
442 1.33 mjacob */
443 1.36 mjacob isp->isp_clock = 60;
444 1.34 mjacob } else {
445 1.31 mjacob sdp->isp_ultramode = 0;
446 1.33 mjacob /*
447 1.33 mjacob * Clock is known. Gronk.
448 1.33 mjacob */
449 1.25 mjacob }
450 1.25 mjacob
451 1.25 mjacob /*
452 1.25 mjacob * Machine dependent clock (if set) overrides
453 1.25 mjacob * our generic determinations.
454 1.25 mjacob */
455 1.25 mjacob if (isp->isp_mdvec->dv_clock) {
456 1.36 mjacob if (isp->isp_mdvec->dv_clock < isp->isp_clock) {
457 1.36 mjacob isp->isp_clock = isp->isp_mdvec->dv_clock;
458 1.25 mjacob }
459 1.25 mjacob }
460 1.31 mjacob
461 1.4 mjacob }
462 1.8 mjacob
463 1.1 cgd /*
464 1.63 mjacob * Clear instrumentation
465 1.63 mjacob */
466 1.63 mjacob isp->isp_intcnt = isp->isp_intbogus = 0;
467 1.63 mjacob
468 1.63 mjacob /*
469 1.10 mjacob * Do MD specific pre initialization
470 1.1 cgd */
471 1.10 mjacob ISP_RESET0(isp);
472 1.25 mjacob
473 1.1 cgd /*
474 1.10 mjacob * Hit the chip over the head with hammer,
475 1.117 mjacob * and give it a chance to recover.
476 1.1 cgd */
477 1.1 cgd
478 1.33 mjacob if (IS_SCSI(isp)) {
479 1.10 mjacob ISP_WRITE(isp, BIU_ICR, BIU_ICR_SOFT_RESET);
480 1.10 mjacob /*
481 1.10 mjacob * A slight delay...
482 1.10 mjacob */
483 1.117 mjacob ISP_DELAY(100);
484 1.33 mjacob
485 1.10 mjacob /*
486 1.10 mjacob * Clear data && control DMA engines.
487 1.10 mjacob */
488 1.117 mjacob ISP_WRITE(isp, CDMA_CONTROL, DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
489 1.117 mjacob ISP_WRITE(isp, DDMA_CONTROL, DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
490 1.33 mjacob
491 1.33 mjacob
492 1.111 mjacob } else if (IS_24XX(isp)) {
493 1.111 mjacob /*
494 1.111 mjacob * Stop DMA and wait for it to stop.
495 1.111 mjacob */
496 1.111 mjacob ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
497 1.111 mjacob for (val = loops = 0; loops < 30000; loops++) {
498 1.117 mjacob ISP_DELAY(10);
499 1.111 mjacob val = ISP_READ(isp, BIU2400_CSR);
500 1.111 mjacob if ((val & BIU2400_DMA_ACTIVE) == 0) {
501 1.111 mjacob break;
502 1.111 mjacob }
503 1.117 mjacob }
504 1.111 mjacob if (val & BIU2400_DMA_ACTIVE) {
505 1.111 mjacob ISP_RESET0(isp);
506 1.111 mjacob isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
507 1.111 mjacob return;
508 1.111 mjacob }
509 1.111 mjacob /*
510 1.111 mjacob * Hold it in SOFT_RESET and STOP state for 100us.
511 1.111 mjacob */
512 1.117 mjacob ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
513 1.117 mjacob ISP_DELAY(100);
514 1.111 mjacob for (loops = 0; loops < 10000; loops++) {
515 1.117 mjacob ISP_DELAY(5);
516 1.111 mjacob val = ISP_READ(isp, OUTMAILBOX0);
517 1.111 mjacob }
518 1.111 mjacob for (val = loops = 0; loops < 500000; loops ++) {
519 1.111 mjacob val = ISP_READ(isp, BIU2400_CSR);
520 1.111 mjacob if ((val & BIU2400_SOFT_RESET) == 0) {
521 1.111 mjacob break;
522 1.111 mjacob }
523 1.111 mjacob }
524 1.111 mjacob if (val & BIU2400_SOFT_RESET) {
525 1.111 mjacob ISP_RESET0(isp);
526 1.111 mjacob isp_prt(isp, ISP_LOGERR, "Failed to come out of reset");
527 1.111 mjacob return;
528 1.111 mjacob }
529 1.10 mjacob } else {
530 1.10 mjacob ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
531 1.10 mjacob /*
532 1.10 mjacob * A slight delay...
533 1.10 mjacob */
534 1.117 mjacob ISP_DELAY(100);
535 1.31 mjacob
536 1.31 mjacob /*
537 1.31 mjacob * Clear data && control DMA engines.
538 1.31 mjacob */
539 1.117 mjacob ISP_WRITE(isp, CDMA2100_CONTROL, DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
540 1.117 mjacob ISP_WRITE(isp, TDMA2100_CONTROL, DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
541 1.117 mjacob ISP_WRITE(isp, RDMA2100_CONTROL, DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
542 1.10 mjacob }
543 1.10 mjacob
544 1.1 cgd /*
545 1.1 cgd * Wait for ISP to be ready to go...
546 1.1 cgd */
547 1.1 cgd loops = MBOX_DELAY_COUNT;
548 1.10 mjacob for (;;) {
549 1.38 mjacob if (IS_SCSI(isp)) {
550 1.111 mjacob if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET)) {
551 1.10 mjacob break;
552 1.111 mjacob }
553 1.111 mjacob } else if (IS_24XX(isp)) {
554 1.111 mjacob if (ISP_READ(isp, OUTMAILBOX0) == 0) {
555 1.111 mjacob break;
556 1.111 mjacob }
557 1.10 mjacob } else {
558 1.10 mjacob if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET))
559 1.10 mjacob break;
560 1.10 mjacob }
561 1.117 mjacob ISP_DELAY(100);
562 1.1 cgd if (--loops < 0) {
563 1.57 mjacob ISP_DUMPREGS(isp, "chip reset timed out");
564 1.111 mjacob ISP_RESET0(isp);
565 1.1 cgd return;
566 1.1 cgd }
567 1.1 cgd }
568 1.31 mjacob
569 1.1 cgd /*
570 1.31 mjacob * After we've fired this chip up, zero out the conf1 register
571 1.31 mjacob * for SCSI adapters and other settings for the 2100.
572 1.1 cgd */
573 1.31 mjacob
574 1.33 mjacob if (IS_SCSI(isp)) {
575 1.10 mjacob ISP_WRITE(isp, BIU_CONF1, 0);
576 1.111 mjacob } else if (!IS_24XX(isp)) {
577 1.10 mjacob ISP_WRITE(isp, BIU2100_CSR, 0);
578 1.10 mjacob }
579 1.1 cgd
580 1.31 mjacob /*
581 1.31 mjacob * Reset RISC Processor
582 1.31 mjacob */
583 1.111 mjacob if (IS_24XX(isp)) {
584 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
585 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE);
586 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET);
587 1.111 mjacob } else {
588 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
589 1.117 mjacob ISP_DELAY(100);
590 1.111 mjacob ISP_WRITE(isp, BIU_SEMA, 0);
591 1.111 mjacob }
592 1.1 cgd
593 1.30 mjacob /*
594 1.111 mjacob * Post-RISC Reset stuff.
595 1.30 mjacob */
596 1.111 mjacob if (IS_24XX(isp)) {
597 1.111 mjacob for (val = loops = 0; loops < 5000000; loops++) {
598 1.117 mjacob ISP_DELAY(5);
599 1.111 mjacob val = ISP_READ(isp, OUTMAILBOX0);
600 1.111 mjacob if (val == 0) {
601 1.111 mjacob break;
602 1.111 mjacob }
603 1.111 mjacob }
604 1.111 mjacob if (val != 0) {
605 1.111 mjacob ISP_RESET0(isp);
606 1.111 mjacob isp_prt(isp, ISP_LOGERR, "reset didn't clear");
607 1.111 mjacob return;
608 1.111 mjacob }
609 1.111 mjacob } else if (IS_SCSI(isp)) {
610 1.111 mjacob uint16_t tmp = isp->isp_mdvec->dv_conf1;
611 1.30 mjacob /*
612 1.30 mjacob * Busted FIFO. Turn off all but burst enables.
613 1.30 mjacob */
614 1.30 mjacob if (isp->isp_type == ISP_HA_SCSI_1040A) {
615 1.31 mjacob tmp &= BIU_BURST_ENABLE;
616 1.30 mjacob }
617 1.31 mjacob ISP_SETBITS(isp, BIU_CONF1, tmp);
618 1.31 mjacob if (tmp & BIU_BURST_ENABLE) {
619 1.1 cgd ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST);
620 1.1 cgd ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST);
621 1.1 cgd }
622 1.114 mjacob if (SDPARAM(isp, 0)->isp_ptisp) {
623 1.114 mjacob if (SDPARAM(isp, 0)->isp_ultramode) {
624 1.111 mjacob while (ISP_READ(isp, RISC_MTR) != 0x1313) {
625 1.111 mjacob ISP_WRITE(isp, RISC_MTR, 0x1313);
626 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_STEP);
627 1.111 mjacob }
628 1.111 mjacob } else {
629 1.111 mjacob ISP_WRITE(isp, RISC_MTR, 0x1212);
630 1.31 mjacob }
631 1.111 mjacob /*
632 1.111 mjacob * PTI specific register
633 1.111 mjacob */
634 1.111 mjacob ISP_WRITE(isp, RISC_EMB, DUAL_BANK);
635 1.34 mjacob } else {
636 1.31 mjacob ISP_WRITE(isp, RISC_MTR, 0x1212);
637 1.31 mjacob }
638 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
639 1.31 mjacob } else {
640 1.31 mjacob ISP_WRITE(isp, RISC_MTR2100, 0x1212);
641 1.87 mjacob if (IS_2200(isp) || IS_23XX(isp)) {
642 1.70 mjacob ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE);
643 1.70 mjacob }
644 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
645 1.1 cgd }
646 1.31 mjacob
647 1.111 mjacob ISP_WRITE(isp, isp->isp_rqstinrp, 0);
648 1.111 mjacob ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
649 1.111 mjacob ISP_WRITE(isp, isp->isp_respinrp, 0);
650 1.111 mjacob ISP_WRITE(isp, isp->isp_respoutrp, 0);
651 1.114 mjacob if (IS_24XX(isp)) {
652 1.114 mjacob ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
653 1.114 mjacob ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
654 1.114 mjacob ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
655 1.114 mjacob ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
656 1.114 mjacob }
657 1.1 cgd
658 1.1 cgd /*
659 1.1 cgd * Do MD specific post initialization
660 1.1 cgd */
661 1.1 cgd ISP_RESET1(isp);
662 1.1 cgd
663 1.1 cgd /*
664 1.81 mjacob * Wait for everything to finish firing up.
665 1.81 mjacob *
666 1.114 mjacob * Avoid doing this on early 2312s because you can generate a PCI
667 1.81 mjacob * parity error (chip breakage).
668 1.31 mjacob */
669 1.114 mjacob if (IS_2312(isp) && isp->isp_revision < 2) {
670 1.117 mjacob ISP_DELAY(100);
671 1.81 mjacob } else {
672 1.81 mjacob loops = MBOX_DELAY_COUNT;
673 1.81 mjacob while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) {
674 1.117 mjacob ISP_DELAY(100);
675 1.81 mjacob if (--loops < 0) {
676 1.111 mjacob ISP_RESET0(isp);
677 1.81 mjacob isp_prt(isp, ISP_LOGERR,
678 1.81 mjacob "MBOX_BUSY never cleared on reset");
679 1.81 mjacob return;
680 1.81 mjacob }
681 1.31 mjacob }
682 1.31 mjacob }
683 1.31 mjacob
684 1.31 mjacob /*
685 1.31 mjacob * Up until this point we've done everything by just reading or
686 1.31 mjacob * setting registers. From this point on we rely on at least *some*
687 1.31 mjacob * kind of firmware running in the card.
688 1.31 mjacob */
689 1.31 mjacob
690 1.31 mjacob /*
691 1.117 mjacob * Do some sanity checking by running a NOP command.
692 1.117 mjacob * If it succeeds, the ROM firmware is now running.
693 1.1 cgd */
694 1.117 mjacob ISP_MEMZERO(&mbs, sizeof (mbs));
695 1.1 cgd mbs.param[0] = MBOX_NO_OP;
696 1.111 mjacob mbs.logval = MBLOGALL;
697 1.111 mjacob isp_mboxcmd(isp, &mbs);
698 1.1 cgd if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
699 1.117 mjacob isp_prt(isp, ISP_LOGERR, "NOP ommand failed (%x)", mbs.param[0]);
700 1.111 mjacob ISP_RESET0(isp);
701 1.1 cgd return;
702 1.1 cgd }
703 1.1 cgd
704 1.117 mjacob /*
705 1.117 mjacob * Do some operational tests
706 1.117 mjacob */
707 1.117 mjacob
708 1.111 mjacob if (IS_SCSI(isp) || IS_24XX(isp)) {
709 1.117 mjacob ISP_MEMZERO(&mbs, sizeof (mbs));
710 1.10 mjacob mbs.param[0] = MBOX_MAILBOX_REG_TEST;
711 1.10 mjacob mbs.param[1] = 0xdead;
712 1.10 mjacob mbs.param[2] = 0xbeef;
713 1.10 mjacob mbs.param[3] = 0xffff;
714 1.10 mjacob mbs.param[4] = 0x1111;
715 1.10 mjacob mbs.param[5] = 0xa5a5;
716 1.111 mjacob mbs.param[6] = 0x0000;
717 1.111 mjacob mbs.param[7] = 0x0000;
718 1.111 mjacob mbs.logval = MBLOGALL;
719 1.111 mjacob isp_mboxcmd(isp, &mbs);
720 1.1 cgd if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
721 1.111 mjacob ISP_RESET0(isp);
722 1.10 mjacob return;
723 1.10 mjacob }
724 1.10 mjacob if (mbs.param[1] != 0xdead || mbs.param[2] != 0xbeef ||
725 1.10 mjacob mbs.param[3] != 0xffff || mbs.param[4] != 0x1111 ||
726 1.10 mjacob mbs.param[5] != 0xa5a5) {
727 1.111 mjacob ISP_RESET0(isp);
728 1.117 mjacob isp_prt(isp, ISP_LOGERR, "Register Test Failed (0x%x 0x%x 0x%x 0x%x 0x%x)", mbs.param[1], mbs.param[2], mbs.param[3], mbs.param[4], mbs.param[5]);
729 1.1 cgd return;
730 1.1 cgd }
731 1.10 mjacob
732 1.1 cgd }
733 1.1 cgd
734 1.1 cgd /*
735 1.18 mjacob * Download new Firmware, unless requested not to do so.
736 1.18 mjacob * This is made slightly trickier in some cases where the
737 1.18 mjacob * firmware of the ROM revision is newer than the revision
738 1.18 mjacob * compiled into the driver. So, where we used to compare
739 1.18 mjacob * versions of our f/w and the ROM f/w, now we just see
740 1.18 mjacob * whether we have f/w at all and whether a config flag
741 1.18 mjacob * has disabled our download.
742 1.1 cgd */
743 1.117 mjacob if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
744 1.10 mjacob dodnld = 0;
745 1.10 mjacob }
746 1.10 mjacob
747 1.111 mjacob if (IS_24XX(isp)) {
748 1.111 mjacob code_org = ISP_CODE_ORG_2400;
749 1.111 mjacob } else if (IS_23XX(isp)) {
750 1.79 mjacob code_org = ISP_CODE_ORG_2300;
751 1.111 mjacob } else {
752 1.79 mjacob code_org = ISP_CODE_ORG;
753 1.111 mjacob }
754 1.111 mjacob
755 1.111 mjacob if (dodnld && IS_24XX(isp)) {
756 1.111 mjacob const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
757 1.111 mjacob
758 1.111 mjacob /*
759 1.111 mjacob * Keep loading until we run out of f/w.
760 1.111 mjacob */
761 1.111 mjacob code_org = ptr[2]; /* 1st load address is our start addr */
762 1.111 mjacob
763 1.111 mjacob for (;;) {
764 1.111 mjacob uint32_t la, wi, wl;
765 1.111 mjacob
766 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
767 1.111 mjacob
768 1.111 mjacob wi = 0;
769 1.111 mjacob la = ptr[2];
770 1.111 mjacob wl = ptr[3];
771 1.111 mjacob
772 1.111 mjacob while (wi < ptr[3]) {
773 1.111 mjacob uint32_t *cp;
774 1.111 mjacob uint32_t nw;
775 1.111 mjacob
776 1.111 mjacob nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 2;
777 1.111 mjacob if (nw > wl) {
778 1.111 mjacob nw = wl;
779 1.111 mjacob }
780 1.111 mjacob cp = isp->isp_rquest;
781 1.111 mjacob for (i = 0; i < nw; i++) {
782 1.112 mjacob ISP_IOXPUT_32(isp, ptr[wi++], &cp[i]);
783 1.111 mjacob wl--;
784 1.111 mjacob }
785 1.117 mjacob MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
786 1.117 mjacob ISP_MEMZERO(&mbs, sizeof (mbs));
787 1.118 mjacob if (la < 0x10000 && nw < 0x10000) {
788 1.118 mjacob mbs.param[0] = MBOX_LOAD_RISC_RAM_2100;
789 1.118 mjacob mbs.param[1] = la;
790 1.118 mjacob mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
791 1.118 mjacob mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
792 1.118 mjacob mbs.param[4] = nw;
793 1.118 mjacob mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
794 1.118 mjacob mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
795 1.118 mjacob } else {
796 1.118 mjacob mbs.param[0] = MBOX_LOAD_RISC_RAM;
797 1.118 mjacob mbs.param[1] = la;
798 1.118 mjacob mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
799 1.118 mjacob mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
800 1.118 mjacob mbs.param[4] = nw >> 16;
801 1.118 mjacob mbs.param[5] = nw;
802 1.118 mjacob mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
803 1.118 mjacob mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
804 1.118 mjacob mbs.param[8] = la >> 16;
805 1.118 mjacob }
806 1.111 mjacob mbs.logval = MBLOGALL;
807 1.111 mjacob isp_mboxcmd(isp, &mbs);
808 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
809 1.117 mjacob isp_prt(isp, ISP_LOGERR, "F/W Risc Ram Load Failed");
810 1.111 mjacob ISP_RESET0(isp);
811 1.111 mjacob return;
812 1.111 mjacob }
813 1.111 mjacob la += nw;
814 1.111 mjacob }
815 1.111 mjacob
816 1.111 mjacob if (ptr[1] == 0) {
817 1.111 mjacob break;
818 1.111 mjacob }
819 1.111 mjacob ptr += ptr[3];
820 1.117 mjacob }
821 1.111 mjacob isp->isp_loaded_fw = 1;
822 1.111 mjacob } else if (dodnld && IS_23XX(isp)) {
823 1.111 mjacob const uint16_t *ptr = isp->isp_mdvec->dv_ispfw;
824 1.111 mjacob uint16_t wi, wl, segno;
825 1.111 mjacob uint32_t la;
826 1.111 mjacob
827 1.111 mjacob la = code_org;
828 1.111 mjacob segno = 0;
829 1.111 mjacob
830 1.111 mjacob for (;;) {
831 1.111 mjacob uint32_t nxtaddr;
832 1.111 mjacob
833 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], la);
834 1.111 mjacob
835 1.111 mjacob wi = 0;
836 1.111 mjacob wl = ptr[3];
837 1.111 mjacob
838 1.111 mjacob while (wi < ptr[3]) {
839 1.111 mjacob uint16_t *cp;
840 1.118 mjacob uint16_t nw;
841 1.117 mjacob
842 1.111 mjacob nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 1;
843 1.111 mjacob if (nw > wl) {
844 1.111 mjacob nw = wl;
845 1.111 mjacob }
846 1.111 mjacob if (nw > (1 << 15)) {
847 1.111 mjacob nw = 1 << 15;
848 1.111 mjacob }
849 1.111 mjacob cp = isp->isp_rquest;
850 1.111 mjacob for (i = 0; i < nw; i++) {
851 1.112 mjacob ISP_IOXPUT_16(isp, ptr[wi++], &cp[i]);
852 1.111 mjacob wl--;
853 1.111 mjacob }
854 1.117 mjacob MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
855 1.117 mjacob ISP_MEMZERO(&mbs, sizeof (mbs));
856 1.118 mjacob if (la < 0x10000) {
857 1.118 mjacob mbs.param[0] = MBOX_LOAD_RISC_RAM_2100;
858 1.118 mjacob mbs.param[1] = la;
859 1.118 mjacob mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
860 1.118 mjacob mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
861 1.118 mjacob mbs.param[4] = nw;
862 1.118 mjacob mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
863 1.118 mjacob mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
864 1.118 mjacob } else {
865 1.118 mjacob mbs.param[0] = MBOX_LOAD_RISC_RAM;
866 1.118 mjacob mbs.param[1] = la;
867 1.118 mjacob mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
868 1.118 mjacob mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
869 1.118 mjacob mbs.param[4] = nw;
870 1.118 mjacob mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
871 1.118 mjacob mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
872 1.118 mjacob mbs.param[8] = la >> 16;
873 1.118 mjacob }
874 1.111 mjacob mbs.logval = MBLOGALL;
875 1.111 mjacob isp_mboxcmd(isp, &mbs);
876 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
877 1.117 mjacob isp_prt(isp, ISP_LOGERR, "F/W Risc Ram Load Failed");
878 1.111 mjacob ISP_RESET0(isp);
879 1.111 mjacob return;
880 1.111 mjacob }
881 1.111 mjacob la += nw;
882 1.111 mjacob }
883 1.111 mjacob
884 1.111 mjacob if (!IS_2322(isp)) {
885 1.111 mjacob break;
886 1.111 mjacob }
887 1.79 mjacob
888 1.111 mjacob if (++segno == 3) {
889 1.111 mjacob break;
890 1.111 mjacob }
891 1.111 mjacob
892 1.111 mjacob /*
893 1.111 mjacob * If we're a 2322, the firmware actually comes in
894 1.111 mjacob * three chunks. We loaded the first at the code_org
895 1.111 mjacob * address. The other two chunks, which follow right
896 1.111 mjacob * after each other in memory here, get loaded at
897 1.111 mjacob * addresses specfied at offset 0x9..0xB.
898 1.111 mjacob */
899 1.111 mjacob
900 1.111 mjacob nxtaddr = ptr[3];
901 1.111 mjacob ptr = &ptr[nxtaddr];
902 1.111 mjacob la = ptr[5] | ((ptr[4] & 0x3f) << 16);
903 1.111 mjacob }
904 1.111 mjacob isp->isp_loaded_fw = 1;
905 1.111 mjacob } else if (dodnld) {
906 1.111 mjacob union {
907 1.111 mjacob const uint16_t *cp;
908 1.111 mjacob uint16_t *np;
909 1.114 mjacob } ucd;
910 1.114 mjacob ucd.cp = isp->isp_mdvec->dv_ispfw;
911 1.114 mjacob isp->isp_mbxworkp = &ucd.np[1];
912 1.114 mjacob isp->isp_mbxwrk0 = ucd.np[3] - 1;
913 1.88 mjacob isp->isp_mbxwrk1 = code_org + 1;
914 1.117 mjacob ISP_MEMZERO(&mbs, sizeof (mbs));
915 1.88 mjacob mbs.param[0] = MBOX_WRITE_RAM_WORD;
916 1.88 mjacob mbs.param[1] = code_org;
917 1.114 mjacob mbs.param[2] = ucd.np[0];
918 1.111 mjacob mbs.logval = MBLOGNONE;
919 1.111 mjacob isp_mboxcmd(isp, &mbs);
920 1.88 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
921 1.117 mjacob isp_prt(isp, ISP_LOGERR, "F/W download failed at word %d", isp->isp_mbxwrk1 - code_org);
922 1.111 mjacob ISP_RESET0(isp);
923 1.111 mjacob return;
924 1.10 mjacob }
925 1.117 mjacob } else {
926 1.117 mjacob isp->isp_loaded_fw = 0;
927 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
928 1.117 mjacob }
929 1.117 mjacob
930 1.117 mjacob /*
931 1.117 mjacob * If we loaded firmware, verify its checksum
932 1.117 mjacob */
933 1.117 mjacob if (isp->isp_loaded_fw) {
934 1.117 mjacob ISP_MEMZERO(&mbs, sizeof (mbs));
935 1.31 mjacob mbs.param[0] = MBOX_VERIFY_CHECKSUM;
936 1.117 mjacob if (IS_24XX(isp)) {
937 1.117 mjacob mbs.param[1] = code_org >> 16;
938 1.117 mjacob mbs.param[2] = code_org;
939 1.117 mjacob } else {
940 1.117 mjacob mbs.param[1] = code_org;
941 1.117 mjacob }
942 1.111 mjacob isp_mboxcmd(isp, &mbs);
943 1.31 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
944 1.111 mjacob isp_prt(isp, ISP_LOGERR, dcrc);
945 1.111 mjacob ISP_RESET0(isp);
946 1.31 mjacob return;
947 1.10 mjacob }
948 1.1 cgd }
949 1.1 cgd
950 1.1 cgd /*
951 1.10 mjacob * Now start it rolling.
952 1.10 mjacob *
953 1.10 mjacob * If we didn't actually download f/w,
954 1.10 mjacob * we still need to (re)start it.
955 1.1 cgd */
956 1.1 cgd
957 1.79 mjacob
958 1.117 mjacob MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 1000000);
959 1.111 mjacob if (IS_24XX(isp)) {
960 1.111 mjacob mbs.param[1] = code_org >> 16;
961 1.111 mjacob mbs.param[2] = code_org;
962 1.111 mjacob if (isp->isp_loaded_fw) {
963 1.111 mjacob mbs.param[3] = 0;
964 1.111 mjacob } else {
965 1.111 mjacob mbs.param[3] = 1;
966 1.111 mjacob }
967 1.117 mjacob if (IS_25XX(isp)) {
968 1.117 mjacob mbs.ibits |= 0x10;
969 1.117 mjacob }
970 1.111 mjacob } else if (IS_2322(isp)) {
971 1.111 mjacob mbs.param[1] = code_org;
972 1.111 mjacob if (isp->isp_loaded_fw) {
973 1.111 mjacob mbs.param[2] = 0;
974 1.111 mjacob } else {
975 1.111 mjacob mbs.param[2] = 1;
976 1.111 mjacob }
977 1.111 mjacob } else {
978 1.111 mjacob mbs.param[1] = code_org;
979 1.111 mjacob }
980 1.111 mjacob isp_mboxcmd(isp, &mbs);
981 1.111 mjacob if (IS_2322(isp) || IS_24XX(isp)) {
982 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
983 1.111 mjacob ISP_RESET0(isp);
984 1.111 mjacob return;
985 1.111 mjacob }
986 1.111 mjacob }
987 1.111 mjacob
988 1.94 mjacob /*
989 1.111 mjacob * Give it a chance to finish starting up.
990 1.117 mjacob * Give the 24XX more time.
991 1.94 mjacob */
992 1.117 mjacob if (IS_24XX(isp)) {
993 1.117 mjacob ISP_DELAY(500000);
994 1.10 mjacob /*
995 1.117 mjacob * Check to see if the 24XX firmware really started.
996 1.10 mjacob */
997 1.117 mjacob if (mbs.param[1] == 0xdead) {
998 1.117 mjacob isp_prt(isp, ISP_LOGERR, "f/w didn't *really* start");
999 1.117 mjacob ISP_RESET0(isp);
1000 1.117 mjacob return;
1001 1.117 mjacob }
1002 1.117 mjacob } else {
1003 1.117 mjacob ISP_DELAY(250000);
1004 1.117 mjacob if (IS_SCSI(isp)) {
1005 1.117 mjacob /*
1006 1.117 mjacob * Set CLOCK RATE, but only if asked to.
1007 1.117 mjacob */
1008 1.117 mjacob if (isp->isp_clock) {
1009 1.117 mjacob mbs.param[0] = MBOX_SET_CLOCK_RATE;
1010 1.117 mjacob mbs.param[1] = isp->isp_clock;
1011 1.117 mjacob mbs.logval = MBLOGNONE;
1012 1.117 mjacob isp_mboxcmd(isp, &mbs);
1013 1.117 mjacob /* we will try not to care if this fails */
1014 1.117 mjacob }
1015 1.4 mjacob }
1016 1.4 mjacob }
1017 1.57 mjacob
1018 1.117 mjacob /*
1019 1.117 mjacob * Ask the chip for the current firmware version.
1020 1.117 mjacob * This should prove that the new firmware is working.
1021 1.117 mjacob */
1022 1.117 mjacob MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 0);
1023 1.111 mjacob isp_mboxcmd(isp, &mbs);
1024 1.1 cgd if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1025 1.111 mjacob ISP_RESET0(isp);
1026 1.111 mjacob return;
1027 1.111 mjacob }
1028 1.111 mjacob
1029 1.80 mjacob /*
1030 1.80 mjacob * The SBus firmware that we are using apparently does not return
1031 1.80 mjacob * major, minor, micro revisions in the mailbox registers, which
1032 1.80 mjacob * is really, really, annoying.
1033 1.80 mjacob */
1034 1.86 mjacob if (ISP_SBUS_SUPPORTED && isp->isp_bustype == ISP_BT_SBUS) {
1035 1.80 mjacob if (dodnld) {
1036 1.80 mjacob #ifdef ISP_TARGET_MODE
1037 1.80 mjacob isp->isp_fwrev[0] = 7;
1038 1.80 mjacob isp->isp_fwrev[1] = 55;
1039 1.80 mjacob #else
1040 1.80 mjacob isp->isp_fwrev[0] = 1;
1041 1.80 mjacob isp->isp_fwrev[1] = 37;
1042 1.80 mjacob #endif
1043 1.80 mjacob isp->isp_fwrev[2] = 0;
1044 1.117 mjacob }
1045 1.80 mjacob } else {
1046 1.80 mjacob isp->isp_fwrev[0] = mbs.param[1];
1047 1.80 mjacob isp->isp_fwrev[1] = mbs.param[2];
1048 1.80 mjacob isp->isp_fwrev[2] = mbs.param[3];
1049 1.80 mjacob }
1050 1.111 mjacob
1051 1.117 mjacob isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
1052 1.117 mjacob btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
1053 1.80 mjacob
1054 1.34 mjacob if (IS_FC(isp)) {
1055 1.80 mjacob /*
1056 1.80 mjacob * We do not believe firmware attributes for 2100 code less
1057 1.98 mjacob * than 1.17.0, unless it's the firmware we specifically
1058 1.98 mjacob * are loading.
1059 1.98 mjacob *
1060 1.111 mjacob * Note that all 22XX and later f/w is greater than 1.X.0.
1061 1.80 mjacob */
1062 1.111 mjacob if ((ISP_FW_OLDER_THAN(isp, 1, 17, 1))) {
1063 1.98 mjacob #ifdef USE_SMALLER_2100_FIRMWARE
1064 1.114 mjacob isp->isp_fwattr = ISP_FW_ATTR_SCCLUN;
1065 1.98 mjacob #else
1066 1.114 mjacob isp->isp_fwattr = 0;
1067 1.98 mjacob #endif
1068 1.80 mjacob } else {
1069 1.114 mjacob isp->isp_fwattr = mbs.param[6];
1070 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "Firmware Attributes = 0x%x", mbs.param[6]);
1071 1.80 mjacob }
1072 1.114 mjacob } else {
1073 1.114 mjacob #ifndef ISP_TARGET_MODE
1074 1.114 mjacob isp->isp_fwattr = ISP_FW_ATTR_TMODE;
1075 1.114 mjacob #else
1076 1.114 mjacob isp->isp_fwattr = 0;
1077 1.114 mjacob #endif
1078 1.25 mjacob }
1079 1.38 mjacob
1080 1.111 mjacob if (!IS_24XX(isp)) {
1081 1.117 mjacob MBSINIT(&mbs, MBOX_GET_FIRMWARE_STATUS, MBLOGALL, 0);
1082 1.111 mjacob isp_mboxcmd(isp, &mbs);
1083 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1084 1.111 mjacob ISP_RESET0(isp);
1085 1.111 mjacob return;
1086 1.111 mjacob }
1087 1.111 mjacob if (isp->isp_maxcmds >= mbs.param[2]) {
1088 1.111 mjacob isp->isp_maxcmds = mbs.param[2];
1089 1.111 mjacob }
1090 1.38 mjacob }
1091 1.117 mjacob isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
1092 1.117 mjacob
1093 1.117 mjacob /*
1094 1.117 mjacob * If we don't have Multi-ID f/w loaded, we need to restrict channels to one.
1095 1.117 mjacob * Only make this check for non-SCSI cards (I'm not sure firmware attributes
1096 1.117 mjacob * work for them).
1097 1.117 mjacob */
1098 1.117 mjacob if (IS_FC(isp) && ISP_CAP_MULTI_ID(isp) == 0 && isp->isp_nchan > 1) {
1099 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, only can enable 1 of %d channels", isp->isp_nchan);
1100 1.117 mjacob isp->isp_nchan = 1;
1101 1.117 mjacob }
1102 1.117 mjacob
1103 1.114 mjacob for (i = 0; i < isp->isp_nchan; i++) {
1104 1.114 mjacob isp_fw_state(isp, i);
1105 1.114 mjacob }
1106 1.114 mjacob if (isp->isp_dead) {
1107 1.114 mjacob isp_shutdown(isp);
1108 1.114 mjacob ISP_DISABLE_INTS(isp);
1109 1.114 mjacob return;
1110 1.114 mjacob }
1111 1.38 mjacob
1112 1.1 cgd isp->isp_state = ISP_RESETSTATE;
1113 1.54 mjacob
1114 1.54 mjacob /*
1115 1.54 mjacob * Okay- now that we have new firmware running, we now (re)set our
1116 1.54 mjacob * notion of how many luns we support. This is somewhat tricky because
1117 1.80 mjacob * if we haven't loaded firmware, we sometimes do not have an easy way
1118 1.80 mjacob * of knowing how many luns we support.
1119 1.54 mjacob *
1120 1.54 mjacob * Expanded lun firmware gives you 32 luns for SCSI cards and
1121 1.93 mjacob * 16384 luns for Fibre Channel cards.
1122 1.54 mjacob *
1123 1.80 mjacob * It turns out that even for QLogic 2100s with ROM 1.10 and above
1124 1.80 mjacob * we do get a firmware attributes word returned in mailbox register 6.
1125 1.80 mjacob *
1126 1.101 mjacob * Because the lun is in a different position in the Request Queue
1127 1.54 mjacob * Entry structure for Fibre Channel with expanded lun firmware, we
1128 1.54 mjacob * can only support one lun (lun zero) when we don't know what kind
1129 1.54 mjacob * of firmware we're running.
1130 1.54 mjacob */
1131 1.95 mjacob if (IS_SCSI(isp)) {
1132 1.95 mjacob if (dodnld) {
1133 1.95 mjacob if (IS_ULTRA2(isp) || IS_ULTRA3(isp)) {
1134 1.54 mjacob isp->isp_maxluns = 32;
1135 1.54 mjacob } else {
1136 1.80 mjacob isp->isp_maxluns = 8;
1137 1.54 mjacob }
1138 1.54 mjacob } else {
1139 1.95 mjacob isp->isp_maxluns = 8;
1140 1.95 mjacob }
1141 1.95 mjacob } else {
1142 1.114 mjacob if (ISP_CAP_SCCFW(isp)) {
1143 1.95 mjacob isp->isp_maxluns = 16384;
1144 1.95 mjacob } else {
1145 1.95 mjacob isp->isp_maxluns = 16;
1146 1.54 mjacob }
1147 1.54 mjacob }
1148 1.114 mjacob
1149 1.111 mjacob /*
1150 1.114 mjacob * We get some default values established. As a side
1151 1.114 mjacob * effect, NVRAM is read here (unless overriden by
1152 1.114 mjacob * a configuration flag).
1153 1.111 mjacob */
1154 1.117 mjacob if (do_load_defaults) {
1155 1.117 mjacob if (IS_SCSI(isp)) {
1156 1.117 mjacob isp_setdfltsdparm(isp);
1157 1.117 mjacob } else {
1158 1.117 mjacob for (i = 0; i < isp->isp_nchan; i++) {
1159 1.117 mjacob isp_setdfltfcparm(isp, i);
1160 1.117 mjacob }
1161 1.111 mjacob }
1162 1.111 mjacob }
1163 1.1 cgd }
1164 1.1 cgd
1165 1.1 cgd /*
1166 1.31 mjacob * Initialize Parameters of Hardware to a known state.
1167 1.24 mjacob *
1168 1.24 mjacob * Locks are held before coming here.
1169 1.1 cgd */
1170 1.24 mjacob
1171 1.1 cgd void
1172 1.111 mjacob isp_init(ispsoftc_t *isp)
1173 1.1 cgd {
1174 1.70 mjacob if (IS_FC(isp)) {
1175 1.114 mjacob if (IS_24XX(isp)) {
1176 1.114 mjacob isp_fibre_init_2400(isp);
1177 1.114 mjacob } else {
1178 1.114 mjacob isp_fibre_init(isp);
1179 1.111 mjacob }
1180 1.70 mjacob } else {
1181 1.70 mjacob isp_scsi_init(isp);
1182 1.36 mjacob }
1183 1.117 mjacob GET_NANOTIME(&isp->isp_init_time);
1184 1.36 mjacob }
1185 1.36 mjacob
1186 1.36 mjacob static void
1187 1.111 mjacob isp_scsi_init(ispsoftc_t *isp)
1188 1.36 mjacob {
1189 1.36 mjacob sdparam *sdp_chan0, *sdp_chan1;
1190 1.1 cgd mbreg_t mbs;
1191 1.36 mjacob
1192 1.114 mjacob sdp_chan0 = SDPARAM(isp, 0);
1193 1.36 mjacob sdp_chan1 = sdp_chan0;
1194 1.44 mjacob if (IS_DUALBUS(isp)) {
1195 1.114 mjacob sdp_chan1 = SDPARAM(isp, 1);
1196 1.70 mjacob }
1197 1.70 mjacob
1198 1.36 mjacob /* First do overall per-card settings. */
1199 1.25 mjacob
1200 1.25 mjacob /*
1201 1.36 mjacob * If we have fast memory timing enabled, turn it on.
1202 1.25 mjacob */
1203 1.58 mjacob if (sdp_chan0->isp_fast_mttr) {
1204 1.36 mjacob ISP_WRITE(isp, RISC_MTR, 0x1313);
1205 1.36 mjacob }
1206 1.25 mjacob
1207 1.25 mjacob /*
1208 1.36 mjacob * Set Retry Delay and Count.
1209 1.36 mjacob * You set both channels at the same time.
1210 1.33 mjacob */
1211 1.117 mjacob MBSINIT(&mbs, MBOX_SET_RETRY_COUNT, MBLOGALL, 0);
1212 1.36 mjacob mbs.param[1] = sdp_chan0->isp_retry_count;
1213 1.36 mjacob mbs.param[2] = sdp_chan0->isp_retry_delay;
1214 1.36 mjacob mbs.param[6] = sdp_chan1->isp_retry_count;
1215 1.36 mjacob mbs.param[7] = sdp_chan1->isp_retry_delay;
1216 1.111 mjacob isp_mboxcmd(isp, &mbs);
1217 1.36 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1218 1.33 mjacob return;
1219 1.33 mjacob }
1220 1.34 mjacob
1221 1.33 mjacob /*
1222 1.36 mjacob * Set ASYNC DATA SETUP time. This is very important.
1223 1.25 mjacob */
1224 1.117 mjacob MBSINIT(&mbs, MBOX_SET_ASYNC_DATA_SETUP_TIME, MBLOGALL, 0);
1225 1.36 mjacob mbs.param[1] = sdp_chan0->isp_async_data_setup;
1226 1.36 mjacob mbs.param[2] = sdp_chan1->isp_async_data_setup;
1227 1.111 mjacob isp_mboxcmd(isp, &mbs);
1228 1.36 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1229 1.10 mjacob return;
1230 1.1 cgd }
1231 1.1 cgd
1232 1.10 mjacob /*
1233 1.36 mjacob * Set ACTIVE Negation State.
1234 1.32 mjacob */
1235 1.117 mjacob MBSINIT(&mbs, MBOX_SET_ACT_NEG_STATE, MBLOGNONE, 0);
1236 1.36 mjacob mbs.param[1] =
1237 1.36 mjacob (sdp_chan0->isp_req_ack_active_neg << 4) |
1238 1.36 mjacob (sdp_chan0->isp_data_line_active_neg << 5);
1239 1.36 mjacob mbs.param[2] =
1240 1.36 mjacob (sdp_chan1->isp_req_ack_active_neg << 4) |
1241 1.36 mjacob (sdp_chan1->isp_data_line_active_neg << 5);
1242 1.111 mjacob isp_mboxcmd(isp, &mbs);
1243 1.36 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1244 1.57 mjacob isp_prt(isp, ISP_LOGERR,
1245 1.57 mjacob "failed to set active negation state (%d,%d), (%d,%d)",
1246 1.36 mjacob sdp_chan0->isp_req_ack_active_neg,
1247 1.36 mjacob sdp_chan0->isp_data_line_active_neg,
1248 1.36 mjacob sdp_chan1->isp_req_ack_active_neg,
1249 1.36 mjacob sdp_chan1->isp_data_line_active_neg);
1250 1.36 mjacob /*
1251 1.36 mjacob * But don't return.
1252 1.36 mjacob */
1253 1.32 mjacob }
1254 1.32 mjacob
1255 1.32 mjacob /*
1256 1.36 mjacob * Set the Tag Aging limit
1257 1.10 mjacob */
1258 1.117 mjacob MBSINIT(&mbs, MBOX_SET_TAG_AGE_LIMIT, MBLOGALL, 0);
1259 1.36 mjacob mbs.param[1] = sdp_chan0->isp_tag_aging;
1260 1.36 mjacob mbs.param[2] = sdp_chan1->isp_tag_aging;
1261 1.111 mjacob isp_mboxcmd(isp, &mbs);
1262 1.1 cgd if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1263 1.57 mjacob isp_prt(isp, ISP_LOGERR, "failed to set tag age limit (%d,%d)",
1264 1.57 mjacob sdp_chan0->isp_tag_aging, sdp_chan1->isp_tag_aging);
1265 1.1 cgd return;
1266 1.1 cgd }
1267 1.1 cgd
1268 1.25 mjacob /*
1269 1.36 mjacob * Set selection timeout.
1270 1.25 mjacob */
1271 1.117 mjacob MBSINIT(&mbs, MBOX_SET_SELECT_TIMEOUT, MBLOGALL, 0);
1272 1.36 mjacob mbs.param[1] = sdp_chan0->isp_selection_timeout;
1273 1.36 mjacob mbs.param[2] = sdp_chan1->isp_selection_timeout;
1274 1.111 mjacob isp_mboxcmd(isp, &mbs);
1275 1.1 cgd if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1276 1.1 cgd return;
1277 1.1 cgd }
1278 1.1 cgd
1279 1.36 mjacob /* now do per-channel settings */
1280 1.36 mjacob isp_scsi_channel_init(isp, 0);
1281 1.44 mjacob if (IS_DUALBUS(isp))
1282 1.36 mjacob isp_scsi_channel_init(isp, 1);
1283 1.36 mjacob
1284 1.25 mjacob /*
1285 1.36 mjacob * Now enable request/response queues
1286 1.25 mjacob */
1287 1.36 mjacob
1288 1.99 mjacob if (IS_ULTRA2(isp) || IS_1240(isp)) {
1289 1.117 mjacob MBSINIT(&mbs, MBOX_INIT_RES_QUEUE_A64, MBLOGALL, 0);
1290 1.99 mjacob mbs.param[1] = RESULT_QUEUE_LEN(isp);
1291 1.99 mjacob mbs.param[2] = DMA_WD1(isp->isp_result_dma);
1292 1.99 mjacob mbs.param[3] = DMA_WD0(isp->isp_result_dma);
1293 1.99 mjacob mbs.param[4] = 0;
1294 1.99 mjacob mbs.param[6] = DMA_WD3(isp->isp_result_dma);
1295 1.99 mjacob mbs.param[7] = DMA_WD2(isp->isp_result_dma);
1296 1.111 mjacob isp_mboxcmd(isp, &mbs);
1297 1.99 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1298 1.99 mjacob return;
1299 1.99 mjacob }
1300 1.99 mjacob isp->isp_residx = mbs.param[5];
1301 1.99 mjacob
1302 1.117 mjacob MBSINIT(&mbs, MBOX_INIT_REQ_QUEUE_A64, MBLOGALL, 0);
1303 1.99 mjacob mbs.param[1] = RQUEST_QUEUE_LEN(isp);
1304 1.99 mjacob mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
1305 1.99 mjacob mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
1306 1.99 mjacob mbs.param[5] = 0;
1307 1.99 mjacob mbs.param[6] = DMA_WD3(isp->isp_result_dma);
1308 1.99 mjacob mbs.param[7] = DMA_WD2(isp->isp_result_dma);
1309 1.111 mjacob isp_mboxcmd(isp, &mbs);
1310 1.99 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1311 1.99 mjacob return;
1312 1.99 mjacob }
1313 1.99 mjacob isp->isp_reqidx = isp->isp_reqodx = mbs.param[4];
1314 1.99 mjacob } else {
1315 1.117 mjacob MBSINIT(&mbs, MBOX_INIT_RES_QUEUE, MBLOGALL, 0);
1316 1.99 mjacob mbs.param[1] = RESULT_QUEUE_LEN(isp);
1317 1.99 mjacob mbs.param[2] = DMA_WD1(isp->isp_result_dma);
1318 1.99 mjacob mbs.param[3] = DMA_WD0(isp->isp_result_dma);
1319 1.99 mjacob mbs.param[4] = 0;
1320 1.111 mjacob isp_mboxcmd(isp, &mbs);
1321 1.99 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1322 1.99 mjacob return;
1323 1.99 mjacob }
1324 1.99 mjacob isp->isp_residx = mbs.param[5];
1325 1.1 cgd
1326 1.117 mjacob MBSINIT(&mbs, MBOX_INIT_REQ_QUEUE, MBLOGALL, 0);
1327 1.99 mjacob mbs.param[1] = RQUEST_QUEUE_LEN(isp);
1328 1.99 mjacob mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
1329 1.99 mjacob mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
1330 1.99 mjacob mbs.param[5] = 0;
1331 1.111 mjacob isp_mboxcmd(isp, &mbs);
1332 1.99 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1333 1.99 mjacob return;
1334 1.99 mjacob }
1335 1.99 mjacob isp->isp_reqidx = isp->isp_reqodx = mbs.param[4];
1336 1.1 cgd }
1337 1.1 cgd
1338 1.25 mjacob /*
1339 1.45 mjacob * Turn on Fast Posting, LVD transitions
1340 1.45 mjacob *
1341 1.45 mjacob * Ultra2 F/W always has had fast posting (and LVD transitions)
1342 1.45 mjacob *
1343 1.50 mjacob * Ultra and older (i.e., SBus) cards may not. It's just safer
1344 1.50 mjacob * to assume not for them.
1345 1.25 mjacob */
1346 1.25 mjacob
1347 1.117 mjacob MBSINIT(&mbs, MBOX_SET_FW_FEATURES, MBLOGALL, 0);
1348 1.45 mjacob if (IS_ULTRA2(isp))
1349 1.45 mjacob mbs.param[1] |= FW_FEATURE_LVD_NOTIFY;
1350 1.88 mjacob #ifndef ISP_NO_RIO
1351 1.88 mjacob if (IS_ULTRA2(isp) || IS_1240(isp))
1352 1.88 mjacob mbs.param[1] |= FW_FEATURE_RIO_16BIT;
1353 1.88 mjacob #else
1354 1.49 mjacob if (IS_ULTRA2(isp) || IS_1240(isp))
1355 1.49 mjacob mbs.param[1] |= FW_FEATURE_FAST_POST;
1356 1.88 mjacob #endif
1357 1.45 mjacob if (mbs.param[1] != 0) {
1358 1.111 mjacob uint16_t sfeat = mbs.param[1];
1359 1.111 mjacob isp_mboxcmd(isp, &mbs);
1360 1.57 mjacob if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
1361 1.57 mjacob isp_prt(isp, ISP_LOGINFO,
1362 1.57 mjacob "Enabled FW features (0x%x)", sfeat);
1363 1.36 mjacob }
1364 1.1 cgd }
1365 1.1 cgd
1366 1.36 mjacob isp->isp_state = ISP_INITSTATE;
1367 1.36 mjacob }
1368 1.25 mjacob
1369 1.36 mjacob static void
1370 1.114 mjacob isp_scsi_channel_init(ispsoftc_t *isp, int chan)
1371 1.36 mjacob {
1372 1.36 mjacob sdparam *sdp;
1373 1.36 mjacob mbreg_t mbs;
1374 1.36 mjacob int tgt;
1375 1.36 mjacob
1376 1.114 mjacob sdp = SDPARAM(isp, chan);
1377 1.36 mjacob
1378 1.36 mjacob /*
1379 1.36 mjacob * Set (possibly new) Initiator ID.
1380 1.36 mjacob */
1381 1.117 mjacob MBSINIT(&mbs, MBOX_SET_INIT_SCSI_ID, MBLOGALL, 0);
1382 1.114 mjacob mbs.param[1] = (chan << 7) | sdp->isp_initiator_id;
1383 1.111 mjacob isp_mboxcmd(isp, &mbs);
1384 1.1 cgd if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1385 1.1 cgd return;
1386 1.1 cgd }
1387 1.114 mjacob isp_prt(isp, ISP_LOGINFO, "Chan %d Initiator ID is %d",
1388 1.114 mjacob chan, sdp->isp_initiator_id);
1389 1.62 mjacob
1390 1.1 cgd
1391 1.25 mjacob /*
1392 1.79 mjacob * Set current per-target parameters to an initial safe minimum.
1393 1.25 mjacob */
1394 1.25 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
1395 1.54 mjacob int lun;
1396 1.111 mjacob uint16_t sdf;
1397 1.10 mjacob
1398 1.36 mjacob if (sdp->isp_devparam[tgt].dev_enable == 0) {
1399 1.1 cgd continue;
1400 1.36 mjacob }
1401 1.74 mjacob #ifndef ISP_TARGET_MODE
1402 1.79 mjacob sdf = sdp->isp_devparam[tgt].goal_flags;
1403 1.79 mjacob sdf &= DPARM_SAFE_DFLT;
1404 1.79 mjacob /*
1405 1.79 mjacob * It is not quite clear when this changed over so that
1406 1.79 mjacob * we could force narrow and async for 1000/1020 cards,
1407 1.79 mjacob * but assume that this is only the case for loaded
1408 1.79 mjacob * firmware.
1409 1.79 mjacob */
1410 1.79 mjacob if (isp->isp_loaded_fw) {
1411 1.79 mjacob sdf |= DPARM_NARROW | DPARM_ASYNC;
1412 1.74 mjacob }
1413 1.74 mjacob #else
1414 1.36 mjacob /*
1415 1.74 mjacob * The !$*!)$!$)* f/w uses the same index into some
1416 1.74 mjacob * internal table to decide how to respond to negotiations,
1417 1.74 mjacob * so if we've said "let's be safe" for ID X, and ID X
1418 1.74 mjacob * selects *us*, the negotiations will back to 'safe'
1419 1.74 mjacob * (as in narrow/async). What the f/w *should* do is
1420 1.74 mjacob * use the initiator id settings to decide how to respond.
1421 1.36 mjacob */
1422 1.79 mjacob sdp->isp_devparam[tgt].goal_flags = sdf = DPARM_DEFAULT;
1423 1.74 mjacob #endif
1424 1.117 mjacob MBSINIT(&mbs, MBOX_SET_TARGET_PARAMS, MBLOGNONE, 0);
1425 1.114 mjacob mbs.param[1] = (chan << 15) | (tgt << 8);
1426 1.32 mjacob mbs.param[2] = sdf;
1427 1.58 mjacob if ((sdf & DPARM_SYNC) == 0) {
1428 1.58 mjacob mbs.param[3] = 0;
1429 1.58 mjacob } else {
1430 1.58 mjacob mbs.param[3] =
1431 1.79 mjacob (sdp->isp_devparam[tgt].goal_offset << 8) |
1432 1.79 mjacob (sdp->isp_devparam[tgt].goal_period);
1433 1.58 mjacob }
1434 1.74 mjacob isp_prt(isp, ISP_LOGDEBUG0,
1435 1.79 mjacob "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x",
1436 1.114 mjacob chan, tgt, mbs.param[2], mbs.param[3] >> 8,
1437 1.74 mjacob mbs.param[3] & 0xff);
1438 1.111 mjacob isp_mboxcmd(isp, &mbs);
1439 1.1 cgd if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1440 1.32 mjacob sdf = DPARM_SAFE_DFLT;
1441 1.117 mjacob MBSINIT(&mbs, MBOX_SET_TARGET_PARAMS, MBLOGALL, 0);
1442 1.114 mjacob mbs.param[1] = (tgt << 8) | (chan << 15);
1443 1.32 mjacob mbs.param[2] = sdf;
1444 1.58 mjacob mbs.param[3] = 0;
1445 1.111 mjacob isp_mboxcmd(isp, &mbs);
1446 1.10 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1447 1.25 mjacob continue;
1448 1.10 mjacob }
1449 1.1 cgd }
1450 1.45 mjacob
1451 1.34 mjacob /*
1452 1.58 mjacob * We don't update any information directly from the f/w
1453 1.58 mjacob * because we need to run at least one command to cause a
1454 1.58 mjacob * new state to be latched up. So, we just assume that we
1455 1.58 mjacob * converge to the values we just had set.
1456 1.58 mjacob *
1457 1.34 mjacob * Ensure that we don't believe tagged queuing is enabled yet.
1458 1.34 mjacob * It turns out that sometimes the ISP just ignores our
1459 1.34 mjacob * attempts to set parameters for devices that it hasn't
1460 1.34 mjacob * seen yet.
1461 1.34 mjacob */
1462 1.79 mjacob sdp->isp_devparam[tgt].actv_flags = sdf & ~DPARM_TQING;
1463 1.57 mjacob for (lun = 0; lun < (int) isp->isp_maxluns; lun++) {
1464 1.117 mjacob MBSINIT(&mbs, MBOX_SET_DEV_QUEUE_PARAMS, MBLOGALL, 0);
1465 1.114 mjacob mbs.param[1] = (chan << 15) | (tgt << 8) | lun;
1466 1.10 mjacob mbs.param[2] = sdp->isp_max_queue_depth;
1467 1.25 mjacob mbs.param[3] = sdp->isp_devparam[tgt].exc_throttle;
1468 1.111 mjacob isp_mboxcmd(isp, &mbs);
1469 1.1 cgd if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1470 1.25 mjacob break;
1471 1.1 cgd }
1472 1.1 cgd }
1473 1.31 mjacob }
1474 1.60 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
1475 1.60 mjacob if (sdp->isp_devparam[tgt].dev_refresh) {
1476 1.114 mjacob sdp->sendmarker = 1;
1477 1.114 mjacob sdp->update = 1;
1478 1.60 mjacob break;
1479 1.60 mjacob }
1480 1.60 mjacob }
1481 1.1 cgd }
1482 1.1 cgd
1483 1.24 mjacob /*
1484 1.24 mjacob * Fibre Channel specific initialization.
1485 1.24 mjacob */
1486 1.10 mjacob static void
1487 1.111 mjacob isp_fibre_init(ispsoftc_t *isp)
1488 1.10 mjacob {
1489 1.10 mjacob fcparam *fcp;
1490 1.86 mjacob isp_icb_t local, *icbp = &local;
1491 1.10 mjacob mbreg_t mbs;
1492 1.111 mjacob int ownloopid;
1493 1.10 mjacob
1494 1.114 mjacob /*
1495 1.114 mjacob * We only support one channel on non-24XX cards
1496 1.114 mjacob */
1497 1.114 mjacob fcp = FCPARAM(isp, 0);
1498 1.114 mjacob if (fcp->role == ISP_ROLE_NONE) {
1499 1.114 mjacob isp->isp_state = ISP_INITSTATE;
1500 1.114 mjacob return;
1501 1.114 mjacob }
1502 1.10 mjacob
1503 1.117 mjacob ISP_MEMZERO(icbp, sizeof (*icbp));
1504 1.25 mjacob icbp->icb_version = ICB_VERSION1;
1505 1.111 mjacob icbp->icb_fwoptions = fcp->isp_fwoptions;
1506 1.58 mjacob
1507 1.58 mjacob /*
1508 1.58 mjacob * Firmware Options are either retrieved from NVRAM or
1509 1.58 mjacob * are patched elsewhere. We check them for sanity here
1510 1.58 mjacob * and make changes based on board revision, but otherwise
1511 1.58 mjacob * let others decide policy.
1512 1.58 mjacob */
1513 1.58 mjacob
1514 1.43 mjacob /*
1515 1.43 mjacob * If this is a 2100 < revision 5, we have to turn off FAIRNESS.
1516 1.43 mjacob */
1517 1.111 mjacob if (IS_2100(isp) && isp->isp_revision < 5) {
1518 1.111 mjacob icbp->icb_fwoptions &= ~ICBOPT_FAIRNESS;
1519 1.43 mjacob }
1520 1.58 mjacob
1521 1.37 mjacob /*
1522 1.38 mjacob * We have to use FULL LOGIN even though it resets the loop too much
1523 1.38 mjacob * because otherwise port database entries don't get updated after
1524 1.52 he * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0.
1525 1.37 mjacob */
1526 1.97 mjacob if (!ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
1527 1.111 mjacob icbp->icb_fwoptions |= ICBOPT_FULL_LOGIN;
1528 1.38 mjacob }
1529 1.37 mjacob
1530 1.37 mjacob /*
1531 1.60 mjacob * Insist on Port Database Update Async notifications
1532 1.60 mjacob */
1533 1.111 mjacob icbp->icb_fwoptions |= ICBOPT_PDBCHANGE_AE;
1534 1.60 mjacob
1535 1.70 mjacob /*
1536 1.70 mjacob * Make sure that target role reflects into fwoptions.
1537 1.70 mjacob */
1538 1.114 mjacob if (fcp->role & ISP_ROLE_TARGET) {
1539 1.111 mjacob icbp->icb_fwoptions |= ICBOPT_TGT_ENABLE;
1540 1.70 mjacob } else {
1541 1.111 mjacob icbp->icb_fwoptions &= ~ICBOPT_TGT_ENABLE;
1542 1.111 mjacob }
1543 1.111 mjacob
1544 1.114 mjacob if (fcp->role & ISP_ROLE_INITIATOR) {
1545 1.111 mjacob icbp->icb_fwoptions &= ~ICBOPT_INI_DISABLE;
1546 1.111 mjacob } else {
1547 1.111 mjacob icbp->icb_fwoptions |= ICBOPT_INI_DISABLE;
1548 1.70 mjacob }
1549 1.70 mjacob
1550 1.114 mjacob icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
1551 1.118 mjacob if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
1552 1.118 mjacob isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
1553 1.35 mjacob icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
1554 1.25 mjacob }
1555 1.25 mjacob icbp->icb_maxalloc = fcp->isp_maxalloc;
1556 1.37 mjacob if (icbp->icb_maxalloc < 1) {
1557 1.118 mjacob isp_prt(isp, ISP_LOGERR, "bad maximum allocation (%d)- using 16", fcp->isp_maxalloc);
1558 1.35 mjacob icbp->icb_maxalloc = 16;
1559 1.35 mjacob }
1560 1.114 mjacob icbp->icb_execthrottle = DEFAULT_EXEC_THROTTLE(isp);
1561 1.35 mjacob if (icbp->icb_execthrottle < 1) {
1562 1.118 mjacob isp_prt(isp, ISP_LOGERR, "bad execution throttle of %d- using %d", DEFAULT_EXEC_THROTTLE(isp), ICB_DFLT_THROTTLE);
1563 1.37 mjacob icbp->icb_execthrottle = ICB_DFLT_THROTTLE;
1564 1.35 mjacob }
1565 1.25 mjacob icbp->icb_retry_delay = fcp->isp_retry_delay;
1566 1.25 mjacob icbp->icb_retry_count = fcp->isp_retry_count;
1567 1.111 mjacob icbp->icb_hardaddr = fcp->isp_loopid;
1568 1.111 mjacob ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
1569 1.114 mjacob if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
1570 1.111 mjacob icbp->icb_hardaddr = 0;
1571 1.111 mjacob ownloopid = 0;
1572 1.111 mjacob }
1573 1.111 mjacob
1574 1.111 mjacob /*
1575 1.111 mjacob * Our life seems so much better with 2200s and later with
1576 1.111 mjacob * the latest f/w if we set Hard Address.
1577 1.111 mjacob */
1578 1.111 mjacob if (ownloopid || ISP_FW_NEWER_THAN(isp, 2, 2, 5)) {
1579 1.111 mjacob icbp->icb_fwoptions |= ICBOPT_HARD_ADDRESS;
1580 1.111 mjacob }
1581 1.111 mjacob
1582 1.58 mjacob /*
1583 1.58 mjacob * Right now we just set extended options to prefer point-to-point
1584 1.58 mjacob * over loop based upon some soft config options.
1585 1.117 mjacob *
1586 1.79 mjacob * NB: for the 2300, ICBOPT_EXTENDED is required.
1587 1.58 mjacob */
1588 1.87 mjacob if (IS_2200(isp) || IS_23XX(isp)) {
1589 1.49 mjacob icbp->icb_fwoptions |= ICBOPT_EXTENDED;
1590 1.49 mjacob /*
1591 1.49 mjacob * Prefer or force Point-To-Point instead Loop?
1592 1.49 mjacob */
1593 1.117 mjacob switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
1594 1.63 mjacob case ISP_CFG_NPORT:
1595 1.81 mjacob icbp->icb_xfwoptions |= ICBXOPT_PTP_2_LOOP;
1596 1.63 mjacob break;
1597 1.63 mjacob case ISP_CFG_NPORT_ONLY:
1598 1.81 mjacob icbp->icb_xfwoptions |= ICBXOPT_PTP_ONLY;
1599 1.63 mjacob break;
1600 1.63 mjacob case ISP_CFG_LPORT_ONLY:
1601 1.81 mjacob icbp->icb_xfwoptions |= ICBXOPT_LOOP_ONLY;
1602 1.63 mjacob break;
1603 1.63 mjacob default:
1604 1.81 mjacob icbp->icb_xfwoptions |= ICBXOPT_LOOP_2_PTP;
1605 1.63 mjacob break;
1606 1.63 mjacob }
1607 1.111 mjacob if (IS_2200(isp)) {
1608 1.114 mjacob /*
1609 1.114 mjacob * There seems to just be too much breakage here
1610 1.114 mjacob * with RIO and Fast Posting- it probably actually
1611 1.114 mjacob * works okay but this driver is messing it up.
1612 1.114 mjacob * This card is really ancient by now, so let's
1613 1.114 mjacob * just opt for safety and not use the feature.
1614 1.114 mjacob */
1615 1.114 mjacob #if 0
1616 1.111 mjacob if (ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
1617 1.111 mjacob icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;
1618 1.113 mjacob icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
1619 1.111 mjacob icbp->icb_racctimer = 4;
1620 1.111 mjacob icbp->icb_idelaytimer = 8;
1621 1.113 mjacob } else {
1622 1.113 mjacob icbp->icb_fwoptions |= ICBOPT_FAST_POST;
1623 1.111 mjacob }
1624 1.114 mjacob #else
1625 1.114 mjacob icbp->icb_xfwoptions &= ~ICBXOPT_RIO_16BIT;
1626 1.114 mjacob icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
1627 1.114 mjacob #endif
1628 1.111 mjacob } else {
1629 1.97 mjacob /*
1630 1.97 mjacob * QLogic recommends that FAST Posting be turned
1631 1.97 mjacob * off for 23XX cards and instead allow the HBA
1632 1.97 mjacob * to write response queue entries and interrupt
1633 1.97 mjacob * after a delay (ZIO).
1634 1.97 mjacob */
1635 1.111 mjacob icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
1636 1.117 mjacob if ((fcp->isp_xfwoptions & ICBXOPT_TIMER_MASK) == ICBXOPT_ZIO) {
1637 1.111 mjacob icbp->icb_xfwoptions |= ICBXOPT_ZIO;
1638 1.111 mjacob icbp->icb_idelaytimer = 10;
1639 1.111 mjacob }
1640 1.81 mjacob if (isp->isp_confopts & ISP_CFG_ONEGB) {
1641 1.81 mjacob icbp->icb_zfwoptions |= ICBZOPT_RATE_ONEGB;
1642 1.81 mjacob } else if (isp->isp_confopts & ISP_CFG_TWOGB) {
1643 1.81 mjacob icbp->icb_zfwoptions |= ICBZOPT_RATE_TWOGB;
1644 1.81 mjacob } else {
1645 1.81 mjacob icbp->icb_zfwoptions |= ICBZOPT_RATE_AUTO;
1646 1.81 mjacob }
1647 1.111 mjacob if (fcp->isp_zfwoptions & ICBZOPT_50_OHM) {
1648 1.111 mjacob icbp->icb_zfwoptions |= ICBZOPT_50_OHM;
1649 1.111 mjacob }
1650 1.79 mjacob }
1651 1.88 mjacob }
1652 1.88 mjacob
1653 1.79 mjacob
1654 1.97 mjacob /*
1655 1.111 mjacob * For 22XX > 2.1.26 && 23XX, set some options.
1656 1.97 mjacob */
1657 1.97 mjacob if (ISP_FW_NEWER_THAN(isp, 2, 26, 0)) {
1658 1.117 mjacob MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
1659 1.118 mjacob mbs.param[1] = IFCOPT1_DISF7SWTCH|IFCOPT1_LIPASYNC|IFCOPT1_LIPF8;
1660 1.79 mjacob mbs.param[2] = 0;
1661 1.79 mjacob mbs.param[3] = 0;
1662 1.118 mjacob if (ISP_FW_NEWER_THAN(isp, 3, 16, 0)) {
1663 1.118 mjacob mbs.param[1] |= IFCOPT1_EQFQASYNC|IFCOPT1_CTIO_RETRY;
1664 1.118 mjacob if (fcp->role & ISP_ROLE_TARGET) {
1665 1.118 mjacob mbs.param[3] = IFCOPT3_NOPRLI;
1666 1.118 mjacob }
1667 1.118 mjacob }
1668 1.111 mjacob isp_mboxcmd(isp, &mbs);
1669 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1670 1.111 mjacob return;
1671 1.111 mjacob }
1672 1.49 mjacob }
1673 1.111 mjacob icbp->icb_logintime = ICB_LOGIN_TOV;
1674 1.111 mjacob icbp->icb_lunetimeout = ICB_LUN_ENABLE_TOV;
1675 1.25 mjacob
1676 1.114 mjacob if (fcp->isp_wwnn && fcp->isp_wwpn && (fcp->isp_wwnn >> 60) != 2) {
1677 1.72 mjacob icbp->icb_fwoptions |= ICBOPT_BOTH_WWNS;
1678 1.114 mjacob MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
1679 1.114 mjacob MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
1680 1.62 mjacob isp_prt(isp, ISP_LOGDEBUG1,
1681 1.62 mjacob "Setting ICB Node 0x%08x%08x Port 0x%08x%08x",
1682 1.114 mjacob ((uint32_t) (fcp->isp_wwnn >> 32)),
1683 1.114 mjacob ((uint32_t) (fcp->isp_wwnn)),
1684 1.114 mjacob ((uint32_t) (fcp->isp_wwpn >> 32)),
1685 1.114 mjacob ((uint32_t) (fcp->isp_wwpn)));
1686 1.114 mjacob } else if (fcp->isp_wwpn) {
1687 1.111 mjacob icbp->icb_fwoptions &= ~ICBOPT_BOTH_WWNS;
1688 1.114 mjacob MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
1689 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG1,
1690 1.111 mjacob "Setting ICB Port 0x%08x%08x",
1691 1.114 mjacob ((uint32_t) (fcp->isp_wwpn >> 32)),
1692 1.114 mjacob ((uint32_t) (fcp->isp_wwpn)));
1693 1.35 mjacob } else {
1694 1.111 mjacob isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
1695 1.111 mjacob return;
1696 1.28 mjacob }
1697 1.57 mjacob icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
1698 1.111 mjacob if (icbp->icb_rqstqlen < 1) {
1699 1.111 mjacob isp_prt(isp, ISP_LOGERR, "bad request queue length");
1700 1.111 mjacob }
1701 1.57 mjacob icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
1702 1.111 mjacob if (icbp->icb_rsltqlen < 1) {
1703 1.111 mjacob isp_prt(isp, ISP_LOGERR, "bad result queue length");
1704 1.111 mjacob }
1705 1.79 mjacob icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
1706 1.79 mjacob icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
1707 1.79 mjacob icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
1708 1.79 mjacob icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
1709 1.79 mjacob icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
1710 1.79 mjacob icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
1711 1.79 mjacob icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
1712 1.79 mjacob icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
1713 1.111 mjacob
1714 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, 0)) {
1715 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
1716 1.115 mjacob return;
1717 1.115 mjacob }
1718 1.97 mjacob isp_prt(isp, ISP_LOGDEBUG0,
1719 1.97 mjacob "isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x",
1720 1.97 mjacob icbp->icb_fwoptions, icbp->icb_xfwoptions, icbp->icb_zfwoptions);
1721 1.88 mjacob
1722 1.86 mjacob isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch);
1723 1.70 mjacob
1724 1.38 mjacob /*
1725 1.70 mjacob * Init the firmware
1726 1.38 mjacob */
1727 1.117 mjacob MBSINIT(&mbs, MBOX_INIT_FIRMWARE, MBLOGALL, 30000000);
1728 1.79 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1729 1.79 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1730 1.79 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1731 1.79 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1732 1.111 mjacob mbs.logval = MBLOGALL;
1733 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %p (%08x%08x)",
1734 1.111 mjacob fcp->isp_scratch, (uint32_t) ((uint64_t)fcp->isp_scdma >> 32),
1735 1.111 mjacob (uint32_t) fcp->isp_scdma);
1736 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp));
1737 1.111 mjacob isp_mboxcmd(isp, &mbs);
1738 1.114 mjacob FC_SCRATCH_RELEASE(isp, 0);
1739 1.57 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1740 1.111 mjacob isp_print_bytes(isp, "isp_fibre_init", sizeof (*icbp), icbp);
1741 1.57 mjacob return;
1742 1.10 mjacob }
1743 1.111 mjacob isp->isp_reqidx = 0;
1744 1.111 mjacob isp->isp_reqodx = 0;
1745 1.10 mjacob isp->isp_residx = 0;
1746 1.33 mjacob
1747 1.33 mjacob /*
1748 1.33 mjacob * Whatever happens, we're now committed to being here.
1749 1.33 mjacob */
1750 1.33 mjacob isp->isp_state = ISP_INITSTATE;
1751 1.33 mjacob }
1752 1.33 mjacob
1753 1.111 mjacob static void
1754 1.111 mjacob isp_fibre_init_2400(ispsoftc_t *isp)
1755 1.70 mjacob {
1756 1.111 mjacob fcparam *fcp;
1757 1.111 mjacob isp_icb_2400_t local, *icbp = &local;
1758 1.70 mjacob mbreg_t mbs;
1759 1.117 mjacob int chan;
1760 1.114 mjacob
1761 1.114 mjacob /*
1762 1.114 mjacob * Check to see whether all channels have *some* kind of role
1763 1.114 mjacob */
1764 1.114 mjacob for (chan = 0; chan < isp->isp_nchan; chan++) {
1765 1.114 mjacob fcp = FCPARAM(isp, chan);
1766 1.114 mjacob if (fcp->role != ISP_ROLE_NONE) {
1767 1.114 mjacob break;
1768 1.114 mjacob }
1769 1.114 mjacob }
1770 1.114 mjacob if (chan == isp->isp_nchan) {
1771 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "all %d channels with role 'none'", chan);
1772 1.114 mjacob isp->isp_state = ISP_INITSTATE;
1773 1.114 mjacob return;
1774 1.114 mjacob }
1775 1.114 mjacob
1776 1.114 mjacob /*
1777 1.114 mjacob * Start with channel 0.
1778 1.114 mjacob */
1779 1.114 mjacob fcp = FCPARAM(isp, 0);
1780 1.111 mjacob
1781 1.111 mjacob /*
1782 1.111 mjacob * Turn on LIP F8 async event (1)
1783 1.111 mjacob */
1784 1.117 mjacob MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
1785 1.111 mjacob mbs.param[1] = 1;
1786 1.111 mjacob isp_mboxcmd(isp, &mbs);
1787 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1788 1.111 mjacob return;
1789 1.111 mjacob }
1790 1.111 mjacob
1791 1.117 mjacob ISP_MEMZERO(icbp, sizeof (*icbp));
1792 1.114 mjacob icbp->icb_fwoptions1 = fcp->isp_fwoptions;
1793 1.114 mjacob if (fcp->role & ISP_ROLE_TARGET) {
1794 1.114 mjacob icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
1795 1.111 mjacob } else {
1796 1.114 mjacob icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
1797 1.111 mjacob }
1798 1.111 mjacob
1799 1.114 mjacob if (fcp->role & ISP_ROLE_INITIATOR) {
1800 1.114 mjacob icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
1801 1.111 mjacob } else {
1802 1.114 mjacob icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
1803 1.111 mjacob }
1804 1.111 mjacob
1805 1.111 mjacob icbp->icb_version = ICB_VERSION1;
1806 1.114 mjacob icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
1807 1.117 mjacob if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
1808 1.117 mjacob isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
1809 1.111 mjacob icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
1810 1.111 mjacob }
1811 1.111 mjacob
1812 1.114 mjacob icbp->icb_execthrottle = DEFAULT_EXEC_THROTTLE(isp);
1813 1.111 mjacob if (icbp->icb_execthrottle < 1) {
1814 1.117 mjacob isp_prt(isp, ISP_LOGERR, "bad execution throttle of %d- using %d", DEFAULT_EXEC_THROTTLE(isp), ICB_DFLT_THROTTLE);
1815 1.111 mjacob icbp->icb_execthrottle = ICB_DFLT_THROTTLE;
1816 1.111 mjacob }
1817 1.70 mjacob
1818 1.114 mjacob if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) {
1819 1.111 mjacob /*
1820 1.111 mjacob * Get current resource count
1821 1.111 mjacob */
1822 1.117 mjacob MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
1823 1.111 mjacob mbs.obits = 0x4cf;
1824 1.111 mjacob isp_mboxcmd(isp, &mbs);
1825 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1826 1.111 mjacob return;
1827 1.111 mjacob }
1828 1.111 mjacob icbp->icb_xchgcnt = mbs.param[3];
1829 1.111 mjacob }
1830 1.111 mjacob
1831 1.111 mjacob
1832 1.111 mjacob icbp->icb_hardaddr = fcp->isp_loopid;
1833 1.114 mjacob if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
1834 1.111 mjacob icbp->icb_hardaddr = 0;
1835 1.111 mjacob }
1836 1.114 mjacob
1837 1.114 mjacob /*
1838 1.114 mjacob * Force this on.
1839 1.114 mjacob */
1840 1.114 mjacob icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
1841 1.111 mjacob
1842 1.111 mjacob icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
1843 1.117 mjacob switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
1844 1.114 mjacob #if 0
1845 1.111 mjacob case ISP_CFG_NPORT:
1846 1.114 mjacob /*
1847 1.114 mjacob * XXX: This causes the f/w to crash.
1848 1.114 mjacob */
1849 1.111 mjacob icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
1850 1.111 mjacob icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_2_LOOP;
1851 1.111 mjacob break;
1852 1.114 mjacob #endif
1853 1.111 mjacob case ISP_CFG_NPORT_ONLY:
1854 1.111 mjacob icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
1855 1.111 mjacob icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
1856 1.111 mjacob break;
1857 1.111 mjacob case ISP_CFG_LPORT_ONLY:
1858 1.111 mjacob icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
1859 1.111 mjacob icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY;
1860 1.111 mjacob break;
1861 1.111 mjacob default:
1862 1.111 mjacob icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
1863 1.111 mjacob icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
1864 1.111 mjacob break;
1865 1.111 mjacob }
1866 1.111 mjacob
1867 1.114 mjacob /* force this on for now */
1868 1.114 mjacob icbp->icb_fwoptions2 |= ICB2400_OPT2_ZIO;
1869 1.114 mjacob
1870 1.111 mjacob switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
1871 1.111 mjacob case ICB2400_OPT2_ZIO:
1872 1.111 mjacob case ICB2400_OPT2_ZIO1:
1873 1.111 mjacob icbp->icb_idelaytimer = 0;
1874 1.111 mjacob break;
1875 1.111 mjacob case 0:
1876 1.111 mjacob break;
1877 1.111 mjacob default:
1878 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
1879 1.111 mjacob icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
1880 1.111 mjacob break;
1881 1.111 mjacob }
1882 1.111 mjacob
1883 1.114 mjacob /*
1884 1.114 mjacob * We don't support FCTAPE, so clear it.
1885 1.114 mjacob */
1886 1.114 mjacob icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
1887 1.114 mjacob
1888 1.111 mjacob icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
1889 1.111 mjacob icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_AUTO;
1890 1.111 mjacob if (isp->isp_confopts & ISP_CFG_ONEGB) {
1891 1.111 mjacob icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_ONEGB;
1892 1.111 mjacob } else if (isp->isp_confopts & ISP_CFG_TWOGB) {
1893 1.111 mjacob icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_TWOGB;
1894 1.111 mjacob } else if (isp->isp_confopts & ISP_CFG_FOURGB) {
1895 1.111 mjacob icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_FOURGB;
1896 1.111 mjacob } else {
1897 1.111 mjacob icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
1898 1.111 mjacob }
1899 1.111 mjacob
1900 1.111 mjacob if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
1901 1.111 mjacob icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
1902 1.111 mjacob }
1903 1.111 mjacob icbp->icb_logintime = ICB_LOGIN_TOV;
1904 1.111 mjacob
1905 1.114 mjacob if (fcp->isp_wwnn && fcp->isp_wwpn && (fcp->isp_wwnn >> 60) != 2) {
1906 1.111 mjacob icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
1907 1.114 mjacob MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
1908 1.114 mjacob MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
1909 1.117 mjacob 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)),
1910 1.117 mjacob ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
1911 1.114 mjacob } else if (fcp->isp_wwpn) {
1912 1.111 mjacob icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
1913 1.114 mjacob MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
1914 1.117 mjacob 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)));
1915 1.111 mjacob } else {
1916 1.111 mjacob isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
1917 1.111 mjacob return;
1918 1.111 mjacob }
1919 1.111 mjacob icbp->icb_retry_count = fcp->isp_retry_count;
1920 1.111 mjacob
1921 1.111 mjacob icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
1922 1.111 mjacob if (icbp->icb_rqstqlen < 8) {
1923 1.117 mjacob isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen);
1924 1.111 mjacob return;
1925 1.111 mjacob }
1926 1.111 mjacob icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
1927 1.111 mjacob if (icbp->icb_rsltqlen < 8) {
1928 1.111 mjacob isp_prt(isp, ISP_LOGERR, "bad result queue length %d",
1929 1.111 mjacob icbp->icb_rsltqlen);
1930 1.111 mjacob return;
1931 1.111 mjacob }
1932 1.111 mjacob icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
1933 1.111 mjacob icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
1934 1.111 mjacob icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
1935 1.111 mjacob icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
1936 1.111 mjacob
1937 1.111 mjacob icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
1938 1.111 mjacob icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
1939 1.111 mjacob icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
1940 1.111 mjacob icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
1941 1.111 mjacob
1942 1.111 mjacob #ifdef ISP_TARGET_MODE
1943 1.114 mjacob /* unconditionally set up the ATIO queue if we support target mode */
1944 1.114 mjacob icbp->icb_atioqlen = RESULT_QUEUE_LEN(isp);
1945 1.114 mjacob if (icbp->icb_atioqlen < 8) {
1946 1.117 mjacob isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen);
1947 1.114 mjacob return;
1948 1.111 mjacob }
1949 1.114 mjacob icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
1950 1.114 mjacob icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
1951 1.114 mjacob icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
1952 1.114 mjacob icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
1953 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "isp_fibre_init_2400: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
1954 1.114 mjacob DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
1955 1.111 mjacob #endif
1956 1.111 mjacob
1957 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "isp_fibre_init_2400: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3);
1958 1.111 mjacob
1959 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "isp_fibre_init_2400: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x", DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma),
1960 1.117 mjacob DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
1961 1.111 mjacob DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
1962 1.111 mjacob
1963 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
1964 1.117 mjacob isp_print_bytes(isp, "isp_fibre_init_2400", sizeof (*icbp), icbp);
1965 1.111 mjacob }
1966 1.114 mjacob
1967 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, 0)) {
1968 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
1969 1.115 mjacob return;
1970 1.115 mjacob }
1971 1.117 mjacob ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
1972 1.111 mjacob isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
1973 1.111 mjacob
1974 1.114 mjacob /*
1975 1.114 mjacob * Now fill in information about any additional channels
1976 1.114 mjacob */
1977 1.117 mjacob if (isp->isp_nchan > 1) {
1978 1.114 mjacob isp_icb_2400_vpinfo_t vpinfo, *vdst;
1979 1.114 mjacob vp_port_info_t pi, *pdst;
1980 1.114 mjacob size_t amt = 0;
1981 1.114 mjacob uint8_t *off;
1982 1.114 mjacob
1983 1.114 mjacob vpinfo.vp_count = isp->isp_nchan - 1;
1984 1.114 mjacob vpinfo.vp_global_options = 0;
1985 1.114 mjacob off = fcp->isp_scratch;
1986 1.114 mjacob off += ICB2400_VPINFO_OFF;
1987 1.114 mjacob vdst = (isp_icb_2400_vpinfo_t *) off;
1988 1.114 mjacob isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst);
1989 1.114 mjacob amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t);
1990 1.114 mjacob for (chan = 1; chan < isp->isp_nchan; chan++) {
1991 1.114 mjacob fcparam *fcp2;
1992 1.114 mjacob
1993 1.117 mjacob ISP_MEMZERO(&pi, sizeof (pi));
1994 1.114 mjacob fcp2 = FCPARAM(isp, chan);
1995 1.114 mjacob if (fcp2->role != ISP_ROLE_NONE) {
1996 1.114 mjacob pi.vp_port_options = ICB2400_VPOPT_ENABLED;
1997 1.114 mjacob if (fcp2->role & ISP_ROLE_INITIATOR) {
1998 1.117 mjacob pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
1999 1.114 mjacob }
2000 1.114 mjacob if ((fcp2->role & ISP_ROLE_TARGET) == 0) {
2001 1.117 mjacob pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE;
2002 1.114 mjacob }
2003 1.117 mjacob MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn);
2004 1.117 mjacob MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn);
2005 1.114 mjacob }
2006 1.114 mjacob off = fcp->isp_scratch;
2007 1.114 mjacob off += ICB2400_VPINFO_PORT_OFF(chan);
2008 1.114 mjacob pdst = (vp_port_info_t *) off;
2009 1.114 mjacob isp_put_vp_port_info(isp, &pi, pdst);
2010 1.114 mjacob amt += ICB2400_VPOPT_WRITE_SIZE;
2011 1.114 mjacob }
2012 1.114 mjacob }
2013 1.111 mjacob
2014 1.111 mjacob /*
2015 1.111 mjacob * Init the firmware
2016 1.111 mjacob */
2017 1.117 mjacob MBSINIT(&mbs, 0, MBLOGALL, 30000000);
2018 1.117 mjacob if (isp->isp_nchan > 1) {
2019 1.114 mjacob mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
2020 1.114 mjacob } else {
2021 1.114 mjacob mbs.param[0] = MBOX_INIT_FIRMWARE;
2022 1.114 mjacob }
2023 1.79 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma);
2024 1.79 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma);
2025 1.111 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma);
2026 1.111 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma);
2027 1.117 mjacob 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));
2028 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp));
2029 1.111 mjacob isp_mboxcmd(isp, &mbs);
2030 1.114 mjacob FC_SCRATCH_RELEASE(isp, 0);
2031 1.114 mjacob
2032 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
2033 1.111 mjacob return;
2034 1.111 mjacob }
2035 1.111 mjacob isp->isp_reqidx = 0;
2036 1.111 mjacob isp->isp_reqodx = 0;
2037 1.111 mjacob isp->isp_residx = 0;
2038 1.111 mjacob
2039 1.70 mjacob /*
2040 1.111 mjacob * Whatever happens, we're now committed to being here.
2041 1.70 mjacob */
2042 1.111 mjacob isp->isp_state = ISP_INITSTATE;
2043 1.70 mjacob }
2044 1.70 mjacob
2045 1.33 mjacob static void
2046 1.114 mjacob isp_mark_portdb(ispsoftc_t *isp, int chan, int disposition)
2047 1.33 mjacob {
2048 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
2049 1.37 mjacob int i;
2050 1.111 mjacob
2051 1.114 mjacob if (chan < 0 || chan >= isp->isp_nchan) {
2052 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "isp_mark_portdb: bad channel %d", chan);
2053 1.114 mjacob return;
2054 1.114 mjacob }
2055 1.37 mjacob for (i = 0; i < MAX_FC_TARG; i++) {
2056 1.114 mjacob if (fcp->portdb[i].target_mode) {
2057 1.114 mjacob if (disposition < 0) {
2058 1.117 mjacob isp_prt(isp, ISP_LOGTINFO, "isp_mark_portdb: Chan %d zeroing handle 0x" "%04x port 0x%06x", chan,
2059 1.117 mjacob fcp->portdb[i].handle, fcp->portdb[i].portid);
2060 1.117 mjacob ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
2061 1.114 mjacob }
2062 1.114 mjacob continue;
2063 1.114 mjacob }
2064 1.114 mjacob if (disposition == 0) {
2065 1.117 mjacob ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
2066 1.111 mjacob } else {
2067 1.111 mjacob switch (fcp->portdb[i].state) {
2068 1.111 mjacob case FC_PORTDB_STATE_CHANGED:
2069 1.111 mjacob case FC_PORTDB_STATE_PENDING_VALID:
2070 1.111 mjacob case FC_PORTDB_STATE_VALID:
2071 1.111 mjacob case FC_PORTDB_STATE_PROBATIONAL:
2072 1.117 mjacob fcp->portdb[i].state = FC_PORTDB_STATE_PROBATIONAL;
2073 1.111 mjacob break;
2074 1.111 mjacob case FC_PORTDB_STATE_ZOMBIE:
2075 1.111 mjacob break;
2076 1.111 mjacob case FC_PORTDB_STATE_NIL:
2077 1.111 mjacob default:
2078 1.117 mjacob ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
2079 1.114 mjacob fcp->portdb[i].state = FC_PORTDB_STATE_NIL;
2080 1.111 mjacob break;
2081 1.111 mjacob }
2082 1.111 mjacob }
2083 1.111 mjacob }
2084 1.111 mjacob }
2085 1.111 mjacob
2086 1.111 mjacob /*
2087 1.111 mjacob * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
2088 1.111 mjacob * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
2089 1.111 mjacob */
2090 1.111 mjacob static int
2091 1.118 mjacob isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags, int gs)
2092 1.111 mjacob {
2093 1.111 mjacob mbreg_t mbs;
2094 1.111 mjacob uint8_t q[QENTRY_LEN];
2095 1.111 mjacob isp_plogx_t *plp;
2096 1.114 mjacob fcparam *fcp;
2097 1.111 mjacob uint8_t *scp;
2098 1.111 mjacob uint32_t sst, parm1;
2099 1.114 mjacob int rval, lev;
2100 1.114 mjacob const char *msg;
2101 1.114 mjacob char buf[64];
2102 1.111 mjacob
2103 1.111 mjacob if (!IS_24XX(isp)) {
2104 1.111 mjacob int action = flags & PLOGX_FLG_CMD_MASK;
2105 1.111 mjacob if (action == PLOGX_FLG_CMD_PLOGI) {
2106 1.111 mjacob return (isp_port_login(isp, handle, portid));
2107 1.111 mjacob } else if (action == PLOGX_FLG_CMD_LOGO) {
2108 1.111 mjacob return (isp_port_logout(isp, handle, portid));
2109 1.111 mjacob } else {
2110 1.111 mjacob return (MBOX_INVALID_COMMAND);
2111 1.111 mjacob }
2112 1.111 mjacob }
2113 1.111 mjacob
2114 1.117 mjacob ISP_MEMZERO(q, QENTRY_LEN);
2115 1.111 mjacob plp = (isp_plogx_t *) q;
2116 1.111 mjacob plp->plogx_header.rqs_entry_count = 1;
2117 1.111 mjacob plp->plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
2118 1.111 mjacob plp->plogx_handle = 0xffffffff;
2119 1.111 mjacob plp->plogx_nphdl = handle;
2120 1.114 mjacob plp->plogx_vphdl = chan;
2121 1.111 mjacob plp->plogx_portlo = portid;
2122 1.111 mjacob plp->plogx_rspsz_porthi = (portid >> 16) & 0xff;
2123 1.111 mjacob plp->plogx_flags = flags;
2124 1.111 mjacob
2125 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
2126 1.111 mjacob isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, plp);
2127 1.111 mjacob }
2128 1.111 mjacob
2129 1.111 mjacob if (gs == 0) {
2130 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2131 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
2132 1.115 mjacob return (-1);
2133 1.115 mjacob }
2134 1.111 mjacob }
2135 1.114 mjacob fcp = FCPARAM(isp, chan);
2136 1.114 mjacob scp = fcp->isp_scratch;
2137 1.111 mjacob isp_put_plogx(isp, plp, (isp_plogx_t *) scp);
2138 1.111 mjacob
2139 1.117 mjacob MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 500000);
2140 1.111 mjacob mbs.param[1] = QENTRY_LEN;
2141 1.114 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma);
2142 1.114 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma);
2143 1.114 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma);
2144 1.114 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma);
2145 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN);
2146 1.111 mjacob isp_mboxcmd(isp, &mbs);
2147 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
2148 1.111 mjacob rval = mbs.param[0];
2149 1.111 mjacob goto out;
2150 1.111 mjacob }
2151 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN);
2152 1.111 mjacob scp += QENTRY_LEN;
2153 1.111 mjacob isp_get_plogx(isp, (isp_plogx_t *) scp, plp);
2154 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
2155 1.111 mjacob isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, plp);
2156 1.111 mjacob }
2157 1.111 mjacob
2158 1.111 mjacob if (plp->plogx_status == PLOGX_STATUS_OK) {
2159 1.111 mjacob rval = 0;
2160 1.111 mjacob goto out;
2161 1.111 mjacob } else if (plp->plogx_status != PLOGX_STATUS_IOCBERR) {
2162 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
2163 1.114 mjacob "status 0x%x on port login IOCB chanel %d",
2164 1.114 mjacob plp->plogx_status, chan);
2165 1.111 mjacob rval = -1;
2166 1.111 mjacob goto out;
2167 1.111 mjacob }
2168 1.111 mjacob
2169 1.111 mjacob sst = plp->plogx_ioparm[0].lo16 | (plp->plogx_ioparm[0].hi16 << 16);
2170 1.111 mjacob parm1 = plp->plogx_ioparm[1].lo16 | (plp->plogx_ioparm[1].hi16 << 16);
2171 1.111 mjacob
2172 1.111 mjacob rval = -1;
2173 1.114 mjacob lev = ISP_LOGERR;
2174 1.114 mjacob msg = NULL;
2175 1.111 mjacob
2176 1.111 mjacob switch (sst) {
2177 1.111 mjacob case PLOGX_IOCBERR_NOLINK:
2178 1.114 mjacob msg = "no link";
2179 1.111 mjacob break;
2180 1.111 mjacob case PLOGX_IOCBERR_NOIOCB:
2181 1.114 mjacob msg = "no IOCB buffer";
2182 1.111 mjacob break;
2183 1.111 mjacob case PLOGX_IOCBERR_NOXGHG:
2184 1.114 mjacob msg = "no Exchange Control Block";
2185 1.111 mjacob break;
2186 1.111 mjacob case PLOGX_IOCBERR_FAILED:
2187 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf),
2188 1.114 mjacob "reason 0x%x (last LOGIN state 0x%x)",
2189 1.114 mjacob parm1 & 0xff, (parm1 >> 8) & 0xff);
2190 1.114 mjacob msg = buf;
2191 1.111 mjacob break;
2192 1.111 mjacob case PLOGX_IOCBERR_NOFABRIC:
2193 1.114 mjacob msg = "no fabric";
2194 1.111 mjacob break;
2195 1.111 mjacob case PLOGX_IOCBERR_NOTREADY:
2196 1.114 mjacob msg = "firmware not ready";
2197 1.111 mjacob break;
2198 1.111 mjacob case PLOGX_IOCBERR_NOLOGIN:
2199 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)",
2200 1.111 mjacob parm1);
2201 1.114 mjacob msg = buf;
2202 1.111 mjacob rval = MBOX_NOT_LOGGED_IN;
2203 1.111 mjacob break;
2204 1.111 mjacob case PLOGX_IOCBERR_REJECT:
2205 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
2206 1.114 mjacob msg = buf;
2207 1.111 mjacob break;
2208 1.111 mjacob case PLOGX_IOCBERR_NOPCB:
2209 1.114 mjacob msg = "no PCB allocated";
2210 1.111 mjacob break;
2211 1.111 mjacob case PLOGX_IOCBERR_EINVAL:
2212 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x",
2213 1.114 mjacob parm1);
2214 1.114 mjacob msg = buf;
2215 1.111 mjacob break;
2216 1.111 mjacob case PLOGX_IOCBERR_PORTUSED:
2217 1.117 mjacob lev = ISP_LOGSANCFG|ISP_LOGDEBUG0;
2218 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf),
2219 1.114 mjacob "already logged in with N-Port handle 0x%x", parm1);
2220 1.114 mjacob msg = buf;
2221 1.114 mjacob rval = MBOX_PORT_ID_USED | (parm1 << 16);
2222 1.111 mjacob break;
2223 1.111 mjacob case PLOGX_IOCBERR_HNDLUSED:
2224 1.114 mjacob lev = ISP_LOGSANCFG|ISP_LOGDEBUG0;
2225 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf),
2226 1.114 mjacob "handle already used for PortID 0x%06x", parm1);
2227 1.114 mjacob msg = buf;
2228 1.111 mjacob rval = MBOX_LOOP_ID_USED;
2229 1.111 mjacob break;
2230 1.111 mjacob case PLOGX_IOCBERR_NOHANDLE:
2231 1.114 mjacob msg = "no handle allocated";
2232 1.111 mjacob break;
2233 1.111 mjacob case PLOGX_IOCBERR_NOFLOGI:
2234 1.114 mjacob msg = "no FLOGI_ACC";
2235 1.111 mjacob break;
2236 1.111 mjacob default:
2237 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x",
2238 1.114 mjacob plp->plogx_status, flags);
2239 1.114 mjacob msg = buf;
2240 1.111 mjacob break;
2241 1.111 mjacob }
2242 1.114 mjacob if (msg) {
2243 1.114 mjacob isp_prt(isp, ISP_LOGERR,
2244 1.114 mjacob "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
2245 1.114 mjacob chan, portid, handle, msg);
2246 1.114 mjacob }
2247 1.111 mjacob out:
2248 1.111 mjacob if (gs == 0) {
2249 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
2250 1.111 mjacob }
2251 1.111 mjacob return (rval);
2252 1.111 mjacob }
2253 1.111 mjacob
2254 1.111 mjacob static int
2255 1.111 mjacob isp_port_login(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
2256 1.111 mjacob {
2257 1.111 mjacob mbreg_t mbs;
2258 1.111 mjacob
2259 1.117 mjacob MBSINIT(&mbs, MBOX_FABRIC_LOGIN, MBLOGNONE, 500000);
2260 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
2261 1.111 mjacob mbs.param[1] = handle;
2262 1.111 mjacob mbs.ibits = (1 << 10);
2263 1.111 mjacob } else {
2264 1.111 mjacob mbs.param[1] = handle << 8;
2265 1.111 mjacob }
2266 1.111 mjacob mbs.param[2] = portid >> 16;
2267 1.111 mjacob mbs.param[3] = portid;
2268 1.111 mjacob mbs.logval = MBLOGNONE;
2269 1.111 mjacob mbs.timeout = 500000;
2270 1.111 mjacob isp_mboxcmd(isp, &mbs);
2271 1.111 mjacob
2272 1.111 mjacob switch (mbs.param[0]) {
2273 1.111 mjacob case MBOX_PORT_ID_USED:
2274 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0,
2275 1.115 mjacob "isp_port_login: portid 0x%06x already logged in as %u",
2276 1.111 mjacob portid, mbs.param[1]);
2277 1.111 mjacob return (MBOX_PORT_ID_USED | (mbs.param[1] << 16));
2278 1.111 mjacob
2279 1.111 mjacob case MBOX_LOOP_ID_USED:
2280 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0,
2281 1.117 mjacob "isp_port_login: handle 0x%04x in use for port id 0x%02xXXXX",
2282 1.111 mjacob handle, mbs.param[1] & 0xff);
2283 1.111 mjacob return (MBOX_LOOP_ID_USED);
2284 1.111 mjacob
2285 1.111 mjacob case MBOX_COMMAND_COMPLETE:
2286 1.111 mjacob return (0);
2287 1.111 mjacob
2288 1.111 mjacob case MBOX_COMMAND_ERROR:
2289 1.111 mjacob isp_prt(isp, ISP_LOGINFO,
2290 1.115 mjacob "isp_port_login: error 0x%x in PLOGI to port 0x%06x",
2291 1.111 mjacob mbs.param[1], portid);
2292 1.111 mjacob return (MBOX_COMMAND_ERROR);
2293 1.111 mjacob
2294 1.111 mjacob case MBOX_ALL_IDS_USED:
2295 1.111 mjacob isp_prt(isp, ISP_LOGINFO,
2296 1.115 mjacob "isp_port_login: all IDs used for fabric login");
2297 1.111 mjacob return (MBOX_ALL_IDS_USED);
2298 1.111 mjacob
2299 1.111 mjacob default:
2300 1.111 mjacob isp_prt(isp, ISP_LOGINFO,
2301 1.115 mjacob "isp_port_login: error 0x%x on port login of 0x%06x@0x%0x",
2302 1.111 mjacob mbs.param[0], portid, handle);
2303 1.111 mjacob return (mbs.param[0]);
2304 1.111 mjacob }
2305 1.111 mjacob }
2306 1.111 mjacob
2307 1.111 mjacob static int
2308 1.111 mjacob isp_port_logout(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
2309 1.111 mjacob {
2310 1.111 mjacob mbreg_t mbs;
2311 1.111 mjacob
2312 1.117 mjacob MBSINIT(&mbs, MBOX_FABRIC_LOGOUT, MBLOGNONE, 500000);
2313 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
2314 1.111 mjacob mbs.param[1] = handle;
2315 1.111 mjacob mbs.ibits = (1 << 10);
2316 1.111 mjacob } else {
2317 1.111 mjacob mbs.param[1] = handle << 8;
2318 1.33 mjacob }
2319 1.111 mjacob isp_mboxcmd(isp, &mbs);
2320 1.111 mjacob return (mbs.param[0] == MBOX_COMMAND_COMPLETE? 0 : mbs.param[0]);
2321 1.33 mjacob }
2322 1.33 mjacob
2323 1.33 mjacob static int
2324 1.114 mjacob isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock)
2325 1.33 mjacob {
2326 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
2327 1.33 mjacob mbreg_t mbs;
2328 1.111 mjacob union {
2329 1.111 mjacob isp_pdb_21xx_t fred;
2330 1.111 mjacob isp_pdb_24xx_t bill;
2331 1.111 mjacob } un;
2332 1.37 mjacob
2333 1.117 mjacob MBSINIT(&mbs, MBOX_GET_PORT_DB, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR, 250000);
2334 1.111 mjacob if (IS_24XX(isp)) {
2335 1.114 mjacob mbs.ibits = (1 << 9)|(1 << 10);
2336 1.111 mjacob mbs.param[1] = id;
2337 1.114 mjacob mbs.param[9] = chan;
2338 1.114 mjacob } else if (ISP_CAP_2KLOGIN(isp)) {
2339 1.111 mjacob mbs.param[1] = id;
2340 1.111 mjacob } else {
2341 1.111 mjacob mbs.param[1] = id << 8;
2342 1.111 mjacob }
2343 1.79 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma);
2344 1.79 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma);
2345 1.79 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma);
2346 1.79 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma);
2347 1.111 mjacob if (dolock) {
2348 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2349 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
2350 1.115 mjacob return (-1);
2351 1.115 mjacob }
2352 1.111 mjacob }
2353 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (un));
2354 1.111 mjacob isp_mboxcmd(isp, &mbs);
2355 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
2356 1.111 mjacob if (dolock) {
2357 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
2358 1.111 mjacob }
2359 1.114 mjacob return (mbs.param[0]);
2360 1.111 mjacob }
2361 1.111 mjacob if (IS_24XX(isp)) {
2362 1.111 mjacob isp_get_pdb_24xx(isp, fcp->isp_scratch, &un.bill);
2363 1.111 mjacob pdb->handle = un.bill.pdb_handle;
2364 1.111 mjacob pdb->s3_role = un.bill.pdb_prli_svc3;
2365 1.111 mjacob pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
2366 1.117 mjacob ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
2367 1.117 mjacob ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
2368 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2369 1.114 mjacob "Chan %d Port 0x%06x flags 0x%x curstate %x",
2370 1.114 mjacob chan, pdb->portid, un.bill.pdb_flags,
2371 1.114 mjacob un.bill.pdb_curstate);
2372 1.117 mjacob if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE ||
2373 1.114 mjacob un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
2374 1.114 mjacob mbs.param[0] = MBOX_NOT_LOGGED_IN;
2375 1.114 mjacob if (dolock) {
2376 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
2377 1.114 mjacob }
2378 1.114 mjacob return (mbs.param[0]);
2379 1.114 mjacob }
2380 1.111 mjacob } else {
2381 1.111 mjacob isp_get_pdb_21xx(isp, fcp->isp_scratch, &un.fred);
2382 1.111 mjacob pdb->handle = un.fred.pdb_loopid;
2383 1.111 mjacob pdb->s3_role = un.fred.pdb_prli_svc3;
2384 1.111 mjacob pdb->portid = BITS2WORD(un.fred.pdb_portid_bits);
2385 1.117 mjacob ISP_MEMCPY(pdb->portname, un.fred.pdb_portname, 8);
2386 1.117 mjacob ISP_MEMCPY(pdb->nodename, un.fred.pdb_nodename, 8);
2387 1.111 mjacob }
2388 1.111 mjacob if (dolock) {
2389 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
2390 1.33 mjacob }
2391 1.111 mjacob return (0);
2392 1.33 mjacob }
2393 1.33 mjacob
2394 1.114 mjacob static void
2395 1.114 mjacob isp_dump_chip_portdb(ispsoftc_t *isp, int chan, int dolock)
2396 1.114 mjacob {
2397 1.114 mjacob isp_pdb_t pdb;
2398 1.114 mjacob int lim, loopid;
2399 1.114 mjacob
2400 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
2401 1.114 mjacob lim = NPH_MAX_2K;
2402 1.114 mjacob } else {
2403 1.114 mjacob lim = NPH_MAX;
2404 1.114 mjacob }
2405 1.114 mjacob for (loopid = 0; loopid != lim; loopid++) {
2406 1.114 mjacob if (isp_getpdb(isp, chan, loopid, &pdb, dolock)) {
2407 1.114 mjacob continue;
2408 1.114 mjacob }
2409 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGINFO, "Chan %d Loopid 0x%04x "
2410 1.114 mjacob "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
2411 1.114 mjacob chan, loopid, pdb.portid, pdb.portname[0], pdb.portname[1],
2412 1.114 mjacob pdb.portname[2], pdb.portname[3], pdb.portname[4],
2413 1.114 mjacob pdb.portname[5], pdb.portname[6], pdb.portname[7]);
2414 1.114 mjacob }
2415 1.114 mjacob }
2416 1.114 mjacob
2417 1.111 mjacob static uint64_t
2418 1.114 mjacob isp_get_wwn(ispsoftc_t *isp, int chan, int loopid, int nodename)
2419 1.37 mjacob {
2420 1.114 mjacob uint64_t wwn = INI_NONE;
2421 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
2422 1.37 mjacob mbreg_t mbs;
2423 1.37 mjacob
2424 1.114 mjacob if (fcp->isp_fwstate < FW_READY ||
2425 1.114 mjacob fcp->isp_loopstate < LOOP_PDB_RCVD) {
2426 1.114 mjacob return (wwn);
2427 1.114 mjacob }
2428 1.117 mjacob MBSINIT(&mbs, MBOX_GET_PORT_NAME, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR, 500000);
2429 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
2430 1.111 mjacob mbs.param[1] = loopid;
2431 1.111 mjacob mbs.ibits = (1 << 10);
2432 1.111 mjacob if (nodename) {
2433 1.111 mjacob mbs.param[10] = 1;
2434 1.111 mjacob }
2435 1.114 mjacob if (ISP_CAP_MULTI_ID(isp)) {
2436 1.114 mjacob mbs.ibits |= (1 << 9);
2437 1.114 mjacob mbs.param[9] = chan;
2438 1.114 mjacob }
2439 1.111 mjacob } else {
2440 1.111 mjacob mbs.param[1] = loopid << 8;
2441 1.111 mjacob if (nodename) {
2442 1.111 mjacob mbs.param[1] |= 1;
2443 1.111 mjacob }
2444 1.111 mjacob }
2445 1.111 mjacob isp_mboxcmd(isp, &mbs);
2446 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
2447 1.111 mjacob return (wwn);
2448 1.111 mjacob }
2449 1.111 mjacob if (IS_24XX(isp)) {
2450 1.111 mjacob wwn =
2451 1.114 mjacob (((uint64_t)(mbs.param[2] >> 8)) << 56) |
2452 1.111 mjacob (((uint64_t)(mbs.param[2] & 0xff)) << 48) |
2453 1.111 mjacob (((uint64_t)(mbs.param[3] >> 8)) << 40) |
2454 1.111 mjacob (((uint64_t)(mbs.param[3] & 0xff)) << 32) |
2455 1.111 mjacob (((uint64_t)(mbs.param[6] >> 8)) << 24) |
2456 1.111 mjacob (((uint64_t)(mbs.param[6] & 0xff)) << 16) |
2457 1.111 mjacob (((uint64_t)(mbs.param[7] >> 8)) << 8) |
2458 1.111 mjacob (((uint64_t)(mbs.param[7] & 0xff)));
2459 1.111 mjacob } else {
2460 1.37 mjacob wwn =
2461 1.111 mjacob (((uint64_t)(mbs.param[2] & 0xff)) << 56) |
2462 1.111 mjacob (((uint64_t)(mbs.param[2] >> 8)) << 48) |
2463 1.111 mjacob (((uint64_t)(mbs.param[3] & 0xff)) << 40) |
2464 1.111 mjacob (((uint64_t)(mbs.param[3] >> 8)) << 32) |
2465 1.111 mjacob (((uint64_t)(mbs.param[6] & 0xff)) << 24) |
2466 1.111 mjacob (((uint64_t)(mbs.param[6] >> 8)) << 16) |
2467 1.111 mjacob (((uint64_t)(mbs.param[7] & 0xff)) << 8) |
2468 1.111 mjacob (((uint64_t)(mbs.param[7] >> 8)));
2469 1.37 mjacob }
2470 1.37 mjacob return (wwn);
2471 1.37 mjacob }
2472 1.37 mjacob
2473 1.33 mjacob /*
2474 1.111 mjacob * Make sure we have good FC link.
2475 1.33 mjacob */
2476 1.33 mjacob
2477 1.33 mjacob static int
2478 1.114 mjacob isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
2479 1.33 mjacob {
2480 1.33 mjacob mbreg_t mbs;
2481 1.114 mjacob int count, check_for_fabric, r;
2482 1.111 mjacob uint8_t lwfs;
2483 1.111 mjacob int loopid;
2484 1.33 mjacob fcparam *fcp;
2485 1.111 mjacob fcportdb_t *lp;
2486 1.37 mjacob isp_pdb_t pdb;
2487 1.70 mjacob
2488 1.114 mjacob fcp = FCPARAM(isp, chan);
2489 1.10 mjacob
2490 1.117 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d FC Link Test Entry", chan);
2491 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
2492 1.57 mjacob
2493 1.57 mjacob /*
2494 1.33 mjacob * Wait up to N microseconds for F/W to go to a ready state.
2495 1.10 mjacob */
2496 1.23 mjacob lwfs = FW_CONFIG_WAIT;
2497 1.57 mjacob count = 0;
2498 1.57 mjacob while (count < usdelay) {
2499 1.111 mjacob uint64_t enano;
2500 1.111 mjacob uint32_t wrk;
2501 1.57 mjacob NANOTIME_T hra, hrb;
2502 1.57 mjacob
2503 1.57 mjacob GET_NANOTIME(&hra);
2504 1.114 mjacob isp_fw_state(isp, chan);
2505 1.23 mjacob if (lwfs != fcp->isp_fwstate) {
2506 1.117 mjacob isp_prt(isp, ISP_LOGCONFIG|ISP_LOGSANCFG, "Chan %d Firmware State <%s->%s>", chan, isp_fc_fw_statename((int)lwfs), isp_fc_fw_statename((int)fcp->isp_fwstate));
2507 1.23 mjacob lwfs = fcp->isp_fwstate;
2508 1.23 mjacob }
2509 1.23 mjacob if (fcp->isp_fwstate == FW_READY) {
2510 1.10 mjacob break;
2511 1.23 mjacob }
2512 1.57 mjacob GET_NANOTIME(&hrb);
2513 1.57 mjacob
2514 1.57 mjacob /*
2515 1.57 mjacob * Get the elapsed time in nanoseconds.
2516 1.57 mjacob * Always guaranteed to be non-zero.
2517 1.57 mjacob */
2518 1.57 mjacob enano = NANOTIME_SUB(&hrb, &hra);
2519 1.57 mjacob
2520 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG1, "usec%d: 0x%lx->0x%lx enano 0x%x%08x", count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb), (uint32_t)(enano >> 32), (uint32_t)(enano));
2521 1.66 mjacob
2522 1.57 mjacob /*
2523 1.57 mjacob * If the elapsed time is less than 1 millisecond,
2524 1.57 mjacob * delay a period of time up to that millisecond of
2525 1.57 mjacob * waiting.
2526 1.66 mjacob *
2527 1.57 mjacob * This peculiar code is an attempt to try and avoid
2528 1.111 mjacob * invoking uint64_t math support functions for some
2529 1.57 mjacob * platforms where linkage is a problem.
2530 1.57 mjacob */
2531 1.57 mjacob if (enano < (1000 * 1000)) {
2532 1.57 mjacob count += 1000;
2533 1.57 mjacob enano = (1000 * 1000) - enano;
2534 1.111 mjacob while (enano > (uint64_t) 4000000000U) {
2535 1.117 mjacob ISP_SLEEP(isp, 4000000);
2536 1.111 mjacob enano -= (uint64_t) 4000000000U;
2537 1.57 mjacob }
2538 1.57 mjacob wrk = enano;
2539 1.73 mjacob wrk /= 1000;
2540 1.117 mjacob ISP_SLEEP(isp, wrk);
2541 1.57 mjacob } else {
2542 1.111 mjacob while (enano > (uint64_t) 4000000000U) {
2543 1.57 mjacob count += 4000000;
2544 1.111 mjacob enano -= (uint64_t) 4000000000U;
2545 1.57 mjacob }
2546 1.57 mjacob wrk = enano;
2547 1.57 mjacob count += (wrk / 1000);
2548 1.57 mjacob }
2549 1.10 mjacob }
2550 1.10 mjacob
2551 1.114 mjacob
2552 1.114 mjacob
2553 1.10 mjacob /*
2554 1.33 mjacob * If we haven't gone to 'ready' state, return.
2555 1.33 mjacob */
2556 1.33 mjacob if (fcp->isp_fwstate != FW_READY) {
2557 1.117 mjacob isp_prt(isp, ISP_LOGSANCFG, "%s: chan %d not at FW_READY state", __func__, chan);
2558 1.33 mjacob return (-1);
2559 1.33 mjacob }
2560 1.34 mjacob
2561 1.33 mjacob /*
2562 1.111 mjacob * Get our Loop ID and Port ID.
2563 1.10 mjacob */
2564 1.117 mjacob MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
2565 1.114 mjacob if (ISP_CAP_MULTI_ID(isp)) {
2566 1.114 mjacob mbs.param[9] = chan;
2567 1.114 mjacob mbs.ibits = (1 << 9);
2568 1.114 mjacob mbs.obits = (1 << 7);
2569 1.114 mjacob }
2570 1.111 mjacob isp_mboxcmd(isp, &mbs);
2571 1.33 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
2572 1.33 mjacob return (-1);
2573 1.23 mjacob }
2574 1.111 mjacob
2575 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
2576 1.111 mjacob fcp->isp_loopid = mbs.param[1];
2577 1.111 mjacob } else {
2578 1.111 mjacob fcp->isp_loopid = mbs.param[1] & 0xff;
2579 1.111 mjacob }
2580 1.111 mjacob
2581 1.111 mjacob if (IS_2100(isp)) {
2582 1.111 mjacob fcp->isp_topo = TOPO_NL_PORT;
2583 1.111 mjacob } else {
2584 1.52 he int topo = (int) mbs.param[6];
2585 1.111 mjacob if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) {
2586 1.52 he topo = TOPO_PTP_STUB;
2587 1.111 mjacob }
2588 1.52 he fcp->isp_topo = topo;
2589 1.38 mjacob }
2590 1.111 mjacob fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
2591 1.70 mjacob
2592 1.98 mjacob if (IS_2100(isp)) {
2593 1.98 mjacob /*
2594 1.98 mjacob * Don't bother with fabric if we are using really old
2595 1.98 mjacob * 2100 firmware. It's just not worth it.
2596 1.98 mjacob */
2597 1.98 mjacob if (ISP_FW_NEWER_THAN(isp, 1, 15, 37)) {
2598 1.98 mjacob check_for_fabric = 1;
2599 1.98 mjacob } else {
2600 1.98 mjacob check_for_fabric = 0;
2601 1.98 mjacob }
2602 1.117 mjacob } else if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_F_PORT) {
2603 1.70 mjacob check_for_fabric = 1;
2604 1.111 mjacob } else {
2605 1.70 mjacob check_for_fabric = 0;
2606 1.111 mjacob }
2607 1.70 mjacob
2608 1.114 mjacob /*
2609 1.114 mjacob * Check to make sure we got a valid loopid
2610 1.117 mjacob * The 24XX seems to mess this up for multiple channels.
2611 1.114 mjacob */
2612 1.117 mjacob if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT) {
2613 1.114 mjacob uint8_t alpa = fcp->isp_portid;
2614 1.114 mjacob
2615 1.114 mjacob if (alpa == 0) {
2616 1.114 mjacob /* "Cannot Happen" */
2617 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "Zero AL_PA for Loop Topology?");
2618 1.114 mjacob } else {
2619 1.114 mjacob int i;
2620 1.114 mjacob for (i = 0; alpa_map[i]; i++) {
2621 1.114 mjacob if (alpa_map[i] == alpa) {
2622 1.114 mjacob break;
2623 1.114 mjacob }
2624 1.114 mjacob }
2625 1.114 mjacob if (alpa_map[i] && fcp->isp_loopid != i) {
2626 1.117 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d deriving loopid %d from AL_PA map (AL_PA 0x%x) and ignoring returned value %d (AL_PA 0x%x)", chan, i, alpa_map[i], fcp->isp_loopid, alpa);
2627 1.114 mjacob fcp->isp_loopid = i;
2628 1.114 mjacob }
2629 1.114 mjacob }
2630 1.114 mjacob }
2631 1.114 mjacob
2632 1.114 mjacob
2633 1.114 mjacob if (IS_24XX(isp)) { /* XXX SHOULDN'T THIS BE FOR 2K F/W? XXX */
2634 1.111 mjacob loopid = NPH_FL_ID;
2635 1.111 mjacob } else {
2636 1.111 mjacob loopid = FL_ID;
2637 1.111 mjacob }
2638 1.114 mjacob if (check_for_fabric) {
2639 1.114 mjacob r = isp_getpdb(isp, chan, loopid, &pdb, 1);
2640 1.117 mjacob if (r && (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT)) {
2641 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "fabric topology but cannot get info about fabric controller (0x%x)", r);
2642 1.114 mjacob fcp->isp_topo = TOPO_PTP_STUB;
2643 1.114 mjacob }
2644 1.114 mjacob } else {
2645 1.114 mjacob r = -1;
2646 1.114 mjacob }
2647 1.114 mjacob if (r == 0) {
2648 1.52 he if (IS_2100(isp)) {
2649 1.52 he fcp->isp_topo = TOPO_FL_PORT;
2650 1.52 he }
2651 1.111 mjacob if (pdb.portid == 0) {
2652 1.70 mjacob /*
2653 1.70 mjacob * Crock.
2654 1.70 mjacob */
2655 1.70 mjacob fcp->isp_topo = TOPO_NL_PORT;
2656 1.70 mjacob goto not_on_fabric;
2657 1.70 mjacob }
2658 1.37 mjacob
2659 1.37 mjacob /*
2660 1.52 he * Save the Fabric controller's port database entry.
2661 1.37 mjacob */
2662 1.111 mjacob lp = &fcp->portdb[FL_ID];
2663 1.111 mjacob lp->state = FC_PORTDB_STATE_PENDING_VALID;
2664 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(lp->node_wwn, pdb.nodename);
2665 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(lp->port_wwn, pdb.portname);
2666 1.111 mjacob lp->roles = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
2667 1.111 mjacob lp->portid = pdb.portid;
2668 1.111 mjacob lp->handle = pdb.handle;
2669 1.111 mjacob lp->new_portid = lp->portid;
2670 1.111 mjacob lp->new_roles = lp->roles;
2671 1.111 mjacob if (IS_24XX(isp)) {
2672 1.114 mjacob fcp->inorder = (mbs.param[7] & ISP24XX_INORDER) != 0;
2673 1.114 mjacob if (ISP_FW_NEWER_THAN(isp, 4, 0, 27)) {
2674 1.117 mjacob fcp->npiv_fabric = (mbs.param[7] & ISP24XX_NPIV_SAN) != 0;
2675 1.114 mjacob if (fcp->npiv_fabric) {
2676 1.117 mjacob isp_prt(isp, ISP_LOGCONFIG, "fabric supports NP-IV");
2677 1.114 mjacob }
2678 1.114 mjacob }
2679 1.114 mjacob if (chan) {
2680 1.114 mjacob fcp->isp_sns_hdl = NPH_SNS_HDLBASE + chan;
2681 1.117 mjacob r = isp_plogx(isp, chan, fcp->isp_sns_hdl, SNS_PORT_ID, PLOGX_FLG_CMD_PLOGI | PLOGX_FLG_COND_PLOGI | PLOGX_FLG_SKIP_PRLI, 0);
2682 1.114 mjacob if (r) {
2683 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "%s: Chan %d cannot log into SNS", __func__, chan);
2684 1.114 mjacob return (-1);
2685 1.114 mjacob }
2686 1.114 mjacob } else {
2687 1.114 mjacob fcp->isp_sns_hdl = NPH_SNS_ID;
2688 1.114 mjacob }
2689 1.114 mjacob r = isp_register_fc4_type_24xx(isp, chan);
2690 1.111 mjacob } else {
2691 1.114 mjacob fcp->isp_sns_hdl = SNS_ID;
2692 1.114 mjacob r = isp_register_fc4_type(isp, chan);
2693 1.111 mjacob }
2694 1.111 mjacob if (r) {
2695 1.117 mjacob isp_prt(isp, ISP_LOGWARN|ISP_LOGSANCFG, "%s: register fc4 type failed", __func__);
2696 1.111 mjacob return (-1);
2697 1.111 mjacob }
2698 1.70 mjacob } else {
2699 1.70 mjacob not_on_fabric:
2700 1.111 mjacob fcp->portdb[FL_ID].state = FC_PORTDB_STATE_NIL;
2701 1.52 he }
2702 1.52 he
2703 1.81 mjacob fcp->isp_gbspeed = 1;
2704 1.111 mjacob if (IS_23XX(isp) || IS_24XX(isp)) {
2705 1.117 mjacob MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
2706 1.81 mjacob mbs.param[1] = MBGSD_GET_RATE;
2707 1.81 mjacob /* mbs.param[2] undefined if we're just getting rate */
2708 1.111 mjacob isp_mboxcmd(isp, &mbs);
2709 1.81 mjacob if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
2710 1.117 mjacob if (mbs.param[1] == MBGSD_EIGHTGB) {
2711 1.117 mjacob isp_prt(isp, ISP_LOGINFO, "Chan %d 8Gb link speed", chan);
2712 1.117 mjacob fcp->isp_gbspeed = 8;
2713 1.117 mjacob } else if (mbs.param[1] == MBGSD_FOURGB) {
2714 1.117 mjacob isp_prt(isp, ISP_LOGINFO, "Chan %d 4Gb link speed", chan);
2715 1.111 mjacob fcp->isp_gbspeed = 4;
2716 1.114 mjacob } else if (mbs.param[1] == MBGSD_TWOGB) {
2717 1.117 mjacob isp_prt(isp, ISP_LOGINFO, "Chan %d 2Gb link speed", chan);
2718 1.81 mjacob fcp->isp_gbspeed = 2;
2719 1.114 mjacob } else if (mbs.param[1] == MBGSD_ONEGB) {
2720 1.117 mjacob isp_prt(isp, ISP_LOGINFO, "Chan %d 1Gb link speed", chan);
2721 1.114 mjacob fcp->isp_gbspeed = 1;
2722 1.81 mjacob }
2723 1.81 mjacob }
2724 1.81 mjacob }
2725 1.81 mjacob
2726 1.70 mjacob /*
2727 1.111 mjacob * Announce ourselves, too.
2728 1.70 mjacob */
2729 1.117 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, topology, chan, (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) fcp->isp_wwpn, fcp->isp_portid, fcp->isp_loopid, isp_fc_toponame(fcp));
2730 1.117 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d FC Link Test Complete", chan);
2731 1.33 mjacob return (0);
2732 1.37 mjacob }
2733 1.37 mjacob
2734 1.111 mjacob /*
2735 1.111 mjacob * Complete the synchronization of our Port Database.
2736 1.111 mjacob *
2737 1.111 mjacob * At this point, we've scanned the local loop (if any) and the fabric
2738 1.111 mjacob * and performed fabric logins on all new devices.
2739 1.111 mjacob *
2740 1.111 mjacob * Our task here is to go through our port database and remove any entities
2741 1.111 mjacob * that are still marked probational (issuing PLOGO for ones which we had
2742 1.111 mjacob * PLOGI'd into) or are dead.
2743 1.111 mjacob *
2744 1.111 mjacob * Our task here is to also check policy to decide whether devices which
2745 1.111 mjacob * have *changed* in some way should still be kept active. For example,
2746 1.111 mjacob * if a device has just changed PortID, we can either elect to treat it
2747 1.111 mjacob * as an old device or as a newly arrived device (and notify the outer
2748 1.111 mjacob * layer appropriately).
2749 1.111 mjacob *
2750 1.111 mjacob * We also do initiator map target id assignment here for new initiator
2751 1.111 mjacob * devices and refresh old ones ot make sure that they point to the corret
2752 1.111 mjacob * entities.
2753 1.111 mjacob */
2754 1.111 mjacob static int
2755 1.114 mjacob isp_pdb_sync(ispsoftc_t *isp, int chan)
2756 1.111 mjacob {
2757 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
2758 1.111 mjacob fcportdb_t *lp;
2759 1.111 mjacob uint16_t dbidx;
2760 1.111 mjacob
2761 1.111 mjacob if (fcp->isp_loopstate == LOOP_READY) {
2762 1.111 mjacob return (0);
2763 1.111 mjacob }
2764 1.111 mjacob
2765 1.111 mjacob /*
2766 1.111 mjacob * Make sure we're okay for doing this right now.
2767 1.111 mjacob */
2768 1.111 mjacob if (fcp->isp_loopstate != LOOP_PDB_RCVD &&
2769 1.111 mjacob fcp->isp_loopstate != LOOP_FSCAN_DONE &&
2770 1.111 mjacob fcp->isp_loopstate != LOOP_LSCAN_DONE) {
2771 1.111 mjacob isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: bad loopstate %d",
2772 1.111 mjacob fcp->isp_loopstate);
2773 1.111 mjacob return (-1);
2774 1.111 mjacob }
2775 1.111 mjacob
2776 1.111 mjacob if (fcp->isp_topo == TOPO_FL_PORT ||
2777 1.111 mjacob fcp->isp_topo == TOPO_NL_PORT ||
2778 1.111 mjacob fcp->isp_topo == TOPO_N_PORT) {
2779 1.111 mjacob if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
2780 1.114 mjacob if (isp_scan_loop(isp, chan) != 0) {
2781 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
2782 1.111 mjacob "isp_pdb_sync: isp_scan_loop failed");
2783 1.111 mjacob return (-1);
2784 1.111 mjacob }
2785 1.111 mjacob }
2786 1.111 mjacob }
2787 1.111 mjacob
2788 1.111 mjacob if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
2789 1.111 mjacob if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
2790 1.114 mjacob if (isp_scan_fabric(isp, chan) != 0) {
2791 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
2792 1.111 mjacob "isp_pdb_sync: isp_scan_fabric failed");
2793 1.111 mjacob return (-1);
2794 1.111 mjacob }
2795 1.111 mjacob }
2796 1.111 mjacob }
2797 1.111 mjacob
2798 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2799 1.114 mjacob "Chan %d Synchronizing PDBs", chan);
2800 1.111 mjacob
2801 1.111 mjacob fcp->isp_loopstate = LOOP_SYNCING_PDB;
2802 1.111 mjacob
2803 1.111 mjacob for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
2804 1.111 mjacob lp = &fcp->portdb[dbidx];
2805 1.111 mjacob
2806 1.114 mjacob if (lp->state == FC_PORTDB_STATE_NIL || lp->target_mode) {
2807 1.111 mjacob continue;
2808 1.111 mjacob }
2809 1.111 mjacob
2810 1.111 mjacob if (lp->state == FC_PORTDB_STATE_VALID) {
2811 1.111 mjacob if (dbidx != FL_ID) {
2812 1.111 mjacob isp_prt(isp,
2813 1.111 mjacob ISP_LOGERR, "portdb idx %d already valid",
2814 1.111 mjacob dbidx);
2815 1.111 mjacob }
2816 1.111 mjacob continue;
2817 1.111 mjacob }
2818 1.111 mjacob
2819 1.111 mjacob switch (lp->state) {
2820 1.111 mjacob case FC_PORTDB_STATE_PROBATIONAL:
2821 1.111 mjacob case FC_PORTDB_STATE_DEAD:
2822 1.111 mjacob /*
2823 1.117 mjacob * It's up to the outer layers to clear isp_dev_map.
2824 1.111 mjacob */
2825 1.111 mjacob lp->state = FC_PORTDB_STATE_NIL;
2826 1.114 mjacob isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
2827 1.111 mjacob if (lp->autologin == 0) {
2828 1.114 mjacob (void) isp_plogx(isp, chan, lp->handle,
2829 1.114 mjacob lp->portid,
2830 1.111 mjacob PLOGX_FLG_CMD_LOGO |
2831 1.111 mjacob PLOGX_FLG_IMPLICIT |
2832 1.111 mjacob PLOGX_FLG_FREE_NPHDL, 0);
2833 1.111 mjacob } else {
2834 1.111 mjacob lp->autologin = 0;
2835 1.111 mjacob }
2836 1.111 mjacob lp->new_roles = 0;
2837 1.111 mjacob lp->new_portid = 0;
2838 1.111 mjacob /*
2839 1.111 mjacob * Note that we might come out of this with our state
2840 1.111 mjacob * set to FC_PORTDB_STATE_ZOMBIE.
2841 1.111 mjacob */
2842 1.111 mjacob break;
2843 1.111 mjacob case FC_PORTDB_STATE_NEW:
2844 1.111 mjacob /*
2845 1.111 mjacob * It's up to the outer layers to assign a virtual
2846 1.117 mjacob * target id in isp_dev_map (if any).
2847 1.111 mjacob */
2848 1.111 mjacob lp->portid = lp->new_portid;
2849 1.111 mjacob lp->roles = lp->new_roles;
2850 1.111 mjacob lp->state = FC_PORTDB_STATE_VALID;
2851 1.114 mjacob isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
2852 1.111 mjacob lp->new_roles = 0;
2853 1.111 mjacob lp->new_portid = 0;
2854 1.111 mjacob lp->reserved = 0;
2855 1.111 mjacob lp->new_reserved = 0;
2856 1.111 mjacob break;
2857 1.111 mjacob case FC_PORTDB_STATE_CHANGED:
2858 1.111 mjacob /*
2859 1.111 mjacob * XXXX FIX THIS
2860 1.111 mjacob */
2861 1.111 mjacob lp->state = FC_PORTDB_STATE_VALID;
2862 1.114 mjacob isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
2863 1.111 mjacob lp->new_roles = 0;
2864 1.111 mjacob lp->new_portid = 0;
2865 1.111 mjacob lp->reserved = 0;
2866 1.111 mjacob lp->new_reserved = 0;
2867 1.111 mjacob break;
2868 1.111 mjacob case FC_PORTDB_STATE_PENDING_VALID:
2869 1.111 mjacob lp->portid = lp->new_portid;
2870 1.111 mjacob lp->roles = lp->new_roles;
2871 1.117 mjacob if (lp->dev_map_idx) {
2872 1.117 mjacob int t = lp->dev_map_idx - 1;
2873 1.117 mjacob fcp->isp_dev_map[t] = dbidx + 1;
2874 1.111 mjacob }
2875 1.111 mjacob lp->state = FC_PORTDB_STATE_VALID;
2876 1.114 mjacob isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
2877 1.111 mjacob if (dbidx != FL_ID) {
2878 1.111 mjacob lp->new_roles = 0;
2879 1.111 mjacob lp->new_portid = 0;
2880 1.111 mjacob }
2881 1.111 mjacob lp->reserved = 0;
2882 1.111 mjacob lp->new_reserved = 0;
2883 1.111 mjacob break;
2884 1.111 mjacob case FC_PORTDB_STATE_ZOMBIE:
2885 1.111 mjacob break;
2886 1.111 mjacob default:
2887 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
2888 1.111 mjacob "isp_scan_loop: state %d for idx %d",
2889 1.111 mjacob lp->state, dbidx);
2890 1.114 mjacob isp_dump_portdb(isp, chan);
2891 1.111 mjacob }
2892 1.111 mjacob }
2893 1.111 mjacob
2894 1.111 mjacob /*
2895 1.111 mjacob * If we get here, we've for sure seen not only a valid loop
2896 1.111 mjacob * but know what is or isn't on it, so mark this for usage
2897 1.111 mjacob * in isp_start.
2898 1.111 mjacob */
2899 1.111 mjacob fcp->loop_seen_once = 1;
2900 1.111 mjacob fcp->isp_loopstate = LOOP_READY;
2901 1.111 mjacob return (0);
2902 1.57 mjacob }
2903 1.33 mjacob
2904 1.1 cgd /*
2905 1.111 mjacob * Scan local loop for devices.
2906 1.37 mjacob */
2907 1.37 mjacob static int
2908 1.114 mjacob isp_scan_loop(ispsoftc_t *isp, int chan)
2909 1.37 mjacob {
2910 1.111 mjacob fcportdb_t *lp, tmp;
2911 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
2912 1.111 mjacob int i;
2913 1.37 mjacob isp_pdb_t pdb;
2914 1.111 mjacob uint16_t handle, lim = 0;
2915 1.37 mjacob
2916 1.111 mjacob if (fcp->isp_fwstate < FW_READY ||
2917 1.111 mjacob fcp->isp_loopstate < LOOP_PDB_RCVD) {
2918 1.70 mjacob return (-1);
2919 1.70 mjacob }
2920 1.70 mjacob
2921 1.111 mjacob if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
2922 1.111 mjacob return (0);
2923 1.70 mjacob }
2924 1.70 mjacob
2925 1.37 mjacob /*
2926 1.111 mjacob * Check our connection topology.
2927 1.111 mjacob *
2928 1.111 mjacob * If we're a public or private loop, we scan 0..125 as handle values.
2929 1.114 mjacob * The firmware has (typically) peformed a PLOGI for us. We skip this
2930 1.114 mjacob * step if we're a ISP_24XX in NP-IV mode.
2931 1.111 mjacob *
2932 1.111 mjacob * If we're a N-port connection, we treat this is a short loop (0..1).
2933 1.37 mjacob */
2934 1.111 mjacob switch (fcp->isp_topo) {
2935 1.111 mjacob case TOPO_NL_PORT:
2936 1.114 mjacob lim = LOCAL_LOOP_LIM;
2937 1.114 mjacob break;
2938 1.111 mjacob case TOPO_FL_PORT:
2939 1.114 mjacob if (IS_24XX(isp) && isp->isp_nchan > 1) {
2940 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2941 1.114 mjacob "Chan %d Skipping Local Loop Scan", chan);
2942 1.114 mjacob fcp->isp_loopstate = LOOP_LSCAN_DONE;
2943 1.114 mjacob return (0);
2944 1.114 mjacob }
2945 1.111 mjacob lim = LOCAL_LOOP_LIM;
2946 1.111 mjacob break;
2947 1.111 mjacob case TOPO_N_PORT:
2948 1.111 mjacob lim = 2;
2949 1.111 mjacob break;
2950 1.111 mjacob default:
2951 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2952 1.114 mjacob "Chan %d no loop topology to scan", chan);
2953 1.111 mjacob fcp->isp_loopstate = LOOP_LSCAN_DONE;
2954 1.70 mjacob return (0);
2955 1.52 he }
2956 1.52 he
2957 1.111 mjacob fcp->isp_loopstate = LOOP_SCANNING_LOOP;
2958 1.70 mjacob
2959 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2960 1.114 mjacob "Chan %d FC scan loop 0..%d", chan, lim-1);
2961 1.70 mjacob
2962 1.46 mjacob
2963 1.43 mjacob /*
2964 1.111 mjacob * Run through the list and get the port database info for each one.
2965 1.43 mjacob */
2966 1.111 mjacob for (handle = 0; handle < lim; handle++) {
2967 1.114 mjacob int r;
2968 1.111 mjacob /*
2969 1.114 mjacob * Don't scan "special" ids.
2970 1.114 mjacob */
2971 1.114 mjacob if (handle >= FL_ID && handle <= SNS_ID) {
2972 1.37 mjacob continue;
2973 1.70 mjacob }
2974 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
2975 1.114 mjacob if (handle >= NPH_RESERVED && handle <= NPH_FL_ID) {
2976 1.114 mjacob continue;
2977 1.114 mjacob }
2978 1.114 mjacob }
2979 1.70 mjacob /*
2980 1.111 mjacob * In older cards with older f/w GET_PORT_DATABASE has been
2981 1.111 mjacob * known to hang. This trick gets around that problem.
2982 1.70 mjacob */
2983 1.111 mjacob if (IS_2100(isp) || IS_2200(isp)) {
2984 1.114 mjacob uint64_t node_wwn = isp_get_wwn(isp, chan, handle, 1);
2985 1.111 mjacob if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
2986 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2987 1.114 mjacob "Chan %d FC scan loop DONE (bad)", chan);
2988 1.111 mjacob return (-1);
2989 1.111 mjacob }
2990 1.114 mjacob if (node_wwn == INI_NONE) {
2991 1.111 mjacob continue;
2992 1.111 mjacob }
2993 1.37 mjacob }
2994 1.38 mjacob
2995 1.37 mjacob /*
2996 1.111 mjacob * Get the port database entity for this index.
2997 1.37 mjacob */
2998 1.114 mjacob r = isp_getpdb(isp, chan, handle, &pdb, 1);
2999 1.114 mjacob if (r != 0) {
3000 1.114 mjacob isp_prt(isp, ISP_LOGDEBUG1,
3001 1.114 mjacob "Chan %d FC scan loop handle %d returned %x",
3002 1.114 mjacob chan, handle, r);
3003 1.111 mjacob if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
3004 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3005 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3006 1.114 mjacob "Chan %d FC scan loop DONE (bad)", chan);
3007 1.111 mjacob return (-1);
3008 1.111 mjacob }
3009 1.37 mjacob continue;
3010 1.37 mjacob }
3011 1.38 mjacob
3012 1.111 mjacob if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
3013 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3014 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3015 1.114 mjacob "Chan %d FC scan loop DONE (bad)", chan);
3016 1.111 mjacob return (-1);
3017 1.111 mjacob }
3018 1.52 he
3019 1.37 mjacob /*
3020 1.111 mjacob * On *very* old 2100 firmware we would end up sometimes
3021 1.111 mjacob * with the firmware returning the port database entry
3022 1.111 mjacob * for something else. We used to restart this, but
3023 1.111 mjacob * now we just punt.
3024 1.111 mjacob */
3025 1.111 mjacob if (IS_2100(isp) && pdb.handle != handle) {
3026 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
3027 1.114 mjacob "Chan %d cannot synchronize port database", chan);
3028 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3029 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3030 1.114 mjacob "Chan %d FC scan loop DONE (bad)", chan);
3031 1.70 mjacob return (-1);
3032 1.37 mjacob }
3033 1.37 mjacob
3034 1.37 mjacob /*
3035 1.111 mjacob * Save the pertinent info locally.
3036 1.37 mjacob */
3037 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(tmp.node_wwn, pdb.nodename);
3038 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(tmp.port_wwn, pdb.portname);
3039 1.111 mjacob tmp.roles = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
3040 1.111 mjacob tmp.portid = pdb.portid;
3041 1.111 mjacob tmp.handle = pdb.handle;
3042 1.111 mjacob
3043 1.111 mjacob /*
3044 1.111 mjacob * Check to make sure it's still a valid entry. The 24XX seems
3045 1.111 mjacob * to return a portid but not a WWPN/WWNN or role for devices
3046 1.111 mjacob * which shift on a loop.
3047 1.111 mjacob */
3048 1.111 mjacob if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) {
3049 1.111 mjacob int a, b, c;
3050 1.111 mjacob a = (tmp.node_wwn == 0);
3051 1.111 mjacob b = (tmp.port_wwn == 0);
3052 1.111 mjacob c = (tmp.portid == 0);
3053 1.114 mjacob if (a == 0 && b == 0) {
3054 1.114 mjacob tmp.node_wwn =
3055 1.114 mjacob isp_get_wwn(isp, chan, handle, 1);
3056 1.114 mjacob tmp.port_wwn =
3057 1.114 mjacob isp_get_wwn(isp, chan, handle, 0);
3058 1.114 mjacob if (tmp.node_wwn && tmp.port_wwn) {
3059 1.114 mjacob isp_prt(isp, ISP_LOGINFO, "DODGED!");
3060 1.114 mjacob goto cont;
3061 1.114 mjacob }
3062 1.114 mjacob }
3063 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
3064 1.114 mjacob "Chan %d bad pdb (%1d%1d%1d) @ handle 0x%x", chan,
3065 1.114 mjacob a, b, c, handle);
3066 1.114 mjacob isp_dump_portdb(isp, chan);
3067 1.111 mjacob continue;
3068 1.37 mjacob }
3069 1.114 mjacob cont:
3070 1.37 mjacob
3071 1.37 mjacob /*
3072 1.111 mjacob * Now search the entire port database
3073 1.111 mjacob * for the same Port and Node WWN.
3074 1.37 mjacob */
3075 1.111 mjacob for (i = 0; i < MAX_FC_TARG; i++) {
3076 1.111 mjacob lp = &fcp->portdb[i];
3077 1.114 mjacob
3078 1.114 mjacob if (lp->state == FC_PORTDB_STATE_NIL ||
3079 1.114 mjacob lp->target_mode) {
3080 1.111 mjacob continue;
3081 1.111 mjacob }
3082 1.111 mjacob if (lp->node_wwn != tmp.node_wwn) {
3083 1.111 mjacob continue;
3084 1.111 mjacob }
3085 1.111 mjacob if (lp->port_wwn != tmp.port_wwn) {
3086 1.111 mjacob continue;
3087 1.111 mjacob }
3088 1.111 mjacob
3089 1.111 mjacob /*
3090 1.111 mjacob * Okay- we've found a non-nil entry that matches.
3091 1.111 mjacob * Check to make sure it's probational or a zombie.
3092 1.111 mjacob */
3093 1.111 mjacob if (lp->state != FC_PORTDB_STATE_PROBATIONAL &&
3094 1.111 mjacob lp->state != FC_PORTDB_STATE_ZOMBIE) {
3095 1.111 mjacob isp_prt(isp, ISP_LOGERR,
3096 1.114 mjacob "Chan %d [%d] not probational/zombie (0x%x)",
3097 1.114 mjacob chan, i, lp->state);
3098 1.114 mjacob isp_dump_portdb(isp, chan);
3099 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3100 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3101 1.114 mjacob "Chan %d FC scan loop DONE (bad)", chan);
3102 1.70 mjacob return (-1);
3103 1.37 mjacob }
3104 1.111 mjacob
3105 1.111 mjacob /*
3106 1.111 mjacob * Mark the device as something the f/w logs into
3107 1.111 mjacob * automatically.
3108 1.111 mjacob */
3109 1.111 mjacob lp->autologin = 1;
3110 1.111 mjacob
3111 1.111 mjacob /*
3112 1.111 mjacob * Check to make see if really still the same
3113 1.111 mjacob * device. If it is, we mark it pending valid.
3114 1.111 mjacob */
3115 1.111 mjacob if (lp->portid == tmp.portid &&
3116 1.111 mjacob lp->handle == tmp.handle &&
3117 1.111 mjacob lp->roles == tmp.roles) {
3118 1.111 mjacob lp->new_portid = tmp.portid;
3119 1.111 mjacob lp->new_roles = tmp.roles;
3120 1.111 mjacob lp->state = FC_PORTDB_STATE_PENDING_VALID;
3121 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3122 1.117 mjacob "Chan %d Loop Port 0x%06x@0x%04x Pending "
3123 1.114 mjacob "Valid", chan, tmp.portid, tmp.handle);
3124 1.70 mjacob break;
3125 1.37 mjacob }
3126 1.117 mjacob
3127 1.111 mjacob /*
3128 1.111 mjacob * We can wipe out the old handle value
3129 1.111 mjacob * here because it's no longer valid.
3130 1.111 mjacob */
3131 1.111 mjacob lp->handle = tmp.handle;
3132 1.111 mjacob
3133 1.111 mjacob /*
3134 1.111 mjacob * Claim that this has changed and let somebody else
3135 1.111 mjacob * decide what to do.
3136 1.111 mjacob */
3137 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3138 1.117 mjacob "Chan %d Loop Port 0x%06x@0x%04x changed",
3139 1.114 mjacob chan, tmp.portid, tmp.handle);
3140 1.111 mjacob lp->state = FC_PORTDB_STATE_CHANGED;
3141 1.111 mjacob lp->new_portid = tmp.portid;
3142 1.111 mjacob lp->new_roles = tmp.roles;
3143 1.111 mjacob break;
3144 1.111 mjacob }
3145 1.37 mjacob
3146 1.37 mjacob /*
3147 1.111 mjacob * Did we find and update an old entry?
3148 1.37 mjacob */
3149 1.111 mjacob if (i < MAX_FC_TARG) {
3150 1.37 mjacob continue;
3151 1.37 mjacob }
3152 1.37 mjacob
3153 1.37 mjacob /*
3154 1.111 mjacob * Ah. A new device entry. Find an empty slot
3155 1.111 mjacob * for it and save info for later disposition.
3156 1.37 mjacob */
3157 1.111 mjacob for (i = 0; i < MAX_FC_TARG; i++) {
3158 1.114 mjacob if (fcp->portdb[i].target_mode) {
3159 1.114 mjacob continue;
3160 1.114 mjacob }
3161 1.111 mjacob if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) {
3162 1.111 mjacob break;
3163 1.111 mjacob }
3164 1.111 mjacob }
3165 1.111 mjacob if (i == MAX_FC_TARG) {
3166 1.114 mjacob isp_prt(isp, ISP_LOGERR,
3167 1.114 mjacob "Chan %d out of portdb entries", chan);
3168 1.111 mjacob continue;
3169 1.70 mjacob }
3170 1.111 mjacob lp = &fcp->portdb[i];
3171 1.111 mjacob
3172 1.117 mjacob ISP_MEMZERO(lp, sizeof (fcportdb_t));
3173 1.111 mjacob lp->autologin = 1;
3174 1.111 mjacob lp->state = FC_PORTDB_STATE_NEW;
3175 1.111 mjacob lp->new_portid = tmp.portid;
3176 1.111 mjacob lp->new_roles = tmp.roles;
3177 1.111 mjacob lp->handle = tmp.handle;
3178 1.111 mjacob lp->port_wwn = tmp.port_wwn;
3179 1.111 mjacob lp->node_wwn = tmp.node_wwn;
3180 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3181 1.117 mjacob "Chan %d Loop Port 0x%06x@0x%04x is New Entry",
3182 1.114 mjacob chan, tmp.portid, tmp.handle);
3183 1.111 mjacob }
3184 1.111 mjacob fcp->isp_loopstate = LOOP_LSCAN_DONE;
3185 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3186 1.114 mjacob "Chan %d FC scan loop DONE", chan);
3187 1.111 mjacob return (0);
3188 1.111 mjacob }
3189 1.111 mjacob
3190 1.111 mjacob /*
3191 1.111 mjacob * Scan the fabric for devices and add them to our port database.
3192 1.111 mjacob *
3193 1.111 mjacob * Use the GID_FT command to get all Port IDs for FC4 SCSI devices it knows.
3194 1.111 mjacob *
3195 1.111 mjacob * For 2100-23XX cards, we can use the SNS mailbox command to pass simple
3196 1.111 mjacob * name server commands to the switch management server via the QLogic f/w.
3197 1.111 mjacob *
3198 1.111 mjacob * For the 24XX card, we have to use CT-Pass through run via the Execute IOCB
3199 1.111 mjacob * mailbox command.
3200 1.111 mjacob *
3201 1.111 mjacob * The net result is to leave the list of Port IDs setting untranslated in
3202 1.111 mjacob * offset IGPOFF of the FC scratch area, whereupon we'll canonicalize it to
3203 1.111 mjacob * host order at OGPOFF.
3204 1.111 mjacob */
3205 1.111 mjacob
3206 1.111 mjacob /*
3207 1.117 mjacob * Take less than half of our scratch area to store Port IDs
3208 1.111 mjacob */
3209 1.114 mjacob #define GIDLEN ((ISP_FC_SCRLEN >> 1) - 16 - SNS_GID_FT_REQ_SIZE)
3210 1.111 mjacob #define NGENT ((GIDLEN - 16) >> 2)
3211 1.111 mjacob
3212 1.111 mjacob #define IGPOFF (2 * QENTRY_LEN)
3213 1.114 mjacob #define OGPOFF (ISP_FC_SCRLEN >> 1)
3214 1.114 mjacob #define ZTXOFF (ISP_FC_SCRLEN - (1 * QENTRY_LEN))
3215 1.114 mjacob #define CTXOFF (ISP_FC_SCRLEN - (2 * QENTRY_LEN))
3216 1.114 mjacob #define XTXOFF (ISP_FC_SCRLEN - (3 * QENTRY_LEN))
3217 1.111 mjacob
3218 1.111 mjacob static int
3219 1.114 mjacob isp_gid_ft_sns(ispsoftc_t *isp, int chan)
3220 1.111 mjacob {
3221 1.111 mjacob union {
3222 1.111 mjacob sns_gid_ft_req_t _x;
3223 1.111 mjacob uint8_t _y[SNS_GID_FT_REQ_SIZE];
3224 1.111 mjacob } un;
3225 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
3226 1.111 mjacob sns_gid_ft_req_t *rq = &un._x;
3227 1.111 mjacob mbreg_t mbs;
3228 1.111 mjacob
3229 1.114 mjacob isp_prt(isp, ISP_LOGDEBUG0,
3230 1.114 mjacob "Chan %d scanning fabric (GID_FT) via SNS", chan);
3231 1.111 mjacob
3232 1.117 mjacob ISP_MEMZERO(rq, SNS_GID_FT_REQ_SIZE);
3233 1.111 mjacob rq->snscb_rblen = GIDLEN >> 1;
3234 1.111 mjacob rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + IGPOFF);
3235 1.111 mjacob rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + IGPOFF);
3236 1.111 mjacob rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + IGPOFF);
3237 1.111 mjacob rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + IGPOFF);
3238 1.111 mjacob rq->snscb_sblen = 6;
3239 1.111 mjacob rq->snscb_cmd = SNS_GID_FT;
3240 1.111 mjacob rq->snscb_mword_div_2 = NGENT;
3241 1.111 mjacob rq->snscb_fc4_type = FC4_SCSI;
3242 1.70 mjacob
3243 1.111 mjacob isp_put_gid_ft_request(isp, rq, fcp->isp_scratch);
3244 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE);
3245 1.111 mjacob
3246 1.117 mjacob MBSINIT(&mbs, MBOX_SEND_SNS, MBLOGALL, 10000000);
3247 1.111 mjacob mbs.param[0] = MBOX_SEND_SNS;
3248 1.111 mjacob mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1;
3249 1.111 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma);
3250 1.111 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma);
3251 1.111 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma);
3252 1.111 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma);
3253 1.111 mjacob isp_mboxcmd(isp, &mbs);
3254 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
3255 1.111 mjacob if (mbs.param[0] == MBOX_INVALID_COMMAND) {
3256 1.111 mjacob return (1);
3257 1.111 mjacob } else {
3258 1.70 mjacob return (-1);
3259 1.70 mjacob }
3260 1.111 mjacob }
3261 1.111 mjacob return (0);
3262 1.111 mjacob }
3263 1.111 mjacob
3264 1.111 mjacob static int
3265 1.114 mjacob isp_gid_ft_ct_passthru(ispsoftc_t *isp, int chan)
3266 1.111 mjacob {
3267 1.111 mjacob mbreg_t mbs;
3268 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
3269 1.111 mjacob union {
3270 1.111 mjacob isp_ct_pt_t plocal;
3271 1.111 mjacob ct_hdr_t clocal;
3272 1.111 mjacob uint8_t q[QENTRY_LEN];
3273 1.111 mjacob } un;
3274 1.111 mjacob isp_ct_pt_t *pt;
3275 1.111 mjacob ct_hdr_t *ct;
3276 1.111 mjacob uint32_t *rp;
3277 1.111 mjacob uint8_t *scp = fcp->isp_scratch;
3278 1.111 mjacob
3279 1.114 mjacob isp_prt(isp, ISP_LOGDEBUG0,
3280 1.114 mjacob "Chan %d scanning fabric (GID_FT) via CT", chan);
3281 1.111 mjacob
3282 1.111 mjacob if (!IS_24XX(isp)) {
3283 1.111 mjacob return (1);
3284 1.111 mjacob }
3285 1.70 mjacob
3286 1.111 mjacob /*
3287 1.111 mjacob * Build a Passthrough IOCB in memory.
3288 1.111 mjacob */
3289 1.111 mjacob pt = &un.plocal;
3290 1.117 mjacob ISP_MEMZERO(un.q, QENTRY_LEN);
3291 1.111 mjacob pt->ctp_header.rqs_entry_count = 1;
3292 1.111 mjacob pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
3293 1.111 mjacob pt->ctp_handle = 0xffffffff;
3294 1.114 mjacob pt->ctp_nphdl = fcp->isp_sns_hdl;
3295 1.111 mjacob pt->ctp_cmd_cnt = 1;
3296 1.117 mjacob pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan);
3297 1.111 mjacob pt->ctp_time = 30;
3298 1.111 mjacob pt->ctp_rsp_cnt = 1;
3299 1.111 mjacob pt->ctp_rsp_bcnt = GIDLEN;
3300 1.111 mjacob pt->ctp_cmd_bcnt = sizeof (*ct) + sizeof (uint32_t);
3301 1.111 mjacob pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
3302 1.111 mjacob pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
3303 1.111 mjacob pt->ctp_dataseg[0].ds_count = sizeof (*ct) + sizeof (uint32_t);
3304 1.111 mjacob pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF);
3305 1.111 mjacob pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF);
3306 1.111 mjacob pt->ctp_dataseg[1].ds_count = GIDLEN;
3307 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
3308 1.111 mjacob isp_print_bytes(isp, "ct IOCB", QENTRY_LEN, pt);
3309 1.37 mjacob }
3310 1.111 mjacob isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]);
3311 1.111 mjacob
3312 1.37 mjacob /*
3313 1.111 mjacob * Build the CT header and command in memory.
3314 1.111 mjacob *
3315 1.111 mjacob * Note that the CT header has to end up as Big Endian format in memory.
3316 1.37 mjacob */
3317 1.111 mjacob ct = &un.clocal;
3318 1.117 mjacob ISP_MEMZERO(ct, sizeof (*ct));
3319 1.111 mjacob ct->ct_revision = CT_REVISION;
3320 1.111 mjacob ct->ct_fcs_type = CT_FC_TYPE_FC;
3321 1.111 mjacob ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
3322 1.111 mjacob ct->ct_cmd_resp = SNS_GID_FT;
3323 1.111 mjacob ct->ct_bcnt_resid = (GIDLEN - 16) >> 2;
3324 1.111 mjacob
3325 1.111 mjacob isp_put_ct_hdr(isp, ct, (ct_hdr_t *) &scp[XTXOFF]);
3326 1.111 mjacob rp = (uint32_t *) &scp[XTXOFF+sizeof (*ct)];
3327 1.111 mjacob ISP_IOZPUT_32(isp, FC4_SCSI, rp);
3328 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
3329 1.111 mjacob isp_print_bytes(isp, "CT HDR + payload after put",
3330 1.111 mjacob sizeof (*ct) + sizeof (uint32_t), &scp[XTXOFF]);
3331 1.111 mjacob }
3332 1.117 mjacob ISP_MEMZERO(&scp[ZTXOFF], QENTRY_LEN);
3333 1.117 mjacob MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 500000);
3334 1.111 mjacob mbs.param[1] = QENTRY_LEN;
3335 1.111 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
3336 1.111 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
3337 1.111 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
3338 1.111 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
3339 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN);
3340 1.111 mjacob isp_mboxcmd(isp, &mbs);
3341 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
3342 1.111 mjacob return (-1);
3343 1.111 mjacob }
3344 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN);
3345 1.111 mjacob pt = &un.plocal;
3346 1.111 mjacob isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt);
3347 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
3348 1.111 mjacob isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt);
3349 1.111 mjacob }
3350 1.111 mjacob
3351 1.111 mjacob if (pt->ctp_status && pt->ctp_status != RQCS_DATA_UNDERRUN) {
3352 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
3353 1.114 mjacob "Chan %d ISP GID FT CT Passthrough returned 0x%x",
3354 1.114 mjacob chan, pt->ctp_status);
3355 1.111 mjacob return (-1);
3356 1.111 mjacob }
3357 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN + 16);
3358 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
3359 1.111 mjacob isp_print_bytes(isp, "CT response", GIDLEN+16, &scp[IGPOFF]);
3360 1.111 mjacob }
3361 1.70 mjacob return (0);
3362 1.70 mjacob }
3363 1.70 mjacob
3364 1.70 mjacob static int
3365 1.114 mjacob isp_scan_fabric(ispsoftc_t *isp, int chan)
3366 1.70 mjacob {
3367 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
3368 1.111 mjacob uint32_t portid;
3369 1.114 mjacob uint16_t handle, oldhandle, loopid;
3370 1.114 mjacob isp_pdb_t pdb;
3371 1.111 mjacob int portidx, portlim, r;
3372 1.111 mjacob sns_gid_ft_rsp_t *rs0, *rs1;
3373 1.111 mjacob
3374 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3375 1.114 mjacob "Chan %d FC Scan Fabric", chan);
3376 1.111 mjacob if (fcp->isp_fwstate != FW_READY ||
3377 1.111 mjacob fcp->isp_loopstate < LOOP_LSCAN_DONE) {
3378 1.111 mjacob return (-1);
3379 1.111 mjacob }
3380 1.111 mjacob if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) {
3381 1.111 mjacob return (0);
3382 1.111 mjacob }
3383 1.111 mjacob if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) {
3384 1.111 mjacob fcp->isp_loopstate = LOOP_FSCAN_DONE;
3385 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3386 1.114 mjacob "Chan %d FC Scan Fabric Done (no fabric)", chan);
3387 1.111 mjacob return (0);
3388 1.111 mjacob }
3389 1.111 mjacob
3390 1.111 mjacob fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
3391 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, chan)) {
3392 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
3393 1.115 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3394 1.115 mjacob return (-1);
3395 1.115 mjacob }
3396 1.114 mjacob if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3397 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3398 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3399 1.114 mjacob return (-1);
3400 1.114 mjacob }
3401 1.114 mjacob
3402 1.114 mjacob /*
3403 1.114 mjacob * Make sure we still are logged into the fabric controller.
3404 1.114 mjacob */
3405 1.114 mjacob if (IS_24XX(isp)) { /* XXX SHOULDN'T THIS BE TRUE FOR 2K F/W? XXX */
3406 1.114 mjacob loopid = NPH_FL_ID;
3407 1.114 mjacob } else {
3408 1.114 mjacob loopid = FL_ID;
3409 1.114 mjacob }
3410 1.114 mjacob r = isp_getpdb(isp, chan, loopid, &pdb, 0);
3411 1.114 mjacob if (r == MBOX_NOT_LOGGED_IN) {
3412 1.114 mjacob isp_dump_chip_portdb(isp, chan, 0);
3413 1.114 mjacob }
3414 1.114 mjacob if (r) {
3415 1.114 mjacob fcp->isp_loopstate = LOOP_PDB_RCVD;
3416 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3417 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3418 1.114 mjacob return (-1);
3419 1.114 mjacob }
3420 1.111 mjacob
3421 1.111 mjacob if (IS_24XX(isp)) {
3422 1.114 mjacob r = isp_gid_ft_ct_passthru(isp, chan);
3423 1.111 mjacob } else {
3424 1.114 mjacob r = isp_gid_ft_sns(isp, chan);
3425 1.114 mjacob }
3426 1.114 mjacob
3427 1.114 mjacob if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3428 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3429 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3430 1.114 mjacob return (-1);
3431 1.111 mjacob }
3432 1.111 mjacob
3433 1.111 mjacob if (r > 0) {
3434 1.111 mjacob fcp->isp_loopstate = LOOP_FSCAN_DONE;
3435 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3436 1.111 mjacob return (0);
3437 1.111 mjacob } else if (r < 0) {
3438 1.111 mjacob fcp->isp_loopstate = LOOP_PDB_RCVD; /* try again */
3439 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3440 1.111 mjacob return (0);
3441 1.111 mjacob }
3442 1.114 mjacob
3443 1.114 mjacob MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN);
3444 1.111 mjacob rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF);
3445 1.111 mjacob rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF);
3446 1.111 mjacob isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
3447 1.114 mjacob if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3448 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3449 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3450 1.114 mjacob return (-1);
3451 1.114 mjacob }
3452 1.111 mjacob if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) {
3453 1.111 mjacob int level;
3454 1.111 mjacob if (rs1->snscb_cthdr.ct_reason == 9 &&
3455 1.111 mjacob rs1->snscb_cthdr.ct_explanation == 7) {
3456 1.111 mjacob level = ISP_LOGSANCFG|ISP_LOGDEBUG0;
3457 1.111 mjacob } else {
3458 1.111 mjacob level = ISP_LOGWARN;
3459 1.111 mjacob }
3460 1.114 mjacob isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_FT"
3461 1.114 mjacob " (Reason=0x%x Expl=0x%x)", chan,
3462 1.114 mjacob rs1->snscb_cthdr.ct_reason,
3463 1.111 mjacob rs1->snscb_cthdr.ct_explanation);
3464 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3465 1.111 mjacob fcp->isp_loopstate = LOOP_FSCAN_DONE;
3466 1.111 mjacob return (0);
3467 1.111 mjacob }
3468 1.111 mjacob
3469 1.111 mjacob
3470 1.111 mjacob /*
3471 1.111 mjacob * If we get this far, we certainly still have the fabric controller.
3472 1.111 mjacob */
3473 1.111 mjacob fcp->portdb[FL_ID].state = FC_PORTDB_STATE_PENDING_VALID;
3474 1.111 mjacob
3475 1.111 mjacob /*
3476 1.111 mjacob * Prime the handle we will start using.
3477 1.111 mjacob */
3478 1.114 mjacob oldhandle = FCPARAM(isp, 0)->isp_lasthdl;
3479 1.111 mjacob
3480 1.111 mjacob /*
3481 1.114 mjacob * Go through the list and remove duplicate port ids.
3482 1.111 mjacob */
3483 1.111 mjacob
3484 1.111 mjacob portlim = 0;
3485 1.111 mjacob portidx = 0;
3486 1.111 mjacob for (portidx = 0; portidx < NGENT-1; portidx++) {
3487 1.111 mjacob if (rs1->snscb_ports[portidx].control & 0x80) {
3488 1.111 mjacob break;
3489 1.111 mjacob }
3490 1.111 mjacob }
3491 1.111 mjacob
3492 1.111 mjacob /*
3493 1.111 mjacob * If we're not at the last entry, our list wasn't big enough.
3494 1.111 mjacob */
3495 1.111 mjacob if ((rs1->snscb_ports[portidx].control & 0x80) == 0) {
3496 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
3497 1.114 mjacob "fabric too big for scratch area: increase ISP_FC_SCRLEN");
3498 1.111 mjacob }
3499 1.111 mjacob portlim = portidx + 1;
3500 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG,
3501 1.114 mjacob "Chan %d got %d ports back from name server", chan, portlim);
3502 1.111 mjacob
3503 1.111 mjacob for (portidx = 0; portidx < portlim; portidx++) {
3504 1.111 mjacob int npidx;
3505 1.111 mjacob
3506 1.111 mjacob portid =
3507 1.111 mjacob ((rs1->snscb_ports[portidx].portid[0]) << 16) |
3508 1.111 mjacob ((rs1->snscb_ports[portidx].portid[1]) << 8) |
3509 1.111 mjacob ((rs1->snscb_ports[portidx].portid[2]));
3510 1.111 mjacob
3511 1.111 mjacob for (npidx = portidx + 1; npidx < portlim; npidx++) {
3512 1.111 mjacob uint32_t new_portid =
3513 1.111 mjacob ((rs1->snscb_ports[npidx].portid[0]) << 16) |
3514 1.111 mjacob ((rs1->snscb_ports[npidx].portid[1]) << 8) |
3515 1.111 mjacob ((rs1->snscb_ports[npidx].portid[2]));
3516 1.111 mjacob if (new_portid == portid) {
3517 1.111 mjacob break;
3518 1.111 mjacob }
3519 1.111 mjacob }
3520 1.37 mjacob
3521 1.111 mjacob if (npidx < portlim) {
3522 1.111 mjacob rs1->snscb_ports[npidx].portid[0] = 0;
3523 1.111 mjacob rs1->snscb_ports[npidx].portid[1] = 0;
3524 1.111 mjacob rs1->snscb_ports[npidx].portid[2] = 0;
3525 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3526 1.114 mjacob "Chan %d removing duplicate PortID 0x%06x"
3527 1.114 mjacob " entry from list", chan, portid);
3528 1.111 mjacob }
3529 1.37 mjacob }
3530 1.70 mjacob
3531 1.70 mjacob /*
3532 1.114 mjacob * We now have a list of Port IDs for all FC4 SCSI devices
3533 1.111 mjacob * that the Fabric Name server knows about.
3534 1.111 mjacob *
3535 1.111 mjacob * For each entry on this list go through our port database looking
3536 1.111 mjacob * for probational entries- if we find one, then an old entry is
3537 1.114 mjacob * maybe still this one. We get some information to find out.
3538 1.70 mjacob *
3539 1.111 mjacob * Otherwise, it's a new fabric device, and we log into it
3540 1.111 mjacob * (unconditionally). After searching the entire database
3541 1.111 mjacob * again to make sure that we never ever ever ever have more
3542 1.111 mjacob * than one entry that has the same PortID or the same
3543 1.111 mjacob * WWNN/WWPN duple, we enter the device into our database.
3544 1.37 mjacob */
3545 1.70 mjacob
3546 1.111 mjacob for (portidx = 0; portidx < portlim; portidx++) {
3547 1.111 mjacob fcportdb_t *lp;
3548 1.111 mjacob uint64_t wwnn, wwpn;
3549 1.111 mjacob int dbidx, nr;
3550 1.37 mjacob
3551 1.111 mjacob portid =
3552 1.111 mjacob ((rs1->snscb_ports[portidx].portid[0]) << 16) |
3553 1.111 mjacob ((rs1->snscb_ports[portidx].portid[1]) << 8) |
3554 1.111 mjacob ((rs1->snscb_ports[portidx].portid[2]));
3555 1.111 mjacob
3556 1.111 mjacob if (portid == 0) {
3557 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG,
3558 1.114 mjacob "Chan %d skipping null PortID at idx %d",
3559 1.114 mjacob chan, portidx);
3560 1.69 mjacob continue;
3561 1.69 mjacob }
3562 1.69 mjacob
3563 1.37 mjacob /*
3564 1.114 mjacob * Skip ourselves here and on other channels. If we're
3565 1.114 mjacob * multi-id, we can't check the portids in other FCPARAM
3566 1.114 mjacob * arenas because the resolutions here aren't synchronized.
3567 1.114 mjacob * The best way to do this is to exclude looking at portids
3568 1.114 mjacob * that have the same domain and area code as our own
3569 1.114 mjacob * portid.
3570 1.37 mjacob */
3571 1.114 mjacob if (ISP_CAP_MULTI_ID(isp)) {
3572 1.114 mjacob if ((portid >> 8) == (fcp->isp_portid >> 8)) {
3573 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG,
3574 1.114 mjacob "Chan %d skip PortID 0x%06x",
3575 1.114 mjacob chan, portid);
3576 1.114 mjacob continue;
3577 1.114 mjacob }
3578 1.114 mjacob } else if (portid == fcp->isp_portid) {
3579 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG,
3580 1.114 mjacob "Chan %d skip ourselves on @ PortID 0x%06x",
3581 1.114 mjacob chan, portid);
3582 1.37 mjacob continue;
3583 1.69 mjacob }
3584 1.114 mjacob
3585 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG,
3586 1.114 mjacob "Chan %d Checking Fabric Port 0x%06x", chan, portid);
3587 1.50 mjacob
3588 1.37 mjacob /*
3589 1.111 mjacob * We now search our Port Database for any
3590 1.111 mjacob * probational entries with this PortID. We don't
3591 1.111 mjacob * look for zombies here- only probational
3592 1.111 mjacob * entries (we've already logged out of zombies).
3593 1.70 mjacob */
3594 1.111 mjacob for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
3595 1.111 mjacob lp = &fcp->portdb[dbidx];
3596 1.111 mjacob
3597 1.114 mjacob if (lp->state != FC_PORTDB_STATE_PROBATIONAL ||
3598 1.114 mjacob lp->target_mode) {
3599 1.70 mjacob continue;
3600 1.70 mjacob }
3601 1.111 mjacob if (lp->portid == portid) {
3602 1.111 mjacob break;
3603 1.111 mjacob }
3604 1.70 mjacob }
3605 1.70 mjacob
3606 1.70 mjacob /*
3607 1.111 mjacob * We found a probational entry with this Port ID.
3608 1.37 mjacob */
3609 1.111 mjacob if (dbidx < MAX_FC_TARG) {
3610 1.111 mjacob int handle_changed = 0;
3611 1.70 mjacob
3612 1.111 mjacob lp = &fcp->portdb[dbidx];
3613 1.37 mjacob
3614 1.111 mjacob /*
3615 1.111 mjacob * See if we're still logged into it.
3616 1.111 mjacob *
3617 1.111 mjacob * If we aren't, mark it as a dead device and
3618 1.111 mjacob * leave the new portid in the database entry
3619 1.111 mjacob * for somebody further along to decide what to
3620 1.111 mjacob * do (policy choice).
3621 1.111 mjacob *
3622 1.111 mjacob * If we are, check to see if it's the same
3623 1.111 mjacob * device still (it should be). If for some
3624 1.111 mjacob * reason it isn't, mark it as a changed device
3625 1.111 mjacob * and leave the new portid and role in the
3626 1.111 mjacob * database entry for somebody further along to
3627 1.111 mjacob * decide what to do (policy choice).
3628 1.111 mjacob *
3629 1.111 mjacob */
3630 1.52 he
3631 1.114 mjacob r = isp_getpdb(isp, chan, lp->handle, &pdb, 0);
3632 1.111 mjacob if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
3633 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3634 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3635 1.111 mjacob return (-1);
3636 1.111 mjacob }
3637 1.111 mjacob if (r != 0) {
3638 1.111 mjacob lp->new_portid = portid;
3639 1.111 mjacob lp->state = FC_PORTDB_STATE_DEAD;
3640 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3641 1.114 mjacob "Chan %d Fabric Port 0x%06x is dead",
3642 1.114 mjacob chan, portid);
3643 1.111 mjacob continue;
3644 1.111 mjacob }
3645 1.52 he
3646 1.37 mjacob
3647 1.70 mjacob /*
3648 1.111 mjacob * Check to make sure that handle, portid, WWPN and
3649 1.111 mjacob * WWNN agree. If they don't, then the association
3650 1.111 mjacob * between this PortID and the stated handle has been
3651 1.111 mjacob * broken by the firmware.
3652 1.70 mjacob */
3653 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
3654 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
3655 1.111 mjacob if (pdb.handle != lp->handle ||
3656 1.111 mjacob pdb.portid != portid ||
3657 1.111 mjacob wwpn != lp->port_wwn ||
3658 1.111 mjacob wwnn != lp->node_wwn) {
3659 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3660 1.114 mjacob fconf, chan, dbidx, pdb.handle, pdb.portid,
3661 1.111 mjacob (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
3662 1.111 mjacob (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
3663 1.111 mjacob lp->handle, portid,
3664 1.111 mjacob (uint32_t) (lp->node_wwn >> 32),
3665 1.111 mjacob (uint32_t) lp->node_wwn,
3666 1.111 mjacob (uint32_t) (lp->port_wwn >> 32),
3667 1.111 mjacob (uint32_t) lp->port_wwn);
3668 1.111 mjacob /*
3669 1.111 mjacob * Try to re-login to this device using a
3670 1.111 mjacob * new handle. If that fails, mark it dead.
3671 1.117 mjacob *
3672 1.111 mjacob * isp_login_device will check for handle and
3673 1.111 mjacob * portid consistency after re-login.
3674 1.117 mjacob *
3675 1.111 mjacob */
3676 1.114 mjacob if (isp_login_device(isp, chan, portid, &pdb,
3677 1.111 mjacob &oldhandle)) {
3678 1.111 mjacob lp->new_portid = portid;
3679 1.111 mjacob lp->state = FC_PORTDB_STATE_DEAD;
3680 1.111 mjacob if (fcp->isp_loopstate !=
3681 1.111 mjacob LOOP_SCANNING_FABRIC) {
3682 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3683 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3684 1.111 mjacob return (-1);
3685 1.111 mjacob }
3686 1.111 mjacob continue;
3687 1.111 mjacob }
3688 1.114 mjacob if (fcp->isp_loopstate !=
3689 1.114 mjacob LOOP_SCANNING_FABRIC) {
3690 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3691 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3692 1.114 mjacob return (-1);
3693 1.114 mjacob }
3694 1.114 mjacob FCPARAM(isp, 0)->isp_lasthdl = oldhandle;
3695 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
3696 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
3697 1.111 mjacob if (wwpn != lp->port_wwn ||
3698 1.111 mjacob wwnn != lp->node_wwn) {
3699 1.111 mjacob isp_prt(isp, ISP_LOGWARN, "changed WWN"
3700 1.111 mjacob " after relogin");
3701 1.111 mjacob lp->new_portid = portid;
3702 1.111 mjacob lp->state = FC_PORTDB_STATE_DEAD;
3703 1.111 mjacob continue;
3704 1.111 mjacob }
3705 1.111 mjacob
3706 1.111 mjacob lp->handle = pdb.handle;
3707 1.111 mjacob handle_changed++;
3708 1.111 mjacob }
3709 1.111 mjacob
3710 1.111 mjacob nr = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
3711 1.70 mjacob
3712 1.70 mjacob /*
3713 1.111 mjacob * Check to see whether the portid and roles have
3714 1.111 mjacob * stayed the same. If they have stayed the same,
3715 1.111 mjacob * we believe that this is the same device and it
3716 1.111 mjacob * hasn't become disconnected and reconnected, so
3717 1.111 mjacob * mark it as pending valid.
3718 1.111 mjacob *
3719 1.111 mjacob * If they aren't the same, mark the device as a
3720 1.111 mjacob * changed device and save the new port id and role
3721 1.111 mjacob * and let somebody else decide.
3722 1.70 mjacob */
3723 1.111 mjacob
3724 1.111 mjacob lp->new_portid = portid;
3725 1.111 mjacob lp->new_roles = nr;
3726 1.111 mjacob if (pdb.portid != lp->portid || nr != lp->roles ||
3727 1.111 mjacob handle_changed) {
3728 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG,
3729 1.114 mjacob "Chan %d Fabric Port 0x%06x changed",
3730 1.114 mjacob chan, portid);
3731 1.111 mjacob lp->state = FC_PORTDB_STATE_CHANGED;
3732 1.111 mjacob } else {
3733 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG,
3734 1.114 mjacob "Chan %d Fabric Port 0x%06x "
3735 1.114 mjacob "Now Pending Valid", chan, portid);
3736 1.111 mjacob lp->state = FC_PORTDB_STATE_PENDING_VALID;
3737 1.111 mjacob }
3738 1.111 mjacob continue;
3739 1.111 mjacob }
3740 1.111 mjacob
3741 1.111 mjacob /*
3742 1.111 mjacob * Ah- a new entry. Search the database again for all non-NIL
3743 1.111 mjacob * entries to make sure we never ever make a new database entry
3744 1.111 mjacob * with the same port id. While we're at it, mark where the
3745 1.111 mjacob * last free entry was.
3746 1.111 mjacob */
3747 1.117 mjacob
3748 1.111 mjacob dbidx = MAX_FC_TARG;
3749 1.111 mjacob for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
3750 1.111 mjacob if (lp >= &fcp->portdb[FL_ID] &&
3751 1.111 mjacob lp <= &fcp->portdb[SNS_ID]) {
3752 1.111 mjacob continue;
3753 1.111 mjacob }
3754 1.114 mjacob /*
3755 1.114 mjacob * Skip any target mode entries.
3756 1.114 mjacob */
3757 1.114 mjacob if (lp->target_mode) {
3758 1.114 mjacob continue;
3759 1.114 mjacob }
3760 1.111 mjacob if (lp->state == FC_PORTDB_STATE_NIL) {
3761 1.111 mjacob if (dbidx == MAX_FC_TARG) {
3762 1.111 mjacob dbidx = lp - fcp->portdb;
3763 1.70 mjacob }
3764 1.111 mjacob continue;
3765 1.111 mjacob }
3766 1.111 mjacob if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
3767 1.111 mjacob continue;
3768 1.111 mjacob }
3769 1.111 mjacob if (lp->portid == portid) {
3770 1.111 mjacob break;
3771 1.38 mjacob }
3772 1.70 mjacob }
3773 1.52 he
3774 1.111 mjacob if (lp < &fcp->portdb[MAX_FC_TARG]) {
3775 1.114 mjacob isp_prt(isp, ISP_LOGWARN, "Chan %d PortID 0x%06x "
3776 1.114 mjacob "already at %d handle %d state %d",
3777 1.114 mjacob chan, portid, dbidx, lp->handle, lp->state);
3778 1.43 mjacob continue;
3779 1.52 he }
3780 1.43 mjacob
3781 1.52 he /*
3782 1.111 mjacob * We should have the index of the first free entry seen.
3783 1.52 he */
3784 1.111 mjacob if (dbidx == MAX_FC_TARG) {
3785 1.111 mjacob isp_prt(isp, ISP_LOGERR,
3786 1.111 mjacob "port database too small to login PortID 0x%06x"
3787 1.111 mjacob "- increase MAX_FC_TARG", portid);
3788 1.111 mjacob continue;
3789 1.43 mjacob }
3790 1.52 he
3791 1.70 mjacob /*
3792 1.111 mjacob * Otherwise, point to our new home.
3793 1.70 mjacob */
3794 1.111 mjacob lp = &fcp->portdb[dbidx];
3795 1.70 mjacob
3796 1.70 mjacob /*
3797 1.111 mjacob * Try to see if we are logged into this device,
3798 1.111 mjacob * and maybe log into it.
3799 1.111 mjacob *
3800 1.111 mjacob * isp_login_device will check for handle and
3801 1.111 mjacob * portid consistency after login.
3802 1.70 mjacob */
3803 1.114 mjacob if (isp_login_device(isp, chan, portid, &pdb, &oldhandle)) {
3804 1.111 mjacob if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
3805 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3806 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3807 1.111 mjacob return (-1);
3808 1.111 mjacob }
3809 1.70 mjacob continue;
3810 1.43 mjacob }
3811 1.114 mjacob if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
3812 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3813 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3814 1.114 mjacob return (-1);
3815 1.114 mjacob }
3816 1.114 mjacob FCPARAM(isp, 0)->isp_lasthdl = oldhandle;
3817 1.52 he
3818 1.111 mjacob handle = pdb.handle;
3819 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
3820 1.111 mjacob MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
3821 1.111 mjacob nr = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
3822 1.111 mjacob
3823 1.43 mjacob /*
3824 1.111 mjacob * And go through the database *one* more time to make sure
3825 1.111 mjacob * that we do not make more than one entry that has the same
3826 1.111 mjacob * WWNN/WWPN duple
3827 1.43 mjacob */
3828 1.111 mjacob for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
3829 1.111 mjacob if (dbidx >= FL_ID && dbidx <= SNS_ID) {
3830 1.111 mjacob continue;
3831 1.111 mjacob }
3832 1.114 mjacob if (fcp->portdb[dbidx].target_mode) {
3833 1.111 mjacob continue;
3834 1.111 mjacob }
3835 1.111 mjacob if (fcp->portdb[dbidx].node_wwn == wwnn &&
3836 1.111 mjacob fcp->portdb[dbidx].port_wwn == wwpn) {
3837 1.91 mjacob break;
3838 1.91 mjacob }
3839 1.91 mjacob }
3840 1.91 mjacob
3841 1.111 mjacob if (dbidx == MAX_FC_TARG) {
3842 1.117 mjacob ISP_MEMZERO(lp, sizeof (fcportdb_t));
3843 1.111 mjacob lp->handle = handle;
3844 1.111 mjacob lp->node_wwn = wwnn;
3845 1.111 mjacob lp->port_wwn = wwpn;
3846 1.111 mjacob lp->new_portid = portid;
3847 1.111 mjacob lp->new_roles = nr;
3848 1.111 mjacob lp->state = FC_PORTDB_STATE_NEW;
3849 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG,
3850 1.114 mjacob "Chan %d Fabric Port 0x%06x is a New Entry",
3851 1.114 mjacob chan, portid);
3852 1.111 mjacob continue;
3853 1.111 mjacob }
3854 1.91 mjacob
3855 1.111 mjacob if (fcp->portdb[dbidx].state != FC_PORTDB_STATE_ZOMBIE) {
3856 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
3857 1.114 mjacob "Chan %d PortID 0x%x 0x%08x%08x/0x%08x%08x %ld "
3858 1.114 mjacob "already at idx %d, state 0x%x", chan, portid,
3859 1.111 mjacob (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
3860 1.111 mjacob (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
3861 1.111 mjacob (long) (lp - fcp->portdb), dbidx,
3862 1.111 mjacob fcp->portdb[dbidx].state);
3863 1.111 mjacob continue;
3864 1.37 mjacob }
3865 1.91 mjacob
3866 1.91 mjacob /*
3867 1.111 mjacob * We found a zombie entry that matches us.
3868 1.111 mjacob * Revive it. We know that WWN and WWPN
3869 1.111 mjacob * are the same. For fabric devices, we
3870 1.111 mjacob * don't care that handle is different
3871 1.111 mjacob * as we assign that. If role or portid
3872 1.111 mjacob * are different, it maybe a changed device.
3873 1.111 mjacob */
3874 1.111 mjacob lp = &fcp->portdb[dbidx];
3875 1.111 mjacob lp->handle = handle;
3876 1.111 mjacob lp->new_portid = portid;
3877 1.111 mjacob lp->new_roles = nr;
3878 1.111 mjacob if (lp->portid != portid || lp->roles != nr) {
3879 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3880 1.114 mjacob "Chan %d Zombie Fabric Port 0x%06x Now Changed",
3881 1.114 mjacob chan, portid);
3882 1.111 mjacob lp->state = FC_PORTDB_STATE_CHANGED;
3883 1.82 mjacob } else {
3884 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3885 1.114 mjacob "Chan %d Zombie Fabric Port 0x%06x "
3886 1.114 mjacob "Now Pending Valid", chan, portid);
3887 1.111 mjacob lp->state = FC_PORTDB_STATE_PENDING_VALID;
3888 1.82 mjacob }
3889 1.37 mjacob }
3890 1.111 mjacob
3891 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
3892 1.111 mjacob if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
3893 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
3894 1.111 mjacob return (-1);
3895 1.91 mjacob }
3896 1.91 mjacob fcp->isp_loopstate = LOOP_FSCAN_DONE;
3897 1.114 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3898 1.114 mjacob "Chan %d FC Scan Fabric Done", chan);
3899 1.91 mjacob return (0);
3900 1.91 mjacob }
3901 1.70 mjacob
3902 1.111 mjacob /*
3903 1.111 mjacob * Find an unused handle and try and use to login to a port.
3904 1.111 mjacob */
3905 1.91 mjacob static int
3906 1.114 mjacob isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p,
3907 1.114 mjacob uint16_t *ohp)
3908 1.91 mjacob {
3909 1.111 mjacob int lim, i, r;
3910 1.111 mjacob uint16_t handle;
3911 1.91 mjacob
3912 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
3913 1.111 mjacob lim = NPH_MAX_2K;
3914 1.111 mjacob } else {
3915 1.111 mjacob lim = NPH_MAX;
3916 1.82 mjacob }
3917 1.70 mjacob
3918 1.114 mjacob handle = isp_nxt_handle(isp, chan, *ohp);
3919 1.111 mjacob for (i = 0; i < lim; i++) {
3920 1.111 mjacob /*
3921 1.111 mjacob * See if we're still logged into something with
3922 1.111 mjacob * this handle and that something agrees with this
3923 1.111 mjacob * port id.
3924 1.111 mjacob */
3925 1.114 mjacob r = isp_getpdb(isp, chan, handle, p, 0);
3926 1.111 mjacob if (r == 0 && p->portid != portid) {
3927 1.114 mjacob (void) isp_plogx(isp, chan, handle, portid,
3928 1.111 mjacob PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT, 1);
3929 1.111 mjacob } else if (r == 0) {
3930 1.111 mjacob break;
3931 1.91 mjacob }
3932 1.114 mjacob if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
3933 1.92 mjacob return (-1);
3934 1.92 mjacob }
3935 1.111 mjacob /*
3936 1.111 mjacob * Now try and log into the device
3937 1.111 mjacob */
3938 1.114 mjacob r = isp_plogx(isp, chan, handle, portid,
3939 1.114 mjacob PLOGX_FLG_CMD_PLOGI, 1);
3940 1.114 mjacob if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
3941 1.92 mjacob return (-1);
3942 1.92 mjacob }
3943 1.111 mjacob if (r == 0) {
3944 1.111 mjacob *ohp = handle;
3945 1.111 mjacob break;
3946 1.111 mjacob } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
3947 1.111 mjacob handle = r >> 16;
3948 1.111 mjacob break;
3949 1.111 mjacob } else if (r != MBOX_LOOP_ID_USED) {
3950 1.111 mjacob i = lim;
3951 1.111 mjacob break;
3952 1.115 mjacob } else if (r == MBOX_TIMEOUT) {
3953 1.115 mjacob return (-1);
3954 1.92 mjacob } else {
3955 1.111 mjacob *ohp = handle;
3956 1.114 mjacob handle = isp_nxt_handle(isp, chan, *ohp);
3957 1.92 mjacob }
3958 1.111 mjacob }
3959 1.91 mjacob
3960 1.111 mjacob if (i == lim) {
3961 1.114 mjacob isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed",
3962 1.114 mjacob chan, portid);
3963 1.111 mjacob return (-1);
3964 1.111 mjacob }
3965 1.91 mjacob
3966 1.91 mjacob /*
3967 1.111 mjacob * If we successfully logged into it, get the PDB for it
3968 1.111 mjacob * so we can crosscheck that it is still what we think it
3969 1.111 mjacob * is and that we also have the role it plays
3970 1.91 mjacob */
3971 1.114 mjacob r = isp_getpdb(isp, chan, handle, p, 0);
3972 1.114 mjacob if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
3973 1.111 mjacob return (-1);
3974 1.111 mjacob }
3975 1.111 mjacob if (r != 0) {
3976 1.114 mjacob isp_prt(isp, ISP_LOGERR,
3977 1.114 mjacob "Chan %d new device 0x%06x@0x%x disappeared",
3978 1.114 mjacob chan, portid, handle);
3979 1.111 mjacob return (-1);
3980 1.91 mjacob }
3981 1.91 mjacob
3982 1.111 mjacob if (p->handle != handle || p->portid != portid) {
3983 1.111 mjacob isp_prt(isp, ISP_LOGERR,
3984 1.114 mjacob "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
3985 1.114 mjacob chan, portid, handle, p->portid, p->handle);
3986 1.111 mjacob return (-1);
3987 1.111 mjacob }
3988 1.37 mjacob return (0);
3989 1.37 mjacob }
3990 1.69 mjacob
3991 1.111 mjacob static int
3992 1.114 mjacob isp_register_fc4_type(ispsoftc_t *isp, int chan)
3993 1.69 mjacob {
3994 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
3995 1.111 mjacob uint8_t local[SNS_RFT_ID_REQ_SIZE];
3996 1.86 mjacob sns_screq_t *reqp = (sns_screq_t *) local;
3997 1.69 mjacob mbreg_t mbs;
3998 1.69 mjacob
3999 1.117 mjacob ISP_MEMZERO((void *) reqp, SNS_RFT_ID_REQ_SIZE);
4000 1.91 mjacob reqp->snscb_rblen = SNS_RFT_ID_RESP_SIZE >> 1;
4001 1.79 mjacob reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100);
4002 1.79 mjacob reqp->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + 0x100);
4003 1.79 mjacob reqp->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + 0x100);
4004 1.79 mjacob reqp->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + 0x100);
4005 1.69 mjacob reqp->snscb_sblen = 22;
4006 1.91 mjacob reqp->snscb_data[0] = SNS_RFT_ID;
4007 1.69 mjacob reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
4008 1.69 mjacob reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff;
4009 1.91 mjacob reqp->snscb_data[6] = (1 << FC4_SCSI);
4010 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, chan)) {
4011 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
4012 1.115 mjacob return (-1);
4013 1.115 mjacob }
4014 1.86 mjacob isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch);
4015 1.117 mjacob MBSINIT(&mbs, MBOX_SEND_SNS, MBLOGALL, 1000000);
4016 1.91 mjacob mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1;
4017 1.79 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma);
4018 1.79 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma);
4019 1.79 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma);
4020 1.79 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma);
4021 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_RFT_ID_REQ_SIZE);
4022 1.111 mjacob isp_mboxcmd(isp, &mbs);
4023 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
4024 1.69 mjacob if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
4025 1.111 mjacob return (0);
4026 1.111 mjacob } else {
4027 1.111 mjacob return (-1);
4028 1.111 mjacob }
4029 1.111 mjacob }
4030 1.111 mjacob
4031 1.111 mjacob static int
4032 1.114 mjacob isp_register_fc4_type_24xx(ispsoftc_t *isp, int chan)
4033 1.111 mjacob {
4034 1.111 mjacob mbreg_t mbs;
4035 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
4036 1.111 mjacob union {
4037 1.111 mjacob isp_ct_pt_t plocal;
4038 1.111 mjacob rft_id_t clocal;
4039 1.111 mjacob uint8_t q[QENTRY_LEN];
4040 1.111 mjacob } un;
4041 1.111 mjacob isp_ct_pt_t *pt;
4042 1.111 mjacob ct_hdr_t *ct;
4043 1.111 mjacob rft_id_t *rp;
4044 1.111 mjacob uint8_t *scp = fcp->isp_scratch;
4045 1.111 mjacob
4046 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, chan)) {
4047 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
4048 1.115 mjacob return (-1);
4049 1.115 mjacob }
4050 1.114 mjacob
4051 1.111 mjacob /*
4052 1.111 mjacob * Build a Passthrough IOCB in memory.
4053 1.111 mjacob */
4054 1.117 mjacob ISP_MEMZERO(un.q, QENTRY_LEN);
4055 1.111 mjacob pt = &un.plocal;
4056 1.111 mjacob pt->ctp_header.rqs_entry_count = 1;
4057 1.111 mjacob pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
4058 1.111 mjacob pt->ctp_handle = 0xffffffff;
4059 1.114 mjacob pt->ctp_nphdl = fcp->isp_sns_hdl;
4060 1.111 mjacob pt->ctp_cmd_cnt = 1;
4061 1.117 mjacob pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan);
4062 1.111 mjacob pt->ctp_time = 1;
4063 1.111 mjacob pt->ctp_rsp_cnt = 1;
4064 1.111 mjacob pt->ctp_rsp_bcnt = sizeof (ct_hdr_t);
4065 1.111 mjacob pt->ctp_cmd_bcnt = sizeof (rft_id_t);
4066 1.111 mjacob pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
4067 1.111 mjacob pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
4068 1.111 mjacob pt->ctp_dataseg[0].ds_count = sizeof (rft_id_t);
4069 1.111 mjacob pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF);
4070 1.111 mjacob pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF);
4071 1.111 mjacob pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t);
4072 1.111 mjacob isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]);
4073 1.114 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
4074 1.114 mjacob isp_print_bytes(isp, "IOCB CT Request", QENTRY_LEN, pt);
4075 1.114 mjacob }
4076 1.111 mjacob
4077 1.111 mjacob /*
4078 1.111 mjacob * Build the CT header and command in memory.
4079 1.111 mjacob *
4080 1.111 mjacob * Note that the CT header has to end up as Big Endian format in memory.
4081 1.111 mjacob */
4082 1.117 mjacob ISP_MEMZERO(&un.clocal, sizeof (un.clocal));
4083 1.111 mjacob ct = &un.clocal.rftid_hdr;
4084 1.111 mjacob ct->ct_revision = CT_REVISION;
4085 1.111 mjacob ct->ct_fcs_type = CT_FC_TYPE_FC;
4086 1.111 mjacob ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
4087 1.111 mjacob ct->ct_cmd_resp = SNS_RFT_ID;
4088 1.111 mjacob ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2;
4089 1.111 mjacob rp = &un.clocal;
4090 1.111 mjacob rp->rftid_portid[0] = fcp->isp_portid >> 16;
4091 1.111 mjacob rp->rftid_portid[1] = fcp->isp_portid >> 8;
4092 1.111 mjacob rp->rftid_portid[2] = fcp->isp_portid;
4093 1.111 mjacob rp->rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
4094 1.111 mjacob isp_put_rft_id(isp, rp, (rft_id_t *) &scp[XTXOFF]);
4095 1.114 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
4096 1.114 mjacob isp_print_bytes(isp, "CT Header", QENTRY_LEN, &scp[XTXOFF]);
4097 1.114 mjacob }
4098 1.111 mjacob
4099 1.117 mjacob ISP_MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t));
4100 1.111 mjacob
4101 1.117 mjacob MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 1000000);
4102 1.111 mjacob mbs.param[1] = QENTRY_LEN;
4103 1.111 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
4104 1.111 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
4105 1.111 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
4106 1.111 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
4107 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN);
4108 1.111 mjacob isp_mboxcmd(isp, &mbs);
4109 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
4110 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
4111 1.111 mjacob return (-1);
4112 1.111 mjacob }
4113 1.111 mjacob MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN);
4114 1.111 mjacob pt = &un.plocal;
4115 1.111 mjacob isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt);
4116 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
4117 1.111 mjacob isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt);
4118 1.111 mjacob }
4119 1.111 mjacob if (pt->ctp_status) {
4120 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
4121 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
4122 1.114 mjacob "Chan %d Register FC4 Type CT Passthrough returned 0x%x",
4123 1.114 mjacob chan, pt->ctp_status);
4124 1.114 mjacob return (1);
4125 1.111 mjacob }
4126 1.111 mjacob
4127 1.111 mjacob isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct);
4128 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
4129 1.111 mjacob
4130 1.111 mjacob if (ct->ct_cmd_resp == LS_RJT) {
4131 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
4132 1.114 mjacob "Chan %d Register FC4 Type rejected", chan);
4133 1.111 mjacob return (-1);
4134 1.111 mjacob } else if (ct->ct_cmd_resp == LS_ACC) {
4135 1.111 mjacob isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
4136 1.114 mjacob "Chan %d Register FC4 Type accepted", chan);
4137 1.117 mjacob return (0);
4138 1.111 mjacob } else {
4139 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
4140 1.114 mjacob "Chan %d Register FC4 Type: 0x%x",
4141 1.114 mjacob chan, ct->ct_cmd_resp);
4142 1.111 mjacob return (-1);
4143 1.111 mjacob }
4144 1.111 mjacob }
4145 1.111 mjacob
4146 1.111 mjacob static uint16_t
4147 1.114 mjacob isp_nxt_handle(ispsoftc_t *isp, int chan, uint16_t handle)
4148 1.111 mjacob {
4149 1.111 mjacob int i;
4150 1.111 mjacob if (handle == NIL_HANDLE) {
4151 1.114 mjacob if (FCPARAM(isp, chan)->isp_topo == TOPO_F_PORT) {
4152 1.111 mjacob handle = 0;
4153 1.111 mjacob } else {
4154 1.111 mjacob handle = SNS_ID+1;
4155 1.111 mjacob }
4156 1.111 mjacob } else {
4157 1.111 mjacob handle += 1;
4158 1.111 mjacob if (handle >= FL_ID && handle <= SNS_ID) {
4159 1.111 mjacob handle = SNS_ID+1;
4160 1.111 mjacob }
4161 1.111 mjacob if (handle >= NPH_RESERVED && handle <= NPH_FL_ID) {
4162 1.111 mjacob handle = NPH_FL_ID+1;
4163 1.111 mjacob }
4164 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
4165 1.111 mjacob if (handle == NPH_MAX_2K) {
4166 1.111 mjacob handle = 0;
4167 1.111 mjacob }
4168 1.111 mjacob } else {
4169 1.111 mjacob if (handle == NPH_MAX) {
4170 1.111 mjacob handle = 0;
4171 1.111 mjacob }
4172 1.111 mjacob }
4173 1.111 mjacob }
4174 1.114 mjacob if (handle == FCPARAM(isp, chan)->isp_loopid) {
4175 1.114 mjacob return (isp_nxt_handle(isp, chan, handle));
4176 1.111 mjacob }
4177 1.111 mjacob for (i = 0; i < MAX_FC_TARG; i++) {
4178 1.114 mjacob if (FCPARAM(isp, chan)->portdb[i].state ==
4179 1.114 mjacob FC_PORTDB_STATE_NIL) {
4180 1.111 mjacob continue;
4181 1.111 mjacob }
4182 1.114 mjacob if (FCPARAM(isp, chan)->portdb[i].handle == handle) {
4183 1.114 mjacob return (isp_nxt_handle(isp, chan, handle));
4184 1.111 mjacob }
4185 1.69 mjacob }
4186 1.111 mjacob return (handle);
4187 1.69 mjacob }
4188 1.70 mjacob
4189 1.37 mjacob /*
4190 1.23 mjacob * Start a command. Locking is assumed done in the caller.
4191 1.1 cgd */
4192 1.23 mjacob
4193 1.57 mjacob int
4194 1.73 mjacob isp_start(XS_T *xs)
4195 1.1 cgd {
4196 1.111 mjacob ispsoftc_t *isp;
4197 1.117 mjacob uint32_t handle;
4198 1.111 mjacob uint8_t local[QENTRY_LEN];
4199 1.117 mjacob ispreq_t *reqp;
4200 1.117 mjacob void *cdbp, *qep;
4201 1.111 mjacob uint16_t *tptr;
4202 1.117 mjacob int target, dmaresult, hdlidx = 0;
4203 1.1 cgd
4204 1.23 mjacob XS_INITERR(xs);
4205 1.23 mjacob isp = XS_ISP(xs);
4206 1.70 mjacob
4207 1.70 mjacob /*
4208 1.70 mjacob * Now make sure we're running.
4209 1.70 mjacob */
4210 1.70 mjacob
4211 1.24 mjacob if (isp->isp_state != ISP_RUNSTATE) {
4212 1.57 mjacob isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
4213 1.24 mjacob XS_SETERR(xs, HBA_BOTCH);
4214 1.24 mjacob return (CMD_COMPLETE);
4215 1.24 mjacob }
4216 1.24 mjacob
4217 1.25 mjacob /*
4218 1.50 mjacob * Check command CDB length, etc.. We really are limited to 16 bytes
4219 1.50 mjacob * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
4220 1.50 mjacob * but probably only if we're running fairly new firmware (we'll
4221 1.50 mjacob * let the old f/w choke on an extended command queue entry).
4222 1.25 mjacob */
4223 1.33 mjacob
4224 1.50 mjacob if (XS_CDBLEN(xs) > (IS_FC(isp)? 16 : 44) || XS_CDBLEN(xs) == 0) {
4225 1.117 mjacob isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
4226 1.25 mjacob XS_SETERR(xs, HBA_BOTCH);
4227 1.25 mjacob return (CMD_COMPLETE);
4228 1.25 mjacob }
4229 1.25 mjacob
4230 1.25 mjacob /*
4231 1.111 mjacob * Translate the target to device handle as appropriate, checking
4232 1.111 mjacob * for correct device state as well.
4233 1.33 mjacob */
4234 1.37 mjacob target = XS_TGT(xs);
4235 1.33 mjacob if (IS_FC(isp)) {
4236 1.114 mjacob fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
4237 1.114 mjacob
4238 1.114 mjacob if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
4239 1.114 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
4240 1.114 mjacob return (CMD_COMPLETE);
4241 1.114 mjacob }
4242 1.111 mjacob
4243 1.111 mjacob /*
4244 1.111 mjacob * Try again later.
4245 1.111 mjacob */
4246 1.117 mjacob if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) {
4247 1.73 mjacob return (CMD_RQLATER);
4248 1.73 mjacob }
4249 1.73 mjacob
4250 1.111 mjacob if (XS_TGT(xs) >= MAX_FC_TARG) {
4251 1.111 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
4252 1.111 mjacob return (CMD_COMPLETE);
4253 1.37 mjacob }
4254 1.37 mjacob
4255 1.117 mjacob hdlidx = fcp->isp_dev_map[XS_TGT(xs)] - 1;
4256 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d- hdlidx value %d", XS_TGT(xs), hdlidx);
4257 1.111 mjacob if (hdlidx < 0 || hdlidx >= MAX_FC_TARG) {
4258 1.37 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
4259 1.111 mjacob return (CMD_COMPLETE);
4260 1.37 mjacob }
4261 1.111 mjacob if (fcp->portdb[hdlidx].state == FC_PORTDB_STATE_ZOMBIE) {
4262 1.70 mjacob return (CMD_RQLATER);
4263 1.70 mjacob }
4264 1.111 mjacob if (fcp->portdb[hdlidx].state != FC_PORTDB_STATE_VALID) {
4265 1.37 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
4266 1.37 mjacob return (CMD_COMPLETE);
4267 1.33 mjacob }
4268 1.111 mjacob target = fcp->portdb[hdlidx].handle;
4269 1.117 mjacob fcp->portdb[hdlidx].dirty = 1;
4270 1.114 mjacob } else {
4271 1.114 mjacob sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
4272 1.114 mjacob if ((sdp->role & ISP_ROLE_INITIATOR) == 0) {
4273 1.114 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
4274 1.114 mjacob return (CMD_COMPLETE);
4275 1.114 mjacob }
4276 1.114 mjacob if (sdp->update) {
4277 1.114 mjacob isp_spi_update(isp, XS_CHANNEL(xs));
4278 1.114 mjacob }
4279 1.10 mjacob }
4280 1.25 mjacob
4281 1.111 mjacob start_again:
4282 1.111 mjacob
4283 1.117 mjacob qep = isp_getrqentry(isp);
4284 1.117 mjacob if (qep == NULL) {
4285 1.57 mjacob isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow");
4286 1.23 mjacob XS_SETERR(xs, HBA_BOTCH);
4287 1.23 mjacob return (CMD_EAGAIN);
4288 1.1 cgd }
4289 1.117 mjacob XS_SETERR(xs, HBA_NOERROR);
4290 1.13 mjacob
4291 1.36 mjacob /*
4292 1.36 mjacob * Now see if we need to synchronize the ISP with respect to anything.
4293 1.36 mjacob * We do dual duty here (cough) for synchronizing for busses other
4294 1.36 mjacob * than which we got here to send a command to.
4295 1.36 mjacob */
4296 1.86 mjacob reqp = (ispreq_t *) local;
4297 1.117 mjacob ISP_MEMZERO(local, QENTRY_LEN);
4298 1.114 mjacob if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
4299 1.111 mjacob if (IS_24XX(isp)) {
4300 1.117 mjacob isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
4301 1.111 mjacob m->mrk_header.rqs_entry_count = 1;
4302 1.111 mjacob m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
4303 1.111 mjacob m->mrk_modifier = SYNC_ALL;
4304 1.117 mjacob isp_put_marker_24xx(isp, m, qep);
4305 1.114 mjacob } else {
4306 1.117 mjacob isp_marker_t *m = (isp_marker_t *) reqp;
4307 1.114 mjacob m->mrk_header.rqs_entry_count = 1;
4308 1.114 mjacob m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
4309 1.114 mjacob m->mrk_target = (XS_CHANNEL(xs) << 7); /* bus # */
4310 1.114 mjacob m->mrk_modifier = SYNC_ALL;
4311 1.117 mjacob isp_put_marker(isp, m, qep);
4312 1.1 cgd }
4313 1.117 mjacob ISP_SYNC_REQUEST(isp);
4314 1.114 mjacob ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
4315 1.114 mjacob goto start_again;
4316 1.1 cgd }
4317 1.1 cgd
4318 1.10 mjacob reqp->req_header.rqs_entry_count = 1;
4319 1.111 mjacob if (IS_24XX(isp)) {
4320 1.111 mjacob reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
4321 1.111 mjacob } else if (IS_FC(isp)) {
4322 1.10 mjacob reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
4323 1.10 mjacob } else {
4324 1.117 mjacob if (XS_CDBLEN(xs) > 12) {
4325 1.50 mjacob reqp->req_header.rqs_entry_type = RQSTYPE_CMDONLY;
4326 1.117 mjacob } else {
4327 1.50 mjacob reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST;
4328 1.117 mjacob }
4329 1.10 mjacob }
4330 1.83 mjacob /* reqp->req_header.rqs_flags = 0; */
4331 1.83 mjacob /* reqp->req_header.rqs_seqno = 0; */
4332 1.111 mjacob if (IS_24XX(isp)) {
4333 1.111 mjacob int ttype;
4334 1.111 mjacob if (XS_TAG_P(xs)) {
4335 1.111 mjacob ttype = XS_TAG_TYPE(xs);
4336 1.111 mjacob } else {
4337 1.111 mjacob if (XS_CDBP(xs)[0] == 0x3) {
4338 1.111 mjacob ttype = REQFLAG_HTAG;
4339 1.111 mjacob } else {
4340 1.111 mjacob ttype = REQFLAG_STAG;
4341 1.111 mjacob }
4342 1.111 mjacob }
4343 1.111 mjacob if (ttype == REQFLAG_OTAG) {
4344 1.111 mjacob ttype = FCP_CMND_TASK_ATTR_ORDERED;
4345 1.111 mjacob } else if (ttype == REQFLAG_HTAG) {
4346 1.111 mjacob ttype = FCP_CMND_TASK_ATTR_HEAD;
4347 1.111 mjacob } else {
4348 1.111 mjacob ttype = FCP_CMND_TASK_ATTR_SIMPLE;
4349 1.111 mjacob }
4350 1.111 mjacob ((ispreqt7_t *)reqp)->req_task_attribute = ttype;
4351 1.111 mjacob } else if (IS_FC(isp)) {
4352 1.10 mjacob /*
4353 1.10 mjacob * See comment in isp_intr
4354 1.10 mjacob */
4355 1.117 mjacob /* XS_SET_RESID(xs, 0); */
4356 1.34 mjacob
4357 1.10 mjacob /*
4358 1.42 mjacob * Fibre Channel always requires some kind of tag.
4359 1.42 mjacob * The Qlogic drivers seem be happy not to use a tag,
4360 1.42 mjacob * but this breaks for some devices (IBM drives).
4361 1.10 mjacob */
4362 1.57 mjacob if (XS_TAG_P(xs)) {
4363 1.86 mjacob ((ispreqt2_t *)reqp)->req_flags = XS_TAG_TYPE(xs);
4364 1.42 mjacob } else {
4365 1.60 mjacob /*
4366 1.60 mjacob * If we don't know what tag to use, use HEAD OF QUEUE
4367 1.79 mjacob * for Request Sense or Simple.
4368 1.60 mjacob */
4369 1.42 mjacob if (XS_CDBP(xs)[0] == 0x3) /* REQUEST SENSE */
4370 1.86 mjacob ((ispreqt2_t *)reqp)->req_flags = REQFLAG_HTAG;
4371 1.42 mjacob else
4372 1.86 mjacob ((ispreqt2_t *)reqp)->req_flags = REQFLAG_STAG;
4373 1.10 mjacob }
4374 1.10 mjacob } else {
4375 1.114 mjacob sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
4376 1.117 mjacob if ((sdp->isp_devparam[target].actv_flags & DPARM_TQING) && XS_TAG_P(xs)) {
4377 1.57 mjacob reqp->req_flags = XS_TAG_TYPE(xs);
4378 1.10 mjacob }
4379 1.10 mjacob }
4380 1.111 mjacob cdbp = reqp->req_cdb;
4381 1.111 mjacob tptr = &reqp->req_time;
4382 1.111 mjacob
4383 1.38 mjacob if (IS_SCSI(isp)) {
4384 1.111 mjacob reqp->req_target = target | (XS_CHANNEL(xs) << 7);
4385 1.28 mjacob reqp->req_lun_trn = XS_LUN(xs);
4386 1.23 mjacob reqp->req_cdblen = XS_CDBLEN(xs);
4387 1.111 mjacob } else if (IS_24XX(isp)) {
4388 1.111 mjacob fcportdb_t *lp;
4389 1.111 mjacob
4390 1.114 mjacob lp = &FCPARAM(isp, XS_CHANNEL(xs))->portdb[hdlidx];
4391 1.111 mjacob ((ispreqt7_t *)reqp)->req_nphdl = target;
4392 1.111 mjacob ((ispreqt7_t *)reqp)->req_tidlo = lp->portid;
4393 1.111 mjacob ((ispreqt7_t *)reqp)->req_tidhi = lp->portid >> 16;
4394 1.117 mjacob ((ispreqt7_t *)reqp)->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs));
4395 1.111 mjacob if (XS_LUN(xs) > 256) {
4396 1.111 mjacob ((ispreqt7_t *)reqp)->req_lun[0] = XS_LUN(xs) >> 8;
4397 1.111 mjacob ((ispreqt7_t *)reqp)->req_lun[0] |= 0x40;
4398 1.111 mjacob }
4399 1.111 mjacob ((ispreqt7_t *)reqp)->req_lun[1] = XS_LUN(xs);
4400 1.111 mjacob cdbp = ((ispreqt7_t *)reqp)->req_cdb;
4401 1.111 mjacob tptr = &((ispreqt7_t *)reqp)->req_time;
4402 1.114 mjacob } else if (ISP_CAP_2KLOGIN(isp)) {
4403 1.111 mjacob ((ispreqt2e_t *)reqp)->req_target = target;
4404 1.111 mjacob ((ispreqt2e_t *)reqp)->req_scclun = XS_LUN(xs);
4405 1.114 mjacob } else if (ISP_CAP_SCCFW(isp)) {
4406 1.111 mjacob ((ispreqt2_t *)reqp)->req_target = target;
4407 1.111 mjacob ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs);
4408 1.28 mjacob } else {
4409 1.111 mjacob ((ispreqt2_t *)reqp)->req_target = target;
4410 1.111 mjacob ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs);
4411 1.10 mjacob }
4412 1.117 mjacob ISP_MEMCPY(cdbp, XS_CDBP(xs), XS_CDBLEN(xs));
4413 1.1 cgd
4414 1.111 mjacob *tptr = XS_TIME(xs) / 1000;
4415 1.111 mjacob if (*tptr == 0 && XS_TIME(xs)) {
4416 1.111 mjacob *tptr = 1;
4417 1.111 mjacob }
4418 1.111 mjacob if (IS_24XX(isp) && *tptr > 0x1999) {
4419 1.111 mjacob *tptr = 0x1999;
4420 1.86 mjacob }
4421 1.33 mjacob
4422 1.73 mjacob if (isp_save_xs(isp, xs, &handle)) {
4423 1.84 mjacob isp_prt(isp, ISP_LOGDEBUG0, "out of xflist pointers");
4424 1.38 mjacob XS_SETERR(xs, HBA_BOTCH);
4425 1.38 mjacob return (CMD_EAGAIN);
4426 1.38 mjacob }
4427 1.111 mjacob /* Whew. Thankfully the same for type 7 requests */
4428 1.73 mjacob reqp->req_handle = handle;
4429 1.86 mjacob
4430 1.38 mjacob /*
4431 1.117 mjacob * Set up DMA and/or do any platform dependent swizzling of the request entry
4432 1.38 mjacob * so that the Qlogic F/W understands what is being asked of it.
4433 1.117 mjacob *
4434 1.117 mjacob * The callee is responsible for adding all requests at this point.
4435 1.86 mjacob */
4436 1.117 mjacob dmaresult = ISP_DMASETUP(isp, xs, reqp);
4437 1.117 mjacob if (dmaresult != CMD_QUEUED) {
4438 1.73 mjacob isp_destroy_handle(isp, handle);
4439 1.27 mjacob /*
4440 1.27 mjacob * dmasetup sets actual error in packet, and
4441 1.27 mjacob * return what we were given to return.
4442 1.27 mjacob */
4443 1.117 mjacob return (dmaresult);
4444 1.1 cgd }
4445 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "START cmd for %d.%d.%d cmd 0x%x datalen %ld", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
4446 1.23 mjacob isp->isp_nactive++;
4447 1.23 mjacob return (CMD_QUEUED);
4448 1.1 cgd }
4449 1.1 cgd
4450 1.1 cgd /*
4451 1.23 mjacob * isp control
4452 1.23 mjacob * Locks (ints blocked) assumed held.
4453 1.1 cgd */
4454 1.1 cgd
4455 1.1 cgd int
4456 1.114 mjacob isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
4457 1.1 cgd {
4458 1.57 mjacob XS_T *xs;
4459 1.114 mjacob mbreg_t *mbr, mbs;
4460 1.114 mjacob int chan, tgt;
4461 1.111 mjacob uint32_t handle;
4462 1.114 mjacob va_list ap;
4463 1.111 mjacob
4464 1.23 mjacob switch (ctl) {
4465 1.23 mjacob case ISPCTL_RESET_BUS:
4466 1.33 mjacob /*
4467 1.33 mjacob * Issue a bus reset.
4468 1.33 mjacob */
4469 1.111 mjacob if (IS_24XX(isp)) {
4470 1.111 mjacob isp_prt(isp, ISP_LOGWARN, "RESET BUS NOT IMPLEMENTED");
4471 1.111 mjacob break;
4472 1.111 mjacob } else if (IS_FC(isp)) {
4473 1.111 mjacob mbs.param[1] = 10;
4474 1.114 mjacob chan = 0;
4475 1.111 mjacob } else {
4476 1.114 mjacob va_start(ap, ctl);
4477 1.114 mjacob chan = va_arg(ap, int);
4478 1.114 mjacob va_end(ap);
4479 1.114 mjacob mbs.param[1] = SDPARAM(isp, chan)->isp_bus_reset_delay;
4480 1.111 mjacob if (mbs.param[1] < 2) {
4481 1.33 mjacob mbs.param[1] = 2;
4482 1.111 mjacob }
4483 1.114 mjacob mbs.param[2] = chan;
4484 1.32 mjacob }
4485 1.117 mjacob MBSINIT(&mbs, MBOX_BUS_RESET, MBLOGALL, 0);
4486 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
4487 1.111 mjacob isp_mboxcmd(isp, &mbs);
4488 1.23 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
4489 1.23 mjacob break;
4490 1.23 mjacob }
4491 1.57 mjacob isp_prt(isp, ISP_LOGINFO,
4492 1.114 mjacob "driver initiated bus reset of bus %d", chan);
4493 1.23 mjacob return (0);
4494 1.23 mjacob
4495 1.34 mjacob case ISPCTL_RESET_DEV:
4496 1.114 mjacob va_start(ap, ctl);
4497 1.114 mjacob chan = va_arg(ap, int);
4498 1.114 mjacob tgt = va_arg(ap, int);
4499 1.114 mjacob va_end(ap);
4500 1.111 mjacob if (IS_24XX(isp)) {
4501 1.114 mjacob uint8_t local[QENTRY_LEN];
4502 1.114 mjacob isp24xx_tmf_t *tmf;
4503 1.114 mjacob isp24xx_statusreq_t *sp;
4504 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
4505 1.114 mjacob fcportdb_t *lp;
4506 1.114 mjacob int hdlidx;
4507 1.114 mjacob
4508 1.117 mjacob hdlidx = fcp->isp_dev_map[tgt] - 1;
4509 1.114 mjacob if (hdlidx < 0 || hdlidx >= MAX_FC_TARG) {
4510 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
4511 1.114 mjacob "Chan %d bad handle %d trying to reset"
4512 1.114 mjacob "target %d", chan, hdlidx, tgt);
4513 1.114 mjacob break;
4514 1.114 mjacob }
4515 1.114 mjacob lp = &fcp->portdb[hdlidx];
4516 1.114 mjacob if (lp->state != FC_PORTDB_STATE_VALID) {
4517 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
4518 1.114 mjacob "Chan %d handle %d for abort of target %d "
4519 1.114 mjacob "no longer valid", chan,
4520 1.114 mjacob hdlidx, tgt);
4521 1.114 mjacob break;
4522 1.114 mjacob }
4523 1.114 mjacob
4524 1.114 mjacob tmf = (isp24xx_tmf_t *) local;
4525 1.117 mjacob ISP_MEMZERO(tmf, QENTRY_LEN);
4526 1.114 mjacob tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
4527 1.114 mjacob tmf->tmf_header.rqs_entry_count = 1;
4528 1.114 mjacob tmf->tmf_nphdl = lp->handle;
4529 1.114 mjacob tmf->tmf_delay = 2;
4530 1.114 mjacob tmf->tmf_timeout = 2;
4531 1.114 mjacob tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
4532 1.114 mjacob tmf->tmf_tidlo = lp->portid;
4533 1.114 mjacob tmf->tmf_tidhi = lp->portid >> 16;
4534 1.117 mjacob tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
4535 1.117 mjacob isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
4536 1.117 mjacob MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
4537 1.114 mjacob mbs.param[1] = QENTRY_LEN;
4538 1.114 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma);
4539 1.114 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma);
4540 1.114 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma);
4541 1.114 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma);
4542 1.114 mjacob
4543 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, chan)) {
4544 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
4545 1.115 mjacob break;
4546 1.115 mjacob }
4547 1.114 mjacob isp_put_24xx_tmf(isp, tmf, fcp->isp_scratch);
4548 1.114 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN);
4549 1.114 mjacob fcp->sendmarker = 1;
4550 1.114 mjacob isp_mboxcmd(isp, &mbs);
4551 1.114 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
4552 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
4553 1.114 mjacob break;
4554 1.114 mjacob }
4555 1.114 mjacob MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN,
4556 1.114 mjacob QENTRY_LEN);
4557 1.114 mjacob sp = (isp24xx_statusreq_t *) local;
4558 1.114 mjacob isp_get_24xx_response(isp,
4559 1.114 mjacob &((isp24xx_statusreq_t *)fcp->isp_scratch)[1], sp);
4560 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
4561 1.114 mjacob if (sp->req_completion_status == 0) {
4562 1.114 mjacob return (0);
4563 1.114 mjacob }
4564 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
4565 1.114 mjacob "Chan %d reset of target %d returned 0x%x",
4566 1.114 mjacob chan, tgt, sp->req_completion_status);
4567 1.111 mjacob break;
4568 1.111 mjacob } else if (IS_FC(isp)) {
4569 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
4570 1.111 mjacob mbs.param[1] = tgt;
4571 1.111 mjacob mbs.ibits = (1 << 10);
4572 1.111 mjacob } else {
4573 1.111 mjacob mbs.param[1] = (tgt << 8);
4574 1.111 mjacob }
4575 1.111 mjacob } else {
4576 1.114 mjacob mbs.param[1] = (chan << 15) | (tgt << 8);
4577 1.111 mjacob }
4578 1.117 mjacob MBSINIT(&mbs, MBOX_ABORT_TARGET, MBLOGALL, 0);
4579 1.32 mjacob mbs.param[2] = 3; /* 'delay', in seconds */
4580 1.111 mjacob isp_mboxcmd(isp, &mbs);
4581 1.23 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
4582 1.23 mjacob break;
4583 1.23 mjacob }
4584 1.57 mjacob isp_prt(isp, ISP_LOGINFO,
4585 1.114 mjacob "Target %d on Bus %d Reset Succeeded", tgt, chan);
4586 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
4587 1.23 mjacob return (0);
4588 1.23 mjacob
4589 1.34 mjacob case ISPCTL_ABORT_CMD:
4590 1.114 mjacob va_start(ap, ctl);
4591 1.114 mjacob xs = va_arg(ap, XS_T *);
4592 1.114 mjacob va_end(ap);
4593 1.114 mjacob
4594 1.54 mjacob tgt = XS_TGT(xs);
4595 1.114 mjacob chan = XS_CHANNEL(xs);
4596 1.111 mjacob
4597 1.38 mjacob handle = isp_find_handle(isp, xs);
4598 1.38 mjacob if (handle == 0) {
4599 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
4600 1.57 mjacob "cannot find handle for command to abort");
4601 1.23 mjacob break;
4602 1.23 mjacob }
4603 1.111 mjacob if (IS_24XX(isp)) {
4604 1.114 mjacob isp24xx_abrt_t local, *ab = &local, *ab2;
4605 1.114 mjacob fcparam *fcp;
4606 1.114 mjacob fcportdb_t *lp;
4607 1.114 mjacob int hdlidx;
4608 1.114 mjacob
4609 1.114 mjacob fcp = FCPARAM(isp, chan);
4610 1.117 mjacob hdlidx = fcp->isp_dev_map[tgt] - 1;
4611 1.114 mjacob if (hdlidx < 0 || hdlidx >= MAX_FC_TARG) {
4612 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
4613 1.114 mjacob "Chan %d bad handle %d trying to abort"
4614 1.114 mjacob "target %d", chan, hdlidx, tgt);
4615 1.114 mjacob break;
4616 1.114 mjacob }
4617 1.114 mjacob lp = &fcp->portdb[hdlidx];
4618 1.114 mjacob if (lp->state != FC_PORTDB_STATE_VALID) {
4619 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
4620 1.114 mjacob "Chan %d handle %d for abort of target %d "
4621 1.114 mjacob "no longer valid", chan, hdlidx, tgt);
4622 1.114 mjacob break;
4623 1.114 mjacob }
4624 1.114 mjacob isp_prt(isp, ISP_LOGALL,
4625 1.114 mjacob "Chan %d Abort Cmd for N-Port 0x%04x @ Port "
4626 1.114 mjacob "0x%06x %p", chan, lp->handle, lp->portid, xs);
4627 1.117 mjacob ISP_MEMZERO(ab, QENTRY_LEN);
4628 1.114 mjacob ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO;
4629 1.114 mjacob ab->abrt_header.rqs_entry_count = 1;
4630 1.114 mjacob ab->abrt_handle = lp->handle;
4631 1.114 mjacob ab->abrt_cmd_handle = handle;
4632 1.114 mjacob ab->abrt_tidlo = lp->portid;
4633 1.114 mjacob ab->abrt_tidhi = lp->portid >> 16;
4634 1.117 mjacob ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan);
4635 1.114 mjacob
4636 1.117 mjacob ISP_MEMZERO(&mbs, sizeof (mbs));
4637 1.117 mjacob MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
4638 1.114 mjacob mbs.param[1] = QENTRY_LEN;
4639 1.114 mjacob mbs.param[2] = DMA_WD1(fcp->isp_scdma);
4640 1.114 mjacob mbs.param[3] = DMA_WD0(fcp->isp_scdma);
4641 1.114 mjacob mbs.param[6] = DMA_WD3(fcp->isp_scdma);
4642 1.114 mjacob mbs.param[7] = DMA_WD2(fcp->isp_scdma);
4643 1.114 mjacob
4644 1.115 mjacob if (FC_SCRATCH_ACQUIRE(isp, chan)) {
4645 1.115 mjacob isp_prt(isp, ISP_LOGERR, sacq);
4646 1.115 mjacob break;
4647 1.115 mjacob }
4648 1.114 mjacob isp_put_24xx_abrt(isp, ab, fcp->isp_scratch);
4649 1.114 mjacob ab2 = (isp24xx_abrt_t *)
4650 1.114 mjacob &((uint8_t *)fcp->isp_scratch)[QENTRY_LEN];
4651 1.114 mjacob ab2->abrt_nphdl = 0xdeaf;
4652 1.114 mjacob MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN);
4653 1.114 mjacob isp_mboxcmd(isp, &mbs);
4654 1.114 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
4655 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
4656 1.114 mjacob break;
4657 1.114 mjacob }
4658 1.114 mjacob MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN,
4659 1.114 mjacob QENTRY_LEN);
4660 1.114 mjacob isp_get_24xx_abrt(isp, ab2, ab);
4661 1.114 mjacob FC_SCRATCH_RELEASE(isp, chan);
4662 1.114 mjacob if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY) {
4663 1.114 mjacob return (0);
4664 1.114 mjacob }
4665 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
4666 1.114 mjacob "Chan %d handle %d abort returned 0x%x", chan,
4667 1.114 mjacob hdlidx, ab->abrt_nphdl);
4668 1.111 mjacob break;
4669 1.111 mjacob } else if (IS_FC(isp)) {
4670 1.114 mjacob if (ISP_CAP_SCCFW(isp)) {
4671 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
4672 1.111 mjacob mbs.param[1] = tgt;
4673 1.111 mjacob } else {
4674 1.111 mjacob mbs.param[1] = tgt << 8;
4675 1.111 mjacob }
4676 1.54 mjacob mbs.param[6] = XS_LUN(xs);
4677 1.54 mjacob } else {
4678 1.54 mjacob mbs.param[1] = tgt << 8 | XS_LUN(xs);
4679 1.54 mjacob }
4680 1.28 mjacob } else {
4681 1.114 mjacob mbs.param[1] = (chan << 15) | (tgt << 8) | XS_LUN(xs);
4682 1.28 mjacob }
4683 1.117 mjacob MBSINIT(&mbs, MBOX_ABORT, MBLOGALL & ~MBOX_COMMAND_ERROR, 0);
4684 1.73 mjacob mbs.param[2] = handle;
4685 1.111 mjacob isp_mboxcmd(isp, &mbs);
4686 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
4687 1.111 mjacob break;
4688 1.23 mjacob }
4689 1.111 mjacob return (0);
4690 1.26 mjacob
4691 1.26 mjacob case ISPCTL_UPDATE_PARAMS:
4692 1.70 mjacob
4693 1.114 mjacob va_start(ap, ctl);
4694 1.114 mjacob chan = va_arg(ap, int);
4695 1.114 mjacob va_end(ap);
4696 1.114 mjacob isp_spi_update(isp, chan);
4697 1.34 mjacob return (0);
4698 1.33 mjacob
4699 1.33 mjacob case ISPCTL_FCLINK_TEST:
4700 1.70 mjacob
4701 1.54 mjacob if (IS_FC(isp)) {
4702 1.114 mjacob int usdelay;
4703 1.114 mjacob va_start(ap, ctl);
4704 1.114 mjacob chan = va_arg(ap, int);
4705 1.114 mjacob usdelay = va_arg(ap, int);
4706 1.114 mjacob va_end(ap);
4707 1.111 mjacob if (usdelay == 0) {
4708 1.111 mjacob usdelay = 250000;
4709 1.111 mjacob }
4710 1.114 mjacob return (isp_fclink_test(isp, chan, usdelay));
4711 1.54 mjacob }
4712 1.54 mjacob break;
4713 1.46 mjacob
4714 1.70 mjacob case ISPCTL_SCAN_FABRIC:
4715 1.70 mjacob
4716 1.70 mjacob if (IS_FC(isp)) {
4717 1.114 mjacob va_start(ap, ctl);
4718 1.114 mjacob chan = va_arg(ap, int);
4719 1.114 mjacob va_end(ap);
4720 1.114 mjacob return (isp_scan_fabric(isp, chan));
4721 1.70 mjacob }
4722 1.70 mjacob break;
4723 1.70 mjacob
4724 1.70 mjacob case ISPCTL_SCAN_LOOP:
4725 1.70 mjacob
4726 1.70 mjacob if (IS_FC(isp)) {
4727 1.114 mjacob va_start(ap, ctl);
4728 1.114 mjacob chan = va_arg(ap, int);
4729 1.114 mjacob va_end(ap);
4730 1.114 mjacob return (isp_scan_loop(isp, chan));
4731 1.70 mjacob }
4732 1.70 mjacob break;
4733 1.70 mjacob
4734 1.46 mjacob case ISPCTL_PDB_SYNC:
4735 1.70 mjacob
4736 1.70 mjacob if (IS_FC(isp)) {
4737 1.114 mjacob va_start(ap, ctl);
4738 1.114 mjacob chan = va_arg(ap, int);
4739 1.114 mjacob va_end(ap);
4740 1.114 mjacob return (isp_pdb_sync(isp, chan));
4741 1.70 mjacob }
4742 1.70 mjacob break;
4743 1.70 mjacob
4744 1.70 mjacob case ISPCTL_SEND_LIP:
4745 1.70 mjacob
4746 1.111 mjacob if (IS_FC(isp) && !IS_24XX(isp)) {
4747 1.117 mjacob MBSINIT(&mbs, MBOX_INIT_LIP, MBLOGALL, 0);
4748 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
4749 1.111 mjacob mbs.ibits = (1 << 10);
4750 1.111 mjacob }
4751 1.111 mjacob isp_mboxcmd(isp, &mbs);
4752 1.70 mjacob if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
4753 1.70 mjacob return (0);
4754 1.70 mjacob }
4755 1.70 mjacob }
4756 1.70 mjacob break;
4757 1.70 mjacob
4758 1.111 mjacob case ISPCTL_GET_PDB:
4759 1.114 mjacob if (IS_FC(isp)) {
4760 1.114 mjacob isp_pdb_t *pdb;
4761 1.114 mjacob va_start(ap, ctl);
4762 1.114 mjacob chan = va_arg(ap, int);
4763 1.114 mjacob tgt = va_arg(ap, int);
4764 1.114 mjacob pdb = va_arg(ap, isp_pdb_t *);
4765 1.114 mjacob va_end(ap);
4766 1.114 mjacob return (isp_getpdb(isp, chan, tgt, pdb, 1));
4767 1.54 mjacob }
4768 1.54 mjacob break;
4769 1.70 mjacob
4770 1.114 mjacob case ISPCTL_GET_NAMES:
4771 1.111 mjacob {
4772 1.114 mjacob uint64_t *wwnn, *wwnp;
4773 1.114 mjacob va_start(ap, ctl);
4774 1.114 mjacob chan = va_arg(ap, int);
4775 1.114 mjacob tgt = va_arg(ap, int);
4776 1.114 mjacob wwnn = va_arg(ap, uint64_t *);
4777 1.114 mjacob wwnp = va_arg(ap, uint64_t *);
4778 1.114 mjacob va_end(ap);
4779 1.114 mjacob if (wwnn == NULL && wwnp == NULL) {
4780 1.111 mjacob break;
4781 1.111 mjacob }
4782 1.114 mjacob if (wwnn) {
4783 1.114 mjacob *wwnn = isp_get_wwn(isp, chan, tgt, 1);
4784 1.114 mjacob if (*wwnn == INI_NONE) {
4785 1.114 mjacob break;
4786 1.114 mjacob }
4787 1.114 mjacob }
4788 1.114 mjacob if (wwnp) {
4789 1.114 mjacob *wwnp = isp_get_wwn(isp, chan, tgt, 0);
4790 1.114 mjacob if (*wwnp == INI_NONE) {
4791 1.114 mjacob break;
4792 1.114 mjacob }
4793 1.114 mjacob }
4794 1.114 mjacob return (0);
4795 1.111 mjacob }
4796 1.71 mjacob case ISPCTL_RUN_MBOXCMD:
4797 1.114 mjacob {
4798 1.114 mjacob va_start(ap, ctl);
4799 1.114 mjacob mbr = va_arg(ap, mbreg_t *);
4800 1.114 mjacob va_end(ap);
4801 1.114 mjacob isp_mboxcmd(isp, mbr);
4802 1.117 mjacob return (0);
4803 1.114 mjacob }
4804 1.111 mjacob case ISPCTL_PLOGX:
4805 1.111 mjacob {
4806 1.114 mjacob isp_plcmd_t *p;
4807 1.111 mjacob int r;
4808 1.111 mjacob
4809 1.114 mjacob va_start(ap, ctl);
4810 1.114 mjacob p = va_arg(ap, isp_plcmd_t *);
4811 1.114 mjacob va_end(ap);
4812 1.114 mjacob
4813 1.117 mjacob if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
4814 1.117 mjacob return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags, 0));
4815 1.111 mjacob }
4816 1.111 mjacob do {
4817 1.114 mjacob p->handle = isp_nxt_handle(isp, p->channel, p->handle);
4818 1.117 mjacob r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags, 0);
4819 1.111 mjacob if ((r & 0xffff) == MBOX_PORT_ID_USED) {
4820 1.111 mjacob p->handle = r >> 16;
4821 1.111 mjacob r = 0;
4822 1.111 mjacob break;
4823 1.111 mjacob }
4824 1.111 mjacob } while ((r & 0xffff) == MBOX_LOOP_ID_USED);
4825 1.111 mjacob return (r);
4826 1.111 mjacob }
4827 1.114 mjacob default:
4828 1.114 mjacob isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
4829 1.114 mjacob break;
4830 1.70 mjacob
4831 1.1 cgd }
4832 1.23 mjacob return (-1);
4833 1.1 cgd }
4834 1.1 cgd
4835 1.23 mjacob /*
4836 1.23 mjacob * Interrupt Service Routine(s).
4837 1.23 mjacob *
4838 1.23 mjacob * External (OS) framework has done the appropriate locking,
4839 1.23 mjacob * and the locking will be held throughout this function.
4840 1.23 mjacob */
4841 1.23 mjacob
4842 1.57 mjacob /*
4843 1.57 mjacob * Limit our stack depth by sticking with the max likely number
4844 1.57 mjacob * of completions on a request queue at any one time.
4845 1.57 mjacob */
4846 1.88 mjacob #ifndef MAX_REQUESTQ_COMPLETIONS
4847 1.111 mjacob #define MAX_REQUESTQ_COMPLETIONS 32
4848 1.88 mjacob #endif
4849 1.57 mjacob
4850 1.79 mjacob void
4851 1.111 mjacob isp_intr(ispsoftc_t *isp, uint32_t isr, uint16_t sema, uint16_t mbox)
4852 1.1 cgd {
4853 1.57 mjacob XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs;
4854 1.111 mjacob uint32_t iptr, optr, junk;
4855 1.32 mjacob int i, nlooked = 0, ndone = 0;
4856 1.1 cgd
4857 1.88 mjacob again:
4858 1.111 mjacob optr = isp->isp_residx;
4859 1.79 mjacob /*
4860 1.79 mjacob * Is this a mailbox related interrupt?
4861 1.79 mjacob * The mailbox semaphore will be nonzero if so.
4862 1.79 mjacob */
4863 1.36 mjacob if (sema) {
4864 1.114 mjacob fmbox:
4865 1.33 mjacob if (mbox & 0x4000) {
4866 1.88 mjacob isp->isp_intmboxc++;
4867 1.86 mjacob if (isp->isp_mboxbsy) {
4868 1.111 mjacob int obits = isp->isp_obits;
4869 1.111 mjacob isp->isp_mboxtmp[0] = mbox;
4870 1.111 mjacob for (i = 1; i < MAX_MAILBOX(isp); i++) {
4871 1.111 mjacob if ((obits & (1 << i)) == 0) {
4872 1.54 mjacob continue;
4873 1.54 mjacob }
4874 1.117 mjacob isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
4875 1.54 mjacob }
4876 1.88 mjacob if (isp->isp_mbxwrk0) {
4877 1.88 mjacob if (isp_mbox_continue(isp) == 0) {
4878 1.88 mjacob return;
4879 1.88 mjacob }
4880 1.88 mjacob }
4881 1.54 mjacob MBOX_NOTIFY_COMPLETE(isp);
4882 1.54 mjacob } else {
4883 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "mailbox cmd (0x%x) with no waiters", mbox);
4884 1.54 mjacob }
4885 1.87 mjacob } else if (isp_parse_async(isp, mbox) < 0) {
4886 1.87 mjacob return;
4887 1.31 mjacob }
4888 1.117 mjacob if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) || isp->isp_state != ISP_RUNSTATE) {
4889 1.111 mjacob goto out;
4890 1.54 mjacob }
4891 1.54 mjacob }
4892 1.54 mjacob
4893 1.54 mjacob /*
4894 1.54 mjacob * We can't be getting this now.
4895 1.54 mjacob */
4896 1.54 mjacob if (isp->isp_state != ISP_RUNSTATE) {
4897 1.114 mjacob /*
4898 1.114 mjacob * This seems to happen to 23XX and 24XX cards- don't know why.
4899 1.114 mjacob */
4900 1.117 mjacob if (isp->isp_mboxbsy && isp->isp_lastmbxcmd == MBOX_ABOUT_FIRMWARE) {
4901 1.114 mjacob goto fmbox;
4902 1.114 mjacob }
4903 1.117 mjacob isp_prt(isp, ISP_LOGINFO, "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema);
4904 1.79 mjacob /*
4905 1.111 mjacob * Thank you very much! *Burrrp*!
4906 1.111 mjacob */
4907 1.117 mjacob ISP_WRITE(isp, isp->isp_respoutrp, ISP_READ(isp, isp->isp_respinrp));
4908 1.111 mjacob if (IS_24XX(isp)) {
4909 1.111 mjacob ISP_DISABLE_INTS(isp);
4910 1.111 mjacob }
4911 1.111 mjacob goto out;
4912 1.111 mjacob }
4913 1.111 mjacob
4914 1.111 mjacob #ifdef ISP_TARGET_MODE
4915 1.111 mjacob /*
4916 1.111 mjacob * Check for ATIO Queue entries.
4917 1.111 mjacob */
4918 1.114 mjacob if (IS_24XX(isp)) {
4919 1.114 mjacob iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
4920 1.114 mjacob optr = ISP_READ(isp, BIU2400_ATIO_RSPOUTP);
4921 1.111 mjacob
4922 1.111 mjacob while (optr != iptr) {
4923 1.111 mjacob uint8_t qe[QENTRY_LEN];
4924 1.111 mjacob isphdr_t *hp;
4925 1.111 mjacob uint32_t oop;
4926 1.111 mjacob void *addr;
4927 1.111 mjacob
4928 1.111 mjacob oop = optr;
4929 1.111 mjacob MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN);
4930 1.111 mjacob addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop);
4931 1.111 mjacob isp_get_hdr(isp, addr, (isphdr_t *)qe);
4932 1.111 mjacob hp = (isphdr_t *)qe;
4933 1.111 mjacob switch (hp->rqs_entry_type) {
4934 1.111 mjacob case RQSTYPE_NOTIFY:
4935 1.111 mjacob case RQSTYPE_ATIO:
4936 1.111 mjacob (void) isp_target_notify(isp, addr, &oop);
4937 1.111 mjacob break;
4938 1.111 mjacob default:
4939 1.117 mjacob isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
4940 1.111 mjacob break;
4941 1.111 mjacob }
4942 1.111 mjacob optr = ISP_NXT_QENTRY(oop, RESULT_QUEUE_LEN(isp));
4943 1.114 mjacob ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
4944 1.111 mjacob }
4945 1.111 mjacob optr = isp->isp_residx;
4946 1.79 mjacob }
4947 1.111 mjacob #endif
4948 1.79 mjacob
4949 1.79 mjacob /*
4950 1.79 mjacob * Get the current Response Queue Out Pointer.
4951 1.79 mjacob *
4952 1.111 mjacob * If we're a 2300 or 2400, we can ask what hardware what it thinks.
4953 1.79 mjacob */
4954 1.111 mjacob if (IS_23XX(isp) || IS_24XX(isp)) {
4955 1.79 mjacob optr = ISP_READ(isp, isp->isp_respoutrp);
4956 1.88 mjacob /*
4957 1.88 mjacob * Debug: to be taken out eventually
4958 1.88 mjacob */
4959 1.79 mjacob if (isp->isp_residx != optr) {
4960 1.117 mjacob isp_prt(isp, ISP_LOGINFO, "isp_intr: hard optr=%x, soft optr %x", optr, isp->isp_residx);
4961 1.111 mjacob isp->isp_residx = optr;
4962 1.79 mjacob }
4963 1.79 mjacob } else {
4964 1.79 mjacob optr = isp->isp_residx;
4965 1.1 cgd }
4966 1.25 mjacob
4967 1.35 mjacob /*
4968 1.79 mjacob * You *must* read the Response Queue In Pointer
4969 1.78 mjacob * prior to clearing the RISC interrupt.
4970 1.87 mjacob *
4971 1.87 mjacob * Debounce the 2300 if revision less than 2.
4972 1.35 mjacob */
4973 1.87 mjacob if (IS_2100(isp) || (IS_2300(isp) && isp->isp_revision < 2)) {
4974 1.54 mjacob i = 0;
4975 1.54 mjacob do {
4976 1.111 mjacob iptr = ISP_READ(isp, isp->isp_respinrp);
4977 1.111 mjacob junk = ISP_READ(isp, isp->isp_respinrp);
4978 1.54 mjacob } while (junk != iptr && ++i < 1000);
4979 1.54 mjacob
4980 1.54 mjacob if (iptr != junk) {
4981 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "Response Queue Out Pointer Unstable (%x, %x)", iptr, junk);
4982 1.111 mjacob goto out;
4983 1.54 mjacob }
4984 1.54 mjacob } else {
4985 1.111 mjacob iptr = ISP_READ(isp, isp->isp_respinrp);
4986 1.54 mjacob }
4987 1.90 mjacob isp->isp_resodx = iptr;
4988 1.54 mjacob
4989 1.54 mjacob
4990 1.54 mjacob if (optr == iptr && sema == 0) {
4991 1.54 mjacob /*
4992 1.54 mjacob * There are a lot of these- reasons unknown- mostly on
4993 1.54 mjacob * faster Alpha machines.
4994 1.54 mjacob *
4995 1.54 mjacob * I tried delaying after writing HCCR_CMD_CLEAR_RISC_INT to
4996 1.54 mjacob * make sure the old interrupt went away (to avoid 'ringing'
4997 1.54 mjacob * effects), but that didn't stop this from occurring.
4998 1.54 mjacob */
4999 1.111 mjacob if (IS_24XX(isp)) {
5000 1.111 mjacob junk = 0;
5001 1.111 mjacob } else if (IS_23XX(isp)) {
5002 1.117 mjacob ISP_DELAY(100);
5003 1.111 mjacob iptr = ISP_READ(isp, isp->isp_respinrp);
5004 1.79 mjacob junk = ISP_READ(isp, BIU_R2HSTSLO);
5005 1.79 mjacob } else {
5006 1.79 mjacob junk = ISP_READ(isp, BIU_ISR);
5007 1.79 mjacob }
5008 1.79 mjacob if (optr == iptr) {
5009 1.111 mjacob if (IS_23XX(isp) || IS_24XX(isp)) {
5010 1.88 mjacob ;
5011 1.88 mjacob } else {
5012 1.88 mjacob sema = ISP_READ(isp, BIU_SEMA);
5013 1.88 mjacob mbox = ISP_READ(isp, OUTMAILBOX0);
5014 1.88 mjacob if ((sema & 0x3) && (mbox & 0x8000)) {
5015 1.88 mjacob goto again;
5016 1.88 mjacob }
5017 1.88 mjacob }
5018 1.88 mjacob isp->isp_intbogus++;
5019 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG1, "bogus intr- isr %x (%x) iptr %x optr %x", isr, junk, iptr, optr);
5020 1.79 mjacob }
5021 1.10 mjacob }
5022 1.90 mjacob isp->isp_resodx = iptr;
5023 1.111 mjacob
5024 1.1 cgd while (optr != iptr) {
5025 1.111 mjacob uint8_t qe[QENTRY_LEN];
5026 1.111 mjacob ispstatusreq_t *sp = (ispstatusreq_t *) qe;
5027 1.86 mjacob isphdr_t *hp;
5028 1.111 mjacob int buddaboom, etype, scsi_status, completion_status;
5029 1.111 mjacob int req_status_flags, req_state_flags;
5030 1.111 mjacob uint8_t *snsp, *resp;
5031 1.111 mjacob uint32_t rlen, slen;
5032 1.111 mjacob long resid;
5033 1.111 mjacob uint16_t oop;
5034 1.1 cgd
5035 1.86 mjacob hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr);
5036 1.25 mjacob oop = optr;
5037 1.57 mjacob optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
5038 1.32 mjacob nlooked++;
5039 1.111 mjacob read_again:
5040 1.111 mjacob buddaboom = req_status_flags = req_state_flags = 0;
5041 1.111 mjacob resid = 0L;
5042 1.111 mjacob
5043 1.38 mjacob /*
5044 1.86 mjacob * Synchronize our view of this response queue entry.
5045 1.86 mjacob */
5046 1.86 mjacob MEMORYBARRIER(isp, SYNC_RESULT, oop, QENTRY_LEN);
5047 1.111 mjacob isp_get_hdr(isp, hp, &sp->req_header);
5048 1.111 mjacob etype = sp->req_header.rqs_entry_type;
5049 1.86 mjacob
5050 1.113 mjacob if (IS_24XX(isp) && etype == RQSTYPE_RESPONSE) {
5051 1.111 mjacob isp24xx_statusreq_t *sp2 = (isp24xx_statusreq_t *)qe;
5052 1.117 mjacob isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp2);
5053 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
5054 1.117 mjacob isp_print_bytes(isp, "Response Queue Entry", QENTRY_LEN, sp2);
5055 1.111 mjacob }
5056 1.111 mjacob scsi_status = sp2->req_scsi_status;
5057 1.111 mjacob completion_status = sp2->req_completion_status;
5058 1.111 mjacob req_state_flags = 0;
5059 1.111 mjacob resid = sp2->req_resid;
5060 1.111 mjacob } else if (etype == RQSTYPE_RESPONSE) {
5061 1.86 mjacob isp_get_response(isp, (ispstatusreq_t *) hp, sp);
5062 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
5063 1.117 mjacob isp_print_bytes(isp, "Response Queue Entry", QENTRY_LEN, sp);
5064 1.111 mjacob }
5065 1.111 mjacob scsi_status = sp->req_scsi_status;
5066 1.111 mjacob completion_status = sp->req_completion_status;
5067 1.111 mjacob req_status_flags = sp->req_status_flags;
5068 1.111 mjacob req_state_flags = sp->req_state_flags;
5069 1.111 mjacob resid = sp->req_resid;
5070 1.111 mjacob } else if (etype == RQSTYPE_RIO2) {
5071 1.111 mjacob isp_rio2_t *rio = (isp_rio2_t *)qe;
5072 1.111 mjacob isp_get_rio2(isp, (isp_rio2_t *) hp, rio);
5073 1.111 mjacob if (isp->isp_dblev & ISP_LOGDEBUG1) {
5074 1.117 mjacob isp_print_bytes(isp, "Response Queue Entry", QENTRY_LEN, rio);
5075 1.111 mjacob }
5076 1.111 mjacob for (i = 0; i < rio->req_header.rqs_seqno; i++) {
5077 1.111 mjacob isp_fastpost_complete(isp, rio->req_handles[i]);
5078 1.111 mjacob }
5079 1.111 mjacob if (isp->isp_fpcchiwater < rio->req_header.rqs_seqno) {
5080 1.117 mjacob isp->isp_fpcchiwater = rio->req_header.rqs_seqno;
5081 1.87 mjacob }
5082 1.117 mjacob ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
5083 1.87 mjacob continue;
5084 1.86 mjacob } else {
5085 1.89 mjacob /*
5086 1.89 mjacob * Somebody reachable via isp_handle_other_response
5087 1.89 mjacob * may have updated the response queue pointers for
5088 1.90 mjacob * us, so we reload our goal index.
5089 1.89 mjacob */
5090 1.115 mjacob int r;
5091 1.115 mjacob uint32_t tsto = oop;
5092 1.114 mjacob r = isp_handle_other_response(isp, etype, hp, &tsto);
5093 1.111 mjacob if (r < 0) {
5094 1.111 mjacob goto read_again;
5095 1.111 mjacob }
5096 1.114 mjacob /*
5097 1.114 mjacob * If somebody updated the output pointer, then reset
5098 1.114 mjacob * optr to be one more than the updated amount.
5099 1.114 mjacob */
5100 1.114 mjacob while (tsto != oop) {
5101 1.114 mjacob optr = ISP_NXT_QENTRY(tsto,
5102 1.114 mjacob RESULT_QUEUE_LEN(isp));
5103 1.114 mjacob }
5104 1.111 mjacob if (r > 0) {
5105 1.114 mjacob ISP_WRITE(isp, isp->isp_respoutrp, optr);
5106 1.117 mjacob ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
5107 1.25 mjacob continue;
5108 1.25 mjacob }
5109 1.86 mjacob
5110 1.86 mjacob /*
5111 1.86 mjacob * After this point, we'll just look at the header as
5112 1.86 mjacob * we don't know how to deal with the rest of the
5113 1.86 mjacob * response.
5114 1.86 mjacob */
5115 1.86 mjacob
5116 1.25 mjacob /*
5117 1.25 mjacob * It really has to be a bounced request just copied
5118 1.36 mjacob * from the request queue to the response queue. If
5119 1.36 mjacob * not, something bad has happened.
5120 1.25 mjacob */
5121 1.111 mjacob if (etype != RQSTYPE_REQUEST) {
5122 1.57 mjacob isp_prt(isp, ISP_LOGERR, notresp,
5123 1.111 mjacob etype, oop, optr, nlooked);
5124 1.111 mjacob isp_print_bytes(isp,
5125 1.111 mjacob "Request Queue Entry", QENTRY_LEN, sp);
5126 1.117 mjacob ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
5127 1.1 cgd continue;
5128 1.1 cgd }
5129 1.1 cgd buddaboom = 1;
5130 1.111 mjacob scsi_status = sp->req_scsi_status;
5131 1.111 mjacob completion_status = sp->req_completion_status;
5132 1.111 mjacob req_status_flags = sp->req_status_flags;
5133 1.111 mjacob req_state_flags = sp->req_state_flags;
5134 1.111 mjacob resid = sp->req_resid;
5135 1.1 cgd }
5136 1.1 cgd
5137 1.111 mjacob if (sp->req_header.rqs_flags & RQSFLAG_MASK) {
5138 1.1 cgd if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {
5139 1.117 mjacob isp_print_bytes(isp, "unexpected continuation segment", QENTRY_LEN, sp);
5140 1.111 mjacob ISP_WRITE(isp, isp->isp_respoutrp, optr);
5141 1.1 cgd continue;
5142 1.1 cgd }
5143 1.23 mjacob if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
5144 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG0, "internal queues full");
5145 1.36 mjacob /*
5146 1.36 mjacob * We'll synthesize a QUEUE FULL message below.
5147 1.36 mjacob */
5148 1.23 mjacob }
5149 1.23 mjacob if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) {
5150 1.117 mjacob isp_print_bytes(isp, "bad header flag", QENTRY_LEN, sp);
5151 1.23 mjacob buddaboom++;
5152 1.23 mjacob }
5153 1.23 mjacob if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) {
5154 1.117 mjacob isp_print_bytes(isp, "bad request packet", QENTRY_LEN, sp);
5155 1.117 mjacob buddaboom++;
5156 1.117 mjacob }
5157 1.117 mjacob if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
5158 1.117 mjacob isp_print_bytes(isp, "invalid entry count", QENTRY_LEN, sp);
5159 1.36 mjacob buddaboom++;
5160 1.36 mjacob }
5161 1.117 mjacob if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
5162 1.117 mjacob isp_print_bytes(isp, "invalid IOCB ordering", QENTRY_LEN, sp);
5163 1.117 mjacob ISP_WRITE(isp, isp->isp_respoutrp, optr);
5164 1.117 mjacob continue;
5165 1.117 mjacob }
5166 1.1 cgd }
5167 1.111 mjacob
5168 1.117 mjacob if ((sp->req_handle != ISP_SPCL_HANDLE) && (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1)) {
5169 1.117 mjacob isp_prt(isp, ISP_LOGERR, "bad request handle %d (type 0x%x)", sp->req_handle, etype);
5170 1.117 mjacob ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
5171 1.111 mjacob ISP_WRITE(isp, isp->isp_respoutrp, optr);
5172 1.1 cgd continue;
5173 1.1 cgd }
5174 1.38 mjacob xs = isp_find_xs(isp, sp->req_handle);
5175 1.1 cgd if (xs == NULL) {
5176 1.111 mjacob uint8_t ts = completion_status & 0xff;
5177 1.92 mjacob /*
5178 1.92 mjacob * Only whine if this isn't the expected fallout of
5179 1.115 mjacob * aborting the command or resetting the target.
5180 1.92 mjacob */
5181 1.111 mjacob if (etype != RQSTYPE_RESPONSE) {
5182 1.117 mjacob isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype);
5183 1.117 mjacob } else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED && sp->req_handle != ISP_SPCL_HANDLE) {
5184 1.117 mjacob isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts);
5185 1.92 mjacob }
5186 1.117 mjacob ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
5187 1.111 mjacob ISP_WRITE(isp, isp->isp_respoutrp, optr);
5188 1.1 cgd continue;
5189 1.1 cgd }
5190 1.111 mjacob if (req_status_flags & RQSTF_BUS_RESET) {
5191 1.86 mjacob XS_SETERR(xs, HBA_BUSRESET);
5192 1.114 mjacob ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1);
5193 1.1 cgd }
5194 1.1 cgd if (buddaboom) {
5195 1.23 mjacob XS_SETERR(xs, HBA_BOTCH);
5196 1.1 cgd }
5197 1.61 mjacob
5198 1.111 mjacob resp = NULL;
5199 1.111 mjacob rlen = 0;
5200 1.111 mjacob snsp = NULL;
5201 1.111 mjacob slen = 0;
5202 1.113 mjacob if (IS_24XX(isp) && (scsi_status & (RQCS_RV|RQCS_SV)) != 0) {
5203 1.111 mjacob resp = ((isp24xx_statusreq_t *)sp)->req_rsp_sense;
5204 1.111 mjacob rlen = ((isp24xx_statusreq_t *)sp)->req_response_len;
5205 1.111 mjacob } else if (IS_FC(isp) && (scsi_status & RQCS_RV) != 0) {
5206 1.111 mjacob resp = sp->req_response;
5207 1.111 mjacob rlen = sp->req_response_len;
5208 1.111 mjacob }
5209 1.111 mjacob if (IS_FC(isp) && (scsi_status & RQCS_SV) != 0) {
5210 1.31 mjacob /*
5211 1.61 mjacob * Fibre Channel F/W doesn't say we got status
5212 1.61 mjacob * if there's Sense Data instead. I guess they
5213 1.61 mjacob * think it goes w/o saying.
5214 1.31 mjacob */
5215 1.111 mjacob req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE;
5216 1.111 mjacob if (IS_24XX(isp)) {
5217 1.117 mjacob snsp = ((isp24xx_statusreq_t *)sp)->req_rsp_sense;
5218 1.111 mjacob snsp += rlen;
5219 1.117 mjacob slen = ((isp24xx_statusreq_t *)sp)->req_sense_len;
5220 1.111 mjacob } else {
5221 1.111 mjacob snsp = sp->req_sense_data;
5222 1.111 mjacob slen = sp->req_sense_len;
5223 1.111 mjacob }
5224 1.111 mjacob } else if (IS_SCSI(isp) && (req_state_flags & RQSF_GOT_SENSE)) {
5225 1.111 mjacob snsp = sp->req_sense_data;
5226 1.111 mjacob slen = sp->req_sense_len;
5227 1.61 mjacob }
5228 1.111 mjacob if (req_state_flags & RQSF_GOT_STATUS) {
5229 1.111 mjacob *XS_STSP(xs) = scsi_status & 0xff;
5230 1.1 cgd }
5231 1.1 cgd
5232 1.111 mjacob switch (etype) {
5233 1.61 mjacob case RQSTYPE_RESPONSE:
5234 1.117 mjacob if (resp && rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
5235 1.117 mjacob const char *ptr;
5236 1.117 mjacob char lb[64];
5237 1.117 mjacob const char *rnames[6] = {
5238 1.117 mjacob "Task Management Function Done",
5239 1.117 mjacob "Data Length Differs From Burst Length",
5240 1.117 mjacob "Invalid FCP Cmnd",
5241 1.117 mjacob "FCP DATA RO mismatch with FCP DATA_XFR_RDY RO",
5242 1.117 mjacob "Task Management Function Rejected",
5243 1.117 mjacob "Task Management Function Failed",
5244 1.117 mjacob };
5245 1.117 mjacob if (resp[FCP_RSPNS_CODE_OFFSET] > 5) {
5246 1.117 mjacob ISP_SNPRINTF(lb, sizeof lb, "Unknown FCP Response Code 0x%x", resp[FCP_RSPNS_CODE_OFFSET]);
5247 1.117 mjacob ptr = lb;
5248 1.117 mjacob } else {
5249 1.117 mjacob ptr = rnames[resp[FCP_RSPNS_CODE_OFFSET]];
5250 1.117 mjacob }
5251 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "%d.%d.%d FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), rlen, ptr, XS_CDBP(xs)[0] & 0xff);
5252 1.117 mjacob if (resp[FCP_RSPNS_CODE_OFFSET] != 0) {
5253 1.117 mjacob XS_SETERR(xs, HBA_BOTCH);
5254 1.117 mjacob }
5255 1.111 mjacob }
5256 1.111 mjacob if (IS_24XX(isp)) {
5257 1.117 mjacob isp_parse_status_24xx(isp, (isp24xx_statusreq_t *)sp, xs, &resid);
5258 1.111 mjacob } else {
5259 1.111 mjacob isp_parse_status(isp, (void *)sp, xs, &resid);
5260 1.111 mjacob }
5261 1.117 mjacob if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) && (*XS_STSP(xs) == SCSI_BUSY)) {
5262 1.57 mjacob XS_SETERR(xs, HBA_TGTBSY);
5263 1.25 mjacob }
5264 1.61 mjacob if (IS_SCSI(isp)) {
5265 1.117 mjacob XS_SET_RESID(xs, resid);
5266 1.61 mjacob /*
5267 1.61 mjacob * A new synchronous rate was negotiated for
5268 1.61 mjacob * this target. Mark state such that we'll go
5269 1.61 mjacob * look up that which has changed later.
5270 1.61 mjacob */
5271 1.111 mjacob if (req_status_flags & RQSTF_NEGOTIATION) {
5272 1.61 mjacob int t = XS_TGT(xs);
5273 1.117 mjacob sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
5274 1.61 mjacob sdp->isp_devparam[t].dev_refresh = 1;
5275 1.114 mjacob sdp->update = 1;
5276 1.61 mjacob }
5277 1.61 mjacob } else {
5278 1.111 mjacob if (req_status_flags & RQSF_XFER_COMPLETE) {
5279 1.117 mjacob XS_SET_RESID(xs, 0);
5280 1.111 mjacob } else if (scsi_status & RQCS_RESID) {
5281 1.117 mjacob XS_SET_RESID(xs, resid);
5282 1.61 mjacob } else {
5283 1.117 mjacob XS_SET_RESID(xs, 0);
5284 1.61 mjacob }
5285 1.111 mjacob }
5286 1.111 mjacob if (snsp && slen) {
5287 1.111 mjacob XS_SAVE_SENSE(xs, snsp, slen);
5288 1.117 mjacob } else if ((req_status_flags & RQSF_GOT_STATUS) && (scsi_status & 0xff) == SCSI_CHECK && IS_FC(isp)) {
5289 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "CHECK CONDITION w/o sense data for CDB=0x%x", XS_CDBP(xs)[0] & 0xff);
5290 1.117 mjacob isp_print_bytes(isp, "CC with no Sense", QENTRY_LEN, qe);
5291 1.61 mjacob }
5292 1.117 mjacob isp_prt(isp, ISP_LOGDEBUG2, "asked for %ld got raw resid %ld settled for %ld", (long) XS_XFRLEN(xs), resid, (long) XS_GET_RESID(xs));
5293 1.61 mjacob break;
5294 1.61 mjacob case RQSTYPE_REQUEST:
5295 1.111 mjacob case RQSTYPE_A64:
5296 1.111 mjacob case RQSTYPE_T2RQS:
5297 1.111 mjacob case RQSTYPE_T3RQS:
5298 1.111 mjacob case RQSTYPE_T7RQS:
5299 1.117 mjacob if (!IS_24XX(isp) && (sp->req_header.rqs_flags & RQSFLAG_FULL)) {
5300 1.36 mjacob /*
5301 1.36 mjacob * Force Queue Full status.
5302 1.36 mjacob */
5303 1.57 mjacob *XS_STSP(xs) = SCSI_QFULL;
5304 1.36 mjacob XS_SETERR(xs, HBA_NOERROR);
5305 1.36 mjacob } else if (XS_NOERR(xs)) {
5306 1.111 mjacob XS_SETERR(xs, HBA_BOTCH);
5307 1.36 mjacob }
5308 1.117 mjacob XS_SET_RESID(xs, XS_XFRLEN(xs));
5309 1.61 mjacob break;
5310 1.61 mjacob default:
5311 1.117 mjacob isp_print_bytes(isp, "Unhandled Response Type", QENTRY_LEN, qe);
5312 1.30 mjacob if (XS_NOERR(xs)) {
5313 1.23 mjacob XS_SETERR(xs, HBA_BOTCH);
5314 1.30 mjacob }
5315 1.61 mjacob break;
5316 1.1 cgd }
5317 1.61 mjacob
5318 1.61 mjacob /*
5319 1.102 wiz * Free any DMA resources. As a side effect, this may
5320 1.113 mjacob * also do any cache flushing necessary for data coherence.
5321 1.113 mjacob */
5322 1.23 mjacob if (XS_XFRLEN(xs)) {
5323 1.38 mjacob ISP_DMAFREE(isp, xs, sp->req_handle);
5324 1.1 cgd }
5325 1.120 mjacob isp_destroy_handle(isp, sp->req_handle);
5326 1.61 mjacob
5327 1.115 mjacob if (((isp->isp_dblev & (ISP_LOGDEBUG1|ISP_LOGDEBUG2|ISP_LOGDEBUG3))) ||
5328 1.113 mjacob ((isp->isp_dblev & ISP_LOGDEBUG0) && ((!XS_NOERR(xs)) ||
5329 1.70 mjacob (*XS_STSP(xs) != SCSI_GOOD)))) {
5330 1.57 mjacob char skey;
5331 1.111 mjacob if (req_state_flags & RQSF_GOT_SENSE) {
5332 1.57 mjacob skey = XS_SNSKEY(xs) & 0xf;
5333 1.57 mjacob if (skey < 10)
5334 1.57 mjacob skey += '0';
5335 1.57 mjacob else
5336 1.70 mjacob skey += 'a' - 10;
5337 1.57 mjacob } else if (*XS_STSP(xs) == SCSI_CHECK) {
5338 1.57 mjacob skey = '?';
5339 1.57 mjacob } else {
5340 1.57 mjacob skey = '.';
5341 1.1 cgd }
5342 1.57 mjacob isp_prt(isp, ISP_LOGALL, finmsg, XS_CHANNEL(xs),
5343 1.117 mjacob XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs), (long) XS_GET_RESID(xs),
5344 1.57 mjacob *XS_STSP(xs), skey, XS_ERR(xs));
5345 1.1 cgd }
5346 1.23 mjacob
5347 1.115 mjacob if (isp->isp_nactive > 0) {
5348 1.28 mjacob isp->isp_nactive--;
5349 1.115 mjacob }
5350 1.25 mjacob complist[ndone++] = xs; /* defer completion call until later */
5351 1.117 mjacob ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
5352 1.57 mjacob if (ndone == MAX_REQUESTQ_COMPLETIONS) {
5353 1.57 mjacob break;
5354 1.57 mjacob }
5355 1.1 cgd }
5356 1.32 mjacob
5357 1.27 mjacob /*
5358 1.32 mjacob * If we looked at any commands, then it's valid to find out
5359 1.32 mjacob * what the outpointer is. It also is a trigger to update the
5360 1.32 mjacob * ISP's notion of what we've seen so far.
5361 1.27 mjacob */
5362 1.33 mjacob if (nlooked) {
5363 1.111 mjacob ISP_WRITE(isp, isp->isp_respoutrp, optr);
5364 1.79 mjacob /*
5365 1.111 mjacob * While we're at it, read the requst queue out pointer.
5366 1.79 mjacob */
5367 1.111 mjacob isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp);
5368 1.111 mjacob if (isp->isp_rscchiwater < ndone) {
5369 1.87 mjacob isp->isp_rscchiwater = ndone;
5370 1.111 mjacob }
5371 1.111 mjacob }
5372 1.111 mjacob
5373 1.111 mjacob out:
5374 1.111 mjacob
5375 1.111 mjacob if (IS_24XX(isp)) {
5376 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
5377 1.111 mjacob } else {
5378 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
5379 1.111 mjacob ISP_WRITE(isp, BIU_SEMA, 0);
5380 1.27 mjacob }
5381 1.54 mjacob
5382 1.1 cgd isp->isp_residx = optr;
5383 1.25 mjacob for (i = 0; i < ndone; i++) {
5384 1.25 mjacob xs = complist[i];
5385 1.25 mjacob if (xs) {
5386 1.87 mjacob isp->isp_rsltccmplt++;
5387 1.57 mjacob isp_done(xs);
5388 1.25 mjacob }
5389 1.25 mjacob }
5390 1.1 cgd }
5391 1.1 cgd
5392 1.1 cgd /*
5393 1.1 cgd * Support routines.
5394 1.1 cgd */
5395 1.1 cgd
5396 1.117 mjacob #define GET_24XX_BUS(isp, chan, msg) \
5397 1.117 mjacob if (IS_24XX(isp)) { \
5398 1.117 mjacob chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; \
5399 1.117 mjacob if (chan >= isp->isp_nchan) { \
5400 1.117 mjacob isp_prt(isp, ISP_LOGERR, "bogus channel %u for %s at line %d", chan, msg, __LINE__); \
5401 1.117 mjacob break; \
5402 1.117 mjacob } \
5403 1.114 mjacob }
5404 1.114 mjacob
5405 1.25 mjacob static int
5406 1.111 mjacob isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
5407 1.25 mjacob {
5408 1.94 mjacob int rval = 0;
5409 1.114 mjacob int pattern = 0;
5410 1.114 mjacob uint16_t chan;
5411 1.31 mjacob
5412 1.44 mjacob if (IS_DUALBUS(isp)) {
5413 1.114 mjacob chan = ISP_READ(isp, OUTMAILBOX6);
5414 1.43 mjacob } else {
5415 1.114 mjacob chan = 0;
5416 1.43 mjacob }
5417 1.87 mjacob isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
5418 1.43 mjacob
5419 1.25 mjacob switch (mbox) {
5420 1.25 mjacob case ASYNC_BUS_RESET:
5421 1.114 mjacob if (IS_FC(isp)) {
5422 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5423 1.114 mjacob "ILLEGAL ASYNC_BUS_RESET for FC card");
5424 1.114 mjacob break;
5425 1.114 mjacob }
5426 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5427 1.29 mjacob #ifdef ISP_TARGET_MODE
5428 1.114 mjacob if (isp_target_async(isp, chan, mbox)) {
5429 1.94 mjacob rval = -1;
5430 1.111 mjacob }
5431 1.29 mjacob #endif
5432 1.114 mjacob isp_async(isp, ISPASYNC_BUS_RESET, chan);
5433 1.25 mjacob break;
5434 1.25 mjacob case ASYNC_SYSTEM_ERROR:
5435 1.114 mjacob isp->isp_dead = 1;
5436 1.111 mjacob isp->isp_state = ISP_CRASHED;
5437 1.111 mjacob if (IS_FC(isp)) {
5438 1.114 mjacob FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
5439 1.114 mjacob FCPARAM(isp, chan)->isp_fwstate = FW_CONFIG_WAIT;
5440 1.111 mjacob }
5441 1.111 mjacob /*
5442 1.111 mjacob * Were we waiting for a mailbox command to complete?
5443 1.111 mjacob * If so, it's dead, so wake up the waiter.
5444 1.111 mjacob */
5445 1.111 mjacob if (isp->isp_mboxbsy) {
5446 1.111 mjacob isp->isp_obits = 1;
5447 1.111 mjacob isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
5448 1.111 mjacob MBOX_NOTIFY_COMPLETE(isp);
5449 1.111 mjacob }
5450 1.96 mjacob /*
5451 1.111 mjacob * It's up to the handler for isp_async to reinit stuff and
5452 1.111 mjacob * restart the firmware
5453 1.96 mjacob */
5454 1.114 mjacob isp_async(isp, ISPASYNC_FW_CRASH);
5455 1.94 mjacob rval = -1;
5456 1.94 mjacob break;
5457 1.25 mjacob
5458 1.25 mjacob case ASYNC_RQS_XFER_ERR:
5459 1.57 mjacob isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
5460 1.25 mjacob break;
5461 1.25 mjacob
5462 1.25 mjacob case ASYNC_RSP_XFER_ERR:
5463 1.57 mjacob isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
5464 1.25 mjacob break;
5465 1.25 mjacob
5466 1.25 mjacob case ASYNC_QWAKEUP:
5467 1.114 mjacob #ifdef ISP_TARGET_MODE
5468 1.114 mjacob if (IS_24XX(isp)) {
5469 1.114 mjacob isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
5470 1.114 mjacob break;
5471 1.114 mjacob }
5472 1.114 mjacob #endif
5473 1.114 mjacob if (IS_FC(isp)) {
5474 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5475 1.114 mjacob "ILLEGAL ASYNC_QWAKEUP for FC card");
5476 1.114 mjacob break;
5477 1.114 mjacob }
5478 1.43 mjacob /*
5479 1.43 mjacob * We've just been notified that the Queue has woken up.
5480 1.43 mjacob * We don't need to be chatty about this- just unlatch things
5481 1.43 mjacob * and move on.
5482 1.43 mjacob */
5483 1.111 mjacob mbox = ISP_READ(isp, isp->isp_rqstoutrp);
5484 1.25 mjacob break;
5485 1.25 mjacob
5486 1.25 mjacob case ASYNC_TIMEOUT_RESET:
5487 1.114 mjacob if (IS_FC(isp)) {
5488 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5489 1.114 mjacob "ILLEGAL ASYNC_TIMEOUT_RESET for FC card");
5490 1.114 mjacob break;
5491 1.114 mjacob }
5492 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
5493 1.114 mjacob "timeout initiated SCSI bus reset of chan %d", chan);
5494 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5495 1.29 mjacob #ifdef ISP_TARGET_MODE
5496 1.114 mjacob if (isp_target_async(isp, chan, mbox)) {
5497 1.94 mjacob rval = -1;
5498 1.111 mjacob }
5499 1.29 mjacob #endif
5500 1.25 mjacob break;
5501 1.25 mjacob
5502 1.28 mjacob case ASYNC_DEVICE_RESET:
5503 1.114 mjacob if (IS_FC(isp)) {
5504 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5505 1.114 mjacob "ILLEGAL DEVICE_RESET for FC card");
5506 1.114 mjacob break;
5507 1.114 mjacob }
5508 1.114 mjacob isp_prt(isp, ISP_LOGINFO, "device reset on chan %d", chan);
5509 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5510 1.29 mjacob #ifdef ISP_TARGET_MODE
5511 1.114 mjacob if (isp_target_async(isp, chan, mbox)) {
5512 1.94 mjacob rval = -1;
5513 1.111 mjacob }
5514 1.29 mjacob #endif
5515 1.25 mjacob break;
5516 1.25 mjacob
5517 1.25 mjacob case ASYNC_EXTMSG_UNDERRUN:
5518 1.114 mjacob if (IS_FC(isp)) {
5519 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5520 1.114 mjacob "ILLEGAL ASYNC_EXTMSG_UNDERRUN for FC card");
5521 1.114 mjacob break;
5522 1.114 mjacob }
5523 1.57 mjacob isp_prt(isp, ISP_LOGWARN, "extended message underrun");
5524 1.25 mjacob break;
5525 1.25 mjacob
5526 1.25 mjacob case ASYNC_SCAM_INT:
5527 1.114 mjacob if (IS_FC(isp)) {
5528 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5529 1.114 mjacob "ILLEGAL ASYNC_SCAM_INT for FC card");
5530 1.114 mjacob break;
5531 1.114 mjacob }
5532 1.57 mjacob isp_prt(isp, ISP_LOGINFO, "SCAM interrupt");
5533 1.25 mjacob break;
5534 1.25 mjacob
5535 1.25 mjacob case ASYNC_HUNG_SCSI:
5536 1.114 mjacob if (IS_FC(isp)) {
5537 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5538 1.114 mjacob "ILLEGAL ASYNC_HUNG_SCSI for FC card");
5539 1.114 mjacob break;
5540 1.114 mjacob }
5541 1.57 mjacob isp_prt(isp, ISP_LOGERR,
5542 1.57 mjacob "stalled SCSI Bus after DATA Overrun");
5543 1.25 mjacob /* XXX: Need to issue SCSI reset at this point */
5544 1.25 mjacob break;
5545 1.25 mjacob
5546 1.25 mjacob case ASYNC_KILLED_BUS:
5547 1.114 mjacob if (IS_FC(isp)) {
5548 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5549 1.114 mjacob "ILLEGAL ASYNC_KILLED_BUS for FC card");
5550 1.114 mjacob break;
5551 1.114 mjacob }
5552 1.57 mjacob isp_prt(isp, ISP_LOGERR, "SCSI Bus reset after DATA Overrun");
5553 1.25 mjacob break;
5554 1.25 mjacob
5555 1.25 mjacob case ASYNC_BUS_TRANSIT:
5556 1.114 mjacob if (IS_FC(isp)) {
5557 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5558 1.114 mjacob "ILLEGAL ASYNC_BUS_TRANSIT for FC card");
5559 1.114 mjacob break;
5560 1.114 mjacob }
5561 1.34 mjacob mbox = ISP_READ(isp, OUTMAILBOX2);
5562 1.34 mjacob switch (mbox & 0x1c00) {
5563 1.34 mjacob case SXP_PINS_LVD_MODE:
5564 1.57 mjacob isp_prt(isp, ISP_LOGINFO, "Transition to LVD mode");
5565 1.114 mjacob SDPARAM(isp, chan)->isp_diffmode = 0;
5566 1.114 mjacob SDPARAM(isp, chan)->isp_ultramode = 0;
5567 1.114 mjacob SDPARAM(isp, chan)->isp_lvdmode = 1;
5568 1.34 mjacob break;
5569 1.34 mjacob case SXP_PINS_HVD_MODE:
5570 1.57 mjacob isp_prt(isp, ISP_LOGINFO,
5571 1.57 mjacob "Transition to Differential mode");
5572 1.114 mjacob SDPARAM(isp, chan)->isp_diffmode = 1;
5573 1.114 mjacob SDPARAM(isp, chan)->isp_ultramode = 0;
5574 1.114 mjacob SDPARAM(isp, chan)->isp_lvdmode = 0;
5575 1.34 mjacob break;
5576 1.34 mjacob case SXP_PINS_SE_MODE:
5577 1.57 mjacob isp_prt(isp, ISP_LOGINFO,
5578 1.57 mjacob "Transition to Single Ended mode");
5579 1.114 mjacob SDPARAM(isp, chan)->isp_diffmode = 0;
5580 1.114 mjacob SDPARAM(isp, chan)->isp_ultramode = 1;
5581 1.114 mjacob SDPARAM(isp, chan)->isp_lvdmode = 0;
5582 1.34 mjacob break;
5583 1.34 mjacob default:
5584 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
5585 1.57 mjacob "Transition to Unknown Mode 0x%x", mbox);
5586 1.34 mjacob break;
5587 1.34 mjacob }
5588 1.34 mjacob /*
5589 1.34 mjacob * XXX: Set up to renegotiate again!
5590 1.34 mjacob */
5591 1.36 mjacob /* Can only be for a 1080... */
5592 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5593 1.25 mjacob break;
5594 1.25 mjacob
5595 1.87 mjacob case ASYNC_RIO5:
5596 1.114 mjacob pattern = 0xce; /* outgoing mailbox regs 1-3, 6-7 */
5597 1.87 mjacob break;
5598 1.87 mjacob
5599 1.87 mjacob case ASYNC_RIO4:
5600 1.114 mjacob pattern = 0x4e; /* outgoing mailbox regs 1-3, 6 */
5601 1.87 mjacob break;
5602 1.87 mjacob
5603 1.87 mjacob case ASYNC_RIO3:
5604 1.114 mjacob pattern = 0x0e; /* outgoing mailbox regs 1-3 */
5605 1.87 mjacob break;
5606 1.87 mjacob
5607 1.87 mjacob case ASYNC_RIO2:
5608 1.114 mjacob pattern = 0x06; /* outgoing mailbox regs 1-2 */
5609 1.87 mjacob break;
5610 1.87 mjacob
5611 1.87 mjacob case ASYNC_RIO1:
5612 1.25 mjacob case ASYNC_CMD_CMPLT:
5613 1.114 mjacob pattern = 0x02; /* outgoing mailbox regs 1 */
5614 1.87 mjacob break;
5615 1.87 mjacob
5616 1.87 mjacob case ASYNC_RIO_RESP:
5617 1.97 mjacob return (rval);
5618 1.25 mjacob
5619 1.25 mjacob case ASYNC_CTIO_DONE:
5620 1.94 mjacob {
5621 1.58 mjacob #ifdef ISP_TARGET_MODE
5622 1.114 mjacob int handle;
5623 1.114 mjacob if (IS_SCSI(isp) || IS_24XX(isp)) {
5624 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5625 1.114 mjacob "bad ASYNC_CTIO_DONE for %s cards",
5626 1.114 mjacob IS_SCSI(isp)? "SCSI" : "24XX");
5627 1.114 mjacob break;
5628 1.114 mjacob }
5629 1.114 mjacob handle =
5630 1.117 mjacob (ISP_READ(isp, OUTMAILBOX2) << 16) |
5631 1.94 mjacob (ISP_READ(isp, OUTMAILBOX1));
5632 1.111 mjacob if (isp_target_async(isp, handle, mbox)) {
5633 1.94 mjacob rval = -1;
5634 1.111 mjacob } else {
5635 1.111 mjacob /* count it as a fast posting intr */
5636 1.111 mjacob isp->isp_fphccmplt++;
5637 1.111 mjacob }
5638 1.58 mjacob #else
5639 1.114 mjacob if (IS_SCSI(isp) || IS_24XX(isp)) {
5640 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5641 1.114 mjacob "bad ASYNC_CTIO_DONE for %s cards",
5642 1.114 mjacob IS_SCSI(isp)? "SCSI" : "24XX");
5643 1.114 mjacob break;
5644 1.114 mjacob }
5645 1.58 mjacob isp_prt(isp, ISP_LOGINFO, "Fast Posting CTIO done");
5646 1.111 mjacob isp->isp_fphccmplt++; /* count it as a fast posting intr */
5647 1.58 mjacob #endif
5648 1.94 mjacob break;
5649 1.94 mjacob }
5650 1.111 mjacob case ASYNC_LIP_ERROR:
5651 1.79 mjacob case ASYNC_LIP_F8:
5652 1.25 mjacob case ASYNC_LIP_OCCURRED:
5653 1.114 mjacob case ASYNC_PTPMODE:
5654 1.114 mjacob if (IS_SCSI(isp)) {
5655 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5656 1.114 mjacob "bad LIP event for SCSI cards");
5657 1.114 mjacob break;
5658 1.114 mjacob }
5659 1.114 mjacob /*
5660 1.114 mjacob * These are broadcast events that have to be sent across
5661 1.114 mjacob * all active channels.
5662 1.114 mjacob */
5663 1.114 mjacob for (chan = 0; chan < isp->isp_nchan; chan++) {
5664 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
5665 1.114 mjacob int topo = fcp->isp_topo;
5666 1.114 mjacob
5667 1.114 mjacob if (fcp->role == ISP_ROLE_NONE) {
5668 1.114 mjacob continue;
5669 1.114 mjacob }
5670 1.114 mjacob
5671 1.114 mjacob fcp->isp_fwstate = FW_CONFIG_WAIT;
5672 1.114 mjacob fcp->isp_loopstate = LOOP_LIP_RCVD;
5673 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5674 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
5675 1.114 mjacob isp_async(isp, ISPASYNC_LIP, chan);
5676 1.46 mjacob #ifdef ISP_TARGET_MODE
5677 1.114 mjacob if (isp_target_async(isp, chan, mbox)) {
5678 1.114 mjacob rval = -1;
5679 1.114 mjacob }
5680 1.46 mjacob #endif
5681 1.114 mjacob /*
5682 1.114 mjacob * We've had problems with data corruption occuring on
5683 1.114 mjacob * commands that complete (with no apparent error) after
5684 1.114 mjacob * we receive a LIP. This has been observed mostly on
5685 1.114 mjacob * Local Loop topologies. To be safe, let's just mark
5686 1.114 mjacob * all active commands as dead.
5687 1.114 mjacob */
5688 1.114 mjacob if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
5689 1.114 mjacob int i, j;
5690 1.114 mjacob for (i = j = 0; i < isp->isp_maxcmds; i++) {
5691 1.114 mjacob XS_T *xs;
5692 1.114 mjacob xs = isp->isp_xflist[i];
5693 1.114 mjacob if (xs == NULL) {
5694 1.114 mjacob continue;
5695 1.114 mjacob }
5696 1.114 mjacob if (XS_CHANNEL(xs) != chan) {
5697 1.114 mjacob continue;
5698 1.114 mjacob }
5699 1.78 mjacob j++;
5700 1.78 mjacob XS_SETERR(xs, HBA_BUSRESET);
5701 1.78 mjacob }
5702 1.114 mjacob if (j) {
5703 1.114 mjacob isp_prt(isp, ISP_LOGERR, lipd, chan, j);
5704 1.114 mjacob }
5705 1.78 mjacob }
5706 1.78 mjacob }
5707 1.25 mjacob break;
5708 1.25 mjacob
5709 1.25 mjacob case ASYNC_LOOP_UP:
5710 1.114 mjacob if (IS_SCSI(isp)) {
5711 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5712 1.114 mjacob "bad LOOP UP event for SCSI cards");
5713 1.114 mjacob break;
5714 1.114 mjacob }
5715 1.114 mjacob /*
5716 1.114 mjacob * This is a broadcast event that has to be sent across
5717 1.114 mjacob * all active channels.
5718 1.114 mjacob */
5719 1.114 mjacob for (chan = 0; chan < isp->isp_nchan; chan++) {
5720 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
5721 1.114 mjacob
5722 1.114 mjacob if (fcp->role == ISP_ROLE_NONE) {
5723 1.114 mjacob continue;
5724 1.114 mjacob }
5725 1.114 mjacob
5726 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5727 1.114 mjacob
5728 1.114 mjacob fcp->isp_fwstate = FW_CONFIG_WAIT;
5729 1.114 mjacob fcp->isp_loopstate = LOOP_LIP_RCVD;
5730 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
5731 1.114 mjacob isp_async(isp, ISPASYNC_LOOP_UP, chan);
5732 1.46 mjacob #ifdef ISP_TARGET_MODE
5733 1.114 mjacob if (isp_target_async(isp, chan, mbox)) {
5734 1.114 mjacob rval = -1;
5735 1.114 mjacob }
5736 1.114 mjacob #endif
5737 1.111 mjacob }
5738 1.25 mjacob break;
5739 1.25 mjacob
5740 1.25 mjacob case ASYNC_LOOP_DOWN:
5741 1.114 mjacob if (IS_SCSI(isp)) {
5742 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5743 1.114 mjacob "bad LOOP DOWN event for SCSI cards");
5744 1.114 mjacob break;
5745 1.114 mjacob }
5746 1.114 mjacob /*
5747 1.114 mjacob * This is a broadcast event that has to be sent across
5748 1.114 mjacob * all active channels.
5749 1.114 mjacob */
5750 1.114 mjacob for (chan = 0; chan < isp->isp_nchan; chan++) {
5751 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
5752 1.114 mjacob
5753 1.114 mjacob if (fcp->role == ISP_ROLE_NONE) {
5754 1.114 mjacob continue;
5755 1.114 mjacob }
5756 1.114 mjacob
5757 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5758 1.114 mjacob fcp->isp_fwstate = FW_CONFIG_WAIT;
5759 1.114 mjacob fcp->isp_loopstate = LOOP_NIL;
5760 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
5761 1.114 mjacob isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
5762 1.46 mjacob #ifdef ISP_TARGET_MODE
5763 1.114 mjacob if (isp_target_async(isp, chan, mbox)) {
5764 1.114 mjacob rval = -1;
5765 1.114 mjacob }
5766 1.114 mjacob #endif
5767 1.111 mjacob }
5768 1.25 mjacob break;
5769 1.25 mjacob
5770 1.25 mjacob case ASYNC_LOOP_RESET:
5771 1.114 mjacob if (IS_SCSI(isp)) {
5772 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5773 1.114 mjacob "bad LIP RESET event for SCSI cards");
5774 1.114 mjacob break;
5775 1.111 mjacob }
5776 1.114 mjacob /*
5777 1.114 mjacob * This is a broadcast event that has to be sent across
5778 1.114 mjacob * all active channels.
5779 1.114 mjacob */
5780 1.114 mjacob for (chan = 0; chan < isp->isp_nchan; chan++) {
5781 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
5782 1.114 mjacob
5783 1.114 mjacob if (fcp->role == ISP_ROLE_NONE) {
5784 1.114 mjacob continue;
5785 1.114 mjacob }
5786 1.114 mjacob
5787 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5788 1.114 mjacob fcp->isp_fwstate = FW_CONFIG_WAIT;
5789 1.114 mjacob fcp->isp_loopstate = LOOP_NIL;
5790 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
5791 1.114 mjacob isp_async(isp, ISPASYNC_LOOP_RESET, chan);
5792 1.114 mjacob #ifdef ISP_TARGET_MODE
5793 1.114 mjacob if (isp_target_async(isp, chan, mbox)) {
5794 1.114 mjacob rval = -1;
5795 1.114 mjacob }
5796 1.114 mjacob #endif
5797 1.114 mjacob }
5798 1.114 mjacob break;
5799 1.25 mjacob
5800 1.25 mjacob case ASYNC_PDB_CHANGED:
5801 1.114 mjacob {
5802 1.114 mjacob int nphdl, nlstate, reason;
5803 1.114 mjacob if (IS_SCSI(isp)) {
5804 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5805 1.114 mjacob "bad PDB CHANGED event for SCSI cards");
5806 1.114 mjacob break;
5807 1.114 mjacob }
5808 1.114 mjacob /*
5809 1.114 mjacob * We *should* get a channel out of the 24XX, but we don't seem
5810 1.114 mjacob * to get more than a PDB CHANGED on channel 0, so turn it into
5811 1.114 mjacob * a broadcast event.
5812 1.114 mjacob */
5813 1.114 mjacob if (IS_24XX(isp)) {
5814 1.114 mjacob nphdl = ISP_READ(isp, OUTMAILBOX1);
5815 1.114 mjacob nlstate = ISP_READ(isp, OUTMAILBOX2);
5816 1.114 mjacob reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
5817 1.114 mjacob } else {
5818 1.114 mjacob nphdl = NIL_HANDLE;
5819 1.114 mjacob nlstate = reason = 0;
5820 1.114 mjacob }
5821 1.114 mjacob for (chan = 0; chan < isp->isp_nchan; chan++) {
5822 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
5823 1.114 mjacob
5824 1.114 mjacob if (fcp->role == ISP_ROLE_NONE) {
5825 1.114 mjacob continue;
5826 1.114 mjacob }
5827 1.114 mjacob ISP_SET_SENDMARKER(isp, chan, 1);
5828 1.114 mjacob fcp->isp_loopstate = LOOP_PDB_RCVD;
5829 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
5830 1.114 mjacob isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
5831 1.114 mjacob ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
5832 1.114 mjacob }
5833 1.25 mjacob break;
5834 1.114 mjacob }
5835 1.114 mjacob case ASYNC_CHANGE_NOTIFY:
5836 1.114 mjacob {
5837 1.114 mjacob int lochan, hichan;
5838 1.25 mjacob
5839 1.114 mjacob if (IS_SCSI(isp)) {
5840 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5841 1.114 mjacob "bad CHANGE NOTIFY event for SCSI cards");
5842 1.114 mjacob break;
5843 1.114 mjacob }
5844 1.114 mjacob if (ISP_FW_NEWER_THAN(isp, 4, 0, 25) && ISP_CAP_MULTI_ID(isp)) {
5845 1.114 mjacob GET_24XX_BUS(isp, chan, "ASYNC_CHANGE_NOTIFY");
5846 1.114 mjacob lochan = chan;
5847 1.114 mjacob hichan = chan + 1;
5848 1.111 mjacob } else {
5849 1.114 mjacob lochan = 0;
5850 1.114 mjacob hichan = isp->isp_nchan;
5851 1.111 mjacob }
5852 1.114 mjacob for (chan = lochan; chan < hichan; chan++) {
5853 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
5854 1.114 mjacob
5855 1.114 mjacob if (fcp->role == ISP_ROLE_NONE) {
5856 1.114 mjacob continue;
5857 1.114 mjacob }
5858 1.25 mjacob
5859 1.114 mjacob if (fcp->isp_topo == TOPO_F_PORT) {
5860 1.114 mjacob fcp->isp_loopstate = LOOP_LSCAN_DONE;
5861 1.114 mjacob } else {
5862 1.114 mjacob fcp->isp_loopstate = LOOP_PDB_RCVD;
5863 1.114 mjacob }
5864 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
5865 1.114 mjacob isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
5866 1.114 mjacob ISPASYNC_CHANGE_SNS);
5867 1.111 mjacob }
5868 1.49 mjacob break;
5869 1.114 mjacob }
5870 1.49 mjacob
5871 1.49 mjacob case ASYNC_CONNMODE:
5872 1.114 mjacob /*
5873 1.114 mjacob * This only applies to 2100 amd 2200 cards
5874 1.114 mjacob */
5875 1.114 mjacob if (!IS_2200(isp) && !IS_2100(isp)) {
5876 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5877 1.114 mjacob "bad card for ASYNC_CONNMODE event");
5878 1.114 mjacob break;
5879 1.114 mjacob }
5880 1.114 mjacob chan = 0;
5881 1.49 mjacob mbox = ISP_READ(isp, OUTMAILBOX1);
5882 1.114 mjacob ISP_MARK_PORTDB(isp, chan, 1);
5883 1.49 mjacob switch (mbox) {
5884 1.49 mjacob case ISP_CONN_LOOP:
5885 1.70 mjacob isp_prt(isp, ISP_LOGINFO,
5886 1.70 mjacob "Point-to-Point -> Loop mode");
5887 1.49 mjacob break;
5888 1.49 mjacob case ISP_CONN_PTP:
5889 1.70 mjacob isp_prt(isp, ISP_LOGINFO,
5890 1.70 mjacob "Loop -> Point-to-Point mode");
5891 1.49 mjacob break;
5892 1.49 mjacob case ISP_CONN_BADLIP:
5893 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
5894 1.70 mjacob "Point-to-Point -> Loop mode (BAD LIP)");
5895 1.49 mjacob break;
5896 1.49 mjacob case ISP_CONN_FATAL:
5897 1.114 mjacob isp->isp_dead = 1;
5898 1.114 mjacob isp->isp_state = ISP_CRASHED;
5899 1.57 mjacob isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR");
5900 1.114 mjacob isp_async(isp, ISPASYNC_FW_CRASH);
5901 1.49 mjacob return (-1);
5902 1.49 mjacob case ISP_CONN_LOOPBACK:
5903 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
5904 1.57 mjacob "Looped Back in Point-to-Point mode");
5905 1.70 mjacob break;
5906 1.70 mjacob default:
5907 1.70 mjacob isp_prt(isp, ISP_LOGWARN,
5908 1.70 mjacob "Unknown connection mode (0x%x)", mbox);
5909 1.70 mjacob break;
5910 1.49 mjacob }
5911 1.114 mjacob isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
5912 1.114 mjacob ISPASYNC_CHANGE_OTHER);
5913 1.114 mjacob FCPARAM(isp, chan)->sendmarker = 1;
5914 1.114 mjacob FCPARAM(isp, chan)->isp_fwstate = FW_CONFIG_WAIT;
5915 1.114 mjacob FCPARAM(isp, chan)->isp_loopstate = LOOP_LIP_RCVD;
5916 1.49 mjacob break;
5917 1.49 mjacob
5918 1.114 mjacob case ASYNC_RCV_ERR:
5919 1.114 mjacob if (IS_24XX(isp)) {
5920 1.114 mjacob isp_prt(isp, ISP_LOGWARN, "Receive Error");
5921 1.114 mjacob } else {
5922 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
5923 1.114 mjacob "Unknown Async Code 0x%x", mbox);
5924 1.114 mjacob }
5925 1.114 mjacob break;
5926 1.111 mjacob case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */
5927 1.111 mjacob if (IS_24XX(isp)) {
5928 1.111 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
5929 1.111 mjacob break;
5930 1.111 mjacob } else if (IS_2200(isp)) {
5931 1.111 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "QFULL sent");
5932 1.111 mjacob break;
5933 1.111 mjacob }
5934 1.111 mjacob /* FALLTHROUGH */
5935 1.25 mjacob default:
5936 1.57 mjacob isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
5937 1.25 mjacob break;
5938 1.25 mjacob }
5939 1.87 mjacob
5940 1.114 mjacob if (pattern) {
5941 1.87 mjacob int i, nh;
5942 1.111 mjacob uint16_t handles[16];
5943 1.87 mjacob
5944 1.111 mjacob for (nh = 0, i = 1; i < MAX_MAILBOX(isp); i++) {
5945 1.114 mjacob if ((pattern & (1 << i)) == 0) {
5946 1.87 mjacob continue;
5947 1.87 mjacob }
5948 1.87 mjacob handles[nh++] = ISP_READ(isp, MBOX_OFF(i));
5949 1.87 mjacob }
5950 1.87 mjacob for (i = 0; i < nh; i++) {
5951 1.87 mjacob isp_fastpost_complete(isp, handles[i]);
5952 1.87 mjacob isp_prt(isp, ISP_LOGDEBUG3,
5953 1.87 mjacob "fast post completion of %u", handles[i]);
5954 1.87 mjacob }
5955 1.111 mjacob if (isp->isp_fpcchiwater < nh) {
5956 1.87 mjacob isp->isp_fpcchiwater = nh;
5957 1.111 mjacob }
5958 1.87 mjacob } else {
5959 1.87 mjacob isp->isp_intoasync++;
5960 1.87 mjacob }
5961 1.94 mjacob return (rval);
5962 1.25 mjacob }
5963 1.25 mjacob
5964 1.43 mjacob /*
5965 1.43 mjacob * Handle other response entries. A pointer to the request queue output
5966 1.43 mjacob * index is here in case we want to eat several entries at once, although
5967 1.43 mjacob * this is not used currently.
5968 1.43 mjacob */
5969 1.43 mjacob
5970 1.25 mjacob static int
5971 1.111 mjacob isp_handle_other_response(ispsoftc_t *isp, int type,
5972 1.111 mjacob isphdr_t *hp, uint32_t *optrp)
5973 1.25 mjacob {
5974 1.86 mjacob switch (type) {
5975 1.58 mjacob case RQSTYPE_STATUS_CONT:
5976 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0, "Ignored Continuation Response");
5977 1.111 mjacob return (1);
5978 1.111 mjacob case RQSTYPE_MARKER:
5979 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0, "Marker Response");
5980 1.90 mjacob return (1);
5981 1.38 mjacob case RQSTYPE_ATIO:
5982 1.46 mjacob case RQSTYPE_CTIO:
5983 1.29 mjacob case RQSTYPE_ENABLE_LUN:
5984 1.29 mjacob case RQSTYPE_MODIFY_LUN:
5985 1.38 mjacob case RQSTYPE_NOTIFY:
5986 1.38 mjacob case RQSTYPE_NOTIFY_ACK:
5987 1.38 mjacob case RQSTYPE_CTIO1:
5988 1.29 mjacob case RQSTYPE_ATIO2:
5989 1.38 mjacob case RQSTYPE_CTIO2:
5990 1.38 mjacob case RQSTYPE_CTIO3:
5991 1.111 mjacob case RQSTYPE_CTIO7:
5992 1.111 mjacob case RQSTYPE_ABTS_RCVD:
5993 1.111 mjacob case RQSTYPE_ABTS_RSP:
5994 1.88 mjacob isp->isp_rsltccmplt++; /* count as a response completion */
5995 1.38 mjacob #ifdef ISP_TARGET_MODE
5996 1.90 mjacob if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)) {
5997 1.90 mjacob return (1);
5998 1.90 mjacob }
5999 1.101 mjacob #endif
6000 1.38 mjacob /* FALLTHROUGH */
6001 1.114 mjacob case RQSTYPE_RPT_ID_ACQ:
6002 1.114 mjacob if (IS_24XX(isp)) {
6003 1.114 mjacob isp_ridacq_t rid;
6004 1.114 mjacob isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
6005 1.114 mjacob if (rid.ridacq_format == 0) {
6006 1.114 mjacob }
6007 1.114 mjacob return (1);
6008 1.114 mjacob }
6009 1.114 mjacob /* FALLTHROUGH */
6010 1.38 mjacob case RQSTYPE_REQUEST:
6011 1.25 mjacob default:
6012 1.117 mjacob ISP_DELAY(100);
6013 1.111 mjacob if (type != isp_get_response_type(isp, hp)) {
6014 1.111 mjacob /*
6015 1.111 mjacob * This is questionable- we're just papering over
6016 1.111 mjacob * something we've seen on SMP linux in target
6017 1.111 mjacob * mode- we don't really know what's happening
6018 1.111 mjacob * here that causes us to think we've gotten
6019 1.111 mjacob * an entry, but that either the entry isn't
6020 1.111 mjacob * filled out yet or our CPU read data is stale.
6021 1.111 mjacob */
6022 1.111 mjacob isp_prt(isp, ISP_LOGINFO,
6023 1.111 mjacob "unstable type in response queue");
6024 1.111 mjacob return (-1);
6025 1.111 mjacob }
6026 1.111 mjacob isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x",
6027 1.111 mjacob isp_get_response_type(isp, hp));
6028 1.90 mjacob return (0);
6029 1.29 mjacob }
6030 1.29 mjacob }
6031 1.29 mjacob
6032 1.23 mjacob static void
6033 1.111 mjacob isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
6034 1.1 cgd {
6035 1.57 mjacob switch (sp->req_completion_status & 0xff) {
6036 1.1 cgd case RQCS_COMPLETE:
6037 1.57 mjacob if (XS_NOERR(xs)) {
6038 1.57 mjacob XS_SETERR(xs, HBA_NOERROR);
6039 1.57 mjacob }
6040 1.23 mjacob return;
6041 1.10 mjacob
6042 1.1 cgd case RQCS_INCOMPLETE:
6043 1.1 cgd if ((sp->req_state_flags & RQSF_GOT_TARGET) == 0) {
6044 1.58 mjacob isp_prt(isp, ISP_LOGDEBUG1,
6045 1.57 mjacob "Selection Timeout for %d.%d.%d",
6046 1.63 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6047 1.57 mjacob if (XS_NOERR(xs)) {
6048 1.57 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
6049 1.111 mjacob *rp = XS_XFRLEN(xs);
6050 1.57 mjacob }
6051 1.23 mjacob return;
6052 1.1 cgd }
6053 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6054 1.57 mjacob "command incomplete for %d.%d.%d, state 0x%x",
6055 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs),
6056 1.25 mjacob sp->req_state_flags);
6057 1.25 mjacob break;
6058 1.25 mjacob
6059 1.25 mjacob case RQCS_DMA_ERROR:
6060 1.57 mjacob isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d",
6061 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6062 1.111 mjacob *rp = XS_XFRLEN(xs);
6063 1.1 cgd break;
6064 1.15 mjacob
6065 1.15 mjacob case RQCS_TRANSPORT_ERROR:
6066 1.57 mjacob {
6067 1.111 mjacob char buf[172];
6068 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "states=>");
6069 1.57 mjacob if (sp->req_state_flags & RQSF_GOT_BUS) {
6070 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s GOT_BUS", buf);
6071 1.57 mjacob }
6072 1.57 mjacob if (sp->req_state_flags & RQSF_GOT_TARGET) {
6073 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s GOT_TGT", buf);
6074 1.57 mjacob }
6075 1.57 mjacob if (sp->req_state_flags & RQSF_SENT_CDB) {
6076 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s SENT_CDB", buf);
6077 1.57 mjacob }
6078 1.57 mjacob if (sp->req_state_flags & RQSF_XFRD_DATA) {
6079 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s XFRD_DATA", buf);
6080 1.57 mjacob }
6081 1.57 mjacob if (sp->req_state_flags & RQSF_GOT_STATUS) {
6082 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s GOT_STS", buf);
6083 1.57 mjacob }
6084 1.57 mjacob if (sp->req_state_flags & RQSF_GOT_SENSE) {
6085 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s GOT_SNS", buf);
6086 1.57 mjacob }
6087 1.57 mjacob if (sp->req_state_flags & RQSF_XFER_COMPLETE) {
6088 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s XFR_CMPLT", buf);
6089 1.57 mjacob }
6090 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s\nstatus=>", buf);
6091 1.57 mjacob if (sp->req_status_flags & RQSTF_DISCONNECT) {
6092 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s Disconnect", buf);
6093 1.57 mjacob }
6094 1.57 mjacob if (sp->req_status_flags & RQSTF_SYNCHRONOUS) {
6095 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s Sync_xfr", buf);
6096 1.57 mjacob }
6097 1.57 mjacob if (sp->req_status_flags & RQSTF_PARITY_ERROR) {
6098 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s Parity", buf);
6099 1.57 mjacob }
6100 1.57 mjacob if (sp->req_status_flags & RQSTF_BUS_RESET) {
6101 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s Bus_Reset", buf);
6102 1.57 mjacob }
6103 1.57 mjacob if (sp->req_status_flags & RQSTF_DEVICE_RESET) {
6104 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s Device_Reset", buf);
6105 1.57 mjacob }
6106 1.57 mjacob if (sp->req_status_flags & RQSTF_ABORTED) {
6107 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s Aborted", buf);
6108 1.57 mjacob }
6109 1.57 mjacob if (sp->req_status_flags & RQSTF_TIMEOUT) {
6110 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s Timeout", buf);
6111 1.57 mjacob }
6112 1.57 mjacob if (sp->req_status_flags & RQSTF_NEGOTIATION) {
6113 1.117 mjacob ISP_SNPRINTF(buf, sizeof (buf), "%s Negotiation", buf);
6114 1.57 mjacob }
6115 1.111 mjacob isp_prt(isp, ISP_LOGERR, "%s", buf);
6116 1.57 mjacob isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d:\n%s",
6117 1.111 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), buf);
6118 1.111 mjacob *rp = XS_XFRLEN(xs);
6119 1.15 mjacob break;
6120 1.57 mjacob }
6121 1.25 mjacob case RQCS_RESET_OCCURRED:
6122 1.114 mjacob {
6123 1.114 mjacob int chan;
6124 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
6125 1.57 mjacob "bus reset destroyed command for %d.%d.%d",
6126 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6127 1.114 mjacob for (chan = 0; chan < isp->isp_nchan; chan++) {
6128 1.114 mjacob FCPARAM(isp, chan)->sendmarker = 1;
6129 1.114 mjacob }
6130 1.57 mjacob if (XS_NOERR(xs)) {
6131 1.57 mjacob XS_SETERR(xs, HBA_BUSRESET);
6132 1.57 mjacob }
6133 1.111 mjacob *rp = XS_XFRLEN(xs);
6134 1.25 mjacob return;
6135 1.114 mjacob }
6136 1.25 mjacob case RQCS_ABORTED:
6137 1.57 mjacob isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d",
6138 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6139 1.114 mjacob ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1);
6140 1.57 mjacob if (XS_NOERR(xs)) {
6141 1.57 mjacob XS_SETERR(xs, HBA_ABORTED);
6142 1.57 mjacob }
6143 1.25 mjacob return;
6144 1.25 mjacob
6145 1.25 mjacob case RQCS_TIMEOUT:
6146 1.57 mjacob isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d",
6147 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6148 1.95 mjacob /*
6149 1.111 mjacob * XXX: Check to see if we logged out of the device.
6150 1.95 mjacob */
6151 1.57 mjacob if (XS_NOERR(xs)) {
6152 1.57 mjacob XS_SETERR(xs, HBA_CMDTIMEOUT);
6153 1.57 mjacob }
6154 1.25 mjacob return;
6155 1.25 mjacob
6156 1.10 mjacob case RQCS_DATA_OVERRUN:
6157 1.117 mjacob XS_SET_RESID(xs, sp->req_resid);
6158 1.117 mjacob isp_prt(isp, ISP_LOGERR, "data overrun (%ld) for command on %d.%d.%d",
6159 1.117 mjacob (long) XS_GET_RESID(xs), XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6160 1.57 mjacob if (XS_NOERR(xs)) {
6161 1.57 mjacob XS_SETERR(xs, HBA_DATAOVR);
6162 1.57 mjacob }
6163 1.23 mjacob return;
6164 1.10 mjacob
6165 1.25 mjacob case RQCS_COMMAND_OVERRUN:
6166 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6167 1.57 mjacob "command overrun for command on %d.%d.%d",
6168 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6169 1.25 mjacob break;
6170 1.25 mjacob
6171 1.25 mjacob case RQCS_STATUS_OVERRUN:
6172 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6173 1.57 mjacob "status overrun for command on %d.%d.%d",
6174 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6175 1.25 mjacob break;
6176 1.25 mjacob
6177 1.25 mjacob case RQCS_BAD_MESSAGE:
6178 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6179 1.57 mjacob "msg not COMMAND COMPLETE after status %d.%d.%d",
6180 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6181 1.25 mjacob break;
6182 1.25 mjacob
6183 1.25 mjacob case RQCS_NO_MESSAGE_OUT:
6184 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6185 1.57 mjacob "No MESSAGE OUT phase after selection on %d.%d.%d",
6186 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6187 1.25 mjacob break;
6188 1.25 mjacob
6189 1.25 mjacob case RQCS_EXT_ID_FAILED:
6190 1.57 mjacob isp_prt(isp, ISP_LOGERR, "EXTENDED IDENTIFY failed %d.%d.%d",
6191 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6192 1.25 mjacob break;
6193 1.25 mjacob
6194 1.25 mjacob case RQCS_IDE_MSG_FAILED:
6195 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6196 1.57 mjacob "INITIATOR DETECTED ERROR rejected by %d.%d.%d",
6197 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6198 1.25 mjacob break;
6199 1.25 mjacob
6200 1.25 mjacob case RQCS_ABORT_MSG_FAILED:
6201 1.57 mjacob isp_prt(isp, ISP_LOGERR, "ABORT OPERATION rejected by %d.%d.%d",
6202 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6203 1.25 mjacob break;
6204 1.25 mjacob
6205 1.25 mjacob case RQCS_REJECT_MSG_FAILED:
6206 1.57 mjacob isp_prt(isp, ISP_LOGERR, "MESSAGE REJECT rejected by %d.%d.%d",
6207 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6208 1.25 mjacob break;
6209 1.25 mjacob
6210 1.25 mjacob case RQCS_NOP_MSG_FAILED:
6211 1.57 mjacob isp_prt(isp, ISP_LOGERR, "NOP rejected by %d.%d.%d",
6212 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6213 1.25 mjacob break;
6214 1.25 mjacob
6215 1.25 mjacob case RQCS_PARITY_ERROR_MSG_FAILED:
6216 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6217 1.57 mjacob "MESSAGE PARITY ERROR rejected by %d.%d.%d",
6218 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6219 1.25 mjacob break;
6220 1.25 mjacob
6221 1.25 mjacob case RQCS_DEVICE_RESET_MSG_FAILED:
6222 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
6223 1.57 mjacob "BUS DEVICE RESET rejected by %d.%d.%d",
6224 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6225 1.25 mjacob break;
6226 1.25 mjacob
6227 1.25 mjacob case RQCS_ID_MSG_FAILED:
6228 1.57 mjacob isp_prt(isp, ISP_LOGERR, "IDENTIFY rejected by %d.%d.%d",
6229 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6230 1.25 mjacob break;
6231 1.25 mjacob
6232 1.25 mjacob case RQCS_UNEXP_BUS_FREE:
6233 1.57 mjacob isp_prt(isp, ISP_LOGERR, "%d.%d.%d had an unexpected bus free",
6234 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6235 1.25 mjacob break;
6236 1.25 mjacob
6237 1.1 cgd case RQCS_DATA_UNDERRUN:
6238 1.94 mjacob {
6239 1.94 mjacob if (IS_FC(isp)) {
6240 1.94 mjacob int ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
6241 1.94 mjacob if (!ru_marked || sp->req_resid > XS_XFRLEN(xs)) {
6242 1.94 mjacob isp_prt(isp, ISP_LOGWARN, bun, XS_TGT(xs),
6243 1.94 mjacob XS_LUN(xs), XS_XFRLEN(xs), sp->req_resid,
6244 1.94 mjacob (ru_marked)? "marked" : "not marked");
6245 1.94 mjacob if (XS_NOERR(xs)) {
6246 1.94 mjacob XS_SETERR(xs, HBA_BOTCH);
6247 1.94 mjacob }
6248 1.94 mjacob return;
6249 1.94 mjacob }
6250 1.94 mjacob }
6251 1.117 mjacob XS_SET_RESID(xs, sp->req_resid);
6252 1.57 mjacob if (XS_NOERR(xs)) {
6253 1.57 mjacob XS_SETERR(xs, HBA_NOERROR);
6254 1.57 mjacob }
6255 1.23 mjacob return;
6256 1.94 mjacob }
6257 1.10 mjacob
6258 1.25 mjacob case RQCS_XACT_ERR1:
6259 1.57 mjacob isp_prt(isp, ISP_LOGERR, xact1, XS_CHANNEL(xs),
6260 1.51 mjacob XS_TGT(xs), XS_LUN(xs));
6261 1.25 mjacob break;
6262 1.25 mjacob
6263 1.25 mjacob case RQCS_XACT_ERR2:
6264 1.57 mjacob isp_prt(isp, ISP_LOGERR, xact2,
6265 1.51 mjacob XS_LUN(xs), XS_TGT(xs), XS_CHANNEL(xs));
6266 1.25 mjacob break;
6267 1.25 mjacob
6268 1.25 mjacob case RQCS_XACT_ERR3:
6269 1.78 mjacob isp_prt(isp, ISP_LOGERR, xact3,
6270 1.78 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6271 1.25 mjacob break;
6272 1.25 mjacob
6273 1.25 mjacob case RQCS_BAD_ENTRY:
6274 1.57 mjacob isp_prt(isp, ISP_LOGERR, "Invalid IOCB entry type detected");
6275 1.25 mjacob break;
6276 1.25 mjacob
6277 1.25 mjacob case RQCS_QUEUE_FULL:
6278 1.84 mjacob isp_prt(isp, ISP_LOGDEBUG0,
6279 1.94 mjacob "internal queues full for %d.%d.%d status 0x%x",
6280 1.94 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), *XS_STSP(xs));
6281 1.84 mjacob
6282 1.30 mjacob /*
6283 1.30 mjacob * If QFULL or some other status byte is set, then this
6284 1.30 mjacob * isn't an error, per se.
6285 1.84 mjacob *
6286 1.84 mjacob * Unfortunately, some QLogic f/w writers have, in
6287 1.84 mjacob * some cases, ommitted to *set* status to QFULL.
6288 1.84 mjacob *
6289 1.84 mjacob
6290 1.57 mjacob if (*XS_STSP(xs) != SCSI_GOOD && XS_NOERR(xs)) {
6291 1.30 mjacob XS_SETERR(xs, HBA_NOERROR);
6292 1.30 mjacob return;
6293 1.30 mjacob }
6294 1.84 mjacob
6295 1.84 mjacob *
6296 1.84 mjacob *
6297 1.84 mjacob */
6298 1.84 mjacob
6299 1.84 mjacob *XS_STSP(xs) = SCSI_QFULL;
6300 1.84 mjacob XS_SETERR(xs, HBA_NOERROR);
6301 1.84 mjacob return;
6302 1.25 mjacob
6303 1.25 mjacob case RQCS_PHASE_SKIPPED:
6304 1.79 mjacob isp_prt(isp, ISP_LOGERR, pskip, XS_CHANNEL(xs),
6305 1.79 mjacob XS_TGT(xs), XS_LUN(xs));
6306 1.25 mjacob break;
6307 1.25 mjacob
6308 1.25 mjacob case RQCS_ARQS_FAILED:
6309 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6310 1.57 mjacob "Auto Request Sense failed for %d.%d.%d",
6311 1.57 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6312 1.57 mjacob if (XS_NOERR(xs)) {
6313 1.57 mjacob XS_SETERR(xs, HBA_ARQFAIL);
6314 1.57 mjacob }
6315 1.23 mjacob return;
6316 1.10 mjacob
6317 1.25 mjacob case RQCS_WIDE_FAILED:
6318 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6319 1.57 mjacob "Wide Negotiation failed for %d.%d.%d",
6320 1.57 mjacob XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
6321 1.36 mjacob if (IS_SCSI(isp)) {
6322 1.114 mjacob sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
6323 1.79 mjacob sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_WIDE;
6324 1.25 mjacob sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
6325 1.114 mjacob sdp->update = 1;
6326 1.25 mjacob }
6327 1.57 mjacob if (XS_NOERR(xs)) {
6328 1.57 mjacob XS_SETERR(xs, HBA_NOERROR);
6329 1.57 mjacob }
6330 1.23 mjacob return;
6331 1.10 mjacob
6332 1.25 mjacob case RQCS_SYNCXFER_FAILED:
6333 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6334 1.57 mjacob "SDTR Message failed for target %d.%d.%d",
6335 1.57 mjacob XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
6336 1.36 mjacob if (IS_SCSI(isp)) {
6337 1.114 mjacob sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
6338 1.36 mjacob sdp += XS_CHANNEL(xs);
6339 1.79 mjacob sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_SYNC;
6340 1.25 mjacob sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
6341 1.114 mjacob sdp->update = 1;
6342 1.25 mjacob }
6343 1.25 mjacob break;
6344 1.25 mjacob
6345 1.25 mjacob case RQCS_LVD_BUSERR:
6346 1.57 mjacob isp_prt(isp, ISP_LOGERR,
6347 1.57 mjacob "Bad LVD condition while talking to %d.%d.%d",
6348 1.57 mjacob XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
6349 1.25 mjacob break;
6350 1.10 mjacob
6351 1.10 mjacob case RQCS_PORT_UNAVAILABLE:
6352 1.10 mjacob /*
6353 1.10 mjacob * No such port on the loop. Moral equivalent of SELTIMEO
6354 1.10 mjacob */
6355 1.10 mjacob case RQCS_PORT_LOGGED_OUT:
6356 1.111 mjacob {
6357 1.111 mjacob const char *reason;
6358 1.111 mjacob uint8_t sts = sp->req_completion_status & 0xff;
6359 1.111 mjacob
6360 1.27 mjacob /*
6361 1.27 mjacob * It was there (maybe)- treat as a selection timeout.
6362 1.27 mjacob */
6363 1.111 mjacob if (sts == RQCS_PORT_UNAVAILABLE) {
6364 1.111 mjacob reason = "unavailable";
6365 1.111 mjacob } else {
6366 1.111 mjacob reason = "logout";
6367 1.111 mjacob }
6368 1.111 mjacob
6369 1.111 mjacob isp_prt(isp, ISP_LOGINFO, "port %s for target %d",
6370 1.111 mjacob reason, XS_TGT(xs));
6371 1.111 mjacob
6372 1.88 mjacob /*
6373 1.88 mjacob * If we're on a local loop, force a LIP (which is overkill)
6374 1.94 mjacob * to force a re-login of this unit. If we're on fabric,
6375 1.111 mjacob * then we'll have to log in again as a matter of course.
6376 1.88 mjacob */
6377 1.114 mjacob if (FCPARAM(isp, 0)->isp_topo == TOPO_NL_PORT ||
6378 1.114 mjacob FCPARAM(isp, 0)->isp_topo == TOPO_FL_PORT) {
6379 1.88 mjacob mbreg_t mbs;
6380 1.117 mjacob MBSINIT(&mbs, MBOX_INIT_LIP, MBLOGALL, 0);
6381 1.114 mjacob if (ISP_CAP_2KLOGIN(isp)) {
6382 1.111 mjacob mbs.ibits = (1 << 10);
6383 1.111 mjacob }
6384 1.88 mjacob isp_mboxcmd_qnw(isp, &mbs, 1);
6385 1.88 mjacob }
6386 1.111 mjacob if (XS_NOERR(xs)) {
6387 1.111 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
6388 1.111 mjacob }
6389 1.111 mjacob return;
6390 1.111 mjacob }
6391 1.111 mjacob case RQCS_PORT_CHANGED:
6392 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
6393 1.111 mjacob "port changed for target %d", XS_TGT(xs));
6394 1.111 mjacob if (XS_NOERR(xs)) {
6395 1.111 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
6396 1.111 mjacob }
6397 1.111 mjacob return;
6398 1.111 mjacob
6399 1.111 mjacob case RQCS_PORT_BUSY:
6400 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
6401 1.111 mjacob "port busy for target %d", XS_TGT(xs));
6402 1.111 mjacob if (XS_NOERR(xs)) {
6403 1.111 mjacob XS_SETERR(xs, HBA_TGTBSY);
6404 1.111 mjacob }
6405 1.111 mjacob return;
6406 1.111 mjacob
6407 1.111 mjacob default:
6408 1.111 mjacob isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x",
6409 1.111 mjacob sp->req_completion_status);
6410 1.111 mjacob break;
6411 1.111 mjacob }
6412 1.111 mjacob if (XS_NOERR(xs)) {
6413 1.111 mjacob XS_SETERR(xs, HBA_BOTCH);
6414 1.111 mjacob }
6415 1.111 mjacob }
6416 1.111 mjacob
6417 1.111 mjacob static void
6418 1.111 mjacob isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
6419 1.111 mjacob XS_T *xs, long *rp)
6420 1.111 mjacob {
6421 1.113 mjacob int ru_marked, sv_marked;
6422 1.114 mjacob int chan = XS_CHANNEL(xs);
6423 1.114 mjacob
6424 1.111 mjacob switch (sp->req_completion_status) {
6425 1.111 mjacob case RQCS_COMPLETE:
6426 1.111 mjacob if (XS_NOERR(xs)) {
6427 1.111 mjacob XS_SETERR(xs, HBA_NOERROR);
6428 1.111 mjacob }
6429 1.111 mjacob return;
6430 1.111 mjacob
6431 1.111 mjacob case RQCS_DMA_ERROR:
6432 1.111 mjacob isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d",
6433 1.111 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6434 1.111 mjacob break;
6435 1.111 mjacob
6436 1.111 mjacob case RQCS_TRANSPORT_ERROR:
6437 1.111 mjacob isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d",
6438 1.111 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6439 1.111 mjacob break;
6440 1.111 mjacob
6441 1.111 mjacob case RQCS_RESET_OCCURRED:
6442 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
6443 1.114 mjacob "reset destroyed command for %d.%d.%d",
6444 1.111 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6445 1.114 mjacob FCPARAM(isp, chan)->sendmarker = 1;
6446 1.111 mjacob if (XS_NOERR(xs)) {
6447 1.111 mjacob XS_SETERR(xs, HBA_BUSRESET);
6448 1.111 mjacob }
6449 1.111 mjacob return;
6450 1.111 mjacob
6451 1.111 mjacob case RQCS_ABORTED:
6452 1.111 mjacob isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d",
6453 1.111 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6454 1.114 mjacob FCPARAM(isp, chan)->sendmarker = 1;
6455 1.111 mjacob if (XS_NOERR(xs)) {
6456 1.111 mjacob XS_SETERR(xs, HBA_ABORTED);
6457 1.111 mjacob }
6458 1.111 mjacob return;
6459 1.111 mjacob
6460 1.111 mjacob case RQCS_TIMEOUT:
6461 1.111 mjacob isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d",
6462 1.111 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6463 1.111 mjacob if (XS_NOERR(xs)) {
6464 1.111 mjacob XS_SETERR(xs, HBA_CMDTIMEOUT);
6465 1.111 mjacob }
6466 1.111 mjacob return;
6467 1.111 mjacob
6468 1.111 mjacob case RQCS_DATA_OVERRUN:
6469 1.117 mjacob XS_SET_RESID(xs, sp->req_resid);
6470 1.113 mjacob isp_prt(isp, ISP_LOGERR,
6471 1.113 mjacob "data overrun for command on %d.%d.%d",
6472 1.111 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
6473 1.111 mjacob if (XS_NOERR(xs)) {
6474 1.111 mjacob XS_SETERR(xs, HBA_DATAOVR);
6475 1.111 mjacob }
6476 1.111 mjacob return;
6477 1.111 mjacob
6478 1.111 mjacob case RQCS_24XX_DRE: /* data reassembly error */
6479 1.114 mjacob isp_prt(isp, ISP_LOGERR,
6480 1.114 mjacob "Chan %d data reassembly error for target %d",
6481 1.114 mjacob chan, XS_TGT(xs));
6482 1.111 mjacob if (XS_NOERR(xs)) {
6483 1.111 mjacob XS_SETERR(xs, HBA_ABORTED);
6484 1.111 mjacob }
6485 1.111 mjacob *rp = XS_XFRLEN(xs);
6486 1.111 mjacob return;
6487 1.111 mjacob
6488 1.111 mjacob case RQCS_24XX_TABORT: /* aborted by target */
6489 1.114 mjacob isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS",
6490 1.114 mjacob chan, XS_TGT(xs));
6491 1.111 mjacob if (XS_NOERR(xs)) {
6492 1.111 mjacob XS_SETERR(xs, HBA_ABORTED);
6493 1.111 mjacob }
6494 1.111 mjacob return;
6495 1.111 mjacob
6496 1.111 mjacob case RQCS_DATA_UNDERRUN:
6497 1.113 mjacob ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
6498 1.113 mjacob /*
6499 1.117 mjacob * We can get an underrun w/o things being marked
6500 1.113 mjacob * if we got a non-zero status.
6501 1.113 mjacob */
6502 1.113 mjacob sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
6503 1.113 mjacob if ((ru_marked == 0 && sv_marked == 0) ||
6504 1.113 mjacob (sp->req_resid > XS_XFRLEN(xs))) {
6505 1.113 mjacob isp_prt(isp, ISP_LOGWARN, bun, XS_TGT(xs),
6506 1.113 mjacob XS_LUN(xs), XS_XFRLEN(xs), sp->req_resid,
6507 1.113 mjacob (ru_marked)? "marked" : "not marked");
6508 1.113 mjacob if (XS_NOERR(xs)) {
6509 1.113 mjacob XS_SETERR(xs, HBA_BOTCH);
6510 1.113 mjacob }
6511 1.113 mjacob return;
6512 1.113 mjacob }
6513 1.117 mjacob XS_SET_RESID(xs, sp->req_resid);
6514 1.113 mjacob isp_prt(isp, ISP_LOGDEBUG0,
6515 1.113 mjacob "%d.%d.%d data underrun (%d) for command 0x%x",
6516 1.113 mjacob XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs),
6517 1.113 mjacob sp->req_resid, XS_CDBP(xs)[0] & 0xff);
6518 1.111 mjacob if (XS_NOERR(xs)) {
6519 1.111 mjacob XS_SETERR(xs, HBA_NOERROR);
6520 1.111 mjacob }
6521 1.111 mjacob return;
6522 1.111 mjacob
6523 1.111 mjacob case RQCS_PORT_UNAVAILABLE:
6524 1.111 mjacob /*
6525 1.111 mjacob * No such port on the loop. Moral equivalent of SELTIMEO
6526 1.111 mjacob */
6527 1.111 mjacob case RQCS_PORT_LOGGED_OUT:
6528 1.111 mjacob {
6529 1.111 mjacob const char *reason;
6530 1.111 mjacob uint8_t sts = sp->req_completion_status & 0xff;
6531 1.111 mjacob
6532 1.111 mjacob /*
6533 1.111 mjacob * It was there (maybe)- treat as a selection timeout.
6534 1.111 mjacob */
6535 1.111 mjacob if (sts == RQCS_PORT_UNAVAILABLE) {
6536 1.111 mjacob reason = "unavailable";
6537 1.111 mjacob } else {
6538 1.111 mjacob reason = "logout";
6539 1.111 mjacob }
6540 1.111 mjacob
6541 1.114 mjacob isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
6542 1.114 mjacob chan, reason, XS_TGT(xs));
6543 1.88 mjacob
6544 1.88 mjacob /*
6545 1.114 mjacob * There is no MBOX_INIT_LIP for the 24XX.
6546 1.88 mjacob */
6547 1.57 mjacob if (XS_NOERR(xs)) {
6548 1.57 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
6549 1.57 mjacob }
6550 1.27 mjacob return;
6551 1.111 mjacob }
6552 1.10 mjacob case RQCS_PORT_CHANGED:
6553 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
6554 1.114 mjacob "port changed for target %d chan %d", XS_TGT(xs), chan);
6555 1.57 mjacob if (XS_NOERR(xs)) {
6556 1.57 mjacob XS_SETERR(xs, HBA_SELTIMEOUT);
6557 1.57 mjacob }
6558 1.51 mjacob return;
6559 1.10 mjacob
6560 1.111 mjacob
6561 1.111 mjacob case RQCS_24XX_ENOMEM: /* f/w resource unavailable */
6562 1.111 mjacob isp_prt(isp, ISP_LOGWARN,
6563 1.114 mjacob "f/w resource unavailable for target %d chan %d",
6564 1.114 mjacob XS_TGT(xs), chan);
6565 1.111 mjacob if (XS_NOERR(xs)) {
6566 1.111 mjacob *XS_STSP(xs) = SCSI_BUSY;
6567 1.111 mjacob XS_SETERR(xs, HBA_TGTBSY);
6568 1.111 mjacob }
6569 1.111 mjacob return;
6570 1.111 mjacob
6571 1.111 mjacob case RQCS_24XX_TMO: /* task management overrun */
6572 1.57 mjacob isp_prt(isp, ISP_LOGWARN,
6573 1.114 mjacob "command for target %d overlapped task management for "
6574 1.114 mjacob "chan %d", XS_TGT(xs), chan);
6575 1.57 mjacob if (XS_NOERR(xs)) {
6576 1.111 mjacob *XS_STSP(xs) = SCSI_BUSY;
6577 1.57 mjacob XS_SETERR(xs, HBA_TGTBSY);
6578 1.57 mjacob }
6579 1.23 mjacob return;
6580 1.10 mjacob
6581 1.1 cgd default:
6582 1.114 mjacob isp_prt(isp, ISP_LOGERR,
6583 1.114 mjacob "Unknown Completion Status 0x%x on chan %d",
6584 1.114 mjacob sp->req_completion_status, chan);
6585 1.1 cgd break;
6586 1.1 cgd }
6587 1.57 mjacob if (XS_NOERR(xs)) {
6588 1.57 mjacob XS_SETERR(xs, HBA_BOTCH);
6589 1.57 mjacob }
6590 1.1 cgd }
6591 1.1 cgd
6592 1.33 mjacob static void
6593 1.111 mjacob isp_fastpost_complete(ispsoftc_t *isp, uint16_t fph)
6594 1.33 mjacob {
6595 1.57 mjacob XS_T *xs;
6596 1.33 mjacob
6597 1.73 mjacob if (fph == 0) {
6598 1.33 mjacob return;
6599 1.38 mjacob }
6600 1.38 mjacob xs = isp_find_xs(isp, fph);
6601 1.33 mjacob if (xs == NULL) {
6602 1.114 mjacob isp_prt(isp, ISP_LOGWARN,
6603 1.57 mjacob "Command for fast post handle 0x%x not found", fph);
6604 1.33 mjacob return;
6605 1.33 mjacob }
6606 1.38 mjacob isp_destroy_handle(isp, fph);
6607 1.38 mjacob
6608 1.33 mjacob /*
6609 1.33 mjacob * Since we don't have a result queue entry item,
6610 1.33 mjacob * we must believe that SCSI status is zero and
6611 1.33 mjacob * that all data transferred.
6612 1.33 mjacob */
6613 1.117 mjacob XS_SET_RESID(xs, 0);
6614 1.57 mjacob *XS_STSP(xs) = SCSI_GOOD;
6615 1.33 mjacob if (XS_XFRLEN(xs)) {
6616 1.38 mjacob ISP_DMAFREE(isp, xs, fph);
6617 1.33 mjacob }
6618 1.115 mjacob if (isp->isp_nactive) {
6619 1.38 mjacob isp->isp_nactive--;
6620 1.115 mjacob }
6621 1.87 mjacob isp->isp_fphccmplt++;
6622 1.60 mjacob isp_done(xs);
6623 1.33 mjacob }
6624 1.33 mjacob
6625 1.88 mjacob static int
6626 1.111 mjacob isp_mbox_continue(ispsoftc_t *isp)
6627 1.88 mjacob {
6628 1.88 mjacob mbreg_t mbs;
6629 1.111 mjacob uint16_t *ptr;
6630 1.111 mjacob uint32_t offset;
6631 1.88 mjacob
6632 1.88 mjacob switch (isp->isp_lastmbxcmd) {
6633 1.88 mjacob case MBOX_WRITE_RAM_WORD:
6634 1.88 mjacob case MBOX_READ_RAM_WORD:
6635 1.111 mjacob case MBOX_WRITE_RAM_WORD_EXTENDED:
6636 1.88 mjacob case MBOX_READ_RAM_WORD_EXTENDED:
6637 1.88 mjacob break;
6638 1.88 mjacob default:
6639 1.88 mjacob return (1);
6640 1.88 mjacob }
6641 1.88 mjacob if (isp->isp_mboxtmp[0] != MBOX_COMMAND_COMPLETE) {
6642 1.88 mjacob isp->isp_mbxwrk0 = 0;
6643 1.88 mjacob return (-1);
6644 1.88 mjacob }
6645 1.88 mjacob
6646 1.88 mjacob /*
6647 1.88 mjacob * Clear the previous interrupt.
6648 1.88 mjacob */
6649 1.111 mjacob if (IS_24XX(isp)) {
6650 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
6651 1.111 mjacob } else {
6652 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
6653 1.111 mjacob ISP_WRITE(isp, BIU_SEMA, 0);
6654 1.111 mjacob }
6655 1.88 mjacob
6656 1.88 mjacob /*
6657 1.88 mjacob * Continue with next word.
6658 1.88 mjacob */
6659 1.117 mjacob ISP_MEMZERO(&mbs, sizeof (mbs));
6660 1.88 mjacob ptr = isp->isp_mbxworkp;
6661 1.88 mjacob switch (isp->isp_lastmbxcmd) {
6662 1.88 mjacob case MBOX_WRITE_RAM_WORD:
6663 1.119 mbalmer mbs.param[1] = isp->isp_mbxwrk1++;
6664 1.119 mbalmer mbs.param[2] = *ptr++;
6665 1.111 mjacob break;
6666 1.111 mjacob case MBOX_READ_RAM_WORD:
6667 1.111 mjacob *ptr++ = isp->isp_mboxtmp[2];
6668 1.88 mjacob mbs.param[1] = isp->isp_mbxwrk1++;
6669 1.88 mjacob break;
6670 1.111 mjacob case MBOX_WRITE_RAM_WORD_EXTENDED:
6671 1.111 mjacob offset = isp->isp_mbxwrk1;
6672 1.111 mjacob offset |= isp->isp_mbxwrk8 << 16;
6673 1.111 mjacob
6674 1.119 mbalmer mbs.param[2] = *ptr++;
6675 1.111 mjacob mbs.param[1] = offset;
6676 1.111 mjacob mbs.param[8] = offset >> 16;
6677 1.111 mjacob isp->isp_mbxwrk1 = ++offset;
6678 1.111 mjacob isp->isp_mbxwrk8 = offset >> 16;
6679 1.111 mjacob break;
6680 1.88 mjacob case MBOX_READ_RAM_WORD_EXTENDED:
6681 1.111 mjacob offset = isp->isp_mbxwrk1;
6682 1.111 mjacob offset |= isp->isp_mbxwrk8 << 16;
6683 1.111 mjacob
6684 1.88 mjacob *ptr++ = isp->isp_mboxtmp[2];
6685 1.111 mjacob mbs.param[1] = offset;
6686 1.111 mjacob mbs.param[8] = offset >> 16;
6687 1.111 mjacob isp->isp_mbxwrk1 = ++offset;
6688 1.111 mjacob isp->isp_mbxwrk8 = offset >> 16;
6689 1.88 mjacob break;
6690 1.88 mjacob }
6691 1.88 mjacob isp->isp_mbxworkp = ptr;
6692 1.111 mjacob isp->isp_mbxwrk0--;
6693 1.88 mjacob mbs.param[0] = isp->isp_lastmbxcmd;
6694 1.111 mjacob mbs.logval = MBLOGALL;
6695 1.88 mjacob isp_mboxcmd_qnw(isp, &mbs, 0);
6696 1.88 mjacob return (0);
6697 1.88 mjacob }
6698 1.88 mjacob
6699 1.111 mjacob #define HIWRD(x) ((x) >> 16)
6700 1.111 mjacob #define LOWRD(x) ((x) & 0xffff)
6701 1.111 mjacob #define ISPOPMAP(a, b) (((a) << 16) | (b))
6702 1.111 mjacob static const uint32_t mbpscsi[] = {
6703 1.54 mjacob ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
6704 1.54 mjacob ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
6705 1.54 mjacob ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */
6706 1.54 mjacob ISPOPMAP(0x1f, 0x01), /* 0x03: MBOX_DUMP_RAM */
6707 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
6708 1.54 mjacob ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
6709 1.54 mjacob ISPOPMAP(0x3f, 0x3f), /* 0x06: MBOX_MAILBOX_REG_TEST */
6710 1.111 mjacob ISPOPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
6711 1.80 mjacob ISPOPMAP(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */
6712 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x09: */
6713 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x0a: */
6714 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x0b: */
6715 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x0c: */
6716 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x0d: */
6717 1.54 mjacob ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
6718 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x0f: */
6719 1.54 mjacob ISPOPMAP(0x1f, 0x1f), /* 0x10: MBOX_INIT_REQ_QUEUE */
6720 1.54 mjacob ISPOPMAP(0x3f, 0x3f), /* 0x11: MBOX_INIT_RES_QUEUE */
6721 1.54 mjacob ISPOPMAP(0x0f, 0x0f), /* 0x12: MBOX_EXECUTE_IOCB */
6722 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
6723 1.54 mjacob ISPOPMAP(0x01, 0x3f), /* 0x14: MBOX_STOP_FIRMWARE */
6724 1.54 mjacob ISPOPMAP(0x0f, 0x0f), /* 0x15: MBOX_ABORT */
6725 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x16: MBOX_ABORT_DEVICE */
6726 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x17: MBOX_ABORT_TARGET */
6727 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x18: MBOX_BUS_RESET */
6728 1.54 mjacob ISPOPMAP(0x03, 0x07), /* 0x19: MBOX_STOP_QUEUE */
6729 1.54 mjacob ISPOPMAP(0x03, 0x07), /* 0x1a: MBOX_START_QUEUE */
6730 1.54 mjacob ISPOPMAP(0x03, 0x07), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
6731 1.54 mjacob ISPOPMAP(0x03, 0x07), /* 0x1c: MBOX_ABORT_QUEUE */
6732 1.54 mjacob ISPOPMAP(0x03, 0x4f), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
6733 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x1e: */
6734 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
6735 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x20: MBOX_GET_INIT_SCSI_ID */
6736 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x21: MBOX_GET_SELECT_TIMEOUT */
6737 1.54 mjacob ISPOPMAP(0x01, 0xc7), /* 0x22: MBOX_GET_RETRY_COUNT */
6738 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x23: MBOX_GET_TAG_AGE_LIMIT */
6739 1.54 mjacob ISPOPMAP(0x01, 0x03), /* 0x24: MBOX_GET_CLOCK_RATE */
6740 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x25: MBOX_GET_ACT_NEG_STATE */
6741 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */
6742 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x27: MBOX_GET_PCI_PARAMS */
6743 1.54 mjacob ISPOPMAP(0x03, 0x4f), /* 0x28: MBOX_GET_TARGET_PARAMS */
6744 1.54 mjacob ISPOPMAP(0x03, 0x0f), /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */
6745 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */
6746 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2b: */
6747 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2c: */
6748 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2d: */
6749 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2e: */
6750 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2f: */
6751 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x30: MBOX_SET_INIT_SCSI_ID */
6752 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x31: MBOX_SET_SELECT_TIMEOUT */
6753 1.54 mjacob ISPOPMAP(0xc7, 0xc7), /* 0x32: MBOX_SET_RETRY_COUNT */
6754 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x33: MBOX_SET_TAG_AGE_LIMIT */
6755 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x34: MBOX_SET_CLOCK_RATE */
6756 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x35: MBOX_SET_ACT_NEG_STATE */
6757 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */
6758 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */
6759 1.54 mjacob ISPOPMAP(0x4f, 0x4f), /* 0x38: MBOX_SET_TARGET_PARAMS */
6760 1.54 mjacob ISPOPMAP(0x0f, 0x0f), /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */
6761 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */
6762 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3b: */
6763 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3c: */
6764 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3d: */
6765 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3e: */
6766 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3f: */
6767 1.54 mjacob ISPOPMAP(0x01, 0x03), /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */
6768 1.54 mjacob ISPOPMAP(0x3f, 0x01), /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */
6769 1.54 mjacob ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_EXEC_BIOS_IOCB */
6770 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x43: */
6771 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x44: */
6772 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x45: SET SYSTEM PARAMETER */
6773 1.54 mjacob ISPOPMAP(0x01, 0x03), /* 0x46: GET SYSTEM PARAMETER */
6774 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x47: */
6775 1.54 mjacob ISPOPMAP(0x01, 0xcf), /* 0x48: GET SCAM CONFIGURATION */
6776 1.54 mjacob ISPOPMAP(0xcf, 0xcf), /* 0x49: SET SCAM CONFIGURATION */
6777 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */
6778 1.54 mjacob ISPOPMAP(0x01, 0x03), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */
6779 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4c: */
6780 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4d: */
6781 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4e: */
6782 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4f: */
6783 1.54 mjacob ISPOPMAP(0xdf, 0xdf), /* 0x50: LOAD RAM A64 */
6784 1.54 mjacob ISPOPMAP(0xdf, 0xdf), /* 0x51: DUMP RAM A64 */
6785 1.99 mjacob ISPOPMAP(0xdf, 0xff), /* 0x52: INITIALIZE REQUEST QUEUE A64 */
6786 1.99 mjacob ISPOPMAP(0xef, 0xff), /* 0x53: INITIALIZE RESPONSE QUEUE A64 */
6787 1.111 mjacob ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUCUTE COMMAND IOCB A64 */
6788 1.74 mjacob ISPOPMAP(0x07, 0x01), /* 0x55: ENABLE TARGET MODE */
6789 1.74 mjacob ISPOPMAP(0x03, 0x0f), /* 0x56: GET TARGET STATUS */
6790 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x57: */
6791 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x58: */
6792 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x59: */
6793 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x5a: SET DATA OVERRUN RECOVERY MODE */
6794 1.54 mjacob ISPOPMAP(0x01, 0x03), /* 0x5b: GET DATA OVERRUN RECOVERY MODE */
6795 1.54 mjacob ISPOPMAP(0x0f, 0x0f), /* 0x5c: SET HOST DATA */
6796 1.54 mjacob ISPOPMAP(0x01, 0x01) /* 0x5d: GET NOST DATA */
6797 1.54 mjacob };
6798 1.54 mjacob
6799 1.107 christos static const char *scsi_mbcmd_names[] = {
6800 1.57 mjacob "NO-OP",
6801 1.57 mjacob "LOAD RAM",
6802 1.57 mjacob "EXEC FIRMWARE",
6803 1.57 mjacob "DUMP RAM",
6804 1.57 mjacob "WRITE RAM WORD",
6805 1.57 mjacob "READ RAM WORD",
6806 1.57 mjacob "MAILBOX REG TEST",
6807 1.57 mjacob "VERIFY CHECKSUM",
6808 1.57 mjacob "ABOUT FIRMWARE",
6809 1.57 mjacob NULL,
6810 1.57 mjacob NULL,
6811 1.57 mjacob NULL,
6812 1.57 mjacob NULL,
6813 1.57 mjacob NULL,
6814 1.57 mjacob "CHECK FIRMWARE",
6815 1.57 mjacob NULL,
6816 1.57 mjacob "INIT REQUEST QUEUE",
6817 1.57 mjacob "INIT RESULT QUEUE",
6818 1.57 mjacob "EXECUTE IOCB",
6819 1.57 mjacob "WAKE UP",
6820 1.57 mjacob "STOP FIRMWARE",
6821 1.57 mjacob "ABORT",
6822 1.57 mjacob "ABORT DEVICE",
6823 1.57 mjacob "ABORT TARGET",
6824 1.57 mjacob "BUS RESET",
6825 1.57 mjacob "STOP QUEUE",
6826 1.57 mjacob "START QUEUE",
6827 1.57 mjacob "SINGLE STEP QUEUE",
6828 1.57 mjacob "ABORT QUEUE",
6829 1.57 mjacob "GET DEV QUEUE STATUS",
6830 1.57 mjacob NULL,
6831 1.57 mjacob "GET FIRMWARE STATUS",
6832 1.57 mjacob "GET INIT SCSI ID",
6833 1.57 mjacob "GET SELECT TIMEOUT",
6834 1.57 mjacob "GET RETRY COUNT",
6835 1.57 mjacob "GET TAG AGE LIMIT",
6836 1.57 mjacob "GET CLOCK RATE",
6837 1.57 mjacob "GET ACT NEG STATE",
6838 1.57 mjacob "GET ASYNC DATA SETUP TIME",
6839 1.57 mjacob "GET PCI PARAMS",
6840 1.57 mjacob "GET TARGET PARAMS",
6841 1.57 mjacob "GET DEV QUEUE PARAMS",
6842 1.57 mjacob "GET RESET DELAY PARAMS",
6843 1.57 mjacob NULL,
6844 1.57 mjacob NULL,
6845 1.57 mjacob NULL,
6846 1.57 mjacob NULL,
6847 1.57 mjacob NULL,
6848 1.57 mjacob "SET INIT SCSI ID",
6849 1.57 mjacob "SET SELECT TIMEOUT",
6850 1.57 mjacob "SET RETRY COUNT",
6851 1.57 mjacob "SET TAG AGE LIMIT",
6852 1.57 mjacob "SET CLOCK RATE",
6853 1.57 mjacob "SET ACT NEG STATE",
6854 1.57 mjacob "SET ASYNC DATA SETUP TIME",
6855 1.57 mjacob "SET PCI CONTROL PARAMS",
6856 1.57 mjacob "SET TARGET PARAMS",
6857 1.57 mjacob "SET DEV QUEUE PARAMS",
6858 1.57 mjacob "SET RESET DELAY PARAMS",
6859 1.57 mjacob NULL,
6860 1.57 mjacob NULL,
6861 1.57 mjacob NULL,
6862 1.57 mjacob NULL,
6863 1.57 mjacob NULL,
6864 1.57 mjacob "RETURN BIOS BLOCK ADDR",
6865 1.57 mjacob "WRITE FOUR RAM WORDS",
6866 1.57 mjacob "EXEC BIOS IOCB",
6867 1.57 mjacob NULL,
6868 1.57 mjacob NULL,
6869 1.57 mjacob "SET SYSTEM PARAMETER",
6870 1.57 mjacob "GET SYSTEM PARAMETER",
6871 1.57 mjacob NULL,
6872 1.57 mjacob "GET SCAM CONFIGURATION",
6873 1.57 mjacob "SET SCAM CONFIGURATION",
6874 1.57 mjacob "SET FIRMWARE FEATURES",
6875 1.57 mjacob "GET FIRMWARE FEATURES",
6876 1.57 mjacob NULL,
6877 1.57 mjacob NULL,
6878 1.57 mjacob NULL,
6879 1.57 mjacob NULL,
6880 1.57 mjacob "LOAD RAM A64",
6881 1.57 mjacob "DUMP RAM A64",
6882 1.57 mjacob "INITIALIZE REQUEST QUEUE A64",
6883 1.57 mjacob "INITIALIZE RESPONSE QUEUE A64",
6884 1.57 mjacob "EXECUTE IOCB A64",
6885 1.57 mjacob "ENABLE TARGET MODE",
6886 1.74 mjacob "GET TARGET MODE STATE",
6887 1.57 mjacob NULL,
6888 1.57 mjacob NULL,
6889 1.57 mjacob NULL,
6890 1.57 mjacob "SET DATA OVERRUN RECOVERY MODE",
6891 1.57 mjacob "GET DATA OVERRUN RECOVERY MODE",
6892 1.57 mjacob "SET HOST DATA",
6893 1.57 mjacob "GET NOST DATA",
6894 1.57 mjacob };
6895 1.57 mjacob
6896 1.111 mjacob static const uint32_t mbpfc[] = {
6897 1.54 mjacob ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
6898 1.54 mjacob ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
6899 1.111 mjacob ISPOPMAP(0x0f, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */
6900 1.71 mjacob ISPOPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */
6901 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
6902 1.54 mjacob ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
6903 1.54 mjacob ISPOPMAP(0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */
6904 1.117 mjacob ISPOPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
6905 1.80 mjacob ISPOPMAP(0x01, 0x4f), /* 0x08: MBOX_ABOUT_FIRMWARE */
6906 1.111 mjacob ISPOPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */
6907 1.54 mjacob ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
6908 1.111 mjacob ISPOPMAP(0x1ff, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */
6909 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x0c: */
6910 1.111 mjacob ISPOPMAP(0x10f, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
6911 1.54 mjacob ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
6912 1.111 mjacob ISPOPMAP(0x10f, 0x05), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
6913 1.54 mjacob ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
6914 1.54 mjacob ISPOPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
6915 1.54 mjacob ISPOPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
6916 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
6917 1.54 mjacob ISPOPMAP(0x01, 0xff), /* 0x14: MBOX_STOP_FIRMWARE */
6918 1.54 mjacob ISPOPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */
6919 1.54 mjacob ISPOPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */
6920 1.54 mjacob ISPOPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */
6921 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */
6922 1.54 mjacob ISPOPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */
6923 1.54 mjacob ISPOPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */
6924 1.54 mjacob ISPOPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
6925 1.54 mjacob ISPOPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */
6926 1.54 mjacob ISPOPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
6927 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x1e: */
6928 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
6929 1.54 mjacob ISPOPMAP(0x01, 0x4f), /* 0x20: MBOX_GET_LOOP_ID */
6930 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x21: */
6931 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x22: MBOX_GET_RETRY_COUNT */
6932 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x23: */
6933 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x24: */
6934 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x25: */
6935 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x26: */
6936 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x27: */
6937 1.81 mjacob ISPOPMAP(0x01, 0x03), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
6938 1.54 mjacob ISPOPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
6939 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2a: */
6940 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2b: */
6941 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2c: */
6942 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2d: */
6943 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2e: */
6944 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x2f: */
6945 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x30: */
6946 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x31: */
6947 1.54 mjacob ISPOPMAP(0x07, 0x07), /* 0x32: MBOX_SET_RETRY_COUNT */
6948 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x33: */
6949 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x34: */
6950 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x35: */
6951 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x36: */
6952 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x37: */
6953 1.54 mjacob ISPOPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
6954 1.54 mjacob ISPOPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
6955 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3a: */
6956 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3b: */
6957 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3c: */
6958 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3d: */
6959 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3e: */
6960 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x3f: */
6961 1.54 mjacob ISPOPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */
6962 1.54 mjacob ISPOPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */
6963 1.111 mjacob ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_GET_RESOURCE_COUNT */
6964 1.111 mjacob ISPOPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */
6965 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x44: */
6966 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x45: */
6967 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x46: */
6968 1.54 mjacob ISPOPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */
6969 1.114 mjacob ISPOPMAP(0xcd, 0x01), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
6970 1.114 mjacob ISPOPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */
6971 1.114 mjacob ISPOPMAP(0x2cd, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
6972 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4b: */
6973 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4c: */
6974 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4d: */
6975 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4e: */
6976 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x4f: */
6977 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x50: */
6978 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x51: */
6979 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x52: */
6980 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x53: */
6981 1.54 mjacob ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
6982 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x55: */
6983 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x56: */
6984 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x57: */
6985 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x58: */
6986 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x59: */
6987 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x5a: */
6988 1.94 mjacob ISPOPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
6989 1.94 mjacob ISPOPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
6990 1.81 mjacob ISPOPMAP(0x07, 0x03), /* 0x5d: MBOX_GET_SET_DATA_RATE */
6991 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x5e: */
6992 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x5f: */
6993 1.111 mjacob ISPOPMAP(0xcd, 0x01), /* 0x60: MBOX_INIT_FIRMWARE */
6994 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x61: */
6995 1.54 mjacob ISPOPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */
6996 1.54 mjacob ISPOPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
6997 1.54 mjacob ISPOPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
6998 1.54 mjacob ISPOPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */
6999 1.54 mjacob ISPOPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */
7000 1.54 mjacob ISPOPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */
7001 1.54 mjacob ISPOPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */
7002 1.54 mjacob ISPOPMAP(0x01, 0x07), /* 0x69: MBOX_GET_FW_STATE */
7003 1.54 mjacob ISPOPMAP(0x03, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */
7004 1.54 mjacob ISPOPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */
7005 1.54 mjacob ISPOPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */
7006 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x6d: */
7007 1.54 mjacob ISPOPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */
7008 1.54 mjacob ISPOPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */
7009 1.54 mjacob ISPOPMAP(0x03, 0x01), /* 0x70: MBOX_SEND_CHANGE_REQUEST */
7010 1.54 mjacob ISPOPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */
7011 1.54 mjacob ISPOPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */
7012 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x73: */
7013 1.54 mjacob ISPOPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */
7014 1.54 mjacob ISPOPMAP(0xcf, 0x03), /* 0x75: GET PORT/NODE NAME LIST */
7015 1.54 mjacob ISPOPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */
7016 1.54 mjacob ISPOPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */
7017 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x78: */
7018 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x79: */
7019 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x7a: */
7020 1.54 mjacob ISPOPMAP(0x00, 0x00), /* 0x7b: */
7021 1.54 mjacob ISPOPMAP(0x4f, 0x03), /* 0x7c: Get ID List */
7022 1.54 mjacob ISPOPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */
7023 1.111 mjacob ISPOPMAP(0x0f, 0x01) /* 0x7e: LUN RESET */
7024 1.1 cgd };
7025 1.88 mjacob /*
7026 1.88 mjacob * Footnotes
7027 1.88 mjacob *
7028 1.117 mjacob * (1): this sets bits 21..16 in mailbox register #8, which we nominally
7029 1.88 mjacob * do not access at this time in the core driver. The caller is
7030 1.111 mjacob * responsible for setting this register first (Gross!). The assumption
7031 1.111 mjacob * is that we won't overflow.
7032 1.88 mjacob */
7033 1.1 cgd
7034 1.107 christos static const char *fc_mbcmd_names[] = {
7035 1.57 mjacob "NO-OP",
7036 1.57 mjacob "LOAD RAM",
7037 1.57 mjacob "EXEC FIRMWARE",
7038 1.57 mjacob "DUMP RAM",
7039 1.57 mjacob "WRITE RAM WORD",
7040 1.57 mjacob "READ RAM WORD",
7041 1.57 mjacob "MAILBOX REG TEST",
7042 1.57 mjacob "VERIFY CHECKSUM",
7043 1.57 mjacob "ABOUT FIRMWARE",
7044 1.57 mjacob "LOAD RAM",
7045 1.57 mjacob "DUMP RAM",
7046 1.111 mjacob "WRITE RAM WORD EXTENDED",
7047 1.57 mjacob NULL,
7048 1.88 mjacob "READ RAM WORD EXTENDED",
7049 1.57 mjacob "CHECK FIRMWARE",
7050 1.57 mjacob NULL,
7051 1.57 mjacob "INIT REQUEST QUEUE",
7052 1.57 mjacob "INIT RESULT QUEUE",
7053 1.57 mjacob "EXECUTE IOCB",
7054 1.57 mjacob "WAKE UP",
7055 1.57 mjacob "STOP FIRMWARE",
7056 1.57 mjacob "ABORT",
7057 1.57 mjacob "ABORT DEVICE",
7058 1.57 mjacob "ABORT TARGET",
7059 1.57 mjacob "BUS RESET",
7060 1.57 mjacob "STOP QUEUE",
7061 1.57 mjacob "START QUEUE",
7062 1.57 mjacob "SINGLE STEP QUEUE",
7063 1.57 mjacob "ABORT QUEUE",
7064 1.57 mjacob "GET DEV QUEUE STATUS",
7065 1.57 mjacob NULL,
7066 1.57 mjacob "GET FIRMWARE STATUS",
7067 1.57 mjacob "GET LOOP ID",
7068 1.57 mjacob NULL,
7069 1.57 mjacob "GET RETRY COUNT",
7070 1.57 mjacob NULL,
7071 1.57 mjacob NULL,
7072 1.57 mjacob NULL,
7073 1.57 mjacob NULL,
7074 1.57 mjacob NULL,
7075 1.57 mjacob "GET FIRMWARE OPTIONS",
7076 1.57 mjacob "GET PORT QUEUE PARAMS",
7077 1.57 mjacob NULL,
7078 1.57 mjacob NULL,
7079 1.57 mjacob NULL,
7080 1.57 mjacob NULL,
7081 1.57 mjacob NULL,
7082 1.57 mjacob NULL,
7083 1.57 mjacob NULL,
7084 1.57 mjacob NULL,
7085 1.57 mjacob "SET RETRY COUNT",
7086 1.57 mjacob NULL,
7087 1.57 mjacob NULL,
7088 1.57 mjacob NULL,
7089 1.57 mjacob NULL,
7090 1.57 mjacob NULL,
7091 1.57 mjacob "SET FIRMWARE OPTIONS",
7092 1.57 mjacob "SET PORT QUEUE PARAMS",
7093 1.57 mjacob NULL,
7094 1.57 mjacob NULL,
7095 1.57 mjacob NULL,
7096 1.57 mjacob NULL,
7097 1.57 mjacob NULL,
7098 1.57 mjacob NULL,
7099 1.57 mjacob "LOOP PORT BYPASS",
7100 1.57 mjacob "LOOP PORT ENABLE",
7101 1.111 mjacob "GET RESOURCE COUNT",
7102 1.57 mjacob "REQUEST NON PARTICIPATING MODE",
7103 1.57 mjacob NULL,
7104 1.57 mjacob NULL,
7105 1.57 mjacob NULL,
7106 1.111 mjacob "GET PORT DATABASE ENHANCED",
7107 1.114 mjacob "INIT FIRMWARE MULTI ID",
7108 1.114 mjacob "GET VP DATABASE",
7109 1.114 mjacob "GET VP DATABASE ENTRY",
7110 1.57 mjacob NULL,
7111 1.57 mjacob NULL,
7112 1.57 mjacob NULL,
7113 1.57 mjacob NULL,
7114 1.57 mjacob NULL,
7115 1.57 mjacob NULL,
7116 1.57 mjacob NULL,
7117 1.57 mjacob NULL,
7118 1.57 mjacob NULL,
7119 1.57 mjacob "EXECUTE IOCB A64",
7120 1.57 mjacob NULL,
7121 1.57 mjacob NULL,
7122 1.57 mjacob NULL,
7123 1.57 mjacob NULL,
7124 1.57 mjacob NULL,
7125 1.57 mjacob NULL,
7126 1.101 mjacob "DRIVER HEARTBEAT",
7127 1.57 mjacob NULL,
7128 1.81 mjacob "GET/SET DATA RATE",
7129 1.57 mjacob NULL,
7130 1.57 mjacob NULL,
7131 1.57 mjacob "INIT FIRMWARE",
7132 1.57 mjacob NULL,
7133 1.57 mjacob "INIT LIP",
7134 1.57 mjacob "GET FC-AL POSITION MAP",
7135 1.57 mjacob "GET PORT DATABASE",
7136 1.57 mjacob "CLEAR ACA",
7137 1.57 mjacob "TARGET RESET",
7138 1.57 mjacob "CLEAR TASK SET",
7139 1.57 mjacob "ABORT TASK SET",
7140 1.57 mjacob "GET FW STATE",
7141 1.57 mjacob "GET PORT NAME",
7142 1.57 mjacob "GET LINK STATUS",
7143 1.57 mjacob "INIT LIP RESET",
7144 1.57 mjacob NULL,
7145 1.57 mjacob "SEND SNS",
7146 1.57 mjacob "FABRIC LOGIN",
7147 1.57 mjacob "SEND CHANGE REQUEST",
7148 1.57 mjacob "FABRIC LOGOUT",
7149 1.57 mjacob "INIT LIP LOGIN",
7150 1.57 mjacob NULL,
7151 1.57 mjacob "LOGIN LOOP PORT",
7152 1.57 mjacob "GET PORT/NODE NAME LIST",
7153 1.57 mjacob "SET VENDOR ID",
7154 1.57 mjacob "INITIALIZE IP MAILBOX",
7155 1.57 mjacob NULL,
7156 1.57 mjacob NULL,
7157 1.57 mjacob NULL,
7158 1.57 mjacob NULL,
7159 1.57 mjacob "Get ID List",
7160 1.57 mjacob "SEND LFA",
7161 1.57 mjacob "Lun RESET"
7162 1.57 mjacob };
7163 1.57 mjacob
7164 1.10 mjacob static void
7165 1.111 mjacob isp_mboxcmd_qnw(ispsoftc_t *isp, mbreg_t *mbp, int nodelay)
7166 1.88 mjacob {
7167 1.103 mjacob unsigned int ibits, obits, box, opcode;
7168 1.111 mjacob const uint32_t *mcp;
7169 1.88 mjacob
7170 1.88 mjacob if (IS_FC(isp)) {
7171 1.88 mjacob mcp = mbpfc;
7172 1.88 mjacob } else {
7173 1.88 mjacob mcp = mbpscsi;
7174 1.88 mjacob }
7175 1.88 mjacob opcode = mbp->param[0];
7176 1.111 mjacob ibits = HIWRD(mcp[opcode]) & NMBOX_BMASK(isp);
7177 1.111 mjacob obits = LOWRD(mcp[opcode]) & NMBOX_BMASK(isp);
7178 1.111 mjacob ibits |= mbp->ibits;
7179 1.111 mjacob obits |= mbp->obits;
7180 1.111 mjacob for (box = 0; box < MAX_MAILBOX(isp); box++) {
7181 1.88 mjacob if (ibits & (1 << box)) {
7182 1.88 mjacob ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
7183 1.88 mjacob }
7184 1.88 mjacob if (nodelay == 0) {
7185 1.88 mjacob isp->isp_mboxtmp[box] = mbp->param[box] = 0;
7186 1.88 mjacob }
7187 1.88 mjacob }
7188 1.88 mjacob if (nodelay == 0) {
7189 1.88 mjacob isp->isp_lastmbxcmd = opcode;
7190 1.88 mjacob isp->isp_obits = obits;
7191 1.88 mjacob isp->isp_mboxbsy = 1;
7192 1.88 mjacob }
7193 1.111 mjacob if (IS_24XX(isp)) {
7194 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
7195 1.111 mjacob } else {
7196 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
7197 1.111 mjacob }
7198 1.88 mjacob /*
7199 1.88 mjacob * Oddly enough, if we're not delaying for an answer,
7200 1.88 mjacob * delay a bit to give the f/w a chance to pick up the
7201 1.88 mjacob * command.
7202 1.88 mjacob */
7203 1.88 mjacob if (nodelay) {
7204 1.117 mjacob ISP_DELAY(1000);
7205 1.88 mjacob }
7206 1.88 mjacob }
7207 1.88 mjacob
7208 1.88 mjacob static void
7209 1.111 mjacob isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
7210 1.1 cgd {
7211 1.111 mjacob const char *cname, *xname;
7212 1.107 christos char tname[16], mname[16];
7213 1.54 mjacob unsigned int lim, ibits, obits, box, opcode;
7214 1.111 mjacob const uint32_t *mcp;
7215 1.54 mjacob
7216 1.54 mjacob if (IS_FC(isp)) {
7217 1.54 mjacob mcp = mbpfc;
7218 1.54 mjacob lim = (sizeof (mbpfc) / sizeof (mbpfc[0]));
7219 1.54 mjacob } else {
7220 1.54 mjacob mcp = mbpscsi;
7221 1.54 mjacob lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0]));
7222 1.1 cgd }
7223 1.1 cgd
7224 1.54 mjacob if ((opcode = mbp->param[0]) >= lim) {
7225 1.54 mjacob mbp->param[0] = MBOX_INVALID_COMMAND;
7226 1.57 mjacob isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
7227 1.10 mjacob return;
7228 1.1 cgd }
7229 1.1 cgd
7230 1.111 mjacob ibits = HIWRD(mcp[opcode]) & NMBOX_BMASK(isp);
7231 1.111 mjacob obits = LOWRD(mcp[opcode]) & NMBOX_BMASK(isp);
7232 1.111 mjacob
7233 1.111 mjacob /*
7234 1.111 mjacob * Pick up any additional bits that the caller might have set.
7235 1.111 mjacob */
7236 1.111 mjacob ibits |= mbp->ibits;
7237 1.111 mjacob obits |= mbp->obits;
7238 1.10 mjacob
7239 1.54 mjacob if (ibits == 0 && obits == 0) {
7240 1.54 mjacob mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
7241 1.57 mjacob isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
7242 1.54 mjacob return;
7243 1.28 mjacob }
7244 1.24 mjacob
7245 1.57 mjacob /*
7246 1.57 mjacob * Get exclusive usage of mailbox registers.
7247 1.57 mjacob */
7248 1.111 mjacob if (MBOX_ACQUIRE(isp)) {
7249 1.111 mjacob mbp->param[0] = MBOX_REGS_BUSY;
7250 1.111 mjacob goto out;
7251 1.111 mjacob }
7252 1.57 mjacob
7253 1.111 mjacob for (box = 0; box < MAX_MAILBOX(isp); box++) {
7254 1.54 mjacob if (ibits & (1 << box)) {
7255 1.115 mjacob isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
7256 1.111 mjacob mbp->param[box]);
7257 1.54 mjacob ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
7258 1.1 cgd }
7259 1.54 mjacob isp->isp_mboxtmp[box] = mbp->param[box] = 0;
7260 1.1 cgd }
7261 1.1 cgd
7262 1.70 mjacob isp->isp_lastmbxcmd = opcode;
7263 1.70 mjacob
7264 1.1 cgd /*
7265 1.54 mjacob * We assume that we can't overwrite a previous command.
7266 1.34 mjacob */
7267 1.86 mjacob isp->isp_obits = obits;
7268 1.86 mjacob isp->isp_mboxbsy = 1;
7269 1.1 cgd
7270 1.1 cgd /*
7271 1.1 cgd * Set Host Interrupt condition so that RISC will pick up mailbox regs.
7272 1.1 cgd */
7273 1.111 mjacob if (IS_24XX(isp)) {
7274 1.111 mjacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
7275 1.111 mjacob } else {
7276 1.111 mjacob ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
7277 1.111 mjacob }
7278 1.1 cgd
7279 1.33 mjacob /*
7280 1.54 mjacob * While we haven't finished the command, spin our wheels here.
7281 1.33 mjacob */
7282 1.111 mjacob MBOX_WAIT_COMPLETE(isp, mbp);
7283 1.86 mjacob
7284 1.111 mjacob /*
7285 1.111 mjacob * Did the command time out?
7286 1.111 mjacob */
7287 1.111 mjacob if (mbp->param[0] == MBOX_TIMEOUT) {
7288 1.115 mjacob isp->isp_mboxbsy = 0;
7289 1.86 mjacob MBOX_RELEASE(isp);
7290 1.111 mjacob goto out;
7291 1.86 mjacob }
7292 1.1 cgd
7293 1.1 cgd /*
7294 1.54 mjacob * Copy back output registers.
7295 1.1 cgd */
7296 1.111 mjacob for (box = 0; box < MAX_MAILBOX(isp); box++) {
7297 1.54 mjacob if (obits & (1 << box)) {
7298 1.54 mjacob mbp->param[box] = isp->isp_mboxtmp[box];
7299 1.115 mjacob isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
7300 1.111 mjacob mbp->param[box]);
7301 1.36 mjacob }
7302 1.36 mjacob }
7303 1.36 mjacob
7304 1.115 mjacob isp->isp_mboxbsy = 0;
7305 1.57 mjacob MBOX_RELEASE(isp);
7306 1.111 mjacob out:
7307 1.111 mjacob if (mbp->logval == 0 || opcode == MBOX_EXEC_FIRMWARE) {
7308 1.57 mjacob return;
7309 1.57 mjacob }
7310 1.57 mjacob cname = (IS_FC(isp))? fc_mbcmd_names[opcode] : scsi_mbcmd_names[opcode];
7311 1.57 mjacob if (cname == NULL) {
7312 1.74 mjacob cname = tname;
7313 1.117 mjacob ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
7314 1.57 mjacob }
7315 1.57 mjacob
7316 1.10 mjacob /*
7317 1.10 mjacob * Just to be chatty here...
7318 1.10 mjacob */
7319 1.57 mjacob xname = NULL;
7320 1.34 mjacob switch (mbp->param[0]) {
7321 1.10 mjacob case MBOX_COMMAND_COMPLETE:
7322 1.10 mjacob break;
7323 1.10 mjacob case MBOX_INVALID_COMMAND:
7324 1.111 mjacob if (mbp->logval & MBLOGMASK(MBOX_COMMAND_COMPLETE)) {
7325 1.57 mjacob xname = "INVALID COMMAND";
7326 1.111 mjacob }
7327 1.10 mjacob break;
7328 1.10 mjacob case MBOX_HOST_INTERFACE_ERROR:
7329 1.111 mjacob if (mbp->logval & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR)) {
7330 1.57 mjacob xname = "HOST INTERFACE ERROR";
7331 1.111 mjacob }
7332 1.10 mjacob break;
7333 1.10 mjacob case MBOX_TEST_FAILED:
7334 1.111 mjacob if (mbp->logval & MBLOGMASK(MBOX_TEST_FAILED)) {
7335 1.57 mjacob xname = "TEST FAILED";
7336 1.111 mjacob }
7337 1.10 mjacob break;
7338 1.10 mjacob case MBOX_COMMAND_ERROR:
7339 1.111 mjacob if (mbp->logval & MBLOGMASK(MBOX_COMMAND_ERROR)) {
7340 1.57 mjacob xname = "COMMAND ERROR";
7341 1.111 mjacob }
7342 1.10 mjacob break;
7343 1.10 mjacob case MBOX_COMMAND_PARAM_ERROR:
7344 1.111 mjacob if (mbp->logval & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR)) {
7345 1.57 mjacob xname = "COMMAND PARAMETER ERROR";
7346 1.111 mjacob }
7347 1.10 mjacob break;
7348 1.50 mjacob case MBOX_LOOP_ID_USED:
7349 1.111 mjacob if (mbp->logval & MBLOGMASK(MBOX_LOOP_ID_USED)) {
7350 1.57 mjacob xname = "LOOP ID ALREADY IN USE";
7351 1.111 mjacob }
7352 1.57 mjacob break;
7353 1.50 mjacob case MBOX_PORT_ID_USED:
7354 1.111 mjacob if (mbp->logval & MBLOGMASK(MBOX_PORT_ID_USED)) {
7355 1.57 mjacob xname = "PORT ID ALREADY IN USE";
7356 1.111 mjacob }
7357 1.57 mjacob break;
7358 1.50 mjacob case MBOX_ALL_IDS_USED:
7359 1.111 mjacob if (mbp->logval & MBLOGMASK(MBOX_ALL_IDS_USED)) {
7360 1.57 mjacob xname = "ALL LOOP IDS IN USE";
7361 1.111 mjacob }
7362 1.57 mjacob break;
7363 1.111 mjacob case MBOX_REGS_BUSY:
7364 1.111 mjacob xname = "REGISTERS BUSY";
7365 1.111 mjacob break;
7366 1.111 mjacob case MBOX_TIMEOUT:
7367 1.57 mjacob xname = "TIMEOUT";
7368 1.50 mjacob break;
7369 1.10 mjacob default:
7370 1.117 mjacob ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
7371 1.57 mjacob xname = mname;
7372 1.10 mjacob break;
7373 1.10 mjacob }
7374 1.111 mjacob if (xname) {
7375 1.57 mjacob isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s)",
7376 1.57 mjacob cname, xname);
7377 1.111 mjacob }
7378 1.10 mjacob }
7379 1.10 mjacob
7380 1.10 mjacob static void
7381 1.114 mjacob isp_fw_state(ispsoftc_t *isp, int chan)
7382 1.10 mjacob {
7383 1.38 mjacob if (IS_FC(isp)) {
7384 1.57 mjacob mbreg_t mbs;
7385 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
7386 1.57 mjacob
7387 1.117 mjacob MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
7388 1.111 mjacob isp_mboxcmd(isp, &mbs);
7389 1.70 mjacob if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
7390 1.57 mjacob fcp->isp_fwstate = mbs.param[1];
7391 1.70 mjacob }
7392 1.10 mjacob }
7393 1.10 mjacob }
7394 1.10 mjacob
7395 1.10 mjacob static void
7396 1.114 mjacob isp_spi_update(ispsoftc_t *isp, int chan)
7397 1.36 mjacob {
7398 1.25 mjacob int tgt;
7399 1.10 mjacob mbreg_t mbs;
7400 1.10 mjacob sdparam *sdp;
7401 1.10 mjacob
7402 1.38 mjacob if (IS_FC(isp)) {
7403 1.58 mjacob /*
7404 1.58 mjacob * There are no 'per-bus' settings for Fibre Channel.
7405 1.58 mjacob */
7406 1.4 mjacob return;
7407 1.4 mjacob }
7408 1.114 mjacob sdp = SDPARAM(isp, chan);
7409 1.114 mjacob sdp->update = 0;
7410 1.36 mjacob
7411 1.25 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
7412 1.111 mjacob uint16_t flags, period, offset;
7413 1.31 mjacob int get;
7414 1.31 mjacob
7415 1.25 mjacob if (sdp->isp_devparam[tgt].dev_enable == 0) {
7416 1.60 mjacob sdp->isp_devparam[tgt].dev_update = 0;
7417 1.60 mjacob sdp->isp_devparam[tgt].dev_refresh = 0;
7418 1.74 mjacob isp_prt(isp, ISP_LOGDEBUG0,
7419 1.114 mjacob "skipping target %d bus %d update", tgt, chan);
7420 1.25 mjacob continue;
7421 1.25 mjacob }
7422 1.34 mjacob /*
7423 1.34 mjacob * If the goal is to update the status of the device,
7424 1.79 mjacob * take what's in goal_flags and try and set the device
7425 1.34 mjacob * toward that. Otherwise, if we're just refreshing the
7426 1.34 mjacob * current device state, get the current parameters.
7427 1.34 mjacob */
7428 1.58 mjacob
7429 1.117 mjacob MBSINIT(&mbs, 0, MBLOGALL, 0);
7430 1.111 mjacob
7431 1.58 mjacob /*
7432 1.58 mjacob * Refresh overrides set
7433 1.58 mjacob */
7434 1.58 mjacob if (sdp->isp_devparam[tgt].dev_refresh) {
7435 1.58 mjacob mbs.param[0] = MBOX_GET_TARGET_PARAMS;
7436 1.58 mjacob get = 1;
7437 1.58 mjacob } else if (sdp->isp_devparam[tgt].dev_update) {
7438 1.31 mjacob mbs.param[0] = MBOX_SET_TARGET_PARAMS;
7439 1.111 mjacob
7440 1.58 mjacob /*
7441 1.79 mjacob * Make sure goal_flags has "Renegotiate on Error"
7442 1.58 mjacob * on and "Freeze Queue on Error" off.
7443 1.58 mjacob */
7444 1.79 mjacob sdp->isp_devparam[tgt].goal_flags |= DPARM_RENEG;
7445 1.79 mjacob sdp->isp_devparam[tgt].goal_flags &= ~DPARM_QFRZ;
7446 1.79 mjacob mbs.param[2] = sdp->isp_devparam[tgt].goal_flags;
7447 1.78 mjacob
7448 1.36 mjacob /*
7449 1.58 mjacob * Insist that PARITY must be enabled
7450 1.58 mjacob * if SYNC or WIDE is enabled.
7451 1.36 mjacob */
7452 1.58 mjacob if ((mbs.param[2] & (DPARM_SYNC|DPARM_WIDE)) != 0) {
7453 1.36 mjacob mbs.param[2] |= DPARM_PARITY;
7454 1.36 mjacob }
7455 1.58 mjacob
7456 1.111 mjacob if (mbs.param[2] & DPARM_SYNC) {
7457 1.58 mjacob mbs.param[3] =
7458 1.79 mjacob (sdp->isp_devparam[tgt].goal_offset << 8) |
7459 1.79 mjacob (sdp->isp_devparam[tgt].goal_period);
7460 1.58 mjacob }
7461 1.34 mjacob /*
7462 1.34 mjacob * A command completion later that has
7463 1.79 mjacob * RQSTF_NEGOTIATION set can cause
7464 1.60 mjacob * the dev_refresh/announce cycle also.
7465 1.34 mjacob *
7466 1.34 mjacob * Note: It is really important to update our current
7467 1.34 mjacob * flags with at least the state of TAG capabilities-
7468 1.34 mjacob * otherwise we might try and send a tagged command
7469 1.34 mjacob * when we have it all turned off. So change it here
7470 1.34 mjacob * to say that current already matches goal.
7471 1.34 mjacob */
7472 1.79 mjacob sdp->isp_devparam[tgt].actv_flags &= ~DPARM_TQING;
7473 1.79 mjacob sdp->isp_devparam[tgt].actv_flags |=
7474 1.79 mjacob (sdp->isp_devparam[tgt].goal_flags & DPARM_TQING);
7475 1.74 mjacob isp_prt(isp, ISP_LOGDEBUG0,
7476 1.57 mjacob "bus %d set tgt %d flags 0x%x off 0x%x period 0x%x",
7477 1.114 mjacob chan, tgt, mbs.param[2], mbs.param[3] >> 8,
7478 1.57 mjacob mbs.param[3] & 0xff);
7479 1.31 mjacob get = 0;
7480 1.31 mjacob } else {
7481 1.25 mjacob continue;
7482 1.25 mjacob }
7483 1.114 mjacob mbs.param[1] = (chan << 15) | (tgt << 8);
7484 1.111 mjacob isp_mboxcmd(isp, &mbs);
7485 1.111 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
7486 1.111 mjacob continue;
7487 1.111 mjacob }
7488 1.31 mjacob if (get == 0) {
7489 1.114 mjacob sdp->sendmarker = 1;
7490 1.111 mjacob sdp->isp_devparam[tgt].dev_update = 0;
7491 1.111 mjacob sdp->isp_devparam[tgt].dev_refresh = 1;
7492 1.111 mjacob } else {
7493 1.111 mjacob sdp->isp_devparam[tgt].dev_refresh = 0;
7494 1.111 mjacob flags = mbs.param[2];
7495 1.111 mjacob period = mbs.param[3] & 0xff;
7496 1.111 mjacob offset = mbs.param[3] >> 8;
7497 1.111 mjacob sdp->isp_devparam[tgt].actv_flags = flags;
7498 1.111 mjacob sdp->isp_devparam[tgt].actv_period = period;
7499 1.111 mjacob sdp->isp_devparam[tgt].actv_offset = offset;
7500 1.114 mjacob isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, chan, tgt);
7501 1.31 mjacob }
7502 1.10 mjacob }
7503 1.60 mjacob
7504 1.60 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
7505 1.60 mjacob if (sdp->isp_devparam[tgt].dev_update ||
7506 1.60 mjacob sdp->isp_devparam[tgt].dev_refresh) {
7507 1.114 mjacob sdp->update = 1;
7508 1.60 mjacob break;
7509 1.60 mjacob }
7510 1.60 mjacob }
7511 1.25 mjacob }
7512 1.10 mjacob
7513 1.25 mjacob static void
7514 1.114 mjacob isp_setdfltsdparm(ispsoftc_t *isp)
7515 1.25 mjacob {
7516 1.34 mjacob int tgt;
7517 1.114 mjacob sdparam *sdp, *sdp1;
7518 1.36 mjacob
7519 1.114 mjacob sdp = SDPARAM(isp, 0);
7520 1.114 mjacob sdp->role = GET_DEFAULT_ROLE(isp, 0);
7521 1.114 mjacob if (IS_DUALBUS(isp)) {
7522 1.114 mjacob sdp1 = sdp + 1;
7523 1.114 mjacob sdp1->role = GET_DEFAULT_ROLE(isp, 1);
7524 1.114 mjacob } else {
7525 1.114 mjacob sdp1 = NULL;
7526 1.114 mjacob }
7527 1.10 mjacob
7528 1.10 mjacob /*
7529 1.74 mjacob * Establish some default parameters.
7530 1.74 mjacob */
7531 1.79 mjacob sdp->isp_cmd_dma_burst_enable = 0;
7532 1.74 mjacob sdp->isp_data_dma_burst_enabl = 1;
7533 1.74 mjacob sdp->isp_fifo_threshold = 0;
7534 1.114 mjacob sdp->isp_initiator_id = DEFAULT_IID(isp, 0);
7535 1.74 mjacob if (isp->isp_type >= ISP_HA_SCSI_1040) {
7536 1.74 mjacob sdp->isp_async_data_setup = 9;
7537 1.74 mjacob } else {
7538 1.74 mjacob sdp->isp_async_data_setup = 6;
7539 1.74 mjacob }
7540 1.74 mjacob sdp->isp_selection_timeout = 250;
7541 1.74 mjacob sdp->isp_max_queue_depth = MAXISPREQUEST(isp);
7542 1.74 mjacob sdp->isp_tag_aging = 8;
7543 1.79 mjacob sdp->isp_bus_reset_delay = 5;
7544 1.79 mjacob /*
7545 1.79 mjacob * Don't retry selection, busy or queue full automatically- reflect
7546 1.79 mjacob * these back to us.
7547 1.79 mjacob */
7548 1.79 mjacob sdp->isp_retry_count = 0;
7549 1.79 mjacob sdp->isp_retry_delay = 0;
7550 1.74 mjacob
7551 1.74 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
7552 1.74 mjacob sdp->isp_devparam[tgt].exc_throttle = ISP_EXEC_THROTTLE;
7553 1.74 mjacob sdp->isp_devparam[tgt].dev_enable = 1;
7554 1.74 mjacob }
7555 1.74 mjacob
7556 1.74 mjacob /*
7557 1.34 mjacob * The trick here is to establish a default for the default (honk!)
7558 1.79 mjacob * state (goal_flags). Then try and get the current status from
7559 1.34 mjacob * the card to fill in the current state. We don't, in fact, set
7560 1.34 mjacob * the default to the SAFE default state- that's not the goal state.
7561 1.34 mjacob */
7562 1.34 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
7563 1.111 mjacob uint8_t off, per;
7564 1.79 mjacob sdp->isp_devparam[tgt].actv_offset = 0;
7565 1.79 mjacob sdp->isp_devparam[tgt].actv_period = 0;
7566 1.79 mjacob sdp->isp_devparam[tgt].actv_flags = 0;
7567 1.79 mjacob
7568 1.79 mjacob sdp->isp_devparam[tgt].goal_flags =
7569 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags = DPARM_DEFAULT;
7570 1.79 mjacob
7571 1.48 mjacob /*
7572 1.48 mjacob * We default to Wide/Fast for versions less than a 1040
7573 1.48 mjacob * (unless it's SBus).
7574 1.48 mjacob */
7575 1.79 mjacob if (IS_ULTRA3(isp)) {
7576 1.79 mjacob off = ISP_80M_SYNCPARMS >> 8;
7577 1.79 mjacob per = ISP_80M_SYNCPARMS & 0xff;
7578 1.79 mjacob } else if (IS_ULTRA2(isp)) {
7579 1.79 mjacob off = ISP_40M_SYNCPARMS >> 8;
7580 1.79 mjacob per = ISP_40M_SYNCPARMS & 0xff;
7581 1.79 mjacob } else if (IS_1240(isp)) {
7582 1.79 mjacob off = ISP_20M_SYNCPARMS >> 8;
7583 1.79 mjacob per = ISP_20M_SYNCPARMS & 0xff;
7584 1.79 mjacob } else if ((isp->isp_bustype == ISP_BT_SBUS &&
7585 1.48 mjacob isp->isp_type < ISP_HA_SCSI_1020A) ||
7586 1.48 mjacob (isp->isp_bustype == ISP_BT_PCI &&
7587 1.48 mjacob isp->isp_type < ISP_HA_SCSI_1040) ||
7588 1.52 he (isp->isp_clock && isp->isp_clock < 60) ||
7589 1.52 he (sdp->isp_ultramode == 0)) {
7590 1.79 mjacob off = ISP_10M_SYNCPARMS >> 8;
7591 1.79 mjacob per = ISP_10M_SYNCPARMS & 0xff;
7592 1.58 mjacob } else {
7593 1.79 mjacob off = ISP_20M_SYNCPARMS_1040 >> 8;
7594 1.79 mjacob per = ISP_20M_SYNCPARMS_1040 & 0xff;
7595 1.10 mjacob }
7596 1.79 mjacob sdp->isp_devparam[tgt].goal_offset =
7597 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset = off;
7598 1.79 mjacob sdp->isp_devparam[tgt].goal_period =
7599 1.79 mjacob sdp->isp_devparam[tgt].nvrm_period = per;
7600 1.79 mjacob
7601 1.10 mjacob }
7602 1.114 mjacob
7603 1.114 mjacob /*
7604 1.114 mjacob * If we're a dual bus card, just copy the data over
7605 1.114 mjacob */
7606 1.114 mjacob if (sdp1) {
7607 1.114 mjacob *sdp1 = *sdp;
7608 1.114 mjacob sdp1->isp_initiator_id = DEFAULT_IID(isp, 1);
7609 1.114 mjacob }
7610 1.114 mjacob
7611 1.114 mjacob /*
7612 1.114 mjacob * If we've not been told to avoid reading NVRAM, try and read it.
7613 1.114 mjacob * If we're successful reading it, we can then return because NVRAM
7614 1.114 mjacob * will tell us what the desired settings are. Otherwise, we establish
7615 1.114 mjacob * some reasonable 'fake' nvram and goal defaults.
7616 1.114 mjacob */
7617 1.114 mjacob if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
7618 1.114 mjacob mbreg_t mbs;
7619 1.114 mjacob
7620 1.114 mjacob if (isp_read_nvram(isp, 0) == 0) {
7621 1.114 mjacob if (IS_DUALBUS(isp)) {
7622 1.114 mjacob if (isp_read_nvram(isp, 1) == 0) {
7623 1.114 mjacob return;
7624 1.114 mjacob }
7625 1.114 mjacob }
7626 1.114 mjacob }
7627 1.117 mjacob MBSINIT(&mbs, MBOX_GET_ACT_NEG_STATE, MBLOGNONE, 0);
7628 1.114 mjacob isp_mboxcmd(isp, &mbs);
7629 1.114 mjacob if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
7630 1.114 mjacob sdp->isp_req_ack_active_neg = 1;
7631 1.114 mjacob sdp->isp_data_line_active_neg = 1;
7632 1.114 mjacob if (sdp1) {
7633 1.114 mjacob sdp1->isp_req_ack_active_neg = 1;
7634 1.114 mjacob sdp1->isp_data_line_active_neg = 1;
7635 1.114 mjacob }
7636 1.114 mjacob } else {
7637 1.114 mjacob sdp->isp_req_ack_active_neg =
7638 1.114 mjacob (mbs.param[1] >> 4) & 0x1;
7639 1.114 mjacob sdp->isp_data_line_active_neg =
7640 1.114 mjacob (mbs.param[1] >> 5) & 0x1;
7641 1.114 mjacob if (sdp1) {
7642 1.114 mjacob sdp1->isp_req_ack_active_neg =
7643 1.114 mjacob (mbs.param[2] >> 4) & 0x1;
7644 1.114 mjacob sdp1->isp_data_line_active_neg =
7645 1.114 mjacob (mbs.param[2] >> 5) & 0x1;
7646 1.114 mjacob }
7647 1.114 mjacob }
7648 1.114 mjacob }
7649 1.114 mjacob
7650 1.10 mjacob }
7651 1.10 mjacob
7652 1.111 mjacob static void
7653 1.114 mjacob isp_setdfltfcparm(ispsoftc_t *isp, int chan)
7654 1.111 mjacob {
7655 1.114 mjacob fcparam *fcp = FCPARAM(isp, chan);
7656 1.111 mjacob
7657 1.114 mjacob /*
7658 1.114 mjacob * Establish some default parameters.
7659 1.114 mjacob */
7660 1.114 mjacob fcp->role = GET_DEFAULT_ROLE(isp, chan);
7661 1.111 mjacob fcp->isp_maxalloc = ICB_DFLT_ALLOC;
7662 1.111 mjacob fcp->isp_retry_delay = ICB_DFLT_RDELAY;
7663 1.111 mjacob fcp->isp_retry_count = ICB_DFLT_RCOUNT;
7664 1.114 mjacob fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
7665 1.114 mjacob fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
7666 1.114 mjacob fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
7667 1.111 mjacob fcp->isp_fwoptions = 0;
7668 1.114 mjacob fcp->isp_lasthdl = NIL_HANDLE;
7669 1.114 mjacob
7670 1.114 mjacob if (IS_24XX(isp)) {
7671 1.114 mjacob fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
7672 1.114 mjacob fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
7673 1.114 mjacob if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) {
7674 1.114 mjacob fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
7675 1.114 mjacob }
7676 1.114 mjacob fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
7677 1.114 mjacob } else {
7678 1.114 mjacob fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
7679 1.114 mjacob fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
7680 1.114 mjacob fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
7681 1.114 mjacob fcp->isp_fwoptions |= ICBOPT_FAST_POST;
7682 1.114 mjacob if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) {
7683 1.114 mjacob fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
7684 1.114 mjacob }
7685 1.114 mjacob /*
7686 1.114 mjacob * Make sure this is turned off now until we get
7687 1.114 mjacob * extended options from NVRAM
7688 1.114 mjacob */
7689 1.114 mjacob fcp->isp_fwoptions &= ~ICBOPT_EXTENDED;
7690 1.111 mjacob }
7691 1.111 mjacob
7692 1.111 mjacob
7693 1.111 mjacob /*
7694 1.111 mjacob * Now try and read NVRAM unless told to not do so.
7695 1.111 mjacob * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
7696 1.111 mjacob */
7697 1.111 mjacob if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
7698 1.111 mjacob int i, j = 0;
7699 1.111 mjacob /*
7700 1.111 mjacob * Give a couple of tries at reading NVRAM.
7701 1.111 mjacob */
7702 1.111 mjacob for (i = 0; i < 2; i++) {
7703 1.114 mjacob j = isp_read_nvram(isp, chan);
7704 1.111 mjacob if (j == 0) {
7705 1.111 mjacob break;
7706 1.111 mjacob }
7707 1.111 mjacob }
7708 1.111 mjacob if (j) {
7709 1.111 mjacob isp->isp_confopts |= ISP_CFG_NONVRAM;
7710 1.111 mjacob }
7711 1.111 mjacob }
7712 1.111 mjacob
7713 1.114 mjacob fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
7714 1.114 mjacob fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
7715 1.114 mjacob isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
7716 1.114 mjacob chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
7717 1.114 mjacob (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
7718 1.114 mjacob isp_class3_roles[fcp->role]);
7719 1.111 mjacob }
7720 1.111 mjacob
7721 1.34 mjacob /*
7722 1.24 mjacob * Re-initialize the ISP and complete all orphaned commands
7723 1.38 mjacob * with a 'botched' notice. The reset/init routines should
7724 1.38 mjacob * not disturb an already active list of commands.
7725 1.24 mjacob */
7726 1.24 mjacob
7727 1.24 mjacob void
7728 1.117 mjacob isp_reinit(ispsoftc_t *isp, int do_load_defaults)
7729 1.10 mjacob {
7730 1.114 mjacob int i;
7731 1.10 mjacob
7732 1.117 mjacob isp_reset(isp, do_load_defaults);
7733 1.114 mjacob
7734 1.70 mjacob if (isp->isp_state != ISP_RESETSTATE) {
7735 1.117 mjacob isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
7736 1.114 mjacob ISP_DISABLE_INTS(isp);
7737 1.114 mjacob goto cleanup;
7738 1.114 mjacob }
7739 1.114 mjacob
7740 1.114 mjacob isp_init(isp);
7741 1.114 mjacob
7742 1.114 mjacob if (isp->isp_state == ISP_INITSTATE) {
7743 1.114 mjacob isp->isp_state = ISP_RUNSTATE;
7744 1.114 mjacob }
7745 1.114 mjacob
7746 1.114 mjacob if (isp->isp_state != ISP_RUNSTATE) {
7747 1.114 mjacob #ifndef ISP_TARGET_MODE
7748 1.117 mjacob isp_prt(isp, ISP_LOGWARN, "%s: not at runstate", __func__);
7749 1.114 mjacob #endif
7750 1.111 mjacob ISP_DISABLE_INTS(isp);
7751 1.111 mjacob if (IS_FC(isp)) {
7752 1.111 mjacob /*
7753 1.111 mjacob * If we're in ISP_ROLE_NONE, turn off the lasers.
7754 1.111 mjacob */
7755 1.111 mjacob if (!IS_24XX(isp)) {
7756 1.111 mjacob ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
7757 1.111 mjacob ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
7758 1.111 mjacob ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
7759 1.111 mjacob ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
7760 1.111 mjacob ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
7761 1.111 mjacob }
7762 1.95 mjacob }
7763 1.111 mjacob }
7764 1.114 mjacob
7765 1.114 mjacob cleanup:
7766 1.114 mjacob
7767 1.38 mjacob isp->isp_nactive = 0;
7768 1.117 mjacob
7769 1.117 mjacob isp_clear_commands(isp);
7770 1.114 mjacob if (IS_FC(isp)) {
7771 1.114 mjacob for (i = 0; i < isp->isp_nchan; i++) {
7772 1.114 mjacob ISP_MARK_PORTDB(isp, i, -1);
7773 1.114 mjacob }
7774 1.114 mjacob }
7775 1.15 mjacob }
7776 1.15 mjacob
7777 1.28 mjacob /*
7778 1.25 mjacob * NVRAM Routines
7779 1.25 mjacob */
7780 1.25 mjacob static int
7781 1.114 mjacob isp_read_nvram(ispsoftc_t *isp, int bus)
7782 1.25 mjacob {
7783 1.111 mjacob int i, amt, retval;
7784 1.111 mjacob uint8_t csum, minversion;
7785 1.25 mjacob union {
7786 1.114 mjacob uint8_t _x[ISP2400_NVRAM_SIZE];
7787 1.114 mjacob uint16_t _s[ISP2400_NVRAM_SIZE>>1];
7788 1.25 mjacob } _n;
7789 1.25 mjacob #define nvram_data _n._x
7790 1.25 mjacob #define nvram_words _n._s
7791 1.25 mjacob
7792 1.111 mjacob if (IS_24XX(isp)) {
7793 1.114 mjacob return (isp_read_nvram_2400(isp, nvram_data));
7794 1.111 mjacob } else if (IS_FC(isp)) {
7795 1.25 mjacob amt = ISP2100_NVRAM_SIZE;
7796 1.25 mjacob minversion = 1;
7797 1.44 mjacob } else if (IS_ULTRA2(isp)) {
7798 1.36 mjacob amt = ISP1080_NVRAM_SIZE;
7799 1.36 mjacob minversion = 0;
7800 1.25 mjacob } else {
7801 1.25 mjacob amt = ISP_NVRAM_SIZE;
7802 1.25 mjacob minversion = 2;
7803 1.25 mjacob }
7804 1.25 mjacob
7805 1.111 mjacob for (i = 0; i < amt>>1; i++) {
7806 1.25 mjacob isp_rdnvram_word(isp, i, &nvram_words[i]);
7807 1.25 mjacob }
7808 1.111 mjacob
7809 1.25 mjacob if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
7810 1.25 mjacob nvram_data[2] != 'P') {
7811 1.25 mjacob if (isp->isp_bustype != ISP_BT_SBUS) {
7812 1.57 mjacob isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header");
7813 1.57 mjacob isp_prt(isp, ISP_LOGDEBUG0, "%x %x %x",
7814 1.57 mjacob nvram_data[0], nvram_data[1], nvram_data[2]);
7815 1.25 mjacob }
7816 1.111 mjacob retval = -1;
7817 1.111 mjacob goto out;
7818 1.25 mjacob }
7819 1.111 mjacob
7820 1.25 mjacob for (csum = 0, i = 0; i < amt; i++) {
7821 1.25 mjacob csum += nvram_data[i];
7822 1.25 mjacob }
7823 1.25 mjacob if (csum != 0) {
7824 1.57 mjacob isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
7825 1.111 mjacob retval = -1;
7826 1.111 mjacob goto out;
7827 1.25 mjacob }
7828 1.111 mjacob
7829 1.25 mjacob if (ISP_NVRAM_VERSION(nvram_data) < minversion) {
7830 1.57 mjacob isp_prt(isp, ISP_LOGWARN, "version %d NVRAM not understood",
7831 1.25 mjacob ISP_NVRAM_VERSION(nvram_data));
7832 1.111 mjacob retval = -1;
7833 1.111 mjacob goto out;
7834 1.25 mjacob }
7835 1.25 mjacob
7836 1.49 mjacob if (IS_ULTRA3(isp)) {
7837 1.114 mjacob isp_parse_nvram_12160(isp, bus, nvram_data);
7838 1.49 mjacob } else if (IS_1080(isp)) {
7839 1.114 mjacob isp_parse_nvram_1080(isp, bus, nvram_data);
7840 1.49 mjacob } else if (IS_1280(isp) || IS_1240(isp)) {
7841 1.114 mjacob isp_parse_nvram_1080(isp, bus, nvram_data);
7842 1.36 mjacob } else if (IS_SCSI(isp)) {
7843 1.49 mjacob isp_parse_nvram_1020(isp, nvram_data);
7844 1.25 mjacob } else {
7845 1.49 mjacob isp_parse_nvram_2100(isp, nvram_data);
7846 1.25 mjacob }
7847 1.111 mjacob retval = 0;
7848 1.111 mjacob out:
7849 1.111 mjacob return (retval);
7850 1.49 mjacob #undef nvram_data
7851 1.49 mjacob #undef nvram_words
7852 1.25 mjacob }
7853 1.25 mjacob
7854 1.111 mjacob static int
7855 1.114 mjacob isp_read_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
7856 1.111 mjacob {
7857 1.111 mjacob int retval = 0;
7858 1.111 mjacob uint32_t addr, csum, lwrds, *dptr;
7859 1.117 mjacob
7860 1.111 mjacob if (isp->isp_port) {
7861 1.111 mjacob addr = ISP2400_NVRAM_PORT1_ADDR;
7862 1.111 mjacob } else {
7863 1.111 mjacob addr = ISP2400_NVRAM_PORT0_ADDR;
7864 1.111 mjacob }
7865 1.117 mjacob
7866 1.111 mjacob dptr = (uint32_t *) nvram_data;
7867 1.111 mjacob for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
7868 1.111 mjacob isp_rd_2400_nvram(isp, addr++, dptr++);
7869 1.111 mjacob }
7870 1.111 mjacob if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
7871 1.111 mjacob nvram_data[2] != 'P') {
7872 1.113 mjacob isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)",
7873 1.113 mjacob nvram_data[0], nvram_data[1], nvram_data[2]);
7874 1.111 mjacob retval = -1;
7875 1.111 mjacob goto out;
7876 1.111 mjacob }
7877 1.111 mjacob dptr = (uint32_t *) nvram_data;
7878 1.111 mjacob for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
7879 1.113 mjacob uint32_t tmp;
7880 1.113 mjacob ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
7881 1.113 mjacob csum += tmp;
7882 1.111 mjacob }
7883 1.111 mjacob if (csum != 0) {
7884 1.111 mjacob isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
7885 1.111 mjacob retval = -1;
7886 1.111 mjacob goto out;
7887 1.111 mjacob }
7888 1.111 mjacob isp_parse_nvram_2400(isp, nvram_data);
7889 1.111 mjacob out:
7890 1.111 mjacob return (retval);
7891 1.111 mjacob }
7892 1.111 mjacob
7893 1.25 mjacob static void
7894 1.111 mjacob isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
7895 1.25 mjacob {
7896 1.25 mjacob int i, cbits;
7897 1.111 mjacob uint16_t bit, rqst, junk;
7898 1.25 mjacob
7899 1.25 mjacob ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
7900 1.117 mjacob ISP_DELAY(10);
7901 1.25 mjacob ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
7902 1.117 mjacob ISP_DELAY(10);
7903 1.25 mjacob
7904 1.36 mjacob if (IS_FC(isp)) {
7905 1.117 mjacob wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1);
7906 1.88 mjacob if (IS_2312(isp) && isp->isp_port) {
7907 1.88 mjacob wo += 128;
7908 1.88 mjacob }
7909 1.36 mjacob rqst = (ISP_NVRAM_READ << 8) | wo;
7910 1.36 mjacob cbits = 10;
7911 1.44 mjacob } else if (IS_ULTRA2(isp)) {
7912 1.36 mjacob wo &= ((ISP1080_NVRAM_SIZE >> 1) - 1);
7913 1.25 mjacob rqst = (ISP_NVRAM_READ << 8) | wo;
7914 1.25 mjacob cbits = 10;
7915 1.25 mjacob } else {
7916 1.25 mjacob wo &= ((ISP_NVRAM_SIZE >> 1) - 1);
7917 1.25 mjacob rqst = (ISP_NVRAM_READ << 6) | wo;
7918 1.25 mjacob cbits = 8;
7919 1.25 mjacob }
7920 1.25 mjacob
7921 1.25 mjacob /*
7922 1.25 mjacob * Clock the word select request out...
7923 1.25 mjacob */
7924 1.25 mjacob for (i = cbits; i >= 0; i--) {
7925 1.25 mjacob if ((rqst >> i) & 1) {
7926 1.25 mjacob bit = BIU_NVRAM_SELECT | BIU_NVRAM_DATAOUT;
7927 1.25 mjacob } else {
7928 1.25 mjacob bit = BIU_NVRAM_SELECT;
7929 1.25 mjacob }
7930 1.25 mjacob ISP_WRITE(isp, BIU_NVRAM, bit);
7931 1.117 mjacob ISP_DELAY(10);
7932 1.111 mjacob junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
7933 1.25 mjacob ISP_WRITE(isp, BIU_NVRAM, bit | BIU_NVRAM_CLOCK);
7934 1.117 mjacob ISP_DELAY(10);
7935 1.111 mjacob junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
7936 1.25 mjacob ISP_WRITE(isp, BIU_NVRAM, bit);
7937 1.117 mjacob ISP_DELAY(10);
7938 1.111 mjacob junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
7939 1.25 mjacob }
7940 1.25 mjacob /*
7941 1.25 mjacob * Now read the result back in (bits come back in MSB format).
7942 1.25 mjacob */
7943 1.25 mjacob *rp = 0;
7944 1.25 mjacob for (i = 0; i < 16; i++) {
7945 1.111 mjacob uint16_t rv;
7946 1.25 mjacob *rp <<= 1;
7947 1.25 mjacob ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
7948 1.117 mjacob ISP_DELAY(10);
7949 1.25 mjacob rv = ISP_READ(isp, BIU_NVRAM);
7950 1.25 mjacob if (rv & BIU_NVRAM_DATAIN) {
7951 1.25 mjacob *rp |= 1;
7952 1.25 mjacob }
7953 1.117 mjacob ISP_DELAY(10);
7954 1.25 mjacob ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
7955 1.117 mjacob ISP_DELAY(10);
7956 1.111 mjacob junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
7957 1.25 mjacob }
7958 1.25 mjacob ISP_WRITE(isp, BIU_NVRAM, 0);
7959 1.117 mjacob ISP_DELAY(10);
7960 1.111 mjacob junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
7961 1.57 mjacob ISP_SWIZZLE_NVRAM_WORD(isp, rp);
7962 1.49 mjacob }
7963 1.49 mjacob
7964 1.49 mjacob static void
7965 1.111 mjacob isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
7966 1.111 mjacob {
7967 1.111 mjacob int loops = 0;
7968 1.117 mjacob uint32_t base = 0x7ffe0000;
7969 1.111 mjacob uint32_t tmp = 0;
7970 1.111 mjacob
7971 1.117 mjacob if (IS_25XX(isp)) {
7972 1.117 mjacob base = 0x7ff00000 | 0x48000;
7973 1.117 mjacob }
7974 1.111 mjacob ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
7975 1.111 mjacob for (loops = 0; loops < 5000; loops++) {
7976 1.117 mjacob ISP_DELAY(10);
7977 1.111 mjacob tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
7978 1.111 mjacob if ((tmp & (1U << 31)) != 0) {
7979 1.111 mjacob break;
7980 1.111 mjacob }
7981 1.111 mjacob }
7982 1.111 mjacob if (tmp & (1U << 31)) {
7983 1.113 mjacob *rp = ISP_READ(isp, BIU2400_FLASH_DATA);
7984 1.113 mjacob ISP_SWIZZLE_NVRAM_LONG(isp, rp);
7985 1.111 mjacob } else {
7986 1.111 mjacob *rp = 0xffffffff;
7987 1.111 mjacob }
7988 1.111 mjacob }
7989 1.111 mjacob
7990 1.111 mjacob static void
7991 1.111 mjacob isp_parse_nvram_1020(ispsoftc_t *isp, uint8_t *nvram_data)
7992 1.49 mjacob {
7993 1.114 mjacob sdparam *sdp = SDPARAM(isp, 0);
7994 1.79 mjacob int tgt;
7995 1.49 mjacob
7996 1.49 mjacob sdp->isp_fifo_threshold =
7997 1.49 mjacob ISP_NVRAM_FIFO_THRESHOLD(nvram_data) |
7998 1.49 mjacob (ISP_NVRAM_FIFO_THRESHOLD_128(nvram_data) << 2);
7999 1.49 mjacob
8000 1.96 mjacob if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
8001 1.96 mjacob sdp->isp_initiator_id =
8002 1.96 mjacob ISP_NVRAM_INITIATOR_ID(nvram_data);
8003 1.49 mjacob
8004 1.49 mjacob sdp->isp_bus_reset_delay =
8005 1.49 mjacob ISP_NVRAM_BUS_RESET_DELAY(nvram_data);
8006 1.49 mjacob
8007 1.49 mjacob sdp->isp_retry_count =
8008 1.49 mjacob ISP_NVRAM_BUS_RETRY_COUNT(nvram_data);
8009 1.49 mjacob
8010 1.49 mjacob sdp->isp_retry_delay =
8011 1.49 mjacob ISP_NVRAM_BUS_RETRY_DELAY(nvram_data);
8012 1.49 mjacob
8013 1.49 mjacob sdp->isp_async_data_setup =
8014 1.49 mjacob ISP_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data);
8015 1.49 mjacob
8016 1.49 mjacob if (isp->isp_type >= ISP_HA_SCSI_1040) {
8017 1.49 mjacob if (sdp->isp_async_data_setup < 9) {
8018 1.49 mjacob sdp->isp_async_data_setup = 9;
8019 1.49 mjacob }
8020 1.49 mjacob } else {
8021 1.49 mjacob if (sdp->isp_async_data_setup != 6) {
8022 1.49 mjacob sdp->isp_async_data_setup = 6;
8023 1.49 mjacob }
8024 1.49 mjacob }
8025 1.49 mjacob
8026 1.49 mjacob sdp->isp_req_ack_active_neg =
8027 1.49 mjacob ISP_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data);
8028 1.49 mjacob
8029 1.49 mjacob sdp->isp_data_line_active_neg =
8030 1.49 mjacob ISP_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data);
8031 1.49 mjacob
8032 1.49 mjacob sdp->isp_data_dma_burst_enabl =
8033 1.49 mjacob ISP_NVRAM_DATA_DMA_BURST_ENABLE(nvram_data);
8034 1.49 mjacob
8035 1.49 mjacob sdp->isp_cmd_dma_burst_enable =
8036 1.49 mjacob ISP_NVRAM_CMD_DMA_BURST_ENABLE(nvram_data);
8037 1.49 mjacob
8038 1.49 mjacob sdp->isp_tag_aging =
8039 1.49 mjacob ISP_NVRAM_TAG_AGE_LIMIT(nvram_data);
8040 1.49 mjacob
8041 1.49 mjacob sdp->isp_selection_timeout =
8042 1.49 mjacob ISP_NVRAM_SELECTION_TIMEOUT(nvram_data);
8043 1.49 mjacob
8044 1.49 mjacob sdp->isp_max_queue_depth =
8045 1.49 mjacob ISP_NVRAM_MAX_QUEUE_DEPTH(nvram_data);
8046 1.49 mjacob
8047 1.58 mjacob sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data);
8048 1.49 mjacob
8049 1.79 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
8050 1.79 mjacob sdp->isp_devparam[tgt].dev_enable =
8051 1.79 mjacob ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt);
8052 1.79 mjacob sdp->isp_devparam[tgt].exc_throttle =
8053 1.79 mjacob ISP_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt);
8054 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset =
8055 1.79 mjacob ISP_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt);
8056 1.79 mjacob sdp->isp_devparam[tgt].nvrm_period =
8057 1.79 mjacob ISP_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt);
8058 1.79 mjacob /*
8059 1.79 mjacob * We probably shouldn't lie about this, but it
8060 1.79 mjacob * it makes it much safer if we limit NVRAM values
8061 1.79 mjacob * to sanity.
8062 1.79 mjacob */
8063 1.49 mjacob if (isp->isp_type < ISP_HA_SCSI_1040) {
8064 1.49 mjacob /*
8065 1.49 mjacob * If we're not ultra, we can't possibly
8066 1.49 mjacob * be a shorter period than this.
8067 1.49 mjacob */
8068 1.79 mjacob if (sdp->isp_devparam[tgt].nvrm_period < 0x19) {
8069 1.79 mjacob sdp->isp_devparam[tgt].nvrm_period = 0x19;
8070 1.49 mjacob }
8071 1.79 mjacob if (sdp->isp_devparam[tgt].nvrm_offset > 0xc) {
8072 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset = 0x0c;
8073 1.49 mjacob }
8074 1.49 mjacob } else {
8075 1.79 mjacob if (sdp->isp_devparam[tgt].nvrm_offset > 0x8) {
8076 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset = 0x8;
8077 1.49 mjacob }
8078 1.49 mjacob }
8079 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags = 0;
8080 1.79 mjacob if (ISP_NVRAM_TGT_RENEG(nvram_data, tgt))
8081 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
8082 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
8083 1.79 mjacob if (ISP_NVRAM_TGT_TQING(nvram_data, tgt))
8084 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
8085 1.79 mjacob if (ISP_NVRAM_TGT_SYNC(nvram_data, tgt))
8086 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
8087 1.79 mjacob if (ISP_NVRAM_TGT_WIDE(nvram_data, tgt))
8088 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
8089 1.79 mjacob if (ISP_NVRAM_TGT_PARITY(nvram_data, tgt))
8090 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
8091 1.79 mjacob if (ISP_NVRAM_TGT_DISC(nvram_data, tgt))
8092 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
8093 1.79 mjacob sdp->isp_devparam[tgt].actv_flags = 0; /* we don't know */
8094 1.79 mjacob sdp->isp_devparam[tgt].goal_offset =
8095 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset;
8096 1.79 mjacob sdp->isp_devparam[tgt].goal_period =
8097 1.79 mjacob sdp->isp_devparam[tgt].nvrm_period;
8098 1.79 mjacob sdp->isp_devparam[tgt].goal_flags =
8099 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags;
8100 1.49 mjacob }
8101 1.49 mjacob }
8102 1.49 mjacob
8103 1.49 mjacob static void
8104 1.111 mjacob isp_parse_nvram_1080(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
8105 1.49 mjacob {
8106 1.114 mjacob sdparam *sdp = SDPARAM(isp, bus);
8107 1.79 mjacob int tgt;
8108 1.79 mjacob
8109 1.78 mjacob sdp->isp_fifo_threshold =
8110 1.49 mjacob ISP1080_NVRAM_FIFO_THRESHOLD(nvram_data);
8111 1.49 mjacob
8112 1.96 mjacob if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
8113 1.96 mjacob sdp->isp_initiator_id =
8114 1.96 mjacob ISP1080_NVRAM_INITIATOR_ID(nvram_data, bus);
8115 1.49 mjacob
8116 1.49 mjacob sdp->isp_bus_reset_delay =
8117 1.49 mjacob ISP1080_NVRAM_BUS_RESET_DELAY(nvram_data, bus);
8118 1.49 mjacob
8119 1.49 mjacob sdp->isp_retry_count =
8120 1.49 mjacob ISP1080_NVRAM_BUS_RETRY_COUNT(nvram_data, bus);
8121 1.49 mjacob
8122 1.49 mjacob sdp->isp_retry_delay =
8123 1.49 mjacob ISP1080_NVRAM_BUS_RETRY_DELAY(nvram_data, bus);
8124 1.49 mjacob
8125 1.49 mjacob sdp->isp_async_data_setup =
8126 1.79 mjacob ISP1080_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data, bus);
8127 1.49 mjacob
8128 1.49 mjacob sdp->isp_req_ack_active_neg =
8129 1.79 mjacob ISP1080_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data, bus);
8130 1.49 mjacob
8131 1.49 mjacob sdp->isp_data_line_active_neg =
8132 1.79 mjacob ISP1080_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data, bus);
8133 1.49 mjacob
8134 1.49 mjacob sdp->isp_data_dma_burst_enabl =
8135 1.49 mjacob ISP1080_NVRAM_BURST_ENABLE(nvram_data);
8136 1.49 mjacob
8137 1.49 mjacob sdp->isp_cmd_dma_burst_enable =
8138 1.49 mjacob ISP1080_NVRAM_BURST_ENABLE(nvram_data);
8139 1.49 mjacob
8140 1.49 mjacob sdp->isp_selection_timeout =
8141 1.49 mjacob ISP1080_NVRAM_SELECTION_TIMEOUT(nvram_data, bus);
8142 1.49 mjacob
8143 1.49 mjacob sdp->isp_max_queue_depth =
8144 1.49 mjacob ISP1080_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus);
8145 1.49 mjacob
8146 1.79 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
8147 1.79 mjacob sdp->isp_devparam[tgt].dev_enable =
8148 1.79 mjacob ISP1080_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt, bus);
8149 1.79 mjacob sdp->isp_devparam[tgt].exc_throttle =
8150 1.79 mjacob ISP1080_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt, bus);
8151 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset =
8152 1.79 mjacob ISP1080_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt, bus);
8153 1.79 mjacob sdp->isp_devparam[tgt].nvrm_period =
8154 1.79 mjacob ISP1080_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt, bus);
8155 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags = 0;
8156 1.79 mjacob if (ISP1080_NVRAM_TGT_RENEG(nvram_data, tgt, bus))
8157 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
8158 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
8159 1.79 mjacob if (ISP1080_NVRAM_TGT_TQING(nvram_data, tgt, bus))
8160 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
8161 1.79 mjacob if (ISP1080_NVRAM_TGT_SYNC(nvram_data, tgt, bus))
8162 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
8163 1.79 mjacob if (ISP1080_NVRAM_TGT_WIDE(nvram_data, tgt, bus))
8164 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
8165 1.79 mjacob if (ISP1080_NVRAM_TGT_PARITY(nvram_data, tgt, bus))
8166 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
8167 1.79 mjacob if (ISP1080_NVRAM_TGT_DISC(nvram_data, tgt, bus))
8168 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
8169 1.79 mjacob sdp->isp_devparam[tgt].actv_flags = 0;
8170 1.79 mjacob sdp->isp_devparam[tgt].goal_offset =
8171 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset;
8172 1.79 mjacob sdp->isp_devparam[tgt].goal_period =
8173 1.79 mjacob sdp->isp_devparam[tgt].nvrm_period;
8174 1.79 mjacob sdp->isp_devparam[tgt].goal_flags =
8175 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags;
8176 1.49 mjacob }
8177 1.49 mjacob }
8178 1.49 mjacob
8179 1.49 mjacob static void
8180 1.111 mjacob isp_parse_nvram_12160(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
8181 1.49 mjacob {
8182 1.114 mjacob sdparam *sdp = SDPARAM(isp, bus);
8183 1.79 mjacob int tgt;
8184 1.49 mjacob
8185 1.49 mjacob sdp->isp_fifo_threshold =
8186 1.49 mjacob ISP12160_NVRAM_FIFO_THRESHOLD(nvram_data);
8187 1.49 mjacob
8188 1.96 mjacob if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
8189 1.96 mjacob sdp->isp_initiator_id =
8190 1.96 mjacob ISP12160_NVRAM_INITIATOR_ID(nvram_data, bus);
8191 1.49 mjacob
8192 1.49 mjacob sdp->isp_bus_reset_delay =
8193 1.49 mjacob ISP12160_NVRAM_BUS_RESET_DELAY(nvram_data, bus);
8194 1.49 mjacob
8195 1.49 mjacob sdp->isp_retry_count =
8196 1.49 mjacob ISP12160_NVRAM_BUS_RETRY_COUNT(nvram_data, bus);
8197 1.49 mjacob
8198 1.49 mjacob sdp->isp_retry_delay =
8199 1.49 mjacob ISP12160_NVRAM_BUS_RETRY_DELAY(nvram_data, bus);
8200 1.49 mjacob
8201 1.49 mjacob sdp->isp_async_data_setup =
8202 1.79 mjacob ISP12160_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data, bus);
8203 1.49 mjacob
8204 1.49 mjacob sdp->isp_req_ack_active_neg =
8205 1.79 mjacob ISP12160_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data, bus);
8206 1.49 mjacob
8207 1.49 mjacob sdp->isp_data_line_active_neg =
8208 1.79 mjacob ISP12160_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data, bus);
8209 1.49 mjacob
8210 1.49 mjacob sdp->isp_data_dma_burst_enabl =
8211 1.49 mjacob ISP12160_NVRAM_BURST_ENABLE(nvram_data);
8212 1.49 mjacob
8213 1.49 mjacob sdp->isp_cmd_dma_burst_enable =
8214 1.49 mjacob ISP12160_NVRAM_BURST_ENABLE(nvram_data);
8215 1.49 mjacob
8216 1.49 mjacob sdp->isp_selection_timeout =
8217 1.49 mjacob ISP12160_NVRAM_SELECTION_TIMEOUT(nvram_data, bus);
8218 1.49 mjacob
8219 1.49 mjacob sdp->isp_max_queue_depth =
8220 1.49 mjacob ISP12160_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus);
8221 1.49 mjacob
8222 1.79 mjacob for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
8223 1.79 mjacob sdp->isp_devparam[tgt].dev_enable =
8224 1.79 mjacob ISP12160_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt, bus);
8225 1.79 mjacob sdp->isp_devparam[tgt].exc_throttle =
8226 1.79 mjacob ISP12160_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt, bus);
8227 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset =
8228 1.79 mjacob ISP12160_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt, bus);
8229 1.79 mjacob sdp->isp_devparam[tgt].nvrm_period =
8230 1.79 mjacob ISP12160_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt, bus);
8231 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags = 0;
8232 1.79 mjacob if (ISP12160_NVRAM_TGT_RENEG(nvram_data, tgt, bus))
8233 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
8234 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
8235 1.79 mjacob if (ISP12160_NVRAM_TGT_TQING(nvram_data, tgt, bus))
8236 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
8237 1.79 mjacob if (ISP12160_NVRAM_TGT_SYNC(nvram_data, tgt, bus))
8238 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
8239 1.79 mjacob if (ISP12160_NVRAM_TGT_WIDE(nvram_data, tgt, bus))
8240 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
8241 1.79 mjacob if (ISP12160_NVRAM_TGT_PARITY(nvram_data, tgt, bus))
8242 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
8243 1.79 mjacob if (ISP12160_NVRAM_TGT_DISC(nvram_data, tgt, bus))
8244 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
8245 1.79 mjacob sdp->isp_devparam[tgt].actv_flags = 0;
8246 1.79 mjacob sdp->isp_devparam[tgt].goal_offset =
8247 1.79 mjacob sdp->isp_devparam[tgt].nvrm_offset;
8248 1.79 mjacob sdp->isp_devparam[tgt].goal_period =
8249 1.79 mjacob sdp->isp_devparam[tgt].nvrm_period;
8250 1.79 mjacob sdp->isp_devparam[tgt].goal_flags =
8251 1.79 mjacob sdp->isp_devparam[tgt].nvrm_flags;
8252 1.49 mjacob }
8253 1.49 mjacob }
8254 1.49 mjacob
8255 1.49 mjacob static void
8256 1.111 mjacob isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
8257 1.49 mjacob {
8258 1.114 mjacob fcparam *fcp = FCPARAM(isp, 0);
8259 1.111 mjacob uint64_t wwn;
8260 1.49 mjacob
8261 1.49 mjacob /*
8262 1.62 mjacob * There is NVRAM storage for both Port and Node entities-
8263 1.62 mjacob * but the Node entity appears to be unused on all the cards
8264 1.62 mjacob * I can find. However, we should account for this being set
8265 1.62 mjacob * at some point in the future.
8266 1.62 mjacob *
8267 1.62 mjacob * Qlogic WWNs have an NAA of 2, but usually nothing shows up in
8268 1.62 mjacob * bits 48..60. In the case of the 2202, it appears that they do
8269 1.62 mjacob * use bit 48 to distinguish between the two instances on the card.
8270 1.62 mjacob * The 2204, which I've never seen, *probably* extends this method.
8271 1.62 mjacob */
8272 1.62 mjacob wwn = ISP2100_NVRAM_PORT_NAME(nvram_data);
8273 1.62 mjacob if (wwn) {
8274 1.62 mjacob isp_prt(isp, ISP_LOGCONFIG, "NVRAM Port WWN 0x%08x%08x",
8275 1.114 mjacob (uint32_t) (wwn >> 32), (uint32_t) (wwn));
8276 1.62 mjacob if ((wwn >> 60) == 0) {
8277 1.111 mjacob wwn |= (((uint64_t) 2)<< 60);
8278 1.62 mjacob }
8279 1.62 mjacob }
8280 1.111 mjacob fcp->isp_wwpn_nvram = wwn;
8281 1.88 mjacob if (IS_2200(isp) || IS_23XX(isp)) {
8282 1.111 mjacob wwn = ISP2100_NVRAM_NODE_NAME(nvram_data);
8283 1.88 mjacob if (wwn) {
8284 1.88 mjacob isp_prt(isp, ISP_LOGCONFIG, "NVRAM Node WWN 0x%08x%08x",
8285 1.111 mjacob (uint32_t) (wwn >> 32),
8286 1.114 mjacob (uint32_t) (wwn));
8287 1.88 mjacob if ((wwn >> 60) == 0) {
8288 1.111 mjacob wwn |= (((uint64_t) 2)<< 60);
8289 1.88 mjacob }
8290 1.118 mjacob } else {
8291 1.118 mjacob wwn = fcp->isp_wwpn_nvram & ~((uint64_t) 0xfff << 48);
8292 1.62 mjacob }
8293 1.88 mjacob } else {
8294 1.111 mjacob wwn &= ~((uint64_t) 0xfff << 48);
8295 1.111 mjacob }
8296 1.111 mjacob fcp->isp_wwnn_nvram = wwn;
8297 1.111 mjacob
8298 1.111 mjacob fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);
8299 1.111 mjacob if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
8300 1.114 mjacob DEFAULT_FRAMESIZE(isp) =
8301 1.114 mjacob ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data);
8302 1.111 mjacob }
8303 1.111 mjacob fcp->isp_retry_delay = ISP2100_NVRAM_RETRY_DELAY(nvram_data);
8304 1.111 mjacob fcp->isp_retry_count = ISP2100_NVRAM_RETRY_COUNT(nvram_data);
8305 1.111 mjacob if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
8306 1.111 mjacob fcp->isp_loopid = ISP2100_NVRAM_HARDLOOPID(nvram_data);
8307 1.111 mjacob }
8308 1.111 mjacob if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) {
8309 1.117 mjacob DEFAULT_EXEC_THROTTLE(isp) =
8310 1.111 mjacob ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data);
8311 1.62 mjacob }
8312 1.111 mjacob fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data);
8313 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0,
8314 1.111 mjacob "NVRAM 0x%08x%08x 0x%08x%08x maxalloc %d maxframelen %d",
8315 1.114 mjacob (uint32_t) (fcp->isp_wwnn_nvram >> 32),
8316 1.114 mjacob (uint32_t) fcp->isp_wwnn_nvram,
8317 1.114 mjacob (uint32_t) (fcp->isp_wwpn_nvram >> 32),
8318 1.114 mjacob (uint32_t) fcp->isp_wwpn_nvram,
8319 1.111 mjacob ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data),
8320 1.111 mjacob ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data));
8321 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0,
8322 1.111 mjacob "execthrottle %d fwoptions 0x%x hardloop %d tov %d",
8323 1.111 mjacob ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data),
8324 1.111 mjacob ISP2100_NVRAM_OPTIONS(nvram_data),
8325 1.111 mjacob ISP2100_NVRAM_HARDLOOPID(nvram_data),
8326 1.111 mjacob ISP2100_NVRAM_TOV(nvram_data));
8327 1.111 mjacob fcp->isp_xfwoptions = ISP2100_XFW_OPTIONS(nvram_data);
8328 1.111 mjacob fcp->isp_zfwoptions = ISP2100_ZFW_OPTIONS(nvram_data);
8329 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0,
8330 1.111 mjacob "xfwoptions 0x%x zfw options 0x%x",
8331 1.111 mjacob ISP2100_XFW_OPTIONS(nvram_data), ISP2100_ZFW_OPTIONS(nvram_data));
8332 1.111 mjacob }
8333 1.111 mjacob
8334 1.111 mjacob static void
8335 1.111 mjacob isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
8336 1.111 mjacob {
8337 1.114 mjacob fcparam *fcp = FCPARAM(isp, 0);
8338 1.111 mjacob uint64_t wwn;
8339 1.111 mjacob
8340 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0,
8341 1.111 mjacob "NVRAM 0x%08x%08x 0x%08x%08x exchg_cnt %d maxframelen %d",
8342 1.111 mjacob (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
8343 1.111 mjacob (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
8344 1.111 mjacob (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
8345 1.111 mjacob (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
8346 1.111 mjacob ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data),
8347 1.111 mjacob ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
8348 1.111 mjacob isp_prt(isp, ISP_LOGDEBUG0,
8349 1.111 mjacob "NVRAM execthr %d loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
8350 1.111 mjacob ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data),
8351 1.111 mjacob ISP2400_NVRAM_HARDLOOPID(nvram_data),
8352 1.111 mjacob ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
8353 1.111 mjacob ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
8354 1.111 mjacob ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
8355 1.62 mjacob
8356 1.111 mjacob wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
8357 1.111 mjacob fcp->isp_wwpn_nvram = wwn;
8358 1.52 he
8359 1.111 mjacob wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
8360 1.111 mjacob if (wwn) {
8361 1.111 mjacob if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
8362 1.111 mjacob wwn = 0;
8363 1.52 he }
8364 1.49 mjacob }
8365 1.118 mjacob if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
8366 1.118 mjacob wwn = fcp->isp_wwpn_nvram;
8367 1.118 mjacob wwn &= ~((uint64_t) 0xfff << 48);
8368 1.118 mjacob }
8369 1.111 mjacob fcp->isp_wwnn_nvram = wwn;
8370 1.62 mjacob
8371 1.111 mjacob if (ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data)) {
8372 1.111 mjacob fcp->isp_maxalloc = ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data);
8373 1.111 mjacob }
8374 1.111 mjacob if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
8375 1.114 mjacob DEFAULT_FRAMESIZE(isp) =
8376 1.114 mjacob ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
8377 1.111 mjacob }
8378 1.111 mjacob if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
8379 1.111 mjacob fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
8380 1.111 mjacob }
8381 1.111 mjacob if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) {
8382 1.117 mjacob DEFAULT_EXEC_THROTTLE(isp) =
8383 1.111 mjacob ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data);
8384 1.111 mjacob }
8385 1.111 mjacob fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
8386 1.111 mjacob fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
8387 1.111 mjacob fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);
8388 1.1 cgd }
8389