xref: /netbsd-src/sys/arch/i386/pci/pci_intr_fixup.c (revision 89c5a767f8fc7a4633b2d409966e2becbb98ff92)
1 /*	$NetBSD: pci_intr_fixup.c,v 1.4 2000/01/25 17:20:47 augustss 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 	int old_irq;
96 	SIMPLEQ_ENTRY(pciintr_link_map) list;
97 };
98 
99 pciintr_icu_tag_t pciintr_icu_tag;
100 pciintr_icu_handle_t pciintr_icu_handle;
101 
102 struct pciintr_link_map *pciintr_link_lookup_pin
103 	__P((struct pcibios_intr_routing *, int));
104 struct pciintr_link_map *pciintr_link_lookup_link __P((int));
105 struct pciintr_link_map *pciintr_link_alloc __P((struct pcibios_intr_routing *,
106 	int));
107 struct pcibios_intr_routing *pciintr_pir_lookup __P((int, int));
108 int	pciintr_link_init __P((void));
109 int	pciintr_link_fixup __P((void));
110 int	pciintr_link_route __P((u_int16_t *));
111 int	pciintr_irq_release __P((u_int16_t *));
112 int	pciintr_header_fixup __P((pci_chipset_tag_t));
113 
114 SIMPLEQ_HEAD(, pciintr_link_map) pciintr_link_map_list;
115 
116 const struct pciintr_icu_table {
117 	pci_vendor_id_t	piit_vendor;
118 	pci_product_id_t piit_product;
119 	int (*piit_init) __P((pci_chipset_tag_t,
120 		bus_space_tag_t, pcitag_t, pciintr_icu_tag_t *,
121 		pciintr_icu_handle_t *));
122 } pciintr_icu_table[] = {
123 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82371MX,
124 	  piix_init },
125 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82371AB_ISA,
126 	  piix_init },
127 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82371FB_ISA,
128 	  piix_init },
129 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82371SB_ISA,
130 	  piix_init },
131 
132 	{ PCI_VENDOR_OPTI,	PCI_PRODUCT_OPTI_82C558,
133 	  opti82c558_init },
134 	{ PCI_VENDOR_OPTI,	PCI_PRODUCT_OPTI_82C700,
135 	  opti82c700_init },
136 
137 	{ PCI_VENDOR_VIATECH,	PCI_PRODUCT_VIATECH_VT82C586_ISA,
138 	  via82c586_init, },
139 
140 	{ PCI_VENDOR_SIS,	PCI_PRODUCT_SIS_85C503,
141 	  sis85c503_init },
142 
143 	{ 0,			0,
144 	  NULL },
145 };
146 
147 const struct pciintr_icu_table *pciintr_icu_lookup __P((pcireg_t));
148 
149 const struct pciintr_icu_table *
150 pciintr_icu_lookup(id)
151 	pcireg_t id;
152 {
153 	const struct pciintr_icu_table *piit;
154 
155 	for (piit = pciintr_icu_table;
156 	     piit->piit_init != NULL;
157 	     piit++) {
158 		if (PCI_VENDOR(id) == piit->piit_vendor &&
159 		    PCI_PRODUCT(id) == piit->piit_product)
160 			return (piit);
161 	}
162 
163 	return (NULL);
164 }
165 
166 struct pciintr_link_map *
167 pciintr_link_lookup_pin(pir, pin)
168 	struct pcibios_intr_routing *pir;
169 	int pin;
170 {
171 
172 	return (pciintr_link_lookup_link(pir->linkmap[pin].link));
173 }
174 
175 struct pciintr_link_map *
176 pciintr_link_lookup_link(link)
177 	int link;
178 {
179 	struct pciintr_link_map *l;
180 
181 	for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
182 	     l = SIMPLEQ_NEXT(l, list)) {
183 		if (l->link == link)
184 			return (l);
185 	}
186 
187 	return (NULL);
188 }
189 
190 struct pciintr_link_map *
191 pciintr_link_alloc(pir, pin)
192 	struct pcibios_intr_routing *pir;
193 	int pin;
194 {
195 	struct pciintr_link_map *l, *lstart;
196 
197 	l = malloc(sizeof(*l), M_DEVBUF, M_NOWAIT);
198 	if (l == NULL)
199 		panic("pciintr_link_alloc");
200 
201 	memset(l, 0, sizeof(*l));
202 
203 	l->link = pir->linkmap[pin].link;
204 	l->bitmap = pir->linkmap[pin].bitmap;
205 
206 	lstart = SIMPLEQ_FIRST(&pciintr_link_map_list);
207 	if (lstart == NULL || lstart->link < l->link)
208 		SIMPLEQ_INSERT_TAIL(&pciintr_link_map_list, l, list);
209 	else
210 		SIMPLEQ_INSERT_HEAD(&pciintr_link_map_list, l, list);
211 
212 	return (l);
213 }
214 
215 struct pcibios_intr_routing *
216 pciintr_pir_lookup(bus, device)
217 	int bus, device;
218 {
219 	struct pcibios_intr_routing *pir;
220 	int entry;
221 
222 	if (pcibios_pir_table == NULL)
223 		return (NULL);
224 
225 	for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
226 		pir = &pcibios_pir_table[entry];
227 		if (pir->bus == bus && ((pir->device >> 3) & 0x1f) == device)
228 			return (pir);
229 	}
230 
231 	return (NULL);
232 }
233 
234 int
235 pciintr_link_init()
236 {
237 	int entry, pin, error, link, clink;
238 	struct pcibios_intr_routing *pir;
239 	struct pciintr_link_map *l;
240 
241 	if (pcibios_pir_table == NULL) {
242 		/* No PIR table; can't do anything. */
243 		printf("pciintr_link_init: no PIR table\n");
244 		return (1);
245 	}
246 
247 	error = 0;
248 	SIMPLEQ_INIT(&pciintr_link_map_list);
249 
250 	for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
251 		pir = &pcibios_pir_table[entry];
252 		for (pin = 0; pin < 4; pin++) {
253 			link = pir->linkmap[pin].link;
254 			if (link == 0) {
255 				/* No connection for this pin. */
256 				continue;
257 			}
258 
259 			/*
260 			 * Check the link value by asking the ICU for
261 			 * the canonical link value.
262 			 */
263 			if (pciintr_icu_getclink(pciintr_icu_tag,
264 			    pciintr_icu_handle, link, &clink) != 0) {
265 				/*
266 				 * Table entry is bogus.  Just ignore it.
267 				 */
268 #ifdef PCIINTR_DEBUG
269 				printf("pciintr_link_init: bad table entry: "
270 				    "bus %d device %d link 0x%02x\n",
271 				    pir->bus, (pir->device >> 3 & 0x1f), link);
272 #endif
273 				continue;
274 			}
275 
276 			/*
277 			 * Multiple devices may be wired to the same
278 			 * interrupt; check to see if we've seen this
279 			 * one already.  If not, allocate a new link
280 			 * map entry and stuff it in the map.
281 			 */
282 			l = pciintr_link_lookup_pin(pir, pin);
283 			if (l == NULL)
284 				(void) pciintr_link_alloc(pir, pin);
285 		}
286 	}
287 
288 	return (error);
289 }
290 
291 int
292 pciintr_link_fixup()
293 {
294 	struct pciintr_link_map *l;
295 	u_int16_t pciirq, bitmap;
296 	int i, j, cnt, irq;
297 
298 	/*
299 	 * First stage: Attempt to connect PIRQs which aren't
300 	 * yet connected.
301 	 */
302 	pciirq = 0;
303 
304 	for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
305 	     l = SIMPLEQ_NEXT(l, list)) {
306 		/*
307 		 * Get the canonical link value for this entry.
308 		 */
309 		if (pciintr_icu_getclink(pciintr_icu_tag, pciintr_icu_handle,
310 		    l->link, &l->clink) != 0) {
311 			/*
312 			 * ICU doesn't understand this link value.
313 			 */
314 #ifdef PCIINTR_DEBUG
315 			printf("pciintr_link_fixup: link 0x%02x invalid\n",
316 			    l->link);
317 #endif
318 			l->clink = -1;
319 			continue;
320 		}
321 
322 		/*
323 		 * Determine if this PIRQ is mapped to an IRQ.
324 		 */
325 		if (pciintr_icu_get_intr(pciintr_icu_tag, pciintr_icu_handle,
326 		    l->clink, &irq) != 0) {
327 			/*
328 			 * ICU doesn't understand this PIRQ value.
329 			 */
330 			l->clink = -1;
331 #ifdef PCIINTR_DEBUG
332 			printf("pciintr_link_fixup: PIRQ %d invalid\n",
333 			    l->clink);
334 #endif
335 			continue;
336 		}
337 
338 		if (irq == 0xff) {
339 			/*
340 			 * Interrupt isn't connected.  Attempt to assign
341 			 * it to an IRQ.
342 			 */
343 #ifdef PCIINTR_DEBUG
344 			printf("pciintr_link_fixup: PIRQ %d not connected",
345 			    l->clink);
346 #endif
347 			bitmap = l->bitmap;
348 			for (i = 0, j = 0xff, cnt = 0; i < 16; i++)
349 				if (bitmap & (1 << i))
350 					j = i, cnt++;
351 			/*
352 			 * Just do the easy case now; we'll defer the
353 			 * harder ones to Stage 2.
354 			 */
355 			if (cnt == 1) {
356 				l->irq = j;
357 				l->old_irq = irq;
358 				l->fixup_stage = 1;
359 				pciirq |= 1 << j;
360 #ifdef PCIINTR_DEBUG
361 				printf(", assigning IRQ %d", l->irq);
362 #endif
363 			}
364 #ifdef PCIINTR_DEBUG
365 			printf("\n");
366 #endif
367 		} else {
368 			/*
369 			 * Interrupt is already connected.  Don't do
370 			 * anything to it.
371 			 */
372 			l->irq = irq;
373 			pciirq |= 1 << irq;
374 #ifdef PCIINTR_DEBUG
375 			printf("pciintr_link_fixup: PIRQ %d already connected "
376 			    "to IRQ %d\n", l->clink, l->irq);
377 #endif
378 		}
379 	}
380 
381 #ifdef PCIBIOS_IRQS
382 	/* In case the user supplied a mask for the PCI irqs we use it. */
383 	pciirq = PCIBIOS_IRQS;
384 #endif
385 
386 	/*
387 	 * Stage 2: Attempt to connect PIRQs which we didn't
388 	 * connect in Stage 1.
389 	 */
390 	for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
391 	     l = SIMPLEQ_NEXT(l, list)) {
392 		if (l->irq == 0) {
393 			bitmap = l->bitmap;
394 			for (i = 0; i < 16; i++) {
395 				if ((pciirq & (1 << i)) != 0 &&
396 				    (bitmap & (1 << i)) != 0) {
397 					/*
398 					 * This IRQ is a valid PCI
399 					 * IRQ already connected to
400 					 * another PIRQ, and also an
401 					 * IRQ our PIRQ can use; connect
402 					 * it up!
403 					 */
404 					l->irq = i;
405 					l->old_irq = 0xff;
406 					l->fixup_stage = 2;
407 #ifdef PCIINTR_DEBUG
408 					printf("pciintr_link_fixup: assigning "
409 					    "IRQ %d to PIRQ %d\n", l->irq,
410 					    l->clink);
411 #endif
412 					break;
413 				}
414 			}
415 		}
416 	}
417 
418 	/*
419 	 * Stage 3: Allow the user to specify interrupt routing
420 	 * information, overriding what we've done above.
421 	 */
422 	/* XXX Not implemented. */
423 
424 	return (0);
425 }
426 
427 int
428 pciintr_link_route(pciirq)
429 	u_int16_t *pciirq;
430 {
431 	struct pciintr_link_map *l;
432 	int rv = 0;
433 
434 	*pciirq = 0;
435 
436 	for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
437 	     l = SIMPLEQ_NEXT(l, list)) {
438 		if (pciintr_icu_set_intr(pciintr_icu_tag, pciintr_icu_handle,
439 					 l->clink, l->irq) != 0 ||
440 		    pciintr_icu_set_trigger(pciintr_icu_tag, pciintr_icu_handle,
441 					    l->irq, IST_LEVEL) != 0) {
442 			printf("pciintr_link_route: route of PIRQ %d -> IRQ %d"
443 			    " failed\n", l->clink, l->irq);
444 			rv = 1;
445 		} else {
446 			/*
447 			 * Succssfully routed interrupt.  Mark this as
448 			 * a PCI interrupt.
449 			 */
450 			*pciirq |= (1 << l->irq);
451 		}
452 	}
453 
454 	return (rv);
455 }
456 
457 int
458 pciintr_irq_release(pciirq)
459 	u_int16_t *pciirq;
460 {
461 	int i;
462 
463 	for (i = 0; i < 16; i++) {
464 		if ((*pciirq & (1 << i)) == 0)
465 			(void) pciintr_icu_set_trigger(pciintr_icu_tag,
466 			    pciintr_icu_handle, i, IST_EDGE);
467 	}
468 
469 	return (0);
470 }
471 
472 int
473 pciintr_header_fixup(pc)
474 	pci_chipset_tag_t pc;
475 {
476 	const struct pci_quirkdata *qd;
477 	struct pcibios_intr_routing *pir;
478 	struct pciintr_link_map *l;
479 	int pin, bus, device, function, maxdevs, nfuncs, irq, link;
480 	pcireg_t id, bhlcr, intr;
481 	pcitag_t tag;
482 
483 #ifdef PCIBIOSVERBOSE
484 	printf("--------------------------------------------\n");
485 	printf("  device vendor product pin PIRQ   IRQ stage\n");
486 	printf("--------------------------------------------\n");
487 #endif
488 
489 	for (bus = 0; bus <= pcibios_max_bus; bus++) {
490 		maxdevs = pci_bus_maxdevs(pc, bus);
491 		for (device = 0; device < maxdevs; device++) {
492 			tag = pci_make_tag(pc, bus, device, 0);
493 			id = pci_conf_read(pc, tag, PCI_ID_REG);
494 
495 			/* Invalid vendor ID value? */
496 			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
497 				continue;
498 			/* XXX Not invalid, but we've done this ~forever. */
499 			if (PCI_VENDOR(id) == 0)
500 				continue;
501 
502 			qd = pci_lookup_quirkdata(PCI_VENDOR(id),
503 			    PCI_PRODUCT(id));
504 
505 			bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
506 			if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
507 			    (qd != NULL &&
508 			     (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
509 				nfuncs = 8;
510 			else
511 				nfuncs = 1;
512 
513 			for (function = 0; function < nfuncs; function++) {
514 				tag = pci_make_tag(pc, bus, device, function);
515 				id = pci_conf_read(pc, tag, PCI_ID_REG);
516 				intr = pci_conf_read(pc, tag,
517 				    PCI_INTERRUPT_REG);
518 
519 				/* Invalid vendor ID value? */
520 				if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
521 					continue;
522 				/*
523 				 * XXX Not invalid, but we've done this
524 				 * ~forever.
525 				 */
526 				if (PCI_VENDOR(id) == 0)
527 					continue;
528 
529 				pin = PCI_INTERRUPT_PIN(intr);
530 				irq = PCI_INTERRUPT_LINE(intr);
531 
532 				if (pin == 0) {
533 					/*
534 					 * No interrupt used.
535 					 */
536 					continue;
537 				}
538 
539 				pir = pciintr_pir_lookup(bus, device);
540 				if (pir == NULL ||
541 				    (link = pir->linkmap[pin - 1].link) == 0) {
542 					/*
543 					 * Interrupt not connected; no
544 					 * need to change.
545 					 */
546 					continue;
547 				}
548 
549 				l = pciintr_link_lookup_link(link);
550 				if (l == NULL) {
551 					/*
552 					 * No link map entry?!
553 					 */
554 					printf("pciintr_header_fixup: no entry "
555 					    "for link 0x%02x (%d:%d:%d:%c)\n",
556 					    link, bus, device, function,
557 					    '@' + pin);
558 					continue;
559 				}
560 
561 				/*
562 				 * IRQs 14 and 15 are reserved for
563 				 * PCI IDE interrupts; don't muck
564 				 * with them.
565 				 */
566 				if (irq == 14 || irq == 15)
567 					continue;
568 
569 #ifdef PCIBIOSVERBOSE
570 				printf("%03d:%02d:%d 0x%04x 0x%04x  %c   "
571 				    "0x%02x   %02d  %d\n",
572 				    bus, device, function,
573 				    PCI_VENDOR(id), PCI_PRODUCT(id),
574 				    '@' + pin, l->clink, l->irq,
575 				    l->fixup_stage);
576 #endif
577 
578 				intr &= ~(PCI_INTERRUPT_LINE_MASK <<
579 				    PCI_INTERRUPT_LINE_SHIFT);
580 				intr |= (l->irq << PCI_INTERRUPT_LINE_SHIFT);
581 				pci_conf_write(pc, tag, PCI_INTERRUPT_REG,
582 				    intr);
583 			}
584 		}
585 	}
586 
587 #ifdef PCIBIOSVERBOSE
588 	printf("--------------------------------------------\n");
589 #endif
590 
591 	return (0);
592 }
593 
594 int
595 pci_intr_fixup(pc, iot, pciirq)
596 	pci_chipset_tag_t pc;
597 	bus_space_tag_t iot;
598 	u_int16_t *pciirq;
599 {
600 	const struct pciintr_icu_table *piit = NULL;
601 	pcitag_t icutag;
602 	pcireg_t icuid;
603 
604 	/*
605 	 * Attempt to initialize our PCI interrupt router.  If
606 	 * the PIR Table is present in ROM, use the location
607 	 * specified by the PIR Table, and use the compat ID,
608 	 * if present.  Otherwise, we have to look for the router
609 	 * ourselves (the PCI-ISA bridge).
610 	 */
611 	if (pcibios_pir_header.signature != 0) {
612 		icutag = pci_make_tag(pc, pcibios_pir_header.router_bus,
613 		    (pcibios_pir_header.router_devfunc >> 3) & 0x1f,
614 		    pcibios_pir_header.router_devfunc & 7);
615 		icuid = pcibios_pir_header.compat_router;
616 		if (icuid == 0 ||
617 		    (piit = pciintr_icu_lookup(icuid)) == NULL) {
618 			/*
619 			 * No compat ID, or don't know the compat ID?  Read
620 			 * it from the configuration header.
621 			 */
622 			icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
623 		}
624 		if (piit == NULL)
625 			piit = pciintr_icu_lookup(icuid);
626 	} else {
627 		int device, maxdevs = pci_bus_maxdevs(pc, 0);
628 
629 		/*
630 		 * Search configuration space for a known interrupt
631 		 * router.
632 		 */
633 		for (device = 0; device < maxdevs; device++) {
634 			icutag = pci_make_tag(pc, 0, device, 0);
635 			icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
636 
637 			/* Invalid vendor ID value? */
638 			if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
639 				continue;
640 			/* XXX Not invalid, but we've done this ~forever. */
641 			if (PCI_VENDOR(icuid) == 0)
642 				continue;
643 
644 			piit = pciintr_icu_lookup(icuid);
645 			if (piit != NULL)
646 				break;
647 		}
648 	}
649 
650 	if (piit == NULL) {
651 		printf("pci_intr_fixup: no compatible PCI ICU found\n");
652 		return (-1);		/* non-fatal */
653 	}
654 
655 	/*
656 	 * Initialize the PCI ICU.
657 	 */
658 	if ((*piit->piit_init)(pc, iot, icutag, &pciintr_icu_tag,
659 	    &pciintr_icu_handle) != 0)
660 		return (-1);		/* non-fatal */
661 
662 	/*
663 	 * Initialize the PCI interrupt link map.
664 	 */
665 	if (pciintr_link_init())
666 		return (-1);		/* non-fatal */
667 
668 	/*
669 	 * Fix up the link->IRQ mappings.
670 	 */
671 	if (pciintr_link_fixup() != 0)
672 		return (-1);		/* non-fatal */
673 
674 	/*
675 	 * Now actually program the PCI ICU with the new
676 	 * routing information.
677 	 */
678 	if (pciintr_link_route(pciirq) != 0)
679 		return (1);		/* fatal */
680 
681 	/*
682 	 * Now that we've routed all of the PIRQs, rewrite the PCI
683 	 * configuration headers to reflect the new mapping.
684 	 */
685 	if (pciintr_header_fixup(pc) != 0)
686 		return (1);		/* fatal */
687 
688 	/*
689 	 * Free any unused PCI IRQs for ISA devices.
690 	 */
691 	if (pciintr_irq_release(pciirq) != 0)
692 		return (-1);		/* non-fatal */
693 
694 	/*
695 	 * All done!
696 	 */
697 	return (0);			/* success! */
698 }
699