diff options
author | Martin Mareš <mj@ucw.cz> | 2024-02-17 23:22:18 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-17 23:22:18 +0100 |
commit | 26a5aaaa945e37a4fd1d05803cdade82b9f9a9e3 (patch) | |
tree | 31aa168a90620afaf4c2aec0da559af972ff8a5c | |
parent | a997ef132d943990cdb65d32a6605b6ff4bfcd79 (diff) | |
parent | ebbd5e810639fe13c6e85eb358b34997253244d8 (diff) | |
download | pciutils-26a5aaaa945e37a4fd1d05803cdade82b9f9a9e3.tar.gz |
Merge pull request #166 from DigitalDJ/master
i386-ports: Add support for OpenBSD
-rw-r--r-- | README | 2 | ||||
-rwxr-xr-x | lib/configure | 6 | ||||
-rw-r--r-- | lib/i386-io-access.h | 75 | ||||
-rw-r--r-- | lib/i386-io-beos.h | 12 | ||||
-rw-r--r-- | lib/i386-io-cygwin.h | 2 | ||||
-rw-r--r-- | lib/i386-io-djgpp.h | 8 | ||||
-rw-r--r-- | lib/i386-io-haiku.h | 21 | ||||
-rw-r--r-- | lib/i386-io-hurd.h | 2 | ||||
-rw-r--r-- | lib/i386-io-linux.h | 2 | ||||
-rw-r--r-- | lib/i386-io-openbsd.h | 54 | ||||
-rw-r--r-- | lib/i386-io-sunos.h | 44 | ||||
-rw-r--r-- | lib/i386-io-windows.h | 87 | ||||
-rw-r--r-- | lib/i386-ports.c | 60 |
13 files changed, 198 insertions, 177 deletions
@@ -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; } |