]> mj.ucw.cz Git - pciutils.git/blob - lib/i386-io-linux.h
libpci: ecam: Fix detect sequence when addresses are not specified
[pciutils.git] / lib / i386-io-linux.h
1 /*
2  *      The PCI Library -- Access to i386 I/O ports on Linux
3  *
4  *      Copyright (c) 1997--2006 Martin Mares <mj@ucw.cz>
5  *
6  *      Can be freely distributed and used under the terms of the GNU GPL v2+
7  *
8  *      SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include <sys/io.h>
12 #include <errno.h>
13
14 #include "i386-io-access.h"
15
16 static int ioperm_enabled;
17 static int iopl_enabled;
18
19 static int
20 intel_setup_io(struct pci_access *a UNUSED)
21 {
22   if (ioperm_enabled || iopl_enabled)
23     return 1;
24
25   /*
26    * Before Linux 2.6.8, only the first 0x3ff I/O ports permissions can be
27    * modified via ioperm(). Since 2.6.8 all ports are supported.
28    * Since Linux 5.5, EFLAGS-based iopl() implementation was removed and
29    * replaced by new TSS-IOPB-map-all-based emulator. Before Linux 5.5,
30    * EFLAGS-based iopl() allowed userspace to enable/disable interrupts,
31    * which is dangerous. So prefer usage of ioperm() and fallback to iopl().
32    */
33   if (ioperm(0xcf8, 8, 1) < 0) /* conf1 + conf2 ports */
34     {
35       if (errno == EINVAL) /* ioperm() unsupported */
36         {
37           if (iopl(3) < 0)
38             return 0;
39           iopl_enabled = 1;
40           return 1;
41         }
42       return 0;
43     }
44   if (ioperm(0xc000, 0xfff, 1) < 0) /* remaining conf2 ports */
45     {
46       ioperm(0xcf8, 8, 0);
47       return 0;
48     }
49
50   ioperm_enabled = 1;
51   return 1;
52 }
53
54 static inline void
55 intel_cleanup_io(struct pci_access *a UNUSED)
56 {
57   if (ioperm_enabled)
58     {
59       ioperm(0xcf8, 8, 0);
60       ioperm(0xc000, 0xfff, 0);
61       ioperm_enabled = 0;
62     }
63
64   if (iopl_enabled)
65     {
66       iopl(0);
67       iopl_enabled = 0;
68     }
69 }
70
71 static inline void intel_io_lock(void)
72 {
73 }
74
75 static inline void intel_io_unlock(void)
76 {
77 }