isa.c revision 1.51 1 1.1 cgd /*-
2 1.40 mycroft * Copyright (c) 1993, 1994 Charles Hannum.
3 1.1 cgd * Copyright (c) 1991 The Regents of the University of California.
4 1.1 cgd * All rights reserved.
5 1.1 cgd *
6 1.1 cgd * This code is derived from software contributed to Berkeley by
7 1.1 cgd * William Jolitz.
8 1.1 cgd *
9 1.1 cgd * Redistribution and use in source and binary forms, with or without
10 1.1 cgd * modification, are permitted provided that the following conditions
11 1.1 cgd * are met:
12 1.1 cgd * 1. Redistributions of source code must retain the above copyright
13 1.1 cgd * notice, this list of conditions and the following disclaimer.
14 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 cgd * notice, this list of conditions and the following disclaimer in the
16 1.1 cgd * documentation and/or other materials provided with the distribution.
17 1.1 cgd * 3. All advertising materials mentioning features or use of this software
18 1.1 cgd * must display the following acknowledgement:
19 1.1 cgd * This product includes software developed by the University of
20 1.1 cgd * California, Berkeley and its contributors.
21 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
22 1.1 cgd * may be used to endorse or promote products derived from this software
23 1.1 cgd * without specific prior written permission.
24 1.1 cgd *
25 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 1.1 cgd * SUCH DAMAGE.
36 1.1 cgd *
37 1.13 cgd * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
38 1.51 mycroft * $Id: isa.c,v 1.51 1994/04/22 22:58:59 mycroft Exp $
39 1.1 cgd */
40 1.1 cgd
41 1.1 cgd /*
42 1.49 mycroft * Code to manage AT bus
43 1.1 cgd */
44 1.1 cgd
45 1.31 mycroft #include <sys/param.h>
46 1.31 mycroft #include <sys/systm.h>
47 1.40 mycroft #include <sys/kernel.h>
48 1.31 mycroft #include <sys/conf.h>
49 1.31 mycroft #include <sys/malloc.h>
50 1.46 mycroft #include <sys/device.h>
51 1.31 mycroft
52 1.32 mycroft #include <machine/pio.h>
53 1.31 mycroft #include <machine/cpufunc.h>
54 1.31 mycroft
55 1.46 mycroft #include <i386/isa/isa.h>
56 1.31 mycroft #include <i386/isa/isa_device.h>
57 1.46 mycroft #include <i386/isa/isavar.h>
58 1.31 mycroft #include <i386/isa/ic/i8042.h>
59 1.31 mycroft #include <i386/isa/timerreg.h>
60 1.31 mycroft #include <i386/isa/spkr_reg.h>
61 1.14 deraadt
62 1.14 deraadt /* sorry, has to be here, no place else really suitable */
63 1.31 mycroft #include <machine/pc/display.h>
64 1.14 deraadt u_short *Crtat = (u_short *)MONO_BUF;
65 1.1 cgd
66 1.21 andrew static void sysbeepstop(int);
67 1.1 cgd
68 1.1 cgd /*
69 1.1 cgd * Configure all ISA devices
70 1.46 mycroft *
71 1.46 mycroft * XXX This code is a hack. It wants to be new config, but can't be until the
72 1.46 mycroft * interrupt system is redone. For now, we do some gross hacks to make it look
73 1.46 mycroft * 99% like new config.
74 1.46 mycroft */
75 1.46 mycroft static char *msgs[3] = { "", " not configured\n", " unsupported\n" };
76 1.46 mycroft
77 1.46 mycroft struct cfdata *
78 1.46 mycroft config_search(fn, parent, aux)
79 1.46 mycroft cfmatch_t fn;
80 1.46 mycroft struct device *parent;
81 1.46 mycroft void *aux;
82 1.46 mycroft {
83 1.46 mycroft struct cfdata *cf = 0;
84 1.46 mycroft struct device *dv = 0;
85 1.46 mycroft size_t devsize;
86 1.46 mycroft struct cfdriver *cd;
87 1.46 mycroft struct isa_device *id,
88 1.46 mycroft *idp = parent ? (void *)parent->dv_cfdata->cf_loc : 0;
89 1.46 mycroft
90 1.46 mycroft for (id = isa_devtab; id->id_driver; id++) {
91 1.46 mycroft if (id->id_state == FSTATE_FOUND)
92 1.46 mycroft continue;
93 1.46 mycroft if (id->id_parent != idp)
94 1.46 mycroft continue;
95 1.46 mycroft cd = id->id_driver;
96 1.46 mycroft if (id->id_unit < cd->cd_ndevs) {
97 1.46 mycroft if (cd->cd_devs[id->id_unit] != 0)
98 1.46 mycroft continue;
99 1.46 mycroft } else {
100 1.46 mycroft int old = cd->cd_ndevs, new;
101 1.46 mycroft void **nsp;
102 1.46 mycroft
103 1.46 mycroft if (old == 0) {
104 1.46 mycroft nsp = malloc(MINALLOCSIZE, M_DEVBUF, M_NOWAIT);
105 1.46 mycroft if (!nsp)
106 1.46 mycroft panic("config_search: creating dev array");
107 1.46 mycroft bzero(nsp, MINALLOCSIZE);
108 1.46 mycroft cd->cd_ndevs = MINALLOCSIZE / sizeof(void *);
109 1.46 mycroft } else {
110 1.46 mycroft new = old;
111 1.46 mycroft do {
112 1.46 mycroft new *= 2;
113 1.46 mycroft } while (new <= id->id_unit);
114 1.46 mycroft cd->cd_ndevs = new;
115 1.46 mycroft nsp = malloc(new * sizeof(void *), M_DEVBUF,
116 1.46 mycroft M_NOWAIT);
117 1.46 mycroft if (!nsp)
118 1.46 mycroft panic("config_search: expanding dev array");
119 1.46 mycroft bzero(nsp, new * sizeof(void *));
120 1.46 mycroft bcopy(cd->cd_devs, nsp, old * sizeof(void *));
121 1.46 mycroft free(cd->cd_devs, M_DEVBUF);
122 1.46 mycroft }
123 1.46 mycroft cd->cd_devs = nsp;
124 1.46 mycroft }
125 1.46 mycroft if (!cf) {
126 1.51 mycroft cf = malloc(sizeof(struct cfdata), M_DEVBUF, M_NOWAIT);
127 1.51 mycroft if (!cf)
128 1.46 mycroft panic("config_search: creating cfdata");
129 1.46 mycroft }
130 1.46 mycroft cf->cf_driver = cd;
131 1.46 mycroft cf->cf_unit = id->id_unit;
132 1.46 mycroft cf->cf_fstate = 0;
133 1.46 mycroft cf->cf_loc = (void *)id;
134 1.46 mycroft cf->cf_flags = id->id_flags;
135 1.46 mycroft cf->cf_parents = 0;
136 1.46 mycroft cf->cf_ivstubs = 0;
137 1.46 mycroft if (dv && devsize != cd->cd_devsize) {
138 1.46 mycroft free(dv, M_DEVBUF);
139 1.46 mycroft dv = 0;
140 1.46 mycroft }
141 1.46 mycroft if (!dv) {
142 1.46 mycroft devsize = cd->cd_devsize;
143 1.46 mycroft dv = malloc(devsize, M_DEVBUF, M_NOWAIT);
144 1.46 mycroft if (!dv)
145 1.46 mycroft panic("config_search: creating softc");
146 1.46 mycroft }
147 1.46 mycroft bzero(dv, cd->cd_devsize);
148 1.46 mycroft dv->dv_class = cd->cd_class;
149 1.46 mycroft dv->dv_cfdata = cf;
150 1.46 mycroft dv->dv_unit = id->id_unit;
151 1.46 mycroft sprintf(dv->dv_xname, "%s%d", cd->cd_name, id->id_unit);
152 1.46 mycroft dv->dv_parent = parent;
153 1.46 mycroft cd->cd_devs[id->id_unit] = dv;
154 1.46 mycroft if (fn) {
155 1.46 mycroft if ((*fn)(parent, dv, aux))
156 1.46 mycroft return cf;
157 1.46 mycroft } else {
158 1.46 mycroft if ((*cd->cd_match)(parent, dv, aux))
159 1.46 mycroft return cf;
160 1.46 mycroft }
161 1.47 mycroft cd->cd_devs[id->id_unit] = 0;
162 1.46 mycroft }
163 1.46 mycroft if (cf)
164 1.46 mycroft free(cf, M_DEVBUF);
165 1.46 mycroft if (dv)
166 1.46 mycroft free(dv, M_DEVBUF);
167 1.46 mycroft return 0;
168 1.46 mycroft }
169 1.46 mycroft
170 1.46 mycroft void
171 1.46 mycroft config_attach(parent, cf, aux, print)
172 1.46 mycroft struct device *parent;
173 1.46 mycroft struct cfdata *cf;
174 1.46 mycroft void *aux;
175 1.46 mycroft cfprint_t print;
176 1.46 mycroft {
177 1.46 mycroft struct isa_device *id = (void *)cf->cf_loc;
178 1.46 mycroft struct cfdriver *cd = cf->cf_driver;
179 1.46 mycroft struct device *dv = cd->cd_devs[id->id_unit];
180 1.46 mycroft
181 1.46 mycroft cf->cf_fstate = id->id_state = FSTATE_FOUND;
182 1.46 mycroft printf("%s at %s", dv->dv_xname, parent ? parent->dv_xname : "isa0");
183 1.46 mycroft if (print)
184 1.46 mycroft (void) (*print)(aux, (char *)0);
185 1.46 mycroft (*cd->cd_attach)(parent, dv, aux);
186 1.46 mycroft }
187 1.46 mycroft
188 1.46 mycroft int
189 1.46 mycroft config_found(parent, aux, print)
190 1.46 mycroft struct device *parent;
191 1.46 mycroft void *aux;
192 1.46 mycroft cfprint_t print;
193 1.46 mycroft {
194 1.46 mycroft struct cfdata *cf;
195 1.46 mycroft
196 1.46 mycroft if ((cf = config_search((cfmatch_t)NULL, parent, aux)) != NULL) {
197 1.46 mycroft config_attach(parent, cf, aux, print);
198 1.46 mycroft return 1;
199 1.46 mycroft }
200 1.46 mycroft if (print)
201 1.46 mycroft printf(msgs[(*print)(aux, parent->dv_xname)]);
202 1.46 mycroft return 0;
203 1.46 mycroft }
204 1.46 mycroft
205 1.46 mycroft int
206 1.46 mycroft isaprint(aux, isa)
207 1.46 mycroft void *aux;
208 1.46 mycroft char *isa;
209 1.46 mycroft {
210 1.46 mycroft struct isa_attach_args *ia = aux;
211 1.46 mycroft
212 1.46 mycroft if (ia->ia_iosize)
213 1.46 mycroft printf(" port 0x%x", ia->ia_iobase);
214 1.46 mycroft if (ia->ia_iosize > 1)
215 1.46 mycroft printf("-0x%x", ia->ia_iobase + ia->ia_iosize - 1);
216 1.46 mycroft if (ia->ia_msize)
217 1.46 mycroft printf(" iomem 0x%x", ia->ia_maddr - atdevbase + 0xa0000);
218 1.46 mycroft if (ia->ia_msize > 1)
219 1.46 mycroft printf("-0x%x",
220 1.46 mycroft ia->ia_maddr - atdevbase + 0xa0000 + ia->ia_msize - 1);
221 1.46 mycroft if (ia->ia_irq)
222 1.46 mycroft printf(" irq %d", ffs(ia->ia_irq) - 1);
223 1.46 mycroft if (ia->ia_drq != (u_short)-1)
224 1.46 mycroft printf(" drq %d", ia->ia_drq);
225 1.46 mycroft /* XXXX print flags */
226 1.46 mycroft return QUIET;
227 1.46 mycroft }
228 1.46 mycroft
229 1.46 mycroft int
230 1.46 mycroft isasubmatch(parent, self, aux)
231 1.46 mycroft struct device *parent, *self;
232 1.46 mycroft void *aux;
233 1.46 mycroft {
234 1.46 mycroft struct isa_device *id = (void *)self->dv_cfdata->cf_loc;
235 1.46 mycroft struct isa_attach_args ia;
236 1.46 mycroft
237 1.46 mycroft ia.ia_iobase = id->id_iobase;
238 1.46 mycroft ia.ia_iosize = 0x666;
239 1.46 mycroft ia.ia_irq = id->id_irq;
240 1.46 mycroft ia.ia_drq = id->id_drq;
241 1.46 mycroft ia.ia_maddr = id->id_maddr - 0xa0000 + atdevbase;
242 1.46 mycroft ia.ia_msize = id->id_msize;
243 1.46 mycroft
244 1.46 mycroft if (!(*id->id_driver->cd_match)(parent, self, &ia)) {
245 1.46 mycroft /*
246 1.46 mycroft * If we don't do this, isa_configure() will repeatedly try to
247 1.46 mycroft * probe devices that weren't found. But we need to be careful
248 1.46 mycroft * to do it only for the ISA bus, or we would cause things like
249 1.46 mycroft * `com0 at ast? slave ?' to not probe on the second ast.
250 1.46 mycroft */
251 1.46 mycroft if (!parent)
252 1.46 mycroft id->id_state = FSTATE_FOUND;
253 1.46 mycroft
254 1.46 mycroft return 0;
255 1.46 mycroft }
256 1.46 mycroft
257 1.46 mycroft config_attach(parent, self->dv_cfdata, &ia, isaprint);
258 1.46 mycroft
259 1.46 mycroft return 1;
260 1.46 mycroft }
261 1.46 mycroft
262 1.21 andrew void
263 1.30 mycroft isa_configure()
264 1.30 mycroft {
265 1.1 cgd
266 1.46 mycroft while (config_search(isasubmatch, NULL, NULL));
267 1.7 cgd
268 1.49 mycroft printf("biomask %x netmask %x ttymask %x\n",
269 1.49 mycroft (u_short)imask[IPL_BIO], (u_short)imask[IPL_NET],
270 1.49 mycroft (u_short)imask[IPL_TTY]);
271 1.26 mycroft
272 1.30 mycroft spl0();
273 1.1 cgd }
274 1.1 cgd
275 1.49 mycroft static int beeping;
276 1.1 cgd
277 1.21 andrew static void
278 1.21 andrew sysbeepstop(int f)
279 1.1 cgd {
280 1.16 mycroft int s = splhigh();
281 1.16 mycroft
282 1.1 cgd /* disable counter 2 */
283 1.16 mycroft disable_intr();
284 1.28 brezak outb(PITAUX_PORT, inb(PITAUX_PORT) & ~PIT_SPKR);
285 1.16 mycroft enable_intr();
286 1.1 cgd if (f)
287 1.24 deraadt timeout((timeout_t)sysbeepstop, (caddr_t)0, f);
288 1.1 cgd else
289 1.1 cgd beeping = 0;
290 1.16 mycroft
291 1.16 mycroft splx(s);
292 1.1 cgd }
293 1.1 cgd
294 1.21 andrew void
295 1.21 andrew sysbeep(int pitch, int period)
296 1.1 cgd {
297 1.16 mycroft int s = splhigh();
298 1.16 mycroft static int last_pitch, last_period;
299 1.1 cgd
300 1.16 mycroft if (beeping) {
301 1.24 deraadt untimeout((timeout_t)sysbeepstop, (caddr_t)(last_period/2));
302 1.24 deraadt untimeout((timeout_t)sysbeepstop, (caddr_t)0);
303 1.1 cgd }
304 1.16 mycroft if (!beeping || last_pitch != pitch) {
305 1.16 mycroft /*
306 1.16 mycroft * XXX - move timer stuff to clock.c.
307 1.16 mycroft */
308 1.16 mycroft disable_intr();
309 1.16 mycroft outb(TIMER_MODE, TIMER_SEL2|TIMER_16BIT|TIMER_SQWAVE);
310 1.19 mycroft outb(TIMER_CNTR2, TIMER_DIV(pitch)%256);
311 1.19 mycroft outb(TIMER_CNTR2, TIMER_DIV(pitch)/256);
312 1.28 brezak outb(PITAUX_PORT, inb(PITAUX_PORT) | PIT_SPKR); /* enable counter 2 */
313 1.16 mycroft enable_intr();
314 1.16 mycroft }
315 1.16 mycroft last_pitch = pitch;
316 1.16 mycroft beeping = last_period = period;
317 1.24 deraadt timeout((timeout_t)sysbeepstop, (caddr_t)(period/2), period);
318 1.16 mycroft
319 1.16 mycroft splx(s);
320 1.1 cgd }
321