summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2012-02-27 10:43:20 -0500
committerAdam Jackson <ajax@redhat.com>2012-02-27 10:46:59 -0500
commitf550c1347d3518874fe1c1d417a57322ee6b52db (patch)
tree1d8a885e60984e215e9dbd8a69217f60eb4347a6
parent2a58cd13c3d14cd2ea57826b56e9906ecfc5648a (diff)
downloadxorg-lib-libpciaccess-f550c1347d3518874fe1c1d417a57322ee6b52db.tar.gz
linux: Don't use /dev/port
Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com> Signed-off-by: Adam Jackson <ajax@redhat.com>
-rw-r--r--src/linux_sysfs.c63
1 files changed, 50 insertions, 13 deletions
diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c
index 09e7138..9566d40 100644
--- a/src/linux_sysfs.c
+++ b/src/linux_sysfs.c
@@ -1,6 +1,7 @@
/*
* (C) Copyright IBM Corporation 2006
* All Rights Reserved.
+ * Copyright 2012 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -44,6 +45,18 @@
#include <dirent.h>
#include <errno.h>
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#include <sys/io.h>
+#else
+#define inb(x) -1
+#define inw(x) -1
+#define inl(x) -1
+#define outb(x) do {} while (0)
+#define outw(x) do {} while (0)
+#define outl(x) do {} while (0)
+#define iopl(x) -1
+#endif
+
#include "config.h"
#ifdef HAVE_MTRR
@@ -769,12 +782,17 @@ pci_device_linux_sysfs_open_legacy_io(struct pci_io_handle *ret,
dev = pci_device_get_parent_bridge(dev);
}
- /* If not, /dev/port is the best we can do */
- if (!dev)
- ret->fd = open("/dev/port", O_RDWR);
+ /*
+ * You would think you'd want to use /dev/port here. Don't make that
+ * mistake, /dev/port only does byte-wide i/o cycles which means it
+ * doesn't work. If you think this is stupid, well, you're right.
+ */
- if (ret->fd < 0)
- return NULL;
+ /* If we've no other choice, iopl */
+ if (ret->fd < 0) {
+ if (iopl(3))
+ return NULL;
+ }
ret->base = base;
ret->size = size;
@@ -786,7 +804,8 @@ static void
pci_device_linux_sysfs_close_io(struct pci_device *dev,
struct pci_io_handle *handle)
{
- close(handle->fd);
+ if (handle->fd > -1)
+ close(handle->fd);
}
static uint32_t
@@ -794,8 +813,11 @@ pci_device_linux_sysfs_read32(struct pci_io_handle *handle, uint32_t port)
{
uint32_t ret;
- pread(handle->fd, &ret, 4, port + handle->base);
-
+ if (handle->fd > -1)
+ pread(handle->fd, &ret, 4, port + handle->base);
+ else
+ ret = inl(port + handle->base);
+
return ret;
}
@@ -804,7 +826,10 @@ pci_device_linux_sysfs_read16(struct pci_io_handle *handle, uint32_t port)
{
uint16_t ret;
- pread(handle->fd, &ret, 2, port + handle->base);
+ if (handle->fd > -1)
+ pread(handle->fd, &ret, 2, port + handle->base);
+ else
+ ret = inw(port + handle->base);
return ret;
}
@@ -814,7 +839,10 @@ pci_device_linux_sysfs_read8(struct pci_io_handle *handle, uint32_t port)
{
uint8_t ret;
- pread(handle->fd, &ret, 1, port + handle->base);
+ if (handle->fd > -1)
+ pread(handle->fd, &ret, 1, port + handle->base);
+ else
+ ret = inb(port + handle->base);
return ret;
}
@@ -823,21 +851,30 @@ static void
pci_device_linux_sysfs_write32(struct pci_io_handle *handle, uint32_t port,
uint32_t data)
{
- pwrite(handle->fd, &data, 4, port + handle->base);
+ if (handle->fd > -1)
+ pwrite(handle->fd, &data, 4, port + handle->base);
+ else
+ outl(data, port + handle->base);
}
static void
pci_device_linux_sysfs_write16(struct pci_io_handle *handle, uint32_t port,
uint16_t data)
{
- pwrite(handle->fd, &data, 2, port + handle->base);
+ if (handle->fd > -1)
+ pwrite(handle->fd, &data, 2, port + handle->base);
+ else
+ outw(data, port + handle->base);
}
static void
pci_device_linux_sysfs_write8(struct pci_io_handle *handle, uint32_t port,
uint8_t data)
{
- pwrite(handle->fd, &data, 1, port + handle->base);
+ if (handle->fd > -1)
+ pwrite(handle->fd, &data, 1, port + handle->base);
+ else
+ outb(data, port + handle->base);
}
static int