summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Table.h
blob: 85fb9e41979c6759e5c496740d018332233e6267 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
/* $NoKeywords:$ */
/**
 * @file
 *
 * AMD CPU Register Table Related Functions
 *
 * Contains code to initialize the CPU MSRs and PCI registers with BKDG recommended values
 *
 * @xrefitem bom "File Content Label" "Release Content"
 * @e project:      AGESA
 * @e sub-project:  CPU
 * @e \$Revision: 85962 $   @e \$Date: 2013-01-14 20:12:29 -0600 (Mon, 14 Jan 2013) $
 *
 */
/*
 ******************************************************************************
 *
 * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************
 */

#ifndef _CPU_TABLE_H_
#define _CPU_TABLE_H_

#define MAX_ENTRY_TYPE_ITEMS32 6        // The maximum number of initializer items for UINT32 entry data types.

/**
 * @page regtableimpl Register Table Implementation Guide
 *
 * This register table implementation is modular and extensible, so that support code as
 * well as table data can be family specific or built out if not needed, and new types
 * of table entries can be added with low overhead.  Because many aspects are now generic,
 * there can be common implementations for CPU revision and platform feature matching and for
 * finding and iterating tables.
 *
 * @par Adding a new table entry type.
 *
 * To add a new table entry type follow these steps.
 * <ul>
 * <li>  Add a member to the enum TABLE_ENTRY_TYPE which is a descriptive name of the entry's purpose
 *       or distinct characteristics.
 *
 * <li>  Create an entry data struct with the customized data needed.  For example, custom register designations,
 *       data and mask sizes, or feature comparisons.  Name your struct by adding "_" and upper-casing the enum name
 *       and adding "_TYPE_ENTRY_DATA" at the end.
 *
 * <li>  Add the entry data type as a member of the TABLE_ENTRY_DATA union.  Be aware of the size of your
 *       entry data struct; all table entries in all tables will share any size increase you introduce!
 *
 * <li>  If your data entry contains any member types except for UINT32, you can't use the generic first union member
 *       for the initializers that make up the actual tables (it's just UINT32's). The generic MSR entry is
 *       an example. Follow the steps below:
 *
 *       <ul>
 *       <li>  Make a union which has your entry data type as the first member.  Use TABLE_ENTRY_DATA as the
 *             second member.  Name this with your register followed by "_DATA_INITIALIZER".
 *
 *       <li>  Make a copy of TABLE_ENTRY_FIELDS, and rename it your register "_TYPE_ENTRY_INITIALIZER".  Rename
 *             the TABLE_ENTRY_DATA member of that struct to have the type you created in the previous step.
 *             This type can be used to declare an array of entries and make a register table in some family specific
 *             file.
 *       </ul>
 *
 * <li>  Add the descriptor that will link table entries of your data type to an implementation for it.
 *       <ul>
 *       <li>  Find the options file which instantiates the CPU_SPECIFIC_SERVICES for each logical model that will
 *             support the new entry type.
 *
 *       <li> From there find the instantiation of its TABLE_ENTRY_TYPE_DESCRIPTOR.  Add a descriptor to the
 *            to the list for your new type.  Provide the name of a function which will implement the
 *            entry data.  The function name should reflect that it implements the action for the entry type.
 *            The function must be an instance of F_DO_TABLE_ENTRY.
 *       </ul>
 *
 * <li>  Implement the function for your entry type data.  (If parts of it are family specific add methods to
 *       CPU_SPECIFIC_SERVICES for that and implement them for each family or model required.)  @n
 *       The definition of the function must conform to F_DO_TABLE_ENTRY.
 *       In the function preamble, include a cross reference to the entry enum:
 *       @code
 *       *
 *       * @TableEntryTypeMethod{::MyRegister}
 *       *
 *       @endcode
 *
 * </ul>
 *
 * @par  Adding a new Register Table
 *
 * To add a new register table for a logical CPU model follow the steps below.
 *
 * <ul>
 * <li>  Find the options file which instantiates the CPU_SPECIFIC_SERVICES for the logical model that
 *       should include the table.
 *
 * <li>  From there find the instantiation of its REGISTER_TABLE list. Add the name of the new register table.
 * </ul>
 *
 */

/*------------------------------------------------------------------------------------------*/
/*
 * Define the supported table entries.
 */
/*------------------------------------------------------------------------------------------*/

/**
 * These are the available types of table entries.
 *
 * Each type corresponds to:
 * - a semantics for the type specific data, for example semantics for a Register value,
 * Data value, and Mask value.
 * - optionally, including a method for type specific matching criteria
 * - a method for writing the desired update to the hardware.
 *
 * All types share in common a method to match CPU Family and Model and a method to match
 * platform feature set.
 *
 */
typedef enum {
  MsrRegister,                 ///< Processor MSR registers.
  PciRegister,                 ///< Processor Config Space registers.
  FamSpecificWorkaround,       ///< Processor Family Specific Workarounds which are @b not practical using the other types.
  HtPhyRegister,               ///< Processor HT Phy registers.
  HtPhyRangeRegister,          ///< Processor HT Phy range of contiguous registers (ex. 40h:48h).
  DeemphasisRegister,          ///< Processor Deemphasis register (HT Phy special case).
  HtPhyFreqRegister,           ///< Processor Frequency dependent HT Phy settings.
  ProfileFixup,                ///< Processor Performance Profile fixups to PCI Config Registers.
  HtHostPciRegister,           ///< Processor Ht Host capability registers (PCI Config).
  HtHostPerfPciRegister,       ///< Processor Ht Host capability registers which depend on performance features.
  HtTokenPciRegister,          ///< Processor Ht Link Token count registers.
  CoreCountsPciRegister,       ///< Processor PCI Config Registers which depend on core counts.
  ProcCountsPciRegister,       ///< Processor PCI Config Registers which depend on processor counts.
  CompUnitCountsPciRegister,   ///< Processor PCI Config Registers which depend on compute unit counts.
  TokenPciRegister,            ///< Processor northbridge Token Count register which may be dependent on connectivity.
  HtFeatPciRegister,           ///< Processor HT Link feature dependant PCI Config Registers.
  HtPhyProfileRegister,        ///< Processor HT Phy registers which depend on performance features.
  HtLinkPciRegister,           ///< Processor HT Link registers (one per link) not part of HT Host capability.
  CompUnitCountsMsr,           ///< Processor MSRs which depend on compute unit counts.
  TableEntryTypeMax            ///< Not a valid entry type, use for limit checking.
} TABLE_ENTRY_TYPE;

/*------------------------------------------------------------------------------------------*/
/*
 * Useful types and defines: Selectors, Platform Features, and type specific features.
 */
/*------------------------------------------------------------------------------------------*/

/**
 * Select tables for the current core.
 *
 * This allows more efficient register table processing, by allowing cores to skip
 * redundantly setting PCI registers, for example.  This feature is not intended to
 * be relied on for function:  it is valid to have a single register table with all settings
 * processed by every core; it's just slower.
 *
 */
typedef enum {
  AllCores,                   ///< Select only tables which apply to all cores.
  ComputeUnitPrimary,         ///< Select tables which apply to the primary core of a compute unit (SharedC, SharedNc).
  PrimaryCores,               ///< Select tables which apply to primary cores.
  BscCore,                    ///< Select tables which apply to the boot core.
  TableCoreSelectorMax        ///< Not a valid selector, use for limit checking.
} TABLE_CORE_SELECTOR;

