7 * Main Memory Feature implementation file for Node Interleaving
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/Main)
12 * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * * Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
28 * its contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 * ***************************************************************************
47 *----------------------------------------------------------------------------
50 *----------------------------------------------------------------------------
55 #include "OptionMemory.h"
61 #include "heapManager.h"
66 #define FILECODE PROC_MEM_MAIN_MMMEMRESTORE_FILECODE
72 /*----------------------------------------------------------------------------
73 * PROTOTYPES OF LOCAL FUNCTIONS
75 *----------------------------------------------------------------------------
79 MemMRestoreDqsTimings (
81 IN MEM_MAIN_DATA_BLOCK *MemMainPtr
87 IN OUT MEM_NB_BLOCK *NBPtr,
88 IN PCI_SPECIAL_CASE *SpecialCases,
96 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr,
97 OUT S3_MEM_NB_BLOCK **S3NBPtr
102 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
107 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
110 /*-----------------------------------------------------------------------------
113 *-----------------------------------------------------------------------------
115 extern MEM_NB_SUPPORT memNBInstalled[];
117 /* -----------------------------------------------------------------------------*/
120 * Check and save memory context if possible.
122 * @param[in,out] *MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
127 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
132 MEM_PARAMETER_STRUCT *RefPtr;
133 LOCATE_HEAP_PTR LocHeap;
134 ALLOCATE_HEAP_PARAMS AllocHeapParams;
135 DEVICE_BLOCK_HEADER *DeviceList;
136 AMD_CONFIG_PARAMS *StdHeader;
139 MEM_NB_BLOCK *NBArray;
140 S3_MEM_NB_BLOCK *S3NBPtr;
141 DESCRIPTOR_GROUP DeviceDescript[MAX_NODES_SUPPORTED];
143 NBArray = MemMainPtr->NBPtr;
144 RefPtr = NBArray[BSP_DIE].RefPtr;
146 if (RefPtr->SaveMemContextCtl) {
147 RefPtr->MemContext.NvStorage = NULL;
148 RefPtr->MemContext.NvStorageSize = 0;
150 // Make sure DQS training has occurred before saving memory context
151 if (!RefPtr->MemRestoreCtl) {
152 StdHeader = &MemMainPtr->MemPtr->StdHeader;
154 MemMCreateS3NbBlock (MemMainPtr, &S3NBPtr);
155 if (S3NBPtr != NULL) {
156 // Get the mask bit and the register list for node that presents
158 for (Node = 0; Node < MemMainPtr->DieCount; Node ++) {
159 S3NBPtr->MemS3GetConPCIMask (&NBArray[Node], (VOID *)&DeviceDescript[Node]);
160 S3NBPtr->MemS3GetConMSRMask (&NBArray[Node], (VOID *)&DeviceDescript[Node]);
161 BufferSize += S3NBPtr->MemS3GetRegLstPtr (&NBArray[Node], (VOID *)&DeviceDescript[Node]);
164 // Base on the size of the device list, apply for a buffer for it.
165 AllocHeapParams.RequestedBufferSize = (UINT32) (BufferSize + sizeof (DEVICE_BLOCK_HEADER));
166 AllocHeapParams.BufferHandle = AMD_MEM_S3_DATA_HANDLE;
167 AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
168 if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
169 DeviceList = (DEVICE_BLOCK_HEADER *) AllocHeapParams.BufferPtr;
170 DeviceList->RelativeOrMaskOffset = (UINT16) AllocHeapParams.RequestedBufferSize;
172 // Copy device list on the stack to the heap.
173 BufferOffset = sizeof (DEVICE_BLOCK_HEADER) + AllocHeapParams.BufferPtr;
174 for (Node = 0; Node < MemMainPtr->DieCount; Node ++) {
175 for (i = PRESELFREF; i <= POSTSELFREF; i ++) {
176 // Copy PCI device descriptor to the heap if it exists.
177 if (DeviceDescript[Node].PCIDevice[i].RegisterListID != 0xFFFFFFFF) {
178 LibAmdMemCopy (BufferOffset, &(DeviceDescript[Node].PCIDevice[i]), sizeof (PCI_DEVICE_DESCRIPTOR), StdHeader);
179 DeviceList->NumDevices ++;
180 BufferOffset = sizeof (PCI_DEVICE_DESCRIPTOR) + (UINT8 *)BufferOffset;
182 // Copy conditional PCI device descriptor to the heap if it exists.
183 if (DeviceDescript[Node].CPCIDevice[i].RegisterListID != 0xFFFFFFFF) {
184 LibAmdMemCopy (BufferOffset, &(DeviceDescript[Node].CPCIDevice[i]), sizeof (CONDITIONAL_PCI_DEVICE_DESCRIPTOR), StdHeader);
185 DeviceList->NumDevices ++;
186 BufferOffset = sizeof (CONDITIONAL_PCI_DEVICE_DESCRIPTOR) + (UINT8 *)BufferOffset;
188 // Copy MSR device descriptor to the heap if it exists.
189 if (DeviceDescript[Node].MSRDevice[i].RegisterListID != 0xFFFFFFFF) {
190 LibAmdMemCopy (BufferOffset, &(DeviceDescript[Node].MSRDevice[i]), sizeof (MSR_DEVICE_DESCRIPTOR), StdHeader);
191 DeviceList->NumDevices ++;
192 BufferOffset = sizeof (MSR_DEVICE_DESCRIPTOR) + (UINT8 *)BufferOffset;
194 // Copy conditional MSR device descriptor to the heap if it exists.
195 if (DeviceDescript[Node].CMSRDevice[i].RegisterListID != 0xFFFFFFFF) {
196 LibAmdMemCopy (BufferOffset, &(DeviceDescript[Node].PCIDevice[i]), sizeof (CONDITIONAL_MSR_DEVICE_DESCRIPTOR), StdHeader);
197 DeviceList->NumDevices ++;
198 BufferOffset = sizeof (CONDITIONAL_MSR_DEVICE_DESCRIPTOR) + (UINT8 *)BufferOffset;
203 // Determine size needed
204 BufferSize = GetWorstCaseContextSize (DeviceList, INIT_RESUME, StdHeader);
205 AllocHeapParams.RequestedBufferSize = BufferSize;
206 AllocHeapParams.BufferHandle = AMD_S3_SAVE_HANDLE;
207 AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
208 if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
209 // Save memory context
210 SaveDeviceListContext (DeviceList, AllocHeapParams.BufferPtr, INIT_RESUME, &BufferSize, StdHeader);
211 RefPtr->MemContext.NvStorageSize = BufferSize;
214 HeapDeallocateBuffer (AMD_MEM_S3_DATA_HANDLE, StdHeader);
217 HeapDeallocateBuffer (AMD_MEM_S3_NB_HANDLE, StdHeader);
219 // Locate MemContext since it might have been shifted after deallocating
220 LocHeap.BufferHandle = AMD_S3_SAVE_HANDLE;
221 if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) {
222 RefPtr->MemContext.NvStorage = LocHeap.BufferPtr;
227 for (Node = 0; Node < MemMainPtr->DieCount; Node++) {
228 NBArray[Node].FamilySpecificHook[AfterSaveRestore] (&NBArray[Node], &NBArray[Node]);
232 /* -----------------------------------------------------------------------------*/
235 * Check and restore memory context if possible.
237 * @param[in,out] *MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
239 * @return TRUE - DQS timing restore succeeds.
240 * @return FALSE - DQS timing restore fails.
244 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
248 MEM_NB_BLOCK *NBArray;
249 MEM_PARAMETER_STRUCT *RefPtr;
250 S3_MEM_NB_BLOCK *S3NBPtr;
252 NBArray = MemMainPtr->NBPtr;
253 RefPtr = NBArray[BSP_DIE].RefPtr;
255 IDS_HDT_CONSOLE (MEM_STATUS, "\nStart Mem Restore\n");
256 if (RefPtr->MemRestoreCtl) {
257 if (RefPtr->MemContext.NvStorage != NULL) {
258 MemMCreateS3NbBlock (MemMainPtr, &S3NBPtr);
259 if (S3NBPtr != NULL) {
260 // Check DIMM config and restore DQS timings if possible
261 if (!MemMRestoreDqsTimings (RefPtr->MemContext.NvStorage, MemMainPtr)) {
262 RefPtr->MemRestoreCtl = FALSE;
265 RefPtr->MemRestoreCtl = FALSE;
267 HeapDeallocateBuffer (AMD_MEM_S3_NB_HANDLE, &(MemMainPtr->MemPtr->StdHeader));
269 RefPtr->MemRestoreCtl = FALSE;
273 for (Node = 0; Node < MemMainPtr->DieCount; Node++) {
274 NBArray[Node].FamilySpecificHook[AfterSaveRestore] (&NBArray[Node], &NBArray[Node]);
276 IDS_HDT_CONSOLE (MEM_FLOW, RefPtr->MemRestoreCtl ? "Mem Restore Succeeds!\n" : "Mem Restore Fails!\n");
277 return RefPtr->MemRestoreCtl;
280 /*----------------------------------------------------------------------------
283 *----------------------------------------------------------------------------
286 /*---------------------------------------------------------------------------------------*/
288 * Restores all devices that contains DQS timings
290 * @param[in] Storage Beginning of the device list.
291 * @param[in,out] MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
293 * @return TRUE - No fatal error occurs.
294 * @return FALSE - Fatal error occurs.
299 MemMRestoreDqsTimings (
301 IN MEM_MAIN_DATA_BLOCK *MemMainPtr
304 AMD_CONFIG_PARAMS *StdHeader;
306 DEVICE_DESCRIPTORS Device;
309 DEVICE_BLOCK_HEADER *DeviceList;
310 PCI_REGISTER_BLOCK_HEADER *Reg;
311 CPCI_REGISTER_BLOCK_HEADER *CReg;
312 MSR_REGISTER_BLOCK_HEADER *MsrReg;
313 CMSR_REGISTER_BLOCK_HEADER *CMsrReg;
315 MEM_NB_BLOCK *NBArray;
321 NBArray = MemMainPtr->NBPtr;
322 StdHeader = &(MemMainPtr->MemPtr->StdHeader);
323 DeviceList = (DEVICE_BLOCK_HEADER *) Storage;
324 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
325 OrMask = (UINT8 *) DeviceList + DeviceList->RelativeOrMaskOffset;
327 if (DeviceList->NumDevices == 0) {
333 for (i = 0; State != ST_DONE; i++) {
334 if (((State == ST_PRE_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_PCI_PRE_ESR)) ||
335 ((State == ST_POST_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_PCI))) {
336 MemFS3GetPciDeviceRegisterList (Device.PciDevice, &Reg, StdHeader);
337 Node = Device.PciDevice->Node;
338 IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", Node);
339 PciAddress = NBArray[Node].PciAddr;
340 for (j = 0; j < Reg->NumRegisters; j++) {
341 PciAddress.Address.Function = Reg->RegisterList[j].Function;
342 PciAddress.Address.Register = Reg->RegisterList[j].Offset;
343 PciAddress.Address.Segment = (Reg->RegisterList[j].Type.SpecialCaseFlag != 0) ?
344 0xF - Reg->RegisterList[j].Type.SpecialCaseIndex : 0;
345 if (!MemMSetCSRNb (&NBArray[Node], Reg->SpecialCases, PciAddress, *((UINT32 *) OrMask) & Reg->RegisterList[j].AndMask)) {
346 return FALSE; // Restore fails
348 OrMask += (Reg->RegisterList[j].Type.RegisterSize == 0) ? 4 : Reg->RegisterList[j].Type.RegisterSize;
351 if (MaxNode < Node) {
355 } else if (((State == ST_PRE_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_CPCI_PRE_ESR)) ||
356 ((State == ST_POST_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_CPCI))) {
357 MemFS3GetCPciDeviceRegisterList (Device.CPciDevice, &CReg, StdHeader);
358 Node = Device.CPciDevice->Node;
359 IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", Node);
360 PciAddress = NBArray[Node].PciAddr;
361 for (j = 0; j < CReg->NumRegisters; j++) {
362 if (((Device.CPciDevice->Mask1 & CReg->RegisterList[j].Mask1) != 0) &&
363 ((Device.CPciDevice->Mask2 & CReg->RegisterList[j].Mask2) != 0)) {
364 PciAddress.Address.Function = CReg->RegisterList[j].Function;
365 PciAddress.Address.Register = CReg->RegisterList[j].Offset;
366 PciAddress.Address.Segment = (CReg->RegisterList[j].Type.SpecialCaseFlag != 0) ?
367 0xF - CReg->RegisterList[j].Type.SpecialCaseIndex : 0;
368 if (!MemMSetCSRNb (&NBArray[Node], CReg->SpecialCases, PciAddress, *((UINT32 *) OrMask) & CReg->RegisterList[j].AndMask)) {
369 return FALSE; // Restore fails
371 OrMask += (CReg->RegisterList[j].Type.RegisterSize == 0) ? 4 : CReg->RegisterList[j].Type.RegisterSize;
374 } else if (((State == ST_PRE_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_MSR_PRE_ESR)) ||
375 ((State == ST_POST_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_MSR))) {
376 MemFS3GetMsrDeviceRegisterList (Device.MsrDevice, &MsrReg, StdHeader);
377 for (j = 0; j < MsrReg->NumRegisters; j++) {
380 } else if (((State == ST_PRE_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_CMSR_PRE_ESR)) ||
381 ((State == ST_POST_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_CMSR))) {
382 MemFS3GetCMsrDeviceRegisterList (Device.CMsrDevice, &CMsrReg, StdHeader);
383 for (j = 0; j < CMsrReg->NumRegisters; j++) {
384 if (((Device.CMsrDevice->Mask1 & CMsrReg->RegisterList[j].Mask1) != 0) &&
385 ((Device.CMsrDevice->Mask2 & CMsrReg->RegisterList[j].Mask2) != 0)) {
391 switch (Device.CommonDeviceHeader->Type) {
392 case DEV_TYPE_PCI_PRE_ESR:
393 // Fall through to advance the pointer after restoring context
397 case DEV_TYPE_CPCI_PRE_ESR:
398 // Fall through to advance the pointer after restoring context
402 case DEV_TYPE_MSR_PRE_ESR:
403 // Fall through to advance the pointer after restoring context
407 case DEV_TYPE_CMSR_PRE_ESR:
408 // Fall through to advance the pointer after restoring context
417 if (i == (DeviceList->NumDevices - 1)) {
421 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
423 // Check to see if processor or DIMM population has changed
424 if ((MaxNode + 1) != MemMainPtr->DieCount) {
425 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: Population changed\n");
429 // Perform MemClk frequency change
430 for (Node = 0; Node < MemMainPtr->DieCount; Node ++) {
431 if (NBArray[Node].MCTPtr->NodeMemSize != 0) {
432 NBArray[Node].BeforeDqsTraining (&NBArray[Node]);
433 if (NBArray[Node].DCTPtr->Timings.Speed < NBArray[Node].DCTPtr->Timings.TargetSpeed) {
434 for (Dct = 0; Dct < NBArray[Node].DctCount; Dct++) {
435 NBArray[Node].SwitchDCT (&NBArray[Node], Dct);
436 NBArray[Node].DCTPtr->Timings.Speed = NBArray[Node].DCTPtr->Timings.TargetSpeed;
438 IDS_OPTION_HOOK (IDS_BEFORE_MEM_FREQ_CHG, &NBArray[Node], &(MemMainPtr->MemPtr->StdHeader));
439 NBArray[Node].ChangeFrequency (&NBArray[Node]);
449 /* -----------------------------------------------------------------------------*/
452 * This function filters out other settings and only restores DQS timings.
454 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
455 * @param[in] SpecialCases - Pointer to special cases array handlers
456 * @param[in] PciAddr - address of the CSR register in PCI_ADDR format.
457 * @param[in] Value - Value to be programmed
459 * @return TRUE - No fatal error occurs.
460 * @return FALSE - Fatal error occurs.
467 IN OUT MEM_NB_BLOCK *NBPtr,
468 IN PCI_SPECIAL_CASE *SpecialCases,
480 if (PciAddr.Address.Segment != 0) {
481 if (PciAddr.Address.Segment == 0xF) {
482 PciAddr.Address.Segment = 0;
483 Dct = (UINT8) ((PciAddr.Address.Register >> 10) & 1);
484 Offset = PciAddr.Address.Register & 0x3FF;
485 BOffset = PciAddr.Address.Register & 0xFF;
486 if ((PciAddr.Address.Register & 0x800) == 0) {
487 if (((BOffset >= 1) && (BOffset <= 3)) ||
488 ((BOffset >= 5) && (BOffset <= 7)) ||
489 ((Offset >= 0x10) && (Offset <= 0x2B)) ||
490 ((Offset >= 0x30) && (Offset <= 0x4A))) {
491 IDS_HDT_CONSOLE (MEM_FLOW, "\t\tF2_%d9C_%03x = %08x\n", Dct, Offset, Value);
493 SpecialCases[0].Restore (AccessS3SaveWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
498 Dct = (UINT8) ((PciAddr.Address.Register >> 8) & 1);
499 Offset = PciAddr.Address.Register & 0xFF;
501 if (PciAddr.Address.Function == 2) {
502 if ((Offset >= 0x40) && (Offset < 0x60) && ((Value & 4) != 0)) {
503 // If TestFail bit is set, set CsTestFail
504 NBPtr->SwitchDCT (NBPtr, Dct);
505 NBPtr->DCTPtr->Timings.CsTrainFail |= (UINT16)1 << ((Offset - 0x40) >> 2);
506 IDS_HDT_CONSOLE (MEM_FLOW, "\tBad CS:%d\n", ((Offset - 0x40) >> 2));
507 } else if (Offset == 0x80) {
508 LibAmdPciRead (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
510 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: DIMM config changed\n");
513 } else if (Offset == 0x90) {
514 LibAmdPciRead (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
515 if ((Temp & 0x0001F000) != (Value & 0x0001F000)) {
516 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: DIMM config changed\n");
519 } else if (Offset == 0x94) {
520 LibAmdPciRead (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
521 if ((Temp & 0x00061000) != (Value & 0x00061000)) {
522 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: DIMM config changed\n");
525 if (((Value & 0x4000) == 0) && (NBPtr->GetMemClkFreqId (NBPtr, NBPtr->DCTPtr->Timings.TargetSpeed) != ((Value & 7) + 1))) {
526 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: MemClk has changed\n");
529 // Restore ZqcsInterval
531 Temp |= (Value & 0x00000C00);
532 LibAmdPciWrite (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
533 } else if (Offset == 0x78) {
535 LibAmdPciRead (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
537 Temp |= (Value & 0xFFC00000);
538 LibAmdPciWrite (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
539 } else if (PciAddr.Address.Register == 0x110) {
540 if ((NBPtr->MCTPtr->NodeMemSize != 0) && (Value == 0x00000100)) {
541 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: DIMM config changed\n");
548 if (RetVal == FALSE) {
549 NBPtr->SwitchDCT (NBPtr, 0);
550 NBPtr->DCTPtr->Timings.CsTrainFail = 0;
551 NBPtr->SwitchDCT (NBPtr, 1);
552 NBPtr->DCTPtr->Timings.CsTrainFail = 0;
558 /* -----------------------------------------------------------------------------*/
561 * Create S3 NB Block.
563 * @param[in,out] MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
564 * @param[out] S3NBPtr - Pointer to the S3 NB Block pointer
569 MemMCreateS3NbBlock (
570 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr,
571 OUT S3_MEM_NB_BLOCK **S3NBPtr
576 MEM_NB_BLOCK *NBArray;
577 MEM_NB_BLOCK *DummyNBs;
578 ALLOCATE_HEAP_PARAMS AllocHeapParams;
580 NBArray = MemMainPtr->NBPtr;
584 // Allocate heap for S3 NB Blocks
585 AllocHeapParams.RequestedBufferSize = (MemMainPtr->DieCount * (sizeof (S3_MEM_NB_BLOCK) + sizeof (MEM_NB_BLOCK)));
586 AllocHeapParams.BufferHandle = AMD_MEM_S3_NB_HANDLE;
587 AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
588 if (HeapAllocateBuffer (&AllocHeapParams, &(MemMainPtr->MemPtr->StdHeader)) == AGESA_SUCCESS) {
589 *S3NBPtr = (S3_MEM_NB_BLOCK *) AllocHeapParams.BufferPtr;
590 DummyNBs = (MEM_NB_BLOCK *) (AllocHeapParams.BufferPtr + MemMainPtr->DieCount * sizeof (S3_MEM_NB_BLOCK));
592 // Initialize S3 NB Blocks
593 for (Node = 0; Node < MemMainPtr->DieCount; Node ++) {
594 (*S3NBPtr)[Node].NBPtr = &DummyNBs[Node];
596 for (i = 0; memNBInstalled[i].MemS3ResumeConstructNBBlock != 0; i++) {
597 if (memNBInstalled[i].MemS3ResumeConstructNBBlock (&(*S3NBPtr)[Node], NBArray[BSP_DIE].MemPtr, Node)) {
601 if (memNBInstalled[i].MemS3ResumeConstructNBBlock == 0) {