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
)
141 OldAcpiPtr
= AcpiPtr
;
144 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
145 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
147 for (; *ListPtr
== DEVICE_RES_TAG
;) {
149 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*) (ListPtr
+ 1);
151 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
152 AcpiPtr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
153 AcpiPtr
->ResType
= (UINT8
) Dsc
->ResType
;
154 AcpiPtr
->GenFlag
= (UINT8
) Dsc
->GenFlag
;
155 AcpiPtr
->SpecificFlag
= (UINT8
) Dsc
->SpecificFlag
;
156 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;;
157 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
158 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
159 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
160 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
162 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
168 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
169 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
170 PtrEnd
->Checksum
= 0;
172 *(VOID
**) Configuration
= OldAcpiPtr
;
178 // Adjust the pointer to the next PCI resource descriptor item
180 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
184 return EFI_UNSUPPORTED
;
188 return EFI_UNSUPPORTED
;
193 Check the incompatible device list and return configuraton register mask values.
195 This function searches the incompatible device list according to request
196 information. If the PCI device belongs to the devices list, corresponding
197 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
199 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
200 @param AccessType Access Type, READ or WRITE.
201 @param Offset The address within the PCI configuration space.
202 @param Configuration Returned information.
204 @retval returns EFI_SUCCESS if check incompatible device ok.
205 Otherwise return EFI_UNSUPPORTED.
209 PciRegisterUpdateCheck (
210 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
211 IN UINT64 AccessType
,
213 OUT VOID
*Configuration
216 EFI_PCI_DEVICE_INFO
*Header
;
219 EFI_PCI_REGISTER_VALUE_DATA
*RegisterPtr
;
220 EFI_PCI_REGISTER_VALUE_DATA
*Dsc
;
222 ASSERT (PciDeviceInfo
!= NULL
);
224 ListPtr
= IncompatiblePciDeviceListForRegister
;
227 // Initialize the return value to NULL
229 * (VOID
**) Configuration
= NULL
;
231 while (*ListPtr
!= LIST_END_TAG
) {
237 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
238 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
241 // Check whether the PCI device matches the device in the incompatible devices list?
244 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
249 // Matched an item, check whether access matches?
251 for (; *ListPtr
== DEVICE_RES_TAG
;) {
253 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->Offset
== (Offset
& 0xfc)) {
254 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->AccessType
== AccessType
) {
256 Dsc
= (EFI_PCI_REGISTER_VALUE_DATA
*) (ListPtr
+ 2);
257 RegisterPtr
= AllocateZeroPool (sizeof (EFI_PCI_REGISTER_VALUE_DATA
));
259 RegisterPtr
->AndValue
= Dsc
->AndValue
;
260 RegisterPtr
->OrValue
= Dsc
->OrValue
;
262 *(VOID
**) Configuration
= RegisterPtr
;
267 ListPtr
+= sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR
) / (sizeof (UINT64
));
269 return EFI_UNSUPPORTED
;
273 // Adjust the pointer to the next item
275 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR
)) / sizeof (UINT64
));
279 return EFI_UNSUPPORTED
;
283 return EFI_UNSUPPORTED
;
287 Check the incompatible device list for access width incompatibility and
288 return the configuration
290 This function searches the incompatible device list for access width
291 incompatibility according to request information. If the PCI device
292 belongs to the devices list, corresponding configuration informtion
293 will be returned, in the meantime return EFI_SUCCESS.
295 @param PciDeviceInfo A pointer to PCI device information.
296 @param AccessType Access type, READ or WRITE.
297 @param Offset The address within the PCI configuration space.
298 @param AccessWidth Access width needs to check incompatibility.
299 @param Configuration Returned information.
301 @retval returns EFI_SUCCESS if check incompatible device ok.
302 Otherwise return EFI_UNSUPPORTED.
306 PciRegisterAccessCheck (
307 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
308 IN UINT64 AccessType
,
310 IN UINT64 AccessWidth
,
311 OUT VOID
*Configuration
314 EFI_PCI_DEVICE_INFO
*Header
;
317 EFI_PCI_REGISTER_ACCESS_DATA
*RegisterPtr
;
318 EFI_PCI_REGISTER_ACCESS_DATA
*Dsc
;
320 ASSERT (PciDeviceInfo
!= NULL
);
322 ListPtr
= DeviceListForAccessWidth
;
325 // Initialize the return value to NULL
327 * (VOID
**) Configuration
= NULL
;
329 while (*ListPtr
!= LIST_END_TAG
) {
335 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
336 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
339 // Check whether the PCI device matches the device in the incompatible devices list?
342 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
347 // Matched an item, check whether access matches?
349 for (; *ListPtr
== DEVICE_RES_TAG
;) {
351 if (((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
*) ListPtr
)->AccessType
== AccessType
&&
352 ((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
*) ListPtr
)->AccessWidth
== AccessWidth
) {
354 Dsc
= (EFI_PCI_REGISTER_ACCESS_DATA
*) (ListPtr
+ 2);
356 if((Dsc
->StartOffset
<= Offset
) && (Dsc
->EndOffset
> Offset
)) {
358 RegisterPtr
= AllocateZeroPool (sizeof (EFI_PCI_REGISTER_ACCESS_DATA
));
360 RegisterPtr
->StartOffset
= Dsc
->StartOffset
;
361 RegisterPtr
->EndOffset
= Dsc
->EndOffset
;
362 RegisterPtr
->Width
= Dsc
->Width
;
364 *(VOID
**) Configuration
= RegisterPtr
;
369 ListPtr
+= sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
) / (sizeof (UINT64
));
371 return EFI_UNSUPPORTED
;
375 // Adjust the pointer to the next item
377 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
)) / sizeof (UINT64
));
381 return EFI_UNSUPPORTED
;
385 return EFI_UNSUPPORTED
;