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