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