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
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.
28 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
29 IN EFI_PCI_DEVICE_INFO
*Header
33 // See if the Header matches the parameters passed in
35 if (Header
->VendorID
!= DEVICE_ID_NOCARE
) {
36 if (PciDeviceInfo
->VendorID
!= Header
->VendorID
) {
37 return EFI_UNSUPPORTED
;
41 if (Header
->DeviceID
!= DEVICE_ID_NOCARE
) {
42 if (PciDeviceInfo
->DeviceID
!= Header
->DeviceID
) {
43 return EFI_UNSUPPORTED
;
47 if (Header
->RevisionID
!= DEVICE_ID_NOCARE
) {
48 if (PciDeviceInfo
->RevisionID
!= Header
->RevisionID
) {
49 return EFI_UNSUPPORTED
;
53 if (Header
->SubsystemVendorID
!= DEVICE_ID_NOCARE
) {
54 if (PciDeviceInfo
->SubsystemVendorID
!= Header
->SubsystemVendorID
) {
55 return EFI_UNSUPPORTED
;
59 if (Header
->SubsystemID
!= DEVICE_ID_NOCARE
) {
60 if (PciDeviceInfo
->SubsystemID
!= Header
->SubsystemID
) {
61 return EFI_UNSUPPORTED
;
70 Check the incompatible device list for ACPI resource update and return
73 This function searches the incompatible device list according to request
74 information. If the PCI device belongs to the devices list, corresponding
75 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
77 @param PciDeviceInfo A pointer to PCI device information.
78 @param Configuration Returned information.
80 @retval returns EFI_SUCCESS if check incompatible device ok.
81 Otherwise return EFI_UNSUPPORTED.
85 PciResourceUpdateCheck (
86 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
87 OUT VOID
*Configuration
93 EFI_PCI_DEVICE_INFO
*Header
;
94 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AcpiPtr
;
95 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*OldAcpiPtr
;
96 EFI_PCI_RESOUCE_DESCRIPTOR
*Dsc
;
97 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
100 ASSERT (PciDeviceInfo
!= NULL
);
103 // Initialize the return value to NULL
105 * (VOID
**) Configuration
= NULL
;
107 ListPtr
= IncompatiblePciDeviceListForResource
;
108 while (*ListPtr
!= LIST_END_TAG
) {
114 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
115 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
117 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
122 // Matched an item, so construct the ACPI descriptor for the resource.
125 // Count the resource items so that to allocate space
127 for (Index
= 0, TempListPtr
= ListPtr
; *TempListPtr
== DEVICE_RES_TAG
; Index
++) {
128 TempListPtr
= TempListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
131 // If there is at least one type of resource request,
132 // allocate a acpi resource node
138 AcpiPtr
= AllocateZeroPool (
139 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
142 OldAcpiPtr
= AcpiPtr
;
145 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
146 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
148 for (; *ListPtr
== DEVICE_RES_TAG
;) {
150 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*) (ListPtr
+ 1);
152 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
153 AcpiPtr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
154 AcpiPtr
->ResType
= (UINT8
) Dsc
->ResType
;
155 AcpiPtr
->GenFlag
= (UINT8
) Dsc
->GenFlag
;
156 AcpiPtr
->SpecificFlag
= (UINT8
) Dsc
->SpecificFlag
;
157 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;;
158 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
159 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
160 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
161 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
163 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
169 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
170 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
171 PtrEnd
->Checksum
= 0;
173 *(VOID
**) Configuration
= OldAcpiPtr
;
179 // Adjust the pointer to the next PCI resource descriptor item
181 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
185 return EFI_UNSUPPORTED
;
189 return EFI_UNSUPPORTED
;
194 Check the incompatible device list and return configuraton register mask values.
196 This function searches the incompatible device list according to request
197 information. If the PCI device belongs to the devices list, corresponding
198 configuration informtion will be returned, in the meantime return EFI_SUCCESS.
200 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
201 @param AccessType Access Type, READ or WRITE.
202 @param Offset The address within the PCI configuration space.
203 @param Configuration Returned information.
205 @retval returns EFI_SUCCESS if check incompatible device ok.
206 Otherwise return EFI_UNSUPPORTED.
210 PciRegisterUpdateCheck (
211 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
212 IN UINT64 AccessType
,
214 OUT VOID
*Configuration
217 EFI_PCI_DEVICE_INFO
*Header
;
220 EFI_PCI_REGISTER_VALUE_DATA
*RegisterPtr
;
221 EFI_PCI_REGISTER_VALUE_DATA
*Dsc
;
223 ASSERT (PciDeviceInfo
!= NULL
);
225 ListPtr
= IncompatiblePciDeviceListForRegister
;
228 // Initialize the return value to NULL
230 * (VOID
**) Configuration
= NULL
;
232 while (*ListPtr
!= LIST_END_TAG
) {
238 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
239 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
242 // Check whether the PCI device matches the device in the incompatible devices list?
245 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
250 // Matched an item, check whether access matches?
252 for (; *ListPtr
== DEVICE_RES_TAG
;) {
254 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->Offset
== (Offset
& 0xfc)) {
255 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR
*)ListPtr
)->AccessType
== AccessType
) {
257 Dsc
= (EFI_PCI_REGISTER_VALUE_DATA
*) (ListPtr
+ 2);
258 RegisterPtr
= AllocateZeroPool (sizeof (EFI_PCI_REGISTER_VALUE_DATA
));
260 RegisterPtr
->AndValue
= Dsc
->AndValue
;
261 RegisterPtr
->OrValue
= Dsc
->OrValue
;
263 *(VOID
**) Configuration
= RegisterPtr
;
268 ListPtr
+= sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR
) / (sizeof (UINT64
));
270 return EFI_UNSUPPORTED
;
274 // Adjust the pointer to the next item
276 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR
)) / sizeof (UINT64
));
280 return EFI_UNSUPPORTED
;
284 return EFI_UNSUPPORTED
;
288 Check the incompatible device list for access width incompatibility and
289 return the configuration
291 This function searches the incompatible device list for access width
292 incompatibility according to request information. If the PCI device
293 belongs to the devices list, corresponding configuration informtion
294 will be returned, in the meantime return EFI_SUCCESS.
296 @param PciDeviceInfo A pointer to PCI device information.
297 @param AccessType Access type, READ or WRITE.
298 @param Offset The address within the PCI configuration space.
299 @param AccessWidth Access width needs to check incompatibility.
300 @param Configuration Returned information.
302 @retval returns EFI_SUCCESS if check incompatible device ok.
303 Otherwise return EFI_UNSUPPORTED.
307 PciRegisterAccessCheck (
308 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
309 IN UINT64 AccessType
,
311 IN UINT64 AccessWidth
,
312 OUT VOID
*Configuration
315 EFI_PCI_DEVICE_INFO
*Header
;
318 EFI_PCI_REGISTER_ACCESS_DATA
*RegisterPtr
;
319 EFI_PCI_REGISTER_ACCESS_DATA
*Dsc
;
321 ASSERT (PciDeviceInfo
!= NULL
);
323 ListPtr
= DeviceListForAccessWidth
;
326 // Initialize the return value to NULL
328 * (VOID
**) Configuration
= NULL
;
330 while (*ListPtr
!= LIST_END_TAG
) {
336 Header
= (EFI_PCI_DEVICE_INFO
*) (ListPtr
+ 1);
337 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_INFO
) / sizeof (UINT64
);
340 // Check whether the PCI device matches the device in the incompatible devices list?
343 if (DeviceCheck (PciDeviceInfo
, Header
) != EFI_SUCCESS
) {
348 // Matched an item, check whether access matches?
350 for (; *ListPtr
== DEVICE_RES_TAG
;) {
352 if (((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
*) ListPtr
)->AccessType
== AccessType
&&
353 ((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
*) ListPtr
)->AccessWidth
== AccessWidth
) {
355 Dsc
= (EFI_PCI_REGISTER_ACCESS_DATA
*) (ListPtr
+ 2);
357 if((Dsc
->StartOffset
<= Offset
) && (Dsc
->EndOffset
> Offset
)) {
359 RegisterPtr
= AllocateZeroPool (sizeof (EFI_PCI_REGISTER_ACCESS_DATA
));
361 RegisterPtr
->StartOffset
= Dsc
->StartOffset
;
362 RegisterPtr
->EndOffset
= Dsc
->EndOffset
;
363 RegisterPtr
->Width
= Dsc
->Width
;
365 *(VOID
**) Configuration
= RegisterPtr
;
370 ListPtr
+= sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
) / (sizeof (UINT64
));
372 return EFI_UNSUPPORTED
;
376 // Adjust the pointer to the next item
378 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR
)) / sizeof (UINT64
));
382 return EFI_UNSUPPORTED
;
386 return EFI_UNSUPPORTED
;