2 The template of PCI incompatible device support libary.
4 Copyright (c) 2006 - 2009, 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
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.
15 #include "IncompatiblePciDeviceList.h"
18 // the incompatible PCI devices list template for ACPI resource
20 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 gIncompatiblePciDeviceListForResource
[] = {
23 // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),
25 // ResType, GFlag , SFlag, Granularity, RangeMin,
26 // RangeMax, Offset, AddrLen
33 //PCI_DEVICE_ID(0xXXXX, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),
48 //PCI_DEVICE_ID(0xXXXX, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),
60 // The end of the list
66 // the incompatible PCI devices list template for the values of configuration registers
68 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 gIncompatiblePciDeviceListForRegister
[] = {
71 // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),
73 // PCI_ACCESS_TYPE, PCI_CONFIG_ADDRESS,
74 // AND_VALUE, OR_VALUE
80 //PCI_DEVICE_ID(0xXXXX, 0xXXXX, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),
83 //PCI_CAPBILITY_POINTER_OFFSET,
91 //PCI_DEVICE_ID(0xXXXX, 0xXXXX, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),
94 //PCI_CAPBILITY_POINTER_OFFSET,
99 // The end of the list
105 // the incompatible PCI devices list template for the access width of configuration registers
107 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 gDeviceListForAccessWidth
[] = {
110 // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),
112 // PCI_ACCESS_TYPE, PCI_ACCESS_WIDTH,
113 // START_ADDRESS, END_ADDRESS,
114 // ACTUAL_PCI_ACCESS_WIDTH,
121 //PCI_DEVICE_ID(0xXXXX, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),
131 // The end of the list
136 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_REGISTER_ACCESS_DATA mPciRegisterAccessData
= {0, 0, 0};
137 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_REGISTER_VALUE_DATA mPciRegisterValueData
= {0, 0};
141 Check whether two PCI devices matched.
143 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
144 @param Header A pointer to EFI_PCI_DEVICE_INFO.
146 @retval EFI_SUCCESS Two PCI devices matched.
147 @retval EFI_UNSUPPORTED Two PCI devices don't match.
152 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
153 IN EFI_PCI_DEVICE_INFO
*Header
157 // See if the Header matches the parameters passed in
159 if (Header
->VendorID
!= DEVICE_ID_NOCARE
) {
160 if (PciDeviceInfo
->VendorID
!= Header
->VendorID
) {
161 return EFI_UNSUPPORTED
;
165 if (Header
->DeviceID
!= DEVICE_ID_NOCARE
) {
166 if (PciDeviceInfo
->DeviceID
!= Header
->DeviceID
) {
167 return EFI_UNSUPPORTED
;
171 if (Header
->RevisionID
!= DEVICE_ID_NOCARE
) {
172 if (PciDeviceInfo
->RevisionID
!= Header
->RevisionID
) {
173 return EFI_UNSUPPORTED
;
177 if (Header
->SubsystemVendorID
!= DEVICE_ID_NOCARE
) {
178 if (PciDeviceInfo
->SubsystemVendorID
!= Header
->SubsystemVendorID
) {
179 return EFI_UNSUPPORTED
;
183 if (Header
->SubsystemID
!= DEVICE_ID_NOCARE
) {
184 if (PciDeviceInfo
->SubsystemID
!= Header
->SubsystemID
) {
185 return EFI_UNSUPPORTED
;
194 Check the incompatible device list for ACPI resource update and return
197 This function searches the incompatible device list according to request
198 information. If the PCI device belongs to the devices list, corresponding
199 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
201 @param PciDeviceInfo A pointer to PCI device information.
202 @param Configuration Returned information.
204 @retval EFI_SUCCESS If check incompatible device successfully.
205 @retval EFI_ABORTED No any resource type.
206 @retval EFI_OUT_OF_RESOURCES No memory available.
207 @retval EFI_UNSUPPORTED Invalid Tag encounted.
212 PciResourceUpdateCheck (
213 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
214 OUT VOID
*Configuration
220 EFI_PCI_DEVICE_INFO
*Header
;
221 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AcpiPtr
;
222 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*OldAcpiPtr
;
223 EFI_PCI_RESOUCE_DESCRIPTOR
*Dsc
;
224 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
227 ASSERT (PciDeviceInfo
!= NULL
);
230 // Initialize the return value to NULL
232 * (VOID
**) Configuration
= NULL
;
234 ListPtr
= gIncompatiblePciDeviceListForResource
;
235 while (*ListPtr
!= LIST_END_TAG
) {
241 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
242 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
244 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
249 // Matched an item, so construct the ACPI descriptor for the resource.
252 // Count the resource items so that to allocate space
254 for (Index
= 0, TempListPtr
= ListPtr
; *TempListPtr
== DEVICE_RES_TAG
; Index
++) {
255 TempListPtr
= TempListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
258 // If there is at least one type of resource request,
259 // allocate a acpi resource node
265 AcpiPtr
= AllocateZeroPool (
266 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
268 if (AcpiPtr
== NULL
) {
269 return EFI_OUT_OF_RESOURCES
;
272 OldAcpiPtr
= AcpiPtr
;
275 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
276 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
278 for (; *ListPtr
== DEVICE_RES_TAG
;) {
280 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*) (ListPtr
+ 1);
282 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
283 AcpiPtr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
284 AcpiPtr
->ResType
= (UINT8
) Dsc
->ResType
;
285 AcpiPtr
->GenFlag
= (UINT8
) Dsc
->GenFlag
;
286 AcpiPtr
->SpecificFlag
= (UINT8
) Dsc
->SpecificFlag
;
287 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;;
288 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
289 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
290 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
291 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
293 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
299 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
300 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
301 PtrEnd
->Checksum
= 0;
303 *(VOID
**) Configuration
= OldAcpiPtr
;
309 // Adjust the pointer to the next PCI resource descriptor item
311 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
315 return EFI_UNSUPPORTED
;
319 return EFI_UNSUPPORTED
;
324 Check the incompatible device list and return configuraton register mask values.
326 This function searches the incompatible device list according to request
327 information. If the PCI device belongs to the devices list, corresponding
328 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
330 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
331 @param AccessType Access Type, READ or WRITE.
332 @param Offset The address within the PCI configuration space.
333 @param Configuration Returned information.
335 @retval EFI_SUCCESS If check incompatible device successfully.
336 @retval EFI_UNSUPPORTED Failed to check incompatibility device.
341 PciRegisterUpdateCheck (
342 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
343 IN UINT64 AccessType
,
345 OUT VOID
*Configuration
348 EFI_PCI_DEVICE_INFO
*Header
;
351 EFI_PCI_REGISTER_VALUE_DATA
*RegisterPtr
;
352 EFI_PCI_REGISTER_VALUE_DATA
*Dsc
;
354 ASSERT (PciDeviceInfo
!= NULL
);
356 ListPtr
= gIncompatiblePciDeviceListForRegister
;
359 // Initialize the return value to NULL
361 * (VOID
**) Configuration
= NULL
;
363 while (*ListPtr
!= LIST_END_TAG
) {
369 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
370 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
373 // Check whether the PCI device matches the device in the incompatible devices list?
376 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
381 // Matched an item, check whether access matches?
383 for (; *ListPtr
== DEVICE_RES_TAG
;) {
385 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->Offset
== (Offset
& 0xfc)) {
386 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->AccessType
== AccessType
) {
388 Dsc
= (EFI_PCI_REGISTER_VALUE_DATA
*) (ListPtr
+ 2);
390 RegisterPtr
= &mPciRegisterValueData
;
392 RegisterPtr
->AndValue
= Dsc
->AndValue
;
393 RegisterPtr
->OrValue
= Dsc
->OrValue
;
395 *(VOID
**) Configuration
= RegisterPtr
;
400 ListPtr
+= sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR
) / (sizeof (UINT64
));
402 return EFI_UNSUPPORTED
;
406 // Adjust the pointer to the next item
408 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR
)) / sizeof (UINT64
));
412 return EFI_UNSUPPORTED
;
416 return EFI_UNSUPPORTED
;
420 Check the incompatible device list for access width incompatibility and
421 return the configuration.
423 This function searches the incompatible device list for access width
424 incompatibility according to request information. If the PCI device
425 belongs to the devices list, corresponding configuration informtion
426 will be returned, in the meantime return EFI_SUCCESS.
428 @param PciDeviceInfo A pointer to PCI device information.
429 @param AccessType Access type, READ or WRITE.
430 @param Offset The address within the PCI configuration space.
431 @param AccessWidth Access width needs to check incompatibility.
432 @param Configuration Returned information.
434 @retval EFI_SUCCESS If check incompatible device successfully.
435 @retval EFI_UNSUPPORTED Failed to check incompatibility device.
440 PciRegisterAccessCheck (
441 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
442 IN UINT64 AccessType
,
444 IN UINT64 AccessWidth
,
445 OUT VOID
*Configuration
448 EFI_PCI_DEVICE_INFO
*Header
;
451 EFI_PCI_REGISTER_ACCESS_DATA
*RegisterPtr
;
452 EFI_PCI_REGISTER_ACCESS_DATA
*Dsc
;
454 ASSERT (PciDeviceInfo
!= NULL
);
456 ListPtr
= gDeviceListForAccessWidth
;
459 // Initialize the return value to NULL
461 * (VOID
**) Configuration
= NULL
;
463 while (*ListPtr
!= LIST_END_TAG
) {
469 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
470 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
473 // Check whether the PCI device matches the device in the incompatible devices list?
476 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
481 // Matched an item, check whether access matches?
483 for (; *ListPtr
== DEVICE_RES_TAG
;) {
485 if (((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
*) ListPtr
)->AccessType
== AccessType
&&
486 ((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
*) ListPtr
)->AccessWidth
== AccessWidth
) {
488 Dsc
= (EFI_PCI_REGISTER_ACCESS_DATA
*) (ListPtr
+ 2);
490 if((Dsc
->StartOffset
<= Offset
) && (Dsc
->EndOffset
> Offset
)) {
492 RegisterPtr
= &mPciRegisterAccessData
;
494 RegisterPtr
->StartOffset
= Dsc
->StartOffset
;
495 RegisterPtr
->EndOffset
= Dsc
->EndOffset
;
496 RegisterPtr
->Width
= Dsc
->Width
;
498 *(VOID
**) Configuration
= RegisterPtr
;
503 ListPtr
+= sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
) / (sizeof (UINT64
));
505 return EFI_UNSUPPORTED
;
509 // Adjust the pointer to the next item
511 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
)) / sizeof (UINT64
));
515 return EFI_UNSUPPORTED
;
519 return EFI_UNSUPPORTED
;