summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.bsd-wrapper7
-rw-r--r--src/openbsd_pci.c156
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;