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