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