[ioapi] Absorb virt_to_phys() and phys_to_virt() into the I/O API
[people/sha0/gpxe.git] / src / arch / i386 / include / gpxe / x86_io.h
1 #ifndef _GPXE_X86_IO_H
2 #define _GPXE_X86_IO_H
3
4 /** @file
5  *
6  * gPXE I/O API for x86
7  *
8  * i386 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  * and will crash original Pentium and earlier CPUs.  Fortunately, no
14  * hardware that requires atomic 64-bit accesses will physically fit
15  * into a machine with such an old CPU anyway.
16  */
17
18 #include <virtaddr.h>
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 static inline __always_inline unsigned long
32 IOAPI_INLINE ( x86, virt_to_phys ) ( volatile const void *addr ) {
33         return ( ( ( unsigned long ) addr ) + virt_offset );
34 }
35
36 static inline __always_inline void *
37 IOAPI_INLINE ( x86, phys_to_virt ) ( unsigned long phys_addr ) {
38         return ( ( void * ) ( phys_addr - virt_offset ) );
39 }
40
41 static inline __always_inline unsigned long
42 IOAPI_INLINE ( x86, virt_to_bus ) ( volatile const void *addr ) {
43         return virt_to_phys ( addr );
44 }
45
46 static inline __always_inline void *
47 IOAPI_INLINE ( x86, bus_to_virt ) ( unsigned long bus_addr ) {
48         return phys_to_virt ( bus_addr );
49 }
50
51 static inline __always_inline void *
52 IOAPI_INLINE ( x86, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
53         return phys_to_virt ( bus_addr );
54 }
55
56 static inline __always_inline void
57 IOAPI_INLINE ( x86, iounmap ) ( volatile const void *io_addr __unused ) {
58         /* Nothing to do */
59 }
60
61 static inline __always_inline unsigned long
62 IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) {
63         return virt_to_phys ( io_addr );
64 }
65
66 /*
67  * MMIO reads and writes up to 32 bits
68  *
69  */
70
71 #define X86_READX( _api_func, _type )                                         \
72 static inline __always_inline _type                                           \
73 IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) {                 \
74         return *io_addr;                                                      \
75 }
76 X86_READX ( readb, uint8_t );
77 X86_READX ( readw, uint16_t );
78 X86_READX ( readl, uint32_t );
79
80 #define X86_WRITEX( _api_func, _type )                                        \
81 static inline __always_inline void                                            \
82 IOAPI_INLINE ( x86, _api_func ) ( _type data,                                 \
83                                   volatile _type *io_addr ) {                 \
84         *io_addr = data;                                                      \
85 }
86 X86_WRITEX ( writeb, uint8_t );
87 X86_WRITEX ( writew, uint16_t );
88 X86_WRITEX ( writel, uint32_t );
89
90 /*
91  * PIO reads and writes up to 32 bits
92  *
93  */
94
95 #define X86_INX( _insn_suffix, _type, _reg_prefix )                           \
96 static inline __always_inline _type                                           \
97 IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) {        \
98         _type data;                                                           \
99         __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0"   \
100                                : "=a" ( data ) : "Nd" ( io_addr ) );          \
101         return data;                                                          \
102 }                                                                             \
103 static inline __always_inline void                                            \
104 IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr,          \
105                                             _type *data,                      \
106                                             unsigned int count ) {            \
107         unsigned int discard_D;                                               \
108         __asm__ __volatile__ ( "rep ins" #_insn_suffix                        \
109                                : "=D" ( discard_D )                           \
110                                : "d" ( io_addr ), "c" ( count ),              \
111                                  "0" ( data ) );                              \
112 }
113 X86_INX ( b, uint8_t, "b" );
114 X86_INX ( w, uint16_t, "w" );
115 X86_INX ( l, uint32_t, "k" );
116
117 #define X86_OUTX( _insn_suffix, _type, _reg_prefix )                          \
118 static inline __always_inline void                                            \
119 IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data,                       \
120                                             volatile _type *io_addr ) {       \
121         __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1"  \
122                                : : "a" ( data ), "Nd" ( io_addr ) );          \
123 }                                                                             \
124 static inline __always_inline void                                            \
125 IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr,         \
126                                              const _type *data,               \
127                                              unsigned int count ) {           \
128         unsigned int discard_D;                                               \
129         __asm__ __volatile__ ( "rep outs" #_insn_suffix                       \
130                                : "=D" ( discard_D )                           \
131                                : "d" ( io_addr ), "c" ( count ),              \
132                                  "0" ( data ) );                              \
133 }
134 X86_OUTX ( b, uint8_t, "b" );
135 X86_OUTX ( w, uint16_t, "w" );
136 X86_OUTX ( l, uint32_t, "k" );
137
138 /*
139  * Slow down I/O
140  *
141  */
142
143 static inline __always_inline void
144 IOAPI_INLINE ( x86, iodelay ) ( void ) {
145         __asm__ __volatile__ ( "outb %al, $0x80" );
146 }
147
148 /*
149  * Memory barrier
150  *
151  */
152
153 static inline __always_inline void
154 IOAPI_INLINE ( x86, mb ) ( void ) {
155         __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
156 }
157
158 #endif /* _GPXE_X86_IO_H */