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