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