/** * Change the hardware state for all Links according to the now optimized data in the * port list data structure for link frequency. * * @HtNbMethod{::F_SET_LINK_FREQUENCY} * * Handle extended frequencies. For HT3 frequencies, ensure Retry and Scrambling are * set. For HT1, clear them. * * @param[in] Node the node on which to set frequency for a link * @param[in] Link the link to set frequency * @param[in] Frequency the frequency to set * @param[in] Nb this northbridge */ VOID SetLinkFrequency ( IN UINT8 Node, IN UINT8 Link, IN UINT8 Frequency, IN NORTHBRIDGE *Nb ) { UINT32 Temp; PCI_ADDR Reg; ASSERT ((Frequency >= HT_FREQUENCY_600M && Frequency <= HT_FREQUENCY_3200M) || (Frequency == HT_FREQUENCY_200M) || (Frequency == HT_FREQUENCY_400M)); // Handle extended frequencies, 2800 MHz and above. 31 > Frequency > 16 in this case. if (Frequency > HT_FREQUENCY_2600M) { Temp = 1; } else { // Clear it if not extended. Temp = 0; } Reg = Nb->MakeLinkBase (Node, Link, Nb); Reg.Address.Register += HTHOST_FREQ_EXTENSION; LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle); Reg = Nb->MakeLinkBase (Node, Link, Nb); Reg.Address.Register += HTHOST_FREQ_REV_REG; Temp = (Frequency & 0x0F); LibAmdPciWriteBits (Reg, 11, 8, &Temp, Nb->ConfigHandle); // Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz if (Frequency > HT_FREQUENCY_1000M) { // Enable for Gen3 frequencies Temp = 1; } else { // Disable for Gen1 frequencies Temp = 0; } // HT3 retry mode enable / disable Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_HTNB_FUNC_00, REG_HT_LINK_RETRY0_0X130 + (4 * Link)); LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle); // and Scrambling enable / disable Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_HTNB_FUNC_00, REG_HT_LINK_EXT_CONTROL0_0X170 + (4 * Link)); LibAmdPciWriteBits (Reg, 3, 3, &Temp, Nb->ConfigHandle); }
/** * Enable config access to a non-coherent chain for the given bus range. * * @HtNbMethod{::F_SET_CONFIG_ADDR_MAP} * * @param[in] ConfigMapIndex the map entry to set * @param[in] SecBus The secondary bus number to use * @param[in] SubBus The subordinate bus number to use * @param[in] TargetNode The Node that shall be the recipient of the traffic * @param[in] TargetLink The Link that shall be the recipient of the traffic * @param[in] State our global state * @param[in] Nb this northbridge */ VOID Fam10SetConfigAddrMap ( IN UINT8 ConfigMapIndex, IN UINT8 SecBus, IN UINT8 SubBus, IN UINT8 TargetNode, IN UINT8 TargetLink, IN STATE_DATA *State, IN NORTHBRIDGE *Nb ) { UINT8 CurNode; PCI_ADDR Reg; UINT32 Temp; Reg = Nb->MakeLinkBase (TargetNode, TargetLink, Nb); ASSERT (SecBus <= SubBus); ASSERT (TargetNode <= State->NodesDiscovered); ASSERT (TargetLink < Nb->MaxLinks); Temp = SecBus; Reg.Address.Register += HTHOST_ISOC_REG; LibAmdPciWriteBits (Reg, 15, 8, &Temp, Nb->ConfigHandle); Temp = ((UINT32)SubBus << 24) + ((UINT32)SecBus << 16) + ((UINT32)TargetLink << 8) + ((UINT32)TargetNode << 4) + (UINT32)3; for (CurNode = 0; CurNode < (State->NodesDiscovered + 1); CurNode++) { Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (CurNode), MakePciBusFromNode (CurNode), MakePciDeviceFromNode (CurNode), CPU_ADDR_FUNC_01, REG_ADDR_CONFIG_MAP0_1XE0 + (4 * ConfigMapIndex)); LibAmdPciWrite (AccessWidth32, Reg, &Temp, Nb->ConfigHandle); } }
/** * Stop a link, so that it is isolated from a connected device. * * @HtNbMethod{::F_STOP_LINK}. * * Use is for fatal incompatible configurations, or for user interface * request to power off a link (IgnoreLink, SkipRegang). * Set ConnDly to make the power effective at the warm reset. * Set XMT and RCV off. * * @param[in] Node the node to stop a link on. * @param[in] Link the link to stop. * @param[in] State access to special routine for writing link control register * @param[in] Nb this northbridge. */ VOID Fam10StopLink ( IN UINT8 Node, IN UINT8 Link, IN STATE_DATA *State, IN NORTHBRIDGE *Nb ) { UINT32 Temp; PCI_ADDR Reg; // Set ConnDly Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_HTNB_FUNC_00, REG_LINK_GLOBAL_EXT_CONTROL_0x16C); Temp = 1; LibAmdPciWriteBits (Reg, 8, 8, &Temp, Nb->ConfigHandle); // Set TransOff and EndOfChain Reg = Nb->MakeLinkBase (Node, Link, Nb); Reg.Address.Register += HTHOST_LINK_CONTROL_REG; Temp = 3; State->HtFeatures->SetHtControlRegisterBits (Reg, 7, 6, &Temp, State); }
/** * Ids Write PCI register to All node * * * @param[in] PciAddress Pci address * @param[in] Highbit High bit position of the field in DWORD * @param[in] Lowbit Low bit position of the field in DWORD * @param[in] Value Pointer to input value * @param[in] StdHeader Standard configuration header * */ VOID IdsLibPciWriteBitsToAllNode ( IN PCI_ADDR PciAddress, IN UINT8 Highbit, IN UINT8 Lowbit, IN UINT32 *Value, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; AGESA_STATUS IgnoreStatus; PCI_ADDR PciAddr; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddr, &IgnoreStatus)) { PciAddr.Address.Function = PciAddress.Address.Function; PciAddr.Address.Register = PciAddress.Address.Register; LibAmdPciWriteBits (PciAddr, Highbit, Lowbit, Value, StdHeader); } } } }
/** * Turns routing tables off for a given Node * * @HtNbMethod{::F_DISABLE_ROUTING_TABLES} * * @param[in] Node the Node that will have it's routing tables disabled * @param[in] Nb this northbridge */ VOID DisableRoutingTables ( IN UINT8 Node, IN NORTHBRIDGE *Nb ) { PCI_ADDR Reg; UINT32 Temp; Temp = 1; ASSERT ((Node < MAX_NODES)); Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_HTNB_FUNC_00, REG_LINK_INIT_CONTROL_0X6C); LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle); }
/** * Modifies the NodeID register on the target Node * * @HtNbMethod{::F_WRITE_NODEID} * * @param[in] Node the Node that will have its NodeID altered. * @param[in] NodeID the new value for NodeID * @param[in] Nb this northbridge */ VOID WriteNodeID ( IN UINT8 Node, IN UINT8 NodeID, IN NORTHBRIDGE *Nb ) { PCI_ADDR Reg; UINT32 Temp; Temp = NodeID; ASSERT ((Node < MAX_NODES) && (NodeID < MAX_NODES)); Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_HTNB_FUNC_00, REG_NODE_ID_0X60); LibAmdPciWriteBits (Reg, 2, 0, &Temp, Nb->ConfigHandle); }
/** * Write the token stored in the scratchpad register * * @HtNbMethod{::F_WRITE_TOKEN} * * Use the CPU core count as a scratch pad. * * @note The location used to store the token is arbitrary. The only requirement is * that the location warm resets to zero, and that using it will have no ill-effects * during HyperTransport initialization. * * @param[in] Node the Node that marked with token * @param[in] Value the token Value * @param[in] Nb this northbridge */ VOID WriteToken ( IN UINT8 Node, IN UINT8 Value, IN NORTHBRIDGE *Nb ) { PCI_ADDR Reg; UINT32 Temp; Temp = Value; ASSERT ((Node < MAX_NODES)); // Use CpuCnt as a scratch register Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_HTNB_FUNC_00, REG_NODE_ID_0X60); LibAmdPciWriteBits (Reg, 19, 16, &Temp, Nb->ConfigHandle); }
/** * Change the hardware state for all Links according to the now optimized data in the * port list data structure for link reganging. * * @HtNbMethod{::F_SET_LINK_REGANG} * * @param[in] Node the node on which to regang a link * @param[in] Link the sublink 0 of the sublink pair to regang * @param[in] Nb this northbridge */ VOID SetLinkRegang ( IN UINT8 Node, IN UINT8 Link, IN NORTHBRIDGE *Nb ) { PCI_ADDR Reg; UINT32 Temp; Temp = 1; Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_HTNB_FUNC_00, REG_HT_LINK_EXT_CONTROL0_0X170 + (4 * Link)); LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle); }
/** * Write the total number of cores to the Node * * @TopoNbMethod{::F_SET_TOTAL_NODES_AND_CORES} * * @param[in] Node the Node that will be examined * @param[in] TotalNodes the total number of Nodes * @param[in] TotalCores the total number of cores * @param[in] Nb this northbridge */ VOID Fam16SetTotalCores ( IN UINT8 Node, IN UINT8 TotalNodes, IN UINT8 TotalCores, IN NORTHBRIDGE *Nb ) { PCI_ADDR NodeIDReg; UINT32 Temp; NodeIDReg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_NB_FUNC_00, REG_NODE_ID_0X60); Temp = ((TotalCores - 1) & REG_NODE_CPUCNT_4_0); LibAmdPciWriteBits (NodeIDReg, 20, 16, &Temp, Nb->ConfigHandle); }
/** * Change the hardware state for all Links according to the now optimized data in the * port list data structure for Unit Id Clumping. * * @HtNbMethod{::F_SET_LINK_UNITID_CLUMPING} * * This applies to the host root of a non-coherent chain. * * @param[in] Node the node on which to enable clumping * @param[in] Link the link for which to enable clumping * @param[in] ClumpingEnables the unit id clumping enables * @param[in] Nb this northbridge */ VOID SetLinkUnitIdClumping ( IN UINT8 Node, IN UINT8 Link, IN UINT32 ClumpingEnables, IN NORTHBRIDGE *Nb ) { PCI_ADDR Reg; // Host Unit Ids are not clumped. ASSERT ((ClumpingEnables & 0x3) == 0); Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), MakePciBusFromNode (Node), MakePciDeviceFromNode (Node), CPU_HTNB_FUNC_00, REG_HT_LINK_CLUMPING0_0X110 + (4 * Link)); LibAmdPciWriteBits (Reg, 31, 0, &ClumpingEnables, Nb->ConfigHandle); }
/** * Process a non-coherent Link. * * @HtFeatMethod{::F_PROCESS_LINK} * * Enable a range of bus numbers, and set the device ID for all devices found. Add * non-coherent devices, links to the system data structure. * * @param[in] Node Node on which to process nc init * @param[in] Link The non-coherent Link on that Node * @param[in] IsCompatChain Is this the chain with the southbridge? TRUE if yes. * @param[in,out] State our global state */ VOID ProcessLink ( IN UINT8 Node, IN UINT8 Link, IN BOOLEAN IsCompatChain, IN OUT STATE_DATA *State ) { UINT8 SecBus; UINT8 SubBus; UINT32 CurrentBuid; UINT32 Temp; UINT32 UnitIdCount; PCI_ADDR CurrentPtr; PCI_ADDR Link1ControlRegister; UINT8 Depth; BUID_SWAP_LIST *SwapPtr; UINT8 LastLink; BOOLEAN IsCaveDevice; ASSERT ((Node < MAX_NODES) && (Link < State->Nb->MaxLinks)); if (!State->HtInterface->GetOverrideBusNumbers (Node, Link, &SecBus, &SubBus, State)) { // Assign Bus numbers if (State->AutoBusCurrent >= State->HtBlock->AutoBusMax) { // If we run out of Bus Numbers, notify and skip this chain // IDS_ERROR_TRAP; NotifyErrorNcohBusMaxExceed (Node, Link, State->AutoBusCurrent, State); return; } if (State->UsedCfgMapEntries >= 4) { // If we have used all the PCI Config maps we can't add another chain. // Notify and if call back is unimplemented or returns, skip this chain. // IDS_ERROR_TRAP; NotifyErrorNcohCfgMapExceed (Node, Link, State); return; } SecBus = State->AutoBusCurrent; SubBus = SecBus + State->HtBlock->AutoBusIncrement - 1; State->AutoBusCurrent = State->AutoBusCurrent + State->HtBlock->AutoBusIncrement; } State->Nb->SetConfigAddrMap (State->UsedCfgMapEntries, SecBus, SubBus, Node, Link, State, State->Nb); State->UsedCfgMapEntries++; if (State->HtInterface->GetManualBuidSwapList (Node, Link, &SwapPtr, State)) { // Manual non-coherent BUID assignment AGESA_TESTPOINT (TpProcHtManualNc, State->ConfigHandle); if (!IsCompatChain || !State->IsUsingRecoveryHt) { // If this is the not southbridge chain or Recovery HT was not used // then we need to assign BUIDs here. // Depth = 0; // Assign BUID's per manual override while (SwapPtr->Swaps[Depth].FromId != 0xFF) { CurrentPtr.AddressValue = MAKE_SBDFO (0, SecBus, SwapPtr->Swaps[Depth].FromId, 0, 0); if (DoesDeviceHaveHtSubtypeCap (CurrentPtr, HT_SLAVE_CAPABILITY, &CurrentPtr, State)) { // Set the device's BUID field [20:16] to the current buid CurrentBuid = SwapPtr->Swaps[Depth].ToId; LibAmdPciWriteBits (CurrentPtr, 20, 16, &CurrentBuid, State->ConfigHandle); Depth++; } else { // All non-coherent devices must have a slave interface capability. ASSERT (FALSE); break; } } } // Build chain of devices. Do this even if Recovery HT assign BUIDs for this chain. Depth = 0; while (SwapPtr->FinalIds[Depth] != 0xFF) { ASSERT (State->TotalLinks < MAX_PLATFORM_LINKS); (*State->PortList)[(State->TotalLinks * 2)].NodeID = Node; // Note: depth == 0 is true before depth > 0. This makes LastLink variable work. if (Depth == 0) { (*State->PortList)[(State->TotalLinks * 2)].Type = PORTLIST_TYPE_CPU; (*State->PortList)[(State->TotalLinks * 2)].Link = Link; } else { // Fill in the host side port. Link and base pointer can be deduced from the upstream link's // downstream port. (*State->PortList)[(State->TotalLinks * 2)].Type = PORTLIST_TYPE_IO; (*State->PortList)[(State->TotalLinks * 2)].Link = 1 - (*State->PortList)[(((State->TotalLinks - 1) * 2) + 1)].Link; (*State->PortList)[(State->TotalLinks * 2)].HostLink = Link; (*State->PortList)[(State->TotalLinks * 2)].HostDepth = Depth - 1; (*State->PortList)[(State->TotalLinks * 2)].Pointer = (*State->PortList)[(((State->TotalLinks - 1) * 2) + 1)].Pointer; } (*State->PortList)[(State->TotalLinks * 2) + 1].Type = PORTLIST_TYPE_IO; (*State->PortList)[(State->TotalLinks * 2) + 1].NodeID = Node; (*State->PortList)[(State->TotalLinks * 2) + 1].HostLink = Link; (*State->PortList)[(State->TotalLinks * 2) + 1].HostDepth = Depth; CurrentPtr.AddressValue = MAKE_SBDFO (0, SecBus, (SwapPtr->FinalIds[Depth] & 0x3F), 0, 0); if (DoesDeviceHaveHtSubtypeCap (CurrentPtr, HT_SLAVE_CAPABILITY, &CurrentPtr, State)) { (*State->PortList)[(State->TotalLinks * 2) + 1].Pointer = CurrentPtr; } else { // All non-coherent devices must have a slave interface capability. ASSERT (FALSE); break; } // Bit 6 indicates whether orientation override is desired. // Bit 7 indicates the upstream Link if overriding. // // assert catches at least the one known incorrect setting, that a non-zero link // is specified, but override desired is not set. ASSERT (((SwapPtr->FinalIds[Depth] & 0x40) != 0) || ((SwapPtr->FinalIds[Depth] & 0x80) == 0)); if ((SwapPtr->FinalIds[Depth] & 0x40) != 0) { // Override the device's orientation LastLink = SwapPtr->FinalIds[Depth] >> 7; } else {
/** * Change the hardware state for all Links according to the now optimized data in the * port list data structure. * * @HtFeatMethod{::F_SET_LINK_DATA} * * @param[in] State our global state, port list */ VOID SetLinkData ( IN STATE_DATA *State ) { UINT8 i; PCI_ADDR LinkBase; PCI_ADDR Reg; UINT32 Temp; UINT32 Widthin; UINT32 Widthout; UINT32 Bits; PCI_ADDR CurrentPtr; HTIDS_PORT_OVERRIDE_LIST PortOverrides; PortOverrides = NULL; for (i = 0; i < (State->TotalLinks * 2); i++) { ASSERT ((*State->PortList)[i & 0xFE].SelWidthOut == (*State->PortList)[ (i & 0xFE) + 1].SelWidthIn); ASSERT ((*State->PortList)[i & 0xFE].SelWidthIn == (*State->PortList)[ (i & 0xFE) + 1].SelWidthOut); ASSERT ((*State->PortList)[i & 0xFE].SelFrequency == (*State->PortList)[ (i & 0xFE) + 1].SelFrequency); if ((*State->PortList)[i].SelRegang) { ASSERT ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU); ASSERT ((*State->PortList)[i].Link < 4); State->Nb->SetLinkRegang ( (*State->PortList)[i].NodeID, (*State->PortList)[i].Link, State->Nb ); } // // IDS port override for CPUs and IO Devices // pf_HtIdsGetPortOverride ((BOOLEAN) ((i & 1) == 0), &(*State->PortList)[i], &(*State->PortList)[i + 1], &PortOverrides, State); LinkBase = (*State->PortList)[i].Pointer; if (((*State->PortList)[i].Type == PORTLIST_TYPE_IO) && ((*State->PortList)[i].Link == 1)) { LinkBase.Address.Register += HTSLAVE_LINK01_OFFSET; } // HT CRC Feature, set if configured. The default is not to set it, because with some chipsets it // will lock up if done here. if (State->IsSetHtCrcFlood) { Temp = 1; Reg = LinkBase; Reg.Address.Register += HTHOST_LINK_CONTROL_REG; State->HtFeatures->SetHtControlRegisterBits (Reg, 1, 1, &Temp, State); if ((*State->PortList)[i].Type == PORTLIST_TYPE_IO) { // IO Devices also need to have SERR enabled. Reg = LinkBase; Reg.Address.Register = PCI_CONFIG_COMMAND_REG04; LibAmdPciWriteBits (Reg, 8, 8, &Temp, State->ConfigHandle); } } // Some IO devices don't work properly when setting widths, so write them in a single operation, // rather than individually. // Widthout = ConvertWidthToBits ((*State->PortList)[i].SelWidthOut); ASSERT (Widthout == 1 || Widthout == 0 || Widthout == 5 || Widthout == 4); Widthin = ConvertWidthToBits ((*State->PortList)[i].SelWidthIn); ASSERT (Widthin == 1 || Widthin == 0 || Widthin == 5 || Widthin == 4); Temp = (Widthin & 7) | ((Widthout & 7) << 4); Reg = LinkBase; Reg.Address.Register += HTHOST_LINK_CONTROL_REG; State->HtFeatures->SetHtControlRegisterBits (Reg, 31, 24, &Temp, State); Temp = (*State->PortList)[i].SelFrequency; IDS_HDT_CONSOLE (HT_TRACE, "Link Frequency: Node %02d: Link %02d: is running at %2d00MHz\n", (*State->PortList)[i].NodeID, (*State->PortList)[i].Link, (Temp < HT_FREQUENCY_800M) ? Temp + 2 : ((Temp < HT_FREQUENCY_2800M) ? 2 * (Temp - 1) : 2 * (Temp - 3))); if ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) { State->Nb->SetLinkFrequency ( (*State->PortList)[i].NodeID, (*State->PortList)[i].Link, (UINT8)Temp, State->Nb ); } else { ASSERT (Temp <= HT_FREQUENCY_2600M); // Write the frequency setting Reg = LinkBase; Reg.Address.Register += HTSLAVE_FREQ_REV_0_REG; SetHtIoFrequencyRegisterBits (Reg, 11, 8, &Temp, State); // Handle additional HT3 frequency requirements, if needed, // or clear them if switching down to ht1 on a warm reset. // Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz // // Even though we assert if debugging, we need to check that the capability was // found always, since this is an unknown hardware device, also we are taking // unqualified frequency from the external interface (could be trying to do ht3 // on an ht1 IO device). // if (Temp > HT_FREQUENCY_1000M) { // Enabling features if gen 3 Bits = 1; } else { // Disabling features if gen 1 Bits = 0; } // Retry Enable if (DoesDeviceHaveHtSubtypeCap (LinkBase, HT_RETRY_CAPABILITY, &CurrentPtr, State)) { ASSERT ((*State->PortList)[i].Link < 2); CurrentPtr.Address.Register += HTRETRY_CONTROL_REG; LibAmdPciWriteBits (CurrentPtr, ((*State->PortList)[i].Link * 16), ((*State->PortList)[i].Link * 16), &Bits, State->ConfigHandle); } else { // If we are turning it off, that may mean the device was only ht1 capable, // so don't complain that we can't do it. // if (Bits != 0) { NotifyWarningOptRequiredCapRetry ((*State->PortList)[i].NodeID, (*State->PortList)[i].HostLink, (*State->PortList)[i].HostDepth, State); } } // Scrambling enable if (DoesDeviceHaveHtSubtypeCap (LinkBase, HT_GEN3_CAPABILITY, &CurrentPtr, State)) { ASSERT ((*State->PortList)[i].Link < 2); CurrentPtr.Address.Register = CurrentPtr.Address.Register + HTGEN3_LINK_TRAINING_0_REG + ((*State->PortList)[i].Link * HTGEN3_LINK01_OFFSET); LibAmdPciWriteBits (CurrentPtr, 3, 3, &Bits, State->ConfigHandle); } else { // If we are turning it off, that may mean the device was only ht1 capable, // so don't complain that we can't do it. // if (Bits != 0) { NotifyWarningOptRequiredCapGen3 ((*State->PortList)[i].NodeID, (*State->PortList)[i].HostLink, (*State->PortList)[i].HostDepth, State); } } } // Enable Unit ID Clumping if supported. if (State->IsUsingUnitIdClumping) { if (((*State->PortList)[i].ClumpingSupport != HT_CLUMPING_PASSIVE) && ((*State->PortList)[i].ClumpingSupport != HT_CLUMPING_DISABLE)) { Bits = (*State->PortList)[i].ClumpingSupport; if ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) { State->Nb->SetLinkUnitIdClumping ( (*State->PortList)[i].NodeID, (*State->PortList)[i].Link, (*State->PortList)[i].ClumpingSupport, State->Nb ); } else { if (DoesDeviceHaveHtSubtypeCap (LinkBase, HT_UNITID_CAPABILITY, &Reg, State)) { Reg.Address.Register += HTUNIT_ENABLE_REG; LibAmdPciWriteBits (Reg, 31, 0, &Bits, State->ConfigHandle); } else { // If we found one when gathering support, we have to find one now. ASSERT (FALSE); } } } } } }
/** * Get Link features into system data structure. * * @HtFeatMethod{::F_GATHER_LINK_DATA} * * For all discovered Links, populate the port list with the frequency and width * capabilities. Gather support data for: * - Unit ID Clumping * * @param[in] State our global state, port list */ VOID GatherLinkData ( IN STATE_DATA *State ) { UINT8 i; PCI_ADDR LinkBase; PCI_ADDR Reg; UINT32 Bits; UINT8 Revision; // Get the capability base for whatever device type the link port is on for (i = 0; i < (State->TotalLinks * 2); i++) { if ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) { LinkBase = State->Nb->MakeLinkBase ((*State->PortList)[i].NodeID, (*State->PortList)[i].Link, State->Nb); (*State->PortList)[i].Pointer = LinkBase; } else { LinkBase = (*State->PortList)[i].Pointer; if ((*State->PortList)[i].Link == 1) { LinkBase.Address.Register += HTSLAVE_LINK01_OFFSET; } } // Getting the Width is standard across device types Reg = LinkBase; Reg.Address.Register += HTSLAVE_LINK_CONTROL_0_REG; LibAmdPciReadBits (Reg, 22, 20, &Bits, State->ConfigHandle); (*State->PortList)[i].PrvWidthOutCap = ConvertBitsToWidth ((UINT8)Bits); LibAmdPciReadBits (Reg, 18, 16, &Bits, State->ConfigHandle); (*State->PortList)[i].PrvWidthInCap = ConvertBitsToWidth ((UINT8)Bits); // Get Frequency and other device type specific features if ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) { State->Nb->GatherLinkFeatures (&(*State->PortList)[i], State->HtInterface, State->PlatformConfiguration, State->Nb); } else { Reg = LinkBase; Reg.Address.Register += HTSLAVE_FREQ_REV_0_REG; LibAmdPciReadBits (Reg, 31, 16, &Bits, State->ConfigHandle); (*State->PortList)[i].PrvFrequencyCap = Bits; // Unit ID Clumping Support if (State->IsUsingUnitIdClumping) { if (DoesDeviceHaveHtSubtypeCap (LinkBase, HT_UNITID_CAPABILITY, &Reg, State)) { Reg.Address.Register += HTUNIT_SUPPORT_REG; LibAmdPciReadBits (Reg, 31, 0, &Bits, State->ConfigHandle); } else { // Not there, that's ok, we don't know that it should have one. // Check for Passive support. (Bit 0 won't be set if full support is implemented, // so we can use it to indicate passive support in our portlist struct). Reg = LinkBase; Reg.Address.Register += HTSLAVE_FEATURECAP_REG; Bits = 1; LibAmdPciWriteBits (Reg, 5, 5, &Bits, State->ConfigHandle); LibAmdPciReadBits (Reg, 5, 5, &Bits, State->ConfigHandle); } (*State->PortList)[i].ClumpingSupport = Bits; } else { (*State->PortList)[i].ClumpingSupport = HT_CLUMPING_DISABLE; } Reg = LinkBase; Reg.Address.Register = PCI_CONFIG_REVISION_REG08; LibAmdPciReadBits ( LinkBase, 7, 0, &Bits, State->ConfigHandle); Revision = (UINT8) Bits; LinkBase.Address.Register = 0; LibAmdPciRead (AccessWidth32, LinkBase, &Bits, State->ConfigHandle); State->HtInterface->GetDeviceCapOverride ((*State->PortList)[i].NodeID, (*State->PortList)[i].HostLink, (*State->PortList)[i].HostDepth, (*State->PortList)[i].Pointer, Bits, Revision, (*State->PortList)[i].Link, &((*State->PortList)[i].PrvWidthInCap), &((*State->PortList)[i].PrvWidthOutCap), &((*State->PortList)[i].PrvFrequencyCap), &((*State->PortList)[i].ClumpingSupport), State); } } }