earlypci.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. earlypci.c
  5. Abstract:
  6. This module implements early access to PCI Configuration Space for BIOSes
  7. that need access to it before the official PCI driver is up.
  8. Author:
  9. Evan Green 16-Dec-2012
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/driver.h>
  17. #include <minoca/kernel/ioport.h>
  18. #include "acpiobj.h"
  19. #include "amlos.h"
  20. #include "earlypci.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // Define the standard I/O ports to use to access PCI configuration space.
  26. //
  27. #define PCI_ROOT_CONFIG_ADDRESS 0xCF8
  28. #define PCI_ROOT_CONFIG_DATA 0xCFC
  29. //
  30. // --------------------------------------------------------------------- Macros
  31. //
  32. //
  33. // This macro creates the address value used to read from or write to PCI
  34. // configuration space. All parameters should be UCHARs.
  35. //
  36. #define PCI_CONFIG_ADDRESS(_Bus, _Device, _Function, _Register) \
  37. (((ULONG)(_Bus) << 16) | ((ULONG)(_Device) << 11) | \
  38. ((ULONG)(_Function) << 8) | ((_Register) & 0xFF) | 0x80000000)
  39. //
  40. // ------------------------------------------------------ Data Type Definitions
  41. //
  42. //
  43. // ----------------------------------------------- Internal Function Prototypes
  44. //
  45. //
  46. // -------------------------------------------------------------------- Globals
  47. //
  48. //
  49. // ------------------------------------------------------------------ Functions
  50. //
  51. ULONGLONG
  52. AcpipEarlyReadPciConfigurationSpace (
  53. UCHAR Bus,
  54. UCHAR Device,
  55. UCHAR Function,
  56. ULONG Register,
  57. ULONG AccessSize
  58. )
  59. /*++
  60. Routine Description:
  61. This routine reads from PCI Configuration Space on the root PCI bus.
  62. Arguments:
  63. Bus - Supplies the bus number to read from.
  64. Device - Supplies the device number to read from. Valid values are 0 to 31.
  65. Function - Supplies the PCI function to read from. Valid values are 0 to 7.
  66. Register - Supplies the configuration register to read from.
  67. AccessSize - Supplies the size of the access to make. Valid values are 1,
  68. 2, 4, and 8.
  69. Return Value:
  70. Returns the value read from the bus, or 0xFFFFFFFF on error.
  71. --*/
  72. {
  73. ULONG Address;
  74. ULONGLONG Value;
  75. //
  76. // Create the configuration address and write it into the address port.
  77. //
  78. Address = PCI_CONFIG_ADDRESS(Bus, Device, Function, Register);
  79. HlIoPortOutLong(PCI_ROOT_CONFIG_ADDRESS, Address);
  80. //
  81. // Read the data at that address.
  82. //
  83. switch (AccessSize) {
  84. case sizeof(UCHAR):
  85. Value = HlIoPortInByte(PCI_ROOT_CONFIG_DATA);
  86. break;
  87. case sizeof(USHORT):
  88. Value = HlIoPortInShort(PCI_ROOT_CONFIG_DATA);
  89. break;
  90. case sizeof(ULONG):
  91. Value = HlIoPortInLong(PCI_ROOT_CONFIG_DATA);
  92. break;
  93. case sizeof(ULONGLONG):
  94. Value = HlIoPortInLong(PCI_ROOT_CONFIG_DATA);
  95. HlIoPortOutLong(PCI_ROOT_CONFIG_ADDRESS, Address + 4);
  96. Value |= ((ULONGLONG)HlIoPortInLong(PCI_ROOT_CONFIG_DATA)) << 32;
  97. break;
  98. default:
  99. ASSERT(FALSE);
  100. Value = -1;
  101. break;
  102. }
  103. return Value;
  104. }
  105. VOID
  106. AcpipEarlyWritePciConfigurationSpace (
  107. UCHAR Bus,
  108. UCHAR Device,
  109. UCHAR Function,
  110. ULONG Register,
  111. ULONG AccessSize,
  112. ULONGLONG Value
  113. )
  114. /*++
  115. Routine Description:
  116. This routine writes to PCI Configuration Space on the PCI root bus.
  117. Arguments:
  118. Bus - Supplies the bus number to write to.
  119. Device - Supplies the device number to write to. Valid values are 0 to 31.
  120. Function - Supplies the PCI function to write to. Valid values are 0 to 7.
  121. Register - Supplies the configuration register to write to.
  122. AccessSize - Supplies the size of the access to make. Valid values are 1,
  123. 2, 4, and 8.
  124. Value - Supplies the value to write to the register.
  125. Return Value:
  126. None.
  127. --*/
  128. {
  129. ULONG Address;
  130. //
  131. // Create the configuration address and write it into the address port.
  132. //
  133. Address = PCI_CONFIG_ADDRESS(Bus, Device, Function, Register);
  134. HlIoPortOutLong(PCI_ROOT_CONFIG_ADDRESS, Address);
  135. //
  136. // Write the data at that address.
  137. //
  138. switch (AccessSize) {
  139. case sizeof(UCHAR):
  140. HlIoPortOutByte(PCI_ROOT_CONFIG_DATA, (UCHAR)Value);
  141. break;
  142. case sizeof(USHORT):
  143. HlIoPortOutShort(PCI_ROOT_CONFIG_DATA, (USHORT)Value);
  144. break;
  145. case sizeof(ULONG):
  146. HlIoPortOutLong(PCI_ROOT_CONFIG_DATA, (ULONG)Value);
  147. break;
  148. case sizeof(ULONGLONG):
  149. HlIoPortOutLong(PCI_ROOT_CONFIG_DATA, (ULONG)Value);
  150. HlIoPortOutLong(PCI_ROOT_CONFIG_ADDRESS, Address + 4);
  151. HlIoPortOutLong(PCI_ROOT_CONFIG_DATA, (ULONG)(Value >> 32));
  152. break;
  153. default:
  154. ASSERT(FALSE);
  155. break;
  156. }
  157. return;
  158. }
  159. //
  160. // --------------------------------------------------------- Internal Functions
  161. //