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