Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / arc / dti / btl.c
blobe5512e1c513a9d9d51f4e6314c978b594369d677
1 /* $NetBSD: btl.c,v 1.23 2009/11/27 03:23:04 rmind Exp $ */
2 /* NetBSD: bt.c,v 1.10 1996/05/12 23:51:54 mycroft Exp */
4 #undef BTDIAG
5 #define integrate
7 #define notyet /* XXX - #undef this, if this driver does actually work */
9 /*
10 * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by Charles M. Hannum.
23 * 4. The name of the author may not be used to endorse or promote products
24 * derived from this software without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * Originally written by Julian Elischer (julian@tfs.com)
40 * for TRW Financial Systems for use under the MACH(2.5) operating system.
42 * TRW Financial Systems, in accordance with their agreement with Carnegie
43 * Mellon University, makes this software available to CMU to distribute
44 * or use in any manner that they see fit as long as this message is kept with
45 * the software. For this reason TFS also grants any other persons or
46 * organisations permission to use or modify this software.
48 * TFS supplies this software to be publicly redistributed
49 * on the understanding that TFS is not responsible for the correct
50 * functioning of this software in any circumstances.
53 #include <sys/cdefs.h>
54 __KERNEL_RCSID(0, "$NetBSD: btl.c,v 1.23 2009/11/27 03:23:04 rmind Exp $");
56 #include <sys/types.h>
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/kernel.h>
60 #include <sys/errno.h>
61 #include <sys/malloc.h>
62 #include <sys/ioctl.h>
63 #include <sys/device.h>
64 #include <sys/buf.h>
65 #include <sys/proc.h>
67 #include <machine/intr.h>
68 #include <machine/pio.h>
70 #include <arc/dti/desktech.h>
72 #include <dev/scsipi/scsi_all.h>
73 #include <dev/scsipi/scsipi_all.h>
74 #include <dev/scsipi/scsiconf.h>
76 #include <dev/isa/isavar.h>
77 #include <arc/dti/btlreg.h>
78 #include <arc/dti/btlvar.h>
80 #ifndef DDB
81 #define Debugger() panic("should call debugger here (bt742a.c)")
82 #endif /* ! DDB */
85 * Mail box defs etc.
86 * these could be bigger but we need the bt_softc to fit on a single page..
88 #define BT_MBX_SIZE 32 /* mail box size (MAX 255 MBxs) */
89 /* don't need that many really */
90 #define BT_CCB_MAX 32 /* store up to 32 CCBs at one time */
91 #define CCB_HASH_SIZE 32 /* hash table size for phystokv */
92 #define CCB_HASH_SHIFT 9
93 #define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
95 #define bt_nextmbx(wmb, mbx, mbio) \
96 if ((wmb) == &(mbx)->mbio[BT_MBX_SIZE - 1]) \
97 (wmb) = &(mbx)->mbio[0]; \
98 else \
99 (wmb)++;
101 struct bt_mbx {
102 struct bt_mbx_out mbo[BT_MBX_SIZE];
103 struct bt_mbx_in mbi[BT_MBX_SIZE];
104 struct bt_mbx_out *cmbo; /* Collection Mail Box out */
105 struct bt_mbx_out *tmbo; /* Target Mail Box out */
106 struct bt_mbx_in *tmbi; /* Target Mail Box in */
109 #define KVTOPHYS(x) (*btl_conf->bc_kvtophys)((int)(x))
110 #define PHYSTOKV(x) (*btl_conf->bc_phystokv)((int)(x))
112 struct bt_softc {
113 device_t sc_dev;
114 void *sc_ih;
116 int sc_iobase;
117 int sc_irq, sc_drq;
119 char sc_model[7],
120 sc_firmware[6];
122 struct bt_mbx *sc_mbx; /* all our mailboxes */
123 #define wmbx (sc->sc_mbx)
124 struct bt_ccb *sc_ccbhash[CCB_HASH_SIZE];
125 TAILQ_HEAD(, bt_ccb) sc_free_ccb, sc_waiting_ccb;
126 TAILQ_HEAD(, bt_buf) sc_free_buf;
127 int sc_numccbs, sc_mbofull;
128 int sc_numbufs;
129 int sc_scsi_dev; /* adapters scsi id */
130 struct scsipi_link sc_link; /* prototype for devs */
131 struct scsipi_adapter sc_adapter;
134 #ifdef BTDEBUG
135 int bt_debug = 0;
136 #endif /* BTDEBUG */
138 int bt_cmd(int, struct bt_softc *, int, u_char *, int, u_char *);
139 integrate void bt_finish_ccbs(struct bt_softc *);
140 int btintr(void *);
141 integrate void bt_reset_ccb(struct bt_softc *, struct bt_ccb *);
142 void bt_free_ccb(struct bt_softc *, struct bt_ccb *);
143 integrate void bt_init_ccb(struct bt_softc *, struct bt_ccb *);
144 struct bt_ccb *bt_get_ccb(struct bt_softc *, int);
145 struct bt_ccb *bt_ccb_phys_kv(struct bt_softc *, u_long);
146 void bt_queue_ccb(struct bt_softc *, struct bt_ccb *);
147 void bt_collect_mbo(struct bt_softc *);
148 void bt_start_ccbs(struct bt_softc *);
149 void bt_done(struct bt_softc *, struct bt_ccb *);
150 int bt_find(struct isa_attach_args *, struct bt_softc *);
151 void bt_init(struct bt_softc *);
152 void bt_inquire_setup_information(struct bt_softc *);
153 void btminphys(struct buf *);
154 int bt_scsi_cmd(struct scsipi_xfer *);
155 int bt_poll(struct bt_softc *, struct scsipi_xfer *, int);
156 void bt_timeout(void *arg);
157 void bt_free_buf(struct bt_softc *, struct bt_buf *);
158 struct bt_buf * bt_get_buf(struct bt_softc *, int);
160 /* the below structure is so we have a default dev struct for out link struct */
161 struct scsipi_device bt_dev = {
162 NULL, /* Use default error handler */
163 NULL, /* have a queue, served by this */
164 NULL, /* have no async handler */
165 NULL, /* Use default 'done' routine */
168 static int btprobe(device_t, cfdata_t, void *);
169 static void btattach(device_t, device_t, void *);
171 CFATTACH_DECL_NEW(btl, sizeof(struct bt_softc),
172 btprobe, btattach, NULL, NULL);
174 #define BT_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
175 #define BT_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
177 struct btl_config *btl_conf = NULL;
180 * bt_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
182 * Activate Adapter command
183 * icnt: number of args (outbound bytes including opcode)
184 * ibuf: argument buffer
185 * ocnt: number of expected returned bytes
186 * obuf: result buffer
187 * wait: number of seconds to wait for response
189 * Performs an adapter command through the ports. Not to be confused with a
190 * scsi command, which is read in via the DMA; one of the adapter commands
191 * tells it to read in a scsi command.
194 bt_cmd(int iobase, struct bt_softc *sc, int icnt, int ocnt, u_char *ibuf,
195 u_char *obuf)
197 const char *name;
198 int i;
199 int wait;
200 u_char sts;
201 u_char opcode = ibuf[0];
203 if (sc != NULL)
204 name = device_xname(sc->sc_dev);
205 else
206 name = "(bt probe)";
209 * Calculate a reasonable timeout for the command.
211 switch (opcode) {
212 case BT_INQUIRE_DEVICES:
213 wait = 15 * 20000;
214 break;
215 default:
216 wait = 1 * 20000;
217 break;
221 * Wait for the adapter to go idle, unless it's one of
222 * the commands which don't need this
224 if (opcode != BT_MBO_INTR_EN) {
225 for (i = 20000; i; i--) { /* 1 sec? */
226 sts = isa_inb(iobase + BT_STAT_PORT);
227 if (sts & BT_STAT_IDLE)
228 break;
229 delay(50);
231 if (!i) {
232 printf("%s: bt_cmd, host not idle(0x%x)\n",
233 name, sts);
234 return ENXIO;
238 * Now that it is idle, if we expect output, preflush the
239 * queue feeding to us.
241 if (ocnt) {
242 while ((isa_inb(iobase + BT_STAT_PORT)) & BT_STAT_DF)
243 isa_inb(iobase + BT_DATA_PORT);
246 * Output the command and the number of arguments given
247 * for each byte, first check the port is empty.
249 while (icnt--) {
250 for (i = wait; i; i--) {
251 sts = isa_inb(iobase + BT_STAT_PORT);
252 if (!(sts & BT_STAT_CDF))
253 break;
254 delay(50);
256 if (!i) {
257 if (opcode != BT_INQUIRE_REVISION &&
258 opcode != BT_INQUIRE_REVISION_3)
259 printf("%s: bt_cmd, cmd/data port full\n", name);
260 isa_outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
261 return ENXIO;
263 isa_outb(iobase + BT_CMD_PORT, *ibuf++);
266 * If we expect input, loop that many times, each time,
267 * looking for the data register to have valid data
269 while (ocnt--) {
270 for (i = wait; i; i--) {
271 sts = isa_inb(iobase + BT_STAT_PORT);
272 if (sts & BT_STAT_DF)
273 break;
274 delay(50);
276 if (!i) {
277 if (opcode != BT_INQUIRE_REVISION &&
278 opcode != BT_INQUIRE_REVISION_3)
279 printf("%s: bt_cmd, cmd/data port empty %d\n",
280 name, ocnt);
281 isa_outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
282 return ENXIO;
284 *obuf++ = isa_inb(iobase + BT_DATA_PORT);
287 * Wait for the board to report a finished instruction.
288 * We may get an extra interrupt for the HACC signal, but this is
289 * unimportant.
291 if (opcode != BT_MBO_INTR_EN) {
292 for (i = 20000; i; i--) { /* 1 sec? */
293 sts = isa_inb(iobase + BT_INTR_PORT);
294 /* XXX Need to save this in the interrupt handler? */
295 if (sts & BT_INTR_HACC)
296 break;
297 delay(50);
299 if (!i) {
300 printf("%s: bt_cmd, host not finished(0x%x)\n",
301 name, sts);
302 return ENXIO;
305 isa_outb(iobase + BT_CTRL_PORT, BT_CTRL_IRST);
306 return 0;
310 * Check if the device can be found at the port given
311 * and if so, set it up ready for further work
312 * as an argument, takes the isa_device structure from
313 * autoconf.c
315 static int
316 btprobe(device_t parent, cfdata_t cf, void *aux)
318 struct isa_attach_args *ia = aux;
320 #ifdef NEWCONFIG
321 if (ia->ia_iobase == IOBASEUNK)
322 return 0;
323 #endif
325 if (btl_conf == NULL)
326 return (0);
328 /* See if there is a unit at this location. */
329 if (bt_find(ia, NULL) != 0)
330 return 0;
332 ia->ia_msize = 0;
333 ia->ia_iosize = 4;
334 /* IRQ and DRQ set by bt_find(). */
335 return 1;
339 * Attach all the sub-devices we can find
341 static void
342 btattach(device_t parent, device_t self, void *aux)
344 struct isa_attach_args *ia = aux;
345 struct bt_softc *sc = device_private(self);
346 struct bt_ccb *ccb;
347 struct bt_buf *buf;
348 u_int bouncearea;
349 u_int bouncebase;
350 u_int bouncesize;
352 sc->sc_dev = self;
354 if (bt_find(ia, sc) != 0)
355 panic("btattach: bt_find of %s failed", self->dv_xname);
356 sc->sc_iobase = ia->ia_iobase;
359 * create mbox area
361 (*btl_conf->bc_bouncemem)(&bouncebase, &bouncesize);
362 bouncearea = bouncebase + sizeof(struct bt_mbx);
363 sc->sc_mbx = (struct bt_mbx *)bouncebase;
365 bt_inquire_setup_information(sc);
366 bt_init(sc);
367 TAILQ_INIT(&sc->sc_free_ccb);
368 TAILQ_INIT(&sc->sc_free_buf);
369 TAILQ_INIT(&sc->sc_waiting_ccb);
372 * fill up with ccb's
374 while (sc->sc_numccbs < BT_CCB_MAX) {
375 ccb = (struct bt_ccb *)bouncearea;
376 bouncearea += sizeof(struct bt_ccb);
377 bt_init_ccb(sc, ccb);
378 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
379 sc->sc_numccbs++;
382 * fill up with bufs's
384 while ((bouncearea + sizeof(struct bt_buf)) < bouncebase + bouncesize) {
385 buf = (struct bt_buf *)bouncearea;
386 bouncearea += sizeof(struct bt_buf);
387 TAILQ_INSERT_HEAD(&sc->sc_free_buf, buf, chain);
388 sc->sc_numbufs++;
391 * Fill in the adapter.
393 sc->sc_adapter.scsipi_cmd = bt_scsi_cmd;
394 sc->sc_adapter.scsipi_minphys = btminphys;
396 * fill in the prototype scsipi_link.
398 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
399 sc->sc_link.adapter_softc = sc;
400 sc->sc_link.scsipi_scsi.adapter_target = sc->sc_scsi_dev;
401 sc->sc_link.adapter = &sc->sc_adapter;
402 sc->sc_link.device = &bt_dev;
403 sc->sc_link.openings = 1;
404 sc->sc_link.scsipi_scsi.max_target = 7;
405 sc->sc_link.scsipi_scsi.max_lun = 7;
406 sc->sc_link.type = BUS_SCSI;
408 sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
409 IPL_BIO, btintr, sc);
412 * ask the adapter what subunits are present
414 config_found(self, &sc->sc_link, scsiprint);
417 integrate void
418 bt_finish_ccbs(struct bt_softc *sc)
420 struct bt_mbx_in *wmbi;
421 struct bt_ccb *ccb;
422 int i;
424 wmbi = wmbx->tmbi;
426 if (wmbi->stat == BT_MBI_FREE) {
427 for (i = 0; i < BT_MBX_SIZE; i++) {
428 if (wmbi->stat != BT_MBI_FREE) {
429 printf("%s: mbi not in round-robin order\n",
430 device_xname(sc->sc_dev));
431 goto AGAIN;
433 bt_nextmbx(wmbi, wmbx, mbi);
435 #ifdef BTDIAGnot
436 printf("%s: mbi interrupt with no full mailboxes\n",
437 device_xname(sc->sc_dev));
438 #endif
439 return;
442 AGAIN:
443 do {
444 ccb = bt_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
445 if (!ccb) {
446 printf("%s: bad mbi ccb pointer; skipping\n",
447 device_xname(sc->sc_dev));
448 goto next;
451 #ifdef BTDEBUG
452 if (bt_debug) {
453 u_char *cp = (u_char *) &ccb->scsi_cmd;
454 printf("op=%x %x %x %x %x %x\n",
455 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
456 printf("stat %x for mbi addr = 0x%08x, ",
457 wmbi->stat, wmbi);
458 printf("ccb addr = 0x%x\n", ccb);
460 #endif /* BTDEBUG */
462 switch (wmbi->stat) {
463 case BT_MBI_OK:
464 case BT_MBI_ERROR:
465 if ((ccb->flags & CCB_ABORT) != 0) {
467 * If we already started an abort, wait for it
468 * to complete before clearing the CCB. We
469 * could instead just clear CCB_SENDING, but
470 * what if the mailbox was already received?
471 * The worst that happens here is that we clear
472 * the CCB a bit later than we need to. BFD.
474 goto next;
476 break;
478 case BT_MBI_ABORT:
479 case BT_MBI_UNKNOWN:
481 * Even if the CCB wasn't found, we clear it anyway.
482 * See preceding comment.
484 break;
486 default:
487 printf("%s: bad mbi status %02x; skipping\n",
488 device_xname(sc->sc_dev), wmbi->stat);
489 goto next;
492 callout_stop(&ccb->xs->xs_callout);
493 bt_done(sc, ccb);
495 next:
496 wmbi->stat = BT_MBI_FREE;
497 bt_nextmbx(wmbi, wmbx, mbi);
498 } while (wmbi->stat != BT_MBI_FREE);
500 wmbx->tmbi = wmbi;
504 * Catch an interrupt from the adaptor
507 btintr(void *arg)
509 struct bt_softc *sc = arg;
510 int iobase = sc->sc_iobase;
511 u_char sts;
513 #ifdef BTDEBUG
514 printf("%s: btintr ", device_xname(sc->sc_dev));
515 #endif /* BTDEBUG */
518 * First acknowlege the interrupt, Then if it's not telling about
519 * a completed operation just return.
521 sts = isa_inb(iobase + BT_INTR_PORT);
522 if ((sts & BT_INTR_ANYINTR) == 0)
523 return 0;
524 isa_outb(iobase + BT_CTRL_PORT, BT_CTRL_IRST);
526 #ifdef BTDIAG
527 /* Make sure we clear CCB_SENDING before finishing a CCB. */
528 bt_collect_mbo(sc);
529 #endif
531 /* Mail box out empty? */
532 if (sts & BT_INTR_MBOA) {
533 struct bt_toggle toggle;
535 toggle.cmd.opcode = BT_MBO_INTR_EN;
536 toggle.cmd.enable = 0;
537 bt_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd, 0,
538 (u_char *)0);
539 bt_start_ccbs(sc);
542 /* Mail box in full? */
543 if (sts & BT_INTR_MBIF)
544 bt_finish_ccbs(sc);
546 return 1;
549 integrate void
550 bt_reset_ccb(struct bt_softc *sc, struct bt_ccb *ccb)
553 ccb->flags = 0;
557 * A ccb is put onto the free list.
559 void
560 bt_free_ccb(struct bt_softc *sc, struct bt_ccb *ccb)
562 int s;
564 s = splbio();
566 bt_reset_ccb(sc, ccb);
567 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
570 * If there were none, wake anybody waiting for one to come free,
571 * starting with queued entries.
573 if (ccb->chain.tqe_next == 0)
574 wakeup(&sc->sc_free_ccb);
576 splx(s);
580 * A buf is put onto the free list.
582 void
583 bt_free_buf(struct bt_softc *sc, struct bt_buf *buf)
585 int s;
587 s = splbio();
589 TAILQ_INSERT_HEAD(&sc->sc_free_buf, buf, chain);
590 sc->sc_numbufs++;
593 * If there were none, wake anybody waiting for one to come free,
594 * starting with queued entries.
596 if (buf->chain.tqe_next == 0)
597 wakeup(&sc->sc_free_buf);
599 splx(s);
602 integrate void
603 bt_init_ccb(struct bt_softc *sc, struct bt_ccb *ccb)
605 int hashnum;
607 memset(ccb, 0, sizeof(struct bt_ccb));
609 * put in the phystokv hash table
610 * Never gets taken out.
612 ccb->hashkey = KVTOPHYS(ccb);
613 hashnum = CCB_HASH(ccb->hashkey);
614 ccb->nexthash = sc->sc_ccbhash[hashnum];
615 sc->sc_ccbhash[hashnum] = ccb;
616 bt_reset_ccb(sc, ccb);
620 * Get a free ccb
622 * If there are none, either return an error or sleep.
624 struct bt_ccb *
625 bt_get_ccb(struct bt_softc *sc, int nosleep)
627 struct bt_ccb *ccb;
628 int s;
630 s = splbio();
633 * If we can and have to, sleep waiting for one to come free.
635 for (;;) {
636 ccb = sc->sc_free_ccb.tqh_first;
637 if (ccb) {
638 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
639 break;
641 if (nosleep)
642 goto out;
643 tsleep(&sc->sc_free_ccb, PRIBIO, "btccb", 0);
646 ccb->flags |= CCB_ALLOC;
648 out:
649 splx(s);
650 return ccb;
654 * Get a free buf
656 * If there are none, either return an error or sleep.
658 struct bt_buf *
659 bt_get_buf(struct bt_softc *sc, int nosleep)
661 struct bt_buf *buf;
662 int s;
664 s = splbio();
667 * If we can and have to, sleep waiting for one to come free.
669 for (;;) {
670 buf = sc->sc_free_buf.tqh_first;
671 if (buf) {
672 TAILQ_REMOVE(&sc->sc_free_buf, buf, chain);
673 sc->sc_numbufs--;
674 break;
676 if (nosleep)
677 goto out;
678 tsleep(&sc->sc_free_buf, PRIBIO, "btbuf", 0);
681 out:
682 splx(s);
683 return buf;
687 * Given a physical address, find the ccb that it corresponds to.
689 struct bt_ccb *
690 bt_ccb_phys_kv(struct bt_softc *sc, u_long ccb_phys)
692 int hashnum = CCB_HASH(ccb_phys);
693 struct bt_ccb *ccb = sc->sc_ccbhash[hashnum];
695 while (ccb) {
696 if (ccb->hashkey == ccb_phys)
697 break;
698 ccb = ccb->nexthash;
700 return ccb;
704 * Queue a CCB to be sent to the controller, and send it if possible.
706 void
707 bt_queue_ccb(struct bt_softc *sc, struct bt_ccb *ccb)
710 TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
711 bt_start_ccbs(sc);
715 * Garbage collect mailboxes that are no longer in use.
717 void
718 bt_collect_mbo(struct bt_softc *sc)
720 struct bt_mbx_out *wmbo; /* Mail Box Out pointer */
722 wmbo = wmbx->cmbo;
724 while (sc->sc_mbofull > 0) {
725 if (wmbo->cmd != BT_MBO_FREE)
726 break;
728 #ifdef BTDIAG
729 ccb = bt_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
730 ccb->flags &= ~CCB_SENDING;
731 #endif
733 --sc->sc_mbofull;
734 bt_nextmbx(wmbo, wmbx, mbo);
737 wmbx->cmbo = wmbo;
741 * Send as many CCBs as we have empty mailboxes for.
743 void
744 bt_start_ccbs(struct bt_softc *sc)
746 int iobase = sc->sc_iobase;
747 struct bt_mbx_out *wmbo; /* Mail Box Out pointer */
748 struct bt_ccb *ccb;
750 wmbo = wmbx->tmbo;
752 while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) {
753 if (sc->sc_mbofull >= BT_MBX_SIZE) {
754 bt_collect_mbo(sc);
755 if (sc->sc_mbofull >= BT_MBX_SIZE) {
756 struct bt_toggle toggle;
758 toggle.cmd.opcode = BT_MBO_INTR_EN;
759 toggle.cmd.enable = 1;
760 bt_cmd(iobase, sc, sizeof(toggle.cmd),
761 (u_char *)&toggle.cmd, 0, (u_char *)0);
762 break;
766 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
767 #ifdef BTDIAG
768 ccb->flags |= CCB_SENDING;
769 #endif
771 /* Link ccb to mbo. */
772 ltophys(KVTOPHYS(ccb), wmbo->ccb_addr);
773 if (ccb->flags & CCB_ABORT)
774 wmbo->cmd = BT_MBO_ABORT;
775 else
776 wmbo->cmd = BT_MBO_START;
778 /* Tell the card to poll immediately. */
779 isa_outb(iobase + BT_CMD_PORT, BT_START_SCSI);
781 if ((ccb->xs->xs_control & XS_CTL_POLL) == 0)
782 callout_reset(&ccb->xs->xs_callout,
783 mstohz(ccb->timeout), bt_timeout, ccb);
785 ++sc->sc_mbofull;
786 bt_nextmbx(wmbo, wmbx, mbo);
789 wmbx->tmbo = wmbo;
793 * We have a ccb which has been processed by the
794 * adaptor, now we look to see how the operation
795 * went. Wake up the owner if waiting
797 void
798 bt_done(struct bt_softc *sc, struct bt_ccb *ccb)
800 struct scsi_sense_data *s1, *s2;
801 struct scsipi_xfer *xs = ccb->xs;
803 u_long thiskv, thisbounce;
804 int bytes_this_page, datalen;
805 struct bt_scat_gath *sg;
806 int seg;
808 SC_DEBUG(xs->sc_link, SDEV_DB2, ("bt_done\n"));
810 * Otherwise, put the results of the operation
811 * into the xfer and call whoever started it
813 #ifdef BTDIAG
814 if (ccb->flags & CCB_SENDING) {
815 printf("%s: exiting ccb still in transit!\n",
816 device_xname(sc->sc_dev));
817 Debugger();
818 return;
820 #endif
821 if ((ccb->flags & CCB_ALLOC) == 0) {
822 printf("%s: exiting ccb not allocated!\n",
823 device_xname(sc->sc_dev));
824 Debugger();
825 return;
827 if (xs->error == XS_NOERROR) {
828 if (ccb->host_stat != BT_OK) {
829 switch (ccb->host_stat) {
830 case BT_SEL_TIMEOUT: /* No response */
831 xs->error = XS_SELTIMEOUT;
832 break;
833 default: /* Other scsi protocol messes */
834 printf("%s: host_stat %x\n",
835 device_xname(sc->sc_dev), ccb->host_stat);
836 xs->error = XS_DRIVER_STUFFUP;
837 break;
839 } else if (ccb->target_stat != SCSI_OK) {
840 switch (ccb->target_stat) {
841 case SCSI_CHECK:
842 s1 = &ccb->scsi_sense;
843 s2 = &xs->sense.scsi_sense;
844 *s2 = *s1;
845 xs->error = XS_SENSE;
846 break;
847 case SCSI_BUSY:
848 xs->error = XS_BUSY;
849 break;
850 default:
851 printf("%s: target_stat %x\n",
852 device_xname(sc->sc_dev), ccb->target_stat);
853 xs->error = XS_DRIVER_STUFFUP;
854 break;
856 } else
857 xs->resid = 0;
860 if((datalen = xs->datalen) != 0) {
861 thiskv = (int)xs->data;
862 sg = ccb->scat_gath;
863 seg = phystol(ccb->data_length) / sizeof(struct bt_scat_gath);
865 while (seg) {
866 thisbounce = PHYSTOKV(phystol(sg->seg_addr));
867 bytes_this_page = phystol(sg->seg_len);
868 if(xs->xs_control & XS_CTL_DATA_IN) {
869 memcpy((void *)thiskv, (void *)thisbounce, bytes_this_page);
871 bt_free_buf(sc, (struct bt_buf *)thisbounce);
872 thiskv += bytes_this_page;
873 datalen -= bytes_this_page;
875 sg++;
876 seg--;
880 bt_free_ccb(sc, ccb);
881 xs->xs_status |= XS_STS_DONE;
882 scsipi_done(xs);
886 * Find the board and find it's irq/drq
889 bt_find(struct isa_attach_args *ia, struct bt_softc *sc)
891 int iobase = ia->ia_iobase;
892 int i;
893 u_char sts;
894 struct bt_extended_inquire inquire;
895 struct bt_config config;
896 int irq, drq;
898 #ifndef notyet
899 /* Check something is at the ports we need to access */
900 sts = isa_inb(iobase + BHA_STAT_PORT);
901 if (sts == 0xFF)
902 return (0);
903 #endif
906 * reset board, If it doesn't respond, assume
907 * that it's not there.. good for the probe
910 isa_outb(iobase + BT_CTRL_PORT, BT_CTRL_HRST | BT_CTRL_SRST);
912 delay(100);
913 for (i = BT_RESET_TIMEOUT; i; i--) {
914 sts = isa_inb(iobase + BT_STAT_PORT);
915 if (sts == (BT_STAT_IDLE | BT_STAT_INIT))
916 break;
917 delay(1000);
919 if (!i) {
920 #ifdef BTDEBUG
921 if (bt_debug)
922 printf("bt_find: No answer from buslogic board\n");
923 #endif /* BTDEBUG */
924 return 1;
927 #ifndef notyet
929 * The BusLogic cards implement an Adaptec 1542 (aha)-compatible
930 * interface. The native bha interface is not compatible with
931 * an aha. 1542. We need to ensure that we never match an
932 * Adaptec 1542. We must also avoid sending Adaptec-compatible
933 * commands to a real bha, lest it go into 1542 emulation mode.
934 * (On an indirect bus like ISA, we should always probe for BusLogic
935 * interfaces before Adaptec interfaces).
939 * Make sure we don't match an AHA-1542A or AHA-1542B, by checking
940 * for an extended-geometry register. The 1542[AB] don't have one.
942 sts = isa_inb(iobase + BT_EXTGEOM_PORT);
943 if (sts == 0xFF)
944 return (0);
945 #endif /* notyet */
948 * Check that we actually know how to use this board.
950 delay(1000);
951 memset(&inquire, 0, sizeof inquire);
952 inquire.cmd.opcode = BT_INQUIRE_EXTENDED;
953 inquire.cmd.len = sizeof(inquire.reply);
954 i = bt_cmd(iobase, sc, sizeof(inquire.cmd), (u_char *)&inquire.cmd,
955 sizeof(inquire.reply), (u_char *)&inquire.reply);
957 #ifndef notyet
959 * Some 1542Cs (CP, perhaps not CF, may depend on firmware rev)
960 * have the extended-geometry register and also respond to
961 * BHA_INQUIRE_EXTENDED. Make sure we never match such cards,
962 * by checking the size of the reply is what a BusLogic card returns.
964 if (i) { /* XXX - this doesn't really check the size. ??? see bha.c */
965 #ifdef BTDEBUG
966 printf("bt_find: board returned %d instead of %d to %s\n",
967 i, sizeof(inquire.reply), "INQUIRE_EXTENDED");
968 #endif
969 return (0);
972 /* OK, we know we've found a buslogic adaptor. */
973 #endif /* notyet */
975 switch (inquire.reply.bus_type) {
976 case BT_BUS_TYPE_24BIT:
977 case BT_BUS_TYPE_32BIT:
978 break;
979 case BT_BUS_TYPE_MCA:
980 /* We don't grok MicroChannel (yet). */
981 return 1;
982 default:
983 printf("bt_find: illegal bus type %c\n", inquire.reply.bus_type);
984 return 1;
988 * Assume we have a board at this stage setup DMA channel from
989 * jumpers and save int level
991 delay(1000);
992 config.cmd.opcode = BT_INQUIRE_CONFIG;
993 bt_cmd(iobase, sc, sizeof(config.cmd), (u_char *)&config.cmd,
994 sizeof(config.reply), (u_char *)&config.reply);
995 switch (config.reply.chan) {
996 case EISADMA:
997 drq = DRQUNK;
998 break;
999 case CHAN0:
1000 drq = 0;
1001 break;
1002 case CHAN5:
1003 drq = 5;
1004 break;
1005 case CHAN6:
1006 drq = 6;
1007 break;
1008 case CHAN7:
1009 drq = 7;
1010 break;
1011 default:
1012 printf("bt_find: illegal drq setting %x\n", config.reply.chan);
1013 return 1;
1016 switch (config.reply.intr) {
1017 case INT9:
1018 irq = 9;
1019 break;
1020 case INT10:
1021 irq = 10;
1022 break;
1023 case INT11:
1024 irq = 11;
1025 break;
1026 case INT12:
1027 irq = 12;
1028 break;
1029 case INT14:
1030 irq = 14;
1031 break;
1032 case INT15:
1033 irq = 15;
1034 break;
1035 default:
1036 printf("bt_find: illegal irq setting %x\n", config.reply.intr);
1037 return 1;
1040 if (sc != NULL) {
1041 /* who are we on the scsi bus? */
1042 sc->sc_scsi_dev = config.reply.scsi_dev;
1044 sc->sc_iobase = iobase;
1045 sc->sc_irq = irq;
1046 sc->sc_drq = drq;
1047 } else {
1048 if (ia->ia_irq == IRQUNK)
1049 ia->ia_irq = irq;
1050 else if (ia->ia_irq != irq)
1051 return 1;
1052 if (ia->ia_drq == DRQUNK)
1053 ia->ia_drq = drq;
1054 else if (ia->ia_drq != drq)
1055 return 1;
1058 return 0;
1062 * Start the board, ready for normal operation
1064 void
1065 bt_init(struct bt_softc *sc)
1067 int iobase = sc->sc_iobase;
1068 struct bt_devices devices;
1069 struct bt_setup setup;
1070 struct bt_mailbox mailbox;
1071 struct bt_period period;
1072 int i;
1074 /* Enable round-robin scheme - appeared at firmware rev. 3.31. */
1075 if (strcmp(sc->sc_firmware, "3.31") >= 0) {
1076 struct bt_toggle toggle;
1078 toggle.cmd.opcode = BT_ROUND_ROBIN;
1079 toggle.cmd.enable = 1;
1080 bt_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd,
1081 0, (u_char *)0);
1084 /* Inquire Installed Devices (to force synchronous negotiation). */
1085 devices.cmd.opcode = BT_INQUIRE_DEVICES;
1086 bt_cmd(iobase, sc, sizeof(devices.cmd), (u_char *)&devices.cmd,
1087 sizeof(devices.reply), (u_char *)&devices.reply);
1089 /* Obtain setup information from. */
1090 setup.cmd.opcode = BT_INQUIRE_SETUP;
1091 setup.cmd.len = sizeof(setup.reply);
1092 bt_cmd(iobase, sc, sizeof(setup.cmd), (u_char *)&setup.cmd,
1093 sizeof(setup.reply), (u_char *)&setup.reply);
1095 printf("%s: %s, %s\n",
1096 device_xname(sc->sc_dev),
1097 setup.reply.sync_neg ? "sync" : "async",
1098 setup.reply.parity ? "parity" : "no parity");
1100 for (i = 0; i < 8; i++)
1101 period.reply.period[i] = setup.reply.sync[i].period * 5 + 20;
1103 if (sc->sc_firmware[0] >= '3') {
1104 period.cmd.opcode = BT_INQUIRE_PERIOD;
1105 period.cmd.len = sizeof(period.reply);
1106 bt_cmd(iobase, sc, sizeof(period.cmd), (u_char *)&period.cmd,
1107 sizeof(period.reply), (u_char *)&period.reply);
1110 for (i = 0; i < 8; i++) {
1111 if (!setup.reply.sync[i].valid ||
1112 (!setup.reply.sync[i].offset && !setup.reply.sync[i].period))
1113 continue;
1114 printf("%s targ %d: sync, offset %d, period %dnsec\n",
1115 device_xname(sc->sc_dev), i,
1116 setup.reply.sync[i].offset, period.reply.period[i] * 10);
1120 * Set up initial mail box for round-robin operation.
1122 for (i = 0; i < BT_MBX_SIZE; i++) {
1123 wmbx->mbo[i].cmd = BT_MBO_FREE;
1124 wmbx->mbi[i].stat = BT_MBI_FREE;
1126 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
1127 wmbx->tmbi = &wmbx->mbi[0];
1128 sc->sc_mbofull = 0;
1130 /* Initialize mail box. */
1131 mailbox.cmd.opcode = BT_MBX_INIT_EXTENDED;
1132 mailbox.cmd.nmbx = BT_MBX_SIZE;
1133 ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr);
1134 bt_cmd(iobase, sc, sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
1135 0, (u_char *)0);
1138 void
1139 bt_inquire_setup_information(struct bt_softc *sc)
1141 int iobase = sc->sc_iobase;
1142 struct bt_model model;
1143 struct bt_revision revision;
1144 struct bt_digit digit;
1145 char *p;
1148 * Get the firmware revision.
1150 p = sc->sc_firmware;
1151 revision.cmd.opcode = BT_INQUIRE_REVISION;
1152 bt_cmd(iobase, sc, sizeof(revision.cmd), (u_char *)&revision.cmd,
1153 sizeof(revision.reply), (u_char *)&revision.reply);
1154 *p++ = revision.reply.firm_revision;
1155 *p++ = '.';
1156 *p++ = revision.reply.firm_version;
1157 digit.cmd.opcode = BT_INQUIRE_REVISION_3;
1158 bt_cmd(iobase, sc, sizeof(digit.cmd), (u_char *)&digit.cmd,
1159 sizeof(digit.reply), (u_char *)&digit.reply);
1160 *p++ = digit.reply.digit;
1161 if (revision.reply.firm_revision >= '3' ||
1162 (revision.reply.firm_revision == '3' && revision.reply.firm_version >= '3')) {
1163 digit.cmd.opcode = BT_INQUIRE_REVISION_4;
1164 bt_cmd(iobase, sc, sizeof(digit.cmd), (u_char *)&digit.cmd,
1165 sizeof(digit.reply), (u_char *)&digit.reply);
1166 *p++ = digit.reply.digit;
1168 while (p > sc->sc_firmware && (p[-1] == ' ' || p[-1] == '\0'))
1169 p--;
1170 *p = '\0';
1173 * Get the model number.
1175 if (revision.reply.firm_revision >= '3') {
1176 p = sc->sc_model;
1177 model.cmd.opcode = BT_INQUIRE_MODEL;
1178 model.cmd.len = sizeof(model.reply);
1179 bt_cmd(iobase, sc, sizeof(model.cmd), (u_char *)&model.cmd,
1180 sizeof(model.reply), (u_char *)&model.reply);
1181 *p++ = model.reply.id[0];
1182 *p++ = model.reply.id[1];
1183 *p++ = model.reply.id[2];
1184 *p++ = model.reply.id[3];
1185 while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
1186 p--;
1187 *p++ = model.reply.version[0];
1188 *p++ = model.reply.version[1];
1189 while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
1190 p--;
1191 *p = '\0';
1192 } else
1193 strcpy(sc->sc_model, "542B");
1195 printf(": model BT-%s, firmware %s\n", sc->sc_model, sc->sc_firmware);
1198 void
1199 btminphys(struct buf *bp)
1202 if (bp->b_bcount > ((BT_NSEG - 1) << PGSHIFT))
1203 bp->b_bcount = ((BT_NSEG - 1) << PGSHIFT);
1204 minphys(bp);
1208 * start a scsi operation given the command and the data address. Also needs
1209 * the unit, target and lu.
1212 bt_scsi_cmd(struct scsipi_xfer *xs)
1214 struct scsipi_link *sc_link = xs->sc_link;
1215 struct bt_softc *sc = sc_link->adapter_softc;
1216 struct bt_ccb *ccb;
1217 struct bt_scat_gath *sg;
1218 int seg; /* scatter gather seg being worked on */
1219 u_long thiskv, thisbounce;
1220 int bytes_this_page, datalen, control;
1221 int s;
1223 SC_DEBUG(sc_link, SDEV_DB2, ("bt_scsi_cmd\n"));
1225 * get a ccb to use. If the transfer
1226 * is from a buf (possibly from interrupt time)
1227 * then we can't allow it to sleep
1229 control = xs->xs_control;
1230 if ((ccb = bt_get_ccb(sc, control & XS_CTL_NOSLEEP)) == NULL) {
1231 xs->error = XS_DRIVER_STUFFUP;
1232 return TRY_AGAIN_LATER;
1234 ccb->xs = xs;
1235 ccb->timeout = xs->timeout;
1238 * Put all the arguments for the xfer in the ccb
1240 if (control & XS_CTL_RESET) {
1241 ccb->opcode = BT_RESET_CCB;
1242 ccb->scsi_cmd_length = 0;
1243 } else {
1244 /* can't use S/G if zero length */
1245 if (xs->cmdlen > sizeof(ccb->scsi_cmd)) {
1246 printf("%s: cmdlen %d too large for CCB\n",
1247 device_xname(sc->sc_dev), xs->cmdlen);
1248 xs->error = XS_DRIVER_STUFFUP;
1249 bt_free_ccb(sc, ccb);
1250 return COMPLETE;
1252 ccb->opcode = (xs->datalen ? BT_INIT_SCAT_GATH_CCB
1253 : BT_INITIATOR_CCB);
1254 memcpy(&ccb->scsi_cmd, xs->cmd,
1255 ccb->scsi_cmd_length = xs->cmdlen);
1258 if (xs->datalen) {
1259 sg = ccb->scat_gath;
1260 seg = 0;
1262 * Set up the scatter-gather block.
1264 SC_DEBUG(sc_link, SDEV_DB4,
1265 ("%d @0x%x:- ", xs->datalen, xs->data));
1267 datalen = xs->datalen;
1268 thiskv = (int)xs->data;
1270 while (datalen && seg < BT_NSEG) {
1272 /* put in the base address of a buf */
1273 thisbounce = (u_long)
1274 bt_get_buf(sc, control & XS_CTL_NOSLEEP);
1275 if(thisbounce == 0)
1276 break;
1277 ltophys(KVTOPHYS(thisbounce), sg->seg_addr);
1278 bytes_this_page = min(sizeof(struct bt_buf), datalen);
1279 if (control & XS_CTL_DATA_OUT) {
1280 memcpy((void *)thisbounce, (void *)thiskv, bytes_this_page);
1282 thiskv += bytes_this_page;
1283 datalen -= bytes_this_page;
1285 ltophys(bytes_this_page, sg->seg_len);
1286 sg++;
1287 seg++;
1289 SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
1290 if (datalen) {
1291 printf("%s: bt_scsi_cmd, out of bufs %d of %d left.\n",
1292 device_xname(sc->sc_dev), datalen, xs->datalen);
1293 goto badbuf;
1295 ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
1296 ltophys(seg * sizeof(struct bt_scat_gath), ccb->data_length);
1297 } else { /* No data xfer, use non S/G values */
1298 ltophys(0, ccb->data_addr);
1299 ltophys(0, ccb->data_length);
1302 ccb->data_out = 0;
1303 ccb->data_in = 0;
1304 ccb->target = sc_link->scsipi_scsi.target;
1305 ccb->lun = sc_link->scsipi_scsi.lun;
1306 ltophys(KVTOPHYS(&ccb->scsi_sense), ccb->sense_ptr);
1307 ccb->req_sense_length = sizeof(ccb->scsi_sense);
1308 ccb->host_stat = 0x00;
1309 ccb->target_stat = 0x00;
1310 ccb->link_id = 0;
1311 ltophys(0, ccb->link_addr);
1313 s = splbio();
1314 bt_queue_ccb(sc, ccb);
1315 splx(s);
1318 * Usually return SUCCESSFULLY QUEUED
1320 SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
1321 if ((control & XS_CTL_POLL) == 0)
1322 return SUCCESSFULLY_QUEUED;
1325 * If we can't use interrupts, poll on completion
1327 if (bt_poll(sc, xs, ccb->timeout)) {
1328 bt_timeout(ccb);
1329 if (bt_poll(sc, xs, ccb->timeout))
1330 bt_timeout(ccb);
1332 return COMPLETE;
1334 badbuf:
1335 sg = ccb->scat_gath;
1336 while (seg) {
1337 thisbounce = PHYSTOKV(phystol(sg->seg_addr));
1338 bt_free_buf(sc, (struct bt_buf *)thisbounce);
1339 sg++;
1340 seg--;
1342 xs->error = XS_DRIVER_STUFFUP;
1343 bt_free_ccb(sc, ccb);
1344 return TRY_AGAIN_LATER;
1348 * Poll a particular unit, looking for a particular xs
1351 bt_poll(struct bt_softc *sc, struct scsipi_xfer *xs, int count)
1353 int iobase = sc->sc_iobase;
1355 /* timeouts are in msec, so we loop in 1000 usec cycles */
1356 while (count) {
1358 * If we had interrupts enabled, would we
1359 * have got an interrupt?
1361 if (isa_inb(iobase + BT_INTR_PORT) & BT_INTR_ANYINTR)
1362 btintr(sc);
1363 if (xs->xs_status & XS_STS_DONE)
1364 return 0;
1365 delay(1000); /* only happens in boot so ok */
1366 count--;
1368 return 1;
1371 void
1372 bt_timeout(void *arg)
1374 struct bt_ccb *ccb = arg;
1375 struct scsipi_xfer *xs = ccb->xs;
1376 struct scsipi_link *sc_link = xs->sc_link;
1377 struct bt_softc *sc = sc_link->adapter_softc;
1378 int s;
1380 scsi_print_addr(sc_link);
1381 printf("timed out");
1383 s = splbio();
1385 #ifdef BTDIAG
1387 * If the ccb's mbx is not free, then the board has gone Far East?
1389 bt_collect_mbo(sc);
1390 if (ccb->flags & CCB_SENDING) {
1391 printf("%s: not taking commands!\n", device_xname(sc->sc_dev));
1392 Debugger();
1394 #endif
1397 * If it has been through before, then
1398 * a previous abort has failed, don't
1399 * try abort again
1401 if (ccb->flags & CCB_ABORT) {
1402 /* abort timed out */
1403 printf(" AGAIN\n");
1404 /* XXX Must reset! */
1405 } else {
1406 /* abort the operation that has timed out */
1407 printf("\n");
1408 ccb->xs->error = XS_TIMEOUT;
1409 ccb->timeout = BT_ABORT_TIMEOUT;
1410 ccb->flags |= CCB_ABORT;
1411 bt_queue_ccb(sc, ccb);
1414 splx(s);