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. 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 PCI_BAR_TYPE_IO ACPI_ADDRESS_SPACE_TYPE_IO
52 #define PCI_BAR_TYPE_MEM ACPI_ADDRESS_SPACE_TYPE_MEM
54 #define DEVICE_INF_TAG 0xFFF2
55 #define DEVICE_RES_TAG 0xFFF1
56 #define LIST_END_TAG 0x0000
60 Returns a list of ACPI resource descriptors that detail the special
61 resource configuration requirements for an incompatible PCI device.
63 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
64 @param VendorId A unique ID to identify the manufacturer of the PCI device.
65 @param DeviceId A unique ID to identify the particular PCI device.
66 @param RevisionId A PCI device-specific revision identifier.
67 @param SubsystemVendorId Specifies the subsystem vendor ID.
68 @param SubsystemDeviceId Specifies the subsystem device ID.
69 @param Configuration A list of ACPI resource descriptors returned that detail
70 the configuration requirement.
72 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
73 @retval EFI_INVALID_PARAMETER Configuration is NULL.
74 @retval EFI_OUT_OF_RESOURCES No memory available.
75 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
81 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
85 IN UINTN SubsystemVendorId
,
86 IN UINTN SubsystemDeviceId
,
87 OUT VOID
**Configuration
91 // Handle onto which the Incompatible PCI Device List is installed
93 EFI_HANDLE mIncompatiblePciDeviceSupportHandle
= NULL
;
96 // The Incompatible PCI Device Support Protocol instance produced by this driver
98 EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL mIncompatiblePciDeviceSupport
= {
103 // The incompatible PCI devices list template
105 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mIncompatiblePciDeviceList
[] = {
108 // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),
110 // ResType, GFlag , SFlag, Granularity, RangeMin,
111 // RangeMax, Offset, AddrLen
114 // Device Adaptec 9004
117 PCI_DEVICE_ID(0x9004, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
128 // Device Adaptec 9005
131 PCI_DEVICE_ID(0x9005, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
142 // Device QLogic 1007
145 PCI_DEVICE_ID(0x1077, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
156 // Device Agilent 103C
159 PCI_DEVICE_ID(0x103C, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
170 // Device Agilent 15BC
173 PCI_DEVICE_ID(0x15BC, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
, DEVICE_ID_NOCARE
),
184 // The end of the list
191 Entry point of the incompatible pci device support code. Setup an incompatible device list template
192 and install EFI Incompatible PCI Device Support protocol.
194 @param ImageHandle A handle for the image that is initializing this driver.
195 @param SystemTable A pointer to the EFI system table.
197 @retval EFI_SUCCESS Installed EFI Incompatible PCI Device Support Protocol successfully.
198 @retval others Failed to install protocol.
203 IncompatiblePciDeviceSupportEntryPoint (
204 IN EFI_HANDLE ImageHandle
,
205 IN EFI_SYSTEM_TABLE
*SystemTable
211 // Install EFI Incompatible PCI Device Support Protocol on a new handle
213 Status
= gBS
->InstallProtocolInterface (
214 &mIncompatiblePciDeviceSupportHandle
,
215 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
216 EFI_NATIVE_INTERFACE
,
217 &mIncompatiblePciDeviceSupport
219 ASSERT_EFI_ERROR (Status
);
225 Returns a list of ACPI resource descriptors that detail the special
226 resource configuration requirements for an incompatible PCI device.
228 @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.
229 @param VendorId A unique ID to identify the manufacturer of the PCI device.
230 @param DeviceId A unique ID to identify the particular PCI device.
231 @param RevisionId A PCI device-specific revision identifier.
232 @param SubsystemVendorId Specifies the subsystem vendor ID.
233 @param SubsystemDeviceId Specifies the subsystem device ID.
234 @param Configuration A list of ACPI resource descriptors returned that detail
235 the configuration requirement.
237 @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.
238 @retval EFI_INVALID_PARAMETER Configuration is NULL.
239 @retval EFI_OUT_OF_RESOURCES No memory available.
240 @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.
246 IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL
*This
,
250 IN UINTN SubsystemVendorId
,
251 IN UINTN SubsystemDeviceId
,
252 OUT VOID
**Configuration
258 EFI_PCI_DEVICE_HEADER_INFO
*Header
;
259 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AcpiPtr
;
260 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*OldAcpiPtr
;
261 EFI_PCI_RESOUCE_DESCRIPTOR
*Dsc
;
262 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
266 // Validate the parameters
268 if (Configuration
== NULL
) {
269 return EFI_INVALID_PARAMETER
;
272 // Initialize the return value to NULL
274 * (VOID
**) Configuration
= NULL
;
276 ListPtr
= mIncompatiblePciDeviceList
;
277 while (*ListPtr
!= LIST_END_TAG
) {
283 Header
= (EFI_PCI_DEVICE_HEADER_INFO
*) (ListPtr
+ 1);
284 ListPtr
= ListPtr
+ 1 + sizeof (EFI_PCI_DEVICE_HEADER_INFO
) / sizeof (UINT64
);
286 // See if the Header matches the parameters passed in
288 if (Header
->VendorId
!= DEVICE_ID_NOCARE
) {
289 if (Header
->VendorId
!= VendorId
) {
294 if (Header
->DeviceId
!= DEVICE_ID_NOCARE
) {
295 if (DeviceId
!= Header
->DeviceId
) {
300 if (Header
->RevisionId
!= DEVICE_ID_NOCARE
) {
301 if (RevisionId
!= Header
->RevisionId
) {
306 if (Header
->SubsystemVendorId
!= DEVICE_ID_NOCARE
) {
307 if (SubsystemVendorId
!= Header
->SubsystemVendorId
) {
312 if (Header
->SubsystemDeviceId
!= DEVICE_ID_NOCARE
) {
313 if (SubsystemDeviceId
!= Header
->SubsystemDeviceId
) {
318 // Matched an item, so construct the ACPI descriptor for the resource.
321 // Count the resource items so that to allocate space
323 for (Index
= 0, TempListPtr
= ListPtr
; *TempListPtr
== DEVICE_RES_TAG
; Index
++) {
324 TempListPtr
= TempListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
327 // If there is at least one type of resource request,
328 // allocate an acpi resource node
331 return EFI_UNSUPPORTED
;
334 AcpiPtr
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * Index
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
335 if (AcpiPtr
== NULL
) {
336 return EFI_OUT_OF_RESOURCES
;
339 OldAcpiPtr
= AcpiPtr
;
341 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure
342 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure
344 for (; *ListPtr
== DEVICE_RES_TAG
;) {
346 Dsc
= (EFI_PCI_RESOUCE_DESCRIPTOR
*) (ListPtr
+ 1);
348 AcpiPtr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
349 AcpiPtr
->Len
= (UINT16
) sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
350 AcpiPtr
->ResType
= (UINT8
) Dsc
->ResType
;
351 AcpiPtr
->GenFlag
= (UINT8
) Dsc
->GenFlag
;
352 AcpiPtr
->SpecificFlag
= (UINT8
) Dsc
->SpecificFlag
;
353 AcpiPtr
->AddrSpaceGranularity
= Dsc
->AddrSpaceGranularity
;;
354 AcpiPtr
->AddrRangeMin
= Dsc
->AddrRangeMin
;
355 AcpiPtr
->AddrRangeMax
= Dsc
->AddrRangeMax
;
356 AcpiPtr
->AddrTranslationOffset
= Dsc
->AddrTranslationOffset
;
357 AcpiPtr
->AddrLen
= Dsc
->AddrLen
;
359 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
365 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (AcpiPtr
);
366 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
367 PtrEnd
->Checksum
= 0;
369 *(VOID
**) Configuration
= OldAcpiPtr
;
375 // Adjust the pointer to the next PCI resource descriptor item
377 ListPtr
= ListPtr
+ 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR
)) / sizeof (UINT64
));
381 return EFI_UNSUPPORTED
;
385 return EFI_UNSUPPORTED
;