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.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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: %lx\n", io_addr, efirc );
  81. return -1ULL;
  82. }
  83. return data;
  84. }
  85. /**
  86. * Write to device
  87. *
  88. * @v data Value to write
  89. * @v io_addr I/O address
  90. * @v size Size of value
  91. */
  92. void efi_iowrite ( unsigned long long data, volatile void *io_addr,
  93. size_t size ) {
  94. EFI_CPU_IO_PROTOCOL_IO_MEM write;
  95. EFI_STATUS efirc;
  96. write = ( IS_PORT_ADDRESS ( io_addr ) ?
  97. cpu_io->Io.Write : cpu_io->Mem.Write );
  98. if ( ( efirc = write ( cpu_io, efi_width ( size ),
  99. ( intptr_t ) io_addr, 1,
  100. ( void * ) &data ) ) != 0 ) {
  101. DBG ( "EFI I/O write at %p failed: %lx\n", io_addr, efirc );
  102. }
  103. }
  104. /**
  105. * String read from device
  106. *
  107. * @v io_addr I/O address
  108. * @v data Data buffer
  109. * @v size Size of values
  110. * @v count Number of values to read
  111. */
  112. void efi_ioreads ( volatile void *io_addr, void *data,
  113. size_t size, unsigned int count ) {
  114. EFI_CPU_IO_PROTOCOL_IO_MEM read;
  115. EFI_STATUS efirc;
  116. read = ( IS_PORT_ADDRESS ( io_addr ) ?
  117. cpu_io->Io.Read : cpu_io->Mem.Read );
  118. if ( ( efirc = read ( cpu_io, efi_width ( size ),
  119. ( intptr_t ) io_addr, count,
  120. ( void * ) data ) ) != 0 ) {
  121. DBG ( "EFI I/O string read at %p failed: %lx\n",
  122. io_addr, efirc );
  123. }
  124. }
  125. /**
  126. * String write to device
  127. *
  128. * @v io_addr I/O address
  129. * @v data Data buffer
  130. * @v size Size of values
  131. * @v count Number of values to write
  132. */
  133. void efi_iowrites ( volatile void *io_addr, const void *data,
  134. size_t size, unsigned int count ) {
  135. EFI_CPU_IO_PROTOCOL_IO_MEM write;
  136. EFI_STATUS efirc;
  137. write = ( IS_PORT_ADDRESS ( io_addr ) ?
  138. cpu_io->Io.Write : cpu_io->Mem.Write );
  139. if ( ( efirc = write ( cpu_io, efi_width ( size ),
  140. ( intptr_t ) io_addr, count,
  141. ( void * ) data ) ) != 0 ) {
  142. DBG ( "EFI I/O write at %p failed: %lx\n",
  143. io_addr, efirc );
  144. }
  145. }
  146. /**
  147. * Wait for I/O-mapped operation to complete
  148. *
  149. */
  150. static void efi_iodelay ( void ) {
  151. /* Write to non-existent port. Probably x86-only. */
  152. outb ( 0, 0x80 );
  153. }
  154. PROVIDE_IOAPI_INLINE ( efi, phys_to_bus );
  155. PROVIDE_IOAPI_INLINE ( efi, bus_to_phys );
  156. PROVIDE_IOAPI_INLINE ( efi, ioremap );
  157. PROVIDE_IOAPI_INLINE ( efi, iounmap );
  158. PROVIDE_IOAPI_INLINE ( efi, io_to_bus );
  159. PROVIDE_IOAPI_INLINE ( efi, readb );
  160. PROVIDE_IOAPI_INLINE ( efi, readw );
  161. PROVIDE_IOAPI_INLINE ( efi, readl );
  162. PROVIDE_IOAPI_INLINE ( efi, readq );
  163. PROVIDE_IOAPI_INLINE ( efi, writeb );
  164. PROVIDE_IOAPI_INLINE ( efi, writew );
  165. PROVIDE_IOAPI_INLINE ( efi, writel );
  166. PROVIDE_IOAPI_INLINE ( efi, writeq );
  167. PROVIDE_IOAPI_INLINE ( efi, inb );
  168. PROVIDE_IOAPI_INLINE ( efi, inw );
  169. PROVIDE_IOAPI_INLINE ( efi, inl );
  170. PROVIDE_IOAPI_INLINE ( efi, outb );
  171. PROVIDE_IOAPI_INLINE ( efi, outw );
  172. PROVIDE_IOAPI_INLINE ( efi, outl );
  173. PROVIDE_IOAPI_INLINE ( efi, insb );
  174. PROVIDE_IOAPI_INLINE ( efi, insw );
  175. PROVIDE_IOAPI_INLINE ( efi, insl );
  176. PROVIDE_IOAPI_INLINE ( efi, outsb );
  177. PROVIDE_IOAPI_INLINE ( efi, outsw );
  178. PROVIDE_IOAPI_INLINE ( efi, outsl );
  179. PROVIDE_IOAPI ( efi, iodelay, efi_iodelay );
  180. PROVIDE_IOAPI_INLINE ( efi, mb );