2 The implementation of PCI incompatible device support libary.
4 Copyright (c) 2007 Intel Corporation. All rights reserved. <BR>
5 This software and associated documentation (if any) is furnished
6 under a license and may only be used or copied in accordance
7 with the terms of the license. Except as permitted by such
8 license, no part of this software or documentation may be
9 reproduced, stored in a retrieval system, or transmitted in any
10 form or by any means without the express written consent of
16 // Include common header file for this module.
18 #include "CommonHeader.h"
20 #include "IncompatiblePciDeviceList.h"
23 Check whether two PCI devices matched
25 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
26 @param Header A pointer to EFI_PCI_DEVICE_INFO.
28 @retval returns EFI_SUCCESS if two PCI device matched.
33 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
34 IN EFI_PCI_DEVICE_INFO
*Header
38 // See if the Header matches the parameters passed in
40 if (Header
->VendorID
!= DEVICE_ID_NOCARE
) {
41 if (PciDeviceInfo
->VendorID
!= Header
->VendorID
) {
42 return EFI_UNSUPPORTED
;
46 if (Header
->DeviceID
!= DEVICE_ID_NOCARE
) {
47 if (PciDeviceInfo
->DeviceID
!= Header
->DeviceID
) {
48 return EFI_UNSUPPORTED
;
52 if (Header
->RevisionID
!= DEVICE_ID_NOCARE
) {
53 if (PciDeviceInfo
->RevisionID
!= Header
->RevisionID
) {
54 return EFI_UNSUPPORTED
;
58 if (Header
->SubsystemVendorID
!= DEVICE_ID_NOCARE
) {
59 if (PciDeviceInfo
->SubsystemVendorID
!= Header
->SubsystemVendorID
) {
60 return EFI_UNSUPPORTED
;
64 if (Header
->SubsystemID
!= DEVICE_ID_NOCARE
) {
65 if (PciDeviceInfo
->SubsystemID
!= Header
->SubsystemID
) {
66 return EFI_UNSUPPORTED
;
75 Check the incompatible device list for ACPI resource update and return
78 This function searches the incompatible device list according to request
79 information. If the PCI device belongs to the devices list, corresponding
80 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
82 @param PciDeviceInfo A pointer to PCI device information.
83 @param Configuration Returned information.
85 @retval returns EFI_SUCCESS if check incompatible device ok.
86 Otherwise return EFI_UNSUPPORTED.
90 PciResourceUpdateCheck (
91 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
92 OUT VOID
*Configuration
98 EFI_PCI_DEVICE_INFO
*Header
;
99 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AcpiPtr
;
100 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*OldAcpiPtr
;
101 EFI_PCI_RESOUCE_DESCRIPTOR
*Dsc
;
102 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
105 ASSERT (PciDeviceInfo
!= NULL
);
108 // Initialize the return value to NULL
110 * (VOID
**) Configuration
= NULL
;
112 ListPtr
= IncompatiblePciDeviceListForResource
;
113 while (*ListPtr
!= LIST_END_TAG
) {
119 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
120 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
122 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
127 // Matched an item, so construct the ACPI descriptor for the resource.
130 // Count the resource items so that to allocate space
132 for (Index
= 0, TempListPtr
= ListPtr
; *TempListPtr
== DEVICE_RES_TAG
; Index
++) {
133 TempListPtr
= TempListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
136 // If there is at least one type of resource request,
137 // allocate a acpi resource node
143 AcpiPtr
= AllocateZeroPool (
144 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
147 OldAcpiPtr
= AcpiPtr
;
150 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
151 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
153 for (; *ListPtr
== DEVICE_RES_TAG
;) {
155 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*) (ListPtr
+ 1);
157 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
158 AcpiPtr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
159 AcpiPtr
->ResType
= (UINT8
) Dsc
->ResType
;
160 AcpiPtr
->GenFlag
= (UINT8
) Dsc
->GenFlag
;
161 AcpiPtr
->SpecificFlag
= (UINT8
) Dsc
->SpecificFlag
;
162 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;;
163 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
164 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
165 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
166 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
168 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
174 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
175 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
176 PtrEnd
->Checksum
= 0;
178 *(VOID
**) Configuration
= OldAcpiPtr
;
184 // Adjust the pointer to the next PCI resource descriptor item
186 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
190 return EFI_UNSUPPORTED
;
194 return EFI_UNSUPPORTED
;
199 Check the incompatible device list and return configuraton register mask values.
201 This function searches the incompatible device list according to request
202 information. If the PCI device belongs to the devices list, corresponding
203 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
205 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
206 @param AccessType Access Type, READ or WRITE.
207 @param Offset The address within the PCI configuration space.
208 @param Configuration Returned information.
210 @retval returns EFI_SUCCESS if check incompatible device ok.
211 Otherwise return EFI_UNSUPPORTED.
215 PciRegisterUpdateCheck (
216 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
217 IN UINT64 AccessType
,
219 OUT VOID
*Configuration
222 EFI_PCI_DEVICE_INFO
*Header
;
225 EFI_PCI_REGISTER_VALUE_DATA
*RegisterPtr
;
226 EFI_PCI_REGISTER_VALUE_DATA
*Dsc
;
228 ASSERT (PciDeviceInfo
!= NULL
);
230 ListPtr
= IncompatiblePciDeviceListForRegister
;
233 // Initialize the return value to NULL
235 * (VOID
**) Configuration
= NULL
;
237 while (*ListPtr
!= LIST_END_TAG
) {
243 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
244 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
247 // Check whether the PCI device matches the device in the incompatible devices list?
250 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
255 // Matched an item, check whether access matches?
257 for (; *ListPtr
== DEVICE_RES_TAG
;) {
259 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->Offset
== (Offset
& 0xfc)) {
260 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->AccessType
== AccessType
) {
262 Dsc
= (EFI_PCI_REGISTER_VALUE_DATA
*) (ListPtr
+ 2);
263 RegisterPtr
= AllocateZeroPool (sizeof (EFI_PCI_REGISTER_VALUE_DATA
));
265 RegisterPtr
->AndValue
= Dsc
->AndValue
;
266 RegisterPtr
->OrValue
= Dsc
->OrValue
;
268 *(VOID
**) Configuration
= RegisterPtr
;
273 ListPtr
+= sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR
) / (sizeof (UINT64
));
275 return EFI_UNSUPPORTED
;
279 // Adjust the pointer to the next item
281 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR
)) / sizeof (UINT64
));
285 return EFI_UNSUPPORTED
;
289 return EFI_UNSUPPORTED
;
293 Check the incompatible device list for access width incompatibility and
294 return the configuration
296 This function searches the incompatible device list for access width
297 incompatibility according to request information. If the PCI device
298 belongs to the devices list, corresponding configuration informtion
299 will be returned, in the meantime return EFI_SUCCESS.
301 @param PciDeviceInfo A pointer to PCI device information.
302 @param AccessType Access type, READ or WRITE.
303 @param Offset The address within the PCI configuration space.
304 @param AccessWidth Access width needs to check incompatibility.
305 @param Configuration Returned information.
307 @retval returns EFI_SUCCESS if check incompatible device ok.
308 Otherwise return EFI_UNSUPPORTED.
312 PciRegisterAccessCheck (
313 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
314 IN UINT64 AccessType
,
316 IN UINT64 AccessWidth
,
317 OUT VOID
*Configuration
320 EFI_PCI_DEVICE_INFO
*Header
;
323 EFI_PCI_REGISTER_ACCESS_DATA
*RegisterPtr
;
324 EFI_PCI_REGISTER_ACCESS_DATA
*Dsc
;
326 ASSERT (PciDeviceInfo
!= NULL
);
328 ListPtr
= DeviceListForAccessWidth
;
331 // Initialize the return value to NULL
333 * (VOID
**) Configuration
= NULL
;
335 while (*ListPtr
!= LIST_END_TAG
) {
341 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
342 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
345 // Check whether the PCI device matches the device in the incompatible devices list?
348 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
353 // Matched an item, check whether access matches?
355 for (; *ListPtr
== DEVICE_RES_TAG
;) {
357 if (((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
*) ListPtr
)->AccessType
== AccessType
&&
358 ((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
*) ListPtr
)->AccessWidth
== AccessWidth
) {
360 Dsc
= (EFI_PCI_REGISTER_ACCESS_DATA
*) (ListPtr
+ 2);
362 if((Dsc
->StartOffset
<= Offset
) && (Dsc
->EndOffset
> Offset
)) {
364 RegisterPtr
= AllocateZeroPool (sizeof (EFI_PCI_REGISTER_ACCESS_DATA
));
366 RegisterPtr
->StartOffset
= Dsc
->StartOffset
;
367 RegisterPtr
->EndOffset
= Dsc
->EndOffset
;
368 RegisterPtr
->Width
= Dsc
->Width
;
370 *(VOID
**) Configuration
= RegisterPtr
;
375 ListPtr
+= sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
) / (sizeof (UINT64
));
377 return EFI_UNSUPPORTED
;
381 // Adjust the pointer to the next item
383 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
)) / sizeof (UINT64
));
387 return EFI_UNSUPPORTED
;
391 return EFI_UNSUPPORTED
;