2 This module is one template module for Incompatible PCI Device Support protocol.
3 It includes one incompatile 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, Intel Corporation
9 All rights reserved. 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.
19 #include <FrameworkDxe.h>
21 #include <Protocol/IncompatiblePciDeviceSupport.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/DebugLib.h>
27 #include <IndustryStandard/Pci.h>
28 #include <IndustryStandard/Acpi.h>
34 UINT64 SubsystemVendorId
;
35 UINT64 SubsystemDeviceId
;
36 } EFI_PCI_DEVICE_HEADER_INFO
;
42 UINT64 AddrSpaceGranularity
;
45 UINT64 AddrTranslationOffset
;
47 } EFI_PCI_RESOUCE_DESCRIPTOR
;
49 #define PCI_DEVICE_ID(VendorId, DeviceId, Revision, SubVendorId, SubDeviceId) \
50 VendorId, DeviceId, Revision, SubVendorId, SubDeviceId
52 #define PCI_BAR_TYPE_IO ACPI_ADDRESS_SPACE_TYPE_IO
53 #define PCI_BAR_TYPE_MEM ACPI_ADDRESS_SPACE_TYPE_MEM
55 #define DEVICE_INF_TAG 0xFFF2
56 #define DEVICE_RES_TAG 0xFFF1
57 #define LIST_END_TAG 0x0000
61 Returns a list of ACPI resource descriptors that detail the special
62 resource configuration requirements for an incompatible PCI device.
64 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
65 @param VendorId A unique ID to identify the manufacturer of the PCI device.
66 @param DeviceId A unique ID to identify the particular PCI device.
67 @param RevisionId A PCI device-specific revision identifier.
68 @param SubsystemVendorId Specifies the subsystem vendor ID.
69 @param SubsystemDeviceId Specifies the subsystem device ID.
70 @param Configuration A list of ACPI resource descriptors returned that detail
71 the configuration requirement.
73 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
74 @retval EFI_INVALID_PARAMETER Configuration is NULL.
75 @retval EFI_OUT_OF_RESOURCES No memory available.
76 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
82 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
88 OUT VOID
**Configuration
92 // Handle onto which the Incompatible PCI Device List is installed
94 EFI_HANDLE mIncompatiblePciDeviceSupportHandle
= NULL
;
97 // The Incompatible PCI Device Support Protocol instance produced by this driver
99 EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL mIncompatiblePciDeviceSupport
= {
104 // The incompatible PCI devices list template
106 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mIncompatiblePciDeviceList
[] = {
109 // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),
111 // ResType, GFlag , SFlag, Granularity, RangeMin,
112 // RangeMax, Offset, AddrLen
115 // Device Adaptec 9004
118 PCI_DEVICE_ID(0x9004, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
129 // Device Adaptec 9005
132 PCI_DEVICE_ID(0x9005, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
143 // Device QLogic 1007
146 PCI_DEVICE_ID(0x1077, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
157 // Device Agilent 103C
160 PCI_DEVICE_ID(0x103C, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
171 // Device Agilent 15BC
174 PCI_DEVICE_ID(0x15BC, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
185 // The end of the list
192 Entry point of the incompatible pci device support code. Setup an incompatible device list template
193 and install EFI Incompatible PCI Device Support protocol.
195 @param ImageHandle A handle for the image that is initializing this driver.
196 @param SystemTable A pointer to the EFI system table.
198 @retval EFI_SUCCESS Installed EFI Incompatible PCI Device Support Protocol successfully.
199 @retval others Failed to install protocol.
204 IncompatiblePciDeviceSupportEntryPoint (
205 IN EFI_HANDLE ImageHandle
,
206 IN EFI_SYSTEM_TABLE
*SystemTable
212 // Install EFI Incompatible PCI Device Support Protocol on a new handle
214 Status
= gBS
->InstallProtocolInterface (
215 &mIncompatiblePciDeviceSupportHandle
,
216 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
217 EFI_NATIVE_INTERFACE
,
218 &mIncompatiblePciDeviceSupport
220 ASSERT_EFI_ERROR (Status
);
226 Returns a list of ACPI resource descriptors that detail the special
227 resource configuration requirements for an incompatible PCI device.
229 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
230 @param VendorId A unique ID to identify the manufacturer of the PCI device.
231 @param DeviceId A unique ID to identify the particular PCI device.
232 @param RevisionId A PCI device-specific revision identifier.
233 @param SubsystemVendorId Specifies the subsystem vendor ID.
234 @param SubsystemDeviceId Specifies the subsystem device ID.
235 @param Configuration A list of ACPI resource descriptors returned that detail
236 the configuration requirement.
238 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
239 @retval EFI_INVALID_PARAMETER Configuration is NULL.
240 @retval EFI_OUT_OF_RESOURCES No memory available.
241 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
247 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
251 IN UINTN SubsystemVendorId
,
252 IN UINTN SubsystemDeviceId
,
253 OUT VOID
**Configuration
259 EFI_PCI_DEVICE_HEADER_INFO
*Header
;
260 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AcpiPtr
;
261 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*OldAcpiPtr
;
262 EFI_PCI_RESOUCE_DESCRIPTOR
*Dsc
;
263 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
267 // Validate the parameters
269 if (Configuration
== NULL
) {
270 return EFI_INVALID_PARAMETER
;
273 // Initialize the return value to NULL
275 * (VOID
**) Configuration
= NULL
;
277 ListPtr
= mIncompatiblePciDeviceList
;
278 while (*ListPtr
!= LIST_END_TAG
) {
284 Header
= (EFI_PCI_DEVICE_HEADER_INFO
*) (ListPtr
+ 1);
285 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_HEADER_INFO
) / sizeof (UINT64
);
287 // See if the Header matches the parameters passed in
289 if (Header
->VendorId
!= DEVICE_ID_NOCARE
) {
290 if (Header
->VendorId
!= VendorId
) {
295 if (Header
->DeviceId
!= DEVICE_ID_NOCARE
) {
296 if (DeviceId
!= Header
->DeviceId
) {
301 if (Header
->RevisionId
!= DEVICE_ID_NOCARE
) {
302 if (RevisionId
!= Header
->RevisionId
) {
307 if (Header
->SubsystemVendorId
!= DEVICE_ID_NOCARE
) {
308 if (SubsystemVendorId
!= Header
->SubsystemVendorId
) {
313 if (Header
->SubsystemDeviceId
!= DEVICE_ID_NOCARE
) {
314 if (SubsystemDeviceId
!= Header
->SubsystemDeviceId
) {
319 // Matched an item, so construct the ACPI descriptor for the resource.
322 // Count the resource items so that to allocate space
324 for (Index
= 0, TempListPtr
= ListPtr
; *TempListPtr
== DEVICE_RES_TAG
; Index
++) {
325 TempListPtr
= TempListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
328 // If there is at least one type of resource request,
329 // allocate an acpi resource node
332 return EFI_UNSUPPORTED
;
335 AcpiPtr
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
336 if (AcpiPtr
== NULL
) {
337 return EFI_OUT_OF_RESOURCES
;
340 OldAcpiPtr
= AcpiPtr
;
342 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
343 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
345 for (; *ListPtr
== DEVICE_RES_TAG
;) {
347 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*) (ListPtr
+ 1);
349 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
350 AcpiPtr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
351 AcpiPtr
->ResType
= (UINT8
) Dsc
->ResType
;
352 AcpiPtr
->GenFlag
= (UINT8
) Dsc
->GenFlag
;
353 AcpiPtr
->SpecificFlag
= (UINT8
) Dsc
->SpecificFlag
;
354 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;;
355 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
356 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
357 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
358 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
360 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
366 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
367 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
368 PtrEnd
->Checksum
= 0;
370 *(VOID
**) Configuration
= OldAcpiPtr
;
376 // Adjust the pointer to the next PCI resource descriptor item
378 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
382 return EFI_UNSUPPORTED
;
386 return EFI_UNSUPPORTED
;