boca.c revision 1.1 1 /* $NetBSD: boca.c,v 1.1 1995/01/03 22:30:26 mycroft Exp $ */
2
3 /*
4 * Multi-port serial card interrupt demuxing support.
5 * Roland McGrath 3/20/94
6 * The author disclaims copyright and places this file in the public domain.
7 *
8 * Modified by: Charles Hannum, 3/22/94
9 *
10 * The programming details of the BOCA board (i.e. how the interrupt register
11 * works) were determined by David Muir Sharnoff. BOCA Research refused to
12 * provide any programming information.
13 */
14
15 #include <sys/param.h>
16 #include <sys/device.h>
17
18 #include <machine/pio.h>
19
20 #include <i386/isa/isavar.h>
21
22 struct boca_softc {
23 struct device sc_dev;
24 struct intrhand sc_ih;
25
26 int sc_iobase;
27 int sc_alive; /* mask of slave units attached */
28 void *sc_slaves[8]; /* com device unit numbers */
29 };
30
31 int bocaprobe();
32 void bocaattach();
33 int bocaintr __P((struct boca_softc *));
34
35 struct cfdriver bocacd = {
36 NULL, "boca", bocaprobe, bocaattach, DV_TTY, sizeof(struct boca_softc)
37 };
38
39 int
40 bocaprobe(parent, self, aux)
41 struct device *parent, *self;
42 void *aux;
43 {
44 struct isa_attach_args *ia = aux;
45
46 /*
47 * Do the normal com probe for the first UART and assume
48 * its presence means there is a multiport board there.
49 * XXX Needs more robustness.
50 */
51 ia->ia_iosize = 8 * 8;
52 return (comprobe1(ia->ia_iobase));
53 }
54
55 struct boca_attach_args {
56 int ba_slave;
57 };
58
59 int
60 bocasubmatch(parent, match, aux)
61 struct device *parent;
62 void *match, *aux;
63 {
64 struct boca_softc *sc = (void *)parent;
65 struct device *self = match;
66 struct isa_attach_args *ia = aux;
67 struct boca_attach_args *ba = ia->ia_aux;
68 struct cfdata *cf = self->dv_cfdata;
69
70 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ba->ba_slave)
71 return (0);
72 return ((*cf->cf_driver->cd_match)(parent, match, ia));
73 }
74
75 int
76 bocaprint(aux, boca)
77 void *aux;
78 char *boca;
79 {
80 struct isa_attach_args *ia = aux;
81 struct boca_attach_args *ba = ia->ia_aux;
82
83 printf(" slave %d", ba->ba_slave);
84 }
85
86 void
87 bocaattach(parent, self, aux)
88 struct device *parent, *self;
89 void *aux;
90 {
91 struct boca_softc *sc = (void *)self;
92 struct isa_attach_args *ia = aux;
93 struct boca_attach_args ba;
94 struct isa_attach_args isa;
95
96 sc->sc_iobase = ia->ia_iobase;
97
98 printf("\n");
99
100 isa.ia_aux = &ba;
101 for (ba.ba_slave = 0; ba.ba_slave < 8; ba.ba_slave++) {
102 struct cfdata *cf;
103 isa.ia_iobase = sc->sc_iobase + 8 * ba.ba_slave;
104 isa.ia_iosize = 0x666;
105 isa.ia_irq = IRQUNK;
106 isa.ia_drq = DRQUNK;
107 isa.ia_msize = 0;
108 if ((cf = config_search(bocasubmatch, self, &isa)) != 0) {
109 config_attach(self, cf, &isa, bocaprint);
110 sc->sc_slaves[ba.ba_slave] =
111 cf->cf_driver->cd_devs[cf->cf_unit];
112 sc->sc_alive |= 1 << ba.ba_slave;
113 }
114 }
115
116 sc->sc_ih.ih_fun = bocaintr;
117 sc->sc_ih.ih_arg = sc;
118 sc->sc_ih.ih_level = IPL_TTY;
119 intr_establish(ia->ia_irq, IST_EDGE, &sc->sc_ih);
120 }
121
122 int
123 bocaintr(sc)
124 struct boca_softc *sc;
125 {
126 int iobase = sc->sc_iobase;
127 int alive = sc->sc_alive;
128 int bits;
129
130 bits = inb(iobase | 0x07) & alive;
131 if (bits == 0)
132 return (0);
133
134 for (;;) {
135 #define TRY(n) \
136 if (bits & (1 << (n))) \
137 comintr(sc->sc_slaves[n]);
138 TRY(0);
139 TRY(1);
140 TRY(2);
141 TRY(3);
142 TRY(4);
143 TRY(5);
144 TRY(6);
145 TRY(7);
146 #undef TRY
147 bits = inb(iobase | 0x07) & alive;
148 if (bits == 0)
149 return (1);
150 }
151 }
152