123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- #ifndef _IPXE_X86_IO_H
- #define _IPXE_X86_IO_H
-
- /** @file
- *
- * iPXE I/O API for x86
- *
- * i386 uses direct pointer dereferences for accesses to memory-mapped
- * I/O space, and the inX/outX instructions for accesses to
- * port-mapped I/O space.
- *
- * 64-bit atomic accesses (readq() and writeq()) use MMX instructions,
- * and will crash original Pentium and earlier CPUs. Fortunately, no
- * hardware that requires atomic 64-bit accesses will physically fit
- * into a machine with such an old CPU anyway.
- */
-
- FILE_LICENCE ( GPL2_OR_LATER );
-
- #ifdef IOAPI_X86
- #define IOAPI_PREFIX_x86
- #else
- #define IOAPI_PREFIX_x86 __x86_
- #endif
-
- /*
- * Memory space mappings
- *
- */
-
- /*
- * Physical<->Bus and Bus<->I/O address mappings
- *
- */
-
- static inline __always_inline unsigned long
- IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
- return phys_addr;
- }
-
- static inline __always_inline unsigned long
- IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
- return bus_addr;
- }
-
- static inline __always_inline void *
- IOAPI_INLINE ( x86, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
- return phys_to_virt ( bus_addr );
- }
-
- static inline __always_inline void
- IOAPI_INLINE ( x86, iounmap ) ( volatile const void *io_addr __unused ) {
- /* Nothing to do */
- }
-
- static inline __always_inline unsigned long
- IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) {
- return virt_to_phys ( io_addr );
- }
-
- /*
- * MMIO reads and writes up to 32 bits
- *
- */
-
- #define X86_READX( _api_func, _type ) \
- static inline __always_inline _type \
- IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \
- return *io_addr; \
- }
- X86_READX ( readb, uint8_t );
- X86_READX ( readw, uint16_t );
- X86_READX ( readl, uint32_t );
-
- #define X86_WRITEX( _api_func, _type ) \
- static inline __always_inline void \
- IOAPI_INLINE ( x86, _api_func ) ( _type data, \
- volatile _type *io_addr ) { \
- *io_addr = data; \
- }
- X86_WRITEX ( writeb, uint8_t );
- X86_WRITEX ( writew, uint16_t );
- X86_WRITEX ( writel, uint32_t );
-
- /*
- * PIO reads and writes up to 32 bits
- *
- */
-
- #define X86_INX( _insn_suffix, _type, _reg_prefix ) \
- static inline __always_inline _type \
- IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) { \
- _type data; \
- __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0" \
- : "=a" ( data ) : "Nd" ( io_addr ) ); \
- return data; \
- } \
- static inline __always_inline void \
- IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr, \
- _type *data, \
- unsigned int count ) { \
- unsigned int discard_D; \
- __asm__ __volatile__ ( "rep ins" #_insn_suffix \
- : "=D" ( discard_D ) \
- : "d" ( io_addr ), "c" ( count ), \
- "0" ( data ) ); \
- }
- X86_INX ( b, uint8_t, "b" );
- X86_INX ( w, uint16_t, "w" );
- X86_INX ( l, uint32_t, "k" );
-
- #define X86_OUTX( _insn_suffix, _type, _reg_prefix ) \
- static inline __always_inline void \
- IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data, \
- volatile _type *io_addr ) { \
- __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1" \
- : : "a" ( data ), "Nd" ( io_addr ) ); \
- } \
- static inline __always_inline void \
- IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr, \
- const _type *data, \
- unsigned int count ) { \
- unsigned int discard_S; \
- __asm__ __volatile__ ( "rep outs" #_insn_suffix \
- : "=S" ( discard_S ) \
- : "d" ( io_addr ), "c" ( count ), \
- "0" ( data ) ); \
- }
- X86_OUTX ( b, uint8_t, "b" );
- X86_OUTX ( w, uint16_t, "w" );
- X86_OUTX ( l, uint32_t, "k" );
-
- /*
- * Slow down I/O
- *
- */
-
- static inline __always_inline void
- IOAPI_INLINE ( x86, iodelay ) ( void ) {
- __asm__ __volatile__ ( "outb %al, $0x80" );
- }
-
- /*
- * Memory barrier
- *
- */
-
- static inline __always_inline void
- IOAPI_INLINE ( x86, mb ) ( void ) {
- __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
- }
-
- #endif /* _IPXE_X86_IO_H */
|