bha.c revision 1.5 1 /* $NetBSD: bha.c,v 1.5 1996/11/05 03:04:28 jonathan Exp $ */
2
3 #undef BHADIAG
4 #ifdef DDB
5 #define integrate
6 #else
7 #define integrate static inline
8 #endif
9
10 /*
11 * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by Charles M. Hannum.
24 * 4. The name of the author may not be used to endorse or promote products
25 * derived from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Originally written by Julian Elischer (julian (at) tfs.com)
41 * for TRW Financial Systems for use under the MACH(2.5) operating system.
42 *
43 * TRW Financial Systems, in accordance with their agreement with Carnegie
44 * Mellon University, makes this software available to CMU to distribute
45 * or use in any manner that they see fit as long as this message is kept with
46 * the software. For this reason TFS also grants any other persons or
47 * organisations permission to use or modify this software.
48 *
49 * TFS supplies this software to be publicly redistributed
50 * on the understanding that TFS is not responsible for the correct
51 * functioning of this software in any circumstances.
52 */
53
54 #include <sys/types.h>
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/kernel.h>
58 #include <sys/errno.h>
59 #include <sys/ioctl.h>
60 #include <sys/device.h>
61 #include <sys/malloc.h>
62 #include <sys/buf.h>
63 #include <sys/proc.h>
64 #include <sys/user.h>
65
66 #include <machine/bus.h>
67 #include <machine/intr.h>
68
69 #include <scsi/scsi_all.h>
70 #include <scsi/scsiconf.h>
71
72 #include <dev/ic/bhareg.h>
73 #include <dev/ic/bhavar.h>
74
75 #ifndef DDB
76 #define Debugger() panic("should call debugger here (bha.c)")
77 #endif /* ! DDB */
78
79 #define KVTOPHYS(x) vtophys(x)
80
81 #ifdef BHADEBUG
82 int bha_debug = 0;
83 #endif /* BHADEBUG */
84
85 int bha_cmd __P((bus_space_tag_t, bus_space_handle_t, struct bha_softc *,
86 int, u_char *, int, u_char *));
87 integrate void bha_finish_ccbs __P((struct bha_softc *));
88 integrate void bha_reset_ccb __P((struct bha_softc *, struct bha_ccb *));
89 void bha_free_ccb __P((struct bha_softc *, struct bha_ccb *));
90 integrate void bha_init_ccb __P((struct bha_softc *, struct bha_ccb *));
91 struct bha_ccb *bha_get_ccb __P((struct bha_softc *, int));
92 struct bha_ccb *bha_ccb_phys_kv __P((struct bha_softc *, u_long));
93 void bha_queue_ccb __P((struct bha_softc *, struct bha_ccb *));
94 void bha_collect_mbo __P((struct bha_softc *));
95 void bha_start_ccbs __P((struct bha_softc *));
96 void bha_done __P((struct bha_softc *, struct bha_ccb *));
97 void bha_init __P((struct bha_softc *));
98 void bha_inquire_setup_information __P((struct bha_softc *));
99 void bhaminphys __P((struct buf *));
100 int bha_scsi_cmd __P((struct scsi_xfer *));
101 int bha_poll __P((struct bha_softc *, struct scsi_xfer *, int));
102 void bha_timeout __P((void *arg));
103
104 struct scsi_adapter bha_switch = {
105 bha_scsi_cmd,
106 bhaminphys,
107 0,
108 0,
109 };
110
111 /* the below structure is so we have a default dev struct for out link struct */
112 struct scsi_device bha_dev = {
113 NULL, /* Use default error handler */
114 NULL, /* have a queue, served by this */
115 NULL, /* have no async handler */
116 NULL, /* Use default 'done' routine */
117 };
118
119 struct cfdriver bha_cd = {
120 NULL, "bha", DV_DULL
121 };
122
123 #define BHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
124 #define BHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
125
126 /*
127 * bha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
128 *
129 * Activate Adapter command
130 * icnt: number of args (outbound bytes including opcode)
131 * ibuf: argument buffer
132 * ocnt: number of expected returned bytes
133 * obuf: result buffer
134 * wait: number of seconds to wait for response
135 *
136 * Performs an adapter command through the ports. Not to be confused with a
137 * scsi command, which is read in via the dma; one of the adapter commands
138 * tells it to read in a scsi command.
139 */
140 int
141 bha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
142 bus_space_tag_t iot;
143 bus_space_handle_t ioh;
144 struct bha_softc *sc;
145 int icnt, ocnt;
146 u_char *ibuf, *obuf;
147 {
148 const char *name;
149 register int i;
150 int wait;
151 u_char sts;
152 u_char opcode = ibuf[0];
153 int rbytes; /* bytes returned in obuf */
154
155 if (sc != NULL)
156 name = sc->sc_dev.dv_xname;
157 else
158 name = "(bha probe)";
159
160 /*
161 * Calculate a reasonable timeout for the command.
162 */
163 switch (opcode) {
164 case BHA_INQUIRE_DEVICES:
165 wait = 90 * 20000;
166 break;
167 default:
168 wait = 1 * 20000;
169 break;
170 }
171
172 /*
173 * Wait for the adapter to go idle, unless it's one of
174 * the commands which don't need this
175 */
176 if (opcode != BHA_MBO_INTR_EN) {
177 for (i = 20000; i; i--) { /* 1 sec? */
178 sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
179 if (sts & BHA_STAT_IDLE)
180 break;
181 delay(50);
182 }
183 if (!i) {
184 printf("%s: bha_cmd, host not idle(0x%x)\n",
185 name, sts);
186 return (-1);
187 }
188 }
189 /*
190 * Now that it is idle, if we expect output, preflush the
191 * queue feeding to us.
192 */
193 if (ocnt) {
194 while ((bus_space_read_1(iot, ioh, BHA_STAT_PORT)) &
195 BHA_STAT_DF)
196 bus_space_read_1(iot, ioh, BHA_DATA_PORT);
197 }
198 /*
199 * Output the command and the number of arguments given
200 * for each byte, first check the port is empty.
201 */
202 while (icnt--) {
203 for (i = wait; i; i--) {
204 sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
205 if (!(sts & BHA_STAT_CDF))
206 break;
207 delay(50);
208 }
209 if (!i) {
210 if (opcode != BHA_INQUIRE_REVISION)
211 printf("%s: bha_cmd, cmd/data port full\n",
212 name);
213 bus_space_write_1(iot, ioh, BHA_CTRL_PORT,
214 BHA_CTRL_SRST);
215 return (-1);
216 }
217 bus_space_write_1(iot, ioh, BHA_CMD_PORT, *ibuf++);
218 }
219 /*
220 * If we expect input, loop that many times, each time,
221 * looking for the data register to have valid data
222 */
223 rbytes = 0;
224 while (rbytes < ocnt) {
225 for (i = wait; i; i--) {
226 sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
227 if (sts & BHA_STAT_DF)
228 break;
229 delay(50);
230 }
231 if (!i) {
232 if (opcode != BHA_INQUIRE_REVISION)
233 printf("%s: bha_cmd, cmd/data port empty %d\n",
234 name, ocnt);
235 bus_space_write_1(iot, ioh, BHA_CTRL_PORT,
236 BHA_CTRL_SRST);
237 return (-1);
238 }
239 *obuf++ = bus_space_read_1(iot, ioh, BHA_DATA_PORT);
240 rbytes++;
241 }
242 /*
243 * Wait for the board to report a finished instruction.
244 * We may get an extra interrupt for the HACC signal, but this is
245 * unimportant.
246 */
247 if (opcode != BHA_MBO_INTR_EN) {
248 for (i = 20000; i; i--) { /* 1 sec? */
249 sts = bus_space_read_1(iot, ioh, BHA_INTR_PORT);
250 /* XXX Need to save this in the interrupt handler? */
251 if (sts & BHA_INTR_HACC)
252 break;
253 delay(50);
254 }
255 if (!i) {
256 printf("%s: bha_cmd, host not finished(0x%x)\n",
257 name, sts);
258 return (-1);
259 }
260 }
261 bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_IRST);
262 return (rbytes);
263 }
264
265 /*
266 * Attach all the sub-devices we can find
267 */
268 void
269 bha_attach(sc)
270 struct bha_softc *sc;
271 {
272
273 bha_inquire_setup_information(sc);
274 bha_init(sc);
275 TAILQ_INIT(&sc->sc_free_ccb);
276 TAILQ_INIT(&sc->sc_waiting_ccb);
277
278 /*
279 * fill in the prototype scsi_link.
280 */
281 sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE;
282 sc->sc_link.adapter_softc = sc;
283 sc->sc_link.adapter_target = sc->sc_scsi_dev;
284 sc->sc_link.adapter = &bha_switch;
285 sc->sc_link.device = &bha_dev;
286 sc->sc_link.openings = 4;
287
288 /*
289 * ask the adapter what subunits are present
290 */
291 config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
292 }
293
294 integrate void
295 bha_finish_ccbs(sc)
296 struct bha_softc *sc;
297 {
298 struct bha_mbx_in *wmbi;
299 struct bha_ccb *ccb;
300 int i;
301
302 wmbi = wmbx->tmbi;
303
304 if (wmbi->stat == BHA_MBI_FREE) {
305 for (i = 0; i < BHA_MBX_SIZE; i++) {
306 if (wmbi->stat != BHA_MBI_FREE) {
307 printf("%s: mbi not in round-robin order\n",
308 sc->sc_dev.dv_xname);
309 goto AGAIN;
310 }
311 bha_nextmbx(wmbi, wmbx, mbi);
312 }
313 #ifdef BHADIAGnot
314 printf("%s: mbi interrupt with no full mailboxes\n",
315 sc->sc_dev.dv_xname);
316 #endif
317 return;
318 }
319
320 AGAIN:
321 do {
322 ccb = bha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
323 if (!ccb) {
324 printf("%s: bad mbi ccb pointer; skipping\n",
325 sc->sc_dev.dv_xname);
326 goto next;
327 }
328
329 #ifdef BHADEBUG
330 if (bha_debug) {
331 u_char *cp = &ccb->scsi_cmd;
332 printf("op=%x %x %x %x %x %x\n",
333 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
334 printf("stat %x for mbi addr = 0x%08x, ",
335 wmbi->stat, wmbi);
336 printf("ccb addr = 0x%x\n", ccb);
337 }
338 #endif /* BHADEBUG */
339
340 switch (wmbi->stat) {
341 case BHA_MBI_OK:
342 case BHA_MBI_ERROR:
343 if ((ccb->flags & CCB_ABORT) != 0) {
344 /*
345 * If we already started an abort, wait for it
346 * to complete before clearing the CCB. We
347 * could instead just clear CCB_SENDING, but
348 * what if the mailbox was already received?
349 * The worst that happens here is that we clear
350 * the CCB a bit later than we need to. BFD.
351 */
352 goto next;
353 }
354 break;
355
356 case BHA_MBI_ABORT:
357 case BHA_MBI_UNKNOWN:
358 /*
359 * Even if the CCB wasn't found, we clear it anyway.
360 * See preceeding comment.
361 */
362 break;
363
364 default:
365 printf("%s: bad mbi status %02x; skipping\n",
366 sc->sc_dev.dv_xname, wmbi->stat);
367 goto next;
368 }
369
370 untimeout(bha_timeout, ccb);
371 bha_done(sc, ccb);
372
373 next:
374 wmbi->stat = BHA_MBI_FREE;
375 bha_nextmbx(wmbi, wmbx, mbi);
376 } while (wmbi->stat != BHA_MBI_FREE);
377
378 wmbx->tmbi = wmbi;
379 }
380
381 /*
382 * Catch an interrupt from the adaptor
383 */
384 int
385 bha_intr(arg)
386 void *arg;
387 {
388 struct bha_softc *sc = arg;
389 bus_space_tag_t iot = sc->sc_iot;
390 bus_space_handle_t ioh = sc->sc_ioh;
391 u_char sts;
392
393 #ifdef BHADEBUG
394 printf("%s: bha_intr ", sc->sc_dev.dv_xname);
395 #endif /* BHADEBUG */
396
397 /*
398 * First acknowlege the interrupt, Then if it's not telling about
399 * a completed operation just return.
400 */
401 sts = bus_space_read_1(iot, ioh, BHA_INTR_PORT);
402 if ((sts & BHA_INTR_ANYINTR) == 0)
403 return (0);
404 bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_IRST);
405
406 #ifdef BHADIAG
407 /* Make sure we clear CCB_SENDING before finishing a CCB. */
408 bha_collect_mbo(sc);
409 #endif
410
411 /* Mail box out empty? */
412 if (sts & BHA_INTR_MBOA) {
413 struct bha_toggle toggle;
414
415 toggle.cmd.opcode = BHA_MBO_INTR_EN;
416 toggle.cmd.enable = 0;
417 bha_cmd(iot, ioh, sc,
418 sizeof(toggle.cmd), (u_char *)&toggle.cmd,
419 0, (u_char *)0);
420 bha_start_ccbs(sc);
421 }
422
423 /* Mail box in full? */
424 if (sts & BHA_INTR_MBIF)
425 bha_finish_ccbs(sc);
426
427 return (1);
428 }
429
430 integrate void
431 bha_reset_ccb(sc, ccb)
432 struct bha_softc *sc;
433 struct bha_ccb *ccb;
434 {
435
436 ccb->flags = 0;
437 }
438
439 /*
440 * A ccb is put onto the free list.
441 */
442 void
443 bha_free_ccb(sc, ccb)
444 struct bha_softc *sc;
445 struct bha_ccb *ccb;
446 {
447 int s;
448
449 s = splbio();
450
451 bha_reset_ccb(sc, ccb);
452 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
453
454 /*
455 * If there were none, wake anybody waiting for one to come free,
456 * starting with queued entries.
457 */
458 if (ccb->chain.tqe_next == 0)
459 wakeup(&sc->sc_free_ccb);
460
461 splx(s);
462 }
463
464 integrate void
465 bha_init_ccb(sc, ccb)
466 struct bha_softc *sc;
467 struct bha_ccb *ccb;
468 {
469 int hashnum;
470
471 bzero(ccb, sizeof(struct bha_ccb));
472 /*
473 * put in the phystokv hash table
474 * Never gets taken out.
475 */
476 ccb->hashkey = KVTOPHYS(ccb);
477 hashnum = CCB_HASH(ccb->hashkey);
478 ccb->nexthash = sc->sc_ccbhash[hashnum];
479 sc->sc_ccbhash[hashnum] = ccb;
480 bha_reset_ccb(sc, ccb);
481 }
482
483 /*
484 * Get a free ccb
485 *
486 * If there are none, see if we can allocate a new one. If so, put it in
487 * the hash table too otherwise either return an error or sleep.
488 */
489 struct bha_ccb *
490 bha_get_ccb(sc, flags)
491 struct bha_softc *sc;
492 int flags;
493 {
494 struct bha_ccb *ccb;
495 int s;
496
497 s = splbio();
498
499 /*
500 * If we can and have to, sleep waiting for one to come free
501 * but only if we can't allocate a new one.
502 */
503 for (;;) {
504 ccb = sc->sc_free_ccb.tqh_first;
505 if (ccb) {
506 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
507 break;
508 }
509 if (sc->sc_numccbs < BHA_CCB_MAX) {
510 ccb = (struct bha_ccb *) malloc(sizeof(struct bha_ccb),
511 M_TEMP, M_NOWAIT);
512 if (!ccb) {
513 printf("%s: can't malloc ccb\n",
514 sc->sc_dev.dv_xname);
515 goto out;
516 }
517 bha_init_ccb(sc, ccb);
518 sc->sc_numccbs++;
519 break;
520 }
521 if ((flags & SCSI_NOSLEEP) != 0)
522 goto out;
523 tsleep(&sc->sc_free_ccb, PRIBIO, "bhaccb", 0);
524 }
525
526 ccb->flags |= CCB_ALLOC;
527
528 out:
529 splx(s);
530 return (ccb);
531 }
532
533 /*
534 * Given a physical address, find the ccb that it corresponds to.
535 */
536 struct bha_ccb *
537 bha_ccb_phys_kv(sc, ccb_phys)
538 struct bha_softc *sc;
539 u_long ccb_phys;
540 {
541 int hashnum = CCB_HASH(ccb_phys);
542 struct bha_ccb *ccb = sc->sc_ccbhash[hashnum];
543
544 while (ccb) {
545 if (ccb->hashkey == ccb_phys)
546 break;
547 ccb = ccb->nexthash;
548 }
549 return (ccb);
550 }
551
552 /*
553 * Queue a CCB to be sent to the controller, and send it if possible.
554 */
555 void
556 bha_queue_ccb(sc, ccb)
557 struct bha_softc *sc;
558 struct bha_ccb *ccb;
559 {
560
561 TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
562 bha_start_ccbs(sc);
563 }
564
565 /*
566 * Garbage collect mailboxes that are no longer in use.
567 */
568 void
569 bha_collect_mbo(sc)
570 struct bha_softc *sc;
571 {
572 struct bha_mbx_out *wmbo; /* Mail Box Out pointer */
573 #ifdef BHADIAG
574 struct bha_ccb *ccb;
575 #endif
576
577 wmbo = wmbx->cmbo;
578
579 while (sc->sc_mbofull > 0) {
580 if (wmbo->cmd != BHA_MBO_FREE)
581 break;
582
583 #ifdef BHADIAG
584 ccb = bha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
585 ccb->flags &= ~CCB_SENDING;
586 #endif
587
588 --sc->sc_mbofull;
589 bha_nextmbx(wmbo, wmbx, mbo);
590 }
591
592 wmbx->cmbo = wmbo;
593 }
594
595 /*
596 * Send as many CCBs as we have empty mailboxes for.
597 */
598 void
599 bha_start_ccbs(sc)
600 struct bha_softc *sc;
601 {
602 bus_space_tag_t iot = sc->sc_iot;
603 bus_space_handle_t ioh = sc->sc_ioh;
604 struct bha_mbx_out *wmbo; /* Mail Box Out pointer */
605 struct bha_ccb *ccb;
606
607 wmbo = wmbx->tmbo;
608
609 while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) {
610 if (sc->sc_mbofull >= BHA_MBX_SIZE) {
611 bha_collect_mbo(sc);
612 if (sc->sc_mbofull >= BHA_MBX_SIZE) {
613 struct bha_toggle toggle;
614
615 toggle.cmd.opcode = BHA_MBO_INTR_EN;
616 toggle.cmd.enable = 1;
617 bha_cmd(iot, ioh, sc,
618 sizeof(toggle.cmd), (u_char *)&toggle.cmd,
619 0, (u_char *)0);
620 break;
621 }
622 }
623
624 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
625 #ifdef BHADIAG
626 ccb->flags |= CCB_SENDING;
627 #endif
628
629 /* Link ccb to mbo. */
630 ltophys(KVTOPHYS(ccb), wmbo->ccb_addr);
631 if (ccb->flags & CCB_ABORT)
632 wmbo->cmd = BHA_MBO_ABORT;
633 else
634 wmbo->cmd = BHA_MBO_START;
635
636 /* Tell the card to poll immediately. */
637 bus_space_write_1(iot, ioh, BHA_CMD_PORT, BHA_START_SCSI);
638
639 if ((ccb->xs->flags & SCSI_POLL) == 0)
640 timeout(bha_timeout, ccb, (ccb->timeout * hz) / 1000);
641
642 ++sc->sc_mbofull;
643 bha_nextmbx(wmbo, wmbx, mbo);
644 }
645
646 wmbx->tmbo = wmbo;
647 }
648
649 /*
650 * We have a ccb which has been processed by the
651 * adaptor, now we look to see how the operation
652 * went. Wake up the owner if waiting
653 */
654 void
655 bha_done(sc, ccb)
656 struct bha_softc *sc;
657 struct bha_ccb *ccb;
658 {
659 struct scsi_sense_data *s1, *s2;
660 struct scsi_xfer *xs = ccb->xs;
661
662 SC_DEBUG(xs->sc_link, SDEV_DB2, ("bha_done\n"));
663 /*
664 * Otherwise, put the results of the operation
665 * into the xfer and call whoever started it
666 */
667 #ifdef BHADIAG
668 if (ccb->flags & CCB_SENDING) {
669 printf("%s: exiting ccb still in transit!\n",
670 sc->sc_dev.dv_xname);
671 Debugger();
672 return;
673 }
674 #endif
675 if ((ccb->flags & CCB_ALLOC) == 0) {
676 printf("%s: exiting ccb not allocated!\n",
677 sc->sc_dev.dv_xname);
678 Debugger();
679 return;
680 }
681 if (xs->error == XS_NOERROR) {
682 if (ccb->host_stat != BHA_OK) {
683 switch (ccb->host_stat) {
684 case BHA_SEL_TIMEOUT: /* No response */
685 xs->error = XS_SELTIMEOUT;
686 break;
687 default: /* Other scsi protocol messes */
688 printf("%s: host_stat %x\n",
689 sc->sc_dev.dv_xname, ccb->host_stat);
690 xs->error = XS_DRIVER_STUFFUP;
691 break;
692 }
693 } else if (ccb->target_stat != SCSI_OK) {
694 switch (ccb->target_stat) {
695 case SCSI_CHECK:
696 s1 = &ccb->scsi_sense;
697 s2 = &xs->sense;
698 *s2 = *s1;
699 xs->error = XS_SENSE;
700 break;
701 case SCSI_BUSY:
702 xs->error = XS_BUSY;
703 break;
704 default:
705 printf("%s: target_stat %x\n",
706 sc->sc_dev.dv_xname, ccb->target_stat);
707 xs->error = XS_DRIVER_STUFFUP;
708 break;
709 }
710 } else
711 xs->resid = 0;
712 }
713 bha_free_ccb(sc, ccb);
714 xs->flags |= ITSDONE;
715 scsi_done(xs);
716 }
717
718 /*
719 * Find the board and find it's irq/drq
720 */
721 int
722 bha_find(iot, ioh, sc)
723 bus_space_tag_t iot;
724 bus_space_handle_t ioh;
725 struct bha_softc *sc;
726 {
727 int i;
728 u_char sts;
729 struct bha_extended_inquire inquire;
730 struct bha_config config;
731 int irq, drq;
732
733 /* Check something is at the ports we need to access */
734 sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
735 if (sts == 0xFF)
736 return (0);
737
738 /*
739 * Reset board, If it doesn't respond, assume
740 * that it's not there.. good for the probe
741 */
742
743 bus_space_write_1(iot, ioh, BHA_CTRL_PORT,
744 BHA_CTRL_HRST | BHA_CTRL_SRST);
745
746 delay(100);
747 for (i = BHA_RESET_TIMEOUT; i; i--) {
748 sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
749 if (sts == (BHA_STAT_IDLE | BHA_STAT_INIT))
750 break;
751 delay(1000);
752 }
753 if (!i) {
754 #ifdef BHADEBUG
755 if (bha_debug)
756 printf("bha_find: No answer from buslogic board\n");
757 #endif /* BHADEBUG */
758 return (0);
759 }
760
761 /*
762 * The BusLogic cards implement an Adaptec 1542 (aha)-compatible
763 * interface. The native bha interface is not compatible with
764 * an aha. 1542. We need to ensure that we never match an
765 * Adaptec 1542. We must also avoid sending Adaptec-compatible
766 * commands to a real bha, lest it go into 1542 emulation mode.
767 * (On an indirect bus like ISA, we should always probe for BusLogic
768 * interfaces before Adaptec interfaces).
769 */
770
771 /*
772 * Make sure we don't match an AHA-1542A or AHA-1542B, by checking
773 * for an extended-geometry register. The 1542[AB] don't have one.
774 */
775 sts = bus_space_read_1(iot, ioh, BHA_EXTGEOM_PORT);
776 if (sts == 0xFF)
777 return (0);
778
779 /*
780 * Check that we actually know how to use this board.
781 */
782 delay(1000);
783 inquire.cmd.opcode = BHA_INQUIRE_EXTENDED;
784 inquire.cmd.len = sizeof(inquire.reply);
785 i = bha_cmd(iot, ioh, sc,
786 sizeof(inquire.cmd), (u_char *)&inquire.cmd,
787 sizeof(inquire.reply), (u_char *)&inquire.reply);
788
789 /*
790 * Some 1542Cs (CP, perhaps not CF, may depend on firmware rev)
791 * have the extended-geometry register and also respond to
792 * BHA_INQUIRE_EXTENDED. Make sure we never match such cards,
793 * by checking the size of the reply is what a BusLogic card returns.
794 */
795 if (i != sizeof(inquire.reply)) {
796 #ifdef BHADEBUG
797 printf("bha_find: board returned %d instead of %d to %s\n",
798 i, sizeof(inquire.reply), "INQUIRE_EXTENDED");
799 #endif
800 return (0);
801 }
802
803 /* OK, we know we've found a buslogic adaptor. */
804
805 switch (inquire.reply.bus_type) {
806 case BHA_BUS_TYPE_24BIT:
807 case BHA_BUS_TYPE_32BIT:
808 break;
809 case BHA_BUS_TYPE_MCA:
810 /* We don't grok MicroChannel (yet). */
811 return (0);
812 default:
813 printf("bha_find: illegal bus type %c\n",
814 inquire.reply.bus_type);
815 return (0);
816 }
817
818 /*
819 * Assume we have a board at this stage setup dma channel from
820 * jumpers and save int level
821 */
822 delay(1000);
823 config.cmd.opcode = BHA_INQUIRE_CONFIG;
824 bha_cmd(iot, ioh, sc,
825 sizeof(config.cmd), (u_char *)&config.cmd,
826 sizeof(config.reply), (u_char *)&config.reply);
827 switch (config.reply.chan) {
828 case EISADMA:
829 drq = -1;
830 break;
831 case CHAN0:
832 drq = 0;
833 break;
834 case CHAN5:
835 drq = 5;
836 break;
837 case CHAN6:
838 drq = 6;
839 break;
840 case CHAN7:
841 drq = 7;
842 break;
843 default:
844 printf("bha_find: illegal drq setting %x\n",
845 config.reply.chan);
846 return (0);
847 }
848
849 switch (config.reply.intr) {
850 case INT9:
851 irq = 9;
852 break;
853 case INT10:
854 irq = 10;
855 break;
856 case INT11:
857 irq = 11;
858 break;
859 case INT12:
860 irq = 12;
861 break;
862 case INT14:
863 irq = 14;
864 break;
865 case INT15:
866 irq = 15;
867 break;
868 default:
869 printf("bha_find: illegal irq setting %x\n",
870 config.reply.intr);
871 return (0);
872 }
873
874 /* if we want to fill in softc, do so now */
875 if (sc != NULL) {
876 sc->sc_irq = irq;
877 sc->sc_drq = drq;
878 sc->sc_scsi_dev = config.reply.scsi_dev;
879 }
880
881 return (1);
882 }
883
884
885 /*
886 * Disable the ISA-compatiblity ioports on PCI bha devices,
887 * to ensure they're not autoconfigured a second time as an ISA bha.
888 */
889 int
890 bha_disable_isacompat(sc)
891 struct bha_softc *sc;
892 {
893 struct bha_isadisable isa_disable;
894
895 isa_disable.cmd.opcode = BHA_MODIFY_IOPORT;
896 isa_disable.cmd.modifier = BHA_IOMODIFY_DISABLE1;
897 bha_cmd(sc->sc_iot, sc->sc_ioh, sc,
898 sizeof(isa_disable.cmd), (u_char*)&isa_disable.cmd,
899 0, 0);
900 return (0);
901 }
902
903
904 /*
905 * Start the board, ready for normal operation
906 */
907 void
908 bha_init(sc)
909 struct bha_softc *sc;
910 {
911 bus_space_tag_t iot = sc->sc_iot;
912 bus_space_handle_t ioh = sc->sc_ioh;
913 struct bha_devices devices;
914 struct bha_setup setup;
915 struct bha_mailbox mailbox;
916 struct bha_period period;
917 int i;
918
919 /* Enable round-robin scheme - appeared at firmware rev. 3.31. */
920 if (strcmp(sc->sc_firmware, "3.31") >= 0) {
921 struct bha_toggle toggle;
922
923 toggle.cmd.opcode = BHA_ROUND_ROBIN;
924 toggle.cmd.enable = 1;
925 bha_cmd(iot, ioh, sc,
926 sizeof(toggle.cmd), (u_char *)&toggle.cmd,
927 0, (u_char *)0);
928 }
929
930 /* Inquire Installed Devices (to force synchronous negotiation). */
931 devices.cmd.opcode = BHA_INQUIRE_DEVICES;
932 bha_cmd(iot, ioh, sc,
933 sizeof(devices.cmd), (u_char *)&devices.cmd,
934 sizeof(devices.reply), (u_char *)&devices.reply);
935
936 /* Obtain setup information from. */
937 setup.cmd.opcode = BHA_INQUIRE_SETUP;
938 setup.cmd.len = sizeof(setup.reply);
939 bha_cmd(iot, ioh, sc,
940 sizeof(setup.cmd), (u_char *)&setup.cmd,
941 sizeof(setup.reply), (u_char *)&setup.reply);
942
943 printf("%s: %s, %s\n",
944 sc->sc_dev.dv_xname,
945 setup.reply.sync_neg ? "sync" : "async",
946 setup.reply.parity ? "parity" : "no parity");
947
948 for (i = 0; i < 8; i++)
949 period.reply.period[i] = setup.reply.sync[i].period * 5 + 20;
950
951 if (sc->sc_firmware[0] >= '3') {
952 period.cmd.opcode = BHA_INQUIRE_PERIOD;
953 period.cmd.len = sizeof(period.reply);
954 bha_cmd(iot, ioh, sc,
955 sizeof(period.cmd), (u_char *)&period.cmd,
956 sizeof(period.reply), (u_char *)&period.reply);
957 }
958
959 for (i = 0; i < 8; i++) {
960 if (!setup.reply.sync[i].valid ||
961 (!setup.reply.sync[i].offset &&
962 !setup.reply.sync[i].period))
963 continue;
964 printf("%s targ %d: sync, offset %d, period %dnsec\n",
965 sc->sc_dev.dv_xname, i,
966 setup.reply.sync[i].offset, period.reply.period[i] * 10);
967 }
968
969 /*
970 * Set up initial mail box for round-robin operation.
971 */
972 for (i = 0; i < BHA_MBX_SIZE; i++) {
973 wmbx->mbo[i].cmd = BHA_MBO_FREE;
974 wmbx->mbi[i].stat = BHA_MBI_FREE;
975 }
976 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
977 wmbx->tmbi = &wmbx->mbi[0];
978 sc->sc_mbofull = 0;
979
980 /* Initialize mail box. */
981 mailbox.cmd.opcode = BHA_MBX_INIT_EXTENDED;
982 mailbox.cmd.nmbx = BHA_MBX_SIZE;
983 ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr);
984 bha_cmd(iot, ioh, sc,
985 sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
986 0, (u_char *)0);
987 }
988
989 void
990 bha_inquire_setup_information(sc)
991 struct bha_softc *sc;
992 {
993 bus_space_tag_t iot = sc->sc_iot;
994 bus_space_handle_t ioh = sc->sc_ioh;
995 struct bha_model model;
996 struct bha_revision revision;
997 struct bha_digit digit;
998 char *p;
999
1000 /*
1001 * Get the firmware revision.
1002 */
1003 p = sc->sc_firmware;
1004 revision.cmd.opcode = BHA_INQUIRE_REVISION;
1005 bha_cmd(iot, ioh, sc,
1006 sizeof(revision.cmd), (u_char *)&revision.cmd,
1007 sizeof(revision.reply), (u_char *)&revision.reply);
1008 *p++ = revision.reply.firm_revision;
1009 *p++ = '.';
1010 *p++ = revision.reply.firm_version;
1011 digit.cmd.opcode = BHA_INQUIRE_REVISION_3;
1012 bha_cmd(iot, ioh, sc,
1013 sizeof(digit.cmd), (u_char *)&digit.cmd,
1014 sizeof(digit.reply), (u_char *)&digit.reply);
1015 *p++ = digit.reply.digit;
1016 if (revision.reply.firm_revision >= '3' ||
1017 (revision.reply.firm_revision == '3' &&
1018 revision.reply.firm_version >= '3')) {
1019 digit.cmd.opcode = BHA_INQUIRE_REVISION_4;
1020 bha_cmd(iot, ioh, sc,
1021 sizeof(digit.cmd), (u_char *)&digit.cmd,
1022 sizeof(digit.reply), (u_char *)&digit.reply);
1023 *p++ = digit.reply.digit;
1024 }
1025 while (p > sc->sc_firmware && (p[-1] == ' ' || p[-1] == '\0'))
1026 p--;
1027 *p = '\0';
1028
1029 /*
1030 * Get the model number.
1031 */
1032 if (revision.reply.firm_revision >= '3') {
1033 p = sc->sc_model;
1034 model.cmd.opcode = BHA_INQUIRE_MODEL;
1035 model.cmd.len = sizeof(model.reply);
1036 bha_cmd(iot, ioh, sc,
1037 sizeof(model.cmd), (u_char *)&model.cmd,
1038 sizeof(model.reply), (u_char *)&model.reply);
1039 *p++ = model.reply.id[0];
1040 *p++ = model.reply.id[1];
1041 *p++ = model.reply.id[2];
1042 *p++ = model.reply.id[3];
1043 while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
1044 p--;
1045 *p++ = model.reply.version[0];
1046 *p++ = model.reply.version[1];
1047 while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
1048 p--;
1049 *p = '\0';
1050 } else
1051 strcpy(sc->sc_model, "542B");
1052
1053 printf("%s: model BT-%s, firmware %s\n", sc->sc_dev.dv_xname,
1054 sc->sc_model, sc->sc_firmware);
1055 }
1056
1057 void
1058 bhaminphys(bp)
1059 struct buf *bp;
1060 {
1061
1062 if (bp->b_bcount > ((BHA_NSEG - 1) << PGSHIFT))
1063 bp->b_bcount = ((BHA_NSEG - 1) << PGSHIFT);
1064 minphys(bp);
1065 }
1066
1067 /*
1068 * start a scsi operation given the command and the data address. Also needs
1069 * the unit, target and lu.
1070 */
1071 int
1072 bha_scsi_cmd(xs)
1073 struct scsi_xfer *xs;
1074 {
1075 struct scsi_link *sc_link = xs->sc_link;
1076 struct bha_softc *sc = sc_link->adapter_softc;
1077 struct bha_ccb *ccb;
1078 struct bha_scat_gath *sg;
1079 int seg; /* scatter gather seg being worked on */
1080 u_long thiskv, thisphys, nextphys;
1081 int bytes_this_seg, bytes_this_page, datalen, flags;
1082 #ifdef TFS
1083 struct iovec *iovp;
1084 #endif
1085 int s;
1086
1087 SC_DEBUG(sc_link, SDEV_DB2, ("bha_scsi_cmd\n"));
1088 /*
1089 * get a ccb to use. If the transfer
1090 * is from a buf (possibly from interrupt time)
1091 * then we can't allow it to sleep
1092 */
1093 flags = xs->flags;
1094 if ((ccb = bha_get_ccb(sc, flags)) == NULL) {
1095 xs->error = XS_DRIVER_STUFFUP;
1096 return (TRY_AGAIN_LATER);
1097 }
1098 ccb->xs = xs;
1099 ccb->timeout = xs->timeout;
1100
1101 /*
1102 * Put all the arguments for the xfer in the ccb
1103 */
1104 if (flags & SCSI_RESET) {
1105 ccb->opcode = BHA_RESET_CCB;
1106 ccb->scsi_cmd_length = 0;
1107 } else {
1108 /* can't use S/G if zero length */
1109 ccb->opcode = (xs->datalen ? BHA_INIT_SCAT_GATH_CCB
1110 : BHA_INITIATOR_CCB);
1111 bcopy(xs->cmd, &ccb->scsi_cmd,
1112 ccb->scsi_cmd_length = xs->cmdlen);
1113 }
1114
1115 if (xs->datalen) {
1116 sg = ccb->scat_gath;
1117 seg = 0;
1118 #ifdef TFS
1119 if (flags & SCSI_DATA_UIO) {
1120 iovp = ((struct uio *)xs->data)->uio_iov;
1121 datalen = ((struct uio *)xs->data)->uio_iovcnt;
1122 xs->datalen = 0;
1123 while (datalen && seg < BHA_NSEG) {
1124 ltophys(iovp->iov_base, sg->seg_addr);
1125 ltophys(iovp->iov_len, sg->seg_len);
1126 xs->datalen += iovp->iov_len;
1127 SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
1128 iovp->iov_len, iovp->iov_base));
1129 sg++;
1130 iovp++;
1131 seg++;
1132 datalen--;
1133 }
1134 } else
1135 #endif /* TFS */
1136 {
1137 /*
1138 * Set up the scatter-gather block.
1139 */
1140 SC_DEBUG(sc_link, SDEV_DB4,
1141 ("%d @0x%x:- ", xs->datalen, xs->data));
1142
1143 datalen = xs->datalen;
1144 thiskv = (int)xs->data;
1145 thisphys = KVTOPHYS(thiskv);
1146
1147 while (datalen && seg < BHA_NSEG) {
1148 bytes_this_seg = 0;
1149
1150 /* put in the base address */
1151 ltophys(thisphys, sg->seg_addr);
1152
1153 SC_DEBUGN(sc_link, SDEV_DB4,
1154 ("0x%x", thisphys));
1155
1156 /* do it at least once */
1157 nextphys = thisphys;
1158 while (datalen && thisphys == nextphys) {
1159 /*
1160 * This page is contiguous (physically)
1161 * with the the last, just extend the
1162 * length
1163 */
1164 /* how far to the end of the page */
1165 nextphys =
1166 (thisphys & ~PGOFSET) + NBPG;
1167 bytes_this_page = nextphys - thisphys;
1168 /**** or the data ****/
1169 bytes_this_page = min(bytes_this_page,
1170 datalen);
1171 bytes_this_seg += bytes_this_page;
1172 datalen -= bytes_this_page;
1173
1174 /* get more ready for the next page */
1175 thiskv = (thiskv & ~PGOFSET) + NBPG;
1176 if (datalen)
1177 thisphys = KVTOPHYS(thiskv);
1178 }
1179 /*
1180 * next page isn't contiguous, finish the seg
1181 */
1182 SC_DEBUGN(sc_link, SDEV_DB4,
1183 ("(0x%x)", bytes_this_seg));
1184 ltophys(bytes_this_seg, sg->seg_len);
1185 sg++;
1186 seg++;
1187 }
1188 }
1189 /* end of iov/kv decision */
1190 SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
1191 if (datalen) {
1192 /*
1193 * there's still data, must have run out of segs!
1194 */
1195 printf("%s: bha_scsi_cmd, more than %d dma segs\n",
1196 sc->sc_dev.dv_xname, BHA_NSEG);
1197 goto bad;
1198 }
1199 ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
1200 ltophys(seg * sizeof(struct bha_scat_gath), ccb->data_length);
1201 } else { /* No data xfer, use non S/G values */
1202 ltophys(0, ccb->data_addr);
1203 ltophys(0, ccb->data_length);
1204 }
1205
1206 ccb->data_out = 0;
1207 ccb->data_in = 0;
1208 ccb->target = sc_link->target;
1209 ccb->lun = sc_link->lun;
1210 ltophys(KVTOPHYS(&ccb->scsi_sense), ccb->sense_ptr);
1211 ccb->req_sense_length = sizeof(ccb->scsi_sense);
1212 ccb->host_stat = 0x00;
1213 ccb->target_stat = 0x00;
1214 ccb->link_id = 0;
1215 ltophys(0, ccb->link_addr);
1216
1217 s = splbio();
1218 bha_queue_ccb(sc, ccb);
1219 splx(s);
1220
1221 /*
1222 * Usually return SUCCESSFULLY QUEUED
1223 */
1224 SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
1225 if ((flags & SCSI_POLL) == 0)
1226 return (SUCCESSFULLY_QUEUED);
1227
1228 /*
1229 * If we can't use interrupts, poll on completion
1230 */
1231 if (bha_poll(sc, xs, ccb->timeout)) {
1232 bha_timeout(ccb);
1233 if (bha_poll(sc, xs, ccb->timeout))
1234 bha_timeout(ccb);
1235 }
1236 return (COMPLETE);
1237
1238 bad:
1239 xs->error = XS_DRIVER_STUFFUP;
1240 bha_free_ccb(sc, ccb);
1241 return (COMPLETE);
1242 }
1243
1244 /*
1245 * Poll a particular unit, looking for a particular xs
1246 */
1247 int
1248 bha_poll(sc, xs, count)
1249 struct bha_softc *sc;
1250 struct scsi_xfer *xs;
1251 int count;
1252 {
1253 bus_space_tag_t iot = sc->sc_iot;
1254 bus_space_handle_t ioh = sc->sc_ioh;
1255
1256 /* timeouts are in msec, so we loop in 1000 usec cycles */
1257 while (count) {
1258 /*
1259 * If we had interrupts enabled, would we
1260 * have got an interrupt?
1261 */
1262 if (bus_space_read_1(iot, ioh, BHA_INTR_PORT) &
1263 BHA_INTR_ANYINTR)
1264 bha_intr(sc);
1265 if (xs->flags & ITSDONE)
1266 return (0);
1267 delay(1000); /* only happens in boot so ok */
1268 count--;
1269 }
1270 return (1);
1271 }
1272
1273 void
1274 bha_timeout(arg)
1275 void *arg;
1276 {
1277 struct bha_ccb *ccb = arg;
1278 struct scsi_xfer *xs = ccb->xs;
1279 struct scsi_link *sc_link = xs->sc_link;
1280 struct bha_softc *sc = sc_link->adapter_softc;
1281 int s;
1282
1283 sc_print_addr(sc_link);
1284 printf("timed out");
1285
1286 s = splbio();
1287
1288 #ifdef BHADIAG
1289 /*
1290 * If the ccb's mbx is not free, then the board has gone Far East?
1291 */
1292 bha_collect_mbo(sc);
1293 if (ccb->flags & CCB_SENDING) {
1294 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1295 Debugger();
1296 }
1297 #endif
1298
1299 /*
1300 * If it has been through before, then
1301 * a previous abort has failed, don't
1302 * try abort again
1303 */
1304 if (ccb->flags & CCB_ABORT) {
1305 /* abort timed out */
1306 printf(" AGAIN\n");
1307 /* XXX Must reset! */
1308 } else {
1309 /* abort the operation that has timed out */
1310 printf("\n");
1311 ccb->xs->error = XS_TIMEOUT;
1312 ccb->timeout = BHA_ABORT_TIMEOUT;
1313 ccb->flags |= CCB_ABORT;
1314 bha_queue_ccb(sc, ccb);
1315 }
1316
1317 splx(s);
1318 }
1319