1 /* $OpenBSD: pcibios.c,v 1.48 2015/09/08 08:33:26 deraadt Exp $ */ 2 /* $NetBSD: pcibios.c,v 1.5 2000/08/01 05:23:59 uch Exp $ */ 3 4 /* 5 * Copyright (c) 2000 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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 /*- 30 * Copyright (c) 1999 The NetBSD Foundation, Inc. 31 * All rights reserved. 32 * 33 * This code is derived from software contributed to The NetBSD Foundation 34 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 35 * NASA Ames Research Center. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 56 * POSSIBILITY OF SUCH DAMAGE. 57 */ 58 /* 59 * Copyright (c) 1999, by UCHIYAMA Yasushi 60 * All rights reserved. 61 * 62 * Redistribution and use in source and binary forms, with or without 63 * modification, are permitted provided that the following conditions 64 * are met: 65 * 1. Redistributions of source code must retain the above copyright 66 * notice, this list of conditions and the following disclaimer. 67 * 2. The name of the developer may NOT be used to endorse or promote products 68 * derived from this software without specific prior written permission. 69 * 70 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 71 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 72 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 73 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 74 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 75 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 76 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 77 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 78 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 79 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 80 * SUCH DAMAGE. 81 */ 82 83 /* 84 * Interface to the PCI BIOS and PCI Interrupt Routing table. 85 */ 86 87 #include <sys/param.h> 88 #include <sys/systm.h> 89 #include <sys/device.h> 90 #include <sys/malloc.h> 91 92 #include <dev/isa/isareg.h> 93 #include <i386/isa/isa_machdep.h> 94 95 #include <dev/pci/pcireg.h> 96 #include <dev/pci/pcivar.h> 97 #include <dev/pci/pcidevs.h> 98 99 #include <i386/pci/pcibiosvar.h> 100 101 #include <machine/biosvar.h> 102 103 int pcibios_flags; 104 int pcibios_present; 105 106 struct pcibios_pir_header pcibios_pir_header; 107 struct pcibios_intr_routing *pcibios_pir_table; 108 int pcibios_pir_table_nentries; 109 int pcibios_flags = 0; 110 111 struct bios32_entry pcibios_entry; 112 struct bios32_entry_info pcibios_entry_info; 113 114 struct pcibios_intr_routing *pcibios_pir_init(struct pcibios_softc *); 115 116 int pcibios_get_status(struct pcibios_softc *, 117 u_int32_t *, u_int32_t *, u_int32_t *, 118 u_int32_t *, u_int32_t *, u_int32_t *, u_int32_t *); 119 int pcibios_get_intr_routing(struct pcibios_softc *, 120 struct pcibios_intr_routing *, int *, u_int16_t *); 121 122 int pcibios_return_code(struct pcibios_softc *, u_int16_t, const char *); 123 124 void pcibios_print_exclirq(struct pcibios_softc *); 125 void pcibios_print_pir_table(void); 126 127 #define PCI_IRQ_TABLE_START 0xf0000 128 #define PCI_IRQ_TABLE_END 0xfffff 129 130 struct cfdriver pcibios_cd = { 131 NULL, "pcibios", DV_DULL 132 }; 133 134 int pcibiosprobe(struct device *, void *, void *); 135 void pcibiosattach(struct device *, struct device *, void *); 136 137 struct cfattach pcibios_ca = { 138 sizeof(struct pcibios_softc), pcibiosprobe, pcibiosattach 139 }; 140 141 int 142 pcibiosprobe(struct device *parent, void *match, void *aux) 143 { 144 struct bios_attach_args *ba = aux; 145 u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2, maxbus; 146 int rv; 147 148 if (strcmp(ba->ba_name, "pcibios")) 149 return 0; 150 151 rv = bios32_service(PCIBIOS_SIGNATURE, &pcibios_entry, 152 &pcibios_entry_info); 153 154 PCIBIOS_PRINTV(("pcibiosprobe: 0x%hx:0x%x at 0x%x[0x%x]\n", 155 pcibios_entry.segment, pcibios_entry.offset, 156 pcibios_entry_info.bei_base, pcibios_entry_info.bei_size)); 157 158 return rv && 159 pcibios_get_status(NULL, &rev_maj, &rev_min, &mech1, &mech2, 160 &scmech1, &scmech2, &maxbus) == PCIBIOS_SUCCESS; 161 } 162 163 void 164 pcibiosattach(struct device *parent, struct device *self, void *aux) 165 { 166 struct pcibios_softc *sc = (struct pcibios_softc *)self; 167 u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2; 168 169 pcibios_flags = sc->sc_dev.dv_cfdata->cf_flags; 170 171 pcibios_get_status((struct pcibios_softc *)self, &rev_maj, 172 &rev_min, &mech1, &mech2, 173 &scmech1, &scmech2, &sc->max_bus); 174 175 printf(": rev %d.%d @ 0x%x/0x%x\n", 176 rev_maj, rev_min >> 4, pcibios_entry_info.bei_base, 177 pcibios_entry_info.bei_size); 178 179 PCIBIOS_PRINTV(("%s: config mechanism %s%s, special cycles %s%s, " 180 "last bus %d\n", sc->sc_dev.dv_xname, 181 mech1 ? "[1]" : "[x]", mech2 ? "[2]" : "[x]", 182 scmech1 ? "[1]" : "[x]", scmech2 ? "[2]" : "[x]", sc->max_bus)); 183 184 /* 185 * The PCI BIOS tells us the config mechanism; fill it in now 186 * so that pci_mode_detect() doesn't have to look for it. 187 */ 188 pci_mode = mech1 ? 1 : 2; 189 190 pcibios_present = 1; 191 192 /* 193 * Find the PCI IRQ Routing table. 194 */ 195 196 if (!(pcibios_flags & PCIBIOS_INTR_FIXUP) && 197 pcibios_pir_init((struct pcibios_softc *)self) != NULL) { 198 int rv; 199 200 /* 201 * Fixup interrupt routing. 202 */ 203 rv = pci_intr_fixup(sc, NULL, I386_BUS_SPACE_IO); 204 switch (rv) { 205 case -1: 206 /* Non-fatal error. */ 207 printf("%s: Warning, unable to fix up PCI interrupt " 208 "routing\n", sc->sc_dev.dv_xname); 209 break; 210 211 case 1: 212 /* Fatal error. */ 213 printf("%s: interrupt fixup failed\n", sc->sc_dev.dv_xname); 214 return; 215 } 216 217 /* 218 * XXX Clear `pciirq' from the ISA interrupt allocation 219 * XXX mask. 220 */ 221 } 222 223 if (!(pcibios_flags & PCIBIOS_BUS_FIXUP)) { 224 sc->max_bus = pci_bus_fixup(NULL, 0); 225 printf("%s: PCI bus #%d is the last bus\n", 226 sc->sc_dev.dv_xname, sc->max_bus); 227 } 228 229 if (!(pcibios_flags & PCIBIOS_ADDR_FIXUP)) 230 pci_addr_fixup(sc, NULL, sc->max_bus); 231 232 bios32_cleanup(); 233 } 234 235 struct pcibios_intr_routing * 236 pcibios_pir_init(struct pcibios_softc *sc) 237 { 238 paddr_t pa; 239 240 pcibios_pir_table = NULL; 241 for (pa = PCI_IRQ_TABLE_START; pa < PCI_IRQ_TABLE_END; pa += 16) { 242 u_int8_t *p, cksum; 243 struct pcibios_pir_header *pirh; 244 int i; 245 246 p = ISA_HOLE_VADDR(pa); 247 pirh = (struct pcibios_pir_header *)p; 248 /* 249 * Some laptops (such as the Toshiba Libretto L series) 250 * use _PIR instead of the standard $PIR for the signature 251 * so we check for that too. 252 */ 253 if (pirh->signature != BIOS32_MAKESIG('$', 'P', 'I', 'R') && 254 pirh->signature != BIOS32_MAKESIG('_', 'P', 'I', 'R')) 255 continue; 256 257 if (pirh->tablesize < sizeof(*pirh)) 258 continue; 259 260 cksum = 0; 261 for (i = 0; i < pirh->tablesize; i++) 262 cksum += p[i]; 263 264 printf("%s: PCI IRQ Routing Table rev %d.%d @ 0x%lx/%d " 265 "(%zd entries)\n", sc->sc_dev.dv_xname, 266 pirh->version >> 8, pirh->version & 0xff, pa, 267 pirh->tablesize, (pirh->tablesize - sizeof(*pirh)) / 16); 268 269 if (cksum != 0) { 270 printf("%s: bad IRQ table checksum\n", 271 sc->sc_dev.dv_xname); 272 continue; 273 } 274 275 if (pirh->tablesize % 16 != 0) { 276 printf("%s: bad IRQ table size\n", sc->sc_dev.dv_xname); 277 continue; 278 } 279 280 if (pirh->version != 0x0100) { 281 printf("%s: unsupported IRQ table version\n", 282 sc->sc_dev.dv_xname); 283 continue; 284 } 285 286 /* 287 * We can handle this table! Make a copy of it. 288 */ 289 pcibios_pir_header = *pirh; 290 pcibios_pir_table = 291 malloc(pirh->tablesize - sizeof(*pirh), M_DEVBUF, M_NOWAIT); 292 if (pcibios_pir_table == NULL) { 293 printf("%s: no memory for $PIR\n", sc->sc_dev.dv_xname); 294 return NULL; 295 } 296 bcopy(p + sizeof(*pirh), pcibios_pir_table, 297 pirh->tablesize - sizeof(*pirh)); 298 pcibios_pir_table_nentries = 299 (pirh->tablesize - sizeof(*pirh)) / 16; 300 301 } 302 303 /* 304 * If there was no PIR table found, try using the PCI BIOS 305 * Get Interrupt Routing call. 306 * 307 * XXX The interface to this call sucks; just allocate enough 308 * XXX room for 32 entries. 309 */ 310 if (pcibios_pir_table == NULL) { 311 312 pcibios_pir_table_nentries = 32; 313 pcibios_pir_table = mallocarray(pcibios_pir_table_nentries, 314 sizeof(*pcibios_pir_table), M_DEVBUF, M_NOWAIT); 315 if (pcibios_pir_table == NULL) { 316 printf("%s: no memory for $PIR\n", sc->sc_dev.dv_xname); 317 return NULL; 318 } 319 if (pcibios_get_intr_routing(sc, pcibios_pir_table, 320 &pcibios_pir_table_nentries, 321 &pcibios_pir_header.exclusive_irq) != PCIBIOS_SUCCESS) { 322 printf("%s: PCI IRQ Routing information unavailable.\n", 323 sc->sc_dev.dv_xname); 324 free(pcibios_pir_table, M_DEVBUF, 325 pcibios_pir_table_nentries * 326 sizeof(*pcibios_pir_table)); 327 pcibios_pir_table = NULL; 328 pcibios_pir_table_nentries = 0; 329 return NULL; 330 } 331 printf("%s: PCI BIOS has %d Interrupt Routing table entries\n", 332 sc->sc_dev.dv_xname, pcibios_pir_table_nentries); 333 } 334 335 pcibios_print_exclirq(sc); 336 if (pcibios_flags & PCIBIOS_INTRDEBUG) 337 pcibios_print_pir_table(); 338 return pcibios_pir_table; 339 } 340 341 int 342 pcibios_get_status(struct pcibios_softc *sc, u_int32_t *rev_maj, 343 u_int32_t *rev_min, u_int32_t *mech1, u_int32_t *mech2, u_int32_t *scmech1, 344 u_int32_t *scmech2, u_int32_t *maxbus) 345 { 346 u_int32_t ax, bx, cx, edx; 347 int rv; 348 349 __asm volatile("pushl %%es\n\t" 350 "pushl %%ds\n\t" 351 "movw 4(%%edi), %%cx\n\t" 352 "movl %%ecx, %%ds\n\t" 353 "lcall *%%cs:(%%edi)\n\t" 354 "pop %%ds\n\t" 355 "pop %%es\n\t" 356 "jc 1f\n\t" 357 "xor %%ah, %%ah\n" 358 "1:" 359 : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (edx) 360 : "0" (0xb101), "D" (&pcibios_entry) 361 : "cc", "memory"); 362 363 rv = pcibios_return_code(sc, ax, "pcibios_get_status"); 364 if (rv != PCIBIOS_SUCCESS) 365 return (rv); 366 367 if (edx != BIOS32_MAKESIG('P', 'C', 'I', ' ')) 368 return (PCIBIOS_SERVICE_NOT_PRESENT); /* XXX */ 369 370 /* 371 * Fill in the various pieces of info we're looking for. 372 */ 373 *mech1 = ax & 1; 374 *mech2 = ax & (1 << 1); 375 *scmech1 = ax & (1 << 4); 376 *scmech2 = ax & (1 << 5); 377 *rev_maj = (bx >> 8) & 0xff; 378 *rev_min = bx & 0xff; 379 *maxbus = cx & 0xff; 380 381 return (PCIBIOS_SUCCESS); 382 } 383 384 int 385 pcibios_get_intr_routing(struct pcibios_softc *sc, 386 struct pcibios_intr_routing *table, int *nentries, u_int16_t *exclirq) 387 { 388 u_int32_t ax, bx; 389 int rv; 390 struct { 391 u_int16_t size; 392 u_int32_t offset; 393 u_int16_t segment; 394 } __packed args; 395 396 args.size = *nentries * sizeof(*table); 397 args.offset = (u_int32_t)table; 398 args.segment = GSEL(GDATA_SEL, SEL_KPL); 399 400 memset(table, 0, args.size); 401 402 __asm volatile("pushl %%es\n\t" 403 "pushl %%ds\n\t" 404 "movw 4(%%esi), %%cx\n\t" 405 "movl %%ecx, %%ds\n\t" 406 "lcall *%%cs:(%%esi)\n\t" 407 "popl %%ds\n\t" 408 "popl %%es\n\t" 409 "jc 1f\n\t" 410 "xor %%ah, %%ah\n" 411 "1:\n" 412 : "=a" (ax), "=b" (bx) 413 : "0" (0xb10e), "1" (0), "D" (&args), "S" (&pcibios_entry) 414 : "%ecx", "%edx", "cc", "memory"); 415 416 rv = pcibios_return_code(sc, ax, "pcibios_get_intr_routing"); 417 if (rv != PCIBIOS_SUCCESS) 418 return (rv); 419 420 *nentries = args.size / sizeof(*table); 421 *exclirq |= bx; 422 423 return (PCIBIOS_SUCCESS); 424 } 425 426 int 427 pcibios_return_code(struct pcibios_softc *sc, u_int16_t ax, const char *func) 428 { 429 const char *errstr; 430 int rv = ax >> 8; 431 char *nam; 432 433 if (sc) 434 nam = sc->sc_dev.dv_xname; 435 else 436 nam = "pcibios0"; 437 438 switch (rv) { 439 case PCIBIOS_SUCCESS: 440 return (PCIBIOS_SUCCESS); 441 442 case PCIBIOS_SERVICE_NOT_PRESENT: 443 errstr = "service not present"; 444 break; 445 446 case PCIBIOS_FUNCTION_NOT_SUPPORTED: 447 errstr = "function not supported"; 448 break; 449 450 case PCIBIOS_BAD_VENDOR_ID: 451 errstr = "bad vendor ID"; 452 break; 453 454 case PCIBIOS_DEVICE_NOT_FOUND: 455 errstr = "device not found"; 456 break; 457 458 case PCIBIOS_BAD_REGISTER_NUMBER: 459 errstr = "bad register number"; 460 break; 461 462 case PCIBIOS_SET_FAILED: 463 errstr = "set failed"; 464 break; 465 466 case PCIBIOS_BUFFER_TOO_SMALL: 467 errstr = "buffer too small"; 468 break; 469 470 default: 471 printf("%s: %s - unknown return code 0x%x\n", 472 nam, func, rv); 473 return (rv); 474 } 475 476 printf("%s: %s - %s\n", nam, func, errstr); 477 return (rv); 478 } 479 480 void 481 pcibios_print_exclirq(struct pcibios_softc *sc) 482 { 483 int i; 484 485 if (pcibios_pir_header.exclusive_irq) { 486 printf("%s: PCI Exclusive IRQs:", sc->sc_dev.dv_xname); 487 for (i = 0; i < 16; i++) { 488 if (pcibios_pir_header.exclusive_irq & (1 << i)) 489 printf(" %d", i); 490 } 491 printf("\n"); 492 } 493 } 494 495 void 496 pcibios_print_pir_table(void) 497 { 498 int i, j; 499 500 for (i = 0; i < pcibios_pir_table_nentries; i++) { 501 printf("PIR Entry %d:\n", i); 502 printf("\tBus: %d Device: %d\n", 503 pcibios_pir_table[i].bus, 504 PIR_DEVFUNC_DEVICE(pcibios_pir_table[i].device)); 505 for (j = 0; j < 4; j++) { 506 printf("\t\tINT%c: link 0x%02x bitmap 0x%04x\n", 507 'A' + j, 508 pcibios_pir_table[i].linkmap[j].link, 509 pcibios_pir_table[i].linkmap[j].bitmap); 510 } 511 } 512 } 513 514 void 515 pci_device_foreach(struct pcibios_softc *sc, pci_chipset_tag_t pc, int maxbus, 516 void (*func)(struct pcibios_softc *, pci_chipset_tag_t, pcitag_t)) 517 { 518 const struct pci_quirkdata *qd; 519 int bus, device, function, maxdevs, nfuncs; 520 pcireg_t id, bhlcr; 521 pcitag_t tag; 522 523 for (bus = 0; bus <= maxbus; bus++) { 524 maxdevs = pci_bus_maxdevs(pc, bus); 525 for (device = 0; device < maxdevs; device++) { 526 tag = pci_make_tag(pc, bus, device, 0); 527 id = pci_conf_read(pc, tag, PCI_ID_REG); 528 529 /* Invalid vendor ID value? */ 530 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 531 continue; 532 /* XXX Not invalid, but we've done this ~forever. */ 533 if (PCI_VENDOR(id) == 0) 534 continue; 535 536 qd = pci_lookup_quirkdata(PCI_VENDOR(id), 537 PCI_PRODUCT(id)); 538 539 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 540 if (PCI_HDRTYPE_MULTIFN(bhlcr) || 541 (qd != NULL && 542 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)) 543 nfuncs = 8; 544 else 545 nfuncs = 1; 546 547 for (function = 0; function < nfuncs; function++) { 548 tag = pci_make_tag(pc, bus, device, function); 549 id = pci_conf_read(pc, tag, PCI_ID_REG); 550 551 /* Invalid vendor ID value? */ 552 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 553 continue; 554 /* 555 * XXX Not invalid, but we've done this 556 * ~forever. 557 */ 558 if (PCI_VENDOR(id) == 0) 559 continue; 560 (*func)(sc, pc, tag); 561 } 562 } 563 } 564 } 565