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, &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}
940