X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fi386-io-linux.h;h=a2fd69e502aaee1688e0830ee62382b55ff344e1;hb=f9447371463eb6bb4c001be132a0d7c495df00d0;hp=ee119d25094608eb1ecc43be4f4c37951671e2f7;hpb=68245cfdf612741cb0916434a25ef86c408821c1;p=pciutils.git diff --git a/lib/i386-io-linux.h b/lib/i386-io-linux.h index ee119d2..a2fd69e 100644 --- a/lib/i386-io-linux.h +++ b/lib/i386-io-linux.h @@ -1,31 +1,73 @@ /* * The PCI Library -- Access to i386 I/O ports on Linux * - * Copyright (c) 1997--2003 Martin Mares + * Copyright (c) 1997--2006 Martin Mares * * Can be freely distributed and used under the terms of the GNU GPL. */ -#ifdef __GLIBC__ #include -#else -#include -#endif +#include -static int intel_iopl_set = -1; +static int ioperm_enabled; +static int iopl_enabled; static int -intel_setup_io(void) +intel_setup_io(struct pci_access *a UNUSED) { - if (intel_iopl_set < 0) - intel_iopl_set = (iopl(3) < 0) ? 0 : 1; - return intel_iopl_set; + if (ioperm_enabled || iopl_enabled) + return 1; + + /* + * Before Linux 2.6.8, only the first 0x3ff I/O ports permissions can be + * modified via ioperm(). Since 2.6.8 all ports are supported. + * Since Linux 5.5, EFLAGS-based iopl() implementation was removed and + * replaced by new TSS-IOPB-map-all-based emulator. Before Linux 5.5, + * EFLAGS-based iopl() allowed userspace to enable/disable interrupts, + * which is dangerous. So prefer usage of ioperm() and fallback to iopl(). + */ + if (ioperm(0xcf8, 8, 1) < 0) /* conf1 + conf2 ports */ + { + if (errno == EINVAL) /* ioperm() unsupported */ + { + if (iopl(3) < 0) + return 0; + iopl_enabled = 1; + return 1; + } + return 0; + } + if (ioperm(0xc000, 0xfff, 1) < 0) /* remaining conf2 ports */ + { + ioperm(0xcf8, 8, 0); + return 0; + } + + ioperm_enabled = 1; + return 1; } static inline void -intel_cleanup_io(void) +intel_cleanup_io(struct pci_access *a UNUSED) +{ + if (ioperm_enabled) + { + ioperm(0xcf8, 8, 0); + ioperm(0xc000, 0xfff, 0); + ioperm_enabled = 0; + } + + if (iopl_enabled) + { + iopl(0); + iopl_enabled = 0; + } +} + +static inline void intel_io_lock(void) +{ +} + +static inline void intel_io_unlock(void) { - if (intel_iopl_set > 0) - iopl(3); - intel_iopl_set = -1; }