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 * $FreeBSD$ 29 * 30 */ 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 <vm/vm.h> 39 #include <vm/pmap.h> 40 #include <machine/md_var.h> 41 #include <dev/pci/pcivar.h> 42 #include <dev/pci/pcireg.h> 43 #include <isa/isavar.h> 44 #include <machine/nexusvar.h> 45 #include <machine/pci_cfgreg.h> 46 #include <machine/segments.h> 47 #include <machine/pc/bios.h> 48 49 #ifdef APIC_IO 50 #include <machine/smp.h> 51 #endif /* APIC_IO */ 52 53 #include "pcib_if.h" 54 55 #define PRVERB(a) printf a 56 57 static int cfgmech; 58 static int devmax; 59 static int usebios; 60 static int enable_pcibios = 0; 61 62 TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios); 63 64 static int pci_cfgintr_unique(struct PIR_entry *pe, int pin); 65 static int pci_cfgintr_linked(struct PIR_entry *pe, int pin); 66 static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin); 67 static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin); 68 69 static int pcibios_cfgread(int bus, int slot, int func, int reg, int bytes); 70 static void pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 71 static int pcibios_cfgopen(void); 72 static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes); 73 static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 74 static int pcireg_cfgopen(void); 75 76 static struct PIR_table *pci_route_table; 77 static int pci_route_count; 78 79 /* 80 * Some BIOS writers seem to want to ignore the spec and put 81 * 0 in the intline rather than 255 to indicate none. Some use 82 * numbers in the range 128-254 to indicate something strange and 83 * apparently undocumented anywhere. Assume these are completely bogus 84 * and map them to 255, which means "none". 85 */ 86 static __inline__ int 87 pci_i386_map_intline(int line) 88 { 89 if (line == 0 || line >= 128) 90 return (PCI_INVALID_IRQ); 91 return (line); 92 } 93 94 int 95 pci_pcibios_active(void) 96 { 97 return (usebios); 98 } 99 100 int 101 pci_kill_pcibios(void) 102 { 103 usebios = 0; 104 return (pcireg_cfgopen() != 0); 105 } 106 107 static u_int16_t 108 pcibios_get_version(void) 109 { 110 struct bios_regs args; 111 112 if (PCIbios.entry == 0) { 113 PRVERB(("pcibios: No call entry point\n")); 114 return (0); 115 } 116 args.eax = PCIBIOS_BIOS_PRESENT; 117 if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { 118 PRVERB(("pcibios: BIOS_PRESENT call failed\n")); 119 return (0); 120 } 121 if (args.edx != 0x20494350) { 122 PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n")); 123 return (0); 124 } 125 return (args.ebx & 0xffff); 126 } 127 128 /* 129 * Initialise access to PCI configuration space 130 */ 131 int 132 pci_cfgregopen(void) 133 { 134 static int opened = 0; 135 u_long sigaddr; 136 static struct PIR_table *pt; 137 u_int8_t ck, *cv; 138 int i; 139 140 if (opened) 141 return(1); 142 143 if (pcibios_cfgopen() != 0) 144 usebios = 1; 145 else if (pcireg_cfgopen() != 0) 146 usebios = 0; 147 else 148 return(0); 149 150 /* 151 * Look for the interrupt routing table. 152 * 153 * We use PCI BIOS's PIR table if it's available $PIR is the 154 * standard way to do this. Sadly, some machines are not 155 * standards conforming and have _PIR instead. We shrug and cope 156 * by looking for both. 157 */ 158 if (pcibios_get_version() >= 0x0210 && pt == NULL) { 159 sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0); 160 if (sigaddr == 0) 161 sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0); 162 if (sigaddr != 0) { 163 pt = (struct PIR_table *)(uintptr_t) 164 BIOS_PADDRTOVADDR(sigaddr); 165 for (cv = (u_int8_t *)pt, ck = 0, i = 0; 166 i < (pt->pt_header.ph_length); i++) { 167 ck += cv[i]; 168 } 169 if (ck == 0) { 170 pci_route_table = pt; 171 pci_route_count = (pt->pt_header.ph_length - 172 sizeof(struct PIR_header)) / 173 sizeof(struct PIR_entry); 174 printf("Using $PIR table, %d entries at %p\n", 175 pci_route_count, pci_route_table); 176 } 177 } 178 } 179 opened = 1; 180 return(1); 181 } 182 183 /* 184 * Read configuration space register 185 */ 186 static u_int32_t 187 pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes) 188 { 189 return(usebios ? 190 pcibios_cfgread(bus, slot, func, reg, bytes) : 191 pcireg_cfgread(bus, slot, func, reg, bytes)); 192 } 193 194 u_int32_t 195 pci_cfgregread(int bus, int slot, int func, int reg, int bytes) 196 { 197 uint32_t line; 198 #ifdef APIC_IO 199 uint32_t pin; 200 201 /* 202 * If we are using the APIC, the contents of the intline 203 * register will probably be wrong (since they are set up for 204 * use with the PIC. Rather than rewrite these registers 205 * (maybe that would be smarter) we trap attempts to read them 206 * and translate to our private vector numbers. 207 */ 208 if ((reg == PCIR_INTLINE) && (bytes == 1)) { 209 210 pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1); 211 line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1); 212 213 if (pin != 0) { 214 int airq; 215 216 airq = pci_apic_irq(bus, slot, pin); 217 if (airq >= 0) { 218 /* PCI specific entry found in MP table */ 219 if (airq != line) 220 undirect_pci_irq(line); 221 return(airq); 222 } else { 223 /* 224 * PCI interrupts might be redirected 225 * to the ISA bus according to some MP 226 * tables. Use the same methods as 227 * used by the ISA devices devices to 228 * find the proper IOAPIC int pin. 229 */ 230 airq = isa_apic_irq(line); 231 if ((airq >= 0) && (airq != line)) { 232 /* XXX: undirect_pci_irq() ? */ 233 undirect_isa_irq(line); 234 return(airq); 235 } 236 } 237 } 238 return(line); 239 } 240 #else 241 /* 242 * Some BIOS writers seem to want to ignore the spec and put 243 * 0 in the intline rather than 255 to indicate none. The rest of 244 * the code uses 255 as an invalid IRQ. 245 */ 246 if (reg == PCIR_INTLINE && bytes == 1) { 247 line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1); 248 return pci_i386_map_intline(line); 249 } 250 #endif /* APIC_IO */ 251 return(pci_do_cfgregread(bus, slot, func, reg, bytes)); 252 } 253 254 /* 255 * Write configuration space register 256 */ 257 void 258 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) 259 { 260 return (usebios ? 261 pcibios_cfgwrite(bus, slot, func, reg, data, bytes) : 262 pcireg_cfgwrite(bus, slot, func, reg, data, bytes)); 263 } 264 265 /* 266 * Route a PCI interrupt 267 * 268 * XXX we don't do anything "right" with the function number in the PIR table 269 * (because the consumer isn't currently passing it in). We don't care 270 * anyway, due to the way PCI interrupts are assigned. 271 */ 272 int 273 pci_cfgintr(int bus, int device, int pin) 274 { 275 struct PIR_entry *pe; 276 int i, irq; 277 struct bios_regs args; 278 u_int16_t v; 279 int already = 0; 280 281 v = pcibios_get_version(); 282 if (v < 0x0210) { 283 PRVERB(( 284 "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n", 285 (v & 0xff00) >> 8, v & 0xff)); 286 return (PCI_INVALID_IRQ); 287 } 288 if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) || 289 (pin < 1) || (pin > 4)) 290 return(PCI_INVALID_IRQ); 291 292 /* 293 * Scan the entry table for a contender 294 */ 295 for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; 296 i++, pe++) { 297 if ((bus != pe->pe_bus) || (device != pe->pe_device)) 298 continue; 299 300 irq = pci_cfgintr_linked(pe, pin); 301 if (irq == PCI_INVALID_IRQ) 302 irq = pci_cfgintr_unique(pe, pin); 303 if (irq != PCI_INVALID_IRQ) 304 already = 1; 305 if (irq == PCI_INVALID_IRQ) 306 irq = pci_cfgintr_virgin(pe, pin); 307 if (irq == PCI_INVALID_IRQ) 308 break; 309 310 /* 311 * Ask the BIOS to route the interrupt 312 */ 313 args.eax = PCIBIOS_ROUTE_INTERRUPT; 314 args.ebx = (bus << 8) | (device << 3); 315 /* pin value is 0xa - 0xd */ 316 args.ecx = (irq << 8) | (0xa + pin - 1); 317 if (!already && 318 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { 319 /* 320 * XXX if it fails, we should try to smack the router 321 * hardware directly. 322 * XXX Also, there may be other choices that we can 323 * try that will work. 324 */ 325 PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n")); 326 return(PCI_INVALID_IRQ); 327 } 328 printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, 329 device, 'A' + pin - 1, irq); 330 return(irq); 331 } 332 333 PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, 334 device, 'A' + pin - 1)); 335 return(PCI_INVALID_IRQ); 336 } 337 338 /* 339 * Look to see if the routing table claims this pin is uniquely routed. 340 */ 341 static int 342 pci_cfgintr_unique(struct PIR_entry *pe, int pin) 343 { 344 int irq; 345 uint32_t irqmask; 346 347 irqmask = pe->pe_intpin[pin - 1].irqs; 348 if (irqmask != 0 && powerof2(irqmask)) { 349 irq = ffs(irqmask) - 1; 350 PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq)); 351 return(irq); 352 } 353 return(PCI_INVALID_IRQ); 354 } 355 356 /* 357 * Look for another device which shares the same link byte and 358 * already has a unique IRQ, or which has had one routed already. 359 */ 360 static int 361 pci_cfgintr_linked(struct PIR_entry *pe, int pin) 362 { 363 struct PIR_entry *oe; 364 struct PIR_intpin *pi; 365 int i, j, irq; 366 367 /* 368 * Scan table slots. 369 */ 370 for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; 371 i++, oe++) { 372 /* scan interrupt pins */ 373 for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) { 374 375 /* don't look at the entry we're trying to match */ 376 if ((pe == oe) && (i == (pin - 1))) 377 continue; 378 /* compare link bytes */ 379 if (pi->link != pe->pe_intpin[pin - 1].link) 380 continue; 381 /* link destination mapped to a unique interrupt? */ 382 if (pi->irqs != 0 && powerof2(pi->irqs)) { 383 irq = ffs(pi->irqs) - 1; 384 PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n", 385 pi->link, irq)); 386 return(irq); 387 } 388 389 /* 390 * look for the real PCI device that matches this 391 * table entry 392 */ 393 irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, 394 j, pin); 395 if (irq != PCI_INVALID_IRQ) 396 return(irq); 397 } 398 } 399 return(PCI_INVALID_IRQ); 400 } 401 402 /* 403 * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and 404 * see if it has already been assigned an interrupt. 405 */ 406 static int 407 pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin) 408 { 409 devclass_t pci_devclass; 410 device_t *pci_devices; 411 int pci_count; 412 device_t *pci_children; 413 int pci_childcount; 414 device_t *busp, *childp; 415 int i, j, irq; 416 417 /* 418 * Find all the PCI busses. 419 */ 420 pci_count = 0; 421 if ((pci_devclass = devclass_find("pci")) != NULL) 422 devclass_get_devices(pci_devclass, &pci_devices, &pci_count); 423 424 /* 425 * Scan all the PCI busses/devices looking for this one. 426 */ 427 irq = PCI_INVALID_IRQ; 428 for (i = 0, busp = pci_devices; (i < pci_count) && (irq == PCI_INVALID_IRQ); 429 i++, busp++) { 430 pci_childcount = 0; 431 device_get_children(*busp, &pci_children, &pci_childcount); 432 433 for (j = 0, childp = pci_children; j < pci_childcount; j++, 434 childp++) { 435 if ((pci_get_bus(*childp) == bus) && 436 (pci_get_slot(*childp) == device) && 437 (pci_get_intpin(*childp) == matchpin)) { 438 irq = pci_i386_map_intline(pci_get_irq(*childp)); 439 if (irq != PCI_INVALID_IRQ) 440 PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n", 441 pe->pe_intpin[pin - 1].link, irq, 442 pci_get_bus(*childp), 443 pci_get_slot(*childp), 444 pci_get_function(*childp))); 445 break; 446 } 447 } 448 if (pci_children != NULL) 449 free(pci_children, M_TEMP); 450 } 451 if (pci_devices != NULL) 452 free(pci_devices, M_TEMP); 453 return(irq); 454 } 455 456 /* 457 * Pick a suitable IRQ from those listed as routable to this device. 458 */ 459 static int 460 pci_cfgintr_virgin(struct PIR_entry *pe, int pin) 461 { 462 int irq, ibit; 463 464 /* 465 * first scan the set of PCI-only interrupts and see if any of these 466 * are routable 467 */ 468 for (irq = 0; irq < 16; irq++) { 469 ibit = (1 << irq); 470 471 /* can we use this interrupt? */ 472 if ((pci_route_table->pt_header.ph_pci_irqs & ibit) && 473 (pe->pe_intpin[pin - 1].irqs & ibit)) { 474 PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq)); 475 return(irq); 476 } 477 } 478 479 /* life is tough, so just pick an interrupt */ 480 for (irq = 0; irq < 16; irq++) { 481 ibit = (1 << irq); 482 if (pe->pe_intpin[pin - 1].irqs & ibit) { 483 PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq)); 484 return(irq); 485 } 486 } 487 return(PCI_INVALID_IRQ); 488 } 489 490 491 /* 492 * Config space access using BIOS functions 493 */ 494 static int 495 pcibios_cfgread(int bus, int slot, int func, int reg, int bytes) 496 { 497 struct bios_regs args; 498 u_int mask; 499 500 switch(bytes) { 501 case 1: 502 args.eax = PCIBIOS_READ_CONFIG_BYTE; 503 mask = 0xff; 504 break; 505 case 2: 506 args.eax = PCIBIOS_READ_CONFIG_WORD; 507 mask = 0xffff; 508 break; 509 case 4: 510 args.eax = PCIBIOS_READ_CONFIG_DWORD; 511 mask = 0xffffffff; 512 break; 513 default: 514 return(-1); 515 } 516 args.ebx = (bus << 8) | (slot << 3) | func; 517 args.edi = reg; 518 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 519 /* check call results? */ 520 return(args.ecx & mask); 521 } 522 523 static void 524 pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 525 { 526 struct bios_regs args; 527 528 switch(bytes) { 529 case 1: 530 args.eax = PCIBIOS_WRITE_CONFIG_BYTE; 531 break; 532 case 2: 533 args.eax = PCIBIOS_WRITE_CONFIG_WORD; 534 break; 535 case 4: 536 args.eax = PCIBIOS_WRITE_CONFIG_DWORD; 537 break; 538 default: 539 return; 540 } 541 args.ebx = (bus << 8) | (slot << 3) | func; 542 args.ecx = data; 543 args.edi = reg; 544 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 545 } 546 547 /* 548 * Determine whether there is a PCI BIOS present 549 */ 550 static int 551 pcibios_cfgopen(void) 552 { 553 u_int16_t v = 0; 554 555 if (PCIbios.entry != 0 && enable_pcibios) { 556 v = pcibios_get_version(); 557 if (v > 0) 558 printf("pcibios: BIOS version %x.%02x\n", 559 (v & 0xff00) >> 8, v & 0xff); 560 } 561 return (v > 0); 562 } 563 564 /* 565 * Configuration space access using direct register operations 566 */ 567 568 /* enable configuration space accesses and return data port address */ 569 static int 570 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 571 { 572 int dataport = 0; 573 574 if (bus <= PCI_BUSMAX 575 && slot < devmax 576 && func <= PCI_FUNCMAX 577 && reg <= PCI_REGMAX 578 && bytes != 3 579 && (unsigned) bytes <= 4 580 && (reg & (bytes -1)) == 0) { 581 switch (cfgmech) { 582 case 1: 583 outl(CONF1_ADDR_PORT, (1 << 31) 584 | (bus << 16) | (slot << 11) 585 | (func << 8) | (reg & ~0x03)); 586 dataport = CONF1_DATA_PORT + (reg & 0x03); 587 break; 588 case 2: 589 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 590 outb(CONF2_FORWARD_PORT, bus); 591 dataport = 0xc000 | (slot << 8) | reg; 592 break; 593 } 594 } 595 return (dataport); 596 } 597 598 /* disable configuration space accesses */ 599 static void 600 pci_cfgdisable(void) 601 { 602 switch (cfgmech) { 603 case 1: 604 outl(CONF1_ADDR_PORT, 0); 605 break; 606 case 2: 607 outb(CONF2_ENABLE_PORT, 0); 608 outb(CONF2_FORWARD_PORT, 0); 609 break; 610 } 611 } 612 613 static int 614 pcireg_cfgread(int bus, int slot, int func, int reg, int bytes) 615 { 616 int data = -1; 617 int port; 618 619 port = pci_cfgenable(bus, slot, func, reg, bytes); 620 621 if (port != 0) { 622 switch (bytes) { 623 case 1: 624 data = inb(port); 625 break; 626 case 2: 627 data = inw(port); 628 break; 629 case 4: 630 data = inl(port); 631 break; 632 } 633 pci_cfgdisable(); 634 } 635 return (data); 636 } 637 638 static void 639 pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 640 { 641 int port; 642 643 port = pci_cfgenable(bus, slot, func, reg, bytes); 644 if (port != 0) { 645 switch (bytes) { 646 case 1: 647 outb(port, data); 648 break; 649 case 2: 650 outw(port, data); 651 break; 652 case 4: 653 outl(port, data); 654 break; 655 } 656 pci_cfgdisable(); 657 } 658 } 659 660 /* check whether the configuration mechanism has been correctly identified */ 661 static int 662 pci_cfgcheck(int maxdev) 663 { 664 u_char device; 665 666 if (bootverbose) 667 printf("pci_cfgcheck:\tdevice "); 668 669 for (device = 0; device < maxdev; device++) { 670 unsigned id, class, header; 671 if (bootverbose) 672 printf("%d ", device); 673 674 id = inl(pci_cfgenable(0, device, 0, 0, 4)); 675 if (id == 0 || id == -1) 676 continue; 677 678 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8; 679 if (bootverbose) 680 printf("[class=%06x] ", class); 681 if (class == 0 || (class & 0xf870ff) != 0) 682 continue; 683 684 header = inb(pci_cfgenable(0, device, 0, 14, 1)); 685 if (bootverbose) 686 printf("[hdr=%02x] ", header); 687 if ((header & 0x7e) != 0) 688 continue; 689 690 if (bootverbose) 691 printf("is there (id=%08x)\n", id); 692 693 pci_cfgdisable(); 694 return (1); 695 } 696 if (bootverbose) 697 printf("-- nothing found\n"); 698 699 pci_cfgdisable(); 700 return (0); 701 } 702 703 static int 704 pcireg_cfgopen(void) 705 { 706 unsigned long mode1res,oldval1; 707 unsigned char mode2res,oldval2; 708 709 oldval1 = inl(CONF1_ADDR_PORT); 710 711 if (bootverbose) { 712 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", 713 oldval1); 714 } 715 716 if ((oldval1 & CONF1_ENABLE_MSK) == 0) { 717 718 cfgmech = 1; 719 devmax = 32; 720 721 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 722 outb(CONF1_ADDR_PORT +3, 0); 723 mode1res = inl(CONF1_ADDR_PORT); 724 outl(CONF1_ADDR_PORT, oldval1); 725 726 if (bootverbose) 727 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 728 mode1res, CONF1_ENABLE_CHK); 729 730 if (mode1res) { 731 if (pci_cfgcheck(32)) 732 return (cfgmech); 733 } 734 735 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 736 mode1res = inl(CONF1_ADDR_PORT); 737 outl(CONF1_ADDR_PORT, oldval1); 738 739 if (bootverbose) 740 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 741 mode1res, CONF1_ENABLE_CHK1); 742 743 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 744 if (pci_cfgcheck(32)) 745 return (cfgmech); 746 } 747 } 748 749 oldval2 = inb(CONF2_ENABLE_PORT); 750 751 if (bootverbose) { 752 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 753 oldval2); 754 } 755 756 if ((oldval2 & 0xf0) == 0) { 757 758 cfgmech = 2; 759 devmax = 16; 760 761 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 762 mode2res = inb(CONF2_ENABLE_PORT); 763 outb(CONF2_ENABLE_PORT, oldval2); 764 765 if (bootverbose) 766 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 767 mode2res, CONF2_ENABLE_CHK); 768 769 if (mode2res == CONF2_ENABLE_RES) { 770 if (bootverbose) 771 printf("pci_open(2a):\tnow trying mechanism 2\n"); 772 773 if (pci_cfgcheck(16)) 774 return (cfgmech); 775 } 776 } 777 778 cfgmech = 0; 779 devmax = 0; 780 return (cfgmech); 781 } 782 783