aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Mareš <mj@ucw.cz>2024-02-17 23:22:18 +0100
committerGitHub <noreply@github.com>2024-02-17 23:22:18 +0100
commit26a5aaaa945e37a4fd1d05803cdade82b9f9a9e3 (patch)
tree31aa168a90620afaf4c2aec0da559af972ff8a5c
parenta997ef132d943990cdb65d32a6605b6ff4bfcd79 (diff)
parentebbd5e810639fe13c6e85eb358b34997253244d8 (diff)
downloadpciutils-26a5aaaa945e37a4fd1d05803cdade82b9f9a9e3.tar.gz
Merge pull request #166 from DigitalDJ/master
i386-ports: Add support for OpenBSD
-rw-r--r--README2
-rwxr-xr-xlib/configure6
-rw-r--r--lib/i386-io-access.h75
-rw-r--r--lib/i386-io-beos.h12
-rw-r--r--lib/i386-io-cygwin.h2
-rw-r--r--lib/i386-io-djgpp.h8
-rw-r--r--lib/i386-io-haiku.h21
-rw-r--r--lib/i386-io-hurd.h2
-rw-r--r--lib/i386-io-linux.h2
-rw-r--r--lib/i386-io-openbsd.h54
-rw-r--r--lib/i386-io-sunos.h44
-rw-r--r--lib/i386-io-windows.h87
-rw-r--r--lib/i386-ports.c60
13 files changed, 198 insertions, 177 deletions
diff --git a/README b/README
index 04e9348..fce2f61 100644
--- a/README
+++ b/README
@@ -20,7 +20,7 @@ In runs on the following systems:
Linux (via /sys/bus/pci, /proc/bus/pci or i386 ports)
FreeBSD (via /dev/pci)
NetBSD (via libpci)
- OpenBSD (via /dev/pci)
+ OpenBSD (via /dev/pci or i386 ports)
GNU/kFreeBSD (via /dev/pci)
Solaris/i386 (direct port access)
Aix (via /dev/pci and odmget)
diff --git a/lib/configure b/lib/configure
index 158cc0a..2479def 100755
--- a/lib/configure
+++ b/lib/configure
@@ -121,6 +121,12 @@ case $sys in
echo >>$c '#define PCI_PATH_DEVMEM_DEVICE "/dev/mem"'
echo >>$c '#define PCI_PATH_ACPI_MCFG "/var/db/acpi/MCFG.*"'
echo >>$c '#define PCI_PATH_EFI_SYSTAB ""'
+ case $cpu in
+ i386|amd64) echo_n " i386-ports"
+ echo >>$c '#define PCI_HAVE_PM_INTEL_CONF'
+ echo >>$m 'WITH_LIBS+=-l'$cpu
+ ;;
+ esac
LIBRESOLV=
;;
diff --git a/lib/i386-io-access.h b/lib/i386-io-access.h
new file mode 100644
index 0000000..8b1ad5f
--- /dev/null
+++ b/lib/i386-io-access.h
@@ -0,0 +1,75 @@
+/*
+ * The PCI Library -- Compiler-specific wrappers around x86 I/O port access instructions
+ *
+ * Copyright (c) 2023 Pali Rohár <pali@kernel.org>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL v2+
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#if defined(__GNUC__)
+
+static inline unsigned char
+intel_inb(unsigned short int port)
+{
+ unsigned char value;
+ asm volatile ("inb %w1, %0" : "=a" (value) : "Nd" (port));
+ return value;
+}
+
+static inline unsigned short int
+intel_inw(unsigned short int port)
+{
+ unsigned short value;
+ asm volatile ("inw %w1, %0" : "=a" (value) : "Nd" (port));
+ return value;
+}
+
+static inline unsigned int
+intel_inl(unsigned short int port)
+{
+ u32 value;
+ asm volatile ("inl %w1, %0" : "=a" (value) : "Nd" (port));
+ return value;
+}
+
+static inline void
+intel_outb(unsigned char value, unsigned short int port)
+{
+ asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port));
+}
+
+static inline void
+intel_outw(unsigned short int value, unsigned short int port)
+{
+ asm volatile ("outw %w0, %w1" : : "a" (value), "Nd" (port));
+}
+
+static inline void
+intel_outl(u32 value, unsigned short int port)
+{
+ asm volatile ("outl %0, %w1" : : "a" (value), "Nd" (port));
+}
+
+#elif defined(_MSC_VER)
+
+#pragma intrinsic(_outp)
+#pragma intrinsic(_outpw)
+#pragma intrinsic(_outpd)
+#pragma intrinsic(_inp)
+#pragma intrinsic(_inpw)
+#pragma intrinsic(_inpd)
+
+#define intel_outb(x, y) _outp(y, x)
+#define intel_outw(x, y) _outpw(y, x)
+#define intel_outl(x, y) _outpd(y, x)
+#define intel_inb(x) _inp(x)
+#define intel_inw(x) _inpw(x)
+#define intel_inl(x) _inpd(x)
+
+#else
+
+#error Do not know how to access I/O ports on this compiler
+
+#endif
diff --git a/lib/i386-io-beos.h b/lib/i386-io-beos.h
index 49b7094..dac0e4b 100644
--- a/lib/i386-io-beos.h
+++ b/lib/i386-io-beos.h
@@ -24,37 +24,37 @@ intel_cleanup_io(struct pci_access *a UNUSED)
}
static inline u8
-inb (u16 port)
+intel_inb (u16 port)
{
return (u8)read_isa_io(0, (void *)(u32)port, sizeof(u8));
}
static inline u16
-inw (u16 port)
+intel_inw (u16 port)
{
return (u16)read_isa_io(0, (void *)(u32)port, sizeof(u16));
}
static inline u32
-inl (u16 port)
+intel_inl (u16 port)
{
return (u32)read_isa_io(0, (void *)(u32)port, sizeof(u32));
}
static inline void
-outb (u8 value, u16 port)
+intel_outb (u8 value, u16 port)
{
write_isa_io(0, (void *)(u32)port, sizeof(value), value);
}
static inline void
-outw (u16 value, u16 port)
+intel_outw (u16 value, u16 port)
{
write_isa_io(0, (void *)(u32)port, sizeof(value), value);
}
static inline void
-outl (u32 value, u16 port)
+intel_outl (u32 value, u16 port)
{
write_isa_io(0, (void *)(u32)port, sizeof(value), value);
}
diff --git a/lib/i386-io-cygwin.h b/lib/i386-io-cygwin.h
index 0b71d16..4118057 100644
--- a/lib/i386-io-cygwin.h
+++ b/lib/i386-io-cygwin.h
@@ -10,6 +10,8 @@
#include <sys/io.h>
+#include "i386-io-access.h"
+
static int
intel_setup_io(struct pci_access *a UNUSED)
{
diff --git a/lib/i386-io-djgpp.h b/lib/i386-io-djgpp.h
index bb29526..1afb00e 100644
--- a/lib/i386-io-djgpp.h
+++ b/lib/i386-io-djgpp.h
@@ -8,15 +8,9 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#include <pc.h>
#include <dos.h>
-#define outb(x,y) outportb(y, x)
-#define outw(x,y) outportw(y, x)
-#define outl(x,y) outportl(y, x)
-#define inb inportb
-#define inw inportw
-#define inl inportl
+#include "i386-io-access.h"
static int irq_enabled;
diff --git a/lib/i386-io-haiku.h b/lib/i386-io-haiku.h
index ce5362b..23843ea 100644
--- a/lib/i386-io-haiku.h
+++ b/lib/i386-io-haiku.h
@@ -66,6 +66,15 @@ static int poke_driver_fd;
static int
intel_setup_io(struct pci_access *a UNUSED)
{
+ /*
+ * Opening poke device on systems with the linked change below
+ * automatically changes process IOPL to 3 and closing its file
+ * descriptor changes process IOPL back to 0, which give access
+ * to all x86 IO ports via x86 in/out instructions for this
+ * userspace process. To support also older systems without this
+ * change, access IO ports via ioctl() instead of x86 in/out.
+ * https://review.haiku-os.org/c/haiku/+/1077
+ */
poke_driver_fd = open(POKE_DEVICE_FULLNAME, O_RDWR);
return (poke_driver_fd < 0) ? 0 : 1;
}
@@ -77,7 +86,7 @@ intel_cleanup_io(struct pci_access *a UNUSED)
}
static inline u8
-inb (u16 port)
+intel_inb (u16 port)
{
port_io_args args = { POKE_SIGNATURE, port, sizeof(u8), 0 };
if (ioctl(poke_driver_fd, POKE_PORT_READ, &args, sizeof(args)) < 0)
@@ -86,7 +95,7 @@ inb (u16 port)
}
static inline u16
-inw (u16 port)
+intel_inw (u16 port)
{
port_io_args args = { POKE_SIGNATURE, port, sizeof(u16), 0 };
if (ioctl(poke_driver_fd, POKE_PORT_READ, &args, sizeof(args)) < 0)
@@ -95,7 +104,7 @@ inw (u16 port)
}
static inline u32
-inl (u16 port)
+intel_inl (u16 port)
{
port_io_args args = { POKE_SIGNATURE, port, sizeof(u32), 0 };
if (ioctl(poke_driver_fd, POKE_PORT_READ, &args, sizeof(args)) < 0)
@@ -104,21 +113,21 @@ inl (u16 port)
}
static inline void
-outb (u8 value, u16 port)
+intel_outb (u8 value, u16 port)
{
port_io_args args = { POKE_SIGNATURE, port, sizeof(u8), value };
ioctl(poke_driver_fd, POKE_PORT_WRITE, &args, sizeof(args));
}
static inline void
-outw (u16 value, u16 port)
+intel_outw (u16 value, u16 port)
{
port_io_args args = { POKE_SIGNATURE, port, sizeof(u16), value };
ioctl(poke_driver_fd, POKE_PORT_WRITE, &args, sizeof(args));
}
static inline void
-outl (u32 value, u16 port)
+intel_outl (u32 value, u16 port)
{
port_io_args args = { POKE_SIGNATURE, port, sizeof(u32), value };
ioctl(poke_driver_fd, POKE_PORT_WRITE, &args, sizeof(args));
diff --git a/lib/i386-io-hurd.h b/lib/i386-io-hurd.h
index d44b2f5..01d684e 100644
--- a/lib/i386-io-hurd.h
+++ b/lib/i386-io-hurd.h
@@ -14,6 +14,8 @@
#include <sys/io.h>
+#include "i386-io-access.h"
+
static inline int
intel_setup_io(struct pci_access *a UNUSED)
{
diff --git a/lib/i386-io-linux.h b/lib/i386-io-linux.h
index e6bb9b6..317f079 100644
--- a/lib/i386-io-linux.h
+++ b/lib/i386-io-linux.h
@@ -11,6 +11,8 @@
#include <sys/io.h>
#include <errno.h>
+#include "i386-io-access.h"
+
static int ioperm_enabled;
static int iopl_enabled;
diff --git a/lib/i386-io-openbsd.h b/lib/i386-io-openbsd.h
new file mode 100644
index 0000000..8a9b4a4
--- /dev/null
+++ b/lib/i386-io-openbsd.h
@@ -0,0 +1,54 @@
+/*
+ * The PCI Library -- Access to i386 I/O ports on OpenBSD
+ *
+ * Copyright (c) 2023 Grant Pannell <grant@pannell.net.au>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <sys/types.h>
+#include <machine/sysarch.h>
+#include <machine/pio.h>
+
+#include "i386-io-access.h"
+
+#if defined(__amd64__)
+ #define obsd_iopl amd64_iopl
+#else
+ #define obsd_iopl i386_iopl
+#endif
+
+static int iopl_enabled;
+
+static int
+intel_setup_io(struct pci_access *a UNUSED)
+{
+ if (iopl_enabled)
+ return 1;
+
+ if (obsd_iopl(3) < 0)
+ {
+ return 0;
+ }
+
+ iopl_enabled = 1;
+ return 1;
+}
+
+static inline void
+intel_cleanup_io(struct pci_access *a UNUSED)
+{
+ if (iopl_enabled)
+ {
+ obsd_iopl(0);
+ iopl_enabled = 0;
+ }
+}
+
+static inline void intel_io_lock(void)
+{
+}
+
+static inline void intel_io_unlock(void)
+{
+}
diff --git a/lib/i386-io-sunos.h b/lib/i386-io-sunos.h
index 86948d9..99fd576 100644
--- a/lib/i386-io-sunos.h
+++ b/lib/i386-io-sunos.h
@@ -12,6 +12,8 @@
#include <sys/sysi86.h>
#include <sys/psw.h>
+#include "i386-io-access.h"
+
static int
intel_setup_io(struct pci_access *a UNUSED)
{
@@ -24,48 +26,6 @@ intel_cleanup_io(struct pci_access *a UNUSED)
/* FIXME: How to switch off I/O port access? */
}
-static inline u8
-inb (u16 port)
-{
- u8 v;
- __asm__ __volatile__ ("inb (%w1)":"=a" (v):"Nd" (port));
- return v;
-}
-
-static inline u16
-inw (u16 port)
-{
- u16 v;
- __asm__ __volatile__ ("inw (%w1)":"=a" (v):"Nd" (port));
- return v;
-}
-
-static inline u32
-inl (u16 port)
-{
- u32 v;
- __asm__ __volatile__ ("inl (%w1)":"=a" (v):"Nd" (port));
- return v;
-}
-
-static inline void
-outb (u8 value, u16 port)
-{
- __asm__ __volatile__ ("outb (%w1)": :"a" (value), "Nd" (port));
-}
-
-static inline void
-outw (u16 value, u16 port)
-{
- __asm__ __volatile__ ("outw (%w1)": :"a" (value), "Nd" (port));
-}
-
-static inline void
-outl (u32 value, u16 port)
-{
- __asm__ __volatile__ ("outl (%w1)": :"a" (value), "Nd" (port));
-}
-
static inline void intel_io_lock(void)
{
}
diff --git a/lib/i386-io-windows.h b/lib/i386-io-windows.h
index 73af883..fd4030d 100644
--- a/lib/i386-io-windows.h
+++ b/lib/i386-io-windows.h
@@ -10,95 +10,10 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#include <io.h>
#include <windows.h>
#include <aclapi.h>
-#ifdef _MSC_VER
-/* MSVC compiler provides I/O port intrinsics for both 32 and 64-bit modes. */
-#pragma intrinsic(_outp)
-#pragma intrinsic(_outpw)
-#pragma intrinsic(_outpd)
-#pragma intrinsic(_inp)
-#pragma intrinsic(_inpw)
-#pragma intrinsic(_inpd)
-#elif defined(_WIN64) || defined(_UCRT)
-/*
- * For other compilers I/O port intrinsics are available in <intrin.h> header
- * file either as inline/external functions or macros. Beware that <intrin.h>
- * names are different than MSVC intrinsics names and glibc function names.
- * Usage of <intrin.h> is also the prefered way for 64-bit mode or when using
- * new UCRT library.
- */
-#include <intrin.h>
-#define _outp(x,y) __outbyte(x,y)
-#define _outpw(x,y) __outword(x,y)
-#define _outpd(x,y) __outdword(x,y)
-#define _inp(x) __inbyte(x)
-#define _inpw(x) __inword(x)
-#define _inpd(x) __indword(x)
-#elif defined(__CRTDLL__) || (defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x400)
-/*
- * Old 32-bit CRTDLL library and pre-4.00 MSVCRT library do not provide I/O
- * port functions. As these libraries exist only in 32-bit mode variant,
- * implement I/O port functions via 32-bit inline assembly.
- */
-static inline int _outp(unsigned short port, int databyte)
-{
- asm volatile ("outb %b0, %w1" : : "a" (databyte), "Nd" (port));
- return databyte;
-}
-static inline unsigned short _outpw(unsigned short port, unsigned short dataword)
-{
- asm volatile ("outw %w0, %w1" : : "a" (dataword), "Nd" (port));
- return dataword;
-}
-static inline unsigned long _outpd(unsigned short port, unsigned long dataword)
-{
- asm volatile ("outl %0, %w1" : : "a" (dataword), "Nd" (port));
- return dataword;
-}
-static inline int _inp(unsigned short port)
-{
- unsigned char ret;
- asm volatile ("inb %w1, %0" : "=a" (ret) : "Nd" (port));
- return ret;
-}
-static inline unsigned short _inpw(unsigned short port)
-{
- unsigned short ret;
- asm volatile ("inw %w1, %0" : "=a" (ret) : "Nd" (port));
- return ret;
-}
-static inline unsigned long _inpd(unsigned short port)
-{
- unsigned long ret;
- asm volatile ("inl %w1, %0" : "=a" (ret) : "Nd" (port));
- return ret;
-}
-#elif !defined(__GNUC__)
-/*
- * Old 32-bit MSVCRT (non-UCRT) library provides I/O port functions. Function
- * prototypes are defined in <conio.h> header file but they are missing in
- * some MinGW toolchains. So for GCC compiler define them manually.
- */
-#include <conio.h>
-#else
-int _outp(unsigned short port, int databyte);
-unsigned short _outpw(unsigned short port, unsigned short dataword);
-unsigned long _outpd(unsigned short port, unsigned long dataword);
-int _inp(unsigned short port);
-unsigned short _inpw(unsigned short port);
-unsigned long _inpd(unsigned short port);
-#endif
-
-#define outb(x,y) _outp(y,x)
-#define outw(x,y) _outpw(y,x)
-#define outl(x,y) _outpd(y,x)
-
-#define inb(x) _inp(x)
-#define inw(x) _inpw(x)
-#define inl(x) _inpd(x)
+#include "i386-io-access.h"
/*
* Define __readeflags() for MSVC and GCC compilers.
diff --git a/lib/i386-ports.c b/lib/i386-ports.c
index 1e2c402..5f8aea4 100644
--- a/lib/i386-ports.c
+++ b/lib/i386-ports.c
@@ -30,6 +30,8 @@
#include "i386-io-beos.h"
#elif defined(PCI_OS_DJGPP)
#include "i386-io-djgpp.h"
+#elif defined(PCI_OS_OPENBSD)
+#include "i386-io-openbsd.h"
#else
#error Do not know how to access I/O ports on this OS.
#endif
@@ -116,12 +118,12 @@ conf1_detect(struct pci_access *a)
}
intel_io_lock();
- outb (0x01, 0xCFB);
- tmp = inl (0xCF8);
- outl (0x80000000, 0xCF8);
- if (inl (0xCF8) == 0x80000000)
+ intel_outb (0x01, 0xCFB);
+ tmp = intel_inl (0xCF8);
+ intel_outl (0x80000000, 0xCF8);
+ if (intel_inl (0xCF8) == 0x80000000)
res = 1;
- outl (tmp, 0xCF8);
+ intel_outl (tmp, 0xCF8);
intel_io_unlock();
if (res)
@@ -142,18 +144,18 @@ conf1_read(struct pci_dev *d, int pos, byte *buf, int len)
return pci_generic_block_read(d, pos, buf, len);
intel_io_lock();
- outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
+ intel_outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
switch (len)
{
case 1:
- buf[0] = inb(addr);
+ buf[0] = intel_inb(addr);
break;
case 2:
- ((u16 *) buf)[0] = cpu_to_le16(inw(addr));
+ ((u16 *) buf)[0] = cpu_to_le16(intel_inw(addr));
break;
case 4:
- ((u32 *) buf)[0] = cpu_to_le32(inl(addr));
+ ((u32 *) buf)[0] = cpu_to_le32(intel_inl(addr));
break;
}
@@ -174,18 +176,18 @@ conf1_write(struct pci_dev *d, int pos, byte *buf, int len)
return pci_generic_block_write(d, pos, buf, len);
intel_io_lock();
- outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
+ intel_outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
switch (len)
{
case 1:
- outb(buf[0], addr);
+ intel_outb(buf[0], addr);
break;
case 2:
- outw(le16_to_cpu(((u16 *) buf)[0]), addr);
+ intel_outw(le16_to_cpu(((u16 *) buf)[0]), addr);
break;
case 4:
- outl(le32_to_cpu(((u32 *) buf)[0]), addr);
+ intel_outl(le32_to_cpu(((u32 *) buf)[0]), addr);
break;
}
intel_io_unlock();
@@ -210,10 +212,10 @@ conf2_detect(struct pci_access *a)
/* This is ugly and tends to produce false positives. Beware. */
intel_io_lock();
- outb(0x00, 0xCFB);
- outb(0x00, 0xCF8);
- outb(0x00, 0xCFA);
- if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00)
+ intel_outb(0x00, 0xCFB);
+ intel_outb(0x00, 0xCF8);
+ intel_outb(0x00, 0xCFA);
+ if (intel_inb(0xCF8) == 0x00 && intel_inb(0xCFA) == 0x00)
res = intel_sanity_check(a, &pm_intel_conf2);
intel_io_unlock();
return res;
@@ -236,21 +238,21 @@ conf2_read(struct pci_dev *d, int pos, byte *buf, int len)
return pci_generic_block_read(d, pos, buf, len);
intel_io_lock();
- outb((d->func << 1) | 0xf0, 0xcf8);
- outb(d->bus, 0xcfa);
+ intel_outb((d->func << 1) | 0xf0, 0xcf8);
+ intel_outb(d->bus, 0xcfa);
switch (len)
{
case 1:
- buf[0] = inb(addr);
+ buf[0] = intel_inb(addr);
break;
case 2:
- ((u16 *) buf)[0] = cpu_to_le16(inw(addr));
+ ((u16 *) buf)[0] = cpu_to_le16(intel_inw(addr));
break;
case 4:
- ((u32 *) buf)[0] = cpu_to_le32(inl(addr));
+ ((u32 *) buf)[0] = cpu_to_le32(intel_inl(addr));
break;
}
- outb(0, 0xcf8);
+ intel_outb(0, 0xcf8);
intel_io_unlock();
return res;
}
@@ -272,22 +274,22 @@ conf2_write(struct pci_dev *d, int pos, byte *buf, int len)
return pci_generic_block_write(d, pos, buf, len);
intel_io_lock();
- outb((d->func << 1) | 0xf0, 0xcf8);
- outb(d->bus, 0xcfa);
+ intel_outb((d->func << 1) | 0xf0, 0xcf8);
+ intel_outb(d->bus, 0xcfa);
switch (len)
{
case 1:
- outb(buf[0], addr);
+ intel_outb(buf[0], addr);
break;
case 2:
- outw(le16_to_cpu(* (u16 *) buf), addr);
+ intel_outw(le16_to_cpu(* (u16 *) buf), addr);
break;
case 4:
- outl(le32_to_cpu(* (u32 *) buf), addr);
+ intel_outl(le32_to_cpu(* (u32 *) buf), addr);
break;
}
- outb(0, 0xcf8);
+ intel_outb(0, 0xcf8);
intel_io_unlock();
return res;
}