]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c
OvmfPkg: CsmSupportLib: Set/use platform specific legacy interrupt device
[mirror_edk2.git] / OvmfPkg / Csm / CsmSupportLib / LegacyInterrupt.c
CommitLineData
8016da21 1/** @file\r
2 Legacy Interrupt Support\r
3\r
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials are\r
7 licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "LegacyInterrupt.h"\r
17\r
18//\r
19// Handle for the Legacy Interrupt Protocol instance produced by this driver\r
20//\r
21STATIC EFI_HANDLE mLegacyInterruptHandle = NULL;\r
22\r
72a11001
GS
23//\r
24// Legacy Interrupt Device number (0x01 on piix4, 0x1f on q35/mch)\r
25//\r
26STATIC UINT8 mLegacyInterruptDevice;\r
27\r
8016da21 28//\r
29// The Legacy Interrupt Protocol instance produced by this driver\r
30//\r
31STATIC EFI_LEGACY_INTERRUPT_PROTOCOL mLegacyInterrupt = {\r
32 GetNumberPirqs,\r
33 GetLocation,\r
34 ReadPirq,\r
35 WritePirq\r
36};\r
37\r
38STATIC UINT8 PirqReg[MAX_PIRQ_NUMBER] = { PIRQA, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH };\r
39\r
40\r
41/**\r
42 Return the number of PIRQs supported by this chipset.\r
43\r
44 @param[in] This Pointer to LegacyInterrupt Protocol\r
45 @param[out] NumberPirqs The pointer to return the max IRQ number supported\r
46\r
47 @retval EFI_SUCCESS Max PIRQs successfully returned\r
48\r
49**/\r
50EFI_STATUS\r
51EFIAPI\r
52GetNumberPirqs (\r
53 IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,\r
54 OUT UINT8 *NumberPirqs\r
55 )\r
56{\r
57 *NumberPirqs = MAX_PIRQ_NUMBER;\r
58\r
59 return EFI_SUCCESS;\r
60}\r
61\r
62\r
63/**\r
64 Return PCI location of this device.\r
65 $PIR table requires this info.\r
66\r
67 @param[in] This - Protocol instance pointer.\r
68 @param[out] Bus - PCI Bus\r
69 @param[out] Device - PCI Device\r
70 @param[out] Function - PCI Function\r
71\r
72 @retval EFI_SUCCESS Bus/Device/Function returned\r
73\r
74**/\r
75EFI_STATUS\r
76EFIAPI\r
77GetLocation (\r
78 IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,\r
79 OUT UINT8 *Bus,\r
80 OUT UINT8 *Device,\r
81 OUT UINT8 *Function\r
82 )\r
83{\r
84 *Bus = LEGACY_INT_BUS;\r
72a11001 85 *Device = mLegacyInterruptDevice;\r
8016da21 86 *Function = LEGACY_INT_FUNC;\r
87\r
88 return EFI_SUCCESS;\r
89}\r
90\r
91\r
92/**\r
93 Builds the PCI configuration address for the register specified by PirqNumber\r
94\r
95 @param[in] PirqNumber - The PIRQ number to build the PCI configuration address for\r
96\r
97 @return The PCI Configuration address for the PIRQ\r
98**/\r
99UINTN\r
100GetAddress (\r
101 UINT8 PirqNumber\r
102 )\r
103{\r
104 return PCI_LIB_ADDRESS(\r
105 LEGACY_INT_BUS,\r
72a11001 106 mLegacyInterruptDevice,\r
8016da21 107 LEGACY_INT_FUNC,\r
108 PirqReg[PirqNumber]\r
109 );\r
110}\r
111\r
112/**\r
113 Read the given PIRQ register\r
114\r
115 @param[in] This Protocol instance pointer\r
116 @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc\r
117 @param[out] PirqData Value read\r
118\r
119 @retval EFI_SUCCESS Decoding change affected.\r
120 @retval EFI_INVALID_PARAMETER Invalid PIRQ number\r
121\r
122**/\r
123EFI_STATUS\r
124EFIAPI\r
125ReadPirq (\r
126 IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,\r
127 IN UINT8 PirqNumber,\r
128 OUT UINT8 *PirqData\r
129 )\r
130{\r
131 if (PirqNumber >= MAX_PIRQ_NUMBER) {\r
132 return EFI_INVALID_PARAMETER;\r
133 }\r
134\r
135 *PirqData = PciRead8 (GetAddress (PirqNumber));\r
136 *PirqData = (UINT8) (*PirqData & 0x7f);\r
137\r
138 return EFI_SUCCESS;\r
139}\r
140\r
141\r
142/**\r
143 Write the given PIRQ register\r
144\r
145 @param[in] This Protocol instance pointer\r
146 @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc\r
147 @param[out] PirqData Value to write\r
148\r
149 @retval EFI_SUCCESS Decoding change affected.\r
150 @retval EFI_INVALID_PARAMETER Invalid PIRQ number\r
151\r
152**/\r
153EFI_STATUS\r
154EFIAPI\r
155WritePirq (\r
156 IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,\r
157 IN UINT8 PirqNumber,\r
158 IN UINT8 PirqData\r
159 )\r
160{\r
161 if (PirqNumber >= MAX_PIRQ_NUMBER) {\r
162 return EFI_INVALID_PARAMETER;\r
163 }\r
164\r
165 PciWrite8 (GetAddress (PirqNumber), PirqData);\r
166 return EFI_SUCCESS;\r
167}\r
168\r
169\r
170/**\r
171 Initialize Legacy Interrupt support\r
172\r
173 @retval EFI_SUCCESS Successfully initialized\r
174\r
175**/\r
176EFI_STATUS\r
177LegacyInterruptInstall (\r
178 VOID\r
179 )\r
180{\r
72a11001 181 UINT16 HostBridgeDevId;\r
8016da21 182 EFI_STATUS Status;\r
183\r
184 //\r
185 // Make sure the Legacy Interrupt Protocol is not already installed in the system\r
186 //\r
187 ASSERT_PROTOCOL_ALREADY_INSTALLED(NULL, &gEfiLegacyInterruptProtocolGuid);\r
188\r
72a11001
GS
189 //\r
190 // Query Host Bridge DID to determine platform type, then set device number\r
191 //\r
192 HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
193 switch (HostBridgeDevId) {\r
194 case INTEL_82441_DEVICE_ID:\r
195 mLegacyInterruptDevice = LEGACY_INT_DEV_PIIX4;\r
196 break;\r
197 case INTEL_Q35_MCH_DEVICE_ID:\r
198 mLegacyInterruptDevice = LEGACY_INT_DEV_Q35;\r
199 break;\r
200 default:\r
201 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
202 __FUNCTION__, HostBridgeDevId));\r
203 ASSERT (FALSE);\r
204 return EFI_UNSUPPORTED;\r
205 }\r
206\r
8016da21 207 //\r
208 // Make a new handle and install the protocol\r
209 //\r
210 Status = gBS->InstallMultipleProtocolInterfaces (\r
211 &mLegacyInterruptHandle,\r
212 &gEfiLegacyInterruptProtocolGuid,\r
213 &mLegacyInterrupt,\r
214 NULL\r
215 );\r
216 ASSERT_EFI_ERROR(Status);\r
217\r
218 return Status;\r
219}\r
220\r