pci_intr_machdep.c revision 1.4.6.2 1 1.4.6.2 rpaulo /* $NetBSD: pci_intr_machdep.c,v 1.4.6.2 2006/09/09 02:44:49 rpaulo Exp $ */
2 1.4.6.2 rpaulo
3 1.4.6.2 rpaulo /*-
4 1.4.6.2 rpaulo * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 1.4.6.2 rpaulo * All rights reserved.
6 1.4.6.2 rpaulo *
7 1.4.6.2 rpaulo * This code is derived from software contributed to The NetBSD Foundation
8 1.4.6.2 rpaulo * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 1.4.6.2 rpaulo * NASA Ames Research Center.
10 1.4.6.2 rpaulo *
11 1.4.6.2 rpaulo * Redistribution and use in source and binary forms, with or without
12 1.4.6.2 rpaulo * modification, are permitted provided that the following conditions
13 1.4.6.2 rpaulo * are met:
14 1.4.6.2 rpaulo * 1. Redistributions of source code must retain the above copyright
15 1.4.6.2 rpaulo * notice, this list of conditions and the following disclaimer.
16 1.4.6.2 rpaulo * 2. Redistributions in binary form must reproduce the above copyright
17 1.4.6.2 rpaulo * notice, this list of conditions and the following disclaimer in the
18 1.4.6.2 rpaulo * documentation and/or other materials provided with the distribution.
19 1.4.6.2 rpaulo * 3. All advertising materials mentioning features or use of this software
20 1.4.6.2 rpaulo * must display the following acknowledgement:
21 1.4.6.2 rpaulo * This product includes software developed by the NetBSD
22 1.4.6.2 rpaulo * Foundation, Inc. and its contributors.
23 1.4.6.2 rpaulo * 4. Neither the name of The NetBSD Foundation nor the names of its
24 1.4.6.2 rpaulo * contributors may be used to endorse or promote products derived
25 1.4.6.2 rpaulo * from this software without specific prior written permission.
26 1.4.6.2 rpaulo *
27 1.4.6.2 rpaulo * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 1.4.6.2 rpaulo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 1.4.6.2 rpaulo * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 1.4.6.2 rpaulo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 1.4.6.2 rpaulo * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.4.6.2 rpaulo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.4.6.2 rpaulo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.4.6.2 rpaulo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.4.6.2 rpaulo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.4.6.2 rpaulo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.4.6.2 rpaulo * POSSIBILITY OF SUCH DAMAGE.
38 1.4.6.2 rpaulo */
39 1.4.6.2 rpaulo
40 1.4.6.2 rpaulo /*
41 1.4.6.2 rpaulo * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
42 1.4.6.2 rpaulo * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
43 1.4.6.2 rpaulo *
44 1.4.6.2 rpaulo * Redistribution and use in source and binary forms, with or without
45 1.4.6.2 rpaulo * modification, are permitted provided that the following conditions
46 1.4.6.2 rpaulo * are met:
47 1.4.6.2 rpaulo * 1. Redistributions of source code must retain the above copyright
48 1.4.6.2 rpaulo * notice, this list of conditions and the following disclaimer.
49 1.4.6.2 rpaulo * 2. Redistributions in binary form must reproduce the above copyright
50 1.4.6.2 rpaulo * notice, this list of conditions and the following disclaimer in the
51 1.4.6.2 rpaulo * documentation and/or other materials provided with the distribution.
52 1.4.6.2 rpaulo * 3. All advertising materials mentioning features or use of this software
53 1.4.6.2 rpaulo * must display the following acknowledgement:
54 1.4.6.2 rpaulo * This product includes software developed by Charles M. Hannum.
55 1.4.6.2 rpaulo * 4. The name of the author may not be used to endorse or promote products
56 1.4.6.2 rpaulo * derived from this software without specific prior written permission.
57 1.4.6.2 rpaulo *
58 1.4.6.2 rpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59 1.4.6.2 rpaulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60 1.4.6.2 rpaulo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61 1.4.6.2 rpaulo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62 1.4.6.2 rpaulo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63 1.4.6.2 rpaulo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64 1.4.6.2 rpaulo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65 1.4.6.2 rpaulo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66 1.4.6.2 rpaulo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67 1.4.6.2 rpaulo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 1.4.6.2 rpaulo */
69 1.4.6.2 rpaulo
70 1.4.6.2 rpaulo /*
71 1.4.6.2 rpaulo * Machine-specific functions for PCI autoconfiguration.
72 1.4.6.2 rpaulo *
73 1.4.6.2 rpaulo * On PCs, there are two methods of generating PCI configuration cycles.
74 1.4.6.2 rpaulo * We try to detect the appropriate mechanism for this machine and set
75 1.4.6.2 rpaulo * up a few function pointers to access the correct method directly.
76 1.4.6.2 rpaulo *
77 1.4.6.2 rpaulo * The configuration method can be hard-coded in the config file by
78 1.4.6.2 rpaulo * using `options PCI_CONF_MODE=N', where `N' is the configuration mode
79 1.4.6.2 rpaulo * as defined section 3.6.4.1, `Generating Configuration Cycles'.
80 1.4.6.2 rpaulo */
81 1.4.6.2 rpaulo
82 1.4.6.2 rpaulo #include <sys/cdefs.h>
83 1.4.6.2 rpaulo __KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.4.6.2 2006/09/09 02:44:49 rpaulo Exp $");
84 1.4.6.2 rpaulo
85 1.4.6.2 rpaulo #include <sys/types.h>
86 1.4.6.2 rpaulo #include <sys/param.h>
87 1.4.6.2 rpaulo #include <sys/time.h>
88 1.4.6.2 rpaulo #include <sys/systm.h>
89 1.4.6.2 rpaulo #include <sys/errno.h>
90 1.4.6.2 rpaulo #include <sys/device.h>
91 1.4.6.2 rpaulo #include <sys/lock.h>
92 1.4.6.2 rpaulo
93 1.4.6.2 rpaulo #include <uvm/uvm_extern.h>
94 1.4.6.2 rpaulo
95 1.4.6.2 rpaulo #include <machine/intr.h>
96 1.4.6.2 rpaulo
97 1.4.6.2 rpaulo #include <dev/pci/pcivar.h>
98 1.4.6.2 rpaulo
99 1.4.6.2 rpaulo #include "ioapic.h"
100 1.4.6.2 rpaulo #include "eisa.h"
101 1.4.6.2 rpaulo #include "acpi.h"
102 1.4.6.2 rpaulo #include "opt_mpbios.h"
103 1.4.6.2 rpaulo #include "opt_acpi.h"
104 1.4.6.2 rpaulo
105 1.4.6.2 rpaulo #if NIOAPIC > 0 || NACPI > 0
106 1.4.6.2 rpaulo #include <machine/i82093var.h>
107 1.4.6.2 rpaulo #include <machine/mpconfig.h>
108 1.4.6.2 rpaulo #include <machine/mpbiosvar.h>
109 1.4.6.2 rpaulo #include <machine/pic.h>
110 1.4.6.2 rpaulo #endif
111 1.4.6.2 rpaulo
112 1.4.6.2 rpaulo #ifdef MPBIOS
113 1.4.6.2 rpaulo #include <machine/mpbiosvar.h>
114 1.4.6.2 rpaulo #endif
115 1.4.6.2 rpaulo
116 1.4.6.2 rpaulo #if NACPI > 0
117 1.4.6.2 rpaulo #include <machine/mpacpi.h>
118 1.4.6.2 rpaulo #endif
119 1.4.6.2 rpaulo
120 1.4.6.2 rpaulo int
121 1.4.6.2 rpaulo pci_intr_map(pa, ihp)
122 1.4.6.2 rpaulo struct pci_attach_args *pa;
123 1.4.6.2 rpaulo pci_intr_handle_t *ihp;
124 1.4.6.2 rpaulo {
125 1.4.6.2 rpaulo int pin = pa->pa_intrpin;
126 1.4.6.2 rpaulo int line = pa->pa_intrline;
127 1.4.6.2 rpaulo #if NIOAPIC > 0 || NACPI > 0
128 1.4.6.2 rpaulo int rawpin = pa->pa_rawintrpin;
129 1.4.6.2 rpaulo pci_chipset_tag_t pc = pa->pa_pc;
130 1.4.6.2 rpaulo int bus, dev, func;
131 1.4.6.2 rpaulo #endif
132 1.4.6.2 rpaulo
133 1.4.6.2 rpaulo if (pin == 0) {
134 1.4.6.2 rpaulo /* No IRQ used. */
135 1.4.6.2 rpaulo goto bad;
136 1.4.6.2 rpaulo }
137 1.4.6.2 rpaulo
138 1.4.6.2 rpaulo *ihp = 0;
139 1.4.6.2 rpaulo
140 1.4.6.2 rpaulo if (pin > PCI_INTERRUPT_PIN_MAX) {
141 1.4.6.2 rpaulo printf("pci_intr_map: bad interrupt pin %d\n", pin);
142 1.4.6.2 rpaulo goto bad;
143 1.4.6.2 rpaulo }
144 1.4.6.2 rpaulo
145 1.4.6.2 rpaulo #if NIOAPIC > 0 || NACPI > 0
146 1.4.6.2 rpaulo pci_decompose_tag(pc, pa->pa_tag, &bus, &dev, &func);
147 1.4.6.2 rpaulo if (mp_busses != NULL) {
148 1.4.6.2 rpaulo if (intr_find_mpmapping(bus, (dev<<2)|(rawpin-1), ihp) == 0) {
149 1.4.6.2 rpaulo if ((*ihp & 0xff) == 0)
150 1.4.6.2 rpaulo *ihp |= line;
151 1.4.6.2 rpaulo return 0;
152 1.4.6.2 rpaulo }
153 1.4.6.2 rpaulo /*
154 1.4.6.2 rpaulo * No explicit PCI mapping found. This is not fatal,
155 1.4.6.2 rpaulo * we'll try the ISA (or possibly EISA) mappings next.
156 1.4.6.2 rpaulo */
157 1.4.6.2 rpaulo }
158 1.4.6.2 rpaulo #endif
159 1.4.6.2 rpaulo
160 1.4.6.2 rpaulo /*
161 1.4.6.2 rpaulo * Section 6.2.4, `Miscellaneous Functions', says that 255 means
162 1.4.6.2 rpaulo * `unknown' or `no connection' on a PC. We assume that a device with
163 1.4.6.2 rpaulo * `no connection' either doesn't have an interrupt (in which case the
164 1.4.6.2 rpaulo * pin number should be 0, and would have been noticed above), or
165 1.4.6.2 rpaulo * wasn't configured by the BIOS (in which case we punt, since there's
166 1.4.6.2 rpaulo * no real way we can know how the interrupt lines are mapped in the
167 1.4.6.2 rpaulo * hardware).
168 1.4.6.2 rpaulo *
169 1.4.6.2 rpaulo * XXX
170 1.4.6.2 rpaulo * Since IRQ 0 is only used by the clock, and we can't actually be sure
171 1.4.6.2 rpaulo * that the BIOS did its job, we also recognize that as meaning that
172 1.4.6.2 rpaulo * the BIOS has not configured the device.
173 1.4.6.2 rpaulo */
174 1.4.6.2 rpaulo if (line == 0 || line == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) {
175 1.4.6.2 rpaulo printf("pci_intr_map: no mapping for pin %c (line=%02x)\n",
176 1.4.6.2 rpaulo '@' + pin, line);
177 1.4.6.2 rpaulo goto bad;
178 1.4.6.2 rpaulo } else {
179 1.4.6.2 rpaulo if (line >= NUM_LEGACY_IRQS) {
180 1.4.6.2 rpaulo printf("pci_intr_map: bad interrupt line %d\n", line);
181 1.4.6.2 rpaulo goto bad;
182 1.4.6.2 rpaulo }
183 1.4.6.2 rpaulo if (line == 2) {
184 1.4.6.2 rpaulo printf("pci_intr_map: changed line 2 to line 9\n");
185 1.4.6.2 rpaulo line = 9;
186 1.4.6.2 rpaulo }
187 1.4.6.2 rpaulo }
188 1.4.6.2 rpaulo #if NIOAPIC > 0 || NACPI > 0
189 1.4.6.2 rpaulo if (mp_busses != NULL) {
190 1.4.6.2 rpaulo if (intr_find_mpmapping(mp_isa_bus, line, ihp) == 0) {
191 1.4.6.2 rpaulo if ((*ihp & 0xff) == 0)
192 1.4.6.2 rpaulo *ihp |= line;
193 1.4.6.2 rpaulo return 0;
194 1.4.6.2 rpaulo }
195 1.4.6.2 rpaulo #if NEISA > 0
196 1.4.6.2 rpaulo if (intr_find_mpmapping(mp_eisa_bus, line, ihp) == 0) {
197 1.4.6.2 rpaulo if ((*ihp & 0xff) == 0)
198 1.4.6.2 rpaulo *ihp |= line;
199 1.4.6.2 rpaulo return 0;
200 1.4.6.2 rpaulo }
201 1.4.6.2 rpaulo #endif
202 1.4.6.2 rpaulo printf("pci_intr_map: bus %d dev %d func %d pin %d; line %d\n",
203 1.4.6.2 rpaulo bus, dev, func, pin, line);
204 1.4.6.2 rpaulo printf("pci_intr_map: no MP mapping found\n");
205 1.4.6.2 rpaulo }
206 1.4.6.2 rpaulo #endif
207 1.4.6.2 rpaulo
208 1.4.6.2 rpaulo *ihp = line;
209 1.4.6.2 rpaulo return 0;
210 1.4.6.2 rpaulo
211 1.4.6.2 rpaulo bad:
212 1.4.6.2 rpaulo *ihp = -1;
213 1.4.6.2 rpaulo return 1;
214 1.4.6.2 rpaulo }
215 1.4.6.2 rpaulo
216 1.4.6.2 rpaulo const char *
217 1.4.6.2 rpaulo pci_intr_string(pc, ih)
218 1.4.6.2 rpaulo pci_chipset_tag_t pc;
219 1.4.6.2 rpaulo pci_intr_handle_t ih;
220 1.4.6.2 rpaulo {
221 1.4.6.2 rpaulo return intr_string(ih);
222 1.4.6.2 rpaulo }
223 1.4.6.2 rpaulo
224 1.4.6.2 rpaulo
225 1.4.6.2 rpaulo const struct evcnt *
226 1.4.6.2 rpaulo pci_intr_evcnt(pc, ih)
227 1.4.6.2 rpaulo pci_chipset_tag_t pc;
228 1.4.6.2 rpaulo pci_intr_handle_t ih;
229 1.4.6.2 rpaulo {
230 1.4.6.2 rpaulo
231 1.4.6.2 rpaulo /* XXX for now, no evcnt parent reported */
232 1.4.6.2 rpaulo return NULL;
233 1.4.6.2 rpaulo }
234 1.4.6.2 rpaulo
235 1.4.6.2 rpaulo void *
236 1.4.6.2 rpaulo pci_intr_establish(pc, ih, level, func, arg)
237 1.4.6.2 rpaulo pci_chipset_tag_t pc;
238 1.4.6.2 rpaulo pci_intr_handle_t ih;
239 1.4.6.2 rpaulo int level, (*func) __P((void *));
240 1.4.6.2 rpaulo void *arg;
241 1.4.6.2 rpaulo {
242 1.4.6.2 rpaulo int pin, irq;
243 1.4.6.2 rpaulo struct pic *pic;
244 1.4.6.2 rpaulo
245 1.4.6.2 rpaulo pic = &i8259_pic;
246 1.4.6.2 rpaulo pin = irq = ih;
247 1.4.6.2 rpaulo
248 1.4.6.2 rpaulo #if NIOAPIC > 0
249 1.4.6.2 rpaulo if (ih & APIC_INT_VIA_APIC) {
250 1.4.6.2 rpaulo pic = (struct pic *)ioapic_find(APIC_IRQ_APIC(ih));
251 1.4.6.2 rpaulo if (pic == NULL) {
252 1.4.6.2 rpaulo printf("pci_intr_establish: bad ioapic %d\n",
253 1.4.6.2 rpaulo APIC_IRQ_APIC(ih));
254 1.4.6.2 rpaulo return NULL;
255 1.4.6.2 rpaulo }
256 1.4.6.2 rpaulo pin = APIC_IRQ_PIN(ih);
257 1.4.6.2 rpaulo irq = APIC_IRQ_LEGACY_IRQ(ih);
258 1.4.6.2 rpaulo if (irq < 0 || irq >= NUM_LEGACY_IRQS)
259 1.4.6.2 rpaulo irq = -1;
260 1.4.6.2 rpaulo }
261 1.4.6.2 rpaulo #endif
262 1.4.6.2 rpaulo
263 1.4.6.2 rpaulo return intr_establish(irq, pic, pin, IST_LEVEL, level, func, arg);
264 1.4.6.2 rpaulo }
265 1.4.6.2 rpaulo
266 1.4.6.2 rpaulo void
267 1.4.6.2 rpaulo pci_intr_disestablish(pc, cookie)
268 1.4.6.2 rpaulo pci_chipset_tag_t pc;
269 1.4.6.2 rpaulo void *cookie;
270 1.4.6.2 rpaulo {
271 1.4.6.2 rpaulo
272 1.4.6.2 rpaulo intr_disestablish(cookie);
273 1.4.6.2 rpaulo }
274