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
183 Entry point of the incompatible pci device support code. Setup an incompatible device list template
184 and install EFI Incompatible PCI Device Support protocol.
186 @param ImageHandle A handle for the image that is initializing this driver.
187 @param SystemTable A pointer to the EFI system table.
189 @retval EFI_SUCCESS Installed EFI Incompatible PCI Device Support Protocol successfully.
190 @retval others Failed to install protocol.
195 IncompatiblePciDeviceSupportEntryPoint (
196 IN EFI_HANDLE ImageHandle
,
197 IN EFI_SYSTEM_TABLE
*SystemTable
203 // Install EFI Incompatible PCI Device Support Protocol on a new handle
205 Status
= gBS
->InstallProtocolInterface (
206 &mIncompatiblePciDeviceSupportHandle
,
207 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
208 EFI_NATIVE_INTERFACE
,
209 &mIncompatiblePciDeviceSupport
211 ASSERT_EFI_ERROR (Status
);
217 Returns a list of ACPI resource descriptors that detail the special
218 resource configuration requirements for an incompatible PCI device.
220 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
221 @param VendorId A unique ID to identify the manufacturer of the PCI device.
222 @param DeviceId A unique ID to identify the particular PCI device.
223 @param RevisionId A PCI device-specific revision identifier.
224 @param SubsystemVendorId Specifies the subsystem vendor ID.
225 @param SubsystemDeviceId Specifies the subsystem device ID.
226 @param Configuration A list of ACPI resource descriptors returned that detail
227 the configuration requirement.
229 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
230 @retval EFI_INVALID_PARAMETER Configuration is NULL.
231 @retval EFI_OUT_OF_RESOURCES No memory available.
232 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
238 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
242 IN UINTN SubsystemVendorId
,
243 IN UINTN SubsystemDeviceId
,
244 OUT VOID
**Configuration
250 EFI_PCI_DEVICE_HEADER_INFO
*Header
;
251 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AcpiPtr
;
252 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*OldAcpiPtr
;
253 EFI_PCI_RESOUCE_DESCRIPTOR
*Dsc
;
254 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
258 // Validate the parameters
260 if (Configuration
== NULL
) {
261 return EFI_INVALID_PARAMETER
;
264 // Initialize the return value to NULL
266 * (VOID
**) Configuration
= NULL
;
268 ListPtr
= mIncompatiblePciDeviceList
;
269 while (*ListPtr
!= LIST_END_TAG
) {
275 Header
= (EFI_PCI_DEVICE_HEADER_INFO
*) (ListPtr
+ 1);
276 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_HEADER_INFO
) / sizeof (UINT64
);
278 // See if the Header matches the parameters passed in
280 if ((Header
->VendorId
!= MAX_UINT64
) && (VendorId
!= MAX_UINTN
)) {
281 if (Header
->VendorId
!= VendorId
) {
286 if ((Header
->DeviceId
!= MAX_UINT64
) && (DeviceId
!= MAX_UINTN
)) {
287 if (DeviceId
!= Header
->DeviceId
) {
292 if ((Header
->RevisionId
!= MAX_UINT64
) && (RevisionId
!= MAX_UINTN
)) {
293 if (RevisionId
!= Header
->RevisionId
) {
298 if ((Header
->SubsystemVendorId
!= MAX_UINT64
) && (SubsystemVendorId
!= MAX_UINTN
)) {
299 if (SubsystemVendorId
!= Header
->SubsystemVendorId
) {
304 if ((Header
->SubsystemDeviceId
!= MAX_UINT64
) && (SubsystemDeviceId
!= MAX_UINTN
)) {
305 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
));
319 // If there is at least one type of resource request,
320 // allocate an acpi resource node
323 return EFI_UNSUPPORTED
;
326 AcpiPtr
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
327 if (AcpiPtr
== NULL
) {
328 return EFI_OUT_OF_RESOURCES
;
331 OldAcpiPtr
= AcpiPtr
;
333 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
334 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
336 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
));
357 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
358 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
359 PtrEnd
->Checksum
= 0;
361 *(VOID
**) Configuration
= OldAcpiPtr
;
367 // Adjust the pointer to the next PCI resource descriptor item
369 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
373 return EFI_UNSUPPORTED
;
377 return EFI_UNSUPPORTED
;