rootbus.c 4.6 KB

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