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