2 The implementation of PCI incompatible device support libary.
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
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 Check whether two PCI devices matched
20 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
21 @param Header A pointer to EFI_PCI_DEVICE_INFO.
23 @retval returns EFI_SUCCESS if two PCI device matched.
27 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
28 IN EFI_PCI_DEVICE_INFO
*Header
32 // See if the Header matches the parameters passed in
34 if (Header
->VendorID
!= DEVICE_ID_NOCARE
) {
35 if (PciDeviceInfo
->VendorID
!= Header
->VendorID
) {
36 return EFI_UNSUPPORTED
;
40 if (Header
->DeviceID
!= DEVICE_ID_NOCARE
) {
41 if (PciDeviceInfo
->DeviceID
!= Header
->DeviceID
) {
42 return EFI_UNSUPPORTED
;
46 if (Header
->RevisionID
!= DEVICE_ID_NOCARE
) {
47 if (PciDeviceInfo
->RevisionID
!= Header
->RevisionID
) {
48 return EFI_UNSUPPORTED
;
52 if (Header
->SubsystemVendorID
!= DEVICE_ID_NOCARE
) {
53 if (PciDeviceInfo
->SubsystemVendorID
!= Header
->SubsystemVendorID
) {
54 return EFI_UNSUPPORTED
;
58 if (Header
->SubsystemID
!= DEVICE_ID_NOCARE
) {
59 if (PciDeviceInfo
->SubsystemID
!= Header
->SubsystemID
) {
60 return EFI_UNSUPPORTED
;
69 Check the incompatible device list for ACPI resource update and return
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.
76 @param PciDeviceInfo A pointer to PCI device information.
77 @param Configuration Returned information.
79 @retval returns EFI_SUCCESS if check incompatible device ok.
80 Otherwise return EFI_UNSUPPORTED.
84 PciResourceUpdateCheck (
85 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
86 OUT VOID
*Configuration
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
;
99 ASSERT (PciDeviceInfo
!= NULL
);
102 // Initialize the return value to NULL
104 * (VOID
**) Configuration
= NULL
;
106 ListPtr
= IncompatiblePciDeviceListForResource
;
107 while (*ListPtr
!= LIST_END_TAG
) {
113 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
114 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
116 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
121 // Matched an item, so construct the ACPI descriptor for the resource.
124 // Count the resource items so that to allocate space
126 for (Index
= 0, TempListPtr
= ListPtr
; *TempListPtr
== DEVICE_RES_TAG
; Index
++) {
127 TempListPtr
= TempListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
130 // If there is at least one type of resource request,
131 // allocate a acpi resource node
137 AcpiPtr
= AllocateZeroPool (
138 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
140 if (AcpiPtr
== NULL
) {
141 return EFI_OUT_OF_RESOURCES
;
144 OldAcpiPtr
= AcpiPtr
;
147 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
148 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
150 for (; *ListPtr
== DEVICE_RES_TAG
;) {
152 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*) (ListPtr
+ 1);
154 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
155 AcpiPtr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
156 AcpiPtr
->ResType
= (UINT8
) Dsc
->ResType
;
157 AcpiPtr
->GenFlag
= (UINT8
) Dsc
->GenFlag
;
158 AcpiPtr
->SpecificFlag
= (UINT8
) Dsc
->SpecificFlag
;
159 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;;
160 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
161 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
162 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
163 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
165 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
171 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
172 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
173 PtrEnd
->Checksum
= 0;
175 *(VOID
**) Configuration
= OldAcpiPtr
;
181 // Adjust the pointer to the next PCI resource descriptor item
183 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
187 return EFI_UNSUPPORTED
;
191 return EFI_UNSUPPORTED
;
196 Check the incompatible device list and return configuraton register mask values.
198 This function searches the incompatible device list according to request
199 information. If the PCI device belongs to the devices list, corresponding
200 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
202 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
203 @param AccessType Access Type, READ or WRITE.
204 @param Offset The address within the PCI configuration space.
205 @param Configuration Returned information.
207 @retval returns EFI_SUCCESS if check incompatible device ok.
208 Otherwise return EFI_UNSUPPORTED.
212 PciRegisterUpdateCheck (
213 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
214 IN UINT64 AccessType
,
216 OUT VOID
*Configuration
219 EFI_PCI_DEVICE_INFO
*Header
;
222 EFI_PCI_REGISTER_VALUE_DATA
*RegisterPtr
;
223 EFI_PCI_REGISTER_VALUE_DATA
*Dsc
;
225 ASSERT (PciDeviceInfo
!= NULL
);
227 ListPtr
= IncompatiblePciDeviceListForRegister
;
230 // Initialize the return value to NULL
232 * (VOID
**) Configuration
= NULL
;
234 while (*ListPtr
!= LIST_END_TAG
) {
240 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
241 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
244 // Check whether the PCI device matches the device in the incompatible devices list?
247 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
252 // Matched an item, check whether access matches?
254 for (; *ListPtr
== DEVICE_RES_TAG
;) {
256 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->Offset
== (Offset
& 0xfc)) {
257 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->AccessType
== AccessType
) {
259 Dsc
= (EFI_PCI_REGISTER_VALUE_DATA
*) (ListPtr
+ 2);
260 RegisterPtr
= AllocateZeroPool (sizeof (EFI_PCI_REGISTER_VALUE_DATA
));
261 if (RegisterPtr
== NULL
) {
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
));
365 if (RegisterPtr
== NULL
) {
366 return EFI_OUT_OF_RESOURCES
;
369 RegisterPtr
->StartOffset
= Dsc
->StartOffset
;
370 RegisterPtr
->EndOffset
= Dsc
->EndOffset
;
371 RegisterPtr
->Width
= Dsc
->Width
;
373 *(VOID
**) Configuration
= RegisterPtr
;
378 ListPtr
+= sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
) / (sizeof (UINT64
));
380 return EFI_UNSUPPORTED
;
384 // Adjust the pointer to the next item
386 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
)) / sizeof (UINT64
));
390 return EFI_UNSUPPORTED
;
394 return EFI_UNSUPPORTED
;