pci_intr_fixup.c revision 1.10.2.4 1 /* $NetBSD: pci_intr_fixup.c,v 1.10.2.4 2001/04/23 09:41:50 bouyer 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 "opt_pcibios.h"
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/kernel.h>
74 #include <sys/malloc.h>
75 #include <sys/queue.h>
76 #include <sys/device.h>
77
78 #include <machine/bus.h>
79 #include <machine/intr.h>
80
81 #include <dev/pci/pcireg.h>
82 #include <dev/pci/pcivar.h>
83 #include <dev/pci/pcidevs.h>
84
85 #include <i386/isa/icu.h>
86 #include <i386/pci/pci_intr_fixup.h>
87 #include <i386/pci/pcibios.h>
88
89 struct pciintr_link_map {
90 int link;
91 int clink;
92 int irq;
93 u_int16_t bitmap;
94 int fixup_stage;
95 SIMPLEQ_ENTRY(pciintr_link_map) list;
96 };
97
98 pciintr_icu_tag_t pciintr_icu_tag = NULL;
99 pciintr_icu_handle_t pciintr_icu_handle;
100
101 #ifdef PCIBIOS_IRQS_HINT
102 int pcibios_irqs_hint = PCIBIOS_IRQS_HINT;
103 #endif
104
105 struct pciintr_link_map *pciintr_link_lookup __P((int));
106 struct pciintr_link_map *pciintr_link_alloc __P((struct pcibios_intr_routing *,
107 int));
108 struct pcibios_intr_routing *pciintr_pir_lookup __P((int, int));
109 static int pciintr_bitmap_count_irq __P((int, int *));
110 static int pciintr_bitmap_find_lowest_irq __P((int, int *));
111 int pciintr_link_init __P((void));
112 #ifdef PCIBIOS_INTR_GUESS
113 int pciintr_guess_irq __P((void));
114 #endif
115 int pciintr_link_fixup __P((void));
116 int pciintr_link_route __P((u_int16_t *));
117 int pciintr_irq_release __P((u_int16_t *));
118 int pciintr_header_fixup __P((pci_chipset_tag_t));
119 void pciintr_do_header_fixup __P((pci_chipset_tag_t, pcitag_t));
120
121 SIMPLEQ_HEAD(, pciintr_link_map) pciintr_link_map_list;
122
123 const struct pciintr_icu_table {
124 pci_vendor_id_t piit_vendor;
125 pci_product_id_t piit_product;
126 int (*piit_init) __P((pci_chipset_tag_t,
127 bus_space_tag_t, pcitag_t, pciintr_icu_tag_t *,
128 pciintr_icu_handle_t *));
129 } pciintr_icu_table[] = {
130 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371MX,
131 piix_init },
132 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_ISA,
133 piix_init },
134 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371FB_ISA,
135 piix_init },
136 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371SB_ISA,
137 piix_init },
138
139 { PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C558,
140 opti82c558_init },
141 { PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C700,
142 opti82c700_init },
143
144 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586_ISA,
145 via82c586_init },
146 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_ISA,
147 via82c586_init },
148
149 { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C503,
150 sis85c503_init },
151
152 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC756_PMC,
153 amd756_init },
154
155 { 0, 0,
156 NULL },
157 };
158
159 const struct pciintr_icu_table *pciintr_icu_lookup __P((pcireg_t));
160
161 const struct pciintr_icu_table *
162 pciintr_icu_lookup(id)
163 pcireg_t id;
164 {
165 const struct pciintr_icu_table *piit;
166
167 for (piit = pciintr_icu_table;
168 piit->piit_init != NULL;
169 piit++) {
170 if (PCI_VENDOR(id) == piit->piit_vendor &&
171 PCI_PRODUCT(id) == piit->piit_product)
172 return (piit);
173 }
174
175 return (NULL);
176 }
177
178 struct pciintr_link_map *
179 pciintr_link_lookup(link)
180 int link;
181 {
182 struct pciintr_link_map *l;
183
184 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
185 l = SIMPLEQ_NEXT(l, list)) {
186 if (l->link == link)
187 return (l);
188 }
189
190 return (NULL);
191 }
192
193 struct pciintr_link_map *
194 pciintr_link_alloc(pir, pin)
195 struct pcibios_intr_routing *pir;
196 int pin;
197 {
198 int link = pir->linkmap[pin].link, clink, irq;
199 struct pciintr_link_map *l, *lstart;
200
201 if (pciintr_icu_tag != NULL) { /* compatible PCI ICU found */
202 /*
203 * Get the canonical link value for this entry.
204 */
205 if (pciintr_icu_getclink(pciintr_icu_tag, pciintr_icu_handle,
206 link, &clink) != 0) {
207 /*
208 * ICU doesn't understand the link value.
209 * Just ignore this PIR entry.
210 */
211 #ifdef DIAGNOSTIC
212 printf("pciintr_link_alloc: bus %d device %d: "
213 "link 0x%02x invalid\n",
214 pir->bus, PIR_DEVFUNC_DEVICE(pir->device), link);
215 #endif
216 return (NULL);
217 }
218
219 /*
220 * Check the link value by asking the ICU for the
221 * canonical link value.
222 * Also, determine if this PIRQ is mapped to an IRQ.
223 */
224 if (pciintr_icu_get_intr(pciintr_icu_tag, pciintr_icu_handle,
225 clink, &irq) != 0) {
226 /*
227 * ICU doesn't understand the canonical link value.
228 * Just ignore this PIR entry.
229 */
230 #ifdef DIAGNOSTIC
231 printf("pciintr_link_alloc: "
232 "bus %d device %d link 0x%02x: "
233 "PIRQ 0x%02x invalid\n",
234 pir->bus, PIR_DEVFUNC_DEVICE(pir->device), link,
235 clink);
236 #endif
237 return (NULL);
238 }
239 }
240
241 l = malloc(sizeof(*l), M_DEVBUF, M_NOWAIT);
242 if (l == NULL)
243 panic("pciintr_link_alloc");
244
245 memset(l, 0, sizeof(*l));
246
247 l->link = link;
248 l->bitmap = pir->linkmap[pin].bitmap;
249 if (pciintr_icu_tag != NULL) { /* compatible PCI ICU found */
250 l->clink = clink;
251 l->irq = irq; /* maybe I386_PCI_INTERRUPT_LINE_NO_CONNECTION */
252 } else {
253 l->clink = link; /* only for PCIBIOSVERBOSE diagnostic */
254 l->irq = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;
255 }
256
257 lstart = SIMPLEQ_FIRST(&pciintr_link_map_list);
258 if (lstart == NULL || lstart->link < l->link)
259 SIMPLEQ_INSERT_TAIL(&pciintr_link_map_list, l, list);
260 else
261 SIMPLEQ_INSERT_HEAD(&pciintr_link_map_list, l, list);
262
263 return (l);
264 }
265
266 struct pcibios_intr_routing *
267 pciintr_pir_lookup(bus, device)
268 int bus, device;
269 {
270 struct pcibios_intr_routing *pir;
271 int entry;
272
273 if (pcibios_pir_table == NULL)
274 return (NULL);
275
276 for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
277 pir = &pcibios_pir_table[entry];
278 if (pir->bus == bus &&
279 PIR_DEVFUNC_DEVICE(pir->device) == device)
280 return (pir);
281 }
282
283 return (NULL);
284 }
285
286 static int
287 pciintr_bitmap_count_irq(irq_bitmap, irqp)
288 int irq_bitmap, *irqp;
289 {
290 int i, bit, count = 0, irq = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;
291
292 if (irq_bitmap != 0) {
293 for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
294 if (irq_bitmap & bit) {
295 irq = i;
296 count++;
297 }
298 }
299 }
300 *irqp = irq;
301 return (count);
302 }
303
304 static int
305 pciintr_bitmap_find_lowest_irq(irq_bitmap, irqp)
306 int irq_bitmap, *irqp;
307 {
308 int i, bit;
309
310 if (irq_bitmap != 0) {
311 for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
312 if (irq_bitmap & bit) {
313 *irqp = i;
314 return (1); /* found */
315 }
316 }
317 }
318 return (0); /* not found */
319 }
320
321 int
322 pciintr_link_init()
323 {
324 int entry, pin, link;
325 struct pcibios_intr_routing *pir;
326 struct pciintr_link_map *l;
327
328 if (pcibios_pir_table == NULL) {
329 /* No PIR table; can't do anything. */
330 printf("pciintr_link_init: no PIR table\n");
331 return (1);
332 }
333
334 SIMPLEQ_INIT(&pciintr_link_map_list);
335
336 for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
337 pir = &pcibios_pir_table[entry];
338 for (pin = 0; pin < PCI_INTERRUPT_PIN_MAX; pin++) {
339 link = pir->linkmap[pin].link;
340 if (link == 0) {
341 /* No connection for this pin. */
342 continue;
343 }
344 /*
345 * Multiple devices may be wired to the same
346 * interrupt; check to see if we've seen this
347 * one already. If not, allocate a new link
348 * map entry and stuff it in the map.
349 */
350 l = pciintr_link_lookup(link);
351 if (l == NULL) {
352 (void) pciintr_link_alloc(pir, pin);
353 } else if (pir->linkmap[pin].bitmap != l->bitmap) {
354 /*
355 * violates PCI IRQ Routing Table Specification
356 */
357 #ifdef DIAGNOSTIC
358 printf("pciintr_link_init: "
359 "bus %d device %d link 0x%02x: "
360 "bad irq bitmap 0x%04x, "
361 "should be 0x%04x\n",
362 pir->bus, PIR_DEVFUNC_DEVICE(pir->device),
363 link, pir->linkmap[pin].bitmap, l->bitmap);
364 #endif
365 /* safer value. */
366 l->bitmap &= pir->linkmap[pin].bitmap;
367 /* XXX - or, should ignore this entry? */
368 }
369 }
370 }
371
372 return (0);
373 }
374
375 #ifdef PCIBIOS_INTR_GUESS
376 /*
377 * No compatible PCI ICU found.
378 * Hopes the BIOS already setup the ICU.
379 */
380 int
381 pciintr_guess_irq()
382 {
383 struct pciintr_link_map *l;
384 int irq, guessed = 0;
385
386 /*
387 * Stage 1: If only one IRQ is available for the link, use it.
388 */
389 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
390 l = SIMPLEQ_NEXT(l, list)) {
391 if (l->irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
392 continue;
393 if (pciintr_bitmap_count_irq(l->bitmap, &irq) == 1) {
394 l->irq = irq;
395 l->fixup_stage = 1;
396 #ifdef PCIINTR_DEBUG
397 printf("pciintr_guess_irq (stage 1): "
398 "guessing PIRQ 0x%02x to be IRQ %d\n",
399 l->clink, l->irq);
400 #endif
401 guessed = 1;
402 }
403 }
404
405 return (guessed ? 0 : -1);
406 }
407 #endif /* PCIBIOS_INTR_GUESS */
408
409 int
410 pciintr_link_fixup()
411 {
412 struct pciintr_link_map *l;
413 int irq;
414 u_int16_t pciirq = 0;
415
416 /*
417 * First stage: Attempt to connect PIRQs which aren't
418 * yet connected.
419 */
420 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
421 l = SIMPLEQ_NEXT(l, list)) {
422 if (l->irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
423 /*
424 * Interrupt is already connected. Don't do
425 * anything to it.
426 * In this case, l->fixup_stage == 0.
427 */
428 pciirq |= 1 << l->irq;
429 #ifdef PCIINTR_DEBUG
430 printf("pciintr_link_fixup: PIRQ 0x%02x already "
431 "connected to IRQ %d\n", l->clink, l->irq);
432 #endif
433 continue;
434 }
435 /*
436 * Interrupt isn't connected. Attempt to assign it to an IRQ.
437 */
438 #ifdef PCIINTR_DEBUG
439 printf("pciintr_link_fixup: PIRQ 0x%02x not connected",
440 l->clink);
441 #endif
442 /*
443 * Just do the easy case now; we'll defer the harder ones
444 * to Stage 2.
445 */
446 if (pciintr_bitmap_count_irq(l->bitmap, &irq) == 1) {
447 l->irq = irq;
448 l->fixup_stage = 1;
449 pciirq |= 1 << irq;
450 #ifdef PCIINTR_DEBUG
451 printf(", assigning IRQ %d", l->irq);
452 #endif
453 }
454 #ifdef PCIINTR_DEBUG
455 printf("\n");
456 #endif
457 }
458
459 /*
460 * Stage 2: Attempt to connect PIRQs which we didn't
461 * connect in Stage 1.
462 */
463 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
464 l = SIMPLEQ_NEXT(l, list)) {
465 if (l->irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
466 continue;
467 if (pciintr_bitmap_find_lowest_irq(l->bitmap & pciirq,
468 &l->irq)) {
469 /*
470 * This IRQ is a valid PCI IRQ already
471 * connected to another PIRQ, and also an
472 * IRQ our PIRQ can use; connect it up!
473 */
474 l->fixup_stage = 2;
475 #ifdef PCIINTR_DEBUG
476 printf("pciintr_link_fixup (stage 2): "
477 "assigning IRQ %d to PIRQ 0x%02x\n",
478 l->irq, l->clink);
479 #endif
480 }
481 }
482
483 #ifdef PCIBIOS_IRQS_HINT
484 /*
485 * Stage 3: The worst case. I need configuration hint that
486 * user supplied a mask for the PCI irqs
487 */
488 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
489 l = SIMPLEQ_NEXT(l, list)) {
490 if (l->irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
491 continue;
492 if (pciintr_bitmap_find_lowest_irq(
493 l->bitmap & pcibios_irqs_hint, &l->irq)) {
494 l->fixup_stage = 3;
495 #ifdef PCIINTR_DEBUG
496 printf("pciintr_link_fixup (stage 3): "
497 "assigning IRQ %d to PIRQ 0x%02x\n",
498 l->irq, l->clink);
499 #endif
500 }
501 }
502 #endif /* PCIBIOS_IRQS_HINT */
503
504 return (0);
505 }
506
507 int
508 pciintr_link_route(pciirq)
509 u_int16_t *pciirq;
510 {
511 struct pciintr_link_map *l;
512 int rv = 0;
513
514 *pciirq = 0;
515
516 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
517 l = SIMPLEQ_NEXT(l, list)) {
518 if (l->fixup_stage == 0) {
519 if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
520 /* Appropriate interrupt was not found. */
521 #ifdef DIAGNOSTIC
522 printf("pciintr_link_route: "
523 "PIRQ 0x%02x: no IRQ, try "
524 "\"options PCIBIOS_IRQS_HINT=0x%04x\"\n",
525 l->clink,
526 /* suggest irq 9/10/11, if possible */
527 (l->bitmap & 0x0e00) ? (l->bitmap & 0x0e00)
528 : l->bitmap);
529 #endif
530 } else {
531 /* BIOS setting has no problem */
532 #ifdef PCIINTR_DEBUG
533 printf("pciintr_link_route: "
534 "route of PIRQ 0x%02x -> "
535 "IRQ %d preserved BIOS setting\n",
536 l->clink, l->irq);
537 #endif
538 *pciirq |= (1 << l->irq);
539 }
540 continue; /* nothing to do. */
541 }
542
543 if (pciintr_icu_set_intr(pciintr_icu_tag, pciintr_icu_handle,
544 l->clink, l->irq) != 0 ||
545 pciintr_icu_set_trigger(pciintr_icu_tag,
546 pciintr_icu_handle,
547 l->irq, IST_LEVEL) != 0) {
548 printf("pciintr_link_route: route of PIRQ 0x%02x -> "
549 "IRQ %d failed\n", l->clink, l->irq);
550 rv = 1;
551 } else {
552 /*
553 * Succssfully routed interrupt. Mark this as
554 * a PCI interrupt.
555 */
556 *pciirq |= (1 << l->irq);
557 }
558 }
559
560 return (rv);
561 }
562
563 int
564 pciintr_irq_release(pciirq)
565 u_int16_t *pciirq;
566 {
567 int i, bit;
568
569 for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
570 if ((*pciirq & bit) == 0)
571 (void) pciintr_icu_set_trigger(pciintr_icu_tag,
572 pciintr_icu_handle, i, IST_EDGE);
573 }
574
575 return (0);
576 }
577
578 int
579 pciintr_header_fixup(pc)
580 pci_chipset_tag_t pc;
581 {
582 PCIBIOS_PRINTV(("------------------------------------------\n"));
583 PCIBIOS_PRINTV((" device vendor product pin PIRQ IRQ stage\n"));
584 PCIBIOS_PRINTV(("------------------------------------------\n"));
585 pci_device_foreach(pc, pcibios_max_bus, pciintr_do_header_fixup);
586 PCIBIOS_PRINTV(("------------------------------------------\n"));
587
588 return (0);
589 }
590
591 void
592 pciintr_do_header_fixup(pc, tag)
593 pci_chipset_tag_t pc;
594 pcitag_t tag;
595 {
596 struct pcibios_intr_routing *pir;
597 struct pciintr_link_map *l;
598 int pin, irq, link;
599 int bus, device, function;
600 pcireg_t intr, id;
601
602 pci_decompose_tag(pc, tag, &bus, &device, &function);
603 id = pci_conf_read(pc, tag, PCI_ID_REG);
604
605 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
606 pin = PCI_INTERRUPT_PIN(intr);
607 irq = PCI_INTERRUPT_LINE(intr);
608
609 if (pin == 0) {
610 /*
611 * No interrupt used.
612 */
613 return;
614 }
615
616 pir = pciintr_pir_lookup(bus, device);
617 if (pir == NULL || (link = pir->linkmap[pin - 1].link) == 0) {
618 /*
619 * Interrupt not connected; no
620 * need to change.
621 */
622 return;
623 }
624
625 l = pciintr_link_lookup(link);
626 if (l == NULL) {
627 #ifdef PCIINTR_DEBUG
628 /*
629 * No link map entry.
630 * Probably pciintr_icu_getclink() or pciintr_icu_get_intr()
631 * was failed.
632 */
633 printf("pciintr_header_fixup: no entry for link 0x%02x "
634 "(%d:%d:%d:%c)\n", link, bus, device, function,
635 '@' + pin);
636 #endif
637 return;
638 }
639
640 #ifdef PCIBIOSVERBOSE
641 if (pcibiosverbose) {
642 printf("%03d:%02d:%d 0x%04x 0x%04x %c 0x%02x",
643 bus, device, function, PCI_VENDOR(id), PCI_PRODUCT(id),
644 '@' + pin, l->clink);
645 if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
646 printf(" -");
647 else
648 printf(" %3d", l->irq);
649 printf(" %d ", l->fixup_stage);
650 }
651 #endif
652
653 /*
654 * IRQs 14 and 15 are reserved for PCI IDE interrupts; don't muck
655 * with them.
656 */
657 if (irq == 14 || irq == 15) {
658 PCIBIOS_PRINTV((" WARNING: ignored\n"));
659 return;
660 }
661
662 if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
663 /* Appropriate interrupt was not found. */
664 if (pciintr_icu_tag == NULL &&
665 irq != 0 && irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
666 /*
667 * Do not print warning,
668 * if no compatible PCI ICU found,
669 * but the irq is already assigned by BIOS.
670 */
671 PCIBIOS_PRINTV(("\n"));
672 } else {
673 PCIBIOS_PRINTV((" WARNING: missing IRQ\n"));
674 }
675 return;
676 }
677
678 if (l->irq == irq) {
679 /* don't have to reconfigure */
680 PCIBIOS_PRINTV((" already assigned\n"));
681 return;
682 }
683
684 if (irq == 0 || irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
685 PCIBIOS_PRINTV((" fixed up\n"));
686 } else {
687 /* routed by BIOS, but inconsistent */
688 #ifdef PCIBIOS_INTR_FIXUP_FORCE
689 /* believe PCI IRQ Routing table */
690 PCIBIOS_PRINTV((" WARNING: overriding irq %d\n", irq));
691 #else
692 /* believe PCI Interrupt Configuration Register (default) */
693 PCIBIOS_PRINTV((" WARNING: preserving irq %d\n", irq));
694 return;
695 #endif
696 }
697
698 intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
699 intr |= (l->irq << PCI_INTERRUPT_LINE_SHIFT);
700 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
701 }
702
703 int
704 pci_intr_fixup(pc, iot, pciirq)
705 pci_chipset_tag_t pc;
706 bus_space_tag_t iot;
707 u_int16_t *pciirq;
708 {
709 const struct pciintr_icu_table *piit = NULL;
710 pcitag_t icutag;
711 pcireg_t icuid;
712
713 /*
714 * Attempt to initialize our PCI interrupt router. If
715 * the PIR Table is present in ROM, use the location
716 * specified by the PIR Table, and use the compat ID,
717 * if present. Otherwise, we have to look for the router
718 * ourselves (the PCI-ISA bridge).
719 */
720 if (pcibios_pir_header.signature != 0) {
721 icutag = pci_make_tag(pc, pcibios_pir_header.router_bus,
722 PIR_DEVFUNC_DEVICE(pcibios_pir_header.router_devfunc),
723 PIR_DEVFUNC_FUNCTION(pcibios_pir_header.router_devfunc));
724 icuid = pcibios_pir_header.compat_router;
725 if (icuid == 0 ||
726 (piit = pciintr_icu_lookup(icuid)) == NULL) {
727 /*
728 * No compat ID, or don't know the compat ID? Read
729 * it from the configuration header.
730 */
731 icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
732 }
733 if (piit == NULL)
734 piit = pciintr_icu_lookup(icuid);
735 } else {
736 int device, maxdevs = pci_bus_maxdevs(pc, 0);
737
738 /*
739 * Search configuration space for a known interrupt
740 * router.
741 */
742 for (device = 0; device < maxdevs; device++) {
743 icutag = pci_make_tag(pc, 0, device, 0);
744 icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
745
746 /* Invalid vendor ID value? */
747 if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
748 continue;
749 /* XXX Not invalid, but we've done this ~forever. */
750 if (PCI_VENDOR(icuid) == 0)
751 continue;
752
753 piit = pciintr_icu_lookup(icuid);
754 if (piit != NULL)
755 break;
756 }
757 }
758
759 if (piit == NULL) {
760 printf("pci_intr_fixup: no compatible PCI ICU found");
761 if (pcibios_pir_header.signature != 0 && icuid != 0)
762 printf(": ICU vendor 0x%04x product 0x%04x",
763 PCI_VENDOR(icuid), PCI_PRODUCT(icuid));
764 printf("\n");
765 #ifdef PCIBIOS_INTR_GUESS
766 if (pciintr_link_init())
767 return (-1); /* non-fatal */
768 if (pciintr_guess_irq())
769 return (-1); /* non-fatal */
770 if (pciintr_header_fixup(pc))
771 return (1); /* fatal */
772 return (0); /* success! */
773 #else
774 return (-1); /* non-fatal */
775 #endif
776 }
777
778 /*
779 * Initialize the PCI ICU.
780 */
781 if ((*piit->piit_init)(pc, iot, icutag, &pciintr_icu_tag,
782 &pciintr_icu_handle) != 0)
783 return (-1); /* non-fatal */
784
785 /*
786 * Initialize the PCI interrupt link map.
787 */
788 if (pciintr_link_init())
789 return (-1); /* non-fatal */
790
791 /*
792 * Fix up the link->IRQ mappings.
793 */
794 if (pciintr_link_fixup() != 0)
795 return (-1); /* non-fatal */
796
797 /*
798 * Now actually program the PCI ICU with the new
799 * routing information.
800 */
801 if (pciintr_link_route(pciirq) != 0)
802 return (1); /* fatal */
803
804 /*
805 * Now that we've routed all of the PIRQs, rewrite the PCI
806 * configuration headers to reflect the new mapping.
807 */
808 if (pciintr_header_fixup(pc) != 0)
809 return (1); /* fatal */
810
811 /*
812 * Free any unused PCI IRQs for ISA devices.
813 */
814 if (pciintr_irq_release(pciirq) != 0)
815 return (-1); /* non-fatal */
816
817 /*
818 * All done!
819 */
820 return (0); /* success! */
821 }
822