2 This module is one template module for Incompatible PCI Device Support protocol.
3 It includes one incompatible pci devices list template.
5 Incompatible PCI Device Support protocol allows the PCI bus driver to support
6 resource allocation for some PCI devices that do not comply with the PCI Specification.
8 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include <Protocol/IncompatiblePciDeviceSupport.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/DebugLib.h>
20 #include <IndustryStandard/Pci.h>
21 #include <IndustryStandard/Acpi.h>
27 UINT64 SubsystemVendorId
;
28 UINT64 SubsystemDeviceId
;
29 } EFI_PCI_DEVICE_HEADER_INFO
;
35 UINT64 AddrSpaceGranularity
;
38 UINT64 AddrTranslationOffset
;
40 } EFI_PCI_RESOUCE_DESCRIPTOR
;
42 #define PCI_DEVICE_ID(VendorId, DeviceId, Revision, SubVendorId, SubDeviceId) \
43 VendorId, DeviceId, Revision, SubVendorId, SubDeviceId
45 #define DEVICE_INF_TAG 0xFFF2
46 #define DEVICE_RES_TAG 0xFFF1
47 #define LIST_END_TAG 0x0000
49 #define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
52 Returns a list of ACPI resource descriptors that detail the special
53 resource configuration requirements for an incompatible PCI device.
55 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
56 @param VendorId A unique ID to identify the manufacturer of the PCI device.
57 @param DeviceId A unique ID to identify the particular PCI device.
58 @param RevisionId A PCI device-specific revision identifier.
59 @param SubsystemVendorId Specifies the subsystem vendor ID.
60 @param SubsystemDeviceId Specifies the subsystem device ID.
61 @param Configuration A list of ACPI resource descriptors returned that detail
62 the configuration requirement.
64 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
65 @retval EFI_INVALID_PARAMETER Configuration is NULL.
66 @retval EFI_OUT_OF_RESOURCES No memory available.
67 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
73 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
77 IN UINTN SubsystemVendorId
,
78 IN UINTN SubsystemDeviceId
,
79 OUT VOID
**Configuration
83 // Handle onto which the Incompatible PCI Device List is installed
85 EFI_HANDLE mIncompatiblePciDeviceSupportHandle
= NULL
;
88 // The Incompatible PCI Device Support Protocol instance produced by this driver
90 EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL mIncompatiblePciDeviceSupport
= {
95 // The incompatible PCI devices list template
97 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mIncompatiblePciDeviceList
[] = {
100 // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),
102 // ResType, GFlag , SFlag, Granularity, RangeMin,
103 // RangeMax, Offset, AddrLen
106 // Device Adaptec 9004
109 PCI_DEVICE_ID (0x9004, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
111 ACPI_ADDRESS_SPACE_TYPE_IO
,
120 // Device Adaptec 9005
123 PCI_DEVICE_ID (0x9005, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
125 ACPI_ADDRESS_SPACE_TYPE_IO
,
134 // Device QLogic 1007
137 PCI_DEVICE_ID (0x1077, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
139 ACPI_ADDRESS_SPACE_TYPE_IO
,
148 // Device Agilent 103C
151 PCI_DEVICE_ID (0x103C, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
153 ACPI_ADDRESS_SPACE_TYPE_IO
,
162 // Device Agilent 15BC
165 PCI_DEVICE_ID (0x15BC, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
167 ACPI_ADDRESS_SPACE_TYPE_IO
,
176 // The end of the list
182 Entry point of the incompatible pci device support code. Setup an incompatible device list template
183 and install EFI Incompatible PCI Device Support protocol.
185 @param ImageHandle A handle for the image that is initializing this driver.
186 @param SystemTable A pointer to the EFI system table.
188 @retval EFI_SUCCESS Installed EFI Incompatible PCI Device Support Protocol successfully.
189 @retval others Failed to install protocol.
194 IncompatiblePciDeviceSupportEntryPoint (
195 IN EFI_HANDLE ImageHandle
,
196 IN EFI_SYSTEM_TABLE
*SystemTable
202 // Install EFI Incompatible PCI Device Support Protocol on a new handle
204 Status
= gBS
->InstallProtocolInterface (
205 &mIncompatiblePciDeviceSupportHandle
,
206 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
207 EFI_NATIVE_INTERFACE
,
208 &mIncompatiblePciDeviceSupport
210 ASSERT_EFI_ERROR (Status
);
216 Returns a list of ACPI resource descriptors that detail the special
217 resource configuration requirements for an incompatible PCI device.
219 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
220 @param VendorId A unique ID to identify the manufacturer of the PCI device.
221 @param DeviceId A unique ID to identify the particular PCI device.
222 @param RevisionId A PCI device-specific revision identifier.
223 @param SubsystemVendorId Specifies the subsystem vendor ID.
224 @param SubsystemDeviceId Specifies the subsystem device ID.
225 @param Configuration A list of ACPI resource descriptors returned that detail
226 the configuration requirement.
228 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
229 @retval EFI_INVALID_PARAMETER Configuration is NULL.
230 @retval EFI_OUT_OF_RESOURCES No memory available.
231 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
237 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
241 IN UINTN SubsystemVendorId
,
242 IN UINTN SubsystemDeviceId
,
243 OUT VOID
**Configuration
249 EFI_PCI_DEVICE_HEADER_INFO
*Header
;
250 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AcpiPtr
;
251 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*OldAcpiPtr
;
252 EFI_PCI_RESOUCE_DESCRIPTOR
*Dsc
;
253 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
257 // Validate the parameters
259 if (Configuration
== NULL
) {
260 return EFI_INVALID_PARAMETER
;
264 // Initialize the return value to NULL
266 *(VOID
**)Configuration
= NULL
;
268 ListPtr
= mIncompatiblePciDeviceList
;
269 while (*ListPtr
!= LIST_END_TAG
) {
274 Header
= (EFI_PCI_DEVICE_HEADER_INFO
*)(ListPtr
+ 1);
275 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_HEADER_INFO
) / sizeof (UINT64
);
277 // See if the Header matches the parameters passed in
279 if ((Header
->VendorId
!= MAX_UINT64
) && (VendorId
!= MAX_UINTN
)) {
280 if (Header
->VendorId
!= VendorId
) {
285 if ((Header
->DeviceId
!= MAX_UINT64
) && (DeviceId
!= MAX_UINTN
)) {
286 if (DeviceId
!= Header
->DeviceId
) {
291 if ((Header
->RevisionId
!= MAX_UINT64
) && (RevisionId
!= MAX_UINTN
)) {
292 if (RevisionId
!= Header
->RevisionId
) {
297 if ((Header
->SubsystemVendorId
!= MAX_UINT64
) && (SubsystemVendorId
!= MAX_UINTN
)) {
298 if (SubsystemVendorId
!= Header
->SubsystemVendorId
) {
303 if ((Header
->SubsystemDeviceId
!= MAX_UINT64
) && (SubsystemDeviceId
!= MAX_UINTN
)) {
304 if (SubsystemDeviceId
!= Header
->SubsystemDeviceId
) {
310 // Matched an item, so construct the ACPI descriptor for the resource.
313 // Count the resource items so that to allocate space
315 for (Index
= 0, TempListPtr
= ListPtr
; *TempListPtr
== DEVICE_RES_TAG
; Index
++) {
316 TempListPtr
= TempListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
320 // If there is at least one type of resource request,
321 // allocate an acpi resource node
324 return EFI_UNSUPPORTED
;
327 AcpiPtr
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
328 if (AcpiPtr
== NULL
) {
329 return EFI_OUT_OF_RESOURCES
;
332 OldAcpiPtr
= AcpiPtr
;
334 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
335 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
337 for ( ; *ListPtr
== DEVICE_RES_TAG
;) {
338 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*)(ListPtr
+ 1);
340 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
341 AcpiPtr
->Len
= (UINT16
)sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
342 AcpiPtr
->ResType
= (UINT8
)Dsc
->ResType
;
343 AcpiPtr
->GenFlag
= (UINT8
)Dsc
->GenFlag
;
344 AcpiPtr
->SpecificFlag
= (UINT8
)Dsc
->SpecificFlag
;
345 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;
346 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
347 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
348 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
349 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
351 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
358 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(AcpiPtr
);
359 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
360 PtrEnd
->Checksum
= 0;
362 *(VOID
**)Configuration
= OldAcpiPtr
;
368 // Adjust the pointer to the next PCI resource descriptor item
370 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
374 return EFI_UNSUPPORTED
;
378 return EFI_UNSUPPORTED
;