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 * Copyright (c) 2004, Scott Long <scottl@freebsd.org> 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 unmodified, this list of conditions, and the following 13 * disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include "opt_xbox.h" 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/bus.h> 38 #include <sys/lock.h> 39 #include <sys/kernel.h> 40 #include <sys/mutex.h> 41 #include <sys/malloc.h> 42 #include <sys/queue.h> 43 #include <dev/pci/pcivar.h> 44 #include <dev/pci/pcireg.h> 45 #include <machine/pci_cfgreg.h> 46 #include <machine/pc/bios.h> 47 48 #include <vm/vm.h> 49 #include <vm/vm_param.h> 50 #include <vm/vm_kern.h> 51 #include <vm/vm_extern.h> 52 #include <vm/pmap.h> 53 #include <machine/pmap.h> 54 55 #ifdef XBOX 56 #include <machine/xbox.h> 57 #endif 58 59 #define PRVERB(a) do { \ 60 if (bootverbose) \ 61 printf a ; \ 62 } while(0) 63 64 #define PCIE_CACHE 8 65 struct pcie_cfg_elem { 66 TAILQ_ENTRY(pcie_cfg_elem) elem; 67 vm_offset_t vapage; 68 vm_paddr_t papage; 69 }; 70 71 enum { 72 CFGMECH_NONE = 0, 73 CFGMECH_1, 74 CFGMECH_2, 75 CFGMECH_PCIE, 76 }; 77 78 static TAILQ_HEAD(pcie_cfg_list, pcie_cfg_elem) pcie_list[MAXCPU]; 79 static uint64_t pcie_base; 80 static int pcie_minbus, pcie_maxbus; 81 static uint32_t pcie_badslots; 82 static int cfgmech; 83 static int devmax; 84 static struct mtx pcicfg_mtx; 85 static int mcfg_enable = 1; 86 TUNABLE_INT("hw.pci.mcfg", &mcfg_enable); 87 88 static uint32_t pci_docfgregread(int bus, int slot, int func, int reg, 89 int bytes); 90 static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes); 91 static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 92 #ifndef XEN 93 static int pcireg_cfgopen(void); 94 #endif 95 static int pciereg_cfgread(int bus, unsigned slot, unsigned func, 96 unsigned reg, unsigned bytes); 97 static void pciereg_cfgwrite(int bus, unsigned slot, unsigned func, 98 unsigned reg, int data, unsigned bytes); 99 100 /* 101 * Some BIOS writers seem to want to ignore the spec and put 102 * 0 in the intline rather than 255 to indicate none. Some use 103 * numbers in the range 128-254 to indicate something strange and 104 * apparently undocumented anywhere. Assume these are completely bogus 105 * and map them to 255, which means "none". 106 */ 107 static __inline int 108 pci_i386_map_intline(int line) 109 { 110 if (line == 0 || line >= 128) 111 return (PCI_INVALID_IRQ); 112 return (line); 113 } 114 115 #ifndef XEN 116 static u_int16_t 117 pcibios_get_version(void) 118 { 119 struct bios_regs args; 120 121 if (PCIbios.ventry == 0) { 122 PRVERB(("pcibios: No call entry point\n")); 123 return (0); 124 } 125 args.eax = PCIBIOS_BIOS_PRESENT; 126 if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { 127 PRVERB(("pcibios: BIOS_PRESENT call failed\n")); 128 return (0); 129 } 130 if (args.edx != 0x20494350) { 131 PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n")); 132 return (0); 133 } 134 return (args.ebx & 0xffff); 135 } 136 #endif 137 138 /* 139 * Initialise access to PCI configuration space 140 */ 141 int 142 pci_cfgregopen(void) 143 { 144 #ifdef XEN 145 return (0); 146 #else 147 static int opened = 0; 148 uint64_t pciebar; 149 u_int16_t vid, did; 150 u_int16_t v; 151 152 if (opened) 153 return (1); 154 155 if (cfgmech == CFGMECH_NONE && pcireg_cfgopen() == 0) 156 return (0); 157 158 v = pcibios_get_version(); 159 if (v > 0) 160 PRVERB(("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8, 161 v & 0xff)); 162 mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN); 163 opened = 1; 164 165 /* $PIR requires PCI BIOS 2.10 or greater. */ 166 if (v >= 0x0210) 167 pci_pir_open(); 168 169 if (cfgmech == CFGMECH_PCIE) 170 return (1); 171 172 /* 173 * Grope around in the PCI config space to see if this is a 174 * chipset that is capable of doing memory-mapped config cycles. 175 * This also implies that it can do PCIe extended config cycles. 176 */ 177 178 /* Check for supported chipsets */ 179 vid = pci_cfgregread(0, 0, 0, PCIR_VENDOR, 2); 180 did = pci_cfgregread(0, 0, 0, PCIR_DEVICE, 2); 181 switch (vid) { 182 case 0x8086: 183 switch (did) { 184 case 0x3590: 185 case 0x3592: 186 /* Intel 7520 or 7320 */ 187 pciebar = pci_cfgregread(0, 0, 0, 0xce, 2) << 16; 188 pcie_cfgregopen(pciebar, 0, 255); 189 break; 190 case 0x2580: 191 case 0x2584: 192 case 0x2590: 193 /* Intel 915, 925, or 915GM */ 194 pciebar = pci_cfgregread(0, 0, 0, 0x48, 4); 195 pcie_cfgregopen(pciebar, 0, 255); 196 break; 197 } 198 } 199 200 return(1); 201 #endif 202 } 203 204 static uint32_t 205 pci_docfgregread(int bus, int slot, int func, int reg, int bytes) 206 { 207 208 if (cfgmech == CFGMECH_PCIE && 209 (bus >= pcie_minbus && bus <= pcie_maxbus) && 210 (bus != 0 || !(1 << slot & pcie_badslots))) 211 return (pciereg_cfgread(bus, slot, func, reg, bytes)); 212 else 213 return (pcireg_cfgread(bus, slot, func, reg, bytes)); 214 } 215 216 /* 217 * Read configuration space register 218 */ 219 u_int32_t 220 pci_cfgregread(int bus, int slot, int func, int reg, int bytes) 221 { 222 uint32_t line; 223 224 /* 225 * Some BIOS writers seem to want to ignore the spec and put 226 * 0 in the intline rather than 255 to indicate none. The rest of 227 * the code uses 255 as an invalid IRQ. 228 */ 229 if (reg == PCIR_INTLINE && bytes == 1) { 230 line = pci_docfgregread(bus, slot, func, PCIR_INTLINE, 1); 231 return (pci_i386_map_intline(line)); 232 } 233 return (pci_docfgregread(bus, slot, func, reg, bytes)); 234 } 235 236 /* 237 * Write configuration space register 238 */ 239 void 240 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) 241 { 242 243 if (cfgmech == CFGMECH_PCIE && 244 (bus >= pcie_minbus && bus <= pcie_maxbus) && 245 (bus != 0 || !(1 << slot & pcie_badslots))) 246 pciereg_cfgwrite(bus, slot, func, reg, data, bytes); 247 else 248 pcireg_cfgwrite(bus, slot, func, reg, data, bytes); 249 } 250 251 /* 252 * Configuration space access using direct register operations 253 */ 254 255 /* enable configuration space accesses and return data port address */ 256 static int 257 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 258 { 259 int dataport = 0; 260 261 #ifdef XBOX 262 if (arch_i386_is_xbox) { 263 /* 264 * The Xbox MCPX chipset is a derivative of the nForce 1 265 * chipset. It almost has the same bus layout; some devices 266 * cannot be used, because they have been removed. 267 */ 268 269 /* 270 * Devices 00:00.1 and 00:00.2 used to be memory controllers on 271 * the nForce chipset, but on the Xbox, using them will lockup 272 * the chipset. 273 */ 274 if (bus == 0 && slot == 0 && (func == 1 || func == 2)) 275 return dataport; 276 277 /* 278 * Bus 1 only contains a VGA controller at 01:00.0. When you try 279 * to probe beyond that device, you only get garbage, which 280 * could cause lockups. 281 */ 282 if (bus == 1 && (slot != 0 || func != 0)) 283 return dataport; 284 285 /* 286 * Bus 2 used to contain the AGP controller, but the Xbox MCPX 287 * doesn't have one. Probing it can cause lockups. 288 */ 289 if (bus >= 2) 290 return dataport; 291 } 292 #endif 293 294 if (bus <= PCI_BUSMAX 295 && slot < devmax 296 && func <= PCI_FUNCMAX 297 && reg <= PCI_REGMAX 298 && bytes != 3 299 && (unsigned) bytes <= 4 300 && (reg & (bytes - 1)) == 0) { 301 switch (cfgmech) { 302 case CFGMECH_PCIE: 303 case CFGMECH_1: 304 outl(CONF1_ADDR_PORT, (1 << 31) 305 | (bus << 16) | (slot << 11) 306 | (func << 8) | (reg & ~0x03)); 307 dataport = CONF1_DATA_PORT + (reg & 0x03); 308 break; 309 case CFGMECH_2: 310 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 311 outb(CONF2_FORWARD_PORT, bus); 312 dataport = 0xc000 | (slot << 8) | reg; 313 break; 314 } 315 } 316 return (dataport); 317 } 318 319 /* disable configuration space accesses */ 320 static void 321 pci_cfgdisable(void) 322 { 323 switch (cfgmech) { 324 case CFGMECH_PCIE: 325 case CFGMECH_1: 326 /* 327 * Do nothing for the config mechanism 1 case. 328 * Writing a 0 to the address port can apparently 329 * confuse some bridges and cause spurious 330 * access failures. 331 */ 332 break; 333 case CFGMECH_2: 334 outb(CONF2_ENABLE_PORT, 0); 335 break; 336 } 337 } 338 339 static int 340 pcireg_cfgread(int bus, int slot, int func, int reg, int bytes) 341 { 342 int data = -1; 343 int port; 344 345 mtx_lock_spin(&pcicfg_mtx); 346 port = pci_cfgenable(bus, slot, func, reg, bytes); 347 if (port != 0) { 348 switch (bytes) { 349 case 1: 350 data = inb(port); 351 break; 352 case 2: 353 data = inw(port); 354 break; 355 case 4: 356 data = inl(port); 357 break; 358 } 359 pci_cfgdisable(); 360 } 361 mtx_unlock_spin(&pcicfg_mtx); 362 return (data); 363 } 364 365 static void 366 pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 367 { 368 int port; 369 370 mtx_lock_spin(&pcicfg_mtx); 371 port = pci_cfgenable(bus, slot, func, reg, bytes); 372 if (port != 0) { 373 switch (bytes) { 374 case 1: 375 outb(port, data); 376 break; 377 case 2: 378 outw(port, data); 379 break; 380 case 4: 381 outl(port, data); 382 break; 383 } 384 pci_cfgdisable(); 385 } 386 mtx_unlock_spin(&pcicfg_mtx); 387 } 388 389 #ifndef XEN 390 /* check whether the configuration mechanism has been correctly identified */ 391 static int 392 pci_cfgcheck(int maxdev) 393 { 394 uint32_t id, class; 395 uint8_t header; 396 uint8_t device; 397 int port; 398 399 if (bootverbose) 400 printf("pci_cfgcheck:\tdevice "); 401 402 for (device = 0; device < maxdev; device++) { 403 if (bootverbose) 404 printf("%d ", device); 405 406 port = pci_cfgenable(0, device, 0, 0, 4); 407 id = inl(port); 408 if (id == 0 || id == 0xffffffff) 409 continue; 410 411 port = pci_cfgenable(0, device, 0, 8, 4); 412 class = inl(port) >> 8; 413 if (bootverbose) 414 printf("[class=%06x] ", class); 415 if (class == 0 || (class & 0xf870ff) != 0) 416 continue; 417 418 port = pci_cfgenable(0, device, 0, 14, 1); 419 header = inb(port); 420 if (bootverbose) 421 printf("[hdr=%02x] ", header); 422 if ((header & 0x7e) != 0) 423 continue; 424 425 if (bootverbose) 426 printf("is there (id=%08x)\n", id); 427 428 pci_cfgdisable(); 429 return (1); 430 } 431 if (bootverbose) 432 printf("-- nothing found\n"); 433 434 pci_cfgdisable(); 435 return (0); 436 } 437 438 static int 439 pcireg_cfgopen(void) 440 { 441 uint32_t mode1res, oldval1; 442 uint8_t mode2res, oldval2; 443 444 /* Check for type #1 first. */ 445 oldval1 = inl(CONF1_ADDR_PORT); 446 447 if (bootverbose) { 448 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08x\n", 449 oldval1); 450 } 451 452 cfgmech = CFGMECH_1; 453 devmax = 32; 454 455 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 456 DELAY(1); 457 mode1res = inl(CONF1_ADDR_PORT); 458 outl(CONF1_ADDR_PORT, oldval1); 459 460 if (bootverbose) 461 printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n", mode1res, 462 CONF1_ENABLE_CHK); 463 464 if (mode1res) { 465 if (pci_cfgcheck(32)) 466 return (cfgmech); 467 } 468 469 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 470 mode1res = inl(CONF1_ADDR_PORT); 471 outl(CONF1_ADDR_PORT, oldval1); 472 473 if (bootverbose) 474 printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n", mode1res, 475 CONF1_ENABLE_CHK1); 476 477 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 478 if (pci_cfgcheck(32)) 479 return (cfgmech); 480 } 481 482 /* Type #1 didn't work, so try type #2. */ 483 oldval2 = inb(CONF2_ENABLE_PORT); 484 485 if (bootverbose) { 486 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 487 oldval2); 488 } 489 490 if ((oldval2 & 0xf0) == 0) { 491 492 cfgmech = CFGMECH_2; 493 devmax = 16; 494 495 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 496 mode2res = inb(CONF2_ENABLE_PORT); 497 outb(CONF2_ENABLE_PORT, oldval2); 498 499 if (bootverbose) 500 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 501 mode2res, CONF2_ENABLE_CHK); 502 503 if (mode2res == CONF2_ENABLE_RES) { 504 if (bootverbose) 505 printf("pci_open(2a):\tnow trying mechanism 2\n"); 506 507 if (pci_cfgcheck(16)) 508 return (cfgmech); 509 } 510 } 511 512 /* Nothing worked, so punt. */ 513 cfgmech = CFGMECH_NONE; 514 devmax = 0; 515 return (cfgmech); 516 } 517 518 int 519 pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus) 520 { 521 struct pcie_cfg_list *pcielist; 522 struct pcie_cfg_elem *pcie_array, *elem; 523 #ifdef SMP 524 struct pcpu *pc; 525 #endif 526 vm_offset_t va; 527 uint32_t val1, val2; 528 int i, slot; 529 530 if (!mcfg_enable) 531 return (0); 532 533 if (minbus != 0) 534 return (0); 535 536 #ifndef PAE 537 if (base >= 0x100000000) { 538 if (bootverbose) 539 printf( 540 "PCI: Memory Mapped PCI configuration area base 0x%jx too high\n", 541 (uintmax_t)base); 542 return (0); 543 } 544 #endif 545 546 if (bootverbose) 547 printf("PCIe: Memory Mapped configuration base @ 0x%jx\n", 548 (uintmax_t)base); 549 550 #ifdef SMP 551 SLIST_FOREACH(pc, &cpuhead, pc_allcpu) 552 #endif 553 { 554 555 pcie_array = malloc(sizeof(struct pcie_cfg_elem) * PCIE_CACHE, 556 M_DEVBUF, M_NOWAIT); 557 if (pcie_array == NULL) 558 return (0); 559 560 va = kmem_alloc_nofault(kernel_map, PCIE_CACHE * PAGE_SIZE); 561 if (va == 0) { 562 free(pcie_array, M_DEVBUF); 563 return (0); 564 } 565 566 #ifdef SMP 567 pcielist = &pcie_list[pc->pc_cpuid]; 568 #else 569 pcielist = &pcie_list[0]; 570 #endif 571 TAILQ_INIT(pcielist); 572 for (i = 0; i < PCIE_CACHE; i++) { 573 elem = &pcie_array[i]; 574 elem->vapage = va + (i * PAGE_SIZE); 575 elem->papage = 0; 576 TAILQ_INSERT_HEAD(pcielist, elem, elem); 577 } 578 } 579 580 pcie_base = base; 581 pcie_minbus = minbus; 582 pcie_maxbus = maxbus; 583 cfgmech = CFGMECH_PCIE; 584 devmax = 32; 585 586 /* 587 * On some AMD systems, some of the devices on bus 0 are 588 * inaccessible using memory-mapped PCI config access. Walk 589 * bus 0 looking for such devices. For these devices, we will 590 * fall back to using type 1 config access instead. 591 */ 592 if (pci_cfgregopen() != 0) { 593 for (slot = 0; slot < 32; slot++) { 594 val1 = pcireg_cfgread(0, slot, 0, 0, 4); 595 if (val1 == 0xffffffff) 596 continue; 597 598 val2 = pciereg_cfgread(0, slot, 0, 0, 4); 599 if (val2 != val1) 600 pcie_badslots |= (1 << slot); 601 } 602 } 603 604 return (1); 605 } 606 #endif /* !XEN */ 607 608 #define PCIE_PADDR(bar, reg, bus, slot, func) \ 609 ((bar) | \ 610 (((bus) & 0xff) << 20) | \ 611 (((slot) & 0x1f) << 15) | \ 612 (((func) & 0x7) << 12) | \ 613 ((reg) & 0xfff)) 614 615 /* 616 * Find an element in the cache that matches the physical page desired, or 617 * create a new mapping from the least recently used element. 618 * A very simple LRU algorithm is used here, does it need to be more 619 * efficient? 620 */ 621 static __inline struct pcie_cfg_elem * 622 pciereg_findelem(vm_paddr_t papage) 623 { 624 struct pcie_cfg_list *pcielist; 625 struct pcie_cfg_elem *elem; 626 627 pcielist = &pcie_list[PCPU_GET(cpuid)]; 628 TAILQ_FOREACH(elem, pcielist, elem) { 629 if (elem->papage == papage) 630 break; 631 } 632 633 if (elem == NULL) { 634 elem = TAILQ_LAST(pcielist, pcie_cfg_list); 635 if (elem->papage != 0) { 636 pmap_kremove(elem->vapage); 637 invlpg(elem->vapage); 638 } 639 pmap_kenter(elem->vapage, papage); 640 elem->papage = papage; 641 } 642 643 if (elem != TAILQ_FIRST(pcielist)) { 644 TAILQ_REMOVE(pcielist, elem, elem); 645 TAILQ_INSERT_HEAD(pcielist, elem, elem); 646 } 647 return (elem); 648 } 649 650 static int 651 pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg, 652 unsigned bytes) 653 { 654 struct pcie_cfg_elem *elem; 655 volatile vm_offset_t va; 656 vm_paddr_t pa, papage; 657 int data = -1; 658 659 if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 || 660 func > PCI_FUNCMAX || reg >= 0x1000 || bytes > 4 || bytes == 3) 661 return (-1); 662 663 critical_enter(); 664 pa = PCIE_PADDR(pcie_base, reg, bus, slot, func); 665 papage = pa & ~PAGE_MASK; 666 elem = pciereg_findelem(papage); 667 va = elem->vapage | (pa & PAGE_MASK); 668 669 switch (bytes) { 670 case 4: 671 data = *(volatile uint32_t *)(va); 672 break; 673 case 2: 674 data = *(volatile uint16_t *)(va); 675 break; 676 case 1: 677 data = *(volatile uint8_t *)(va); 678 break; 679 } 680 681 critical_exit(); 682 return (data); 683 } 684 685 static void 686 pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data, 687 unsigned bytes) 688 { 689 struct pcie_cfg_elem *elem; 690 volatile vm_offset_t va; 691 vm_paddr_t pa, papage; 692 693 if (bus < pcie_minbus || bus > pcie_maxbus || slot >= 32 || 694 func > PCI_FUNCMAX || reg >= 0x1000) 695 return; 696 697 critical_enter(); 698 pa = PCIE_PADDR(pcie_base, reg, bus, slot, func); 699 papage = pa & ~PAGE_MASK; 700 elem = pciereg_findelem(papage); 701 va = elem->vapage | (pa & PAGE_MASK); 702 703 switch (bytes) { 704 case 4: 705 *(volatile uint32_t *)(va) = data; 706 break; 707 case 2: 708 *(volatile uint16_t *)(va) = data; 709 break; 710 case 1: 711 *(volatile uint8_t *)(va) = data; 712 break; 713 } 714 715 critical_exit(); 716 } 717