diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/PCI/PciHostBridge.c | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/PCI/PciHostBridge.c')
-rw-r--r-- | Core/EM/PCI/PciHostBridge.c | 3814 |
1 files changed, 3814 insertions, 0 deletions
diff --git a/Core/EM/PCI/PciHostBridge.c b/Core/EM/PCI/PciHostBridge.c new file mode 100644 index 0000000..873101a --- /dev/null +++ b/Core/EM/PCI/PciHostBridge.c @@ -0,0 +1,3814 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/Modules/PciBus/PciHostBridge.c 48 9/10/12 12:49p Yakovlevs $ +// +// $Revision: 48 $ +// +// $Date: 9/10/12 12:49p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Modules/PciBus/PciHostBridge.c $ +// +// 48 9/10/12 12:49p Yakovlevs +// Minor changes fix for multi host system +// +// 47 7/17/12 1:48p Yakovlevs +// +// 45 7/16/12 3:10p Yakovlevs +// [TAG] EIP90378 +// [Category] Improvement +// [Description] Pci Root bridge driver should be able to access MMIO +// above 4G +// [Files] PciHostBridge.c +// +// 44 6/26/12 6:24p Yakovlevs +// [TAG] EIP90378 +// [Category] Improvement +// [Description] Pci Root bridge driver should be able to access MMIO +// above 4G +// [Files] PciHostBridge.c +// +// 43 5/22/12 4:50p Yakovlevs +// Removing wrong comment +// +// 42 5/01/12 5:05p Yakovlevs +// [TAG] EIP84986 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Yellow mark issue in windows device manager on +// PCIe slots if only 2 CPU for potter city platform. +// [RootCause] For multy root system where root socets partialy +// populated SDL data interfered with +// Actual Hardware configuration. +// [Solution] Allow control flow keep going when certain +// ERROR_STATUS received. +// [Files] PciBus.c; PciHostBridge.c +// +// 41 2/27/12 4:47p Yakovlevs +// +// 40 11/23/11 11:08a Yakovlevs +// [TAG] EIP76109 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] VIA VX900 / VX11 CopyMem issue +// [RootCause] When Src and Dst buffers overlaps +// size of copy operation was determined incorrectly. +// [Solution] Added additional cases with negative increments +// [Files] PciHostBridge.c +// +// 39 11/10/11 12:26p Yakovlevs +// [TAG] EIP72122 +// [Category] Improvement +// [Description] If system uses UEFI GOP driver, then BIOS does not +// report legacy VGA resources to ACPI. +// +// [Files] PciHostBridge.c +// +// 38 8/30/11 2:27p Yakovlevs +// [TAG] EIP68120 +// [Category] Bug Fix +// [Symptom] When new PCIe card be plugged, It hangs at 0x94 before +// adjusting new memory ceiling to nvram with CORE4651. +// [RootCause] AdjustMmioOverlap() was not called if builtin allocation +// function returned EFI_ERROR. +// [Solution] Reorganize code to call this function before returning +// ERROR Status. +// [Files] PciHostBridge.c +// +// 37 8/02/11 4:13p Yakovlevs +// [TAG] EIP66216 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Hotplug resource padding not working for ROOT bridges other +// than 0 +// [RootCause] Hot plug slots was incorrectly associated alvays withthe +// RootBridge #0 +// [Solution] Changed algorithm to beter distinguish between Root +// Bridges. Added debug messagers to monitor HPC_LOCATION_DATA. +// [Files] PciBus.c; PciHostBridge.c. +// +// 36 7/08/11 5:00p Yakovlevs +// [TAG] EIP64414 +// [Category] Improvement +// [Description] During PCIOUTOF RESOURCE Condition,resource freeing is +// not done +// [Files] PciHostBridge.c +// +// 35 6/28/11 5:29p Yakovlevs +// [TAG] EIP 60123 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Resource padding is not functional for PCIe hot-plug. +// [RootCause] In hot plug function was missed changes in BusXlat +// Structure. +// [Solution] Xlat header gets incremented based on AMI_BOARD_INFO +// driver wersion. +// [Files] PciHostBridge.c +// +// 34 5/04/11 6:15p Yakovlevs +// Fixed potential issue with EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE +// attribute some drivers may set. +// +// 33 4/05/11 11:40a Yakovlevs +// [TAG] EIP 38174 +// [Category] New Feature +// [Description] Generic support to handle PCI OUT OF RESOURDCES added. +// [Files] PciBus.c; PciHostBridge.c; +// +// 32 1/20/11 3:07p Yakovlevs +// [TAG] EIP45278 +// [Category] Improvement +// [Description] Added PCI_MMIO_RES_TOP_ALLIGN token to control Resource +// allocation algorithm selection. +// [Files] PciBus.c; PciHostBridge.c; PciBus.sdl. +// +// 31 1/13/11 1:30p Yakovlevs +// +// 30 1/13/11 1:28p Yakovlevs +// [TAG] EIP45278 +// [Category] Improvement +// [Description] Changed default resource allocation algorithm to work +// more efficiently. +// [Files] PciBus.c; PciHostBridge.c +// +// 28 8/23/10 12:29p Yakovlevs +// Fixed issue with incorrect settings COMPATIBILITY ATTRIBUTES was +// missing Legacy VGA_ATTRIBUTES. +// +// 27 8/16/10 1:07p Yakovlevs +// Updated ClaimMmioResources to use MMIO resources as-is if AllocType is +// set to EfiGcdAllocateAddress. For this chipset, each root bridge is +// programmed with base and limit values for 32bit and 64bit MMIO. The +// root bridge will only decode addresses within these ranges. For this +// reason, the Base and Limit values passed to the PCI Bus driver should +// be used as-is and not modified. +// +// 26 3/01/10 6:18p Yakovlevs +// Generic Multi-ROOT Support Added. +// +// 25 9/22/09 6:10p Yakovlevs +// 3. Generic support for multiple root bridges resources reporting to +// ACPI DSDT Root Bridge Object (EIP 23548 Support MMIO allocation above +// 4GB, if devices are capable) +// +// 24 8/21/09 4:25p Yakovlevs +// Added Print out Message in DEBUG_MODE with PCI BUS Driver Version. +// Added Initialization of ImageHandle field in Host Bridge and Root +// Bridge Structures. New PciHostBridge.h required. +// +// 23 4/28/09 5:50p Yakovlevs +// Ami Board Info Protocol moved into separate Core\AmiBoardInfo +// subcomponent. +// +// 22 3/27/09 11:48a Yakovlevs +// +// 21 3/23/09 2:27p Yakovlevs +// ADDED support for PCI Root HPC INit Protocol generation based on AMI +// SDL output. +// +// 20 1/30/09 1:01p Yakovlevs +// Changed gPciHost to gPciRbHost to avoid name collision gPCiHost +// variable name been differently used in PciBus.c +// +// 19 11/21/08 7:01p Yakovlevs +// +// 18 11/14/08 3:34p Yakovlevs +// Removed EFI_DEADLOOP() used for debug +// +// 17 11/14/08 1:28p Yakovlevs +// Implemented AMI Board Info Protocol which has *.inc OUTPUTs generated +// by AMISDL tool. To keep it in one place and Make PciBus Driver use it. +// +// 16 11/03/08 2:35p Yakovlevs +// +// 15 11/03/08 2:33p Yakovlevs +// Fixed EIP 17068: AdjustMmioOverlap() has to be called each boot. +// +// 14 10/01/08 7:12p Yakovlevs +// Updated AMI FUNC HEADER information +// +// 13 9/24/08 6:08p Yakovlevs +// New features added. Multy host support using VeB wizard. No initial +// porting required. +// +// 12 4/29/08 6:56p Yakovlevs +// Added mechanism to suppress PCI BUs driver debug messages(Latest +// PciBus.sdl and PciBus.h required). +// +// 11 2/19/08 3:38p Felixp +// +// 10 2/13/08 1:02p Yakovlevs +// Fixed issue with incorrect usage of GCD AllocateXX services. +// +// 9 10/23/07 5:30p Felixp +// VC8 warnings fixed +// +// 8 8/07/07 2:45p Felixp +// Additional Status Codes added +// +// 7 4/19/07 12:59p Felixp +// Added Chipset specific call to set RB Attributes +// +// 5 4/17/07 11:55a Yakovlevs +// +// 4 4/17/07 11:19a Yakovlevs +// +// 3 4/17/07 11:18a Yakovlevs +// Added Chipset specific call to set RB Attributes +// +// 2 4/13/07 6:23p Yakovlevs +// make use of LibGetDxeSvcTbl() instead of manualy getting the DXE Svc +// Tbl pointer. +// +// 1 3/12/07 12:02p Yakovlevs +// +// 9 12/28/06 7:20p Yakovlevs +// +// 8 12/19/06 12:07p Yakovlevs +// PciRb->Map; Unmap implementation fixes +// +// 7 10/24/06 12:18p Yakovlevs +// Removed EFI_MEMORY_RUNTIME attribute from PCI BUS resource request. +// +// 6 9/20/06 4:47p Felixp +// x64 warnings fixed +// +// 5 6/01/06 12:17p Yakovlevs +// Handling of memceil logic added. +// +// 4 5/23/06 12:59a Felixp +// Bug fix in HbResAllocStartBusEnumeration - invalid error condition +// check +// +// 3 5/19/06 10:51p Felixp +// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH +// macros to remove direct access to the Length field +// +// 2 4/07/06 2:33p Felixp +// Bug fix in resource allocation (AllocateResources): Attributes for +// Prefetchable memory changed from WB to WT +// +// 1 4/03/06 5:32p Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: PciHostBridge.c +// +// Description: AMI's Native Root Bridge Protocol Implementation +// +//<AMI_FHDR_END> +//********************************************************************** + +#include <Token.h> +#include <AmiDxeLib.h> +#include <PciHostBridge.h> +#include <Protocol\DevicePath.h> +#include <AmiCspLib.h> +#include "PciPort.h" +#include "PciSetup.h" + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: gAmiBoardProtocol +// +// Description: Ami Board Info Protocol Instance. +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> +AMI_BOARD_INFO_PROTOCOL *gAmiBoardInfoProtocol=NULL; + + + +//********************************************************************** +//Global Vars and Constants been used +//********************************************************************** + +//GUIDs +EFI_GUID gHbResAllocProtocolGuid=EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GUID; +EFI_GUID gRbIoProtocolGuid=EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; +EFI_GUID gDevPathProtocolGuid=EFI_DEVICE_PATH_PROTOCOL_GUID; +EFI_GUID gDeviceIoProtocolGuid=DEVICE_IO_PROTOCOL; +EFI_GUID gAmiBoardInfoGuid=AMI_BOARD_INFO_PROTOCOL_GUID; + +#if AMI_HOTPLUG_INIT_SUPPORT == 1 +EFI_GUID gHotPlugInitProtocolGuid=EFI_PCI_HOT_PLUG_INIT_PROTOCOL_GUID; +#endif + + + +//********************************************************************** +//Variables + +T_ITEM_LIST gRootBusDb={0,0,NULL}; + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: gPciHost +// +// Description: Array of PCI Host Bridge Data Sructures. +// Initial data point for PCI Subsystem. +// +// Notes: See PCI_HOST_BRG_DATA. Number of elements in gPciHost[] array +// defined by NB_NUMBER_OF_HOST_BRG in NB.sdl +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> +PCI_HOST_BRG_DATA gPciRbHost[NB_NUMBER_OF_HOST_BRG]; + +//TODO//TODO //TODO //TODO //TODO +//Change this to reference VeB output EIP 24469 +//TEMP Hardcoding of ASL RB Device Object NAME +#if AMI_BOARD_VER_COMBINED < 100 +CHAR8 *RbAslName[]={"PCI0","PCFF"}; +#endif + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: *gPciSetupData; PciSetupDataBuffer +// +// Description: Global Setup Variable to get the setup settings pointer. +// +// Notes: PCI_SETUP_DATA +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> +PCI_SETUP_DATA gRbSetupData; + +UINT64 TmpBot[raMaxRes]={0,0,0,0}; +UINT64 TmpTop[raMaxRes]={0,0,0,0}; + +//********************************************************************** +//Function Prototypes needed forward declaration +//********************************************************************** +EFI_STATUS ConvertMemoryMap(EFI_HANDLE ImgHandle, EFI_HANDLE CntrHandle OPTIONAL); +EFI_STATUS CreateRootBusData(); +EFI_STATUS HpcInitProtocol(PCI_HOST_BRG_DATA *HostBrg); +BOOLEAN IsPowerOfTwo(UINT64 Value); +VOID RbReadyToBoot(IN EFI_EVENT Event, IN VOID *Context); + + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//PCI Root Bridge Driver Entry Point +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InitializePCIHostBridge() +// +// Description: This function is the entry point for PCI Root Bridge Driver. +// Since PCI Root Bridge Driver follows EFI 1.1 driver model in it's entry +// point it will initialize some global data and install +// EFI_DRIVER_BINDING_PROTOCOL. +// +// Input: +// EFI_HANDLE ImageHandle Image handle. +// EFI_SYSTEM_TABLE *SystemTable Pointer to the EFI system table. +// +// Output: EFI_STATUS +// EFI_SUCCESS When everything is going on fine! +// EFI_NOT_FOUND When something required is not found! +// EFI_DEVICE_ERROR When the device is not responding! +// +// Notes: +// Entry Points are used to locate or install protocol interfaces and +// notification events. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS InitializePCIHostBridge(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS Status=EFI_SUCCESS; + UINTN i,j,n; + PCI_HOST_BRG_DATA *hb; + PCI_ROOT_BRG_DATA *rb; + EFI_EVENT ReadyToBootEvent=NULL; +//----------------------------------------- + + //Init Lib globals... + InitAmiLib(ImageHandle,SystemTable); + PROGRESS_CODE(DXE_NB_HB_INIT); + + //Print PCI Bus Driver Version + PCI_TRACE((TRACE_PCI,"\nPciRootBrg: Initializing... PCI Driver Version %d.%d.%d\n", PCI_BUS_MAJOR_VER, PCI_BUS_MINOR_VER, PCI_BUS_REVISION)); + + Status = pBS->LocateProtocol(&gAmiBoardInfoGuid, NULL,(VOID**)&gAmiBoardInfoProtocol); + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"PciRootBrg: Fail to Locate AMI_BOARD_INFO_PROTOCOL Status=%r\n",Status)); + ASSERT_EFI_ERROR(Status); + return Status; + } + + //Zerouot Privete HOST BRG data structure and Setup Data Buffer + pBS->SetMem(&gPciRbHost[0], sizeof(gPciRbHost), 0); + pBS->SetMem(&gRbSetupData, sizeof(PCI_SETUP_DATA), 0); + + //Get Setup Data it has some Root Brg related features + BrdGetPciSetupData(&gRbSetupData); + + //Update GCD resource map with static Chipset Specific Resources decoded. + Status=ConvertMemoryMap(ImageHandle,NULL); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + + //Parse BusXlatTable extracting ROOT BRIDGE data from there. + Status=CreateRootBusData(); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + + //try to map available roots from gRootBusDb.Items to + //the corresponded HOST abstraction + //each HOST has to have a separate instance of ResourceAllocation Protocol + //each ROOT will have a separate instance of RootBridgeIo Protocol. + //This "FOR" loop will construcr HOST/ROOT bridge infrastructure and will + //try to map each root collected in call CreateRootBusData() to it's correcponded HOST + //using HbCspMapRootBrgToHost() CSP hook. For MULTY-HOST systems this hook must be ported + for(i=0;i<gRootBusDb.ItemCount; i++){ + PCI_BUS_XLAT_HDR *roothdr=(PCI_BUS_XLAT_HDR*)gRootBusDb.Items[i]; + PCI_BUS_XLAT_HDR *nexthdr=NULL; + ASLR_QWORD_ASD *busrd; + UINT64 aa=0, ra=0; + //--------------------------------------- + //fill Allocation Atributes Property. + //Based on Token values of COMBINE_MEM_PMEM and ABOVE_4G_PCI_DECODE + if(COMBINE_MEM_PMEM) aa |= EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM; + if(ABOVE_4G_PCI_DECODE){ + aa |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE; + ra |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE; + } + + if(roothdr->BusBuild ==0) ra |= (PCI_ROOT_COMPATIBILITY_ATTRIBUTES | PCI_ROOT_VGA_ATTRIBUTES); + + //Call Chipset Specific function to map this ROOT to HOST. + //And override Allocation attributes based on TOKEN VALUES. + //Have no clue how to do it automatically though.......... + j=HbCspMapRootBrgToHost(roothdr, &aa, &ra); + + //If we got NUMBER + if(j>=NB_NUMBER_OF_HOST_BRG) { + PCI_TRACE((TRACE_PCI,"PciRootBrg: Root2Host mapping [HOST=%d >= MAX_HOSTs=%d; ROOT %X|%X \n ", + j, NB_NUMBER_OF_HOST_BRG, roothdr->BusBuild, roothdr->BusRun )); + ASSERT_EFI_ERROR(EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + hb=&gPciRbHost[j]; + + //Check if setup allows us to decode PCI Space above 4G + if( gRbSetupData.Above4gDecode == 0 ) aa &= (~(EFI_PCI_HOST_BRIDGE_MEM64_DECODE)); + + hb->AllocAttrib=aa; + + //Allocate memory for Root Bridge Data structure; + rb=MallocZ(sizeof(PCI_ROOT_BRG_DATA)); + ASSERT(rb); + if(!rb)return EFI_OUT_OF_RESOURCES; + + //Save BusXlatEntry for this Root + rb->BusXlatEntry=roothdr; + +#if AMI_BOARD_VER_COMBINED >= 100 + //Change this to reference VeB output EIP 24469 + rb->RbAslName=(CHAR8*)((UINT8*)(roothdr+1)+2); //Including DEV_FN 1Byte + terminator 1 byte. +#endif + + //Save returned Attributes + rb->Supports=ra; + + //Get Next root header to determine current root Build Bus range + if(i<gRootBusDb.ItemCount-1) nexthdr=(PCI_BUS_XLAT_HDR*)gRootBusDb.Items[i+1]; + + //Get memory for Bus Resource Descriptor + busrd=MallocZ(sizeof(ASLR_QWORD_ASD)); + //fill Bus Resource descriptor fields + busrd->Hdr.HDR=0x8A; + busrd->Hdr.Length=0x2B; + busrd->Type=ASLRV_SPC_TYPE_BUS; + busrd->_GRA=1; + busrd->_MIN=roothdr->BusBuild; + //if this is last ROOT xlat entry make it MAX Bus Number; + if(nexthdr == NULL) busrd->_MAX = 0xFF; + else busrd->_MAX=nexthdr->BusBuild-1; + busrd->_LEN = busrd->_MAX - busrd->_MIN + 1; + + Status=AppendItemLst((T_ITEM_LIST*)&hb->RbInitCnt,rb); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + + Status=AppendItemLst((T_ITEM_LIST*)&rb->ResInitCnt,busrd); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + } + + //Init Number of nitial Host Bridge Structures; + for(i=0,n=0; i<NB_NUMBER_OF_HOST_BRG; i++){ + hb=&gPciRbHost[i]; + hb->ImageHandle=ImageHandle; + //Init Host Bridge Private Data instance + //here goes Allocation Arrtibutes + //hb->AllocAttrib=gHbAllocAttribTbl[i]; + + //Init Prtocol Functions + hb->ResAllocProtocol.NotifyPhase=HbResAllocNotifyPhase; + hb->ResAllocProtocol.GetNextRootBridge=HbResAllocGetNextRootBridge; + hb->ResAllocProtocol.GetAllocAttributes=HbResAllocGetAllocAttributes; + hb->ResAllocProtocol.StartBusEnumeration=HbResAllocStartBusEnumeration; + hb->ResAllocProtocol.SetBusNumbers=HbResAllocSetBusNumbers; + hb->ResAllocProtocol.SubmitResources=HbResAllocSubmitResources; + hb->ResAllocProtocol.GetProposedResources=HbResAllocGetProposedResources; + hb->ResAllocProtocol.PreprocessController=HbResAllocPreprocessController; + + hb->AllocPhase=-1; + //hb->PciSegment=HbCspGetPicSegment(); + + //Install HB res Alloc Protocol on this HOST BRG + Status=pBS->InstallMultipleProtocolInterfaces( + &hb->HbHandle, //it was NULL so it going to be a new handle + &gHbResAllocProtocolGuid, &hb->ResAllocProtocol,//RbIo Protocol GUID - I/F pare + NULL); //terminator + + + //Init Root Bridge objects of Current Host Bridge + //hb->RbInitCnt=gRbCountTbl[i]+1; + for(j=0; j<hb->RootBridgeCount; j++,n++){ + ACPI_HID_DEVICE_PATH *rbdp; + //----------------------------------- + //Reinit rb pointer for this loop + rb=hb->RootBridges[j]; + rb->ImageHandle=ImageHandle; + +#if AMI_BOARD_VER_COMBINED < 100 + //Change this to reference VeB output EIP 24469 + rb->RbAslName=RbAslName[j]; +#endif + + //Init Root Bridge Private Data instance + rbdp=Malloc(sizeof(ACPI_HID_DEVICE_PATH)+sizeof(EFI_DEVICE_PATH_PROTOCOL)); + ASSERT(rbdp); + if(!rbdp)return EFI_OUT_OF_RESOURCES; + + rb->DevPath=&rbdp->Header; + //generate RB device path + rbdp->Header.Type=ACPI_DEVICE_PATH; + rbdp->Header.SubType=ACPI_DP; + SET_NODE_LENGTH(&rbdp->Header,ACPI_DEVICE_PATH_LENGTH); + rbdp->HID=EISA_PNP_ID(0x0A03); + rbdp->UID=(UINT32)j; + + rbdp++; + rbdp->Header.Type=END_DEVICE_PATH; + rbdp->Header.SubType=END_ENTIRE_SUBTYPE; + SET_NODE_LENGTH(&rbdp->Header,END_DEVICE_PATH_LENGTH); + + //FillOut Capabilities + //rb->Supports=gRbSupportsTbl[n]; + //if Host bridge has capability to decode 64 bit address space we + //will add EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE Capability bit + //to the RootBridge Supported features Set. + if(hb->AllocAttrib & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) + rb->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE; + + //Fill out Protocol Interface for RB Protocol Member functions + rb->RbIoProtocol.ParentHandle=hb->HbHandle; + rb->RbIoProtocol.PollMem=PollMem; + rb->RbIoProtocol.PollIo=PollIo; + rb->RbIoProtocol.Mem.Read=PciMemRead; + rb->RbIoProtocol.Mem.Write=PciMemWrite; + rb->RbIoProtocol.Io.Read=PciIoRead; + rb->RbIoProtocol.Io.Write=PciIoWrite; + rb->RbIoProtocol.Pci.Read=PciRead; + rb->RbIoProtocol.Pci.Write=PciWrite; + rb->RbIoProtocol.CopyMem=CopyMem; + rb->RbIoProtocol.Map=Map; + rb->RbIoProtocol.Unmap=Unmap; + rb->RbIoProtocol.AllocateBuffer=AllocateBuffer; + rb->RbIoProtocol.FreeBuffer=FreeBuffer; + rb->RbIoProtocol.Flush=Flush; + rb->RbIoProtocol.GetAttributes=GetAttributes; + rb->RbIoProtocol.SetAttributes=SetAttributes; + rb->RbIoProtocol.Configuration=Configuration; + rb->RbIoProtocol.SegmentNumber=(UINT32)HbCspGetPciSegment(i,j); + rb->Owner=hb; + + rb->DevIoProtocol=ConstructDeviceIoProtocol(&rb->RbIoProtocol, rb->DevPath); + ASSERT(rb->DevIoProtocol); + if(!rb->DevIoProtocol) return EFI_OUT_OF_RESOURCES; + + Status=pBS->InstallMultipleProtocolInterfaces( + &rb->RbHandle, //it was NULL so it going to be a new handle + &gRbIoProtocolGuid, &rb->RbIoProtocol, //RbIo Protocol GUID - I/F pare + &gDevPathProtocolGuid, rb->DevPath, //DevPath Protocol GUID - I/F pare + &gDeviceIoProtocolGuid, rb->DevIoProtocol, + NULL); //terminator + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + } //rb loop + //Here we must initialize and install PciHotPlugControllerInit Protocol + //based on VeB provided OUTPUT, IRQ_ASM_APIC output registy can do that. + +#if AMI_HOTPLUG_INIT_SUPPORT + if(gRbSetupData.HotPlug == 1){ + Status = HpcInitProtocol(hb); + PCI_TRACE((TRACE_PCI,"PciRootBrg: HpcInitProtocol() call returned %r\n", Status)); + + if(!EFI_ERROR(Status)){ + // Install HB res Alloc Protocol on this HOST BRG + Status=pBS->InstallMultipleProtocolInterfaces( + &hb->HbHandle, //it is NOT NULL now + &gHotPlugInitProtocolGuid, &hb->HpcData->RootHotplugProtocol, + NULL); //terminator + PCI_TRACE((TRACE_PCI,"PciRootBrg: Install PCI RHPC Init Protocol call - returned %r\n", Status)); + } else { + if (Status!=EFI_NOT_FOUND) ASSERT_EFI_ERROR(Status); + + } + + }//if Setup allows (gRbSetupData.HotPlug==1)... +#endif + + } //hb loop + + Status = CreateReadyToBootEvent(TPL_CALLBACK, + RbReadyToBoot, + NULL, + &ReadyToBootEvent); + PCI_TRACE((TRACE_PCI,"PciRootBrg: Create ReadyToBootEvent - returned %r\n", Status)); + ASSERT_EFI_ERROR(Status); + + //Call Chipset Hook aftert we have initialized Pci Host bridge. + Status=HbCspBasicChipsetInit(&gPciRbHost[0]); + ASSERT_EFI_ERROR(Status); + + return Status; +} + + +//********************************************************************** +//HelperFunctions +//********************************************************************** +#if AMI_HOTPLUG_INIT_SUPPORT == 1 + +BOOLEAN HpcCheckHpBus(PCI_HOST_BRG_DATA *HostBrg, UINT8 HpSlotBus, + OUT PCI_ROOT_BRG_DATA **RootBrg, OUT PCI_BUS_XLAT_HDR **HlatHdr){ + UINTN i; + PCI_ROOT_BRG_DATA *rb=NULL; + PCI_DEV_FUN *rootdf=NULL; + UINT8 maxbus; +//--------------- + if(RootBrg==NULL || HlatHdr == NULL) return FALSE; + + PCI_TRACE((TRACE_PCI,"PciHp: Locating RB for Slot @ bus 0x%X ... ", HpSlotBus)); + + for(i=0; i<HostBrg->RootBridgeCount; i++){ + PCI_BUS_XLAT_HDR *xhdr=gAmiBoardInfoProtocol->BusXlatTable; + PCI_DEV_FUN *devf = (PCI_DEV_FUN*)(xhdr+1); + //----------------------------- + + //Init Data... + rb=HostBrg->RootBridges[i]; + + //See how many buses this root decodes... + if(i < HostBrg->RootBridgeCount-1) maxbus=HostBrg->RootBridges[i+1]->BusXlatEntry->BusBuild-1; + else maxbus=0xFF; + + //Check if it HpSlotBus falls in this RB bus range. + if( (HpSlotBus > maxbus) || (rb->BusXlatEntry->BusBuild > HpSlotBus) )continue; + + + rootdf=(PCI_DEV_FUN*)(rb->BusXlatEntry+1); + + while((UINTN)devf<=(UINTN)(gAmiBoardInfoProtocol->BusXlatTable)+gAmiBoardInfoProtocol->BusXlatLength){ + //Terminator found... + if(devf->DEV_FUN == 0xFF){ + //Check if BusBuild # of Xlat entry matches the HpSlotBus + if(xhdr->BusBuild == HpSlotBus){ + PCI_DEV_FUN *rdf=(PCI_DEV_FUN*)(xhdr+1); //Root DevFunc is the first node after header. + //----------------- + if(rootdf->DEV_FUN == rdf->DEV_FUN ){ + *RootBrg=rb; + *HlatHdr=xhdr; + PCI_TRACE((TRACE_PCI,"FOUND! Rb #%d; maxbus=0x%X minbus=0x%X\n ",i, maxbus, rb->BusXlatEntry->BusBuild)); + return TRUE; + } + } + //Advance to the next record in BusXlatTbl. +#if AMI_BOARD_VER_COMBINED >= 100 + //Now we have AslName[5] following devf data + xhdr=(PCI_BUS_XLAT_HDR*)(devf+1+5); +#else + xhdr=(PCI_BUS_XLAT_HDR*)(devf+1); +#endif + devf = (PCI_DEV_FUN*)(xhdr+1); + continue; + } else { + devf++; + } + } + //Search through all the ROOTs.. + } //for + + //we can't find + *RootBrg=NULL; + *HlatHdr=NULL; + + PCI_TRACE((TRACE_PCI,"NOT FOUND! Rb #%d; maxbus=0x%X minbus=0x%X\n",i, maxbus, rb->BusXlatEntry->BusBuild)); + return FALSE; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HpcFindHpSlots +// +// Description: +// This function find +// information and initialize an instance of PCI Root Hotplug Controller +// Initialization Protocol. +// +// Input: PCI_HOST_BRG_DATA *HostBrg - Pointer on Private Data +// structure for which PCI Hot Plug Init Protocol going to +// be initialized +// +// Output: EFI_SUCCESS is OK +// EFI_NOT_FOUND no Hotplug slots where found. +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HpcFindSlots(PCI_HOST_BRG_DATA *HostBrg){ + EFI_STATUS Status=EFI_NOT_FOUND; + UINTN i; + PCI_IRQ_PIC_ROUTE *picr=NULL; + PCI_IRQ_APIC_ROUTE *apicr=NULL; + PCI_DEVICE_PATH pcidp; + UINTN hpscnt=0; +//------------------------- + //Check The conditions and validity of a call...using PIC HP Slots Information... + hpscnt=gAmiBoardInfoProtocol->HpSltPicLength/sizeof(PCI_IRQ_PIC_ROUTE); + + PCI_TRACE((TRACE_PCI,"PciHp: Found 0x%X HP Slots; processing...:\n", hpscnt)); + + if(hpscnt != (gAmiBoardInfoProtocol->HpSltApicLength/sizeof(PCI_IRQ_APIC_ROUTE)) ){ + PCI_TRACE((TRACE_PCI,"PciHp: APIC HP Slot count != PIC HPC Slot Count: exiting - EFI_INVALID_PARAMETER\n")); + return EFI_INVALID_PARAMETER; + } + + + //init PCI Device Path variable we will not touch header data there.. + pcidp.Header.SubType=HW_PCI_DP; + pcidp.Header.Type=HARDWARE_DEVICE_PATH; + SET_NODE_LENGTH(&pcidp.Header,HW_PCI_DEVICE_PATH_LENGTH); + + //Now look for Hotplug slots we know it must be there... + for(i=0,picr=gAmiBoardInfoProtocol->HpSltTablePic; i<hpscnt; i++, picr++){ + PCI_ROOT_BRG_DATA *hprb=NULL; + PCI_BUS_XLAT_HDR *hpsh=NULL; + //-------------------------- + + //Our helper function identified the Slot and ROOT where it belongs. + //We are assuming PCI Express Hotplug. So the Bridge is the HPC and Bus It produces is HPB. + if( HpcCheckHpBus(HostBrg, picr->PciBusNumber, &hprb, &hpsh)){ + HPC_LOCATION_DATA *locdata=NULL; + EFI_DEVICE_PATH_PROTOCOL *tmpdp=NULL; + PCI_DEV_FUN *df; + //---------------- + PCI_TRACE((TRACE_PCI,"PciHp: Found HP Slot #0x%X (%d dec) at BusBuild #0x%X\n",picr->SlotNum, picr->SlotNum, picr->PciBusNumber)); + + //Generate the device path for the HPController\HPBus we have pci device path reserved there. + tmpdp=DPCopy(hprb->DevPath); + if(tmpdp==NULL) { + Status=EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR(Status); + return Status; + } + + df=(PCI_DEV_FUN*)(hpsh+1); + df+=1; //One node is for ROOT bridge + + while (df->DEV_FUN != 0xFF){ + VOID *oldp=tmpdp; + //--------- + pcidp.Function=df->Fun; + pcidp.Device=df->Dev; + tmpdp=DPAddNode(tmpdp, (EFI_DEVICE_PATH_PROTOCOL*)&pcidp); + + if(tmpdp==NULL) { + Status=EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR(Status); + return Status; + } + df+=1; + if(oldp!=NULL)pBS->FreePool(oldp); + } + //Here DevicePath Is Ready. + + //Store data returned by HpcCheckHpBus in private structures. + locdata=MallocZ(sizeof(HPC_LOCATION_DATA)); + if(locdata==NULL) { + Status = EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR(Status); + return Status; + } else Status=EFI_SUCCESS; + + locdata->Owner=hprb; + locdata->SlotHdr=hpsh; + + //For SHPC and PCIExpress Hotplug HPC==HPB = tmpdp. + //make a copy of generated DP into hpclocation buffer + locdata->HpcLocation.HpcDevicePath=DPCopy(tmpdp); + locdata->HpcLocation.HpbDevicePath=DPCopy(tmpdp); + + pBS->FreePool(tmpdp); + + if(locdata->HpcLocation.HpbDevicePath==NULL || locdata->HpcLocation.HpcDevicePath==NULL) { + Status = EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR(Status); + return Status; + } + + //fill out Padding Information for this slot... + locdata->Padding[ptBus] = gRbSetupData.BusPadd; + locdata->Padding[ptIo ] = gRbSetupData.IoPadd; + locdata->Padding[ptMmio32] = gRbSetupData.Mmio32Padd; + locdata->Padding[ptMmio32pf]= gRbSetupData.Mmio32PfPadd; + locdata->Padding[ptMmio64] = gRbSetupData.Mmio64Padd; + locdata->Padding[ptMmio64pf]= gRbSetupData.Mmio64PfPadd; + + Status=AppendItemLst((T_ITEM_LIST*)&HostBrg->HpcData->HpclInitCnt, locdata); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) break; + } + if((UINTN)picr>((UINTN)gAmiBoardInfoProtocol->HpSltTablePic+gAmiBoardInfoProtocol->HpSltPicLength)) break; + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HpcInitGetRootHpcList +// +// Description: GetRootHpcList() Function of the PCI Root Hotplug Controller +// Initialization Protocol. See PI 1.1 Spec or details +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HpcInitGetRootHpcList(IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + OUT UINTN *HpcCount, + OUT EFI_HPC_LOCATION **HpcList) +{ + EFI_STATUS Status=EFI_SUCCESS; + UINTN i; + EFI_HPC_LOCATION *hpcl=NULL, *lp=NULL; + PCI_HPC_DATA *hpcdata=NULL; + +//------------------------ + hpcdata=(PCI_HPC_DATA*)This; + + PCI_TRACE((TRACE_PCI,"PciHb: Get Location - HpcLocCount=%d\n", hpcdata->HpcLocCount)); + PCI_TRACE((TRACE_PCI,"-------------------------------------------------\n")); + + //Allocate Buffer for HPC List + hpcl=MallocZ(sizeof(EFI_HPC_LOCATION) * hpcdata->HpcLocCount); + + //Check conditions + if(hpcl==NULL){ + Status=EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR(Status); + return Status; + } + + //Fill data in RHPC List Data... + for(i=0, lp=hpcl; i<hpcdata->HpcLocCount; i++, lp++){ + HPC_LOCATION_DATA *locdata=hpcdata->HpcLocData[i]; + //---------------- + MemCpy(lp, &locdata->HpcLocation, sizeof(EFI_HPC_LOCATION)); + PCI_TRACE((TRACE_PCI," lp->HpcDP=[HID(%X)UID(%X)]; lp->HpbDP[HID(%X)UID(%X)]\n", + ((ACPI_HID_DEVICE_PATH*)lp->HpcDevicePath)->HID,((ACPI_HID_DEVICE_PATH*)lp->HpcDevicePath)->UID, + ((ACPI_HID_DEVICE_PATH*)lp->HpbDevicePath)->HID,((ACPI_HID_DEVICE_PATH*)lp->HpbDevicePath)->UID)); + } + PCI_TRACE((TRACE_PCI,"-------------------------------------------------\n")); + + *HpcCount=hpcdata->HpcLocCount; + *HpcList=hpcl; + + return Status; +} + + +EFI_STATUS FindHpcLocData( IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + IN PCI_HPC_DATA *HpcData, + OUT HPC_LOCATION_DATA **HpcLocData ) +{ + UINTN i; + HPC_LOCATION_DATA *locdata; +//------------------ + + for(i=0; i< HpcData->HpcLocCount; i++){ + locdata=HpcData->HpcLocData[i]; + if(DPCmp(HpcDevicePath, locdata->HpcLocation.HpcDevicePath) == 0 ){ + *HpcLocData=locdata; + return EFI_SUCCESS; + } + } + + PCI_TRACE((TRACE_PCI,"PciHp: Can't find matching HPC for DevicePath @ 0x%X \n",HpcDevicePath)); + + return EFI_NOT_FOUND; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HpcInitInitializeRootHpc +// +// Description: InitializeRootHpc() Function of the PCI Root Hotplug Controller +// Initialization Protocol. See PI 1.1 Spec or details +// +// NOTE: +// This function call will be used to overwrite default resource Padding settings. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HpcInitInitializeRootHpc(IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + IN UINT64 HpcPciAddress, + IN EFI_EVENT Event, OPTIONAL + OUT EFI_HPC_STATE *HpcState) +{ + EFI_STATUS Status=EFI_SUCCESS; + PCI_HPC_DATA *hpcdata=NULL; + HPC_LOCATION_DATA *locdata; +//------------------------ + hpcdata=(PCI_HPC_DATA*)This; + + //Find which exactly HPC PCI BUS Driver means.. + Status=FindHpcLocData(HpcDevicePath, hpcdata,&locdata); + if(EFI_ERROR(Status)) return Status; + + //Call Porting function to overwrite HP Padding Settings if needed; + PciPortSetOemPadding(hpcdata, locdata, HpcPciAddress); + + *HpcState=(EFI_HPC_STATE_INITIALIZED|EFI_HPC_STATE_ENABLED); + + return EFI_SUCCESS; +} + +VOID HpcFillDescriptor(ASLR_QWORD_ASD *Descriptor, HP_PADD_RES_TYPE PaddType, UINT64 Length){ + +//--------------------- + + Descriptor->Hdr.HDR=0x8A; + Descriptor->Hdr.Length=0x2B; + + Descriptor->_LEN=Length; + if(PaddType==ptBus)Descriptor->_MAX=1; + else{ + if(IsPowerOfTwo(Length))Descriptor->_MAX=Length-1; + else Descriptor->_MAX=1; + } + + Descriptor->GFlags._MIF=1; + Descriptor->GFlags._MAF=1; + Descriptor->TFlags.TFLAGS=0; + + switch(PaddType){ + case ptBus: + Descriptor->Type=ASLRV_SPC_TYPE_BUS; + break; + case ptIo: + Descriptor->Type=ASLRV_SPC_TYPE_IO; + break; + case ptMmio32: + Descriptor->Type=ASLRV_SPC_TYPE_MEM; + Descriptor->_GRA=32; + break; + case ptMmio32pf: + Descriptor->Type=ASLRV_SPC_TYPE_MEM; + Descriptor->TFlags.TFLAGS=0x06; + Descriptor->_GRA=32; + break; + case ptMmio64: //4 + Descriptor->Type=ASLRV_SPC_TYPE_MEM; + Descriptor->_GRA=64; + break; + case ptMmio64pf: //5 + Descriptor->Type=ASLRV_SPC_TYPE_MEM; + Descriptor->TFlags.TFLAGS=0x06; + Descriptor->_GRA=64; + break; + } + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HpcInitInitializeRootHpc +// +// Description: InitializeRootHpc() Function of the PCI Root Hotplug Controller +// Initialization Protocol. See PI 1.1 Spec or details +// +// NOTE: +// This function call will be used to overwrite default resource Padding settings. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HpcGetResourcePadding(IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + IN UINT64 HpcPciAddress, + OUT EFI_HPC_STATE *HpcState, + OUT VOID **Padding, + OUT EFI_HPC_PADDING_ATTRIBUTES *Attributes) +{ + EFI_STATUS Status=EFI_SUCCESS; + PCI_HPC_DATA *hpcdata=NULL; + HPC_LOCATION_DATA *locdata; + UINTN i, cnt; + ASLR_QWORD_ASD *pd, *qw; +//---------------------------------------------- + hpcdata=(PCI_HPC_DATA*)This; + + //Find which exactly HPC PCI BUS Driver means.. + Status=FindHpcLocData(HpcDevicePath, hpcdata,&locdata); + if(EFI_ERROR(Status)) return Status; + + //Calculate how many ACPI_QW_DESC we need for Padding Info. + for(i=0, cnt=0; i<ptMaxType; i++){ + if(locdata->Padding[i]!=0) cnt++; + } + + //Get memory for it. + pd=MallocZ(sizeof(ASLR_QWORD_ASD)*cnt+sizeof(ASLR_EndTag)); + if (pd==NULL) { + Status=EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR(Status); + return Status; + } + + //fill out QW Resopurce Descriptors for resource requirements. + for(i=0, qw=pd; i<ptMaxType; i++){ + if(locdata->Padding[i]!=0){ + HpcFillDescriptor(qw, (HP_PADD_RES_TYPE)i, locdata->Padding[i]); + qw++; + } + } + + ((ASLR_EndTag*)qw)->Hdr.HDR=ASLV_END_TAG_HDR; + ((ASLR_EndTag*)qw)->Chsum=0; + + *Padding=pd; + *HpcState=(EFI_HPC_STATE_INITIALIZED|EFI_HPC_STATE_ENABLED); + *Attributes=EfiPaddingPciBus; + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HpcInitProtocol +// +// Description: This function will collect all information HP related +// information and initialize an instance of PCI Root Hotplug Controller +// Initialization Protocol. +// +// Input: PCI_HOST_BRG_DATA *HostBrg - Pointer on Private Data +// structure for which PCI Hot Plug Init Protocol going to +// be initialized +// +// Output: EFI_SUCCESS is OK +// EFI_NOT_FOUND no Hotplug slots where found. +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HpcInitProtocol(PCI_HOST_BRG_DATA *HostBrg){ + EFI_STATUS Status=EFI_NOT_FOUND; +// PCI_HPC_DATA *HpcData; +//--------------------------- + + HostBrg->HpcData=MallocZ(sizeof(PCI_HPC_DATA)); + if(HostBrg->HpcData==NULL){ + Status=EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR(Status); + return Status; + } + HostBrg->HpcData->Owner=HostBrg; + + //Get HP Slots information and Device Path. + Status=HpcFindSlots(HostBrg); + if(EFI_ERROR(Status)) return Status; + + //So far so good... Init Protocol Instance Functions + HostBrg->HpcData->RootHotplugProtocol.GetRootHpcList=HpcInitGetRootHpcList; + HostBrg->HpcData->RootHotplugProtocol.InitializeRootHpc=HpcInitInitializeRootHpc; + HostBrg->HpcData->RootHotplugProtocol.GetResourcePadding=HpcGetResourcePadding; + + + return Status; +} + +#endif //AMI_HOTPLUG_INIT_SUPPORT == 1 + +EFI_STATUS FindRbBusData(PCI_ROOT_BRG_DATA *RootBrg, ASLR_QWORD_ASD **ResDsc){ + UINTN i; + ASLR_QWORD_ASD *res; +//---------------------------- + + //Init return walue with NOT_FOUND result + *ResDsc=NULL; + + for(i=0;i<RootBrg->ResCount;i++){ + + res=RootBrg->RbRes[i]; + if(res->Type== ASLRV_SPC_TYPE_BUS){ + *ResDsc=res; + return EFI_SUCCESS; + } + }//for k + + return EFI_NOT_FOUND; +} + + +EFI_STATUS ClaimMmioResources(PCI_ROOT_BRG_DATA *CurRootBrg, PCI_ROOT_BRG_DATA *NextRootBrg, ACPI_RES_TYPE ResType){ + EFI_STATUS Status; + DXE_SERVICES *dxe=NULL; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR mem; + UINT64 top, bot, tmp, ct, cb; + ACPI_RES_DATA *car, *nar; +//-------------------------------- + // Get GCD's Memory Space and IO Space Maps + Status=LibGetDxeSvcTbl(&dxe); + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"PciRootBrg: Fail to Get DXE Services Table Pointer - %r\n", Status)); + ASSERT_EFI_ERROR(Status); + return EFI_DEVICE_ERROR; + } + + if(ResType==raMmio32)car=&CurRootBrg->AcpiRbRes[raMmio32]; + else car=&CurRootBrg->AcpiRbRes[raMmio64]; + + if(car->Len==0) return EFI_NOT_FOUND; + + // Use MMIO resources as-is if AllocType is set to EfiGcdAllocateAddress. + if(car->AllocType == EfiGcdAllocateAddress) return EFI_SUCCESS; + + if(NextRootBrg!=NULL) { + if(ResType==raMmio32)nar=&NextRootBrg->AcpiRbRes[raMmio32]; + else nar=&NextRootBrg->AcpiRbRes[raMmio64]; + }else nar=NULL; + + + if( nar==NULL ) { + if(ResType==raMmio32){ + top=MAX_PCI_MMIO32; + bot=MIN_PCI_MMIO32; + } else { + top=MAX_PCI_MMIO64; + bot=MIN_PCI_MMIO64; + } + } else { + if(car->AllocType<=EfiGcdAllocateAddress){ + top=nar->Min-1; + bot=car->Min; + } else { + top=car->Max; + if(ResType==raMmio32) bot=MIN_PCI_MMIO32; + else bot=MIN_PCI_MMIO64; + } + } + + if( TmpTop[ResType] != 0 ) bot=TmpTop[ResType]+1; +// if( TmpBot[ResType] != 0 ) bot=TmpBot[ResType]; + + cb=car->Min; + ct=car->Max; + + PCI_TRACE((TRACE_PCI," Ajusting ACPI MMIO MAP [0x%lX...[0x%lX...0x%lX]...0x%lX]\n",bot,cb,ct,top)); + + PCI_TRACE((TRACE_PCI," Searching from ")); + + if(car->AllocType<=EfiGcdAllocateAddress) { + tmp=ct+1; + PCI_TRACE((TRACE_PCI,"0x%lX ==> UP.....to 0x%lX\n", tmp, top)); + } else { + tmp=cb-1; + PCI_TRACE((TRACE_PCI,"0x%lX <== DOWN...to 0x%lX\n", tmp, bot)); + } + + //All IO map's EfiGcdIoTypeNonExistent IO type, must be converted to EfiGcdIoTypeIo + while(TRUE){ + Status=dxe->GetMemorySpaceDescriptor(tmp,&mem); + + //Check if we reach end of GCD Space map... + if(EFI_ERROR(Status)) break; + + //Check if we hit another RB + if(mem.DeviceHandle!=NULL && mem.DeviceHandle!=CurRootBrg->RbHandle) break; + + //Check if we hit system memory... + if(mem.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) break; + + PCI_TRACE((TRACE_PCI," MemDsc: BAS=0x%lX; LEN=0x%lX; TYP=%d; IH=0x%X; DX=0x%X; %r\n", + mem.BaseAddress, mem.Length, mem.GcdMemoryType, mem.ImageHandle, mem.DeviceHandle, Status)); + + if(car->AllocType<=EfiGcdAllocateAddress){ + ct=mem.BaseAddress+mem.Length-1; + } else { + cb=mem.BaseAddress; + } + + if(car->AllocType<=EfiGcdAllocateAddress){ + //if we are searching bottom to top... + if(ct>=top){ + ct=top; + break; + } + } else { + //if we are searching top to bottom... + if(cb<=bot){ + cb=bot; + break; + } + } + + if(car->AllocType<=EfiGcdAllocateAddress) tmp=ct+1; + else tmp=cb-1; + } + + car->Max=ct; + car->Min=cb; + car->Len=ct-cb+1; + + TmpTop[ResType]=ct; + TmpBot[ResType]=cb; + + return EFI_SUCCESS; +} + + +EFI_STATUS ClaimIoResources(PCI_ROOT_BRG_DATA *CurRootBrg, PCI_ROOT_BRG_DATA *NextRootBrg){ + EFI_STATUS Status; + DXE_SERVICES *dxe=NULL; + EFI_GCD_IO_SPACE_DESCRIPTOR io; + UINT64 top, bot, tmp, ct, cb; + ACPI_RES_DATA *car, *nar; +//-------------------------------- + // Get GCD's Memory Space and IO Space Maps + Status=LibGetDxeSvcTbl(&dxe); + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"PciRootBrg: Fail to Get DXE Services Table Pointer - %r\n", Status)); + ASSERT_EFI_ERROR(Status); + return EFI_DEVICE_ERROR; + } + + car=&CurRootBrg->AcpiRbRes[raIo]; + + if(car->Len==0) return EFI_NOT_FOUND; + + if(NextRootBrg!=NULL) nar=&NextRootBrg->AcpiRbRes[raIo]; + else nar=NULL; + + if( nar==NULL ) { + top=MAX_PCI_IO; + bot=MIN_PCI_IO; + } else { + if(car->AllocType<=EfiGcdAllocateAddress){ + top=nar->Min-1; + bot=car->Min; + } else { + top=car->Max; + bot=MIN_PCI_IO; + } + } + + if( TmpTop[raIo] != 0 ) bot=TmpTop[raIo]+1; + //if( TmpBot[raIo] != 0 ) bot=TmpBot[raIo]; + + cb=car->Min; + ct=car->Max; + + PCI_TRACE((TRACE_PCI," Ajusting ACPI IO MAP [0x%lX...[0x%lX...0x%lX]...0x%lX]\n",bot,cb,ct,top)); + + PCI_TRACE((TRACE_PCI," Searching from ")); + + if(car->AllocType<=EfiGcdAllocateAddress) { + tmp=ct+1; + PCI_TRACE((TRACE_PCI,"0x%lX ==> UP.....to 0x%lX\n", tmp, top)); + } else { + tmp=cb-1; + PCI_TRACE((TRACE_PCI,"0x%lX <== DOWN...to 0x%lX\n", tmp, bot)); + } + + //All IO map's EfiGcdIoTypeNonExistent IO type, must be converted to EfiGcdIoTypeIo + while(TRUE){ + Status=dxe->GetIoSpaceDescriptor(tmp,&io); + + //Check if we reach end of GCD Space map... + if(EFI_ERROR(Status)) break; + + //Check if we hit another RB + if(io.DeviceHandle!=NULL && io.DeviceHandle!=CurRootBrg->RbHandle) break; + + PCI_TRACE((TRACE_PCI," IoDes: BAS=0x%lX; LEN=0x%lX; TYP=%d; IH=0x%X; DX=0x%X; %r\n", + io.BaseAddress, io.Length, io.GcdIoType, io.ImageHandle, io.DeviceHandle, Status)); + + if(car->AllocType<=EfiGcdAllocateAddress){ + ct=io.BaseAddress+io.Length-1; + } else { + cb=io.BaseAddress; + } + if(car->AllocType<=EfiGcdAllocateAddress){ + //if we are searching bottom to top... + if(ct>=top){ + ct=top; + break; + } + } else { + //if we are searching top to bottom... + if(cb<=bot){ + cb=bot; + break; + } + } + + if(car->AllocType<=EfiGcdAllocateAddress) tmp=ct+1; + else tmp=cb-1; + } + + car->Max=ct; + car->Min=cb; + car->Len=ct-cb+1; + + TmpTop[raIo]=ct; + TmpBot[raIo]=cb; + + return EFI_SUCCESS; +} + +EFI_STATUS AjustAcpiResource(UINTN HostIndex, UINTN RootIndex, ACPI_RES_TYPE ResType){ + EFI_STATUS Status=EFI_SUCCESS; + PCI_HOST_BRG_DATA *hb, *nexthb; + PCI_ROOT_BRG_DATA *rb, *nextrb; + ASLR_QWORD_ASD *res, *nextres; +//-------------------- + + //Get pointers to the main data structures we are going to work with. + hb=&gPciRbHost[HostIndex]; + rb=hb->RootBridges[RootIndex]; + + //Check if system has NEXT entity available... + if(NB_NUMBER_OF_HOST_BRG>HostIndex+1) nexthb=&gPciRbHost[HostIndex+1]; + else nexthb=NULL; + + if(hb->RootBridgeCount>RootIndex+1)nextrb=hb->RootBridges[RootIndex+1]; + else { + if(nexthb!=NULL) nextrb=nexthb->RootBridges[0]; + else nextrb=NULL; + } + + //Start parsing resources... + switch(ResType){ + case raBus: + //Trying to make bus ranges among the bridges be decoded consistently + //even RB0 decodes buses 0..5 and RB1 decodes 0x80..0x82 for ACPI + //make it decode 0..0x7F and 80..0xFF correspondently. + Status=FindRbBusData(rb, &res); + //BUS resources must be there + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return EFI_DEVICE_ERROR; + + //fill ACPI Resource properties + rb->AcpiRbRes[raBus].Min=res->_MIN; + rb->AcpiRbRes[raBus].Gra=1; + if (nextrb!=NULL) { + Status=FindRbBusData(nextrb, &nextres); + //BUS resources must be there + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return EFI_DEVICE_ERROR; + //Check if NULL bus descriptor... + if(nextres->_MIN==0 && nextres->_MAX==0 && nextres->_LEN==0) + rb->AcpiRbRes[raBus].Max=MAX_PCI_BUSES; + else + rb->AcpiRbRes[raBus].Max=nextres->_MIN-1; + } else { + rb->AcpiRbRes[raBus].Max=MAX_PCI_BUSES; + } + rb->AcpiRbRes[raBus].Len=rb->AcpiRbRes[raBus].Max-rb->AcpiRbRes[raBus].Min+1; + + PCI_TRACE((TRACE_PCI," Ajusting ACPI BUS MAP [0x%lX...[0x%lX...0x%lX]...0x%lX]\n", + rb->AcpiRbRes[raBus].Min,res->_MIN,res->_MIN+res->_LEN-1,rb->AcpiRbRes[raBus].Max)); + PCI_TRACE((TRACE_PCI," ACPI BUS MAP Set to [0x%lX...0x%lX]\n", + rb->AcpiRbRes[raBus].Min,rb->AcpiRbRes[raBus].Max)); + break; + + case raIo: + //With IO picture is much worse. we should scan and assume any unallocated IO to the + //corresponded RB keeping in mind boundary between RB0..RB1..RBn decoding ranges. + //IO resources may not be there ISA res 0...0xFFF is taken care of automatically + //If system don't have second root bridge and does not decode any IO, assume all IO + //from 0x1000...Fset decoded by + Status=ClaimIoResources(rb, nextrb); + PCI_TRACE((TRACE_PCI," ACPI IO MAP Set to [0x%lX...0x%lX] %r\n", + rb->AcpiRbRes[raIo].Min,rb->AcpiRbRes[raIo].Max,Status)); + break; + case raMmio32: + Status=ClaimMmioResources(rb, nextrb, raMmio32); + PCI_TRACE((TRACE_PCI," ACPI MEM32 MAP Set to [0x%lX...0x%lX] %r\n", + rb->AcpiRbRes[raMmio32].Min,rb->AcpiRbRes[raMmio32].Max, Status)); + + break; + case raMmio64: + Status=ClaimMmioResources(rb, nextrb, raMmio64); + PCI_TRACE((TRACE_PCI," ACPI MEM64 MAP Set to [0x%lX...0x%lX] %r\n", + rb->AcpiRbRes[raMmio64].Min,rb->AcpiRbRes[raMmio64].Max, Status)); + break; + default: return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: RbReadyToBoot +// +// Description: This function will create ReadyToBoot Event to update each +// Root Bridge ASL Object with corresponded resources decoded. +// +// Input: Nothing +// +// Output: EFI_SUCCESS is OK +// +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID RbReadyToBoot(IN EFI_EVENT Event, IN VOID *Context){ + EFI_STATUS Status; + UINTN i,j,k; + PCI_HOST_BRG_DATA *hb; + PCI_ROOT_BRG_DATA *rb; + ACPI_HDR *dsdt; + EFI_PHYSICAL_ADDRESS a; + BOOLEAN vga=FALSE; +//----------------------------- + +// EFI_DEADLOOP(); + + //Get DSDT.. we have to update it. + Status=LibGetDsdt(&a,EFI_ACPI_TABLE_VERSION_ALL); + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"PciRootBrg: Fail to Get DSDT - returned %r\n", Status)); + ASSERT_EFI_ERROR(Status); + return; + } else dsdt=(ACPI_HDR*)a; + + //Collect currently programed resource requirements, we will need to ajust it + //to clame all Unallocated IO/MMIO to report it to OS. + for(i=0; i<NB_NUMBER_OF_HOST_BRG; i++){ + hb=&gPciRbHost[i]; + for(j=0; j<hb->RootBridgeCount; j++){ + rb=hb->RootBridges[j]; + + PCI_TRACE((TRACE_PCI,"PciRootBrg: Host[ %d ].Root[ %d ] \n", i, j)); + + for(k=raBus; k<raMaxRes; k++){ + Status=AjustAcpiResource(i,j,k); + }//for k + }//for j + }//for i + + //after collectinfg and ajusting all Rb decoding info info + //Update place holders in each Rb Device Scope in DSDT. + for(i=0; i<NB_NUMBER_OF_HOST_BRG; i++){ + hb=&gPciRbHost[i]; + for(j=0; j<hb->RootBridgeCount; j++){ + rb=hb->RootBridges[j]; + + //Check if this is a Compatibility Root Bridge. + PCI_TRACE((TRACE_PCI,"PciRootBrg: Updating ASL Device Object '%s': ...\n", rb->RbAslName)); + + if(rb->Supports & (PCI_ROOT_COMPATIBILITY_ATTRIBUTES)){ + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "CPRB", 1); + PCI_TRACE((TRACE_PCI," =>'CPRB'= 1 -> %r;\n", Status)); + } else { + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "CPRB", 0); + PCI_TRACE((TRACE_PCI," =>'CPRB'= 0 -> %r;\n", Status)); + } + + if(rb->Attributes & (PCI_ROOT_VGA_ATTRIBUTES)){ + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "LVGA", 1); + PCI_TRACE((TRACE_PCI," =>'LVGA'= 1 -> %r;\n", Status)); + vga=TRUE; + } else { + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "LVGA", 0); + PCI_TRACE((TRACE_PCI," =>'LVGA'= 0 -> %r;\n", Status)); + } + + //Now Update place holders fit in collected system resource consumption. + + //0. Update device Status + if( rb->NotPresent ) Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "STAV", 0x00); + PCI_TRACE((TRACE_PCI," =>'SATV'=%d -> %r;\n", !rb->NotPresent, Status)); + + //1.Update Bus Object + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "BRB", rb->AcpiRbRes[raBus].Min); + PCI_TRACE((TRACE_PCI," =>'BRB_'=0x%lX -> %r; ",rb->AcpiRbRes[raBus].Min, Status)); + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "BRL", rb->AcpiRbRes[raBus].Len); + PCI_TRACE((TRACE_PCI," 'BRL_'=0x%lX -> %r;\n",rb->AcpiRbRes[raBus].Len, Status)); + + //2.Update IO Object + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "IOB", rb->AcpiRbRes[raIo].Min); + PCI_TRACE((TRACE_PCI," =>'IOB_'=0x%lX -> %r; ",rb->AcpiRbRes[raIo].Min, Status)); + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "IOL", rb->AcpiRbRes[raIo].Len); + PCI_TRACE((TRACE_PCI," 'IOL_'=0x%lX -> %r;\n",rb->AcpiRbRes[raIo].Len, Status)); + + //3.Update MMIO32 Object + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MBB", rb->AcpiRbRes[raMmio32].Min); + PCI_TRACE((TRACE_PCI," =>'MBB_'=0x%lX -> %r; ",rb->AcpiRbRes[raMmio32].Min, Status)); + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MBL", rb->AcpiRbRes[raMmio32].Len); + PCI_TRACE((TRACE_PCI," 'MBL_'=0x%lX -> %r;\n",rb->AcpiRbRes[raMmio32].Len, Status)); + + //3.Update MMIO64 Object + //3.1 Update LO part of _MIN + a=rb->AcpiRbRes[raMmio64].Min & 0xFFFFFFFF; + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MABL", a); + PCI_TRACE((TRACE_PCI," =>'MABL'=0x%lX -> %r; ", a, Status)); + + //3.2 Update HI part of _MIN + a=Shr64(rb->AcpiRbRes[raMmio64].Min, 32); + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MABH", a); + PCI_TRACE((TRACE_PCI,"'MABH'=0x%lX -> %r;\n", a, Status)); + + //3.3 Update LO part of MAX + a=rb->AcpiRbRes[raMmio64].Max & 0xFFFFFFFF; + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MAML", a); + PCI_TRACE((TRACE_PCI," =>'MAML'=0x%lX -> %r; ", a, Status)); + + //3.4 Update HI part of _MAX + a=Shr64(rb->AcpiRbRes[raMmio64].Max, 32); + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MAMH", a); + PCI_TRACE((TRACE_PCI,"'MAMH'=0x%lX -> %r;\n", a, Status)); + + //3.3 Update LO part of MAX + a=rb->AcpiRbRes[raMmio64].Len & 0xFFFFFFFF; + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MALL", a); + PCI_TRACE((TRACE_PCI," =>'MALL'=0x%lX -> %r; ", a, Status)); + + //3.4 Update HI part of _MAX + a=Shr64(rb->AcpiRbRes[raMmio64].Len, 32); + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MALH", a); + PCI_TRACE((TRACE_PCI,"'MALH'=0x%lX -> %r;\n", a, Status)); + + }//j + }//i + + //if PCI_ROOT_VGA_ATTRIBUTES were not set by drivers we have to clame Legacy VGS IO and MEM Space. + if(!vga){ + hb=&gPciRbHost[0]; + rb=hb->RootBridges[0]; + PCI_TRACE((TRACE_PCI,"PciRootBrg: Legacy VGA Attributes were not set!!!\n")); + PCI_TRACE((TRACE_PCI," Setting 'LVGA'=1 of Device Object '%s' for Hb[0].Rb[0] -> ", rb->RbAslName)); + Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "LVGA", 1); + PCI_TRACE((TRACE_PCI,"%r;\n", Status)); + } + + //Checksum + dsdt->Checksum = 0; + dsdt->Checksum = ChsumTbl((UINT8*)dsdt, dsdt->Length); + + // Check for invalid Pci RootBridge Handle. + //If Rootbridge handle is invalid, then uninstall PCI Rootbridge IO protocol on this handle. + for(i=0; i<NB_NUMBER_OF_HOST_BRG; i++){ + hb=&gPciRbHost[i]; + for(j=0; j<hb->RootBridgeCount; j++){ + rb=hb->RootBridges[j]; + PCI_TRACE((TRACE_PCI,"PciRootBrg: Host[ %d ].Root[ %d ] \n", i, j)); + + if(rb->NotPresent) { + PCI_TRACE((TRACE_PCI,"Hb.SetBusNumbers - Invalid RB Hndle Passed\n")); + Status = pBS->UninstallMultipleProtocolInterfaces ( + rb->RbHandle, + &gRbIoProtocolGuid, &rb->RbIoProtocol, + &gDevPathProtocolGuid, rb->DevPath, + NULL + ); + + PCI_TRACE((TRACE_PCI,"Uninstall RbIoProtocol Status %r; \n", Status)); + rb->RbHandle=NULL; + }//if + }//for j + }//for i + + pBS->CloseEvent(Event); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CreateRootBusData +// +// Description: This function will parse NusXlat Table looking for HostBridge +// entries (one who has Bus IN == Bus OUT) and populate gRootBusDb +// Structure. +// +// Input: Nothing +// +// Output: EFI_SUCCESS is OK +// +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CreateRootBusData(){ + PCI_BUS_XLAT_HDR *xhdr=gAmiBoardInfoProtocol->BusXlatTable; + PCI_DEV_FUN *devf = (PCI_DEV_FUN*)(xhdr+1); + UINTN i=0; + EFI_STATUS Status; +//-------------------------------- + while((UINTN)devf<=(UINTN)(gAmiBoardInfoProtocol->BusXlatTable)+gAmiBoardInfoProtocol->BusXlatLength){ + if(devf->DEV_FUN == 0xFF){ + //if we are looking for host device it shouldn't be any other guys in it's chain. + if(i==1) { + Status=AddBusDbEntry(xhdr, &gRootBusDb); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + } + //Advance to the next record in BusXlatTbl. +#if AMI_BOARD_VER_COMBINED >= 100 + //Now we have AslName[5] following devf data + xhdr=(PCI_BUS_XLAT_HDR*)(devf+1+5); +#else + xhdr=(PCI_BUS_XLAT_HDR*)(devf+1); +#endif + devf = (PCI_DEV_FUN*)(xhdr+1); + i=0; + } else { + devf++; + i++; + } + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ConvertMemoryMap +// +// Description: This function will adjust the final GCD resource map and +// convert all NonrExistant Memory resources into MMIO. +// +// Input: ImgHandle Image handle +// CntrHandle Controller Handle +// +// Output: None +// +// Notes: CHIPSET AND/OR BOARD PORTING NEEDED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ConvertMemoryMap(EFI_HANDLE ImgHandle, EFI_HANDLE CntrHandle) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *pMap; + EFI_GCD_IO_SPACE_DESCRIPTOR *pIo; + UINTN Size, i; + DXE_SERVICES *dxe; +//---------------------------------------------------------------------- + + // Convert All Nonexistent Memory space to MMIO + // Once GCD and Memory manager gets initialized + Status=LibGetDxeSvcTbl(&dxe); + if(EFI_ERROR(Status)) return Status; + + + Status=dxe->GetMemorySpaceMap(&Size, &pMap); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + + for(i=0; i<Size; i++) + if (pMap[i].GcdMemoryType == EfiGcdMemoryTypeNonExistent ){ + Status=dxe->AddMemorySpace(EfiGcdMemoryTypeMemoryMappedIo, + pMap[i].BaseAddress,pMap[i].Length, GCD_COMMON_MMIO_CAPS); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + } + pBS->FreePool(pMap); + + //Convert all non-existant IO to existant IO + Status=dxe->GetIoSpaceMap(&Size, &pIo); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + for(i=0; i<Size; i++) + if (pIo[i].GcdIoType == EfiGcdIoTypeNonExistent){ + Status=dxe->AddIoSpace(EfiGcdIoTypeIo,pIo[i].BaseAddress,pIo[i].Length); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + } + pBS->FreePool(pIo); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsResSubmited() +// +// Description: +// Will check if all root bridges belonging to the "Host" has submitted +// it's resources +// +// Input: +// PCI_HOST_BRG_DATA *Host Pointer to HOST Bridge private data +// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured +// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor +// EFI_PCI_CONFIGURATION_ADDRESS PciBusAddress Address of the controller on the PCI bus +// EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase The Phase during resource allocation +// +// Output: BOOLEAN +// TRUE all root bridges belonging to the "Host" has its resources submitted +// FALSE opposite ... +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsResSubmited(PCI_HOST_BRG_DATA *Host){ + PCI_ROOT_BRG_DATA *rb; + UINTN i; +//--------------------- + for(i=0; i<NB_NUMBER_OF_HOST_BRG; i++){ + rb=Host->RootBridges[i]; + if(!rb->ResSubmited) return FALSE; + } + return TRUE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetRbByHandle() +// +// Description: +// Lokates +// +// Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance +// EFI_HANDLE RbHandle PCI Root Bridge Handle to get Private data for. +// UINTN *Index Updated Index of the Found Root Bridge private data +// +// Output: PCI_ROOT_BRG_DATA +// Not NULL if Root was found. +// NULL if Root was not found. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +PCI_ROOT_BRG_DATA *GetRbByHandle(EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + EFI_HANDLE RbHandle, + UINTN *Index OPTIONAL) +{ + PCI_HOST_BRG_DATA *hbdata=(PCI_HOST_BRG_DATA*)This; + PCI_ROOT_BRG_DATA *rbdata; + UINTN i; +//---------------------------------- + for(i=0;i<hbdata->RootBridgeCount;i++){ + rbdata=hbdata->RootBridges[i]; + if(rbdata->RbHandle==RbHandle){ + if(Index)(*Index)=i; +// hbdata->CurrentRb=i; + return rbdata; + } + } + return NULL; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetResources() +// +// Description: +// This function will generate Resource descriptors block based on information +// stored in RootBridge->RbRes array +// +// Input: +// PCI_HOST_BRG_DATA *Host Pointer to HOST Bridge private data +// ASLR_QWORD_ASD **Resources Resource List in a form of ACPI QWORD Resource Descriptor. +// ASLR_TYPE_ENUM ResType Describes what type of resources we are getting. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_OUT_OF_RESOURCES - If SubmitResources ( ) could not allocate resources +// EFI_NOT_READY - This phase cannot be entered at this time +// EFI_DEVICE_ERROR - SetResources failed due to HW error. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetResources(PCI_ROOT_BRG_DATA *RootBrg, ASLR_QWORD_ASD **Resources, ASLR_TYPE_ENUM ResType) +{ + UINTN i,cnt=0; + ASLR_QWORD_ASD *qw; + BOOLEAN cpy; +//---------------------------------1 + //count descriptors first + if(ResType==tResAll) cnt=RootBrg->ResCount; + else { + for(i=0;i<RootBrg->ResCount;i++){ + if(ResType==tResBus){ + if(RootBrg->RbRes[i]->Type == ASLRV_SPC_TYPE_BUS)cnt++; + } else { + if(RootBrg->RbRes[i]->Type < ASLRV_SPC_TYPE_BUS) cnt++; + } + } + } + //if(!cnt) return EFI_NOT_FOUND; + + //Allocate memory for ASL Resource Descriptors + qw=Malloc(sizeof(ASLR_QWORD_ASD)*cnt+sizeof(ASLR_EndTag)); + if(!qw) return EFI_OUT_OF_RESOURCES; + + *Resources=qw; + + //Copy Resource information + for(i=0; i<RootBrg->ResCount; i++, cpy=FALSE){ + if(ResType==tResAll) cpy=TRUE; + else { + if(ResType==tResBus){ + if(RootBrg->RbRes[i]->Type == ASLRV_SPC_TYPE_BUS)cpy=TRUE; + } else { + if(RootBrg->RbRes[i]->Type < ASLRV_SPC_TYPE_BUS) cpy=TRUE; + } + } + if(cpy){ + MemCpy(qw,RootBrg->RbRes[i],sizeof(ASLR_QWORD_ASD)); + qw++; + } + } + ((ASLR_EndTag*)qw)->Hdr.HDR=ASLV_END_TAG_HDR; + ((ASLR_EndTag*)qw)->Chsum=0; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SetResources() +// +// Description: +// This function will update RootBridge->RbRes array with Descriptors +// prowided with *Resources parameter +// +// Input: +// PCI_HOST_BRG_DATA *Host Pointer to HOST Bridge private data +// ASLR_QWORD_ASD *Resources Resource List in a form of ACPI QWORD Resource Descriptor. +// ASLR_TYPE_ENUM ResType Describes what type of resources we are getting. +// BOOLEAN Replace if TRUE function will Remove all descriptors of "ResType" before adding. +// if FALSE function will just add "Resources" +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_OUT_OF_RESOURCES - If SubmitResources ( ) could not allocate resources +// EFI_NOT_READY - This phase cannot be entered at this time +// EFI_DEVICE_ERROR - SetResources failed due to HW error. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SetResources(PCI_ROOT_BRG_DATA *RootBrg, ASLR_QWORD_ASD *Resources, + ASLR_TYPE_ENUM ResType, BOOLEAN Replace) +{ + UINTN i, len, cnt; + ASLR_QWORD_ASD *res; +//--------------------------------- + + len=ValidateDescriptorBlock((ASLR_QWORD_ASD*)Resources, ResType, FALSE); + if(!len) return EFI_INVALID_PARAMETER; + + cnt=(len-sizeof(ASLR_EndTag))/sizeof(ASLR_QWORD_ASD); + //We have received Empty descriptor nothing to do just return. + if(!cnt) return EFI_SUCCESS; + + if(Replace){ + if(ResType==tResAll) ClearItemLst((T_ITEM_LIST*)&RootBrg->ResInitCnt, TRUE); + else { + i=RootBrg->ResCount; + while(i){ + i--; + if(ResType==tResBus){ + if(RootBrg->RbRes[i]->Type == ASLRV_SPC_TYPE_BUS) + DeleteItemLst((T_ITEM_LIST*)&RootBrg->ResInitCnt, i,TRUE); + } else { + if(RootBrg->RbRes[i]->Type < ASLRV_SPC_TYPE_BUS) + DeleteItemLst((T_ITEM_LIST*)&RootBrg->ResInitCnt, i,TRUE); + } + } + } + } + + //Update Bus Resources in rbdata + for(i=0; i<cnt; i++,Resources++) { + res=Malloc(sizeof(ASLR_QWORD_ASD)); + if(!res) return EFI_OUT_OF_RESOURCES; + + MemCpy(res,Resources,sizeof(ASLR_QWORD_ASD)); + + if(EFI_ERROR(AppendItemLst((T_ITEM_LIST*)&RootBrg->ResInitCnt,res))) return EFI_OUT_OF_RESOURCES; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsPowerOfTwo() +// +// Description: +// Checks if value passed makes "POWER OF TWO" +// +// Input: +// UINT64 Value Value to check. +// +// Output: BOOLEAN +// TRUE or FALSE based on value passed. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsPowerOfTwo(UINT64 Value){ + UINTN i; + UINT64 t; +//-------------- + for(i=0; i<64; i++){ + t=Shl64(1,(UINT8)i); + if(Value&t) { + if(Value&(~t))return FALSE; + else return TRUE; + } + } + return FALSE; +} + +//(EIP45278)> +#if PCI_MMIO_RES_TOP_ALLIGN == 1 +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AllocateMemoryResource() +// +// Description: +// This function will try to Allocate from GCD set of resources requested by +// input Length and Alignment. +// +// Input: +// UINTN Alignment Align with 2^Alignment +// UINT64 Length Length to allocate +// EFI_PHYSICAL_ADDRESS *BaseAddress Base address to allocate +// EFI_HANDLE ImageHandle The image handle consume the allocated space. +// EFI_HANDLE DeviceHandle The device handle consume the allocated space. +// +// Output: EFI_STATUS +// EFI_INVALID_PARAMETER Invalid parameter. +// EFI_NOT_FOUND No descriptor contains the desired space. +// EFI_SUCCESS Memory space successfully allocated. +// +// EFI_PHYSICAL_ADDRESS *BaseAddress Base address to be allocated +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AllocateMemoryResource ( + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle +) +{ + EFI_STATUS Status; + DXE_SERVICES *dxe; + EFI_PHYSICAL_ADDRESS AlignmentMask; + + Status=LibGetDxeSvcTbl(&dxe); + if(EFI_ERROR(Status)) return Status; + + AlignmentMask = (1 << Alignment) - 1; + // Search an unused for fit the length + while (((*BaseAddress + Length) & AlignmentMask)) { + Status = dxe->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchTopDown, + EfiGcdMemoryTypeMemoryMappedIo, + 0, + Length, + BaseAddress, + ImageHandle, + DeviceHandle); + if(EFI_ERROR(Status)) break; + // Check if the space is under Alignment + if (((*BaseAddress + Length) & AlignmentMask)) { + Status = dxe->FreeMemorySpace (*BaseAddress, Length); + if(EFI_ERROR(Status)) break; + *BaseAddress = ((*BaseAddress + Length) & (~AlignmentMask)) - Length; + } + } + return Status; +} +#endif +//<(EIP45278) + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AlignFromGra() +// +// Description: +// Converts C passed into Alignment format +// +// Input: +// UINTN g AlignFromGra Value to convert +// +// Output: UINTN +// Converted Alignment value. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINTN AlignFromGra(UINTN g){ + UINTN a=0; +//------------ + while(g&1){ + a++; + g=g>>1; + } + return a; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AllocateResources() +// +// Description: +// This function will try to Allocate from GCD set of resources requested by +// PCI BUS driver in "*Resources" buffer. +// +// Input: +// PCI_ROOT_BRG_DATA *RootBrg Pointer to ROOT Bridge private data +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_OUT_OF_RESOURCES - If could not allocate resources +// EFI_DEVICE_ERROR - failed due to HW error. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AllocateResources(PCI_ROOT_BRG_DATA *RootBrg){ + EFI_STATUS Status=0; + EFI_STATUS ReturnStatus = 0; + UINTN i; + ASLR_QWORD_ASD *res; + ACPI_RES_DATA *ar; + UINT64 a=0; + DXE_SERVICES *dxe; +//OUT_OF_RES HANDLING++ must be added in Custom Res allocate function. +#if BoardPciRes_SUPPORT + AMI_OUT_OF_RES_VAR OutOfResVar; +//-------------------------------------- + //Check if OUT_OF_RES_VAR was already created. + Status=AmiPciOutOfRes(&OutOfResVar, TRUE); + if(EFI_ERROR(Status)) pBS->SetMem(&OutOfResVar,sizeof(AMI_OUT_OF_RES_VAR),0); + else OutOfResVar.Count++; +#endif +//OUT_OF_RES HANDLING-- must be added in Custom Res allocate function. + + Status=LibGetDxeSvcTbl(&dxe); + if(EFI_ERROR(Status)) return Status; + + + for(i=0; i<RootBrg->ResCount; i++){ + res=RootBrg->RbRes[i]; + if(res->Type==ASLRV_SPC_TYPE_BUS) continue; + //Check if Alignment + if(!IsPowerOfTwo(res->_MAX+1)) return EFI_INVALID_PARAMETER; + switch(res->_GRA){ + case 16 : a=0xFFFF;//-res->_LEN; + break; + case 32 : a=0xFFFFFFFF;//-res->_LEN; + break; + case 64 : a=0xFFFFFFFFFFFFFFFF;//-res->_LEN+1; + break; + default :ASSERT(0); return EFI_INVALID_PARAMETER; + } + + PCI_TRACE((TRACE_PCI,"PciRootBrg:AllocateResources In -> _MIN=0x%lX; _MAX=0x%lX; _LEN=0x%lX; _GRA=0x%lX\n", + res->_MIN,res->_MAX,res->_LEN,res->_GRA)); + + + //Allocate IO + if(res->Type==ASLRV_SPC_TYPE_IO){ + + ar=&RootBrg->AcpiRbRes[raIo]; + ar->AddrUsed=a; + ar->AllocType=EfiGcdAllocateMaxAddressSearchTopDown; + + Status=dxe->AllocateIoSpace(EfiGcdAllocateMaxAddressSearchTopDown, + EfiGcdIoTypeIo, + AlignFromGra((UINTN)res->_MAX), + res->_LEN, + &a, + RootBrg->ImageHandle, RootBrg->RbHandle); + + if(EFI_ERROR(Status)) { + ReturnStatus = Status; + PCI_TRACE((TRACE_PCI,"PciRootBrg: IO Allocation Failed: Length: %lX\n",res->_LEN)); +//++OUT_OF_RES!! IO +#if BoardPciRes_SUPPORT + OutOfResVar.Resource=*res; + Status=AmiPciOutOfRes(&OutOfResVar, FALSE); + return ReturnStatus; +//--OUT_OF_RES!! IO +#else + continue; +#endif + } + + } + //Allocate MMIO + else if( res->Type==ASLRV_SPC_TYPE_MEM){ + + if(res->_GRA==32)ar=&RootBrg->AcpiRbRes[raMmio32]; + else ar=&RootBrg->AcpiRbRes[raMmio64]; + ar->AddrUsed=a; + ar->AllocType=EfiGcdAllocateMaxAddressSearchTopDown; +//(EIP45278)> +#if PCI_MMIO_RES_TOP_ALLIGN == 1 + Status = AllocateMemoryResource( + AlignFromGra((UINTN)res->_MAX), + res->_LEN, + &a, + RootBrg->ImageHandle, + RootBrg->RbHandle); +#else + Status=dxe->AllocateMemorySpace(EfiGcdAllocateMaxAddressSearchTopDown, + EfiGcdMemoryTypeMemoryMappedIo, + AlignFromGra((UINTN)res->_MAX), + res->_LEN, + &a, + RootBrg->ImageHandle, RootBrg->RbHandle); +#endif +//<(EIP45278) + + if(EFI_ERROR(Status)) { + ReturnStatus = Status; + PCI_TRACE((TRACE_PCI,"PciRootBrg: Memory Allocation Failed: Length: %lX\n",res->_LEN)); +//++OUT_OF_RES!! MEM +#if BoardPciRes_SUPPORT + OutOfResVar.Resource=*res; + Status=AmiPciOutOfRes(&OutOfResVar, FALSE); + return ReturnStatus; +#else +//--OUT_OF_RES!! MEM + continue; +#endif + } + + //Set this region as WT cache if it is PREFETCHABLE + if(res->TFlags.MEM_FLAGS._MEM!=ASLRV_MEM_UC) + { + //Status=gDxeSvcTbl->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_WT|EFI_MEMORY_RUNTIME); + Status=dxe->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_WT); + //if attempt to set WT attributes has filed, let's try UC + if(EFI_ERROR(Status)) + { + PCI_TRACE((TRACE_DXE_CHIPSET,"PciHostBridge: Setting of WT attributes for prefetchable memory has failed(%r). UC is used.\n",Status)); + //Status=gDxeSvcTbl->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_UC|EFI_MEMORY_RUNTIME); + Status=dxe->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_UC); + } + } + else Status=dxe->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_UC); + // Status=gDxeSvcTbl->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_UC|EFI_MEMORY_RUNTIME); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + + } + res->_MIN=a; + + + PCI_TRACE((TRACE_PCI,"PciRootBrg:AllocateResources Out-> _MIN=0x%lX; _MAX=0x%lX; _LEN=0x%lX; _GRA=0x%lX\n", + res->_MIN,res->_MAX,res->_LEN,res->_GRA)); + + //Do some calculation for ACPI _CRS update. + if (ar->Min==0) ar->Min=res->_MIN; + else { + if(ar->Min > res->_MIN)ar->Min=res->_MIN; + } +//(EIP45278+)> +#if PCI_MMIO_RES_TOP_ALLIGN == 1 + ar->Gra = 0; +#else + if (ar->Gra==0) ar->Gra=res->_MAX; + else { + if(ar->Gra<res->_MAX)ar->Gra=res->_MAX; + } +#endif +//<(EIP45278+) + if(ar->Len==0){ + ar->Len=res->_LEN; + if(ar->Len & ar->Gra) ar->Len=(ar->Len |ar->Gra)+1; + ar->Max=ar->Min+ar->Len-1; + } else { + UINT64 max; + //-------- + max=res->_MIN + res->_LEN - 1; + if(max>ar->Max)ar->Max=max; + ar->Len=ar->Max - ar->Min + 1; + if(ar->Len & ar->Gra) ar->Len=(ar->Len |ar->Gra)+1; + ar->Max=ar->Min+ar->Len-1; + } + PCI_TRACE((TRACE_PCI,"PciRootBrg:AcpiResources Min=0x%lX; Max=0x%lX; Len=0x%lX; Gra=0x%lX, AdrUsed=0x%lX\n\n", + ar->Min,ar->Max,ar->Len,ar->Gra, ar->AddrUsed)); + + //Don't need to set this to actual value it could be calculated using commented formula. + //More important to preserve alignment requirements of the resource window. + //res->_MAX=res->_MIN+res->_LEN-1; + } + return ReturnStatus; +} + + + + +//********************************************************************** +//Pci Host Bridge Resource Allocation Protocol function Implementation +//********************************************************************** + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HbResAllocNotifyPhase() +// +//Description: Enter a certain phase of the PCI enumeration process +// +// Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase The phase during enumeration +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_OUT_OF_RESOURCES - If SubmitResources ( ) could not allocate resources +// EFI_NOT_READY - This phase cannot be entered at this time +// EFI_DEVICE_ERROR - SetResources failed due to HW error. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HbResAllocNotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase ) +{ + PCI_HOST_BRG_DATA *hbdata=(PCI_HOST_BRG_DATA*)This; + EFI_STATUS Status=0; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **pp; + UINTN i; +//-------------------------------------------------------- + pp=Malloc(sizeof(VOID*)*hbdata->RootBridgeCount); + ASSERT(pp); + if(!pp) return EFI_INVALID_PARAMETER; + + for(i=0; i<hbdata->RootBridgeCount; i++) pp[i]=&hbdata->RootBridges[i]->RbIoProtocol; + + switch(Phase){ + case EfiPciHostBridgeBeginEnumeration: + //if(hbdata->AllocPhase!=EfiPciHostBridgeBeginEnumeration) return EFI_INVALID_PARAMETER; + Status=HbNotifyCspBeforeEnumeration(&hbdata->ResAllocProtocol, &pp[0], hbdata->RootBridgeCount); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return Status; + break; + case EfiPciHostBridgeBeginBusAllocation: + Status=HbNotifyCspBeginBusAllocation(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount); + ASSERT_EFI_ERROR(Status); + break; + case EfiPciHostBridgeEndBusAllocation: + if(hbdata->AllocPhase+1!=Phase) return EFI_INVALID_PARAMETER; + Status=HbNotifyCspEndBusAllocation(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount); + ASSERT_EFI_ERROR(Status); + break; + case EfiPciHostBridgeBeginResourceAllocation: + if(hbdata->AllocPhase+1!=Phase) return EFI_INVALID_PARAMETER; + Status=HbNotifyCspBeginResourceAllocation(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount); + ASSERT_EFI_ERROR(Status); + break; + case EfiPciHostBridgeAllocateResources: + if(hbdata->AllocPhase+1!=Phase) return EFI_INVALID_PARAMETER; + if(!IsResSubmited(hbdata)) return EFI_NOT_READY; + Status=HbNotifyCspAllocateResources(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount); + ASSERT_EFI_ERROR(Status); + break; + case EfiPciHostBridgeSetResources: + if(hbdata->AllocPhase+1!=Phase) return EFI_INVALID_PARAMETER; + if(!IsResSubmited(hbdata)) return EFI_NOT_READY; + Status=HbNotifyCspSetResources(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount); + ASSERT_EFI_ERROR(Status); + break; + case EfiPciHostBridgeFreeResources: + return EFI_UNSUPPORTED; + break; + case EfiPciHostBridgeEndResourceAllocation: + if(hbdata->AllocPhase+2!=Phase) return EFI_INVALID_PARAMETER; + Status=HbNotifyCspEndResourceAllocation(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount); + ASSERT_EFI_ERROR(Status); + break; + default: return EFI_INVALID_PARAMETER; + } + + if(EFI_ERROR(Status)) return Status; + hbdata->AllocPhase=Phase; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HbResAllocGetNextRootBridge() +// +// Description: +// Return the device handle of the next PCI root bridge that is +// associated with this Host Bridge. +// +// Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance +// EFI_HANDLE *RootBridgeHandle Returns the device handle +// of the next PCI Root Bridge. On input, it holds the RootBridgeHandle +// returned by the most recent call to GetNextRootBridge(). +// The handle for the first PCI Root Bridge is returned if RootBridgeHandle +// is NULL on input. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HbResAllocGetNextRootBridge( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN OUT EFI_HANDLE *RootBridgeHandle) +{ + PCI_HOST_BRG_DATA *hbdata=(PCI_HOST_BRG_DATA*)This; + PCI_ROOT_BRG_DATA *rbdata; + UINTN i=0; +//-------------------------------------------------- + if(!This) return EFI_INVALID_PARAMETER; + if(*RootBridgeHandle==NULL) { + rbdata=hbdata->RootBridges[i]; + *RootBridgeHandle=rbdata->RbHandle; + return EFI_SUCCESS; + } else { + rbdata=GetRbByHandle(This,*RootBridgeHandle,&i); + if(!rbdata) return EFI_INVALID_PARAMETER; + if(hbdata->RootBridgeCount-1>i){ + rbdata=hbdata->RootBridges[i+1]; + *RootBridgeHandle=rbdata->RbHandle; + return EFI_SUCCESS; + } else return EFI_NOT_FOUND; + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HbResAllocGetAllocAttributes() +// +// Description: +// Returns the attributes of a PCI Root Bridge. +// +// Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance +// EFI_HANDLE RootBridgeHandle The device handle of the PCI Root Bridge +// that the caller is interested in +// UINT64 Attribute The pointer to attributes of the PCI Root Bridge +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid +// EFI_INVALID_PARAMETER - Attributes is NULL +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HbResAllocGetAllocAttributes( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT UINT64 *Attributes) +{ + PCI_ROOT_BRG_DATA *rbdata; +//---------------------------------- + if(!This || !Attributes) return EFI_INVALID_PARAMETER; + rbdata=GetRbByHandle(This,RootBridgeHandle,NULL); + if(!rbdata)return EFI_INVALID_PARAMETER; + else *Attributes=rbdata->Owner->AllocAttrib; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HbResAllocStartBusEnumeration() +// +// Description: +// This is the request from the PCI enumerator to set up +// the specified PCI Root Bridge for bus enumeration process. +// +// Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This PROTOCOL instance +// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured +// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid +// EFI_DEVICE_ERROR - Request failed due to hardware error +// EFI_OUT_OF_RESOURCES - Request failed due to lack of resources +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HbResAllocStartBusEnumeration( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration) +{ + PCI_ROOT_BRG_DATA *rbdata; + UINTN i; + EFI_STATUS Status; + ASLR_QWORD_ASD *qw; +//----------------------------- + if(!Configuration || !This) return EFI_INVALID_PARAMETER; + + + rbdata=GetRbByHandle(This,RootBridgeHandle,&i); + if(!rbdata){ + PCI_TRACE((TRACE_PCI,"Hb.StartBusEnumeration - Invalid Rb Handle Passed\n")); + ASSERT(rbdata); + return EFI_INVALID_PARAMETER; + } + + //ThisCSP Function MIGHT Update rbdata->RbRes[] with bus ranges to scan + //and program corresponded RB registers to decode this ranges. + //If function overwrites BUS ranges this ROOT decodes IT MUST UPDATE rbdata->RbRes[]! + //If NOT it should not touch BUS resource descriptor. + Status=HbCspStartBusEnumeration((PCI_HOST_BRG_DATA*)This, rbdata,i); + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"Hb.StartBusEnumeration - HbCspUpdateBusesBefore returned ERROR!\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } + + Status=GetResources(rbdata, (ASLR_QWORD_ASD**)Configuration, tResBus); + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"Hb.StartBusEnum - RB Resources Invalid!\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } + + qw=(ASLR_QWORD_ASD*)*Configuration; + + PCI_TRACE((TRACE_PCI,"PciRb#%d: Enumerating Buses 0x%lX - 0x%lX \n", i, qw->_MIN, qw->_MIN+qw->_LEN-1)); + PCI_TRACE((TRACE_PCI,"=====================================================================\n\n")); + + + ((PCI_HOST_BRG_DATA*)This)->EnumStarted=TRUE; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HbResAllocSetBusNumbers() +// +// Description: +// This function programs the PCI Root Bridge hardware so that +// it decodes the specified PCI bus range +// +//Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance +// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured +// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid +// EFI_INVALID_PARAMETER - Configuration is NULL +// EFI_INVALID_PARAMETER - Configuration does not point to a valid ACPI resource descriptor +// EFI_INVALID_PARAMETER - Configuration contains one or more memory or IO ACPI resource descriptor +// EFI_INVALID_PARAMETER - Address Range Minimum or Address Range Length fields in Configuration +// are invalid for this Root Bridge. +// EFI_INVALID_PARAMETER - Configuration contains one or more invalid ACPI resource descriptor +// EFI_DEVICE_ERROR - Request failed due to hardware error +// EFI_OUT_OF_RESOURCES - Request failed due to lack of resources +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HbResAllocSetBusNumbers( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration) +{ + PCI_ROOT_BRG_DATA *rbdata; + UINTN i; + EFI_STATUS Status; + ASLR_QWORD_ASD *qw=(ASLR_QWORD_ASD*)Configuration; +//----------------------------- + if(!Configuration || !This) return EFI_INVALID_PARAMETER; + + rbdata=GetRbByHandle(This,RootBridgeHandle,&i); + if(!rbdata) { + PCI_TRACE((TRACE_PCI,"Hb.SetBusNumbers - Invalid RB Hndle Passed\n")); + return EFI_INVALID_PARAMETER; + } + + Status=SetResources(rbdata, Configuration, tResBus, TRUE); + + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"Hb.SetBusNumbers - Invalid Resoutce Descriptor(s) Passed\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } + + //Call CSP function to update RB Buses accordinaly submited information + Status=HbCspSetBusNnumbers((PCI_HOST_BRG_DATA*)This, rbdata, i); + + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"Hb.SetBusNumbers - HbCspUpdateBusesAfter returned ERROR!\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } + + PCI_TRACE((TRACE_PCI,"PciRb#%d: Assigning Buses 0x%lX - 0x%lX \n", i, qw->_MIN, qw->_MIN+qw->_LEN-1)); + + + rbdata->BusesSet=TRUE; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FreeUsedResources() +// +// Description: +// Cleans internal RB data and free resources allocated trough GCD. +// +// Input: +// PCI_ROOT_BRG_DATA *RootBrg Pointer to RB Private data. +// +// Output: NONE +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID FreeUsedResources(PCI_ROOT_BRG_DATA *RootBrg){ + ASLR_QWORD_ASD *res; + UINTN i; + DXE_SERVICES *dxe; + EFI_STATUS Status; +//------------------------------ + Status=LibGetDxeSvcTbl(&dxe); + ASSERT_EFI_ERROR(Status); + + for(i=0; i<RootBrg->ResCount; i++){ + res=RootBrg->RbRes[i]; + + //Clean only IO and MMIO resources buses was submitted in different call and must stay. + if(res->Type < ASLRV_SPC_TYPE_BUS){ + if(res->_MIN != 0){ + //Free IO + if(res->Type==ASLRV_SPC_TYPE_IO){ + Status=dxe->FreeIoSpace(res->_MIN, res->_LEN); + } else { + Status=dxe->FreeMemorySpace(res->_MIN, res->_LEN); + } + ASSERT_EFI_ERROR(Status); + } //res_MIN + //Don't free resource list, it will be reupdated with RPLACE option. + } + } //for + + //Almost done now clean AcpiRbRes[] data + pBS->SetMem(&RootBrg->AcpiRbRes[0], sizeof(RootBrg->AcpiRbRes),0); + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HbResAllocSubmitResources() +// +// Description: +// Submits the I/O and memory resource requirements for the specified PCI Root Bridge +// +// Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance +// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured +// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid +// EFI_INVALID_PARAMETER - Configuration is NULL +// EFI_INVALID_PARAMETER - Configuration does not point to a valid ACPI resource descriptor +// EFI_INVALID_PARAMETER - Configuration includes a resource descriptor of unsupported type +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HbResAllocSubmitResources( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration) +{ + PCI_ROOT_BRG_DATA *rbdata; + UINTN i, sz=sizeof(UINT32); + EFI_STATUS Status,AllocStatus; +// UINT32 mc; //MemCeil Variable Available? +// EFI_GUID gvg = EFI_GLOBAL_VARIABLE; + ASLR_EndTag *endtag=(ASLR_EndTag*)Configuration; +//----------------------------- + if(!Configuration || !This) return EFI_INVALID_PARAMETER; + + rbdata=GetRbByHandle(This,RootBridgeHandle,&i); + if(!rbdata) { + PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - Invalid RB Hndle Passed\n")); + return EFI_INVALID_PARAMETER; + } + + //Update Internal data structures with Resource Request + Status=SetResources(rbdata, Configuration, tResIoMem, TRUE); + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - Invalid Resoutce Descriptor(s) Passed\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } + + + //Call CSP function to update RB Resources Windows + Status=HbCspSubmitResources((PCI_HOST_BRG_DATA*)This, rbdata,i); + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - HbCspSubmitResources return an ERROR!\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } + rbdata->ResSubmited=TRUE; //set the FLAG + + //Check if we are able to accomodate resource request + //CSP Routine First... + PCI_TRACE((TRACE_PCI,"PciRb: Calling CSP HbCspAllocateResources() - returned ")); + AllocStatus=HbCspAllocateResources((PCI_HOST_BRG_DATA*)This, rbdata,i); + PCI_TRACE((TRACE_PCI,"%r\n", AllocStatus)); + + if(EFI_ERROR(AllocStatus)){ + if( AllocStatus==EFI_UNSUPPORTED ){ + PCI_TRACE((TRACE_PCI,"PciRb: Calling Generic AllocateResources() routine; returned ")); + AllocStatus=AllocateResources(rbdata); + PCI_TRACE((TRACE_PCI,"%r\n", AllocStatus)); + } + //If custom function Fails or Generic on report it. + if(EFI_ERROR(AllocStatus)){ + PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - Fail to allocate resources AllocStatus=%r\n",AllocStatus)); + } + } else { + //Custom function Returned Correct Status: + //Check if Above 4G Memory was correctly updated by custom function + //and if it match with Above4g setup question? + if((gRbSetupData.Above4gDecode==0) && (rbdata->AcpiRbRes[raMmio64].Len!=0)){ + rbdata->AcpiRbRes[raMmio64].Min=0; + rbdata->AcpiRbRes[raMmio64].Max=0; + rbdata->AcpiRbRes[raMmio64].Len=0; + rbdata->AcpiRbRes[raMmio64].AddrUsed=0; + rbdata->AcpiRbRes[raMmio64].AllocType=0; + PCI_TRACE((TRACE_PCI,"PciRB: PCI Above 4G Decode Setup Settings and Custom Alloc Function Data Mismatched\n")); + } + } + + //Check if we can use previoce MRC settings + //if(!mc || EFI_ERROR(Status)){ + Status = HbCspAdjustMemoryMmioOverlap((PCI_HOST_BRG_DATA*)This, rbdata,i ); + + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - AdjustMmioOverlap() returned %r\n",Status)); + //AdjustMmioOverlap() must return SUCCESS or Reset the system... + ASSERT_EFI_ERROR(Status); + } + + //Reflecting What TYPE and HOW MUCH of resouces is not enough... + if(EFI_ERROR(AllocStatus)) { + ((PCI_HOST_BRG_DATA*)This)->AllocPhase--; + FreeUsedResources(rbdata); + Status=AllocStatus; + } + + if(EFI_ERROR(Status))return Status; + + rbdata->ResAsquired=TRUE; //set the FLAG + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HbResAllocGetProposedResources() +// +// Description: +// This function returns the proposed resource settings for the specified +// PCI Root Bridge +// +// Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance +// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured +// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid +// EFI_DEVICE_ERROR - Request failed due to hardware error +// EFI_OUT_OF_RESOURCES - Request failed due to lack of resources +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HbResAllocGetProposedResources( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration) +{ +/* + PCI_ROOT_BRG_DATA *rbdata; + UINTN i; + EFI_STATUS Status; +//----------------------------- + if(!Configuration || !This) return EFI_INVALID_PARAMETER; + + rbdata=GetRbByHandle(This,RootBridgeHandle,&i); + if(!rbdata) { + PCI_TRACE((TRACE_PCI,"Hb.GetProposedResources - Invalid RB Hndle Passed\n")); + return EFI_INVALID_PARAMETER; + } + + //Call CSP function to update RB Resources Windows + Status=HbCspGetProposedResources((PCI_HOST_BRG_DATA*)This, rbdata,i); + + if(EFI_ERROR(Status)){ + PCI_TRACE((TRACE_PCI,"Hb.GetProposedResources - HbCspGetProposedResources return an ERROR!\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } +*/ + + +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO// +// implement this function +// +// +// +// +// +// +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO// + + + return EFI_UNSUPPORTED; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HbResAllocPreprocessController() +// +// Description: +// This function is called for all the PCI controllers that the PCI +// bus driver finds. Can be used to Preprogram the controller. +// +//Arguments: +// Input: +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance +// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured +// EFI_PCI_CONFIGURATION_ADDRESS PciBusAddress Address of the controller on the PCI bus +// EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase The Phase during resource allocation +// +// Output: EFI_STATUS +// EFI_SUCCESS - Success +// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid +// EFI_DEVICE_ERROR - Device pre-initialization failed due to hardware error. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HbResAllocPreprocessController( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN EFI_PCI_CONFIGURATION_ADDRESS PciAddress, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase) +{ +// EFI_STATUS Status=0; + UINTN i; + PCI_ROOT_BRG_DATA *rb; +//----------------------------------- + rb=GetRbByHandle(This,RootBridgeHandle,&i); + ASSERT(rb) + if(!rb) return EFI_INVALID_PARAMETER; + //Call CSP function... + return HbCspPreprocessController((PCI_HOST_BRG_DATA*)This,rb,i,PciAddress,Phase); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SetTmr() +// +// Description: +// Enables timer event to poll PCI IO and MEMORY. +// +//Arguments: +// Input: +// UINT64 Delay Delay value in us +// +// Output: EFI_EVENT if Success +// NULL if unable to set timer event. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_EVENT SetTmr(UINT64 Delay) +{ + EFI_STATUS Status; + EFI_EVENT evt; +//-------------------------------------------- + Status=pBS->CreateEvent(EVT_TIMER,TPL_NOTIFY,NULL,NULL,&evt); + if (EFI_ERROR(Status)) return NULL; + + + Status = pBS->SetTimer(evt, TimerRelative, Delay); + if (EFI_ERROR(Status)){ + pBS->CloseEvent(evt); + evt=NULL; + } + return evt; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: KillTmr() +// +// Description: +// Disables and Clear timer event to poll PCI IO and MEMORY. +// +//Arguments: +// Input: +// EFI_EVENT TmrEvt Timer event to close. +// +// Output: Nothing +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +void KillTmr(EFI_EVENT TmrEvt) +{ + pBS->CloseEvent(TmrEvt); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PollMem +// +// Description: Poll Memory for a value or until times out. +// +// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Memory Width +// IN UINT64 - Memory Address +// IN UINT64 - Bit Mask +// IN UINT64 - Value for exit +// IN UINT64 - Timout +// OUT UINT64 * - Contents of memory +// +// Output: EFI_STATUS +// EFI_SUCCESS - Found value +// EFI_TIMEOUT - Did not find value. +// EFI_INVALID_PARAMETER +// +// Modified: None +// +// Referrals: None +// +// Notes: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PollMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + if (Result==NULL ||((UINTN)Width>=(UINTN)EfiPciWidthFifoUint8)) return EFI_INVALID_PARAMETER; + + Status = PciMemRead(This, Width, Address, 1, Result); //Read memory at least once. + if (EFI_ERROR(Status)) return Status; + + if ((*Result & Mask)==Value) return EFI_SUCCESS; //If correct value, exit. + if (Delay == 0) return EFI_TIMEOUT; + + Event=SetTmr(Delay); + if (!Event) return EFI_NOT_AVAILABLE_YET; + + while(pBS->CheckEvent(Event)==EFI_NOT_READY){ + Status = PciMemRead(This, Width, Address, 1, Result); + if (EFI_ERROR(Status)) break; + if ((*Result & Mask)==Value){ + Status = EFI_SUCCESS; + break; + } else Status=EFI_TIMEOUT; //correct value? + } + KillTmr(Event); //Correct value not read, in time alloted. + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PollIo +// +// Description: Poll IO for a value or until times out. +// +// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Memory Width +// IN UINT64 - Memory Address +// IN UINT64 - Bit Mask +// IN UINT64 - Value for exit +// IN UINT64 - Timout +// OUT UINT64 * - Contents of IO +// +// Output: EFI_STATUS +// EFI_SUCCESS - Found value +// EFI_TIMEOUT - Did not find value. +// EFI_INVALID_PARAMETER +// +// Modified: None +// +// Referrals: None +// +// Notes: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PollIo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + if (Result==NULL) return EFI_INVALID_PARAMETER; + if ((UINTN)Width >= (UINTN)EfiPciWidthFifoUint8) return EFI_INVALID_PARAMETER; + + + Status = PciIoRead(This, Width, Address, 1, Result); //Read memory at least once. + if (EFI_ERROR(Status)) return Status; + + if ((*Result & Mask)==Value) return EFI_SUCCESS; //If correct value, exit. + if (Delay == 0) return EFI_TIMEOUT; + + Event=SetTmr(Delay); + if (!Event) return EFI_NOT_AVAILABLE_YET; + + while(pBS->CheckEvent(Event)==EFI_NOT_READY){ + Status = PciIoRead(This, Width, Address, 1, Result); + if (EFI_ERROR(Status)) break; + if ((*Result & Mask)==Value){ + Status = EFI_SUCCESS; + break; + } else Status=EFI_TIMEOUT; //correct value? + } + KillTmr(Event); //Correct value not read, in time alloted. + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PciMemRead +// +// Description: Read memory IO into buffer. +// +// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Memory Width +// IN UINT64 - Memory Address +// IN UINTN - Number of width reads. +// IN OUT VOID * - Buffer where memory is read into. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful read. +// EFI_INVALID_PARAMETER +// +// Modified: None +// +// Referrals: None +// +// Notes: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PciMemRead ( +IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, +IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, +IN UINT64 Address, +IN UINTN Count, +IN OUT VOID *Buffer) +{ + UINTN IncrementType = Width & ~3; + UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type. + UINT8 IncrementBuffer = 0; + UINT8 IncrementAddress = 0; + + if (Buffer==NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER; + if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER; + + if(sizeof(UINTN)==8){ + if (( 0xffffffffffffffff - Count * IncrementValue) <= Address) + return EFI_INVALID_PARAMETER; + } else { + if ((Address + Count * IncrementValue) > 0xffffffff) + return EFI_INVALID_PARAMETER; + } + + switch (IncrementType) + { + case 0: //EfiPciWidthUintxx + IncrementAddress = IncrementBuffer = IncrementValue; + break; + case 4: //EfiPciWidthFifoUintxx + IncrementBuffer = IncrementValue; + break; + default: //EfiPciWidthFillUintxx + IncrementAddress = IncrementValue; + } + + while(Count--) + { + switch(IncrementValue) + { + case 1: //byte + *(UINT8*) Buffer = *(UINT8*)Address; + break; + case 2: //word + *(UINT16*) Buffer = *(UINT16*)Address; + break; + case 4: //dword + *(UINT32*) Buffer = *(UINT32*)Address; + break; + case 8: //dword + *(UINT64*) Buffer = *(UINT64*)Address; + break; + default: return EFI_INVALID_PARAMETER; + } + (UINT8*) Buffer += IncrementBuffer; + Address += IncrementAddress; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PciMemWrite +// +// Description: Write memory IO from buffer. +// +// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Memory Width +// IN UINT64 - Memory Address +// IN UINTN - Number of width writes. +// IN OUT VOID * - Buffer where memory is written from. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful write. +// EFI_INVALID_PARAMETER +// +// Modified: None +// +// Referrals: None +// +// Notes: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PciMemWrite ( +IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, +IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, +IN UINT64 Address, +IN UINTN Count, +IN OUT VOID *Buffer) +{ + UINTN IncrementType = Width & ~3; + UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type. + UINT8 IncrementBuffer = 0; + UINT8 IncrementAddress = 0; + + if (Buffer==NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER; + if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER; + + if ((Address + Count * IncrementValue) > 0xffffffff) + return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge. + + switch (IncrementType) + { + case 0: //EfiPciWidthUintxx + IncrementAddress = IncrementBuffer = IncrementValue; + break; + case 4: //EfiPciWidthFifoUintxx + IncrementBuffer = IncrementValue; + break; + default: //EfiPciWidthFillUintxx + IncrementAddress = IncrementValue; + } + + while(Count--) + { + switch(IncrementValue) + { + case 1: //byte + *(UINT8*) Address = *(UINT8*)Buffer; + break; + case 2: //word + *(UINT16*) Address = *(UINT16*)Buffer; + break; + case 4: //dword + *(UINT32*) Address = *(UINT32*)Buffer; + break; + case 8: //dword + *(UINT64*) Address = *(UINT64*)Buffer; + break; + default: return EFI_INVALID_PARAMETER; + } + (UINT8*) Buffer += IncrementBuffer; + Address += IncrementAddress; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PciIoRead +// +// Description: Read IO into buffer. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Io Width +// IN UINT64 - Io Address +// IN UINTN - Number of width reads. +// IN OUT VOID * - Buffer where Io is read into. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful read. +// EFI_INVALID_PARAMETER +// +// Modified: None +// +// Referrals: None +// +// Notes: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PciIoRead ( +IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, +IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, +IN UINT64 Address, +IN UINTN Count, +IN OUT VOID *Buffer) +{ + UINTN IncrementType = Width & ~3; + UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type. + UINT8 IncrementBuffer = 0; + UINT8 IncrementAddress = 0; + + if (Buffer==NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER; + if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER; + + if ((Address + Count * IncrementValue) > 0xffff) + return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge. + + switch (IncrementType) + { + case 0: //EfiPciWidthUintxx + IncrementAddress = IncrementBuffer = IncrementValue; + break; + case 4: //EfiPciWidthFifoUintxx + IncrementBuffer = IncrementValue; + break; + default: //EfiPciWidthFillUintxx + IncrementAddress = IncrementValue; + } + + while(Count--) + { + switch(IncrementValue) + { + case 1: //byte + *(UINT8*) Buffer = IoRead8((UINT16)Address); + break; + case 2: //word + *(UINT16*) Buffer = IoRead16((UINT16)Address); + break; + case 4: //dword + *(UINT32*) Buffer = IoRead32((UINT16)Address); + break; + case 8: + *(UINT32*) Buffer = IoRead32((UINT16)Address); + *((UINT32*)((UINT32*)Buffer+1)) = IoRead32((UINT16)(Address+4)); + break; + default: return EFI_INVALID_PARAMETER; + } + (UINT8*) Buffer += IncrementBuffer; + Address += IncrementAddress; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PciIoWrite +// +// Description: Write IO from buffer. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol instance +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Pci Width +// IN UINT64 Address IO Address +// IN UINTN Count Number of width writes. +// IN OUT VOID *Buffer where Pci registers are written from. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful write. +// EFI_INVALID_PARAMETER +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PciIoWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer) +{ + UINTN IncrementType = Width & ~3; + UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type. + UINT8 IncrementBuffer = 0; + UINT8 IncrementAddress = 0; + + if (Buffer==NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER; + if (IncrementType > 16 || IncrementValue > 4) return EFI_INVALID_PARAMETER; + + if ((Address + Count * IncrementValue) > 0xffff) + return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge. + + switch (IncrementType) + { + case 0: //EfiPciWidthUintxx + IncrementAddress = IncrementBuffer = IncrementValue; + break; + case 4: //EfiPciWidthFifoUintxx + IncrementBuffer = IncrementValue; + break; + default: //EfiPciWidthFillUintxx + IncrementAddress = IncrementValue; + } + + while(Count--) + { + switch(IncrementValue) + { + case 1: //byte + IoWrite8((UINT16)Address,*(UINT8*) Buffer); + break; + case 2: //word + IoWrite16((UINT16)Address,*(UINT16*) Buffer); + break; + default: //dword + IoWrite32((UINT16)Address,*(UINT32*) Buffer); + break; + } + (UINT8*) Buffer += IncrementBuffer; + Address += IncrementAddress; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CopyMem +// +// Description: Copy PCI memory to PCI memory in bridge. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol instance +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Pci Width +// IN UINT64 DestAddress Pci Address +// IN UINT64 SrcAddress Pci Address +// IN UINTN Count Number of width writes. +// IN OUT VOID *Buffer where Pci registers are written from. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful copy. +// EFI_INVALID_PARAMETER +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CopyMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count) +{ + INTN IncrementValue; + + if ((SrcAddress == 0) || (DestAddress==0)) return EFI_INVALID_PARAMETER; + if ((UINTN)Width > (UINTN)EfiPciWidthUint64) return EFI_INVALID_PARAMETER; + + IncrementValue = (INTN)1<<(Width&3); + if ((SrcAddress + Count * IncrementValue) > 0xffffffff) + return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge. + + if ((DestAddress + Count * IncrementValue) > 0xffffffff) + return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge. + + + if (SrcAddress==DestAddress) return EFI_SUCCESS; //Nothing to do. + + + if ( (DestAddress > SrcAddress) && (SrcAddress + Count * IncrementValue) ) { + SrcAddress += (Count-1) * IncrementValue; //End of source + DestAddress += (Count-1) * IncrementValue; //End of destination + IncrementValue = -IncrementValue; //Count backwards. + } //If Destination addres and after and overlapps Source Address, Copy backwards. + + switch(IncrementValue) + { + case 1: + case -1: + while (Count--) + { + *(UINT8*) DestAddress = *(UINT8*)SrcAddress; + SrcAddress += IncrementValue; + DestAddress += IncrementValue; + } + break; + case 2: + case -2: + while (Count--) + { + *(UINT16*) DestAddress = *(UINT16*)SrcAddress; + SrcAddress += IncrementValue; + DestAddress += IncrementValue; + } + break; + default: + while (Count--) + { + *(UINT32*) DestAddress = *(UINT32*)SrcAddress; + SrcAddress += IncrementValue; + DestAddress += IncrementValue; + } + break; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PciRead() +// +// Description: +// Read Pci registers into buffer. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol instance +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Pci Width +// IN UINT64 Address Pci Address +// IN UINTN Count Number of width writes. +// IN OUT VOID *Buffer where Pci registers are written from. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful read. +// EFI_INVALID_PARAMETER +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PciRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer) +{ + PCI_ROOT_BRG_DATA *Private = (PCI_ROOT_BRG_DATA*)This; + + if (Buffer == NULL ||((UINTN)Width>=(UINTN)EfiPciWidthMaximum) ) return EFI_INVALID_PARAMETER; + + return RootBridgeIoPciRW (Private, Width, Address, Count, Buffer, FALSE); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PciWrite() +// +// Description: +// Write Pci registers from buffer. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol instance +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Pci Width +// IN UINT64 Address Pci Address +// IN UINTN Count Number of width writes. +// IN OUT VOID *Buffer where Pci registers are written from. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful write. +// EFI_INVALID_PARAMETER +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PciWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer) +{ + PCI_ROOT_BRG_DATA *Private = (PCI_ROOT_BRG_DATA*)This; + + if (Buffer == NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER; + + Private = (PCI_ROOT_BRG_DATA *) This; + + return RootBridgeIoPciRW (Private, Width, Address, Count, Buffer, TRUE); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: Map() +// +// Description: +// Provide addresses required to access system memory from a DMA +// bus master. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation +// IN VOID *HostAddress Host address +// IN OUT UINTN **NumberOfBytes Number of bytes +// OUT EFI_PHYSICAL_ADDRESS *DeviceAddress Device Address +// OUT VOID **Mapping +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful map +// +// Modified: None +// +// Referrals: None +// +// Notes: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS Map ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping) +{ + EFI_STATUS Status; +// PCI_ROOT_BRIDGE_MAPPING *mapping; + EFI_PHYSICAL_ADDRESS addr; +//------------------------------------------------- + + if ( !HostAddress || !NumberOfBytes || !DeviceAddress || !Mapping ) + return EFI_INVALID_PARAMETER; + + if ((UINT32)Operation >= (UINT32)EfiPciOperationMaximum ) return EFI_INVALID_PARAMETER; + + *Mapping=NULL; + + addr=(EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + + if ((addr + *NumberOfBytes) > 0xffffffff)Status=RbCspIoPciMap((PCI_ROOT_BRG_DATA*)This, + Operation, addr, NumberOfBytes, DeviceAddress, Mapping); + else *DeviceAddress = addr; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: Unmap +// +// Description: Remove mapping +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance +// IN VOID *Mapping Pointer to Mapping formation to Unmap +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful unmapping. +// EFI_INVALID_PARAMETER +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS Unmap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping) + +{ + EFI_STATUS Status=EFI_SUCCESS; + PCI_ROOT_BRIDGE_MAPPING *mapping=(PCI_ROOT_BRIDGE_MAPPING*)Mapping; +//------- + + if (mapping!=NULL) Status=RbCspIoPciUnmap((PCI_ROOT_BRG_DATA*)This,mapping); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: AllocateBuffer +// +// Description: Allocate buffer for PCI use. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance +// IN EFI_ALLOCATE_TYPE Type Alloocation Type (ignored and uses AllocateMaxAddress) +// IN EFI_MEMORY_TYPE MemoryType Memory Type (ex. EfiBootServicesData) +// IN UINTN Pages Number of pages to allocate. +// OUT VOID **HostAddress Host Address +// IN UINT64 Attributes Allocation Attributes. +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful allocation. +// EFI_UNSUPPORTED - Attribute not supported. +// EFI_INVALID_PARAMETER +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +#define BUFF_ATTR (EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |\ + EFI_PCI_ATTRIBUTE_MEMORY_CACHED |\ + EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) +//--------------------------------------------------------------- +EFI_STATUS AllocateBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes) + +{ + //PCI_ROOT_BRIDGE_STRUCT *Private = (PCI_ROOT_BRIDGE_STRUCT *)This; + + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS addr; + + if (HostAddress == NULL) return EFI_INVALID_PARAMETER; + + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) + return EFI_INVALID_PARAMETER; + + //Check if legal Attributes for this function is passed + //Check if any other Attributes set except supported + if( Attributes & ~BUFF_ATTR ) return EFI_UNSUPPORTED; + + + //865 chipset does not support any of Attributes above so as spec. says ignore it + //and Allocate buffer + // Limit allocations to memory below 4GB + addr = 0xffffffff; + + Status = pBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &addr); + if (EFI_ERROR(Status)) return Status; + + *HostAddress = (VOID *)(UINTN)addr; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: FreeBuffer() +// +// Description: Frees buffer +// +// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance +// IN UINTN Pages Number of pages to free. +// IN VOID* HostAddress Host Address +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful free. +// EFI_INVALID_PARAMETER +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FreeBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress) + +{ + return pBS->FreePages((EFI_PHYSICAL_ADDRESS) HostAddress, Pages); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: Flush() +// +// Description: +// Flush buffer used by PCI DMA Transfere. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful flushing +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS Flush (IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This) +{ + return EFI_SUCCESS; //Doesn't need buffer to be flushed. +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: GetAttributes() +// +// Description: Get Supported and Current Root Bridge Attributes. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance +// OUT UINT64 *Supported Supported Attributes +// OUT UINT64 *Attributes Current Attributes +// +// Output: EFI_STATUS +// EFI_SUCCESS - Successful reading attributes. +// EFI_INVALID_PARAMETER - If both for attributes are invalid. +// +// Notes: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supported, + OUT UINT64 *Attributes) +{ + PCI_ROOT_BRG_DATA *Private = (PCI_ROOT_BRG_DATA*) This; + + if (Attributes == NULL && Supported == NULL) return EFI_INVALID_PARAMETER; + + if (Supported) *Supported = Private->Supports; + if (Attributes) *Attributes = Private->Attributes; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: GetAttributes() +// +// Description: Get Supported and Current Root Bridge Attributes. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance +// IN UINT64 Attributes +// IN OUT UINT64 *ResourceBase Resource Base (optional, unused) +// IN OUT UINT64 *ResourceLength Resource Length (optional, unused) +// +// Output: EFI_STATUS +// EFI_SUCCESS Successful setting attributes. +// EFI_UNSUPPORTED Unsupported attributes +// +// Notes: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength) +{ + EFI_STATUS Status; + PCI_ROOT_BRG_DATA *Private = (PCI_ROOT_BRG_DATA *) This; +//------------------------------------ + + + //First Check if RB supports passed Attributes + if((Attributes & Private->Supports)!=Attributes)return EFI_UNSUPPORTED; + + //Note: Only some attributes can be both enabled and disabled. + + Status=RbCspIoPciAttributes(Private, Attributes, ResourceBase, ResourceLength); + + if(EFI_ERROR(Status)) return Status; + + //Update the attributes property + //Private->Attributes&=Attributes; //reset all bits that has to be reseted + Private->Attributes |= Attributes; //set bits that has to be seted + + return Status; +} +//-------------------------------------------------- + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: Configuration() +// +// Description: Returns, using ACPI 2.0 Descriptors, resources allocated. +// +// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This +// IN VOID *Resources +// +// Output: EFI_STATUS +// EFI_SUCCESS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS Configuration ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources) +{ + PCI_ROOT_BRG_DATA *rb=(PCI_ROOT_BRG_DATA*)This; + EFI_STATUS Status=0; +//--------------------- + if(rb->ResAsquired) + Status=GetResources((PCI_ROOT_BRG_DATA*)This, (ASLR_QWORD_ASD**)Resources, tResAll); + else Status=EFI_NOT_AVAILABLE_YET; + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: PciRw() +// +// Description: Provides Read and Write access to the PCI Configuration Space. +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Data Width. +// IN UINT64 Address PCI Config Address +// IN UINT32 Mask Mask for the bits to be preserved +// IN UINT32 Value Data to be written +// +// Output: EFI_STATUS +// EFI_SUCCESS - OK +// EFI_DEVICE_ERROR - HW ERROR +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID PciRw ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT32 Mask, + IN UINT32 Value + ) +{ + EFI_STATUS Status; + UINT32 Data; + + Status = This->Pci.Read (This,Width,Address,1,&Data); + ASSERT_EFI_ERROR (Status); + + Data = (Data & Mask) | Value; + Status = This->Pci.Write (This,Width,Address,1,&Data); + ASSERT_EFI_ERROR (Status); +} + + + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |