1 /* $NetBSD: pcibios.c,v 1.19 2004/05/03 07:08:46 kochi 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 * Interface to the PCI BIOS and PCI Interrupt Routing table. 67 */ 68 69 #include <sys/cdefs.h> 70 __KERNEL_RCSID(0, "$NetBSD: pcibios.c,v 1.19 2004/05/03 07:08:46 kochi Exp $"); 71 72 #include "opt_pcibios.h" 73 74 #include <sys/param.h> 75 #include <sys/systm.h> 76 #include <sys/device.h> 77 #include <sys/malloc.h> 78 79 #include <dev/isa/isareg.h> 80 #include <machine/isa_machdep.h> 81 82 #include <dev/pci/pcireg.h> 83 #include <dev/pci/pcivar.h> 84 #include <dev/pci/pcidevs.h> 85 86 #include <i386/pci/pcibios.h> 87 #ifdef PCIBIOS_INTR_FIXUP 88 #include <i386/pci/pci_intr_fixup.h> 89 #endif 90 #ifdef PCIBIOS_BUS_FIXUP 91 #include <i386/pci/pci_bus_fixup.h> 92 #endif 93 #ifdef PCIBIOS_ADDR_FIXUP 94 #include <i386/pci/pci_addr_fixup.h> 95 #endif 96 97 #include <machine/bios32.h> 98 99 #ifdef PCIBIOSVERBOSE 100 int pcibiosverbose = 1; 101 #endif 102 103 int pcibios_present; 104 105 struct pcibios_pir_header pcibios_pir_header; 106 struct pcibios_intr_routing *pcibios_pir_table; 107 int pcibios_pir_table_nentries; 108 int pcibios_max_bus; 109 110 struct bios32_entry pcibios_entry; 111 112 void pcibios_pir_init(void); 113 114 int pcibios_get_status(u_int32_t *, u_int32_t *, u_int32_t *, 115 u_int32_t *, u_int32_t *, u_int32_t *, u_int32_t *); 116 int pcibios_get_intr_routing(struct pcibios_intr_routing *, 117 int *, u_int16_t *); 118 119 int pcibios_return_code(u_int16_t, const char *); 120 121 void pcibios_print_exclirq(void); 122 123 #ifdef PCIBIOS_LIBRETTO_FIXUP 124 /* for Libretto L2/L3 hack */ 125 static void pcibios_fixup_pir_table(void); 126 static void pcibios_fixup_pir_table_mask(struct pcibios_linkmap *); 127 128 struct pcibios_linkmap pir_mask[] = { 129 { 2, 0x0040 }, 130 { 7, 0x0080 }, 131 { 8, 0x0020 }, 132 { 0, 0x0000 } 133 }; 134 #endif 135 136 #ifdef PCIINTR_DEBUG 137 void pcibios_print_pir_table(void); 138 #endif 139 140 #define PCI_IRQ_TABLE_START 0xf0000 141 #define PCI_IRQ_TABLE_END 0xfffff 142 143 static void pci_bridge_hook(pci_chipset_tag_t, pcitag_t, void *); 144 struct pci_bridge_hook_arg { 145 void (*func)(pci_chipset_tag_t, pcitag_t, void *); 146 void *arg; 147 }; 148 149 void 150 pcibios_init() 151 { 152 struct bios32_entry_info ei; 153 u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2; 154 155 if (bios32_service(BIOS32_MAKESIG('$', 'P', 'C', 'I'), 156 &pcibios_entry, &ei) == 0) { 157 /* 158 * No PCI BIOS found; will fall back on old 159 * mechanism. 160 */ 161 return; 162 } 163 164 /* 165 * We've located the PCI BIOS service; get some information 166 * about it. 167 */ 168 if (pcibios_get_status(&rev_maj, &rev_min, &mech1, &mech2, 169 &scmech1, &scmech2, &pcibios_max_bus) != PCIBIOS_SUCCESS) { 170 /* 171 * We can't use the PCI BIOS; will fall back on old 172 * mechanism. 173 */ 174 return; 175 } 176 177 printf("PCI BIOS rev. %d.%d found at 0x%lx\n", rev_maj, rev_min >> 4, 178 ei.bei_entry); 179 #ifdef PCIBIOSVERBOSE 180 printf("pcibios: config mechanism %s%s, special cycles %s%s, " 181 "last bus %d\n", 182 mech1 ? "[1]" : "[x]", 183 mech2 ? "[2]" : "[x]", 184 scmech1 ? "[1]" : "[x]", 185 scmech2 ? "[2]" : "[x]", 186 pcibios_max_bus); 187 188 #endif 189 190 /* 191 * The PCI BIOS tells us the config mechanism; fill it in now 192 * so that pci_mode_detect() doesn't have to look for it. 193 */ 194 pci_mode = mech1 ? 1 : 2; 195 196 pcibios_present = 1; 197 198 /* 199 * Find the PCI IRQ Routing table. 200 */ 201 pcibios_pir_init(); 202 203 #ifdef PCIBIOS_INTR_FIXUP 204 if (pcibios_pir_table != NULL) { 205 int rv; 206 u_int16_t pciirq; 207 208 /* 209 * Fixup interrupt routing. 210 */ 211 rv = pci_intr_fixup(NULL, X86_BUS_SPACE_IO, &pciirq); 212 switch (rv) { 213 case -1: 214 /* Non-fatal error. */ 215 printf("Warning: unable to fix up PCI interrupt " 216 "routing\n"); 217 break; 218 219 case 1: 220 /* Fatal error. */ 221 panic("pcibios_init: interrupt fixup failed"); 222 break; 223 } 224 225 /* 226 * XXX Clear `pciirq' from the ISA interrupt allocation 227 * XXX mask. 228 */ 229 } 230 #endif 231 232 #ifdef PCIBIOS_BUS_FIXUP 233 pcibios_max_bus = pci_bus_fixup(NULL, 0); 234 #ifdef PCIBIOSVERBOSE 235 printf("PCI bus #%d is the last bus\n", pcibios_max_bus); 236 #endif 237 #endif 238 239 #ifdef PCIBIOS_ADDR_FIXUP 240 pci_addr_fixup(NULL, pcibios_max_bus); 241 #endif 242 } 243 244 void 245 pcibios_pir_init() 246 { 247 char *devinfo; 248 paddr_t pa; 249 caddr_t p; 250 unsigned char cksum; 251 u_int16_t tablesize; 252 u_int8_t rev_maj, rev_min; 253 int i; 254 255 for (pa = PCI_IRQ_TABLE_START; pa < PCI_IRQ_TABLE_END; pa += 16) { 256 p = (caddr_t)ISA_HOLE_VADDR(pa); 257 if (*(int *)p != BIOS32_MAKESIG('$', 'P', 'I', 'R')) { 258 /* 259 * XXX: Some laptops (Toshiba/Libretto L series) 260 * use _PIR instead of $PIR. So we try that too. 261 */ 262 if (*(int *)p != BIOS32_MAKESIG('_', 'P', 'I', 'R')) 263 continue; 264 } 265 266 rev_min = *(p + 4); 267 rev_maj = *(p + 5); 268 tablesize = *(u_int16_t *)(p + 6); 269 270 cksum = 0; 271 for (i = 0; i < tablesize; i++) 272 cksum += *(unsigned char *)(p + i); 273 274 printf("PCI IRQ Routing Table rev. %d.%d found at 0x%lx, " 275 "size %d bytes (%d entries)\n", rev_maj, rev_min, pa, 276 tablesize, (tablesize - 32) / 16); 277 278 if (cksum != 0) { 279 printf("pcibios_pir_init: bad IRQ table checksum\n"); 280 continue; 281 } 282 283 if (tablesize < 32 || (tablesize % 16) != 0) { 284 printf("pcibios_pir_init: bad IRQ table size\n"); 285 continue; 286 } 287 288 if (rev_maj != 1 || rev_min != 0) { 289 printf("pcibios_pir_init: unsupported IRQ table " 290 "version\n"); 291 continue; 292 } 293 294 /* 295 * We can handle this table! Make a copy of it. 296 */ 297 memcpy(&pcibios_pir_header, p, 32); 298 pcibios_pir_table = malloc(tablesize - 32, M_DEVBUF, 299 M_NOWAIT); 300 if (pcibios_pir_table == NULL) { 301 printf("pcibios_pir_init: no memory for $PIR\n"); 302 return; 303 } 304 memcpy(pcibios_pir_table, p + 32, tablesize - 32); 305 pcibios_pir_table_nentries = (tablesize - 32) / 16; 306 307 printf("PCI Interrupt Router at %03d:%02d:%01d", 308 pcibios_pir_header.router_bus, 309 PIR_DEVFUNC_DEVICE(pcibios_pir_header.router_devfunc), 310 PIR_DEVFUNC_FUNCTION(pcibios_pir_header.router_devfunc)); 311 if (pcibios_pir_header.compat_router != 0) { 312 devinfo = malloc(256, M_DEVBUF, M_NOWAIT); 313 if (devinfo) { 314 pci_devinfo(pcibios_pir_header.compat_router, 315 0, 0, devinfo, 256); 316 printf(" (%s compatible)", devinfo); 317 free(devinfo, M_DEVBUF); 318 } 319 } 320 printf("\n"); 321 pcibios_print_exclirq(); 322 323 #ifdef PCIBIOS_LIBRETTO_FIXUP 324 /* for Libretto L2/L3 hack */ 325 pcibios_fixup_pir_table(); 326 #endif 327 #ifdef PCIINTR_DEBUG 328 pcibios_print_pir_table(); 329 #endif 330 return; 331 } 332 333 /* 334 * If there was no PIR table found, try using the PCI BIOS 335 * Get Interrupt Routing call. 336 * 337 * XXX The interface to this call sucks; just allocate enough 338 * XXX room for 32 entries. 339 */ 340 pcibios_pir_table_nentries = 32; 341 pcibios_pir_table = malloc(pcibios_pir_table_nentries * 342 sizeof(*pcibios_pir_table), M_DEVBUF, M_NOWAIT); 343 if (pcibios_pir_table == NULL) { 344 printf("pcibios_pir_init: no memory for $PIR\n"); 345 return; 346 } 347 if (pcibios_get_intr_routing(pcibios_pir_table, 348 &pcibios_pir_table_nentries, 349 &pcibios_pir_header.exclusive_irq) != PCIBIOS_SUCCESS) { 350 printf("No PCI IRQ Routing information available.\n"); 351 free(pcibios_pir_table, M_DEVBUF); 352 pcibios_pir_table = NULL; 353 pcibios_pir_table_nentries = 0; 354 return; 355 } 356 printf("PCI BIOS has %d Interrupt Routing table entries\n", 357 pcibios_pir_table_nentries); 358 pcibios_print_exclirq(); 359 360 #ifdef PCIBIOS_LIBRETTO_FIXUP 361 /* for Libretto L2/L3 hack */ 362 pcibios_fixup_pir_table(); 363 #endif 364 #ifdef PCIINTR_DEBUG 365 pcibios_print_pir_table(); 366 #endif 367 } 368 369 int 370 pcibios_get_status(u_int32_t *rev_maj, u_int32_t *rev_min, 371 u_int32_t *mech1, u_int32_t *mech2, u_int32_t *scmech1, u_int32_t *scmech2, 372 u_int32_t *maxbus) 373 { 374 u_int16_t ax, bx, cx; 375 u_int32_t edx; 376 int rv; 377 378 __asm __volatile("lcall *(%%edi) ; \ 379 jc 1f ; \ 380 xor %%ah, %%ah ; \ 381 1:" 382 : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (edx) 383 : "0" (0xb101), "D" (&pcibios_entry)); 384 385 rv = pcibios_return_code(ax, "pcibios_get_status"); 386 if (rv != PCIBIOS_SUCCESS) 387 return (rv); 388 389 if (edx != BIOS32_MAKESIG('P', 'C', 'I', ' ')) 390 return (PCIBIOS_SERVICE_NOT_PRESENT); /* XXX */ 391 392 /* 393 * Fill in the various pieces if info we're looking for. 394 */ 395 *mech1 = ax & 1; 396 *mech2 = ax & (1 << 1); 397 *scmech1 = ax & (1 << 4); 398 *scmech2 = ax & (1 << 5); 399 *rev_maj = (bx >> 8) & 0xff; 400 *rev_min = bx & 0xff; 401 *maxbus = cx & 0xff; 402 403 return (PCIBIOS_SUCCESS); 404 } 405 406 int 407 pcibios_get_intr_routing(struct pcibios_intr_routing *table, 408 int *nentries, u_int16_t *exclirq) 409 { 410 u_int16_t ax, bx; 411 int rv; 412 struct { 413 u_int16_t size; 414 caddr_t offset; 415 u_int16_t segment; 416 } __attribute__((__packed__)) args; 417 418 args.size = *nentries * sizeof(*table); 419 args.offset = (caddr_t)table; 420 args.segment = GSEL(GDATA_SEL, SEL_KPL); 421 422 memset(table, 0, args.size); 423 424 __asm __volatile("lcall *(%%esi) ; \ 425 jc 1f ; \ 426 xor %%ah, %%ah ; \ 427 1: movw %w2, %%ds ; \ 428 movw %w2, %%es" 429 : "=a" (ax), "=b" (bx) 430 : "r" GSEL(GDATA_SEL, SEL_KPL), "0" (0xb10e), "1" (0), 431 "D" (&args), "S" (&pcibios_entry)); 432 433 rv = pcibios_return_code(ax, "pcibios_get_intr_routing"); 434 if (rv != PCIBIOS_SUCCESS) 435 return (rv); 436 437 *nentries = args.size / sizeof(*table); 438 *exclirq = bx; 439 440 return (PCIBIOS_SUCCESS); 441 } 442 443 int 444 pcibios_return_code(u_int16_t ax, const char *func) 445 { 446 const char *errstr; 447 int rv = ax >> 8; 448 449 switch (rv) { 450 case PCIBIOS_SUCCESS: 451 return (PCIBIOS_SUCCESS); 452 453 case PCIBIOS_SERVICE_NOT_PRESENT: 454 errstr = "service not present"; 455 break; 456 457 case PCIBIOS_FUNCTION_NOT_SUPPORTED: 458 errstr = "function not supported"; 459 break; 460 461 case PCIBIOS_BAD_VENDOR_ID: 462 errstr = "bad vendor ID"; 463 break; 464 465 case PCIBIOS_DEVICE_NOT_FOUND: 466 errstr = "device not found"; 467 break; 468 469 case PCIBIOS_BAD_REGISTER_NUMBER: 470 errstr = "bad register number"; 471 break; 472 473 case PCIBIOS_SET_FAILED: 474 errstr = "set failed"; 475 break; 476 477 case PCIBIOS_BUFFER_TOO_SMALL: 478 errstr = "buffer too small"; 479 break; 480 481 default: 482 printf("%s: unknown return code 0x%x\n", func, rv); 483 return (rv); 484 } 485 486 printf("%s: %s\n", func, errstr); 487 return (rv); 488 } 489 490 void 491 pcibios_print_exclirq() 492 { 493 int i; 494 495 if (pcibios_pir_header.exclusive_irq) { 496 printf("PCI Exclusive IRQs:"); 497 for (i = 0; i < 16; i++) { 498 if (pcibios_pir_header.exclusive_irq & (1 << i)) 499 printf(" %d", i); 500 } 501 printf("\n"); 502 } 503 } 504 505 #ifdef PCIBIOS_LIBRETTO_FIXUP 506 /* for Libretto L2/L3 hack */ 507 static void 508 pcibios_fixup_pir_table() 509 { 510 struct pcibios_linkmap *m; 511 512 for (m = pir_mask; m->link != 0; m++) 513 pcibios_fixup_pir_table_mask(m); 514 } 515 516 void 517 pcibios_fixup_pir_table_mask(mask) 518 struct pcibios_linkmap *mask; 519 { 520 int i, j; 521 522 for (i = 0; i < pcibios_pir_table_nentries; i++) { 523 for (j = 0; j < 4; j++) { 524 if (pcibios_pir_table[i].linkmap[j].link == mask->link) { 525 pcibios_pir_table[i].linkmap[j].bitmap 526 &= mask->bitmap; 527 } 528 } 529 } 530 } 531 #endif 532 533 #ifdef PCIINTR_DEBUG 534 void 535 pcibios_print_pir_table() 536 { 537 int i, j; 538 539 for (i = 0; i < pcibios_pir_table_nentries; i++) { 540 printf("PIR Entry %d:\n", i); 541 printf("\tBus: %d Device: %d\n", 542 pcibios_pir_table[i].bus, 543 PIR_DEVFUNC_DEVICE(pcibios_pir_table[i].device)); 544 for (j = 0; j < 4; j++) { 545 printf("\t\tINT%c: link 0x%02x bitmap 0x%04x\n", 546 'A' + j, 547 pcibios_pir_table[i].linkmap[j].link, 548 pcibios_pir_table[i].linkmap[j].bitmap); 549 } 550 } 551 } 552 #endif 553 554 void 555 pci_device_foreach(pci_chipset_tag_t pc, int maxbus, 556 void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *context) 557 { 558 pci_device_foreach_min(pc, 0, maxbus, func, context); 559 } 560 561 void 562 pci_device_foreach_min(pci_chipset_tag_t pc, int minbus, int maxbus, 563 void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *context) 564 { 565 const struct pci_quirkdata *qd; 566 int bus, device, function, maxdevs, nfuncs; 567 pcireg_t id, bhlcr; 568 pcitag_t tag; 569 570 for (bus = minbus; bus <= maxbus; bus++) { 571 maxdevs = pci_bus_maxdevs(pc, bus); 572 for (device = 0; device < maxdevs; device++) { 573 tag = pci_make_tag(pc, bus, device, 0); 574 id = pci_conf_read(pc, tag, PCI_ID_REG); 575 576 /* Invalid vendor ID value? */ 577 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 578 continue; 579 /* XXX Not invalid, but we've done this ~forever. */ 580 if (PCI_VENDOR(id) == 0) 581 continue; 582 583 qd = pci_lookup_quirkdata(PCI_VENDOR(id), 584 PCI_PRODUCT(id)); 585 586 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 587 if (PCI_HDRTYPE_MULTIFN(bhlcr) || 588 (qd != NULL && 589 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)) 590 nfuncs = 8; 591 else 592 nfuncs = 1; 593 594 for (function = 0; function < nfuncs; function++) { 595 tag = pci_make_tag(pc, bus, device, function); 596 id = pci_conf_read(pc, tag, PCI_ID_REG); 597 598 /* Invalid vendor ID value? */ 599 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 600 continue; 601 /* 602 * XXX Not invalid, but we've done this 603 * ~forever. 604 */ 605 if (PCI_VENDOR(id) == 0) 606 continue; 607 (*func)(pc, tag, context); 608 } 609 } 610 } 611 } 612 613 void 614 pci_bridge_foreach(pci_chipset_tag_t pc, int minbus, int maxbus, 615 void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *ctx) 616 { 617 struct pci_bridge_hook_arg bridge_hook; 618 619 bridge_hook.func = func; 620 bridge_hook.arg = ctx; 621 622 pci_device_foreach_min(pc, minbus, maxbus, pci_bridge_hook, 623 &bridge_hook); 624 } 625 626 void 627 pci_bridge_hook(pci_chipset_tag_t pc, pcitag_t tag, void *ctx) 628 { 629 struct pci_bridge_hook_arg *bridge_hook = (void *)ctx; 630 pcireg_t reg; 631 632 reg = pci_conf_read(pc, tag, PCI_CLASS_REG); 633 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE && 634 (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI || 635 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) { 636 (*bridge_hook->func)(pc, tag, bridge_hook->arg); 637 } 638 } 639