//----------------------------------------------------------------------------
//                         CPU PERFORM EARLY INIT ON CORE
//
//----------------------------------------------------------------------------
/// Flag definition.

// Condition
#define PERFORM_EARLY_WARM_RESET    0x1          // bit  0 --- the related function needs to be run if it's warm reset
#define PERFORM_EARLY_COLD_BOOT     0x2          // bit  1 --- the related function needs to be run if it's cold boot

// TimePoint
#define PERFORM_TP_AFTER_AP_LAUNCH  0x40000000ul // bit 30 --- the related function needs to be run after AP launch
#define PERFORM_TP_BEFORE_AP_LAUNCH 0x80000000ul // bit 31 --- the related function needs to be run before AP launch

#define PERFORM_TP_ALL (PERFORM_TP_AFTER_AP_LAUNCH | PERFORM_TP_BEFORE_AP_LAUNCH)

#define PERFORM_EARLY_ANY_CONDITION (PERFORM_EARLY_WARM_RESET | PERFORM_EARLY_COLD_BOOT)

// Initializer bit pattern values for platform features.
// Keep in synch with the PLATFORM_FEATURES struct!

// The 5 control flow modes.
#define AMD_PF_NFCM           BIT0
#define AMD_PF_UMA            BIT1    // UMA_DR
#define AMD_PF_UMA_IFCM       BIT2
#define AMD_PF_IFCM           BIT3
#define AMD_PF_IOMMU          BIT4
// Degree of HT connectivity possible.
#define AMD_PF_SINGLE_LINK    BIT5
#define AMD_PF_MULTI_LINK     BIT6
// For some legacy MSRs, define a couple core count bits.  Do not continue adding
// core counts to the platform feats, if you need more than this design a table entry type.
// Here, provide exactly 1, exactly 2, or anything else.
#define AMD_PF_SINGLE_CORE    BIT7
#define AMD_PF_DUAL_CORE      BIT8
#define AMD_PF_MULTI_CORE     BIT9

// Not a platform type, but treat all others as AND
#define AMD_PF_AND            BIT31

#define AMD_PF_ALL    (AMD_PF_NFCM          | \
                       AMD_PF_UMA           | \
                       AMD_PF_UMA_IFCM      | \
                       AMD_PF_IFCM          | \
                       AMD_PF_IOMMU         | \
                       AMD_PF_SINGLE_LINK   | \
                       AMD_PF_MULTI_LINK    | \
                       AMD_PF_SINGLE_CORE   | \
                       AMD_PF_DUAL_CORE     | \
                       AMD_PF_MULTI_CORE)
// Do not include AMD_PF_AND in AMD_PF_ALL !

/**
 * The current platform features.
 *
 * Keep this in sync with defines above that are used in the initializers!
 *
 * The comments with the bit number are useful for the computing the reserved member size, but
 * do not write code that assumes you know what bit number one of these members is.
 *
 * These platform features are standard for all logical families and models.
 */
typedef struct {
  UINT32          PlatformNfcm:1;             ///< BIT_0 Normal Flow Control Mode.
  UINT32          PlatformUma:1;              ///< BIT_1 UMA (Display Refresh) Flow Control.
  UINT32          PlatformUmaIfcm:1;          ///< BIT_2 UMA using Isochronous Flow Control.
  UINT32          PlatformIfcm:1;             ///< BIT_3 Isochronous Flow Control Mode (not UMA).
  UINT32          PlatformIommu:1;            ///< BIT_4 IOMMU (a special case Isochronous mode).
  UINT32          PlatformSingleLink:1;       ///< BIT_5 The processor is in a package which implements only a single HT Link.
  UINT32          PlatformMultiLink:1;        ///< BIT_6 The processor is in a package which implements more than one HT Link.
  UINT32          PlatformSingleCore:1;       ///< BIT_7 Single Core processor, for legacy entries.
  UINT32          PlatformDualCore:1;         ///< BIT_8 Dual Core processor, for legacy entries.
  UINT32          PlatformMultiCore:1;        ///< BIT_9 More than dual Core processor, for legacy entries.
  UINT32          :(30 - 9);                  ///< The possibilities are (not quite) endless.
  UINT32          AndPlatformFeats:1;         ///< BIT_31
} PLATFORM_FEATURES;

/**
 * Platform Features
 */
typedef union {
  UINT32            PlatformValue;            ///< Describe Platform Features in UINT32.
  ///< This one goes first, because then initializers use it automatically for the union.
  PLATFORM_FEATURES PlatformFeatures;         ///< Describe Platform Features in structure
} PLATFORM_FEATS;

// Sublink Types are defined so they can match each attribute against either
// sublink zero or one.  The table entry must contain the correct matching
// values based on the register. This is available in the BKDG, for each register
// which sublink it controls.  If the register is independent of sublink, OR values
// together or use HT_LINKTYPE_ALL to match if either sublink matches (ex. E0 - E5).
// Sublink 0 types, bits 0 thru 14
#define HTPHY_LINKTYPE_SL0_HT3          BIT0
#define HTPHY_LINKTYPE_SL0_HT1          BIT1
#define HTPHY_LINKTYPE_SL0_COHERENT     BIT2
#define HTPHY_LINKTYPE_SL0_NONCOHERENT  BIT3
#define HTPHY_LINKTYPE_SL0_LINK0        BIT4
#define HTPHY_LINKTYPE_SL0_LINK1        BIT5
#define HTPHY_LINKTYPE_SL0_LINK2        BIT6
#define HTPHY_LINKTYPE_SL0_LINK3        BIT7
#define HTPHY_LINKTYPE_SL0_INTERNAL     BIT8
#define HTPHY_LINKTYPE_SL0_EXTERNAL     BIT9
#define HTPHY_LINKTYPE_SL0_AND          BIT15

// SubLink 1 types, bits 16 thru 30
#define HTPHY_LINKTYPE_SL1_HT3          BIT16
#define HTPHY_LINKTYPE_SL1_HT1          BIT17
#define HTPHY_LINKTYPE_SL1_COHERENT     BIT18
#define HTPHY_LINKTYPE_SL1_NONCOHERENT  BIT19
#define HTPHY_LINKTYPE_SL1_LINK4        BIT20
#define HTPHY_LINKTYPE_SL1_LINK5        BIT21
#define HTPHY_LINKTYPE_SL1_LINK6        BIT22
#define HTPHY_LINKTYPE_SL1_LINK7        BIT23
#define HTPHY_LINKTYPE_SL1_INTERNAL     BIT24
#define HTPHY_LINKTYPE_SL1_EXTERNAL     BIT25
#define HTPHY_LINKTYPE_SL1_AND          BIT31

#define HTPHY_LINKTYPE_SL0_ALL          (HTPHY_LINKTYPE_SL0_HT3         | \
                                         HTPHY_LINKTYPE_SL0_HT1         | \
                                         HTPHY_LINKTYPE_SL0_COHERENT    | \
                                         HTPHY_LINKTYPE_SL0_NONCOHERENT | \
                                         HTPHY_LINKTYPE_SL0_LINK0       | \
                                         HTPHY_LINKTYPE_SL0_LINK1       | \
                                         HTPHY_LINKTYPE_SL0_LINK2       | \
                                         HTPHY_LINKTYPE_SL0_LINK3       | \
                                         HTPHY_LINKTYPE_SL0_INTERNAL    | \
                                         HTPHY_LINKTYPE_SL0_EXTERNAL)
