summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/prdf/occ_firdata/prdfWriteHomerFirData.C
blob: 2e9b6f963e02b2f578d97c3c2b55641dccfebbdf (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/occ_firdata/prdfWriteHomerFirData.C $       */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <homerData_common.h>

#include <prdfErrlUtil.H>
#include <prdfPlatServices.H>
#include <prdfTrace.H>
#include <prdfWriteHomerFirData.H>

#include <fsi/fsiif.H>
#include <pnor/pnorif.H>
#include <targeting/common/targetservice.H>
#include <targeting/namedtarget.H> // for getMasterCore()

using namespace TARGETING;

namespace PRDF
{

using namespace PlatServices;

//------------------------------------------------------------------------------
// Register lists
//------------------------------------------------------------------------------


// TODO RTC 124849: Auto-generate this list from rule code.
// although HDCT plays a role
// currently have a mix from HDCT, P8->P9 manual conversion
// and some other chiplet attn regs

// For Creating list of registers
typedef std::vector<uint64_t> AddrList_t;
typedef std::map<RegType_t, AddrList_t> RegMap_t;
typedef std::map<TrgtType_t, RegMap_t> TrgtMap_t;

/**
 * @fn void getAddresses( TrgtMap_t & io_targMap )
 *
 * @brief Fills in the SCOM addresses we need for all targets
 *          and for all register types.
 */
void getAddresses( TrgtMap_t & io_targMap )
{
    io_targMap[TRGT_PROC][REG_GLBL] =
    {
        0x500F001C, // GLOBAL_CS_FIR
        0x500F001B, // GLOBAL_RE_FIR
        0x50040018, // GLOBAL_UNIT_CS_FIR

        // NOTE: The SPA/HOST_ATTN global/chiplet registers will not be captured
        //       because those attention types are not used for checkstop
        //       analysis.
    };

    io_targMap[TRGT_PHB][REG_FIR] =
    {
        0x04010C40, // PHBNFIR
        0x0D010840, // PCIFIR
        0x0D010908, // ETUFIR
    };

    io_targMap[TRGT_PHB][REG_REG] =
    {
        // c_err_rpt registers
        0x0D01084B, // PBAIB CERR Report Hold Reg
    };

    io_targMap[TRGT_CAPP][REG_FIR] =
    {
        0x02010800, // CXAFIR
    };

    io_targMap[TRGT_CAPP][REG_REG] =
    {
        // c_err_rpt registers
        0x0201080a, // Snoop Error Report Reg
        0x0201080b, // APC CERR Hold
        0x0201080c, // XPT Error Report
        0x0201080d, // TLBI Error Report
        0x0201080e, // Capp Error Status and Ctrl Reg
    };

    io_targMap[TRGT_XBUS][REG_FIR] =
    {
        0x06010c00, // IOXBFIR
        0x06011800, // IOELFIR
    };

    io_targMap[TRGT_XBUS][REG_REG] =
    {
        // c_err_rpt registers
        0x06011816, // PB ELL Link0 ErrStatus
        0x06011817, // PB ELL Link1 ErrStatus
    };

    io_targMap[TRGT_OBUS][REG_GLBL] =
    {
        0x09040000, // OB_CHIPLET_CS_FIR
        0x09040001, // OB_CHIPLET_RE_FIR
        0x09040018, // OB_CHIPLET_UCS_FIR
    };

    io_targMap[TRGT_OBUS][REG_FIR] =
    {
        0x0904000a, // OB LFIR
        0x09010800, // IOOLFIR
        0x09010C00, // IOOBFIR
        0x09011040, // OBPPEFIR
    };

    io_targMap[TRGT_OBUS][REG_REG] =
    {
        // Chiplet FIRs
        0x09040002, // OB_CHIPLET_FIR_MASK
        0x09040019, // OB_CHIPLET_UCS_FIR_MASK

        // PLL registers
        0x090F001E, // OBUS_CONFIG_REG
        0x090F001F, // OBUS_ERROR_REG

        // c_err_rpt registers
        0x09010816, // PB OLL Link0 ErrStatus
        0x09010817, // PB OLL Link1 ErrStatus
    };

    io_targMap[TRGT_PEC][REG_FIR] =
    {
        0x0D04000a, // PCI_LFIR
        0x0D010C00, // IOPCIFIR
    };

    io_targMap[TRGT_PEC][REG_REG] =
    {
        // PLL registers
        0x0D0F001E, // PCI_CONFIG_REG
        0x0D0F001F, // PCI_ERROR_REG
    };

    io_targMap[TRGT_MCS][REG_FIR] =
    {
        0x05010800, // MCIFIR
    };

    io_targMap[TRGT_MCS][REG_REG] =
    {
        // c_err_rpt registers
        0x0501081a, // MC Error Report 2
        0x0501081e, // MC Error Report 0
        0x0501081f, // MC Error Report 1

        // Memory config registers
        0x0501080a, // Primary MemCfg Reg
        0x0501080b, // MCFGPA
        0x0501080c, // MCFGPM
        0x0501080d, // MCFGPMA
    };

    io_targMap[TRGT_MCBIST][REG_GLBL] =
    {
        0x07040000, // MC_CHIPLET_CS_FIR
        0x07040001, // MC_CHIPLET_RE_FIR
        0x07040018, // MC_CHIPLET_UCS_FIR
    };

    io_targMap[TRGT_MCBIST][REG_FIR] =
    {
        0x0704000A, // MC_LFIR
        0x07012300, // MCBISTFIR
    };

    io_targMap[TRGT_MCA][REG_FIR] =
    {
        0x07010900, // MCACALFIR
        0x07010A00, // MCAECCFIR
        0x07011000, // DDRPHYFIR
    };

    io_targMap[TRGT_MCBIST][REG_REG] =
    {
        // Chiplet FIRs
        0x07040002, // MC_CHIPLET_FIR_MASK
        0x07040019, // MC_CHIPLET_UCS_FIR_MASK

        // PLL registers
        0x070F001E, // MC_CONFIG_REG
        0x070F001F, // MC_ERROR_REG

        // AUE/IAUE analysis
        0x0701236D, // MCB0_MBUER
        0x0701236E, // MCB0_MBAUER
        0x07012372, // MCB1_MBUER
        0x07012373, // MCB1_MBAUER
        0x07012377, // MCB2_MBUER
        0x07012378, // MCB2_MBAUER
        0x0701237C, // MCB3_MBUER
        0x0701237D, // MCB3_MBAUER
        0x070123D7, // MCBMCAT
    };

    io_targMap[TRGT_EQ][REG_GLBL] =
    {
        0x10040000, // EQ_CHIPLET_CS_FIR
        0x10040001, // EQ_CHIPLET_RE_FIR
    };

    io_targMap[TRGT_EQ][REG_FIR] =
    {
        0x1004000A, // EQ_LFIR
    };

    io_targMap[TRGT_EQ][REG_REG] =
    {
        // Chiplet FIRs
        0x10040002, // EQ_CHIPLET_FIR_MASK

        // PLL registers
        0x100F001E, // EQ_CONFIG_REG
        0x100F001F, // EQ_ERROR_REG
    };

    io_targMap[TRGT_PROC][REG_FIR] =
    {
        0x0104000a, // TP_LFIR
        0x01010800, // OCCFIR

        0x0204000a, // N0_LFIR
        0x02011080, // NXCQFIR
        0x02011100, // NXDMAENGFIR

        0x0304000a, // N1_LFIR
        0x03011000, // MCDFIR_0
        0x03011400, // MCDFIR_1
        0x03011800, // VASFIR

        0x0404000a, // N2_LFIR
        0x04011800, // PSIFIR

        0x0504000a, // N3_LFIR
        0x05011800, // PBWESTFIR
        0x05011C00, // PBCENTFIR
        0x05012000, // PBEASTFIR
        0x05012400, // PBPPEFIR
        0x05012840, // PBAFIR
        0x05012900, // PSIHBFIR
        0x05012940, // ENHCAFIR
        0x050129C0, // PBAMFIR
        0x05012C00, // NMMUCQFIR
        0x05012C40, // NMMUFIR
        0x05013030, // INTCQFIR
        0x05013400, // PBIOEFIR
        0x05013800, // PBIOOFIR
        0x05013C00, // NPU0FIR
        0x05013C40, // NPU1FIR
        0x05013C80, // NPU2FIR

        0x0604000a, // XBUS_LFIR
        0x06010840, // XBPPEFIR
    };

    io_targMap[TRGT_PROC][REG_REG] =
    {
        // Global FIRs
        0x500F001A, // GLOBAL_SPA (FFDC only, in case there was a TI)

        // Chiplet FIRs
        0x01040000, // TP_CHIPLET_CS_FIR
        0x01040001, // TP_CHIPLET_RE_FIR
        0x01040002, // TP_CHIPLET_FIR_MASK

        0x02040000, // N0_CHIPLET_CS_FIR
        0x02040001, // N0_CHIPLET_RE_FIR
        0x02040002, // N0_CHIPLET_FIR_MASK
        0x02040018, // N0_CHIPLET_UCS_FIR
        0x02040019, // N0_CHIPLET_UCS_FIR_MASK

        0x03040000, // N1_CHIPLET_CS_FIR
        0x03040001, // N1_CHIPLET_RE_FIR
        0x03040002, // N1_CHIPLET_FIR_MASK
        0x03040018, // N1_CHIPLET_UCS_FIR
        0x03040019, // N1_CHIPLET_UCS_FIR_MASK

        0x04040000, // N2_CHIPLET_CS_FIR
        0x04040001, // N2_CHIPLET_RE_FIR
        0x04040002, // N2_CHIPLET_FIR_MASK
        0x04040018, // N2_CHIPLET_UCS_FIR
        0x04040019, // N2_CHIPLET_UCS_FIR_MASK

        // There are over 90 registers captured for NPU0FIR, but that is too
        // much for the limited space in the OP checkstop analysis design. The
        // hardware team agreed this was the minimum set of registers needed
        // for a checkstop. We have also been told most of these should have a
        // zero value so they should not take up too much space.
        0x05011018, // NPU_S0_CS_SM0_CERR_1
        0x05011019, // NPU_S0_CS_SM0_CERR_2
        0x05011048, // NPU_S0_CS_SM1_CERR_1
        0x05011049, // NPU_S0_CS_SM1_CERR_2
        0x05011078, // NPU_S0_CS_SM2_CERR_1
        0x05011079, // NPU_S0_CS_SM2_CERR_2
        0x050110A8, // NPU_S0_CS_SM3_CERR_1
        0x050110A9, // NPU_S0_CS_SM3_CERR_2
        0x050110DB, // NPU_S0_CS_CTL_CERR_1
        0x050110FA, // NPU_S0_DAT_CERR_LOG_HOLD
        0x050110FD, // NPU_S0_DAT_REM0
        0x050110FE, // NPU_S0_DAT_REM1
        0x05011218, // NPU_S1_CS_SM0_CERR_1
        0x05011219, // NPU_S1_CS_SM0_CERR_2
        0x05011248, // NPU_S1_CS_SM1_CERR_1
        0x05011249, // NPU_S1_CS_SM1_CERR_2
        0x05011278, // NPU_S1_CS_SM2_CERR_1
        0x05011279, // NPU_S1_CS_SM2_CERR_2
        0x050112A8, // NPU_S1_CS_SM3_CERR_1
        0x050112A9, // NPU_S1_CS_SM3_CERR_2
        0x050112DB, // NPU_S1_CS_CTL_CERR_1
        0x050112FA, // NPU_S1_DAT_CERR_LOG_HOLD
        0x050112FD, // NPU_S1_DAT_REM0
        0x050112FE, // NPU_S1_DAT_REM1
        0x05011418, // NPU_S2_CS_SM0_CERR_1
        0x05011419, // NPU_S2_CS_SM0_CERR_2
        0x05011448, // NPU_S2_CS_SM1_CERR_1
        0x05011449, // NPU_S2_CS_SM1_CERR_2
        0x05011478, // NPU_S2_CS_SM2_CERR_1
        0x05011479, // NPU_S2_CS_SM2_CERR_2
        0x050114A8, // NPU_S2_CS_SM3_CERR_1
        0x050114A9, // NPU_S2_CS_SM3_CERR_2
        0x050114DB, // NPU_S2_CS_CTL_CERR_1
        0x050114FA, // NPU_S2_DAT_CERR_LOG_HOLD
        0x050114FD, // NPU_S2_DAT_REM0
        0x050114FE, // NPU_S2_DAT_REM1

        0x05040000, // N3_CHIPLET_CS_FIR
        0x05040001, // N3_CHIPLET_RE_FIR
        0x05040002, // N3_CHIPLET_FIR_MASK
        0x05040018, // N3_CHIPLET_UCS_FIR
        0x05040019, // N3_CHIPLET_UCS_FIR_MASK

        0x06040000, // XB_CHIPLET_CS_FIR
        0x06040001, // XB_CHIPLET_RE_FIR
        0x06040002, // XB_CHIPLET_FIR_MASK
        0x06040018, // XB_CHIPLET_UCS_FIR
        0x06040019, // XB_CHIPLET_UCS_FIR_MASK

        // Chiplet FIRs
        0x0D040000, // PCI0_CHIPLET_CS_FIR
        0x0D040001, // PCI0_CHIPLET_RE_FIR
        0x0D040002, // PCI0_CHIPLET_FIR_MASK
        0x0E040000, // PCI1_CHIPLET_CS_FIR
        0x0E040001, // PCI1_CHIPLET_RE_FIR
        0x0E040002, // PCI1_CHIPLET_FIR_MASK
        0x0F040000, // PCI2_CHIPLET_CS_FIR
        0x0F040001, // PCI2_CHIPLET_RE_FIR
        0x0F040002, // PCI2_CHIPLET_FIR_MASK

        // Misc registers needed for PRD analysis
        0x05011C2E, // PBEXTFIR (does not raise attn, used for fabric sorting)
        0x05011C0A, // PB_CENT_MODE
        0x00040020, // TODWOF

        // PLL registers
        0x010F001E, // TP_CONFIG_REG
        0x010F001F, // TP_ERROR_REG
        0x060F001E, // XBUS_CONFIG_REG
        0x060F001F, // XBUS_ERROR_REG

        // c_err_rpt registers
        0x0101080a, // OCC Error Report Reg
        0x020110a1, // PB Error Report
        0x020110a2, // PB Pty Error Report
        0x02011057, // DMA CERR 0
        0x02011058, // DMA CERR 1
        0x05011c2c, // PB Cent CR ERROR
        0x0501284c, // PBA Err Report0
        0x0501284d, // PBA Err Report1
        0x0501284e, // PBA Err Report2
        0x05012C22, // PB Pty Error Report

        // TOD registers
        0x00040005, // TOD: Slave path ctrl reg
        0x00040006, // TOD: Internal path ctrl reg
        0x00040007, // TOD: primary/secondary config ctrl
        0x00040008, // TOD: PSS MSS Status Reg
        0x00040009, // TOD: Master Path Status Reg
        0x0004000E, // TOD: Master Path0 Step Steering
        0x0004000F, // TOD: Master Path1 Step Steering
        0x0004001D, // TOD: Trace dataset 1
        0x0004001E, // TOD: Trace dataset 2
        0x0004001F, // TOD: Trace dataset 3
        0x01020019, // OSC Error Hold
        0x0102001A, // OSC Error Mask
        0x0102001B, // OSC Error Mode
        0x00040024, // TOD:FSM Register
        0x00040027, // TOD: TX TType Ctrl reg
        0x00040029, // TOD: RX TType Ctrl reg
        0x00040030, // TOD: Error and Interrupts
        0x00040032, // TOD: C_Err_Rpt
        0x00040033, // TOD: Route Errors to Core/FIR

        // INTCQFIR c_err_rpt registers
        0x05013038, // INT_CQ_WOF
        0x05013039, // INT_CQ_ERROR_HOLD_OUT
        0x0501303A, // INT_CQ_ERR_INFO0
        0x0501303B, // INT_CQ_ERR_INFO1
        0x0501303C, // INT_CQ_ERR_INFO2
        0x0501303D, // INT_CQ_ERR_INFO3
        0x05013142, // INT_PC_ERR0_WOF
        0x05013143, // INT_PC_ERR0_WOF_DETAIL
        0x05013144, // INT_PC_ERR0_FATAL
        0x05013145, // INT_PC_ERR0_RECOV
        0x05013146, // INT_PC_ERR0_INFO
        0x0501314A, // INT_PC_ERR1_WOF
        0x0501314B, // INT_PC_ERR1_WOF_DETAIL
        0x0501314C, // INT_PC_ERR1_FATAL
        0x0501314D, // INT_PC_ERR1_RECOV
        0x0501314E, // INT_PC_ERR1_INFO
        0x0501317A, // INT_PC_VPC_ERR1_WOF
        0x0501317B, // INT_PC_VPC_ERR1_WOF_DETAIL
        0x0501317C, // INT_PC_VPC_FATAL_ERR
        0x0501317D, // INT_PC_VPC_RECOV_ERR
        0x0501317E, // INT_PC_VPC_INFO_ERR
        0x05013274, // INT_VC_WOF_ERR_G0
        0x05013275, // INT_VC_WOF_ERR_G0_DETAIL
        0x05013276, // INT_VC_WOF_ERR_G1
        0x05013277, // INT_VC_WOF_ERR_G1_DETAIL
        0x05013278, // INT_VC_FATAL_ERR_G0
        0x05013279, // INT_VC_RECOV_ERR_G0
        0x0501327A, // INT_VC_INFO_ERR_G0
        0x0501327B, // INT_VC_FATAL_ERR_G1
        0x0501327C, // INT_VC_RECOV_ERR_G1
        0x0501327D, // INT_VC_INFO_ERR_G1
    };

    io_targMap[TRGT_EC][REG_GLBL] =
    {
        0x20040000, // EC_CHIPLET_CS_FIR
        0x20040001, // EC_CHIPLET_RE_FIR
        0x20040018, // EC_CHIPLET_UCS_FIR
    };

    io_targMap[TRGT_EC][REG_FIR] =
    {
        0x2004000A, // EC_LFIR
        0x20010A40, // COREFIR
    };

    io_targMap[TRGT_EC][REG_REG] =
    {
        // Chiplet FIRs
        0x20040002, // EC_CHIPLET_FIR_MASK
        0x20040019, // EC_CHIPLET_UCS_FIR_MASK

        // Local FIRs
        0x20010A48, // COREFIR_WOF (required for analysis)

        // PLL registers
        0x200F001E, // EC_CONFIG_REG
        0x200F001F, // EC_ERROR_REG

        // Misc
        0x20010A96, // HOMER_ENABLE
        0x20010A99, // SPEC_ATTN_REASON
        0x20010A9A, // SPEC_ATTN_REASON_MASK

        // c_err_rpt registers
        0x20010AB5, // SPR Core Error Report Hold Out Reg
        0x20010AB6, // PMU Error Report Hold Out Register
        0x20010AB7, // TFAC Error Report Hold Out Register
        0x20010AB8, // SPR Common Error Report Hold Out Register
        0x20010C00, // IFU Error Report Hold Out 0 Register
        0x20010C01, // IFU Error Report Hold Out 1 Register
        0x20010C02, // IFU Error Report Hold Out 2 Register
        0x20010C03, // IFU Error Report Hold Out 3 Register
        0x20010C40, // ISU error report hold_out register 0
        0x20010C41, // ISU error report hold_out register 1
        0x20010C42, // ISU error report hold_out register 2
        0x20010C43, // ISU error report hold_out register 3
        0x20010C44, // ISU error report hold_out register 4
        0x20010C45, // ISU error report hold_out register 5
        0x20010C80, // LSU error report hold_out register 0
        0x20010C81, // LSU error report hold_out register 1
        0x20010C82, // LSU error report hold_out register 2
        0x20010C83, // LSU error report hold_out register 3
        0x20010A51, // FIR/RECOV Error Report Hold Out Register
        0x20010A03, // Thread Control Error Report Hold Out Register
        0x200F0110, // PPM STOP_STATE_HIST_SRC_REG
    };

    io_targMap[TRGT_EX][REG_FIR] =
    {
        0x10010800, // L2FIR
        0x10011000, // NCUFIR
        0x10011800, // L3FIR
        0x10012000, // CMEFIR
    };

    io_targMap[TRGT_EX][REG_REG] =
    {
        // c_err_rpt registers
        0x10010812, // ERROR REPORT REGISTER0
        0x10010813, // ERROR REPORT REGISTER1
        0x1001100E, // NCU error rpt register
        0x1001180E, // L3 PRD Purge Register
        0x10011810, // L3 Error Report Reg 0
        0x10011817, // L3 Error Report Reg 1
        0x10011819, // L3 eDRAM RD Err Stat Reg0
        0x1001181A, // L3 eDRAM RD Err Stat Reg1
        0x1001181B, // L3 Edram Bank Fail
    };

    io_targMap[TRGT_NPU][REG_FIR] =
    {
        0x05013C00, // NPU0FIR
        0x05013C40, // NPU1FIR
        0x05013C80, // NPU2FIR
    };

    io_targMap[TRGT_NPU][REG_REG] =
    {
        // There are over 90 registers captured for NPU0FIR, but that is too
        // much for the limited space in the OP checkstop analysis design. The
        // hardware team agreed this was the minimum set of registers needed
        // for a checkstop. We have also been told most of these should have a
        // zero value so they should not take up too much space.
        0x05011018, // NPU_S0_CS_SM0_CERR_1
        0x05011019, // NPU_S0_CS_SM0_CERR_2
        0x05011048, // NPU_S0_CS_SM1_CERR_1
        0x05011049, // NPU_S0_CS_SM1_CERR_2
        0x05011078, // NPU_S0_CS_SM2_CERR_1
        0x05011079, // NPU_S0_CS_SM2_CERR_2
        0x050110A8, // NPU_S0_CS_SM3_CERR_1
        0x050110A9, // NPU_S0_CS_SM3_CERR_2
        0x050110DB, // NPU_S0_CS_CTL_CERR_1
        0x050110FA, // NPU_S0_DAT_CERR_LOG_HOLD
        0x050110FD, // NPU_S0_DAT_REM0
        0x050110FE, // NPU_S0_DAT_REM1
        0x05011218, // NPU_S1_CS_SM0_CERR_1
        0x05011219, // NPU_S1_CS_SM0_CERR_2
        0x05011248, // NPU_S1_CS_SM1_CERR_1
        0x05011249, // NPU_S1_CS_SM1_CERR_2
        0x05011278, // NPU_S1_CS_SM2_CERR_1
        0x05011279, // NPU_S1_CS_SM2_CERR_2
        0x050112A8, // NPU_S1_CS_SM3_CERR_1
        0x050112A9, // NPU_S1_CS_SM3_CERR_2
        0x050112DB, // NPU_S1_CS_CTL_CERR_1
        0x050112FA, // NPU_S1_DAT_CERR_LOG_HOLD
        0x050112FD, // NPU_S1_DAT_REM0
        0x050112FE, // NPU_S1_DAT_REM1
        0x05011418, // NPU_S2_CS_SM0_CERR_1
        0x05011419, // NPU_S2_CS_SM0_CERR_2
        0x05011448, // NPU_S2_CS_SM1_CERR_1
        0x05011449, // NPU_S2_CS_SM1_CERR_2
        0x05011478, // NPU_S2_CS_SM2_CERR_1
        0x05011479, // NPU_S2_CS_SM2_CERR_2
        0x050114A8, // NPU_S2_CS_SM3_CERR_1
        0x050114A9, // NPU_S2_CS_SM3_CERR_2
        0x050114DB, // NPU_S2_CS_CTL_CERR_1
        0x050114FA, // NPU_S2_DAT_CERR_LOG_HOLD
        0x050114FD, // NPU_S2_DAT_REM0
        0x050114FE, // NPU_S2_DAT_REM1
    };

    io_targMap[TRGT_MC][REG_GLBL] =
    {
        0x07040000, // MC_CHIPLET_CS_FIR
        0x07040001, // MC_CHIPLET_RE_FIR
        0x07040018, // MC_CHIPLET_UCS_FIR
    };

    io_targMap[TRGT_MC][REG_FIR] =
    {
        0x07012300, // MCBISTFIR
    };

    io_targMap[TRGT_MI][REG_FIR] =
    {
        0x05010800, // MCFIR
    };

    io_targMap[TRGT_MI][REG_REG] =
    {
        // c_err_rpt registers
        0x0501081E, // MCERPT0
        0x0501081F, // MCERPT1
        0x0501081A, // MCERPT2
        0x0501080A, // MCFGP
        0x0501080C, // MCFGPM
    };

    io_targMap[TRGT_MCC][REG_FIR] =
    {
        0x07010900, // DSTLFIR
        0x07010a00, // USTLFIR
    };

    io_targMap[TRGT_OMIC][REG_FIR] =
    {
        0x07011000, // IOOMIFIR
        0x07012440, // MCPPEFIR
        0x07013340, // OMIDLFIR
    };

    io_targMap[TRGT_OMIC][REG_REG] =
    {
        0x07013353, // DL0_ERROR_HOLD
        0x07013363, // DL1_ERROR_HOLD
        0x07013373, // DL2_ERROR_HOLD
    };

    // EC level handling will be done with a
    // structure and separate register count field.

} // end getAddresses

//------------------------------------------------------------------------------

errlHndl_t getPnorInfo( HOMER_Data_t & o_data )
{
    #define FUNC "[PRDF::getPnorInfo] "

    errlHndl_t errl = NULL;

    //----------------------------------------------------------------------
    // Get the PNOR information.
    //----------------------------------------------------------------------
    do
    {
        PNOR::SectionInfo_t sectionInfo;
        errl = PNOR::getSectionInfo( PNOR::FIRDATA, sectionInfo );
        if ( NULL != errl )
        {
            PRDF_ERR( FUNC "getSectionInfo() failed" );
            break;
        }

        PNOR::PnorInfo_t pnorInfo;
        PNOR::getPnorInfo( pnorInfo );

        // Saving the flash workarounds in an attribute for when we
        // call getPnorInfo() in the runtime code.
        // Using sys target
        Target* sys = NULL;
        targetService().getTopLevelTarget( sys );
        assert(sys != NULL);

        sys->setAttr<ATTR_PNOR_FLASH_WORKAROUNDS>(pnorInfo.norWorkarounds);

        o_data.pnorInfo.pnorOffset      = sectionInfo.flashAddr;
        o_data.pnorInfo.pnorSize        = sectionInfo.size;
        o_data.pnorInfo.mmioOffset      = pnorInfo.mmioOffset;
        o_data.pnorInfo.norWorkarounds  = pnorInfo.norWorkarounds;
    }while(0);

    return errl;

    #undef FUNC
}

//------------------------------------------------------------------------------

/* Helper struct for chip information inserted into HOMER data section after the
 * header. There is basically an array of these after the initial HOMER section
 * (HOMER_Data_t).  The register info then follows.
 */
typedef struct __attribute__((packed))
{
    HOMER_Chip_t  hChipType;  /* Nimbus, Axone, EC Level, etc...*/

    union
    {
        HOMER_ChipNimbus_t   hChipN;
        HOMER_ChipAxone_t    hChipA;
    };

} HOMER_ChipInfo_t;

//------------------------------------------------------------------------------

void __initChipInfo( TargetHandle_t i_chip, HOMER_ChipType_t i_chipModel,
                     uint32_t i_maxChipsPerNode, HOMER_ChipInfo_t & o_chipInfo )
{
    // Determine the chip position.
    uint32_t chipPos = getTargetPosition( i_chip );
    PRDF_ASSERT( chipPos < i_maxChipsPerNode );

    // Fill in the HOMER chip info.
    o_chipInfo.hChipType             = HOMER_getChip( i_chipModel );
    o_chipInfo.hChipType.chipPos     = chipPos;
    o_chipInfo.hChipType.chipEcLevel = i_chip->getAttr<ATTR_EC>();

    if( HOMER_CHIP_EXPLORER == i_chipModel )
    {
        //@todo - RTC:201781 - Add i2c information
    }
    else
    {
        // Get the chip FSI address.
        FSI::FsiLinkInfo_t fsiInfo;
        FSI::getFsiLinkInfo( i_chip, fsiInfo );
        o_chipInfo.hChipType.fsiBaseAddr = fsiInfo.baseAddr;
    }
}

// Returns a right justified config mask of the unit
uint32_t __getUnitMask( TargetHandle_t i_chip, TARGETING::TYPE i_unitType,
                        const HwInitialized_t i_curHw )
{
    #define FUNC "[PRDF::__getUnitMask] "

    uint32_t o_mask = 0;

    uint32_t maxPos = 0; // default invalid

    if ( TYPE_PROC == getTargetType(i_chip) )
    {
        switch ( i_unitType )
        {
            case TYPE_CAPP:   maxPos = TrgtPos_t::MAX_CAPP_PER_PROC;   break;
            case TYPE_XBUS:   maxPos = TrgtPos_t::MAX_XBUS_PER_PROC;   break;
            case TYPE_OBUS:   maxPos = TrgtPos_t::MAX_OBUS_PER_PROC;   break;
            case TYPE_PEC:    maxPos = TrgtPos_t::MAX_PEC_PER_PROC;    break;
            case TYPE_PHB:    maxPos = TrgtPos_t::MAX_PHB_PER_PROC;    break;
            case TYPE_EQ:     maxPos = TrgtPos_t::MAX_EQ_PER_PROC;     break;
            case TYPE_EX:     maxPos = TrgtPos_t::MAX_EX_PER_PROC;     break;
            case TYPE_CORE:   maxPos = TrgtPos_t::MAX_EC_PER_PROC;     break;
            case TYPE_MCBIST: maxPos = TrgtPos_t::MAX_MCBIST_PER_PROC; break;
            case TYPE_MCS:    maxPos = TrgtPos_t::MAX_MCS_PER_PROC;    break;
            case TYPE_MCA:    maxPos = TrgtPos_t::MAX_MCA_PER_PROC;    break;
            case TYPE_MC:     maxPos = TrgtPos_t::MAX_MC_PER_PROC;     break;
            case TYPE_MI:     maxPos = TrgtPos_t::MAX_MI_PER_PROC;     break;
            case TYPE_MCC:    maxPos = TrgtPos_t::MAX_MCC_PER_PROC;    break;
            case TYPE_OMIC:   maxPos = TrgtPos_t::MAX_OMIC_PER_PROC;   break;
            case TYPE_NPU:    maxPos = TrgtPos_t::MAX_NPU_PER_PROC;    break;
            default: ;
        }
    }

    // If maxPos is still zero, then this function was passed invalid parameters
    if ( 0 == maxPos )
    {
        PRDF_ERR( FUNC "Unsupported chip 0x%08x or unit type %u",
                  getHuid(i_chip), i_unitType );
        PRDF_ASSERT( false );
    }

    // Get the unit list for this chip.
    TargetHandleList unitList = getConnected( i_chip, i_unitType );

    // Initially this variable will be null. It will only be set to a non-null
    // value if the hardware config indicates we only want the master core.
    ConstTargetHandle_t masterCore = nullptr;

    // Special handling for specific configs.
    switch ( i_unitType )
    {
        case TYPE_CORE:
            if ( MASTER_PROC_CORE         == i_curHw ||
                 ALL_PROC_MASTER_CORE     == i_curHw ||
                 ALL_PROC_MEM_MASTER_CORE == i_curHw )
            {
                #ifndef __HOSTBOOT_RUNTIME // only supported during IPL
                masterCore = TARGETING::getMasterCore();
                #endif
                PRDF_ASSERT( nullptr != masterCore );
            }
            break;

        case TYPE_MCBIST:
        case TYPE_MCS:
        case TYPE_MCA:
        case TYPE_MC:
        case TYPE_MI:
        case TYPE_MCC:
        case TYPE_OMIC:
            if ( ALL_PROC_MEM_MASTER_CORE != i_curHw &&
                 ALL_HARDWARE             != i_curHw    )
            {
                // Clear out the list because we don't want any memory units.
                unitList.clear();
            }
            break;

        default: ;
    }

    // Get the config mask for all units of this type.
    for ( auto & unit : unitList )
    {
        // Special handling for master-core-only configs.
        if ( nullptr != masterCore && unit != masterCore )
        {
            // At this point, we only want the master core, but this is not it.
            // So continue onto the next target.
            continue;
        }

        uint32_t chipPos = getTargetPosition( unit );
        PRDF_ASSERT( chipPos < maxPos );

        o_mask |= (1 << (maxPos - chipPos - 1));
    }

    return o_mask;

    #undef FUNC
}

//------------------------------------------------------------------------------

errlHndl_t getHwConfig( std::vector<HOMER_ChipInfo_t> & o_chipInfVector,
                        const HwInitialized_t i_curHw )
{
    #define FUNC "[PRDF::getHwConfig] "

    errlHndl_t errl = nullptr;

    o_chipInfVector.clear();

    do
    {
        // Get the master PROC. This is used in several locations.
        TargetHandle_t masterProc = PlatServices::getMasterProc();
        PRDF_ASSERT( nullptr != masterProc );

        // Get the complete PROC list.
        TargetHandleList procList;
        if ( MASTER_PROC_CORE == i_curHw )
        {
            // Get just the master PROC.
            procList.push_back( masterProc );
        }
        else
        {
            // Get all configured PROCs.
            procList = getFunctionalTargetList( TYPE_PROC );
        }

        // Iterate the list of functional PROCs.
        for ( auto & proc : procList )
        {
            // Get the PROC model type.
            HOMER_ChipType_t procModelType = HOMER_CHIP_INVALID;
            switch ( getChipModel(proc) )
            {
                case MODEL_NIMBUS: procModelType = HOMER_CHIP_NIMBUS; break;
                case MODEL_AXONE:  procModelType = HOMER_CHIP_AXONE;  break;
                default:
                    PRDF_ERR( FUNC "Unsupported chip model %d on 0x%08x",
                              procModelType, getHuid(proc) );
                    PRDF_ASSERT( false );
            }

            // Init the chip info.
            HOMER_ChipInfo_t ci;
            __initChipInfo( proc, procModelType, MAX_PROC_PER_NODE, ci );

            // Set the chip specific data.
            if ( HOMER_CHIP_NIMBUS == procModelType )
            {
                // Init the chiplet masks
                ci.hChipN = HOMER_initChipNimbus();

                // Check for master processor
                ci.hChipN.isMaster = (proc == masterProc) ? 1 : 0;

                // Set all of the unit masks.
                ci.hChipN.cappMask   = __getUnitMask(proc, TYPE_CAPP,  i_curHw);
                ci.hChipN.xbusMask   = __getUnitMask(proc, TYPE_XBUS,  i_curHw);
                ci.hChipN.obusMask   = __getUnitMask(proc, TYPE_OBUS,  i_curHw);
                ci.hChipN.pecMask    = __getUnitMask(proc, TYPE_PEC,   i_curHw);
                ci.hChipN.phbMask    = __getUnitMask(proc, TYPE_PHB,   i_curHw);
                ci.hChipN.eqMask     = __getUnitMask(proc, TYPE_EQ,    i_curHw);
                ci.hChipN.exMask     = __getUnitMask(proc, TYPE_EX,    i_curHw);
                ci.hChipN.ecMask     = __getUnitMask(proc, TYPE_CORE,  i_curHw);
                ci.hChipN.mcbistMask = __getUnitMask(proc, TYPE_MCBIST,i_curHw);
                ci.hChipN.mcsMask    = __getUnitMask(proc, TYPE_MCS,   i_curHw);
                ci.hChipN.mcaMask    = __getUnitMask(proc, TYPE_MCA,   i_curHw);
            }
            else if ( HOMER_CHIP_AXONE == procModelType )
            {
                // Init the chiplet masks
                ci.hChipA = HOMER_initChipAxone();

                // Check for master processor
                ci.hChipA.isMaster = (proc == masterProc) ? 1 : 0;

                // Set all of the unit masks.
                ci.hChipA.cappMask = __getUnitMask(proc, TYPE_CAPP, i_curHw);
                ci.hChipA.xbusMask = __getUnitMask(proc, TYPE_XBUS, i_curHw);
                ci.hChipA.obusMask = __getUnitMask(proc, TYPE_OBUS, i_curHw);
                ci.hChipA.pecMask  = __getUnitMask(proc, TYPE_PEC,  i_curHw);
                ci.hChipA.phbMask  = __getUnitMask(proc, TYPE_PHB,  i_curHw);
                ci.hChipA.eqMask   = __getUnitMask(proc, TYPE_EQ,   i_curHw);
                ci.hChipA.exMask   = __getUnitMask(proc, TYPE_EX,   i_curHw);
                ci.hChipA.ecMask   = __getUnitMask(proc, TYPE_CORE, i_curHw);
                ci.hChipA.npuMask  = __getUnitMask(proc, TYPE_NPU,  i_curHw);
                ci.hChipA.mcMask   = __getUnitMask(proc, TYPE_MC,   i_curHw);
                ci.hChipA.miMask   = __getUnitMask(proc, TYPE_MI,   i_curHw);
                ci.hChipA.mccMask  = __getUnitMask(proc, TYPE_MCC,  i_curHw);
                ci.hChipA.omicMask = __getUnitMask(proc, TYPE_OMIC, i_curHw);
            }

            // Save the chip info we collected.
            o_chipInfVector.push_back( ci );
        }

        // Only continue with the memory subsystem if the config allows.
        if ( ALL_PROC_MEM_MASTER_CORE != i_curHw && ALL_HARDWARE != i_curHw )
            break;

        // Iterate all of the OCMB chips.
        for ( auto & ocmb : getFunctionalTargetList(TYPE_OCMB_CHIP) )
        {
            // Get the OCMB chip type.
            HOMER_ChipType_t ocmbType = HOMER_CHIP_INVALID;
            switch ( getChipId(ocmb) )
            {
                case POWER_CHIPID::GEMINI_16:
                    // Skip Gemini OCMBs. They can exist, but PRD won't support
                    // them (set invalid).
                    ocmbType = HOMER_CHIP_INVALID; break;
                case POWER_CHIPID::EXPLORER_16:
                    ocmbType = HOMER_CHIP_EXPLORER; break;
                default:
                    PRDF_ERR( FUNC "Unsupported chip ID 0x%08x on 0x%08x",
                              getChipId(ocmb), getHuid(ocmb) );
                    PRDF_ASSERT( false );
            }
            if ( HOMER_CHIP_INVALID == ocmbType ) continue;

            // Init the chip info.
            HOMER_ChipInfo_t ci;
            __initChipInfo( ocmb, ocmbType, MAX_OCMB_PER_NODE, ci );

            // NOTE: Explorer does not have any unit data.

            // Save the chip info we collected.
            o_chipInfVector.push_back( ci );
        }

    } while (0);

    return errl;

    #undef FUNC
}

//------------------------------------------------------------------------------

/***************************************************/
/* Define EC level dependent registers here        */
/*   chipType         Target     RegType  EC level */
/*     Unused  - scomAddress                       */
/***************************************************/
static HOMER_ChipSpecAddr_t  s_ecDepProcRegisters[]
{
    /* EXAMPLE:
    { HOMER_CHIP_NIMBUS, TRGT_PROC, REG_FIR, 0x10, 0, 0x05011400ll }, // DD1
    { HOMER_CHIP_NIMBUS, TRGT_PROC, REG_FIR, 0x20, 0, 0x05013C00ll }, // DD2
    */
};

//------------------------------------------------------------------------------
errlHndl_t  homerVerifySizeFits( const size_t i_maxSize,
                                 const size_t i_currentSize )
{
    errlHndl_t  l_errl = NULL;


    // Verify we haven't exceeded max size
    if ( i_currentSize > i_maxSize )
    {
        PRDF_ERR( "HOMER SIZE issue: curDataSize %d is greater than max "
                 "HOMER data %d", i_currentSize, i_maxSize );
        /*@
         * @errortype
         * @reasoncode PRDF_INVALID_CONFIG
         * @severity   ERRL_SEV_UNRECOVERABLE
         * @moduleid   PRDF_CS_FIRDATA_WRITE
         * @userdata1  Size needed
         * @userdata2  Size available
         * @devdesc    Invalid configuration in CS FIR Data handling.
         */
        l_errl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                          PRDF_CS_FIRDATA_WRITE,
                                          PRDF_INVALID_CONFIG,
                                          i_currentSize,
                                          i_maxSize );
    } // end if too big of size

    return(l_errl);

} // end routine  homerVerifySizeFits

//------------------------------------------------------------------------------

errlHndl_t writeData( uint8_t * i_hBuf, size_t i_hBufSize,
                      const HwInitialized_t i_curHw,
                      std::vector<HOMER_ChipInfo_t> &i_chipVector,
                      HOMER_Data_t  &io_homerData )
{
    #define FUNC "[PRDF::writeData] "

    errlHndl_t errl = NULL;
    TrgtMap_t  l_targMap;

    const size_t u32 = sizeof(uint32_t);
    const size_t u64 = sizeof(uint64_t);

    do
    {
        size_t sz_hBuf = 0;

        // Grab size of all the registers being collected
        size_t sz_data = sizeof(io_homerData);
        sz_hBuf += sz_data;

        // The HOMER_Data_t struct may have an uneven size. Add some padding to
        // ensure the subsequent HOMER_Chip_t structs are word aligned. */
        const size_t padding = (u32 - (sizeof(HOMER_Data_t) % u32)) % u32;
        sz_hBuf += padding;

        // Add register counts to the data.
        // initialize SCOM addresses for all targets & regs
        getAddresses(l_targMap);

        // loop thru targets to get register counts
        for ( auto & t : l_targMap )
        {
            // loop thru register types
            for ( auto & r : t.second )
            {
                // Want all proc chiplets but only include
                // memory when asked for
                if ( (ALL_PROC_MEM_MASTER_CORE == i_curHw) ||
                     (ALL_HARDWARE == i_curHw)             ||
                     ( (TRGT_MCBIST != t.first) &&
                       (TRGT_MCS    != t.first) &&
                       (TRGT_MCA    != t.first) &&
                       (TRGT_MC     != t.first) &&
                       (TRGT_MI     != t.first) &&
                       (TRGT_MCC    != t.first) &&
                       (TRGT_OMIC   != t.first)
                     )
                   )
                {
                    // save the number of regs for target/regType
                    io_homerData.regCounts[t.first][r.first] = r.second.size();
                } // end if need this target included

            } // end for on regTypes

        } // end for on Targets


        // Setup EC level dependent register counts
        // (currently just proc has some)
        io_homerData.ecDepCounts =
                    sizeof(s_ecDepProcRegisters) / sizeof(HOMER_ChipSpecAddr_t);

        // Add everything to the buffer.
        uint32_t idx = 0;

        // Fill in the header & number of chips
        io_homerData.header = HOMER_FIR2;
        io_homerData.chipCount = i_chipVector.size();
        // Fill the input buffer with chipcount, regcount, pnor info
        memcpy( &i_hBuf[idx], &io_homerData,  sz_data   ); idx += sz_data;

        // Add the padding at the end of the HOMER_Data_t struct.
        idx += padding;

        // We want a list of chips next
        if (0 != io_homerData.chipCount)
        {
            // Roll thru the chips we have
            std::vector<HOMER_ChipInfo_t>::iterator  l_chipItr;
            uint32_t  l_chipTypeSize = sizeof(HOMER_Chip_t);

            for ( l_chipItr = i_chipVector.begin();
                  (l_chipItr < i_chipVector.end());
                  l_chipItr++ )
            {
                // Ensure we won't copy beyond space allowed
                sz_hBuf += l_chipTypeSize;
                errl = homerVerifySizeFits(i_hBufSize, sz_hBuf);
                if (NULL != errl) { break; }

                // place the CHIP information
                memcpy( &i_hBuf[idx], &(l_chipItr->hChipType),
                        l_chipTypeSize ); idx += l_chipTypeSize;

                // Place the configured chiplet information.
                if ( HOMER_CHIP_NIMBUS == l_chipItr->hChipType.chipType )
                {
                    // Ensure we won't copy beyond space allowed
                    sz_hBuf += sizeof(HOMER_ChipNimbus_t);
                    errl = homerVerifySizeFits(i_hBufSize, sz_hBuf);
                    if (NULL != errl) { break; }

                    memcpy( &i_hBuf[idx], &(l_chipItr->hChipN),
                            sizeof(HOMER_ChipNimbus_t) );

                    idx += sizeof(HOMER_ChipNimbus_t);
                }
                else if ( HOMER_CHIP_AXONE == l_chipItr->hChipType.chipType )
                {
                    // Ensure we won't copy beyond space allowed
                    sz_hBuf += sizeof(HOMER_ChipAxone_t);
                    errl = homerVerifySizeFits(i_hBufSize, sz_hBuf);
                    if (NULL != errl) { break; }

                    memcpy( &i_hBuf[idx], &(l_chipItr->hChipA),
                            sizeof(HOMER_ChipAxone_t) );

                    idx += sizeof(HOMER_ChipAxone_t);
                }
                else if ( HOMER_CHIP_EXPLORER == l_chipItr->hChipType.chipType )
                {
                    // NOTE: Explorer does not have any unit data.
                }

            } // end for loop on chip vector

            // ensure size is ok before any other copy
            if (NULL != errl) { break; }

            // Verify registers will fit before copying them
            uint32_t  l_reg32Count = 0;
            uint32_t  l_reg64Count = 0;

            // Count number of 32 bit addresses first
            for ( uint32_t  l_regIdx = REG_FIRST;
                   (l_regIdx < REG_IDFIR); l_regIdx++ )
            {
                for ( uint32_t l_tgtIndex = TRGT_FIRST;
                       (l_tgtIndex < TRGT_MAX); l_tgtIndex++ )
                {
                    l_reg32Count +=io_homerData.regCounts[l_tgtIndex][l_regIdx];
                } // end for on target index
            } // end for on register index


            // Count number of 64 bit addresses now
            for ( uint32_t  l_regIdx = REG_IDFIR;
                   (l_regIdx < REG_MAX); l_regIdx++ )
            {
                for ( uint32_t l_tgtIndex = TRGT_FIRST;
                       (l_tgtIndex < TRGT_MAX); l_tgtIndex++ )
                {
                    l_reg64Count +=io_homerData.regCounts[l_tgtIndex][l_regIdx];
                } // end for on target index
            } // end for on register index

            // Calculate additional size we need from the counts.
            // We have 32 bit addrs, 64 bit addrs, then EC level structures.
            sz_hBuf +=(l_reg32Count             * sizeof(uint32_t)) +
                      (l_reg64Count             * sizeof(uint64_t)) +
                      (io_homerData.ecDepCounts * sizeof(HOMER_ChipSpecAddr_t));

            // ensure we fit in HOMER before doing register copies
            errl = homerVerifySizeFits(i_hBufSize, sz_hBuf);
            if (NULL != errl) { break; }

            // loop thru targets
            for ( auto & t : l_targMap )
            {
                if ( (ALL_PROC_MEM_MASTER_CORE == i_curHw) ||
                     (ALL_HARDWARE == i_curHw)             ||
                     ( (TRGT_MCBIST != t.first) &&
                       (TRGT_MCS    != t.first) &&
                       (TRGT_MCA    != t.first) &&
                       (TRGT_MC     != t.first) &&
                       (TRGT_MI     != t.first) &&
                       (TRGT_MCC    != t.first) &&
                       (TRGT_OMIC   != t.first)
                     )
                   )
                {
                    // loop thru register types
                    for ( auto & r : t.second )
                    {
                        // loop thru SCOM addresses for reg type
                        for ( auto &  rAddr : r.second )
                        {
                            if ( (REG_IDFIR == r.first) ||
                                 (REG_IDREG == r.first)
                               )
                            {
                                memcpy( &i_hBuf[idx],
                                        &rAddr,
                                        u64 );

                                idx += u64;
                            }
                            else
                            {
                                uint32_t  tempAddr = (uint32_t)rAddr;
                                memcpy( &i_hBuf[idx],
                                        &tempAddr,
                                        u32 );

                                idx += u32;
                            }

                        } // end for on register addresses

                    } // end for on regs

                } // end if we need this target

            } // end for on targets

            // Add EC Level dependencies at the end
            uint8_t  *l_ecDepSourceRegs = (uint8_t *)(s_ecDepProcRegisters);
            memcpy( &i_hBuf[idx], l_ecDepSourceRegs,
                                  sizeof(s_ecDepProcRegisters) );

        } // end if chipCount non-zero


    } while(0);

    return errl;

    #undef FUNC
}

//------------------------------------------------------------------------------

errlHndl_t writeHomerFirData( uint8_t * i_hBuf, size_t i_hBufSize,
                              const HwInitialized_t i_curHw )
{
    #define FUNC "[PRDF::writeHomerFirData] "

    errlHndl_t errl = NULL;

    do
    {
        // FIRDATA not supported on Cumulus based systems. So do nothing.
        if ( MODEL_CUMULUS == getChipModel(getMasterProc()) ) break;

        HOMER_Data_t  l_homerData = HOMER_getData(); // Initializes data

        // Set flag indicating if IPL or runtime situation.
        l_homerData.iplState = (ALL_HARDWARE == i_curHw)
                          ? FIRDATA_STATE_RUNTIME : FIRDATA_STATE_IPL;

        // Get the PNOR information
        errl = getPnorInfo( l_homerData );
        if ( NULL != errl )
        {
            PRDF_ERR( FUNC "getPnorInfo() failed" );
            break;
        }

        // Hardware present gets pushed into this vector
        // (one element per chip)
        std::vector<HOMER_ChipInfo_t> l_chipInfVector;

        // Get the hardware configuration
        errl = getHwConfig( l_chipInfVector, i_curHw );
        if ( NULL != errl )
        {
            PRDF_ERR( FUNC "getHwConfig() failed" );
            break;
        }

        // Write the HOMER data
        errl = writeData( i_hBuf, i_hBufSize, i_curHw,
                          l_chipInfVector, l_homerData );

        if ( NULL != errl )
        {
            PRDF_ERR( FUNC "writeData() failed" );
            break;
        }

    } while (0);

    if ( NULL != errl )
    {
        errl->collectTrace( PRDF_COMP_NAME, 512 );
    }

    return errl;

    #undef FUNC

}

}; // end namespace PRDF
OpenPOWER on IntegriCloud