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