AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / Family / 0x10 / cpuF10Dmi.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD DMI Record Creation API, and related functions.
6  *
7  * Contains code that produce the DMI related information.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU
12  * @e \$Revision: 58105 $   @e \$Date: 2011-08-19 17:46:09 -0600 (Fri, 19 Aug 2011) $
13  *
14  */
15 /*****************************************************************************
16  *
17  * Copyright (C) 2012 Advanced Micro Devices, Inc.
18  * All rights reserved.
19  *
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.
30  *
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.
41  *
42  ******************************************************************************
43  */
44
45 /*----------------------------------------------------------------------------------------
46  *                             M O D U L E S    U S E D
47  *----------------------------------------------------------------------------------------
48  */
49 #include "AGESA.h"
50 #include "amdlib.h"
51 #include "cpuRegisters.h"
52 #include "cpuFamilyTranslation.h"
53 #include "cpuPstateTables.h"
54 #include "cpuLateInit.h"
55 #include "cpuF10PowerMgmt.h"
56 #include "cpuServices.h"
57 #include "GeneralServices.h"
58 #include "cpuF10Utilities.h"
59 #include "Filecode.h"
60 CODE_GROUP (G3_DXE)
61 RDATA_GROUP (G3_DXE)
62
63 #define FILECODE PROC_CPU_FAMILY_0X10_CPUF10DMI_FILECODE
64
65 /*----------------------------------------------------------------------------------------
66  *                   D E F I N I T I O N S    A N D    M A C R O S
67  *----------------------------------------------------------------------------------------
68  */
69 extern CPU_FAMILY_SUPPORT_TABLE            PstateFamilyServiceTable;
70 /*----------------------------------------------------------------------------------------
71  *                  T Y P E D E F S     A N D     S T R U C T U R E S
72  *----------------------------------------------------------------------------------------
73  */
74
75 /*----------------------------------------------------------------------------------------
76  *           P R O T O T Y P E S     O F     L O C A L     F U N C T I O N S
77  *----------------------------------------------------------------------------------------
78  */
79 VOID
80 DmiF10GetInfo (
81   IN OUT   CPU_TYPE_INFO *CpuInfoPtr,
82   IN       AMD_CONFIG_PARAMS  *StdHeader
83   );
84
85 UINT8
86 DmiF10GetVoltage (
87   IN       AMD_CONFIG_PARAMS  *StdHeader
88   );
89
90 UINT16
91 DmiF10GetMaxSpeed (
92   IN       AMD_CONFIG_PARAMS  *StdHeader
93   );
94
95 UINT16
96 DmiF10GetExtClock (
97   IN       AMD_CONFIG_PARAMS  *StdHeader
98   );
99
100 VOID
101 DmiF10GetMemInfo (
102   IN OUT   CPU_GET_MEM_INFO  *CpuGetMemInfoPtr,
103   IN       AMD_CONFIG_PARAMS  *StdHeader
104   );
105
106 VOID
107 STATIC
108 F10Translate7BitVidTo6Bit (
109   IN OUT   UINT8 * MaxVidPtr
110   );
111
112 /*----------------------------------------------------------------------------------------
113  *                          E X P O R T E D    F U N C T I O N S
114  *----------------------------------------------------------------------------------------
115  */
116
117 /* -----------------------------------------------------------------------------*/
118 /**
119  *
120  *  DmiF10GetInfo
121  *
122  *    Get CPU type information
123  *
124  *    @param[in,out]  CpuInfoPtr     Pointer to CPU_TYPE_INFO struct.
125  *    @param[in]      StdHeader      Standard Head Pointer
126  *
127  */
128 VOID
129 DmiF10GetInfo (
130   IN OUT   CPU_TYPE_INFO *CpuInfoPtr,
131   IN       AMD_CONFIG_PARAMS  *StdHeader
132   )
133 {
134   CPUID_DATA CpuId;
135   CPU_SPECIFIC_SERVICES *FamilySpecificServices;
136
137   LibAmdCpuidRead (AMD_CPUID_FMF, &CpuId, StdHeader);
138   CpuInfoPtr->ExtendedFamily = (UINT8) (CpuId.EAX_Reg >> 20) & 0xFF; // bit 27:20
139   CpuInfoPtr->ExtendedModel = (UINT8) (CpuId.EAX_Reg >> 16) & 0xF; // bit 19:16
140   CpuInfoPtr->BaseFamily = (UINT8) (CpuId.EAX_Reg >> 8) & 0xF; // bit 11:8
141   CpuInfoPtr->BaseModel = (UINT8) (CpuId.EAX_Reg >> 4)  & 0xF; // bit 7:4
142   CpuInfoPtr->Stepping = (UINT8) (CpuId.EAX_Reg & 0xF); // bit 3:0
143
144   CpuInfoPtr->PackageType = (UINT8) (CpuId.EBX_Reg >> 28) & 0xF; // bit 31:28
145   CpuInfoPtr->BrandId.Pg = (UINT8) (CpuId.EBX_Reg >> 15) & 0x1; // bit 15
146   CpuInfoPtr->BrandId.String1 = (UINT8) (CpuId.EBX_Reg >> 11) & 0xF; // bit 14:11
147   CpuInfoPtr->BrandId.Model = (UINT8) (CpuId.EBX_Reg >> 4) & 0x7F; // bit 10:4
148   CpuInfoPtr->BrandId.String2 = (UINT8) (CpuId.EBX_Reg & 0xF); // bit 3:0
149
150   GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
151   CpuInfoPtr->TotalCoreNumber = FamilySpecificServices->GetNumberOfPhysicalCores (FamilySpecificServices, StdHeader);
152   CpuInfoPtr->TotalCoreNumber--;
153
154   LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuId, StdHeader);
155   CpuInfoPtr->EnabledCoreNumber = (UINT8) (CpuId.ECX_Reg & 0xFF); // bit 7:0
156
157   switch (CpuInfoPtr->PackageType) {
158   case DR_SOCKET_1207:
159     CpuInfoPtr->ProcUpgrade = P_UPGRADE_F1207;
160     break;
161   case DR_SOCKET_AM3:
162     CpuInfoPtr->ProcUpgrade = P_UPGRADE_AM3;
163     break;
164   case DR_SOCKET_S1G3:
165     CpuInfoPtr->ProcUpgrade = P_UPGRADE_S1GX;
166     break;
167   case DR_SOCKET_G34:
168     CpuInfoPtr->ProcUpgrade = P_UPGRADE_G34;
169     break;
170   case DR_SOCKET_ASB2:
171     CpuInfoPtr->ProcUpgrade = P_UPGRADE_NONE;
172     break;
173   case DR_SOCKET_C32:
174     CpuInfoPtr->ProcUpgrade = P_UPGRADE_C32;
175     break;
176   default:
177     CpuInfoPtr->ProcUpgrade = P_UPGRADE_UNKNOWN;
178     break;
179   }
180
181   LibAmdCpuidRead (AMD_CPUID_TLB_L1Cache, &CpuId, StdHeader);
182   CpuInfoPtr->L1CacheSize = (UINT32) (((UINT8) (CpuId.ECX_Reg >> 24) + (UINT8) (CpuId.EDX_Reg >> 24)) * (CpuInfoPtr->EnabledCoreNumber + 1));
183
184   LibAmdCpuidRead (AMD_CPUID_L2L3Cache_L2TLB, &CpuId, StdHeader);
185   CpuInfoPtr->L2CacheSize = (UINT32) ((UINT16) (CpuId.ECX_Reg >> 16) * (CpuInfoPtr->EnabledCoreNumber + 1));
186 }
187
188 /* -----------------------------------------------------------------------------*/
189 /**
190  *
191  *  DmiF10GetVoltage
192  *
193  *    Get the voltage value according to SMBIOS SPEC's requirement.
194  *
195  *    @param[in]      StdHeader      Standard Head Pointer
196  *
197  *    @retval  Voltage   - CPU Voltage.
198  *
199  */
200 UINT8
201 DmiF10GetVoltage (
202   IN       AMD_CONFIG_PARAMS  *StdHeader
203   )
204 {
205   UINT8     MaxVid;
206   UINT8     Voltage;
207   UINT8     NumberBoostStates;
208   UINT32    Pvimode;
209   UINT32    CurrentNodeNum;
210   UINT64    MsrData;
211   PCI_ADDR  TempAddr;
212   CPU_LOGICAL_ID    CpuFamilyRevision;
213   CPB_CTRL_REGISTER CpbCtrl;
214
215   // Voltage = 0x80 + (voltage at boot time * 10)
216   GetCurrentNodeNum (&CurrentNodeNum, StdHeader);
217   TempAddr.AddressValue = MAKE_SBDFO (0, 0, (24 + CurrentNodeNum), FUNC_3, PW_CTL_MISC_REG);
218   LibAmdPciReadBits (TempAddr, 8, 8, &Pvimode, (VOID *)StdHeader);
219   //Pvimode is a 1-bit register field:  1-PVI 0-SVI
220
221   GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
222   if ((CpuFamilyRevision.Revision & AMD_F10_PH_ALL) != 0) {
223     TempAddr.AddressValue = MAKE_SBDFO (0, 0, (24 + CurrentNodeNum), FUNC_4, CPB_CTRL_REG);
224     LibAmdPciRead (AccessWidth32, TempAddr, &CpbCtrl, StdHeader);  // F4x15C
225     NumberBoostStates = (UINT8) CpbCtrl.NumBoostStates;
226   } else {
227     NumberBoostStates = 0;
228   }
229
230   LibAmdMsrRead ((MSR_PSTATE_0 + NumberBoostStates), &MsrData, StdHeader);
231   MaxVid = (UINT8) (((PSTATE_MSR *)&MsrData)->CpuVid);
232
233   if (Pvimode) {
234     // PVI mode
235     F10Translate7BitVidTo6Bit (&MaxVid);
236     if (MaxVid >= 0x20) {
237       Voltage = (UINT8) ((7625 - (125 * (MaxVid - 0x20)) + 500) / 1000);
238     } else {
239       Voltage = (UINT8) ((1550 - (25 * MaxVid) + 50) / 100);
240     }
241   } else {
242     // is SVI mode
243     if ((MaxVid >= 0x7C) && (MaxVid <= 0x7F)) {
244       Voltage = 0;
245     } else {
246       Voltage = (UINT8) ((15500 - (125 * MaxVid) + 500) / 1000);
247     }
248   }
249
250   Voltage += 0x80;
251   return (Voltage);
252 }
253
254 /* -----------------------------------------------------------------------------*/
255 /**
256  *
257  *  DmiF10GetMaxSpeed
258  *
259  *    Get the Max Speed
260  *
261  *    @param[in]      StdHeader      Standard Head Pointer
262  *
263  *    @retval  MaxSpeed   - CPU Max Speed.
264  *
265  */
266 UINT16
267 DmiF10GetMaxSpeed (
268   IN       AMD_CONFIG_PARAMS  *StdHeader
269   )
270 {
271   UINT8 NumBoostStates;
272   UINT32 P0Frequency;
273   PSTATE_CPU_FAMILY_SERVICES  *FamilyServices;
274
275   FamilyServices = NULL;
276   GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
277   ASSERT (FamilyServices != NULL);
278   NumBoostStates = F10GetNumberOfBoostedPstatesOnCore (StdHeader);
279
280   FamilyServices->GetPstateFrequency (FamilyServices, NumBoostStates, &P0Frequency, StdHeader);
281   return ((UINT16) P0Frequency);
282 }
283
284 /* -----------------------------------------------------------------------------*/
285 /**
286  *
287  *  DmiF10GetExtClock
288  *
289  *    Get the external clock Speed
290  *
291  *    @param[in]      StdHeader      Standard Head Pointer
292  *
293  *    @retval  ExtClock   - CPU external clock Speed.
294  *
295  */
296 UINT16
297 DmiF10GetExtClock (
298   IN       AMD_CONFIG_PARAMS  *StdHeader
299   )
300 {
301   return (EXTERNAL_CLOCK_DFLT);
302 }
303
304 /* -----------------------------------------------------------------------------*/
305 /**
306  *
307  *  DmiF10GetMemInfo
308  *
309  *    Get memory information.
310  *
311  *    @param[in,out]  CpuGetMemInfoPtr      Pointer to CPU_GET_MEM_INFO struct.
312  *    @param[in]      StdHeader             Standard Head Pointer
313  *
314  */
315 VOID
316 DmiF10GetMemInfo (
317   IN OUT   CPU_GET_MEM_INFO  *CpuGetMemInfoPtr,
318   IN       AMD_CONFIG_PARAMS  *StdHeader
319   )
320 {
321   UINT32 PciData;
322   PCI_ADDR PciAddress;
323
324   CpuGetMemInfoPtr->EccCapable = FALSE;
325
326   // DCT 0
327   PciAddress.AddressValue = MAKE_SBDFO (0, 0 , PCI_DEV_BASE, FUNC_2, 0x90);
328   LibAmdPciRead (AccessWidth32, PciAddress, &PciData, StdHeader);
329   // Check if F2x90[DimmEccEn] is set
330   if ((PciData & 0x00080000) != 0) {
331     CpuGetMemInfoPtr->EccCapable = TRUE;
332   } else {
333     // DCT 1
334     PciAddress.AddressValue = MAKE_SBDFO (0, 0 , PCI_DEV_BASE, FUNC_2, 0x190);
335     LibAmdPciRead (AccessWidth32, PciAddress, &PciData, StdHeader);
336     // Check if F2x190[DimmEccEn] is set
337     if ((PciData & 0x00080000) != 0) {
338       CpuGetMemInfoPtr->EccCapable = TRUE;
339     }
340   }
341
342   // Partition Row Position - 0 is for dual channel memory
343   CpuGetMemInfoPtr->PartitionRowPosition = 0;
344 }
345
346 /*---------------------------------------------------------------------------------------
347  * Processor Family Table
348  *
349  * Note: 'x' means we don't care this field
350  *       002h = "Unknown"
351  *       038h = "AMD Turion(TM) II Ultra Dual-Core Mobile M Processor Family"
352  *       039h = "AMD Turion(TM) II Dual-Core Mobile M Processor Family"
353  *       03Ah = "AMD Athlon(TM) II Dual-Core M Processor Family"
354  *       083h = "AMD Athlon(tm) 64 Processor Family"
355  *       084h = "AMD Opteron(TM) Processor Family"
356  *       085h = "AMD Sempron(tm) Processor Family"
357  *       087h = "Dual-Core AMD Opteron Processor Family"
358  *       08Ah = "Quad-Core AMD Opteron Processor Family"
359  *       08Ch = "AMD Phenom FX Quad-Core Processor Family"
360  *       08Dh = "AMD Phenom X4 Quad-Core Processor Family"
361  *       08Eh = "AMD Phenom X2 Dual-Core Processor Family"
362  *       08Fh = "AMD Athlon X2 Dual-Core Processor Family"
363  *       0E6h = "Embedded AMD Opteron Processor Family"
364  *       0E7h = "AMD Phenom Triple-Core Processor Family"
365  *       0ECh = "AMD Phenom(TM) II Processor Family"
366  *       0EDh = "AMD Athlon(TM) II Processor Family"
367  *       0EEh = "Six-Core AMD Opteron(TM) Processor Family"
368  *       0EFh = "AMD Sempron(TM) M Processor Family"
369  *-------------------------------------------------------------------------------------*/
370 CONST DMI_BRAND_ENTRY ROMDATA Family10BrandList[] =
371 {
372   // Brand --> DMI ID translation table
373   // PackageType, PgOfBrandId, NumberOfCores, String1ofBrandId, ValueSetToDmiTable
374   // {'x', 'x', 'x', 'x', 0x02} MUST be the last one.
375     {0, 0, 1, 0, 0x87},
376     {0, 0, 1, 1, 0x87},
377     {0, 0, 2, 0, 0xE6},
378     {0, 0, 3, 0, 0x8A},
379     {0, 0, 3, 1, 0x8A},
380     {0, 0, 3, 2, 0xE6},
381     {0, 0, 3, 3, 0xE6},
382     {0, 0, 3, 4, 0xE6},
383     {0, 0, 3, 5, 0x8C},
384     {0, 0, 5, 0, 0xEE},
385     {0, 0, 5, 1, 0xEE},
386     {0, 1, 3, 1, 0xE6},
387     {0, 1, 5, 1, 0xE6},
388     {1, 0, 0, 0, 0x83},
389     {1, 0, 0, 1, 0x85},
390     {1, 0, 0, 2, 0x85},
391     {1, 0, 0, 3, 0xED},
392     {1, 0, 1, 0, 0x87},
393     {1, 0, 1, 1, 0x8F},
394     {1, 0, 1, 2, 0xED},
395     {1, 0, 1, 3, 0xED},
396     {1, 0, 1, 4, 0xED},
397     {1, 0, 1, 5, 0xED},
398     {1, 0, 1, 6, 0xED},
399     {1, 0, 1, 7, 0xEC},
400     {1, 0, 1, 8, 0xED},
401     {1, 0, 1, 9, 0xED},
402     {1, 0, 1, 0xA, 0xEC},
403     {1, 0, 1, 0xB, 0xEC},
404     {1, 0, 1, 0xC, 0x85},
405     {1, 0, 2, 0, 0xE7},
406     {1, 0, 2, 1, 0xEC},
407     {1, 0, 2, 2, 0xEC},
408     {1, 0, 2, 3, 0xEC},
409     {1, 0, 2, 4, 0xEC},
410     {1, 0, 2, 5, 0xED},
411     {1, 0, 2, 6, 0xED},
412     {1, 0, 2, 7, 0xED},
413     {1, 0, 2, 8, 0xEC},
414     {1, 0, 2, 9, 0xED},
415     {1, 0, 2, 0xA, 0xED},
416     {1, 0, 3, 0, 0x8A},
417     {1, 0, 3, 1, 0x8C},
418     {1, 0, 3, 2, 0x8D},
419     {1, 0, 3, 3, 0xEC},
420     {1, 0, 3, 4, 0xEC},
421     {1, 0, 3, 5, 0xEC},
422     {1, 0, 3, 6, 0xEC},
423     {1, 0, 3, 7, 0xEC},
424     {1, 0, 3, 8, 0xEC},
425     {1, 0, 3, 9, 0xEC},
426     {1, 0, 3, 0xA, 0xED},
427     {1, 0, 3, 0xB, 0xED},
428     {1, 0, 3, 0xC, 0xED},
429     {1, 0, 3, 0xD, 0xED},
430     {1, 0, 3, 0xE, 0xEC},
431     {1, 0, 3, 0xF, 0xED},
432     {1, 0, 5, 0, 0xEC},
433     {1, 1, 1, 1, 0xED},
434     {1, 1, 1, 2, 0xED},
435     {1, 1, 3, 0, 0xEC},
436     {1, 1, 3, 1, 0xEC},
437     {1, 1, 3, 2, 0xEC},
438     {1, 1, 3, 3, 0xEC},
439     {1, 1, 3, 4, 0xEC},
440     {2, 0, 0, 0, 0xEF},
441     {2, 0, 0, 1, 0xEF},
442     {2, 0, 1, 0, 0x38},
443     {2, 0, 1, 1, 0x39},
444     {2, 0, 1, 2, 0x3A},
445     {2, 0, 1, 3, 0x39},
446     {2, 0, 1, 4, 0xED},
447     {2, 0, 1, 5, 0xEC},
448     {2, 0, 1, 6, 0xEC},
449     {2, 0, 1, 7, 0x39},
450     {2, 0, 1, 8, 0xED},
451     {2, 0, 1, 9, 0xEC},
452     {2, 0, 2, 2, 0xEC},
453     {2, 0, 2, 3, 0xEC},
454     {2, 0, 2, 4, 0xEC},
455     {2, 0, 3, 1, 0xEC},
456     {2, 0, 3, 2, 0xEC},
457     {2, 0, 3, 3, 0xEC},
458     {3, 0, 7, 0, 0x84},
459     {3, 0, 0xB, 0, 0x84},
460     {3, 1, 7, 1, 0xE6},
461     {4, 0, 0, 1, 0xED},
462     {4, 0, 0, 2, 0xEF},
463     {4, 0, 0, 3, 0xED},
464     {4, 0, 1, 1, 0x39},
465     {4, 0, 1, 2, 0x3A},
466     {4, 0, 1, 3, 0xEF},
467     {4, 0, 1, 4, 0x39},
468     {4, 0, 1, 5, 0x3A},
469     {5, 0, 3, 0, 0x84},
470     {5, 0, 5, 0, 0x84},
471     {5, 1, 3, 1, 0xE6},
472     {5, 1, 5, 1, 0xE6},
473     {'x', 'x', 'x', 'x', P_FAMILY_UNKNOWN}
474   };
475
476 CONST PROC_FAMILY_TABLE ROMDATA ProcFamily10DmiTable =
477 {
478 // This table is for Processor family 10h
479   AMD_FAMILY_10,                  // ID for Family 10h
480   DmiF10GetInfo,                  // Transfer vectors for family
481   DmiGetT4ProcFamilyFromBrandId,  // Get type 4 processor family information from CPUID_8000_0001_EBX[BrandId]
482   DmiF10GetVoltage,               //   specific routines (above)
483   DmiF10GetMaxSpeed,
484   DmiF10GetExtClock,
485   DmiF10GetMemInfo,               // Get memory information
486   (sizeof (Family10BrandList) / sizeof (Family10BrandList[0])), // Number of entries in following table
487   &Family10BrandList[0]
488 };
489
490
491 /*---------------------------------------------------------------------------------------
492  *                          L O C A L    F U N C T I O N S
493  *---------------------------------------------------------------------------------------
494  */
495
496 /* -----------------------------------------------------------------------------*/
497 /**
498  *
499  *  F10Translate7BitVidTo6Bit
500  *
501  *    translate 7 bit VID to 6 bit VID
502  *
503  *    @param[in, out]  MaxVidPtr   - Pointer to MaxVid.
504  */
505 VOID
506 STATIC
507 F10Translate7BitVidTo6Bit (
508   IN OUT   UINT8 * MaxVidPtr
509   )
510 {
511   if ((*MaxVidPtr >= 0x5E) && (*MaxVidPtr <= 0x7F)) {
512     *MaxVidPtr = 0x3F;
513   } else if ((*MaxVidPtr >= 0x3F) && (*MaxVidPtr <= 0x5D)) {
514     *MaxVidPtr = *MaxVidPtr - 0x1F;
515   } else if (*MaxVidPtr <= 0x3E) {
516     *MaxVidPtr = (*MaxVidPtr & 0x7E) >> 1;
517   }
518 }
519