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