#define HTPHY_LINKTYPE_SL1_ALL          (HTPHY_LINKTYPE_SL1_HT3         | \
                                         HTPHY_LINKTYPE_SL1_HT1         | \
                                         HTPHY_LINKTYPE_SL1_COHERENT    | \
                                         HTPHY_LINKTYPE_SL1_NONCOHERENT | \
                                         HTPHY_LINKTYPE_SL1_LINK4       | \
                                         HTPHY_LINKTYPE_SL1_LINK5       | \
                                         HTPHY_LINKTYPE_SL1_LINK6       | \
                                         HTPHY_LINKTYPE_SL1_LINK7       | \
                                         HTPHY_LINKTYPE_SL1_INTERNAL    | \
                                         HTPHY_LINKTYPE_SL1_EXTERNAL)
#define HTPHY_LINKTYPE_ALL              (HTPHY_LINKTYPE_SL0_ALL | HTPHY_LINKTYPE_SL1_ALL)

#define HTPHY_REGISTER_MAX              0x0000FFFFul
/**
 * HT PHY Link Features
 */
typedef struct {
  UINT32 HtPhySL0Ht3:1;                       ///< Ht Phy Sub-link 0 Ht3
  UINT32 HtPhySL0Ht1:1;                       ///< Ht Phy Sub-link 0 Ht1
  UINT32 HtPhySL0Coh:1;                       ///< Ht Phy Sub-link 0 Coherent
  UINT32 HtPhySL0NonCoh:1;                    ///< Ht Phy Sub-link 0 NonCoherent
  UINT32 HtPhySL0Link0:1;                     ///< Ht Phy Sub-link 0 specifically for node link 0.
  UINT32 HtPhySL0Link1:1;                     ///< Ht Phy Sub-link 0 specifically for node link 1.
  UINT32 HtPhySL0Link2:1;                     ///< Ht Phy Sub-link 0 specifically for node link 2.
  UINT32 HtPhySL0Link3:1;                     ///< Ht Phy Sub-link 0 specifically for node link 3.
  UINT32 HtPhySL0Internal:1;                  ///< Ht Phy Sub-link 0 is internal link.  Intended for IDS support.
  UINT32 HtPhySL0External:1;                  ///< Ht Phy Sub-link 0 is external link.  Intended for IDS support.
  UINT32 :(14 - 9);                           ///< Ht Phy Sub-link 0 Pad
  UINT32 HtPhySL0And:1;                       ///< Ht Phy feature match should match all selected features, for sub-link 0.
  UINT32 HtPhySL1Ht3:1;                       ///< Ht Phy Sub-link 1 Ht3
  UINT32 HtPhySL1Ht1:1;                       ///< Ht Phy Sub-link 1 Ht1
  UINT32 HtPhySL1Coh:1;                       ///< Ht Phy Sub-link 1 Coherent
  UINT32 HtPhySL1NonCoh:1;                    ///< Ht Phy Sub-link 1 NonCoherent
  UINT32 HtPhySL1Link4:1;                     ///< Ht Phy Sub-link 1 specifically for node link 4.
  UINT32 HtPhySL1Link5:1;                     ///< Ht Phy Sub-link 1 specifically for node link 5.
  UINT32 HtPhySL1Link6:1;                     ///< Ht Phy Sub-link 1 specifically for node link 6.
  UINT32 HtPhySL1Link7:1;                     ///< Ht Phy Sub-link 1 specifically for node link 7.
  UINT32 HtPhySL1Internal:1;                  ///< Ht Phy Sub-link 1 is internal link.  Intended for IDS support.
  UINT32 HtPhySL1External:1;                  ///< Ht Phy Sub-link 1 is external link.  Intended for IDS support.
  UINT32 :(30 - 25);                          ///< Ht Phy Sub-link 1 Pad
  UINT32 HtPhySL1And:1;                       ///< Ht Phy feature match should match all selected features, for sub-link 1.
} HT_PHY_LINK_FEATURES;

/**
 * Ht Phy Link Features
 */
typedef union {
  UINT32                  HtPhyLinkValue;     ///< Describe HY Phy Features in UINT32.
  ///< This one goes first, because then initializers use it automatically for the union.
  HT_PHY_LINK_FEATURES    HtPhyLinkFeatures;  ///< Describe HT Phy Features in structure.
} HT_PHY_LINK_FEATS;

// DB Level for initializing Deemphasis
// This must be in sync with DEEMPHASIS_FEATURES and PLATFORM_DEEMPHASIS_LEVEL (agesa.h)
#define DEEMPHASIS_LEVEL_NONE   BIT0
#define DEEMPHASIS_LEVEL__3     BIT1
#define DEEMPHASIS_LEVEL__6     BIT2
#define DEEMPHASIS_LEVEL__8     BIT3
#define DEEMPHASIS_LEVEL__11    BIT4
#define DEEMPHASIS_LEVEL__11_8  BIT5
#define DCV_LEVEL_NONE          BIT16
#define DCV_LEVEL__2            BIT17
#define DCV_LEVEL__3            BIT18
#define DCV_LEVEL__5            BIT19
#define DCV_LEVEL__6            BIT20
#define DCV_LEVEL__7            BIT21
#define DCV_LEVEL__8            BIT22
#define DCV_LEVEL__9            BIT23
#define DCV_LEVEL__11           BIT24
// Note that an "AND" feature doesn't make any sense, levels are mutually exclusive.

// An error check value.
#define DEEMPHASIS_LEVELS_ALL    (DEEMPHASIS_LEVEL_NONE    | \
                                  DEEMPHASIS_LEVEL__3      | \
                                  DEEMPHASIS_LEVEL__6      | \
                                  DEEMPHASIS_LEVEL__8      | \
                                  DEEMPHASIS_LEVEL__11     | \
                                  DEEMPHASIS_LEVEL__11_8)

#define DCV_LEVELS_ALL           (DCV_LEVEL_NONE           | \
                                  DCV_LEVEL__2             | \
                                  DCV_LEVEL__3             | \
                                  DCV_LEVEL__5             | \
                                  DCV_LEVEL__6             | \
                                  DCV_LEVEL__7             | \
                                  DCV_LEVEL__8             | \
                                  DCV_LEVEL__9             | \
                                  DCV_LEVEL__11)

#define VALID_DEEMPHASIS_LEVELS  (DEEMPHASIS_LEVELS_ALL | DCV_LEVELS_ALL)

/**
 * Deemphasis Ht Phy Link Deemphasis.
 *
 * This must be in sync with defines above and ::PLATFORM_DEEMPHASIS_LEVEL (agesa.h)
 */
typedef struct {
  UINT32          DeemphasisLevelNone:1;         ///< The deemphasis level None.
  UINT32          DeemphasisLevelMinus3:1;       ///< The deemphasis level minus 3 db.
  UINT32          DeemphasisLevelMinus6:1;       ///< The deemphasis level minus 6 db.
  UINT32          DeemphasisLevelMinus8:1;       ///< The deemphasis level minus 8 db.
  UINT32          DeemphasisLevelMinus11:1;      ///< The deemphasis level minus 11 db.
  UINT32          DeemphasisLevelMinus11w8:1;    ///< The deemphasis level minus 11 db, minus 8 precursor.
  UINT32          :(15 - 5);                     ///< reserved.
  UINT32          DcvLevelNone:1;                ///< The level for DCV None.
  UINT32          DcvLevelMinus2:1;              ///< The level for DCV minus 2 db.
  UINT32          DcvLevelMinus3:1;              ///< The level for DCV minus 3 db.
  UINT32          DcvLevelMinus5:1;              ///< The level for DCV minus 5 db.
  UINT32          DcvLevelMinus6:1;              ///< The level for DCV minus 6 db.
  UINT32          DcvLevelMinus7:1;              ///< The level for DCV minus 7 db.
  UINT32          DcvLevelMinus8:1;              ///< The level for DCV minus 8 db.
  UINT32          DcvLevelMinus9:1;              ///< The level for DCV minus 9 db.
  UINT32          DcvLevelMinus11:1;             ///< The level for DCV minus 11 db.
  UINT32          :(15 - 8);                     ///< reserved.
} DEEMPHASIS_FEATURES;

