pci: Remove PC98 code
[dragonfly.git] / sys / bus / pci / i386 / pci_pir.c
1 /*-
2  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3  * Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
4  * Copyright (c) 2000, BSDi
5  * Copyright (c) 2004, John Baldwin <jhb@FreeBSD.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice unmodified, this list of conditions, and the following
13  *    disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  * __FBSDID("$FreeBSD: src/sys/i386/pci/pci_pir.c,v 1.120.2.1.4.1 2009/04/15 03:14:26 kensmith Exp $");
29  */
30
31 #include <sys/cdefs.h>
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/sysctl.h>
40 #include <vm/vm.h>
41 #include <vm/pmap.h>
42 #include <vm/vm_param.h>
43 #include <machine/md_var.h>
44 #include <bus/pci/pcivar.h>
45 #include <bus/pci/pcireg.h>
46 #include "pci_cfgreg.h"
47 #include <machine/segments.h>
48 #include <machine/pc/bios.h>
49
50 #define NUM_ISA_INTERRUPTS      16
51
52 /*
53  * A link device.  Loosely based on the ACPI PCI link device.  This doesn't
54  * try to support priorities for different ISA interrupts.
55  */
56 struct pci_link {
57         TAILQ_ENTRY(pci_link) pl_links;
58         uint8_t         pl_id;
59         uint8_t         pl_irq;
60         uint16_t        pl_irqmask;
61         int             pl_references;
62         int             pl_routed;
63 };
64
65 struct pci_link_lookup {
66         struct pci_link **pci_link_ptr;
67         int             bus;
68         int             device;
69         int             pin;
70 };
71
72 struct pci_dev_lookup {
73         uint8_t         link;
74         int             bus;
75         int             device;
76         int             pin;
77 };
78
79 typedef void pir_entry_handler(struct PIR_entry *entry,
80     struct PIR_intpin* intpin, void *arg);
81
82 static void     pci_print_irqmask(u_int16_t irqs);
83 static int      pci_pir_biosroute(int bus, int device, int func, int pin,
84                     int irq);
85 static int      pci_pir_choose_irq(struct pci_link *pci_link, int irqmask);
86 static void     pci_pir_create_links(struct PIR_entry *entry,
87                     struct PIR_intpin *intpin, void *arg);
88 static void     pci_pir_dump_links(void);
89 static struct pci_link *pci_pir_find_link(uint8_t link_id);
90 static void     pci_pir_find_link_handler(struct PIR_entry *entry,
91                     struct PIR_intpin *intpin, void *arg);
92 static void     pci_pir_initial_irqs(struct PIR_entry *entry,
93                     struct PIR_intpin *intpin, void *arg);
94 static void     pci_pir_parse(void);
95 static uint8_t  pci_pir_search_irq(int bus, int device, int pin);
96 static int      pci_pir_valid_irq(struct pci_link *pci_link, int irq);
97 static void     pci_pir_walk_table(pir_entry_handler *handler, void *arg);
98
99 static MALLOC_DEFINE(M_PIR, "$PIR", "$PIR structures");
100
101 static struct PIR_table *pci_route_table;
102 static device_t pir_device;
103 static int pci_route_count, pir_bios_irqs, pir_parsed;
104 static TAILQ_HEAD(, pci_link) pci_links;
105 static int pir_interrupt_weight[NUM_ISA_INTERRUPTS];
106
107 /* sysctl vars */
108 SYSCTL_DECL(_hw_pci);
109
110 /* XXX this likely should live in a header file */
111 /* IRQs 3, 4, 5, 6, 7, 9, 10, 11, 12, 14, 15 */
112 #define PCI_IRQ_OVERRIDE_MASK 0xdef8
113
114 static uint32_t pci_irq_override_mask = PCI_IRQ_OVERRIDE_MASK;
115 TUNABLE_INT("hw.pci.irq_override_mask", &pci_irq_override_mask);
116 SYSCTL_INT(_hw_pci, OID_AUTO, irq_override_mask, CTLFLAG_RD,
117     &pci_irq_override_mask, PCI_IRQ_OVERRIDE_MASK,
118     "Mask of allowed irqs to try to route when it has no good clue about\n"
119     "which irqs it should use.");
120
121 /*
122  * Look for the interrupt routing table.
123  *
124  * We use PCI BIOS's PIR table if it's available. $PIR is the standard way
125  * to do this.  Sadly, some machines are not standards conforming and have
126  * _PIR instead.  We shrug and cope by looking for both.
127  */
128 void
129 pci_pir_open(void)
130 {
131         struct PIR_table *pt;
132         uint32_t sigaddr;
133         int i;
134         uint8_t ck, *cv;
135
136         /* Don't try if we've already found a table. */
137         if (pci_route_table != NULL)
138                 return;
139
140         /* Look for $PIR and then _PIR. */
141         sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0);
142         if (sigaddr == 0)
143                 sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0);
144         if (sigaddr == 0)
145                 return;
146
147         /* If we found something, check the checksum and length. */
148         /* XXX - Use pmap_mapdev()? */
149         pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
150         if (pt->pt_header.ph_length <= sizeof(struct PIR_header))
151                 return;
152         for (cv = (u_int8_t *)pt, ck = 0, i = 0;
153              i < (pt->pt_header.ph_length); i++)
154                 ck += cv[i];
155         if (ck != 0)
156                 return;
157
158         /* Ok, we've got a valid table. */
159         pci_route_table = pt;
160         pci_route_count = (pt->pt_header.ph_length -
161             sizeof(struct PIR_header)) / 
162             sizeof(struct PIR_entry);
163 }
164
165 /*
166  * Find the pci_link structure for a given link ID.
167  */
168 static struct pci_link *
169 pci_pir_find_link(uint8_t link_id)
170 {
171         struct pci_link *pci_link;
172
173         TAILQ_FOREACH(pci_link, &pci_links, pl_links) {
174                 if (pci_link->pl_id == link_id)
175                         return (pci_link);
176         }
177         return (NULL);
178 }
179
180 /*
181  * Find the link device associated with a PCI device in the table.
182  */
183 static void
184 pci_pir_find_link_handler(struct PIR_entry *entry, struct PIR_intpin *intpin,
185     void *arg)
186 {
187         struct pci_link_lookup *lookup;
188
189         lookup = (struct pci_link_lookup *)arg;
190         if (entry->pe_bus == lookup->bus &&
191             entry->pe_device == lookup->device &&
192             intpin - entry->pe_intpin == lookup->pin)
193                 *lookup->pci_link_ptr = pci_pir_find_link(intpin->link);
194 }
195
196 /*
197  * Check to see if a possible IRQ setting is valid.
198  */
199 static int
200 pci_pir_valid_irq(struct pci_link *pci_link, int irq)
201 {
202
203         if (!PCI_INTERRUPT_VALID(irq))
204                 return (0);
205         return (pci_link->pl_irqmask & (1 << irq));
206 }
207
208 /*
209  * Walk the $PIR executing the worker function for each valid intpin entry
210  * in the table.  The handler is passed a pointer to both the entry and
211  * the intpin in the entry.
212  */
213 static void
214 pci_pir_walk_table(pir_entry_handler *handler, void *arg)
215 {
216         struct PIR_entry *entry;
217         struct PIR_intpin *intpin;
218         int i, pin;
219
220         entry = &pci_route_table->pt_entry[0];
221         for (i = 0; i < pci_route_count; i++, entry++) {
222                 intpin = &entry->pe_intpin[0];
223                 for (pin = 0; pin < 4; pin++, intpin++)
224                         if (intpin->link != 0)
225                                 handler(entry, intpin, arg);
226         }
227 }
228
229 static void
230 pci_pir_create_links(struct PIR_entry *entry, struct PIR_intpin *intpin,
231     void *arg)
232 {
233         struct pci_link *pci_link;
234
235         pci_link = pci_pir_find_link(intpin->link);
236         if (pci_link != NULL) {
237                 pci_link->pl_references++;
238                 if (intpin->irqs != pci_link->pl_irqmask) {
239                         if (bootverbose)
240                                 kprintf(
241         "$PIR: Entry %d.%d.INT%c has different mask for link %#x, merging\n",
242                                     entry->pe_bus, entry->pe_device,
243                                     (intpin - entry->pe_intpin) + 'A',
244                                     pci_link->pl_id);
245                         pci_link->pl_irqmask &= intpin->irqs;
246                 }
247         } else {
248                 pci_link = kmalloc(sizeof(struct pci_link), M_PIR, M_WAITOK);
249                 pci_link->pl_id = intpin->link;
250                 pci_link->pl_irqmask = intpin->irqs;
251                 pci_link->pl_irq = PCI_INVALID_IRQ;
252                 pci_link->pl_references = 1;
253                 pci_link->pl_routed = 0;
254                 TAILQ_INSERT_TAIL(&pci_links, pci_link, pl_links);
255         }
256 }
257
258 /*
259  * Look to see if any of the function on the PCI device at bus/device have
260  * an interrupt routed to intpin 'pin' by the BIOS.
261  */
262 static uint8_t
263 pci_pir_search_irq(int bus, int device, int pin)
264 {
265         uint32_t value;
266         uint8_t func, maxfunc;
267
268         /* See if we have a valid device at function 0. */
269         value = pci_cfgregread(bus, device, 0, PCIR_HDRTYPE, 1);
270         if ((value & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
271                 return (PCI_INVALID_IRQ);
272         if (value & PCIM_MFDEV)
273                 maxfunc = PCI_FUNCMAX;
274         else
275                 maxfunc = 0;
276
277         /* Scan all possible functions at this device. */
278         for (func = 0; func <= maxfunc; func++) {
279                 value = pci_cfgregread(bus, device, func, PCIR_DEVVENDOR, 4);
280                 if (value == 0xffffffff)
281                         continue;
282                 value = pci_cfgregread(bus, device, func, PCIR_INTPIN, 1);
283
284                 /*
285                  * See if it uses the pin in question.  Note that the passed
286                  * in pin uses 0 for A, .. 3 for D whereas the intpin
287                  * register uses 0 for no interrupt, 1 for A, .. 4 for D.
288                  */
289                 if (value != pin + 1)
290                         continue;
291                 value = pci_cfgregread(bus, device, func, PCIR_INTLINE, 1);
292                 if (bootverbose)
293                         kprintf(
294                 "$PIR: Found matching pin for %d.%d.INT%c at func %d: %d\n",
295                             bus, device, pin + 'A', func, value);
296                 if (value != PCI_INVALID_IRQ)
297                         return (value);
298         }
299         return (PCI_INVALID_IRQ);
300 }
301
302 /*
303  * Try to initialize IRQ based on this device's IRQ.
304  */
305 static void
306 pci_pir_initial_irqs(struct PIR_entry *entry, struct PIR_intpin *intpin,
307     void *arg)
308 {
309         struct pci_link *pci_link;
310         uint8_t irq, pin;
311
312         pin = intpin - entry->pe_intpin;
313         pci_link = pci_pir_find_link(intpin->link);
314         irq = pci_pir_search_irq(entry->pe_bus, entry->pe_device, pin);
315         if (irq == PCI_INVALID_IRQ || irq == pci_link->pl_irq)
316                 return;
317
318         /* Don't trust any BIOS IRQs greater than 15. */
319         if (irq >= NUM_ISA_INTERRUPTS) {
320                 kprintf(
321         "$PIR: Ignoring invalid BIOS IRQ %d from %d.%d.INT%c for link %#x\n",
322                     irq, entry->pe_bus, entry->pe_device, pin + 'A',
323                     pci_link->pl_id);
324                 return;
325         }
326
327         /*
328          * If we don't have an IRQ for this link yet, then we trust the
329          * BIOS, even if it seems invalid from the $PIR entries.
330          */
331         if (pci_link->pl_irq == PCI_INVALID_IRQ) {
332                 if (!pci_pir_valid_irq(pci_link, irq))
333                         kprintf(
334         "$PIR: Using invalid BIOS IRQ %d from %d.%d.INT%c for link %#x\n",
335                             irq, entry->pe_bus, entry->pe_device, pin + 'A',
336                             pci_link->pl_id);
337                 pci_link->pl_irq = irq;
338                 pci_link->pl_routed = 1;
339                 return;
340         }
341
342         /*
343          * We have an IRQ and it doesn't match the current IRQ for this
344          * link.  If the new IRQ is invalid, then warn about it and ignore
345          * it.  If the old IRQ is invalid and the new IRQ is valid, then
346          * prefer the new IRQ instead.  If both IRQs are valid, then just
347          * use the first one.  Note that if we ever get into this situation
348          * we are having to guess which setting the BIOS actually routed.
349          * Perhaps we should just give up instead.
350          */
351         if (!pci_pir_valid_irq(pci_link, irq)) {
352                 kprintf(
353                 "$PIR: BIOS IRQ %d for %d.%d.INT%c is not valid for link %#x\n",
354                     irq, entry->pe_bus, entry->pe_device, pin + 'A',
355                     pci_link->pl_id);
356         } else if (!pci_pir_valid_irq(pci_link, pci_link->pl_irq)) {
357                 kprintf(
358 "$PIR: Preferring valid BIOS IRQ %d from %d.%d.INT%c for link %#x to IRQ %d\n", 
359                     irq, entry->pe_bus, entry->pe_device, pin + 'A',
360                     pci_link->pl_id, pci_link->pl_irq);
361                 pci_link->pl_irq = irq;
362                 pci_link->pl_routed = 1;
363         } else
364                 kprintf(
365         "$PIR: BIOS IRQ %d for %d.%d.INT%c does not match link %#x irq %d\n",
366                     irq, entry->pe_bus, entry->pe_device, pin + 'A',
367                     pci_link->pl_id, pci_link->pl_irq);
368 }
369
370 /*
371  * Parse $PIR to enumerate link devices and attempt to determine their
372  * initial state.  This could perhaps be cleaner if we had drivers for the
373  * various interrupt routers as they could read the initial IRQ for each
374  * link.
375  */
376 static void
377 pci_pir_parse(void)
378 {
379         char tunable_buffer[64];
380         struct pci_link *pci_link;
381         int i, irq;
382
383         /* Only parse once. */
384         if (pir_parsed)
385                 return;
386         pir_parsed = 1;
387
388         /* Enumerate link devices. */
389         TAILQ_INIT(&pci_links);
390         pci_pir_walk_table(pci_pir_create_links, NULL);
391         if (bootverbose) {
392                 kprintf("$PIR: Links after initial probe:\n");
393                 pci_pir_dump_links();
394         }
395
396         /*
397          * Check to see if the BIOS has already routed any of the links by
398          * checking each device connected to each link to see if it has a
399          * valid IRQ.
400          */
401         pci_pir_walk_table(pci_pir_initial_irqs, NULL);
402         if (bootverbose) {
403                 kprintf("$PIR: Links after initial IRQ discovery:\n");
404                 pci_pir_dump_links();
405         }
406
407         /*
408          * Allow the user to override the IRQ for a given link device.  We
409          * allow invalid IRQs to be specified but warn about them.  An IRQ
410          * of 255 or 0 clears any preset IRQ.
411          */
412         i = 0;
413         TAILQ_FOREACH(pci_link, &pci_links, pl_links) {
414                 ksnprintf(tunable_buffer, sizeof(tunable_buffer),
415                     "hw.pci.link.%#x.irq", pci_link->pl_id);
416                 if (kgetenv_int(tunable_buffer, &irq) == 0)
417                         continue;
418                 if (irq == 0)
419                         irq = PCI_INVALID_IRQ;
420                 if (irq != PCI_INVALID_IRQ &&
421                     !pci_pir_valid_irq(pci_link, irq) && bootverbose)
422                         kprintf(
423                 "$PIR: Warning, IRQ %d for link %#x is not listed as valid\n",
424                             irq, pci_link->pl_id);
425                 pci_link->pl_routed = 0;
426                 pci_link->pl_irq = irq;
427                 i = 1;
428         }
429         if (bootverbose && i) {
430                 kprintf("$PIR: Links after tunable overrides:\n");
431                 pci_pir_dump_links();
432         }
433
434         /*
435          * Build initial interrupt weights as well as bitmap of "known-good"
436          * IRQs that the BIOS has already used for PCI link devices.
437          */
438         TAILQ_FOREACH(pci_link, &pci_links, pl_links) {
439                 if (!PCI_INTERRUPT_VALID(pci_link->pl_irq))
440                         continue;
441                 pir_bios_irqs |= 1 << pci_link->pl_irq;
442                 pir_interrupt_weight[pci_link->pl_irq] +=
443                     pci_link->pl_references;
444         }
445         if (bootverbose) {
446                 kprintf("$PIR: IRQs used by BIOS: ");
447                 pci_print_irqmask(pir_bios_irqs);
448                 kprintf("\n");
449                 kprintf("$PIR: Interrupt Weights:\n[ ");
450                 for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
451                         kprintf(" %3d", i);
452                 kprintf(" ]\n[ ");
453                 for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
454                         kprintf(" %3d", pir_interrupt_weight[i]);
455                 kprintf(" ]\n");
456         }
457 }
458
459 /*
460  * Use the PCI BIOS to route an interrupt for a given device.
461  *
462  * Input:
463  * AX = PCIBIOS_ROUTE_INTERRUPT
464  * BH = bus
465  * BL = device [7:3] / function [2:0]
466  * CH = IRQ
467  * CL = Interrupt Pin (0x0A = A, ... 0x0D = D)
468  */
469 static int
470 pci_pir_biosroute(int bus, int device, int func, int pin, int irq)
471 {
472         struct bios_regs args;
473
474         args.eax = PCIBIOS_ROUTE_INTERRUPT;
475         args.ebx = (bus << 8) | (device << 3) | func;
476         args.ecx = (irq << 8) | (0xa + pin);
477         return (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)));
478 }
479
480
481 /*
482  * Route a PCI interrupt using a link device from the $PIR.
483  */
484 int
485 pci_pir_route_interrupt(int bus, int device, int func, int pin)
486 {
487         struct pci_link_lookup lookup;
488         struct pci_link *pci_link;
489         int error, irq;
490
491         if (pci_route_table == NULL)
492                 return (PCI_INVALID_IRQ);
493
494         /* Lookup link device for this PCI device/pin. */
495         pci_link = NULL;
496         lookup.bus = bus;
497         lookup.device = device;
498         lookup.pin = pin - 1;
499         lookup.pci_link_ptr = &pci_link;
500         pci_pir_walk_table(pci_pir_find_link_handler, &lookup);
501         if (pci_link == NULL) {
502                 kprintf("$PIR: No matching entry for %d.%d.INT%c\n", bus,
503                     device, pin - 1 + 'A');
504                 return (PCI_INVALID_IRQ);
505         }
506
507         /*
508          * Pick a new interrupt if we don't have one already.  We look
509          * for an interrupt from several different sets.  First, if
510          * this link only has one valid IRQ, use that.  Second, we
511          * check the set of PCI only interrupts from the $PIR.  Third,
512          * we check the set of known-good interrupts that the BIOS has
513          * already used.  Lastly, we check the "all possible valid
514          * IRQs" set.
515          */
516         if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) {
517                 if (pci_link->pl_irqmask != 0 && powerof2(pci_link->pl_irqmask))
518                         irq = ffs(pci_link->pl_irqmask) - 1;
519                 else
520                         irq = pci_pir_choose_irq(pci_link,
521                             pci_route_table->pt_header.ph_pci_irqs);
522                 if (!PCI_INTERRUPT_VALID(irq))
523                         irq = pci_pir_choose_irq(pci_link, pir_bios_irqs);
524                 if (!PCI_INTERRUPT_VALID(irq))
525                         irq = pci_pir_choose_irq(pci_link,
526                             pci_irq_override_mask);
527                 if (!PCI_INTERRUPT_VALID(irq)) {
528                         if (bootverbose)
529                                 kprintf(
530                         "$PIR: Failed to route interrupt for %d:%d INT%c\n",
531                                     bus, device, pin - 1 + 'A');
532                         return (PCI_INVALID_IRQ);
533                 }
534                 pci_link->pl_irq = irq;
535         }
536
537         /* Ask the BIOS to route this IRQ if we haven't done so already. */
538         if (!pci_link->pl_routed) {
539                 error = pci_pir_biosroute(bus, device, func, pin - 1,
540                     pci_link->pl_irq);
541
542                 /* Ignore errors when routing a unique interrupt. */
543                 if (error && !powerof2(pci_link->pl_irqmask)) {
544                         kprintf("$PIR: ROUTE_INTERRUPT failed.\n");
545                         return (PCI_INVALID_IRQ);
546                 }
547                 pci_link->pl_routed = 1;
548
549                 /* Ensure the interrupt is set to level/low trigger. */
550                 KASSERT(pir_device != NULL, ("missing pir device"));
551                 BUS_CONFIG_INTR(pir_device, pci_link->pl_irq,
552                     INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
553         }
554         if (bootverbose)
555                 kprintf("$PIR: %d:%d INT%c routed to irq %d\n", bus, device,
556                     pin - 1 + 'A', pci_link->pl_irq);
557         return (pci_link->pl_irq);
558 }
559
560 /*
561  * Try to pick an interrupt for the specified link from the interrupts
562  * set in the mask.
563  */
564 static int
565 pci_pir_choose_irq(struct pci_link *pci_link, int irqmask)
566 {
567         int i, irq, realmask;
568
569         /* XXX: Need to have a #define of known bad IRQs to also mask out? */
570         realmask = pci_link->pl_irqmask & irqmask;
571         if (realmask == 0)
572                 return (PCI_INVALID_IRQ);
573
574         /* Find IRQ with lowest weight. */
575         irq = PCI_INVALID_IRQ;
576         for (i = 0; i < NUM_ISA_INTERRUPTS; i++) {
577                 if (!(realmask & 1 << i))
578                         continue;
579                 if (irq == PCI_INVALID_IRQ ||
580                     pir_interrupt_weight[i] < pir_interrupt_weight[irq])
581                         irq = i;
582         }
583         if (bootverbose && PCI_INTERRUPT_VALID(irq)) {
584                 kprintf("$PIR: Found IRQ %d for link %#x from ", irq,
585                     pci_link->pl_id);
586                 pci_print_irqmask(realmask);
587                 kprintf("\n");
588         }
589         return (irq);
590 }
591
592 static void
593 pci_print_irqmask(u_int16_t irqs)
594 {
595         int i, first;
596
597         if (irqs == 0) {
598                 kprintf("none");
599                 return;
600         }
601         first = 1;
602         for (i = 0; i < 16; i++, irqs >>= 1)
603                 if (irqs & 1) {
604                         if (!first)
605                                 kprintf(" ");
606                         else
607                                 first = 0;
608                         kprintf("%d", i);
609                 }
610 }
611
612 /*
613  * Display link devices.
614  */
615 static void
616 pci_pir_dump_links(void)
617 {
618         struct pci_link *pci_link;
619
620         kprintf("Link  IRQ  Rtd  Ref  IRQs\n");
621         TAILQ_FOREACH(pci_link, &pci_links, pl_links) {
622                 kprintf("%#4x  %3d   %c   %3d  ", pci_link->pl_id,
623                     pci_link->pl_irq, pci_link->pl_routed ? 'Y' : 'N',
624                     pci_link->pl_references);
625                 pci_print_irqmask(pci_link->pl_irqmask);
626                 kprintf("\n");
627         }
628 }
629
630 /*
631  * See if any interrupts for a given PCI bus are routed in the PIR.  Don't
632  * even bother looking if the BIOS doesn't support routing anyways.  If we
633  * are probing a PCI-PCI bridge, then require_parse will be true and we should
634  * only succeed if a host-PCI bridge has already attached and parsed the PIR.
635  */
636 int
637 pci_pir_probe(int bus, int require_parse)
638 {
639         int i;
640         if (pci_route_table == NULL || (require_parse && !pir_parsed))
641                 return (0);
642         for (i = 0; i < pci_route_count; i++)
643                 if (pci_route_table->pt_entry[i].pe_bus == bus)
644                         return (1);
645         return (0);
646 }
647
648 /*
649  * The driver for the new-bus psuedo device pir0 for the $PIR table.
650  */
651
652 static int
653 pir_probe(device_t dev)
654 {
655         char buf[64];
656 kprintf("pir probe\n");
657         ksnprintf(buf, sizeof(buf), "PCI Interrupt Routing Table: %d Entries",
658             pci_route_count);
659         device_set_desc_copy(dev, buf);
660         return (0);
661 }
662
663 static int
664 pir_attach(device_t dev)
665 {
666
667         pci_pir_parse();
668         KASSERT(pir_device == NULL, ("Multiple pir devices"));
669         pir_device = dev;
670         return (0);
671 }
672
673 static void
674 pir_resume_find_device(struct PIR_entry *entry, struct PIR_intpin *intpin,
675     void *arg)
676 {
677         struct pci_dev_lookup *pd;
678
679         pd = (struct pci_dev_lookup *)arg;
680         if (intpin->link != pd->link || pd->bus != -1)
681                 return;
682         pd->bus = entry->pe_bus;
683         pd->device = entry->pe_device;
684         pd->pin = intpin - entry->pe_intpin;
685 }
686
687 static int
688 pir_resume(device_t dev)
689 {
690         struct pci_dev_lookup pd;
691         struct pci_link *pci_link;
692         int error;
693
694         /* Ask the BIOS to re-route each link that was already routed. */
695         TAILQ_FOREACH(pci_link, &pci_links, pl_links) {
696                 if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) {
697                         KASSERT(!pci_link->pl_routed,
698                             ("link %#x is routed but has invalid PCI IRQ",
699                             pci_link->pl_id));
700                         continue;
701                 }
702                 if (pci_link->pl_routed) {
703                         pd.bus = -1;
704                         pd.link = pci_link->pl_id;
705                         pci_pir_walk_table(pir_resume_find_device, &pd);
706                         KASSERT(pd.bus != -1,
707                 ("did not find matching entry for link %#x in the $PIR table",
708                             pci_link->pl_id));
709                         if (bootverbose)
710                                 device_printf(dev,
711                             "Using %d.%d.INT%c to route link %#x to IRQ %d\n",
712                                     pd.bus, pd.device, pd.pin + 'A',
713                                     pci_link->pl_id, pci_link->pl_irq);
714                         error = pci_pir_biosroute(pd.bus, pd.device, 0, pd.pin,
715                             pci_link->pl_irq);
716                         if (error)
717                                 device_printf(dev,
718                             "ROUTE_INTERRUPT on resume for link %#x failed.\n",
719                                     pci_link->pl_id);
720                 }
721         }
722         return (0);
723 }
724
725 static device_method_t pir_methods[] = {
726         /* Device interface */
727         DEVMETHOD(device_probe,         pir_probe),
728         DEVMETHOD(device_attach,        pir_attach),
729         DEVMETHOD(device_resume,        pir_resume),
730
731         { 0, 0 }
732 };
733
734 static driver_t pir_driver = {
735         "pir",
736         pir_methods,
737         1,
738 };
739
740 static devclass_t pir_devclass;
741
742 DRIVER_MODULE(pir, legacy, pir_driver, pir_devclass, 0, 0);