1 /* $NetBSD: pci_intr_fixup.c,v 1.4 2000/01/25 17:20:47 augustss 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 int old_irq; 96 SIMPLEQ_ENTRY(pciintr_link_map) list; 97 }; 98 99 pciintr_icu_tag_t pciintr_icu_tag; 100 pciintr_icu_handle_t pciintr_icu_handle; 101 102 struct pciintr_link_map *pciintr_link_lookup_pin 103 __P((struct pcibios_intr_routing *, int)); 104 struct pciintr_link_map *pciintr_link_lookup_link __P((int)); 105 struct pciintr_link_map *pciintr_link_alloc __P((struct pcibios_intr_routing *, 106 int)); 107 struct pcibios_intr_routing *pciintr_pir_lookup __P((int, int)); 108 int pciintr_link_init __P((void)); 109 int pciintr_link_fixup __P((void)); 110 int pciintr_link_route __P((u_int16_t *)); 111 int pciintr_irq_release __P((u_int16_t *)); 112 int pciintr_header_fixup __P((pci_chipset_tag_t)); 113 114 SIMPLEQ_HEAD(, pciintr_link_map) pciintr_link_map_list; 115 116 const struct pciintr_icu_table { 117 pci_vendor_id_t piit_vendor; 118 pci_product_id_t piit_product; 119 int (*piit_init) __P((pci_chipset_tag_t, 120 bus_space_tag_t, pcitag_t, pciintr_icu_tag_t *, 121 pciintr_icu_handle_t *)); 122 } pciintr_icu_table[] = { 123 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371MX, 124 piix_init }, 125 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_ISA, 126 piix_init }, 127 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371FB_ISA, 128 piix_init }, 129 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371SB_ISA, 130 piix_init }, 131 132 { PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C558, 133 opti82c558_init }, 134 { PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C700, 135 opti82c700_init }, 136 137 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586_ISA, 138 via82c586_init, }, 139 140 { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C503, 141 sis85c503_init }, 142 143 { 0, 0, 144 NULL }, 145 }; 146 147 const struct pciintr_icu_table *pciintr_icu_lookup __P((pcireg_t)); 148 149 const struct pciintr_icu_table * 150 pciintr_icu_lookup(id) 151 pcireg_t id; 152 { 153 const struct pciintr_icu_table *piit; 154 155 for (piit = pciintr_icu_table; 156 piit->piit_init != NULL; 157 piit++) { 158 if (PCI_VENDOR(id) == piit->piit_vendor && 159 PCI_PRODUCT(id) == piit->piit_product) 160 return (piit); 161 } 162 163 return (NULL); 164 } 165 166 struct pciintr_link_map * 167 pciintr_link_lookup_pin(pir, pin) 168 struct pcibios_intr_routing *pir; 169 int pin; 170 { 171 172 return (pciintr_link_lookup_link(pir->linkmap[pin].link)); 173 } 174 175 struct pciintr_link_map * 176 pciintr_link_lookup_link(link) 177 int link; 178 { 179 struct pciintr_link_map *l; 180 181 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL; 182 l = SIMPLEQ_NEXT(l, list)) { 183 if (l->link == link) 184 return (l); 185 } 186 187 return (NULL); 188 } 189 190 struct pciintr_link_map * 191 pciintr_link_alloc(pir, pin) 192 struct pcibios_intr_routing *pir; 193 int pin; 194 { 195 struct pciintr_link_map *l, *lstart; 196 197 l = malloc(sizeof(*l), M_DEVBUF, M_NOWAIT); 198 if (l == NULL) 199 panic("pciintr_link_alloc"); 200 201 memset(l, 0, sizeof(*l)); 202 203 l->link = pir->linkmap[pin].link; 204 l->bitmap = pir->linkmap[pin].bitmap; 205 206 lstart = SIMPLEQ_FIRST(&pciintr_link_map_list); 207 if (lstart == NULL || lstart->link < l->link) 208 SIMPLEQ_INSERT_TAIL(&pciintr_link_map_list, l, list); 209 else 210 SIMPLEQ_INSERT_HEAD(&pciintr_link_map_list, l, list); 211 212 return (l); 213 } 214 215 struct pcibios_intr_routing * 216 pciintr_pir_lookup(bus, device) 217 int bus, device; 218 { 219 struct pcibios_intr_routing *pir; 220 int entry; 221 222 if (pcibios_pir_table == NULL) 223 return (NULL); 224 225 for (entry = 0; entry < pcibios_pir_table_nentries; entry++) { 226 pir = &pcibios_pir_table[entry]; 227 if (pir->bus == bus && ((pir->device >> 3) & 0x1f) == device) 228 return (pir); 229 } 230 231 return (NULL); 232 } 233 234 int 235 pciintr_link_init() 236 { 237 int entry, pin, error, link, clink; 238 struct pcibios_intr_routing *pir; 239 struct pciintr_link_map *l; 240 241 if (pcibios_pir_table == NULL) { 242 /* No PIR table; can't do anything. */ 243 printf("pciintr_link_init: no PIR table\n"); 244 return (1); 245 } 246 247 error = 0; 248 SIMPLEQ_INIT(&pciintr_link_map_list); 249 250 for (entry = 0; entry < pcibios_pir_table_nentries; entry++) { 251 pir = &pcibios_pir_table[entry]; 252 for (pin = 0; pin < 4; pin++) { 253 link = pir->linkmap[pin].link; 254 if (link == 0) { 255 /* No connection for this pin. */ 256 continue; 257 } 258 259 /* 260 * Check the link value by asking the ICU for 261 * the canonical link value. 262 */ 263 if (pciintr_icu_getclink(pciintr_icu_tag, 264 pciintr_icu_handle, link, &clink) != 0) { 265 /* 266 * Table entry is bogus. Just ignore it. 267 */ 268 #ifdef PCIINTR_DEBUG 269 printf("pciintr_link_init: bad table entry: " 270 "bus %d device %d link 0x%02x\n", 271 pir->bus, (pir->device >> 3 & 0x1f), link); 272 #endif 273 continue; 274 } 275 276 /* 277 * Multiple devices may be wired to the same 278 * interrupt; check to see if we've seen this 279 * one already. If not, allocate a new link 280 * map entry and stuff it in the map. 281 */ 282 l = pciintr_link_lookup_pin(pir, pin); 283 if (l == NULL) 284 (void) pciintr_link_alloc(pir, pin); 285 } 286 } 287 288 return (error); 289 } 290 291 int 292 pciintr_link_fixup() 293 { 294 struct pciintr_link_map *l; 295 u_int16_t pciirq, bitmap; 296 int i, j, cnt, irq; 297 298 /* 299 * First stage: Attempt to connect PIRQs which aren't 300 * yet connected. 301 */ 302 pciirq = 0; 303 304 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL; 305 l = SIMPLEQ_NEXT(l, list)) { 306 /* 307 * Get the canonical link value for this entry. 308 */ 309 if (pciintr_icu_getclink(pciintr_icu_tag, pciintr_icu_handle, 310 l->link, &l->clink) != 0) { 311 /* 312 * ICU doesn't understand this link value. 313 */ 314 #ifdef PCIINTR_DEBUG 315 printf("pciintr_link_fixup: link 0x%02x invalid\n", 316 l->link); 317 #endif 318 l->clink = -1; 319 continue; 320 } 321 322 /* 323 * Determine if this PIRQ is mapped to an IRQ. 324 */ 325 if (pciintr_icu_get_intr(pciintr_icu_tag, pciintr_icu_handle, 326 l->clink, &irq) != 0) { 327 /* 328 * ICU doesn't understand this PIRQ value. 329 */ 330 l->clink = -1; 331 #ifdef PCIINTR_DEBUG 332 printf("pciintr_link_fixup: PIRQ %d invalid\n", 333 l->clink); 334 #endif 335 continue; 336 } 337 338 if (irq == 0xff) { 339 /* 340 * Interrupt isn't connected. Attempt to assign 341 * it to an IRQ. 342 */ 343 #ifdef PCIINTR_DEBUG 344 printf("pciintr_link_fixup: PIRQ %d not connected", 345 l->clink); 346 #endif 347 bitmap = l->bitmap; 348 for (i = 0, j = 0xff, cnt = 0; i < 16; i++) 349 if (bitmap & (1 << i)) 350 j = i, cnt++; 351 /* 352 * Just do the easy case now; we'll defer the 353 * harder ones to Stage 2. 354 */ 355 if (cnt == 1) { 356 l->irq = j; 357 l->old_irq = irq; 358 l->fixup_stage = 1; 359 pciirq |= 1 << j; 360 #ifdef PCIINTR_DEBUG 361 printf(", assigning IRQ %d", l->irq); 362 #endif 363 } 364 #ifdef PCIINTR_DEBUG 365 printf("\n"); 366 #endif 367 } else { 368 /* 369 * Interrupt is already connected. Don't do 370 * anything to it. 371 */ 372 l->irq = irq; 373 pciirq |= 1 << irq; 374 #ifdef PCIINTR_DEBUG 375 printf("pciintr_link_fixup: PIRQ %d already connected " 376 "to IRQ %d\n", l->clink, l->irq); 377 #endif 378 } 379 } 380 381 #ifdef PCIBIOS_IRQS 382 /* In case the user supplied a mask for the PCI irqs we use it. */ 383 pciirq = PCIBIOS_IRQS; 384 #endif 385 386 /* 387 * Stage 2: Attempt to connect PIRQs which we didn't 388 * connect in Stage 1. 389 */ 390 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL; 391 l = SIMPLEQ_NEXT(l, list)) { 392 if (l->irq == 0) { 393 bitmap = l->bitmap; 394 for (i = 0; i < 16; i++) { 395 if ((pciirq & (1 << i)) != 0 && 396 (bitmap & (1 << i)) != 0) { 397 /* 398 * This IRQ is a valid PCI 399 * IRQ already connected to 400 * another PIRQ, and also an 401 * IRQ our PIRQ can use; connect 402 * it up! 403 */ 404 l->irq = i; 405 l->old_irq = 0xff; 406 l->fixup_stage = 2; 407 #ifdef PCIINTR_DEBUG 408 printf("pciintr_link_fixup: assigning " 409 "IRQ %d to PIRQ %d\n", l->irq, 410 l->clink); 411 #endif 412 break; 413 } 414 } 415 } 416 } 417 418 /* 419 * Stage 3: Allow the user to specify interrupt routing 420 * information, overriding what we've done above. 421 */ 422 /* XXX Not implemented. */ 423 424 return (0); 425 } 426 427 int 428 pciintr_link_route(pciirq) 429 u_int16_t *pciirq; 430 { 431 struct pciintr_link_map *l; 432 int rv = 0; 433 434 *pciirq = 0; 435 436 for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL; 437 l = SIMPLEQ_NEXT(l, list)) { 438 if (pciintr_icu_set_intr(pciintr_icu_tag, pciintr_icu_handle, 439 l->clink, l->irq) != 0 || 440 pciintr_icu_set_trigger(pciintr_icu_tag, pciintr_icu_handle, 441 l->irq, IST_LEVEL) != 0) { 442 printf("pciintr_link_route: route of PIRQ %d -> IRQ %d" 443 " failed\n", l->clink, l->irq); 444 rv = 1; 445 } else { 446 /* 447 * Succssfully routed interrupt. Mark this as 448 * a PCI interrupt. 449 */ 450 *pciirq |= (1 << l->irq); 451 } 452 } 453 454 return (rv); 455 } 456 457 int 458 pciintr_irq_release(pciirq) 459 u_int16_t *pciirq; 460 { 461 int i; 462 463 for (i = 0; i < 16; i++) { 464 if ((*pciirq & (1 << i)) == 0) 465 (void) pciintr_icu_set_trigger(pciintr_icu_tag, 466 pciintr_icu_handle, i, IST_EDGE); 467 } 468 469 return (0); 470 } 471 472 int 473 pciintr_header_fixup(pc) 474 pci_chipset_tag_t pc; 475 { 476 const struct pci_quirkdata *qd; 477 struct pcibios_intr_routing *pir; 478 struct pciintr_link_map *l; 479 int pin, bus, device, function, maxdevs, nfuncs, irq, link; 480 pcireg_t id, bhlcr, intr; 481 pcitag_t tag; 482 483 #ifdef PCIBIOSVERBOSE 484 printf("--------------------------------------------\n"); 485 printf(" device vendor product pin PIRQ IRQ stage\n"); 486 printf("--------------------------------------------\n"); 487 #endif 488 489 for (bus = 0; bus <= pcibios_max_bus; bus++) { 490 maxdevs = pci_bus_maxdevs(pc, bus); 491 for (device = 0; device < maxdevs; device++) { 492 tag = pci_make_tag(pc, bus, device, 0); 493 id = pci_conf_read(pc, tag, PCI_ID_REG); 494 495 /* Invalid vendor ID value? */ 496 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 497 continue; 498 /* XXX Not invalid, but we've done this ~forever. */ 499 if (PCI_VENDOR(id) == 0) 500 continue; 501 502 qd = pci_lookup_quirkdata(PCI_VENDOR(id), 503 PCI_PRODUCT(id)); 504 505 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 506 if (PCI_HDRTYPE_MULTIFN(bhlcr) || 507 (qd != NULL && 508 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)) 509 nfuncs = 8; 510 else 511 nfuncs = 1; 512 513 for (function = 0; function < nfuncs; function++) { 514 tag = pci_make_tag(pc, bus, device, function); 515 id = pci_conf_read(pc, tag, PCI_ID_REG); 516 intr = pci_conf_read(pc, tag, 517 PCI_INTERRUPT_REG); 518 519 /* Invalid vendor ID value? */ 520 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 521 continue; 522 /* 523 * XXX Not invalid, but we've done this 524 * ~forever. 525 */ 526 if (PCI_VENDOR(id) == 0) 527 continue; 528 529 pin = PCI_INTERRUPT_PIN(intr); 530 irq = PCI_INTERRUPT_LINE(intr); 531 532 if (pin == 0) { 533 /* 534 * No interrupt used. 535 */ 536 continue; 537 } 538 539 pir = pciintr_pir_lookup(bus, device); 540 if (pir == NULL || 541 (link = pir->linkmap[pin - 1].link) == 0) { 542 /* 543 * Interrupt not connected; no 544 * need to change. 545 */ 546 continue; 547 } 548 549 l = pciintr_link_lookup_link(link); 550 if (l == NULL) { 551 /* 552 * No link map entry?! 553 */ 554 printf("pciintr_header_fixup: no entry " 555 "for link 0x%02x (%d:%d:%d:%c)\n", 556 link, bus, device, function, 557 '@' + pin); 558 continue; 559 } 560 561 /* 562 * IRQs 14 and 15 are reserved for 563 * PCI IDE interrupts; don't muck 564 * with them. 565 */ 566 if (irq == 14 || irq == 15) 567 continue; 568 569 #ifdef PCIBIOSVERBOSE 570 printf("%03d:%02d:%d 0x%04x 0x%04x %c " 571 "0x%02x %02d %d\n", 572 bus, device, function, 573 PCI_VENDOR(id), PCI_PRODUCT(id), 574 '@' + pin, l->clink, l->irq, 575 l->fixup_stage); 576 #endif 577 578 intr &= ~(PCI_INTERRUPT_LINE_MASK << 579 PCI_INTERRUPT_LINE_SHIFT); 580 intr |= (l->irq << PCI_INTERRUPT_LINE_SHIFT); 581 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, 582 intr); 583 } 584 } 585 } 586 587 #ifdef PCIBIOSVERBOSE 588 printf("--------------------------------------------\n"); 589 #endif 590 591 return (0); 592 } 593 594 int 595 pci_intr_fixup(pc, iot, pciirq) 596 pci_chipset_tag_t pc; 597 bus_space_tag_t iot; 598 u_int16_t *pciirq; 599 { 600 const struct pciintr_icu_table *piit = NULL; 601 pcitag_t icutag; 602 pcireg_t icuid; 603 604 /* 605 * Attempt to initialize our PCI interrupt router. If 606 * the PIR Table is present in ROM, use the location 607 * specified by the PIR Table, and use the compat ID, 608 * if present. Otherwise, we have to look for the router 609 * ourselves (the PCI-ISA bridge). 610 */ 611 if (pcibios_pir_header.signature != 0) { 612 icutag = pci_make_tag(pc, pcibios_pir_header.router_bus, 613 (pcibios_pir_header.router_devfunc >> 3) & 0x1f, 614 pcibios_pir_header.router_devfunc & 7); 615 icuid = pcibios_pir_header.compat_router; 616 if (icuid == 0 || 617 (piit = pciintr_icu_lookup(icuid)) == NULL) { 618 /* 619 * No compat ID, or don't know the compat ID? Read 620 * it from the configuration header. 621 */ 622 icuid = pci_conf_read(pc, icutag, PCI_ID_REG); 623 } 624 if (piit == NULL) 625 piit = pciintr_icu_lookup(icuid); 626 } else { 627 int device, maxdevs = pci_bus_maxdevs(pc, 0); 628 629 /* 630 * Search configuration space for a known interrupt 631 * router. 632 */ 633 for (device = 0; device < maxdevs; device++) { 634 icutag = pci_make_tag(pc, 0, device, 0); 635 icuid = pci_conf_read(pc, icutag, PCI_ID_REG); 636 637 /* Invalid vendor ID value? */ 638 if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID) 639 continue; 640 /* XXX Not invalid, but we've done this ~forever. */ 641 if (PCI_VENDOR(icuid) == 0) 642 continue; 643 644 piit = pciintr_icu_lookup(icuid); 645 if (piit != NULL) 646 break; 647 } 648 } 649 650 if (piit == NULL) { 651 printf("pci_intr_fixup: no compatible PCI ICU found\n"); 652 return (-1); /* non-fatal */ 653 } 654 655 /* 656 * Initialize the PCI ICU. 657 */ 658 if ((*piit->piit_init)(pc, iot, icutag, &pciintr_icu_tag, 659 &pciintr_icu_handle) != 0) 660 return (-1); /* non-fatal */ 661 662 /* 663 * Initialize the PCI interrupt link map. 664 */ 665 if (pciintr_link_init()) 666 return (-1); /* non-fatal */ 667 668 /* 669 * Fix up the link->IRQ mappings. 670 */ 671 if (pciintr_link_fixup() != 0) 672 return (-1); /* non-fatal */ 673 674 /* 675 * Now actually program the PCI ICU with the new 676 * routing information. 677 */ 678 if (pciintr_link_route(pciirq) != 0) 679 return (1); /* fatal */ 680 681 /* 682 * Now that we've routed all of the PIRQs, rewrite the PCI 683 * configuration headers to reflect the new mapping. 684 */ 685 if (pciintr_header_fixup(pc) != 0) 686 return (1); /* fatal */ 687 688 /* 689 * Free any unused PCI IRQs for ISA devices. 690 */ 691 if (pciintr_irq_release(pciirq) != 0) 692 return (-1); /* non-fatal */ 693 694 /* 695 * All done! 696 */ 697 return (0); /* success! */ 698 } 699