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