You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

x86_io.h 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #ifndef _IPXE_X86_IO_H
  2. #define _IPXE_X86_IO_H
  3. /** @file
  4. *
  5. * iPXE I/O API for x86
  6. *
  7. * x86 uses direct pointer dereferences for accesses to memory-mapped
  8. * I/O space, and the inX/outX instructions for accesses to
  9. * port-mapped I/O space.
  10. *
  11. * 64-bit atomic accesses (readq() and writeq()) use MMX instructions
  12. * under i386, and will crash original Pentium and earlier CPUs.
  13. * Fortunately, no hardware that requires atomic 64-bit accesses will
  14. * physically fit into a machine with such an old CPU anyway.
  15. */
  16. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  17. #ifdef IOAPI_X86
  18. #define IOAPI_PREFIX_x86
  19. #else
  20. #define IOAPI_PREFIX_x86 __x86_
  21. #endif
  22. /*
  23. * Memory space mappings
  24. *
  25. */
  26. /** Page shift */
  27. #define PAGE_SHIFT 12
  28. /*
  29. * Physical<->Bus address mappings
  30. *
  31. */
  32. static inline __always_inline unsigned long
  33. IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
  34. return phys_addr;
  35. }
  36. static inline __always_inline unsigned long
  37. IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
  38. return bus_addr;
  39. }
  40. /*
  41. * MMIO reads and writes up to native word size
  42. *
  43. */
  44. #define X86_READX( _api_func, _type ) \
  45. static inline __always_inline _type \
  46. IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \
  47. return *io_addr; \
  48. }
  49. X86_READX ( readb, uint8_t );
  50. X86_READX ( readw, uint16_t );
  51. X86_READX ( readl, uint32_t );
  52. #ifdef __x86_64__
  53. X86_READX ( readq, uint64_t );
  54. #endif
  55. #define X86_WRITEX( _api_func, _type ) \
  56. static inline __always_inline void \
  57. IOAPI_INLINE ( x86, _api_func ) ( _type data, \
  58. volatile _type *io_addr ) { \
  59. *io_addr = data; \
  60. }
  61. X86_WRITEX ( writeb, uint8_t );
  62. X86_WRITEX ( writew, uint16_t );
  63. X86_WRITEX ( writel, uint32_t );
  64. #ifdef __x86_64__
  65. X86_WRITEX ( writeq, uint64_t );
  66. #endif
  67. /*
  68. * PIO reads and writes up to 32 bits
  69. *
  70. */
  71. #define X86_INX( _insn_suffix, _type, _reg_prefix ) \
  72. static inline __always_inline _type \
  73. IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) { \
  74. _type data; \
  75. __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0" \
  76. : "=a" ( data ) : "Nd" ( io_addr ) ); \
  77. return data; \
  78. } \
  79. static inline __always_inline void \
  80. IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr, \
  81. _type *data, \
  82. unsigned int count ) { \
  83. unsigned int discard_D; \
  84. __asm__ __volatile__ ( "rep ins" #_insn_suffix \
  85. : "=D" ( discard_D ) \
  86. : "d" ( io_addr ), "c" ( count ), \
  87. "0" ( data ) ); \
  88. }
  89. X86_INX ( b, uint8_t, "b" );
  90. X86_INX ( w, uint16_t, "w" );
  91. X86_INX ( l, uint32_t, "k" );
  92. #define X86_OUTX( _insn_suffix, _type, _reg_prefix ) \
  93. static inline __always_inline void \
  94. IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data, \
  95. volatile _type *io_addr ) { \
  96. __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1" \
  97. : : "a" ( data ), "Nd" ( io_addr ) ); \
  98. } \
  99. static inline __always_inline void \
  100. IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr, \
  101. const _type *data, \
  102. unsigned int count ) { \
  103. unsigned int discard_S; \
  104. __asm__ __volatile__ ( "rep outs" #_insn_suffix \
  105. : "=S" ( discard_S ) \
  106. : "d" ( io_addr ), "c" ( count ), \
  107. "0" ( data ) ); \
  108. }
  109. X86_OUTX ( b, uint8_t, "b" );
  110. X86_OUTX ( w, uint16_t, "w" );
  111. X86_OUTX ( l, uint32_t, "k" );
  112. /*
  113. * Slow down I/O
  114. *
  115. */
  116. static inline __always_inline void
  117. IOAPI_INLINE ( x86, iodelay ) ( void ) {
  118. __asm__ __volatile__ ( "outb %al, $0x80" );
  119. }
  120. /*
  121. * Memory barrier
  122. *
  123. */
  124. static inline __always_inline void
  125. IOAPI_INLINE ( x86, mb ) ( void ) {
  126. __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
  127. }
  128. #endif /* _IPXE_X86_IO_H */