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 - 2017, Intel Corporation. All rights reserved.<BR>
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include <Protocol/IncompatiblePciDeviceSupport.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/DebugLib.h>
26 #include <IndustryStandard/Pci.h>
27 #include <IndustryStandard/Acpi.h>
33 UINT64 SubsystemVendorId
;
34 UINT64 SubsystemDeviceId
;
35 } EFI_PCI_DEVICE_HEADER_INFO
;
41 UINT64 AddrSpaceGranularity
;
44 UINT64 AddrTranslationOffset
;
46 } EFI_PCI_RESOUCE_DESCRIPTOR
;
48 #define PCI_DEVICE_ID(VendorId, DeviceId, Revision, SubVendorId, SubDeviceId) \
49 VendorId, DeviceId, Revision, SubVendorId, SubDeviceId
51 #define DEVICE_INF_TAG 0xFFF2
52 #define DEVICE_RES_TAG 0xFFF1
53 #define LIST_END_TAG 0x0000
55 #define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
58 Returns a list of ACPI resource descriptors that detail the special
59 resource configuration requirements for an incompatible PCI device.
61 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
62 @param VendorId A unique ID to identify the manufacturer of the PCI device.
63 @param DeviceId A unique ID to identify the particular PCI device.
64 @param RevisionId A PCI device-specific revision identifier.
65 @param SubsystemVendorId Specifies the subsystem vendor ID.
66 @param SubsystemDeviceId Specifies the subsystem device ID.
67 @param Configuration A list of ACPI resource descriptors returned that detail
68 the configuration requirement.
70 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
71 @retval EFI_INVALID_PARAMETER Configuration is NULL.
72 @retval EFI_OUT_OF_RESOURCES No memory available.
73 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
79 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
83 IN UINTN SubsystemVendorId
,
84 IN UINTN SubsystemDeviceId
,
85 OUT VOID
**Configuration
89 // Handle onto which the Incompatible PCI Device List is installed
91 EFI_HANDLE mIncompatiblePciDeviceSupportHandle
= NULL
;
94 // The Incompatible PCI Device Support Protocol instance produced by this driver
96 EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL mIncompatiblePciDeviceSupport
= {
101 // The incompatible PCI devices list template
103 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mIncompatiblePciDeviceList
[] = {
106 // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),
108 // ResType, GFlag , SFlag, Granularity, RangeMin,
109 // RangeMax, Offset, AddrLen
112 // Device Adaptec 9004
115 PCI_DEVICE_ID(0x9004, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
117 ACPI_ADDRESS_SPACE_TYPE_IO
,
126 // Device Adaptec 9005
129 PCI_DEVICE_ID(0x9005, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
131 ACPI_ADDRESS_SPACE_TYPE_IO
,
140 // Device QLogic 1007
143 PCI_DEVICE_ID(0x1077, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
145 ACPI_ADDRESS_SPACE_TYPE_IO
,
154 // Device Agilent 103C
157 PCI_DEVICE_ID(0x103C, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
159 ACPI_ADDRESS_SPACE_TYPE_IO
,
168 // Device Agilent 15BC
171 PCI_DEVICE_ID(0x15BC, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
, MAX_UINT64
),
173 ACPI_ADDRESS_SPACE_TYPE_IO
,
182 // The end of the list
189 Entry point of the incompatible pci device support code. Setup an incompatible device list template
190 and install EFI Incompatible PCI Device Support protocol.
192 @param ImageHandle A handle for the image that is initializing this driver.
193 @param SystemTable A pointer to the EFI system table.
195 @retval EFI_SUCCESS Installed EFI Incompatible PCI Device Support Protocol successfully.
196 @retval others Failed to install protocol.
201 IncompatiblePciDeviceSupportEntryPoint (
202 IN EFI_HANDLE ImageHandle
,
203 IN EFI_SYSTEM_TABLE
*SystemTable
209 // Install EFI Incompatible PCI Device Support Protocol on a new handle
211 Status
= gBS
->InstallProtocolInterface (
212 &mIncompatiblePciDeviceSupportHandle
,
213 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
214 EFI_NATIVE_INTERFACE
,
215 &mIncompatiblePciDeviceSupport
217 ASSERT_EFI_ERROR (Status
);
223 Returns a list of ACPI resource descriptors that detail the special
224 resource configuration requirements for an incompatible PCI device.
226 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
227 @param VendorId A unique ID to identify the manufacturer of the PCI device.
228 @param DeviceId A unique ID to identify the particular PCI device.
229 @param RevisionId A PCI device-specific revision identifier.
230 @param SubsystemVendorId Specifies the subsystem vendor ID.
231 @param SubsystemDeviceId Specifies the subsystem device ID.
232 @param Configuration A list of ACPI resource descriptors returned that detail
233 the configuration requirement.
235 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
236 @retval EFI_INVALID_PARAMETER Configuration is NULL.
237 @retval EFI_OUT_OF_RESOURCES No memory available.
238 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
244 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
248 IN UINTN SubsystemVendorId
,
249 IN UINTN SubsystemDeviceId
,
250 OUT VOID
**Configuration
256 EFI_PCI_DEVICE_HEADER_INFO
*Header
;
257 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AcpiPtr
;
258 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*OldAcpiPtr
;
259 EFI_PCI_RESOUCE_DESCRIPTOR
*Dsc
;
260 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
264 // Validate the parameters
266 if (Configuration
== NULL
) {
267 return EFI_INVALID_PARAMETER
;
270 // Initialize the return value to NULL
272 * (VOID
**) Configuration
= NULL
;
274 ListPtr
= mIncompatiblePciDeviceList
;
275 while (*ListPtr
!= LIST_END_TAG
) {
281 Header
= (EFI_PCI_DEVICE_HEADER_INFO
*) (ListPtr
+ 1);
282 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_HEADER_INFO
) / sizeof (UINT64
);
284 // See if the Header matches the parameters passed in
286 if (Header
->VendorId
!= MAX_UINT64
) {
287 if (Header
->VendorId
!= VendorId
) {
292 if (Header
->DeviceId
!= MAX_UINT64
) {
293 if (DeviceId
!= Header
->DeviceId
) {
298 if (Header
->RevisionId
!= MAX_UINT64
) {
299 if (RevisionId
!= Header
->RevisionId
) {
304 if (Header
->SubsystemVendorId
!= MAX_UINT64
) {
305 if (SubsystemVendorId
!= Header
->SubsystemVendorId
) {
310 if (Header
->SubsystemDeviceId
!= MAX_UINT64
) {
311 if (SubsystemDeviceId
!= Header
->SubsystemDeviceId
) {
316 // Matched an item, so construct the ACPI descriptor for the resource.
319 // Count the resource items so that to allocate space
321 for (Index
= 0, TempListPtr
= ListPtr
; *TempListPtr
== DEVICE_RES_TAG
; Index
++) {
322 TempListPtr
= TempListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
325 // If there is at least one type of resource request,
326 // allocate an acpi resource node
329 return EFI_UNSUPPORTED
;
332 AcpiPtr
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
333 if (AcpiPtr
== NULL
) {
334 return EFI_OUT_OF_RESOURCES
;
337 OldAcpiPtr
= AcpiPtr
;
339 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
340 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
342 for (; *ListPtr
== DEVICE_RES_TAG
;) {
344 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*) (ListPtr
+ 1);
346 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
347 AcpiPtr
->Len
= (UINT16
) sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
348 AcpiPtr
->ResType
= (UINT8
) Dsc
->ResType
;
349 AcpiPtr
->GenFlag
= (UINT8
) Dsc
->GenFlag
;
350 AcpiPtr
->SpecificFlag
= (UINT8
) Dsc
->SpecificFlag
;
351 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;;
352 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
353 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
354 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
355 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
357 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
363 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
364 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
365 PtrEnd
->Checksum
= 0;
367 *(VOID
**) Configuration
= OldAcpiPtr
;
373 // Adjust the pointer to the next PCI resource descriptor item
375 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
379 return EFI_UNSUPPORTED
;
383 return EFI_UNSUPPORTED
;