x86_io.h

Go to the documentation of this file.
00001 #ifndef _GPXE_X86_IO_H
00002 #define _GPXE_X86_IO_H
00003 
00004 /** @file
00005  *
00006  * gPXE I/O API for x86
00007  *
00008  * i386 uses direct pointer dereferences for accesses to memory-mapped
00009  * I/O space, and the inX/outX instructions for accesses to
00010  * port-mapped I/O space.
00011  *
00012  * 64-bit atomic accesses (readq() and writeq()) use MMX instructions,
00013  * and will crash original Pentium and earlier CPUs.  Fortunately, no
00014  * hardware that requires atomic 64-bit accesses will physically fit
00015  * into a machine with such an old CPU anyway.
00016  */
00017 
00018 FILE_LICENCE ( GPL2_OR_LATER );
00019 
00020 #ifdef IOAPI_X86
00021 #define IOAPI_PREFIX_x86
00022 #else
00023 #define IOAPI_PREFIX_x86 __x86_
00024 #endif
00025 
00026 /*
00027  * Memory space mappings
00028  *
00029  */
00030 
00031 /*
00032  * Physical<->Bus and Bus<->I/O address mappings
00033  *
00034  */
00035 
00036 static inline __always_inline unsigned long
00037 IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
00038         return phys_addr;
00039 }
00040 
00041 static inline __always_inline unsigned long
00042 IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
00043         return bus_addr;
00044 }
00045 
00046 static inline __always_inline void *
00047 IOAPI_INLINE ( x86, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
00048         return phys_to_virt ( bus_addr );
00049 }
00050 
00051 static inline __always_inline void
00052 IOAPI_INLINE ( x86, iounmap ) ( volatile const void *io_addr __unused ) {
00053         /* Nothing to do */
00054 }
00055 
00056 static inline __always_inline unsigned long
00057 IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) {
00058         return virt_to_phys ( io_addr );
00059 }
00060 
00061 /*
00062  * MMIO reads and writes up to 32 bits
00063  *
00064  */
00065 
00066 #define X86_READX( _api_func, _type )                                         \
00067 static inline __always_inline _type                                           \
00068 IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) {                 \
00069         return *io_addr;                                                      \
00070 }
00071 X86_READX ( readb, uint8_t );
00072 X86_READX ( readw, uint16_t );
00073 X86_READX ( readl, uint32_t );
00074 
00075 #define X86_WRITEX( _api_func, _type )                                        \
00076 static inline __always_inline void                                            \
00077 IOAPI_INLINE ( x86, _api_func ) ( _type data,                                 \
00078                                   volatile _type *io_addr ) {                 \
00079         *io_addr = data;                                                      \
00080 }
00081 X86_WRITEX ( writeb, uint8_t );
00082 X86_WRITEX ( writew, uint16_t );
00083 X86_WRITEX ( writel, uint32_t );
00084 
00085 /*
00086  * PIO reads and writes up to 32 bits
00087  *
00088  */
00089 
00090 #define X86_INX( _insn_suffix, _type, _reg_prefix )                           \
00091 static inline __always_inline _type                                           \
00092 IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) {        \
00093         _type data;                                                           \
00094         __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0"   \
00095                                : "=a" ( data ) : "Nd" ( io_addr ) );          \
00096         return data;                                                          \
00097 }                                                                             \
00098 static inline __always_inline void                                            \
00099 IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr,          \
00100                                             _type *data,                      \
00101                                             unsigned int count ) {            \
00102         unsigned int discard_D;                                               \
00103         __asm__ __volatile__ ( "rep ins" #_insn_suffix                        \
00104                                : "=D" ( discard_D )                           \
00105                                : "d" ( io_addr ), "c" ( count ),              \
00106                                  "0" ( data ) );                              \
00107 }
00108 X86_INX ( b, uint8_t, "b" );
00109 X86_INX ( w, uint16_t, "w" );
00110 X86_INX ( l, uint32_t, "k" );
00111 
00112 #define X86_OUTX( _insn_suffix, _type, _reg_prefix )                          \
00113 static inline __always_inline void                                            \
00114 IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data,                       \
00115                                             volatile _type *io_addr ) {       \
00116         __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1"  \
00117                                : : "a" ( data ), "Nd" ( io_addr ) );          \
00118 }                                                                             \
00119 static inline __always_inline void                                            \
00120 IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr,         \
00121                                              const _type *data,               \
00122                                              unsigned int count ) {           \
00123         unsigned int discard_S;                                               \
00124         __asm__ __volatile__ ( "rep outs" #_insn_suffix                       \
00125                                : "=S" ( discard_S )                           \
00126                                : "d" ( io_addr ), "c" ( count ),              \
00127                                  "0" ( data ) );                              \
00128 }
00129 X86_OUTX ( b, uint8_t, "b" );
00130 X86_OUTX ( w, uint16_t, "w" );
00131 X86_OUTX ( l, uint32_t, "k" );
00132 
00133 /*
00134  * Slow down I/O
00135  *
00136  */
00137 
00138 static inline __always_inline void
00139 IOAPI_INLINE ( x86, iodelay ) ( void ) {
00140         __asm__ __volatile__ ( "outb %al, $0x80" );
00141 }
00142 
00143 /*
00144  * Memory barrier
00145  *
00146  */
00147 
00148 static inline __always_inline void
00149 IOAPI_INLINE ( x86, mb ) ( void ) {
00150         __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
00151 }
00152 
00153 #endif /* _GPXE_X86_IO_H */

Generated on Tue Apr 6 20:00:50 2010 for gPXE by  doxygen 1.5.7.1