alder_lake_bios/Insyde/InsydeModulePkg/Universal/Recovery/PciResourceInitPei/AhciInit.c

183 lines
5.2 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2019 - 2020, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "AhciInit.h"
PEI_AHCI_CONTROLLER_PPI mAhciControllerPpi = {
GetAhciMemBase
};
EFI_PEI_PPI_DESCRIPTOR mAhciPpiList = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gPeiAhciControllerPpiGuid,
NULL
};
EFI_PEI_NOTIFY_DESCRIPTOR mAhciNotifyList = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiEndOfPeiSignalPpiGuid,
AhciEndOfPeiPpiNotifyCallback
};
/**
Get memory mapped base address of AHCI
@param [in] PeiServices Pointer to the PEI Services Table.
@param [in] This Pointer to PEI_AHCI_CONTROLLER_PPI
@param [in] AhciControllerId AHCI controller ID
@param [out] BaseAddress The result AHCI memory base address
@retval EFI_INVALID_PARAMETER Invalid AhciControllerId is given
@retval EFI_SUCCESS ACHI memory base address is successfully retrieved
**/
EFI_STATUS
GetAhciMemBase (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_AHCI_CONTROLLER_PPI *This,
IN UINT8 AhciControllerId,
OUT EFI_PHYSICAL_ADDRESS *BaseAddress
)
{
PEI_AHCI_DEVICE *PeiAhciDev;
PeiAhciDev = PEI_AHCI_DEVICE_FROM_THIS (This);
if (AhciControllerId >= PeiAhciDev->TotalControllers) {
return EFI_INVALID_PARAMETER;
}
*BaseAddress = PeiAhciDev->BaseAddress;
return EFI_SUCCESS;
}
/**
Register notify ppi to reset the AHCI.
@param[in] PeiServices Pointer to the PEI Services Table.
@param[in] NotifyDescriptor Pointer to the notify descriptor
@retval EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
AhciEndOfPeiPpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
PEI_AHCI_DEVICE *PeiAhciDev;
PeiAhciDev = PEI_AHCI_DEVICE_FROM_NOTIFY_DESC (NotifyDescriptor);
//
// Clear ABAR
//
PciWrite32 (PeiAhciDev->PciAddress | AHCI_ABAR_OFFSET, 0);
//
// Disable AHCI
//
PciAnd16 (
PeiAhciDev->PciAddress | PCI_COMMAND_OFFSET,
(UINT16)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE)
);
return EFI_SUCCESS;
}
/**
Init AHCI controller.
@param [in] PeiServices Pointer to the PEI Services Table.
@param [in] Bus PCI Bus number
@param [in] Device PCI Device number
@param [in] Function PCI Function number
@param [in] BaseAddress MMIO base address
@retval EFI_SUCCESS Operation completed successfully.
@retval Others Operation was unsuccessful.
**/
EFI_STATUS
InitAhciController (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN PCI_RESOURCE_DATA *PciRes
)
{
EFI_STATUS Status;
PEI_AHCI_DEVICE *PeiAhciDev;
UINT8 SubClass;
UINT8 BaseClass;
UINT32 Bus;
UINT32 Device;
UINT32 Function;
Bus = PciRes->Bus;
Device = PciRes->Device;
Function = PciRes->Function;
SubClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_CLASSCODE_OFFSET + 1));
BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_CLASSCODE_OFFSET + 2));
if ((SubClass != PCI_CLASS_MASS_STORAGE_SATADPA) || (BaseClass != PCI_CLASS_MASS_STORAGE)) {
return EFI_UNSUPPORTED;
}
//
// Program BARs and enable AHCI controller
//
Status = ProgramBar (PciRes);
if (EFI_ERROR (Status)) {
return Status;
}
PeiAhciDev = (PEI_AHCI_DEVICE *)AllocateZeroPool (sizeof (PEI_AHCI_DEVICE));
ASSERT (PeiAhciDev != NULL);
if (PeiAhciDev == NULL) {
return EFI_OUT_OF_RESOURCES;
}
PeiAhciDev->Signature = PEI_AHCI_SIGNATURE;
PeiAhciDev->ControllerPpi = mAhciControllerPpi;
PeiAhciDev->PpiList = mAhciPpiList;
PeiAhciDev->PpiList.Ppi = &PeiAhciDev->ControllerPpi;
PeiAhciDev->NotifyList = mAhciNotifyList;
PeiAhciDev->TotalControllers = 1;
PeiAhciDev->BaseAddress = PciRes->PciBar[5]; // ABAR
PeiAhciDev->PciAddress = PCI_LIB_ADDRESS (Bus, Device, Function, 0);
//
// Install notification in order to reset the AHCI
//
Status = PeiServicesNotifyPpi (&PeiAhciDev->NotifyList);
if (EFI_ERROR(Status)) {
return Status;
}
//
// Install AHCI Controller PPI
//
Status = PeiServicesInstallPpi (&PeiAhciDev->PpiList);
DEBUG ((DEBUG_ERROR | DEBUG_INFO, "InstallPpi :%r\n",Status));
if (EFI_ERROR(Status)) {
return Status;
}
DEBUG ((DEBUG_ERROR | DEBUG_INFO, "End InitAhciController !\n"));
return EFI_SUCCESS;
}