pci_intr_fixup.c revision 1.33 1 /* $NetBSD: pci_intr_fixup.c,v 1.33 2005/12/11 12:17:44 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
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.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1999, by UCHIYAMA Yasushi
42 * All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. The name of the developer may NOT be used to endorse or promote products
50 * derived from this software without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 */
64
65 /*
66 * PCI Interrupt Router support.
67 */
68
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: pci_intr_fixup.c,v 1.33 2005/12/11 12:17:44 christos Exp $");
71
72 #include "opt_pcibios.h"
73 #include "opt_pcifixup.h"
74
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/kernel.h>
78 #include <sys/malloc.h>
79 #include <sys/queue.h>
80 #include <sys/device.h>
81
82 #include <machine/bus.h>
83 #include <machine/intr.h>
84
85 #include <dev/pci/pcireg.h>
86 #include <dev/pci/pcivar.h>
87 #include <dev/pci/pcidevs.h>
88
89 #include <i386/pci/pci_intr_fixup.h>
90 #include <i386/pci/pcibios.h>
91
92 struct pciintr_link_map {
93 int link;
94 int clink;
95 int irq;
96 u_int16_t bitmap;
97 int fixup_stage;
98 SIMPLEQ_ENTRY(pciintr_link_map) list;
99 };
100
101 pciintr_icu_tag_t pciintr_icu_tag;
102 pciintr_icu_handle_t pciintr_icu_handle;
103
104 #ifdef PCIBIOS_IRQS_HINT
105 int pcibios_irqs_hint = PCIBIOS_IRQS_HINT;
106 #endif
107
108 struct pciintr_link_map *pciintr_link_lookup(int);
109 struct pciintr_link_map *pciintr_link_alloc(struct pcibios_intr_routing *,
110 int);
111 struct pcibios_intr_routing *pciintr_pir_lookup(int, int);
112 static int pciintr_bitmap_count_irq(int, int *);
113 static int pciintr_bitmap_find_lowest_irq(int, int *);
114 int pciintr_link_init (void);
115 #ifdef PCIBIOS_INTR_GUESS
116 int pciintr_guess_irq(void);
117 #endif
118 int pciintr_link_fixup(void);
119 int pciintr_link_route(u_int16_t *);
120 int pciintr_irq_release(u_int16_t *);
121 int pciintr_header_fixup(pci_chipset_tag_t);
122 void pciintr_do_header_fixup(pci_chipset_tag_t, pcitag_t, void*);
123
124 SIMPLEQ_HEAD(, pciintr_link_map) pciintr_link_map_list;
125
126 const struct pciintr_icu_table {
127 pci_vendor_id_t piit_vendor;
128 pci_product_id_t piit_product;
129 int (*piit_init)(pci_chipset_tag_t,
130 bus_space_tag_t, pcitag_t, pciintr_icu_tag_t *,
131 pciintr_icu_handle_t *);
132 } pciintr_icu_table[] = {
133 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371MX,
134 piix_init },
135 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_ISA,
136 piix_init },
137 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371FB_ISA,
138 piix_init },
139 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371SB_ISA,
140 piix_init },
141 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_LPC,
142 piix_init }, /* ICH */
143 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_LPC,
144 piix_init }, /* ICH0 */
145 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_LPC,
146 ich_init }, /* ICH2 */
147 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BAM_LPC,
148 ich_init }, /* ICH2M */
149 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_LPC,
150 ich_init }, /* ICH3S */
151 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CAM_LPC,
152 ich_init }, /* ICH3M */
153 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_LPC,
154 ich_init }, /* ICH4 */
155 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_ISA,
156 ich_init }, /* ICH4M */
157 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_LPC,
158 ich_init }, /* ICH5 */
159
160 { PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C558,
161 opti82c558_init },
162 { PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C700,
163 opti82c700_init },
164
165 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586_ISA,
166 via82c586_init },
167 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C596A,
168 via82c586_init },
169 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_ISA,
170 via82c586_init },
171
172 { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C503,
173 sis85c503_init },
174
175 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC756_PMC,
176 amd756_init },
177
178 { PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1543,
179 ali1543_init },
180
181 { 0, 0,
182 NULL },
183 };
184
185 const struct pciintr_icu_table *pciintr_icu_lookup(pcireg_t);
186
187 const struct pciintr_icu_table *
188 pciintr_icu_lookup(pcireg_t id)
189 {
190 const struct pciintr_icu_table *piit;
191
192 for (piit = pciintr_icu_table;
193 piit->piit_init != NULL;
194 piit++) {
195 if (PCI_VENDOR(id) == piit->piit_vendor &&
196 PCI_PRODUCT(id) == piit->piit_product)
197 return (piit);
198 }
199
200 return (NULL);
201 }
202
203 struct pciintr_link_map *
204 pciintr_link_lookup(int link)
205 {
206 struct pciintr_link_map *l;
207
208 SIMPLEQ_FOREACH(l, &pciintr_link_map_list, list) {
209 if (l->link == link)
210 return (l);
211 }
212
213 return (NULL);
214 }
215
216 struct pciintr_link_map *
217 pciintr_link_alloc(struct pcibios_intr_routing *pir, int pin)
218 {
219 int link = pir->linkmap[pin].link, clink, irq;
220 struct pciintr_link_map *l, *lstart;
221
222 if (pciintr_icu_tag != NULL) { /* compatible PCI ICU found */
223 /*
224 * Get the canonical link value for this entry.
225 */
226 if (pciintr_icu_getclink(pciintr_icu_tag, pciintr_icu_handle,
227 link, &clink) != 0) {
228 /*
229 * ICU doesn't understand the link value.
230 * Just ignore this PIR entry.
231 */
232 #ifdef DIAGNOSTIC
233 printf("pciintr_link_alloc: bus %d device %d: "
234 "link 0x%02x invalid\n",
235 pir->bus, PIR_DEVFUNC_DEVICE(pir->device), link);
236 #endif
237 return (NULL);
238 }
239
240 /*
241 * Check the link value by asking the ICU for the
242 * canonical link value.
243 * Also, determine if this PIRQ is mapped to an IRQ.
244 */
245 if (pciintr_icu_get_intr(pciintr_icu_tag, pciintr_icu_handle,
246 clink, &irq) != 0) {
247 /*
248 * ICU doesn't understand the canonical link value.
249 * Just ignore this PIR entry.
250 */
251 #ifdef DIAGNOSTIC
252 printf("pciintr_link_alloc: "
253 "bus %d device %d link 0x%02x: "
254 "PIRQ 0x%02x invalid\n",
255 pir->bus, PIR_DEVFUNC_DEVICE(pir->device), link,
256 clink);
257 #endif
258 return (NULL);
259 }
260 }
261
262 l = malloc(sizeof(*l), M_DEVBUF, M_NOWAIT);
263 if (l == NULL)
264 panic("pciintr_link_alloc");
265
266 memset(l, 0, sizeof(*l));
267
268 l->link = link;
269 l->bitmap = pir->linkmap[pin].bitmap;
270 if (pciintr_icu_tag != NULL) { /* compatible PCI ICU found */
271 l->clink = clink;
272 l->irq = irq; /* maybe X86_PCI_INTERRUPT_LINE_NO_CONNECTION */
273 } else {
274 l->clink = link; /* only for PCIBIOSVERBOSE diagnostic */
275 l->irq = X86_PCI_INTERRUPT_LINE_NO_CONNECTION;
276 }
277
278 lstart = SIMPLEQ_FIRST(&pciintr_link_map_list);
279 if (lstart == NULL || lstart->link < l->link)
280 SIMPLEQ_INSERT_TAIL(&pciintr_link_map_list, l, list);
281 else
282 SIMPLEQ_INSERT_HEAD(&pciintr_link_map_list, l, list);
283
284 return (l);
285 }
286
287 struct pcibios_intr_routing *
288 pciintr_pir_lookup(int bus, int device)
289 {
290 struct pcibios_intr_routing *pir;
291 int entry;
292
293 if (pcibios_pir_table == NULL)
294 return (NULL);
295
296 for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
297 pir = &pcibios_pir_table[entry];
298 if (pir->bus == bus &&
299 PIR_DEVFUNC_DEVICE(pir->device) == device)
300 return (pir);
301 }
302
303 return (NULL);
304 }
305
306 static int
307 pciintr_bitmap_count_irq(int irq_bitmap, int *irqp)
308 {
309 int i, bit, count = 0, irq = X86_PCI_INTERRUPT_LINE_NO_CONNECTION;
310
311 if (irq_bitmap != 0) {
312 for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
313 if (irq_bitmap & bit) {
314 irq = i;
315 count++;
316 }
317 }
318 }
319 *irqp = irq;
320 return (count);
321 }
322
323 static int
324 pciintr_bitmap_find_lowest_irq(int irq_bitmap, int *irqp)
325 {
326 int i, bit;
327
328 if (irq_bitmap != 0) {
329 for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
330 if (irq_bitmap & bit) {
331 *irqp = i;
332 return (1); /* found */
333 }
334 }
335 }
336 return (0); /* not found */
337 }
338
339 int
340 pciintr_link_init(void)
341 {
342 int entry, pin, link;
343 struct pcibios_intr_routing *pir;
344 struct pciintr_link_map *l;
345
346 if (pcibios_pir_table == NULL) {
347 /* No PIR table; can't do anything. */
348 printf("pciintr_link_init: no PIR table\n");
349 return (1);
350 }
351
352 SIMPLEQ_INIT(&pciintr_link_map_list);
353
354 for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
355 pir = &pcibios_pir_table[entry];
356 for (pin = 0; pin < PCI_INTERRUPT_PIN_MAX; pin++) {
357 link = pir->linkmap[pin].link;
358 if (link == 0) {
359 /* No connection for this pin. */
360 continue;
361 }
362 /*
363 * Multiple devices may be wired to the same
364 * interrupt; check to see if we've seen this
365 * one already. If not, allocate a new link
366 * map entry and stuff it in the map.
367 */
368 l = pciintr_link_lookup(link);
369 if (l == NULL) {
370 (void) pciintr_link_alloc(pir, pin);
371 } else if (pir->linkmap[pin].bitmap != l->bitmap) {
372 /*
373 * violates PCI IRQ Routing Table Specification
374 */
375 #ifdef DIAGNOSTIC
376 printf("pciintr_link_init: "
377 "bus %d device %d link 0x%02x: "
378 "bad irq bitmap 0x%04x, "
379 "should be 0x%04x\n",
380 pir->bus, PIR_DEVFUNC_DEVICE(pir->device),
381 link, pir->linkmap[pin].bitmap, l->bitmap);
382 #endif
383 /* safer value. */
384 l->bitmap &= pir->linkmap[pin].bitmap;
385 /* XXX - or, should ignore this entry? */
386 }
387 }
388 }
389
390 return (0);
391 }
392
393 #ifdef PCIBIOS_INTR_GUESS
394 /*
395 * No compatible PCI ICU found.
396 * Hopes the BIOS already setup the ICU.
397 */
398 int
399 pciintr_guess_irq(void)
400 {
401 struct pciintr_link_map *l;
402 int irq, guessed = 0;
403
404 /*
405 * Stage 1: If only one IRQ is available for the link, use it.
406 */
407 SIMPLEQ_FOREACH(l, &pciintr_link_map_list, list) {
408 if (l->irq != X86_PCI_INTERRUPT_LINE_NO_CONNECTION)
409 continue;
410 if (pciintr_bitmap_count_irq(l->bitmap, &irq) == 1) {
411 l->irq = irq;
412 l->fixup_stage = 1;
413 #ifdef PCIINTR_DEBUG
414 printf("pciintr_guess_irq (stage 1): "
415 "guessing PIRQ 0x%02x to be IRQ %d\n",
416 l->clink, l->irq);
417 #endif
418 guessed = 1;
419 }
420 }
421
422 return (guessed ? 0 : -1);
423 }
424 #endif /* PCIBIOS_INTR_GUESS */
425
426 int
427 pciintr_link_fixup(void)
428 {
429 struct pciintr_link_map *l;
430 int irq;
431 u_int16_t pciirq = 0;
432
433 /*
434 * First stage: Attempt to connect PIRQs which aren't
435 * yet connected.
436 */
437 SIMPLEQ_FOREACH(l, &pciintr_link_map_list, list) {
438 if (l->irq != X86_PCI_INTERRUPT_LINE_NO_CONNECTION) {
439 /*
440 * Interrupt is already connected. Don't do
441 * anything to it.
442 * In this case, l->fixup_stage == 0.
443 */
444 pciirq |= 1 << l->irq;
445 #ifdef PCIINTR_DEBUG
446 printf("pciintr_link_fixup: PIRQ 0x%02x already "
447 "connected to IRQ %d\n", l->clink, l->irq);
448 #endif
449 continue;
450 }
451 /*
452 * Interrupt isn't connected. Attempt to assign it to an IRQ.
453 */
454 #ifdef PCIINTR_DEBUG
455 printf("pciintr_link_fixup: PIRQ 0x%02x not connected",
456 l->clink);
457 #endif
458 /*
459 * Just do the easy case now; we'll defer the harder ones
460 * to Stage 2.
461 */
462 if (pciintr_bitmap_count_irq(l->bitmap, &irq) == 1) {
463 l->irq = irq;
464 l->fixup_stage = 1;
465 pciirq |= 1 << irq;
466 #ifdef PCIINTR_DEBUG
467 printf(", assigning IRQ %d", l->irq);
468 #endif
469 }
470 #ifdef PCIINTR_DEBUG
471 printf("\n");
472 #endif
473 }
474
475 /*
476 * Stage 2: Attempt to connect PIRQs which we didn't
477 * connect in Stage 1.
478 */
479 SIMPLEQ_FOREACH(l, &pciintr_link_map_list, list) {
480 if (l->irq != X86_PCI_INTERRUPT_LINE_NO_CONNECTION)
481 continue;
482 if (pciintr_bitmap_find_lowest_irq(l->bitmap & pciirq,
483 &l->irq)) {
484 /*
485 * This IRQ is a valid PCI IRQ already
486 * connected to another PIRQ, and also an
487 * IRQ our PIRQ can use; connect it up!
488 */
489 l->fixup_stage = 2;
490 #ifdef PCIINTR_DEBUG
491 printf("pciintr_link_fixup (stage 2): "
492 "assigning IRQ %d to PIRQ 0x%02x\n",
493 l->irq, l->clink);
494 #endif
495 }
496 }
497
498 #ifdef PCIBIOS_IRQS_HINT
499 /*
500 * Stage 3: The worst case. I need configuration hint that
501 * user supplied a mask for the PCI irqs
502 */
503 SIMPLEQ_FOREACH(l, &pciintr_link_map_list, list) {
504 if (l->irq != X86_PCI_INTERRUPT_LINE_NO_CONNECTION)
505 continue;
506 if (pciintr_bitmap_find_lowest_irq(
507 l->bitmap & pcibios_irqs_hint, &l->irq)) {
508 l->fixup_stage = 3;
509 #ifdef PCIINTR_DEBUG
510 printf("pciintr_link_fixup (stage 3): "
511 "assigning IRQ %d to PIRQ 0x%02x\n",
512 l->irq, l->clink);
513 #endif
514 }
515 }
516 #endif /* PCIBIOS_IRQS_HINT */
517
518 return (0);
519 }
520
521 int
522 pciintr_link_route(u_int16_t *pciirq)
523 {
524 struct pciintr_link_map *l;
525 int rv = 0;
526
527 *pciirq = 0;
528
529 SIMPLEQ_FOREACH(l, &pciintr_link_map_list, list) {
530 if (l->fixup_stage == 0) {
531 if (l->irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) {
532 /* Appropriate interrupt was not found. */
533 #ifdef DIAGNOSTIC
534 printf("pciintr_link_route: "
535 "PIRQ 0x%02x: no IRQ, try "
536 "\"options PCIBIOS_IRQS_HINT=0x%04x\"\n",
537 l->clink,
538 /* suggest irq 9/10/11, if possible */
539 (l->bitmap & 0x0e00) ? (l->bitmap & 0x0e00)
540 : l->bitmap);
541 #endif
542 } else {
543 /* BIOS setting has no problem */
544 #ifdef PCIINTR_DEBUG
545 printf("pciintr_link_route: "
546 "route of PIRQ 0x%02x -> "
547 "IRQ %d preserved BIOS setting\n",
548 l->clink, l->irq);
549 #endif
550 *pciirq |= (1 << l->irq);
551 }
552 continue; /* nothing to do. */
553 }
554
555 if (pciintr_icu_set_intr(pciintr_icu_tag, pciintr_icu_handle,
556 l->clink, l->irq) != 0 ||
557 pciintr_icu_set_trigger(pciintr_icu_tag,
558 pciintr_icu_handle,
559 l->irq, IST_LEVEL) != 0) {
560 printf("pciintr_link_route: route of PIRQ 0x%02x -> "
561 "IRQ %d failed\n", l->clink, l->irq);
562 rv = 1;
563 } else {
564 /*
565 * Succssfully routed interrupt. Mark this as
566 * a PCI interrupt.
567 */
568 *pciirq |= (1 << l->irq);
569 }
570 }
571
572 return (rv);
573 }
574
575 int
576 pciintr_irq_release(u_int16_t *pciirq)
577 {
578 int i, bit;
579 u_int16_t bios_pciirq;
580 int reg;
581
582 #ifdef PCIINTR_DEBUG
583 printf("pciintr_irq_release: fixup pciirq level/edge map 0x%04x\n",
584 *pciirq);
585 #endif
586
587 /* Get bios level/edge setting. */
588 bios_pciirq = 0;
589 for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
590 (void)pciintr_icu_get_trigger(pciintr_icu_tag,
591 pciintr_icu_handle, i, ®);
592 if (reg == IST_LEVEL)
593 bios_pciirq |= bit;
594 }
595
596 #ifdef PCIINTR_DEBUG
597 printf("pciintr_irq_release: bios pciirq level/edge map 0x%04x\n",
598 bios_pciirq);
599 #endif /* PCIINTR_DEBUG */
600
601 /* fixup final level/edge setting. */
602 *pciirq |= bios_pciirq;
603 for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
604 if ((*pciirq & bit) == 0)
605 reg = IST_EDGE;
606 else
607 reg = IST_LEVEL;
608 (void) pciintr_icu_set_trigger(pciintr_icu_tag,
609 pciintr_icu_handle, i, reg);
610
611 }
612
613 #ifdef PCIINTR_DEBUG
614 printf("pciintr_irq_release: final pciirq level/edge map 0x%04x\n",
615 *pciirq);
616 #endif /* PCIINTR_DEBUG */
617
618 return (0);
619 }
620
621 int
622 pciintr_header_fixup(pci_chipset_tag_t pc)
623 {
624 PCIBIOS_PRINTV(("------------------------------------------\n"));
625 PCIBIOS_PRINTV((" device vendor product pin PIRQ IRQ stage\n"));
626 PCIBIOS_PRINTV(("------------------------------------------\n"));
627 pci_device_foreach(pc, pcibios_max_bus, pciintr_do_header_fixup, NULL);
628 PCIBIOS_PRINTV(("------------------------------------------\n"));
629
630 return (0);
631 }
632
633 void
634 pciintr_do_header_fixup(pci_chipset_tag_t pc, pcitag_t tag, void *context)
635 {
636 struct pcibios_intr_routing *pir;
637 struct pciintr_link_map *l;
638 int pin, irq, link;
639 int bus, device, function;
640 pcireg_t intr, id;
641
642 pci_decompose_tag(pc, tag, &bus, &device, &function);
643 id = pci_conf_read(pc, tag, PCI_ID_REG);
644
645 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
646 pin = PCI_INTERRUPT_PIN(intr);
647 irq = PCI_INTERRUPT_LINE(intr);
648
649 #if 0
650 if (pin == 0) {
651 /*
652 * No interrupt used.
653 */
654 return;
655 }
656 #endif
657
658 pir = pciintr_pir_lookup(bus, device);
659 if (pir == NULL || (link = pir->linkmap[pin - 1].link) == 0) {
660 /*
661 * Interrupt not connected; no
662 * need to change.
663 */
664 return;
665 }
666
667 l = pciintr_link_lookup(link);
668 if (l == NULL) {
669 #ifdef PCIINTR_DEBUG
670 /*
671 * No link map entry.
672 * Probably pciintr_icu_getclink() or pciintr_icu_get_intr()
673 * was failed.
674 */
675 printf("pciintr_header_fixup: no entry for link 0x%02x "
676 "(%d:%d:%d:%c)\n", link, bus, device, function,
677 '@' + pin);
678 #endif
679 return;
680 }
681
682 #ifdef PCIBIOSVERBOSE
683 if (pcibiosverbose) {
684 printf("%03d:%02d:%d 0x%04x 0x%04x %c 0x%02x",
685 bus, device, function, PCI_VENDOR(id), PCI_PRODUCT(id),
686 '@' + pin, l->clink);
687 if (l->irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION)
688 printf(" -");
689 else
690 printf(" %3d", l->irq);
691 printf(" %d ", l->fixup_stage);
692 }
693 #endif
694
695 /*
696 * IRQs 14 and 15 are reserved for PCI IDE interrupts; don't muck
697 * with them.
698 */
699 if (irq == 14 || irq == 15) {
700 PCIBIOS_PRINTV((" WARNING: ignored\n"));
701 return;
702 }
703
704 if (l->irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) {
705 /* Appropriate interrupt was not found. */
706 if (pciintr_icu_tag == NULL &&
707 irq != 0 && irq != X86_PCI_INTERRUPT_LINE_NO_CONNECTION) {
708 /*
709 * Do not print warning,
710 * if no compatible PCI ICU found,
711 * but the irq is already assigned by BIOS.
712 */
713 PCIBIOS_PRINTV(("\n"));
714 } else {
715 PCIBIOS_PRINTV((" WARNING: missing IRQ\n"));
716 }
717 return;
718 }
719
720 if (l->irq == irq) {
721 /* don't have to reconfigure */
722 PCIBIOS_PRINTV((" already assigned\n"));
723 return;
724 }
725
726 if (irq == 0 || irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) {
727 PCIBIOS_PRINTV((" fixed up\n"));
728 } else {
729 /* routed by BIOS, but inconsistent */
730 #ifdef PCI_INTR_FIXUP_FORCE
731 /* believe PCI IRQ Routing table */
732 PCIBIOS_PRINTV((" WARNING: overriding irq %d\n", irq));
733 #else
734 /* believe PCI Interrupt Configuration Register (default) */
735 PCIBIOS_PRINTV((" WARNING: preserving irq %d\n", irq));
736 return;
737 #endif
738 }
739
740 intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
741 intr |= (l->irq << PCI_INTERRUPT_LINE_SHIFT);
742 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
743 }
744
745 int
746 pci_intr_fixup(pci_chipset_tag_t pc, bus_space_tag_t iot, u_int16_t *pciirq)
747 {
748 const struct pciintr_icu_table *piit = NULL;
749 pcitag_t icutag;
750 pcireg_t icuid;
751
752 /*
753 * Attempt to initialize our PCI interrupt router. If
754 * the PIR Table is present in ROM, use the location
755 * specified by the PIR Table, and use the compat ID,
756 * if present. Otherwise, we have to look for the router
757 * ourselves (the PCI-ISA bridge).
758 *
759 * A number of buggy BIOS implementations leave the router
760 * entry as 000:00:0, which is typically not the correct
761 * device/function. If the router device address is set to
762 * this value, and the compatible router entry is undefined
763 * (zero is the correct value to indicate undefined), then we
764 * work on the basis it is most likely an error, and search
765 * the entire device-space of bus 0 (but obviously starting
766 * with 000:00:0, in case that really is the right one).
767 */
768 if (pcibios_pir_header.signature != 0 &&
769 (pcibios_pir_header.router_bus != 0 ||
770 PIR_DEVFUNC_DEVICE(pcibios_pir_header.router_devfunc) != 0 ||
771 PIR_DEVFUNC_FUNCTION(pcibios_pir_header.router_devfunc) != 0 ||
772 pcibios_pir_header.compat_router != 0)) {
773 icutag = pci_make_tag(pc, pcibios_pir_header.router_bus,
774 PIR_DEVFUNC_DEVICE(pcibios_pir_header.router_devfunc),
775 PIR_DEVFUNC_FUNCTION(pcibios_pir_header.router_devfunc));
776 icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
777 if ((piit = pciintr_icu_lookup(icuid)) == NULL) {
778 /*
779 * if we fail to look up an ICU at given
780 * PCI address, try compat ID next.
781 */
782 icuid = pcibios_pir_header.compat_router;
783 piit = pciintr_icu_lookup(icuid);
784 }
785 } else {
786 int device, maxdevs = pci_bus_maxdevs(pc, 0);
787
788 /*
789 * Search configuration space for a known interrupt
790 * router.
791 */
792 for (device = 0; device < maxdevs; device++) {
793 const struct pci_quirkdata *qd;
794 int function, nfuncs;
795 pcireg_t bhlcr;
796
797 icutag = pci_make_tag(pc, 0, device, 0);
798 icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
799
800 /* Invalid vendor ID value? */
801 if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
802 continue;
803 /* XXX Not invalid, but we've done this ~forever. */
804 if (PCI_VENDOR(icuid) == 0)
805 continue;
806
807 qd = pci_lookup_quirkdata(PCI_VENDOR(icuid),
808 PCI_PRODUCT(icuid));
809
810 bhlcr = pci_conf_read(pc, icutag, PCI_BHLC_REG);
811 if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
812 (qd != NULL &&
813 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
814 nfuncs = 8;
815 else
816 nfuncs = 1;
817
818 for (function = 0; function < nfuncs; function++) {
819 icutag = pci_make_tag(pc, 0, device, function);
820 icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
821
822 /* Invalid vendor ID value? */
823 if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
824 continue;
825 /* Not invalid, but we've done this ~forever */
826 if (PCI_VENDOR(icuid) == 0)
827 continue;
828
829 piit = pciintr_icu_lookup(icuid);
830 if (piit != NULL)
831 goto found;
832 }
833 }
834
835 /*
836 * Invalidate the ICU ID. If we failed to find the
837 * interrupt router (piit == NULL) we don't want to
838 * display a spurious device address below containing
839 * the product information of the last device we
840 * looked at.
841 */
842 icuid = 0;
843 found:;
844 }
845
846 if (piit == NULL) {
847 printf("pci_intr_fixup: no compatible PCI ICU found");
848 if (pcibios_pir_header.signature != 0 && icuid != 0)
849 printf(": ICU vendor 0x%04x product 0x%04x",
850 PCI_VENDOR(icuid), PCI_PRODUCT(icuid));
851 printf("\n");
852 #ifdef PCIBIOS_INTR_GUESS
853 if (pciintr_link_init())
854 return (-1); /* non-fatal */
855 if (pciintr_guess_irq())
856 return (-1); /* non-fatal */
857 if (pciintr_header_fixup(pc))
858 return (1); /* fatal */
859 return (0); /* success! */
860 #else
861 return (-1); /* non-fatal */
862 #endif
863 }
864
865 /*
866 * Initialize the PCI ICU.
867 */
868 if ((*piit->piit_init)(pc, iot, icutag, &pciintr_icu_tag,
869 &pciintr_icu_handle) != 0)
870 return (-1); /* non-fatal */
871
872 /*
873 * Initialize the PCI interrupt link map.
874 */
875 if (pciintr_link_init())
876 return (-1); /* non-fatal */
877
878 /*
879 * Fix up the link->IRQ mappings.
880 */
881 if (pciintr_link_fixup() != 0)
882 return (-1); /* non-fatal */
883
884 /*
885 * Now actually program the PCI ICU with the new
886 * routing information.
887 */
888 if (pciintr_link_route(pciirq) != 0)
889 return (1); /* fatal */
890
891 /*
892 * Now that we've routed all of the PIRQs, rewrite the PCI
893 * configuration headers to reflect the new mapping.
894 */
895 if (pciintr_header_fixup(pc) != 0)
896 return (1); /* fatal */
897
898 /*
899 * Free any unused PCI IRQs for ISA devices.
900 */
901 if (pciintr_irq_release(pciirq) != 0)
902 return (-1); /* non-fatal */
903
904 /*
905 * All done!
906 */
907 return (0); /* success! */
908 }
909