ast.c revision 1.8 1 1.1 cgd /*
2 1.1 cgd * Multi-port serial card interrupt demuxing support.
3 1.1 cgd * Roland McGrath 3/20/94
4 1.4 cgd * The author disclaims copyright and places this file in the public domain.
5 1.1 cgd *
6 1.4 cgd * Modified by: Charles Hannum, 3/22/94
7 1.4 cgd *
8 1.8 mycroft * $Id: ast.c,v 1.8 1994/08/14 14:13:25 mycroft Exp $
9 1.1 cgd */
10 1.1 cgd
11 1.5 mycroft #include <sys/param.h>
12 1.2 mycroft #include <sys/device.h>
13 1.1 cgd
14 1.1 cgd #include <machine/pio.h>
15 1.5 mycroft
16 1.5 mycroft #ifndef NEWCONFIG
17 1.1 cgd #include <i386/isa/isa_device.h>
18 1.5 mycroft #endif
19 1.5 mycroft #include <i386/isa/isavar.h>
20 1.1 cgd
21 1.2 mycroft struct ast_softc {
22 1.2 mycroft struct device sc_dev;
23 1.7 mycroft struct intrhand sc_ih;
24 1.7 mycroft
25 1.2 mycroft u_short sc_iobase;
26 1.5 mycroft int sc_alive; /* mask of slave units attached */
27 1.7 mycroft void *sc_slaves[4]; /* com device unit numbers */
28 1.5 mycroft };
29 1.5 mycroft
30 1.5 mycroft int astprobe();
31 1.5 mycroft void astattach();
32 1.7 mycroft int astintr __P((struct ast_softc *));
33 1.5 mycroft
34 1.5 mycroft struct cfdriver astcd = {
35 1.5 mycroft NULL, "ast", astprobe, astattach, DV_TTY, sizeof(struct ast_softc)
36 1.5 mycroft };
37 1.1 cgd
38 1.1 cgd int
39 1.5 mycroft astprobe(parent, self, aux)
40 1.5 mycroft struct device *parent, *self;
41 1.5 mycroft void *aux;
42 1.1 cgd {
43 1.5 mycroft struct isa_attach_args *ia = aux;
44 1.2 mycroft
45 1.1 cgd /*
46 1.1 cgd * Do the normal com probe for the first UART and assume
47 1.1 cgd * its presence means there is a multiport board there.
48 1.5 mycroft * XXX Needs more robustness.
49 1.1 cgd */
50 1.6 mycroft ia->ia_iosize = 4 * 8;
51 1.5 mycroft return comprobe1(ia->ia_iobase);
52 1.1 cgd }
53 1.1 cgd
54 1.5 mycroft struct ast_attach_args {
55 1.5 mycroft u_short aa_iobase;
56 1.5 mycroft int aa_slave;
57 1.5 mycroft };
58 1.5 mycroft
59 1.1 cgd int
60 1.5 mycroft astsubmatch(parent, self, aux)
61 1.5 mycroft struct device *parent, *self;
62 1.5 mycroft void *aux;
63 1.1 cgd {
64 1.5 mycroft struct ast_softc *sc = (void *)parent;
65 1.5 mycroft struct ast_attach_args *aa = aux;
66 1.5 mycroft struct cfdata *cf = self->dv_cfdata;
67 1.5 mycroft int found, frobbed = 0;
68 1.5 mycroft #ifdef NEWCONFIG
69 1.2 mycroft
70 1.5 mycroft #define cf_slave cf_loc[6]
71 1.5 mycroft if (cf->cf_slave != -1 && cf->cf_slave != aa->aa_slave)
72 1.5 mycroft return 0;
73 1.5 mycroft if (cf->cf_iobase == IOBASEUNK) {
74 1.5 mycroft frobbed = 1;
75 1.5 mycroft cf->cf_iobase = aa->aa_iobase;
76 1.5 mycroft }
77 1.5 mycroft #undef cf_slave
78 1.5 mycroft #else
79 1.5 mycroft struct isa_device *id = (void *)cf->cf_loc;
80 1.1 cgd
81 1.5 mycroft if (id->id_physid != -1 && id->id_physid != aa->aa_slave)
82 1.5 mycroft return 0;
83 1.5 mycroft if (id->id_iobase == 0) {
84 1.5 mycroft frobbed = 1;
85 1.5 mycroft id->id_iobase = aa->aa_iobase;
86 1.5 mycroft }
87 1.5 mycroft #endif
88 1.5 mycroft found = isasubmatch(parent, self, aux);
89 1.5 mycroft if (found) {
90 1.7 mycroft sc->sc_slaves[aa->aa_slave] = self;
91 1.5 mycroft sc->sc_alive |= 1 << aa->aa_slave;
92 1.5 mycroft }
93 1.1 cgd /*
94 1.5 mycroft * If we changed the iobase, we have to set it back now, because it
95 1.5 mycroft * might be a clone device, and the iobase wouldn't get set properly on
96 1.5 mycroft * the next iteration.
97 1.1 cgd */
98 1.5 mycroft #ifdef NEWCONFIG
99 1.5 mycroft if (frobbed)
100 1.5 mycroft cf->cf_iobase = IOBASEUNK;
101 1.5 mycroft #else
102 1.5 mycroft if (frobbed)
103 1.5 mycroft id->id_iobase = 0;
104 1.5 mycroft #endif
105 1.5 mycroft return found;
106 1.1 cgd }
107 1.1 cgd
108 1.1 cgd void
109 1.5 mycroft astattach(parent, self, aux)
110 1.5 mycroft struct device *parent, *self;
111 1.5 mycroft void *aux;
112 1.1 cgd {
113 1.5 mycroft struct ast_softc *sc = (void *)self;
114 1.5 mycroft struct isa_attach_args *ia = aux;
115 1.5 mycroft struct ast_attach_args aa;
116 1.1 cgd
117 1.5 mycroft /*
118 1.5 mycroft * Enable the master interrupt.
119 1.5 mycroft */
120 1.5 mycroft sc->sc_iobase = ia->ia_iobase;
121 1.5 mycroft outb(sc->sc_iobase | 0x1f, 0x80);
122 1.5 mycroft printf("\n");
123 1.5 mycroft
124 1.5 mycroft for (aa.aa_slave = 0, aa.aa_iobase = sc->sc_iobase;
125 1.5 mycroft aa.aa_slave < 4;
126 1.5 mycroft aa.aa_slave++, aa.aa_iobase += 8)
127 1.5 mycroft config_search(astsubmatch, self, &aa);
128 1.7 mycroft
129 1.7 mycroft sc->sc_ih.ih_fun = astintr;
130 1.7 mycroft sc->sc_ih.ih_arg = sc;
131 1.7 mycroft sc->sc_ih.ih_level = IPL_TTY;
132 1.7 mycroft intr_establish(ia->ia_irq, &sc->sc_ih);
133 1.1 cgd }
134 1.1 cgd
135 1.1 cgd int
136 1.7 mycroft astintr(sc)
137 1.7 mycroft struct ast_softc *sc;
138 1.1 cgd {
139 1.2 mycroft u_short iobase = sc->sc_iobase;
140 1.2 mycroft int alive = sc->sc_alive;
141 1.1 cgd int bits;
142 1.1 cgd
143 1.8 mycroft bits = ~(inb(iobase | 0x1f)) & alive;
144 1.8 mycroft if (bits == 0)
145 1.2 mycroft return 0;
146 1.2 mycroft
147 1.8 mycroft for (;;) {
148 1.2 mycroft #define TRY(n) \
149 1.8 mycroft if (bits & (1 << (n))) \
150 1.5 mycroft comintr(sc->sc_slaves[n]);
151 1.2 mycroft TRY(0);
152 1.2 mycroft TRY(1);
153 1.2 mycroft TRY(2);
154 1.2 mycroft TRY(3);
155 1.5 mycroft #undef TRY
156 1.8 mycroft bits = ~(inb(iobase | 0x1f)) & alive;
157 1.8 mycroft if (bits == 0)
158 1.8 mycroft return 1;
159 1.8 mycroft }
160 1.1 cgd }
161