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