123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- /** @file
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <PiDxe.h>
- #include <Protocol/IioUds.h>
- #include <PciPlatform.h>
- #include <PciPlatformHooks.h>
- #include <PciSupportLib.h>
- #include <IoApic.h>
- #include <Library/S3BootScriptLib.h>
- #include <Protocol/IioSystem.h>
- EFI_IIO_UDS_PROTOCOL *mIioUds = NULL;
- EFI_IIO_SYSTEM_PROTOCOL *IioSystemProtocol = NULL;
- IIO_GLOBALS *IioGlobalData = NULL;
- VOID
- ChipsetCallback (
- IN EFI_HANDLE RootBridgeHandle,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
- IN EFI_PCI_ENUMERATION_PHASE Phase,
- EFI_PCI_CALLBACK_CONTEXT *Context
- )
- {
- EFI_LIST_ENTRY *NodeEntry;
- PCI_CALLBACK_DATA *PciCallbackData;
- //
- // Check if the node has been added
- //
- // DEBUG ((DEBUG_ERROR, "PCI Callback (%d,%d,%d)\n",PciAddress.Bus, PciAddress.Device, PciAddress.Function ));
- //
- Context->PciRootBridgeIo = mPciPrivateData.PciRootBridgeIo;
- NodeEntry = GetFirstNode (&mPciPrivateData.PciCallbackList);
- while (!IsNull (&mPciPrivateData.PciCallbackList, NodeEntry)) {
- PciCallbackData = PCI_CALLBACK_DATA_FROM_LINK (NodeEntry);
- if (PciCallbackData->Phase & Phase) {
- (PciCallbackData->Function) (RootBridgeHandle, PciAddress, Phase, Context);
- }
- NodeEntry = GetNextNode (&mPciPrivateData.PciCallbackList, NodeEntry);
- }
- }
- /**
- GC_TODO: add routine description
- @param StartBus - GC_TODO: add arg description
- @retval EFI_SUCCESS - GC_TODO: add retval description
- **/
- EFI_STATUS
- PciTreeTraverse (
- IN UINT8 StartBus
- )
- {
- UINT64 PciAddress;
- UINT8 Device;
- UINT8 Func;
- UINT8 SecondaryBus;
- BOOLEAN MultiFunc;
- for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
- MultiFunc = FALSE;
- for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
- if (IsPciDevicePresent (
- mPciPrivateData.PciRootBridgeIo,
- &mPciPrivateData.Context.PciHeader,
- StartBus,
- Device,
- Func
- )) {
- if ((Func == 0) && IS_PCI_MULTI_FUNC(&(mPciPrivateData.Context.PciHeader))) {
- MultiFunc = TRUE;
- }
- PciAddress = EFI_PCI_ADDRESS (StartBus, Device, Func, 0);
- ChipsetCallback (
- mPciPrivateData.RootBridgeHandle,
- *(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &PciAddress,
- mPciPrivateData.PciEnumerationPhase,
- &(mPciPrivateData.Context)
- );
- if (IS_PCI_BRIDGE (&(mPciPrivateData.Context.PciHeader))) {
- PciAddress = EFI_PCI_ADDRESS (StartBus, Device, Func, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
- mPciPrivateData.PciRootBridgeIo->Pci.Read (
- mPciPrivateData.PciRootBridgeIo,
- EfiPciWidthUint8,
- *(UINT64 *) &PciAddress,
- 1,
- &SecondaryBus
- );
- if ((SecondaryBus > 0) && (SecondaryBus < 0xFF)) {
- PciTreeTraverse (SecondaryBus);
- }
- }
- }
- if (MultiFunc == FALSE) {
- //
- // Skip sub functions, this is not a multi function device
- //
- Func = PCI_MAX_FUNC;
- }
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Program Io Apic Id
- @param IoApicAddress and IoApicId
- @retval None
- **/
- VOID
- ProgramIoApicId (
- IN UINT32 IoApicAddress,
- IN UINT8 IoApicId
- )
- {
- UINT32 Data;
- mPciPrivateData.CpuIo->Mem.Read (
- mPciPrivateData.CpuIo,
- EfiCpuIoWidthUint32,
- IoApicAddress + EFI_IO_APIC_INDEX_OFFSET,
- 1,
- &Data
- );
- //
- // IOAPIC is not there
- //
- if (Data == (UINT32) -1) {
- return ;
- }
- //
- // Set up IO APIC ID and enable FSB delivery
- // Use CPU IO protocol since the IO APIC ranges
- // are not included in PCI apertures
- //
- Data = EFI_IO_APIC_ID_REGISTER;
- mPciPrivateData.CpuIo->Mem.Write (
- mPciPrivateData.CpuIo,
- EfiCpuIoWidthUint32,
- IoApicAddress + EFI_IO_APIC_INDEX_OFFSET,
- 1,
- &Data
- );
- Data = IoApicId << EFI_IO_APIC_ID_BITSHIFT;
- mPciPrivateData.CpuIo->Mem.Write (
- mPciPrivateData.CpuIo,
- EfiCpuIoWidthUint32,
- IoApicAddress + EFI_IO_APIC_DATA_OFFSET,
- 1,
- &Data
- );
- Data = EFI_IO_APIC_BOOT_CONFIG_REGISTER;
- mPciPrivateData.CpuIo->Mem.Write (
- mPciPrivateData.CpuIo,
- EfiCpuIoWidthUint32,
- IoApicAddress + EFI_IO_APIC_INDEX_OFFSET,
- 1,
- &Data
- );
- Data = EFI_IO_APIC_FSB_INT_DELIVERY;
- mPciPrivateData.CpuIo->Mem.Write (
- mPciPrivateData.CpuIo,
- EfiCpuIoWidthUint32,
- IoApicAddress + EFI_IO_APIC_DATA_OFFSET,
- 1,
- &Data
- );
- }
- #ifdef EFI_PCI_IOV_SUPPORT
- /**
- Initialize the Pci Iov Platform Data.
- @param ImageHandle - Handle to the image.
- @param SystemTable - Handle to System Table.
- @retval EFI_STATUS - Status of the function calling.
- **/
- EFI_STATUS
- EFIAPI
- PciPlatformInitPciIovData (
- VOID
- )
- {
- EFI_STATUS Status;
- EFI_PCI_IOV_PLATFORM_POLICY PciIovPolicy;
- UINT32 SystemPageSize;
- EFI_PCI_IOV_PLATFORM_PROTOCOL *gPciIovPlatformProtocol;
- Status = gBS->LocateProtocol (
- &gEfiPciIovPlatformProtocolGuid,
- NULL,
- &gPciIovPlatformProtocol
- );
- if (!EFI_ERROR (Status)) {
- Status = gPciIovPlatformProtocol->GetSystemLowestPageSize (
- gPciIovPlatformProtocol,
- &SystemPageSize
- );
- if (!EFI_ERROR (Status)) {
- Status = PcdSet32S (PcdSrIovSystemPageSize, (1 << SystemPageSize));
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR(Status)) return Status;
- } else {
- return Status;
- }
- Status = gPciIovPlatformProtocol->GetPlatformPolicy (
- gPciIovPlatformProtocol,
- &PciIovPolicy
- );
- if (!EFI_ERROR (Status)) {
- if (PciIovPolicy & EFI_PCI_IOV_POLICY_ARI) {
- Status = PcdSetBoolS (PcdAriSupport, TRUE);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR(Status)) return Status;
- } else {
- Status = PcdSetBoolS (PcdAriSupport, FALSE);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR(Status)) return Status;
- }
- if (PciIovPolicy & EFI_PCI_IOV_POLICY_SRIOV) {
- Status = PcdSetBoolS (PcdSrIovSupport, TRUE);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR(Status)) return Status;
- } else {
- Status = PcdSetBoolS (PcdSrIovSupport, FALSE);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR(Status)) return Status;
- }
- if (PciIovPolicy & EFI_PCI_IOV_POLICY_MRIOV) {
- Status = PcdSetBoolS (PcdMrIovSupport, TRUE);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR(Status)) return Status;
- } else {
- Status = PcdSetBoolS (PcdMrIovSupport, FALSE);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR(Status)) return Status;
- }
- } else {
- return Status;
- }
- DEBUG ((
- EFI_D_INFO,
- " Initialized SR-IOV Platform Data: PCIIovPolicy = 0x%x; SystemPageSize = 0x%x;\n",
- PciIovPolicy, SystemPageSize
- ));
- } else {
- DEBUG ((
- EFI_D_INFO,
- " Using default values for SystemPageSize;\n"
- ));
- }
- return Status;
- }
- #endif
- /**
- Platform Pci Express init.
- @param HostBridgeInstance - Pointer to Host Bridge private data
- does not support 64 bit memory addresses.
- @retval EFI_SUCCESS - Success.
-
- **/
- EFI_STATUS
- PciPlatformEarlyInit (
- VOID
- )
- {
- EFI_STATUS Status;
- //
- // Locate the IIO Protocol Interface
- //
- Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid,NULL,&mIioUds);
- ASSERT_EFI_ERROR (Status);
- Status = gBS->LocateProtocol (&gEfiIioSystemProtocolGuid, NULL, &IioSystemProtocol);
- ASSERT_EFI_ERROR (Status);
- IioGlobalData = IioSystemProtocol->IioGlobalData;
- #ifdef EFI_PCI_IOV_SUPPORT
- Status = PciPlatformInitPciIovData(); // Update IOV PCD values
- #endif
- return EFI_SUCCESS;
- }
- /**
-
- Init pci device registers after the device resources have been allocated, so
- that devices behind a bus could be accessed.
-
- @param HostBridgeInstance - PCI_HOST_BRIDGE_INSTANCE.
- @retval EFI_SUCCESS - Function has completed successfully.
- **/
- EFI_STATUS
- PciPlatformPostInit (
- VOID
- )
- {
- //
- // Program all the IOAPIC in system
- //
- UINT8 Socket, Stack, IoApicId;
- UINT8 Step;
- UINT8 MaxSocket;
- #if MAX_SOCKET <= 4
- Step = 6;
- MaxSocket = 4;
- #else
- Step = 4;
- MaxSocket = 8;
- #endif
- Stack = 0;
- IoApicId = 0;
- ProgramIoApicId (mIioUds->IioUdsPtr->PlatformData.IIO_resource[0].StackRes[0].IoApicBase, PcdGet8(PcdIoApicId));
- for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
- if (!(mIioUds->IioUdsPtr->SystemStatus.socketPresentBitMap & (1 << Socket)))
- continue;
- for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
- if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack)))
- continue;
- if ((Socket < MaxSocket) && (Stack < Step)) {
- IoApicId = PcdGet8(PcdPcIoApicIdBase) + Step * Socket + Stack;
- }
- if ((Socket == 0) && (Stack == 0)) {
- ProgramIoApicId ((mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].IoApicBase + 0x1000), IoApicId);
- } else {
- ProgramIoApicId (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].IoApicBase, IoApicId);
- }
- }
- }
- return EFI_SUCCESS;
- }
- /**
- The PlatformPrepController() function can be used to notify the platform driver so that
- it can perform platform-specific actions. No specific actions are required.
- Several notification points are defined at this time. More synchronization points may be
- added as required in the future. The PCI bus driver calls the platform driver twice for
- every PCI controller-once before the PCI Host Bridge Resource Allocation Protocol driver
- is notified, and once after the PCI Host Bridge Resource Allocation Protocol driver has
- been notified.
- This member function may not perform any error checking on the input parameters. It also
- does not return any error codes. If this member function detects any error condition, it
- needs to handle those errors on its own because there is no way to surface any errors to
- the caller.
-
- @param This - Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
- @param HostBridge - The associated PCI host bridge handle.
- @param RootBridge - The associated PCI root bridge handle.
- @param PciAddress - The address of the PCI device on the PCI bus.
- @param Phase - The phase of the PCI controller enumeration.
- @param ChipsetPhase - Defines the execution phase of the PCI chipset driver.
-
- @retval EFI_SUCCESS - The function completed successfully.
- @retval EFI_UNSUPPORTED - Not supported.
-
- **/
- EFI_STATUS
- EFIAPI
- PlatformPrepController (
- IN EFI_PCI_PLATFORM_PROTOCOL *This,
- IN EFI_HANDLE HostBridge,
- IN EFI_HANDLE RootBridge,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
- IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase,
- IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
- )
- {
- if (mPciPrivateData.RootBridgeHandle == NULL) {
- mPciPrivateData.RootBridgeHandle = RootBridge;
- }
- return EFI_SUCCESS;
- }
- /**
- Perform initialization by the phase indicated.
- @param This - Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
- @param HostBridge - The associated PCI host bridge handle.
- @param Phase - The phase of the PCI controller enumeration.
- @param ChipsetPhase - Defines the execution phase of the PCI chipset driver.
- @retval EFI_SUCCESS - Must return with success.
- **/
- EFI_STATUS
- EFIAPI
- PhaseNotify (
- IN EFI_PCI_PLATFORM_PROTOCOL *This,
- IN EFI_HANDLE HostBridge,
- IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase,
- IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
- )
- {
- EFI_STATUS Status;
- UINT8 i;
- UINT8 Stack;
- if (ChipsetPhase == ChipsetEntry) {
- return EFI_SUCCESS;
- }
- //
- // If for multiple host bridges, need special consideration
- //
- switch (Phase) {
- case EfiPciHostBridgeBeginEnumeration:
- //
- // Pre-initialization before PCI bus enumeration
- // No bus number and no PCI resource
- //
- Status = gBS->LocateProtocol (
- &gEfiPciRootBridgeIoProtocolGuid,
- NULL,
- &(mPciPrivateData.PciRootBridgeIo)
- );
- ASSERT_EFI_ERROR (Status);
- Status = gBS->LocateProtocol (
- &gEfiCpuIo2ProtocolGuid,
- NULL,
- &(mPciPrivateData.CpuIo)
- );
- ASSERT_EFI_ERROR (Status);
- mPciPrivateData.Context.CpuIo = mPciPrivateData.CpuIo;
- DEBUG ((DEBUG_ERROR, "PCI Platform Pre-Initialization (Before bus scanning)\n"));
- PciPlatformEarlyInit ();
- break;
- case EfiPciHostBridgeEndBusAllocation:
- //
- // There are two rounds PCI bus scanning
- // First round will initilize the PCI hotplug device
- // Second round will be the final one
- //
- if (mPciPrivateData.BusAssignedTime == 0) {
- mPciPrivateData.PciEnumerationPhase = EfiPciEnumerationDeviceScanning;
- for (i = 0 ; i < MaxIIO ; i++) {
- if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].Valid) {
- for(Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
- PciTreeTraverse (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[i].StackBus[Stack]);
- }
- }
- }
- mPciPrivateData.BusAssignedTime++;
- DEBUG ((DEBUG_ERROR, "PCI Platform bus assigned\n"));
- }
- break;
- case EfiPciHostBridgeBeginResourceAllocation:
- //
- // PCI bus number has been assigned, but resource is still empty
- //
- DEBUG ((DEBUG_ERROR, "PCI Platform Mid-Initialization (After bus number assignment)\n"));
- mPciPrivateData.PciEnumerationPhase = EfiPciEnumerationBusNumberAssigned;
- for (i = 0 ; i < MaxIIO ; i++) {
- if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].Valid) {
- for(Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
- PciTreeTraverse (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[i].StackBus[Stack]);
- }
- }
- }
- //PciPlatformMidInit ();
- break;
- case EfiPciHostBridgeEndResourceAllocation:
- //
- // Resource enumeration is done.
- // Both bus number and resource have been assigned
- // Do any post initialization.
- //
- DEBUG ((DEBUG_ERROR, "PCI Platform Post-Initialization (After resource alloction)\n"));
- mPciPrivateData.PciEnumerationPhase = EfiPciEnumerationResourceAssigned;
- for (i = 0 ; i < MaxIIO ; i++) {
- if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].Valid) {
- for(Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
- PciTreeTraverse (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[i].StackBus[Stack]);
- }
- }
- }
- PciPlatformPostInit ();
- break;
- default:
- return EFI_UNSUPPORTED;
- }
- return EFI_SUCCESS;
- }
|