LegacyInterrupt.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /** @file
  2. Legacy Interrupt Support
  3. Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "LegacyInterrupt.h"
  7. //
  8. // Handle for the Legacy Interrupt Protocol instance produced by this driver
  9. //
  10. STATIC EFI_HANDLE mLegacyInterruptHandle = NULL;
  11. //
  12. // Legacy Interrupt Device number (0x01 on piix4, 0x1f on q35/mch)
  13. //
  14. STATIC UINT8 mLegacyInterruptDevice;
  15. //
  16. // The Legacy Interrupt Protocol instance produced by this driver
  17. //
  18. STATIC EFI_LEGACY_INTERRUPT_PROTOCOL mLegacyInterrupt = {
  19. GetNumberPirqs,
  20. GetLocation,
  21. ReadPirq,
  22. WritePirq
  23. };
  24. STATIC UINT8 PirqReg[MAX_PIRQ_NUMBER] = { PIRQA, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH };
  25. /**
  26. Return the number of PIRQs supported by this chipset.
  27. @param[in] This Pointer to LegacyInterrupt Protocol
  28. @param[out] NumberPirqs The pointer to return the max IRQ number supported
  29. @retval EFI_SUCCESS Max PIRQs successfully returned
  30. **/
  31. EFI_STATUS
  32. EFIAPI
  33. GetNumberPirqs (
  34. IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
  35. OUT UINT8 *NumberPirqs
  36. )
  37. {
  38. *NumberPirqs = MAX_PIRQ_NUMBER;
  39. return EFI_SUCCESS;
  40. }
  41. /**
  42. Return PCI location of this device.
  43. $PIR table requires this info.
  44. @param[in] This - Protocol instance pointer.
  45. @param[out] Bus - PCI Bus
  46. @param[out] Device - PCI Device
  47. @param[out] Function - PCI Function
  48. @retval EFI_SUCCESS Bus/Device/Function returned
  49. **/
  50. EFI_STATUS
  51. EFIAPI
  52. GetLocation (
  53. IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
  54. OUT UINT8 *Bus,
  55. OUT UINT8 *Device,
  56. OUT UINT8 *Function
  57. )
  58. {
  59. *Bus = LEGACY_INT_BUS;
  60. *Device = mLegacyInterruptDevice;
  61. *Function = LEGACY_INT_FUNC;
  62. return EFI_SUCCESS;
  63. }
  64. /**
  65. Builds the PCI configuration address for the register specified by PirqNumber
  66. @param[in] PirqNumber - The PIRQ number to build the PCI configuration address for
  67. @return The PCI Configuration address for the PIRQ
  68. **/
  69. UINTN
  70. GetAddress (
  71. UINT8 PirqNumber
  72. )
  73. {
  74. return PCI_LIB_ADDRESS (
  75. LEGACY_INT_BUS,
  76. mLegacyInterruptDevice,
  77. LEGACY_INT_FUNC,
  78. PirqReg[PirqNumber]
  79. );
  80. }
  81. /**
  82. Read the given PIRQ register
  83. @param[in] This Protocol instance pointer
  84. @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
  85. @param[out] PirqData Value read
  86. @retval EFI_SUCCESS Decoding change affected.
  87. @retval EFI_INVALID_PARAMETER Invalid PIRQ number
  88. **/
  89. EFI_STATUS
  90. EFIAPI
  91. ReadPirq (
  92. IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
  93. IN UINT8 PirqNumber,
  94. OUT UINT8 *PirqData
  95. )
  96. {
  97. if (PirqNumber >= MAX_PIRQ_NUMBER) {
  98. return EFI_INVALID_PARAMETER;
  99. }
  100. *PirqData = PciRead8 (GetAddress (PirqNumber));
  101. *PirqData = (UINT8)(*PirqData & 0x7f);
  102. return EFI_SUCCESS;
  103. }
  104. /**
  105. Write the given PIRQ register
  106. @param[in] This Protocol instance pointer
  107. @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
  108. @param[out] PirqData Value to write
  109. @retval EFI_SUCCESS Decoding change affected.
  110. @retval EFI_INVALID_PARAMETER Invalid PIRQ number
  111. **/
  112. EFI_STATUS
  113. EFIAPI
  114. WritePirq (
  115. IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
  116. IN UINT8 PirqNumber,
  117. IN UINT8 PirqData
  118. )
  119. {
  120. if (PirqNumber >= MAX_PIRQ_NUMBER) {
  121. return EFI_INVALID_PARAMETER;
  122. }
  123. PciWrite8 (GetAddress (PirqNumber), PirqData);
  124. return EFI_SUCCESS;
  125. }
  126. /**
  127. Initialize Legacy Interrupt support
  128. @retval EFI_SUCCESS Successfully initialized
  129. **/
  130. EFI_STATUS
  131. LegacyInterruptInstall (
  132. VOID
  133. )
  134. {
  135. UINT16 HostBridgeDevId;
  136. EFI_STATUS Status;
  137. //
  138. // Make sure the Legacy Interrupt Protocol is not already installed in the system
  139. //
  140. ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiLegacyInterruptProtocolGuid);
  141. //
  142. // Query Host Bridge DID to determine platform type, then set device number
  143. //
  144. HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
  145. switch (HostBridgeDevId) {
  146. case INTEL_82441_DEVICE_ID:
  147. mLegacyInterruptDevice = LEGACY_INT_DEV_PIIX4;
  148. break;
  149. case INTEL_Q35_MCH_DEVICE_ID:
  150. mLegacyInterruptDevice = LEGACY_INT_DEV_Q35;
  151. break;
  152. default:
  153. DEBUG ((
  154. DEBUG_ERROR,
  155. "%a: Unknown Host Bridge Device ID: 0x%04x\n",
  156. __FUNCTION__,
  157. HostBridgeDevId
  158. ));
  159. ASSERT (FALSE);
  160. return EFI_UNSUPPORTED;
  161. }
  162. //
  163. // Make a new handle and install the protocol
  164. //
  165. Status = gBS->InstallMultipleProtocolInterfaces (
  166. &mLegacyInterruptHandle,
  167. &gEfiLegacyInterruptProtocolGuid,
  168. &mLegacyInterrupt,
  169. NULL
  170. );
  171. ASSERT_EFI_ERROR (Status);
  172. return Status;
  173. }