isp_netbsd.c revision 1.18.2.1 1 /* $NetBSD: isp_netbsd.c,v 1.18.2.1 1999/10/19 17:47:37 thorpej Exp $ */
2 /*
3 * Platform (NetBSD) dependent common attachment code for Qlogic adapters.
4 * Matthew Jacob <mjacob (at) nas.nasa.gov>
5 */
6 /*
7 * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <dev/ic/isp_netbsd.h>
34 #include <sys/scsiio.h>
35
36 static void ispminphys __P((struct buf *));
37 static void isp_scsipi_request __P((struct scsipi_channel *,
38 scsipi_adapter_req_t, void *));
39 static int
40 ispioctl __P((struct scsipi_channel *, u_long, caddr_t, int, struct proc *));
41
42 static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
43 static void isp_watch __P((void *));
44 static void isp_command_requeue __P((void *));
45 static void isp_internal_restart __P((void *));
46
47 /*
48 * Complete attachment of hardware, include subdevices.
49 */
50 void
51 isp_attach(isp)
52 struct ispsoftc *isp;
53 {
54 struct scsipi_adapter *adapt = &isp->isp_osinfo._adapter;
55 struct scsipi_channel *chan;
56 int i;
57
58 isp->isp_state = ISP_RUNSTATE;
59 TAILQ_INIT(&isp->isp_osinfo.waitq); /* XXX 2nd Bus? */
60
61 /*
62 * Fill in the scsipi_adapter.
63 */
64 adapt->adapt_dev = &isp->isp_osinfo._dev;
65 if (IS_FC(isp) == 0 && IS_12X0(isp) != 0)
66 adapt->adapt_nchannels = 2;
67 else
68 adapt->adapt_nchannels = 1;
69 adapt->adapt_openings = isp->isp_maxcmds;
70 adapt->adapt_max_periph = adapt->adapt_openings;
71 adapt->adapt_request = isp_scsipi_request;
72 adapt->adapt_minphys = ispminphys;
73 adapt->adapt_ioctl = ispioctl;
74
75 /*
76 * Fill in the scsipi_channel(s).
77 */
78 for (i = 0; i < adapt->adapt_nchannels; i++) {
79 chan = &isp->isp_osinfo._channels[i];
80 chan->chan_adapter = adapt;
81 chan->chan_bustype = &scsi_bustype;
82 chan->chan_channel = i;
83
84 if (IS_FC(isp)) {
85 fcparam *fcp = isp->isp_param;
86 fcp = &fcp[i];
87
88 /*
89 * Give it another chance here to come alive...
90 */
91 if (fcp->isp_fwstate != FW_READY) {
92 (void) isp_control(isp, ISPCTL_FCLINK_TEST,
93 NULL);
94 }
95 chan->chan_ntargets = MAX_FC_TARG;
96 #ifdef ISP2100_SCCLUN
97 /*
98 * 16 bits worth, but let's be reasonable..
99 */
100 chan->chan_nluns = 256;
101 #else
102 chan->chan_nluns = 16;
103 #endif
104 chan->chan_id = fcp->isp_loopid;
105 } else {
106 sdparam *sdp = isp->isp_param;
107 sdp = &sdp[i];
108
109 chan->chan_ntargets = MAX_TARGETS;
110 if (isp->isp_bustype == ISP_BT_SBUS)
111 chan->chan_nluns = 8;
112 else {
113 #if 0
114 /* Too many broken targets... */
115 if (isp->isp_fwrev >= ISP_FW_REV(7,55,0))
116 chan->chan_nluns = 32;
117 else
118 #endif
119 chan->chan_nluns = 7;
120 }
121 chan->chan_id = sdp->isp_initiator_id;
122 }
123 }
124
125 /*
126 * Send a SCSI Bus Reset (used to be done as part of attach,
127 * but now left to the OS outer layers).
128 */
129 if (IS_SCSI(isp)) {
130 for (i = 0; i < adapt->adapt_nchannels; i++)
131 (void) isp_control(isp, ISPCTL_RESET_BUS, &i);
132 SYS_DELAY(2*1000000);
133 }
134
135 /*
136 * Start the watchdog.
137 */
138 isp->isp_dogactive = 1;
139 timeout(isp_watch, isp, WATCH_INTERVAL * hz);
140
141 /*
142 * And attach children (if any).
143 */
144 for (i = 0; i < adapt->adapt_nchannels; i++)
145 (void) config_found((void *)isp, &isp->isp_osinfo._channels[i],
146 scsiprint);
147 }
148
149 /*
150 * minphys our xfers
151 *
152 * Unfortunately, the buffer pointer describes the target device- not the
153 * adapter device, so we can't use the pointer to find out what kind of
154 * adapter we are and adjust accordingly.
155 */
156
157 static void
158 ispminphys(bp)
159 struct buf *bp;
160 {
161 /*
162 * XX: Only the 1020 has a 24 bit limit.
163 */
164 if (bp->b_bcount >= (1 << 24)) {
165 bp->b_bcount = (1 << 24);
166 }
167 minphys(bp);
168 }
169
170 static int
171 ispioctl(chan, cmd, addr, flag, p)
172 struct scsipi_channel *chan;
173 u_long cmd;
174 caddr_t addr;
175 int flag;
176 struct proc *p;
177 {
178 struct ispsoftc *isp = (void *)chan->chan_adapter->adapt_dev;
179 int s, ch, retval = ENOTTY;
180
181 switch (cmd) {
182 case SCBUSIORESET:
183 ch = chan->chan_channel;
184 s = splbio();
185 if (isp_control(isp, ISPCTL_RESET_BUS, &ch))
186 retval = EIO;
187 else
188 retval = 0;
189 (void) splx(s);
190 break;
191 default:
192 break;
193 }
194 return (retval);
195 }
196
197 static void
198 isp_scsipi_request(chan, req, arg)
199 struct scsipi_channel *chan;
200 scsipi_adapter_req_t req;
201 void *arg;
202 {
203 struct scsipi_xfer *xs;
204 struct ispsoftc *isp = (void *)chan->chan_adapter->adapt_dev;
205 int result, s;
206
207 switch (req) {
208 case ADAPTER_REQ_RUN_XFER:
209 s = splbio();
210 if (isp->isp_state < ISP_RUNSTATE) {
211 DISABLE_INTS(isp);
212 isp_init(isp);
213 if (isp->isp_state != ISP_INITSTATE) {
214 ENABLE_INTS(isp);
215 (void) splx(s);
216 XS_SETERR(xs, HBA_BOTCH);
217 XS_CMD_DONE(xs);
218 return;
219 }
220 isp->isp_state = ISP_RUNSTATE;
221 ENABLE_INTS(isp);
222 }
223
224 /*
225 * Check for queue blockage...
226 * XXX Should be done in the mid-layer.
227 */
228 if (isp->isp_osinfo.blocked) {
229 if (xs->xs_control & XS_CTL_POLL) {
230 xs->error = XS_BUSY;
231 scsipi_done(xs);
232 splx(s);
233 return;
234 }
235 TAILQ_INSERT_TAIL(&isp->isp_osinfo.waitq, xs,
236 channel_q);
237 splx(s);
238 return;
239 }
240
241 DISABLE_INTS(isp);
242 result = ispscsicmd(xs);
243 ENABLE_INTS(isp);
244
245 switch (result) {
246 case CMD_QUEUED:
247 /*
248 * If we're not polling for completion, just return.
249 */
250 if ((xs->xs_control & XS_CTL_POLL) == 0) {
251 (void) splx(s);
252 return;
253 }
254 break;
255
256 case CMD_EAGAIN:
257 /*
258 * Adapter resource shortage of some sort. Should
259 * retry later.
260 */
261 XS_SETERR(xs, XS_RESOURCE_SHORTAGE);
262 XS_CMD_DONE(xs);
263 (void) splx(s);
264 return;
265
266 case CMD_RQLATER:
267 /*
268 * XXX I think what we should do here is freeze
269 * XXX the channel queue, and do a timed thaw
270 * XXX of it. Need to add this to the mid-layer.
271 */
272 if ((xs->xs_control & XS_CTL_POLL) != 0) {
273 XS_SETERR(xs, XS_DRIVER_STUFFUP);
274 XS_CMD_DONE(xs);
275 } else
276 timeout(isp_command_requeue, xs, hz);
277 (void) splx(s);
278 return;
279
280 case CMD_COMPLETE:
281 /*
282 * Something went horribly wrong, xs->error is set,
283 * and we just need to finish it off.
284 */
285 XS_CMD_DONE(xs);
286 (void) splx(s);
287 return;
288 }
289
290 /*
291 * If we can't use interrupts, poll on completion.
292 */
293 if (isp_poll(isp, xs, XS_TIME(xs))) {
294 /*
295 * If no other error occurred but we didn't finish,
296 * something bad happened.
297 */
298 if (XS_IS_CMD_DONE(xs) == 0) {
299 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
300 isp_restart(isp);
301 }
302 if (XS_NOERR(xs)) {
303 XS_SETERR(xs, HBA_BOTCH);
304 }
305 XS_CMD_DONE(xs);
306 }
307 }
308 (void) splx(s);
309 return;
310
311 case ADAPTER_REQ_GROW_RESOURCES:
312 /* XXX Not supported. */
313 return;
314
315 case ADAPTER_REQ_SET_XFER_MODE:
316 if (isp->isp_type & ISP_HA_SCSI) {
317 sdparam *sdp = isp->isp_param;
318 struct scsipi_periph *periph = arg;
319 u_int16_t flags;
320
321 sdp = &sdp[periph->periph_channel->chan_channel];
322
323 flags =
324 sdp->isp_devparam[periph->periph_target].dev_flags;
325 flags &= ~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING);
326
327 if (periph->periph_cap & PERIPH_CAP_SYNC)
328 flags |= DPARM_SYNC;
329
330 if (periph->periph_cap & PERIPH_CAP_WIDE16)
331 flags |= DPARM_WIDE;
332
333 if (periph->periph_cap & PERIPH_CAP_TQING)
334 flags |= DPARM_TQING;
335
336 sdp->isp_devparam[periph->periph_target].dev_flags =
337 flags;
338 sdp->isp_devparam[periph->periph_target].dev_update = 1;
339 isp->isp_update |=
340 (1 << periph->periph_channel->chan_channel);
341 (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
342 }
343 return;
344
345 case ADAPTER_REQ_GET_XFER_MODE:
346 if (isp->isp_type & ISP_HA_SCSI) {
347 sdparam *sdp = isp->isp_param;
348 struct scsipi_periph *periph = arg;
349 u_int16_t flags;
350
351 sdp = &sdp[periph->periph_channel->chan_channel];
352
353 periph->periph_mode = 0;
354 periph->periph_period = 0;
355 periph->periph_offset = 0;
356
357 flags =
358 sdp->isp_devparam[periph->periph_target].cur_dflags;
359
360 if (flags & DPARM_SYNC) {
361 periph->periph_mode |= PERIPH_CAP_SYNC;
362 periph->periph_period =
363 sdp->isp_devparam[periph->periph_target].cur_period;
364 periph->periph_offset =
365 sdp->isp_devparam[periph->periph_target].cur_offset;
366 }
367 if (flags & DPARM_WIDE)
368 periph->periph_mode |= PERIPH_CAP_WIDE16;
369 if (flags & DPARM_TQING)
370 periph->periph_mode |= PERIPH_CAP_TQING;
371
372 periph->periph_flags |= PERIPH_MODE_VALID;
373 }
374 return;
375 }
376 }
377
378 static int
379 isp_poll(isp, xs, mswait)
380 struct ispsoftc *isp;
381 ISP_SCSI_XFER_T *xs;
382 int mswait;
383 {
384
385 while (mswait) {
386 /* Try the interrupt handling routine */
387 (void)isp_intr((void *)isp);
388
389 /* See if the xs is now done */
390 if (XS_IS_CMD_DONE(xs)) {
391 return (0);
392 }
393 SYS_DELAY(1000); /* wait one millisecond */
394 mswait--;
395 }
396 return (1);
397 }
398
399 static void
400 isp_watch(arg)
401 void *arg;
402 {
403 int i;
404 struct ispsoftc *isp = arg;
405 struct scsipi_xfer *xs;
406 int s;
407
408 /*
409 * Look for completely dead commands (but not polled ones).
410 */
411 s = splbio();
412 for (i = 0; i < isp->isp_maxcmds; i++) {
413 xs = isp->isp_xflist[i];
414 if (xs == NULL) {
415 continue;
416 }
417 if (xs->timeout == 0 || (xs->xs_control & XS_CTL_POLL)) {
418 continue;
419 }
420 xs->timeout -= (WATCH_INTERVAL * 1000);
421 /*
422 * Avoid later thinking that this
423 * transaction is not being timed.
424 * Then give ourselves to watchdog
425 * periods of grace.
426 */
427 if (xs->timeout == 0) {
428 xs->timeout = 1;
429 } else if (xs->timeout > -(2 * WATCH_INTERVAL * 1000)) {
430 continue;
431 }
432 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
433 printf("%s: isp_watch failed to abort command\n",
434 isp->isp_name);
435 isp_restart(isp);
436 break;
437 }
438 }
439 timeout(isp_watch, isp, WATCH_INTERVAL * hz);
440 isp->isp_dogactive = 1;
441 (void) splx(s);
442 }
443
444 /*
445 * Free any associated resources prior to decommissioning and
446 * set the card to a known state (so it doesn't wake up and kick
447 * us when we aren't expecting it to).
448 *
449 * Locks are held before coming here.
450 */
451 void
452 isp_uninit(isp)
453 struct ispsoftc *isp;
454 {
455 ISP_ILOCKVAL_DECL;
456 ISP_ILOCK(isp);
457 /*
458 * Leave with interrupts disabled.
459 */
460 DISABLE_INTS(isp);
461
462 /*
463 * Turn off the watchdog (if active).
464 */
465 if (isp->isp_dogactive) {
466 untimeout(isp_watch, isp);
467 isp->isp_dogactive = 0;
468 }
469
470 ISP_IUNLOCK(isp);
471 }
472
473 /*
474 * Restart function for a command to be requeued later.
475 */
476 static void
477 isp_command_requeue(arg)
478 void *arg;
479 {
480 struct scsipi_xfer *xs = arg;
481 int s;
482
483 s = splbio();
484 scsipi_adapter_request(xs->xs_periph->periph_channel,
485 ADAPTER_REQ_RUN_XFER, xs);
486 (void) splx(s);
487 }
488
489 /*
490 * Restart function after a LOOP UP event (e.g.),
491 * done as a timeout for some hysteresis.
492 */
493 static void
494 isp_internal_restart(arg)
495 void *arg;
496 {
497 struct ispsoftc *isp = arg;
498 int result, nrestarted = 0, s;
499
500 s = splbio();
501 if (isp->isp_osinfo.blocked == 0) {
502 struct scsipi_xfer *xs;
503 while ((xs = TAILQ_FIRST(&isp->isp_osinfo.waitq)) != NULL) {
504 TAILQ_REMOVE(&isp->isp_osinfo.waitq, xs, channel_q);
505 DISABLE_INTS(isp);
506 result = ispscsicmd(xs);
507 ENABLE_INTS(isp);
508 if (result != CMD_QUEUED) {
509 printf("%s: botched command restart (0x%x)\n",
510 isp->isp_name, result);
511 if (XS_ERR(xs) == XS_NOERROR)
512 XS_SETERR(xs, HBA_BOTCH);
513 XS_CMD_DONE(xs);
514 }
515 nrestarted++;
516 }
517 printf("%s: requeued %d commands\n", isp->isp_name, nrestarted);
518 }
519 (void) splx(s);
520 }
521
522 int
523 isp_async(isp, cmd, arg)
524 struct ispsoftc *isp;
525 ispasync_t cmd;
526 void *arg;
527 {
528 int bus;
529 int s = splbio();
530 switch (cmd) {
531 case ISPASYNC_NEW_TGT_PARAMS:
532 /*
533 * XXX Should we really do anything here?
534 */
535 break;
536 case ISPASYNC_BUS_RESET:
537 if (arg)
538 bus = *((int *) arg);
539 else
540 bus = 0;
541 printf("%s: SCSI bus %d reset detected\n", isp->isp_name, bus);
542 break;
543 case ISPASYNC_LOOP_DOWN:
544 /*
545 * Hopefully we get here in time to minimize the number
546 * of commands we are firing off that are sure to die.
547 */
548 isp->isp_osinfo.blocked = 1;
549 printf("%s: Loop DOWN\n", isp->isp_name);
550 break;
551 case ISPASYNC_LOOP_UP:
552 isp->isp_osinfo.blocked = 0;
553 timeout(isp_internal_restart, isp, 1);
554 printf("%s: Loop UP\n", isp->isp_name);
555 break;
556 case ISPASYNC_PDB_CHANGED:
557 if (IS_FC(isp) && isp->isp_dblev) {
558 const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
559 "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
560 const static char *roles[4] = {
561 "No", "Target", "Initiator", "Target/Initiator"
562 };
563 char *ptr;
564 fcparam *fcp = isp->isp_param;
565 int tgt = *((int *) arg);
566 struct lportdb *lp = &fcp->portdb[tgt];
567
568 if (lp->valid) {
569 ptr = "arrived";
570 } else {
571 ptr = "disappeared";
572 }
573 printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid,
574 roles[lp->roles & 0x3], ptr,
575 (u_int32_t) (lp->port_wwn >> 32),
576 (u_int32_t) (lp->port_wwn & 0xffffffffLL),
577 (u_int32_t) (lp->node_wwn >> 32),
578 (u_int32_t) (lp->node_wwn & 0xffffffffLL));
579 break;
580 }
581 #ifdef ISP2100_FABRIC
582 case ISPASYNC_CHANGE_NOTIFY:
583 printf("%s: Name Server Database Changed\n", isp->isp_name);
584 break;
585 case ISPASYNC_FABRIC_DEV:
586 {
587 int target;
588 struct lportdb *lp;
589 sns_scrsp_t *resp = (sns_scrsp_t *) arg;
590 u_int32_t portid;
591 u_int64_t wwn;
592 fcparam *fcp = isp->isp_param;
593
594 portid =
595 (((u_int32_t) resp->snscb_port_id[0]) << 16) |
596 (((u_int32_t) resp->snscb_port_id[1]) << 8) |
597 (((u_int32_t) resp->snscb_port_id[2]));
598 wwn =
599 (((u_int64_t)resp->snscb_portname[0]) << 56) |
600 (((u_int64_t)resp->snscb_portname[1]) << 48) |
601 (((u_int64_t)resp->snscb_portname[2]) << 40) |
602 (((u_int64_t)resp->snscb_portname[3]) << 32) |
603 (((u_int64_t)resp->snscb_portname[4]) << 24) |
604 (((u_int64_t)resp->snscb_portname[5]) << 16) |
605 (((u_int64_t)resp->snscb_portname[6]) << 8) |
606 (((u_int64_t)resp->snscb_portname[7]));
607 printf("%s: Fabric Device (Type 0x%x)@PortID 0x%x WWN "
608 "0x%08x%08x\n", isp->isp_name, resp->snscb_port_type,
609 portid, ((u_int32_t)(wwn >> 32)),
610 ((u_int32_t)(wwn & 0xffffffff)));
611 if (resp->snscb_port_type != 2)
612 break;
613 for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
614 lp = &fcp->portdb[target];
615 if (lp->port_wwn == wwn)
616 break;
617 }
618 if (target < MAX_FC_TARG) {
619 break;
620 }
621 for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
622 lp = &fcp->portdb[target];
623 if (lp->port_wwn == 0)
624 break;
625 }
626 if (target == MAX_FC_TARG) {
627 printf("%s: no more space for fabric devices\n",
628 isp->isp_name);
629 return (-1);
630 }
631 lp->port_wwn = lp->node_wwn = wwn;
632 lp->portid = portid;
633 break;
634 }
635 #endif
636 default:
637 break;
638 }
639 (void) splx(s);
640 return (0);
641 }
642