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