/**
 * Deemphasis Ht Phy Link Features.
 */
typedef union {
  UINT32                  DeemphasisValues;      ///< Initialize HT Deemphasis in UINT32.
  DEEMPHASIS_FEATURES     DeemphasisLevels;      ///< HT Deemphasis levels.
} DEEMPHASIS_FEATS;

// Initializer bit patterns for PERFORMANCE_PROFILE_FEATS.
#define PERFORMANCE_REFRESH_REQUEST_32B       BIT0
#define PERFORMANCE_PROBEFILTER               BIT1
#define PERFORMANCE_L3_CACHE                  BIT2
#define PERFORMANCE_NO_L3_CACHE               BIT3
#define PERFORMANCE_MCT_ISOC_VARIABLE         BIT4
#define PERFORMANCE_IS_WARM_RESET             BIT5
#define PERFORMANCE_VRM_HIGH_SPEED_ENABLE     BIT6
#define PERFORMANCE_NB_PSTATES_ENABLE         BIT7
#define PERFORMANCE_AND                       BIT31

#define PERFORMANCE_PROFILE_ALL   (PERFORMANCE_REFRESH_REQUEST_32B | \
                                   PERFORMANCE_PROBEFILTER         | \
                                   PERFORMANCE_L3_CACHE            | \
                                   PERFORMANCE_NO_L3_CACHE         | \
                                   PERFORMANCE_MCT_ISOC_VARIABLE   | \
                                   PERFORMANCE_IS_WARM_RESET       | \
                                   PERFORMANCE_VRM_HIGH_SPEED_ENABLE | \
                                   PERFORMANCE_NB_PSTATES_ENABLE)

/**
 * Performance Profile specific Type Features.
 *
 * Register settings for the different control flow modes can have additional dependencies
 */
typedef struct {
  UINT32       RefreshRequest32Byte:1;         ///< BIT_0.   Display Refresh Requests use 32 bytes (32BE).
  UINT32       ProbeFilter:1;                  ///< BIT_1    Probe Filter will be enabled.
  UINT32       L3Cache:1;                      ///< BIT_2    L3 Cache is present.
  UINT32       NoL3Cache:1;                    ///< BIT_3    L3 Cache is NOT present.
  UINT32       MctIsocVariable:1;              ///< BIT_4    Mct Isoc Read Priority set to variable.
  UINT32       IsWarmReset:1;                  ///< BIT_5    This boot is on a warm reset, cold reset pass is already completed.
  UINT32       VrmHighSpeed:1;                 ///< BIT_6    Select high speed VRM.
  UINT32       NbPstates:1;                    ///< BIT_7    Northbridge PStates are enabled
  UINT32       :(30 - 7);                      ///< available for future expansion.
  UINT32       AndPerformanceFeats:1;          ///< BIT_31.  AND other selected features.
} PERFORMANCE_PROFILE_FEATURES;

/**
 * Performance Profile features.
 */
typedef union {
  UINT32                        PerformanceProfileValue;     ///< Initializer value.
  PERFORMANCE_PROFILE_FEATURES  PerformanceProfileFeatures;  ///< The performance profile features.
} PERFORMANCE_PROFILE_FEATS;

/**
 * Package Type Features
 *
 */
typedef struct {
  UINT32        PkgType0:1;                 ///< Package Type 0
  UINT32        PkgType1:1;                 ///< Package Type 1
  UINT32        PkgType2:1;                 ///< Package Type 2
  UINT32        PkgType3:1;                 ///< Package Type 3
  UINT32        PkgType4:1;                 ///< Package Type 4
  UINT32        PkgType5:1;                 ///< Package Type 5
  UINT32        PkgType6:1;                 ///< Package Type 6
  UINT32        PkgType7:1;                 ///< Package Type 7
  UINT32        PkgType8:1;                 ///< Package Type 8
  UINT32        PkgType9:1;                 ///< Package Type 9
  UINT32        PkgType10:1;                ///< Package Type 10
  UINT32        PkgType11:1;                ///< Package Type 11
  UINT32        PkgType12:1;                ///< Package Type 12
  UINT32        PkgType13:1;                ///< Package Type 13
  UINT32        PkgType14:1;                ///< Package Type 14
  UINT32        PkgType15:1;                ///< Package Type 15
  UINT32        Reserved:15;                ///< Package Type Reserved
  UINT32        ReservedAndFeats:1;         ///< BIT_31.  AND other selected features. Always zero here.
} PACKAGE_TYPE_FEATURES;

// Initializer Values for Package Type
#define PACKAGE_TYPE_ALL              0xFFFF       ///< Package Type apply all packages

// Initializer Values for Ht Host Pci Config Registers
#define HT_HOST_FEAT_COHERENT          BIT0
#define HT_HOST_FEAT_NONCOHERENT       BIT1
#define HT_HOST_FEAT_GANGED            BIT2
#define HT_HOST_FEAT_UNGANGED          BIT3
#define HT_HOST_FEAT_HT3               BIT4
#define HT_HOST_FEAT_HT1               BIT5
#define HT_HOST_AND                    BIT31

#define HT_HOST_FEATURES_ALL    (HT_HOST_FEAT_COHERENT    | \
                                 HT_HOST_FEAT_NONCOHERENT | \
                                 HT_HOST_FEAT_GANGED      | \
                                 HT_HOST_FEAT_UNGANGED    | \
                                 HT_HOST_FEAT_HT3         | \
                                 HT_HOST_FEAT_HT1)

/**
 * HT Host PCI register features.
 *
 * Links which are not connected do not match any of these features.
 */
typedef struct {
  UINT32       Coherent:1;                 ///< BIT_0 Apply to links with a coherent connection.
  UINT32       NonCoherent:1;              ///< BIT_1 Apply to links with a non-coherent connection.
  UINT32       Ganged:1;                   ///< BIT_2 Apply to links with a ganged connection.
  UINT32       UnGanged:1;                 ///< BIT_3 Apply to links with a unganged connection.
  UINT32       Ht3:1;                      ///< BIT_4 Apply to links with HT3 frequency (> 1000 MHz)
  UINT32       Ht1:1;                      ///< BIT_5 Apply to links with HT1 frequency (< 1200 MHz)
  UINT32       :(30 - 5);                  ///< Future expansion.
  UINT32       AndHtHostFeats:1;           ///< BIT_31.  AND other selected features.
} HT_HOST_FEATURES;

/**
 * HT Host features for table data.
 */
typedef union {
  UINT32                 HtHostValue;                ///< Initializer value.
  HT_HOST_FEATURES       HtHostFeatures;             ///< The HT Host Features.
} HT_HOST_FEATS;

// Core Range Initializer values.
#define COUNT_RANGE_LOW            0ul
#define COUNT_RANGE_HIGH           0xFFul

