]> mj.ucw.cz Git - pciutils.git/commitdiff
libpci: i386-io-windows.h: Fix definitions of I/O port functions for UCRT, CRTDLL...
authorPali Rohár <pali@kernel.org>
Sat, 25 Dec 2021 12:45:28 +0000 (13:45 +0100)
committerMartin Mareš <mj@ucw.cz>
Sun, 26 Dec 2021 21:32:18 +0000 (22:32 +0100)
Functions _outp(), _outpw(), _outpd(), _inp(), _inpw() and _inpd() are
available only in 32-bit version of the old MSVCRT library. They are not
available in 64-bit version of old MSVCRT library and neither the oldest
CRTDLL library or in new UCRT library.

Function prototypes for 32-bit mode should be available in <conio.h> header
file. But they are missing in some MinGW toolchains.

For 64-bit mode I/O port functions are defined only as inline functions or
intrinsics macros in <intrin.h> header file but under different names:
__outbyte(), __outword(), __outdword(), __inbyte(), __inword(), __indword()
This header file is available also in UCRT-compatible compilers.

When compiling with the oldest CRTDLL library and not using <intrin.h>
header file, it is required to provide own implementation of these
functions. Do it via inline assembly.

With this change it is possible to compile i386-io-windows.h with all
combination of toolchains, compilers, crt library and arch mode.

The most important is the fix to allow compilation with modern UCRT
library.

lib/i386-io-windows.h

index e2492df71a73e6c4f1c1b53f3332065aca928ee9..e065620de29bf62c76d7e9d47d29f5d4407770b5 100644 (file)
 #include <io.h>
 #include <windows.h>
 
-#ifndef __GNUC__
+#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__)
+/*
+ * Old CRTDLL library does not provide I/O port functions. Even it is the oldest
+ * CRT library it exists also in 64-bit variant. Implement I/O port functions
+ * via inline assembly just for 32-bit mode as 64-bit mode uses above <intrin.h>
+ * header.
+ */
+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);