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