pcib.c revision 1.23 1 1.23 matt /* $NetBSD: pcib.c,v 1.23 2011/07/08 18:48:59 matt Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*-
4 1.1 thorpej * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
5 1.1 thorpej * All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * This code is derived from software contributed to The NetBSD Foundation
8 1.1 thorpej * by Jason R. Thorpe.
9 1.1 thorpej *
10 1.1 thorpej * Redistribution and use in source and binary forms, with or without
11 1.1 thorpej * modification, are permitted provided that the following conditions
12 1.1 thorpej * are met:
13 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
14 1.1 thorpej * notice, this list of conditions and the following disclaimer.
15 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
17 1.1 thorpej * documentation and/or other materials provided with the distribution.
18 1.1 thorpej *
19 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 thorpej * POSSIBILITY OF SUCH DAMAGE.
30 1.1 thorpej */
31 1.1 thorpej
32 1.1 thorpej #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
33 1.1 thorpej
34 1.23 matt __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.23 2011/07/08 18:48:59 matt Exp $");
35 1.1 thorpej
36 1.1 thorpej #include "opt_algor_p5064.h"
37 1.1 thorpej #include "opt_algor_p6032.h"
38 1.1 thorpej
39 1.1 thorpej #include <sys/param.h>
40 1.1 thorpej #include <sys/systm.h>
41 1.1 thorpej #include <sys/kernel.h>
42 1.1 thorpej #include <sys/device.h>
43 1.1 thorpej #include <sys/malloc.h>
44 1.1 thorpej
45 1.1 thorpej #include <machine/intr.h>
46 1.22 dyoung #include <sys/bus.h>
47 1.1 thorpej
48 1.3 thorpej #include <dev/isa/isareg.h>
49 1.1 thorpej #include <dev/isa/isavar.h>
50 1.1 thorpej
51 1.1 thorpej #include <dev/pci/pcireg.h>
52 1.1 thorpej #include <dev/pci/pcivar.h>
53 1.1 thorpej #include <dev/pci/pcidevs.h>
54 1.1 thorpej
55 1.6 thorpej #include <dev/ic/i8259reg.h>
56 1.6 thorpej
57 1.1 thorpej #ifdef ALGOR_P5064
58 1.1 thorpej #include <algor/algor/algor_p5064var.h>
59 1.1 thorpej #endif
60 1.1 thorpej
61 1.1 thorpej #ifdef ALGOR_P6032
62 1.1 thorpej #include <algor/algor/algor_p6032var.h>
63 1.1 thorpej #endif
64 1.1 thorpej
65 1.23 matt const char * const pcib_intrnames[16] = {
66 1.3 thorpej "irq 0",
67 1.3 thorpej "irq 1",
68 1.3 thorpej "irq 2",
69 1.3 thorpej "irq 3",
70 1.3 thorpej "irq 4",
71 1.3 thorpej "irq 5",
72 1.3 thorpej "irq 6",
73 1.3 thorpej "irq 7",
74 1.3 thorpej "irq 8",
75 1.3 thorpej "irq 9",
76 1.3 thorpej "irq 10",
77 1.3 thorpej "irq 11",
78 1.3 thorpej "irq 12",
79 1.3 thorpej "irq 13",
80 1.3 thorpej "irq 14",
81 1.3 thorpej "irq 15",
82 1.3 thorpej };
83 1.3 thorpej
84 1.3 thorpej struct pcib_intrhead {
85 1.3 thorpej LIST_HEAD(, algor_intrhand) intr_q;
86 1.3 thorpej struct evcnt intr_count;
87 1.3 thorpej int intr_type;
88 1.3 thorpej };
89 1.1 thorpej
90 1.1 thorpej struct pcib_softc {
91 1.1 thorpej struct device sc_dev;
92 1.3 thorpej
93 1.3 thorpej bus_space_tag_t sc_iot;
94 1.3 thorpej bus_space_handle_t sc_ioh_icu1;
95 1.3 thorpej bus_space_handle_t sc_ioh_icu2;
96 1.3 thorpej bus_space_handle_t sc_ioh_elcr;
97 1.3 thorpej
98 1.23 matt struct mips_isa_chipset sc_ic;
99 1.3 thorpej
100 1.3 thorpej struct pcib_intrhead sc_intrtab[16];
101 1.3 thorpej
102 1.6 thorpej u_int16_t sc_imask;
103 1.3 thorpej u_int16_t sc_elcr;
104 1.3 thorpej
105 1.3 thorpej #if defined(ALGOR_P5064)
106 1.3 thorpej isa_chipset_tag_t sc_parent_ic;
107 1.6 thorpej #endif
108 1.6 thorpej
109 1.3 thorpej u_int16_t sc_reserved;
110 1.3 thorpej
111 1.3 thorpej void *sc_ih;
112 1.1 thorpej };
113 1.1 thorpej
114 1.1 thorpej int pcib_match(struct device *, struct cfdata *, void *);
115 1.1 thorpej void pcib_attach(struct device *, struct device *, void *);
116 1.1 thorpej
117 1.11 thorpej CFATTACH_DECL(pcib, sizeof(struct pcib_softc),
118 1.12 thorpej pcib_match, pcib_attach, NULL, NULL);
119 1.1 thorpej
120 1.1 thorpej void pcib_isa_attach_hook(struct device *, struct device *,
121 1.1 thorpej struct isabus_attach_args *);
122 1.21 dyoung void pcib_isa_detach_hook(isa_chipset_tag_t, device_t);
123 1.1 thorpej
124 1.3 thorpej int pcib_intr(void *);
125 1.3 thorpej
126 1.1 thorpej void pcib_bridge_callback(struct device *);
127 1.1 thorpej
128 1.3 thorpej const struct evcnt *pcib_isa_intr_evcnt(void *, int);
129 1.3 thorpej void *pcib_isa_intr_establish(void *, int, int, int,
130 1.3 thorpej int (*)(void *), void *);
131 1.3 thorpej void pcib_isa_intr_disestablish(void *, void *);
132 1.3 thorpej int pcib_isa_intr_alloc(void *, int, int, int *);
133 1.3 thorpej
134 1.3 thorpej void pcib_set_icus(struct pcib_softc *);
135 1.3 thorpej
136 1.1 thorpej int
137 1.1 thorpej pcib_match(struct device *parent, struct cfdata *match, void *aux)
138 1.1 thorpej {
139 1.1 thorpej struct pci_attach_args *pa = aux;
140 1.1 thorpej
141 1.1 thorpej if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
142 1.1 thorpej PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA)
143 1.1 thorpej return (1);
144 1.1 thorpej
145 1.1 thorpej return (0);
146 1.1 thorpej }
147 1.1 thorpej
148 1.1 thorpej void
149 1.1 thorpej pcib_attach(struct device *parent, struct device *self, void *aux)
150 1.1 thorpej {
151 1.3 thorpej struct pcib_softc *sc = (void *) self;
152 1.1 thorpej struct pci_attach_args *pa = aux;
153 1.1 thorpej char devinfo[256];
154 1.3 thorpej int i;
155 1.1 thorpej
156 1.15 itojun pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
157 1.1 thorpej printf(": %s (rev. 0x%02x)\n", devinfo,
158 1.1 thorpej PCI_REVISION(pa->pa_class));
159 1.1 thorpej
160 1.3 thorpej sc->sc_iot = pa->pa_iot;
161 1.3 thorpej
162 1.3 thorpej /*
163 1.3 thorpej * Map the PIC/ELCR registers.
164 1.3 thorpej */
165 1.3 thorpej if (bus_space_map(sc->sc_iot, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0)
166 1.3 thorpej printf("%s: unable to map ELCR registers\n",
167 1.3 thorpej sc->sc_dev.dv_xname);
168 1.3 thorpej if (bus_space_map(sc->sc_iot, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0)
169 1.3 thorpej printf("%s: unable to map ICU1 registers\n",
170 1.3 thorpej sc->sc_dev.dv_xname);
171 1.3 thorpej if (bus_space_map(sc->sc_iot, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0)
172 1.3 thorpej printf("%s: unable to map ICU2 registers\n",
173 1.3 thorpej sc->sc_dev.dv_xname);
174 1.3 thorpej
175 1.6 thorpej /* All interrupts default to "masked off". */
176 1.6 thorpej sc->sc_imask = 0xffff;
177 1.6 thorpej
178 1.6 thorpej /* All interrupts default to edge-triggered. */
179 1.6 thorpej sc->sc_elcr = 0;
180 1.6 thorpej
181 1.3 thorpej /*
182 1.3 thorpej * Initialize the 8259s.
183 1.3 thorpej */
184 1.3 thorpej
185 1.6 thorpej /* reset, program device, 4 bytes */
186 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW1,
187 1.7 thorpej ICW1_SELECT | ICW1_IC4);
188 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW2,
189 1.9 thorpej ICW2_VECTOR(0)/*XXX*/);
190 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW3,
191 1.7 thorpej ICW3_CASCADE(2));
192 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW4,
193 1.6 thorpej ICW4_8086);
194 1.6 thorpej
195 1.6 thorpej /* mask all interrupts */
196 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
197 1.6 thorpej sc->sc_imask & 0xff);
198 1.6 thorpej
199 1.6 thorpej /* enable special mask mode */
200 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
201 1.7 thorpej OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
202 1.6 thorpej
203 1.6 thorpej /* read IRR by default */
204 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
205 1.7 thorpej OCW3_SELECT | OCW3_RR);
206 1.6 thorpej
207 1.6 thorpej /* reset; program device, 4 bytes */
208 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW1,
209 1.7 thorpej ICW1_SELECT | ICW1_IC4);
210 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW2,
211 1.9 thorpej ICW2_VECTOR(0)/*XXX*/);
212 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW3,
213 1.6 thorpej ICW3_SIC(2));
214 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW4,
215 1.6 thorpej ICW4_8086);
216 1.6 thorpej
217 1.6 thorpej /* mask all interrupts */
218 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
219 1.6 thorpej (sc->sc_imask >> 8) & 0xff);
220 1.6 thorpej
221 1.6 thorpej /* enable special mask mode */
222 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
223 1.7 thorpej OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
224 1.6 thorpej
225 1.6 thorpej /* read IRR by default */
226 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
227 1.7 thorpej OCW3_SELECT | OCW3_RR);
228 1.3 thorpej
229 1.3 thorpej /*
230 1.3 thorpej * Default all interrupts to edge-triggered.
231 1.3 thorpej */
232 1.3 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
233 1.3 thorpej sc->sc_elcr & 0xff);
234 1.3 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
235 1.3 thorpej (sc->sc_elcr >> 8) & 0xff);
236 1.3 thorpej
237 1.6 thorpej /*
238 1.6 thorpej * Some ISA interrupts are reserved for devices that
239 1.6 thorpej * we know are hard-wired to certain IRQs.
240 1.6 thorpej */
241 1.6 thorpej sc->sc_reserved =
242 1.6 thorpej (1U << 0) | /* timer */
243 1.6 thorpej (1U << 1) | /* keyboard controller */
244 1.7 thorpej (1U << 2) | /* PIC cascade */
245 1.6 thorpej (1U << 3) | /* COM 2 */
246 1.6 thorpej (1U << 4) | /* COM 1 */
247 1.6 thorpej (1U << 6) | /* floppy */
248 1.6 thorpej (1U << 7) | /* centronics */
249 1.6 thorpej (1U << 8) | /* RTC */
250 1.6 thorpej (1U << 12) | /* keyboard controller */
251 1.6 thorpej (1U << 14) | /* IDE 0 */
252 1.6 thorpej (1U << 15); /* IDE 1 */
253 1.6 thorpej
254 1.3 thorpej #if defined(ALGOR_P5064)
255 1.3 thorpej /*
256 1.3 thorpej * Some "ISA" interrupts are a little wacky, wired up directly
257 1.3 thorpej * to the P-5064 interrupt controller.
258 1.3 thorpej */
259 1.3 thorpej sc->sc_parent_ic = &p5064_configuration.ac_ic;
260 1.3 thorpej #endif /* ALGOR_P5064 */
261 1.3 thorpej
262 1.3 thorpej /* Set up our ISA chipset. */
263 1.3 thorpej sc->sc_ic.ic_v = sc;
264 1.3 thorpej sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt;
265 1.3 thorpej sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish;
266 1.3 thorpej sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish;
267 1.3 thorpej sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc;
268 1.3 thorpej
269 1.3 thorpej /* Initialize our interrupt table. */
270 1.3 thorpej for (i = 0; i < 16; i++) {
271 1.3 thorpej LIST_INIT(&sc->sc_intrtab[i].intr_q);
272 1.3 thorpej evcnt_attach_dynamic(&sc->sc_intrtab[i].intr_count,
273 1.3 thorpej EVCNT_TYPE_INTR, NULL, "pcib", pcib_intrnames[i]);
274 1.3 thorpej sc->sc_intrtab[i].intr_type = IST_NONE;
275 1.3 thorpej }
276 1.3 thorpej
277 1.3 thorpej /* Hook up our interrupt handler. */
278 1.3 thorpej #if defined(ALGOR_P5064)
279 1.5 thorpej sc->sc_ih = (*algor_intr_establish)(P5064_IRQ_ISABRIDGE,
280 1.5 thorpej pcib_intr, sc);
281 1.3 thorpej #elif defined(ALGOR_P6032)
282 1.8 thorpej sc->sc_ih = (*algor_intr_establish)(P6032_IRQ_ISABRIDGE,
283 1.3 thorpej pcib_intr, sc);
284 1.3 thorpej #endif
285 1.3 thorpej if (sc->sc_ih == NULL)
286 1.3 thorpej printf("%s: WARNING: unable to register interrupt handler\n",
287 1.3 thorpej sc->sc_dev.dv_xname);
288 1.3 thorpej
289 1.1 thorpej config_defer(self, pcib_bridge_callback);
290 1.1 thorpej }
291 1.1 thorpej
292 1.1 thorpej void
293 1.20 dsl pcib_bridge_callback(struct device *self)
294 1.1 thorpej {
295 1.1 thorpej struct pcib_softc *sc = (struct pcib_softc *)self;
296 1.1 thorpej struct isabus_attach_args iba;
297 1.1 thorpej
298 1.1 thorpej memset(&iba, 0, sizeof(iba));
299 1.1 thorpej
300 1.2 thorpej #if defined(ALGOR_P5064)
301 1.1 thorpej {
302 1.1 thorpej struct p5064_config *acp = &p5064_configuration;
303 1.1 thorpej
304 1.1 thorpej iba.iba_iot = &acp->ac_iot;
305 1.1 thorpej iba.iba_memt = &acp->ac_memt;
306 1.1 thorpej iba.iba_dmat = &acp->ac_isa_dmat;
307 1.1 thorpej }
308 1.1 thorpej #elif defined(ALGOR_P6032)
309 1.1 thorpej {
310 1.9 thorpej struct p6032_config *acp = &p6032_configuration;
311 1.9 thorpej
312 1.9 thorpej iba.iba_iot = &acp->ac_iot;
313 1.9 thorpej iba.iba_memt = &acp->ac_memt;
314 1.9 thorpej iba.iba_dmat = &acp->ac_isa_dmat;
315 1.1 thorpej }
316 1.1 thorpej #endif
317 1.1 thorpej
318 1.6 thorpej iba.iba_ic = &sc->sc_ic;
319 1.1 thorpej iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook;
320 1.21 dyoung iba.iba_ic->ic_detach_hook = pcib_isa_detach_hook;
321 1.1 thorpej
322 1.16 drochner (void) config_found_ia(&sc->sc_dev, "isabus", &iba, isabusprint);
323 1.1 thorpej }
324 1.1 thorpej
325 1.1 thorpej void
326 1.1 thorpej pcib_isa_attach_hook(struct device *parent, struct device *self,
327 1.1 thorpej struct isabus_attach_args *iba)
328 1.1 thorpej {
329 1.1 thorpej
330 1.1 thorpej /* Nothing to do. */
331 1.3 thorpej }
332 1.3 thorpej
333 1.3 thorpej void
334 1.21 dyoung pcib_isa_detach_hook(isa_chipset_tag_t ic, device_t self)
335 1.21 dyoung {
336 1.21 dyoung
337 1.21 dyoung /* Nothing to do. */
338 1.21 dyoung }
339 1.21 dyoung
340 1.21 dyoung void
341 1.3 thorpej pcib_set_icus(struct pcib_softc *sc)
342 1.3 thorpej {
343 1.3 thorpej
344 1.3 thorpej /* Enable the cascade IRQ (2) if 8-15 is enabled. */
345 1.6 thorpej if ((sc->sc_imask & 0xff00) != 0xff00)
346 1.6 thorpej sc->sc_imask &= ~(1U << 2);
347 1.3 thorpej else
348 1.6 thorpej sc->sc_imask |= (1U << 2);
349 1.3 thorpej
350 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
351 1.6 thorpej sc->sc_imask & 0xff);
352 1.6 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
353 1.6 thorpej (sc->sc_imask >> 8) & 0xff);
354 1.3 thorpej
355 1.3 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
356 1.3 thorpej sc->sc_elcr & 0xff);
357 1.3 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
358 1.3 thorpej (sc->sc_elcr >> 8) & 0xff);
359 1.3 thorpej }
360 1.3 thorpej
361 1.3 thorpej int
362 1.3 thorpej pcib_intr(void *v)
363 1.3 thorpej {
364 1.3 thorpej struct pcib_softc *sc = v;
365 1.3 thorpej struct algor_intrhand *ih;
366 1.6 thorpej int irq;
367 1.3 thorpej
368 1.7 thorpej for (;;) {
369 1.7 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
370 1.6 thorpej OCW3_SELECT | OCW3_POLL);
371 1.7 thorpej irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3);
372 1.7 thorpej if ((irq & OCW3_POLL_PENDING) == 0)
373 1.7 thorpej return (1);
374 1.7 thorpej
375 1.7 thorpej irq = OCW3_POLL_IRQ(irq);
376 1.7 thorpej
377 1.7 thorpej if (irq == 2) {
378 1.7 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
379 1.7 thorpej PIC_OCW3, OCW3_SELECT | OCW3_POLL);
380 1.7 thorpej irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2,
381 1.7 thorpej PIC_OCW3);
382 1.7 thorpej if (irq & OCW3_POLL_PENDING)
383 1.7 thorpej irq = OCW3_POLL_IRQ(irq) + 8;
384 1.7 thorpej else
385 1.7 thorpej irq = 2;
386 1.7 thorpej }
387 1.7 thorpej
388 1.7 thorpej sc->sc_intrtab[irq].intr_count.ev_count++;
389 1.7 thorpej for (ih = LIST_FIRST(&sc->sc_intrtab[irq].intr_q);
390 1.7 thorpej ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
391 1.7 thorpej (*ih->ih_func)(ih->ih_arg);
392 1.7 thorpej }
393 1.7 thorpej
394 1.7 thorpej /* Send a specific EOI to the 8259. */
395 1.7 thorpej if (irq > 7) {
396 1.7 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
397 1.18 tsutsui PIC_OCW2, OCW2_SELECT | OCW2_EOI | OCW2_SL |
398 1.7 thorpej OCW2_ILS(irq & 7));
399 1.7 thorpej irq = 2;
400 1.7 thorpej }
401 1.3 thorpej
402 1.7 thorpej bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW2,
403 1.18 tsutsui OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq));
404 1.3 thorpej }
405 1.3 thorpej }
406 1.3 thorpej
407 1.3 thorpej const struct evcnt *
408 1.3 thorpej pcib_isa_intr_evcnt(void *v, int irq)
409 1.3 thorpej {
410 1.3 thorpej struct pcib_softc *sc = v;
411 1.4 thorpej
412 1.4 thorpej #if defined(ALGOR_P5064)
413 1.6 thorpej if (p5064_isa_to_irqmap[irq] != -1)
414 1.4 thorpej return (isa_intr_evcnt(sc->sc_parent_ic, irq));
415 1.4 thorpej #endif
416 1.3 thorpej
417 1.3 thorpej return (&sc->sc_intrtab[irq].intr_count);
418 1.3 thorpej }
419 1.3 thorpej
420 1.3 thorpej void *
421 1.3 thorpej pcib_isa_intr_establish(void *v, int irq, int type, int level,
422 1.3 thorpej int (*func)(void *), void *arg)
423 1.3 thorpej {
424 1.3 thorpej struct pcib_softc *sc = v;
425 1.3 thorpej struct algor_intrhand *ih;
426 1.3 thorpej int s;
427 1.3 thorpej
428 1.3 thorpej if (irq > 15 || irq == 2 || type == IST_NONE)
429 1.3 thorpej panic("pcib_isa_intr_establish: bad irq or type");
430 1.3 thorpej
431 1.3 thorpej #if defined(ALGOR_P5064)
432 1.6 thorpej if (p5064_isa_to_irqmap[irq] != -1)
433 1.6 thorpej return (isa_intr_establish(sc->sc_parent_ic, irq, type,
434 1.6 thorpej level, func, arg));
435 1.3 thorpej #endif
436 1.3 thorpej
437 1.3 thorpej switch (sc->sc_intrtab[irq].intr_type) {
438 1.3 thorpej case IST_NONE:
439 1.3 thorpej sc->sc_intrtab[irq].intr_type = type;
440 1.3 thorpej break;
441 1.3 thorpej
442 1.3 thorpej case IST_EDGE:
443 1.3 thorpej case IST_LEVEL:
444 1.3 thorpej if (type == sc->sc_intrtab[irq].intr_type)
445 1.3 thorpej break;
446 1.3 thorpej /* FALLTHROUGH */
447 1.3 thorpej case IST_PULSE:
448 1.3 thorpej /*
449 1.3 thorpej * We can't share interrupts in this case.
450 1.3 thorpej */
451 1.3 thorpej return (NULL);
452 1.3 thorpej }
453 1.3 thorpej
454 1.3 thorpej ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
455 1.3 thorpej if (ih == NULL)
456 1.3 thorpej return (NULL);
457 1.3 thorpej
458 1.3 thorpej ih->ih_func = func;
459 1.3 thorpej ih->ih_arg = arg;
460 1.3 thorpej ih->ih_irq = irq;
461 1.3 thorpej ih->ih_irqmap = NULL;
462 1.3 thorpej
463 1.3 thorpej s = splhigh();
464 1.3 thorpej
465 1.3 thorpej /* Insert the handler into the table. */
466 1.3 thorpej LIST_INSERT_HEAD(&sc->sc_intrtab[irq].intr_q, ih, ih_q);
467 1.3 thorpej sc->sc_intrtab[irq].intr_type = type;
468 1.3 thorpej
469 1.3 thorpej /* Enable it, set trigger mode. */
470 1.6 thorpej sc->sc_imask &= ~(1 << irq);
471 1.3 thorpej if (sc->sc_intrtab[irq].intr_type == IST_LEVEL)
472 1.3 thorpej sc->sc_elcr |= (1 << irq);
473 1.3 thorpej else
474 1.3 thorpej sc->sc_elcr &= ~(1 << irq);
475 1.3 thorpej
476 1.3 thorpej pcib_set_icus(sc);
477 1.3 thorpej
478 1.3 thorpej splx(s);
479 1.3 thorpej
480 1.3 thorpej return (ih);
481 1.3 thorpej }
482 1.3 thorpej
483 1.3 thorpej void
484 1.3 thorpej pcib_isa_intr_disestablish(void *v, void *arg)
485 1.3 thorpej {
486 1.3 thorpej struct pcib_softc *sc = v;
487 1.3 thorpej struct algor_intrhand *ih = arg;
488 1.3 thorpej int s;
489 1.3 thorpej
490 1.3 thorpej #if defined(ALGOR_P5064)
491 1.6 thorpej if (p5064_isa_to_irqmap[ih->ih_irq] != -1) {
492 1.3 thorpej isa_intr_disestablish(sc->sc_parent_ic, ih);
493 1.3 thorpej return;
494 1.3 thorpej }
495 1.3 thorpej #endif
496 1.3 thorpej
497 1.3 thorpej s = splhigh();
498 1.3 thorpej
499 1.3 thorpej LIST_REMOVE(ih, ih_q);
500 1.3 thorpej
501 1.3 thorpej /* If there are no more handlers on this IRQ, disable it. */
502 1.3 thorpej if (LIST_FIRST(&sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) {
503 1.6 thorpej sc->sc_imask |= (1 << ih->ih_irq);
504 1.3 thorpej pcib_set_icus(sc);
505 1.3 thorpej }
506 1.3 thorpej
507 1.3 thorpej splx(s);
508 1.3 thorpej
509 1.3 thorpej free(ih, M_DEVBUF);
510 1.3 thorpej }
511 1.3 thorpej
512 1.3 thorpej int
513 1.3 thorpej pcib_isa_intr_alloc(void *v, int mask, int type, int *irq)
514 1.3 thorpej {
515 1.3 thorpej struct pcib_softc *sc = v;
516 1.3 thorpej int i, tmp, bestirq, count;
517 1.3 thorpej struct algor_intrhand *ih;
518 1.3 thorpej
519 1.3 thorpej if (type == IST_NONE)
520 1.3 thorpej panic("pcib_intr_alloc: bogus type");
521 1.3 thorpej
522 1.3 thorpej bestirq = -1;
523 1.3 thorpej count = -1;
524 1.3 thorpej
525 1.3 thorpej mask &= ~sc->sc_reserved;
526 1.6 thorpej
527 1.6 thorpej #if 0
528 1.6 thorpej printf("pcib_intr_alloc: mask = 0x%04x\n", mask);
529 1.3 thorpej #endif
530 1.3 thorpej
531 1.3 thorpej for (i = 0; i < 16; i++) {
532 1.7 thorpej if ((mask & (1 << i)) == 0)
533 1.3 thorpej continue;
534 1.3 thorpej
535 1.3 thorpej switch (sc->sc_intrtab[i].intr_type) {
536 1.3 thorpej case IST_NONE:
537 1.3 thorpej /*
538 1.3 thorpej * If nothing's using the IRQ, just return it.
539 1.3 thorpej */
540 1.3 thorpej *irq = i;
541 1.3 thorpej return (0);
542 1.3 thorpej
543 1.3 thorpej case IST_EDGE:
544 1.3 thorpej case IST_LEVEL:
545 1.3 thorpej if (type != sc->sc_intrtab[i].intr_type)
546 1.3 thorpej continue;
547 1.3 thorpej /*
548 1.3 thorpej * If the IRQ is sharable, count the number of
549 1.3 thorpej * other handlers, and if it's smaller than the
550 1.3 thorpej * last IRQ like this, remember it.
551 1.3 thorpej */
552 1.3 thorpej tmp = 0;
553 1.3 thorpej for (ih = LIST_FIRST(&sc->sc_intrtab[i].intr_q);
554 1.3 thorpej ih != NULL; ih = LIST_NEXT(ih, ih_q))
555 1.3 thorpej tmp++;
556 1.3 thorpej if (bestirq == -1 || count > tmp) {
557 1.3 thorpej bestirq = i;
558 1.3 thorpej count = tmp;
559 1.3 thorpej }
560 1.3 thorpej break;
561 1.3 thorpej
562 1.3 thorpej case IST_PULSE:
563 1.3 thorpej /* This just isn't sharable. */
564 1.3 thorpej continue;
565 1.3 thorpej }
566 1.3 thorpej }
567 1.3 thorpej
568 1.3 thorpej if (bestirq == -1)
569 1.3 thorpej return (1);
570 1.3 thorpej
571 1.3 thorpej *irq = bestirq;
572 1.3 thorpej return (0);
573 1.1 thorpej }
574