// A count range matching none is often useful as the second range, matching will then be
// based on the first range.  A count range all is provided as a first range for default settings.
#define COUNT_RANGE_NONE           ((((COUNT_RANGE_HIGH) << 8) | (COUNT_RANGE_HIGH)) << 16)
#define COUNT_RANGE_ALL            (((COUNT_RANGE_HIGH) << 8) | (COUNT_RANGE_LOW))
#define IGNORE_FREQ_0              (((COUNT_RANGE_HIGH) << 8) | (COUNT_RANGE_HIGH))
#define IGNORE_PROCESSOR_0         (((COUNT_RANGE_HIGH) << 8) | (COUNT_RANGE_HIGH))

#define CORE_RANGE_0(min, max)            ((((UINT32)(max)) << 8) | (UINT32)(min))
#define CORE_RANGE_1(min, max)            (((((UINT32)(max)) << 8) | (UINT32)(min)) << 16)
#define PROCESSOR_RANGE_0(min, max)       ((((UINT32)(max)) << 8) | (UINT32)(min))
#define PROCESSOR_RANGE_1(min, max)       (((((UINT32)(max)) << 8) | (UINT32)(min)) << 16)
#define DEGREE_RANGE_0(min, max)          ((((UINT32)(max)) << 8) | (UINT32)(min))
#define DEGREE_RANGE_1(min, max)          (((((UINT32)(max)) << 8) | (UINT32)(min)) << 16)
#define FREQ_RANGE_0(min, max)            ((((UINT32)(max)) << 8) | (UINT32)(min))
#define FREQ_RANGE_1(min, max)            (((((UINT32)(max)) << 8) | (UINT32)(min)) << 16)
#define COMPUTE_UNIT_RANGE_0(min, max)    ((((UINT32)(max)) << 8) | (UINT32)(min))
#define COMPUTE_UNIT_RANGE_1(min, max)    (((((UINT32)(max)) << 8) | (UINT32)(min)) << 16)

/**
 * Count Range Feature, two count ranges for core counts, processor counts, or node counts.
 */
typedef struct {
  UINT32       Range0Min:8;           ///< The minimum of the first count range.
  UINT32       Range0Max:8;           ///< The maximum of the first count range.
  UINT32       Range1Min:8;           ///< The minimum of the second count range.
  UINT32       Range1Max:8;           ///< The maximum of the second count range.
} COUNT_RANGE_FEATURE;

/**
 * Core Count Ranges for table data.
 *
 * Provide a pair of core count ranges. If the actual core count is included in either range (OR),
 * the feature should be considered a match.
 */
typedef union {
  UINT32       CoreRangeValue;          ///< Initializer value.
  COUNT_RANGE_FEATURE CoreRanges;       ///< The Core Counts.
} CORE_COUNT_RANGES;

/**
 * Processor count ranges for table data.
 *
 * Provide a pair of processor count ranges.  If the actual counts are included in either range (OR),
 * the feature should be considered a match.
 */
typedef union {
  UINT32       ProcessorCountRangeValue;             ///< Initializer value.
  COUNT_RANGE_FEATURE ProcessorCountRanges;          ///< The Processor and Node Counts.
} PROCESSOR_COUNTS;

/**
 * Compute unit count ranges for table data.
 *
 * Provide a pair of compute unit count ranges. If the actual counts are included in either ranges (OR),
 * the feature should be considered a match.
 */
typedef union {
  UINT32    ComputeUnitRangeValue;                ///< Initializer value.
  COUNT_RANGE_FEATURE ComputeUnitRanges;          ///< The Processor and Node Counts.
} COMPUTE_UNIT_COUNTS;

/**
 * Connectivity count ranges for table data.
 *
 * Provide a processor count range and a system degree range.  The degree of a system is
 * the maximum degree of any node.  The degree of a node is the number of nodes to which
 * it is directly connected (not considering width or redundant links). If both the actual
 * counts are included in each range (AND), the feature should be considered a match.
 */
typedef union {
  UINT32       ConnectivityCountRangeValue;             ///< Initializer value.
  COUNT_RANGE_FEATURE ConnectivityCountRanges;          ///< The Processor and Degree Counts.
} CONNECTIVITY_COUNT;

/**
 * HT Frequency Count Range.
 *
 * Provide a pair of Frequency count ranges, with the frequency encoded as an HT Frequency value
 * (such as would be programmed into the HT Host Link Frequency register).  By converting a NB freq,
 * the same count can be applied for it.  If the actual value is included in either range
 */
typedef union {
  UINT32       HtFreqCountRangeValue;                  ///< Initializer value.
  COUNT_RANGE_FEATURE HtFreqCountRanges;               ///< The HT Freq counts.
} HT_FREQ_COUNTS;

/*------------------------------------------------------------------------------------------*/
/*
 * The specific data for each table entry.
 */
/*------------------------------------------------------------------------------------------*/

/**
 *  Make an extra type so we can use compilers that don't support designated initializers.
 *
 *  All the entry type unions are no more than 5 UINT32's in size.  For entry types which are a struct of UINT32's,
 *  this type can be used so that initializers can be declared TABLE_ENTRY_FIELDS, instead of a special non-union type.
 *  A non-union type then has to be cast back to TABLE_ENTRY_FIELDS in order to process the table, and you can't mix
 *  entry types with non-union initializers in the same table with any other type.
 *
 *  If the entry type contains anything but UINT32's, then it must have a non-union initializer type for creating the
 *  actual tables.  For example, MSR entry has UINT64 and workaround entry has a function pointer.
 */
typedef UINT32 GENERIC_TYPE_ENTRY_INITIALIZER[MAX_ENTRY_TYPE_ITEMS32];

/**
 * Table Entry Data for MSR Registers.
 *
 * Apply data to register after mask, for MSRs.
 */
typedef struct {
  UINT32  Address;                    ///< MSR address
  UINT64  Data;                       ///< Data to set in the MSR
  UINT64  Mask;                       ///< Mask to be applied to the MSR. Set every bit of all updated fields.
} MSR_TYPE_ENTRY_DATA;

/**
 * Table Entry Data for PCI Registers.
 *
 * Apply data to register after mask, for PCI Config registers.
 */
typedef struct {
  PCI_ADDR  Address;                  ///< Address should contain Function, Offset only.  It will apply to all CPUs
  UINT32    Data;                     ///< Data to be written into PCI device
  UINT32    Mask;                     ///< Mask to be used before data write. Set every bit of all updated fields.
} PCI_TYPE_ENTRY_DATA;

/**
 * Table Entry Data for HT Phy Registers.
 *
 * Apply data to register after mask, for HT Phy registers, repeated for all active links.
 */
typedef struct {
  HT_PHY_LINK_FEATS TypeFeats;        ///< HT Phy Link Features
  UINT32            Address;          ///< Address of Ht Phy Register
  UINT32            Data;             ///< Data to be written into PCI device
  UINT32            Mask;             ///< Mask to be used before data write.  Set every bit of all updated fields.
} HT_PHY_TYPE_ENTRY_DATA;

/**
 * Table Entry Data for HT Phy Register Ranges.
 *
 * Apply data to register after mask, for a range of HT Phy registers, repeated for all active links.
 */
typedef struct {
  HT_PHY_LINK_FEATS TypeFeats;        ///< HT Phy Link Features
  UINT32            LowAddress;       ///< Low address of Ht Phy Register range.
  UINT32            HighAddress;      ///< High address of register range.
  UINT32            Data;             ///< Data to be written into PCI device.
  UINT32            Mask;             ///< Mask to be used before data write.  Set every bit of all updated fields.
} HT_PHY_RANGE_TYPE_ENTRY_DATA;

