1 /* $NetBSD: piix.c,v 1.13 2006/11/16 01:32:39 christos Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1999, by UCHIYAMA Yasushi
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. The name of the developer may NOT be used to endorse or promote products
43 * derived from this software without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * Support for the Intel PIIX PCI-ISA bridge interrupt controller
60 * and ICHn I/O controller hub
64 * ICH2 and later support 8 interrupt routers while the first
65 * generation (ICH and ICH0) support 4 which is same as PIIX.
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: piix.c,v 1.13 2006/11/16 01:32:39 christos Exp $");
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/device.h>
74 #include <sys/malloc.h>
76 #include <machine/intr.h>
77 #include <machine/bus.h>
79 #include <dev/pci/pcivar.h>
80 #include <dev/pci/pcireg.h>
81 #include <dev/pci/pcidevs.h>
83 #include <i386/pci/pci_intr_fixup.h>
84 #include <i386/pci/piixreg.h>
85 #include <i386/pci/piixvar.h>
88 #define DPRINTF(arg) printf arg
93 int piix_getclink(pciintr_icu_handle_t
, int, int *);
94 int ich_getclink(pciintr_icu_handle_t
, int, int *);
95 int piix_get_intr(pciintr_icu_handle_t
, int, int *);
96 int piix_set_intr(pciintr_icu_handle_t
, int, int);
98 void piix_pir_dump(struct piix_handle
*);
99 void ich_pir_dump(struct piix_handle
*);
102 const struct pciintr_icu piix_pci_icu
= {
110 const struct pciintr_icu ich_pci_icu
= {
118 static int piix_max_link
= 3;
121 piix_init(pci_chipset_tag_t pc
, bus_space_tag_t iot
, pcitag_t tag
,
122 pciintr_icu_tag_t
*ptagp
, pciintr_icu_handle_t
*phandp
)
124 struct piix_handle
*ph
;
126 ph
= malloc(sizeof(*ph
), M_DEVBUF
, M_NOWAIT
);
134 if (bus_space_map(iot
, PIIX_REG_ELCR
, PIIX_REG_ELCR_SIZE
, 0,
135 &ph
->ph_elcr_ioh
) != 0) {
143 *ptagp
= &piix_pci_icu
;
149 piix_uninit(pciintr_icu_handle_t v
)
151 struct piix_handle
*ph
= v
;
156 bus_space_unmap(ph
->ph_iot
, ph
->ph_elcr_ioh
, PIIX_REG_ELCR_SIZE
);
162 ich_init(pci_chipset_tag_t pc
, bus_space_tag_t iot
, pcitag_t tag
,
163 pciintr_icu_tag_t
*ptagp
, pciintr_icu_handle_t
*phandp
)
167 rv
= piix_init(pc
, iot
, tag
, ptagp
, phandp
);
171 *ptagp
= &ich_pci_icu
;
174 ich_pir_dump(*phandp
);
182 piix_getclink(pciintr_icu_handle_t v
, int link
, int *clinkp
)
184 DPRINTF(("PIIX link value 0x%x: ", link
));
186 /* Pattern 1: simple. */
187 if (PIIX_LEGAL_LINK(link
- 1)) {
189 DPRINTF(("PIRQ %d (simple)\n", *clinkp
));
193 /* Pattern 2: configuration register offset */
194 if (link
>= 0x60 && link
<= 0x63) {
195 *clinkp
= link
- 0x60;
196 DPRINTF(("PIRQ %d (register offset)\n", *clinkp
));
201 * XXX Pattern 3: configuration register offset 1
202 * Some BIOS return 0x68, 0x69
204 if (link
>= 0x68 && link
<= 0x69) {
205 *clinkp
= link
- 0x67;
206 DPRINTF(("PIRQ %d (register offset 1)\n", *clinkp
));
210 DPRINTF(("bogus IRQ selection source\n"));
215 ich_getclink(pciintr_icu_handle_t v
, int link
, int *clinkp
)
218 * configuration registers 0x68..0x6b are for PIRQ[EFGH]
220 if (link
>= 0x68 && link
<= 0x6b) {
221 *clinkp
= link
- 0x68 + 4;
222 DPRINTF(("PIIX link value 0x%x: ", link
));
223 DPRINTF(("PIRQ %d (register offset)\n", *clinkp
));
227 return piix_getclink(v
, link
, clinkp
);
231 piix_get_intr(pciintr_icu_handle_t v
, int clink
, int *irqp
)
233 struct piix_handle
*ph
= v
;
238 if (PIIX_LEGAL_LINK(clink
) == 0)
241 cfgreg
= clink
<= 3 ? PIIX_CFG_PIRQ
: PIIX_CFG_PIRQ2
;
244 reg
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, cfgreg
);
246 if ((reg
>> shift
) & PIIX_CFG_PIRQ_NONE
)
247 *irqp
= X86_PCI_INTERRUPT_LINE_NO_CONNECTION
;
249 *irqp
= PIIX_PIRQ(reg
, clink
);
255 piix_set_intr(pciintr_icu_handle_t v
, int clink
, int irq
)
257 struct piix_handle
*ph
= v
;
262 if (PIIX_LEGAL_LINK(clink
) == 0 || PIIX_LEGAL_IRQ(irq
) == 0)
265 cfgreg
= clink
<= 3 ? PIIX_CFG_PIRQ
: PIIX_CFG_PIRQ2
;
268 reg
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, cfgreg
);
270 reg
&= ~((PIIX_CFG_PIRQ_NONE
| PIIX_CFG_PIRQ_MASK
) << shift
);
272 pci_conf_write(ph
->ph_pc
, ph
->ph_tag
, cfgreg
, reg
);
278 piix_get_trigger(pciintr_icu_handle_t v
, int irq
, int *triggerp
)
280 struct piix_handle
*ph
= v
;
284 if (PIIX_LEGAL_IRQ(irq
) == 0)
287 off
= (irq
> 7) ? 1 : 0;
290 elcr
= bus_space_read_1(ph
->ph_iot
, ph
->ph_elcr_ioh
, off
);
291 if (elcr
& (1 << bit
))
292 *triggerp
= IST_LEVEL
;
294 *triggerp
= IST_EDGE
;
300 piix_set_trigger(pciintr_icu_handle_t v
, int irq
, int trigger
)
302 struct piix_handle
*ph
= v
;
306 if (PIIX_LEGAL_IRQ(irq
) == 0)
309 off
= (irq
> 7) ? 1 : 0;
312 elcr
= bus_space_read_1(ph
->ph_iot
, ph
->ph_elcr_ioh
, off
);
313 if (trigger
== IST_LEVEL
)
317 bus_space_write_1(ph
->ph_iot
, ph
->ph_elcr_ioh
, off
, elcr
);
324 piix_pir_dump(struct piix_handle
*ph
)
327 pcireg_t irqs
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, PIIX_CFG_PIRQ
);
330 elcr
[0] = bus_space_read_1(ph
->ph_iot
, ph
->ph_elcr_ioh
, 0);
331 elcr
[1] = bus_space_read_1(ph
->ph_iot
, ph
->ph_elcr_ioh
, 1);
333 for (i
= 0; i
< 4; i
++) {
334 irq
= PIIX_PIRQ(irqs
, i
);
335 if (irq
& PIIX_CFG_PIRQ_NONE
)
336 printf("PIIX PIRQ %d: irq none (0x%x)\n", i
, irq
);
338 printf("PIIX PIRQ %d: irq %d\n", i
, irq
);
341 for (i
= 0; i
< 16; i
++)
345 for (i
= 0; i
< 16; i
++)
346 printf(" %c", (elcr
[(i
& 8) ? 1 : 0] & (1 << (i
& 7))) ?
352 ich_pir_dump(struct piix_handle
*ph
)
355 pcireg_t irqs
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, PIIX_CFG_PIRQ2
);
357 for (i
= 0; i
< 4; i
++) {
358 irq
= PIIX_PIRQ(irqs
, i
);
359 if (irq
& PIIX_CFG_PIRQ_NONE
)
360 printf("PIIX PIRQ %d: irq none (0x%x)\n", i
+4, irq
);
362 printf("PIIX PIRQ %d: irq %d\n", i
+4, irq
);
365 #endif /* PIIX_DEBUG */