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