Index: src/openbsd_pci.c --- src/openbsd_pci.c.orig +++ src/openbsd_pci.c @@ -17,17 +17,23 @@ #include "config.h" #endif -#include #include +#include +#include +#if defined(__i386__) || defined(__amd64__) #include +#endif #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -36,6 +42,8 @@ #include "pciaccess.h" #include "pciaccess_private.h" +#define MIN(a,b) (((a)<(b))?(a):(b)) + /* * This should allow for 16 domains, which should cover everything * except perhaps the really big fridge-sized sparc64 server machines @@ -190,21 +198,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 +233,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 +246,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 +322,7 @@ pci_device_openbsd_write(struct pci_device *dev, const return errno; offset += 4; - data = (char *)data + 4; + data = (const char *)data + 4; size -= 4; *bytes_written += 4; } @@ -416,50 +432,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 #include #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,9 +608,9 @@ static const struct pci_system_methods openbsd_pci_met pci_device_openbsd_write, pci_fill_capabilities_generic, NULL, + pci_device_openbsd_boot_vga, NULL, NULL, - NULL, pci_device_openbsd_open_legacy_io, NULL, pci_device_openbsd_read32, @@ -585,33 +628,32 @@ pci_system_openbsd_create(void) { struct pci_device_private *device; int domain, bus, dev, func, ndevs, nfuncs; - char path[MAXPATHLEN]; + char path[PATH_MAX]; uint32_t reg; 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 +725,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 +753,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 +785,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 +838,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 +857,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;