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 
20 #ifdef IOAPI_X86
21 #define IOAPI_PREFIX_x86
22 #else
23 #define IOAPI_PREFIX_x86 __x86_
24 #endif
25 
26 /*
27  * Memory space mappings
28  *
29  */
30 
31 /*
32  * Physical<->Bus address mappings
33  *
34  */
35 
36 static inline __always_inline unsigned long
37 IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
38  return phys_addr;
39 }
40 
41 static inline __always_inline unsigned long
42 IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
43  return bus_addr;
44 }
45 
46 /*
47  * MMIO reads and writes up to native word size
48  *
49  */
50 
51 #define X86_READX( _api_func, _type ) \
52 static inline __always_inline _type \
53 IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \
54  return *io_addr; \
55 }
59 #ifdef __x86_64__
61 #endif
62 
63 #define X86_WRITEX( _api_func, _type ) \
64 static inline __always_inline void \
65 IOAPI_INLINE ( x86, _api_func ) ( _type data, \
66  volatile _type *io_addr ) { \
67  *io_addr = data; \
68 }
72 #ifdef __x86_64__
74 #endif
75 
76 /*
77  * PIO reads and writes up to 32 bits
78  *
79  */
80 
81 #define X86_INX( _insn_suffix, _type, _reg_prefix ) \
82 static inline __always_inline _type \
83 IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) { \
84  _type data; \
85  __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0" \
86  : "=a" ( data ) : "Nd" ( io_addr ) ); \
87  return data; \
88 } \
89 static inline __always_inline void \
90 IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr, \
91  _type *data, \
92  unsigned int count ) { \
93  unsigned int discard_D; \
94  __asm__ __volatile__ ( "rep ins" #_insn_suffix \
95  : "=D" ( discard_D ) \
96  : "d" ( io_addr ), "c" ( count ), \
97  "0" ( data ) ); \
98 }
99 X86_INX ( b, uint8_t, "b" );
100 X86_INX ( w, uint16_t, "w" );
101 X86_INX ( l, uint32_t, "k" );
102 
103 #define X86_OUTX( _insn_suffix, _type, _reg_prefix ) \
104 static inline __always_inline void \
105 IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data, \
106  volatile _type *io_addr ) { \
107  __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1" \
108  : : "a" ( data ), "Nd" ( io_addr ) ); \
109 } \
110 static inline __always_inline void \
111 IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr, \
112  const _type *data, \
113  unsigned int count ) { \
114  unsigned int discard_S; \
115  __asm__ __volatile__ ( "rep outs" #_insn_suffix \
116  : "=S" ( discard_S ) \
117  : "d" ( io_addr ), "c" ( count ), \
118  "0" ( data ) ); \
119 }
120 X86_OUTX ( b, uint8_t, "b" );
121 X86_OUTX ( w, uint16_t, "w" );
122 X86_OUTX ( l, uint32_t, "k" );
123 
124 /*
125  * Slow down I/O
126  *
127  */
128 
129 static inline __always_inline void
130 IOAPI_INLINE ( x86, iodelay ) ( void ) {
131  __asm__ __volatile__ ( "outb %al, $0x80" );
132 }
133 
134 /*
135  * Memory barrier
136  *
137  */
138 
139 static inline __always_inline void
140 IOAPI_INLINE ( x86, mb ) ( void ) {
141  __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
142 }
143 
144 #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:51
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
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:63
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:81
static __always_inline unsigned long IOAPI_INLINE(x86, phys_to_bus)(unsigned long phys_addr)
Definition: x86_io.h:37
#define __always_inline
Declare a function to be always inline.
Definition: compiler.h:611
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned char uint8_t
Definition: stdint.h:10
__asm__ __volatile__("\n1:\n\t" "movb -1(%3,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %4, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c), "+m"(*value) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
unsigned int uint32_t
Definition: stdint.h:12
unsigned long phys_to_bus(unsigned long phys_addr)
Convert physical address to a bus address.
uint32_t w[16]
Definition: md4.c:32
__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
uint32_t b
Definition: md4.c:29
#define X86_OUTX(_insn_suffix, _type, _reg_prefix)
Definition: x86_io.h:103
void mb(void)
Memory barrier.
static __always_inline void unsigned long bus_addr
Definition: ecam_io.h:135
void iodelay(void)
Slow down I/O.
unsigned long bus_to_phys(unsigned long bus_addr)
Convert bus address to a physical address.
void writeq(uint64_t data, volatile uint64_t *io_addr)
Write 64-bit qword to memory-mapped device.