1 /* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 * 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 #include <sys/kernel.h> 34 35 #include <pci/pcivar.h> 36 #include <pci/pcireg.h> 37 #include <i386/isa/pcibus.h> 38 39 #include <machine/segments.h> 40 #include <machine/pc/bios.h> 41 42 static int cfgmech; 43 static int devmax; 44 static int usebios; 45 46 static int pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes); 47 static void pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes); 48 static int pcibios_cfgopen(void); 49 static int pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes); 50 static void pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes); 51 static int pcireg_cfgopen(void); 52 53 /* read configuration space register */ 54 55 int 56 pci_cfgread(pcicfgregs *cfg, int reg, int bytes) 57 { 58 return(usebios ? 59 pcibios_cfgread(cfg, reg, bytes) : 60 pcireg_cfgread(cfg, reg, bytes)); 61 } 62 63 /* write configuration space register */ 64 65 void 66 pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes) 67 { 68 return(usebios ? 69 pcibios_cfgwrite(cfg, reg, data, bytes) : 70 pcireg_cfgwrite(cfg, reg, data, bytes)); 71 } 72 73 /* initialise access to PCI configuration space */ 74 static int 75 pci_cfgopen(void) 76 { 77 if (pcibios_cfgopen() != 0) { 78 usebios = 1; 79 } else if (pcireg_cfgopen() != 0) { 80 usebios = 0; 81 } else { 82 return(0); 83 } 84 return(1); 85 } 86 87 /* config space access using BIOS functions */ 88 89 static int 90 pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes) 91 { 92 struct bios_regs args; 93 u_int mask; 94 95 switch(bytes) { 96 case 1: 97 args.eax = PCIBIOS_READ_CONFIG_BYTE; 98 mask = 0xff; 99 break; 100 case 2: 101 args.eax = PCIBIOS_READ_CONFIG_WORD; 102 mask = 0xffff; 103 break; 104 case 4: 105 args.eax = PCIBIOS_READ_CONFIG_DWORD; 106 mask = 0xffffffff; 107 break; 108 default: 109 return(-1); 110 } 111 args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func); 112 args.edi = reg; 113 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 114 /* check call results? */ 115 return(args.ecx & mask); 116 } 117 118 static void 119 pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes) 120 { 121 struct bios_regs args; 122 123 switch(bytes) { 124 case 1: 125 args.eax = PCIBIOS_WRITE_CONFIG_BYTE; 126 break; 127 case 2: 128 args.eax = PCIBIOS_WRITE_CONFIG_WORD; 129 break; 130 case 4: 131 args.eax = PCIBIOS_WRITE_CONFIG_DWORD; 132 break; 133 default: 134 return; 135 } 136 args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func); 137 args.ecx = data; 138 args.edi = reg; 139 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 140 } 141 142 /* determine whether there is a PCI BIOS present */ 143 144 static int 145 pcibios_cfgopen(void) 146 { 147 /* check for a found entrypoint */ 148 return(PCIbios.entry != 0); 149 } 150 151 /* configuration space access using direct register operations */ 152 153 /* enable configuration space accesses and return data port address */ 154 155 static int 156 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 157 { 158 int dataport = 0; 159 160 if (bus <= PCI_BUSMAX 161 && slot < devmax 162 && func <= PCI_FUNCMAX 163 && reg <= PCI_REGMAX 164 && bytes != 3 165 && (unsigned) bytes <= 4 166 && (reg & (bytes -1)) == 0) { 167 switch (cfgmech) { 168 case 1: 169 outl(CONF1_ADDR_PORT, (1 << 31) 170 | (bus << 16) | (slot << 11) 171 | (func << 8) | (reg & ~0x03)); 172 dataport = CONF1_DATA_PORT + (reg & 0x03); 173 break; 174 case 2: 175 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 176 outb(CONF2_FORWARD_PORT, bus); 177 dataport = 0xc000 | (slot << 8) | reg; 178 break; 179 } 180 } 181 return (dataport); 182 } 183 184 /* disable configuration space accesses */ 185 186 static void 187 pci_cfgdisable(void) 188 { 189 switch (cfgmech) { 190 case 1: 191 outl(CONF1_ADDR_PORT, 0); 192 break; 193 case 2: 194 outb(CONF2_ENABLE_PORT, 0); 195 outb(CONF2_FORWARD_PORT, 0); 196 break; 197 } 198 } 199 200 static int 201 pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes) 202 { 203 int data = -1; 204 int port; 205 206 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes); 207 208 if (port != 0) { 209 switch (bytes) { 210 case 1: 211 data = inb(port); 212 break; 213 case 2: 214 data = inw(port); 215 break; 216 case 4: 217 data = inl(port); 218 break; 219 } 220 pci_cfgdisable(); 221 } 222 return (data); 223 } 224 225 static void 226 pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes) 227 { 228 int port; 229 230 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes); 231 if (port != 0) { 232 switch (bytes) { 233 case 1: 234 outb(port, data); 235 break; 236 case 2: 237 outw(port, data); 238 break; 239 case 4: 240 outl(port, data); 241 break; 242 } 243 pci_cfgdisable(); 244 } 245 } 246 247 /* check whether the configuration mechanism has been correct identified */ 248 249 static int 250 pci_cfgcheck(int maxdev) 251 { 252 u_char device; 253 254 if (bootverbose) 255 printf("pci_cfgcheck:\tdevice "); 256 257 for (device = 0; device < maxdev; device++) { 258 unsigned id, class, header; 259 if (bootverbose) 260 printf("%d ", device); 261 262 id = inl(pci_cfgenable(0, device, 0, 0, 4)); 263 if (id == 0 || id == -1) 264 continue; 265 266 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8; 267 if (bootverbose) 268 printf("[class=%06x] ", class); 269 if (class == 0 || (class & 0xf870ff) != 0) 270 continue; 271 272 header = inb(pci_cfgenable(0, device, 0, 14, 1)); 273 if (bootverbose) 274 printf("[hdr=%02x] ", header); 275 if ((header & 0x7e) != 0) 276 continue; 277 278 if (bootverbose) 279 printf("is there (id=%08x)\n", id); 280 281 pci_cfgdisable(); 282 return (1); 283 } 284 if (bootverbose) 285 printf("-- nothing found\n"); 286 287 pci_cfgdisable(); 288 return (0); 289 } 290 291 static int 292 pcireg_cfgopen(void) 293 { 294 unsigned long mode1res,oldval1; 295 unsigned char mode2res,oldval2; 296 297 oldval1 = inl(CONF1_ADDR_PORT); 298 299 if (bootverbose) { 300 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", 301 oldval1); 302 } 303 304 if ((oldval1 & CONF1_ENABLE_MSK) == 0) { 305 306 cfgmech = 1; 307 devmax = 32; 308 309 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 310 outb(CONF1_ADDR_PORT +3, 0); 311 mode1res = inl(CONF1_ADDR_PORT); 312 outl(CONF1_ADDR_PORT, oldval1); 313 314 if (bootverbose) 315 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 316 mode1res, CONF1_ENABLE_CHK); 317 318 if (mode1res) { 319 if (pci_cfgcheck(32)) 320 return (cfgmech); 321 } 322 323 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 324 mode1res = inl(CONF1_ADDR_PORT); 325 outl(CONF1_ADDR_PORT, oldval1); 326 327 if (bootverbose) 328 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 329 mode1res, CONF1_ENABLE_CHK1); 330 331 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 332 if (pci_cfgcheck(32)) 333 return (cfgmech); 334 } 335 } 336 337 oldval2 = inb(CONF2_ENABLE_PORT); 338 339 if (bootverbose) { 340 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 341 oldval2); 342 } 343 344 if ((oldval2 & 0xf0) == 0) { 345 346 cfgmech = 2; 347 devmax = 16; 348 349 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 350 mode2res = inb(CONF2_ENABLE_PORT); 351 outb(CONF2_ENABLE_PORT, oldval2); 352 353 if (bootverbose) 354 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 355 mode2res, CONF2_ENABLE_CHK); 356 357 if (mode2res == CONF2_ENABLE_RES) { 358 if (bootverbose) 359 printf("pci_open(2a):\tnow trying mechanism 2\n"); 360 361 if (pci_cfgcheck(16)) 362 return (cfgmech); 363 } 364 } 365 366 cfgmech = 0; 367 devmax = 0; 368 return (cfgmech); 369 } 370 371 static devclass_t pcib_devclass; 372 373 static const char * 374 nexus_pcib_is_host_bridge(pcicfgregs *cfg, 375 u_int32_t id, u_int8_t class, u_int8_t subclass, 376 u_int8_t *busnum) 377 { 378 const char *s = NULL; 379 static u_int8_t pxb[4]; /* hack for 450nx */ 380 381 *busnum = 0; 382 383 switch (id) { 384 case 0x12258086: 385 s = "Intel 824?? host to PCI bridge"; 386 /* XXX This is a guess */ 387 /* *busnum = pci_cfgread(cfg, 0x41, 1); */ 388 *busnum = cfg->bus; 389 break; 390 case 0x71208086: 391 s = "Intel 82810 (i810 GMCH) Host To Hub bridge"; 392 break; 393 case 0x71228086: 394 s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge"; 395 break; 396 case 0x71248086: 397 s = "Intel 82810E (i810E GMCH) Host To Hub bridge"; 398 break; 399 case 0x71808086: 400 s = "Intel 82443LX (440 LX) host to PCI bridge"; 401 break; 402 case 0x71908086: 403 s = "Intel 82443BX (440 BX) host to PCI bridge"; 404 break; 405 case 0x71928086: 406 s = "Intel 82443BX host to PCI bridge (AGP disabled)"; 407 break; 408 case 0x71948086: 409 s = "Intel 82443MX host to PCI bridge"; 410 break; 411 case 0x71a08086: 412 s = "Intel 82443GX host to PCI bridge"; 413 break; 414 case 0x71a18086: 415 s = "Intel 82443GX host to AGP bridge"; 416 break; 417 case 0x71a28086: 418 s = "Intel 82443GX host to PCI bridge (AGP disabled)"; 419 break; 420 case 0x84c48086: 421 s = "Intel 82454KX/GX (Orion) host to PCI bridge"; 422 *busnum = pci_cfgread(cfg, 0x4a, 1); 423 break; 424 case 0x84ca8086: 425 /* 426 * For the 450nx chipset, there is a whole bundle of 427 * things pretending to be host bridges. The MIOC will 428 * be seen first and isn't really a pci bridge (the 429 * actual busses are attached to the PXB's). We need to 430 * read the registers of the MIOC to figure out the 431 * bus numbers for the PXB channels. 432 * 433 * Since the MIOC doesn't have a pci bus attached, we 434 * pretend it wasn't there. 435 */ 436 pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */ 437 pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */ 438 pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */ 439 pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */ 440 return NULL; 441 case 0x84cb8086: 442 switch (cfg->slot) { 443 case 0x12: 444 s = "Intel 82454NX PXB#0, Bus#A"; 445 *busnum = pxb[0]; 446 break; 447 case 0x13: 448 s = "Intel 82454NX PXB#0, Bus#B"; 449 *busnum = pxb[1]; 450 break; 451 case 0x14: 452 s = "Intel 82454NX PXB#1, Bus#A"; 453 *busnum = pxb[2]; 454 break; 455 case 0x15: 456 s = "Intel 82454NX PXB#1, Bus#B"; 457 *busnum = pxb[3]; 458 break; 459 } 460 break; 461 462 /* AMD -- vendor 0x1022 */ 463 case 0x70061022: 464 s = "AMD-751 host to PCI bridge"; 465 break; 466 467 /* SiS -- vendor 0x1039 */ 468 case 0x04961039: 469 s = "SiS 85c496"; 470 break; 471 case 0x04061039: 472 s = "SiS 85c501"; 473 break; 474 case 0x06011039: 475 s = "SiS 85c601"; 476 break; 477 case 0x55911039: 478 s = "SiS 5591 host to PCI bridge"; 479 break; 480 case 0x00011039: 481 s = "SiS 5591 host to AGP bridge"; 482 break; 483 484 /* VLSI -- vendor 0x1004 */ 485 case 0x00051004: 486 s = "VLSI 82C592 Host to PCI bridge"; 487 break; 488 489 /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */ 490 /* totally. Please let me know if anything wrong. -F */ 491 /* XXX need info on the MVP3 -- any takers? */ 492 case 0x05981106: 493 s = "VIA 82C598MVP (Apollo MVP3) host bridge"; 494 break; 495 496 /* AcerLabs -- vendor 0x10b9 */ 497 /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */ 498 /* id is '10b9" but the register always shows "10b9". -Foxfair */ 499 case 0x154110b9: 500 s = "AcerLabs M1541 (Aladdin-V) PCI host bridge"; 501 break; 502 503 /* OPTi -- vendor 0x1045 */ 504 case 0xc7011045: 505 s = "OPTi 82C700 host to PCI bridge"; 506 break; 507 case 0xc8221045: 508 s = "OPTi 82C822 host to PCI Bridge"; 509 break; 510 511 /* RCC -- vendor 0x1166 */ 512 case 0x00051166: 513 s = "RCC HE host to PCI bridge"; 514 *busnum = pci_cfgread(cfg, 0x44, 1); 515 break; 516 517 case 0x00061166: 518 /* FALLTHROUGH */ 519 case 0x00081166: 520 s = "RCC host to PCI bridge"; 521 *busnum = pci_cfgread(cfg, 0x44, 1); 522 break; 523 524 case 0x00091166: 525 s = "RCC LE host to PCI bridge"; 526 *busnum = pci_cfgread(cfg, 0x44, 1); 527 break; 528 529 /* Integrated Micro Solutions -- vendor 0x10e0 */ 530 case 0x884910e0: 531 s = "Integrated Micro Solutions VL Bridge"; 532 break; 533 534 default: 535 if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST) 536 s = "Host to PCI bridge"; 537 break; 538 } 539 540 return s; 541 } 542 543 /* 544 * Scan the first pci bus for host-pci bridges and add pcib instances 545 * to the nexus for each bridge. 546 */ 547 static void 548 nexus_pcib_identify(driver_t *driver, device_t parent) 549 { 550 pcicfgregs probe; 551 u_int8_t hdrtype; 552 int found = 0; 553 int pcifunchigh; 554 int found824xx = 0; 555 556 if (pci_cfgopen() == 0) 557 return; 558 probe.hose = 0; 559 probe.bus = 0; 560 retry: 561 for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { 562 probe.func = 0; 563 hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1); 564 if (hdrtype & PCIM_MFDEV) 565 pcifunchigh = 7; 566 else 567 pcifunchigh = 0; 568 for (probe.func = 0; 569 probe.func <= pcifunchigh; 570 probe.func++) { 571 /* 572 * Read the IDs and class from the device. 573 */ 574 u_int32_t id; 575 u_int8_t class, subclass, busnum; 576 device_t child; 577 const char *s; 578 579 id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4); 580 if (id == -1) 581 continue; 582 class = pci_cfgread(&probe, PCIR_CLASS, 1); 583 subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1); 584 585 s = nexus_pcib_is_host_bridge(&probe, id, 586 class, subclass, 587 &busnum); 588 if (s) { 589 /* 590 * Add at priority 100 to make sure we 591 * go after any motherboard resources 592 */ 593 child = BUS_ADD_CHILD(parent, 100, 594 "pcib", busnum); 595 device_set_desc(child, s); 596 found = 1; 597 if (id == 0x12258086) 598 found824xx = 1; 599 } 600 } 601 } 602 if (found824xx && probe.bus == 0) { 603 probe.bus++; 604 goto retry; 605 } 606 607 /* 608 * Make sure we add at least one bridge since some old 609 * hardware doesn't actually have a host-pci bridge device. 610 * Note that pci_cfgopen() thinks we have PCI devices.. 611 */ 612 if (!found) { 613 if (bootverbose) 614 printf( 615 "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n"); 616 BUS_ADD_CHILD(parent, 100, "pcib", 0); 617 } 618 } 619 620 static int 621 nexus_pcib_probe(device_t dev) 622 { 623 if (pci_cfgopen() != 0) { 624 device_add_child(dev, "pci", device_get_unit(dev)); 625 return 0; 626 } 627 return ENXIO; 628 } 629 630 static device_method_t nexus_pcib_methods[] = { 631 /* Device interface */ 632 DEVMETHOD(device_identify, nexus_pcib_identify), 633 DEVMETHOD(device_probe, nexus_pcib_probe), 634 DEVMETHOD(device_attach, bus_generic_attach), 635 DEVMETHOD(device_shutdown, bus_generic_shutdown), 636 DEVMETHOD(device_suspend, bus_generic_suspend), 637 DEVMETHOD(device_resume, bus_generic_resume), 638 639 /* Bus interface */ 640 DEVMETHOD(bus_print_child, bus_generic_print_child), 641 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 642 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 643 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 644 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 645 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 646 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 647 648 { 0, 0 } 649 }; 650 651 static driver_t nexus_pcib_driver = { 652 "pcib", 653 nexus_pcib_methods, 654 1, 655 }; 656 657 DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0); 658