ast.c revision 1.5 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.5 mycroft * $Id: ast.c,v 1.5 1994/03/29 04:35:37 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.2 mycroft u_short sc_iobase;
24 1.5 mycroft int sc_alive; /* mask of slave units attached */
25 1.5 mycroft int sc_slaves[8]; /* com device unit numbers */
26 1.5 mycroft };
27 1.5 mycroft
28 1.5 mycroft int astprobe();
29 1.5 mycroft void astattach();
30 1.5 mycroft
31 1.5 mycroft struct cfdriver astcd = {
32 1.5 mycroft NULL, "ast", astprobe, astattach, DV_TTY, sizeof(struct ast_softc)
33 1.5 mycroft };
34 1.1 cgd
35 1.1 cgd int
36 1.5 mycroft astprobe(parent, self, aux)
37 1.5 mycroft struct device *parent, *self;
38 1.5 mycroft void *aux;
39 1.1 cgd {
40 1.5 mycroft struct isa_attach_args *ia = aux;
41 1.2 mycroft
42 1.1 cgd /*
43 1.1 cgd * Do the normal com probe for the first UART and assume
44 1.1 cgd * its presence means there is a multiport board there.
45 1.5 mycroft * XXX Needs more robustness.
46 1.1 cgd */
47 1.5 mycroft return comprobe1(ia->ia_iobase);
48 1.1 cgd }
49 1.1 cgd
50 1.5 mycroft struct ast_attach_args {
51 1.5 mycroft u_short aa_iobase;
52 1.5 mycroft int aa_slave;
53 1.5 mycroft };
54 1.5 mycroft
55 1.1 cgd int
56 1.5 mycroft astsubmatch(parent, self, aux)
57 1.5 mycroft struct device *parent, *self;
58 1.5 mycroft void *aux;
59 1.1 cgd {
60 1.5 mycroft struct ast_softc *sc = (void *)parent;
61 1.5 mycroft struct ast_attach_args *aa = aux;
62 1.5 mycroft struct cfdata *cf = self->dv_cfdata;
63 1.5 mycroft int found, frobbed = 0;
64 1.5 mycroft #ifdef NEWCONFIG
65 1.2 mycroft
66 1.5 mycroft #define cf_slave cf_loc[6]
67 1.5 mycroft if (cf->cf_slave != -1 && cf->cf_slave != aa->aa_slave)
68 1.5 mycroft return 0;
69 1.5 mycroft if (cf->cf_iobase == IOBASEUNK) {
70 1.5 mycroft frobbed = 1;
71 1.5 mycroft cf->cf_iobase = aa->aa_iobase;
72 1.5 mycroft }
73 1.5 mycroft #undef cf_slave
74 1.5 mycroft #else
75 1.5 mycroft struct isa_device *id = (void *)cf->cf_loc;
76 1.1 cgd
77 1.5 mycroft if (id->id_physid != -1 && id->id_physid != aa->aa_slave)
78 1.5 mycroft return 0;
79 1.5 mycroft if (id->id_iobase == 0) {
80 1.5 mycroft frobbed = 1;
81 1.5 mycroft id->id_iobase = aa->aa_iobase;
82 1.5 mycroft }
83 1.5 mycroft #endif
84 1.5 mycroft found = isasubmatch(parent, self, aux);
85 1.5 mycroft if (found) {
86 1.5 mycroft sc->sc_slaves[aa->aa_slave] = cf->cf_unit;
87 1.5 mycroft sc->sc_alive |= 1 << aa->aa_slave;
88 1.5 mycroft }
89 1.1 cgd /*
90 1.5 mycroft * If we changed the iobase, we have to set it back now, because it
91 1.5 mycroft * might be a clone device, and the iobase wouldn't get set properly on
92 1.5 mycroft * the next iteration.
93 1.1 cgd */
94 1.5 mycroft #ifdef NEWCONFIG
95 1.5 mycroft if (frobbed)
96 1.5 mycroft cf->cf_iobase = IOBASEUNK;
97 1.5 mycroft #else
98 1.5 mycroft if (frobbed)
99 1.5 mycroft id->id_iobase = 0;
100 1.5 mycroft #endif
101 1.5 mycroft return found;
102 1.1 cgd }
103 1.1 cgd
104 1.1 cgd void
105 1.5 mycroft astattach(parent, self, aux)
106 1.5 mycroft struct device *parent, *self;
107 1.5 mycroft void *aux;
108 1.1 cgd {
109 1.5 mycroft struct ast_softc *sc = (void *)self;
110 1.5 mycroft struct isa_attach_args *ia = aux;
111 1.5 mycroft struct ast_attach_args aa;
112 1.1 cgd
113 1.5 mycroft /*
114 1.5 mycroft * Enable the master interrupt.
115 1.5 mycroft */
116 1.5 mycroft sc->sc_iobase = ia->ia_iobase;
117 1.5 mycroft outb(sc->sc_iobase | 0x1f, 0x80);
118 1.5 mycroft printf("\n");
119 1.5 mycroft
120 1.5 mycroft for (aa.aa_slave = 0, aa.aa_iobase = sc->sc_iobase;
121 1.5 mycroft aa.aa_slave < 4;
122 1.5 mycroft aa.aa_slave++, aa.aa_iobase += 8)
123 1.5 mycroft config_search(astsubmatch, self, &aa);
124 1.1 cgd }
125 1.1 cgd
126 1.1 cgd int
127 1.2 mycroft astintr(unit)
128 1.2 mycroft int unit;
129 1.1 cgd {
130 1.5 mycroft struct ast_softc *sc = astcd.cd_devs[unit];
131 1.2 mycroft u_short iobase = sc->sc_iobase;
132 1.2 mycroft int alive = sc->sc_alive;
133 1.1 cgd int bits;
134 1.1 cgd
135 1.2 mycroft bits = inb(iobase | 0x1f) & alive;
136 1.2 mycroft if (bits == alive)
137 1.2 mycroft return 0;
138 1.2 mycroft
139 1.1 cgd do {
140 1.2 mycroft #define TRY(n) \
141 1.2 mycroft if ((bits & (1 << (n))) == 0) \
142 1.5 mycroft comintr(sc->sc_slaves[n]);
143 1.2 mycroft TRY(0);
144 1.2 mycroft TRY(1);
145 1.2 mycroft TRY(2);
146 1.2 mycroft TRY(3);
147 1.5 mycroft #undef TRY
148 1.2 mycroft bits = inb(iobase | 0x1f) & alive;
149 1.1 cgd } while (bits != alive);
150 1.1 cgd
151 1.1 cgd return 1;
152 1.1 cgd }
153