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 0x71a08086: 409 s = "Intel 82443GX host to PCI bridge"; 410 break; 411 case 0x71a18086: 412 s = "Intel 82443GX host to AGP bridge"; 413 break; 414 case 0x71a28086: 415 s = "Intel 82443GX host to PCI bridge (AGP disabled)"; 416 break; 417 case 0x84c48086: 418 s = "Intel 82454KX/GX (Orion) host to PCI bridge"; 419 *busnum = pci_cfgread(cfg, 0x4a, 1); 420 break; 421 case 0x84ca8086: 422 /* 423 * For the 450nx chipset, there is a whole bundle of 424 * things pretending to be host bridges. The MIOC will 425 * be seen first and isn't really a pci bridge (the 426 * actual busses are attached to the PXB's). We need to 427 * read the registers of the MIOC to figure out the 428 * bus numbers for the PXB channels. 429 * 430 * Since the MIOC doesn't have a pci bus attached, we 431 * pretend it wasn't there. 432 */ 433 pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */ 434 pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */ 435 pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */ 436 pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */ 437 return NULL; 438 case 0x84cb8086: 439 switch (cfg->slot) { 440 case 0x12: 441 s = "Intel 82454NX PXB#0, Bus#A"; 442 *busnum = pxb[0]; 443 break; 444 case 0x13: 445 s = "Intel 82454NX PXB#0, Bus#B"; 446 *busnum = pxb[1]; 447 break; 448 case 0x14: 449 s = "Intel 82454NX PXB#1, Bus#A"; 450 *busnum = pxb[2]; 451 break; 452 case 0x15: 453 s = "Intel 82454NX PXB#1, Bus#B"; 454 *busnum = pxb[3]; 455 break; 456 } 457 break; 458 459 /* AMD -- vendor 0x1022 */ 460 case 0x70061022: 461 s = "AMD-751 host to PCI bridge"; 462 break; 463 464 /* SiS -- vendor 0x1039 */ 465 case 0x04961039: 466 s = "SiS 85c496"; 467 break; 468 case 0x04061039: 469 s = "SiS 85c501"; 470 break; 471 case 0x06011039: 472 s = "SiS 85c601"; 473 break; 474 case 0x55911039: 475 s = "SiS 5591 host to PCI bridge"; 476 break; 477 case 0x00011039: 478 s = "SiS 5591 host to AGP bridge"; 479 break; 480 481 /* VLSI -- vendor 0x1004 */ 482 case 0x00051004: 483 s = "VLSI 82C592 Host to PCI bridge"; 484 break; 485 486 /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */ 487 /* totally. Please let me know if anything wrong. -F */ 488 /* XXX need info on the MVP3 -- any takers? */ 489 case 0x05981106: 490 s = "VIA 82C598MVP (Apollo MVP3) host bridge"; 491 break; 492 493 /* AcerLabs -- vendor 0x10b9 */ 494 /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */ 495 /* id is '10b9" but the register always shows "10b9". -Foxfair */ 496 case 0x154110b9: 497 s = "AcerLabs M1541 (Aladdin-V) PCI host bridge"; 498 break; 499 500 /* OPTi -- vendor 0x1045 */ 501 case 0xc8221045: 502 s = "OPTi 82C822 host to PCI Bridge"; 503 break; 504 505 /* RCC -- vendor 0x1166 */ 506 case 0x00051166: 507 s = "RCC HE host to PCI bridge"; 508 *busnum = pci_cfgread(cfg, 0x44, 1); 509 break; 510 511 case 0x00061166: 512 /* FALLTHROUGH */ 513 case 0x00081166: 514 s = "RCC host to PCI bridge"; 515 *busnum = pci_cfgread(cfg, 0x44, 1); 516 break; 517 518 case 0x00091166: 519 s = "RCC LE host to PCI bridge"; 520 *busnum = pci_cfgread(cfg, 0x44, 1); 521 break; 522 523 /* Integrated Micro Solutions -- vendor 0x10e0 */ 524 case 0x884910e0: 525 s = "Integrated Micro Solutions VL Bridge"; 526 break; 527 528 default: 529 if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST) 530 s = "Host to PCI bridge"; 531 break; 532 } 533 534 return s; 535 } 536 537 /* 538 * Scan the first pci bus for host-pci bridges and add pcib instances 539 * to the nexus for each bridge. 540 */ 541 static void 542 nexus_pcib_identify(driver_t *driver, device_t parent) 543 { 544 pcicfgregs probe; 545 u_int8_t hdrtype; 546 int found = 0; 547 int pcifunchigh; 548 int found824xx = 0; 549 550 if (pci_cfgopen() == 0) 551 return; 552 probe.hose = 0; 553 probe.bus = 0; 554 retry: 555 for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { 556 probe.func = 0; 557 hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1); 558 if (hdrtype & PCIM_MFDEV) 559 pcifunchigh = 7; 560 else 561 pcifunchigh = 0; 562 for (probe.func = 0; 563 probe.func <= pcifunchigh; 564 probe.func++) { 565 /* 566 * Read the IDs and class from the device. 567 */ 568 u_int32_t id; 569 u_int8_t class, subclass, busnum; 570 device_t child; 571 const char *s; 572 573 id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4); 574 if (id == -1) 575 continue; 576 class = pci_cfgread(&probe, PCIR_CLASS, 1); 577 subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1); 578 579 s = nexus_pcib_is_host_bridge(&probe, id, 580 class, subclass, 581 &busnum); 582 if (s) { 583 /* 584 * Add at priority 100 to make sure we 585 * go after any motherboard resources 586 */ 587 child = BUS_ADD_CHILD(parent, 100, 588 "pcib", busnum); 589 device_set_desc(child, s); 590 found = 1; 591 if (id == 0x12258086) 592 found824xx = 1; 593 } 594 } 595 } 596 if (found824xx && probe.bus == 0) { 597 probe.bus++; 598 goto retry; 599 } 600 601 /* 602 * Make sure we add at least one bridge since some old 603 * hardware doesn't actually have a host-pci bridge device. 604 * Note that pci_cfgopen() thinks we have PCI devices.. 605 */ 606 if (!found) { 607 if (bootverbose) 608 printf( 609 "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n"); 610 BUS_ADD_CHILD(parent, 100, "pcib", 0); 611 } 612 } 613 614 static int 615 nexus_pcib_probe(device_t dev) 616 { 617 if (pci_cfgopen() != 0) { 618 device_add_child(dev, "pci", device_get_unit(dev)); 619 return 0; 620 } 621 return ENXIO; 622 } 623 624 static device_method_t nexus_pcib_methods[] = { 625 /* Device interface */ 626 DEVMETHOD(device_identify, nexus_pcib_identify), 627 DEVMETHOD(device_probe, nexus_pcib_probe), 628 DEVMETHOD(device_attach, bus_generic_attach), 629 DEVMETHOD(device_shutdown, bus_generic_shutdown), 630 DEVMETHOD(device_suspend, bus_generic_suspend), 631 DEVMETHOD(device_resume, bus_generic_resume), 632 633 /* Bus interface */ 634 DEVMETHOD(bus_print_child, bus_generic_print_child), 635 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 636 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 637 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 638 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 639 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 640 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 641 642 { 0, 0 } 643 }; 644 645 static driver_t nexus_pcib_driver = { 646 "pcib", 647 nexus_pcib_methods, 648 1, 649 }; 650 651 DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0); 652