isp_netbsd.c revision 1.18.2.2 1 /* $NetBSD: isp_netbsd.c,v 1.18.2.2 1999/10/19 20:02:23 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 xs = arg;
210 s = splbio();
211 if (isp->isp_state < ISP_RUNSTATE) {
212 DISABLE_INTS(isp);
213 isp_init(isp);
214 if (isp->isp_state != ISP_INITSTATE) {
215 ENABLE_INTS(isp);
216 (void) splx(s);
217 XS_SETERR(xs, HBA_BOTCH);
218 XS_CMD_DONE(xs);
219 return;
220 }
221 isp->isp_state = ISP_RUNSTATE;
222 ENABLE_INTS(isp);
223 }
224
225 /*
226 * Check for queue blockage...
227 * XXX Should be done in the mid-layer.
228 */
229 if (isp->isp_osinfo.blocked) {
230 if (xs->xs_control & XS_CTL_POLL) {
231 xs->error = XS_BUSY;
232 scsipi_done(xs);
233 splx(s);
234 return;
235 }
236 TAILQ_INSERT_TAIL(&isp->isp_osinfo.waitq, xs,
237 channel_q);
238 splx(s);
239 return;
240 }
241
242 DISABLE_INTS(isp);
243 result = ispscsicmd(xs);
244 ENABLE_INTS(isp);
245
246 switch (result) {
247 case CMD_QUEUED:
248 /*
249 * If we're not polling for completion, just return.
250 */
251 if ((xs->xs_control & XS_CTL_POLL) == 0) {
252 (void) splx(s);
253 return;
254 }
255 break;
256
257 case CMD_EAGAIN:
258 /*
259 * Adapter resource shortage of some sort. Should
260 * retry later.
261 */
262 XS_SETERR(xs, XS_RESOURCE_SHORTAGE);
263 XS_CMD_DONE(xs);
264 (void) splx(s);
265 return;
266
267 case CMD_RQLATER:
268 /*
269 * XXX I think what we should do here is freeze
270 * XXX the channel queue, and do a timed thaw
271 * XXX of it. Need to add this to the mid-layer.
272 */
273 if ((xs->xs_control & XS_CTL_POLL) != 0) {
274 XS_SETERR(xs, XS_DRIVER_STUFFUP);
275 XS_CMD_DONE(xs);
276 } else
277 timeout(isp_command_requeue, xs, hz);
278 (void) splx(s);
279 return;
280
281 case CMD_COMPLETE:
282 /*
283 * Something went horribly wrong, xs->error is set,
284 * and we just need to finish it off.
285 */
286 XS_CMD_DONE(xs);
287 (void) splx(s);
288 return;
289 }
290
291 /*
292 * If we can't use interrupts, poll on completion.
293 */
294 if (isp_poll(isp, xs, XS_TIME(xs))) {
295 /*
296 * If no other error occurred but we didn't finish,
297 * something bad happened.
298 */
299 if (XS_IS_CMD_DONE(xs) == 0) {
300 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
301 isp_restart(isp);
302 }
303 if (XS_NOERR(xs)) {
304 XS_SETERR(xs, HBA_BOTCH);
305 }
306 XS_CMD_DONE(xs);
307 }
308 }
309 (void) splx(s);
310 return;
311
312 case ADAPTER_REQ_GROW_RESOURCES:
313 /* XXX Not supported. */
314 return;
315
316 case ADAPTER_REQ_SET_XFER_MODE:
317 if (isp->isp_type & ISP_HA_SCSI) {
318 sdparam *sdp = isp->isp_param;
319 struct scsipi_periph *periph = arg;
320 u_int16_t flags;
321
322 sdp = &sdp[periph->periph_channel->chan_channel];
323
324 flags =
325 sdp->isp_devparam[periph->periph_target].dev_flags;
326 flags &= ~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING);
327
328 if (periph->periph_cap & PERIPH_CAP_SYNC)
329 flags |= DPARM_SYNC;
330
331 if (periph->periph_cap & PERIPH_CAP_WIDE16)
332 flags |= DPARM_WIDE;
333
334 if (periph->periph_cap & PERIPH_CAP_TQING)
335 flags |= DPARM_TQING;
336
337 sdp->isp_devparam[periph->periph_target].dev_flags =
338 flags;
339 sdp->isp_devparam[periph->periph_target].dev_update = 1;
340 isp->isp_update |=
341 (1 << periph->periph_channel->chan_channel);
342 (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
343 }
344 return;
345
346 case ADAPTER_REQ_GET_XFER_MODE:
347 if (isp->isp_type & ISP_HA_SCSI) {
348 sdparam *sdp = isp->isp_param;
349 struct scsipi_periph *periph = arg;
350 u_int16_t flags;
351
352 sdp = &sdp[periph->periph_channel->chan_channel];
353
354 periph->periph_mode = 0;
355 periph->periph_period = 0;
356 periph->periph_offset = 0;
357
358 flags =
359 sdp->isp_devparam[periph->periph_target].cur_dflags;
360
361 if (flags & DPARM_SYNC) {
362 periph->periph_mode |= PERIPH_CAP_SYNC;
363 periph->periph_period =
364 sdp->isp_devparam[periph->periph_target].cur_period;
365 periph->periph_offset =
366 sdp->isp_devparam[periph->periph_target].cur_offset;
367 }
368 if (flags & DPARM_WIDE)
369 periph->periph_mode |= PERIPH_CAP_WIDE16;
370 if (flags & DPARM_TQING)
371 periph->periph_mode |= PERIPH_CAP_TQING;
372
373 periph->periph_flags |= PERIPH_MODE_VALID;
374 }
375 return;
376 }
377 }
378
379 static int
380 isp_poll(isp, xs, mswait)
381 struct ispsoftc *isp;
382 ISP_SCSI_XFER_T *xs;
383 int mswait;
384 {
385
386 while (mswait) {
387 /* Try the interrupt handling routine */
388 (void)isp_intr((void *)isp);
389
390 /* See if the xs is now done */
391 if (XS_IS_CMD_DONE(xs)) {
392 return (0);
393 }
394 SYS_DELAY(1000); /* wait one millisecond */
395 mswait--;
396 }
397 return (1);
398 }
399
400 static void
401 isp_watch(arg)
402 void *arg;
403 {
404 int i;
405 struct ispsoftc *isp = arg;
406 struct scsipi_xfer *xs;
407 int s;
408
409 /*
410 * Look for completely dead commands (but not polled ones).
411 */
412 s = splbio();
413 for (i = 0; i < isp->isp_maxcmds; i++) {
414 xs = isp->isp_xflist[i];
415 if (xs == NULL) {
416 continue;
417 }
418 if (xs->timeout == 0 || (xs->xs_control & XS_CTL_POLL)) {
419 continue;
420 }
421 xs->timeout -= (WATCH_INTERVAL * 1000);
422 /*
423 * Avoid later thinking that this
424 * transaction is not being timed.
425 * Then give ourselves to watchdog
426 * periods of grace.
427 */
428 if (xs->timeout == 0) {
429 xs->timeout = 1;
430 } else if (xs->timeout > -(2 * WATCH_INTERVAL * 1000)) {
431 continue;
432 }
433 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
434 printf("%s: isp_watch failed to abort command\n",
435 isp->isp_name);
436 isp_restart(isp);
437 break;
438 }
439 }
440 timeout(isp_watch, isp, WATCH_INTERVAL * hz);
441 isp->isp_dogactive = 1;
442 (void) splx(s);
443 }
444
445 /*
446 * Free any associated resources prior to decommissioning and
447 * set the card to a known state (so it doesn't wake up and kick
448 * us when we aren't expecting it to).
449 *
450 * Locks are held before coming here.
451 */
452 void
453 isp_uninit(isp)
454 struct ispsoftc *isp;
455 {
456 ISP_ILOCKVAL_DECL;
457 ISP_ILOCK(isp);
458 /*
459 * Leave with interrupts disabled.
460 */
461 DISABLE_INTS(isp);
462
463 /*
464 * Turn off the watchdog (if active).
465 */
466 if (isp->isp_dogactive) {
467 untimeout(isp_watch, isp);
468 isp->isp_dogactive = 0;
469 }
470
471 ISP_IUNLOCK(isp);
472 }
473
474 /*
475 * Restart function for a command to be requeued later.
476 */
477 static void
478 isp_command_requeue(arg)
479 void *arg;
480 {
481 struct scsipi_xfer *xs = arg;
482 int s;
483
484 s = splbio();
485 scsipi_adapter_request(xs->xs_periph->periph_channel,
486 ADAPTER_REQ_RUN_XFER, xs);
487 (void) splx(s);
488 }
489
490 /*
491 * Restart function after a LOOP UP event (e.g.),
492 * done as a timeout for some hysteresis.
493 */
494 static void
495 isp_internal_restart(arg)
496 void *arg;
497 {
498 struct ispsoftc *isp = arg;
499 int result, nrestarted = 0, s;
500
501 s = splbio();
502 if (isp->isp_osinfo.blocked == 0) {
503 struct scsipi_xfer *xs;
504 while ((xs = TAILQ_FIRST(&isp->isp_osinfo.waitq)) != NULL) {
505 TAILQ_REMOVE(&isp->isp_osinfo.waitq, xs, channel_q);
506 DISABLE_INTS(isp);
507 result = ispscsicmd(xs);
508 ENABLE_INTS(isp);
509 if (result != CMD_QUEUED) {
510 printf("%s: botched command restart (0x%x)\n",
511 isp->isp_name, result);
512 if (XS_ERR(xs) == XS_NOERROR)
513 XS_SETERR(xs, HBA_BOTCH);
514 XS_CMD_DONE(xs);
515 }
516 nrestarted++;
517 }
518 printf("%s: requeued %d commands\n", isp->isp_name, nrestarted);
519 }
520 (void) splx(s);
521 }
522
523 int
524 isp_async(isp, cmd, arg)
525 struct ispsoftc *isp;
526 ispasync_t cmd;
527 void *arg;
528 {
529 int bus;
530 int s = splbio();
531 switch (cmd) {
532 case ISPASYNC_NEW_TGT_PARAMS:
533 /*
534 * XXX Should we really do anything here?
535 */
536 break;
537 case ISPASYNC_BUS_RESET:
538 if (arg)
539 bus = *((int *) arg);
540 else
541 bus = 0;
542 printf("%s: SCSI bus %d reset detected\n", isp->isp_name, bus);
543 break;
544 case ISPASYNC_LOOP_DOWN:
545 /*
546 * Hopefully we get here in time to minimize the number
547 * of commands we are firing off that are sure to die.
548 */
549 isp->isp_osinfo.blocked = 1;
550 printf("%s: Loop DOWN\n", isp->isp_name);
551 break;
552 case ISPASYNC_LOOP_UP:
553 isp->isp_osinfo.blocked = 0;
554 timeout(isp_internal_restart, isp, 1);
555 printf("%s: Loop UP\n", isp->isp_name);
556 break;
557 case ISPASYNC_PDB_CHANGED:
558 if (IS_FC(isp) && isp->isp_dblev) {
559 const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
560 "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
561 const static char *roles[4] = {
562 "No", "Target", "Initiator", "Target/Initiator"
563 };
564 char *ptr;
565 fcparam *fcp = isp->isp_param;
566 int tgt = *((int *) arg);
567 struct lportdb *lp = &fcp->portdb[tgt];
568
569 if (lp->valid) {
570 ptr = "arrived";
571 } else {
572 ptr = "disappeared";
573 }
574 printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid,
575 roles[lp->roles & 0x3], ptr,
576 (u_int32_t) (lp->port_wwn >> 32),
577 (u_int32_t) (lp->port_wwn & 0xffffffffLL),
578 (u_int32_t) (lp->node_wwn >> 32),
579 (u_int32_t) (lp->node_wwn & 0xffffffffLL));
580 break;
581 }
582 #ifdef ISP2100_FABRIC
583 case ISPASYNC_CHANGE_NOTIFY:
584 printf("%s: Name Server Database Changed\n", isp->isp_name);
585 break;
586 case ISPASYNC_FABRIC_DEV:
587 {
588 int target;
589 struct lportdb *lp;
590 sns_scrsp_t *resp = (sns_scrsp_t *) arg;
591 u_int32_t portid;
592 u_int64_t wwn;
593 fcparam *fcp = isp->isp_param;
594
595 portid =
596 (((u_int32_t) resp->snscb_port_id[0]) << 16) |
597 (((u_int32_t) resp->snscb_port_id[1]) << 8) |
598 (((u_int32_t) resp->snscb_port_id[2]));
599 wwn =
600 (((u_int64_t)resp->snscb_portname[0]) << 56) |
601 (((u_int64_t)resp->snscb_portname[1]) << 48) |
602 (((u_int64_t)resp->snscb_portname[2]) << 40) |
603 (((u_int64_t)resp->snscb_portname[3]) << 32) |
604 (((u_int64_t)resp->snscb_portname[4]) << 24) |
605 (((u_int64_t)resp->snscb_portname[5]) << 16) |
606 (((u_int64_t)resp->snscb_portname[6]) << 8) |
607 (((u_int64_t)resp->snscb_portname[7]));
608 printf("%s: Fabric Device (Type 0x%x)@PortID 0x%x WWN "
609 "0x%08x%08x\n", isp->isp_name, resp->snscb_port_type,
610 portid, ((u_int32_t)(wwn >> 32)),
611 ((u_int32_t)(wwn & 0xffffffff)));
612 if (resp->snscb_port_type != 2)
613 break;
614 for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
615 lp = &fcp->portdb[target];
616 if (lp->port_wwn == wwn)
617 break;
618 }
619 if (target < MAX_FC_TARG) {
620 break;
621 }
622 for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
623 lp = &fcp->portdb[target];
624 if (lp->port_wwn == 0)
625 break;
626 }
627 if (target == MAX_FC_TARG) {
628 printf("%s: no more space for fabric devices\n",
629 isp->isp_name);
630 return (-1);
631 }
632 lp->port_wwn = lp->node_wwn = wwn;
633 lp->portid = portid;
634 break;
635 }
636 #endif
637 default:
638 break;
639 }
640 (void) splx(s);
641 return (0);
642 }
643