x86_pci.c revision 6a94483f
1/* 2 * Copyright (c) 2009, 2012 Samuel Thibault 3 * Heavily inspired from the freebsd, netbsd, and openbsd backends 4 * (C) Copyright Eric Anholt 2006 5 * (C) Copyright IBM Corporation 2006 6 * Copyright (c) 2008 Juan Romero Pardines 7 * Copyright (c) 2008 Mark Kettenis 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22#define _GNU_SOURCE 23#include <unistd.h> 24#include <stdio.h> 25#include <stdlib.h> 26#include <errno.h> 27#include <fcntl.h> 28#include <sys/mman.h> 29#include <string.h> 30#include <strings.h> 31 32#include "pciaccess.h" 33#include "pciaccess_private.h" 34 35#if defined(__GNU__) 36 37#include <sys/io.h> 38 39static int 40x86_enable_io(void) 41{ 42 if (!ioperm(0, 0xffff, 1)) 43 return 0; 44 return errno; 45} 46 47static int 48x86_disable_io(void) 49{ 50 if (!ioperm(0, 0xffff, 0)) 51 return 0; 52 return errno; 53} 54 55#elif defined(__GLIBC__) 56 57#include <sys/io.h> 58 59static int 60x86_enable_io(void) 61{ 62 if (!iopl(3)) 63 return 0; 64 return errno; 65} 66 67static int 68x86_disable_io(void) 69{ 70 if (!iopl(0)) 71 return 0; 72 return errno; 73} 74 75#elif defined(__CYGWIN__) 76 77#include <windows.h> 78 79/* WinIo declarations */ 80typedef BYTE bool; 81typedef struct tagPhysStruct { 82 DWORD64 dwPhysMemSizeInBytes; 83 DWORD64 pvPhysAddress; 84 DWORD64 PhysicalMemoryHandle; 85 DWORD64 pvPhysMemLin; 86 DWORD64 pvPhysSection; 87} tagPhysStruct; 88 89typedef bool (_stdcall* INITIALIZEWINIO)(void); 90typedef void (_stdcall* SHUTDOWNWINIO)(void); 91typedef bool (_stdcall* GETPORTVAL)(WORD,PDWORD,BYTE); 92typedef bool (_stdcall* SETPORTVAL)(WORD,DWORD,BYTE); 93typedef PBYTE (_stdcall* MAPPHYSTOLIN)(tagPhysStruct*); 94typedef bool (_stdcall* UNMAPPHYSMEM)(tagPhysStruct*); 95 96SHUTDOWNWINIO ShutdownWinIo; 97GETPORTVAL GetPortVal; 98SETPORTVAL SetPortVal; 99INITIALIZEWINIO InitializeWinIo; 100MAPPHYSTOLIN MapPhysToLin; 101UNMAPPHYSMEM UnmapPhysicalMemory; 102 103static int 104x86_enable_io(void) 105{ 106 HMODULE lib = NULL; 107 108 if ((GetVersion() & 0x80000000) == 0) { 109 /* running on NT, try WinIo version 3 (32 or 64 bits) */ 110#ifdef WIN64 111 lib = LoadLibrary("WinIo64.dll"); 112#else 113 lib = LoadLibrary("WinIo32.dll"); 114#endif 115 } 116 117 if (!lib) { 118 fprintf(stderr, "Failed to load WinIo library.\n"); 119 return 1; 120 } 121 122#define GETPROC(n, d) \ 123 n = (d) GetProcAddress(lib, #n); \ 124 if (!n) { \ 125 fprintf(stderr, "Failed to load " #n " function.\n"); \ 126 return 1; \ 127 } 128 129 GETPROC(InitializeWinIo, INITIALIZEWINIO); 130 GETPROC(ShutdownWinIo, SHUTDOWNWINIO); 131 GETPROC(GetPortVal, GETPORTVAL); 132 GETPROC(SetPortVal, SETPORTVAL); 133 GETPROC(MapPhysToLin, MAPPHYSTOLIN); 134 GETPROC(UnmapPhysicalMemory, UNMAPPHYSMEM); 135 136#undef GETPROC 137 138 if (!InitializeWinIo()) { 139 fprintf(stderr, "Failed to initialize WinIo.\n" 140 "NOTE: WinIo.dll and WinIo.sys must be in the same directory as the executable!\n"); 141 return 0; 142 } 143 144 return 0; 145} 146 147static int 148x86_disable_io(void) 149{ 150 ShutdownWinIo(); 151 return 1; 152} 153 154static inline uint8_t 155inb(uint16_t port) 156{ 157 DWORD pv; 158 159 if (GetPortVal(port, &pv, 1)) 160 return (uint8_t)pv; 161 return 0; 162} 163 164static inline uint16_t 165inw(uint16_t port) 166{ 167 DWORD pv; 168 169 if (GetPortVal(port, &pv, 2)) 170 return (uint16_t)pv; 171 return 0; 172} 173 174static inline uint32_t 175inl(uint16_t port) 176{ 177 DWORD pv; 178 179 if (GetPortVal(port, &pv, 4)) 180 return (uint32_t)pv; 181 return 0; 182} 183 184static inline void 185outb(uint8_t value, uint16_t port) 186{ 187 SetPortVal(port, value, 1); 188} 189 190static inline void 191outw(uint16_t value, uint16_t port) 192{ 193 SetPortVal(port, value, 2); 194} 195 196static inline void 197outl(uint32_t value, uint16_t port) 198{ 199 SetPortVal(port, value, 4); 200} 201 202#else 203 204#error How to enable IO ports on this system? 205 206#endif 207 208#define PCI_VENDOR(reg) ((reg) & 0xFFFF) 209#define PCI_VENDOR_INVALID 0xFFFF 210 211#define PCI_VENDOR_ID 0x00 212#define PCI_SUB_VENDOR_ID 0x2c 213#define PCI_VENDOR_ID_COMPAQ 0x0e11 214#define PCI_VENDOR_ID_INTEL 0x8086 215 216#define PCI_DEVICE(reg) (((reg) >> 16) & 0xFFFF) 217#define PCI_DEVICE_INVALID 0xFFFF 218 219#define PCI_CLASS 0x08 220#define PCI_CLASS_DEVICE 0x0a 221#define PCI_CLASS_DISPLAY_VGA 0x0300 222#define PCI_CLASS_BRIDGE_HOST 0x0600 223 224#define PCIC_DISPLAY 0x03 225#define PCIS_DISPLAY_VGA 0x00 226 227#define PCI_HDRTYPE 0x0E 228#define PCI_IRQ 0x3C 229 230struct pci_system_x86 { 231 struct pci_system system; 232 int (*read)(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, void *data, unsigned size); 233 int (*write)(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, const void *data, unsigned size); 234}; 235 236static int 237pci_system_x86_conf1_probe(void) 238{ 239 unsigned long sav; 240 int res = ENODEV; 241 242 outb(0x01, 0xCFB); 243 sav = inl(0xCF8); 244 outl(0x80000000, 0xCF8); 245 if (inl(0xCF8) == 0x80000000) 246 res = 0; 247 outl(sav, 0xCF8); 248 249 return res; 250} 251 252static int 253pci_system_x86_conf1_read(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, void *data, unsigned size) 254{ 255 unsigned addr = 0xCFC + (reg & 3); 256 unsigned long sav; 257 int ret = 0; 258 259 if (bus >= 0x100 || dev >= 32 || func >= 8 || reg >= 0x100 || size > 4 || size == 3) 260 return EIO; 261 262 sav = inl(0xCF8); 263 outl(0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3), 0xCF8); 264 /* NOTE: x86 is already LE */ 265 switch (size) { 266 case 1: { 267 uint8_t *val = data; 268 *val = inb(addr); 269 break; 270 } 271 case 2: { 272 uint16_t *val = data; 273 *val = inw(addr); 274 break; 275 } 276 case 4: { 277 uint32_t *val = data; 278 *val = inl(addr); 279 break; 280 } 281 } 282 outl(sav, 0xCF8); 283 284 return ret; 285} 286 287static int 288pci_system_x86_conf1_write(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, const void *data, unsigned size) 289{ 290 unsigned addr = 0xCFC + (reg & 3); 291 unsigned long sav; 292 int ret = 0; 293 294 if (bus >= 0x100 || dev >= 32 || func >= 8 || reg >= 0x100 || size > 4 || size == 3) 295 return EIO; 296 297 sav = inl(0xCF8); 298 outl(0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3), 0xCF8); 299 /* NOTE: x86 is already LE */ 300 switch (size) { 301 case 1: { 302 const uint8_t *val = data; 303 outb(*val, addr); 304 break; 305 } 306 case 2: { 307 const uint16_t *val = data; 308 outw(*val, addr); 309 break; 310 } 311 case 4: { 312 const uint32_t *val = data; 313 outl(*val, addr); 314 break; 315 } 316 } 317 outl(sav, 0xCF8); 318 319 return ret; 320} 321 322static int 323pci_system_x86_conf2_probe(void) 324{ 325 outb(0, 0xCFB); 326 outb(0, 0xCF8); 327 outb(0, 0xCFA); 328 if (inb(0xCF8) == 0 && inb(0xCFA) == 0) 329 return 0; 330 331 return ENODEV; 332} 333 334static int 335pci_system_x86_conf2_read(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, void *data, unsigned size) 336{ 337 unsigned addr = 0xC000 | dev << 8 | reg; 338 int ret = 0; 339 340 if (bus >= 0x100 || dev >= 16 || func >= 8 || reg >= 0x100) 341 return EIO; 342 343 outb((func << 1) | 0xF0, 0xCF8); 344 outb(bus, 0xCFA); 345 /* NOTE: x86 is already LE */ 346 switch (size) { 347 case 1: { 348 uint8_t *val = data; 349 *val = inb(addr); 350 break; 351 } 352 case 2: { 353 uint16_t *val = data; 354 *val = inw(addr); 355 break; 356 } 357 case 4: { 358 uint32_t *val = data; 359 *val = inl(addr); 360 break; 361 } 362 default: 363 ret = EIO; 364 break; 365 } 366 outb(0, 0xCF8); 367 368 return ret; 369} 370 371static int 372pci_system_x86_conf2_write(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, const void *data, unsigned size) 373{ 374 unsigned addr = 0xC000 | dev << 8 | reg; 375 int ret = 0; 376 377 if (bus >= 0x100 || dev >= 16 || func >= 8 || reg >= 0x100) 378 return EIO; 379 380 outb((func << 1) | 0xF0, 0xCF8); 381 outb(bus, 0xCFA); 382 /* NOTE: x86 is already LE */ 383 switch (size) { 384 case 1: { 385 const uint8_t *val = data; 386 outb(*val, addr); 387 break; 388 } 389 case 2: { 390 const uint16_t *val = data; 391 outw(*val, addr); 392 break; 393 } 394 case 4: { 395 const uint32_t *val = data; 396 outl(*val, addr); 397 break; 398 } 399 default: 400 ret = EIO; 401 break; 402 } 403 outb(0, 0xCF8); 404 405 return ret; 406} 407 408/* Check that this really looks like a PCI configuration. */ 409static int 410pci_system_x86_check(struct pci_system_x86 *pci_sys_x86) 411{ 412 int dev; 413 uint16_t class, vendor; 414 415 /* Look on bus 0 for a device that is a host bridge, a VGA card, 416 * or an intel or compaq device. */ 417 418 for (dev = 0; dev < 32; dev++) { 419 if (pci_sys_x86->read(0, dev, 0, PCI_CLASS_DEVICE, &class, sizeof(class))) 420 continue; 421 if (class == PCI_CLASS_BRIDGE_HOST || class == PCI_CLASS_DISPLAY_VGA) 422 return 0; 423 if (pci_sys_x86->read(0, dev, 0, PCI_VENDOR_ID, &vendor, sizeof(vendor))) 424 continue; 425 if (vendor == PCI_VENDOR_ID_INTEL || class == PCI_VENDOR_ID_COMPAQ) 426 return 0; 427 } 428 429 return ENODEV; 430} 431 432static int 433pci_nfuncs(struct pci_system_x86 *pci_sys_x86, int bus, int dev) 434{ 435 uint8_t hdr; 436 int err; 437 438 err = pci_sys_x86->read(bus, dev, 0, PCI_HDRTYPE, &hdr, sizeof(hdr)); 439 440 if (err) 441 return err; 442 443 return hdr & 0x80 ? 8 : 1; 444} 445 446/** 447 * Read a VGA rom using the 0xc0000 mapping. 448 */ 449static int 450pci_device_x86_read_rom(struct pci_device *dev, void *buffer) 451{ 452 void *bios; 453 int memfd; 454 455 if ((dev->device_class & 0x00ffff00) != 456 ((PCIC_DISPLAY << 16) | ( PCIS_DISPLAY_VGA << 8))) { 457 return ENOSYS; 458 } 459 460 memfd = open("/dev/mem", O_RDONLY | O_CLOEXEC); 461 if (memfd == -1) 462 return errno; 463 464 bios = mmap(NULL, dev->rom_size, PROT_READ, 0, memfd, 0xc0000); 465 if (bios == MAP_FAILED) { 466 close(memfd); 467 return errno; 468 } 469 470 memcpy(buffer, bios, dev->rom_size); 471 472 munmap(bios, dev->rom_size); 473 close(memfd); 474 475 return 0; 476} 477 478/** Returns the number of regions (base address registers) the device has */ 479static int 480pci_device_x86_get_num_regions(uint8_t header_type) 481{ 482 switch (header_type & 0x7f) { 483 case 0: 484 return 6; 485 case 1: 486 return 2; 487 case 2: 488 return 1; 489 default: 490 fprintf(stderr,"unknown header type %02x\n", header_type); 491 return 0; 492 } 493} 494 495/** Masks out the flag bigs of the base address register value */ 496static uint32_t 497get_map_base( uint32_t val ) 498{ 499 if (val & 0x01) 500 return val & ~0x03; 501 else 502 return val & ~0x0f; 503} 504 505/** Returns the size of a region based on the all-ones test value */ 506static unsigned 507get_test_val_size( uint32_t testval ) 508{ 509 unsigned size = 1; 510 511 if (testval == 0) 512 return 0; 513 514 /* Mask out the flag bits */ 515 testval = get_map_base( testval ); 516 if (!testval) 517 return 0; 518 519 while ((testval & 1) == 0) { 520 size <<= 1; 521 testval >>= 1; 522 } 523 524 return size; 525} 526 527static int 528pci_device_x86_probe(struct pci_device *dev) 529{ 530 uint8_t irq, hdrtype; 531 int err, i, bar; 532 533 /* Many of the fields were filled in during initial device enumeration. 534 * At this point, we need to fill in regions, rom_size, and irq. 535 */ 536 537 err = pci_device_cfg_read_u8(dev, &irq, PCI_IRQ); 538 if (err) 539 return err; 540 dev->irq = irq; 541 542 err = pci_device_cfg_read_u8(dev, &hdrtype, PCI_HDRTYPE); 543 if (err) 544 return err; 545 546 bar = 0x10; 547 for (i = 0; i < pci_device_x86_get_num_regions(hdrtype); i++, bar += 4) { 548 uint32_t addr, testval; 549 550 /* Get the base address */ 551 err = pci_device_cfg_read_u32(dev, &addr, bar); 552 if (err != 0) 553 continue; 554 555 /* Test write all ones to the register, then restore it. */ 556 err = pci_device_cfg_write_u32(dev, 0xffffffff, bar); 557 if (err != 0) 558 continue; 559 pci_device_cfg_read_u32(dev, &testval, bar); 560 err = pci_device_cfg_write_u32(dev, addr, bar); 561 562 if (addr & 0x01) 563 dev->regions[i].is_IO = 1; 564 if (addr & 0x04) 565 dev->regions[i].is_64 = 1; 566 if (addr & 0x08) 567 dev->regions[i].is_prefetchable = 1; 568 569 /* Set the size */ 570 dev->regions[i].size = get_test_val_size(testval); 571 572 /* Set the base address value */ 573 if (dev->regions[i].is_64) { 574 uint32_t top; 575 576 err = pci_device_cfg_read_u32(dev, &top, bar + 4); 577 if (err != 0) 578 continue; 579 580 dev->regions[i].base_addr = ((uint64_t)top << 32) | 581 get_map_base(addr); 582 bar += 4; 583 i++; 584 } else { 585 dev->regions[i].base_addr = get_map_base(addr); 586 } 587 } 588 589 /* If it's a VGA device, set up the rom size for read_rom using the 590 * 0xc0000 mapping. 591 */ 592 if ((dev->device_class & 0x00ffff00) == 593 ((PCIC_DISPLAY << 16) | (PCIS_DISPLAY_VGA << 8))) 594 { 595 dev->rom_size = 64 * 1024; 596 } 597 598 return 0; 599} 600 601#if defined(__CYGWIN__) 602 603static int 604pci_device_x86_map_range(struct pci_device *dev, 605 struct pci_device_mapping *map) 606{ 607 tagPhysStruct phys; 608 609 phys.pvPhysAddress = (DWORD64)(DWORD32)map->base; 610 phys.dwPhysMemSizeInBytes = map->size; 611 612 map->memory = (PDWORD)MapPhysToLin(&phys); 613 if (map->memory == NULL) 614 return EFAULT; 615 616 return 0; 617} 618 619static int 620pci_device_x86_unmap_range(struct pci_device *dev, 621 struct pci_device_mapping *map) 622{ 623 tagPhysStruct phys; 624 625 phys.pvPhysAddress = (DWORD64)(DWORD32)map->base; 626 phys.dwPhysMemSizeInBytes = map->size; 627 628 if (!UnmapPhysicalMemory(&phys)) 629 return EFAULT; 630 631 return 0; 632} 633 634#else 635 636static int 637pci_device_x86_map_range(struct pci_device *dev, 638 struct pci_device_mapping *map) 639{ 640 int memfd = open("/dev/mem", O_RDWR | O_CLOEXEC); 641 int prot = PROT_READ; 642 643 if (memfd == -1) 644 return errno; 645 646 if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE) 647 prot |= PROT_WRITE; 648 649 map->memory = mmap(NULL, map->size, prot, MAP_SHARED, memfd, map->base); 650 close(memfd); 651 if (map->memory == MAP_FAILED) 652 return errno; 653 654 return 0; 655} 656 657static int 658pci_device_x86_unmap_range(struct pci_device *dev, 659 struct pci_device_mapping *map) 660{ 661 return pci_device_generic_unmap_range(dev, map); 662} 663 664#endif 665 666static int 667pci_device_x86_read(struct pci_device *dev, void *data, 668 pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read) 669{ 670 struct pci_system_x86 *pci_sys_x86 = (struct pci_system_x86 *) pci_sys; 671 int err; 672 673 *bytes_read = 0; 674 while (size > 0) { 675 int toread = 1 << (ffs(0x4 + (offset & 0x03)) - 1); 676 if (toread > size) 677 toread = size; 678 679 err = pci_sys_x86->read(dev->bus, dev->dev, dev->func, offset, data, toread); 680 if (err) 681 return err; 682 683 offset += toread; 684 data = (char*)data + toread; 685 size -= toread; 686 *bytes_read += toread; 687 } 688 return 0; 689} 690 691static int 692pci_device_x86_write(struct pci_device *dev, const void *data, 693 pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written) 694{ 695 struct pci_system_x86 *pci_sys_x86 = (struct pci_system_x86 *) pci_sys; 696 int err; 697 698 *bytes_written = 0; 699 while (size > 0) { 700 int towrite = 4; 701 if (towrite > size) 702 towrite = size; 703 if (towrite > 4 - (offset & 0x3)) 704 towrite = 4 - (offset & 0x3); 705 706 err = pci_sys_x86->write(dev->bus, dev->dev, dev->func, offset, data, towrite); 707 if (err) 708 return err; 709 710 offset += towrite; 711 data = (const char*)data + towrite; 712 size -= towrite; 713 *bytes_written += towrite; 714 } 715 return 0; 716} 717 718static void 719pci_system_x86_destroy(void) 720{ 721 x86_disable_io(); 722} 723 724static struct pci_io_handle * 725pci_device_x86_open_legacy_io(struct pci_io_handle *ret, 726 struct pci_device *dev, pciaddr_t base, pciaddr_t size) 727{ 728 x86_enable_io(); 729 730 ret->base = base; 731 ret->size = size; 732 ret->is_legacy = 1; 733 734 return ret; 735} 736 737static void 738pci_device_x86_close_io(struct pci_device *dev, struct pci_io_handle *handle) 739{ 740 /* Like in the Linux case, do not disable I/O, as it may be opened several 741 * times, and closed fewer times. */ 742 /* x86_disable_io(); */ 743} 744 745static uint32_t 746pci_device_x86_read32(struct pci_io_handle *handle, uint32_t reg) 747{ 748 return inl(reg + handle->base); 749} 750 751static uint16_t 752pci_device_x86_read16(struct pci_io_handle *handle, uint32_t reg) 753{ 754 return inw(reg + handle->base); 755} 756 757static uint8_t 758pci_device_x86_read8(struct pci_io_handle *handle, uint32_t reg) 759{ 760 return inb(reg + handle->base); 761} 762 763static void 764pci_device_x86_write32(struct pci_io_handle *handle, uint32_t reg, 765 uint32_t data) 766{ 767 outl(data, reg + handle->base); 768} 769 770static void 771pci_device_x86_write16(struct pci_io_handle *handle, uint32_t reg, 772 uint16_t data) 773{ 774 outw(data, reg + handle->base); 775} 776 777static void 778pci_device_x86_write8(struct pci_io_handle *handle, uint32_t reg, 779 uint8_t data) 780{ 781 outb(data, reg + handle->base); 782} 783 784static int 785pci_device_x86_map_legacy(struct pci_device *dev, pciaddr_t base, 786 pciaddr_t size, unsigned map_flags, void **addr) 787{ 788 struct pci_device_mapping map; 789 int err; 790 791 map.base = base; 792 map.size = size; 793 map.flags = map_flags; 794 err = pci_device_x86_map_range(dev, &map); 795 *addr = map.memory; 796 797 return err; 798} 799 800static int 801pci_device_x86_unmap_legacy(struct pci_device *dev, void *addr, 802 pciaddr_t size) 803{ 804 struct pci_device_mapping map; 805 806 map.size = size; 807 map.flags = 0; 808 map.memory = addr; 809 810 return pci_device_x86_unmap_range(dev, &map); 811} 812 813static const struct pci_system_methods x86_pci_methods = { 814 .destroy = pci_system_x86_destroy, 815 .read_rom = pci_device_x86_read_rom, 816 .probe = pci_device_x86_probe, 817 .map_range = pci_device_x86_map_range, 818 .unmap_range = pci_device_x86_unmap_range, 819 .read = pci_device_x86_read, 820 .write = pci_device_x86_write, 821 .fill_capabilities = pci_fill_capabilities_generic, 822 .open_legacy_io = pci_device_x86_open_legacy_io, 823 .close_io = pci_device_x86_close_io, 824 .read32 = pci_device_x86_read32, 825 .read16 = pci_device_x86_read16, 826 .read8 = pci_device_x86_read8, 827 .write32 = pci_device_x86_write32, 828 .write16 = pci_device_x86_write16, 829 .write8 = pci_device_x86_write8, 830 .map_legacy = pci_device_x86_map_legacy, 831 .unmap_legacy = pci_device_x86_unmap_legacy, 832}; 833 834static int pci_probe(struct pci_system_x86 *pci_sys_x86) 835{ 836 if (pci_system_x86_conf1_probe() == 0) { 837 pci_sys_x86->read = pci_system_x86_conf1_read; 838 pci_sys_x86->write = pci_system_x86_conf1_write; 839 if (pci_system_x86_check(pci_sys_x86) == 0) 840 return 0; 841 } 842 843 if (pci_system_x86_conf2_probe() == 0) { 844 pci_sys_x86->read = pci_system_x86_conf2_read; 845 pci_sys_x86->write = pci_system_x86_conf2_write; 846 if (pci_system_x86_check(pci_sys_x86) == 0) 847 return 0; 848 } 849 850 return ENODEV; 851} 852 853_pci_hidden int 854pci_system_x86_create(void) 855{ 856 struct pci_device_private *device; 857 int ret, bus, dev, ndevs, func, nfuncs; 858 struct pci_system_x86 *pci_sys_x86; 859 uint32_t reg; 860 861 ret = x86_enable_io(); 862 if (ret) 863 return ret; 864 865 pci_sys_x86 = calloc(1, sizeof(struct pci_system_x86)); 866 if (pci_sys_x86 == NULL) { 867 x86_disable_io(); 868 return ENOMEM; 869 } 870 pci_sys = &pci_sys_x86->system; 871 872 ret = pci_probe(pci_sys_x86); 873 if (ret) { 874 x86_disable_io(); 875 free(pci_sys_x86); 876 pci_sys = NULL; 877 return ret; 878 } 879 880 pci_sys->methods = &x86_pci_methods; 881 882 ndevs = 0; 883 for (bus = 0; bus < 256; bus++) { 884 for (dev = 0; dev < 32; dev++) { 885 nfuncs = pci_nfuncs(pci_sys_x86, bus, dev); 886 for (func = 0; func < nfuncs; func++) { 887 if (pci_sys_x86->read(bus, dev, func, PCI_VENDOR_ID, ®, sizeof(reg)) != 0) 888 continue; 889 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID || 890 PCI_VENDOR(reg) == 0) 891 continue; 892 ndevs++; 893 } 894 } 895 } 896 897 pci_sys->num_devices = ndevs; 898 pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private)); 899 if (pci_sys->devices == NULL) { 900 x86_disable_io(); 901 free(pci_sys_x86); 902 pci_sys = NULL; 903 return ENOMEM; 904 } 905 906 device = pci_sys->devices; 907 for (bus = 0; bus < 256; bus++) { 908 for (dev = 0; dev < 32; dev++) { 909 nfuncs = pci_nfuncs(pci_sys_x86, bus, dev); 910 for (func = 0; func < nfuncs; func++) { 911 if (pci_sys_x86->read(bus, dev, func, PCI_VENDOR_ID, ®, sizeof(reg)) != 0) 912 continue; 913 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID || 914 PCI_VENDOR(reg) == 0) 915 continue; 916 device->base.domain = 0; 917 device->base.bus = bus; 918 device->base.dev = dev; 919 device->base.func = func; 920 device->base.vendor_id = PCI_VENDOR(reg); 921 device->base.device_id = PCI_DEVICE(reg); 922 923 if (pci_sys_x86->read(bus, dev, func, PCI_CLASS, ®, sizeof(reg)) != 0) 924 continue; 925 device->base.device_class = reg >> 8; 926 device->base.revision = reg & 0xFF; 927 928 if (pci_sys_x86->read(bus, dev, func, PCI_SUB_VENDOR_ID, ®, sizeof(reg)) != 0) 929 continue; 930 device->base.subvendor_id = PCI_VENDOR(reg); 931 device->base.subdevice_id = PCI_DEVICE(reg); 932 933 device++; 934 } 935 } 936 } 937 938 return 0; 939} 940