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