audk/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.c

200 lines
6.0 KiB
C

/** @file
* Pci Host Bridge support for the Xpress-RICH3 PCIe Root Complex
*
* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include "PciHostBridge.h"
#include <Guid/EventGroup.h>
/**
* PCI Root Bridge Description
*/
typedef struct {
UINT32 AcpiUid;
UINT64 MemAllocAttributes;
} PCI_ROOT_BRIDGE_DESC;
PCI_ROOT_BRIDGE_DESC PciRbDescriptions = {
0, // AcpiUid
PCI_MEMORY_ALLOCATION_ATTRIBUTES // MemAllocAttributes
};
/**
* Template for PCI Host Bridge Instance
**/
STATIC CONST PCI_HOST_BRIDGE_INSTANCE
gPciHostBridgeInstanceTemplate = {
PCI_HOST_BRIDGE_SIGNATURE, //Signature
NULL, // Handle
NULL, // ImageHandle
NULL, // RootBridge
TRUE, // CanRestarted
NULL, // CpuIo
NULL, // Metronome
{ // ResAlloc
PciHbRaNotifyPhase, // ResAlloc.NotifyPhase
PciHbRaGetNextRootBridge, // ResAlloc.GetNextRootBridge
PciHbRaGetAllocAttributes, // ResAlloc.GetAllocAttributes
PciHbRaStartBusEnumeration, // ResAlloc.StartBusEnumeration
PciHbRaSetBusNumbers, // ResAlloc.SetBusNumbers
PciHbRaSubmitResources, // ResAlloc.SubmitResources
PciHbRaGetProposedResources, // ResAlloc.GetProposedResources
PciHbRaPreprocessController // ResAlloc.PreprocessController
}
};
PCI_HOST_BRIDGE_INSTANCE* gpPciHostBridgeInstance;
EFI_STATUS
HostBridgeConstructor (
IN OUT PCI_HOST_BRIDGE_INSTANCE** Instance,
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
PCI_HOST_BRIDGE_INSTANCE* HostBridge;
PCI_TRACE ("HostBridgeConstructor()");
if (Instance == NULL) {
return EFI_INVALID_PARAMETER;
}
HostBridge = AllocateCopyPool (sizeof (PCI_HOST_BRIDGE_INSTANCE), &gPciHostBridgeInstanceTemplate);
if (HostBridge == NULL) {
PCI_TRACE ("HostBridgeConstructor(): FAIL to allocate resources");
return EFI_OUT_OF_RESOURCES;
}
// It will also create a device handle for the PCI Host Bridge (as HostBridge->Handle == NULL)
Status = gBS->InstallMultipleProtocolInterfaces (
&HostBridge->Handle,
&gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
NULL
);
if (EFI_ERROR (Status)) {
PCI_TRACE ("HostBridgeConstructor(): FAIL to install resource allocator");
FreePool (HostBridge);
return EFI_DEVICE_ERROR;
} else {
PCI_TRACE ("HostBridgeConstructor(): SUCCEED to install resource allocator");
}
Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)(&(HostBridge->CpuIo)));
ASSERT_EFI_ERROR (Status);
Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)(&(HostBridge->Metronome)));
ASSERT_EFI_ERROR (Status);
HostBridge->ImageHandle = ImageHandle;
*Instance = HostBridge;
return EFI_SUCCESS;
}
EFI_STATUS
HostBridgeDestructor (
IN PCI_HOST_BRIDGE_INSTANCE* HostBridge
)
{
EFI_STATUS Status;
Status = gBS->UninstallMultipleProtocolInterfaces (
HostBridge->Handle,
&gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
NULL
);
if (HostBridge->RootBridge) {
PciRbDestructor (HostBridge->RootBridge);
}
FreePool (HostBridge);
return Status;
}
/**
Entry point of this driver
@param ImageHandle Handle of driver image
@param SystemTable Point to EFI_SYSTEM_TABLE
@retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
@retval EFI_DEVICE_ERROR Can not install the protocol instance
@retval EFI_SUCCESS Success to initialize the Pci host bridge.
**/
EFI_STATUS
EFIAPI
PciHostBridgeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
PCI_TRACE ("PciHostBridgeEntryPoint()");
// Creation of the PCI Host Bridge Instance
Status = HostBridgeConstructor (&gpPciHostBridgeInstance, ImageHandle);
if (EFI_ERROR (Status)) {
PCI_TRACE ("PciHostBridgeEntryPoint(): ERROR: Fail to construct PCI Host Bridge.");
return Status;
}
// Creation of the PCIe Root Bridge
Status = PciRbConstructor (gpPciHostBridgeInstance, PciRbDescriptions.AcpiUid, PciRbDescriptions.MemAllocAttributes);
if (EFI_ERROR (Status)) {
PCI_TRACE ("PciHostBridgeEntryPoint(): ERROR: Fail to construct PCI Root Bridge.");
return Status;
}
ASSERT (gpPciHostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
// PCI 32bit Memory Space
Status = gDS->AddMemorySpace (
EfiGcdMemoryTypeMemoryMappedIo,
PCI_MEM32_BASE,
PCI_MEM32_SIZE,
0
);
// PCI 64bit Memory Space
Status = gDS->AddMemorySpace (
EfiGcdMemoryTypeMemoryMappedIo,
PCI_MEM64_BASE,
PCI_MEM64_SIZE,
0
);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PciHostBridgeUnload (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
// Free Reserved memory space in GCD
gDS->RemoveMemorySpace (PCI_MEM32_BASE, PCI_MEM32_SIZE);
gDS->RemoveMemorySpace (PCI_MEM64_BASE, PCI_MEM64_SIZE);
// Free the allocated memory
Status = HostBridgeDestructor (gpPciHostBridgeInstance);
ASSERT_EFI_ERROR (Status);
return Status;
}