iPXE
x86_io.h
Go to the documentation of this file.
1 #ifndef _IPXE_X86_IO_H
2 #define _IPXE_X86_IO_H
3 
4 /** @file
5  *
6  * iPXE I/O API for x86
7  *
8  * x86 uses direct pointer dereferences for accesses to memory-mapped
9  * I/O space, and the inX/outX instructions for accesses to
10  * port-mapped I/O space.
11  *
12  * 64-bit atomic accesses (readq() and writeq()) use MMX instructions
13  * under i386, and will crash original Pentium and earlier CPUs.
14  * Fortunately, no hardware that requires atomic 64-bit accesses will
15  * physically fit into a machine with such an old CPU anyway.
16  */
17 
18 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
19 FILE_SECBOOT ( PERMITTED );
20 
21 #ifdef IOAPI_X86
22 #define IOAPI_PREFIX_x86
23 #else
24 #define IOAPI_PREFIX_x86 __x86_
25 #endif
26 
27 /*
28  * Memory space mappings
29  *
30  */
31 
32 /*
33  * Physical<->Bus address mappings
34  *
35  */
36 
37 static inline __always_inline unsigned long
38 IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
39  return phys_addr;
40 }
41 
42 static inline __always_inline unsigned long
43 IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
44  return bus_addr;
45 }
46 
47 /*
48  * MMIO reads and writes up to native word size
49  *
50  */
51 
52 #define X86_READX( _api_func, _type ) \
53 static inline __always_inline _type \
54 IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \
55  return *io_addr; \
56 }
60 #ifdef __x86_64__
62 #endif
63 
64 #define X86_WRITEX( _api_func, _type ) \
65 static inline __always_inline void \
66 IOAPI_INLINE ( x86, _api_func ) ( _type data, \
67  volatile _type *io_addr ) { \
68  *io_addr = data; \
69 }
73 #ifdef __x86_64__
75 #endif
76 
77 /*
78  * PIO reads and writes up to 32 bits
79  *
80  */
81 
82 #define X86_INX( _insn_suffix, _type, _reg_prefix ) \
83 static inline __always_inline _type \
84 IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) { \
85  _type data; \
86  __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0" \
87  : "=a" ( data ) : "Nd" ( io_addr ) ); \
88  return data; \
89 } \
90 static inline __always_inline void \
91 IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr, \
92  _type *data, \
93  unsigned int count ) { \
94  unsigned int discard_D; \
95  __asm__ __volatile__ ( "rep ins" #_insn_suffix \
96  : "=D" ( discard_D ) \
97  : "d" ( io_addr ), "c" ( count ), \
98  "0" ( data ) ); \
99 }
100 X86_INX ( b, uint8_t, "b" );
101 X86_INX ( w, uint16_t, "w" );
102 X86_INX ( l, uint32_t, "k" );
103 
104 #define X86_OUTX( _insn_suffix, _type, _reg_prefix ) \
105 static inline __always_inline void \
106 IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data, \
107  volatile _type *io_addr ) { \
108  __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1" \
109  : : "a" ( data ), "Nd" ( io_addr ) ); \
110 } \
111 static inline __always_inline void \
112 IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr, \
113  const _type *data, \
114  unsigned int count ) { \
115  unsigned int discard_S; \
116  __asm__ __volatile__ ( "rep outs" #_insn_suffix \
117  : "=S" ( discard_S ) \
118  : "d" ( io_addr ), "c" ( count ), \
119  "0" ( data ) ); \
120 }
121 X86_OUTX ( b, uint8_t, "b" );
122 X86_OUTX ( w, uint16_t, "w" );
123 X86_OUTX ( l, uint32_t, "k" );
124 
125 /*
126  * Slow down I/O
127  *
128  */
129 
130 static inline __always_inline void
131 IOAPI_INLINE ( x86, iodelay ) ( void ) {
132  __asm__ __volatile__ ( "outb %al, $0x80" );
133 }
134 
135 /*
136  * Memory barrier
137  *
138  */
139 
140 static inline __always_inline void
141 IOAPI_INLINE ( x86, mb ) ( void ) {
142  __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
143 }
144 
145 #endif /* _IPXE_X86_IO_H */
unsigned short uint16_t
Definition: stdint.h:11
uint8_t l
Definition: registers.h:15
uint8_t readb(volatile uint8_t *io_addr)
Read byte from memory-mapped device.
#define X86_READX(_api_func, _type)
Definition: x86_io.h:52
uint64_t readq(volatile uint64_t *io_addr)
Read 64-bit qword from memory-mapped device.
uint16_t readw(volatile uint16_t *io_addr)
Read 16-bit word from memory-mapped device.
uint32_t readl(volatile uint32_t *io_addr)
Read 32-bit dword from memory-mapped device.
unsigned long long uint64_t
Definition: stdint.h:13
static __always_inline void unsigned long bus_addr
Definition: pcibios.h:156
void writeb(uint8_t data, volatile uint8_t *io_addr)
Write byte to memory-mapped device.
#define X86_WRITEX(_api_func, _type)
Definition: x86_io.h:64
void writel(uint32_t data, volatile uint32_t *io_addr)
Write 32-bit dword to memory-mapped device.
#define X86_INX(_insn_suffix, _type, _reg_prefix)
Definition: x86_io.h:82
static __always_inline unsigned long IOAPI_INLINE(x86, phys_to_bus)(unsigned long phys_addr)
Definition: x86_io.h:38
#define __always_inline
Declare a function to be always inline.
Definition: compiler.h:611
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned char uint8_t
Definition: stdint.h:10
unsigned int uint32_t
Definition: stdint.h:12
unsigned long phys_to_bus(unsigned long phys_addr)
Convert physical address to a bus address.
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
#define writew
Definition: w89c840.c:159
#define X86_OUTX(_insn_suffix, _type, _reg_prefix)
Definition: x86_io.h:104
void mb(void)
Memory barrier.
void iodelay(void)
Slow down I/O.
unsigned long bus_to_phys(unsigned long bus_addr)
Convert bus address to a physical address.
FILE_SECBOOT(PERMITTED)
void writeq(uint64_t data, volatile uint64_t *io_addr)
Write 64-bit qword to memory-mapped device.