diff options
-rw-r--r-- | Makefile.bsd-wrapper | 7 | ||||
-rw-r--r-- | src/openbsd_pci.c | 156 |
2 files changed, 110 insertions, 53 deletions
diff --git a/Makefile.bsd-wrapper b/Makefile.bsd-wrapper new file mode 100644 index 0000000..3836057 --- /dev/null +++ b/Makefile.bsd-wrapper @@ -0,0 +1,7 @@ +# $OpenBSD: Makefile.bsd-wrapper,v 1.6 2013/08/13 07:07:21 guenther Exp $ + +SHARED_LIBS= pciaccess 2.0 + +CONFIGURE_ARGS+= --with-pciids-path=${X11BASE}/share + +.include <bsd.xorg.mk> diff --git a/src/openbsd_pci.c b/src/openbsd_pci.c index c061fd8..1ca98de 100644 --- a/src/openbsd_pci.c +++ b/src/openbsd_pci.c @@ -19,9 +19,13 @@ #include <sys/param.h> #include <sys/ioctl.h> +#if defined(__i386__) || defined(__amd64__) #include <sys/memrange.h> +#endif #include <sys/mman.h> #include <sys/pciio.h> +#include <sys/sysctl.h> +#include <machine/cpu.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcidevs.h> @@ -190,21 +194,28 @@ static int pci_device_openbsd_map_range(struct pci_device *dev, struct pci_device_mapping *map) { - struct mem_range_desc mr; - struct mem_range_op mo; int prot = PROT_READ; + off_t addr = map->base; if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE) prot |= PROT_WRITE; +#ifdef MEMRANGE_WC_RANGE + if (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE) + addr += MEMRANGE_WC_RANGE; +#endif + map->memory = mmap(NULL, map->size, prot, MAP_SHARED, aperturefd, - map->base); + addr); if (map->memory == MAP_FAILED) return errno; #if defined(__i386__) || defined(__amd64__) /* No need to set an MTRR if it's the default mode. */ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) || (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) { + struct mem_range_desc mr; + struct mem_range_op mo; + mr.mr_base = map->base; mr.mr_len = map->size; mr.mr_flags = 0; @@ -218,7 +229,8 @@ pci_device_openbsd_map_range(struct pci_device *dev, mo.mo_arg[0] = MEMRANGE_SET_UPDATE; if (ioctl(aperturefd, MEMRANGE_SET, &mo)) - (void)fprintf(stderr, "mtrr set failed: %s\n", + (void)fprintf(stderr, "mtrr set %lx %lx failed: %s\n", + (intptr_t)map->base, (intptr_t)map->size, strerror(errno)); } #endif @@ -230,11 +242,11 @@ pci_device_openbsd_unmap_range(struct pci_device *dev, struct pci_device_mapping *map) { #if defined(__i386__) || defined(__amd64__) - struct mem_range_desc mr; - struct mem_range_op mo; - if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) || (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) { + struct mem_range_desc mr; + struct mem_range_op mo; + mr.mr_base = map->base; mr.mr_len = map->size; mr.mr_flags = MDF_UNCACHEABLE; @@ -306,7 +318,7 @@ pci_device_openbsd_write(struct pci_device *dev, const void *data, return errno; offset += 4; - data = (char *)data + 4; + data = (const char *)data + 4; size -= 4; *bytes_written += 4; } @@ -416,50 +428,77 @@ pci_device_openbsd_probe(struct pci_device *device) return 0; } +static int +pci_device_openbsd_boot_vga(struct pci_device *dev) +{ + struct pci_vga pv; + int err; + + if (dev->domain != 0) + return 0; + + pv.pv_sel.pc_bus = 0; + pv.pv_sel.pc_dev = 0; + pv.pv_sel.pc_func = 0; + err = ioctl(pcifd[0], PCIOCGETVGA, &pv); + if (err) + return 0; + + if (dev->bus == pv.pv_sel.pc_bus && + dev->dev == pv.pv_sel.pc_dev && + dev->func == pv.pv_sel.pc_func) + return 1; + + return 0; +} + #if defined(__i386__) || defined(__amd64__) #include <machine/sysarch.h> #include <machine/pio.h> #endif +static struct pci_io_handle *legacy_io_handle = NULL; + static struct pci_io_handle * pci_device_openbsd_open_legacy_io(struct pci_io_handle *ret, struct pci_device *dev, pciaddr_t base, pciaddr_t size) { #if defined(__i386__) struct i386_iopl_args ia; +#elif defined(__amd64__) + struct amd64_iopl_args ia; +#endif + /* With X server privilege separation, i/o access is + enabled early and never disabled, allow recursive, + privilege-less calls */ + if (legacy_io_handle != NULL) { + ret->base = legacy_io_handle->base; + ret->size = legacy_io_handle->size; + ret->memory = legacy_io_handle->memory; + ret->is_legacy = 1; + return ret; + } +#if defined(__i386__) ia.iopl = 1; if (sysarch(I386_IOPL, &ia)) return NULL; - - ret->base = base; - ret->size = size; - ret->is_legacy = 1; - return ret; #elif defined(__amd64__) - struct amd64_iopl_args ia; - ia.iopl = 1; if (sysarch(AMD64_IOPL, &ia)) return NULL; - - ret->base = base; - ret->size = size; - ret->is_legacy = 1; - return ret; #elif defined(PCI_MAGIC_IO_RANGE) ret->memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, aperturefd, PCI_MAGIC_IO_RANGE + base); if (ret->memory == MAP_FAILED) return NULL; - - ret->base = base; - ret->size = size; - ret->is_legacy = 1; - return ret; #else return NULL; #endif + ret->base = base; + ret->size = size; + legacy_io_handle = ret; + return ret; } static uint32_t @@ -565,7 +604,7 @@ static const struct pci_system_methods openbsd_pci_methods = { pci_device_openbsd_write, pci_fill_capabilities_generic, NULL, - NULL, + pci_device_openbsd_boot_vga, NULL, NULL, pci_device_openbsd_open_legacy_io, @@ -591,27 +630,26 @@ pci_system_openbsd_create(void) if (ndomains > 0) return 0; + pci_sys = calloc(1, sizeof(struct pci_system)); + if (pci_sys == NULL) + return ENOMEM; + + pci_sys->methods = &openbsd_pci_methods; + for (domain = 0; domain < sizeof(pcifd) / sizeof(pcifd[0]); domain++) { snprintf(path, sizeof(path), "/dev/pci%d", domain); pcifd[domain] = open(path, O_RDWR | O_CLOEXEC); - if (pcifd[domain] == -1) - break; + if (pcifd[domain] == -1) { + pcifd[domain] = open(path, O_RDONLY | O_CLOEXEC); + if (pcifd[domain] == -1) + break; + } ndomains++; } if (ndomains == 0) return ENXIO; - pci_sys = calloc(1, sizeof(struct pci_system)); - if (pci_sys == NULL) { - for (domain = 0; domain < ndomains; domain++) - close(pcifd[domain]); - ndomains = 0; - return ENOMEM; - } - - pci_sys->methods = &openbsd_pci_methods; - ndevs = 0; for (domain = 0; domain < ndomains; domain++) { for (bus = 0; bus < 256; bus++) { @@ -683,10 +721,6 @@ pci_system_openbsd_create(void) device->base.subvendor_id = PCI_VENDOR(reg); device->base.subdevice_id = PCI_PRODUCT(reg); - device->base.vgaarb_rsrc = - VGA_ARB_RSRC_LEGACY_IO | - VGA_ARB_RSRC_LEGACY_MEM; - device++; } } @@ -715,6 +749,22 @@ pci_device_vgaarb_init(void) struct pci_vga pv; int err; +#ifdef CPU_ALLOWAPERTURE + int mib[2]; + int allowaperture; + size_t len; + + mib[0] = CTL_MACHDEP; + mib[1] = CPU_ALLOWAPERTURE; + len = sizeof(allowaperture); + if (sysctl(mib, 2, &allowaperture, &len, NULL, 0) == 0 && + allowaperture == 0) { + /* No direct hardware access allowed. */ + pci_sys->vga_count = 0; + return 0; + } +#endif + pv.pv_sel.pc_bus = 0; pv.pv_sel.pc_dev = 0; pv.pv_sel.pc_func = 0; @@ -731,8 +781,18 @@ pci_device_vgaarb_init(void) return -1; pci_sys->vga_count = 0; while ((dev = pci_device_next(iter)) != NULL) { - if (dev->domain == 0) + if (dev->domain == 0) { pci_sys->vga_count++; + pv.pv_sel.pc_bus = dev->bus; + pv.pv_sel.pc_dev = dev->dev; + pv.pv_sel.pc_func = dev->func; + if (ioctl(pcifd[0], PCIOCGETVGA, &pv)) + continue; + if (pv.pv_decode) + dev->vgaarb_rsrc = + VGA_ARB_RSRC_LEGACY_IO | + VGA_ARB_RSRC_LEGACY_MEM; + } } pci_iterator_destroy(iter); @@ -774,13 +834,8 @@ pci_device_vgaarb_lock(void) if (dev == NULL) return -1; -#if 0 if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1) return 0; -#else - if (pci_sys->vga_count == 1) - return 0; -#endif pv.pv_sel.pc_bus = dev->bus; pv.pv_sel.pc_dev = dev->dev; @@ -798,13 +853,8 @@ pci_device_vgaarb_unlock(void) if (dev == NULL) return -1; -#if 0 if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1) return 0; -#else - if (pci_sys->vga_count == 1) - return 0; -#endif pv.pv_sel.pc_bus = dev->bus; pv.pv_sel.pc_dev = dev->dev; |