]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/PciIncompatibleDeviceSupportLib/PciIncompatibleDeviceSupportLib.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / PciIncompatibleDeviceSupportLib / PciIncompatibleDeviceSupportLib.c
1 /** @file
2 The implementation of PCI incompatible device support libary.
3
4 Copyright (c) 2006 - 2007, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "IncompatiblePciDeviceList.h"
16
17 /**
18 Check whether two PCI devices matched
19
20 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
21 @param Header A pointer to EFI_PCI_DEVICE_INFO.
22
23 @retval returns EFI_SUCCESS if two PCI device matched.
24 **/
25 EFI_STATUS
26 DeviceCheck (
27 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
28 IN EFI_PCI_DEVICE_INFO *Header
29 )
30 {
31 //
32 // See if the Header matches the parameters passed in
33 //
34 if (Header->VendorID != DEVICE_ID_NOCARE) {
35 if (PciDeviceInfo->VendorID != Header->VendorID) {
36 return EFI_UNSUPPORTED;
37 }
38 }
39
40 if (Header->DeviceID != DEVICE_ID_NOCARE) {
41 if (PciDeviceInfo->DeviceID != Header->DeviceID) {
42 return EFI_UNSUPPORTED;
43 }
44 }
45
46 if (Header->RevisionID != DEVICE_ID_NOCARE) {
47 if (PciDeviceInfo->RevisionID != Header->RevisionID) {
48 return EFI_UNSUPPORTED;
49 }
50 }
51
52 if (Header->SubsystemVendorID != DEVICE_ID_NOCARE) {
53 if (PciDeviceInfo->SubsystemVendorID != Header->SubsystemVendorID) {
54 return EFI_UNSUPPORTED;
55 }
56 }
57
58 if (Header->SubsystemID != DEVICE_ID_NOCARE) {
59 if (PciDeviceInfo->SubsystemID != Header->SubsystemID) {
60 return EFI_UNSUPPORTED;
61 }
62 }
63
64 return EFI_SUCCESS;
65 }
66
67
68 /**
69 Check the incompatible device list for ACPI resource update and return
70 the configuration
71
72 This function searches the incompatible device list according to request
73 information. If the PCI device belongs to the devices list, corresponding
74 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
75
76 @param PciDeviceInfo A pointer to PCI device information.
77 @param Configuration Returned information.
78
79 @retval returns EFI_SUCCESS if check incompatible device ok.
80 Otherwise return EFI_UNSUPPORTED.
81 **/
82 RETURN_STATUS
83 EFIAPI
84 PciResourceUpdateCheck (
85 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
86 OUT VOID *Configuration
87 )
88 {
89 UINT64 Tag;
90 UINT64 *ListPtr;
91 UINT64 *TempListPtr;
92 EFI_PCI_DEVICE_INFO *Header;
93 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AcpiPtr;
94 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *OldAcpiPtr;
95 EFI_PCI_RESOUCE_DESCRIPTOR *Dsc;
96 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
97 UINTN Index;
98
99 ASSERT (PciDeviceInfo != NULL);
100
101 //
102 // Initialize the return value to NULL
103 //
104 * (VOID **) Configuration = NULL;
105
106 ListPtr = IncompatiblePciDeviceListForResource;
107 while (*ListPtr != LIST_END_TAG) {
108
109 Tag = *ListPtr;
110
111 switch (Tag) {
112 case DEVICE_INF_TAG:
113 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);
114 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);
115
116 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {
117 continue;
118 }
119
120 //
121 // Matched an item, so construct the ACPI descriptor for the resource.
122 //
123 //
124 // Count the resource items so that to allocate space
125 //
126 for (Index = 0, TempListPtr = ListPtr; *TempListPtr == DEVICE_RES_TAG; Index++) {
127 TempListPtr = TempListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));
128 }
129 //
130 // If there is at least one type of resource request,
131 // allocate a acpi resource node
132 //
133 if (Index == 0) {
134 return EFI_ABORTED;
135 }
136
137 AcpiPtr = AllocateZeroPool (
138 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Index + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
139 );
140
141 OldAcpiPtr = AcpiPtr;
142
143 //
144 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
145 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
146 //
147 for (; *ListPtr == DEVICE_RES_TAG;) {
148
149 Dsc = (EFI_PCI_RESOUCE_DESCRIPTOR *) (ListPtr + 1);
150
151 AcpiPtr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
152 AcpiPtr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
153 AcpiPtr->ResType = (UINT8) Dsc->ResType;
154 AcpiPtr->GenFlag = (UINT8) Dsc->GenFlag;
155 AcpiPtr->SpecificFlag = (UINT8) Dsc->SpecificFlag;
156 AcpiPtr->AddrSpaceGranularity = Dsc->AddrSpaceGranularity;;
157 AcpiPtr->AddrRangeMin = Dsc->AddrRangeMin;
158 AcpiPtr->AddrRangeMax = Dsc->AddrRangeMax;
159 AcpiPtr->AddrTranslationOffset = Dsc->AddrTranslationOffset;
160 AcpiPtr->AddrLen = Dsc->AddrLen;
161
162 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));
163 AcpiPtr++;
164 }
165 //
166 // put the checksum
167 //
168 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AcpiPtr);
169 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
170 PtrEnd->Checksum = 0;
171
172 *(VOID **) Configuration = OldAcpiPtr;
173
174 return EFI_SUCCESS;
175
176 case DEVICE_RES_TAG:
177 //
178 // Adjust the pointer to the next PCI resource descriptor item
179 //
180 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));
181 break;
182
183 default:
184 return EFI_UNSUPPORTED;
185 }
186 }
187
188 return EFI_UNSUPPORTED;
189
190 }
191
192 /**
193 Check the incompatible device list and return configuraton register mask values.
194
195 This function searches the incompatible device list according to request
196 information. If the PCI device belongs to the devices list, corresponding
197 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
198
199 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
200 @param AccessType Access Type, READ or WRITE.
201 @param Offset The address within the PCI configuration space.
202 @param Configuration Returned information.
203
204 @retval returns EFI_SUCCESS if check incompatible device ok.
205 Otherwise return EFI_UNSUPPORTED.
206 **/
207 RETURN_STATUS
208 EFIAPI
209 PciRegisterUpdateCheck (
210 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
211 IN UINT64 AccessType,
212 IN UINT64 Offset,
213 OUT VOID *Configuration
214 )
215 {
216 EFI_PCI_DEVICE_INFO *Header;
217 UINT64 Tag;
218 UINT64 *ListPtr;
219 EFI_PCI_REGISTER_VALUE_DATA *RegisterPtr;
220 EFI_PCI_REGISTER_VALUE_DATA *Dsc;
221
222 ASSERT (PciDeviceInfo != NULL);
223
224 ListPtr = IncompatiblePciDeviceListForRegister;
225
226 //
227 // Initialize the return value to NULL
228 //
229 * (VOID **) Configuration = NULL;
230
231 while (*ListPtr != LIST_END_TAG) {
232
233 Tag = *ListPtr;
234
235 switch (Tag) {
236 case DEVICE_INF_TAG:
237 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);
238 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);
239
240 //
241 // Check whether the PCI device matches the device in the incompatible devices list?
242 // If not, ship next
243 //
244 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {
245 continue;
246 }
247
248 //
249 // Matched an item, check whether access matches?
250 //
251 for (; *ListPtr == DEVICE_RES_TAG;) {
252 ListPtr ++;
253 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR *)ListPtr)->Offset == (Offset & 0xfc)) {
254 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR *)ListPtr)->AccessType == AccessType) {
255
256 Dsc = (EFI_PCI_REGISTER_VALUE_DATA *) (ListPtr + 2);
257 RegisterPtr = AllocateZeroPool (sizeof (EFI_PCI_REGISTER_VALUE_DATA));
258
259 RegisterPtr->AndValue = Dsc->AndValue;
260 RegisterPtr->OrValue = Dsc->OrValue;
261
262 *(VOID **) Configuration = RegisterPtr;
263
264 return EFI_SUCCESS;
265 }
266 }
267 ListPtr += sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR) / (sizeof (UINT64));
268 }
269 return EFI_UNSUPPORTED;
270
271 case DEVICE_RES_TAG:
272 //
273 // Adjust the pointer to the next item
274 //
275 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR)) / sizeof (UINT64));
276 break;
277
278 default:
279 return EFI_UNSUPPORTED;
280 }
281 }
282
283 return EFI_UNSUPPORTED;
284 }
285
286 /**
287 Check the incompatible device list for access width incompatibility and
288 return the configuration
289
290 This function searches the incompatible device list for access width
291 incompatibility according to request information. If the PCI device
292 belongs to the devices list, corresponding configuration informtion
293 will be returned, in the meantime return EFI_SUCCESS.
294
295 @param PciDeviceInfo A pointer to PCI device information.
296 @param AccessType Access type, READ or WRITE.
297 @param Offset The address within the PCI configuration space.
298 @param AccessWidth Access width needs to check incompatibility.
299 @param Configuration Returned information.
300
301 @retval returns EFI_SUCCESS if check incompatible device ok.
302 Otherwise return EFI_UNSUPPORTED.
303 **/
304 RETURN_STATUS
305 EFIAPI
306 PciRegisterAccessCheck (
307 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
308 IN UINT64 AccessType,
309 IN UINT64 Offset,
310 IN UINT64 AccessWidth,
311 OUT VOID *Configuration
312 )
313 {
314 EFI_PCI_DEVICE_INFO *Header;
315 UINT64 Tag;
316 UINT64 *ListPtr;
317 EFI_PCI_REGISTER_ACCESS_DATA *RegisterPtr;
318 EFI_PCI_REGISTER_ACCESS_DATA *Dsc;
319
320 ASSERT (PciDeviceInfo != NULL);
321
322 ListPtr = DeviceListForAccessWidth;
323
324 //
325 // Initialize the return value to NULL
326 //
327 * (VOID **) Configuration = NULL;
328
329 while (*ListPtr != LIST_END_TAG) {
330
331 Tag = *ListPtr;
332
333 switch (Tag) {
334 case DEVICE_INF_TAG:
335 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);
336 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);
337
338 //
339 // Check whether the PCI device matches the device in the incompatible devices list?
340 // If not, ship next
341 //
342 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {
343 continue;
344 }
345
346 //
347 // Matched an item, check whether access matches?
348 //
349 for (; *ListPtr == DEVICE_RES_TAG;) {
350 ListPtr ++;
351 if (((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR *) ListPtr)->AccessType == AccessType &&
352 ((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR *) ListPtr)->AccessWidth == AccessWidth ) {
353
354 Dsc = (EFI_PCI_REGISTER_ACCESS_DATA *) (ListPtr + 2);
355
356 if((Dsc->StartOffset <= Offset) && (Dsc->EndOffset > Offset)) {
357
358 RegisterPtr = AllocateZeroPool (sizeof (EFI_PCI_REGISTER_ACCESS_DATA));
359
360 RegisterPtr->StartOffset = Dsc->StartOffset;
361 RegisterPtr->EndOffset = Dsc->EndOffset;
362 RegisterPtr->Width = Dsc->Width;
363
364 *(VOID **) Configuration = RegisterPtr;
365
366 return EFI_SUCCESS;
367 }
368 }
369 ListPtr += sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR) / (sizeof (UINT64));
370 }
371 return EFI_UNSUPPORTED;
372
373 case DEVICE_RES_TAG:
374 //
375 // Adjust the pointer to the next item
376 //
377 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR)) / sizeof (UINT64));
378 break;
379
380 default:
381 return EFI_UNSUPPORTED;
382 }
383 }
384
385 return EFI_UNSUPPORTED;
386 }
387