Sat Aug 19 04:27:35 2017 UTC ()
Pull up following revision(s) (requested by mrg in ticket #1485):
	sys/dev/ic/isp_netbsd.c: revision 1.89
Reject out-of-bounds channel index.
From Ilja Van Sprundel.


(snj)
diff -r1.85.2.1 -r1.85.2.1.2.1 src/sys/dev/ic/isp_netbsd.c

cvs diff -r1.85.2.1 -r1.85.2.1.2.1 src/sys/dev/ic/isp_netbsd.c (switch to unified diff)

--- src/sys/dev/ic/isp_netbsd.c 2012/09/03 18:38:34 1.85.2.1
+++ src/sys/dev/ic/isp_netbsd.c 2017/08/19 04:27:35 1.85.2.1.2.1
@@ -1,1476 +1,1480 @@ @@ -1,1476 +1,1480 @@
1/* $NetBSD: isp_netbsd.c,v 1.85.2.1 2012/09/03 18:38:34 riz Exp $ */ 1/* $NetBSD: isp_netbsd.c,v 1.85.2.1.2.1 2017/08/19 04:27:35 snj Exp $ */
2/* 2/*
3 * Platform (NetBSD) dependent common attachment code for Qlogic adapters. 3 * Platform (NetBSD) dependent common attachment code for Qlogic adapters.
4 */ 4 */
5/* 5/*
6 * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration 6 * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Additional Copyright (C) 2000-2007 by Matthew Jacob 9 * Additional Copyright (C) 2000-2007 by Matthew Jacob
10 * All rights reserved. 10 * All rights reserved.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
15 * 1. Redistributions of source code must retain the above copyright 15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer. 16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright 17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the 18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution. 19 * documentation and/or other materials provided with the distribution.
20 * 3. The name of the author may not be used to endorse or promote products 20 * 3. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission 21 * derived from this software without specific prior written permission
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: isp_netbsd.c,v 1.85.2.1 2012/09/03 18:38:34 riz Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: isp_netbsd.c,v 1.85.2.1.2.1 2017/08/19 04:27:35 snj Exp $");
37 37
38#include <dev/ic/isp_netbsd.h> 38#include <dev/ic/isp_netbsd.h>
39#include <dev/ic/isp_ioctl.h> 39#include <dev/ic/isp_ioctl.h>
40#include <sys/scsiio.h> 40#include <sys/scsiio.h>
41 41
42#include <sys/timevar.h> 42#include <sys/timevar.h>
43 43
44/* 44/*
45 * Set a timeout for the watchdogging of a command. 45 * Set a timeout for the watchdogging of a command.
46 * 46 *
47 * The dimensional analysis is 47 * The dimensional analysis is
48 * 48 *
49 * milliseconds * (seconds/millisecond) * (ticks/second) = ticks 49 * milliseconds * (seconds/millisecond) * (ticks/second) = ticks
50 * 50 *
51 * = 51 * =
52 * 52 *
53 * (milliseconds / 1000) * hz = ticks 53 * (milliseconds / 1000) * hz = ticks
54 * 54 *
55 * 55 *
56 * For timeouts less than 1 second, we'll get zero. Because of this, and 56 * For timeouts less than 1 second, we'll get zero. Because of this, and
57 * because we want to establish *our* timeout to be longer than what the 57 * because we want to establish *our* timeout to be longer than what the
58 * firmware might do, we just add 3 seconds at the back end. 58 * firmware might do, we just add 3 seconds at the back end.
59 */ 59 */
60#define _XT(xs) ((((xs)->timeout/1000) * hz) + (3 * hz)) 60#define _XT(xs) ((((xs)->timeout/1000) * hz) + (3 * hz))
61 61
62static void isp_config_interrupts(device_t); 62static void isp_config_interrupts(device_t);
63static void ispminphys_1020(struct buf *); 63static void ispminphys_1020(struct buf *);
64static void ispminphys(struct buf *); 64static void ispminphys(struct buf *);
65static void ispcmd(struct ispsoftc *, XS_T *); 65static void ispcmd(struct ispsoftc *, XS_T *);
66static void isprequest(struct scsipi_channel *, scsipi_adapter_req_t, void *); 66static void isprequest(struct scsipi_channel *, scsipi_adapter_req_t, void *);
67static int 67static int
68ispioctl(struct scsipi_channel *, u_long, void *, int, struct proc *); 68ispioctl(struct scsipi_channel *, u_long, void *, int, struct proc *);
69 69
70static void isp_polled_cmd_wait(struct ispsoftc *, XS_T *); 70static void isp_polled_cmd_wait(struct ispsoftc *, XS_T *);
71static void isp_dog(void *); 71static void isp_dog(void *);
72static void isp_gdt(void *); 72static void isp_gdt(void *);
73static void isp_ldt(void *); 73static void isp_ldt(void *);
74static void isp_make_here(ispsoftc_t *, int); 74static void isp_make_here(ispsoftc_t *, int);
75static void isp_make_gone(ispsoftc_t *, int); 75static void isp_make_gone(ispsoftc_t *, int);
76static void isp_fc_worker(void *); 76static void isp_fc_worker(void *);
77 77
78static const char *roles[4] = { 78static const char *roles[4] = {
79 "(none)", "Target", "Initiator", "Target/Initiator" 79 "(none)", "Target", "Initiator", "Target/Initiator"
80}; 80};
81static const char prom3[] = 81static const char prom3[] =
82 "PortID 0x%06x Departed from Target %u because of %s"; 82 "PortID 0x%06x Departed from Target %u because of %s";
83int isp_change_is_bad = 0; /* "changed" devices are bad */ 83int isp_change_is_bad = 0; /* "changed" devices are bad */
84int isp_quickboot_time = 15; /* don't wait more than N secs for loop up */ 84int isp_quickboot_time = 15; /* don't wait more than N secs for loop up */
85static int isp_fabric_hysteresis = 5; 85static int isp_fabric_hysteresis = 5;
86#define isp_change_is_bad 0 86#define isp_change_is_bad 0
87 87
88/* 88/*
89 * Complete attachment of hardware, include subdevices. 89 * Complete attachment of hardware, include subdevices.
90 */ 90 */
91 91
92void 92void
93isp_attach(struct ispsoftc *isp) 93isp_attach(struct ispsoftc *isp)
94{ 94{
95 device_t self = isp->isp_osinfo.dev; 95 device_t self = isp->isp_osinfo.dev;
96 int i; 96 int i;
97 97
98 isp->isp_state = ISP_RUNSTATE; 98 isp->isp_state = ISP_RUNSTATE;
99 99
100 isp->isp_osinfo.adapter.adapt_dev = self; 100 isp->isp_osinfo.adapter.adapt_dev = self;
101 isp->isp_osinfo.adapter.adapt_openings = isp->isp_maxcmds; 101 isp->isp_osinfo.adapter.adapt_openings = isp->isp_maxcmds;
102 isp->isp_osinfo.loop_down_limit = 300; 102 isp->isp_osinfo.loop_down_limit = 300;
103 103
104 /* 104 /*
105 * It's not stated whether max_periph is limited by SPI 105 * It's not stated whether max_periph is limited by SPI
106 * tag uage, but let's assume that it is. 106 * tag uage, but let's assume that it is.
107 */ 107 */
108 isp->isp_osinfo.adapter.adapt_max_periph = min(isp->isp_maxcmds, 255); 108 isp->isp_osinfo.adapter.adapt_max_periph = min(isp->isp_maxcmds, 255);
109 isp->isp_osinfo.adapter.adapt_ioctl = ispioctl; 109 isp->isp_osinfo.adapter.adapt_ioctl = ispioctl;
110 isp->isp_osinfo.adapter.adapt_request = isprequest; 110 isp->isp_osinfo.adapter.adapt_request = isprequest;
111 if (isp->isp_type <= ISP_HA_SCSI_1020A) { 111 if (isp->isp_type <= ISP_HA_SCSI_1020A) {
112 isp->isp_osinfo.adapter.adapt_minphys = ispminphys_1020; 112 isp->isp_osinfo.adapter.adapt_minphys = ispminphys_1020;
113 } else { 113 } else {
114 isp->isp_osinfo.adapter.adapt_minphys = ispminphys; 114 isp->isp_osinfo.adapter.adapt_minphys = ispminphys;
115 } 115 }
116 116
117 callout_init(&isp->isp_osinfo.gdt, 0); 117 callout_init(&isp->isp_osinfo.gdt, 0);
118 callout_setfunc(&isp->isp_osinfo.gdt, isp_gdt, isp); 118 callout_setfunc(&isp->isp_osinfo.gdt, isp_gdt, isp);
119 callout_init(&isp->isp_osinfo.ldt, 0); 119 callout_init(&isp->isp_osinfo.ldt, 0);
120 callout_setfunc(&isp->isp_osinfo.ldt, isp_ldt, isp); 120 callout_setfunc(&isp->isp_osinfo.ldt, isp_ldt, isp);
121 if (IS_FC(isp)) { 121 if (IS_FC(isp)) {
122 if (kthread_create(PRI_NONE, 0, NULL, isp_fc_worker, isp, 122 if (kthread_create(PRI_NONE, 0, NULL, isp_fc_worker, isp,
123 &isp->isp_osinfo.thread, "%s:fc_thrd", 123 &isp->isp_osinfo.thread, "%s:fc_thrd",
124 device_xname(self))) { 124 device_xname(self))) {
125 isp_prt(isp, ISP_LOGERR, 125 isp_prt(isp, ISP_LOGERR,
126 "unable to create FC worker thread"); 126 "unable to create FC worker thread");
127 return; 127 return;
128 } 128 }
129 } 129 }
130 130
131 for (i = 0; i != isp->isp_osinfo.adapter.adapt_nchannels; i++) { 131 for (i = 0; i != isp->isp_osinfo.adapter.adapt_nchannels; i++) {
132 isp->isp_osinfo.chan[i].chan_adapter = 132 isp->isp_osinfo.chan[i].chan_adapter =
133 &isp->isp_osinfo.adapter; 133 &isp->isp_osinfo.adapter;
134 isp->isp_osinfo.chan[i].chan_bustype = &scsi_bustype; 134 isp->isp_osinfo.chan[i].chan_bustype = &scsi_bustype;
135 isp->isp_osinfo.chan[i].chan_channel = i; 135 isp->isp_osinfo.chan[i].chan_channel = i;
136 /* 136 /*
137 * Until the midlayer is fixed to use REPORT LUNS, 137 * Until the midlayer is fixed to use REPORT LUNS,
138 * limit to 8 luns. 138 * limit to 8 luns.
139 */ 139 */
140 isp->isp_osinfo.chan[i].chan_nluns = min(isp->isp_maxluns, 8); 140 isp->isp_osinfo.chan[i].chan_nluns = min(isp->isp_maxluns, 8);
141 if (IS_FC(isp)) { 141 if (IS_FC(isp)) {
142 isp->isp_osinfo.chan[i].chan_ntargets = MAX_FC_TARG; 142 isp->isp_osinfo.chan[i].chan_ntargets = MAX_FC_TARG;
143 if (ISP_CAP_2KLOGIN(isp) == 0 && MAX_FC_TARG > 256) { 143 if (ISP_CAP_2KLOGIN(isp) == 0 && MAX_FC_TARG > 256) {
144 isp->isp_osinfo.chan[i].chan_ntargets = 256; 144 isp->isp_osinfo.chan[i].chan_ntargets = 256;
145 } 145 }
146 isp->isp_osinfo.chan[i].chan_id = MAX_FC_TARG; 146 isp->isp_osinfo.chan[i].chan_id = MAX_FC_TARG;
147 } else { 147 } else {
148 isp->isp_osinfo.chan[i].chan_ntargets = MAX_TARGETS; 148 isp->isp_osinfo.chan[i].chan_ntargets = MAX_TARGETS;
149 isp->isp_osinfo.chan[i].chan_id = 149 isp->isp_osinfo.chan[i].chan_id =
150 SDPARAM(isp, i)->isp_initiator_id; 150 SDPARAM(isp, i)->isp_initiator_id;
151 ISP_LOCK(isp); 151 ISP_LOCK(isp);
152 (void) isp_control(isp, ISPCTL_RESET_BUS, i); 152 (void) isp_control(isp, ISPCTL_RESET_BUS, i);
153 ISP_UNLOCK(isp); 153 ISP_UNLOCK(isp);
154 } 154 }
155 } 155 }
156 156
157 /* 157 /*
158 * Defer enabling mailbox interrupts until later. 158 * Defer enabling mailbox interrupts until later.
159 */ 159 */
160 config_interrupts(self, isp_config_interrupts); 160 config_interrupts(self, isp_config_interrupts);
161} 161}
162 162
163static void 163static void
164isp_config_interrupts(device_t self) 164isp_config_interrupts(device_t self)
165{ 165{
166 int i; 166 int i;
167 struct ispsoftc *isp = device_private(self); 167 struct ispsoftc *isp = device_private(self);
168 168
169 isp->isp_osinfo.mbox_sleep_ok = 1; 169 isp->isp_osinfo.mbox_sleep_ok = 1;
170 170
171 if (IS_FC(isp) && (FCPARAM(isp, 0)->isp_fwstate != FW_READY || 171 if (IS_FC(isp) && (FCPARAM(isp, 0)->isp_fwstate != FW_READY ||
172 FCPARAM(isp, 0)->isp_loopstate != LOOP_READY)) { 172 FCPARAM(isp, 0)->isp_loopstate != LOOP_READY)) {
173 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 173 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
174 "Starting Initial Loop Down Timer"); 174 "Starting Initial Loop Down Timer");
175 callout_schedule(&isp->isp_osinfo.ldt, isp_quickboot_time * hz); 175 callout_schedule(&isp->isp_osinfo.ldt, isp_quickboot_time * hz);
176 } 176 }
177 177
178 /* 178 /*
179 * And attach children (if any). 179 * And attach children (if any).
180 */ 180 */
181 for (i = 0; i < isp->isp_osinfo.adapter.adapt_nchannels; i++) { 181 for (i = 0; i < isp->isp_osinfo.adapter.adapt_nchannels; i++) {
182 config_found(self, &isp->isp_osinfo.chan[i], scsiprint); 182 config_found(self, &isp->isp_osinfo.chan[i], scsiprint);
183 } 183 }
184} 184}
185 185
186/* 186/*
187 * minphys our xfers 187 * minphys our xfers
188 */ 188 */
189static void 189static void
190ispminphys_1020(struct buf *bp) 190ispminphys_1020(struct buf *bp)
191{ 191{
192 if (bp->b_bcount >= (1 << 24)) { 192 if (bp->b_bcount >= (1 << 24)) {
193 bp->b_bcount = (1 << 24); 193 bp->b_bcount = (1 << 24);
194 } 194 }
195 minphys(bp); 195 minphys(bp);
196} 196}
197 197
198static void 198static void
199ispminphys(struct buf *bp) 199ispminphys(struct buf *bp)
200{ 200{
201 if (bp->b_bcount >= (1 << 30)) { 201 if (bp->b_bcount >= (1 << 30)) {
202 bp->b_bcount = (1 << 30); 202 bp->b_bcount = (1 << 30);
203 } 203 }
204 minphys(bp); 204 minphys(bp);
205} 205}
206 206
207static int 207static int
208ispioctl(struct scsipi_channel *chan, u_long cmd, void *addr, int flag, 208ispioctl(struct scsipi_channel *chan, u_long cmd, void *addr, int flag,
209 struct proc *p) 209 struct proc *p)
210{ 210{
211 struct ispsoftc *isp = device_private(chan->chan_adapter->adapt_dev); 211 struct ispsoftc *isp = device_private(chan->chan_adapter->adapt_dev);
212 int nr, bus, retval = ENOTTY; 212 int nr, bus, retval = ENOTTY;
213 213
214 switch (cmd) { 214 switch (cmd) {
215 case ISP_SDBLEV: 215 case ISP_SDBLEV:
216 { 216 {
217 int olddblev = isp->isp_dblev; 217 int olddblev = isp->isp_dblev;
218 isp->isp_dblev = *(int *)addr; 218 isp->isp_dblev = *(int *)addr;
219 *(int *)addr = olddblev; 219 *(int *)addr = olddblev;
220 retval = 0; 220 retval = 0;
221 break; 221 break;
222 } 222 }
223 case ISP_GETROLE: 223 case ISP_GETROLE:
224 bus = *(int *)addr; 224 bus = *(int *)addr;
225 if (bus < 0 || bus >= isp->isp_nchan) { 225 if (bus < 0 || bus >= isp->isp_nchan) {
226 retval = -ENXIO; 226 retval = -ENXIO;
227 break; 227 break;
228 } 228 }
229 if (IS_FC(isp)) { 229 if (IS_FC(isp)) {
230 *(int *)addr = FCPARAM(isp, bus)->role; 230 *(int *)addr = FCPARAM(isp, bus)->role;
231 } else { 231 } else {
232 *(int *)addr = SDPARAM(isp, bus)->role; 232 *(int *)addr = SDPARAM(isp, bus)->role;
233 } 233 }
234 retval = 0; 234 retval = 0;
235 break; 235 break;
236 case ISP_SETROLE: 236 case ISP_SETROLE:
237 237
238 nr = *(int *)addr; 238 nr = *(int *)addr;
239 bus = nr >> 8; 239 bus = nr >> 8;
240 if (bus < 0 || bus >= isp->isp_nchan) { 240 if (bus < 0 || bus >= isp->isp_nchan) {
241 retval = -ENXIO; 241 retval = -ENXIO;
242 break; 242 break;
243 } 243 }
244 nr &= 0xff; 244 nr &= 0xff;
245 if (nr & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) { 245 if (nr & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) {
246 retval = EINVAL; 246 retval = EINVAL;
247 break; 247 break;
248 } 248 }
249 if (IS_FC(isp)) { 249 if (IS_FC(isp)) {
250 *(int *)addr = FCPARAM(isp, bus)->role; 250 *(int *)addr = FCPARAM(isp, bus)->role;
251 FCPARAM(isp, bus)->role = nr; 251 FCPARAM(isp, bus)->role = nr;
252 } else { 252 } else {
253 *(int *)addr = SDPARAM(isp, bus)->role; 253 *(int *)addr = SDPARAM(isp, bus)->role;
254 SDPARAM(isp, bus)->role = nr; 254 SDPARAM(isp, bus)->role = nr;
255 } 255 }
256 retval = 0; 256 retval = 0;
257 break; 257 break;
258 258
259 case ISP_RESETHBA: 259 case ISP_RESETHBA:
260 ISP_LOCK(isp); 260 ISP_LOCK(isp);
261 isp_reinit(isp, 0); 261 isp_reinit(isp, 0);
262 ISP_UNLOCK(isp); 262 ISP_UNLOCK(isp);
263 retval = 0; 263 retval = 0;
264 break; 264 break;
265 265
266 case ISP_RESCAN: 266 case ISP_RESCAN:
267 if (IS_FC(isp)) { 267 if (IS_FC(isp)) {
268 bus = *(int *)addr; 268 bus = *(int *)addr;
269 if (bus < 0 || bus >= isp->isp_nchan) { 269 if (bus < 0 || bus >= isp->isp_nchan) {
270 retval = -ENXIO; 270 retval = -ENXIO;
271 break; 271 break;
272 } 272 }
273 ISP_LOCK(isp); 273 ISP_LOCK(isp);
274 if (isp_fc_runstate(isp, bus, 5 * 1000000)) { 274 if (isp_fc_runstate(isp, bus, 5 * 1000000)) {
275 retval = EIO; 275 retval = EIO;
276 } else { 276 } else {
277 retval = 0; 277 retval = 0;
278 } 278 }
279 ISP_UNLOCK(isp); 279 ISP_UNLOCK(isp);
280 } 280 }
281 break; 281 break;
282 282
283 case ISP_FC_LIP: 283 case ISP_FC_LIP:
284 if (IS_FC(isp)) { 284 if (IS_FC(isp)) {
285 bus = *(int *)addr; 285 bus = *(int *)addr;
286 if (bus < 0 || bus >= isp->isp_nchan) { 286 if (bus < 0 || bus >= isp->isp_nchan) {
287 retval = -ENXIO; 287 retval = -ENXIO;
288 break; 288 break;
289 } 289 }
290 ISP_LOCK(isp); 290 ISP_LOCK(isp);
291 if (isp_control(isp, ISPCTL_SEND_LIP, bus)) { 291 if (isp_control(isp, ISPCTL_SEND_LIP, bus)) {
292 retval = EIO; 292 retval = EIO;
293 } else { 293 } else {
294 retval = 0; 294 retval = 0;
295 } 295 }
296 ISP_UNLOCK(isp); 296 ISP_UNLOCK(isp);
297 } 297 }
298 break; 298 break;
299 case ISP_FC_GETDINFO: 299 case ISP_FC_GETDINFO:
300 { 300 {
301 struct isp_fc_device *ifc = (struct isp_fc_device *) addr; 301 struct isp_fc_device *ifc = (struct isp_fc_device *) addr;
302 fcportdb_t *lp; 302 fcportdb_t *lp;
303 303
304 if (IS_SCSI(isp)) { 304 if (IS_SCSI(isp)) {
305 break; 305 break;
306 } 306 }
307 if (ifc->loopid >= MAX_FC_TARG) { 307 if (ifc->loopid >= MAX_FC_TARG) {
308 retval = EINVAL; 308 retval = EINVAL;
309 break; 309 break;
310 } 310 }
311 lp = &FCPARAM(isp, ifc->chan)->portdb[ifc->loopid]; 311 lp = &FCPARAM(isp, ifc->chan)->portdb[ifc->loopid];
312 if (lp->state == FC_PORTDB_STATE_VALID) { 312 if (lp->state == FC_PORTDB_STATE_VALID) {
313 ifc->role = lp->roles; 313 ifc->role = lp->roles;
314 ifc->loopid = lp->handle; 314 ifc->loopid = lp->handle;
315 ifc->portid = lp->portid; 315 ifc->portid = lp->portid;
316 ifc->node_wwn = lp->node_wwn; 316 ifc->node_wwn = lp->node_wwn;
317 ifc->port_wwn = lp->port_wwn; 317 ifc->port_wwn = lp->port_wwn;
318 retval = 0; 318 retval = 0;
319 } else { 319 } else {
320 retval = ENODEV; 320 retval = ENODEV;
321 } 321 }
322 break; 322 break;
323 } 323 }
324 case ISP_GET_STATS: 324 case ISP_GET_STATS:
325 { 325 {
326 isp_stats_t *sp = (isp_stats_t *) addr; 326 isp_stats_t *sp = (isp_stats_t *) addr;
327 327
328 ISP_MEMZERO(sp, sizeof (*sp)); 328 ISP_MEMZERO(sp, sizeof (*sp));
329 sp->isp_stat_version = ISP_STATS_VERSION; 329 sp->isp_stat_version = ISP_STATS_VERSION;
330 sp->isp_type = isp->isp_type; 330 sp->isp_type = isp->isp_type;
331 sp->isp_revision = isp->isp_revision; 331 sp->isp_revision = isp->isp_revision;
332 ISP_LOCK(isp); 332 ISP_LOCK(isp);
333 sp->isp_stats[ISP_INTCNT] = isp->isp_intcnt; 333 sp->isp_stats[ISP_INTCNT] = isp->isp_intcnt;
334 sp->isp_stats[ISP_INTBOGUS] = isp->isp_intbogus; 334 sp->isp_stats[ISP_INTBOGUS] = isp->isp_intbogus;
335 sp->isp_stats[ISP_INTMBOXC] = isp->isp_intmboxc; 335 sp->isp_stats[ISP_INTMBOXC] = isp->isp_intmboxc;
336 sp->isp_stats[ISP_INGOASYNC] = isp->isp_intoasync; 336 sp->isp_stats[ISP_INGOASYNC] = isp->isp_intoasync;
337 sp->isp_stats[ISP_RSLTCCMPLT] = isp->isp_rsltccmplt; 337 sp->isp_stats[ISP_RSLTCCMPLT] = isp->isp_rsltccmplt;
338 sp->isp_stats[ISP_FPHCCMCPLT] = isp->isp_fphccmplt; 338 sp->isp_stats[ISP_FPHCCMCPLT] = isp->isp_fphccmplt;
339 sp->isp_stats[ISP_RSCCHIWAT] = isp->isp_rscchiwater; 339 sp->isp_stats[ISP_RSCCHIWAT] = isp->isp_rscchiwater;
340 sp->isp_stats[ISP_FPCCHIWAT] = isp->isp_fpcchiwater; 340 sp->isp_stats[ISP_FPCCHIWAT] = isp->isp_fpcchiwater;
341 ISP_UNLOCK(isp); 341 ISP_UNLOCK(isp);
342 retval = 0; 342 retval = 0;
343 break; 343 break;
344 } 344 }
345 case ISP_CLR_STATS: 345 case ISP_CLR_STATS:
346 ISP_LOCK(isp); 346 ISP_LOCK(isp);
347 isp->isp_intcnt = 0; 347 isp->isp_intcnt = 0;
348 isp->isp_intbogus = 0; 348 isp->isp_intbogus = 0;
349 isp->isp_intmboxc = 0; 349 isp->isp_intmboxc = 0;
350 isp->isp_intoasync = 0; 350 isp->isp_intoasync = 0;
351 isp->isp_rsltccmplt = 0; 351 isp->isp_rsltccmplt = 0;
352 isp->isp_fphccmplt = 0; 352 isp->isp_fphccmplt = 0;
353 isp->isp_rscchiwater = 0; 353 isp->isp_rscchiwater = 0;
354 isp->isp_fpcchiwater = 0; 354 isp->isp_fpcchiwater = 0;
355 ISP_UNLOCK(isp); 355 ISP_UNLOCK(isp);
356 retval = 0; 356 retval = 0;
357 break; 357 break;
358 case ISP_FC_GETHINFO: 358 case ISP_FC_GETHINFO:
359 { 359 {
360 struct isp_hba_device *hba = (struct isp_hba_device *) addr; 360 struct isp_hba_device *hba = (struct isp_hba_device *) addr;
361 bus = hba->fc_channel; 361 bus = hba->fc_channel;
362 362
363 if (bus < 0 || bus >= isp->isp_nchan) { 363 if (bus < 0 || bus >= isp->isp_nchan) {
364 retval = ENXIO; 364 retval = ENXIO;
365 break; 365 break;
366 } 366 }
367 hba->fc_fw_major = ISP_FW_MAJORX(isp->isp_fwrev); 367 hba->fc_fw_major = ISP_FW_MAJORX(isp->isp_fwrev);
368 hba->fc_fw_minor = ISP_FW_MINORX(isp->isp_fwrev); 368 hba->fc_fw_minor = ISP_FW_MINORX(isp->isp_fwrev);
369 hba->fc_fw_micro = ISP_FW_MICROX(isp->isp_fwrev); 369 hba->fc_fw_micro = ISP_FW_MICROX(isp->isp_fwrev);
370 hba->fc_nchannels = isp->isp_nchan; 370 hba->fc_nchannels = isp->isp_nchan;
371 hba->fc_nports = isp->isp_nchan;/* XXXX 24XX STUFF? XXX */ 371 hba->fc_nports = isp->isp_nchan;/* XXXX 24XX STUFF? XXX */
372 if (IS_FC(isp)) { 372 if (IS_FC(isp)) {
373 hba->fc_speed = FCPARAM(isp, bus)->isp_gbspeed; 373 hba->fc_speed = FCPARAM(isp, bus)->isp_gbspeed;
374 hba->fc_topology = FCPARAM(isp, bus)->isp_topo + 1; 374 hba->fc_topology = FCPARAM(isp, bus)->isp_topo + 1;
375 hba->fc_loopid = FCPARAM(isp, bus)->isp_loopid; 375 hba->fc_loopid = FCPARAM(isp, bus)->isp_loopid;
376 hba->nvram_node_wwn = FCPARAM(isp, bus)->isp_wwnn_nvram; 376 hba->nvram_node_wwn = FCPARAM(isp, bus)->isp_wwnn_nvram;
377 hba->nvram_port_wwn = FCPARAM(isp, bus)->isp_wwpn_nvram; 377 hba->nvram_port_wwn = FCPARAM(isp, bus)->isp_wwpn_nvram;
378 hba->active_node_wwn = FCPARAM(isp, bus)->isp_wwnn; 378 hba->active_node_wwn = FCPARAM(isp, bus)->isp_wwnn;
379 hba->active_port_wwn = FCPARAM(isp, bus)->isp_wwpn; 379 hba->active_port_wwn = FCPARAM(isp, bus)->isp_wwpn;
380 } else { 380 } else {
381 hba->fc_speed = 0; 381 hba->fc_speed = 0;
382 hba->fc_topology = 0; 382 hba->fc_topology = 0;
383 hba->nvram_node_wwn = 0ull; 383 hba->nvram_node_wwn = 0ull;
384 hba->nvram_port_wwn = 0ull; 384 hba->nvram_port_wwn = 0ull;
385 hba->active_node_wwn = 0ull; 385 hba->active_node_wwn = 0ull;
386 hba->active_port_wwn = 0ull; 386 hba->active_port_wwn = 0ull;
387 } 387 }
388 retval = 0; 388 retval = 0;
389 break; 389 break;
390 } 390 }
391 case ISP_TSK_MGMT: 391 case ISP_TSK_MGMT:
392 { 392 {
393 int needmarker; 393 int needmarker;
394 struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr; 394 struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr;
395 uint16_t loopid; 395 uint16_t loopid;
396 mbreg_t mbs; 396 mbreg_t mbs;
397 397
398 if (IS_SCSI(isp)) { 398 if (IS_SCSI(isp)) {
399 break; 399 break;
400 } 400 }
401 401
402 bus = fct->chan; 402 bus = fct->chan;
403 if (bus < 0 || bus >= isp->isp_nchan) { 403 if (bus < 0 || bus >= isp->isp_nchan) {
404 retval = -ENXIO; 404 retval = -ENXIO;
405 break; 405 break;
406 } 406 }
407 407
408 memset(&mbs, 0, sizeof (mbs)); 408 memset(&mbs, 0, sizeof (mbs));
409 needmarker = retval = 0; 409 needmarker = retval = 0;
410 loopid = fct->loopid; 410 loopid = fct->loopid;
411 if (ISP_CAP_2KLOGIN(isp) == 0) { 411 if (ISP_CAP_2KLOGIN(isp) == 0) {
412 loopid <<= 8; 412 loopid <<= 8;
413 } 413 }
414 switch (fct->action) { 414 switch (fct->action) {
415 case IPT_CLEAR_ACA: 415 case IPT_CLEAR_ACA:
416 mbs.param[0] = MBOX_CLEAR_ACA; 416 mbs.param[0] = MBOX_CLEAR_ACA;
417 mbs.param[1] = loopid; 417 mbs.param[1] = loopid;
418 mbs.param[2] = fct->lun; 418 mbs.param[2] = fct->lun;
419 break; 419 break;
420 case IPT_TARGET_RESET: 420 case IPT_TARGET_RESET:
421 mbs.param[0] = MBOX_TARGET_RESET; 421 mbs.param[0] = MBOX_TARGET_RESET;
422 mbs.param[1] = loopid; 422 mbs.param[1] = loopid;
423 needmarker = 1; 423 needmarker = 1;
424 break; 424 break;
425 case IPT_LUN_RESET: 425 case IPT_LUN_RESET:
426 mbs.param[0] = MBOX_LUN_RESET; 426 mbs.param[0] = MBOX_LUN_RESET;
427 mbs.param[1] = loopid; 427 mbs.param[1] = loopid;
428 mbs.param[2] = fct->lun; 428 mbs.param[2] = fct->lun;
429 needmarker = 1; 429 needmarker = 1;
430 break; 430 break;
431 case IPT_CLEAR_TASK_SET: 431 case IPT_CLEAR_TASK_SET:
432 mbs.param[0] = MBOX_CLEAR_TASK_SET; 432 mbs.param[0] = MBOX_CLEAR_TASK_SET;
433 mbs.param[1] = loopid; 433 mbs.param[1] = loopid;
434 mbs.param[2] = fct->lun; 434 mbs.param[2] = fct->lun;
435 needmarker = 1; 435 needmarker = 1;
436 break; 436 break;
437 case IPT_ABORT_TASK_SET: 437 case IPT_ABORT_TASK_SET:
438 mbs.param[0] = MBOX_ABORT_TASK_SET; 438 mbs.param[0] = MBOX_ABORT_TASK_SET;
439 mbs.param[1] = loopid; 439 mbs.param[1] = loopid;
440 mbs.param[2] = fct->lun; 440 mbs.param[2] = fct->lun;
441 needmarker = 1; 441 needmarker = 1;
442 break; 442 break;
443 default: 443 default:
444 retval = EINVAL; 444 retval = EINVAL;
445 break; 445 break;
446 } 446 }
447 if (retval == 0) { 447 if (retval == 0) {
448 if (needmarker) { 448 if (needmarker) {
449 FCPARAM(isp, bus)->sendmarker = 1; 449 FCPARAM(isp, bus)->sendmarker = 1;
450 } 450 }
451 ISP_LOCK(isp); 451 ISP_LOCK(isp);
452 retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs); 452 retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
453 ISP_UNLOCK(isp); 453 ISP_UNLOCK(isp);
454 if (retval) { 454 if (retval) {
455 retval = EIO; 455 retval = EIO;
456 } 456 }
457 } 457 }
458 break; 458 break;
459 } 459 }
460 case ISP_FC_GETDLIST: 460 case ISP_FC_GETDLIST:
461 { 461 {
462 isp_dlist_t local, *ua; 462 isp_dlist_t local, *ua;
463 uint16_t nph, nphe, count, channel, lim; 463 uint16_t nph, nphe, count, channel, lim;
464 struct wwnpair pair, *uptr; 464 struct wwnpair pair, *uptr;
465 465
466 if (IS_SCSI(isp)) { 466 if (IS_SCSI(isp)) {
467 retval = EINVAL; 467 retval = EINVAL;
468 break; 468 break;
469 } 469 }
470 470
471 ua = *(isp_dlist_t **)addr; 471 ua = *(isp_dlist_t **)addr;
472 if (copyin(ua, &local, sizeof (isp_dlist_t))) { 472 if (copyin(ua, &local, sizeof (isp_dlist_t))) {
473 retval = EFAULT; 473 retval = EFAULT;
474 break; 474 break;
475 } 475 }
476 lim = local.count; 476 lim = local.count;
477 channel = local.channel; 477 channel = local.channel;
 478 if (channel >= isp->isp_nchan) {
 479 retval = EINVAL;
 480 break;
 481 }
478 482
479 ua = *(isp_dlist_t **)addr; 483 ua = *(isp_dlist_t **)addr;
480 uptr = &ua->wwns[0]; 484 uptr = &ua->wwns[0];
481 485
482 if (ISP_CAP_2KLOGIN(isp)) { 486 if (ISP_CAP_2KLOGIN(isp)) {
483 nphe = NPH_MAX_2K; 487 nphe = NPH_MAX_2K;
484 } else { 488 } else {
485 nphe = NPH_MAX; 489 nphe = NPH_MAX;
486 } 490 }
487 for (count = 0, nph = 0; count < lim && nph != nphe; nph++) { 491 for (count = 0, nph = 0; count < lim && nph != nphe; nph++) {
488 ISP_LOCK(isp); 492 ISP_LOCK(isp);
489 retval = isp_control(isp, ISPCTL_GET_NAMES, channel, 493 retval = isp_control(isp, ISPCTL_GET_NAMES, channel,
490 nph, &pair.wwnn, &pair.wwpn); 494 nph, &pair.wwnn, &pair.wwpn);
491 ISP_UNLOCK(isp); 495 ISP_UNLOCK(isp);
492 if (retval || (pair.wwpn == INI_NONE && 496 if (retval || (pair.wwpn == INI_NONE &&
493 pair.wwnn == INI_NONE)) { 497 pair.wwnn == INI_NONE)) {
494 retval = 0; 498 retval = 0;
495 continue; 499 continue;
496 } 500 }
497 if (copyout(&pair, (void *)uptr++, sizeof (pair))) { 501 if (copyout(&pair, (void *)uptr++, sizeof (pair))) {
498 retval = EFAULT; 502 retval = EFAULT;
499 break; 503 break;
500 } 504 }
501 count++; 505 count++;
502 } 506 }
503 if (retval == 0) { 507 if (retval == 0) {
504 if (copyout(&count, (void *)&ua->count, 508 if (copyout(&count, (void *)&ua->count,
505 sizeof (count))) { 509 sizeof (count))) {
506 retval = EFAULT; 510 retval = EFAULT;
507 } 511 }
508 } 512 }
509 break; 513 break;
510 } 514 }
511 case SCBUSIORESET: 515 case SCBUSIORESET:
512 ISP_LOCK(isp); 516 ISP_LOCK(isp);
513 if (isp_control(isp, ISPCTL_RESET_BUS, &chan->chan_channel)) { 517 if (isp_control(isp, ISPCTL_RESET_BUS, &chan->chan_channel)) {
514 retval = EIO; 518 retval = EIO;
515 } else { 519 } else {
516 retval = 0; 520 retval = 0;
517 } 521 }
518 ISP_UNLOCK(isp); 522 ISP_UNLOCK(isp);
519 break; 523 break;
520 default: 524 default:
521 break; 525 break;
522 } 526 }
523 return (retval); 527 return (retval);
524} 528}
525 529
526static void 530static void
527ispcmd(struct ispsoftc *isp, XS_T *xs) 531ispcmd(struct ispsoftc *isp, XS_T *xs)
528{ 532{
529 volatile uint8_t ombi; 533 volatile uint8_t ombi;
530 int lim, chan; 534 int lim, chan;
531 535
532 ISP_LOCK(isp); 536 ISP_LOCK(isp);
533 if (isp->isp_state < ISP_RUNSTATE) { 537 if (isp->isp_state < ISP_RUNSTATE) {
534 ISP_DISABLE_INTS(isp); 538 ISP_DISABLE_INTS(isp);
535 isp_init(isp); 539 isp_init(isp);
536 if (isp->isp_state != ISP_INITSTATE) { 540 if (isp->isp_state != ISP_INITSTATE) {
537 ISP_ENABLE_INTS(isp); 541 ISP_ENABLE_INTS(isp);
538 ISP_UNLOCK(isp); 542 ISP_UNLOCK(isp);
539 isp_prt(isp, ISP_LOGERR, "isp not at init state"); 543 isp_prt(isp, ISP_LOGERR, "isp not at init state");
540 XS_SETERR(xs, HBA_BOTCH); 544 XS_SETERR(xs, HBA_BOTCH);
541 scsipi_done(xs); 545 scsipi_done(xs);
542 return; 546 return;
543 } 547 }
544 isp->isp_state = ISP_RUNSTATE; 548 isp->isp_state = ISP_RUNSTATE;
545 ISP_ENABLE_INTS(isp); 549 ISP_ENABLE_INTS(isp);
546 } 550 }
547 chan = XS_CHANNEL(xs); 551 chan = XS_CHANNEL(xs);
548 552
549 /* 553 /*
550 * Handle the case of a FC card where the FC thread hasn't 554 * Handle the case of a FC card where the FC thread hasn't
551 * fired up yet and we don't yet have a known loop state. 555 * fired up yet and we don't yet have a known loop state.
552 */ 556 */
553 if (IS_FC(isp) && (FCPARAM(isp, chan)->isp_fwstate != FW_READY || 557 if (IS_FC(isp) && (FCPARAM(isp, chan)->isp_fwstate != FW_READY ||
554 FCPARAM(isp, chan)->isp_loopstate != LOOP_READY) && 558 FCPARAM(isp, chan)->isp_loopstate != LOOP_READY) &&
555 isp->isp_osinfo.thread == NULL) { 559 isp->isp_osinfo.thread == NULL) {
556 ombi = isp->isp_osinfo.mbox_sleep_ok != 0; 560 ombi = isp->isp_osinfo.mbox_sleep_ok != 0;
557 int delay_time; 561 int delay_time;
558 562
559 if (xs->xs_control & XS_CTL_POLL) { 563 if (xs->xs_control & XS_CTL_POLL) {
560 isp->isp_osinfo.mbox_sleep_ok = 0; 564 isp->isp_osinfo.mbox_sleep_ok = 0;
561 } 565 }
562 566
563 if (isp->isp_osinfo.loop_checked == 0) { 567 if (isp->isp_osinfo.loop_checked == 0) {
564 delay_time = 10 * 1000000; 568 delay_time = 10 * 1000000;
565 isp->isp_osinfo.loop_checked = 1; 569 isp->isp_osinfo.loop_checked = 1;
566 } else { 570 } else {
567 delay_time = 250000; 571 delay_time = 250000;
568 } 572 }
569 573
570 if (isp_fc_runstate(isp, XS_CHANNEL(xs), delay_time) != 0) { 574 if (isp_fc_runstate(isp, XS_CHANNEL(xs), delay_time) != 0) {
571 if (xs->xs_control & XS_CTL_POLL) { 575 if (xs->xs_control & XS_CTL_POLL) {
572 isp->isp_osinfo.mbox_sleep_ok = ombi; 576 isp->isp_osinfo.mbox_sleep_ok = ombi;
573 } 577 }
574 if (FCPARAM(isp, XS_CHANNEL(xs))->loop_seen_once == 0) { 578 if (FCPARAM(isp, XS_CHANNEL(xs))->loop_seen_once == 0) {
575 XS_SETERR(xs, HBA_SELTIMEOUT); 579 XS_SETERR(xs, HBA_SELTIMEOUT);
576 scsipi_done(xs); 580 scsipi_done(xs);
577 ISP_UNLOCK(isp); 581 ISP_UNLOCK(isp);
578 return; 582 return;
579 } 583 }
580 /* 584 /*
581 * Otherwise, fall thru to be queued up for later. 585 * Otherwise, fall thru to be queued up for later.
582 */ 586 */
583 } else { 587 } else {
584 int wasblocked = 588 int wasblocked =
585 (isp->isp_osinfo.blocked || isp->isp_osinfo.paused); 589 (isp->isp_osinfo.blocked || isp->isp_osinfo.paused);
586 isp->isp_osinfo.blocked = isp->isp_osinfo.paused = 0; 590 isp->isp_osinfo.blocked = isp->isp_osinfo.paused = 0;
587 if (wasblocked) { 591 if (wasblocked) {
588 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 592 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
589 "THAW QUEUES @ LINE %d", __LINE__); 593 "THAW QUEUES @ LINE %d", __LINE__);
590 scsipi_channel_thaw(&isp->isp_osinfo.chan[chan], 594 scsipi_channel_thaw(&isp->isp_osinfo.chan[chan],
591 1); 595 1);
592 } 596 }
593 } 597 }
594 if (xs->xs_control & XS_CTL_POLL) { 598 if (xs->xs_control & XS_CTL_POLL) {
595 isp->isp_osinfo.mbox_sleep_ok = ombi; 599 isp->isp_osinfo.mbox_sleep_ok = ombi;
596 } 600 }
597 } 601 }
598 602
599 if (isp->isp_osinfo.paused) { 603 if (isp->isp_osinfo.paused) {
600 isp_prt(isp, ISP_LOGWARN, "I/O while paused"); 604 isp_prt(isp, ISP_LOGWARN, "I/O while paused");
601 xs->error = XS_RESOURCE_SHORTAGE; 605 xs->error = XS_RESOURCE_SHORTAGE;
602 scsipi_done(xs); 606 scsipi_done(xs);
603 ISP_UNLOCK(isp); 607 ISP_UNLOCK(isp);
604 return; 608 return;
605 } 609 }
606 if (isp->isp_osinfo.blocked) { 610 if (isp->isp_osinfo.blocked) {
607 isp_prt(isp, ISP_LOGWARN, 611 isp_prt(isp, ISP_LOGWARN,
608 "I/O while blocked with retries %d", xs, xs->xs_retries); 612 "I/O while blocked with retries %d", xs, xs->xs_retries);
609 if (xs->xs_retries) { 613 if (xs->xs_retries) {
610 xs->error = XS_REQUEUE; 614 xs->error = XS_REQUEUE;
611 xs->xs_retries--; 615 xs->xs_retries--;
612 } else { 616 } else {
613 XS_SETERR(xs, HBA_SELTIMEOUT); 617 XS_SETERR(xs, HBA_SELTIMEOUT);
614 } 618 }
615 scsipi_done(xs); 619 scsipi_done(xs);
616 ISP_UNLOCK(isp); 620 ISP_UNLOCK(isp);
617 return; 621 return;
618 } 622 }
619 623
620 if (xs->xs_control & XS_CTL_POLL) { 624 if (xs->xs_control & XS_CTL_POLL) {
621 ombi = isp->isp_osinfo.mbox_sleep_ok; 625 ombi = isp->isp_osinfo.mbox_sleep_ok;
622 isp->isp_osinfo.mbox_sleep_ok = 0; 626 isp->isp_osinfo.mbox_sleep_ok = 0;
623 } 627 }
624 628
625 switch (isp_start(xs)) { 629 switch (isp_start(xs)) {
626 case CMD_QUEUED: 630 case CMD_QUEUED:
627 if (IS_FC(isp) && isp->isp_osinfo.wwns[XS_TGT(xs)] == 0) { 631 if (IS_FC(isp) && isp->isp_osinfo.wwns[XS_TGT(xs)] == 0) {
628 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs)); 632 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
629 int dbidx = fcp->isp_dev_map[XS_TGT(xs)] - 1; 633 int dbidx = fcp->isp_dev_map[XS_TGT(xs)] - 1;
630 device_t dev = xs->xs_periph->periph_dev; 634 device_t dev = xs->xs_periph->periph_dev;
631  635
632 if (dbidx >= 0 && dev && 636 if (dbidx >= 0 && dev &&
633 prop_dictionary_set_uint64(device_properties(dev), 637 prop_dictionary_set_uint64(device_properties(dev),
634 "port-wwn", fcp->portdb[dbidx].port_wwn) == TRUE) { 638 "port-wwn", fcp->portdb[dbidx].port_wwn) == TRUE) {
635 isp->isp_osinfo.wwns[XS_TGT(xs)] = 639 isp->isp_osinfo.wwns[XS_TGT(xs)] =
636 fcp->portdb[dbidx].port_wwn; 640 fcp->portdb[dbidx].port_wwn;
637 } 641 }
638 } 642 }
639 if (xs->xs_control & XS_CTL_POLL) { 643 if (xs->xs_control & XS_CTL_POLL) {
640 isp_polled_cmd_wait(isp, xs); 644 isp_polled_cmd_wait(isp, xs);
641 isp->isp_osinfo.mbox_sleep_ok = ombi; 645 isp->isp_osinfo.mbox_sleep_ok = ombi;
642 } else if (xs->timeout) { 646 } else if (xs->timeout) {
643 callout_reset(&xs->xs_callout, _XT(xs), isp_dog, xs); 647 callout_reset(&xs->xs_callout, _XT(xs), isp_dog, xs);
644 } 648 }
645 break; 649 break;
646 case CMD_EAGAIN: 650 case CMD_EAGAIN:
647 isp->isp_osinfo.paused = 1; 651 isp->isp_osinfo.paused = 1;
648 xs->error = XS_RESOURCE_SHORTAGE; 652 xs->error = XS_RESOURCE_SHORTAGE;
649 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 653 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
650 "FREEZE QUEUES @ LINE %d", __LINE__); 654 "FREEZE QUEUES @ LINE %d", __LINE__);
651 for (chan = 0; chan < isp->isp_nchan; chan++) { 655 for (chan = 0; chan < isp->isp_nchan; chan++) {
652 scsipi_channel_freeze(&isp->isp_osinfo.chan[chan], 1); 656 scsipi_channel_freeze(&isp->isp_osinfo.chan[chan], 1);
653 } 657 }
654 scsipi_done(xs); 658 scsipi_done(xs);
655 break; 659 break;
656 case CMD_RQLATER: 660 case CMD_RQLATER:
657 /* 661 /*
658 * We can only get RQLATER from FC devices (1 channel only) 662 * We can only get RQLATER from FC devices (1 channel only)
659 * 663 *
660 * If we've never seen loop up see if if we've been down 664 * If we've never seen loop up see if if we've been down
661 * quickboot time, otherwise wait loop down limit time. 665 * quickboot time, otherwise wait loop down limit time.
662 * If so, then we start giving up on commands. 666 * If so, then we start giving up on commands.
663 */ 667 */
664 if (FCPARAM(isp, XS_CHANNEL(xs))->loop_seen_once == 0) { 668 if (FCPARAM(isp, XS_CHANNEL(xs))->loop_seen_once == 0) {
665 lim = isp_quickboot_time; 669 lim = isp_quickboot_time;
666 } else { 670 } else {
667 lim = isp->isp_osinfo.loop_down_limit; 671 lim = isp->isp_osinfo.loop_down_limit;
668 } 672 }
669 if (isp->isp_osinfo.loop_down_time >= lim) { 673 if (isp->isp_osinfo.loop_down_time >= lim) {
670 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 674 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
671 "RQLATER->SELTIMEOUT for %d (%d >= %d)", XS_TGT(xs), 675 "RQLATER->SELTIMEOUT for %d (%d >= %d)", XS_TGT(xs),
672 isp->isp_osinfo.loop_down_time, lim); 676 isp->isp_osinfo.loop_down_time, lim);
673 XS_SETERR(xs, HBA_SELTIMEOUT); 677 XS_SETERR(xs, HBA_SELTIMEOUT);
674 scsipi_done(xs); 678 scsipi_done(xs);
675 break; 679 break;
676 } 680 }
677 if (isp->isp_osinfo.blocked == 0) { 681 if (isp->isp_osinfo.blocked == 0) {
678 isp->isp_osinfo.blocked = 1; 682 isp->isp_osinfo.blocked = 1;
679 scsipi_channel_freeze(&isp->isp_osinfo.chan[chan], 1); 683 scsipi_channel_freeze(&isp->isp_osinfo.chan[chan], 1);
680 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 684 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
681 "FREEZE QUEUES @ LINE %d", __LINE__); 685 "FREEZE QUEUES @ LINE %d", __LINE__);
682 } else { 686 } else {
683 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 687 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
684 "RQLATER WITH FROZEN QUEUES @ LINE %d", __LINE__); 688 "RQLATER WITH FROZEN QUEUES @ LINE %d", __LINE__);
685 } 689 }
686 xs->error = XS_REQUEUE; 690 xs->error = XS_REQUEUE;
687 scsipi_done(xs); 691 scsipi_done(xs);
688 break; 692 break;
689 case CMD_COMPLETE: 693 case CMD_COMPLETE:
690 scsipi_done(xs); 694 scsipi_done(xs);
691 break; 695 break;
692 } 696 }
693 ISP_UNLOCK(isp); 697 ISP_UNLOCK(isp);
694} 698}
695 699
696static void 700static void
697isprequest(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg) 701isprequest(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
698{ 702{
699 struct ispsoftc *isp = device_private(chan->chan_adapter->adapt_dev); 703 struct ispsoftc *isp = device_private(chan->chan_adapter->adapt_dev);
700 704
701 switch (req) { 705 switch (req) {
702 case ADAPTER_REQ_RUN_XFER: 706 case ADAPTER_REQ_RUN_XFER:
703 ispcmd(isp, (XS_T *) arg); 707 ispcmd(isp, (XS_T *) arg);
704 break; 708 break;
705 709
706 case ADAPTER_REQ_GROW_RESOURCES: 710 case ADAPTER_REQ_GROW_RESOURCES:
707 /* Not supported. */ 711 /* Not supported. */
708 break; 712 break;
709 713
710 case ADAPTER_REQ_SET_XFER_MODE: 714 case ADAPTER_REQ_SET_XFER_MODE:
711 if (IS_SCSI(isp)) { 715 if (IS_SCSI(isp)) {
712 struct scsipi_xfer_mode *xm = arg; 716 struct scsipi_xfer_mode *xm = arg;
713 int dflags = 0; 717 int dflags = 0;
714 sdparam *sdp = SDPARAM(isp, chan->chan_channel); 718 sdparam *sdp = SDPARAM(isp, chan->chan_channel);
715 719
716 if (xm->xm_mode & PERIPH_CAP_TQING) 720 if (xm->xm_mode & PERIPH_CAP_TQING)
717 dflags |= DPARM_TQING; 721 dflags |= DPARM_TQING;
718 if (xm->xm_mode & PERIPH_CAP_WIDE16) 722 if (xm->xm_mode & PERIPH_CAP_WIDE16)
719 dflags |= DPARM_WIDE; 723 dflags |= DPARM_WIDE;
720 if (xm->xm_mode & PERIPH_CAP_SYNC) 724 if (xm->xm_mode & PERIPH_CAP_SYNC)
721 dflags |= DPARM_SYNC; 725 dflags |= DPARM_SYNC;
722 ISP_LOCK(isp); 726 ISP_LOCK(isp);
723 sdp->isp_devparam[xm->xm_target].goal_flags |= dflags; 727 sdp->isp_devparam[xm->xm_target].goal_flags |= dflags;
724 dflags = sdp->isp_devparam[xm->xm_target].goal_flags; 728 dflags = sdp->isp_devparam[xm->xm_target].goal_flags;
725 sdp->isp_devparam[xm->xm_target].dev_update = 1; 729 sdp->isp_devparam[xm->xm_target].dev_update = 1;
726 sdp->update = 1; 730 sdp->update = 1;
727 ISP_UNLOCK(isp); 731 ISP_UNLOCK(isp);
728 isp_prt(isp, ISP_LOGDEBUG1, 732 isp_prt(isp, ISP_LOGDEBUG1,
729 "isprequest: device flags 0x%x for %d.%d.X", 733 "isprequest: device flags 0x%x for %d.%d.X",
730 dflags, chan->chan_channel, xm->xm_target); 734 dflags, chan->chan_channel, xm->xm_target);
731 break; 735 break;
732 } 736 }
733 default: 737 default:
734 break; 738 break;
735 } 739 }
736} 740}
737 741
738static void 742static void
739isp_polled_cmd_wait(struct ispsoftc *isp, XS_T *xs) 743isp_polled_cmd_wait(struct ispsoftc *isp, XS_T *xs)
740{ 744{
741 int infinite = 0, mswait; 745 int infinite = 0, mswait;
742 746
743 /* 747 /*
744 * If we can't use interrupts, poll on completion. 748 * If we can't use interrupts, poll on completion.
745 */ 749 */
746 if ((mswait = XS_TIME(xs)) == 0) { 750 if ((mswait = XS_TIME(xs)) == 0) {
747 infinite = 1; 751 infinite = 1;
748 } 752 }
749 753
750 while (mswait || infinite) { 754 while (mswait || infinite) {
751 uint32_t isr; 755 uint32_t isr;
752 uint16_t sema, mbox; 756 uint16_t sema, mbox;
753 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { 757 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
754 isp_intr(isp, isr, sema, mbox); 758 isp_intr(isp, isr, sema, mbox);
755 if (XS_CMD_DONE_P(xs)) { 759 if (XS_CMD_DONE_P(xs)) {
756 break; 760 break;
757 } 761 }
758 } 762 }
759 ISP_DELAY(1000); 763 ISP_DELAY(1000);
760 mswait -= 1; 764 mswait -= 1;
761 } 765 }
762 766
763 /* 767 /*
764 * If no other error occurred but we didn't finish 768 * If no other error occurred but we didn't finish
765 * something bad happened, so abort the command. 769 * something bad happened, so abort the command.
766 */ 770 */
767 if (XS_CMD_DONE_P(xs) == 0) { 771 if (XS_CMD_DONE_P(xs) == 0) {
768 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) { 772 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
769 isp_reinit(isp, 0); 773 isp_reinit(isp, 0);
770 } 774 }
771 if (XS_NOERR(xs)) { 775 if (XS_NOERR(xs)) {
772 isp_prt(isp, ISP_LOGERR, "polled command timed out"); 776 isp_prt(isp, ISP_LOGERR, "polled command timed out");
773 XS_SETERR(xs, HBA_BOTCH); 777 XS_SETERR(xs, HBA_BOTCH);
774 } 778 }
775 } 779 }
776 scsipi_done(xs); 780 scsipi_done(xs);
777} 781}
778 782
779void 783void
780isp_done(XS_T *xs) 784isp_done(XS_T *xs)
781{ 785{
782 if (XS_CMD_WDOG_P(xs) == 0) { 786 if (XS_CMD_WDOG_P(xs) == 0) {
783 struct ispsoftc *isp = XS_ISP(xs); 787 struct ispsoftc *isp = XS_ISP(xs);
784 callout_stop(&xs->xs_callout); 788 callout_stop(&xs->xs_callout);
785 if (XS_CMD_GRACE_P(xs)) { 789 if (XS_CMD_GRACE_P(xs)) {
786 isp_prt(isp, ISP_LOGDEBUG1, 790 isp_prt(isp, ISP_LOGDEBUG1,
787 "finished command on borrowed time"); 791 "finished command on borrowed time");
788 } 792 }
789 XS_CMD_S_CLEAR(xs); 793 XS_CMD_S_CLEAR(xs);
790 /* 794 /*
791 * Fixup- if we get a QFULL, we need 795 * Fixup- if we get a QFULL, we need
792 * to set XS_BUSY as the error. 796 * to set XS_BUSY as the error.
793 */ 797 */
794 if (xs->status == SCSI_QUEUE_FULL) { 798 if (xs->status == SCSI_QUEUE_FULL) {
795 xs->error = XS_BUSY; 799 xs->error = XS_BUSY;
796 } 800 }
797 if (isp->isp_osinfo.paused) { 801 if (isp->isp_osinfo.paused) {
798 int i; 802 int i;
799 isp->isp_osinfo.paused = 0; 803 isp->isp_osinfo.paused = 0;
800 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 804 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
801 "THAW QUEUES @ LINE %d", __LINE__); 805 "THAW QUEUES @ LINE %d", __LINE__);
802 for (i = 0; i < isp->isp_nchan; i++) { 806 for (i = 0; i < isp->isp_nchan; i++) {
803 scsipi_channel_timed_thaw(&isp->isp_osinfo.chan[i]); 807 scsipi_channel_timed_thaw(&isp->isp_osinfo.chan[i]);
804 } 808 }
805 } 809 }
806 if (xs->error == XS_DRIVER_STUFFUP) { 810 if (xs->error == XS_DRIVER_STUFFUP) {
807 isp_prt(isp, ISP_LOGERR, 811 isp_prt(isp, ISP_LOGERR,
808 "BOTCHED cmd for %d.%d.%d cmd 0x%x datalen %ld", 812 "BOTCHED cmd for %d.%d.%d cmd 0x%x datalen %ld",
809 XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), 813 XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs),
810 XS_CDBP(xs)[0], (long) XS_XFRLEN(xs)); 814 XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
811 } 815 }
812 scsipi_done(xs); 816 scsipi_done(xs);
813 } 817 }
814} 818}
815 819
816static void 820static void
817isp_dog(void *arg) 821isp_dog(void *arg)
818{ 822{
819 XS_T *xs = arg; 823 XS_T *xs = arg;
820 struct ispsoftc *isp = XS_ISP(xs); 824 struct ispsoftc *isp = XS_ISP(xs);
821 uint32_t handle; 825 uint32_t handle;
822 826
823 827
824 ISP_ILOCK(isp); 828 ISP_ILOCK(isp);
825 /* 829 /*
826 * We've decided this command is dead. Make sure we're not trying 830 * We've decided this command is dead. Make sure we're not trying
827 * to kill a command that's already dead by getting it's handle and 831 * to kill a command that's already dead by getting it's handle and
828 * and seeing whether it's still alive. 832 * and seeing whether it's still alive.
829 */ 833 */
830 handle = isp_find_handle(isp, xs); 834 handle = isp_find_handle(isp, xs);
831 if (handle) { 835 if (handle) {
832 uint32_t isr; 836 uint32_t isr;
833 uint16_t mbox, sema; 837 uint16_t mbox, sema;
834 838
835 if (XS_CMD_DONE_P(xs)) { 839 if (XS_CMD_DONE_P(xs)) {
836 isp_prt(isp, ISP_LOGDEBUG1, 840 isp_prt(isp, ISP_LOGDEBUG1,
837 "watchdog found done cmd (handle 0x%x)", handle); 841 "watchdog found done cmd (handle 0x%x)", handle);
838 ISP_IUNLOCK(isp); 842 ISP_IUNLOCK(isp);
839 return; 843 return;
840 } 844 }
841 845
842 if (XS_CMD_WDOG_P(xs)) { 846 if (XS_CMD_WDOG_P(xs)) {
843 isp_prt(isp, ISP_LOGDEBUG1, 847 isp_prt(isp, ISP_LOGDEBUG1,
844 "recursive watchdog (handle 0x%x)", handle); 848 "recursive watchdog (handle 0x%x)", handle);
845 ISP_IUNLOCK(isp); 849 ISP_IUNLOCK(isp);
846 return; 850 return;
847 } 851 }
848 852
849 XS_CMD_S_WDOG(xs); 853 XS_CMD_S_WDOG(xs);
850 854
851 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { 855 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
852 isp_intr(isp, isr, sema, mbox); 856 isp_intr(isp, isr, sema, mbox);
853 857
854 } 858 }
855 if (XS_CMD_DONE_P(xs)) { 859 if (XS_CMD_DONE_P(xs)) {
856 isp_prt(isp, ISP_LOGDEBUG1, 860 isp_prt(isp, ISP_LOGDEBUG1,
857 "watchdog cleanup for handle 0x%x", handle); 861 "watchdog cleanup for handle 0x%x", handle);
858 XS_CMD_C_WDOG(xs); 862 XS_CMD_C_WDOG(xs);
859 isp_done(xs); 863 isp_done(xs);
860 } else if (XS_CMD_GRACE_P(xs)) { 864 } else if (XS_CMD_GRACE_P(xs)) {
861 isp_prt(isp, ISP_LOGDEBUG1, 865 isp_prt(isp, ISP_LOGDEBUG1,
862 "watchdog timeout for handle 0x%x", handle); 866 "watchdog timeout for handle 0x%x", handle);
863 /* 867 /*
864 * Make sure the command is *really* dead before we 868 * Make sure the command is *really* dead before we
865 * release the handle (and DMA resources) for reuse. 869 * release the handle (and DMA resources) for reuse.
866 */ 870 */
867 (void) isp_control(isp, ISPCTL_ABORT_CMD, arg); 871 (void) isp_control(isp, ISPCTL_ABORT_CMD, arg);
868 872
869 /* 873 /*
870 * After this point, the command is really dead. 874 * After this point, the command is really dead.
871 */ 875 */
872 if (XS_XFRLEN(xs)) { 876 if (XS_XFRLEN(xs)) {
873 ISP_DMAFREE(isp, xs, handle); 877 ISP_DMAFREE(isp, xs, handle);
874 } 878 }
875 isp_destroy_handle(isp, handle); 879 isp_destroy_handle(isp, handle);
876 XS_SETERR(xs, XS_TIMEOUT); 880 XS_SETERR(xs, XS_TIMEOUT);
877 XS_CMD_S_CLEAR(xs); 881 XS_CMD_S_CLEAR(xs);
878 isp_done(xs); 882 isp_done(xs);
879 } else { 883 } else {
880 void *qe; 884 void *qe;
881 isp_marker_t local, *mp = &local; 885 isp_marker_t local, *mp = &local;
882 isp_prt(isp, ISP_LOGDEBUG2, 886 isp_prt(isp, ISP_LOGDEBUG2,
883 "possible command timeout on handle %x", handle); 887 "possible command timeout on handle %x", handle);
884 XS_CMD_C_WDOG(xs); 888 XS_CMD_C_WDOG(xs);
885 callout_reset(&xs->xs_callout, hz, isp_dog, xs); 889 callout_reset(&xs->xs_callout, hz, isp_dog, xs);
886 qe = isp_getrqentry(isp); 890 qe = isp_getrqentry(isp);
887 if (qe == NULL) { 891 if (qe == NULL) {
888 ISP_UNLOCK(isp); 892 ISP_UNLOCK(isp);
889 return; 893 return;
890 } 894 }
891 XS_CMD_S_GRACE(xs); 895 XS_CMD_S_GRACE(xs);
892 ISP_MEMZERO((void *) mp, sizeof (*mp)); 896 ISP_MEMZERO((void *) mp, sizeof (*mp));
893 mp->mrk_header.rqs_entry_count = 1; 897 mp->mrk_header.rqs_entry_count = 1;
894 mp->mrk_header.rqs_entry_type = RQSTYPE_MARKER; 898 mp->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
895 mp->mrk_modifier = SYNC_ALL; 899 mp->mrk_modifier = SYNC_ALL;
896 mp->mrk_target = XS_CHANNEL(xs) << 7; 900 mp->mrk_target = XS_CHANNEL(xs) << 7;
897 isp_put_marker(isp, mp, qe); 901 isp_put_marker(isp, mp, qe);
898 ISP_SYNC_REQUEST(isp); 902 ISP_SYNC_REQUEST(isp);
899 } 903 }
900 } else { 904 } else {
901 isp_prt(isp, ISP_LOGDEBUG0, "watchdog with no command"); 905 isp_prt(isp, ISP_LOGDEBUG0, "watchdog with no command");
902 } 906 }
903 ISP_IUNLOCK(isp); 907 ISP_IUNLOCK(isp);
904} 908}
905 909
906/* 910/*
907 * Gone Device Timer Function- when we have decided that a device has gone 911 * Gone Device Timer Function- when we have decided that a device has gone
908 * away, we wait a specific period of time prior to telling the OS it has 912 * away, we wait a specific period of time prior to telling the OS it has
909 * gone away. 913 * gone away.
910 * 914 *
911 * This timer function fires once a second and then scans the port database 915 * This timer function fires once a second and then scans the port database
912 * for devices that are marked dead but still have a virtual target assigned. 916 * for devices that are marked dead but still have a virtual target assigned.
913 * We decrement a counter for that port database entry, and when it hits zero, 917 * We decrement a counter for that port database entry, and when it hits zero,
914 * we tell the OS the device has gone away. 918 * we tell the OS the device has gone away.
915 */ 919 */
916static void 920static void
917isp_gdt(void *arg) 921isp_gdt(void *arg)
918{ 922{
919 ispsoftc_t *isp = arg; 923 ispsoftc_t *isp = arg;
920 fcportdb_t *lp; 924 fcportdb_t *lp;
921 int dbidx, tgt, more_to_do = 0; 925 int dbidx, tgt, more_to_do = 0;
922 926
923 isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired"); 927 isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
924 ISP_LOCK(isp); 928 ISP_LOCK(isp);
925 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { 929 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
926 lp = &FCPARAM(isp, 0)->portdb[dbidx]; 930 lp = &FCPARAM(isp, 0)->portdb[dbidx];
927 931
928 if (lp->state != FC_PORTDB_STATE_ZOMBIE) { 932 if (lp->state != FC_PORTDB_STATE_ZOMBIE) {
929 continue; 933 continue;
930 } 934 }
931 if (lp->dev_map_idx == 0) { 935 if (lp->dev_map_idx == 0) {
932 continue; 936 continue;
933 } 937 }
934 if (lp->new_reserved == 0) { 938 if (lp->new_reserved == 0) {
935 continue; 939 continue;
936 } 940 }
937 lp->new_reserved -= 1; 941 lp->new_reserved -= 1;
938 if (lp->new_reserved != 0) { 942 if (lp->new_reserved != 0) {
939 more_to_do++; 943 more_to_do++;
940 continue; 944 continue;
941 } 945 }
942 tgt = lp->dev_map_idx - 1; 946 tgt = lp->dev_map_idx - 1;
943 FCPARAM(isp, 0)->isp_dev_map[tgt] = 0; 947 FCPARAM(isp, 0)->isp_dev_map[tgt] = 0;
944 lp->dev_map_idx = 0; 948 lp->dev_map_idx = 0;
945 lp->state = FC_PORTDB_STATE_NIL; 949 lp->state = FC_PORTDB_STATE_NIL;
946 isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt, 950 isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
947 "Gone Device Timeout"); 951 "Gone Device Timeout");
948 isp_make_gone(isp, tgt); 952 isp_make_gone(isp, tgt);
949 } 953 }
950 if (more_to_do) { 954 if (more_to_do) {
951 callout_schedule(&isp->isp_osinfo.gdt, hz); 955 callout_schedule(&isp->isp_osinfo.gdt, hz);
952 } else { 956 } else {
953 isp->isp_osinfo.gdt_running = 0; 957 isp->isp_osinfo.gdt_running = 0;
954 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 958 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
955 "stopping Gone Device Timer"); 959 "stopping Gone Device Timer");
956 } 960 }
957 ISP_UNLOCK(isp); 961 ISP_UNLOCK(isp);
958} 962}
959 963
960/* 964/*
961 * Loop Down Timer Function- when loop goes down, a timer is started and 965 * Loop Down Timer Function- when loop goes down, a timer is started and
962 * and after it expires we come here and take all probational devices that 966 * and after it expires we come here and take all probational devices that
963 * the OS knows about and the tell the OS that they've gone away. 967 * the OS knows about and the tell the OS that they've gone away.
964 *  968 *
965 * We don't clear the devices out of our port database because, when loop 969 * We don't clear the devices out of our port database because, when loop
966 * come back up, we have to do some actual cleanup with the chip at that 970 * come back up, we have to do some actual cleanup with the chip at that
967 * point (implicit PLOGO, e.g., to get the chip's port database state right). 971 * point (implicit PLOGO, e.g., to get the chip's port database state right).
968 */ 972 */
969static void 973static void
970isp_ldt(void *arg) 974isp_ldt(void *arg)
971{ 975{
972 ispsoftc_t *isp = arg; 976 ispsoftc_t *isp = arg;
973 fcportdb_t *lp; 977 fcportdb_t *lp;
974 int dbidx, tgt; 978 int dbidx, tgt;
975 979
976 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired"); 980 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
977 ISP_LOCK(isp); 981 ISP_LOCK(isp);
978 982
979 /* 983 /*
980 * Notify to the OS all targets who we now consider have departed. 984 * Notify to the OS all targets who we now consider have departed.
981 */ 985 */
982 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { 986 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
983 lp = &FCPARAM(isp, 0)->portdb[dbidx]; 987 lp = &FCPARAM(isp, 0)->portdb[dbidx];
984 988
985 if (lp->state != FC_PORTDB_STATE_PROBATIONAL) { 989 if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
986 continue; 990 continue;
987 } 991 }
988 if (lp->dev_map_idx == 0) { 992 if (lp->dev_map_idx == 0) {
989 continue; 993 continue;
990 } 994 }
991 995
992 /* 996 /*
993 * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST! 997 * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
994 */ 998 */
995 999
996 /* 1000 /*
997 * Mark that we've announced that this device is gone.... 1001 * Mark that we've announced that this device is gone....
998 */ 1002 */
999 lp->reserved = 1; 1003 lp->reserved = 1;
1000 1004
1001 /* 1005 /*
1002 * but *don't* change the state of the entry. Just clear 1006 * but *don't* change the state of the entry. Just clear
1003 * any target id stuff and announce to CAM that the 1007 * any target id stuff and announce to CAM that the
1004 * device is gone. This way any necessary PLOGO stuff 1008 * device is gone. This way any necessary PLOGO stuff
1005 * will happen when loop comes back up. 1009 * will happen when loop comes back up.
1006 */ 1010 */
1007 1011
1008 tgt = lp->dev_map_idx - 1; 1012 tgt = lp->dev_map_idx - 1;
1009 FCPARAM(isp, 0)->isp_dev_map[tgt] = 0; 1013 FCPARAM(isp, 0)->isp_dev_map[tgt] = 0;
1010 lp->dev_map_idx = 0; 1014 lp->dev_map_idx = 0;
1011 isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt, 1015 isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
1012 "Loop Down Timeout"); 1016 "Loop Down Timeout");
1013 isp_make_gone(isp, tgt); 1017 isp_make_gone(isp, tgt);
1014 } 1018 }
1015 1019
1016 /* 1020 /*
1017 * The loop down timer has expired. Wake up the kthread 1021 * The loop down timer has expired. Wake up the kthread
1018 * to notice that fact (or make it false). 1022 * to notice that fact (or make it false).
1019 */ 1023 */
1020 isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1; 1024 isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
1021 wakeup(&isp->isp_osinfo.thread); 1025 wakeup(&isp->isp_osinfo.thread);
1022 ISP_UNLOCK(isp); 1026 ISP_UNLOCK(isp);
1023} 1027}
1024 1028
1025static void 1029static void
1026isp_make_here(ispsoftc_t *isp, int tgt) 1030isp_make_here(ispsoftc_t *isp, int tgt)
1027{ 1031{
1028 isp_prt(isp, ISP_LOGINFO, "target %d has arrived", tgt); 1032 isp_prt(isp, ISP_LOGINFO, "target %d has arrived", tgt);
1029} 1033}
1030 1034
1031static void 1035static void
1032isp_make_gone(ispsoftc_t *isp, int tgt) 1036isp_make_gone(ispsoftc_t *isp, int tgt)
1033{ 1037{
1034 isp_prt(isp, ISP_LOGINFO, "target %d has departed", tgt); 1038 isp_prt(isp, ISP_LOGINFO, "target %d has departed", tgt);
1035} 1039}
1036 1040
1037static void 1041static void
1038isp_fc_worker(void *arg) 1042isp_fc_worker(void *arg)
1039{ 1043{
1040 void scsipi_run_queue(struct scsipi_channel *); 1044 void scsipi_run_queue(struct scsipi_channel *);
1041 ispsoftc_t *isp = arg; 1045 ispsoftc_t *isp = arg;
1042 int slp = 0; 1046 int slp = 0;
1043 int chan = 0; 1047 int chan = 0;
1044 1048
1045 int s = splbio(); 1049 int s = splbio();
1046 /* 1050 /*
1047 * The first loop is for our usage where we have yet to have 1051 * The first loop is for our usage where we have yet to have
1048 * gotten good fibre channel state. 1052 * gotten good fibre channel state.
1049 */ 1053 */
1050 while (isp->isp_osinfo.thread != NULL) { 1054 while (isp->isp_osinfo.thread != NULL) {
1051 int sok, lb, lim; 1055 int sok, lb, lim;
1052 1056
1053 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "checking FC state"); 1057 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "checking FC state");
1054 sok = isp->isp_osinfo.mbox_sleep_ok; 1058 sok = isp->isp_osinfo.mbox_sleep_ok;
1055 isp->isp_osinfo.mbox_sleep_ok = 1; 1059 isp->isp_osinfo.mbox_sleep_ok = 1;
1056 lb = isp_fc_runstate(isp, chan, 250000); 1060 lb = isp_fc_runstate(isp, chan, 250000);
1057 isp->isp_osinfo.mbox_sleep_ok = sok; 1061 isp->isp_osinfo.mbox_sleep_ok = sok;
1058 if (lb) { 1062 if (lb) {
1059 /* 1063 /*
1060 * Increment loop down time by the last sleep interval 1064 * Increment loop down time by the last sleep interval
1061 */ 1065 */
1062 isp->isp_osinfo.loop_down_time += slp; 1066 isp->isp_osinfo.loop_down_time += slp;
1063 1067
1064 if (lb < 0) { 1068 if (lb < 0) {
1065 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1069 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1066 "FC loop not up (down count %d)", 1070 "FC loop not up (down count %d)",
1067 isp->isp_osinfo.loop_down_time); 1071 isp->isp_osinfo.loop_down_time);
1068 } else { 1072 } else {
1069 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1073 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1070 "FC got to %d (down count %d)", 1074 "FC got to %d (down count %d)",
1071 lb, isp->isp_osinfo.loop_down_time); 1075 lb, isp->isp_osinfo.loop_down_time);
1072 } 1076 }
1073 1077
1074 1078
1075 /* 1079 /*
1076 * If we've never seen loop up and we've waited longer 1080 * If we've never seen loop up and we've waited longer
1077 * than quickboot time, or we've seen loop up but we've 1081 * than quickboot time, or we've seen loop up but we've
1078 * waited longer than loop_down_limit, give up and go 1082 * waited longer than loop_down_limit, give up and go
1079 * to sleep until loop comes up. 1083 * to sleep until loop comes up.
1080 */ 1084 */
1081 if (FCPARAM(isp, 0)->loop_seen_once == 0) { 1085 if (FCPARAM(isp, 0)->loop_seen_once == 0) {
1082 lim = isp_quickboot_time; 1086 lim = isp_quickboot_time;
1083 } else { 1087 } else {
1084 lim = isp->isp_osinfo.loop_down_limit; 1088 lim = isp->isp_osinfo.loop_down_limit;
1085 } 1089 }
1086 if (isp->isp_osinfo.loop_down_time >= lim) { 1090 if (isp->isp_osinfo.loop_down_time >= lim) {
1087 /* 1091 /*
1088 * If we're now past our limit, release 1092 * If we're now past our limit, release
1089 * the queues and let them come in and 1093 * the queues and let them come in and
1090 * either get HBA_SELTIMOUT or cause 1094 * either get HBA_SELTIMOUT or cause
1091 * another freeze. 1095 * another freeze.
1092 */ 1096 */
1093 isp->isp_osinfo.blocked = 1; 1097 isp->isp_osinfo.blocked = 1;
1094 slp = 0; 1098 slp = 0;
1095 } else if (isp->isp_osinfo.loop_down_time < 10) { 1099 } else if (isp->isp_osinfo.loop_down_time < 10) {
1096 slp = 1; 1100 slp = 1;
1097 } else if (isp->isp_osinfo.loop_down_time < 30) { 1101 } else if (isp->isp_osinfo.loop_down_time < 30) {
1098 slp = 5; 1102 slp = 5;
1099 } else if (isp->isp_osinfo.loop_down_time < 60) { 1103 } else if (isp->isp_osinfo.loop_down_time < 60) {
1100 slp = 10; 1104 slp = 10;
1101 } else if (isp->isp_osinfo.loop_down_time < 120) { 1105 } else if (isp->isp_osinfo.loop_down_time < 120) {
1102 slp = 20; 1106 slp = 20;
1103 } else { 1107 } else {
1104 slp = 30; 1108 slp = 30;
1105 } 1109 }
1106 1110
1107 } else { 1111 } else {
1108 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1112 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1109 "FC state OK"); 1113 "FC state OK");
1110 isp->isp_osinfo.loop_down_time = 0; 1114 isp->isp_osinfo.loop_down_time = 0;
1111 slp = 0; 1115 slp = 0;
1112 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1116 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1113 "THAW QUEUES @ LINE %d", __LINE__); 1117 "THAW QUEUES @ LINE %d", __LINE__);
1114 scsipi_channel_thaw(&isp->isp_osinfo.chan[chan], 1); 1118 scsipi_channel_thaw(&isp->isp_osinfo.chan[chan], 1);
1115 } 1119 }
1116 1120
1117 /* 1121 /*
1118 * If we'd frozen the queues, unfreeze them now so that 1122 * If we'd frozen the queues, unfreeze them now so that
1119 * we can start getting commands. If the FC state isn't 1123 * we can start getting commands. If the FC state isn't
1120 * okay yet, they'll hit that in isp_start which will 1124 * okay yet, they'll hit that in isp_start which will
1121 * freeze the queues again. 1125 * freeze the queues again.
1122 */ 1126 */
1123 if (isp->isp_osinfo.blocked) { 1127 if (isp->isp_osinfo.blocked) {
1124 isp->isp_osinfo.blocked = 0; 1128 isp->isp_osinfo.blocked = 0;
1125 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1129 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1126 "THAW QUEUES @ LINE %d", __LINE__); 1130 "THAW QUEUES @ LINE %d", __LINE__);
1127 scsipi_channel_thaw(&isp->isp_osinfo.chan[chan], 1); 1131 scsipi_channel_thaw(&isp->isp_osinfo.chan[chan], 1);
1128 } 1132 }
1129 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "sleep time %d", slp); 1133 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "sleep time %d", slp);
1130 tsleep(&isp->isp_osinfo.thread, PRIBIO, "ispf", slp * hz); 1134 tsleep(&isp->isp_osinfo.thread, PRIBIO, "ispf", slp * hz);
1131 1135
1132 /* 1136 /*
1133 * If slp is zero, we're waking up for the first time after 1137 * If slp is zero, we're waking up for the first time after
1134 * things have been okay. In this case, we set a deferral state 1138 * things have been okay. In this case, we set a deferral state
1135 * for all commands and delay hysteresis seconds before starting 1139 * for all commands and delay hysteresis seconds before starting
1136 * the FC state evaluation. This gives the loop/fabric a chance 1140 * the FC state evaluation. This gives the loop/fabric a chance
1137 * to settle. 1141 * to settle.
1138 */ 1142 */
1139 if (slp == 0 && isp_fabric_hysteresis) { 1143 if (slp == 0 && isp_fabric_hysteresis) {
1140 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1144 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1141 "sleep hysteresis tick time %d", 1145 "sleep hysteresis tick time %d",
1142 isp_fabric_hysteresis * hz); 1146 isp_fabric_hysteresis * hz);
1143 (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT", 1147 (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
1144 (isp_fabric_hysteresis * hz)); 1148 (isp_fabric_hysteresis * hz));
1145 } 1149 }
1146 } 1150 }
1147 splx(s); 1151 splx(s);
1148 1152
1149 /* In case parent is waiting for us to exit. */ 1153 /* In case parent is waiting for us to exit. */
1150 wakeup(&isp->isp_osinfo.thread); 1154 wakeup(&isp->isp_osinfo.thread);
1151 kthread_exit(0); 1155 kthread_exit(0);
1152} 1156}
1153 1157
1154/* 1158/*
1155 * Free any associated resources prior to decommissioning and 1159 * Free any associated resources prior to decommissioning and
1156 * set the card to a known state (so it doesn't wake up and kick 1160 * set the card to a known state (so it doesn't wake up and kick
1157 * us when we aren't expecting it to). 1161 * us when we aren't expecting it to).
1158 * 1162 *
1159 * Locks are held before coming here. 1163 * Locks are held before coming here.
1160 */ 1164 */
1161void 1165void
1162isp_uninit(struct ispsoftc *isp) 1166isp_uninit(struct ispsoftc *isp)
1163{ 1167{
1164 isp_lock(isp); 1168 isp_lock(isp);
1165 /* 1169 /*
1166 * Leave with interrupts disabled. 1170 * Leave with interrupts disabled.
1167 */ 1171 */
1168 ISP_DISABLE_INTS(isp); 1172 ISP_DISABLE_INTS(isp);
1169 isp_unlock(isp); 1173 isp_unlock(isp);
1170} 1174}
1171 1175
1172void 1176void
1173isp_async(struct ispsoftc *isp, ispasync_t cmd, ...) 1177isp_async(struct ispsoftc *isp, ispasync_t cmd, ...)
1174{ 1178{
1175 int bus, tgt; 1179 int bus, tgt;
1176 const char *msg = NULL; 1180 const char *msg = NULL;
1177 static const char prom[] = 1181 static const char prom[] =
1178 "PortID 0x%06x handle 0x%x role %s %s\n" 1182 "PortID 0x%06x handle 0x%x role %s %s\n"
1179 " WWNN 0x%08x%08x WWPN 0x%08x%08x"; 1183 " WWNN 0x%08x%08x WWPN 0x%08x%08x";
1180 static const char prom2[] = 1184 static const char prom2[] =
1181 "PortID 0x%06x handle 0x%x role %s %s tgt %u\n" 1185 "PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
1182 " WWNN 0x%08x%08x WWPN 0x%08x%08x"; 1186 " WWNN 0x%08x%08x WWPN 0x%08x%08x";
1183 fcportdb_t *lp; 1187 fcportdb_t *lp;
1184 va_list ap; 1188 va_list ap;
1185 1189
1186 switch (cmd) { 1190 switch (cmd) {
1187 case ISPASYNC_NEW_TGT_PARAMS: 1191 case ISPASYNC_NEW_TGT_PARAMS:
1188 if (IS_SCSI(isp)) { 1192 if (IS_SCSI(isp)) {
1189 sdparam *sdp; 1193 sdparam *sdp;
1190 int flags; 1194 int flags;
1191 struct scsipi_xfer_mode xm; 1195 struct scsipi_xfer_mode xm;
1192 1196
1193 va_start(ap, cmd); 1197 va_start(ap, cmd);
1194 bus = va_arg(ap, int); 1198 bus = va_arg(ap, int);
1195 tgt = va_arg(ap, int); 1199 tgt = va_arg(ap, int);
1196 va_end(ap); 1200 va_end(ap);
1197 sdp = SDPARAM(isp, bus); 1201 sdp = SDPARAM(isp, bus);
1198 flags = sdp->isp_devparam[tgt].actv_flags; 1202 flags = sdp->isp_devparam[tgt].actv_flags;
1199 1203
1200 xm.xm_mode = 0; 1204 xm.xm_mode = 0;
1201 xm.xm_period = sdp->isp_devparam[tgt].actv_period; 1205 xm.xm_period = sdp->isp_devparam[tgt].actv_period;
1202 xm.xm_offset = sdp->isp_devparam[tgt].actv_offset; 1206 xm.xm_offset = sdp->isp_devparam[tgt].actv_offset;
1203 xm.xm_target = tgt; 1207 xm.xm_target = tgt;
1204 1208
1205 if ((flags & DPARM_SYNC) && xm.xm_period && xm.xm_offset) 1209 if ((flags & DPARM_SYNC) && xm.xm_period && xm.xm_offset)
1206 xm.xm_mode |= PERIPH_CAP_SYNC; 1210 xm.xm_mode |= PERIPH_CAP_SYNC;
1207 if (flags & DPARM_WIDE) 1211 if (flags & DPARM_WIDE)
1208 xm.xm_mode |= PERIPH_CAP_WIDE16; 1212 xm.xm_mode |= PERIPH_CAP_WIDE16;
1209 if (flags & DPARM_TQING) 1213 if (flags & DPARM_TQING)
1210 xm.xm_mode |= PERIPH_CAP_TQING; 1214 xm.xm_mode |= PERIPH_CAP_TQING;
1211 scsipi_async_event(&isp->isp_osinfo.chan[bus], 1215 scsipi_async_event(&isp->isp_osinfo.chan[bus],
1212 ASYNC_EVENT_XFER_MODE, &xm); 1216 ASYNC_EVENT_XFER_MODE, &xm);
1213 break; 1217 break;
1214 } 1218 }
1215 case ISPASYNC_BUS_RESET: 1219 case ISPASYNC_BUS_RESET:
1216 va_start(ap, cmd); 1220 va_start(ap, cmd);
1217 bus = va_arg(ap, int); 1221 bus = va_arg(ap, int);
1218 va_end(ap); 1222 va_end(ap);
1219 isp_prt(isp, ISP_LOGINFO, "SCSI bus %d reset detected", bus); 1223 isp_prt(isp, ISP_LOGINFO, "SCSI bus %d reset detected", bus);
1220 scsipi_async_event(&isp->isp_osinfo.chan[bus], 1224 scsipi_async_event(&isp->isp_osinfo.chan[bus],
1221 ASYNC_EVENT_RESET, NULL); 1225 ASYNC_EVENT_RESET, NULL);
1222 break; 1226 break;
1223 case ISPASYNC_LIP: 1227 case ISPASYNC_LIP:
1224 if (msg == NULL) { 1228 if (msg == NULL) {
1225 msg = "LIP Received"; 1229 msg = "LIP Received";
1226 } 1230 }
1227 /* FALLTHROUGH */ 1231 /* FALLTHROUGH */
1228 case ISPASYNC_LOOP_RESET: 1232 case ISPASYNC_LOOP_RESET:
1229 if (msg == NULL) { 1233 if (msg == NULL) {
1230 msg = "LOOP Reset Received"; 1234 msg = "LOOP Reset Received";
1231 } 1235 }
1232 /* FALLTHROUGH */ 1236 /* FALLTHROUGH */
1233 case ISPASYNC_LOOP_DOWN: 1237 case ISPASYNC_LOOP_DOWN:
1234 if (msg == NULL) { 1238 if (msg == NULL) {
1235 msg = "Loop DOWN"; 1239 msg = "Loop DOWN";
1236 } 1240 }
1237 va_start(ap, cmd); 1241 va_start(ap, cmd);
1238 bus = va_arg(ap, int); 1242 bus = va_arg(ap, int);
1239 va_end(ap); 1243 va_end(ap);
1240 1244
1241 /* 1245 /*
1242 * Don't do queue freezes or blockage until we have the 1246 * Don't do queue freezes or blockage until we have the
1243 * thread running and interrupts that can unfreeze/unblock us. 1247 * thread running and interrupts that can unfreeze/unblock us.
1244 */ 1248 */
1245 if (isp->isp_osinfo.mbox_sleep_ok && 1249 if (isp->isp_osinfo.mbox_sleep_ok &&
1246 isp->isp_osinfo.blocked == 0 && 1250 isp->isp_osinfo.blocked == 0 &&
1247 isp->isp_osinfo.thread) { 1251 isp->isp_osinfo.thread) {
1248 isp->isp_osinfo.blocked = 1; 1252 isp->isp_osinfo.blocked = 1;
1249 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1253 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1250 "FREEZE QUEUES @ LINE %d", __LINE__); 1254 "FREEZE QUEUES @ LINE %d", __LINE__);
1251 scsipi_channel_freeze(&isp->isp_osinfo.chan[bus], 1); 1255 scsipi_channel_freeze(&isp->isp_osinfo.chan[bus], 1);
1252 if (callout_pending(&isp->isp_osinfo.ldt) == 0) { 1256 if (callout_pending(&isp->isp_osinfo.ldt) == 0) {
1253 callout_schedule(&isp->isp_osinfo.ldt, 1257 callout_schedule(&isp->isp_osinfo.ldt,
1254 isp->isp_osinfo.loop_down_limit * hz); 1258 isp->isp_osinfo.loop_down_limit * hz);
1255 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1259 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1256 "Starting Loop Down Timer"); 1260 "Starting Loop Down Timer");
1257 } 1261 }
1258 } 1262 }
1259 isp_prt(isp, ISP_LOGINFO, msg); 1263 isp_prt(isp, ISP_LOGINFO, msg);
1260 break; 1264 break;
1261 case ISPASYNC_LOOP_UP: 1265 case ISPASYNC_LOOP_UP:
1262 /* 1266 /*
1263 * Let the subsequent ISPASYNC_CHANGE_NOTIFY invoke 1267 * Let the subsequent ISPASYNC_CHANGE_NOTIFY invoke
1264 * the FC worker thread. When the FC worker thread 1268 * the FC worker thread. When the FC worker thread
1265 * is done, let *it* call scsipi_channel_thaw... 1269 * is done, let *it* call scsipi_channel_thaw...
1266 */ 1270 */
1267 isp_prt(isp, ISP_LOGINFO, "Loop UP"); 1271 isp_prt(isp, ISP_LOGINFO, "Loop UP");
1268 break; 1272 break;
1269 case ISPASYNC_DEV_ARRIVED: 1273 case ISPASYNC_DEV_ARRIVED:
1270 va_start(ap, cmd); 1274 va_start(ap, cmd);
1271 bus = va_arg(ap, int); 1275 bus = va_arg(ap, int);
1272 lp = va_arg(ap, fcportdb_t *); 1276 lp = va_arg(ap, fcportdb_t *);
1273 va_end(ap); 1277 va_end(ap);
1274 lp->reserved = 0; 1278 lp->reserved = 0;
1275 if ((FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) && 1279 if ((FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) &&
1276 (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) { 1280 (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
1277 int dbidx = lp - FCPARAM(isp, bus)->portdb; 1281 int dbidx = lp - FCPARAM(isp, bus)->portdb;
1278 int i; 1282 int i;
1279 1283
1280 for (i = 0; i < MAX_FC_TARG; i++) { 1284 for (i = 0; i < MAX_FC_TARG; i++) {
1281 if (i >= FL_ID && i <= SNS_ID) { 1285 if (i >= FL_ID && i <= SNS_ID) {
1282 continue; 1286 continue;
1283 } 1287 }
1284 if (FCPARAM(isp, bus)->isp_dev_map[i] == 0) { 1288 if (FCPARAM(isp, bus)->isp_dev_map[i] == 0) {
1285 break; 1289 break;
1286 } 1290 }
1287 } 1291 }
1288 if (i < MAX_FC_TARG) { 1292 if (i < MAX_FC_TARG) {
1289 FCPARAM(isp, bus)->isp_dev_map[i] = dbidx + 1; 1293 FCPARAM(isp, bus)->isp_dev_map[i] = dbidx + 1;
1290 lp->dev_map_idx = i + 1; 1294 lp->dev_map_idx = i + 1;
1291 } else { 1295 } else {
1292 isp_prt(isp, ISP_LOGWARN, "out of target ids"); 1296 isp_prt(isp, ISP_LOGWARN, "out of target ids");
1293 isp_dump_portdb(isp, bus); 1297 isp_dump_portdb(isp, bus);
1294 } 1298 }
1295 } 1299 }
1296 if (lp->dev_map_idx) { 1300 if (lp->dev_map_idx) {
1297 tgt = lp->dev_map_idx - 1; 1301 tgt = lp->dev_map_idx - 1;
1298 isp_prt(isp, ISP_LOGCONFIG, prom2, 1302 isp_prt(isp, ISP_LOGCONFIG, prom2,
1299 lp->portid, lp->handle, 1303 lp->portid, lp->handle,
1300 roles[lp->roles], "arrived at", tgt, 1304 roles[lp->roles], "arrived at", tgt,
1301 (uint32_t) (lp->node_wwn >> 32), 1305 (uint32_t) (lp->node_wwn >> 32),
1302 (uint32_t) lp->node_wwn, 1306 (uint32_t) lp->node_wwn,
1303 (uint32_t) (lp->port_wwn >> 32), 1307 (uint32_t) (lp->port_wwn >> 32),
1304 (uint32_t) lp->port_wwn); 1308 (uint32_t) lp->port_wwn);
1305 isp_make_here(isp, tgt); 1309 isp_make_here(isp, tgt);
1306 } else { 1310 } else {
1307 isp_prt(isp, ISP_LOGCONFIG, prom, 1311 isp_prt(isp, ISP_LOGCONFIG, prom,
1308 lp->portid, lp->handle, 1312 lp->portid, lp->handle,
1309 roles[lp->roles], "arrived", 1313 roles[lp->roles], "arrived",
1310 (uint32_t) (lp->node_wwn >> 32), 1314 (uint32_t) (lp->node_wwn >> 32),
1311 (uint32_t) lp->node_wwn, 1315 (uint32_t) lp->node_wwn,
1312 (uint32_t) (lp->port_wwn >> 32), 1316 (uint32_t) (lp->port_wwn >> 32),
1313 (uint32_t) lp->port_wwn); 1317 (uint32_t) lp->port_wwn);
1314 } 1318 }
1315 break; 1319 break;
1316 case ISPASYNC_DEV_CHANGED: 1320 case ISPASYNC_DEV_CHANGED:
1317 va_start(ap, cmd); 1321 va_start(ap, cmd);
1318 bus = va_arg(ap, int); 1322 bus = va_arg(ap, int);
1319 lp = va_arg(ap, fcportdb_t *); 1323 lp = va_arg(ap, fcportdb_t *);
1320 va_end(ap); 1324 va_end(ap);
1321 if (isp_change_is_bad) { 1325 if (isp_change_is_bad) {
1322 lp->state = FC_PORTDB_STATE_NIL; 1326 lp->state = FC_PORTDB_STATE_NIL;
1323 if (lp->dev_map_idx) { 1327 if (lp->dev_map_idx) {
1324 tgt = lp->dev_map_idx - 1; 1328 tgt = lp->dev_map_idx - 1;
1325 FCPARAM(isp, bus)->isp_dev_map[tgt] = 0; 1329 FCPARAM(isp, bus)->isp_dev_map[tgt] = 0;
1326 lp->dev_map_idx = 0; 1330 lp->dev_map_idx = 0;
1327 isp_prt(isp, ISP_LOGCONFIG, prom3, 1331 isp_prt(isp, ISP_LOGCONFIG, prom3,
1328 lp->portid, tgt, "change is bad"); 1332 lp->portid, tgt, "change is bad");
1329 isp_make_gone(isp, tgt); 1333 isp_make_gone(isp, tgt);
1330 } else { 1334 } else {
1331 isp_prt(isp, ISP_LOGCONFIG, prom, 1335 isp_prt(isp, ISP_LOGCONFIG, prom,
1332 lp->portid, lp->handle, 1336 lp->portid, lp->handle,
1333 roles[lp->roles], 1337 roles[lp->roles],
1334 "changed and departed", 1338 "changed and departed",
1335 (uint32_t) (lp->node_wwn >> 32), 1339 (uint32_t) (lp->node_wwn >> 32),
1336 (uint32_t) lp->node_wwn, 1340 (uint32_t) lp->node_wwn,
1337 (uint32_t) (lp->port_wwn >> 32), 1341 (uint32_t) (lp->port_wwn >> 32),
1338 (uint32_t) lp->port_wwn); 1342 (uint32_t) lp->port_wwn);
1339 } 1343 }
1340 } else { 1344 } else {
1341 lp->portid = lp->new_portid; 1345 lp->portid = lp->new_portid;
1342 lp->roles = lp->new_roles; 1346 lp->roles = lp->new_roles;
1343 if (lp->dev_map_idx) { 1347 if (lp->dev_map_idx) {
1344 int t = lp->dev_map_idx - 1; 1348 int t = lp->dev_map_idx - 1;
1345 FCPARAM(isp, bus)->isp_dev_map[t] = 1349 FCPARAM(isp, bus)->isp_dev_map[t] =
1346 (lp - FCPARAM(isp, bus)->portdb) + 1; 1350 (lp - FCPARAM(isp, bus)->portdb) + 1;
1347 tgt = lp->dev_map_idx - 1; 1351 tgt = lp->dev_map_idx - 1;
1348 isp_prt(isp, ISP_LOGCONFIG, prom2, 1352 isp_prt(isp, ISP_LOGCONFIG, prom2,
1349 lp->portid, lp->handle, 1353 lp->portid, lp->handle,
1350 roles[lp->roles], "changed at", tgt, 1354 roles[lp->roles], "changed at", tgt,
1351 (uint32_t) (lp->node_wwn >> 32), 1355 (uint32_t) (lp->node_wwn >> 32),
1352 (uint32_t) lp->node_wwn, 1356 (uint32_t) lp->node_wwn,
1353 (uint32_t) (lp->port_wwn >> 32), 1357 (uint32_t) (lp->port_wwn >> 32),
1354 (uint32_t) lp->port_wwn); 1358 (uint32_t) lp->port_wwn);
1355 } else { 1359 } else {
1356 isp_prt(isp, ISP_LOGCONFIG, prom, 1360 isp_prt(isp, ISP_LOGCONFIG, prom,
1357 lp->portid, lp->handle, 1361 lp->portid, lp->handle,
1358 roles[lp->roles], "changed", 1362 roles[lp->roles], "changed",
1359 (uint32_t) (lp->node_wwn >> 32), 1363 (uint32_t) (lp->node_wwn >> 32),
1360 (uint32_t) lp->node_wwn, 1364 (uint32_t) lp->node_wwn,
1361 (uint32_t) (lp->port_wwn >> 32), 1365 (uint32_t) (lp->port_wwn >> 32),
1362 (uint32_t) lp->port_wwn); 1366 (uint32_t) lp->port_wwn);
1363 } 1367 }
1364 } 1368 }
1365 break; 1369 break;
1366 case ISPASYNC_DEV_STAYED: 1370 case ISPASYNC_DEV_STAYED:
1367 va_start(ap, cmd); 1371 va_start(ap, cmd);
1368 bus = va_arg(ap, int); 1372 bus = va_arg(ap, int);
1369 lp = va_arg(ap, fcportdb_t *); 1373 lp = va_arg(ap, fcportdb_t *);
1370 va_end(ap); 1374 va_end(ap);
1371 if (lp->dev_map_idx) { 1375 if (lp->dev_map_idx) {
1372 tgt = lp->dev_map_idx - 1; 1376 tgt = lp->dev_map_idx - 1;
1373 isp_prt(isp, ISP_LOGCONFIG, prom2, 1377 isp_prt(isp, ISP_LOGCONFIG, prom2,
1374 lp->portid, lp->handle, 1378 lp->portid, lp->handle,
1375 roles[lp->roles], "stayed at", tgt, 1379 roles[lp->roles], "stayed at", tgt,
1376 (uint32_t) (lp->node_wwn >> 32), 1380 (uint32_t) (lp->node_wwn >> 32),
1377 (uint32_t) lp->node_wwn, 1381 (uint32_t) lp->node_wwn,
1378 (uint32_t) (lp->port_wwn >> 32), 1382 (uint32_t) (lp->port_wwn >> 32),
1379 (uint32_t) lp->port_wwn); 1383 (uint32_t) lp->port_wwn);
1380 } else { 1384 } else {
1381 isp_prt(isp, ISP_LOGCONFIG, prom, 1385 isp_prt(isp, ISP_LOGCONFIG, prom,
1382 lp->portid, lp->handle, 1386 lp->portid, lp->handle,
1383 roles[lp->roles], "stayed", 1387 roles[lp->roles], "stayed",
1384 (uint32_t) (lp->node_wwn >> 32), 1388 (uint32_t) (lp->node_wwn >> 32),
1385 (uint32_t) lp->node_wwn, 1389 (uint32_t) lp->node_wwn,
1386 (uint32_t) (lp->port_wwn >> 32), 1390 (uint32_t) (lp->port_wwn >> 32),
1387 (uint32_t) lp->port_wwn); 1391 (uint32_t) lp->port_wwn);
1388 } 1392 }
1389 break; 1393 break;
1390 case ISPASYNC_DEV_GONE: 1394 case ISPASYNC_DEV_GONE:
1391 va_start(ap, cmd); 1395 va_start(ap, cmd);
1392 bus = va_arg(ap, int); 1396 bus = va_arg(ap, int);
1393 lp = va_arg(ap, fcportdb_t *); 1397 lp = va_arg(ap, fcportdb_t *);
1394 va_end(ap); 1398 va_end(ap);
1395 /* 1399 /*
1396 * If this has a virtual target and we haven't marked it 1400 * If this has a virtual target and we haven't marked it
1397 * that we're going to have isp_gdt tell the OS it's gone, 1401 * that we're going to have isp_gdt tell the OS it's gone,
1398 * set the isp_gdt timer running on it. 1402 * set the isp_gdt timer running on it.
1399 * 1403 *
1400 * If it isn't marked that isp_gdt is going to get rid of it, 1404 * If it isn't marked that isp_gdt is going to get rid of it,
1401 * announce that it's gone. 1405 * announce that it's gone.
1402 */ 1406 */
1403 if (lp->dev_map_idx && lp->reserved == 0) { 1407 if (lp->dev_map_idx && lp->reserved == 0) {
1404 lp->reserved = 1; 1408 lp->reserved = 1;
1405 lp->new_reserved = isp->isp_osinfo.gone_device_time; 1409 lp->new_reserved = isp->isp_osinfo.gone_device_time;
1406 lp->state = FC_PORTDB_STATE_ZOMBIE; 1410 lp->state = FC_PORTDB_STATE_ZOMBIE;
1407 if (isp->isp_osinfo.gdt_running == 0) { 1411 if (isp->isp_osinfo.gdt_running == 0) {
1408 isp->isp_osinfo.gdt_running = 1; 1412 isp->isp_osinfo.gdt_running = 1;
1409 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1413 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1410 "starting Gone Device Timer"); 1414 "starting Gone Device Timer");
1411 callout_schedule(&isp->isp_osinfo.gdt, hz); 1415 callout_schedule(&isp->isp_osinfo.gdt, hz);
1412 } 1416 }
1413 tgt = lp->dev_map_idx - 1; 1417 tgt = lp->dev_map_idx - 1;
1414 isp_prt(isp, ISP_LOGCONFIG, prom2, 1418 isp_prt(isp, ISP_LOGCONFIG, prom2,
1415 lp->portid, lp->handle, 1419 lp->portid, lp->handle,
1416 roles[lp->roles], "gone zombie at", tgt, 1420 roles[lp->roles], "gone zombie at", tgt,
1417 (uint32_t) (lp->node_wwn >> 32), 1421 (uint32_t) (lp->node_wwn >> 32),
1418 (uint32_t) lp->node_wwn, 1422 (uint32_t) lp->node_wwn,
1419 (uint32_t) (lp->port_wwn >> 32), 1423 (uint32_t) (lp->port_wwn >> 32),
1420 (uint32_t) lp->port_wwn); 1424 (uint32_t) lp->port_wwn);
1421 } else if (lp->reserved == 0) { 1425 } else if (lp->reserved == 0) {
1422 isp_prt(isp, ISP_LOGCONFIG, prom, 1426 isp_prt(isp, ISP_LOGCONFIG, prom,
1423 lp->portid, lp->handle, 1427 lp->portid, lp->handle,
1424 roles[lp->roles], "departed", 1428 roles[lp->roles], "departed",
1425 (uint32_t) (lp->node_wwn >> 32), 1429 (uint32_t) (lp->node_wwn >> 32),
1426 (uint32_t) lp->node_wwn, 1430 (uint32_t) lp->node_wwn,
1427 (uint32_t) (lp->port_wwn >> 32), 1431 (uint32_t) (lp->port_wwn >> 32),
1428 (uint32_t) lp->port_wwn); 1432 (uint32_t) lp->port_wwn);
1429 } 1433 }
1430 break; 1434 break;
1431 case ISPASYNC_CHANGE_NOTIFY: 1435 case ISPASYNC_CHANGE_NOTIFY:
1432 { 1436 {
1433 int opt; 1437 int opt;
1434 1438
1435 va_start(ap, cmd); 1439 va_start(ap, cmd);
1436 bus = va_arg(ap, int); 1440 bus = va_arg(ap, int);
1437 opt = va_arg(ap, int); 1441 opt = va_arg(ap, int);
1438 va_end(ap); 1442 va_end(ap);
1439 1443
1440 if (opt == ISPASYNC_CHANGE_PDB) { 1444 if (opt == ISPASYNC_CHANGE_PDB) {
1441 msg = "Port Database Changed"; 1445 msg = "Port Database Changed";
1442 } else if (opt == ISPASYNC_CHANGE_SNS) { 1446 } else if (opt == ISPASYNC_CHANGE_SNS) {
1443 msg = "Name Server Database Changed"; 1447 msg = "Name Server Database Changed";
1444 } else { 1448 } else {
1445 msg = "Other Change Notify"; 1449 msg = "Other Change Notify";
1446 } 1450 }
1447 /* 1451 /*
1448 * If the loop down timer is running, cancel it. 1452 * If the loop down timer is running, cancel it.
1449 */ 1453 */
1450 if (callout_pending(&isp->isp_osinfo.ldt)) { 1454 if (callout_pending(&isp->isp_osinfo.ldt)) {
1451 callout_stop(&isp->isp_osinfo.ldt); 1455 callout_stop(&isp->isp_osinfo.ldt);
1452 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1456 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1453 "Stopping Loop Down Timer"); 1457 "Stopping Loop Down Timer");
1454 } 1458 }
1455 isp_prt(isp, ISP_LOGINFO, msg); 1459 isp_prt(isp, ISP_LOGINFO, msg);
1456 /* 1460 /*
1457 * We can set blocked here because we know it's now okay 1461 * We can set blocked here because we know it's now okay
1458 * to try and run isp_fc_runstate (in order to build loop 1462 * to try and run isp_fc_runstate (in order to build loop
1459 * state). But we don't try and freeze the midlayer's queue 1463 * state). But we don't try and freeze the midlayer's queue
1460 * if we have no thread that we can wake to later unfreeze 1464 * if we have no thread that we can wake to later unfreeze
1461 * it. 1465 * it.
1462 */ 1466 */
1463 if (isp->isp_osinfo.blocked == 0) { 1467 if (isp->isp_osinfo.blocked == 0) {
1464 isp->isp_osinfo.blocked = 1; 1468 isp->isp_osinfo.blocked = 1;
1465 if (isp->isp_osinfo.thread) { 1469 if (isp->isp_osinfo.thread) {
1466 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, 1470 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1467 "FREEZE QUEUES @ LINE %d", __LINE__); 1471 "FREEZE QUEUES @ LINE %d", __LINE__);
1468 scsipi_channel_freeze(&isp->isp_osinfo.chan[bus], 1); 1472 scsipi_channel_freeze(&isp->isp_osinfo.chan[bus], 1);
1469 } 1473 }
1470 } 1474 }
1471 /* 1475 /*
1472 * Note that we have work for the thread to do, and 1476 * Note that we have work for the thread to do, and
1473 * if the thread is here already, wake it up. 1477 * if the thread is here already, wake it up.
1474 */ 1478 */
1475 if (isp->isp_osinfo.thread) { 1479 if (isp->isp_osinfo.thread) {
1476 wakeup(&isp->isp_osinfo.thread); 1480 wakeup(&isp->isp_osinfo.thread);