x86_pci.c revision dc7d6647
1/*
2 * Copyright (c) 2018 Damien Zammit
3 * Copyright (c) 2017 Joan Lledó
4 * Copyright (c) 2009, 2012 Samuel Thibault
5 * Heavily inspired from the freebsd, netbsd, and openbsd backends
6 * (C) Copyright Eric Anholt 2006
7 * (C) Copyright IBM Corporation 2006
8 * Copyright (c) 2008 Juan Romero Pardines
9 * Copyright (c) 2008 Mark Kettenis
10 *
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "x86_pci.h"
28
29#include <unistd.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <errno.h>
33#include <fcntl.h>
34#include <sys/mman.h>
35#include <string.h>
36#include <strings.h>
37
38#include "pciaccess.h"
39#include "pciaccess_private.h"
40
41#if defined(__GNU__)
42
43#include <sys/io.h>
44
45int
46x86_enable_io(void)
47{
48    if (!ioperm(0, 0xffff, 1))
49        return 0;
50    return errno;
51}
52
53int
54x86_disable_io(void)
55{
56    if (!ioperm(0, 0xffff, 0))
57        return 0;
58    return errno;
59}
60
61#elif defined(__GLIBC__)
62
63#include <sys/io.h>
64
65static int
66x86_enable_io(void)
67{
68    if (!iopl(3))
69        return 0;
70    return errno;
71}
72
73static int
74x86_disable_io(void)
75{
76    if (!iopl(0))
77        return 0;
78    return errno;
79}
80
81#elif defined(__CYGWIN__)
82
83#include <windows.h>
84
85/* WinIo declarations */
86typedef BYTE bool;
87typedef struct tagPhysStruct {
88    DWORD64 dwPhysMemSizeInBytes;
89    DWORD64 pvPhysAddress;
90    DWORD64 PhysicalMemoryHandle;
91    DWORD64 pvPhysMemLin;
92    DWORD64 pvPhysSection;
93} tagPhysStruct;
94
95typedef bool  (_stdcall* INITIALIZEWINIO)(void);
96typedef void  (_stdcall* SHUTDOWNWINIO)(void);
97typedef bool  (_stdcall* GETPORTVAL)(WORD,PDWORD,BYTE);
98typedef bool  (_stdcall* SETPORTVAL)(WORD,DWORD,BYTE);
99typedef PBYTE (_stdcall* MAPPHYSTOLIN)(tagPhysStruct*);
100typedef bool  (_stdcall* UNMAPPHYSMEM)(tagPhysStruct*);
101
102SHUTDOWNWINIO ShutdownWinIo;
103GETPORTVAL GetPortVal;
104SETPORTVAL SetPortVal;
105INITIALIZEWINIO InitializeWinIo;
106MAPPHYSTOLIN MapPhysToLin;
107UNMAPPHYSMEM UnmapPhysicalMemory;
108
109static int
110x86_enable_io(void)
111{
112    HMODULE lib = NULL;
113
114    if ((GetVersion() & 0x80000000) == 0) {
115      /* running on NT, try WinIo version 3 (32 or 64 bits) */
116#ifdef WIN64
117      lib = LoadLibrary("WinIo64.dll");
118#else
119      lib = LoadLibrary("WinIo32.dll");
120#endif
121    }
122
123    if (!lib) {
124      fprintf(stderr, "Failed to load WinIo library.\n");
125      return 1;
126    }
127
128#define GETPROC(n, d) 						\
129    n = (d) GetProcAddress(lib, #n); 				\
130    if (!n) { 							\
131      fprintf(stderr, "Failed to load " #n " function.\n");	\
132      return 1; 						\
133    }
134
135    GETPROC(InitializeWinIo, INITIALIZEWINIO);
136    GETPROC(ShutdownWinIo, SHUTDOWNWINIO);
137    GETPROC(GetPortVal, GETPORTVAL);
138    GETPROC(SetPortVal, SETPORTVAL);
139    GETPROC(MapPhysToLin, MAPPHYSTOLIN);
140    GETPROC(UnmapPhysicalMemory, UNMAPPHYSMEM);
141
142#undef GETPROC
143
144    if (!InitializeWinIo()) {
145      fprintf(stderr, "Failed to initialize WinIo.\n"
146		      "NOTE: WinIo.dll and WinIo.sys must be in the same directory as the executable!\n");
147      return 0;
148    }
149
150    return 0;
151}
152
153static int
154x86_disable_io(void)
155{
156    ShutdownWinIo();
157    return 1;
158}
159
160static inline uint8_t
161inb(uint16_t port)
162{
163    DWORD pv;
164
165    if (GetPortVal(port, &pv, 1))
166      return (uint8_t)pv;
167    return 0;
168}
169
170static inline uint16_t
171inw(uint16_t port)
172{
173    DWORD pv;
174
175    if (GetPortVal(port, &pv, 2))
176      return (uint16_t)pv;
177    return 0;
178}
179
180static inline uint32_t
181inl(uint16_t port)
182{
183    DWORD pv;
184
185    if (GetPortVal(port, &pv, 4))
186        return (uint32_t)pv;
187    return 0;
188}
189
190static inline void
191outb(uint8_t value, uint16_t port)
192{
193    SetPortVal(port, value, 1);
194}
195
196static inline void
197outw(uint16_t value, uint16_t port)
198{
199    SetPortVal(port, value, 2);
200}
201
202static inline void
203outl(uint32_t value, uint16_t port)
204{
205    SetPortVal(port, value, 4);
206}
207
208#else
209
210#error How to enable IO ports on this system?
211
212#endif
213
214static int
215pci_system_x86_conf1_probe(void)
216{
217    unsigned long sav;
218    int res = ENODEV;
219
220    outb(0x01, 0xCFB);
221    sav = inl(0xCF8);
222    outl(0x80000000, 0xCF8);
223    if (inl(0xCF8) == 0x80000000)
224	res = 0;
225    outl(sav, 0xCF8);
226
227    return res;
228}
229
230static int
231pci_system_x86_conf1_read(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, void *data, unsigned size)
232{
233    unsigned addr = 0xCFC + (reg & 3);
234    unsigned long sav;
235    int ret = 0;
236
237    if (bus >= 0x100 || dev >= 32 || func >= 8 || reg >= 0x100 || size > 4 || size == 3)
238	return EIO;
239
240    sav = inl(0xCF8);
241    outl(0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3), 0xCF8);
242    /* NOTE: x86 is already LE */
243    switch (size) {
244	case 1: {
245	    uint8_t *val = data;
246	    *val = inb(addr);
247	    break;
248	}
249	case 2: {
250	    uint16_t *val = data;
251	    *val = inw(addr);
252	    break;
253	}
254	case 4: {
255	    uint32_t *val = data;
256	    *val = inl(addr);
257	    break;
258	}
259    }
260    outl(sav, 0xCF8);
261
262    return ret;
263}
264
265static int
266pci_system_x86_conf1_write(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, const void *data, unsigned size)
267{
268    unsigned addr = 0xCFC + (reg & 3);
269    unsigned long sav;
270    int ret = 0;
271
272    if (bus >= 0x100 || dev >= 32 || func >= 8 || reg >= 0x100 || size > 4 || size == 3)
273	return EIO;
274
275    sav = inl(0xCF8);
276    outl(0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3), 0xCF8);
277    /* NOTE: x86 is already LE */
278    switch (size) {
279	case 1: {
280	    const uint8_t *val = data;
281	    outb(*val, addr);
282	    break;
283	}
284	case 2: {
285	    const uint16_t *val = data;
286	    outw(*val, addr);
287	    break;
288	}
289	case 4: {
290	    const uint32_t *val = data;
291	    outl(*val, addr);
292	    break;
293	}
294    }
295    outl(sav, 0xCF8);
296
297    return ret;
298}
299
300static int
301pci_system_x86_conf2_probe(void)
302{
303    outb(0, 0xCFB);
304    outb(0, 0xCF8);
305    outb(0, 0xCFA);
306    if (inb(0xCF8) == 0 && inb(0xCFA) == 0)
307	return 0;
308
309    return ENODEV;
310}
311
312static int
313pci_system_x86_conf2_read(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, void *data, unsigned size)
314{
315    unsigned addr = 0xC000 | dev << 8 | reg;
316    int ret = 0;
317
318    if (bus >= 0x100 || dev >= 16 || func >= 8 || reg >= 0x100)
319	return EIO;
320
321    outb((func << 1) | 0xF0, 0xCF8);
322    outb(bus, 0xCFA);
323    /* NOTE: x86 is already LE */
324    switch (size) {
325	case 1: {
326	    uint8_t *val = data;
327	    *val = inb(addr);
328	    break;
329	}
330	case 2: {
331	    uint16_t *val = data;
332	    *val = inw(addr);
333	    break;
334	}
335	case 4: {
336	    uint32_t *val = data;
337	    *val = inl(addr);
338	    break;
339	}
340	default:
341	    ret = EIO;
342	    break;
343    }
344    outb(0, 0xCF8);
345
346    return ret;
347}
348
349static int
350pci_system_x86_conf2_write(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, const void *data, unsigned size)
351{
352    unsigned addr = 0xC000 | dev << 8 | reg;
353    int ret = 0;
354
355    if (bus >= 0x100 || dev >= 16 || func >= 8 || reg >= 0x100)
356	return EIO;
357
358    outb((func << 1) | 0xF0, 0xCF8);
359    outb(bus, 0xCFA);
360    /* NOTE: x86 is already LE */
361    switch (size) {
362	case 1: {
363	    const uint8_t *val = data;
364	    outb(*val, addr);
365	    break;
366	}
367	case 2: {
368	    const uint16_t *val = data;
369	    outw(*val, addr);
370	    break;
371	}
372	case 4: {
373	    const uint32_t *val = data;
374	    outl(*val, addr);
375	    break;
376	}
377	default:
378	    ret = EIO;
379	    break;
380    }
381    outb(0, 0xCF8);
382
383    return ret;
384}
385
386/* Check that this really looks like a PCI configuration. */
387static error_t
388pci_system_x86_check (void)
389{
390    int dev;
391    uint16_t class, vendor;
392    struct pci_device tmpdev = { 0 };
393
394    /* Look on bus 0 for a device that is a host bridge, a VGA card,
395     * or an intel or compaq device.  */
396    tmpdev.bus = 0;
397    tmpdev.func = 0;
398    class = 0;
399    vendor = 0;
400
401    for (dev = 0; dev < 32; dev++) {
402       tmpdev.dev = dev;
403       if (pci_device_cfg_read_u16 (&tmpdev, &class, PCI_CLASS_DEVICE))
404           continue;
405       if (class == PCI_CLASS_BRIDGE_HOST || class == PCI_CLASS_DISPLAY_VGA)
406           return 0;
407       if (pci_device_cfg_read_u16 (&tmpdev, &vendor, PCI_VENDOR_ID))
408           continue;
409       if (vendor == PCI_VENDOR_ID_INTEL || class == PCI_VENDOR_ID_COMPAQ)
410           return 0;
411    }
412
413    return ENODEV;
414}
415
416static int
417pci_nfuncs(struct pci_device *dev, uint8_t *nfuncs)
418{
419    uint8_t hdr;
420    int err;
421    struct pci_device tmpdev = *dev;
422
423    tmpdev.func = 0;
424
425    err = pci_device_cfg_read_u8 (&tmpdev, &hdr, PCI_HDRTYPE);
426
427    if (err)
428	return err;
429
430    *nfuncs = hdr & 0x80 ? 8 : 1;
431    return err;
432}
433
434/**
435 * Read a PCI rom.
436 */
437static error_t
438pci_device_x86_read_rom(struct pci_device *dev, void *buffer)
439{
440    void *bios;
441    int memfd;
442    struct pci_device_private *d = (struct pci_device_private *)dev;
443
444    memfd = open("/dev/mem", O_RDONLY | O_CLOEXEC);
445    if (memfd == -1)
446	return errno;
447
448    bios = mmap(NULL, dev->rom_size, PROT_READ, MAP_SHARED, memfd, d->rom_base);
449    if (bios == MAP_FAILED) {
450	close(memfd);
451	return errno;
452    }
453
454    memcpy(buffer, bios, dev->rom_size);
455
456    munmap(bios, dev->rom_size);
457    close(memfd);
458
459    return 0;
460}
461
462/** Returns the number of regions (base address registers) the device has */
463static int
464pci_device_x86_get_num_regions(uint8_t header_type)
465{
466    switch (header_type & 0x7f) {
467	case 0:
468	    return 6;
469	case 1:
470	    return 2;
471	case 2:
472	    return 1;
473	default:
474	    fprintf(stderr,"unknown header type %02x\n", header_type);
475	    return 0;
476    }
477}
478
479/** Masks out the flag bigs of the base address register value */
480static uint32_t
481get_map_base( uint32_t val )
482{
483    if (val & 0x01)
484	return val & ~0x03;
485    else
486	return val & ~0x0f;
487}
488
489/** Returns the size of a region based on the all-ones test value */
490static unsigned
491get_test_val_size( uint32_t testval )
492{
493    unsigned size = 1;
494
495    if (testval == 0)
496	return 0;
497
498    /* Mask out the flag bits */
499    testval = get_map_base( testval );
500    if (!testval)
501	return 0;
502
503    while ((testval & 1) == 0) {
504	size <<= 1;
505	testval >>= 1;
506    }
507
508    return size;
509}
510
511/* Read BAR `reg_num' in `dev' and map the data if any */
512static error_t
513pci_device_x86_region_probe (struct pci_device *dev, int reg_num)
514{
515    error_t err;
516    uint8_t offset;
517    uint32_t reg, addr, testval;
518    int memfd;
519
520    offset = PCI_BAR_ADDR_0 + 0x4 * reg_num;
521
522    /* Get the base address */
523    err = pci_device_cfg_read_u32 (dev, &addr, offset);
524    if (err)
525        return err;
526
527    /* Test write all ones to the register, then restore it. */
528    reg = 0xffffffff;
529    err = pci_device_cfg_write_u32 (dev, reg, offset);
530    if (err)
531        return err;
532    err = pci_device_cfg_read_u32 (dev, &testval, offset);
533    if (err)
534        return err;
535    err = pci_device_cfg_write_u32 (dev, addr, offset);
536    if (err)
537        return err;
538
539    if (addr & 0x01)
540        dev->regions[reg_num].is_IO = 1;
541    if (addr & 0x04)
542        dev->regions[reg_num].is_64 = 1;
543    if (addr & 0x08)
544        dev->regions[reg_num].is_prefetchable = 1;
545
546    /* Set the size */
547    dev->regions[reg_num].size = get_test_val_size (testval);
548
549    /* Set the base address value */
550    dev->regions[reg_num].base_addr = get_map_base (addr);
551
552    if (dev->regions[reg_num].is_64)
553    {
554        err = pci_device_cfg_read_u32 (dev, &addr, offset + 4);
555        if (err)
556            return err;
557
558        dev->regions[reg_num].base_addr |= ((uint64_t) addr << 32);
559    }
560
561    if (dev->regions[reg_num].is_IO)
562    {
563        /* Enable the I/O Space bit */
564        err = pci_device_cfg_read_u32 (dev, &reg, PCI_COMMAND);
565        if (err)
566            return err;
567
568        if (!(reg & 0x1))
569        {
570            reg |= 0x1;
571
572            err = pci_device_cfg_write_u32 (dev, reg, PCI_COMMAND);
573            if (err)
574                return err;
575        }
576
577        /* Clear the map pointer */
578        dev->regions[reg_num].memory = 0;
579    }
580    else if (dev->regions[reg_num].size > 0)
581    {
582        /* Enable the Memory Space bit */
583        err = pci_device_cfg_read_u32 (dev, &reg, PCI_COMMAND);
584        if (err)
585            return err;
586
587        if (!(reg & 0x2))
588        {
589            reg |= 0x2;
590
591            err = pci_device_cfg_write_u32 (dev, reg, PCI_COMMAND);
592            if (err)
593                return err;
594        }
595
596        /* Map the region in our space */
597        memfd = open ("/dev/mem", O_RDWR | O_CLOEXEC);
598        if (memfd == -1)
599            return errno;
600
601        dev->regions[reg_num].memory =
602         mmap (NULL, dev->regions[reg_num].size, PROT_READ | PROT_WRITE, MAP_SHARED,
603               memfd, dev->regions[reg_num].base_addr);
604        if (dev->regions[reg_num].memory == MAP_FAILED)
605        {
606            dev->regions[reg_num].memory = 0;
607            close (memfd);
608            return errno;
609        }
610    }
611
612    return 0;
613}
614
615/* Read the XROMBAR in `dev' and save the rom size and rom base */
616static error_t
617pci_device_x86_probe_rom (struct pci_device *dev)
618{
619    error_t err;
620    uint8_t reg_8, xrombar_addr;
621    uint32_t reg, reg_back;
622    pciaddr_t rom_size;
623    pciaddr_t rom_base;
624    struct pci_device_private *d = (struct pci_device_private *)dev;
625
626    /* First we need to know which type of header is this */
627    err = pci_device_cfg_read_u8 (dev, &reg_8, PCI_HDRTYPE);
628    if (err)
629        return err;
630
631    /* Get the XROMBAR register address */
632    switch (reg_8 & 0x3)
633    {
634    case PCI_HDRTYPE_DEVICE:
635        xrombar_addr = PCI_XROMBAR_ADDR_00;
636        break;
637    case PCI_HDRTYPE_BRIDGE:
638        xrombar_addr = PCI_XROMBAR_ADDR_01;
639        break;
640    default:
641        return -1;
642    }
643
644    /* Get size and physical address */
645    err = pci_device_cfg_read_u32 (dev, &reg, xrombar_addr);
646    if (err)
647        return err;
648
649    reg_back = reg;
650    reg = 0xFFFFF800;            /* Base address: first 21 bytes */
651    err = pci_device_cfg_write_u32 (dev, reg, xrombar_addr);
652    if (err)
653        return err;
654    err = pci_device_cfg_read_u32 (dev, &reg, xrombar_addr);
655    if (err)
656        return err;
657
658    rom_size = (~reg + 1);
659    rom_base = reg_back & reg;
660
661    if (rom_size == 0)
662        return 0;
663
664    /* Enable the address decoder and write the physical address back */
665    reg_back |= 0x1;
666    err = pci_device_cfg_write_u32 (dev, reg_back, xrombar_addr);
667    if (err)
668        return err;
669
670    /* Enable the Memory Space bit */
671    err = pci_device_cfg_read_u32 (dev, &reg, PCI_COMMAND);
672    if (err)
673        return err;
674
675    if (!(reg & 0x2))
676    {
677        reg |= 0x2;
678
679        err = pci_device_cfg_write_u32 (dev, reg, PCI_COMMAND);
680        if (err)
681            return err;
682    }
683
684    dev->rom_size = rom_size;
685    d->rom_base = rom_base;
686
687    return 0;
688}
689
690/* Configure BARs and ROM */
691static error_t
692pci_device_x86_probe (struct pci_device *dev)
693{
694    error_t err;
695    uint8_t hdrtype;
696    int i;
697
698    /* Probe BARs */
699    err = pci_device_cfg_read_u8 (dev, &hdrtype, PCI_HDRTYPE);
700    if (err)
701        return err;
702
703    for (i = 0; i < pci_device_x86_get_num_regions (hdrtype); i++)
704    {
705        err = pci_device_x86_region_probe (dev, i);
706        if (err)
707            return err;
708
709        if (dev->regions[i].is_64)
710            /* Move the pointer one BAR ahead */
711            i++;
712    }
713
714    /* Probe ROM */
715    pci_device_x86_probe_rom(dev);
716
717    return 0;
718}
719
720/* Recursively scan bus number `bus' */
721static error_t
722pci_system_x86_scan_bus (uint8_t bus)
723{
724    error_t err;
725    uint8_t dev, func, nfuncs, hdrtype, secbus;
726    uint32_t reg;
727    struct pci_device_private *d, *devices;
728    struct pci_device scratchdev;
729
730    scratchdev.bus = bus;
731
732    for (dev = 0; dev < 32; dev++)
733    {
734        scratchdev.dev = dev;
735        scratchdev.func = 0;
736        err = pci_nfuncs (&scratchdev, &nfuncs);
737        if (err)
738           return err;
739
740        for (func = 0; func < nfuncs; func++)
741        {
742            scratchdev.func = func;
743            err = pci_device_cfg_read_u32 (&scratchdev, &reg, PCI_VENDOR_ID);
744            if (err)
745                return err;
746
747            if (PCI_VENDOR (reg) == PCI_VENDOR_INVALID || PCI_VENDOR (reg) == 0)
748                continue;
749
750            err = pci_device_cfg_read_u32 (&scratchdev, &reg, PCI_CLASS);
751            if (err)
752                return err;
753
754            err = pci_device_cfg_read_u8 (&scratchdev, &hdrtype, PCI_HDRTYPE);
755            if (err)
756                return err;
757
758            devices =
759              realloc (pci_sys->devices,
760                       (pci_sys->num_devices + 1) * sizeof (struct pci_device_private));
761            if (!devices)
762                return ENOMEM;
763
764            d = devices + pci_sys->num_devices;
765            memset (d, 0, sizeof (struct pci_device_private));
766
767            /* Fixed values as PCI express is still not supported */
768            d->base.domain = 0;
769            d->base.bus = bus;
770            d->base.dev = dev;
771            d->base.func = func;
772
773            d->base.device_class = reg >> 8;
774
775            err = pci_device_x86_probe (&d->base);
776            if (err)
777                return err;
778
779            pci_sys->devices = devices;
780            pci_sys->num_devices++;
781
782            switch (hdrtype & 0x3)
783            {
784            case PCI_HDRTYPE_DEVICE:
785                break;
786            case PCI_HDRTYPE_BRIDGE:
787            case PCI_HDRTYPE_CARDBUS:
788                {
789                    err = pci_device_cfg_read_u8 (&scratchdev, &secbus, PCI_SECONDARY_BUS);
790                    if (err)
791                        return err;
792
793                    err = pci_system_x86_scan_bus (secbus);
794                    if (err)
795                        return err;
796
797                    break;
798                }
799            default:
800                /* Unknown header, do nothing */
801                break;
802            }
803        }
804    }
805
806    return 0;
807}
808
809#if defined(__CYGWIN__)
810
811static int
812pci_device_x86_map_range(struct pci_device *dev,
813    struct pci_device_mapping *map)
814{
815    tagPhysStruct phys;
816
817    phys.pvPhysAddress        = (DWORD64)(DWORD32)map->base;
818    phys.dwPhysMemSizeInBytes = map->size;
819
820    map->memory = (PDWORD)MapPhysToLin(&phys);
821    if (map->memory == NULL)
822        return EFAULT;
823
824    return 0;
825}
826
827static int
828pci_device_x86_unmap_range(struct pci_device *dev,
829    struct pci_device_mapping *map)
830{
831    tagPhysStruct phys;
832
833    phys.pvPhysAddress        = (DWORD64)(DWORD32)map->base;
834    phys.dwPhysMemSizeInBytes = map->size;
835
836    if (!UnmapPhysicalMemory(&phys))
837        return EFAULT;
838
839    return 0;
840}
841
842#else
843
844int
845pci_device_x86_map_range(struct pci_device *dev,
846    struct pci_device_mapping *map)
847{
848    int memfd = open("/dev/mem", O_RDWR | O_CLOEXEC);
849    int prot = PROT_READ;
850
851    if (memfd == -1)
852	return errno;
853
854    if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE)
855	prot |= PROT_WRITE;
856
857    map->memory = mmap(NULL, map->size, prot, MAP_SHARED, memfd, map->base);
858    if (map->memory == MAP_FAILED) {
859    	close(memfd);
860	return errno;
861    }
862    return 0;
863}
864
865int
866pci_device_x86_unmap_range(struct pci_device *dev,
867    struct pci_device_mapping *map)
868{
869    return pci_device_generic_unmap_range(dev, map);
870}
871
872#endif
873
874static int
875pci_device_x86_read_conf1(struct pci_device *dev, void *data,
876    pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read)
877{
878    int err;
879
880    *bytes_read = 0;
881    while (size > 0) {
882	int toread = 1 << (ffs(0x4 + (offset & 0x03)) - 1);
883	if (toread > size)
884	    toread = size;
885
886	err = pci_system_x86_conf1_read(dev->bus, dev->dev, dev->func, offset, data, toread);
887	if (err)
888	    return err;
889
890	offset += toread;
891	data = (char*)data + toread;
892	size -= toread;
893	*bytes_read += toread;
894    }
895    return 0;
896}
897
898static int
899pci_device_x86_read_conf2(struct pci_device *dev, void *data,
900    pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read)
901{
902    int err;
903
904    *bytes_read = 0;
905    while (size > 0) {
906	int toread = 1 << (ffs(0x4 + (offset & 0x03)) - 1);
907	if (toread > size)
908	    toread = size;
909
910	err = pci_system_x86_conf2_read(dev->bus, dev->dev, dev->func, offset, data, toread);
911	if (err)
912	    return err;
913
914	offset += toread;
915	data = (char*)data + toread;
916	size -= toread;
917	*bytes_read += toread;
918    }
919    return 0;
920}
921
922static int
923pci_device_x86_write_conf1(struct pci_device *dev, const void *data,
924    pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written)
925{
926    int err;
927
928    *bytes_written = 0;
929    while (size > 0) {
930	int towrite = 4;
931	if (towrite > size)
932	    towrite = size;
933	if (towrite > 4 - (offset & 0x3))
934	    towrite = 4 - (offset & 0x3);
935
936	err = pci_system_x86_conf1_write(dev->bus, dev->dev, dev->func, offset, data, towrite);
937	if (err)
938	    return err;
939
940	offset += towrite;
941	data = (const char*)data + towrite;
942	size -= towrite;
943	*bytes_written += towrite;
944    }
945    return 0;
946}
947
948static int
949pci_device_x86_write_conf2(struct pci_device *dev, const void *data,
950    pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written)
951{
952    int err;
953
954    *bytes_written = 0;
955    while (size > 0) {
956	int towrite = 4;
957	if (towrite > size)
958	    towrite = size;
959	if (towrite > 4 - (offset & 0x3))
960	    towrite = 4 - (offset & 0x3);
961
962	err = pci_system_x86_conf2_write(dev->bus, dev->dev, dev->func, offset, data, towrite);
963	if (err)
964	    return err;
965
966	offset += towrite;
967	data = (const char*)data + towrite;
968	size -= towrite;
969	*bytes_written += towrite;
970    }
971    return 0;
972}
973
974void
975pci_system_x86_destroy(void)
976{
977    x86_disable_io();
978}
979
980struct pci_io_handle *
981pci_device_x86_open_legacy_io(struct pci_io_handle *ret,
982    struct pci_device *dev, pciaddr_t base, pciaddr_t size)
983{
984    x86_enable_io();
985
986    ret->base = base;
987    ret->size = size;
988    ret->is_legacy = 1;
989
990    return ret;
991}
992
993void
994pci_device_x86_close_io(struct pci_device *dev, struct pci_io_handle *handle)
995{
996    /* Like in the Linux case, do not disable I/O, as it may be opened several
997     * times, and closed fewer times. */
998    /* x86_disable_io(); */
999}
1000
1001uint32_t
1002pci_device_x86_read32(struct pci_io_handle *handle, uint32_t reg)
1003{
1004    return inl(reg + handle->base);
1005}
1006
1007uint16_t
1008pci_device_x86_read16(struct pci_io_handle *handle, uint32_t reg)
1009{
1010    return inw(reg + handle->base);
1011}
1012
1013uint8_t
1014pci_device_x86_read8(struct pci_io_handle *handle, uint32_t reg)
1015{
1016    return inb(reg + handle->base);
1017}
1018
1019void
1020pci_device_x86_write32(struct pci_io_handle *handle, uint32_t reg,
1021		       uint32_t data)
1022{
1023    outl(data, reg + handle->base);
1024}
1025
1026void
1027pci_device_x86_write16(struct pci_io_handle *handle, uint32_t reg,
1028		       uint16_t data)
1029{
1030    outw(data, reg + handle->base);
1031}
1032
1033void
1034pci_device_x86_write8(struct pci_io_handle *handle, uint32_t reg,
1035		      uint8_t data)
1036{
1037    outb(data, reg + handle->base);
1038}
1039
1040int
1041pci_device_x86_map_legacy(struct pci_device *dev, pciaddr_t base,
1042    pciaddr_t size, unsigned map_flags, void **addr)
1043{
1044    struct pci_device_mapping map;
1045    int err;
1046
1047    map.base = base;
1048    map.size = size;
1049    map.flags = map_flags;
1050    err = pci_device_x86_map_range(dev, &map);
1051    *addr = map.memory;
1052
1053    return err;
1054}
1055
1056int
1057pci_device_x86_unmap_legacy(struct pci_device *dev, void *addr,
1058    pciaddr_t size)
1059{
1060    struct pci_device_mapping map;
1061
1062    map.size = size;
1063    map.flags = 0;
1064    map.memory = addr;
1065
1066    return pci_device_x86_unmap_range(dev, &map);
1067}
1068
1069static const struct pci_system_methods x86_pci_method_conf1 = {
1070    .destroy = pci_system_x86_destroy,
1071    .read_rom = pci_device_x86_read_rom,
1072    .probe = pci_device_x86_probe,
1073    .map_range = pci_device_x86_map_range,
1074    .unmap_range = pci_device_x86_unmap_range,
1075    .read = pci_device_x86_read_conf1,
1076    .write = pci_device_x86_write_conf1,
1077    .fill_capabilities = pci_fill_capabilities_generic,
1078    .open_legacy_io = pci_device_x86_open_legacy_io,
1079    .close_io = pci_device_x86_close_io,
1080    .read32 = pci_device_x86_read32,
1081    .read16 = pci_device_x86_read16,
1082    .read8 = pci_device_x86_read8,
1083    .write32 = pci_device_x86_write32,
1084    .write16 = pci_device_x86_write16,
1085    .write8 = pci_device_x86_write8,
1086    .map_legacy = pci_device_x86_map_legacy,
1087    .unmap_legacy = pci_device_x86_unmap_legacy,
1088};
1089
1090static const struct pci_system_methods x86_pci_method_conf2 = {
1091    .destroy = pci_system_x86_destroy,
1092    .read_rom = pci_device_x86_read_rom,
1093    .probe = pci_device_x86_probe,
1094    .map_range = pci_device_x86_map_range,
1095    .unmap_range = pci_device_x86_unmap_range,
1096    .read = pci_device_x86_read_conf2,
1097    .write = pci_device_x86_write_conf2,
1098    .fill_capabilities = pci_fill_capabilities_generic,
1099    .open_legacy_io = pci_device_x86_open_legacy_io,
1100    .close_io = pci_device_x86_close_io,
1101    .read32 = pci_device_x86_read32,
1102    .read16 = pci_device_x86_read16,
1103    .read8 = pci_device_x86_read8,
1104    .write32 = pci_device_x86_write32,
1105    .write16 = pci_device_x86_write16,
1106    .write8 = pci_device_x86_write8,
1107    .map_legacy = pci_device_x86_map_legacy,
1108    .unmap_legacy = pci_device_x86_unmap_legacy,
1109};
1110
1111static int pci_probe(void)
1112{
1113    pci_sys->methods = &x86_pci_method_conf1;
1114    if (pci_system_x86_conf1_probe() == 0) {
1115	if (pci_system_x86_check() == 0)
1116	    return 1;
1117    }
1118
1119    pci_sys->methods = &x86_pci_method_conf2;
1120    if (pci_system_x86_conf2_probe() == 0) {
1121	if (pci_system_x86_check() == 0)
1122	    return 2;
1123    }
1124
1125    pci_sys->methods = NULL;
1126    return 0;
1127}
1128
1129_pci_hidden int
1130pci_system_x86_create(void)
1131{
1132    error_t err;
1133    int confx;
1134
1135    err = x86_enable_io ();
1136    if (err)
1137        return err;
1138
1139    pci_sys = calloc (1, sizeof (struct pci_system));
1140    if (pci_sys == NULL)
1141    {
1142        x86_disable_io ();
1143        return ENOMEM;
1144    }
1145
1146    confx = pci_probe ();
1147    if (!confx)
1148    {
1149        x86_disable_io ();
1150        free (pci_sys);
1151        pci_sys = NULL;
1152        return ENODEV;
1153    }
1154    else if (confx == 1)
1155        pci_sys->methods = &x86_pci_method_conf1;
1156    else
1157        pci_sys->methods = &x86_pci_method_conf2;
1158
1159    /* Recursive scan */
1160    pci_sys->num_devices = 0;
1161    err = pci_system_x86_scan_bus (0);
1162    if (err)
1163    {
1164        x86_disable_io ();
1165        free (pci_sys);
1166        pci_sys = NULL;
1167        return err;
1168    }
1169
1170    return 0;
1171}
1172