OSDN Git Service

Fix IO access functions on linux+sysfs.
[android-x86/external-libpciaccess.git] / src / x86_pci.c
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
39 static int
40 x86_enable_io(void)
41 {
42     if (!ioperm(0, 0xffff, 1))
43         return 0;
44     return errno;
45 }
46
47 static int
48 x86_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
59 static int
60 x86_enable_io(void)
61 {
62     if (!iopl(3))
63         return 0;
64     return errno;
65 }
66
67 static int
68 x86_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 */
80 typedef BYTE bool;
81 typedef struct tagPhysStruct {
82     DWORD64 dwPhysMemSizeInBytes;
83     DWORD64 pvPhysAddress;
84     DWORD64 PhysicalMemoryHandle;
85     DWORD64 pvPhysMemLin;
86     DWORD64 pvPhysSection;
87 } tagPhysStruct;
88
89 typedef bool  (_stdcall* INITIALIZEWINIO)(void);
90 typedef void  (_stdcall* SHUTDOWNWINIO)(void);
91 typedef bool  (_stdcall* GETPORTVAL)(WORD,PDWORD,BYTE);
92 typedef bool  (_stdcall* SETPORTVAL)(WORD,DWORD,BYTE);
93 typedef PBYTE (_stdcall* MAPPHYSTOLIN)(tagPhysStruct*);
94 typedef bool  (_stdcall* UNMAPPHYSMEM)(tagPhysStruct*);
95
96 SHUTDOWNWINIO ShutdownWinIo;
97 GETPORTVAL GetPortVal;
98 SETPORTVAL SetPortVal;
99 INITIALIZEWINIO InitializeWinIo;
100 MAPPHYSTOLIN MapPhysToLin;
101 UNMAPPHYSMEM UnmapPhysicalMemory;
102
103 static int
104 x86_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
147 static int
148 x86_disable_io(void)
149 {
150     ShutdownWinIo();
151     return 1;
152 }
153
154 static inline uint8_t
155 inb(uint16_t port)
156 {
157     DWORD pv;
158
159     if (GetPortVal(port, &pv, 1))
160       return (uint8_t)pv;
161     return 0;
162 }
163
164 static inline uint16_t
165 inw(uint16_t port)
166 {
167     DWORD pv;
168
169     if (GetPortVal(port, &pv, 2))
170       return (uint16_t)pv;
171     return 0;
172 }
173
174 static inline uint32_t
175 inl(uint16_t port)
176 {
177     DWORD pv;
178
179     if (GetPortVal(port, &pv, 4))
180         return (uint32_t)pv;
181     return 0;
182 }
183
184 static inline void
185 outb(uint8_t value, uint16_t port)
186 {
187     SetPortVal(port, value, 1);
188 }
189
190 static inline void
191 outw(uint16_t value, uint16_t port)
192 {
193     SetPortVal(port, value, 2);
194 }
195
196 static inline void
197 outl(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
230 struct 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
236 static int
237 pci_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
252 static int
253 pci_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
287 static int
288 pci_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
322 static int
323 pci_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
334 static int
335 pci_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
371 static int
372 pci_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. */
409 static int
410 pci_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
432 static int
433 pci_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  */
449 static int
450 pci_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 */
479 static int
480 pci_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 */
496 static uint32_t
497 get_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 */
506 static unsigned
507 get_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
527 static int
528 pci_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
603 static int
604 pci_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
619 static int
620 pci_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
636 static int
637 pci_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
657 static int
658 pci_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
666 static int
667 pci_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
691 static int
692 pci_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
718 static void
719 pci_system_x86_destroy(void)
720 {
721     x86_disable_io();
722 }
723
724 static struct pci_io_handle *
725 pci_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
737 static void
738 pci_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
745 static uint32_t
746 pci_device_x86_read32(struct pci_io_handle *handle, uint32_t reg)
747 {
748     return inl(reg + handle->base);
749 }
750
751 static uint16_t
752 pci_device_x86_read16(struct pci_io_handle *handle, uint32_t reg)
753 {
754     return inw(reg + handle->base);
755 }
756
757 static uint8_t
758 pci_device_x86_read8(struct pci_io_handle *handle, uint32_t reg)
759 {
760     return inb(reg + handle->base);
761 }
762
763 static void
764 pci_device_x86_write32(struct pci_io_handle *handle, uint32_t reg,
765                        uint32_t data)
766 {
767     outl(data, reg + handle->base);
768 }
769
770 static void
771 pci_device_x86_write16(struct pci_io_handle *handle, uint32_t reg,
772                        uint16_t data)
773 {
774     outw(data, reg + handle->base);
775 }
776
777 static void
778 pci_device_x86_write8(struct pci_io_handle *handle, uint32_t reg,
779                       uint8_t data)
780 {
781     outb(data, reg + handle->base);
782 }
783
784 static int
785 pci_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
800 static int
801 pci_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
813 static 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
834 static 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
854 pci_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, &reg, 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, &reg, 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, &reg, 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, &reg, 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 }