1 /* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000, BSDi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * 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 BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> /* XXX trim includes */ 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/malloc.h> 38 #include <sys/lock.h> 39 #include <sys/mutex.h> 40 #include <sys/sysctl.h> 41 #include <vm/vm.h> 42 #include <vm/pmap.h> 43 #include <machine/md_var.h> 44 #include <dev/pci/pcivar.h> 45 #include <dev/pci/pcireg.h> 46 #include <isa/isavar.h> 47 #include <machine/pci_cfgreg.h> 48 #include <machine/segments.h> 49 #include <machine/pc/bios.h> 50 51 #include "pcib_if.h" 52 53 #define PRVERB(a) do { \ 54 if (bootverbose) \ 55 printf a ; \ 56 } while(0) 57 58 static int cfgmech; 59 static int devmax; 60 61 static int pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq); 62 static int pci_cfgintr_unique(struct PIR_entry *pe, int pin); 63 static int pci_cfgintr_linked(struct PIR_entry *pe, int pin); 64 static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin); 65 static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin); 66 67 static void pci_print_irqmask(u_int16_t irqs); 68 static void pci_print_route_table(struct PIR_table *prt, int size); 69 static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes); 70 static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 71 static int pcireg_cfgopen(void); 72 73 static struct PIR_table *pci_route_table; 74 static int pci_route_count; 75 76 static struct mtx pcicfg_mtx; 77 78 /* sysctl vars */ 79 SYSCTL_DECL(_hw_pci); 80 81 #ifdef PC98 82 #define PCI_IRQ_OVERRIDE_MASK 0x3e68 83 #else 84 #define PCI_IRQ_OVERRIDE_MASK 0xdef4 85 #endif 86 87 static uint32_t pci_irq_override_mask = PCI_IRQ_OVERRIDE_MASK; 88 TUNABLE_INT("hw.pci.irq_override_mask", &pci_irq_override_mask); 89 SYSCTL_INT(_hw_pci, OID_AUTO, irq_override_mask, CTLFLAG_RDTUN, 90 &pci_irq_override_mask, PCI_IRQ_OVERRIDE_MASK, 91 "Mask of allowed irqs to try to route when it has no good clue about\n" 92 "which irqs it should use."); 93 94 95 /* 96 * Some BIOS writers seem to want to ignore the spec and put 97 * 0 in the intline rather than 255 to indicate none. Some use 98 * numbers in the range 128-254 to indicate something strange and 99 * apparently undocumented anywhere. Assume these are completely bogus 100 * and map them to 255, which means "none". 101 */ 102 static __inline__ int 103 pci_i386_map_intline(int line) 104 { 105 if (line == 0 || line >= 128) 106 return (PCI_INVALID_IRQ); 107 return (line); 108 } 109 110 static u_int16_t 111 pcibios_get_version(void) 112 { 113 struct bios_regs args; 114 115 if (PCIbios.ventry == 0) { 116 PRVERB(("pcibios: No call entry point\n")); 117 return (0); 118 } 119 args.eax = PCIBIOS_BIOS_PRESENT; 120 if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { 121 PRVERB(("pcibios: BIOS_PRESENT call failed\n")); 122 return (0); 123 } 124 if (args.edx != 0x20494350) { 125 PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n")); 126 return (0); 127 } 128 return (args.ebx & 0xffff); 129 } 130 131 /* 132 * Initialise access to PCI configuration space 133 */ 134 int 135 pci_cfgregopen(void) 136 { 137 static int opened = 0; 138 u_long sigaddr; 139 static struct PIR_table *pt; 140 u_int16_t v; 141 u_int8_t ck, *cv; 142 int i; 143 144 if (opened) 145 return(1); 146 147 if (pcireg_cfgopen() == 0) 148 return(0); 149 150 v = pcibios_get_version(); 151 if (v > 0) 152 printf("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8, 153 v & 0xff); 154 155 /* 156 * Look for the interrupt routing table. 157 * 158 * We use PCI BIOS's PIR table if it's available $PIR is the 159 * standard way to do this. Sadly, some machines are not 160 * standards conforming and have _PIR instead. We shrug and cope 161 * by looking for both. 162 */ 163 if (pcibios_get_version() >= 0x0210 && pt == NULL) { 164 sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0); 165 if (sigaddr == 0) 166 sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0); 167 if (sigaddr != 0) { 168 pt = (struct PIR_table *)(uintptr_t) 169 BIOS_PADDRTOVADDR(sigaddr); 170 for (cv = (u_int8_t *)pt, ck = 0, i = 0; 171 i < (pt->pt_header.ph_length); i++) { 172 ck += cv[i]; 173 } 174 if (ck == 0 && pt->pt_header.ph_length > 175 sizeof(struct PIR_header)) { 176 pci_route_table = pt; 177 pci_route_count = (pt->pt_header.ph_length - 178 sizeof(struct PIR_header)) / 179 sizeof(struct PIR_entry); 180 printf("Using $PIR table, %d entries at %p\n", 181 pci_route_count, pci_route_table); 182 if (bootverbose) 183 pci_print_route_table(pci_route_table, 184 pci_route_count); 185 } 186 } 187 } 188 mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN); 189 opened = 1; 190 return(1); 191 } 192 193 /* 194 * Read configuration space register 195 */ 196 u_int32_t 197 pci_cfgregread(int bus, int slot, int func, int reg, int bytes) 198 { 199 uint32_t line; 200 201 /* 202 * Some BIOS writers seem to want to ignore the spec and put 203 * 0 in the intline rather than 255 to indicate none. The rest of 204 * the code uses 255 as an invalid IRQ. 205 */ 206 if (reg == PCIR_INTLINE && bytes == 1) { 207 line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1); 208 return (pci_i386_map_intline(line)); 209 } 210 return (pcireg_cfgread(bus, slot, func, reg, bytes)); 211 } 212 213 /* 214 * Write configuration space register 215 */ 216 void 217 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) 218 { 219 220 pcireg_cfgwrite(bus, slot, func, reg, data, bytes); 221 } 222 223 /* 224 * Route a PCI interrupt 225 */ 226 int 227 pci_cfgintr(int bus, int device, int pin, int oldirq) 228 { 229 struct PIR_entry *pe; 230 int i, irq; 231 struct bios_regs args; 232 u_int16_t v; 233 int already = 0; 234 int errok = 0; 235 236 v = pcibios_get_version(); 237 if (v < 0x0210) { 238 PRVERB(( 239 "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n", 240 (v & 0xff00) >> 8, v & 0xff)); 241 return (PCI_INVALID_IRQ); 242 } 243 if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) || 244 (pin < 1) || (pin > 4)) 245 return(PCI_INVALID_IRQ); 246 247 /* 248 * Scan the entry table for a contender 249 */ 250 for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; 251 i++, pe++) { 252 if ((bus != pe->pe_bus) || (device != pe->pe_device)) 253 continue; 254 /* 255 * A link of 0 means that this intpin is not connected to 256 * any other device's interrupt pins and is not connected to 257 * any of the Interrupt Router's interrupt pins, so we can't 258 * route it. 259 */ 260 if (pe->pe_intpin[pin - 1].link == 0) 261 continue; 262 263 if (pci_cfgintr_valid(pe, pin, oldirq)) { 264 printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus, 265 device, 'A' + pin - 1, oldirq); 266 return (oldirq); 267 } 268 269 /* 270 * We try to find a linked interrupt, then we look to see 271 * if the interrupt is uniquely routed, then we look for 272 * a virgin interrupt. The virgin interrupt should return 273 * an interrupt we can route, but if that fails, maybe we 274 * should try harder to route a different interrupt. 275 * However, experience has shown that that's rarely the 276 * failure mode we see. 277 */ 278 irq = pci_cfgintr_linked(pe, pin); 279 if (irq != PCI_INVALID_IRQ) 280 already = 1; 281 if (irq == PCI_INVALID_IRQ) { 282 irq = pci_cfgintr_unique(pe, pin); 283 if (irq != PCI_INVALID_IRQ) 284 errok = 1; 285 } 286 if (irq == PCI_INVALID_IRQ) 287 irq = pci_cfgintr_virgin(pe, pin); 288 if (irq == PCI_INVALID_IRQ) 289 break; 290 291 /* 292 * Ask the BIOS to route the interrupt. If we picked an 293 * interrupt that failed, we should really try other 294 * choices that the BIOS offers us. 295 * 296 * For uniquely routed interrupts, we need to try 297 * to route them on some machines. Yet other machines 298 * fail to route, so we have to pretend that in that 299 * case it worked. Isn't pc hardware fun? 300 * 301 * NOTE: if we want to whack hardware to do this, then 302 * I think the right way to do that would be to have 303 * bridge drivers that do this. I'm not sure that the 304 * $PIR table would be valid for those interrupt 305 * routers. 306 */ 307 args.eax = PCIBIOS_ROUTE_INTERRUPT; 308 args.ebx = (bus << 8) | (device << 3); 309 /* pin value is 0xa - 0xd */ 310 args.ecx = (irq << 8) | (0xa + pin - 1); 311 if (!already && 312 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)) && 313 !errok) { 314 PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n")); 315 return(PCI_INVALID_IRQ); 316 } 317 printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, 318 device, 'A' + pin - 1, irq); 319 return(irq); 320 } 321 322 PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, 323 device, 'A' + pin - 1)); 324 return(PCI_INVALID_IRQ); 325 } 326 327 /* 328 * Check to see if an existing IRQ setting is valid. 329 */ 330 static int 331 pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq) 332 { 333 uint32_t irqmask; 334 335 if (!PCI_INTERRUPT_VALID(irq)) 336 return (0); 337 irqmask = pe->pe_intpin[pin - 1].irqs; 338 if (irqmask & (1 << irq)) { 339 PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq)); 340 return (1); 341 } 342 return (0); 343 } 344 345 /* 346 * Look to see if the routing table claims this pin is uniquely routed. 347 */ 348 static int 349 pci_cfgintr_unique(struct PIR_entry *pe, int pin) 350 { 351 int irq; 352 uint32_t irqmask; 353 354 irqmask = pe->pe_intpin[pin - 1].irqs; 355 if (irqmask != 0 && powerof2(irqmask)) { 356 irq = ffs(irqmask) - 1; 357 PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq)); 358 return(irq); 359 } 360 return(PCI_INVALID_IRQ); 361 } 362 363 /* 364 * Look for another device which shares the same link byte and 365 * already has a unique IRQ, or which has had one routed already. 366 */ 367 static int 368 pci_cfgintr_linked(struct PIR_entry *pe, int pin) 369 { 370 struct PIR_entry *oe; 371 struct PIR_intpin *pi; 372 int i, j, irq; 373 374 /* 375 * Scan table slots. 376 */ 377 for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; 378 i++, oe++) { 379 /* scan interrupt pins */ 380 for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) { 381 382 /* don't look at the entry we're trying to match */ 383 if ((pe == oe) && (i == (pin - 1))) 384 continue; 385 /* compare link bytes */ 386 if (pi->link != pe->pe_intpin[pin - 1].link) 387 continue; 388 /* link destination mapped to a unique interrupt? */ 389 if (pi->irqs != 0 && powerof2(pi->irqs)) { 390 irq = ffs(pi->irqs) - 1; 391 PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n", 392 pi->link, irq)); 393 return(irq); 394 } 395 396 /* 397 * look for the real PCI device that matches this 398 * table entry 399 */ 400 irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, 401 j + 1, pin); 402 if (irq != PCI_INVALID_IRQ) 403 return(irq); 404 } 405 } 406 return(PCI_INVALID_IRQ); 407 } 408 409 /* 410 * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and 411 * see if it has already been assigned an interrupt. 412 */ 413 static int 414 pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin) 415 { 416 devclass_t pci_devclass; 417 device_t *pci_devices; 418 int pci_count; 419 device_t *pci_children; 420 int pci_childcount; 421 device_t *busp, *childp; 422 int i, j, irq; 423 424 /* 425 * Find all the PCI busses. 426 */ 427 pci_count = 0; 428 if ((pci_devclass = devclass_find("pci")) != NULL) 429 devclass_get_devices(pci_devclass, &pci_devices, &pci_count); 430 431 /* 432 * Scan all the PCI busses/devices looking for this one. 433 */ 434 irq = PCI_INVALID_IRQ; 435 for (i = 0, busp = pci_devices; (i < pci_count) && (irq == PCI_INVALID_IRQ); 436 i++, busp++) { 437 pci_childcount = 0; 438 device_get_children(*busp, &pci_children, &pci_childcount); 439 440 for (j = 0, childp = pci_children; j < pci_childcount; j++, 441 childp++) { 442 if ((pci_get_bus(*childp) == bus) && 443 (pci_get_slot(*childp) == device) && 444 (pci_get_intpin(*childp) == matchpin)) { 445 irq = pci_i386_map_intline(pci_get_irq(*childp)); 446 if (irq != PCI_INVALID_IRQ) 447 PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n", 448 pe->pe_intpin[pin - 1].link, irq, 449 pci_get_bus(*childp), 450 pci_get_slot(*childp), 451 pci_get_function(*childp))); 452 break; 453 } 454 } 455 if (pci_children != NULL) 456 free(pci_children, M_TEMP); 457 } 458 if (pci_devices != NULL) 459 free(pci_devices, M_TEMP); 460 return(irq); 461 } 462 463 /* 464 * Pick a suitable IRQ from those listed as routable to this device. 465 */ 466 static int 467 pci_cfgintr_virgin(struct PIR_entry *pe, int pin) 468 { 469 int irq, ibit; 470 471 /* 472 * first scan the set of PCI-only interrupts and see if any of these 473 * are routable 474 */ 475 for (irq = 0; irq < 16; irq++) { 476 ibit = (1 << irq); 477 478 /* can we use this interrupt? */ 479 if ((pci_route_table->pt_header.ph_pci_irqs & ibit) && 480 (pe->pe_intpin[pin - 1].irqs & ibit)) { 481 PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq)); 482 return(irq); 483 } 484 } 485 486 /* life is tough, so just pick an interrupt */ 487 for (irq = 0; irq < 16; irq++) { 488 ibit = (1 << irq); 489 if ((ibit & pci_irq_override_mask) == 0) 490 continue; 491 if (pe->pe_intpin[pin - 1].irqs & ibit) { 492 PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq)); 493 return(irq); 494 } 495 } 496 return(PCI_INVALID_IRQ); 497 } 498 499 static void 500 pci_print_irqmask(u_int16_t irqs) 501 { 502 int i, first; 503 504 if (irqs == 0) { 505 printf("none"); 506 return; 507 } 508 first = 1; 509 for (i = 0; i < 16; i++, irqs >>= 1) 510 if (irqs & 1) { 511 if (!first) 512 printf(" "); 513 else 514 first = 0; 515 printf("%d", i); 516 } 517 } 518 519 /* 520 * Dump the contents of a PCI BIOS Interrupt Routing Table to the console. 521 */ 522 static void 523 pci_print_route_table(struct PIR_table *prt, int size) 524 { 525 struct PIR_entry *entry; 526 struct PIR_intpin *intpin; 527 int i, pin; 528 529 printf("PCI-Only Interrupts: "); 530 pci_print_irqmask(prt->pt_header.ph_pci_irqs); 531 printf("\nLocation Bus Device Pin Link IRQs\n"); 532 entry = &prt->pt_entry[0]; 533 for (i = 0; i < size; i++, entry++) { 534 intpin = &entry->pe_intpin[0]; 535 for (pin = 0; pin < 4; pin++, intpin++) 536 if (intpin->link != 0) { 537 if (entry->pe_slot == 0) 538 printf("embedded "); 539 else 540 printf("slot %-3d ", entry->pe_slot); 541 printf(" %3d %3d %c 0x%02x ", 542 entry->pe_bus, entry->pe_device, 543 'A' + pin, intpin->link); 544 pci_print_irqmask(intpin->irqs); 545 printf("\n"); 546 } 547 } 548 } 549 550 /* 551 * See if any interrupts for a given PCI bus are routed in the PIR. Don't 552 * even bother looking if the BIOS doesn't support routing anyways. 553 */ 554 int 555 pci_probe_route_table(int bus) 556 { 557 int i; 558 u_int16_t v; 559 560 v = pcibios_get_version(); 561 if (v < 0x0210) 562 return (0); 563 for (i = 0; i < pci_route_count; i++) 564 if (pci_route_table->pt_entry[i].pe_bus == bus) 565 return (1); 566 return (0); 567 } 568 569 /* 570 * Configuration space access using direct register operations 571 */ 572 573 /* enable configuration space accesses and return data port address */ 574 static int 575 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 576 { 577 int dataport = 0; 578 579 if (bus <= PCI_BUSMAX 580 && slot < devmax 581 && func <= PCI_FUNCMAX 582 && reg <= PCI_REGMAX 583 && bytes != 3 584 && (unsigned) bytes <= 4 585 && (reg & (bytes - 1)) == 0) { 586 switch (cfgmech) { 587 case 1: 588 outl(CONF1_ADDR_PORT, (1 << 31) 589 | (bus << 16) | (slot << 11) 590 | (func << 8) | (reg & ~0x03)); 591 dataport = CONF1_DATA_PORT + (reg & 0x03); 592 break; 593 case 2: 594 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 595 outb(CONF2_FORWARD_PORT, bus); 596 dataport = 0xc000 | (slot << 8) | reg; 597 break; 598 } 599 } 600 return (dataport); 601 } 602 603 /* disable configuration space accesses */ 604 static void 605 pci_cfgdisable(void) 606 { 607 switch (cfgmech) { 608 case 1: 609 outl(CONF1_ADDR_PORT, 0); 610 break; 611 case 2: 612 outb(CONF2_ENABLE_PORT, 0); 613 outb(CONF2_FORWARD_PORT, 0); 614 break; 615 } 616 } 617 618 static int 619 pcireg_cfgread(int bus, int slot, int func, int reg, int bytes) 620 { 621 int data = -1; 622 int port; 623 624 mtx_lock_spin(&pcicfg_mtx); 625 port = pci_cfgenable(bus, slot, func, reg, bytes); 626 if (port != 0) { 627 switch (bytes) { 628 case 1: 629 data = inb(port); 630 break; 631 case 2: 632 data = inw(port); 633 break; 634 case 4: 635 data = inl(port); 636 break; 637 } 638 pci_cfgdisable(); 639 } 640 mtx_unlock_spin(&pcicfg_mtx); 641 return (data); 642 } 643 644 static void 645 pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 646 { 647 int port; 648 649 mtx_lock_spin(&pcicfg_mtx); 650 port = pci_cfgenable(bus, slot, func, reg, bytes); 651 if (port != 0) { 652 switch (bytes) { 653 case 1: 654 outb(port, data); 655 break; 656 case 2: 657 outw(port, data); 658 break; 659 case 4: 660 outl(port, data); 661 break; 662 } 663 pci_cfgdisable(); 664 } 665 mtx_unlock_spin(&pcicfg_mtx); 666 } 667 668 /* check whether the configuration mechanism has been correctly identified */ 669 static int 670 pci_cfgcheck(int maxdev) 671 { 672 uint32_t id, class; 673 uint8_t header; 674 uint8_t device; 675 int port; 676 677 if (bootverbose) 678 printf("pci_cfgcheck:\tdevice "); 679 680 for (device = 0; device < maxdev; device++) { 681 if (bootverbose) 682 printf("%d ", device); 683 684 port = pci_cfgenable(0, device, 0, 0, 4); 685 id = inl(port); 686 if (id == 0 || id == 0xffffffff) 687 continue; 688 689 port = pci_cfgenable(0, device, 0, 8, 4); 690 class = inl(port) >> 8; 691 if (bootverbose) 692 printf("[class=%06x] ", class); 693 if (class == 0 || (class & 0xf870ff) != 0) 694 continue; 695 696 port = pci_cfgenable(0, device, 0, 14, 1); 697 header = inb(port); 698 if (bootverbose) 699 printf("[hdr=%02x] ", header); 700 if ((header & 0x7e) != 0) 701 continue; 702 703 if (bootverbose) 704 printf("is there (id=%08x)\n", id); 705 706 pci_cfgdisable(); 707 return (1); 708 } 709 if (bootverbose) 710 printf("-- nothing found\n"); 711 712 pci_cfgdisable(); 713 return (0); 714 } 715 716 static int 717 pcireg_cfgopen(void) 718 { 719 uint32_t mode1res, oldval1; 720 uint8_t mode2res, oldval2; 721 722 oldval1 = inl(CONF1_ADDR_PORT); 723 724 if (bootverbose) { 725 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08x\n", 726 oldval1); 727 } 728 729 if ((oldval1 & CONF1_ENABLE_MSK) == 0) { 730 731 cfgmech = 1; 732 devmax = 32; 733 734 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 735 DELAY(1); 736 mode1res = inl(CONF1_ADDR_PORT); 737 outl(CONF1_ADDR_PORT, oldval1); 738 739 if (bootverbose) 740 printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n", 741 mode1res, CONF1_ENABLE_CHK); 742 743 if (mode1res) { 744 if (pci_cfgcheck(32)) 745 return (cfgmech); 746 } 747 748 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 749 mode1res = inl(CONF1_ADDR_PORT); 750 outl(CONF1_ADDR_PORT, oldval1); 751 752 if (bootverbose) 753 printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n", 754 mode1res, CONF1_ENABLE_CHK1); 755 756 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 757 if (pci_cfgcheck(32)) 758 return (cfgmech); 759 } 760 } 761 762 oldval2 = inb(CONF2_ENABLE_PORT); 763 764 if (bootverbose) { 765 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 766 oldval2); 767 } 768 769 if ((oldval2 & 0xf0) == 0) { 770 771 cfgmech = 2; 772 devmax = 16; 773 774 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 775 mode2res = inb(CONF2_ENABLE_PORT); 776 outb(CONF2_ENABLE_PORT, oldval2); 777 778 if (bootverbose) 779 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 780 mode2res, CONF2_ENABLE_CHK); 781 782 if (mode2res == CONF2_ENABLE_RES) { 783 if (bootverbose) 784 printf("pci_open(2a):\tnow trying mechanism 2\n"); 785 786 if (pci_cfgcheck(16)) 787 return (cfgmech); 788 } 789 } 790 791 cfgmech = 0; 792 devmax = 0; 793 return (cfgmech); 794 } 795 796