/**
 * Table Entry Data for HT Phy Deemphasis Registers.
 *
 * Apply data to register after mask, for HT Phy registers, repeated for all active links.
 */
typedef struct {
  DEEMPHASIS_FEATS        Levels;       ///< The DCV and Deemphasis levels to match
  HT_PHY_TYPE_ENTRY_DATA  HtPhyEntry;   ///< The HT Phy Entry to set the deemphasis values
} DEEMPHASIS_HT_PHY_TYPE_ENTRY_DATA;

/**
 * Table Entry Date for HT Phy Frequency Count Register updates.
 *
 * Compare the NB freq to a range, the HT freq to a range, the link features.
 * Apply data to register after mask, if all three matched.
 */
typedef struct {
  HT_FREQ_COUNTS       HtFreqCounts;      ///< Specify the HT Frequency range.
  HT_FREQ_COUNTS       NbFreqCounts;      ///< Specify the NB Frequency range.
  HT_PHY_TYPE_ENTRY_DATA HtPhyEntry;      ///< The HT Phy register update to perform.
} HT_PHY_FREQ_TYPE_ENTRY_DATA;

/**
 * Table Entry Data for Profile Fixup Registers.
 *
 * If TypeFeats matches current config, apply data to register after mask for PCI Config registers.
 */
typedef struct {
  PERFORMANCE_PROFILE_FEATS TypeFeats; ///< Profile Fixup Features.
  PCI_TYPE_ENTRY_DATA PciEntry;        ///< The PCI Register entry data.
} PROFILE_FIXUP_TYPE_ENTRY_DATA;

/**
 * A variation of PCI register for the HT Host registers.
 *
 * A setting to the HT Host buffer counts needs to be made to all the registers for
 * all the links.  There are also link specific criteria to check.
 */
typedef struct {
  HT_HOST_FEATS     TypeFeats;        ///< Link Features.
  PCI_ADDR          Address;          ///< Address of PCI Register to Fixed Up.
  UINT32            Data;             ///< Data to be written into PCI device
  UINT32            Mask;             ///< Mask to be used before data write.  Set every bit of all updated fields.
} HT_HOST_PCI_TYPE_ENTRY_DATA;

/**
 * A variation of PCI register for the HT Host performance registers.
 *
 * A setting to the HT Host buffer counts needs to be made to all the registers for
 * all the links.  There are also link specific criteria to check.
 */
typedef struct {
  PERFORMANCE_PROFILE_FEATS   PerformanceFeats;    ///< Performance Profile features.
  HT_HOST_PCI_TYPE_ENTRY_DATA HtHostEntry;         ///< Link Features.
} HT_HOST_PERFORMANCE_PCI_TYPE_ENTRY_DATA;

/**
 * A variation of HT Host PCI register for the Link Token registers.
 *
 * Use Link Features, Performance Fixup features, and processor counts to match entries.
 * Link Features are iterated through the connected links.  All the matching Link Token count
 * registers are updated.
 */
typedef struct {
  CONNECTIVITY_COUNT          ConnectivityCount;   ///< Specify Processor count and Degree count range.
  PERFORMANCE_PROFILE_FEATS   PerformanceFeats;    ///< Performance Profile features.
  HT_HOST_FEATS               LinkFeats;           ///< Link Features.
  PCI_ADDR                    Address;             ///< Address of PCI Register to Fixed Up.
  UINT32                      Data;                ///< Data to be written into PCI device
  UINT32                      Mask;                ///< Mask to be used before data write. Set every bit of all updated fields.
} HT_TOKEN_PCI_REGISTER;

/**
 * Core Count dependent PCI registers.
 *
 */
typedef struct {
  PERFORMANCE_PROFILE_FEATS TypeFeats; ///< Profile Fixup Features.
  CORE_COUNT_RANGES CoreCounts;        ///< Specify up to two core count ranges to match.
  PCI_TYPE_ENTRY_DATA PciEntry;        ///< The PCI Register entry data.
} CORE_COUNTS_PCI_TYPE_ENTRY_DATA;

/**
 * Processor Count dependent PCI registers.
 *
 */
typedef struct {
  PERFORMANCE_PROFILE_FEATS TypeFeats; ///< Profile Fixup Features.
  PROCESSOR_COUNTS  ProcessorCounts;   ///< Specify a processor count range.
  PCI_TYPE_ENTRY_DATA PciEntry;        ///< The PCI Register entry data.
} PROCESSOR_COUNTS_PCI_TYPE_ENTRY_DATA;

/**
 * Compute Unit Count dependent PCI registers.
 *
 */
typedef struct {
  PERFORMANCE_PROFILE_FEATS TypeFeats;         ///< Profile Fixup Features.
  COMPUTE_UNIT_COUNTS       ComputeUnitCounts; ///< Specify a compute unit count range.
  PCI_TYPE_ENTRY_DATA       PciEntry;          ///< The PCI Register entry data.
} COMPUTE_UNIT_COUNTS_PCI_TYPE_ENTRY_DATA;

/**
 * Compute Unit Count dependent MSR registers.
 *
 */
typedef struct {
  COMPUTE_UNIT_COUNTS       ComputeUnitCounts; ///< Specify a compute unit count range.
  MSR_TYPE_ENTRY_DATA       MsrEntry;          ///< The MSR Register entry data.
} COMPUTE_UNIT_COUNTS_MSR_TYPE_ENTRY_DATA;

/**
 * System connectivity dependent PCI registers.
 *
 * The topology specific recommended settings are based on the different connectivity of nodes
 * in each configuration:  the more connections, the fewer resources each connection gets.
 * The connectivity criteria translate as:
 * - 2 Socket, half populated  ==   Degree 1
 * - 4 Socket, half populated   ==  Degree 2
 * - 2 Socket, fully populated  ==  Degree 3
 * - 4 Socket, fully populated  ==  Degree > 3.  (4 or 5 if 3P, 6 if 4P)
 *
 */
typedef struct {
  PERFORMANCE_PROFILE_FEATS TypeFeats;     ///< Profile Fixup Features.
  CONNECTIVITY_COUNT  ConnectivityCount;   ///< Specify a system degree range.
  PCI_TYPE_ENTRY_DATA PciEntry;            ///< The PCI Register entry data.
} CONNECTIVITY_COUNTS_PCI_TYPE_ENTRY_DATA;

/**
 * A Family Specific Workaround method.
 *
 * \@TableTypeFamSpecificInstances.
 *
 * When called, the entry's CPU Logical ID and Platform Features matched the current config.
 * The method must implement any specific criteria checking for the workaround.
 *
 * See if you can use the other entries or make an entry specifically for the fix.
 * After all, the purpose of having a table entry is to @b NOT have code which
 * isn't generic feature code, but is family/model specific.
 *
 * @param[in]     Data       The table data value, for example to indicate which CPU and Platform types matched.
 * @param[in]     StdHeader  Config params for library, services.
 */
typedef VOID F_FAM_SPECIFIC_WORKAROUND (
  IN       UINT32              Data,
  IN       AMD_CONFIG_PARAMS   *StdHeader
  );
/// Reference to a method.
typedef F_FAM_SPECIFIC_WORKAROUND *PF_FAM_SPECIFIC_WORKAROUND;

