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/sysctl.h> 39 #include <vm/vm.h> 40 #include <vm/pmap.h> 41 #include <machine/md_var.h> 42 #include <dev/pci/pcivar.h> 43 #include <dev/pci/pcireg.h> 44 #include <machine/pci_cfgreg.h> 45 #include <machine/segments.h> 46 #include <machine/pc/bios.h> 47 48 #define NUM_ISA_INTERRUPTS 16 49 50 /* 51 * A link device. Loosely based on the ACPI PCI link device. This doesn't 52 * try to support priorities for different ISA interrupts. 53 */ 54 struct pci_link { 55 TAILQ_ENTRY(pci_link) pl_links; 56 uint8_t pl_id; 57 uint8_t pl_irq; 58 uint16_t pl_irqmask; 59 int pl_references; 60 int pl_routed; 61 }; 62 63 struct pci_link_lookup { 64 struct pci_link **pci_link_ptr; 65 int bus; 66 int device; 67 int pin; 68 }; 69 70 typedef void pir_entry_handler(struct PIR_entry *entry, 71 struct PIR_intpin* intpin, void *arg); 72 73 static void pci_print_irqmask(u_int16_t irqs); 74 static int pci_pir_biosroute(int bus, int device, int func, int pin, 75 int irq); 76 static int pci_pir_choose_irq(struct pci_link *pci_link, int irqmask); 77 static void pci_pir_create_links(struct PIR_entry *entry, 78 struct PIR_intpin *intpin, void *arg); 79 static void pci_pir_dump_links(void); 80 static struct pci_link *pci_pir_find_link(uint8_t link_id); 81 static void pci_pir_find_link_handler(struct PIR_entry *entry, 82 struct PIR_intpin *intpin, void *arg); 83 static void pci_pir_initial_irqs(struct PIR_entry *entry, 84 struct PIR_intpin *intpin, void *arg); 85 static void pci_pir_print_intpin(struct PIR_entry *entry, 86 struct PIR_intpin *intpin, void *arg); 87 static void pci_pir_print_table(void); 88 static uint8_t pci_pir_search_irq(int bus, int device, int pin); 89 static int pci_pir_valid_irq(struct pci_link *pci_link, int irq); 90 static void pci_pir_walk_table(pir_entry_handler *handler, void *arg); 91 92 MALLOC_DEFINE(M_PIR, "$PIR", "$PIR structures"); 93 94 static struct PIR_table *pci_route_table; 95 static int pci_route_count, pir_bios_irqs, pir_parsed; 96 static TAILQ_HEAD(, pci_link) pci_links; 97 static int pir_interrupt_weight[NUM_ISA_INTERRUPTS]; 98 99 /* sysctl vars */ 100 SYSCTL_DECL(_hw_pci); 101 102 #ifdef PC98 103 /* IRQs 3, 5, 7, 9, 10, 11, 12, 13 */ 104 #define PCI_IRQ_OVERRIDE_MASK 0x3e68 105 #else 106 /* IRQs 3, 4, 5, 6, 7, 9, 10, 11, 12, 14, 15 */ 107 #define PCI_IRQ_OVERRIDE_MASK 0xdef8 108 #endif 109 110 static uint32_t pci_irq_override_mask = PCI_IRQ_OVERRIDE_MASK; 111 TUNABLE_INT("hw.pci.irq_override_mask", &pci_irq_override_mask); 112 SYSCTL_INT(_hw_pci, OID_AUTO, irq_override_mask, CTLFLAG_RDTUN, 113 &pci_irq_override_mask, PCI_IRQ_OVERRIDE_MASK, 114 "Mask of allowed irqs to try to route when it has no good clue about\n" 115 "which irqs it should use."); 116 117 /* 118 * Look for the interrupt routing table. 119 * 120 * We use PCI BIOS's PIR table if it's available. $PIR is the standard way 121 * to do this. Sadly, some machines are not standards conforming and have 122 * _PIR instead. We shrug and cope by looking for both. 123 */ 124 void 125 pci_pir_open(void) 126 { 127 struct PIR_table *pt; 128 uint32_t sigaddr; 129 int i; 130 uint8_t ck, *cv; 131 132 /* Don't try if we've already found a table. */ 133 if (pci_route_table != NULL) 134 return; 135 136 /* Look for $PIR and then _PIR. */ 137 sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0); 138 if (sigaddr == 0) 139 sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0); 140 if (sigaddr == 0) 141 return; 142 143 /* If we found something, check the checksum and length. */ 144 /* XXX - Use pmap_mapdev()? */ 145 pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); 146 if (pt->pt_header.ph_length <= sizeof(struct PIR_header)) 147 return; 148 for (cv = (u_int8_t *)pt, ck = 0, i = 0; 149 i < (pt->pt_header.ph_length); i++) 150 ck += cv[i]; 151 if (ck != 0) 152 return; 153 154 /* Ok, we've got a valid table. */ 155 pci_route_table = pt; 156 pci_route_count = (pt->pt_header.ph_length - 157 sizeof(struct PIR_header)) / 158 sizeof(struct PIR_entry); 159 printf("Found $PIR table, %d entries at %p\n", 160 pci_route_count, pci_route_table); 161 if (bootverbose) 162 pci_pir_print_table(); 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 printf( 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 = malloc(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 printf( 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) 316 return; 317 if (pci_pir_valid_irq(pci_link, irq)) { 318 if (pci_link->pl_irq == PCI_INVALID_IRQ) 319 pci_link->pl_irq = irq; 320 else if (pci_link->pl_irq != irq) 321 printf( 322 "$PIR: BIOS IRQ %d for %d.%d.INT%c does not match link %#x irq %d\n", 323 irq, entry->pe_bus, entry->pe_device, pin + 'A', 324 pci_link->pl_id, pci_link->pl_irq); 325 } else 326 printf( 327 "$PIR: BIOS IRQ %d for %d.%d.INT%c is not valid for link %#x\n", 328 irq, entry->pe_bus, entry->pe_device, pin + 'A', 329 pci_link->pl_id); 330 } 331 332 /* 333 * Parse $PIR to enumerate link devices and attempt to determine their 334 * initial state. This could perhaps be cleaner if we had drivers for the 335 * various interrupt routers as they could read the initial IRQ for each 336 * link. 337 */ 338 void 339 pci_pir_parse(void) 340 { 341 char tunable_buffer[64]; 342 struct pci_link *pci_link; 343 int i, irq; 344 345 /* Only parse once. */ 346 if (pir_parsed) 347 return; 348 pir_parsed = 1; 349 350 /* Enumerate link devices. */ 351 TAILQ_INIT(&pci_links); 352 pci_pir_walk_table(pci_pir_create_links, NULL); 353 if (bootverbose) { 354 printf("$PIR: Links after initial probe:\n"); 355 pci_pir_dump_links(); 356 } 357 358 /* Check for unique IRQ masks. */ 359 TAILQ_FOREACH(pci_link, &pci_links, pl_links) { 360 if (pci_link->pl_irqmask != 0 && powerof2(pci_link->pl_irqmask)) 361 pci_link->pl_irq = ffs(pci_link->pl_irqmask) - 1; 362 } 363 364 /* 365 * Check to see if the BIOS has already routed any of the links by 366 * checking each device connected to each link to see if it has a 367 * valid IRQ. 368 */ 369 pci_pir_walk_table(pci_pir_initial_irqs, NULL); 370 if (bootverbose) { 371 printf("$PIR: Links after initial IRQ discovery:\n"); 372 pci_pir_dump_links(); 373 } 374 375 /* 376 * Allow the user to override the IRQ for a given link device as 377 * long as the override is valid or is 255 or 0 to clear a preset 378 * IRQ. 379 */ 380 i = 0; 381 TAILQ_FOREACH(pci_link, &pci_links, pl_links) { 382 snprintf(tunable_buffer, sizeof(tunable_buffer), 383 "hw.pci.link.%#x.irq", pci_link->pl_id); 384 if (getenv_int(tunable_buffer, &irq) == 0) 385 continue; 386 if (irq == 0) 387 irq = PCI_INVALID_IRQ; 388 if (irq == PCI_INVALID_IRQ || 389 pci_pir_valid_irq(pci_link, irq)) { 390 pci_link->pl_irq = irq; 391 i = 1; 392 } 393 } 394 if (bootverbose && i) { 395 printf("$PIR: Links after tunable overrides:\n"); 396 pci_pir_dump_links(); 397 } 398 399 /* 400 * Build initial interrupt weights as well as bitmap of "known-good" 401 * IRQs that the BIOS has already used for PCI link devices. 402 */ 403 TAILQ_FOREACH(pci_link, &pci_links, pl_links) { 404 if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) 405 continue; 406 pir_bios_irqs |= 1 << pci_link->pl_irq; 407 pir_interrupt_weight[pci_link->pl_irq] += 408 pci_link->pl_references; 409 } 410 if (bootverbose) { 411 printf("$PIR: IRQs used by BIOS: "); 412 pci_print_irqmask(pir_bios_irqs); 413 printf("\n"); 414 printf("$PIR: Interrupt Weights:\n[ "); 415 for (i = 0; i < NUM_ISA_INTERRUPTS; i++) 416 printf(" %3d", i); 417 printf(" ]\n[ "); 418 for (i = 0; i < NUM_ISA_INTERRUPTS; i++) 419 printf(" %3d", pir_interrupt_weight[i]); 420 printf(" ]\n"); 421 } 422 } 423 424 /* 425 * Use the PCI BIOS to route an interrupt for a given device. 426 * 427 * Input: 428 * AX = PCIBIOS_ROUTE_INTERRUPT 429 * BH = bus 430 * BL = device [7:3] / function [2:0] 431 * CH = IRQ 432 * CL = Interrupt Pin (0x0A = A, ... 0x0D = D) 433 */ 434 static int 435 pci_pir_biosroute(int bus, int device, int func, int pin, int irq) 436 { 437 struct bios_regs args; 438 439 args.eax = PCIBIOS_ROUTE_INTERRUPT; 440 args.ebx = (bus << 8) | (device << 3) | func; 441 args.ecx = (irq << 8) | (0xa + pin); 442 return (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))); 443 } 444 445 446 /* 447 * Route a PCI interrupt using a link device from the $PIR. 448 */ 449 int 450 pci_pir_route_interrupt(int bus, int device, int func, int pin) 451 { 452 struct pci_link_lookup lookup; 453 struct pci_link *pci_link; 454 int error, irq; 455 456 if (pci_route_table == NULL) 457 return (PCI_INVALID_IRQ); 458 459 /* Lookup link device for this PCI device/pin. */ 460 pci_link = NULL; 461 lookup.bus = bus; 462 lookup.device = device; 463 lookup.pin = pin - 1; 464 lookup.pci_link_ptr = &pci_link; 465 pci_pir_walk_table(pci_pir_find_link_handler, &lookup); 466 if (pci_link == NULL) { 467 printf("$PIR: No matching entry for %d.%d.INT%c\n", bus, 468 device, pin - 1 + 'A'); 469 return (PCI_INVALID_IRQ); 470 } 471 472 /* 473 * Pick a new interrupt if we don't have one already. We look for 474 * an interrupt from several different sets. First, we check the 475 * set of PCI only interrupts from the $PIR. Second, we check the 476 * set of known-good interrupts that the BIOS has already used. 477 * Lastly, we check the "all possible valid IRQs" set. 478 */ 479 if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) { 480 irq = pci_pir_choose_irq(pci_link, 481 pci_route_table->pt_header.ph_pci_irqs); 482 if (!PCI_INTERRUPT_VALID(irq)) 483 irq = pci_pir_choose_irq(pci_link, pir_bios_irqs); 484 if (!PCI_INTERRUPT_VALID(irq)) 485 irq = pci_pir_choose_irq(pci_link, 486 pci_irq_override_mask); 487 if (!PCI_INTERRUPT_VALID(irq)) { 488 if (bootverbose) 489 printf( 490 "$PIR: Failed to route interrupt for %d:%d INT%c\n", 491 bus, device, pin - 1 + 'A'); 492 return (PCI_INVALID_IRQ); 493 } 494 pci_link->pl_irq = irq; 495 } 496 497 /* Ask the BIOS to route this IRQ if we haven't done so already. */ 498 if (!pci_link->pl_routed) { 499 error = pci_pir_biosroute(bus, device, func, pin - 1, 500 pci_link->pl_irq); 501 502 /* Ignore errors when routing a unique interrupt. */ 503 if (error && !powerof2(pci_link->pl_irqmask)) { 504 printf("$PIR: ROUTE_INTERRUPT failed.\n"); 505 return (PCI_INVALID_IRQ); 506 } 507 pci_link->pl_routed = 1; 508 } 509 printf("$PIR: %d:%d INT%c routed to irq %d\n", bus, device, 510 pin - 1 + 'A', pci_link->pl_irq); 511 return (pci_link->pl_irq); 512 } 513 514 /* 515 * Try to pick an interrupt for the specified link from the interrupts 516 * set in the mask. 517 */ 518 static int 519 pci_pir_choose_irq(struct pci_link *pci_link, int irqmask) 520 { 521 int i, irq, realmask; 522 523 /* XXX: Need to have a #define of known bad IRQs to also mask out? */ 524 realmask = pci_link->pl_irqmask & irqmask; 525 if (realmask == 0) 526 return (PCI_INVALID_IRQ); 527 528 /* Find IRQ with lowest weight. */ 529 irq = PCI_INVALID_IRQ; 530 for (i = 0; i < NUM_ISA_INTERRUPTS; i++) { 531 if (!(realmask & 1 << i)) 532 continue; 533 if (irq == PCI_INVALID_IRQ || 534 pir_interrupt_weight[i] < pir_interrupt_weight[irq]) 535 irq = i; 536 } 537 if (bootverbose && PCI_INTERRUPT_VALID(irq)) { 538 printf("$PIR: Found IRQ %d for link %#x from ", irq, 539 pci_link->pl_id); 540 pci_print_irqmask(realmask); 541 printf("\n"); 542 } 543 return (irq); 544 } 545 546 static void 547 pci_print_irqmask(u_int16_t irqs) 548 { 549 int i, first; 550 551 if (irqs == 0) { 552 printf("none"); 553 return; 554 } 555 first = 1; 556 for (i = 0; i < 16; i++, irqs >>= 1) 557 if (irqs & 1) { 558 if (!first) 559 printf(" "); 560 else 561 first = 0; 562 printf("%d", i); 563 } 564 } 565 566 /* 567 * Dump the contents of a single intpin entry to the console. 568 */ 569 static void 570 pci_pir_print_intpin(struct PIR_entry *entry, struct PIR_intpin *intpin, 571 void *arg) 572 { 573 574 if (entry->pe_slot == 0) 575 printf("embedded "); 576 else 577 printf("slot %-3d ", entry->pe_slot); 578 printf(" %3d %3d %c 0x%02x ", entry->pe_bus, entry->pe_device, 579 intpin - entry->pe_intpin + 'A', intpin->link); 580 pci_print_irqmask(intpin->irqs); 581 printf("\n"); 582 } 583 584 /* 585 * Dump the contents of a PCI BIOS Interrupt Routing Table to the console. 586 */ 587 static void 588 pci_pir_print_table(void) 589 { 590 591 printf("PCI-Only Interrupts: "); 592 pci_print_irqmask(pci_route_table->pt_header.ph_pci_irqs); 593 printf("\nLocation Bus Device Pin Link IRQs\n"); 594 pci_pir_walk_table(pci_pir_print_intpin, NULL); 595 } 596 597 /* 598 * Display link devices. 599 */ 600 static void 601 pci_pir_dump_links(void) 602 { 603 struct pci_link *pci_link; 604 605 printf("Link IRQ Ref IRQs\n"); 606 TAILQ_FOREACH(pci_link, &pci_links, pl_links) { 607 printf("%#4x %3d %3d ", pci_link->pl_id, pci_link->pl_irq, 608 pci_link->pl_references); 609 pci_print_irqmask(pci_link->pl_irqmask); 610 printf("\n"); 611 } 612 } 613 614 /* 615 * See if any interrupts for a given PCI bus are routed in the PIR. Don't 616 * even bother looking if the BIOS doesn't support routing anyways. If we 617 * are probing a PCI-PCI bridge, then require_parse will be true and we should 618 * only succeed if a host-PCI bridge has already attached and parsed the PIR. 619 */ 620 int 621 pci_pir_probe(int bus, int require_parse) 622 { 623 int i; 624 625 if (pci_route_table == NULL || (require_parse && !pir_parsed)) 626 return (0); 627 for (i = 0; i < pci_route_count; i++) 628 if (pci_route_table->pt_entry[i].pe_bus == bus) 629 return (1); 630 return (0); 631 } 632