/**@file Copyright (c) 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "TbtSmiHandler.h" #include #include #include #include #include #include #include #define MEM_PER_SLOT (DEF_RES_MEM_PER_DEV << 4) #define PMEM_PER_SLOT (DEF_RES_PMEM_PER_DEV << 4) #define IO_PER_SLOT (DEF_RES_IO_PER_DEV << 2) GLOBAL_REMOVE_IF_UNREFERENCED UINTN gDeviceBaseAddress; // //US(X:0:0), DS(X+1:3:0),DS(X+1:4:0),DS(X+1:5:0),DS(X+1:6:0) // GLOBAL_REMOVE_IF_UNREFERENCED BRDG_CONFIG HrConfigs[MAX_CFG_PORTS]; extern UINT8 gCurrentDiscreteTbtRootPort; extern UINT8 gCurrentDiscreteTbtRootPortType; BOOLEAN isLegacyDevice = FALSE; STATIC UINT8 TbtSegment = 0; STATIC VOID PortInfoInit ( IN OUT PORT_INFO *PortInfo ) { PortInfo->BusNumLimit = 4; } STATIC VOID UnsetVesc ( IN UINT8 Bus, IN UINT8 Dev, IN UINT8 Fun ) { UINT8 Dbus; UINT32 Data32; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0); // // Check for abcence of DS bridge // if(0xFFFF == PciSegmentRead16(gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) { return; } // // Unset vesc_reg2[23] bit (to have an option to access below DS) // Data32 = PciSegmentRead32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2); Data32 &= 0xFF7FFFFF; PciSegmentWrite32(gDeviceBaseAddress + PCI_TBT_VESC_REG2, Data32); // // Go to Device behind DS // Dbus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); DEBUG((DEBUG_INFO, "Dbus = %d\n",Dbus)); // // Check if there is something behind this Downstream Port (Up or Ep) // If there nothing behind Downstream Port Set vesc_reg2[23] bit -> this will flush all future MemWr // gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Dbus, 0x00, 0x00, 0); if(0xFFFF == PciSegmentRead16(gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) { gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0); Data32 = PciSegmentRead32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2); Data32 |= 0x00800000; PciSegmentWrite32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2, Data32); } }// Unset_VESC_REG2 STATIC UINT16 MemPerSlot ( IN UINT16 CurrentUsage ) { if (CurrentUsage == 0) { return 0; } if (CurrentUsage <= 16) { return 16; } if (CurrentUsage <= 64) { return 64; } if (CurrentUsage <= 128) { return 128; } if (CurrentUsage <= 256) { return 256; } if (CurrentUsage <= 512) { return 512; } if (CurrentUsage <= 1024) { return 1024; } return CurrentUsage; } // MemPerSlot STATIC UINT64 PMemPerSlot ( IN UINT64 CurrentUsage ) { if (CurrentUsage == 0) { return 0; } if (CurrentUsage <= 1024ULL) { return 1024ULL; } if (CurrentUsage <= 4096ULL) { return 4096ULL; } return CurrentUsage; } // PMemPerSlot STATIC VOID SetPhyPortResources ( IN UINT8 Bus, IN UINT8 Dev, IN UINT8 SubBus, IN INT8 Depth, IN PORT_INFO *CurrentPi, IN OUT PORT_INFO *PortInfo ) { UINT8 Cmd; UINT16 DeltaMem; UINT64 DeltaPMem; Cmd = CMD_BUS_MASTER; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, 0x00, 0); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, SubBus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd); DeltaMem = PortInfo->MemBase - CurrentPi->MemBase; if (isLegacyDevice) { if (Depth >= 0 && (DeltaMem < MEM_PER_SLOT)) { PortInfo->MemBase += MEM_PER_SLOT - DeltaMem; } } else { if (DeltaMem < MemPerSlot (DeltaMem)) { PortInfo->MemBase += MemPerSlot (DeltaMem) - DeltaMem; } } if (PortInfo->MemBase > CurrentPi->MemBase && (PortInfo->MemBase - 0x10) <= PortInfo->MemLimit) { PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), CurrentPi->MemBase); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), PortInfo->MemBase - 0x10); Cmd |= CMD_BM_MEM; } else { PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20); PortInfo->MemBase = CurrentPi->MemBase; } DeltaPMem = PortInfo->PMemBase64 - CurrentPi->PMemBase64; if (isLegacyDevice) { if ((Depth >= 0) && ((UINTN)DeltaPMem < (UINTN)PMEM_PER_SLOT)) { PortInfo->PMemBase64 += PMEM_PER_SLOT - DeltaPMem; } } else { if (DeltaPMem < PMemPerSlot (DeltaPMem)) { PortInfo->PMemBase64 += PMemPerSlot (DeltaPMem) - DeltaPMem; } } if (PortInfo->PMemBase64 > CurrentPi->PMemBase64 && (PortInfo->PMemBase64 - 0x10) <= PortInfo->PMemLimit64) { PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (CurrentPi->PMemBase64 & 0xFFFF)); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) ((PortInfo->PMemBase64 - 0x10) & 0xFFFF)); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (CurrentPi->PMemBase64 >> 16)); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) ((PortInfo->PMemBase64 - 0x10) >> 16)); Cmd |= CMD_BM_MEM; } else { PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), 0); PortInfo->PMemBase64 = CurrentPi->PMemBase64; } PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd); PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE); } // SetPhyPortResources STATIC UINT32 SaveSetGetRestoreBar ( IN UINTN Bar ) { UINT32 BarReq; UINT32 OrigBar; OrigBar = PciSegmentRead32(Bar); // Save BAR PciSegmentWrite32(Bar, 0xFFFFFFFF); // Set BAR BarReq = PciSegmentRead32(Bar); // Get BAR PciSegmentWrite32(Bar, OrigBar); // Restore BAR return BarReq; } // SaveSetGetRestoreBar STATIC VOID SetIoBar ( IN UINTN BAR, IN UINT32 BarReq, IN OUT UINT8 *Cmd, IN OUT IO_REGS *IoReg ) { UINT16 Alignment; UINT16 Size; UINT16 NewBase; Alignment = ~(BarReq & 0xFFFC); Size = Alignment + 1; if (IoReg->Base > IoReg->Limit || !Size) { return ; } NewBase = BAR_ALIGN (IoReg->Base, Alignment); if (NewBase > IoReg->Limit || NewBase + Size - 1 > IoReg->Limit) { return ; } PciSegmentWrite16(BAR, NewBase); IoReg->Base = NewBase + Size; // Advance to new position *Cmd |= CMD_BM_IO; // Set Io Space Enable } // SetIoBar STATIC VOID SetMemBar ( IN UINTN BAR, IN UINT32 BarReq, IN OUT UINT8 *Cmd, IN OUT MEM_REGS *MemReg ) { UINT32 Alignment; UINT32 Size; UINT32 NewBase; Alignment = ~(BarReq & 0xFFFFFFF0); Size = Alignment + 1; if (MemReg->Base > MemReg->Limit || !Size) { return ; } NewBase = BAR_ALIGN (MemReg->Base, Alignment); if (NewBase > MemReg->Limit || NewBase + Size - 1 > MemReg->Limit) { return ; } PciSegmentWrite32(BAR, NewBase); MemReg->Base = NewBase + Size; // Advance to new position *Cmd |= CMD_BM_MEM; // Set Memory Space Enable } // SetMemBar STATIC VOID SetPMem64Bar ( IN UINTN BAR, IN BOOLEAN IsMaxBar, IN UINT32 BarReq, IN OUT UINT8 *Cmd, IN OUT PMEM_REGS *MemReg ) { UINT32 Alignment; UINT32 Size; UINT64 NewBase; Alignment = ~(BarReq & 0xFFFFFFF0); Size = Alignment + 1; if (MemReg->Base64 > MemReg->Limit64 || !Size) { return ; } NewBase = BAR_ALIGN (MemReg->Base64, Alignment); if (NewBase > MemReg->Limit64 || NewBase + Size - 1 > MemReg->Limit64) { return ; } PciSegmentWrite32(BAR, (UINT32)(NewBase & 0xFFFFFFFF)); if (!IsMaxBar) { BAR++; PciSegmentWrite32(BAR, (UINT32)(NewBase >> 32)); } MemReg->Base64 = NewBase + Size; // Advance to new position *Cmd |= CMD_BM_MEM; // Set Memory Space Enable } // SetPMem64Bar STATIC VOID SetDevResources ( IN UINT8 Bus, IN UINT8 Dev, IN UINT8 MaxFun, // PCI_MAX_FUNC for devices, 1 for bridge IN UINT8 MaxBar, // PCI_BAR5 for devices, PCI_BAR1 for bridge IN OUT PORT_INFO *PortInfo ) { UINT8 Fun; UINT8 Reg; UINT32 BarReq; IO_REGS Io; MEM_REGS Mem; PMEM_REGS PMem; UINT8 Cmd; Io.Base = PortInfo->IoBase << 8; Io.Limit = (PortInfo->IoLimit << 8) | 0xFF; Mem.Base = PortInfo->MemBase << 16; Mem.Limit = (PortInfo->MemLimit << 16) | 0xFFFF; PMem.Base64 = PortInfo->PMemBase64 << 16; PMem.Limit64 = (PortInfo->PMemLimit64 << 16) | 0xFFFF; for (Fun = 0; Fun < MaxFun; ++Fun) { gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0); PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BUS_MASTER); Cmd = PciSegmentRead8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET); if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) { continue; } for (Reg = PCI_BASE_ADDRESSREG_OFFSET; Reg <= MaxBar; Reg += 4) { BarReq = SaveSetGetRestoreBar(gDeviceBaseAddress + Reg); // Perform BAR sizing if (BarReq & BIT0) { // // I/O BAR // SetIoBar ( (gDeviceBaseAddress + Reg), BarReq, &Cmd, &Io ); continue; } if (BarReq & BIT3) { // // P-Memory BAR // SetPMem64Bar ((gDeviceBaseAddress + Reg), MaxBar == Reg, BarReq, &Cmd, &PMem); } else { SetMemBar ((gDeviceBaseAddress + Reg), BarReq, &Cmd, &Mem); } if (BIT2 == (BarReq & (BIT2 | BIT1))) { // // Base address is 64 bits wide // Reg += 4; if (!(BarReq & BIT3)) { // // 64-bit memory bar // PciSegmentWrite32 (gDeviceBaseAddress + Reg, 0); } } } if (Cmd & BIT1) { // // If device uses I/O and MEM mapping use only MEM mepping // Cmd &= ~BIT0; } PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd); PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE); } // // Update PortInfo if any changes // if (Io.Base > ((UINT32) PortInfo->IoBase << 8)) { PortInfo->IoBase = (UINT8) (BAR_ALIGN (Io.Base, 0xFFF) >> 8); } if (Mem.Base > ((UINT32) PortInfo->MemBase << 16)) { PortInfo->MemBase = (UINT16) (BAR_ALIGN (Mem.Base, 0xFFFFF) >> 16); } if (PMem.Base64 > (PortInfo->PMemBase64 << 16)) { PortInfo->PMemBase64 = (BAR_ALIGN (PMem.Base64, 0xFFFFF) >> 16); } } // SetDevResources STATIC VOID InitARHRConfigs( IN HR_CONFIG *Hr_Config, IN UINT8 BusNumLimit, IN OUT BRDG_RES_CONFIG* HrResConf ) { UINT8 i,j; // // DS port for USB device // HrConfigs[AR_DS_PORT2].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1; HrConfigs[AR_DS_PORT2].DevId.Dev = 2; HrConfigs[AR_DS_PORT2].DevId.Fun = 0; HrConfigs[AR_DS_PORT2].PBus = HrConfigs[AR_DS_PORT2].DevId.Bus; HrConfigs[AR_DS_PORT2].SBus = HrConfigs[AR_DS_PORT2].PBus + 1; HrConfigs[AR_DS_PORT2].SubBus = HrConfigs[AR_DS_PORT2].PBus + 1; // // CIO port // HrConfigs[AR_DS_PORT1].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1; HrConfigs[AR_DS_PORT1].DevId.Dev = 1; HrConfigs[AR_DS_PORT1].DevId.Fun = 0; HrConfigs[AR_DS_PORT1].PBus = HrConfigs[AR_DS_PORT1].DevId.Bus; HrConfigs[AR_DS_PORT1].SBus = HrConfigs[HR_DS_PORT0].SubBus + 1; HrConfigs[AR_DS_PORT1].SubBus = BusNumLimit; switch(Hr_Config->DeviceId) { // // HR with 1 DS and 1 USB // case AR_HR_2C: case AR_HR_LP: case AR_HR_C0_2C: case TR_HR_2C: Hr_Config->MinDSNumber = HrConfigs[AR_DS_PORT1].DevId.Dev; Hr_Config->MaxDSNumber = HrConfigs[AR_DS_PORT2].DevId.Dev; Hr_Config->BridgeLoops = 4; break; // // HR with 2 DS and 1 USB // case AR_HR_4C: case TR_HR_4C: case AR_HR_C0_4C: Hr_Config->MinDSNumber = 1; Hr_Config->MaxDSNumber = 4; Hr_Config->BridgeLoops = 6; for(j = 2, i = Hr_Config->MinDSNumber; j < count(HrConfigs) && i <= Hr_Config->MaxDSNumber; ++j, ++i) { HrConfigs[j].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1; HrConfigs[j].DevId.Dev = i; HrConfigs[j].DevId.Fun = 0; HrConfigs[j].PBus = HrConfigs[j].DevId.Bus; HrConfigs[j].Res.Cls = DEF_CACHE_LINE_SIZE; } break; } }//InitARHRConfigs STATIC VOID InitCommonHRConfigs ( IN HR_CONFIG *Hr_Config, IN UINT8 BusNumLimit, IN OUT BRDG_RES_CONFIG *HrResConf ) { UINT8 i; UINT8 j; for(i = 0; i < count(HrConfigs); ++i) { HrConfigs[i].IsDSBridge = TRUE; } // // US(HRBus:0:0) // HrConfigs[HR_US_PORT].DevId.Bus = Hr_Config->HRBus; HrConfigs[HR_US_PORT].DevId.Dev = 0; HrConfigs[HR_US_PORT].DevId.Fun = 0; HrConfigs[HR_US_PORT].Res = *HrResConf; HrConfigs[HR_US_PORT].Res.IoBase = 0xF1; HrConfigs[HR_US_PORT].Res.IoLimit = 0x01; HrConfigs[HR_US_PORT].PBus = HrConfigs[HR_US_PORT].DevId.Bus; HrConfigs[HR_US_PORT].SBus = HrConfigs[HR_US_PORT].PBus + 1; HrConfigs[HR_US_PORT].SubBus = BusNumLimit; HrConfigs[HR_US_PORT].IsDSBridge = FALSE; // // HIA resides here // HrConfigs[HR_DS_PORT0].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1; HrConfigs[HR_DS_PORT0].DevId.Dev = 0; HrConfigs[HR_DS_PORT0].DevId.Fun = 0; HrConfigs[HR_DS_PORT0].Res = NOT_IN_USE_BRIDGE; HrConfigs[HR_DS_PORT0].Res.MemBase = HrResConf->MemLimit; HrConfigs[HR_DS_PORT0].Res.MemLimit = HrResConf->MemLimit; HrResConf->MemLimit -= 0x10; //This 1 MB chunk will be used by HIA HrConfigs[HR_DS_PORT0].Res.Cmd = CMD_BM_MEM; HrConfigs[HR_DS_PORT0].Res.Cls = DEF_CACHE_LINE_SIZE; HrConfigs[HR_DS_PORT0].PBus = HrConfigs[HR_DS_PORT0].DevId.Bus; HrConfigs[HR_DS_PORT0].SBus = HrConfigs[HR_DS_PORT0].PBus + 1; HrConfigs[HR_DS_PORT0].SubBus = HrConfigs[HR_DS_PORT0].PBus + 1; switch (Hr_Config->DeviceId) { // // Alpine Ridge // case AR_HR_2C: case AR_HR_C0_2C: case AR_HR_LP: case AR_HR_4C: case AR_HR_C0_4C: // // Titan Ridge // case TR_HR_2C: case TR_HR_4C: InitARHRConfigs(Hr_Config, BusNumLimit, HrResConf); break; default: // // DS(HRBus+2:3-6:0) // Hr_Config->MinDSNumber = 3; Hr_Config->MaxDSNumber = 6; Hr_Config->BridgeLoops = count (HrConfigs); for (j = 2, i = Hr_Config->MinDSNumber; j < count (HrConfigs) && i <= Hr_Config->MaxDSNumber; ++j, ++i) { HrConfigs[j].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1; HrConfigs[j].DevId.Dev = i; HrConfigs[j].DevId.Fun = 0; HrConfigs[j].PBus = HrConfigs[j].DevId.Bus; HrConfigs[j].Res.Cls = DEF_CACHE_LINE_SIZE; } } } // InitCommonHRConfigs STATIC VOID InitHRDSPort_Disable ( IN UINT8 id, IN OUT BRDG_CONFIG *BrdgConf ) { HrConfigs[id].Res = NOT_IN_USE_BRIDGE; HrConfigs[id].SBus = BrdgConf->SBus; HrConfigs[id].SubBus = BrdgConf->SBus; BrdgConf->SBus++; } // InitHRDSPort_Disable //AR only STATIC VOID InitARDSPort_1Port( IN OUT BRDG_CONFIG* BrdgConf ) { UINT16 MemBase = BrdgConf->Res.MemBase & 0xFFF0; UINT64 PMemBase64 = BrdgConf->Res.PMemBase64 & ~0xFULL; UINT8 BusRange = BrdgConf->SubBus - BrdgConf->PBus - 2; HrConfigs[AR_DS_PORT1].Res = NOT_IN_USE_BRIDGE; HrConfigs[AR_DS_PORT1].Res.Cls = DEF_CACHE_LINE_SIZE; HrConfigs[AR_DS_PORT1].Res.Cmd = CMD_BM_MEM; HrConfigs[AR_DS_PORT1].Res.MemBase = MemBase; HrConfigs[AR_DS_PORT1].Res.MemLimit = BrdgConf->Res.MemLimit - 1; HrConfigs[AR_DS_PORT1].Res.PMemBase64 = PMemBase64; HrConfigs[AR_DS_PORT1].Res.PMemLimit64 = BrdgConf->Res.PMemLimit64; HrConfigs[AR_DS_PORT1].SBus = BrdgConf->SBus; HrConfigs[AR_DS_PORT1].SubBus = BrdgConf->SBus + BusRange; BrdgConf->SBus = HrConfigs[AR_DS_PORT1].SubBus + 1; HrConfigs[AR_DS_PORT2].Res = NOT_IN_USE_BRIDGE; HrConfigs[AR_DS_PORT2].Res.Cls = DEF_CACHE_LINE_SIZE; HrConfigs[AR_DS_PORT2].Res.Cmd = CMD_BM_MEM; HrConfigs[AR_DS_PORT2].Res.MemBase = BrdgConf->Res.MemLimit; HrConfigs[AR_DS_PORT2].Res.MemLimit = BrdgConf->Res.MemLimit; HrConfigs[AR_DS_PORT2].SBus = BrdgConf->SBus; HrConfigs[AR_DS_PORT2].SubBus = BrdgConf->SBus; BrdgConf->SBus = HrConfigs[AR_DS_PORT2].SubBus + 1; }//InitARDSPort_1Port STATIC VOID InitARDSPort_2Port( IN OUT BRDG_CONFIG* BrdgConf ) { UINT16 MemBase = BrdgConf->Res.MemBase & 0xFFF0; UINT64 PMemBase64 = BrdgConf->Res.PMemBase64 & ~0xFULL; UINT8 BusRange = BrdgConf->SubBus - BrdgConf->PBus - 3; // Busses are split between ports 1 and 4 BusRange /= 2; HrConfigs[AR_DS_PORT1].Res = NOT_IN_USE_BRIDGE; HrConfigs[AR_DS_PORT1].Res.Cls = DEF_CACHE_LINE_SIZE; HrConfigs[AR_DS_PORT1].Res.Cmd = CMD_BM_MEM; HrConfigs[AR_DS_PORT1].Res.MemBase = MemBase; HrConfigs[AR_DS_PORT1].Res.MemLimit = MemBase + 0x17F0 - 1; HrConfigs[AR_DS_PORT1].Res.PMemBase64 = PMemBase64; HrConfigs[AR_DS_PORT1].Res.PMemLimit64 = PMemBase64 + 0x2000 - 1; HrConfigs[AR_DS_PORT1].SBus = BrdgConf->SBus; HrConfigs[AR_DS_PORT1].SubBus = BrdgConf->SBus + BusRange; BrdgConf->SBus = HrConfigs[AR_DS_PORT1].SubBus + 1; HrConfigs[AR_DS_PORT2].Res = NOT_IN_USE_BRIDGE; HrConfigs[AR_DS_PORT2].Res.Cls = DEF_CACHE_LINE_SIZE; HrConfigs[AR_DS_PORT2].Res.Cmd = CMD_BM_MEM; HrConfigs[AR_DS_PORT2].Res.MemBase = MemBase + 0x17F0; HrConfigs[AR_DS_PORT2].Res.MemLimit = MemBase + 0x1800 - 1; HrConfigs[AR_DS_PORT2].SBus = BrdgConf->SBus; HrConfigs[AR_DS_PORT2].SubBus = BrdgConf->SBus; BrdgConf->SBus = HrConfigs[AR_DS_PORT2].SubBus + 1; HrConfigs[AR_DS_PORT4].Res = NOT_IN_USE_BRIDGE; HrConfigs[AR_DS_PORT4].Res.Cls = DEF_CACHE_LINE_SIZE; HrConfigs[AR_DS_PORT4].Res.Cmd = CMD_BM_MEM; HrConfigs[AR_DS_PORT4].Res.MemBase = MemBase + 0x1800; HrConfigs[AR_DS_PORT4].Res.MemLimit = BrdgConf->Res.MemLimit; HrConfigs[AR_DS_PORT4].Res.PMemBase64 = PMemBase64 + 0x2000; HrConfigs[AR_DS_PORT4].Res.PMemLimit64 = BrdgConf->Res.PMemLimit64; HrConfigs[AR_DS_PORT4].SBus = BrdgConf->SBus; HrConfigs[AR_DS_PORT4].SubBus = BrdgConf->SubBus; BrdgConf->SBus = HrConfigs[AR_DS_PORT4].SubBus + 1; }//InitARDSPort_2Port STATIC BOOLEAN CheckLimits ( IN BOOLEAN Is2PortDev, IN BRDG_RES_CONFIG *HrResConf, IN UINT8 BusRange ) { UINT16 MemBase; UINT16 MemLimit; UINT64 PMemBase64; UINT64 PMemLimit64; MemBase = HrResConf->MemBase & 0xFFF0; MemLimit = HrResConf->MemLimit & 0xFFF0; PMemBase64 = HrResConf->PMemBase64 & 0xFFF0; PMemLimit64 = HrResConf->PMemLimit64 & 0xFFF0; // // Check memoty alignment // if (MemBase & 0x3FF) { DEBUG((DEBUG_INFO, "M alig\n")); return FALSE; } if (PMemBase64 & 0xFFF) { DEBUG((DEBUG_INFO, "PM alig\n")); return FALSE; } if (Is2PortDev) { // // Check mem size // if (MemLimit + 0x10 - MemBase < 0x2E00) { DEBUG((DEBUG_INFO, "M size\n")); return FALSE; } // // Check P-mem size // if (PMemLimit64 + 0x10 - PMemBase64 < 0x4A00) { DEBUG((DEBUG_INFO, "PM size\n")); return FALSE; } // // Check bus range // if (BusRange < 106) { DEBUG((DEBUG_INFO, "Bus range\n")); return FALSE; } } else { // // Check mem size // if (MemLimit + 0x10 - MemBase < 0x1600) { DEBUG((DEBUG_INFO, "M size\n")); return FALSE; } // // Check P-mem size // if (PMemLimit64 + 0x10 - PMemBase64 < 0x2200) { DEBUG((DEBUG_INFO, "PM size\n")); return FALSE; } // // Check bus range // if (BusRange < 56) { DEBUG((DEBUG_INFO, "Bus range\n")); return FALSE; } } return TRUE; } // CheckLimits STATIC BOOLEAN InitHRResConfigs ( IN OUT HR_CONFIG *Hr_Config, IN UINT8 BusNumLimit, IN OUT BRDG_RES_CONFIG*HrResConf ) { BRDG_CONFIG BrdgConf = { { 0 } }; InitCommonHRConfigs (Hr_Config, BusNumLimit, HrResConf); BrdgConf.PBus = Hr_Config->HRBus + 2;// Take into account busses BrdgConf.SBus = Hr_Config->HRBus + 3;// for US and DS of HIA BrdgConf.SubBus = BusNumLimit; BrdgConf.Res = *HrResConf; while (TRUE) { switch (Hr_Config->DeviceId) { case AR_HR_4C: case TR_HR_4C: case AR_HR_C0_4C: // // 2 Port host // if (CheckLimits (TRUE, HrResConf, BusNumLimit - Hr_Config->HRBus)) { InitARDSPort_2Port(&BrdgConf); DEBUG((DEBUG_INFO, "AR2\n")); return TRUE; } else { return FALSE; } // AR only case AR_HR_2C: // 1 port host case AR_HR_C0_2C: case AR_HR_LP: case TR_HR_2C: DEBUG((DEBUG_INFO, "AR1\n")); InitARDSPort_1Port(&BrdgConf); return TRUE; default: InitHRDSPort_Disable (HR_DS_PORT3, &BrdgConf); InitHRDSPort_Disable (HR_DS_PORT4, &BrdgConf); InitHRDSPort_Disable (HR_DS_PORT5, &BrdgConf); InitHRDSPort_Disable (HR_DS_PORT6, &BrdgConf); return FALSE; } } } // InitHRResConfigs STATIC BOOLEAN InitializeHostRouter ( OUT HR_CONFIG *Hr_Config, IN UINTN RpSegment, IN UINTN RpBus, IN UINTN RpDevice, IN UINTN RpFunction ) { UINT8 BusNumLimit; BRDG_RES_CONFIG HrResConf = { 0 }; UINT8 i; BOOLEAN Ret; Ret = TRUE; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0); Hr_Config->HRBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, Hr_Config->HRBus, 0x00, 0x00, 0); Hr_Config->DeviceId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET); if (!(IsTbtHostRouter (Hr_Config->DeviceId))) { return FALSE; } TbtSegment = (UINT8)RpSegment; HrResConf.Cmd = CMD_BM_MEM; HrResConf.Cls = DEF_CACHE_LINE_SIZE; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0); HrResConf.IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase)); HrResConf.IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit)); HrResConf.MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)); HrResConf.MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)); HrResConf.PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase)); HrResConf.PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit)); HrResConf.PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16; HrResConf.PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16; BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); Ret = InitHRResConfigs (Hr_Config, BusNumLimit, &HrResConf); for (i = 0; i < Hr_Config->BridgeLoops; ++i) { UINT8 Bus; UINT8 Dev; UINT8 Fun; Bus = HrConfigs[i].DevId.Bus; Dev = HrConfigs[i].DevId.Dev; Fun = HrConfigs[i].DevId.Fun; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0); PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, HrConfigs[i].Res.Cls); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, HrConfigs[i].PBus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, HrConfigs[i].SBus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, HrConfigs[i].SubBus); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), HrConfigs[i].Res.MemBase); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), HrConfigs[i].Res.MemLimit); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (HrConfigs[i].Res.PMemBase64 & 0xFFFF)); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) (HrConfigs[i].Res.PMemLimit64 & 0xFFFF)); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (HrConfigs[i].Res.PMemBase64 >> 16)); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) (HrConfigs[i].Res.PMemLimit64 >> 16)); PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), HrConfigs[i].Res.IoBase); PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit), HrConfigs[i].Res.IoLimit); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16), 0x00000000); PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, HrConfigs[i].Res.Cmd); } if (Hr_Config->DeviceId == AR_HR_2C || Hr_Config->DeviceId == AR_HR_4C || Hr_Config->DeviceId == AR_HR_LP) { for (i = 0; i < Hr_Config->BridgeLoops; ++i) { if(HrConfigs[i].IsDSBridge) { UnsetVesc(HrConfigs[i].DevId.Bus, HrConfigs[i].DevId.Dev, HrConfigs[i].DevId.Fun); } } } gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,(Hr_Config->HRBus + 2), 0x00, 0x00, 0); PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX0 * 4), HrConfigs[HR_DS_PORT0].Res.MemLimit << 16); PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), (HrConfigs[HR_DS_PORT0].Res.MemLimit + 0x4) << 16); PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE); PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BM_MEM); return Ret; } // InitializeHostRouter STATIC UINT8 ConfigureSlot ( IN UINT8 Bus, IN UINT8 MAX_DEVICE, IN INT8 Depth, IN BOOLEAN ArPcie, IN OUT PORT_INFO *PortInfo ) { UINT8 Device; UINT8 SBus; UINT8 UsedBusNumbers; UINT8 RetBusNum; PORT_INFO CurrentSlot; RetBusNum = 0; for (Device = 0; Device < MAX_DEVICE; Device++) { // // Continue if device is absent // gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, 0x00, 0); if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) { continue; } if (P2P_BRIDGE != PciSegmentRead16 (gDeviceBaseAddress + (PCI_CLASSCODE_OFFSET + 1))) { SetDevResources ( Bus, Device, PCI_MAX_FUNC, PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX5 * 4), PortInfo ); continue; } // // Else Bridge // CopyMem (&CurrentSlot, PortInfo, sizeof (PORT_INFO)); ++RetBusNum; // UP Bridge SBus = Bus + RetBusNum; // DS Bridge if (SBus + 1 >= PortInfo->BusNumLimit) { continue; } SetDevResources (Bus, Device, 1, PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), PortInfo); // // Init UP Bridge to reach DS Bridge // PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, SBus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit); PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BM_MEM); if(ArPcie) { UnsetVesc(Bus, Device, 0x00); } UsedBusNumbers = ConfigureSlot(SBus, PCI_MAX_DEVICE + 1, -1, FALSE, PortInfo); RetBusNum += UsedBusNumbers; SetPhyPortResources ( Bus, Device, SBus + UsedBusNumbers, Depth, &CurrentSlot, PortInfo ); } // // for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) // return RetBusNum; } // ConfigureSlot STATIC VOID SetCioPortResources ( IN UINT8 Bus, IN UINT8 Dev, IN UINT8 SBus, IN UINT8 SubBus, IN PORT_INFO *portInfoBeforeChange, IN OUT PORT_INFO *PortInfo ) { UINT8 Cmd; Cmd = CMD_BUS_MASTER; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, 0x00, 0); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, SBus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, SubBus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd); if (PortInfo->IoBase <= PortInfo->IoLimit) { PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), PortInfo->IoBase); PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit), PortInfo->IoLimit); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16), 0x00000000); Cmd |= CMD_BM_IO; } else { PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), DISBL_IO_REG1C); } if (PortInfo->MemBase <= PortInfo->MemLimit) { PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), PortInfo->MemBase); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), PortInfo->MemLimit); Cmd |= CMD_BM_MEM; } else { PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20); } if (PortInfo->PMemBase64 <= PortInfo->PMemLimit64) { PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (PortInfo->PMemBase64 & 0xFFFF)); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) (PortInfo->PMemLimit64 & 0xFFFF)); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (PortInfo->PMemBase64 >> 16)); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) (PortInfo->PMemLimit64 >> 16)); Cmd |= CMD_BM_MEM; } else { PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), 0); } PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd); PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE); } // SetCioPortResources STATIC VOID SetSlotsAsUnused ( IN UINT8 Bus, IN UINT8 MaxSlotNum, IN UINT8 CioSlot, IN OUT PORT_INFO *PortInfo ) { UINT8 Slot; for (Slot = MaxSlotNum; Slot > CioSlot; --Slot) { gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Slot, 0x00, 0); if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) { continue; } PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit); PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), DISBL_IO_REG1C); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24); PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BUS_MASTER); PortInfo->BusNumLimit--; } } // SetSlotsAsUnused STATIC UINT16 FindVendorSpecificHeader( IN UINT8 Bus ) { PCI_EXP_EXT_HDR *ExtHdr; UINT32 ExtHdrValue; UINT16 ExtendedRegister; ExtHdr = (PCI_EXP_EXT_HDR*) &ExtHdrValue; ExtendedRegister = 0x100; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0); while (ExtendedRegister) { ExtHdrValue = PciSegmentRead32 (gDeviceBaseAddress + ExtendedRegister); if (ExtHdr->CapabilityId == 0xFFFF) { return 0x0000; // No Vendor-Specific Extended Capability header } if (PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_ID == ExtHdr->CapabilityId) { return ExtendedRegister; } ExtendedRegister = (UINT16) ExtHdr->NextCapabilityOffset; } return 0x0000; // No Vendor-Specific Extended Capability header } STATIC UINT8 FindSsid_SsvidHeader ( IN UINT8 Bus ) { UINT8 CapHeaderId; UINT8 CapHeaderOffset; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0); CapHeaderOffset = PciSegmentRead8 (gDeviceBaseAddress + PCI_CAPBILITY_POINTER_OFFSET); while (CapHeaderOffset != 0) { CapHeaderId = PciSegmentRead8 (gDeviceBaseAddress + CapHeaderOffset); if (CapHeaderId == PCIE_CAP_ID_SSID_SSVID) { return CapHeaderOffset; } CapHeaderOffset = PciSegmentRead8 (gDeviceBaseAddress + CapHeaderOffset + 1); } DEBUG((DEBUG_INFO, "SID0\n")); return 0; } // FindSsid_SsvidHeader STATIC BOOLEAN GetCioSlotByDevId ( IN UINT8 Bus, OUT UINT8 *CioSlot, OUT UINT8 *MaxSlotNum, OUT BOOLEAN *ArPcie ) { UINT16 VSECRegister; BRDG_CIO_MAP_REG BridgMap; UINT32 BitScanRes; UINT16 DevId; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, 0x00, 0x00, 0); DevId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET); // // Init out params in case device is not recognised // *CioSlot = 4; *MaxSlotNum = 7; *ArPcie = FALSE; switch (DevId) { // // For known device IDs // case 0x1578: *ArPcie = TRUE; } switch (DevId) { // // For known device IDs // case 0x1513: case 0x151A: case 0x151B: case 0x1547: case 0x1548: return TRUE; // Just return case 0x1549: return FALSE; // Just return } VSECRegister = FindVendorSpecificHeader(Bus); if (!VSECRegister) { return TRUE; // Just return } // // Go to Bridge/CIO map register // VSECRegister += 0x18; BridgMap.AB_REG = PciSegmentRead32(gDeviceBaseAddress + VSECRegister); // // Check for range // if (BridgMap.Bits.NumOfDSPorts < 1 || BridgMap.Bits.NumOfDSPorts > 27) { return TRUE; // // Not a valid register // } // // Set OUT params // *MaxSlotNum = (UINT8) BridgMap.Bits.NumOfDSPorts; #ifdef _MSC_VER if(!_BitScanForward(&BitScanRes, BridgMap.Bits.CioPortMap)) { // No DS bridge which is CIO port return FALSE; } #else #ifdef __GNUC__ if (BridgMap.Bits.CioPortMap == 0) { return FALSE; } BitScanRes = __builtin_ctz (BridgMap.Bits.CioPortMap); #else #error Unsupported Compiler #endif #endif *CioSlot = (UINT8)BitScanRes; return TRUE; } // GetCioSlotByDevId #define TBT_LEGACY_SUB_SYS_ID 0x11112222 STATIC BOOLEAN IsLegacyDevice ( IN UINT8 Bus ) { UINT32 Sid; UINT8 SidRegister; UINT16 DevId; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0); DevId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET); switch (DevId) { // // For known device IDs // case 0x1513: case 0x151A: case 0x151B: DEBUG((DEBUG_INFO, "Legacy ")); DEBUG((DEBUG_INFO, "DevId = %d\n",DevId)); return TRUE; // // Legacy device by Device Id // } SidRegister = FindSsid_SsvidHeader(Bus); if (!SidRegister) { return TRUE; // May be absent for legacy devices } // // Go to register // SidRegister += 0x4; Sid = PciSegmentRead32(gDeviceBaseAddress + SidRegister); DEBUG((DEBUG_INFO, "SID")); DEBUG((DEBUG_INFO, " = %d\n", Sid)); return TBT_LEGACY_SUB_SYS_ID == Sid || 0 == Sid; } // IsLegacyDevice STATIC VOID UnsetVescEp( IN UINT8 Bus, IN UINT8 MaxSlotNum ) { UINT8 i; for (i = 0; i <= MaxSlotNum; ++i) { UnsetVesc(Bus, i, 0); } }// Unset_VESC_REG2_EP STATIC BOOLEAN ConfigureEP ( IN INT8 Depth, IN OUT UINT8 *Bus, IN OUT PORT_INFO *PortInfo ) { UINT8 SBus; UINT8 CioSlot; UINT8 MaxSlotNum; BOOLEAN ArPcie; UINT8 MaxPHYSlots; UINT8 UsedBusNumbers; UINT8 cmd; BOOLEAN CioSlotPresent; BOOLEAN Continue; PORT_INFO PortInfoOrg; UINT8 CioBus; CioSlot = 4; MaxSlotNum = 7; CopyMem (&PortInfoOrg, PortInfo, sizeof (PORT_INFO)); gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, *Bus, 0x00, 0x00, 0); cmd = PciSegmentRead8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET); // AR ONLY // Endpoint on CIO slot, but not a bridge device if (P2P_BRIDGE != PciSegmentRead16 (gDeviceBaseAddress + (PCI_CLASSCODE_OFFSET + 1))) { DEBUG((DEBUG_INFO, "UEP\n")); // Check whether EP already configured by examining CMD register if(cmd & CMD_BUS_MASTER) // Yes, no need to touch this EP { DEBUG((DEBUG_INFO, "BMF\n")); return FALSE; } // Configure it as regular PCIe device ConfigureSlot(*Bus, PCI_MAX_DEVICE + 1, -1, FALSE, PortInfo); return FALSE; } // // Based on Device ID assign Cio slot and max number of PHY slots to scan // CioSlotPresent = GetCioSlotByDevId(*Bus, &CioSlot, &MaxSlotNum, &ArPcie); MaxPHYSlots = MaxSlotNum; // // Check whether EP already configured by examining CMD register // if (cmd & CMD_BUS_MASTER) { // // Yes no need to touch this EP, just move to next one in chain // CioBus = *Bus + 1; if(ArPcie){ UnsetVescEp(CioBus, MaxSlotNum); } if (!CioSlotPresent) { // // Cio slot is not present in EP, just return FALSE // DEBUG((DEBUG_INFO, "BMF\n")); return FALSE; } // // Take all resources from Cio slot and return // gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,CioBus, CioSlot, 0x00, 0); PortInfo->BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); PortInfo->IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase)); PortInfo->IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit)); PortInfo->MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)); PortInfo->MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)); PortInfo->PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase)) & 0xFFF0; PortInfo->PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit)) & 0xFFF0; PortInfo->PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16; PortInfo->PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16; PortInfo->PMemLimit64 |= 0xF; // // Jump to next EP // *Bus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); // // Should we continue? // gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,*Bus, 0x00, 0x00, 0); Continue = 0xFFFF != PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET); return Continue; } // // Set is legacy dvice // isLegacyDevice = IsLegacyDevice (*Bus); SetCioPortResources ( *Bus, 0, // Assign all available resources to US port of EP *Bus + 1, PortInfo->BusNumLimit, 0, PortInfo ); SBus = *Bus + 1;// Jump to DS port if (CioSlotPresent) { MaxPHYSlots = CioSlot; } UsedBusNumbers = ConfigureSlot(SBus, MaxPHYSlots, Depth, ArPcie, PortInfo); if (!CioSlotPresent) { return FALSE; // // Stop resource assignment on this chain // } // // Set rest of slots us unused // SetSlotsAsUnused (SBus, MaxSlotNum, CioSlot, PortInfo); SetCioPortResources ( SBus, CioSlot, SBus + UsedBusNumbers + 1, PortInfo->BusNumLimit, &PortInfoOrg, PortInfo ); *Bus = SBus + UsedBusNumbers + 1;// Go to next EP if(ArPcie) { UnsetVesc(SBus, CioSlot, 0x00); } if (*Bus > PortInfo->BusNumLimit - 2) { // // In case of bus numbers are exhausted stop enumeration // return FALSE; } // // Check whether we should continue on this chain // gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,*Bus, 0x00, 0x00, 0); Continue = 0xFFFF != PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET); return Continue; } // ConfigureEP STATIC VOID GetPortResources ( IN UINT8 Bus, IN UINT8 Dev, IN UINT8 Fun, IN OUT PORT_INFO *PortInfo ) { gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0); PortInfo->BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); PortInfo->IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase)) & 0xF0; PortInfo->IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit)) & 0xF0; PortInfo->MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)) & 0xFFF0; PortInfo->MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)) & 0xFFF0; PortInfo->PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase)) & 0xFFF0; PortInfo->PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit)) & 0xFFF0; PortInfo->PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16; PortInfo->PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16; PortInfo->IoLimit |= 0xF; PortInfo->MemLimit |= 0xF; PortInfo->PMemLimit64 |= 0xF; } // GetPortResources STATIC VOID ConfigurePort ( IN UINT8 Bus, IN UINT8 Dev, IN UINT8 Fun, IN OUT PORT_INFO *PortInfo ) { INT8 i; UINT8 USBusNum; gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0); USBusNum = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, USBusNum, 0x00, 0x00, 0); if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) { // // Nothing to do if TBT device is not connected // return ; } GetPortResources(Bus, Dev, Fun, PortInfo);// Take reserved resources from DS port // // Assign resources to EPs // for (i = 0; i < MAX_TBT_DEPTH; ++i) { PortInfo->ConfedEP++; if (!ConfigureEP (i, &USBusNum, PortInfo)) { return ; } } } // ConfigurePort VOID ThunderboltCallback ( IN UINT8 Type ) { PORT_INFO PortInfoOrg = { 0 }; HR_CONFIG HrConfig = { 0 }; UINT8 i; UINTN Segment = 0; UINTN Bus = 0; UINTN Device; UINTN Function; DEBUG((DEBUG_INFO, "ThunderboltCallback.Entry\n")); DEBUG((DEBUG_INFO, "PortInfo Initialization\n")); PortInfoInit (&PortInfoOrg); if(Type == DTBT_CONTROLLER) { if (gCurrentDiscreteTbtRootPort == 0) { DEBUG((DEBUG_ERROR, "Invalid RP Input\n")); return; } GetDTbtRpDevFun(gCurrentDiscreteTbtRootPortType, gCurrentDiscreteTbtRootPort - 1, &Device, &Function); DEBUG((DEBUG_INFO, "InitializeHostRouter. \n")); if (!InitializeHostRouter (&HrConfig, Segment, Bus, Device, Function)) { return ; } // // Configure DS ports // for (i = HrConfig.MinDSNumber; i <= HrConfig.MaxDSNumber; ++i) { DEBUG((DEBUG_INFO, "ConfigurePort. \n")); ConfigurePort (HrConfig.HRBus + 1, i,0, &PortInfoOrg); } DEBUG((DEBUG_INFO, "EndOfThunderboltCallback.\n")); EndOfThunderboltCallback (Segment, Bus, Device, Function); } DEBUG((DEBUG_INFO, "ThunderboltCallback.Exit\n")); } // ThunderboltCallback VOID DisablePCIDevicesAndBridges ( IN UINT8 MinBus, IN UINT8 MaxBus ) { UINT8 Bus; UINT8 Dev; UINT8 Fun; UINT8 RegVal; // // Disable PCI device First, and then Disable PCI Bridge // for (Bus = MaxBus; Bus > MinBus; --Bus) { for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) { for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) { gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0); if (INVALID_PCI_DEVICE == PciSegmentRead32 (gDeviceBaseAddress + PCI_VENDOR_ID_OFFSET)) { if (Fun == 0) { break; } continue; } RegVal = PciSegmentRead8 (gDeviceBaseAddress + PCI_HEADER_TYPE_OFFSET); if (HEADER_TYPE_DEVICE == (RegVal & 1)) { // // ******** Disable PCI Device ******** // BIT0 I/O Space Enabled BIT1 Memory Space Enabled // BIT2 Bus Master Enabled BIT4 Memory Write and Invalidation Enable // PciSegmentAnd8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, (UINT8)~(BIT0 | BIT1 | BIT2 | BIT4)); PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX0 * 4), 0); PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), 0); PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX2 * 4), 0); PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX3 * 4), 0); PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX4 * 4), 0); PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX5 * 4), 0); } } } } // // now no more PCI dev on another side of PCI Bridge can safty disable PCI Bridge // for (Bus = MaxBus; Bus > MinBus; --Bus) { for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) { for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) { gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0); if (INVALID_PCI_DEVICE == PciSegmentRead32 (gDeviceBaseAddress + PCI_VENDOR_ID_OFFSET)) { if (Fun == 0) { break; } continue; } RegVal = PciSegmentRead8 (gDeviceBaseAddress + PCI_HEADER_TYPE_OFFSET); if (HEADER_TYPE_PCI_TO_PCI_BRIDGE == (RegVal & BIT0)) { PciSegmentAnd8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, (UINT8)~(BIT0 | BIT1 | BIT2 | BIT4)); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, 0); PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 0); PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0); } } // for ( Fun .. ) } // for ( Dev ... ) } // for ( Bus ... ) } // DisablePCIDevicesAndBridges VOID TbtDisablePCIDevicesAndBridges ( IN UINT8 Type ) { UINTN Segment = 0; UINTN Bus = 0; UINTN Device; UINTN Function; UINT8 MinBus; UINT8 MaxBus; UINT16 DeviceId; MinBus = 1; if(Type == DTBT_CONTROLLER) { // // for(Dev = 0; Dev < 8; ++Dev) // { // PciOr8(PCI_LIB_ADDRESS(2, Dev, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET), 0x40); // gBS->Stall(2000); // 2msec // PciAnd8(PCI_LIB_ADDRESS(2, Dev, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET), 0xBF); // } // gBS->Stall(200 * 1000); // 200 msec // if (gCurrentDiscreteTbtRootPort == 0) { DEBUG((DEBUG_ERROR, "Invalid RP Input\n")); return; } GetDTbtRpDevFun(gCurrentDiscreteTbtRootPortType, gCurrentDiscreteTbtRootPort - 1, &Device, &Function); gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0); MinBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); MaxBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (Segment, MinBus, 0x00, 0x00, 0); DeviceId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET); if (!(IsTbtHostRouter (DeviceId))) { return; } TbtSegment = (UINT8)Segment; MinBus++; // // @todo : Move this out when we dont have Loop for ITBT // DisablePCIDevicesAndBridges(MinBus, MaxBus); } } // DisablePCIDevicesAndBridges