/**
 * Table Entry Data for Family Specific Workarounds.
 *
 * See if you can use the other entries or make an entry specifically for the fix.
 * After all, the purpose of having a table entry is to @b NOT have code which
 * isn't generic feature code, but is family/model specific.
 *
 * Call DoAction passing Data.
 */
typedef struct {
  PF_FAM_SPECIFIC_WORKAROUND  DoAction;     ///< A function implementing the workaround.
  UINT32                Data;               ///< This data is passed to DoAction().
} FAM_SPECIFIC_WORKAROUND_TYPE_ENTRY_DATA;

/**
 * Package Type Features
 *
 * FamilyPackageType are various among CPU families.
 *
 */
typedef union {
  UINT32                      PackageTypeValue;    ///< Package Type
  PACKAGE_TYPE_FEATURES       FamilyPackageType;   ///< Package Type of CPU family
} PACKAGE_TYPE_FEATS;

/**
 * HT Features dependent Global PCI registers.
 *
 */
typedef struct {
  HT_HOST_FEATS               LinkFeats;           ///< Link Features.
  PACKAGE_TYPE_FEATS          PackageType;         ///< Package Type
  PCI_TYPE_ENTRY_DATA         PciEntry;            ///< The PCI Register entry data.
} HT_FEATURES_PCI_TYPE_ENTRY_DATA;

/**
 * Table Entry Data for HT Phy Registers which depend on performance profile features.
 *
 * Match performance profile features and link features.
 * Apply data to register after mask, for HT Phy registers, repeated for all active links.
 */
typedef struct {
  PERFORMANCE_PROFILE_FEATS  TypeFeats;            ///< Profile Fixup Features.
  HT_PHY_TYPE_ENTRY_DATA     HtPhyEntry;           ///< The HT Phy Entry to set the deemphasis values
} PROFILE_HT_PHY_TYPE_ENTRY_DATA;

/**
 * HT Link PCI registers that are not in the HT Host capability.
 *
 * Some HT Link registers have an instance per link, but are just sequential.  Specify the base register
 * in the table register address (link 0 sublink 0).
 */
typedef struct {
  HT_HOST_FEATS               LinkFeats;           ///< Link Features.
  PCI_TYPE_ENTRY_DATA         PciEntry;            ///< The PCI Register entry data.
} HT_LINK_PCI_TYPE_ENTRY_DATA;

/*------------------------------------------------------------------------------------------*/
/*
 * A complete register table and table entries.
 */
/*------------------------------------------------------------------------------------------*/

/**
 * All the available entry data types.
 */
typedef union {
  GENERIC_TYPE_ENTRY_INITIALIZER          InitialValues;         ///< Not a valid entry type; as the first union item,
                                                                 ///< it can be used with initializers.
  MSR_TYPE_ENTRY_DATA                     MsrEntry;              ///< Msr entry.
  PCI_TYPE_ENTRY_DATA                     PciEntry;              ///< PCI entry.
  FAM_SPECIFIC_WORKAROUND_TYPE_ENTRY_DATA FamSpecificEntry;      ///< Family Specific Workaround entry.
  HT_PHY_TYPE_ENTRY_DATA                  HtPhyEntry;            ///< HT Phy entry.
  HT_PHY_RANGE_TYPE_ENTRY_DATA            HtPhyRangeEntry;       ///< A range of Ht Phy Registers
  DEEMPHASIS_HT_PHY_TYPE_ENTRY_DATA       DeemphasisEntry;       ///< A HT Deemphasis level's settings.
  HT_PHY_FREQ_TYPE_ENTRY_DATA             HtPhyFreqEntry;        ///< A frequency dependent Ht Phy Register setting.
  PROFILE_FIXUP_TYPE_ENTRY_DATA           FixupEntry;            ///< Profile Fixup entry.
  HT_HOST_PCI_TYPE_ENTRY_DATA             HtHostEntry;           ///< HT Host PCI entry.
  HT_HOST_PERFORMANCE_PCI_TYPE_ENTRY_DATA HtHostPerfEntry;       ///< HT Host Performance PCI entry
  HT_TOKEN_PCI_REGISTER                   HtTokenEntry;          ///< HT Link Token Count entry.
  CORE_COUNTS_PCI_TYPE_ENTRY_DATA         CoreCountEntry;        ///< Core count dependent settings.
  PROCESSOR_COUNTS_PCI_TYPE_ENTRY_DATA    ProcCountEntry;        ///< Processor count entry.
  COMPUTE_UNIT_COUNTS_PCI_TYPE_ENTRY_DATA CompUnitCountEntry;    ///< Compute unit count dependent entry.
  CONNECTIVITY_COUNTS_PCI_TYPE_ENTRY_DATA TokenPciEntry;         ///< System connectivity dependent Token register.
  HT_FEATURES_PCI_TYPE_ENTRY_DATA         HtFeatPciEntry;        ///< HT Features PCI entry.
  PROFILE_HT_PHY_TYPE_ENTRY_DATA          HtPhyProfileEntry;     ///< Performance dependent HT Phy register.
  HT_LINK_PCI_TYPE_ENTRY_DATA             HtLinkPciEntry;        ///< Per Link, non HT Host, PCI registers.
  COMPUTE_UNIT_COUNTS_MSR_TYPE_ENTRY_DATA CompUnitCountMsrEntry; ///< Compute unit count dependent MSR entry.
} TABLE_ENTRY_DATA;

/**
 * Register Table Entry common fields.
 *
 * All the various types of register table entries are subclasses of this object.
 */
typedef struct {
  TABLE_ENTRY_TYPE       EntryType;                  ///< The type of table entry this is.
  CPU_LOGICAL_ID         CpuRevision;                ///< Common CPU Logical ID match criteria.
  PLATFORM_FEATS         Features;                   ///< Common Platform Features match criteria.
  TABLE_ENTRY_DATA       Entry;                      ///< The type dependent entry data (ex. register, data, mask).
} TABLE_ENTRY_FIELDS;

/**
 * An entire register table.
 */
typedef struct {
  TABLE_CORE_SELECTOR  Selector;                     ///< For efficiency, these cores should process this table
  UINT32               TimePoint;                    ///< Time Point designator
  UINTN                NumberOfEntries;              ///< The number of entries in the table.
  CONST TABLE_ENTRY_FIELDS  *Table;                  ///< The table entries.
} REGISTER_TABLE;

/*------------------------------------------------------------------------------------------*/
/*
 * Describe implementers for table entries.
 */
/*------------------------------------------------------------------------------------------*/

/**
 * Implement the semantics of a Table Entry Type.
 *
 * @TableEntryTypeInstances.
 *
 * @param[in]       CurrentEntry        The type specific entry data to be implemented (that is written).
 * @param[in]       PlatformConfig      Config handle for platform specific information
 * @param[in]       StdHeader           Config params for library, services.
 */
typedef VOID F_DO_TABLE_ENTRY (
  IN       TABLE_ENTRY_DATA       *CurrentEntry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );
/// Reference to a method
typedef F_DO_TABLE_ENTRY *PF_DO_TABLE_ENTRY;

/**
 * Describe the attributes of a Table Entry Type.
 */
typedef struct {
  TABLE_ENTRY_TYPE       EntryType;                  ///< The type of table entry this describes.
  PF_DO_TABLE_ENTRY      DoTableEntry;               ///< Provide all semantics associated with TABLE_ENTRY_DATA
} TABLE_ENTRY_TYPE_DESCRIPTOR;

/*------------------------------------------------------------------------------------------*/
/*
 * Non-union initializers for entry data which is not just UINT32.
 */
