isabus.c revision 1.13.2.3 1 1.13.2.3 bouyer /* $NetBSD: isabus.c,v 1.13.2.3 2001/01/05 17:33:56 bouyer Exp $ */
2 1.13.2.2 bouyer /* $OpenBSD: isabus.c,v 1.15 1998/03/16 09:38:46 pefo Exp $ */
3 1.13.2.2 bouyer /* NetBSD: isa.c,v 1.33 1995/06/28 04:30:51 cgd Exp */
4 1.13.2.2 bouyer
5 1.13.2.2 bouyer /*-
6 1.13.2.2 bouyer * Copyright (c) 1995 Per Fogelstrom
7 1.13.2.2 bouyer * Copyright (c) 1993, 1994 Charles M. Hannum.
8 1.13.2.2 bouyer * Copyright (c) 1990 The Regents of the University of California.
9 1.13.2.2 bouyer * All rights reserved.
10 1.13.2.2 bouyer *
11 1.13.2.2 bouyer * This code is derived from software contributed to Berkeley by
12 1.13.2.2 bouyer * William Jolitz and Don Ahn.
13 1.13.2.2 bouyer *
14 1.13.2.2 bouyer * Redistribution and use in source and binary forms, with or without
15 1.13.2.2 bouyer * modification, are permitted provided that the following conditions
16 1.13.2.2 bouyer * are met:
17 1.13.2.2 bouyer * 1. Redistributions of source code must retain the above copyright
18 1.13.2.2 bouyer * notice, this list of conditions and the following disclaimer.
19 1.13.2.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
20 1.13.2.2 bouyer * notice, this list of conditions and the following disclaimer in the
21 1.13.2.2 bouyer * documentation and/or other materials provided with the distribution.
22 1.13.2.2 bouyer * 3. All advertising materials mentioning features or use of this software
23 1.13.2.2 bouyer * must display the following acknowledgement:
24 1.13.2.2 bouyer * This product includes software developed by the University of
25 1.13.2.2 bouyer * California, Berkeley and its contributors.
26 1.13.2.2 bouyer * 4. Neither the name of the University nor the names of its contributors
27 1.13.2.2 bouyer * may be used to endorse or promote products derived from this software
28 1.13.2.2 bouyer * without specific prior written permission.
29 1.13.2.2 bouyer *
30 1.13.2.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 1.13.2.2 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 1.13.2.2 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 1.13.2.2 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 1.13.2.2 bouyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 1.13.2.2 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 1.13.2.2 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 1.13.2.2 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 1.13.2.2 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 1.13.2.2 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 1.13.2.2 bouyer * SUCH DAMAGE.
41 1.13.2.2 bouyer *
42 1.13.2.2 bouyer * @(#)isa.c 7.2 (Berkeley) 5/12/91
43 1.13.2.2 bouyer */
44 1.13.2.2 bouyer /*
45 1.13.2.2 bouyer * Mach Operating System
46 1.13.2.2 bouyer * Copyright (c) 1991,1990,1989 Carnegie Mellon University
47 1.13.2.2 bouyer * All Rights Reserved.
48 1.13.2.2 bouyer *
49 1.13.2.2 bouyer * Permission to use, copy, modify and distribute this software and its
50 1.13.2.2 bouyer * documentation is hereby granted, provided that both the copyright
51 1.13.2.2 bouyer * notice and this permission notice appear in all copies of the
52 1.13.2.2 bouyer * software, derivative works or modified versions, and any portions
53 1.13.2.2 bouyer * thereof, and that both notices appear in supporting documentation.
54 1.13.2.2 bouyer *
55 1.13.2.2 bouyer * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
56 1.13.2.2 bouyer * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
57 1.13.2.2 bouyer * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
58 1.13.2.2 bouyer *
59 1.13.2.2 bouyer * Carnegie Mellon requests users of this software to return to
60 1.13.2.2 bouyer *
61 1.13.2.2 bouyer * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
62 1.13.2.2 bouyer * School of Computer Science
63 1.13.2.2 bouyer * Carnegie Mellon University
64 1.13.2.2 bouyer * Pittsburgh PA 15213-3890
65 1.13.2.2 bouyer *
66 1.13.2.2 bouyer * any improvements or extensions that they make and grant Carnegie Mellon
67 1.13.2.2 bouyer * the rights to redistribute these changes.
68 1.13.2.2 bouyer */
69 1.13.2.2 bouyer /*
70 1.13.2.2 bouyer Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
71 1.13.2.2 bouyer
72 1.13.2.2 bouyer All Rights Reserved
73 1.13.2.2 bouyer
74 1.13.2.2 bouyer Permission to use, copy, modify, and distribute this software and
75 1.13.2.2 bouyer its documentation for any purpose and without fee is hereby
76 1.13.2.2 bouyer granted, provided that the above copyright notice appears in all
77 1.13.2.2 bouyer copies and that both the copyright notice and this permission notice
78 1.13.2.2 bouyer appear in supporting documentation, and that the name of Intel
79 1.13.2.2 bouyer not be used in advertising or publicity pertaining to distribution
80 1.13.2.2 bouyer of the software without specific, written prior permission.
81 1.13.2.2 bouyer
82 1.13.2.2 bouyer INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
83 1.13.2.2 bouyer INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
84 1.13.2.2 bouyer IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
85 1.13.2.2 bouyer CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
86 1.13.2.2 bouyer LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
87 1.13.2.2 bouyer NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
88 1.13.2.2 bouyer WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
89 1.13.2.2 bouyer */
90 1.13.2.2 bouyer
91 1.13.2.2 bouyer #include <sys/param.h>
92 1.13.2.2 bouyer #include <sys/proc.h>
93 1.13.2.2 bouyer #include <sys/user.h>
94 1.13.2.2 bouyer #include <sys/systm.h>
95 1.13.2.2 bouyer #include <sys/callout.h>
96 1.13.2.2 bouyer #include <sys/time.h>
97 1.13.2.2 bouyer #include <sys/kernel.h>
98 1.13.2.2 bouyer #include <sys/device.h>
99 1.13.2.2 bouyer #include <sys/malloc.h>
100 1.13.2.2 bouyer
101 1.13.2.2 bouyer #include <uvm/uvm_extern.h>
102 1.13.2.2 bouyer
103 1.13.2.2 bouyer #include <machine/cpu.h>
104 1.13.2.2 bouyer #include <machine/pio.h>
105 1.13.2.2 bouyer #include <machine/autoconf.h>
106 1.13.2.2 bouyer #include <machine/intr.h>
107 1.13.2.2 bouyer
108 1.13.2.2 bouyer #include <arc/arc/arctype.h>
109 1.13.2.3 bouyer #include <arc/jazz/pica.h>
110 1.13.2.3 bouyer #include <arc/jazz/rd94.h>
111 1.13.2.2 bouyer
112 1.13.2.2 bouyer #include <dev/isa/isareg.h>
113 1.13.2.2 bouyer #include <dev/isa/isavar.h>
114 1.13.2.2 bouyer #include <arc/isa/timerreg.h>
115 1.13.2.2 bouyer #include <arc/isa/spkrreg.h>
116 1.13.2.2 bouyer #include <machine/isa_machdep.h>
117 1.13.2.2 bouyer
118 1.13.2.2 bouyer static int beeping;
119 1.13.2.2 bouyer static struct callout sysbeep_ch = CALLOUT_INITIALIZER;
120 1.13.2.2 bouyer
121 1.13.2.2 bouyer #define IRQ_SLAVE 2
122 1.13.2.2 bouyer #define ICU_LEN 16
123 1.13.2.2 bouyer
124 1.13.2.2 bouyer struct isabr_softc {
125 1.13.2.2 bouyer struct device sc_dv;
126 1.13.2.2 bouyer struct arc_isa_bus arc_isa_cs;
127 1.13.2.2 bouyer struct abus sc_bus;
128 1.13.2.2 bouyer struct arc_bus_dma_tag sc_dmat;
129 1.13.2.2 bouyer };
130 1.13.2.2 bouyer
131 1.13.2.2 bouyer /* Definition of the driver for autoconfig. */
132 1.13.2.2 bouyer int isabrmatch(struct device *, struct cfdata *, void *);
133 1.13.2.2 bouyer void isabrattach(struct device *, struct device *, void *);
134 1.13.2.2 bouyer int isabrprint(void *, const char *);
135 1.13.2.2 bouyer
136 1.13.2.2 bouyer struct cfattach isabr_ca = {
137 1.13.2.2 bouyer sizeof(struct isabr_softc), isabrmatch, isabrattach
138 1.13.2.2 bouyer };
139 1.13.2.2 bouyer extern struct cfdriver isabr_cd;
140 1.13.2.2 bouyer
141 1.13.2.2 bouyer extern struct arc_bus_space arc_bus_io, arc_bus_mem;
142 1.13.2.2 bouyer
143 1.13.2.2 bouyer void isabr_attach_hook __P((struct device *, struct device *,
144 1.13.2.2 bouyer struct isabus_attach_args *));
145 1.13.2.2 bouyer const struct evcnt *isabr_intr_evcnt __P((isa_chipset_tag_t, int));
146 1.13.2.2 bouyer void *isabr_intr_establish __P((isa_chipset_tag_t, int, int, int,
147 1.13.2.2 bouyer int (*)(void *), void *));
148 1.13.2.2 bouyer void isabr_intr_disestablish __P((isa_chipset_tag_t, void*));
149 1.13.2.2 bouyer int isabr_iointr __P((unsigned int, struct clockframe *));
150 1.13.2.2 bouyer void isabr_initicu __P((void));
151 1.13.2.2 bouyer void intr_calculatemasks __P((void));
152 1.13.2.2 bouyer int fakeintr __P((void *a));
153 1.13.2.2 bouyer
154 1.13.2.2 bouyer int
155 1.13.2.2 bouyer isabrmatch(parent, match, aux)
156 1.13.2.2 bouyer struct device *parent;
157 1.13.2.2 bouyer struct cfdata *match;
158 1.13.2.2 bouyer void *aux;
159 1.13.2.2 bouyer {
160 1.13.2.2 bouyer struct confargs *ca = aux;
161 1.13.2.2 bouyer
162 1.13.2.2 bouyer /* Make sure that we're looking for a ISABR. */
163 1.13.2.2 bouyer if (strcmp(ca->ca_name, isabr_cd.cd_name) != 0)
164 1.13.2.2 bouyer return (0);
165 1.13.2.2 bouyer
166 1.13.2.2 bouyer return (1);
167 1.13.2.2 bouyer }
168 1.13.2.2 bouyer
169 1.13.2.2 bouyer void
170 1.13.2.2 bouyer isabrattach(parent, self, aux)
171 1.13.2.2 bouyer struct device *parent;
172 1.13.2.2 bouyer struct device *self;
173 1.13.2.2 bouyer void *aux;
174 1.13.2.2 bouyer {
175 1.13.2.2 bouyer struct isabr_softc *sc = (struct isabr_softc *)self;
176 1.13.2.2 bouyer struct isabus_attach_args iba;
177 1.13.2.2 bouyer
178 1.13.2.2 bouyer printf("\n");
179 1.13.2.2 bouyer
180 1.13.2.2 bouyer /* Initialize interrupt controller */
181 1.13.2.2 bouyer isabr_initicu();
182 1.13.2.2 bouyer
183 1.13.2.2 bouyer /* set up interrupt handlers */
184 1.13.2.2 bouyer switch(cputype) {
185 1.13.2.2 bouyer case ACER_PICA_61:
186 1.13.2.2 bouyer case MAGNUM:
187 1.13.2.2 bouyer case NEC_R94:
188 1.13.2.2 bouyer case NEC_R96:
189 1.13.2.2 bouyer jazz_bus_dma_tag_init(&sc->sc_dmat);
190 1.13.2.2 bouyer set_intr(MIPS_INT_MASK_2, isabr_iointr, 3);
191 1.13.2.2 bouyer break;
192 1.13.2.2 bouyer case DESKSTATION_TYNE:
193 1.13.2.2 bouyer _bus_dma_tag_init(&sc->sc_dmat); /* XXX dedicated bounce mem */
194 1.13.2.2 bouyer set_intr(MIPS_INT_MASK_2, isabr_iointr, 2);
195 1.13.2.2 bouyer break;
196 1.13.2.2 bouyer case DESKSTATION_RPC44:
197 1.13.2.2 bouyer isadma_bounce_tag_init(&sc->sc_dmat);
198 1.13.2.2 bouyer set_intr(MIPS_INT_MASK_2, isabr_iointr, 2);
199 1.13.2.2 bouyer break;
200 1.13.2.2 bouyer default:
201 1.13.2.2 bouyer panic("isabrattach: unkown cputype!");
202 1.13.2.2 bouyer }
203 1.13.2.2 bouyer
204 1.13.2.2 bouyer /*XXX we may remove the abus part of the softc struct... */
205 1.13.2.2 bouyer sc->sc_bus.ab_dv = (struct device *)sc;
206 1.13.2.2 bouyer sc->sc_bus.ab_type = BUS_ISABR;
207 1.13.2.2 bouyer
208 1.13.2.2 bouyer sc->arc_isa_cs.ic_attach_hook = isabr_attach_hook;
209 1.13.2.2 bouyer sc->arc_isa_cs.ic_intr_evcnt = isabr_intr_evcnt;
210 1.13.2.2 bouyer sc->arc_isa_cs.ic_intr_establish = isabr_intr_establish;
211 1.13.2.2 bouyer sc->arc_isa_cs.ic_intr_disestablish = isabr_intr_disestablish;
212 1.13.2.2 bouyer
213 1.13.2.2 bouyer iba.iba_busname = "isa";
214 1.13.2.2 bouyer iba.iba_iot = &arc_bus_io;
215 1.13.2.2 bouyer iba.iba_memt = &arc_bus_mem;
216 1.13.2.2 bouyer iba.iba_dmat = &sc->sc_dmat;
217 1.13.2.2 bouyer iba.iba_ic = &sc->arc_isa_cs;
218 1.13.2.2 bouyer config_found(self, &iba, isabrprint);
219 1.13.2.2 bouyer }
220 1.13.2.2 bouyer
221 1.13.2.2 bouyer int
222 1.13.2.2 bouyer isabrprint(aux, pnp)
223 1.13.2.2 bouyer void *aux;
224 1.13.2.2 bouyer const char *pnp;
225 1.13.2.2 bouyer {
226 1.13.2.2 bouyer struct confargs *ca = aux;
227 1.13.2.2 bouyer
228 1.13.2.2 bouyer if (pnp)
229 1.13.2.2 bouyer printf("%s at %s", ca->ca_name, pnp);
230 1.13.2.2 bouyer printf(" isa_io_base 0x%lx isa_mem_base 0x%lx",
231 1.13.2.2 bouyer arc_bus_io.bs_vbase, arc_bus_mem.bs_vbase);
232 1.13.2.2 bouyer return (UNCONF);
233 1.13.2.2 bouyer }
234 1.13.2.2 bouyer
235 1.13.2.2 bouyer
236 1.13.2.2 bouyer /*
237 1.13.2.2 bouyer * Interrupt system driver code
238 1.13.2.2 bouyer * ============================
239 1.13.2.2 bouyer */
240 1.13.2.2 bouyer #define LEGAL_IRQ(x) ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
241 1.13.2.2 bouyer
242 1.13.2.2 bouyer int imen;
243 1.13.2.2 bouyer int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
244 1.13.2.2 bouyer struct intrhand *intrhand[ICU_LEN];
245 1.13.2.2 bouyer
246 1.13.2.2 bouyer int fakeintr(a)
247 1.13.2.2 bouyer void *a;
248 1.13.2.2 bouyer {
249 1.13.2.2 bouyer return 0;
250 1.13.2.2 bouyer }
251 1.13.2.2 bouyer
252 1.13.2.2 bouyer /*
253 1.13.2.2 bouyer * Recalculate the interrupt masks from scratch.
254 1.13.2.2 bouyer * We could code special registry and deregistry versions of this function that
255 1.13.2.2 bouyer * would be faster, but the code would be nastier, and we don't expect this to
256 1.13.2.2 bouyer * happen very much anyway.
257 1.13.2.2 bouyer */
258 1.13.2.2 bouyer void
259 1.13.2.2 bouyer intr_calculatemasks()
260 1.13.2.2 bouyer {
261 1.13.2.2 bouyer int irq, level;
262 1.13.2.2 bouyer struct intrhand *q;
263 1.13.2.2 bouyer
264 1.13.2.2 bouyer /* First, figure out which levels each IRQ uses. */
265 1.13.2.2 bouyer for (irq = 0; irq < ICU_LEN; irq++) {
266 1.13.2.2 bouyer register int levels = 0;
267 1.13.2.2 bouyer for (q = intrhand[irq]; q; q = q->ih_next)
268 1.13.2.2 bouyer levels |= 1 << q->ih_level;
269 1.13.2.2 bouyer intrlevel[irq] = levels;
270 1.13.2.2 bouyer }
271 1.13.2.2 bouyer
272 1.13.2.2 bouyer /* Then figure out which IRQs use each level. */
273 1.13.2.2 bouyer for (level = 0; level < 5; level++) {
274 1.13.2.2 bouyer register int irqs = 0;
275 1.13.2.2 bouyer for (irq = 0; irq < ICU_LEN; irq++)
276 1.13.2.2 bouyer if (intrlevel[irq] & (1 << level))
277 1.13.2.2 bouyer irqs |= 1 << irq;
278 1.13.2.2 bouyer imask[level] = irqs | SIR_ALLMASK;
279 1.13.2.2 bouyer }
280 1.13.2.2 bouyer
281 1.13.2.2 bouyer /*
282 1.13.2.2 bouyer * There are tty, network and disk drivers that use free() at interrupt
283 1.13.2.2 bouyer * time, so imp > (tty | net | bio).
284 1.13.2.2 bouyer */
285 1.13.2.2 bouyer imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO];
286 1.13.2.2 bouyer
287 1.13.2.2 bouyer /*
288 1.13.2.2 bouyer * Enforce a hierarchy that gives slow devices a better chance at not
289 1.13.2.2 bouyer * dropping data.
290 1.13.2.2 bouyer */
291 1.13.2.2 bouyer imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO];
292 1.13.2.2 bouyer imask[IPL_NET] |= imask[IPL_BIO];
293 1.13.2.2 bouyer
294 1.13.2.2 bouyer /*
295 1.13.2.2 bouyer * These are pseudo-levels.
296 1.13.2.2 bouyer */
297 1.13.2.2 bouyer imask[IPL_NONE] = 0x00000000;
298 1.13.2.2 bouyer imask[IPL_HIGH] = 0xffffffff;
299 1.13.2.2 bouyer
300 1.13.2.2 bouyer /* And eventually calculate the complete masks. */
301 1.13.2.2 bouyer for (irq = 0; irq < ICU_LEN; irq++) {
302 1.13.2.2 bouyer register int irqs = 1 << irq;
303 1.13.2.2 bouyer for (q = intrhand[irq]; q; q = q->ih_next)
304 1.13.2.2 bouyer irqs |= imask[q->ih_level];
305 1.13.2.2 bouyer intrmask[irq] = irqs | SIR_ALLMASK;
306 1.13.2.2 bouyer }
307 1.13.2.2 bouyer
308 1.13.2.2 bouyer /* Lastly, determine which IRQs are actually in use. */
309 1.13.2.2 bouyer {
310 1.13.2.2 bouyer register int irqs = 0;
311 1.13.2.2 bouyer for (irq = 0; irq < ICU_LEN; irq++)
312 1.13.2.2 bouyer if (intrhand[irq])
313 1.13.2.2 bouyer irqs |= 1 << irq;
314 1.13.2.2 bouyer if (irqs >= 0x100) /* any IRQs >= 8 in use */
315 1.13.2.2 bouyer irqs |= 1 << IRQ_SLAVE;
316 1.13.2.2 bouyer imen = ~irqs;
317 1.13.2.2 bouyer isa_outb(IO_ICU1 + 1, imen);
318 1.13.2.2 bouyer isa_outb(IO_ICU2 + 1, imen >> 8);
319 1.13.2.2 bouyer }
320 1.13.2.2 bouyer }
321 1.13.2.2 bouyer
322 1.13.2.2 bouyer void
323 1.13.2.2 bouyer isabr_attach_hook(parent, self, iba)
324 1.13.2.2 bouyer struct device *parent, *self;
325 1.13.2.2 bouyer struct isabus_attach_args *iba;
326 1.13.2.2 bouyer {
327 1.13.2.2 bouyer
328 1.13.2.2 bouyer /* Nothing to do. */
329 1.13.2.2 bouyer }
330 1.13.2.2 bouyer
331 1.13.2.2 bouyer const struct evcnt *
332 1.13.2.2 bouyer isabr_intr_evcnt(ic, irq)
333 1.13.2.2 bouyer isa_chipset_tag_t ic;
334 1.13.2.2 bouyer int irq;
335 1.13.2.2 bouyer {
336 1.13.2.2 bouyer
337 1.13.2.2 bouyer /* XXX for now, no evcnt parent reported */
338 1.13.2.2 bouyer return NULL;
339 1.13.2.2 bouyer }
340 1.13.2.2 bouyer
341 1.13.2.2 bouyer /*
342 1.13.2.2 bouyer * Establish a ISA bus interrupt.
343 1.13.2.2 bouyer */
344 1.13.2.2 bouyer void *
345 1.13.2.2 bouyer isabr_intr_establish(ic, irq, type, level, ih_fun, ih_arg)
346 1.13.2.2 bouyer isa_chipset_tag_t ic;
347 1.13.2.2 bouyer int irq;
348 1.13.2.2 bouyer int type;
349 1.13.2.2 bouyer int level;
350 1.13.2.2 bouyer int (*ih_fun) __P((void *));
351 1.13.2.2 bouyer void *ih_arg;
352 1.13.2.2 bouyer {
353 1.13.2.2 bouyer struct intrhand **p, *q, *ih;
354 1.13.2.2 bouyer static struct intrhand fakehand = {NULL, fakeintr};
355 1.13.2.2 bouyer extern int cold;
356 1.13.2.2 bouyer
357 1.13.2.2 bouyer /* no point in sleeping unless someone can free memory. */
358 1.13.2.2 bouyer ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
359 1.13.2.2 bouyer if (ih == NULL)
360 1.13.2.2 bouyer panic("isa_intr_establish: can't malloc handler info");
361 1.13.2.2 bouyer
362 1.13.2.2 bouyer if (!LEGAL_IRQ(irq) || type == IST_NONE)
363 1.13.2.2 bouyer panic("intr_establish: bogus irq or type");
364 1.13.2.2 bouyer
365 1.13.2.2 bouyer switch (intrtype[irq]) {
366 1.13.2.2 bouyer case IST_EDGE:
367 1.13.2.2 bouyer case IST_LEVEL:
368 1.13.2.2 bouyer if (type == intrtype[irq])
369 1.13.2.2 bouyer break;
370 1.13.2.2 bouyer case IST_PULSE:
371 1.13.2.2 bouyer if (type != IST_NONE)
372 1.13.2.2 bouyer panic("intr_establish: can't share %s with %s",
373 1.13.2.2 bouyer isa_intr_typename(intrtype[irq]),
374 1.13.2.2 bouyer isa_intr_typename(type));
375 1.13.2.2 bouyer break;
376 1.13.2.2 bouyer }
377 1.13.2.2 bouyer
378 1.13.2.2 bouyer /*
379 1.13.2.2 bouyer * Figure out where to put the handler.
380 1.13.2.2 bouyer * This is O(N^2), but we want to preserve the order, and N is
381 1.13.2.2 bouyer * generally small.
382 1.13.2.2 bouyer */
383 1.13.2.2 bouyer for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
384 1.13.2.2 bouyer ;
385 1.13.2.2 bouyer
386 1.13.2.2 bouyer /*
387 1.13.2.2 bouyer * Actually install a fake handler momentarily, since we might be doing
388 1.13.2.2 bouyer * this with interrupts enabled and don't want the real routine called
389 1.13.2.2 bouyer * until masking is set up.
390 1.13.2.2 bouyer */
391 1.13.2.2 bouyer fakehand.ih_level = level;
392 1.13.2.2 bouyer *p = &fakehand;
393 1.13.2.2 bouyer
394 1.13.2.2 bouyer intr_calculatemasks();
395 1.13.2.2 bouyer
396 1.13.2.2 bouyer /*
397 1.13.2.2 bouyer * Poke the real handler in now.
398 1.13.2.2 bouyer */
399 1.13.2.2 bouyer ih->ih_fun = ih_fun;
400 1.13.2.2 bouyer ih->ih_arg = ih_arg;
401 1.13.2.2 bouyer ih->ih_count = 0;
402 1.13.2.2 bouyer ih->ih_next = NULL;
403 1.13.2.2 bouyer ih->ih_level = level;
404 1.13.2.2 bouyer ih->ih_irq = irq;
405 1.13.2.2 bouyer ih->ih_what = ""; /* XXX - should be eliminated */
406 1.13.2.2 bouyer *p = ih;
407 1.13.2.2 bouyer
408 1.13.2.2 bouyer return (ih);
409 1.13.2.2 bouyer }
410 1.13.2.2 bouyer
411 1.13.2.2 bouyer void
412 1.13.2.2 bouyer isabr_intr_disestablish(ic, arg)
413 1.13.2.2 bouyer isa_chipset_tag_t ic;
414 1.13.2.2 bouyer void *arg;
415 1.13.2.2 bouyer {
416 1.13.2.2 bouyer
417 1.13.2.2 bouyer }
418 1.13.2.2 bouyer
419 1.13.2.2 bouyer /*
420 1.13.2.2 bouyer * Process an interrupt from the ISA bus.
421 1.13.2.2 bouyer */
422 1.13.2.2 bouyer int
423 1.13.2.2 bouyer isabr_iointr(mask, cf)
424 1.13.2.2 bouyer unsigned mask;
425 1.13.2.2 bouyer struct clockframe *cf;
426 1.13.2.2 bouyer {
427 1.13.2.2 bouyer struct intrhand *ih;
428 1.13.2.2 bouyer int isa_vector;
429 1.13.2.2 bouyer int o_imen;
430 1.13.2.2 bouyer char vector;
431 1.13.2.2 bouyer
432 1.13.2.2 bouyer (void) &isa_vector; /* shut off gcc unused-variable warnings */
433 1.13.2.2 bouyer
434 1.13.2.2 bouyer switch(cputype) {
435 1.13.2.2 bouyer case ACER_PICA_61:
436 1.13.2.2 bouyer case MAGNUM:
437 1.13.2.2 bouyer isa_vector = in32(R4030_SYS_ISA_VECTOR) & (ICU_LEN - 1);
438 1.13.2.2 bouyer break;
439 1.13.2.2 bouyer
440 1.13.2.2 bouyer case NEC_R94:
441 1.13.2.2 bouyer case NEC_R96:
442 1.13.2.2 bouyer isa_vector = in32(RD94_SYS_INTSTAT2) & (ICU_LEN - 1);
443 1.13.2.2 bouyer break;
444 1.13.2.2 bouyer
445 1.13.2.2 bouyer case DESKSTATION_TYNE:
446 1.13.2.2 bouyer isa_outb(IO_ICU1, 0x0f); /* Poll */
447 1.13.2.2 bouyer vector = isa_inb(IO_ICU1);
448 1.13.2.2 bouyer if(vector > 0 || (isa_vector = vector & 7) == 2) {
449 1.13.2.2 bouyer isa_outb(IO_ICU2, 0x0f);
450 1.13.2.2 bouyer vector = isa_inb(IO_ICU2);
451 1.13.2.2 bouyer if(vector > 0) {
452 1.13.2.2 bouyer printf("isa: spurious interrupt.\n");
453 1.13.2.2 bouyer return(~0);
454 1.13.2.2 bouyer }
455 1.13.2.2 bouyer isa_vector = (vector & 7) | 8;
456 1.13.2.2 bouyer }
457 1.13.2.2 bouyer break;
458 1.13.2.2 bouyer
459 1.13.2.2 bouyer case DESKSTATION_RPC44:
460 1.13.2.2 bouyer isa_outb(IO_ICU1, 0x0f); /* Poll */
461 1.13.2.2 bouyer vector = isa_inb(IO_ICU1);
462 1.13.2.2 bouyer if(vector > 0 || (isa_vector = vector & 7) == 2) {
463 1.13.2.2 bouyer isa_outb(IO_ICU2, 0x0f);
464 1.13.2.2 bouyer vector = isa_inb(IO_ICU2);
465 1.13.2.2 bouyer if(vector > 0) {
466 1.13.2.2 bouyer printf("isa: spurious interrupt.\n");
467 1.13.2.2 bouyer return(~0);
468 1.13.2.2 bouyer }
469 1.13.2.2 bouyer isa_vector = (vector & 7) | 8;
470 1.13.2.2 bouyer }
471 1.13.2.2 bouyer break;
472 1.13.2.2 bouyer }
473 1.13.2.2 bouyer
474 1.13.2.2 bouyer o_imen = imen;
475 1.13.2.2 bouyer imen |= 1 << (isa_vector & (ICU_LEN - 1));
476 1.13.2.2 bouyer if(isa_vector & 0x08) {
477 1.13.2.2 bouyer isa_inb(IO_ICU2 + 1);
478 1.13.2.2 bouyer isa_outb(IO_ICU2 + 1, imen >> 8);
479 1.13.2.2 bouyer isa_outb(IO_ICU2, 0x60 + (isa_vector & 7));
480 1.13.2.2 bouyer isa_outb(IO_ICU1, 0x60 + IRQ_SLAVE);
481 1.13.2.2 bouyer }
482 1.13.2.2 bouyer else {
483 1.13.2.2 bouyer isa_inb(IO_ICU1 + 1);
484 1.13.2.2 bouyer isa_outb(IO_ICU1 + 1, imen);
485 1.13.2.2 bouyer isa_outb(IO_ICU1, 0x60 + isa_vector);
486 1.13.2.2 bouyer }
487 1.13.2.2 bouyer ih = intrhand[isa_vector];
488 1.13.2.2 bouyer if(isa_vector == 0) { /* Clock */ /*XXX*/
489 1.13.2.2 bouyer (*ih->ih_fun)(cf);
490 1.13.2.2 bouyer ih = ih->ih_next;
491 1.13.2.2 bouyer }
492 1.13.2.2 bouyer while(ih) {
493 1.13.2.2 bouyer (*ih->ih_fun)(ih->ih_arg);
494 1.13.2.2 bouyer ih = ih->ih_next;
495 1.13.2.2 bouyer }
496 1.13.2.2 bouyer imen = o_imen;
497 1.13.2.2 bouyer isa_inb(IO_ICU1 + 1);
498 1.13.2.2 bouyer isa_inb(IO_ICU2 + 1);
499 1.13.2.2 bouyer isa_outb(IO_ICU1 + 1, imen);
500 1.13.2.2 bouyer isa_outb(IO_ICU2 + 1, imen >> 8);
501 1.13.2.2 bouyer
502 1.13.2.2 bouyer return(~0); /* Dont reenable */
503 1.13.2.2 bouyer }
504 1.13.2.2 bouyer
505 1.13.2.2 bouyer
506 1.13.2.2 bouyer /*
507 1.13.2.2 bouyer * Initialize the Interrupt controller logic.
508 1.13.2.2 bouyer */
509 1.13.2.2 bouyer void
510 1.13.2.2 bouyer isabr_initicu()
511 1.13.2.2 bouyer {
512 1.13.2.2 bouyer
513 1.13.2.2 bouyer isa_outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
514 1.13.2.2 bouyer isa_outb(IO_ICU1+1, 0); /* starting at this vector index */
515 1.13.2.2 bouyer isa_outb(IO_ICU1+1, 1 << IRQ_SLAVE); /* slave on line 2 */
516 1.13.2.2 bouyer isa_outb(IO_ICU1+1, 1); /* 8086 mode */
517 1.13.2.2 bouyer isa_outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
518 1.13.2.2 bouyer isa_outb(IO_ICU1, 0x68); /* special mask mode (if available) */
519 1.13.2.2 bouyer isa_outb(IO_ICU1, 0x0a); /* Read IRR by default. */
520 1.13.2.2 bouyer #ifdef REORDER_IRQ
521 1.13.2.2 bouyer isa_outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
522 1.13.2.2 bouyer #endif
523 1.13.2.2 bouyer
524 1.13.2.2 bouyer isa_outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
525 1.13.2.2 bouyer isa_outb(IO_ICU2+1, 8); /* staring at this vector index */
526 1.13.2.2 bouyer isa_outb(IO_ICU2+1, IRQ_SLAVE);
527 1.13.2.2 bouyer isa_outb(IO_ICU2+1, 1); /* 8086 mode */
528 1.13.2.2 bouyer isa_outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
529 1.13.2.2 bouyer isa_outb(IO_ICU2, 0x68); /* special mask mode (if available) */
530 1.13.2.2 bouyer isa_outb(IO_ICU2, 0x0a); /* Read IRR by default. */
531 1.13.2.2 bouyer }
532 1.13.2.2 bouyer
533 1.13.2.2 bouyer
534 1.13.2.2 bouyer /*
535 1.13.2.2 bouyer * SPEAKER BEEPER...
536 1.13.2.2 bouyer */
537 1.13.2.2 bouyer void
538 1.13.2.2 bouyer sysbeepstop(arg)
539 1.13.2.2 bouyer void *arg;
540 1.13.2.2 bouyer {
541 1.13.2.2 bouyer int s;
542 1.13.2.2 bouyer
543 1.13.2.2 bouyer /* disable counter 2 */
544 1.13.2.2 bouyer s = splhigh();
545 1.13.2.2 bouyer isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) & ~PIT_SPKR);
546 1.13.2.2 bouyer splx(s);
547 1.13.2.2 bouyer beeping = 0;
548 1.13.2.2 bouyer }
549 1.13.2.2 bouyer
550 1.13.2.2 bouyer void
551 1.13.2.2 bouyer sysbeep(pitch, period)
552 1.13.2.2 bouyer int pitch, period;
553 1.13.2.2 bouyer {
554 1.13.2.2 bouyer static int last_pitch, last_period;
555 1.13.2.2 bouyer int s;
556 1.13.2.2 bouyer extern int cold;
557 1.13.2.2 bouyer
558 1.13.2.2 bouyer if (cold)
559 1.13.2.2 bouyer return; /* Can't beep yet. */
560 1.13.2.2 bouyer
561 1.13.2.2 bouyer if (beeping)
562 1.13.2.2 bouyer callout_stop(&sysbeep_ch);
563 1.13.2.2 bouyer if (!beeping || last_pitch != pitch) {
564 1.13.2.2 bouyer s = splhigh();
565 1.13.2.2 bouyer isa_outb(IO_TIMER1 + TIMER_MODE,
566 1.13.2.2 bouyer TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
567 1.13.2.2 bouyer isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) % 256);
568 1.13.2.2 bouyer isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) / 256);
569 1.13.2.2 bouyer isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) | PIT_SPKR);
570 1.13.2.2 bouyer splx(s);
571 1.13.2.2 bouyer }
572 1.13.2.2 bouyer last_pitch = pitch;
573 1.13.2.2 bouyer beeping = last_period = period;
574 1.13.2.2 bouyer callout_reset(&sysbeep_ch, period, sysbeepstop, NULL);
575 1.13.2.2 bouyer }
576