[contrib] Allow Network Protocol header to display in rom-o-matic
[gpxe.git] / src / arch / i386 / include / gpxe / x86_io.h
blobbeb5b22a6e8bfa3250894dfff1ab3aabbb5b2473
1 #ifndef _GPXE_X86_IO_H
2 #define _GPXE_X86_IO_H
4 /** @file
6 * gPXE I/O API for x86
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.
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.
18 FILE_LICENCE ( GPL2_OR_LATER );
20 #ifdef IOAPI_X86
21 #define IOAPI_PREFIX_x86
22 #else
23 #define IOAPI_PREFIX_x86 __x86_
24 #endif
27 * Memory space mappings
32 * Physical<->Bus and Bus<->I/O address mappings
36 static inline __always_inline unsigned long
37 IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
38 return phys_addr;
41 static inline __always_inline unsigned long
42 IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
43 return bus_addr;
46 static inline __always_inline void *
47 IOAPI_INLINE ( x86, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
48 return phys_to_virt ( bus_addr );
51 static inline __always_inline void
52 IOAPI_INLINE ( x86, iounmap ) ( volatile const void *io_addr __unused ) {
53 /* Nothing to do */
56 static inline __always_inline unsigned long
57 IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) {
58 return virt_to_phys ( io_addr );
62 * MMIO reads and writes up to 32 bits
66 #define X86_READX( _api_func, _type ) \
67 static inline __always_inline _type \
68 IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \
69 return *io_addr; \
71 X86_READX ( readb, uint8_t );
72 X86_READX ( readw, uint16_t );
73 X86_READX ( readl, uint32_t );
75 #define X86_WRITEX( _api_func, _type ) \
76 static inline __always_inline void \
77 IOAPI_INLINE ( x86, _api_func ) ( _type data, \
78 volatile _type *io_addr ) { \
79 *io_addr = data; \
81 X86_WRITEX ( writeb, uint8_t );
82 X86_WRITEX ( writew, uint16_t );
83 X86_WRITEX ( writel, uint32_t );
86 * PIO reads and writes up to 32 bits
90 #define X86_INX( _insn_suffix, _type, _reg_prefix ) \
91 static inline __always_inline _type \
92 IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) { \
93 _type data; \
94 __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0" \
95 : "=a" ( data ) : "Nd" ( io_addr ) ); \
96 return data; \
97 } \
98 static inline __always_inline void \
99 IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr, \
100 _type *data, \
101 unsigned int count ) { \
102 unsigned int discard_D; \
103 __asm__ __volatile__ ( "rep ins" #_insn_suffix \
104 : "=D" ( discard_D ) \
105 : "d" ( io_addr ), "c" ( count ), \
106 "0" ( data ) ); \
108 X86_INX ( b, uint8_t, "b" );
109 X86_INX ( w, uint16_t, "w" );
110 X86_INX ( l, uint32_t, "k" );
112 #define X86_OUTX( _insn_suffix, _type, _reg_prefix ) \
113 static inline __always_inline void \
114 IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data, \
115 volatile _type *io_addr ) { \
116 __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1" \
117 : : "a" ( data ), "Nd" ( io_addr ) ); \
119 static inline __always_inline void \
120 IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr, \
121 const _type *data, \
122 unsigned int count ) { \
123 unsigned int discard_S; \
124 __asm__ __volatile__ ( "rep outs" #_insn_suffix \
125 : "=S" ( discard_S ) \
126 : "d" ( io_addr ), "c" ( count ), \
127 "0" ( data ) ); \
129 X86_OUTX ( b, uint8_t, "b" );
130 X86_OUTX ( w, uint16_t, "w" );
131 X86_OUTX ( l, uint32_t, "k" );
134 * Slow down I/O
138 static inline __always_inline void
139 IOAPI_INLINE ( x86, iodelay ) ( void ) {
140 __asm__ __volatile__ ( "outb %al, $0x80" );
144 * Memory barrier
148 static inline __always_inline void
149 IOAPI_INLINE ( x86, mb ) ( void ) {
150 __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
153 #endif /* _GPXE_X86_IO_H */