/*------------------------------------------------------------------------------------------*/

/**
 * A union of data types, that can be initialized with MSR data.
 *
 * This ensures the entry data is the same size as TABLE_ENTRY_DATA.
 */
typedef union {
  MSR_TYPE_ENTRY_DATA    MsrInitializer;            ///< The data in the table initializer is assigned to this member.
  TABLE_ENTRY_DATA       Reserved;                  ///< Make sure the size is the same as the real union.
} MSR_DATA_INITIALIZER;

/**
 * A type suitable for an initializer for MSR Table entries.
 */
typedef struct {
  TABLE_ENTRY_TYPE       Type;                       ///< The type of table entry this is.
  CPU_LOGICAL_ID         CpuRevision;                ///< Common CPU Logical ID match criteria.
  PLATFORM_FEATS         Features;                   ///< Common Platform Features match criteria.
  MSR_DATA_INITIALIZER    EntryData;                 ///< The special union which accepts msr data initializer.
} MSR_TYPE_ENTRY_INITIALIZER;

/**
 * A union of data types, that can be initialized with MSR CU data.
 *
 * This ensures the entry data is the same size as TABLE_ENTRY_DATA.
 */
typedef union {
  COMPUTE_UNIT_COUNTS_MSR_TYPE_ENTRY_DATA  MsrInitializer;  ///< The data in the table initializer is assigned to this member.
  TABLE_ENTRY_DATA       Reserved;                          ///< Make sure the size is the same as the real union.
} MSR_CU_DATA_INITIALIZER;

/**
 * A type suitable for an initializer for MSR CU count Table entries.
 */
typedef struct {
  TABLE_ENTRY_TYPE           Type;                   ///< The type of table entry this is.
  CPU_LOGICAL_ID             CpuRevision;            ///< Common CPU Logical ID match criteria.
  PLATFORM_FEATS             Features;               ///< Common Platform Features match criteria.
  MSR_CU_DATA_INITIALIZER    EntryData;              ///< The special union which accepts msr data initializer.
} MSR_CU_TYPE_ENTRY_INITIALIZER;

/**
 * A union of data types, that can be initialized with Family Specific Workaround data.
 *
 * This ensures the entry data is the same size as TABLE_ENTRY_DATA.
 */
typedef union {
  FAM_SPECIFIC_WORKAROUND_TYPE_ENTRY_DATA    FamSpecificInitializer; ///< The data in the table initializer is assigned to this member.
  TABLE_ENTRY_DATA       Reserved;                                   ///< Make sure the size is the same as the real union.
} FAM_SPECIFIC_WORKAROUND_DATA_INITIALIZER;

/**
 * A type suitable for an initializer for Family Specific Workaround Table entries.
 */
typedef struct {
  TABLE_ENTRY_TYPE       Type;                             ///< The type of table entry this is.
  CPU_LOGICAL_ID         CpuRevision;                      ///< Common CPU Logical ID match criteria.
  PLATFORM_FEATS         Features;                         ///< Common Platform Features match criteria.
  FAM_SPECIFIC_WORKAROUND_DATA_INITIALIZER    EntryData;   ///< Special union accepts family specific workaround data initializer.
} FAM_SPECIFIC_WORKAROUND_TYPE_ENTRY_INITIALIZER;

/*------------------------------------------------------------------------------------------*/
/*
 * Table related function prototypes (many are instance of F_DO_TABLE_ENTRY method).
 */
/*------------------------------------------------------------------------------------------*/

/**
 * Set the registers for this core based on entries in a list of Register Tables.
 */
VOID SetRegistersFromTables (
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       UINT32                 TimePoint,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Find the features of the running platform.
 */
VOID
GetPlatformFeatures (
     OUT   PLATFORM_FEATS    *Features,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS *StdHeader
  );

/**
 * Checks register table entry type specific criteria to the platform.
 */
BOOLEAN
DoesEntryTypeSpecificInfoMatch (
  IN       UINT32   PlatformTypeSpecificFeatures,
  IN       UINT32   EntryTypeFeatures
  );

/**
 * Perform the MSR Register Entry.
 */
VOID
SetRegisterForMsrEntry (
  IN       TABLE_ENTRY_DATA      *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS     *StdHeader
  );

/**
 * Perform the PCI Register Entry.
 */
VOID
SetRegisterForPciEntry (
  IN       TABLE_ENTRY_DATA      *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS     *StdHeader
  );

/**
 * Perform the Performance Profile PCI Register Entry.
 */
VOID
SetRegisterForPerformanceProfileEntry (
  IN       TABLE_ENTRY_DATA      *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS     *StdHeader
  );

/**
 * Perform the HT Host PCI Register Entry.
 */
VOID
SetRegisterForHtHostEntry (
  IN       TABLE_ENTRY_DATA      *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS     *StdHeader
  );

/**
 * Perform the HT Host Performance PCI Register Entry.
 */
VOID
SetRegisterForHtHostPerfEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Set the HT Link Token Count registers.
 */
VOID
SetRegisterForHtLinkTokenEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Perform the Core Counts Performance PCI Register Entry.
 */
VOID
SetRegisterForCoreCountsPerformanceEntry (
  IN       TABLE_ENTRY_DATA      *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS     *StdHeader
  );

/**
 * Perform the Processor Counts PCI Register Entry.
 */
VOID
SetRegisterForProcessorCountsEntry (
  IN       TABLE_ENTRY_DATA      *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS     *StdHeader
  );

/**
 * Perform the Compute Unit Counts PCI Register Entry.
 */
VOID
SetRegisterForComputeUnitCountsEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Perform the Compute Unit Counts MSR Register Entry.
 */
VOID
SetMsrForComputeUnitCountsEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Perform the Family Specific Workaround Register Entry.
 */
VOID
SetRegisterForFamSpecificWorkaroundEntry (
  IN       TABLE_ENTRY_DATA      *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS     *StdHeader
  );

/**
 * Program HT Phy PCI registers.
 */
VOID
SetRegisterForHtPhyEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Program a range of HT Phy PCI registers.
 */
VOID
SetRegisterForHtPhyRangeEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Program Deemphasis registers, for the platform specified levels.
 */
VOID
SetRegisterForDeemphasisEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Program HT Phy PCI registers which have complex frequency dependencies.
 */
VOID
SetRegisterForHtPhyFreqEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Perform the Processor Token Counts PCI Register Entry.
 */
VOID
SetRegisterForTokenPciEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Perform the HT Link Feature PCI Register Entry.
 */
VOID
SetRegisterForHtFeaturePciEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Perform the HT Phy Performance Profile Register Entry.
 */
VOID
SetRegisterForHtPhyProfileEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Perform the HT Link PCI Register Entry.
 */
VOID
SetRegisterForHtLinkPciEntry (
  IN       TABLE_ENTRY_DATA       *Entry,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

/**
 * Compare counts to a pair of ranges.
 */
BOOLEAN
IsEitherCountInRange (
  IN       UINTN                FirstCount,
  IN       UINTN                SecondCount,
  IN       COUNT_RANGE_FEATURE  Ranges
  );

/**
 * Returns the performance profile features list of the currently running processor core.
 */
VOID
GetPerformanceFeatures (
     OUT   PERFORMANCE_PROFILE_FEATS    *Features,
  IN       PLATFORM_CONFIGURATION       *PlatformConfig,
  IN       AMD_CONFIG_PARAMS            *StdHeader
  );

#endif  // _CPU_TABLE_H_