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.

efi_io.c 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include <assert.h>
  19. #include <gpxe/io.h>
  20. #include <gpxe/efi/efi.h>
  21. #include <gpxe/efi/Protocol/CpuIo.h>
  22. #include <gpxe/efi/efi_io.h>
  23. /** @file
  24. *
  25. * gPXE I/O API for EFI
  26. *
  27. */
  28. /** CPU I/O protocol */
  29. static EFI_CPU_IO_PROTOCOL *cpu_io;
  30. EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io );
  31. /** Maximum address that can be used for port I/O */
  32. #define MAX_PORT_ADDRESS 0xffff
  33. /**
  34. * Determine whether or not address is a port I/O address
  35. *
  36. * @v io_addr I/O address
  37. * @v is_port I/O address is a port I/O address
  38. */
  39. #define IS_PORT_ADDRESS(io_addr) \
  40. ( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS )
  41. /**
  42. * Determine EFI CPU I/O width code
  43. *
  44. * @v size Size of value
  45. * @ret width EFI width code
  46. *
  47. * Someone at Intel clearly gets paid by the number of lines of code
  48. * they write. No-one should ever be able to make I/O this
  49. * convoluted. The EFI_CPU_IO_PROTOCOL_WIDTH enum is my favourite
  50. * idiocy.
  51. */
  52. static EFI_CPU_IO_PROTOCOL_WIDTH efi_width ( size_t size ) {
  53. switch ( size ) {
  54. case 1 : return EfiCpuIoWidthFifoUint8;
  55. case 2 : return EfiCpuIoWidthFifoUint16;
  56. case 4 : return EfiCpuIoWidthFifoUint32;
  57. case 8 : return EfiCpuIoWidthFifoUint64;
  58. default :
  59. assert ( 0 );
  60. /* I wonder what this will actually do... */
  61. return EfiCpuIoWidthMaximum;
  62. }
  63. }
  64. /**
  65. * Read from device
  66. *
  67. * @v io_addr I/O address
  68. * @v size Size of value
  69. * @ret data Value read
  70. */
  71. unsigned long long efi_ioread ( volatile void *io_addr, size_t size ) {
  72. EFI_CPU_IO_PROTOCOL_IO_MEM read;
  73. unsigned long long data = 0;
  74. EFI_STATUS efirc;
  75. read = ( IS_PORT_ADDRESS ( io_addr ) ?
  76. cpu_io->Io.Read : cpu_io->Mem.Read );
  77. if ( ( efirc = read ( cpu_io, efi_width ( size ),
  78. ( intptr_t ) io_addr, 1,
  79. ( void * ) &data ) ) != 0 ) {
  80. DBG ( "EFI I/O read at %p failed: %s\n",
  81. io_addr, efi_strerror ( efirc ) );
  82. return -1ULL;
  83. }
  84. return data;
  85. }
  86. /**
  87. * Write to device
  88. *
  89. * @v data Value to write
  90. * @v io_addr I/O address
  91. * @v size Size of value
  92. */
  93. void efi_iowrite ( unsigned long long data, volatile void *io_addr,
  94. size_t size ) {
  95. EFI_CPU_IO_PROTOCOL_IO_MEM write;
  96. EFI_STATUS efirc;
  97. write = ( IS_PORT_ADDRESS ( io_addr ) ?
  98. cpu_io->Io.Write : cpu_io->Mem.Write );
  99. if ( ( efirc = write ( cpu_io, efi_width ( size ),
  100. ( intptr_t ) io_addr, 1,
  101. ( void * ) &data ) ) != 0 ) {
  102. DBG ( "EFI I/O write at %p failed: %s\n",
  103. io_addr, efi_strerror ( efirc ) );
  104. }
  105. }
  106. /**
  107. * String read from device
  108. *
  109. * @v io_addr I/O address
  110. * @v data Data buffer
  111. * @v size Size of values
  112. * @v count Number of values to read
  113. */
  114. void efi_ioreads ( volatile void *io_addr, void *data,
  115. size_t size, unsigned int count ) {
  116. EFI_CPU_IO_PROTOCOL_IO_MEM read;
  117. EFI_STATUS efirc;
  118. read = ( IS_PORT_ADDRESS ( io_addr ) ?
  119. cpu_io->Io.Read : cpu_io->Mem.Read );
  120. if ( ( efirc = read ( cpu_io, efi_width ( size ),
  121. ( intptr_t ) io_addr, count,
  122. ( void * ) data ) ) != 0 ) {
  123. DBG ( "EFI I/O string read at %p failed: %s\n",
  124. io_addr, efi_strerror ( efirc ) );
  125. }
  126. }
  127. /**
  128. * String write to device
  129. *
  130. * @v io_addr I/O address
  131. * @v data Data buffer
  132. * @v size Size of values
  133. * @v count Number of values to write
  134. */
  135. void efi_iowrites ( volatile void *io_addr, const void *data,
  136. size_t size, unsigned int count ) {
  137. EFI_CPU_IO_PROTOCOL_IO_MEM write;
  138. EFI_STATUS efirc;
  139. write = ( IS_PORT_ADDRESS ( io_addr ) ?
  140. cpu_io->Io.Write : cpu_io->Mem.Write );
  141. if ( ( efirc = write ( cpu_io, efi_width ( size ),
  142. ( intptr_t ) io_addr, count,
  143. ( void * ) data ) ) != 0 ) {
  144. DBG ( "EFI I/O write at %p failed: %s\n",
  145. io_addr, efi_strerror ( efirc ) );
  146. }
  147. }
  148. /**
  149. * Wait for I/O-mapped operation to complete
  150. *
  151. */
  152. static void efi_iodelay ( void ) {
  153. /* Write to non-existent port. Probably x86-only. */
  154. outb ( 0, 0x80 );
  155. }
  156. PROVIDE_IOAPI_INLINE ( efi, phys_to_bus );
  157. PROVIDE_IOAPI_INLINE ( efi, bus_to_phys );
  158. PROVIDE_IOAPI_INLINE ( efi, ioremap );
  159. PROVIDE_IOAPI_INLINE ( efi, iounmap );
  160. PROVIDE_IOAPI_INLINE ( efi, io_to_bus );
  161. PROVIDE_IOAPI_INLINE ( efi, readb );
  162. PROVIDE_IOAPI_INLINE ( efi, readw );
  163. PROVIDE_IOAPI_INLINE ( efi, readl );
  164. PROVIDE_IOAPI_INLINE ( efi, readq );
  165. PROVIDE_IOAPI_INLINE ( efi, writeb );
  166. PROVIDE_IOAPI_INLINE ( efi, writew );
  167. PROVIDE_IOAPI_INLINE ( efi, writel );
  168. PROVIDE_IOAPI_INLINE ( efi, writeq );
  169. PROVIDE_IOAPI_INLINE ( efi, inb );
  170. PROVIDE_IOAPI_INLINE ( efi, inw );
  171. PROVIDE_IOAPI_INLINE ( efi, inl );
  172. PROVIDE_IOAPI_INLINE ( efi, outb );
  173. PROVIDE_IOAPI_INLINE ( efi, outw );
  174. PROVIDE_IOAPI_INLINE ( efi, outl );
  175. PROVIDE_IOAPI_INLINE ( efi, insb );
  176. PROVIDE_IOAPI_INLINE ( efi, insw );
  177. PROVIDE_IOAPI_INLINE ( efi, insl );
  178. PROVIDE_IOAPI_INLINE ( efi, outsb );
  179. PROVIDE_IOAPI_INLINE ( efi, outsw );
  180. PROVIDE_IOAPI_INLINE ( efi, outsl );
  181. PROVIDE_IOAPI ( efi, iodelay, efi_iodelay );
  182. PROVIDE_IOAPI_INLINE ( efi, mb );