//********************************************************************** //********************************************************************** //** ** //** (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 // //********************************************************************** // // // Name: PciHostBridge.c // // Description: AMI's Native Root Bridge Protocol Implementation // // //********************************************************************** #include #include #include #include #include #include "PciPort.h" #include "PciSetup.h" // //---------------------------------------------------------------------------- // Name: gAmiBoardProtocol // // Description: Ami Board Info Protocol Instance. // //---------------------------------------------------------------------------- // 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}; // //---------------------------------------------------------------------------- // 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 // //---------------------------------------------------------------------------- // 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 // //---------------------------------------------------------------------------- // Name: *gPciSetupData; PciSetupDataBuffer // // Description: Global Setup Variable to get the setup settings pointer. // // Notes: PCI_SETUP_DATA // //---------------------------------------------------------------------------- // 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 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // //---------------------------------------------------------------------------- // 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. // //---------------------------------------------------------------------------- // 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;iBusBuild ==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(iHdr.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; iImageHandle=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; jRootBridgeCount; 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; iRootBridgeCount; 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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; iPciBusNumber, &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; } // //---------------------------------------------------------------------------- // Procedure: HpcInitGetRootHpcList // // Description: GetRootHpcList() Function of the PCI Root Hotplug Controller // Initialization Protocol. See PI 1.1 Spec or details // //---------------------------------------------------------------------------- // 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; iHpcLocCount; 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; } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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; } } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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; iPadding[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; iPadding[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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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;iResCount;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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; iRootBridgeCount; j++){ rb=hb->RootBridges[j]; PCI_TRACE((TRACE_PCI,"PciRootBrg: Host[ %d ].Root[ %d ] \n", i, j)); for(k=raBus; kRootBridgeCount; 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; iRootBridgeCount; 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); } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; iAddMemorySpace(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; iAddIoSpace(EfiGcdIoTypeIo,pIo[i].BaseAddress,pIo[i].Length); ASSERT_EFI_ERROR(Status); if(EFI_ERROR(Status)) return Status; } pBS->FreePool(pIo); return Status; } // //---------------------------------------------------------------------------- // 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 ... //---------------------------------------------------------------------------- // BOOLEAN IsResSubmited(PCI_HOST_BRG_DATA *Host){ PCI_ROOT_BRG_DATA *rb; UINTN i; //--------------------- for(i=0; iRootBridges[i]; if(!rb->ResSubmited) return FALSE; } return TRUE; } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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;iRootBridgeCount;i++){ rbdata=hbdata->RootBridges[i]; if(rbdata->RbHandle==RbHandle){ if(Index)(*Index)=i; // hbdata->CurrentRb=i; return rbdata; } } return NULL; } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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;iResCount;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; iResCount; 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; } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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; iResInitCnt,res))) return EFI_OUT_OF_RESOURCES; } return EFI_SUCCESS; } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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 // //---------------------------------------------------------------------------- // 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 // //---------------------------------------------------------------------------- // 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) // //---------------------------------------------------------------------------- // Procedure: AlignFromGra() // // Description: // Converts C passed into Alignment format // // Input: // UINTN g AlignFromGra Value to convert // // Output: UINTN // Converted Alignment value. //---------------------------------------------------------------------------- // UINTN AlignFromGra(UINTN g){ UINTN a=0; //------------ while(g&1){ a++; g=g>>1; } return a; } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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; iResCount; 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_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 //********************************************************************** // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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; iRootBridgeCount; 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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; } } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; iResCount; 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); } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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); } // //---------------------------------------------------------------------------- // 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. //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // 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 //---------------------------------------------------------------------------- // void KillTmr(EFI_EVENT TmrEvt) { pBS->CloseEvent(TmrEvt); } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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); } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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); } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // #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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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); } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // EFI_STATUS Flush (IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This) { return EFI_SUCCESS; //Doesn't need buffer to be flushed. } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } //-------------------------------------------------- // //---------------------------------------------------------------------------- // // 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 // //---------------------------------------------------------------------------- // 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; } // //---------------------------------------------------------------------------- // // 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 //---------------------------------------------------------------------------- // 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 ** //** ** //********************************************************************** //**********************************************************************