summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xsrc/Makefile90
-rwxr-xr-xsrc/lib/Makefile79
-rwxr-xr-xsrc/lib/assert.c47
-rwxr-xr-xsrc/lib/ctype.c22
-rwxr-xr-xsrc/lib/ctype.h125
-rw-r--r--src/lib/ctype_table.c278
-rwxr-xr-xsrc/lib/errno.h25
-rwxr-xr-xsrc/lib/fgetc.c88
-rwxr-xr-xsrc/lib/gpe.h78
-rwxr-xr-xsrc/lib/gpe_control.h171
-rwxr-xr-xsrc/lib/gpe_control.pS160
-rwxr-xr-xsrc/lib/gpe_data.h672
-rwxr-xr-xsrc/lib/gpe_data.pS1585
-rwxr-xr-xsrc/lib/gpe_pba.c148
-rw-r--r--src/lib/gpe_pba.h116
-rwxr-xr-xsrc/lib/gpe_pba_pgas.pS110
-rw-r--r--src/lib/gpe_scom.h471
-rw-r--r--src/lib/gpe_scom.pS709
-rwxr-xr-xsrc/lib/gpsm.c600
-rwxr-xr-xsrc/lib/gpsm.h191
-rwxr-xr-xsrc/lib/gpsm_dcm.c753
-rwxr-xr-xsrc/lib/gpsm_dcm.h192
-rwxr-xr-xsrc/lib/gpsm_dcm_fast_handler.S147
-rwxr-xr-xsrc/lib/gpsm_init.c1638
-rwxr-xr-xsrc/lib/heartbeat.c328
-rwxr-xr-xsrc/lib/heartbeat.h46
-rwxr-xr-xsrc/lib/libfiles.mk57
-rwxr-xr-xsrc/lib/libgpefiles.mk30
-rwxr-xr-xsrc/lib/libssx.h20
-rwxr-xr-xsrc/lib/memcpy.c78
-rwxr-xr-xsrc/lib/memset.c118
-rwxr-xr-xsrc/lib/pgas.h1153
-rwxr-xr-xsrc/lib/pgas_ppc.h529
-rwxr-xr-xsrc/lib/pgp_config.h108
-rwxr-xr-xsrc/lib/pmc_dcm.c425
-rwxr-xr-xsrc/lib/pmc_dcm.h102
-rw-r--r--src/lib/polling.c73
-rw-r--r--src/lib/polling.h94
-rwxr-xr-xsrc/lib/pore_hooks.h171
-rwxr-xr-xsrc/lib/printf.c679
-rwxr-xr-xsrc/lib/pstates.c410
-rwxr-xr-xsrc/lib/pstates.h601
-rwxr-xr-xsrc/lib/puts.c95
-rwxr-xr-xsrc/lib/simics_stdio.c150
-rwxr-xr-xsrc/lib/simics_stdio.h69
-rwxr-xr-xsrc/lib/simics_stdio_addresses.h67
-rw-r--r--src/lib/special_wakeup.c149
-rw-r--r--src/lib/special_wakeup.h32
-rwxr-xr-xsrc/lib/sprintf.c112
-rw-r--r--src/lib/ssx_dump.c209
-rw-r--r--src/lib/ssx_dump.h58
-rwxr-xr-xsrc/lib/ssx_io.c311
-rwxr-xr-xsrc/lib/ssx_io.h204
-rwxr-xr-xsrc/lib/stdlib.c91
-rw-r--r--src/lib/strcasecmp.c66
-rwxr-xr-xsrc/lib/strdup.c39
-rwxr-xr-xsrc/lib/string.c168
-rwxr-xr-xsrc/lib/string.h64
-rwxr-xr-xsrc/lib/string_stream.c386
-rwxr-xr-xsrc/lib/string_stream.h253
-rwxr-xr-xsrc/lib/strtox.c593
-rwxr-xr-xsrc/lib/strtox.h127
-rwxr-xr-xsrc/lib/time.c58
-rwxr-xr-xsrc/lib/vrm.c394
-rwxr-xr-xsrc/lib/vrm.h59
-rwxr-xr-xsrc/occ/Makefile104
-rwxr-xr-xsrc/occ/amec/amec_amester.c1502
-rwxr-xr-xsrc/occ/amec/amec_amester.h398
-rwxr-xr-xsrc/occ/amec/amec_analytics.c624
-rwxr-xr-xsrc/occ/amec/amec_analytics.h34
-rw-r--r--src/occ/amec/amec_controller.c444
-rw-r--r--src/occ/amec/amec_controller.h135
-rwxr-xr-xsrc/occ/amec/amec_data.c507
-rwxr-xr-xsrc/occ/amec/amec_data.h81
-rwxr-xr-xsrc/occ/amec/amec_dps.c371
-rwxr-xr-xsrc/occ/amec/amec_dps.h117
-rwxr-xr-xsrc/occ/amec/amec_external.h66
-rwxr-xr-xsrc/occ/amec/amec_freq.c1092
-rwxr-xr-xsrc/occ/amec/amec_freq.h186
-rwxr-xr-xsrc/occ/amec/amec_health.c1037
-rwxr-xr-xsrc/occ/amec/amec_health.h47
-rwxr-xr-xsrc/occ/amec/amec_init.c426
-rwxr-xr-xsrc/occ/amec/amec_master_smh.c1114
-rwxr-xr-xsrc/occ/amec/amec_master_smh.h169
-rwxr-xr-xsrc/occ/amec/amec_oversub.c272
-rwxr-xr-xsrc/occ/amec/amec_oversub.h139
-rwxr-xr-xsrc/occ/amec/amec_parm.c302
-rwxr-xr-xsrc/occ/amec/amec_parm.h202
-rwxr-xr-xsrc/occ/amec/amec_parm_table.c160
-rwxr-xr-xsrc/occ/amec/amec_part.c475
-rwxr-xr-xsrc/occ/amec/amec_part.h177
-rwxr-xr-xsrc/occ/amec/amec_pcap.c572
-rwxr-xr-xsrc/occ/amec/amec_pcap.h73
-rwxr-xr-xsrc/occ/amec/amec_perfcount.c134
-rwxr-xr-xsrc/occ/amec/amec_perfcount.h90
-rw-r--r--src/occ/amec/amec_sensors_centaur.c703
-rw-r--r--src/occ/amec/amec_sensors_centaur.h31
-rwxr-xr-xsrc/occ/amec/amec_sensors_core.c886
-rwxr-xr-xsrc/occ/amec/amec_sensors_core.h55
-rwxr-xr-xsrc/occ/amec/amec_sensors_fw.c221
-rwxr-xr-xsrc/occ/amec/amec_sensors_fw.h46
-rwxr-xr-xsrc/occ/amec/amec_sensors_power.c574
-rwxr-xr-xsrc/occ/amec/amec_sensors_power.h48
-rwxr-xr-xsrc/occ/amec/amec_service_codes.h77
-rwxr-xr-xsrc/occ/amec/amec_slave_smh.c669
-rwxr-xr-xsrc/occ/amec/amec_slave_smh.h110
-rwxr-xr-xsrc/occ/amec/amec_smh.h103
-rwxr-xr-xsrc/occ/amec/amec_sys.h742
-rwxr-xr-xsrc/occ/amec/amec_tasks.c297
-rwxr-xr-xsrc/occ/aplt/aplt_service_codes.h70
-rwxr-xr-xsrc/occ/aplt/appletManager.c1371
-rwxr-xr-xsrc/occ/aplt/appletManager.h127
-rwxr-xr-xsrc/occ/aplt/incl/appletId.h73
-rwxr-xr-xsrc/occ/aplt/incl/cmdhDbugCmd.h78
-rwxr-xr-xsrc/occ/aplt/incl/sensorQueryList.h73
-rwxr-xr-xsrc/occ/app.mk257
-rwxr-xr-xsrc/occ/arl_test.c234
-rwxr-xr-xsrc/occ/arl_test_data.h115
-rwxr-xr-xsrc/occ/cent/centaur_control.c698
-rwxr-xr-xsrc/occ/cent/centaur_control.h100
-rwxr-xr-xsrc/occ/cent/centaur_data.c1194
-rwxr-xr-xsrc/occ/cent/centaur_data.h180
-rwxr-xr-xsrc/occ/cent/centaur_data_service_codes.h64
-rwxr-xr-xsrc/occ/cfiles.mk107
-rwxr-xr-xsrc/occ/cmdh/cmdh_fsp.c1421
-rwxr-xr-xsrc/occ/cmdh/cmdh_fsp.h516
-rwxr-xr-xsrc/occ/cmdh/cmdh_fsp_cmds.c1841
-rwxr-xr-xsrc/occ/cmdh/cmdh_fsp_cmds.h725
-rwxr-xr-xsrc/occ/cmdh/cmdh_fsp_cmds_datacnfg.c2452
-rwxr-xr-xsrc/occ/cmdh/cmdh_fsp_cmds_datacnfg.h550
-rwxr-xr-xsrc/occ/cmdh/cmdh_mnfg_intf.c814
-rwxr-xr-xsrc/occ/cmdh/cmdh_mnfg_intf.h236
-rwxr-xr-xsrc/occ/cmdh/cmdh_service_codes.h55
-rwxr-xr-xsrc/occ/cmdh/cmdh_snapshot.c542
-rwxr-xr-xsrc/occ/cmdh/cmdh_snapshot.h143
-rw-r--r--src/occ/cmdh/cmdh_thread.c166
-rwxr-xr-xsrc/occ/cmdh/cmdh_tunable_parms.c293
-rwxr-xr-xsrc/occ/cmdh/cmdh_tunable_parms.h107
-rwxr-xr-xsrc/occ/cmdh/ffdc.c145
-rwxr-xr-xsrc/occ/cmdh/ffdc.h50
-rw-r--r--src/occ/cmdh/ll_ffdc.S959
-rwxr-xr-xsrc/occ/common.c77
-rwxr-xr-xsrc/occ/dcom/dcom.c902
-rwxr-xr-xsrc/occ/dcom/dcom.h585
-rw-r--r--src/occ/dcom/dcomMasterRx.c430
-rwxr-xr-xsrc/occ/dcom/dcomMasterTx.c628
-rw-r--r--src/occ/dcom/dcomSlaveRx.c671
-rwxr-xr-xsrc/occ/dcom/dcomSlaveTx.c431
-rwxr-xr-xsrc/occ/dcom/dcom_service_codes.h73
-rwxr-xr-xsrc/occ/dcom/dcom_thread.c223
-rwxr-xr-xsrc/occ/debug_trace.mk76
-rwxr-xr-xsrc/occ/debug_trace_ode.mk76
-rwxr-xr-xsrc/occ/doc/Doxyfile1252
-rwxr-xr-xsrc/occ/errl/errl.c984
-rwxr-xr-xsrc/occ/errl/errl.h404
-rwxr-xr-xsrc/occ/errl/test/Makefile55
-rwxr-xr-xsrc/occ/errl/test/app.mk99
-rwxr-xr-xsrc/occ/errl/test/errltest.c786
-rwxr-xr-xsrc/occ/errl/test/gpefiles.mk24
-rwxr-xr-xsrc/occ/errl/test/parser.c292
-rwxr-xr-xsrc/occ/errl/test/test.mk28
-rw-r--r--src/occ/gcov.h110
-rwxr-xr-xsrc/occ/gpe/apss_altitude.pS163
-rwxr-xr-xsrc/occ/gpe/apss_composite.pS169
-rwxr-xr-xsrc/occ/gpe/apss_constants.h68
-rwxr-xr-xsrc/occ/gpe/apss_init.pS230
-rwxr-xr-xsrc/occ/gpe/apss_meas_read_complete.pS143
-rwxr-xr-xsrc/occ/gpe/apss_meas_read_cont.pS161
-rwxr-xr-xsrc/occ/gpe/apss_meas_read_start.pS144
-rwxr-xr-xsrc/occ/gpe/gpe_export.h67
-rwxr-xr-xsrc/occ/gpe/gpe_macros.h178
-rwxr-xr-xsrc/occ/gpe/pore_nop.pS41
-rwxr-xr-xsrc/occ/gpe/pore_test.pS74
-rwxr-xr-xsrc/occ/gpe/pore_test_error.pS246
-rwxr-xr-xsrc/occ/gpe/pore_test_pss.pS444
-rwxr-xr-xsrc/occ/gpe/pss_constants.h71
-rwxr-xr-xsrc/occ/gpe/pss_macros.h192
-rwxr-xr-xsrc/occ/gpefiles.mk33
-rwxr-xr-xsrc/occ/homer.c158
-rwxr-xr-xsrc/occ/homer.h105
-rwxr-xr-xsrc/occ/incl/common_types.h225
-rwxr-xr-xsrc/occ/incl/comp_ids.h126
-rwxr-xr-xsrc/occ/incl/occ_common.h354
-rwxr-xr-xsrc/occ/linkocc.cmd570
-rwxr-xr-xsrc/occ/main.c1180
-rwxr-xr-xsrc/occ/mode.c489
-rwxr-xr-xsrc/occ/mode.h133
-rw-r--r--src/occ/occLinkInputFile1
-rwxr-xr-xsrc/occ/occ_service_codes.h303
-rwxr-xr-xsrc/occ/occ_sys_config.c516
-rwxr-xr-xsrc/occ/occ_sys_config.h458
-rwxr-xr-xsrc/occ/occbuildname.c1
-rwxr-xr-xsrc/occ/proc/proc_data.c925
-rwxr-xr-xsrc/occ/proc/proc_data.h255
-rwxr-xr-xsrc/occ/proc/proc_data_control.c312
-rwxr-xr-xsrc/occ/proc/proc_data_control.h54
-rwxr-xr-xsrc/occ/proc/proc_data_service_codes.h70
-rwxr-xr-xsrc/occ/proc/proc_pstate.c1171
-rwxr-xr-xsrc/occ/proc/proc_pstate.h159
-rwxr-xr-xsrc/occ/proc/test/Makefile85
-rwxr-xr-xsrc/occ/proc/test/app.mk103
-rwxr-xr-xsrc/occ/proc/test/main.c451
-rwxr-xr-xsrc/occ/pss/apss.c911
-rwxr-xr-xsrc/occ/pss/apss.h181
-rwxr-xr-xsrc/occ/pss/dpss.c233
-rwxr-xr-xsrc/occ/pss/dpss.h68
-rwxr-xr-xsrc/occ/pss/pss_service_codes.h74
-rwxr-xr-xsrc/occ/pss/test/Makefile76
-rwxr-xr-xsrc/occ/pss/test/app.mk128
-rwxr-xr-xsrc/occ/pss/test/apsstest.c478
-rwxr-xr-xsrc/occ/reset.c234
-rwxr-xr-xsrc/occ/rtls/rtls.c574
-rwxr-xr-xsrc/occ/rtls/rtls.h214
-rwxr-xr-xsrc/occ/rtls/rtls_service_codes.h66
-rwxr-xr-xsrc/occ/rtls/rtls_tables.c370
-rwxr-xr-xsrc/occ/rtls/test/Makefile65
-rwxr-xr-xsrc/occ/rtls/test/app.mk101
-rwxr-xr-xsrc/occ/rtls/test/main.c730
-rwxr-xr-xsrc/occ/rtls/test/rtls_tables.c199
-rw-r--r--src/occ/scom.c239
-rw-r--r--src/occ/scom.h64
-rwxr-xr-xsrc/occ/sensor/sensor.c626
-rwxr-xr-xsrc/occ/sensor/sensor.h282
-rwxr-xr-xsrc/occ/sensor/sensor_enum.h631
-rwxr-xr-xsrc/occ/sensor/sensor_info.c336
-rwxr-xr-xsrc/occ/sensor/sensor_service_codes.h63
-rwxr-xr-xsrc/occ/sensor/sensor_table.c530
-rwxr-xr-xsrc/occ/ssx_app_cfg.h103
-rwxr-xr-xsrc/occ/state.c810
-rwxr-xr-xsrc/occ/state.h234
-rwxr-xr-xsrc/occ/thread/chom.c511
-rwxr-xr-xsrc/occ/thread/chom.h249
-rwxr-xr-xsrc/occ/thread/test/Makefile60
-rwxr-xr-xsrc/occ/thread/test/app.mk101
-rwxr-xr-xsrc/occ/thread/test/threadtest.c398
-rwxr-xr-xsrc/occ/thread/thread.h133
-rwxr-xr-xsrc/occ/thread/threadSch.c370
-rwxr-xr-xsrc/occ/thread/threadSch.h83
-rwxr-xr-xsrc/occ/thread/thread_service_codes.h79
-rwxr-xr-xsrc/occ/thread/thrm_thread.c538
-rwxr-xr-xsrc/occ/thread/thrm_thread.h70
-rwxr-xr-xsrc/occ/timer/timer.c318
-rwxr-xr-xsrc/occ/timer/timer.h76
-rwxr-xr-xsrc/occ/timer/timer_service_codes.h62
-rwxr-xr-xsrc/occ/tools/EXAMPLE_.occ_simics_config22
-rw-r--r--src/occ/tools/Gcov.pm811
-rwxr-xr-xsrc/occ/tools/OccSimicsAutomate.pm1010
-rwxr-xr-xsrc/occ/tools/cpPluginFiles.pl78
-rwxr-xr-xsrc/occ/tools/fsp_trace_parse.pl73
-rwxr-xr-xsrc/occ/tools/hocct.pl739
-rwxr-xr-xsrc/occ/tools/mkvpozip.sh66
-rwxr-xr-xsrc/occ/tools/occGcov.pl19
-rwxr-xr-xsrc/occ/tools/occWebTool/Makefile36
-rwxr-xr-xsrc/occ/tools/occWebTool/parser.c451
-rwxr-xr-xsrc/occ/tools/occ_amec_sensors.py367
-rwxr-xr-xsrc/occ/tools/occ_autotest609
-rw-r--r--src/occ/tools/occ_autotest_extend.example46
-rwxr-xr-xsrc/occ/tools/occ_fsp_fakeout.py302
-rwxr-xr-xsrc/occ/tools/occ_gdb.pl282
-rwxr-xr-xsrc/occ/tools/occ_gdb.py116
-rw-r--r--src/occ/tools/occ_hwp_id.pl458
-rwxr-xr-xsrc/occ/tools/occ_post_model_hook.simics344
-rwxr-xr-xsrc/occ/tools/occ_simics_debug.py174
-rw-r--r--src/occ/tools/occ_simics_gen_lists.py53
-rwxr-xr-xsrc/occ/tools/occ_trace.simics3
-rwxr-xr-xsrc/occ/tools/occgenlid.pl123
-rwxr-xr-xsrc/occ/tools/scanforsrcs.pl1121
-rwxr-xr-xsrc/occ/tools/start_occ_simics.pl251
-rwxr-xr-xsrc/occ/tools/trexStringFile12
-rwxr-xr-xsrc/occ/trac/trac.h298
-rwxr-xr-xsrc/occ/trac/trac_interface.c1207
-rwxr-xr-xsrc/occ/trac/trac_interface.h335
-rwxr-xr-xsrc/occ/trac/trac_service_codes.h69
-rwxr-xr-xsrc/occApplet/Makefile53
-rwxr-xr-xsrc/occApplet/createApplet135
-rwxr-xr-xsrc/occApplet/productApplet/Makefile130
-rwxr-xr-xsrc/occApplet/productApplet/apssInitApplet.c322
-rwxr-xr-xsrc/occApplet/productApplet/cmdhDbugCmd.c341
-rwxr-xr-xsrc/occApplet/productApplet/dpssInitApplet.c304
-rwxr-xr-xsrc/occApplet/productApplet/linkProductApplet.cmd55
-rw-r--r--src/occApplet/productApplet/occLinkInputFile1
-rwxr-xr-xsrc/occApplet/productApplet/productappletfiles.mk30
-rwxr-xr-xsrc/occApplet/productApplet/sensorQueryList.c308
-rwxr-xr-xsrc/occApplet/template.c73
-rwxr-xr-xsrc/occApplet/testApplet/Makefile107
-rwxr-xr-xsrc/occApplet/testApplet/apsstest.c107
-rwxr-xr-xsrc/occApplet/testApplet/errlTest.c1210
-rwxr-xr-xsrc/occApplet/testApplet/linkTestApplet.cmd60
-rw-r--r--src/occApplet/testApplet/occLinkInputFile1
-rwxr-xr-xsrc/occApplet/testApplet/pstApplet.c124
-rwxr-xr-xsrc/occApplet/testApplet/sensorTest.c1175
-rwxr-xr-xsrc/occApplet/testApplet/testApltId.h60
-rwxr-xr-xsrc/occApplet/testApplet/testappletfiles.mk37
-rwxr-xr-xsrc/occApplet/testApplet/traceTest.c340
-rwxr-xr-xsrc/occBootLoader/Makefile90
-rwxr-xr-xsrc/occBootLoader/bootInit.S234
-rwxr-xr-xsrc/occBootLoader/bootMain.c308
-rwxr-xr-xsrc/occBootLoader/bootMain.h102
-rwxr-xr-xsrc/occBootLoader/bootfiles.mk28
-rwxr-xr-xsrc/occBootLoader/imageHdrScript.c877
-rwxr-xr-xsrc/occBootLoader/linkboot.cmd117
-rw-r--r--src/occBootLoader/occLinkInputFile1
-rwxr-xr-xsrc/ssx/pgp/Makefile38
-rwxr-xr-xsrc/ssx/pgp/linkssx.cmd499
-rwxr-xr-xsrc/ssx/pgp/pgp.h328
-rwxr-xr-xsrc/ssx/pgp/pgp_async.c1024
-rwxr-xr-xsrc/ssx/pgp/pgp_async.h1654
-rwxr-xr-xsrc/ssx/pgp/pgp_async_ocb.c953
-rwxr-xr-xsrc/ssx/pgp/pgp_async_pba.c1201
-rwxr-xr-xsrc/ssx/pgp/pgp_async_pore.c644
-rwxr-xr-xsrc/ssx/pgp/pgp_cache.S99
-rw-r--r--src/ssx/pgp/pgp_centaur.c597
-rw-r--r--src/ssx/pgp/pgp_centaur.h254
-rwxr-xr-xsrc/ssx/pgp/pgp_common.h717
-rwxr-xr-xsrc/ssx/pgp/pgp_core.h20
-rw-r--r--src/ssx/pgp/pgp_id.c135
-rw-r--r--src/ssx/pgp/pgp_id.h183
-rwxr-xr-xsrc/ssx/pgp/pgp_init.c340
-rwxr-xr-xsrc/ssx/pgp/pgp_irq.h252
-rwxr-xr-xsrc/ssx/pgp/pgp_irq_init.c155
-rwxr-xr-xsrc/ssx/pgp/pgp_ocb.c335
-rwxr-xr-xsrc/ssx/pgp/pgp_ocb.h88
-rwxr-xr-xsrc/ssx/pgp/pgp_pba.c460
-rwxr-xr-xsrc/ssx/pgp/pgp_pba.h358
-rwxr-xr-xsrc/ssx/pgp/pgp_pmc.c366
-rwxr-xr-xsrc/ssx/pgp/pgp_pmc.h105
-rwxr-xr-xsrc/ssx/pgp/pgp_pore.h39
-rwxr-xr-xsrc/ssx/pgp/pgp_sramctl.h18
-rwxr-xr-xsrc/ssx/pgp/pgp_trace.h155
-rwxr-xr-xsrc/ssx/pgp/pgp_vrm.h223
-rwxr-xr-xsrc/ssx/pgp/registers/centaur_firmware_registers.h1496
-rwxr-xr-xsrc/ssx/pgp/registers/centaur_register_addresses.h66
-rw-r--r--src/ssx/pgp/registers/fasti2c_firmware_registers.h232
-rw-r--r--src/ssx/pgp/registers/fasti2c_register_addresses.h27
-rw-r--r--src/ssx/pgp/registers/i2cengine_firmware_registers.h710
-rw-r--r--src/ssx/pgp/registers/i2cengine_register_addresses.h33
-rwxr-xr-xsrc/ssx/pgp/registers/icp_firmware_registers.h189
-rwxr-xr-xsrc/ssx/pgp/registers/icp_register_addresses.h24
-rwxr-xr-xsrc/ssx/pgp/registers/mcs_firmware_registers.h161
-rwxr-xr-xsrc/ssx/pgp/registers/mcs_register_addresses.h46
-rwxr-xr-xsrc/ssx/pgp/registers/ocb_firmware_registers.h2668
-rwxr-xr-xsrc/ssx/pgp/registers/ocb_register_addresses.h148
-rwxr-xr-xsrc/ssx/pgp/registers/oha_firmware_registers.h1248
-rwxr-xr-xsrc/ssx/pgp/registers/oha_register_addresses.h39
-rwxr-xr-xsrc/ssx/pgp/registers/pba_firmware_registers.h2184
-rwxr-xr-xsrc/ssx/pgp/registers/pba_register_addresses.h94
-rwxr-xr-xsrc/ssx/pgp/registers/pc_firmware_registers.h442
-rwxr-xr-xsrc/ssx/pgp/registers/pc_register_addresses.h61
-rwxr-xr-xsrc/ssx/pgp/registers/pcbs_firmware_registers.h2477
-rwxr-xr-xsrc/ssx/pgp/registers/pcbs_register_addresses.h74
-rw-r--r--src/ssx/pgp/registers/pibmem_firmware_registers.h264
-rw-r--r--src/ssx/pgp/registers/pibmem_register_addresses.h30
-rwxr-xr-xsrc/ssx/pgp/registers/plb_arbiter_firmware_registers.h215
-rwxr-xr-xsrc/ssx/pgp/registers/plb_arbiter_register_addresses.h28
-rwxr-xr-xsrc/ssx/pgp/registers/pmc_firmware_registers.h3140
-rwxr-xr-xsrc/ssx/pgp/registers/pmc_register_addresses.h116
-rwxr-xr-xsrc/ssx/pgp/registers/pore_firmware_registers.h906
-rwxr-xr-xsrc/ssx/pgp/registers/pore_register_addresses.h130
-rw-r--r--src/ssx/pgp/registers/sbe_firmware_registers.h906
-rw-r--r--src/ssx/pgp/registers/sbe_register_addresses.h48
-rwxr-xr-xsrc/ssx/pgp/registers/sensors_firmware_registers.h668
-rwxr-xr-xsrc/ssx/pgp/registers/sensors_register_addresses.h47
-rwxr-xr-xsrc/ssx/pgp/registers/sramctl_firmware_registers.h211
-rwxr-xr-xsrc/ssx/pgp/registers/sramctl_register_addresses.h30
-rwxr-xr-xsrc/ssx/pgp/registers/tod_firmware_registers.h58
-rwxr-xr-xsrc/ssx/pgp/registers/tod_register_addresses.h22
-rw-r--r--src/ssx/pgp/registers/tpc_firmware_registers.h213
-rw-r--r--src/ssx/pgp/registers/tpc_register_addresses.h30
-rwxr-xr-xsrc/ssx/pgp/ssx.mk424
-rwxr-xr-xsrc/ssx/pgp/ssx_port.h19
-rwxr-xr-xsrc/ssx/pgp/ssxpgpfiles.mk37
-rwxr-xr-xsrc/ssx/ppc32/Makefile33
-rwxr-xr-xsrc/ssx/ppc32/div64.S255
-rw-r--r--src/ssx/ppc32/gnu/stubs-32.h21
-rwxr-xr-xsrc/ssx/ppc32/ppc32.h171
-rwxr-xr-xsrc/ssx/ppc32/ppc32_asm.h408
-rwxr-xr-xsrc/ssx/ppc32/ppc32_gcc.c309
-rwxr-xr-xsrc/ssx/ppc32/ppc32_gcc.h75
-rwxr-xr-xsrc/ssx/ppc32/savegpr.S78
-rwxr-xr-xsrc/ssx/ppc32/ssxppc32files.mk29
-rwxr-xr-xsrc/ssx/ppc405/Makefile40
-rwxr-xr-xsrc/ssx/ppc405/ppc405.h771
-rwxr-xr-xsrc/ssx/ppc405/ppc405_boot.S242
-rw-r--r--src/ssx/ppc405/ppc405_breakpoint.S103
-rwxr-xr-xsrc/ssx/ppc405/ppc405_cache.h113
-rwxr-xr-xsrc/ssx/ppc405/ppc405_cache_core.c115
-rwxr-xr-xsrc/ssx/ppc405/ppc405_cache_init.S314
-rwxr-xr-xsrc/ssx/ppc405/ppc405_context.h594
-rwxr-xr-xsrc/ssx/ppc405/ppc405_core.c183
-rwxr-xr-xsrc/ssx/ppc405/ppc405_dcr.h55
-rwxr-xr-xsrc/ssx/ppc405/ppc405_exceptions.S832
-rwxr-xr-xsrc/ssx/ppc405/ppc405_init.c80
-rwxr-xr-xsrc/ssx/ppc405/ppc405_irq.h342
-rwxr-xr-xsrc/ssx/ppc405/ppc405_irq_core.c49
-rwxr-xr-xsrc/ssx/ppc405/ppc405_irq_init.c169
-rwxr-xr-xsrc/ssx/ppc405/ppc405_lib_core.c42
-rwxr-xr-xsrc/ssx/ppc405/ppc405_mmu.c474
-rwxr-xr-xsrc/ssx/ppc405/ppc405_mmu.h170
-rwxr-xr-xsrc/ssx/ppc405/ppc405_mmu_asm.S73
-rwxr-xr-xsrc/ssx/ppc405/ppc405_msr.h85
-rwxr-xr-xsrc/ssx/ppc405/ppc405_spr.h319
-rwxr-xr-xsrc/ssx/ppc405/ppc405_thread_init.S126
-rwxr-xr-xsrc/ssx/ppc405/ssx_port_types.h44
-rwxr-xr-xsrc/ssx/ppc405/ssxppc405files.mk53
-rwxr-xr-xsrc/ssx/ssx/Makefile25
-rwxr-xr-xsrc/ssx/ssx/ssx.h126
-rwxr-xr-xsrc/ssx/ssx/ssx_api.h888
-rwxr-xr-xsrc/ssx/ssx/ssx_core.c81
-rwxr-xr-xsrc/ssx/ssx/ssx_init.c159
-rwxr-xr-xsrc/ssx/ssx/ssx_kernel.h281
-rwxr-xr-xsrc/ssx/ssx/ssx_macros.h119
-rwxr-xr-xsrc/ssx/ssx/ssx_semaphore_core.c331
-rwxr-xr-xsrc/ssx/ssx/ssx_semaphore_init.c84
-rwxr-xr-xsrc/ssx/ssx/ssx_stack_init.c87
-rwxr-xr-xsrc/ssx/ssx/ssx_thread_core.c946
-rwxr-xr-xsrc/ssx/ssx/ssx_thread_init.c140
-rwxr-xr-xsrc/ssx/ssx/ssx_timer_core.c447
-rwxr-xr-xsrc/ssx/ssx/ssx_timer_init.c124
-rwxr-xr-xsrc/ssx/ssx/ssxssxfiles.mk35
419 files changed, 137187 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100755
index 0000000..8b2a26f
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,90 @@
+# $Id$
+
+# @file Makefile
+#
+# @brief bootloader Makefile
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# pb000 pbavari 07/21/11 Created
+# th000 thallet 01/09/12 Removed simics-workspace
+# at009 859308 alvinwan 10/15/2012 Added tracepp support
+# at011 866759 alvinwan 01/15/2013 Fix OCC trexStringFile and trace
+# rt001 901927 tapiar 10/01/2013 SRC plugin file generation
+# gitprep sbroyles 11/02/2014 Prepare files for move to git/gnu build
+# @endverbatim
+#
+
+# >> gitprep
+ifndef ROOTPATH
+ROOTPATH = $(shell pwd)
+export OCCROOT = $(ROOTPATH)
+endif
+# << gitprep
+
+#*******************************************************************************
+# mk variable Declaration
+#*******************************************************************************
+SUBDIRS = occBootLoader occ occApplet
+COMBINE_IMAGE_SUBDIRS = occBootLoader occ occApplet
+CLEAN_SUBDIRS = occBootLoader occ occApplet ssx/pgp lib
+CLEANCMD = $(MAKE) clean -C $(dir);
+ALLCMD = $(MAKE) -j6 -C $(dir);
+COMBINEIMAGE = $(MAKE) combineImage -C $(dir);
+IMAGEFILE = image.bin
+
+#*******************************************************************************
+# Compilation
+#*******************************************************************************
+
+all:
+ $(foreach dir,$(SUBDIRS),$(ALLCMD))
+
+#*******************************************************************************
+# Combine Objects/Executables into OCC Image
+#*******************************************************************************
+.PHONY : combineImage
+combineImage:
+ rm -rf $(IMAGEFILE)
+ $(foreach dir,$(COMBINE_IMAGE_SUBDIRS),$(COMBINEIMAGE))
+
+#*******************************************************************************
+# Create lid or ruhx out of OCC Image
+#*******************************************************************************
+.PHONY : 81e004%.ruhx
+81e004%.ruhx:
+ ./occ/tools/occgenlid.pl -i ${IMAGEFILE} -l $(basename $@)
+
+.PHONY : 81e004%.lid
+81e004%.lid:
+ cp ${IMAGEFILE} $(dir $(IMAGEFILE))/$@
+
+#*******************************************************************************
+# Create trexStringFile
+#*******************************************************************************
+.PHONY : tracehash
+tracehash:
+ mkdir -p ${sb}/../obj
+ tracehash.pl -c -d ${SANDBOXBASE}/obj/ppc/occc/405/ -s ${SANDBOXBASE}/obj/trexStringFile
+
+#*******************************************************************************
+# Create occcSrcParse.C @rt001
+#*******************************************************************************
+.PHONY : srcPluginFile
+srcPluginFile:
+ ./occ/tools/scanforsrcs.pl
+
+#*******************************************************************************
+# Clean
+#*******************************************************************************
+clean:
+ $(foreach dir,$(CLEAN_SUBDIRS),$(CLEANCMD))
+ rm -rf image.bin
+
diff --git a/src/lib/Makefile b/src/lib/Makefile
new file mode 100755
index 0000000..c9e4640
--- /dev/null
+++ b/src/lib/Makefile
@@ -0,0 +1,79 @@
+# $Id: Makefile,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+#
+# This Makefile currently builds a single archive, 'libssx.a', from
+# various library source files.
+#
+# Beware that although this library can be built standalone, parts of
+# its behavior are controlled by options that may be configured in
+# the optional "ssx_app_cfg.h", so it is best to build the library as
+# part of the complete application build.
+#
+# The object files stored in the archive are loaded 'on demand'.
+# It may be possible to save a little code space therefore by splitting up
+# the implementation of a header file into multiple files whose
+# functions are not necessarily called together.
+
+SSX = ../ssx
+PGP = $(SSX)/pgp
+LIB = .
+
+include ./libfiles.mk
+include ./libgpefiles.mk
+INCLUDES =
+
+include $(PGP)/ssx.mk
+
+# >> gitprep
+# Disabled for GNU builds
+#If it's for OCC_FIRMWARE and non-PGAS_PPC build, the library gpefiles needs to be taken out of libssx.a
+#LIBSSX_OBJECTS += $(if $(filter -DOCC_FIRMWARE=1,$(DEFS)),\
+# $(if $(PGAS_PPC),$(LIB_PSOBJECTS),),\
+# $(LIB_PSOBJECTS))
+# << gitprep
+
+libssx.a: $(LIBSSX_OBJECTS)
+ $(AR) crs libssx.a $(LIBSSX_OBJECTS)
+
+clean:
+ rm -f *.o *.a *.d *.d.* *.lst *.hooks.cc
+ rm -f $(TEST_EXECUTABLES)
+
+disassemble: libssx.a
+ $(OBJDUMP) -d libssx.a
+
+
+# The targets 'push_updates_to_lab' and 'diff_with_lab' require that an
+# environment variable P8PROCS be defined. You can also define this on the
+# 'make' command line, for example
+#
+# make P8PROCS=<... path to your P8 procedures sandbox ...> \
+# push_updates_to_lab
+
+# LIB-TO-PROCS-FILES are files kept here that need to go there, where 'there'
+# is the top-level procedures directory.
+
+LIB-TO-PROCS-FILES = pgas.h pgas_ppc.h
+
+push_updates_to_lab:
+ if [ -z "$(P8PROCS)" ]; then echo "P8PROCS is not defined"; exit 1; fi
+ cp -u $(LIB-TO-PROCS-FILES) $(P8PROCS)
+
+diff_with_lab:
+ if [ -z "$(P8PROCS)" ]; then echo "P8PROCS is not defined"; exit 1; fi
+
+ for file in $(LIB-TO-PROCS-FILES); do \
+ echo "@@@ $$file"; \
+ diff $$file $(P8PROCS)/$$file; \
+ done; exit 0
+
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),push_updates_to_lab)
+ifneq ($(MAKECMDGOALS),diff_with_lab)
+include $(C-SOURCES:.c=.d)
+include $(S-SOURCES:.S=.d)
+include $(if $(filter -DOCC_FIRMWARE=1,$(DEFS)),$(if $(PGAS_PPC),$(pS-SOURCES:.pS=.d),),$(pS-SOURCES:.pS=.d))
+endif
+endif
+endif
+
diff --git a/src/lib/assert.c b/src/lib/assert.c
new file mode 100755
index 0000000..36e3caf
--- /dev/null
+++ b/src/lib/assert.c
@@ -0,0 +1,47 @@
+// $Id: assert.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/assert.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file assert.c
+/// \brief Implementation of library routines implied by <assert.h>
+
+#include "ssx.h"
+#include "ssx_io.h"
+#include "libssx.h"
+
+/// The __assert_fail() function is used to implement the assert() interface
+/// of ISO POSIX (2003). The __assert_fail() function prints the given \a
+/// file filename, \a line line number, \a function function name and a
+/// message on the standard error stream then causes a kernel panic. If there
+/// is no standard error stream then the error message is printed on the \a
+/// ssxout (printk()) stream.
+///
+/// If function is NULL, __assert_fail() omits information about the
+/// function. The aguments \a assertion, \a file, and \a line must be
+/// non-NULL.
+
+void
+__assert_fail(const char *assertion,
+ const char *file,
+ unsigned line,
+ const char *function)
+{
+ FILE *stream;
+
+ stream = stderr;
+ if (stream == 0) {
+ stream = ssxout;
+ }
+
+ fprintf(stream, "%s:%u:%s%s Assertion '%s' failed\n",
+ file, line,
+ function ? function : "", function ? ":" : "",
+ assertion);
+
+ SSX_PANIC(ASSERTION_FAILURE);
+}
+
diff --git a/src/lib/ctype.c b/src/lib/ctype.c
new file mode 100755
index 0000000..5b10635
--- /dev/null
+++ b/src/lib/ctype.c
@@ -0,0 +1,22 @@
+// $Id: ctype.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ctype.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ctype.c
+/// \brief Replacement for <ctype.h> functions
+///
+/// This file contains entry point equivalents for the "ctype.h" macros.
+/// These would only ever be used by assembler programs, therefore it's likely
+/// that the object file will never be linked into an image.
+
+#define __CTYPE_C__
+#include "ctype.h"
+#undef __CTYPE_C__
+
+
+
+
diff --git a/src/lib/ctype.h b/src/lib/ctype.h
new file mode 100755
index 0000000..9072c41
--- /dev/null
+++ b/src/lib/ctype.h
@@ -0,0 +1,125 @@
+#ifndef __CTYPE_H__
+#define __CTYPE_H__
+
+// $Id: ctype.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ctype.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ctype.h
+/// \brief Replacement for <ctype.h>
+///
+/// The Gnu <ctype.h> requires some locale information to be defined. We
+/// avoid this overhead and implement the simple functions, simply assuming
+/// standard 8-bit ASCII. The standard requires that these be defined as entry
+/// points, but may be defined as macros, therefore all macros defined by
+/// ctype.h are also be replicated in \c ctype.c
+
+// The reference for which characters are included in each set was:
+//
+// http://www.cplusplus.com/reference/clibrary/cctype/
+//
+// Note that no code was copied from the above or any other published
+// description of the ctype.h functionality.
+
+// To keep space to a minimum we encode the 8 common types directly into
+// an 8-bit mask. Other types take a little longer to compute.
+
+#define _CTYPE_CNTRL 0x01
+#define _CTYPE_SPACE 0x02
+#define _CTYPE_PRINT 0x04
+#define _CTYPE_PUNCT 0x08
+#define _CTYPE_UPPER 0x10
+#define _CTYPE_LOWER 0x20
+#define _CTYPE_DIGIT 0x40
+#define _CTYPE_XDIGIT 0x80
+
+#ifndef __ASSEMBLER__
+
+#include "stdint.h"
+
+/// \bug <ctype.h> can not include <stdio.h> to get the definition of
+/// EOF. This is because it causes conflicts withe the pore_inline* code which
+/// is portable (and ported) to Linux and PHYP. We need to go back through the
+/// way the includes are done in SSX and this library and fix this. We should
+/// have redefined <stdio.h> rather than creating a new "ssx_io.h"
+
+#define _CTYPE_EOF -1
+
+// Note that in all of the type macros, 'c' is an unsigned char.
+
+extern const uint8_t _ctype[256];
+
+#define _CTYPE_ISLOWER(c) (_ctype[c] & _CTYPE_LOWER)
+
+#define _CTYPE_ISUPPER(c) (_ctype[c] & _CTYPE_UPPER)
+
+#define _CTYPE_ISALPHA(c) (_CTYPE_ISUPPER(c) || _CTYPE_ISLOWER(c))
+
+#define _CTYPE_ISDIGIT(c) (_ctype[c] & _CTYPE_DIGIT)
+
+#define _CTYPE_ISALNUM(c) (_CTYPE_ISALPHA(c) || _CTYPE_ISDIGIT(c))
+
+#define _CTYPE_ISXDIGIT(c) (_ctype[c] & _CTYPE_XDIGIT)
+
+#define _CTYPE_ISCNTRL(c) (_ctype[c] & _CTYPE_CNTRL)
+
+#define _CTYPE_ISSPACE(c) (_ctype[c] & _CTYPE_SPACE)
+
+#define _CTYPE_ISPRINT(c) (_ctype[c] & _CTYPE_PRINT)
+
+#define _CTYPE_ISGRAPH(c) (_CTYPE_ISPRINT(c) && ((c) != 0x20))
+
+#define _CTYPE_ISPUNCT(c) (_ctype[c] & _CTYPE_PUNCT)
+
+#define _CTYPE_TOUPPER(c) (islower(c) ? ((c) + ('A' - 'a')) : (c))
+
+#define _CTYPE_TOLOWER(c) (isupper(c) ? ((c) - ('A' - 'a')) : (c))
+
+// When #include'ed into ctype.c, the non-inline forms of the functions are
+// created.
+//
+// Note that the specification requires that 'c' "must have the value of an
+// unsigned char or EOF". The specification also stipulates that "The values
+// returned are non-zero if the character c falls into the tested class, and a
+// zero value if not."
+
+#ifdef __CTYPE_C__
+#define _CTYPE_EXTERN_INLINE
+#else
+#define _CTYPE_EXTERN_INLINE extern inline
+#endif
+
+#define _CTYPE_PREDICATE(predicate, def) \
+ _CTYPE_EXTERN_INLINE int predicate(int c) { \
+ return ((c == _CTYPE_EOF) ? \
+ 0 : _CTYPE_##def((unsigned char)c)); \
+ }
+
+#define _CTYPE_FUNCTION(function, def) \
+ _CTYPE_EXTERN_INLINE int function(int c) { \
+ return ((c == _CTYPE_EOF) ? \
+ _CTYPE_EOF : _CTYPE_##def((unsigned char)c)); \
+ }
+
+_CTYPE_PREDICATE(islower, ISLOWER)
+_CTYPE_PREDICATE(isupper, ISUPPER)
+_CTYPE_PREDICATE(isalpha, ISALPHA)
+_CTYPE_PREDICATE(isdigit, ISDIGIT)
+_CTYPE_PREDICATE(isalnum, ISALNUM)
+_CTYPE_PREDICATE(isxdigit, ISXDIGIT)
+_CTYPE_PREDICATE(iscntrl, ISCNTRL)
+_CTYPE_PREDICATE(isspace, ISSPACE)
+_CTYPE_PREDICATE(isprint, ISPRINT)
+_CTYPE_PREDICATE(isgraph, ISGRAPH)
+_CTYPE_PREDICATE(ispunct, ISPUNCT)
+
+_CTYPE_FUNCTION(tolower, TOLOWER)
+_CTYPE_FUNCTION(toupper, TOUPPER)
+
+#endif // __ASSEMBLER__
+
+#endif /* __CTYPE_H__ */
diff --git a/src/lib/ctype_table.c b/src/lib/ctype_table.c
new file mode 100644
index 0000000..6f3e576
--- /dev/null
+++ b/src/lib/ctype_table.c
@@ -0,0 +1,278 @@
+// $Id: ctype_table.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ctype_table.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ctype_table.c
+/// \brief Character table for <ctype.h> functions.
+///
+/// This table is used by the <ctype.h> functions for a quick lookup of
+/// character type information. Because the true functional forms of <ctype.h>
+/// functions are likely never required, but this file is always required, it
+/// is stored separately from ctype.c to (slightly) reduce code/data space
+/// requirements.
+
+#include <stdint.h>
+#include <ctype.h>
+
+const uint8_t _ctype[256] = {
+ _CTYPE_CNTRL, /* 0 00 NUL Null char */
+ _CTYPE_CNTRL, /* 1 01 SOH Start of Heading */
+ _CTYPE_CNTRL, /* 2 02 STX Start of Text */
+ _CTYPE_CNTRL, /* 3 03 ETX End of Text */
+ _CTYPE_CNTRL, /* 4 04 EOT End of Transmission */
+ _CTYPE_CNTRL, /* 5 05 ENQ Enquiry */
+ _CTYPE_CNTRL, /* 6 06 ACK Acknowledgment */
+ _CTYPE_CNTRL, /* 7 07 BEL Bell */
+ _CTYPE_CNTRL, /* 8 08 BS Back Space */
+ _CTYPE_CNTRL | _CTYPE_SPACE, /* 9 09 HT Horizontal Tab */
+ _CTYPE_CNTRL | _CTYPE_SPACE, /* 10 0A LF Line Feed */
+ _CTYPE_CNTRL | _CTYPE_SPACE, /* 11 0B VT Vertical Tab */
+ _CTYPE_CNTRL | _CTYPE_SPACE, /* 12 0C FF Form Feed */
+ _CTYPE_CNTRL | _CTYPE_SPACE, /* 13 0D CR Carriage Return */
+ _CTYPE_CNTRL, /* 14 0E SO Shift Out / X-On */
+ _CTYPE_CNTRL, /* 15 0F SI Shift In / X-Off */
+ 0, /* 16 10 DLE Data Line Escape */
+ 0, /* 17 11 DC1 Device Control 1 (oft. XON) */
+ 0, /* 18 12 DC2 Device Control 2 */
+ 0, /* 19 13 DC3 Device Control 3 (oft. XOFF) */
+ 0, /* 20 14 DC4 Device Control 4 */
+ 0, /* 21 15 NAK Negative Acknowledgement */
+ 0, /* 22 16 SYN Synchronous Idle */
+ 0, /* 23 17 ETB End of Transmit Block */
+ 0, /* 24 18 CAN Cancel */
+ 0, /* 25 19 EM End of Medium */
+ 0, /* 26 1A SUB Substitute */
+ 0, /* 27 1B ESC Escape */
+ 0, /* 28 1C FS File Separator */
+ 0, /* 29 1D GS Group Separator */
+ 0, /* 30 1E RS Record Separator */
+ 0, /* 31 1F US Unit Separator */
+ _CTYPE_PRINT | _CTYPE_SPACE, /* 32 20 Space */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 33 21 ! Exclamation mark */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 34 22 " Double quotes (or speech marks) */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 35 23 # Number */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 36 24 $ Dollar */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 37 25 % Procenttecken */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 38 26 & Ampersand */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 39 27 ' Single quote */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 40 28 ( Open parenthesis (or open bracket) */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 41 29 ) Close parenthesis (or close bracket) */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 42 2A * Asterisk */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 43 2B + Plus */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 44 2C , Comma */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 45 2D - Hyphen */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 46 2E . Period, dot or full stop */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 47 2F / Slash or divide */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 48 30 0 Zero */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 49 31 1 One */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 50 32 2 Two */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 51 33 3 Three */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 52 34 4 Four */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 53 35 5 Five */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 54 36 6 Six */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 55 37 7 Seven */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 56 38 8 Eight */
+ _CTYPE_PRINT | _CTYPE_DIGIT, /* 57 39 9 Nine */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 58 3A : Colon */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 59 3B ; Semicolon */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 60 3C < Less than (or open angled bracket) */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 61 3D = Equals */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 62 3E > Greater than (or close angled bracket) */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 63 3F ? Question mark */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 64 40 @ At symbol */
+ _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 65 41 A Uppercase A */
+ _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 66 42 B Uppercase B */
+ _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 67 43 C Uppercase C */
+ _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 68 44 D Uppercase D */
+ _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 69 45 E Uppercase E */
+ _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 70 46 F Uppercase F */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 71 47 G Uppercase G */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 72 48 H Uppercase H */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 73 49 I Uppercase I */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 74 4A J Uppercase J */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 75 4B K Uppercase K */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 76 4C L Uppercase L */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 77 4D M Uppercase M */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 78 4E N Uppercase N */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 79 4F O Uppercase O */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 80 50 P Uppercase P */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 81 51 Q Uppercase Q */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 82 52 R Uppercase R */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 83 53 S Uppercase S */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 84 54 T Uppercase T */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 85 55 U Uppercase U */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 86 56 V Uppercase V */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 87 57 W Uppercase W */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 88 58 X Uppercase X */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 89 59 Y Uppercase Y */
+ _CTYPE_PRINT | _CTYPE_UPPER, /* 90 5A Z Uppercase Z */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 91 5B [ Opening bracket */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 92 5C \ Backslash */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 93 5D ] Closing bracket */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 94 5E ^ Caret - circumflex */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 95 5F _ Underscore */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 96 60 ` Grave accent */
+ _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 97 61 a Lowercase a */
+ _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 98 62 b Lowercase b */
+ _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 99 63 c Lowercase c */
+ _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 100 64 d Lowercase d */
+ _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 101 65 e Lowercase e */
+ _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 102 66 f Lowercase f */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 103 67 g Lowercase g */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 104 68 h Lowercase h */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 105 69 i Lowercase i */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 106 6A j Lowercase j */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 107 6B k Lowercase k */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 108 6C l Lowercase l */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 109 6D m Lowercase m */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 110 6E n Lowercase n */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 111 6F o Lowercase o */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 112 70 p Lowercase p */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 113 71 q Lowercase q */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 114 72 r Lowercase r */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 115 73 s Lowercase s */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 116 74 t Lowercase t */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 117 75 u Lowercase u */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 118 76 v Lowercase v */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 119 77 w Lowercase w */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 120 78 x Lowercase x */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 121 79 y Lowercase y */
+ _CTYPE_PRINT | _CTYPE_LOWER, /* 122 7A z Lowercase z */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 123 7B { Opening brace */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 124 7C | Vertical bar */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 125 7D } Closing brace */
+ _CTYPE_PRINT | _CTYPE_PUNCT, /* 126 7E ~ Equivalency sign - tilde */
+ 0, /* 127 7F Delete */
+ 0, /* 128 80 Euro sign */
+ 0, /* 129 81 */
+ 0, /* 130 82 ' Single low-9 quotation mark */
+ 0, /* 131 83 Latin small letter f with hook */
+ 0, /* 132 84 " Double low-9 quotation mark */
+ 0, /* 133 85 Horizontal ellipsis */
+ 0, /* 134 86 Dagger */
+ 0, /* 135 87 Double dagger */
+ 0, /* 136 88 Modifier letter circumflex accent */
+ 0, /* 137 89 Per mille sign */
+ 0, /* 138 8A Latin capital letter S with caron */
+ 0, /* 139 8B Single left-pointing angle quotation */
+ 0, /* 140 8C Latin capital ligature OE */
+ 0, /* 141 8D */
+ 0, /* 142 8E Latin captial letter Z with caron */
+ 0, /* 143 8F */
+ 0, /* 144 90 */
+ 0, /* 145 91 ' Left single quotation mark */
+ 0, /* 146 92 ' Right single quotation mark */
+ 0, /* 147 93 " Left double quotation mark */
+ 0, /* 148 94 " Right double quotation mark */
+ 0, /* 149 95 Bullet */
+ 0, /* 150 96 En dash */
+ 0, /* 151 97 Em dash */
+ 0, /* 152 98 Small tilde */
+ 0, /* 153 99 Trade mark sign */
+ 0, /* 154 9A Latin small letter S with caron */
+ 0, /* 155 9B Single right-pointing angle quotation mark */
+ 0, /* 156 9C Latin small ligature oe */
+ 0, /* 157 9D */
+ 0, /* 158 9E Latin small letter z with caron */
+ 0, /* 159 9F Latin capital letter Y with diaeresis */
+ 0, /* 160 A0 Non-breaking space */
+ 0, /* 161 A1 Inverted exclamation mark */
+ 0, /* 162 A2 Cent sign */
+ 0, /* 163 A3 Pound sign */
+ 0, /* 164 A4 Currency sign */
+ 0, /* 165 A5 Yen sign */
+ 0, /* 166 A6 Pipe, Broken vertical bar */
+ 0, /* 167 A7 Section sign */
+ 0, /* 168 A8 Spacing diaeresis - umlaut */
+ 0, /* 169 A9 Copyright sign */
+ 0, /* 170 AA Feminine ordinal indicator */
+ 0, /* 171 AB Left double angle quotes */
+ 0, /* 172 AC Not sign */
+ 0, /* 173 AD Soft hyphen */
+ 0, /* 174 AE Registered trade mark sign */
+ 0, /* 175 AF Spacing macron - overline */
+ 0, /* 176 B0 Degree sign */
+ 0, /* 177 B1 Plus-or-minus sign */
+ 0, /* 178 B2 Superscript two - squared */
+ 0, /* 179 B3 Superscript three - cubed */
+ 0, /* 180 B4 Acute accent - spacing acute */
+ 0, /* 181 B5 Micro sign */
+ 0, /* 182 B6 Pilcrow sign - paragraph sign */
+ 0, /* 183 B7 Middle dot - Georgian comma */
+ 0, /* 184 B8 Spacing cedilla */
+ 0, /* 185 B9 Superscript one */
+ 0, /* 186 BA Masculine ordinal indicator */
+ 0, /* 187 BB Right double angle quotes */
+ 0, /* 188 BC one quarter */
+ 0, /* 189 BD Fraction one half */
+ 0, /* 190 BE Fraction three quarters */
+ 0, /* 191 BF Inverted question mark */
+ 0, /* 192 C0 Latin capital letter A with grave */
+ 0, /* 193 C1 Latin capital letter A with acute */
+ 0, /* 194 C2 Latin capital letter A with circumflex */
+ 0, /* 195 C3 Latin capital letter A with tilde */
+ 0, /* 196 C4 Latin capital letter A with diaeresis */
+ 0, /* 197 C5 Latin capital letter A with ring above */
+ 0, /* 198 C6 Latin capital letter AE */
+ 0, /* 199 C7 Latin capital letter C with cedilla */
+ 0, /* 200 C8 Latin capital letter E with grave */
+ 0, /* 201 C9 Latin capital letter E with acute */
+ 0, /* 202 CA Latin capital letter E with circumflex */
+ 0, /* 203 CB Latin capital letter E with diaeresis */
+ 0, /* 204 CC Latin capital letter I with grave */
+ 0, /* 205 CD Latin capital letter I with acute */
+ 0, /* 206 CE Latin capital letter I with circumflex */
+ 0, /* 207 CF Latin capital letter I with diaeresis */
+ 0, /* 208 D0 Latin capital letter ETH */
+ 0, /* 209 D1 Latin capital letter N with tilde */
+ 0, /* 210 D2 Latin capital letter O with grave */
+ 0, /* 211 D3 Latin capital letter O with acute */
+ 0, /* 212 D4 Latin capital letter O with circumflex */
+ 0, /* 213 D5 Latin capital letter O with tilde */
+ 0, /* 214 D6 Latin capital letter O with diaeresis */
+ 0, /* 215 D7 Multiplication sign */
+ 0, /* 216 D8 Latin capital letter O with slash */
+ 0, /* 217 D9 Latin capital letter U with grave */
+ 0, /* 218 DA Latin capital letter U with acute */
+ 0, /* 219 DB Latin capital letter U with circumflex */
+ 0, /* 220 DC Latin capital letter U with diaeresis */
+ 0, /* 221 DD Latin capital letter Y with acute */
+ 0, /* 222 DE Latin capital letter THORN */
+ 0, /* 223 DF Latin small letter sharp s - ess-zed */
+ 0, /* 224 E0 Latin small letter a with grave */
+ 0, /* 225 E1 Latin small letter a with acute */
+ 0, /* 226 E2 Latin small letter a with circumflex */
+ 0, /* 227 E3 Latin small letter a with tilde */
+ 0, /* 228 E4 Latin small letter a with diaeresis */
+ 0, /* 229 E5 Latin small letter a with ring above */
+ 0, /* 230 E6 Latin small letter ae */
+ 0, /* 231 E7 Latin small letter c with cedilla */
+ 0, /* 232 E8 Latin small letter e with grave */
+ 0, /* 233 E9 Latin small letter e with acute */
+ 0, /* 234 EA Latin small letter e with circumflex */
+ 0, /* 235 EB Latin small letter e with diaeresis */
+ 0, /* 236 EC Latin small letter i with grave */
+ 0, /* 237 ED Latin small letter i with acute */
+ 0, /* 238 EE Latin small letter i with circumflex */
+ 0, /* 239 EF Latin small letter i with diaeresis */
+ 0, /* 240 F0 Latin small letter eth */
+ 0, /* 241 F1 Latin small letter n with tilde */
+ 0, /* 242 F2 Latin small letter o with grave */
+ 0, /* 243 F3 Latin small letter o with acute */
+ 0, /* 244 F4 Latin small letter o with circumflex */
+ 0, /* 245 F5 Latin small letter o with tilde */
+ 0, /* 246 F6 Latin small letter o with diaeresis */
+ 0, /* 247 F7 Division sign */
+ 0, /* 248 F8 Latin small letter o with slash */
+ 0, /* 249 F9 Latin small letter u with grave */
+ 0, /* 250 FA Latin small letter u with acute */
+ 0, /* 251 FB Latin small letter u with circumflex */
+ 0, /* 252 FC Latin small letter u with diaeresis */
+ 0, /* 253 FD Latin small letter y with acute */
+ 0, /* 254 FE Latin small letter thorn */
+ 0, /* 255 FF Latin small letter y with diaeresis */
+};
diff --git a/src/lib/errno.h b/src/lib/errno.h
new file mode 100755
index 0000000..a45bb84
--- /dev/null
+++ b/src/lib/errno.h
@@ -0,0 +1,25 @@
+#ifndef __ERRNO_H__
+#define __ERRNO_H__
+
+// $Id: errno.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/errno.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file errno.h
+/// \brief Replacement for <errno.h>
+///
+/// SSX does not support a per-thread or global 'errno'. The standard Unix
+/// errno values returned by library functions are defined here. The prefix
+/// code is the 'telephone code' for "errn".
+
+#define EINVAL 0x00377601
+#define EBADF 0x00377602
+#define EAGAIN 0x00377603
+#define ENXIO 0x00377604
+#define ENOMEM 0x00377605
+
+#endif /* __ERRNO_H__ */
diff --git a/src/lib/fgetc.c b/src/lib/fgetc.c
new file mode 100755
index 0000000..e4e4a49
--- /dev/null
+++ b/src/lib/fgetc.c
@@ -0,0 +1,88 @@
+// $Id: fgetc.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/fgetc.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file fgetc.c
+/// \brief Implementation of fgetc() and ungetc()
+///
+/// The implementations of these APIs are split out to save code space for
+/// applications that do not require them.
+
+#include "ssx_io.h"
+
+
+/// Read a character from a stream
+///
+/// fgetc() reads the next character from \a stream and returns it as an
+/// unsigned char cast to an int, or EOF on end of file or error.
+
+int
+fgetc(FILE* stream)
+{
+ unsigned char c;
+ size_t read;
+ int rc;
+
+ if (stream->flags & SSX_FILE_HAS_CHARACTER) {
+ stream->flags &= ~SSX_FILE_HAS_CHARACTER;
+ rc = stream->character;
+ } else {
+ rc = sread(stream, &c, 1, &read);
+ if (rc || (read != 1)) {
+ rc = EOF;
+ } else {
+ rc = c;
+ if (c == '\n') {
+ stream->lines++;
+ }
+ }
+ }
+ return rc;
+}
+
+
+/// Push a character back onto a stream
+///
+/// ungetc() pushes \a c back to \a stream, cast to unsigned char, where it is
+/// available for subsequent fgetc() operations. Only one pushback is
+/// implemented. A call of ungetc() on a stream that already has a character
+/// pushed back will drop the new push-back and return EOF. Otherwise
+/// ungetc() returns \a c.
+
+int
+ungetc(int c, FILE* stream)
+{
+ int rc;
+
+ if (stream->flags & SSX_FILE_HAS_CHARACTER) {
+ rc = EOF;
+ } else {
+ stream->flags |= SSX_FILE_HAS_CHARACTER;
+ stream->character = c;
+ rc = c;
+ }
+ return rc;
+}
+
+/// Return the number of newline characters read from a stream
+///
+/// This API is an SSX entension to the \<stdio\> APIs. It returns the number
+/// of newline characters read from the stream using fgetc(). Newline
+/// characters read via direct calls to sread() in the stream are not counted.
+///
+/// An application that sees an error while reading from a stream can print
+/// flines() or flines() + 1 (depending on the application) to help users
+/// track down errors in their input.
+size_t
+flines(FILE* stream)
+{
+ return stream->lines;
+}
+
+
+
+
diff --git a/src/lib/gpe.h b/src/lib/gpe.h
new file mode 100755
index 0000000..e759c7d
--- /dev/null
+++ b/src/lib/gpe.h
@@ -0,0 +1,78 @@
+#ifndef __GPE_H__
+#define __GPE_H__
+
+// $Id: gpe.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe.h
+/// \brief Useful PGAS macros for PORE-GPE procedures
+
+#include "pgas.h"
+
+#ifdef __ASSEMBLER__
+#ifdef __PGAS__
+
+// Required to guarantee that the .purgem below always works. .purgem on
+// undefined macros causes an error; There appears to be no way to determine
+// if a macro is defined.
+#include "ppc32_asm.h"
+
+
+ // All GPE code should be assembled in the .text.pore section, and
+ // all GPE data should be assembled in the .data.pore section.
+
+ .macro .text.pore
+ .section .text.pore, "ax", @progbits
+ .balign 4
+ .endm
+
+
+ .macro .data.pore
+ .section .data.pore, "a", @progbits
+ .balign 8
+ .endm
+
+ .purgem .function
+ .macro .function symbol
+ .text.pore
+ .align 2
+ .endm
+
+ .purgem .global_function
+ .macro .global_function symbol
+ .text.pore
+ .align 2
+ .global \symbol
+ .endm
+
+
+ // Get the CFAM Id right-justified in a Dx register, scratching a Px
+ // register in the process.
+
+ .macro cfam_id, Dx:req, Px:req
+ ..data (\Dx)
+ ..pervasive_chiplet_id (\Px)
+ lpcs (\Px), 0x000f000f
+ ldandi (\Dx), 0x000f000f, (\Px), 0xffffffff00000000
+ rols (\Dx), (\Dx), 32
+ .endm
+
+
+ // This macro defines structure offsets for PORE assembler-versions of
+ // structures.
+
+ .macro .gpeStructField, field:req, size=8
+\field\():
+ .struct \field + (\size)
+ .endm
+
+
+#endif // __PGAS__
+#endif // __ASSEMBLER__
+
+#endif // __GPE_H__
diff --git a/src/lib/gpe_control.h b/src/lib/gpe_control.h
new file mode 100755
index 0000000..355330f
--- /dev/null
+++ b/src/lib/gpe_control.h
@@ -0,0 +1,171 @@
+#ifndef __GPE_CONTROL_H__
+#define __GPE_CONTROL_H__
+
+// $Id: gpe_control.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe_control.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe_control.h
+/// \brief GPE procedures for control
+
+#include "pstates.h"
+#include "pgp_config.h"
+
+////////////////////////////////////////////////////////////////////////////
+// PcbsPstateRegs
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// Per-core Pstate control registers
+///
+/// Firmware maintains a vector of PcbsPstateRegs structures - one for
+/// each core on the chip - and updates the register fields in place. The GPE
+/// procedure gpe_set_pstates() is run periodically to update the core
+/// chiplets from this data structure. The array can (should) be cleared
+/// initially.
+
+typedef struct {
+
+ /// The clipping register
+ pcbs_power_management_bounds_reg_t pmbr;
+
+ /// The idle control register
+ pcbs_power_management_idle_control_reg_t pmicr;
+
+ /// The Pstate control register
+ pcbs_power_management_control_reg_t pmcr;
+
+} PcbsPstateRegs;
+
+#endif /* __ASSEMBLER__ */
+
+// Offsets into PcbsPstateRegs
+
+#define PCBSPSTATEREGS_PMBR 0x00
+#define PCBSPSTATEREGS_PMICR 0x08
+#define PCBSPSTATEREGS_PMCR 0x10
+
+#define SIZEOF_PCBSPSTATEREGS 0x18
+
+
+#ifndef __ASSEMBLER__
+
+/// Set a chiplet Pmax clipping Pstate
+static inline void
+set_chiplet_pmax(PcbsPstateRegs *regs, int chiplet, Pstate pmax)
+{
+ regs[chiplet].pmbr.fields.pmax_clip = pmax;
+}
+
+/// Set a chiplet Pmin clipping Pstate
+static inline void
+set_chiplet_pmin(PcbsPstateRegs *regs, int chiplet, Pstate pmin)
+{
+ regs[chiplet].pmbr.fields.pmin_clip = pmin;
+}
+
+/// Set chiplet Global and Local Pstate requests
+static inline void
+set_chiplet_pstate(PcbsPstateRegs *regs, int chiplet,
+ Pstate global, Pstate local)
+{
+ regs[chiplet].pmcr.fields.global_pstate_req = global;
+ regs[chiplet].pmcr.fields.local_pstate_req = local;
+}
+
+/// Enable/Disable/Configure chiplet Nap Pstates
+static inline void
+set_chiplet_nap_pstate(PcbsPstateRegs *regs, int chiplet,
+ Pstate pstate, int enable, int global, int latency)
+{
+ regs[chiplet].pmicr.fields.nap_pstate_req = pstate;
+ regs[chiplet].pmicr.fields.nap_pstate_en = (enable != 0);
+ regs[chiplet].pmicr.fields.nap_global_en = (global != 0);
+ regs[chiplet].pmicr.fields.nap_latency = latency;
+}
+
+/// Enable/Disable/Configure chiplet Sleep Pstates
+static inline void
+set_chiplet_sleep_pstate(PcbsPstateRegs *regs, int chiplet,
+ Pstate pstate, int enable, int global, int latency)
+{
+ regs[chiplet].pmicr.fields.sleep_pstate_req = pstate;
+ regs[chiplet].pmicr.fields.sleep_pstate_en = (enable != 0);
+ regs[chiplet].pmicr.fields.sleep_global_en = (global != 0);
+ regs[chiplet].pmicr.fields.sleep_latency = latency;
+}
+
+/// Enable/Disable/Configure chiplet Winkle Pstates
+static inline void
+set_chiplet_winkle_pstate(PcbsPstateRegs *regs, int chiplet,
+ Pstate pstate, int enable, int global, int latency)
+{
+ regs[chiplet].pmicr.fields.winkle_pstate_req = pstate;
+ regs[chiplet].pmicr.fields.winkle_pstate_en = (enable != 0);
+ regs[chiplet].pmicr.fields.winkle_global_en = (global != 0);
+ regs[chiplet].pmicr.fields.winkle_latency = latency;
+}
+
+#endif /* __ASSEMBLER__ */
+
+/// \bug These need to be defined and documented
+
+#define SLEEP_LATENCY_DISABLED 0
+#define SLEEP_LATENCY_CLOCKS_OFF 1
+#define SLEEP_LATENCY_FAST 2
+#define SLEEP_LATENCY_DEEP 3
+
+#define WINKLE_LATENCY_DISABLED 0
+#define WINKLE_LATENCY_CLOCKS_OFF 1
+#define WINKLE_LATENCY_FAST 2
+#define WINKLE_LATENCY_DEEP 3
+
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_set_pstates()
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// Parameters for the GPE procedure gpe_set_pstates()
+
+typedef struct {
+
+ // The chip configuration (for actuation purposes). Only those core
+ // chiplets with bits set in the mask will be actuated.
+ ChipConfig config;
+
+ /// This mask, comprised of a logical OR of the GPE_SET_PSTATE_*
+ /// macros, controls which register(s) is(are) actuated for each core.
+ uint64_t select;
+
+ /// The 32-bit pointer to the array of PcbsPstateRegs holding the register
+ /// data, coerced to a 64-bit unsigned. The real 32-bit pointer must be
+ /// the low-order 32 bits of this value.
+ uint64_t regs;
+
+} GpeSetPstatesParms;
+
+PoreEntryPoint gpe_set_pstates;
+
+#endif /* __ASSEMBLER__ */
+
+// Parameter offsets for gpe_set_pstates()
+
+#define GPESETPSTATESPARMS_CONFIG 0x00
+#define GPESETPSTATESPARMS_SELECT 0x08
+#define GPESETPSTATESPARMS_REGS 0x10
+
+// Register/Function select masks for gpe_set_pstates()
+
+#define GPE_SET_PSTATES_PMBR 0x01
+#define GPE_SET_PSTATES_PMICR 0x02
+#define GPE_SET_PSTATES_PMCR 0x04
+#define GPE_SET_PSTATES_SYNC 0x08
+
+#endif /* __GPE_CONTROL_H__ */
diff --git a/src/lib/gpe_control.pS b/src/lib/gpe_control.pS
new file mode 100755
index 0000000..3f3c790
--- /dev/null
+++ b/src/lib/gpe_control.pS
@@ -0,0 +1,160 @@
+// $Id: gpe_control.pS,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe_control.pS,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe_control.S
+/// \brief GPE procedures for control
+
+ .nolist
+
+#include "ssx.h"
+#include "pgas.h"
+#include "gpe.h"
+#include "gpe_control.h"
+
+ .list
+
+ .oci
+ .text.pore
+
+/// \fn gpe_set_pstates(GpeSetPstatesParms *parms)
+/// \brief Set core chiplet Pstate registers
+///
+/// This routine loops through an array of PcbsPstateRegs structures
+/// holding the register images to be actuated. A pointer to the array is
+/// provided as the \a registers parameter. For every core chiplet
+/// appearing in the \a cfg parameter, those registers marked in the \a select
+/// parameter are updated.
+///
+/// When the PMBR is being updated, an option is provided to
+/// set PCBS_PCBSPM_MODE_REG[enable_pmax_sync_interrupt] around the
+/// update of PMBR. This will cause a SYNC interrupt from each
+/// core. This mode currently does not set up the sync protocol in the PMC -
+/// the caller must do that.
+///
+/// Note that actuating the PMCR and PMICR using this method requires that the
+/// PCB Slave bit PMGP0_REG.pm_spr_override_en is set.
+#ifdef DOXYGEN_ONLY
+void gpe_set_pstates(GpeSetPstatesParms *parms);
+#endif
+/// \cond
+
+ // Register usage:
+ //
+ // A1 : Holds the (constant) pointer to the paramaters
+ // A0 : Holds the (varying) pointer to the next register block
+ // D1 : Holds the (varying) ChipConfig mask
+ // D0 : Scratch
+ // P0 : Holds the (varying) chiplet id
+
+ .global gpe_set_pstates
+
+gpe_set_pstates:
+
+ // Set up registers. The chiplet part of the ChipConfig is left
+ // justified in D1, which will be rotated on each loop.
+
+ mr A1, ETR
+ ld D0, GPESETPSTATESPARMS_REGS, A1
+ mr A0, D0
+ ld D0, GPESETPSTATESPARMS_CONFIG, A1
+ mr D1, D0
+ left_justify_core_config D1
+ lpcs P0, 0x10000000 # Load P0 with core chiplet 0 address
+ ls CTR, PGP_NCORES
+ bra start_loop
+
+set_pstates_loop:
+ // If the chiplet is not configured, simply continue
+
+ andi D0, D1, 0x8000000000000000
+ braz D0, set_pstates_continue
+
+ // Test/actuate each register in order
+
+ ldandi D0, GPESETPSTATESPARMS_SELECT, A1, GPE_SET_PSTATES_PMBR
+ braz D0, pmicr
+
+ // PMBR.
+
+ // If SYNCing, the register write is wrapped by a read-modify-write of
+ // the PCBS_PCBSPM_MODE_REG which enables the PMAX Sync
+ // acknowledge. Note that the original PCBSPM mode reg is saved and
+ // restored.
+pmbr:
+ ldandi D0, GPESETPSTATESPARMS_SELECT, A1, GPE_SET_PSTATES_SYNC
+ braz D0, nosync
+
+sync:
+ ld D0, PCBS_PCBSPM_MODE_REG, P0
+ la A1, gsp_pcbs_pcbspm_mode_reg
+ std D0, 0, A1
+ ori D0, D0, PCBS_PCBSPM_MODE_REG_ENABLE_PMC_PMAX_SYNC_NOTIFICATION
+ std D0, PCBS_PCBSPM_MODE_REG, P0
+
+ ld D0, PCBSPSTATEREGS_PMBR, A0
+ std D0, PCBS_POWER_MANAGEMENT_BOUNDS_REG, P0
+
+ ld D0, 0, A1
+ std D0, PCBS_PCBSPM_MODE_REG, P0
+ // restore A1
+ mr A1, ETR
+ bra pmicr
+
+nosync:
+ ld D0, PCBSPSTATEREGS_PMBR, A0
+ std D0, PCBS_POWER_MANAGEMENT_BOUNDS_REG, P0
+
+ // PMICR
+pmicr:
+ ldandi D0, GPESETPSTATESPARMS_SELECT, A1, GPE_SET_PSTATES_PMICR
+ braz D0, pmcr
+ ld D0, PCBSPSTATEREGS_PMICR, A0
+ std D0, PCBS_POWER_MANAGEMENT_IDLE_CONTROL_REG, P0
+
+ // PMCR
+pmcr:
+ ldandi D0, GPESETPSTATESPARMS_SELECT, A1, GPE_SET_PSTATES_PMCR
+ braz D0, set_pstates_continue
+ ld D0, PCBSPSTATEREGS_PMCR, A0
+ std D0, PCBS_POWER_MANAGEMENT_CONTROL_REG, P0
+
+set_pstates_continue:
+
+ // Increment the chiplet index and data pointer, then loop or halt.
+
+ adds P0, P0, 1
+ adds A0, A0, SIZEOF_PCBSPSTATEREGS
+ rotldi D1, D1, 1
+start_loop:
+ loop set_pstates_loop
+
+ halt
+
+ .epilogue gpe_set_pstates
+
+/// \endcond
+
+/// Data storage for procedures.
+/// Placing data in the .rodata section to prevent the 405 from stomping them.
+ .section .rodata
+ .balign 8
+/// data for gpe_set_pstates
+
+
+
+
+
+
+
+
+
+/// \cond
+
+gsp_pcbs_pcbspm_mode_reg:
+ .quad 0
+/// \endcond
diff --git a/src/lib/gpe_data.h b/src/lib/gpe_data.h
new file mode 100755
index 0000000..790d82b
--- /dev/null
+++ b/src/lib/gpe_data.h
@@ -0,0 +1,672 @@
+#ifndef __GPE_DATA_H__
+#define __GPE_DATA_H__
+
+// $Id: gpe_data.h,v 820.1 2014/08/22 16:33:56 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/fw820/procedures/lib/gpe_data.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe_data.h
+/// \brief Data structures for the GPE programs that collect raw data defined
+/// in gpe_data.S. The data structure layouts are also documented in the
+/// spreadsheet "Pgp Procedures.ods" in lib/doc.
+///
+/// \todo Add SPURR Fraction update as an option
+
+#include "ssx.h"
+#include "gpe.h"
+#include "pgp_config.h"
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_get_core_data()
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// Paramaters for gpe_get_core_data() & gpe_get_per_core_data()
+
+typedef struct {
+
+ /// gpe_get_core_data() and gpe_get_per_core_data() only collects data for
+ /// core chiplets configured in this mask.
+ ChipConfig config;
+
+ /// This mask, comprised of a logical OR of the GPE_GET_CORE_DATA_*
+ /// macros, controls which data groups are collected.
+ uint64_t select;
+
+ /// This is the 32-bit pointer (cast to a uint64_t) to the core chiplet
+ /// raw data area to be filled by this invocation of gpe_get_core_data().
+ ///
+ /// For gpe_get_core_data() (used by the lab thread coreData) this is a
+ /// pointer to an array of CoreData structures, with one structure
+ /// allocated for each possible core supported by the architecture.
+ ///
+ /// For gpe_get_per_core_data() (used by OCC FW) this is a pointer to a
+ /// single CoreData structure to be filled in by the routine.
+ uint64_t data;
+
+} GpeGetCoreDataParms;
+
+// Get data for all cores, placing data at an index into
+// GpeGetCoreDataParms->data pointer, depending on the core which got data.
+PoreEntryPoint gpe_get_core_data;
+
+// Get data for first core in GpeGetCoreDataParms->config, placing data
+// directly into GpeGetCoreDataParms->data pointer
+PoreEntryPoint gpe_get_per_core_data;
+
+#endif /* __ASSEMBLER__ */
+
+// Parameter offsets for gpe_get_core_data()
+
+#define GPEGETCOREDATAPARMS_CONFIG 0x00
+#define GPEGETCOREDATAPARMS_SELECT 0x08
+#define GPEGETCOREDATAPARMS_DATA 0x10
+
+// Data group select masks for gpe_get_core_data()
+
+#define GPE_GET_CORE_DATA_EMPATH 0x0001
+#define GPE_GET_CORE_DATA_MEMORY 0x0002
+#define GPE_GET_CORE_DATA_THROTTLE 0x0004
+#define GPE_GET_CORE_DATA_THREAD 0x0008
+#define GPE_GET_CORE_DATA_DTS_CPM 0x0010
+#define GPE_GET_CORE_DATA_PCB_SLAVE 0x0020
+
+#define GPE_GET_CORE_DATA_ALL 0x003f
+
+// Per-core data area offsets
+
+#define CORE_DATA_EMPATH_BASE 0
+#define CORE_DATA_EMPATH_SIZE 40
+
+#define CORE_DATA_MEMORY_BASE \
+ (CORE_DATA_EMPATH_BASE + CORE_DATA_EMPATH_SIZE)
+#define CORE_DATA_MEMORY_SIZE 24
+
+#define CORE_DATA_THROTTLE_BASE \
+ (CORE_DATA_MEMORY_BASE + CORE_DATA_MEMORY_SIZE)
+#define CORE_DATA_THROTTLE_SIZE 24
+
+#define CORE_DATA_THREAD_BASE(t) \
+ (CORE_DATA_THROTTLE_BASE + CORE_DATA_THROTTLE_SIZE + (24 * (t)))
+#define CORE_DATA_THREAD_SIZE (24 * 8)
+
+#define CORE_DATA_DTS_CPM_BASE \
+ (CORE_DATA_THREAD_BASE(0) + CORE_DATA_THREAD_SIZE)
+#define CORE_DATA_DTS_CPM_SIZE 40
+
+#define CORE_DATA_PCB_SLAVE_BASE \
+ (CORE_DATA_DTS_CPM_BASE + CORE_DATA_DTS_CPM_SIZE)
+#define CORE_DATA_PCB_SLAVE_SIZE 32
+
+#define CORE_DATA_OHA_BASE \
+ (CORE_DATA_PCB_SLAVE_BASE + CORE_DATA_PCB_SLAVE_SIZE)
+#define CORE_DATA_OHA_SIZE 8
+
+#define CORE_DATA_SIZE (CORE_DATA_OHA_BASE + CORE_DATA_OHA_SIZE)
+
+// Data area components. Each data group is marked with the TOD captured just
+// before each data group capture. Data groups that may have some relation to
+// frequency are also tagged with the current raw cycles reading. The offsets
+// are _byte_ offsets into a byte array. The user needs to be aware of
+// whether each datum represents a 32- or 64-bit integer.
+
+#define CORE_DATA_EMPATH_UNUSED (CORE_DATA_EMPATH_BASE + 0x00)
+#define CORE_DATA_EMPATH_TOD (CORE_DATA_EMPATH_BASE + 0x04)
+#define CORE_DATA_DISPATCH (CORE_DATA_EMPATH_BASE + 0x08)
+#define CORE_DATA_COMPLETION (CORE_DATA_EMPATH_BASE + 0x0c)
+#define CORE_DATA_FREQ_SENS_BUSY (CORE_DATA_EMPATH_BASE + 0x10)
+#define CORE_DATA_FREQ_SENS_FINISH (CORE_DATA_EMPATH_BASE + 0x14)
+#define CORE_DATA_RUN_CYCLES (CORE_DATA_EMPATH_BASE + 0x18)
+#define CORE_DATA_RAW_CYCLES (CORE_DATA_EMPATH_BASE + 0x1c)
+#define CORE_DATA_MEM_A (CORE_DATA_EMPATH_BASE + 0x20)
+#define CORE_DATA_MEM_B (CORE_DATA_EMPATH_BASE + 0x24)
+
+#define CORE_DATA_MEMORY_RAW_CYCLES (CORE_DATA_MEMORY_BASE + 0x00)
+#define CORE_DATA_MEMORY_TOD (CORE_DATA_MEMORY_BASE + 0x04)
+#define CORE_DATA_MEMORY_COUNT(p) (CORE_DATA_MEMORY_BASE + 0x08 + ((p) * 4))
+
+#define CORE_DATA_THROTTLE_RAW_CYCLES (CORE_DATA_THROTTLE_BASE + 0x00)
+#define CORE_DATA_THROTTLE_TOD (CORE_DATA_THROTTLE_BASE + 0x04)
+#define CORE_DATA_THROTTLE_IFU_THROTTLE (CORE_DATA_THROTTLE_BASE + 0x08)
+#define CORE_DATA_THROTTLE_ISU_THROTTLE (CORE_DATA_THROTTLE_BASE + 0x10)
+#define CORE_DATA_THROTTLE_IFU_ACTIVE (CORE_DATA_THROTTLE_BASE + 0x18)
+
+#define CORE_DATA_THREAD_RAW_CYCLES(t) (CORE_DATA_THREAD_BASE(t) + 0x00)
+#define CORE_DATA_THREAD_TOD(t) (CORE_DATA_THREAD_BASE(t) + 0x04)
+#define CORE_DATA_THREAD_RUN_CYCLES(t) (CORE_DATA_THREAD_BASE(t) + 0x08)
+#define CORE_DATA_THREAD_COMPLETION(t) (CORE_DATA_THREAD_BASE(t) + 0x0c)
+#define CORE_DATA_THREAD_MEM_A(t) (CORE_DATA_THREAD_BASE(t) + 0x10)
+#define CORE_DATA_THREAD_MEM_B(t) (CORE_DATA_THREAD_BASE(t) + 0x14)
+
+#define CORE_DATA_DTS_CPM_UNUSED (CORE_DATA_DTS_CPM_BASE + 0x00)
+#define CORE_DATA_DTS_CPM_TOD (CORE_DATA_DTS_CPM_BASE + 0x04)
+#define CORE_DATA_SENSOR_V0 (CORE_DATA_DTS_CPM_BASE + 0x08)
+#define CORE_DATA_SENSOR_V1 (CORE_DATA_DTS_CPM_BASE + 0x10)
+#define CORE_DATA_SENSOR_V8 (CORE_DATA_DTS_CPM_BASE + 0x18)
+#define CORE_DATA_SENSOR_V9 (CORE_DATA_DTS_CPM_BASE + 0x20)
+
+#define CORE_DATA_PCB_SLAVE_UNUSED (CORE_DATA_PCB_SLAVE_BASE + 0x00)
+#define CORE_DATA_PCB_SLAVE_TOD (CORE_DATA_PCB_SLAVE_BASE + 0x04)
+#define CORE_DATA_PMCR (CORE_DATA_PCB_SLAVE_BASE + 0x08)
+#define CORE_DATA_PMSR (CORE_DATA_PCB_SLAVE_BASE + 0x10)
+#define CORE_DATA_PM_HISTORY (CORE_DATA_PCB_SLAVE_BASE + 0x18)
+
+#define CORE_DATA_OHA_RO_STATUS_REG (CORE_DATA_OHA_BASE + 0x00)
+
+
+#ifndef __ASSEMBLER__
+
+// The GPE routine requires that the structure of core data collected by
+// gpe_get_core_data() be represented as the offsets defined above. This set
+// of structures represents the equivalent C-structure form of the data. Note
+// that the procedure formats the TOD as a 32-bit, 2 MHz timebase.
+
+typedef struct {
+ uint32_t unused;
+ uint32_t tod_2mhz;
+ uint32_t dispatch;
+ uint32_t completion;
+ uint32_t freq_sens_busy;
+ uint32_t freq_sens_finish;
+ uint32_t run_cycles;
+ uint32_t raw_cycles;
+ uint32_t mem_a;
+ uint32_t mem_b;
+} CoreDataEmpath;
+
+typedef struct {
+ uint32_t raw_cycles;
+ uint32_t tod_2mhz;
+ uint32_t count[4];
+} CoreDataPerPartitionMemory;
+
+typedef struct {
+ uint32_t raw_cycles;
+ uint32_t tod_2mhz;
+ uint32_t ifu_throttle;
+ uint32_t isu_throttle;
+ uint32_t ifu_active;
+ uint32_t undefined;
+} CoreDataThrottle;
+
+typedef struct {
+ uint32_t raw_cycles;
+ uint32_t tod_2mhz;
+ uint32_t run_cycles;
+ uint32_t completion;
+ uint32_t mem_a;
+ uint32_t mem_b;
+} CoreDataPerThread;
+
+typedef struct {
+ uint32_t unused;
+ uint32_t tod_2mhz;
+ sensors_v0_t sensors_v0;
+ sensors_v1_t sensors_v1;
+ sensors_v8_t sensors_v8;
+ sensors_v9_t sensors_v9;
+} CoreDataDtsCpm;
+
+typedef struct {
+ uint32_t unused;
+ uint32_t tod_2mhz;
+ pcbs_power_management_control_reg_t pmcr;
+ pcbs_power_management_status_reg_t pmsr;
+ pcbs_pmstatehistocc_reg_t pm_history;
+} CoreDataPcbSlave;
+
+typedef struct {
+ oha_ro_status_reg_t oha_ro_status_reg;
+} CoreDataOha;
+
+typedef struct {
+ CoreDataEmpath empath;
+ CoreDataPerPartitionMemory per_partition_memory;
+ CoreDataThrottle throttle;
+ CoreDataPerThread per_thread[8];
+ CoreDataDtsCpm dts_cpm;
+ CoreDataPcbSlave pcb_slave;
+ CoreDataOha oha;
+} CoreData;
+
+#endif // __ASSEMBLER__
+
+
+/// \defgroup core_data_status_bits Core Data Status Bits
+///
+/// These bits are set (if appropriate) in the low-order reserved area of the
+/// OHA_RO_STATUS_REG image stored in the CoreData structure.
+///
+/// @{
+
+/// This bit is set if SCOM access to the OHA returns a non-0 PIB return code
+/// when trying to write the OHA_CPM_HIST_RESET_REG to set up PC-only special
+/// wakeup.
+#define CORE_DATA_CPM_HIST_RESET_ACCESS_FAILED 0x01
+
+/// This bit is set if access to the OHA returns a non-0 PIB return code when
+/// trying to read the OHA_RO_STATUS_REG to determine core status.
+#define CORE_DATA_OHA_RO_STATUS_ACCESS_FAILED 0x02
+
+/// This bit is set if EMPATH data was requested to be collected and was
+/// collected. If this bit is not set then any EMPATH data requested to be
+/// collected will be 0.
+///
+/// If EMPATH data was requested but was not collected, then one of the bits
+/// CORE_DATA_EXPECTED_EMPATH_ERROR or CORE_DATA_UNEXPECTED_EMPATH_ERROR will
+/// be set, and the error code is stored in the OHA_RO_STATUS register image.
+#define CORE_DATA_EMPATH_COLLECTED 0x04
+
+/// This bit is set if core sensor data (DTS/CPM) was collected. If this bit
+/// is not set then core DTS/CPM data will be 0.
+#define CORE_DATA_CORE_SENSORS_COLLECTED 0x08
+
+/// This bit is set if L3 sensor data (DTS/CPM) was collected. If this bit is
+/// not set then L3 DTS/CPM data will be 0.
+#define CORE_DATA_L3_SENSORS_COLLECTED 0x10
+
+/// If this bit is set, then an "expected" error was encountered while
+/// collecting EMPATH data. Given that the procedure has gone through the
+/// PC-only special wakeup protocol, the only "expected" error is the
+/// intermittant PCB error code #4 due to HW280375.
+#define CORE_DATA_EXPECTED_EMPATH_ERROR 0x20
+
+/// If this bit is set, then an "unexpected" error was encountered while
+/// collecting EMPATH data. Given that the procedure has gone through the
+/// PC-only special wakeup protocol, the only "expected" error is the
+/// intermittant PCB error code #4 due to HW280375. If this bit is set it
+/// indicates a serious problem.
+#define CORE_DATA_UNEXPECTED_EMPATH_ERROR 0x40
+
+/// The first bit of the 4-bit PCB parity + error code, in the event a PCB
+/// error is encountered during EMPATH processing.
+#define CORE_DATA_EMPATH_ERROR_LOCATION 52
+
+#define CORE_DATA_EMPATH_ERROR_BITS 4
+
+/// @}
+
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_get_core_data_fast()
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// Paramaters for gpe_get_chip_data_fast()
+
+typedef struct {
+
+ /// gpe_get_core_data_fast() only collects data for chiplets configured in
+ /// this mask.
+ ChipConfig config;
+
+ /// This mask, comprised of a logical OR of the GPE_GET_CORE_DATA_FAST_*
+ /// macros, controls which data groups are collected.
+ uint64_t select;
+
+ /// This is the 32-bit pointer (cast to a uint64_t) to the chiplet raw
+ /// data area to be filled by this invocation of gpe_get_core_data_fast().
+ uint64_t data;
+
+} GpeGetChipDataFastParms;
+
+PoreEntryPoint gpe_get_core_data_fast;
+
+#endif /* __ASSEMBLER__ */
+
+// Parameter offsets for gpe_get_core_data()
+
+#define GPEGETCOREDATAFASTPARMS_CONFIG 0x00
+#define GPEGETCOREDATAFASTPARMS_SELECT 0x08
+#define GPEGETCOREDATAFASTPARMS_DATA 0x10
+
+// Data group select masks for gpe_get_core_data_fast()
+
+#define GPE_GET_CORE_DATA_FAST_FREQ_TARGET 0x0001
+
+#define CORE_DATA_FAST_FREQ_TARGET_BASE 0x0
+#define CORE_DATA_FAST_FREQ_TARGET_SIZE (8 + (PGP_NCORES * 8))
+
+#define CORE_DATA_FAST_SIZE \
+ (CORE_DATA_FAST_FREQ_TARGET_BASE + CORE_DATA_FAST_FREQ_TARGET_SIZE)
+
+#define CORE_DATA_FAST_FREQ_TARGET_UNUSED (CORE_DATA_FAST_FREQ_TARGET_BASE + 0)
+#define CORE_DATA_FAST_FREQ_TARGET_TOD (CORE_DATA_FAST_FREQ_TARGET_BASE + 4)
+#define CORE_DATA_FAST_FREQ_TARGET_LPFTSR(n) (CORE_DATA_FAST_FREQ_TARGET_BASE + 8 + ((n) * 8))
+
+#ifndef __ASSEMBLER__
+
+typedef struct {
+ uint32_t unused;
+ uint32_t tod_2mhz;
+ pcbs_local_pstate_frequency_target_status_reg_t lpftsr[PGP_NCORES];
+} CoreDataFast;
+
+#endif // __ASSEMBLER__
+
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_get_chip_data()
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// Paramaters for gpe_get_chip_data()
+
+typedef struct {
+
+ /// This mask, comprised of a logical OR of the GPE_GET_CHIP_DATA_*
+ /// macros, controls which data groups are collected.
+ uint64_t select;
+
+ /// This is the 32-bit pointer (cast to a uint64_t) to the chiplet raw
+ /// data area to be filled by this invocation of gpe_get_chip_data().
+ uint64_t data;
+
+} GpeGetChipDataParms;
+
+PoreEntryPoint gpe_get_chip_data;
+
+#endif /* __ASSEMBLER__ */
+
+// Parameter offsets for gpe_get_chip_data()
+
+#define GPEGETCHIPDATAPARMS_SELECT 0x00
+#define GPEGETCHIPDATAPARMS_DATA 0x08
+
+// Data group select masks for gpe_get_chip_data()
+
+#define GPE_GET_CHIP_DATA_OVERCOMMIT 0x0001
+
+#define CHIP_DATA_OVERCOMMIT_BASE 0
+#define CHIP_DATA_OVERCOMMIT_SIZE 56
+
+#define CHIP_DATA_SIZE (CHIP_DATA_OVERCOMMIT_BASE + CHIP_DATA_OVERCOMMIT_SIZE)
+
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_get_mem_data()
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// Paramaters for gpe_get_mem_data()
+
+typedef struct {
+
+ /// The index (0 .. PGP_NCENTAUR - 1) of the Centaur whose sensor cache
+ /// data to collect, or -1 to bypass collection.
+ uint64_t collect;
+
+ /// The index (0 .. PGP_NCENTAUR - 1) of the Centaur to "poke" to cause it
+ /// to begin collecting the next round of data into its sensor cache, or
+ /// -1 to bypass updating.
+ uint64_t update;
+
+ /// This is the 32-bit pointer (cast to a uint64_t) to the chiplet raw
+ /// data area to be filled by this invocation of gpe_get_mem_data(). This
+ /// pointer need not be valid if the \a collect field of the structure is
+ /// -1.
+ uint64_t data;
+
+ /// The return code returned by the last invocation of the procedure; See
+ /// \ref gpe_get_mem_date_rc.
+ uint64_t rc;
+
+ /// The 'update' timestamp
+ ///
+ /// This is the value of the chip TOD at the time the 'update' phase of
+ /// the procedure is run, as close as possible to the "poke" of the
+ /// Centaur. This timestamp indicates the time that the Centaur sensor
+ /// cache line collection was kicked off. The timestamp is collected even
+ /// if the \a update field of the structure is -1. Consistent with
+ /// gpe_get_core_data() the timestamp is reduced to a 32-bit, 2MHz
+ /// timestamp, and stored in the low-order half of a doubleword.
+ uint32_t pad;
+ uint32_t tod_2mhz;
+
+} GpeGetMemDataParms;
+
+PoreEntryPoint gpe_get_mem_data;
+
+#endif /* __ASSEMBLER__ */
+
+// Parameter offsets for gpe_get_mem_data()
+
+#define GPEGETMEMDATAPARMS_COLLECT 0x00
+#define GPEGETMEMDATAPARMS_UPDATE 0x08
+#define GPEGETMEMDATAPARMS_DATA 0x10
+#define GPEGETMEMDATAPARMS_RC 0x18
+#define GPEGETMEMDATAPARMS_PAD_TOD 0x20
+#define SIZEOF_GPEGETMEMDATAPARMS 0x28
+
+
+/// \defgroup gpe_mem_data_rc gpe_get_mem_data() Error Return Codes
+///
+/// The gpe_get_mem_data() procedure deposits a non-0 return code into the \a
+/// rc field of its parameter structure in the event of failure. Note that the
+/// procedure stops on the first failure, and in particular the TOD timestamp
+/// is not valid in the event of failure.
+///
+/// @{
+
+/// The procedure died, but no other information is available. This would have
+/// signalled an error interrupt and the PORE flex request will contain FFDC
+/// about the failure.
+#define GPE_GET_MEM_DATA_DIED 1
+
+/// The \a collect parameter was invalid, i.e. it either was an illegal index
+/// or the index of an unconfigured MCS or Centaur.
+#define GPE_GET_MEM_DATA_COLLECT_INVALID 2
+
+/// The \a update parameter was invalid, i.e. it either was an illegal index
+/// or the index of an unconfigured MCS or Centaur.
+#define GPE_GET_MEM_DATA_UPDATE_INVALID 3
+
+/// The global G_centaurConfiguration is not valid
+#define GPE_GET_MEM_DATA_NOT_CONFIGURED 4
+
+/// The workaround for HW256773 failed. To diagnose the failure look at the
+/// 'rc' field of the global variable G_hw256773.
+#define GPE_GET_MEM_DATA_HW256773_FAILED 5
+
+/// This code is established in the RC field prior to collecting the Centaur
+/// sensor cache data. If this RC is observed on a hard failure it most likely
+/// indicates an error assiciated with the Centaur whose data was being
+/// collected.
+#define GPE_GET_MEM_DATA_SENSOR_CACHE_FAILED 6
+
+/// This code is established in the RC field prior to "poking" the Centaur (if
+/// any) that is being updated this pass. If this RC is observed on a hard
+/// failure it most likely indicates an error associated with the Centaur
+/// being updated.
+#define GPE_GET_MEM_DATA_UPDATE_FAILED 7
+
+/// @}
+
+
+#ifndef __ASSEMBLER__
+
+// The GPE routine requires that the structure of centaur data collected by
+// gpe_get_mem_data() be represented as the offsets defined above. This set
+// of structures represent the equivalent C-structure form of the data. Note
+// that the procedure formats the TOD as a 32-bit, 2 MHz timebase.
+
+/// Layout of data collected from MCS
+///
+/// This is currently empty, however to avoid code rewrites if any data is
+/// ever collected here the structure is declared and placed in the larger
+/// MemData structure. The fact that the structure is empty does not seem to
+/// cause problems.
+
+typedef struct {
+} MemDataMcs;
+
+/// The layout of a Centaur chip thermal sensor
+///
+/// \todo Centaur spec. has no doc. on layout of these bits; Waiting for more
+/// info from Centaur team.
+
+typedef union {
+ uint16_t value;
+ struct {
+ uint16_t value;
+ } fields;
+} centaur_sensor_t;
+
+/// The layout of a Centaur DIMM sensor
+///
+/// Mnemonic macros for the 2-bit status codes (DIMM_SENSOR_STATUS_*) are
+/// currently defined in ssx/pgp/pgp_common.h
+///
+/// \todo Waiting for more info from Centaur team on how to interpret
+
+typedef union {
+ uint16_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint16_t crit_trip : 1;
+ uint16_t alarm_trip : 1;
+ uint16_t below_trip : 1;
+ uint16_t sign_bit : 1;
+ uint16_t temperature : 8;
+ uint16_t temp_fraction : 2;
+ uint16_t status : 2;
+#else
+ uint16_t status : 2;
+ uint16_t temp_fraction : 2;
+ uint16_t temperature : 8;
+ uint16_t sign_bit : 1;
+ uint16_t below_trip : 1;
+ uint16_t alarm_trip : 1;
+ uint16_t crit_trip : 1;
+#endif
+ } fields;
+} centaur_dimm_sensor_t;
+
+/// The layout of the status bits of the sensor cache line
+///
+/// The sensor cache-line aggregator gets each element of the sensor cache
+/// line by an internal SCOM. The individual PCB return codes for each SCOM
+/// are collected here (3 bits each) - note that many of the 32-bit registers
+/// come back in a single 64-bit internal SCOM. Normally this register will
+/// always read as 0 indicating all data was collected successfully. The PCB
+/// error codes (PCB_ERROR_*) are currently defined in ssx/pgp/pgp_common.h.
+
+typedef union {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t mba01_rw : 3; /// mba01_rd[+ wr]
+ uint64_t mba01_ap : 3; /// mba01_act[+ powerups]
+ uint64_t mba23_rw : 3; /// mba23_rd[+ wr]
+ uint64_t mba23_ap : 3; /// mba23_act[+ powerups]
+ uint64_t mba_sc : 3; /// mba01[+ 23]_spec_cancels
+ uint64_t lp2_exits : 3; /// lp2_exits
+ uint64_t frame_count : 3; /// frame_count
+ uint64_t mba01_chrw : 3; /// mba01_cache_hits_rd[+ wr]
+ uint64_t mba23_chrw : 3; /// mba23_cache_hits_rd[+ wr]
+ uint64_t mba01_iac_bl : 3; /// mba01_intreq_arr_cnt_base[+ low]
+ uint64_t mba01_iac_mh : 3; /// mba01_intreq_arr_cnt_med[+ high]
+ uint64_t mba23_iac_bl : 3; /// mba23_intreq_arr_cnt_base[+ low]
+ uint64_t mba23_iac_mh : 3; /// mba23_intreq_arr_cnt_med[+ high]
+ uint64_t iac_high_latency : 3; /// intereq_arr_cnt_high_latency
+ uint64_t centaur01 : 3; /// centaur_thermal_sensor[0 - 1]
+ uint64_t dimm03 : 3; /// dimm_thermal_sensor[0 - 3]
+ uint64_t dimm47 : 3; /// dimm_thermal_sensor[4 - 7]
+ uint64_t reserved : 13;
+#else
+ uint64_t reserved : 13;
+ uint64_t dimm47 : 3; /// dimm_thermal_sensor[4 - 7]
+ uint64_t dimm03 : 3; /// dimm_thermal_sensor[0 - 3]
+ uint64_t centaur01 : 3; /// centaur_thermal_sensor[0 - 1]
+ uint64_t iac_high_latency : 3; /// intereq_arr_cnt_high_latency
+ uint64_t mba23_iac_mh : 3; /// mba23_intreq_arr_cnt_med[+ high]
+ uint64_t mba23_iac_bl : 3; /// mba23_intreq_arr_cnt_base[+ low]
+ uint64_t mba01_iac_mh : 3; /// mba01_intreq_arr_cnt_med[+ high]
+ uint64_t mba01_iac_bl : 3; /// mba01_intreq_arr_cnt_base[+ low]
+ uint64_t mba23_chrw : 3; /// mba23_cache_hits_rd[+ wr]
+ uint64_t mba01_chrw : 3; /// mba01_cache_hits_rd[+ wr]
+ uint64_t frame_count : 3; /// frame_count
+ uint64_t lp2_exits : 3; /// lp2_exits
+ uint64_t mba_sc : 3; /// mba01[+ 23]_spec_cancels
+ uint64_t mba23_ap : 3; /// mba23_act[+ powerups]
+ uint64_t mba23_rw : 3; /// mba23_rd[+ wr]
+ uint64_t mba01_ap : 3; /// mba01_act[+ powerups]
+ uint64_t mba01_rw : 3; /// mba01_rd[+ wr]
+#endif
+ } fields;
+} centaur_scom_status_t;
+
+/// The layout of the Centaur sensor cache line
+
+typedef struct {
+ uint32_t mba01_rd; // PP1/MBA01 Reads
+ uint32_t mba01_wr; // PP1/MBA01 Writes
+ uint32_t mba01_act; // PP1/MBA01 Activations
+ uint32_t mba01_powerups; // PP1/MBA01 PowerUps
+
+ uint32_t mba23_rd; // PP2/MBA23 Reads
+ uint32_t mba23_wr; // PP2/MBA23 Writes
+ uint32_t mba23_act; // PP2/MBA23 Activations
+ uint32_t mba23_powerups; // PP2/MBA23 PowerUps
+
+ uint32_t mba01_spec_cancels; // PP1/MBA01 Speculative Cancels
+ uint32_t mba23_spec_cancels; // PP2/MBA23 Speculative Cancels
+#ifdef _BIG_ENDIAN
+ uint32_t eventn :4; // EVENTN
+ uint32_t reserved_0 :20; // Reserved
+ uint32_t lp2_exits :8; // LP2 Exits
+#else
+ uint32_t lp2_exits :8; // LP2 Exits
+ uint32_t reserved_0 :20; // Reserved
+ uint32_t eventn :4; // EVENTN
+#endif
+ uint32_t frame_count; // Frame Count (timestamp)
+
+ uint32_t mba01_cache_hits_rd; // PP1/MBA01 Cache Hits Reads
+ uint32_t mba01_cache_hits_wr; // PP1/MBA01 Cache Hits Writes
+ uint32_t mba23_cache_hits_rd; // PP2/MBA23 Cache Hits Reads
+ uint32_t mba23_cache_hits_wr; // PP2/MBA23 Cache Hits Writes
+
+ uint32_t mba01_intreq_arr_cnt_base; // PP1/MBA01 Inter-Req Arrival Count Base
+ uint32_t mba01_intreq_arr_cnt_low; // PP1/MBA01 Inter-Req Arrival Count Low
+ uint32_t mba01_intreq_arr_cnt_med; // PP1/MBA01 Inter-Req Arrival Count Med
+ uint32_t mba01_intreq_arr_cnt_high; // PP1/MBA01 Inter-Req Arrival Count High
+
+ uint32_t mba23_intreq_arr_cnt_base; // PP2/MBA23 Inter-Req Arrival Count Base
+ uint32_t mba23_intreq_arr_cnt_low; // PP2/MBA23 Inter-Req Arrival Count Low
+ uint32_t mba23_intreq_arr_cnt_med; // PP2/MBA23 Inter-Req Arrival Count Med
+ uint32_t mba23_intreq_arr_cnt_high; // PP2/MBA23 Inter-Req Arrival Count High
+
+ uint32_t intreq_arr_cnt_high_latency; // Inter-Req Arrival Count High Latency
+ centaur_sensor_t centaur_thermal_sensor[2]; // Centaur Thermal Sensors 0-1
+ centaur_dimm_sensor_t dimm_thermal_sensor[8]; // DIMM Thermal Sensors 0-7
+ centaur_scom_status_t status; // Aggregated internal SCOM status
+} MemDataSensorCache;
+
+typedef struct {
+ MemDataMcs mcs; // TODO: Not collected yet
+ MemDataSensorCache scache; // OCC Centaur Sensor Cache Line (128 bytes)
+} MemData;
+
+#endif // __ASSEMBLER__
+
+
+// Data offsets for gpe_get_mem_data()
+
+#define MEM_DATA_MCS_BASE 0
+#define MEM_DATA_MCS_SIZE 0
+
+#define MEM_DATA_CENTAUR_BASE (MEM_DATA_MCS_BASE + MEM_DATA_MCS_SIZE)
+#define MEM_DATA_CENTAUR_SIZE 128
+
+#define MEM_DATA_SIZE (MEM_DATA_MCS_SIZE + MEM_DATA_CENTAUR_SIZE)
+
+#endif /* __GPE_DATA_H__ */
diff --git a/src/lib/gpe_data.pS b/src/lib/gpe_data.pS
new file mode 100755
index 0000000..2338276
--- /dev/null
+++ b/src/lib/gpe_data.pS
@@ -0,0 +1,1585 @@
+// $Id: gpe_data.pS,v 820.1 2014/08/22 16:33:56 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/fw820/procedures/lib/gpe_data.pS,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe_data.S
+/// \brief GPE procedures for raw data collection
+
+ .nolist
+
+#include "ssx.h"
+#include "pgas.h"
+#include "pgp_config.h"
+#include "gpe.h"
+#include "gpe_pba.h"
+#include "gpe_data.h"
+#include "gpe_scom.h"
+
+ .list
+
+ .oci
+ .text.pore
+
+ .revision_string G_gpe_data_pS_revision, "$Revision: 820.1 $"
+
+/// \cond
+
+////////////////////////////////////////////////////////////////////////////
+// Common Macros
+////////////////////////////////////////////////////////////////////////////
+
+ // Get a full 64-bit SCOM and write to OCI space. Clobbers a Data
+ // register.
+
+ .macro get_scom, dx, scom, chiplet_base, oci_offset, oci_base
+
+ ld (\dx), (\scom), (\chiplet_base)
+ std (\dx), (\oci_offset), (\oci_base)
+
+ .endm
+
+
+ // Tag a data group with TOD[24..56]. This macro clobbers a data
+ // register.
+
+ .macro tag_data_group, base, dx, oci_base, tod_chiplet
+
+ ld (\dx), TOD_VALUE_REG, (\tod_chiplet)
+ extrdi (\dx), (\dx), 32, 24
+ std (\dx), (\base), (\oci_base)
+
+ .endm
+
+
+ // An OCI - OCI copy. Dx gets clobbered
+
+ .macro ocicopy, dx, src_offset, src_base, dst_offset, dst_base
+
+ ld (\dx), (\src_offset), (\src_base)
+ std (\dx), (\dst_offset), (\dst_base)
+
+ .endm
+
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_get_core_data()
+////////////////////////////////////////////////////////////////////////////
+
+ // Macros for gpe_get_core_data().
+
+ // Tag a core data group with TOD[24..56], and optionally with the raw
+ // cycle count. Always clobbers D0 and D1. If called with store=0, the
+ // tag ends up in D0.
+
+ .macro tag_core_data_group, base, oci_base, pc_chiplet, tod_chiplet, \
+ raw=1, store=1
+
+ ld D0, TOD_VALUE_REG, (\tod_chiplet)
+ extrdi D0, D0, 32, 24
+ .if (\raw)
+ sti PC_OCC_SPRC, (\pc_chiplet), SPRN_CORE_RAW_CYCLE
+ ld D1, PC_OCC_SPRD, (\pc_chiplet)
+ rotldi D1, D1, 32
+ or D0, D0, D1
+ .endif
+ .if (\store)
+ std D0, (\base), (\oci_base)
+ .endif
+ .endm
+
+
+ // Get a pair of SCOMs from PC, packing them into a single 64-bit value
+ // and writing them to OCI space. Clobbers D0 and D1. Assumes that
+ // PC_OCC_SPRC is set up for autoincrement access as well.
+ //
+ // This macro takes advantage of the fact that PC-unit SCOMs only
+ // define the lower 32 bits, and the high-32 are 0.
+
+ .macro get_pc_pair, offset, oci_base, chiplet_base
+
+ ld D0, PC_OCC_SPRD, (\chiplet_base)
+ ld D1, PC_OCC_SPRD, (\chiplet_base)
+ rotldi D0, D0, 32
+ or D0, D0, D1
+ std D0, (\offset), (\oci_base)
+
+ .endm
+/// \endcond
+
+
+
+
+/// \fn gpe_get_core_data(GpeGetCoreDataParms *parms);
+/// \brief Get core chiplet raw data on performance/thermal timescale
+///
+/// This routine uses get_per_core_raw_data() to collect raw data for one or
+/// more cores. The \a data field of the GpeGetCoreDataParms parameter
+/// contains a pointer to an array of CoreData* pointers. Data for every core
+/// configured in the configuration mask is collected - it is assumed that the
+/// data area for the data exists.
+///
+/// This entry point is used by the lab thread 'coreData'.
+#ifdef DOXYGEN_ONLY
+void gpe_get_core_data(GpeGetCoreDataParms *parms);
+#endif
+/// \cond
+
+ // Register usage:
+ //
+ // ETR : At entry, holds the parameter pointer.
+ // A1 : Holds the pointer to the paramaters
+ // A0 : Holds the (varying) pointer to the data area for the
+ // current core.
+ // P1 : Holds the (constant) chiplet id of the TOD
+ // P0 : Holds the (varying) chiplet id of the current core
+ // SPRG0 : Temporary storage of the chiplet mask as it rotates.
+ // CTR : Loops through core chiplets indices
+ // D1 : Scratch
+ // D0 : Scratch
+
+ .global gpe_get_core_data
+
+gpe_get_core_data:
+
+ // Set up registers. The chiplet part of the ChipConfig is left
+ // justified then stored in SPRG0, where it will be maintained as we
+ // rotate through it. Note that SPRG0 is 32 bits, so it needs to be
+ // manipulated from the low-order portion of a data register.
+
+ mr D0, ETR
+ la A1, core_data_parms
+ std D0, 0, A1
+ mr A1, D0
+
+ ld D0, GPEGETCOREDATAPARMS_DATA, A1
+ mr A0, D0
+
+ ld D0, GPEGETCOREDATAPARMS_CONFIG, A1
+ left_justify_core_config D0
+ rotldi D0, D0, 32
+ mr SPRG0, D0
+
+ lpcs P1, TOD_VALUE_REG
+ ls P0, 0x10
+ ls CTR, (PGP_NCORES - 1) # PORE does test, then decr. and branch
+
+core_data_loop:
+
+ // Load/test the chiplet mask, and store the rotated mask back to
+ // SPRG0. If the chiplet is not configured, simply continue.
+
+ mr D0, SPRG0
+ andi D1, D0, 0x80000000
+ rotldi D0, D0, 1
+ mr SPRG0, D0
+ braz D1, core_data_continue
+
+ // Collect Raw Data for Core specified by P0, stored at A0
+
+ bsr get_per_core_raw_data
+
+core_data_continue:
+
+ // Increment the core chiplet index and data pointer, then loop or
+ // halt.
+
+ adds P0, P0, 1
+ adds A0, A0, CORE_DATA_SIZE
+ loop core_data_loop
+
+ halt
+
+ .epilogue gpe_get_core_data
+
+/// \endcond
+
+
+
+/// \fn gpe_get_per_core_data(GpeGetCoreDataParms *parms);
+/// \brief Get core chiplet raw data for a single core
+///
+/// This routine uses get_per_core_raw_data() to collect raw data for a single
+/// core. Regardless of the configuration mask setting, this routine exits
+/// after collecting data for a single core. The \a data field of the
+/// GpeGetCoreDataParms contains a pointer to a single CoreData object.
+///
+/// This entry point is used by OCC product firmware.
+#ifdef DOXYGEN_ONLY
+void gpe_get_per_core_data(GpeGetCoreDataParms *parms);
+#endif
+/// \cond
+
+ // Register usage:
+ //
+ // A1 : Holds the pointer to the paramaters
+ // A0 : Holds the (varying) pointer to the data area for the
+ // current core, as well as the data pointer-pointer while
+ // searching for a configured core.
+ // P1 : Holds the (constant) chiplet id of the TOD
+ // P0 : Holds the (varying) chiplet id of the current core
+ // SPRG0 : Temporary storage of the chiplet mask as it rotates.
+ // CTR : Loops through core chiplets indices
+ // D1 : Scratch
+ // D0 : Scratch
+
+ .global gpe_get_per_core_data
+
+gpe_get_per_core_data:
+
+ // Set up registers. A1 gets the parameters (which must also be
+ // stored in memory), the the ETR is replaced by the data
+ // pointer-pointer. The chiplet part of the ChipConfig is left
+ // justified then stored in SPRG0, where it will be maintained as we
+ // rotate through it. Note that SPRG0 is 32 bits, so it needs to be
+ // manipulated from the low-order portion of a data register.
+
+ mr D0, ETR
+ la A1, core_data_parms
+ std D0, 0, A1
+ mr A1, D0
+
+ ld D0, GPEGETCOREDATAPARMS_DATA, A1
+ mr A0, D0
+
+ ld D0, GPEGETCOREDATAPARMS_CONFIG, A1
+ left_justify_core_config D0
+ rotldi D0, D0, 32
+ mr SPRG0, D0
+
+ lpcs P1, TOD_VALUE_REG
+ ls P0, 0x10
+ ls CTR, (PGP_NCORES - 1) # PORE does test, then decr. and branch
+
+per_core_data_loop:
+
+ // Load/test the chiplet mask, and store the rotated mask back to
+ // SPRG0. If the chiplet is not configured, simply continue.
+
+ mr D0, SPRG0
+ andi D1, D0, 0x80000000
+ rotldi D0, D0, 1
+ mr SPRG0, D0
+ braz D1, per_core_data_continue
+
+ // Collect Raw Data for Core specified by P0, stored at A0
+
+ bsr get_per_core_raw_data
+
+ // Exit GPE after gathering data for one core
+ bra per_core_data_complete
+
+per_core_data_continue:
+
+ // Increment the core chiplet index and data pointer, then loop or
+ // halt.
+ adds P0, P0, 1
+ loop per_core_data_loop
+
+per_core_data_complete:
+ halt
+
+ .epilogue gpe_get_per_core_data
+
+/// \endcond
+
+/// \fn gpe_get_per_core_raw_data();
+/// \brief Get core chiplet raw data for one core
+///
+/// This routine collects raw data from the core designated by P0. Data is
+/// grouped into logical groups, and the collection of any group is enabled by
+/// a group select mask. All data and thread groups (except the PCB Slave
+/// group) are tagged with the TOD and raw cycle counts sampled immediately
+/// before the group data are sampled.
+///
+/// The final PCB Slave data group should always be selected (but \e is
+/// configurable) as it contains the PCB Slave Power Management history
+/// register. This register value is required to determine how to interpret
+/// the other data items.
+///
+/// The PC counters are collected using the SPRC/SPRD autoincrement
+/// mechanism. Be very cautious about changing this code or the data layout
+/// because the counter order is fixed by hardware and the data layout
+/// reflects the most natural way to collect the data based on the
+/// hardware. Note that SPRC/SPRD autoincrement IS NOT OPTIONAL for the OCC
+/// registers, regardless of how it may be documented in the PC workbook, or
+/// the fact that the procedure redundantly sets up auto-increment. That is,
+/// the hardware always does auto-increment for these SPRC/SPRD reads.
+///
+/// The data structure includes a TOD/Raw cycles word for each set of counters
+/// for each thread. Due to the amount of time it may take to collect
+/// per-thread data for 8 threads, errors of 1% or more could accrue at thread
+/// 7 if each thread group were not individually tagged. To avoid having to
+/// SCOM the TOD plus a SCOMC/SCOMD pair to create each thread group header
+/// however, we instead tag thread0 with actual data, then tag the remaining
+/// thread groups with interpolated TOD/Raw cycle values computed by obtaining
+/// a tag at the end of all threads. This takes only a little more time than
+/// the simpler expedient of copying the Tod/Raw Cycles count from thread0 to
+/// threads 1-7.
+///
+/// At the entry point of the routine, the code must go through the PC-ONLY
+/// special wakeup procedure to ensure that we can SCOM a napping core. This
+/// has to be done carefully as it's possible that SCOM access to the OHA will
+/// result in a 0x1 PIB response if the core is coming out of deep
+/// sleep/winkle. This PIB response would discombobulate the PORE engine so we
+/// have to run these SCOMs with error handling done manually. If a core is
+/// inaccessible due to an idle state we clear all of the configured EMPATH
+/// counts, per-thread counts and DTS and CPM for the core. If the core is
+/// only asleep (not winkled) then we attempt to read the DTS and CPM for the
+/// L3. Note that TOD timestamps are always collected, even if the data is
+/// simply zeroed.
+///
+/// A modified copy of the OHA_RO_STATUS_REG read during the PC-only SPWU
+/// protocol is stored with the data. Several low-order reserved bits of the
+/// register image are programmed with the following masks. See the
+/// documentation for these bits for full details.
+///
+/// - CORE_DATA_CPM_HIST_RESET_ACCESS_FAILED
+/// - CORE_DATA_OHA_RO_STATUS_ACCESS_FAILED
+/// - CORE_DATA_EMPATH_COLLECTED
+/// - CORE_DATA_CORE_SENSORS_COLLECTED
+/// - CORE_DATA_L3_SENSORS_COLLECTED
+/// - CORE_DATA_EXPECTED_EMPATH_ERROR
+/// - CORE_DATA_UNEXPECTED_EMPATH_ERROR
+///
+/// In the event of expected or unexpected errors during EMPATH data
+/// collection the 3-bit PCB error code will also be stored at bit
+/// CORE_DATA_EMPATH_ERROR_LOCATION.
+///
+/// This is the PC-ONLY Special Wakeup + processing Sequence
+///
+/// 1. Switch to manual error handling mode and disable PIB errors.
+///
+/// 2. Write OHA_CPM_HIST_RESET_REG.pconly_special_wakeup = 1. If the write
+/// fails, note the failure and go to the bypass routine.
+///
+/// 3. Read OHA_RO_STATUS_REG. If the SCOM fails, access is impossible and
+/// noted. If the special wakeup complete is not immediately set that error is
+/// also noted. If either test fails then go to the bypass routine. Otherwise
+/// note success and continue.
+///
+/// 4. Attempt to collect sensor (DTS/CPM) data for the core and L3. This must
+/// be done with manual error handling as these SCOMs are not protected by
+/// PC-only SPWU.
+///
+/// 5. Switch to a private error handling table setup that allows the
+/// procedure to catch PCB data errors during EMPATH processing. This is
+/// required as a workaround for HW280375.
+///
+/// 6. Collect EMPATH data.
+///
+/// 7. Restore error handling; Clear the PC-only SPWU bit.
+///
+/// 8. Collect PCB Slave data.
+///
+/// When the core is inaccessible a similar "bypass" sequence to the data
+/// collection sequence is run, however all data other than timestamps and the
+/// PCB Slave data are stored as 0, and the PC-Only SPWU bit is cleared before
+/// error handling is re-enabled. The bypass routine will also take care of
+/// attempting to collect L3 DTS/CPM data for sleeping cores.
+///
+/// Note that the PCB slave data must be collected after the removal of
+/// PC-only special wakeup, otherwise a napping core will always appear to be
+/// in the run state.
+///
+/// Several global variables are required. Thus this procedure and its callers
+/// are not reentrant.
+#ifdef DOXYGEN_ONLY
+ void get_per_core_raw_data();
+#endif
+/// \cond
+
+get_per_core_raw_data:
+
+ // At entry:
+ //
+ // P0 : The chiplet to access (invariant)
+ // A0 : Pointer to the data area for the core (invariant)
+ // SPRG0 : Reserved to the caller (invariant)
+ // CTR : Reserved to the caller (invariant)
+ //
+ // core_data_parms: Holds the pointer to the parameters
+ //
+ // At exit:
+ //
+ // All other registers are scratched by this routine
+
+ // (1) Switch to manual error handling mode and disable PIB errors.
+
+ mr D0, EMR
+ la A1, saved_emr
+ std D0, 0, A1
+
+ andi D0, D0, ~(PORE_ERROR_MASK_ENABLE_ERR_HANDLER0 | \
+ PORE_ERROR_MASK_ENABLE_ERR_OUTPUT0 | \
+ PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 | \
+ PORE_ERROR_MASK_STOP_EXE_ON_ERROR0)
+ mr EMR, D0
+ la A1, manual_emr
+ std D0, 0, A1
+
+
+ // (2) Write OHA_CPM_HIST_RESET_REG.pconly_special_wakeup = 1. If the
+ // write fails, note the failure and go to the bypass routine.
+
+ sti OHA_CPM_HIST_RESET_REG, P0, \
+ OHA_CPM_HIST_RESET_REG_PCONLY_SPECIAL_WAKEUP
+ tprcbz D0, 3f
+
+ sti CORE_DATA_OHA_RO_STATUS_REG, A0, \
+ CORE_DATA_CPM_HIST_RESET_ACCESS_FAILED
+ bra bypass_core_data
+
+
+ // 3. Read OHA_RO_STATUS_REG. If the SCOM fails, access is impossible
+ // and noted. If the special wakeup complete is not immediately set
+ // that error is also noted. If either test fails then go to the
+ // bypass routine. Otherwise note success and continue.
+
+3:
+ ld D0, OHA_RO_STATUS_REG, P0
+ tprcbz D1, 31f
+
+ sti CORE_DATA_OHA_RO_STATUS_REG, A0, \
+ CORE_DATA_OHA_RO_STATUS_ACCESS_FAILED
+ bra bypass_core_data
+
+31:
+ std D0, CORE_DATA_OHA_RO_STATUS_REG, A0
+
+ // If either access is impossible we go to bypass. The bypass code
+ // will read the L3 DTS/CPM data if it is possible.
+
+ andi D1, D0, (OHA_RO_STATUS_REG_CORE_ACCESS_IMPOSSIBLE | \
+ OHA_RO_STATUS_REG_ECO_ACCESS_IMPOSSIBLE)
+ branz D1, bypass_core_data
+
+ andi D1, D0, OHA_RO_STATUS_REG_SPECIAL_WAKEUP_COMPLETED
+ braz D1, bypass_core_data
+
+
+ // 4. Attempt to collect sensor (DTS/CPM) data. This must be done with
+ // manual error handling (in effect here) as these SCOMs are not
+ // protected by a PC-only SPWU.
+
+ la A1, core_data_parms
+ ld D0, 0, A1
+ mr A1, D0
+
+ bsr getSensors
+
+
+ // 5. Switch to a private error handling table setup that allows the
+ // procedure to catch PCB errors during EMPATH processing.
+
+ // NB: We know that this is being run as a PoreFlex job from OCC FW on
+ // either GPE0 or GPE1. We also know that the default error mask does
+ // not handle any errors with a table.
+
+ tebngpe0 D0, 1f
+ la A1, PORE_GPE0_TABLE_BASE_ADDR
+ bra 2f
+1:
+ la A1, PORE_GPE1_TABLE_BASE_ADDR
+2:
+ la D0, empathErrorHandlers
+ std D0, 0, A1
+
+ la A1, saved_emr
+ ld D0, 0, A1
+ ori D0, D0, PORE_ERROR_MASK_ENABLE_ERR_HANDLER0
+ andi D0, D0, ~(PORE_ERROR_MASK_ENABLE_ERR_OUTPUT0 | \
+ PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 | \
+ PORE_ERROR_MASK_STOP_EXE_ON_ERROR0)
+ mr EMR, D0
+
+#if INJECT_HW280375_ERRORS
+
+ // This code is used to test the workaround for HW280375. The
+ // undiagnosed hardware bug causes PCB error 4 to occur intermittantly
+ // when accessing EMPATH registers. The appearance of the defect is
+ // actually quite rare in practice, therefore this code remains in
+ // case future development and testing of this procedure is necessary.
+
+ // The test generates PCB error 4 by reading a non-existant OHA
+ // register of the current core, once every 1024 samples on
+ // average. The LFSR modifies A0 so we need to shuffle A0 <->
+ // A1. (Note the LFSR code is not delivered to OCC FW).
+
+ mr A1, A0
+
+ la A0, testHw280375Lfsr
+ ld D0, 0, A0
+ bsr pore_rand64
+ la A0, testHw280375Lfsr
+ std D0, 0, A0
+
+ mr A0, A1
+
+ andi D0, D0, 0x3ff
+ branz D0, 1f
+ ld D0, 0x200ff, P0 # Force PCB error 4
+1:
+
+#endif
+
+ // 6. Collect EMPATH data
+
+ // Test/collect each data group in order. First reload the parameter
+ // pointer into A1.
+
+ la A1, core_data_parms
+ ld D0, 0, A1
+ mr A1, D0
+
+ // EMPATH
+empath:
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_EMPATH
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_EMPATH_BASE
+ tag_core_data_group _BASE, A0, P0, P1, raw=0
+
+ sti PC_OCC_SPRC, P0, \
+ (SPRN_CORE_INSTRUCTION_DISPATCH | SPRN_PC_AUTOINCREMENT)
+
+ get_pc_pair (_BASE + 0x08), A0, P0
+ get_pc_pair (_BASE + 0x10), A0, P0
+ get_pc_pair (_BASE + 0x18), A0, P0
+ get_pc_pair (_BASE + 0x20), A0, P0
+
+ // Per-Core (partition) Memory Counters
+per_core_memory:
+1:
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_MEMORY
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_MEMORY_BASE
+ tag_core_data_group _BASE, A0, P0, P1
+
+ sti PC_OCC_SPRC, P0, \
+ (SPRN_CORE_MEM_C_LPAR(0) | SPRN_PC_AUTOINCREMENT)
+
+ get_pc_pair (_BASE + 0x08), A0, P0
+ get_pc_pair (_BASE + 0x10), A0, P0
+
+ // Throttling Counters
+throttling:
+1:
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_THROTTLE
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_THROTTLE_BASE
+ tag_core_data_group _BASE, A0, P0, P1
+
+ sti PC_OCC_SPRC, P0, \
+ (SPRN_IFU_THROTTLE_COUNTER | SPRN_PC_AUTOINCREMENT)
+
+ get_pc_pair (_BASE + 0x08), A0, P0
+ get_pc_pair (_BASE + 0x10), A0, P0
+
+ // Per-Thread Counters
+per_thread:
+1:
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_THREAD
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_THREAD_BASE(0)
+ tag_core_data_group _BASE, A0, P0, P1
+
+ sti PC_OCC_SPRC, P0, \
+ (SPRN_THREAD_RUN_CYCLES(0) | SPRN_PC_AUTOINCREMENT)
+
+ get_pc_pair (_BASE + 0x08), A0, P0 # Run/Completion T0
+ get_pc_pair (_BASE + 0x10), A0, P0 # Mem A/B T0
+ // (_BASE + 0x18), A0, P0 # Tag T1
+ get_pc_pair (_BASE + 0x20), A0, P0 # Run/Completion T1
+ get_pc_pair (_BASE + 0x28), A0, P0 # Mem A/B T1
+ // (_BASE + 0x30), A0, P0 # Tag T2
+ get_pc_pair (_BASE + 0x38), A0, P0 # Run/Completion T2
+ get_pc_pair (_BASE + 0x40), A0, P0 # Mem A/B T2
+ // (_BASE + 0x48), A0, P0 # Tag T3
+ get_pc_pair (_BASE + 0x50), A0, P0 # Run/Completion T3
+ get_pc_pair (_BASE + 0x58), A0, P0 # Mem A/B T3
+ // (_BASE + 0x60), A0, P0 # Tag T4
+ get_pc_pair (_BASE + 0x68), A0, P0 # Run/Completion T4
+ get_pc_pair (_BASE + 0x70), A0, P0 # Mem A/B T4
+ // (_BASE + 0x78), A0, P0 # Tag T5
+ get_pc_pair (_BASE + 0x80), A0, P0 # Run/Completion T5
+ get_pc_pair (_BASE + 0x88), A0, P0 # Mem A/B T5
+ // (_BASE + 0x90), A0, P0 # Tag T6
+ get_pc_pair (_BASE + 0x98), A0, P0 # Run/Completion T6
+ get_pc_pair (_BASE + 0xa0), A0, P0 # Mem A/B T6
+ // (_BASE + 0xa8), A0, P0 # Tag T7
+ get_pc_pair (_BASE + 0xb0), A0, P0 # Run/Completion T7
+ get_pc_pair (_BASE + 0xb8), A0, P0 # Mem A/B T7
+
+
+ // Interpolation of TOD and Raw Cycles over 8 threads. First collect
+ // a new tag, then compute the difference with the thread0 tag. The
+ // differences are then divided by 8 to form the interpolation
+ // increment, and interpolation takes places in an unrolled loop.
+ //
+ // Note that we're doing parallel arithmetic here, and ignoring the
+ // fact that there may be a carry/borrow from the low-order TOD into
+ // the high-order cycle count. A single LSB is noise for the cycle
+ // count, but would be significant for the TOD, which is why the
+ // TOD is placed in the low-order part of the doubleword. Given that
+ // a single LSB is noise for the cycle count there is no reason to
+ // expend the time/code space to do the arithmetic 'correctly'.
+
+interpolate:
+ tag_core_data_group 0, 0, P0, P1, store=0 # D0 contains the _NOW_ tag
+
+ ld D1, CORE_DATA_THREAD_BASE(0), A0 # D1 will be used for interp.
+ sub D0, D0, D1
+ andi D0, D0, 0xfffffff8fffffff8 # Mask off bad bits and div. by 8.
+ rotrdi D0, D0, 3
+
+ .macro interpolate, thread
+ add D1, D0, D1
+ std D1, CORE_DATA_THREAD_BASE(\thread), A0
+ .endm
+
+ interpolate 1
+ interpolate 2
+ interpolate 3
+ interpolate 4
+ interpolate 5
+ interpolate 6
+ interpolate 7
+
+
+ // If we made it here there were no errors - Yippee! If we were asked
+ // to collect any EMPATH data then acknowledge that we did.
+1:
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, \
+ (GPE_GET_CORE_DATA_EMPATH | \
+ GPE_GET_CORE_DATA_MEMORY | \
+ GPE_GET_CORE_DATA_THROTTLE | \
+ GPE_GET_CORE_DATA_THREAD)
+ braz D0, 1f
+
+ ld D0, CORE_DATA_OHA_RO_STATUS_REG, A0
+ ori D0, D0, CORE_DATA_EMPATH_COLLECTED
+ std D0, CORE_DATA_OHA_RO_STATUS_REG, A0
+
+
+ // 7. Restore error handling; Clear the PC-Only SPWU bit
+1:
+ la A1, saved_emr
+ ld D0, 0, A1
+ mr EMR, D0
+
+ sti OHA_CPM_HIST_RESET_REG, P0, 0
+
+ la A1, core_data_parms
+ ld D0, 0, A1
+ mr A1, D0
+
+
+ // 8. Collect PCB-Slave data
+pcb_slave:
+
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_PCB_SLAVE
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_PCB_SLAVE_BASE
+ tag_core_data_group _BASE, A0, P0, P1, raw=0
+
+ get_scom D0, PCBS_POWER_MANAGEMENT_CONTROL_REG, P0, CORE_DATA_PMCR, A0
+ get_scom D0, PCBS_POWER_MANAGEMENT_STATUS_REG, P0, CORE_DATA_PMSR, A0
+ get_scom D0, PCBS_PMSTATEHISTOCC_REG, P0, CORE_DATA_PM_HISTORY, A0
+
+1:
+ ret
+
+
+ //////////////////////////////////////////////////////////////////////
+ // getSensors
+ //////////////////////////////////////////////////////////////////////
+ //
+ // Try to get core and L3 sensor (DTS/CPM) data
+ //
+ // At Entry:
+ //
+ // We are in manual PIB error handling mode
+ // A0 : Base address of core data area
+ // A1 : Address of the parameter block
+ // P0 : Chiplet
+ //
+ // At exit:
+ //
+ // A0, P0 unchanged
+ // D0, D1 scratched
+ //
+ // Note that due to HW279433, we can not read the CPM sensors without
+ // the possiblity of a FIR bit being set due to a PCB timeout. Since
+ // the CPMs are currently not in plan for P8, these fields of the data
+ // structure are simply zeroed.
+
+getSensors:
+
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_DTS_CPM
+ braz D0, getSensorsDone
+
+ // HW279433, see above
+ ls D0, 0
+ std D0, CORE_DATA_SENSOR_V8, A0
+ std D0, CORE_DATA_SENSOR_V9, A0
+
+ .set _BASE, CORE_DATA_DTS_CPM_BASE
+ tag_core_data_group _BASE, A0, P0, P1, raw=0
+
+ // First try the core
+
+ ld D0, SENSORS_CORE_V0, P0
+ tprcbnz D1, coreSensorsFailed
+ std D0, CORE_DATA_SENSOR_V0, A0
+
+ ld D0, CORE_DATA_OHA_RO_STATUS_REG, A0
+ ori D0, D0, CORE_DATA_CORE_SENSORS_COLLECTED
+ std D0, CORE_DATA_OHA_RO_STATUS_REG, A0
+
+ bra tryL3
+
+coreSensorsFailed:
+
+ la A1, G_ggcd_coreSensorFail
+ std D1, 0, A1
+ la A1, core_data_parms
+ ld D0, 0, A1
+ mr A1, D0
+
+ ls D0, 0
+ std D0, CORE_DATA_SENSOR_V0, A0
+
+ // Now try the L3
+tryL3:
+ ld D0, SENSORS_CORE_V1, P0
+ tprcbnz D1, l3SensorsFailed
+ std D0, CORE_DATA_SENSOR_V1, A0
+
+ ld D0, CORE_DATA_OHA_RO_STATUS_REG, A0
+ ori D0, D0, CORE_DATA_L3_SENSORS_COLLECTED
+ std D0, CORE_DATA_OHA_RO_STATUS_REG, A0
+
+ bra getSensorsDone
+
+l3SensorsFailed:
+
+ la A1, G_ggcd_l3SensorFail
+ std D1, 0, A1
+ la A1, core_data_parms
+ ld D0, 0, A1
+ mr A1, D0
+
+ ls D0, 0
+ std D0, CORE_DATA_SENSOR_V1, A0
+
+getSensorsDone:
+ ret
+
+
+ //////////////////////////////////////////////////////////////////////
+ // gpcrdError0
+ //
+ // Trap error 0 during EMPATH processing, and set a bit indicating if
+ // this is an "expected" or "unexpected" error. The only expected
+ // error is a PCB error #4 due to HW280375.
+ //
+ // Note that PORE treats error branches as subroutine calls. We need
+ // to pop the HW stack before continuing. We assume we are running on
+ // either GPE0 or GPE1.
+ ////////////////////////////////////////////////////////////////////////////
+
+ .global empathErrorHandlers
+empathErrorHandlers:
+ bra gpcrdError0
+
+gpcrdError0:
+
+ // Set A1 for current engine
+
+ tebngpe0 D0, 1f
+ la A1, PORE_GPE0_OCI_BASE
+ bra 2f
+1:
+ la A1, PORE_GPE1_OCI_BASE
+2:
+
+ // Extract PCB parity error + 3-bit code and compare. Apparently the
+ // PCB error code is not set in the IFR when we take the error branch,
+ // so we have to get it from the debug register. The error code is
+ // used to decide if the error is "expected" or "unexpected".
+
+ ld D0, PORE_DBG0_OFFSET, A1
+ extrdi D0, D0, 4, 32
+
+ ld D1, CORE_DATA_OHA_RO_STATUS_REG, A0
+ cmpibraeq D0, 1f, 4
+
+ // This error is "unexpected"
+
+ ori D1, D1, CORE_DATA_UNEXPECTED_EMPATH_ERROR
+ bra 2f
+
+ // This error (#4) is "expected"
+1:
+ ori D1, D1, CORE_DATA_EXPECTED_EMPATH_ERROR
+
+ // Insert the error code into the OHA_RO_STATUS image
+2:
+ insrdi D1, D0, \
+ CORE_DATA_EMPATH_ERROR_BITS, CORE_DATA_EMPATH_ERROR_LOCATION
+ std D1, CORE_DATA_OHA_RO_STATUS_REG, A0
+
+
+ // Pop the hardware stack. The easiest way to do this is to modify the
+ // current stack pointer and "return" to a local label.
+
+ la D0, 1f
+ sldi D0, D0, 16
+ std D0, PORE_PC_STACK0_OFFSET, A1
+ ret
+1:
+
+ // Clear the debug registers.
+
+ ls D0, 0
+ std D0, PORE_DBG0_OFFSET, A1
+ std D0, PORE_DBG1_OFFSET, A1
+
+ // Bypass EMPATH data (that routine will restore the default error
+ // handling and re-establish A1)
+
+ bra bypass_core_data
+
+
+ //////////////////////////////////////////////////////////////////////
+ // bypass_core_data
+ //////////////////////////////////////////////////////////////////////
+ //
+ // This entry point is used when the core is inaccessible due to idle
+ // modes or other conditions. At entry we are in manual SCOM error
+ // handling mode. The routine will first attempt to collect the
+ // core and L3 DTS/CPM for Sleeping cores, then restore error
+ // handling and zero out the EMPATH data before collecting PCBS data.
+
+ // HW243646: We never read EMPATH counters here. The
+ // counters are all zeroed and all calls of tag_core_data_group
+ // specify raw=0.
+
+bypass_core_data:
+
+ la A1, core_data_parms
+ ld D0, 0, A1
+ mr A1, D0
+
+ bsr getSensors
+
+ // Clear the PC-Only SPWU bit and restore SCOM error handling. Then
+ // reload the parameter pointer into A1.
+
+ sti OHA_CPM_HIST_RESET_REG, P0, 0
+
+ la A1, saved_emr
+ ld D0, 0, A1
+ mr EMR, D0
+
+ la A1, core_data_parms
+ ld D0, 0, A1
+ mr A1, D0
+
+ // Bypass core data
+
+ // EMPATH
+
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_EMPATH
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_EMPATH_BASE
+ tag_core_data_group _BASE, A0, P0, P1, raw=0
+
+ ls D0, 0
+ std D0, (_BASE + 0x08), A0
+ std D0, (_BASE + 0x10), A0
+ std D0, (_BASE + 0x18), A0
+ std D0, (_BASE + 0x20), A0
+
+
+ // Per-Core Memory Counters
+
+1:
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_MEMORY
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_MEMORY_BASE
+ tag_core_data_group _BASE, A0, P0, P1, raw=0
+
+ ls D0, 0
+ std D0, (_BASE + 0x08), A0
+ std D0, (_BASE + 0x10), A0
+
+
+ // Throttling Counters
+
+1:
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_THROTTLE
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_THROTTLE_BASE
+ tag_core_data_group _BASE, A0, P0, P1, raw=0
+
+ ls D0, 0
+ std D0, (_BASE + 0x08), A0
+ std D0, (_BASE + 0x10), A0
+
+
+ // Per-Thread Counters
+
+1:
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_THREAD
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_THREAD_BASE(0)
+ tag_core_data_group _BASE, A0, P0, P1, raw=0
+
+ ls D0, 0
+ std D0, (_BASE + 0x08), A0 # Run/Completion T0
+ std D0, (_BASE + 0x10), A0 # Mem A/B T0
+ // (_BASE + 0x18), A0 # Tag T1
+ std D0, (_BASE + 0x20), A0 # Run/Completion T1
+ std D0, (_BASE + 0x28), A0 # Mem A/B T1
+ // (_BASE + 0x30), A0 # Tag T2
+ std D0, (_BASE + 0x38), A0 # Run/Completion T2
+ std D0, (_BASE + 0x40), A0 # Mem A/B T2
+ // (_BASE + 0x48), A0 # Tag T3
+ std D0, (_BASE + 0x50), A0 # Run/Completion T3
+ std D0, (_BASE + 0x58), A0 # Mem A/B T3
+ // (_BASE + 0x60), A0 # Tag T4
+ std D0, (_BASE + 0x68), A0 # Run/Completion T4
+ std D0, (_BASE + 0x70), A0 # Mem A/B T4
+ // (_BASE + 0x78), A0 # Tag T5
+ std D0, (_BASE + 0x80), A0 # Run/Completion T5
+ std D0, (_BASE + 0x88), A0 # Mem A/B T5
+ // (_BASE + 0x90), A0 # Tag T6
+ std D0, (_BASE + 0x98), A0 # Run/Completion T6
+ std D0, (_BASE + 0xa0), A0 # Mem A/B T6
+ // (_BASE + 0xa8), A0 # Tag T7
+ std D0, (_BASE + 0xb0), A0 # Run/Completion T7
+ std D0, (_BASE + 0xb8), A0 # Mem A/B T7
+
+
+ // Interpolation of TOD and Raw Cycles over 8 threads. First collect
+ // a new tag, then compute the difference with the thread0 tag. The
+ // differences are then divided by 8 to form the interpolation
+ // increment, and interpolation takes places in an unrolled loop.
+ //
+ // Note that we're doing parallel arithmetic here, and ignoring the
+ // fact that there may be a carry/borrow from the low-order TOD into
+ // the high-order cycle count. A single LSB is noise for the cycle
+ // count, but would be significant for the TOD, which is why the
+ // TOD is placed in the low-order part of the doubleword. Given that
+ // a single LSB is noise for the cycle count there is no reason to
+ // expend the time/code space to do the arithmetic 'correctly'.
+
+ tag_core_data_group 0, 0, P0, P1, raw=0, store=0 # D0 contains _NOW_ tag
+
+ ld D1, CORE_DATA_THREAD_BASE(0), A0 # D1 will be used for interp.
+ sub D0, D0, D1
+ andi D0, D0, 0xfffffff8fffffff8 # Mask off bad bits and div. by 8.
+ rotrdi D0, D0, 3
+
+ interpolate 1
+ interpolate 2
+ interpolate 3
+ interpolate 4
+ interpolate 5
+ interpolate 6
+ interpolate 7
+
+
+ // Per-Core PCB Slave Registers
+get_pcbs_data:
+
+ ldandi D0, GPEGETCOREDATAPARMS_SELECT, A1, GPE_GET_CORE_DATA_PCB_SLAVE
+ braz D0, 1f
+
+ .set _BASE, CORE_DATA_PCB_SLAVE_BASE
+ tag_core_data_group _BASE, A0, P0, P1, raw=0
+
+ get_scom D0, PCBS_POWER_MANAGEMENT_CONTROL_REG, P0, CORE_DATA_PMCR, A0
+ get_scom D0, PCBS_POWER_MANAGEMENT_STATUS_REG, P0, CORE_DATA_PMSR, A0
+ get_scom D0, PCBS_PMSTATEHISTOCC_REG, P0, CORE_DATA_PM_HISTORY, A0
+
+1:
+ ret
+
+/// \endcond
+
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_get_core_data_fast()
+////////////////////////////////////////////////////////////////////////////
+
+/// \fn gpe_get_core_data_fast(GpeGetChipDataFastParms *parms);
+/// \brief Get chip raw data on fastest possible timescale
+///
+/// This routine collects raw data for the entire chip on the fastest possible
+/// timescale. Where chiplet data is collected, the configured chiplets are
+/// specified in the configuration mask parameter. Data is grouped
+/// into logical groups, and the collection of any group is enabled by a group
+/// select mask. All data groups are tagged with the TOD.
+#ifdef DOXYGEN_ONLY
+void gpe_get_core_data_fast(GpeGetChipDataFastParms *parms);
+#endif
+/// \cond
+
+ // Register usage:
+ //
+ // A1 : Holds the (constant) pointer to the paramaters
+ // A0 : Holds the (varying) pointer to the data area for the current
+ // data group or datum.
+ // P1 : Holds the (constant) chiplet id of the TOD
+ // P0 : Holds the (varying) chiplet id of interest
+ // CTR : Loops through chiplet indices
+ // D1 : Holds/rotates configuration mask
+ // D0 : Scratch
+
+ .global gpe_get_core_data_fast
+
+gpe_get_core_data_fast:
+
+ // Set up registers. A0 must follow the target OCI address as each core
+ // chiplet is considered. Since we're only doing a single
+ // getscom/putOCI, we can keep the chiplet mask in D1. The data group
+ // is tagged with the TOD.
+
+ mr A1, ETR
+ ld D0, GPEGETCOREDATAFASTPARMS_CONFIG, A1
+ left_justify_core_config D0
+ mr D1, D0
+ lpcs P1, TOD_VALUE_REG
+ ld D0, GPEGETCOREDATAFASTPARMS_DATA, A1
+ mr A0, D0
+
+ tag_data_group CORE_DATA_FAST_FREQ_TARGET_BASE, D0, A0, P1
+ adds A0, A0, 8
+
+ ls P0, 0x10
+ ls CTR, (PGP_NCORES - 1) # PORE does test, then decr. and branch
+
+freq_target_loop:
+
+ // Test the chiplet mask. If the chiplet is not configured, simply
+ // continue.
+
+ andi D0, D1, 0x8000000000000000
+ rotldi D1, D1, 1
+ braz D0, freq_target_continue
+
+ get_scom D0, PCBS_LOCAL_PSTATE_FREQUENCY_TARGET_STATUS_REG, P0, \
+ 0x00, A0
+
+freq_target_continue:
+
+ // Increment the core chiplet index and data pointer, then loop or
+ // carry on.
+
+ adds P0, P0, 1
+ adds A0, A0, 8
+ loop freq_target_loop
+
+1:
+ halt
+
+/// \endcond
+
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_get_chip_data()
+////////////////////////////////////////////////////////////////////////////
+
+/// \fn gpe_get_chip_data(GpeGetChipDataParms *parms);
+/// \brief Get chip-level raw data
+///
+/// This routine collects chip-level raw data. Data is grouped into logical
+/// groups, and the collection of any group is enabled by a group select
+/// mask. All data groups are tagged with the TOD.
+#ifdef DOXYGEN_ONLY
+void gpe_get_chip_data(GpeGetChipDataParms *parms);
+#endif
+/// \cond
+
+ // Register usage:
+ //
+ // A0 : Holds the (varying) pointer to the data area for the current
+ // data group or datum.
+ // P1 : Holds the (constant) chiplet id of the TOD
+ // D1 : Holds the (constant) select mask
+
+ .global gpe_get_chip_data
+
+gpe_get_chip_data:
+
+ // Set up registers.
+
+ mr A1, ETR
+ ld D0, GPEGETCHIPDATAPARMS_SELECT, A1
+ mr D1, D0
+ lpcs P1, TOD_VALUE_REG
+ ld D0, GPEGETCHIPDATAPARMS_DATA, A1
+ mr A0, D0
+
+ // Overcommit data.
+
+ andi D0, D1, GPE_GET_CHIP_DATA_OVERCOMMIT
+ braz D0, 1f
+ tag_data_group CHIP_DATA_OVERCOMMIT_BASE, D0, A0, P1
+
+ // Overcommit data consists of PBA_PBOCR(0)...PBA_PBOCR(5), all stored
+ // at 8-byte offsets
+
+ la A1, PBA_PBOCRN(0)
+ ocicopy D0, 0x00, A1, 0x08, A0
+ ocicopy D0, 0x08, A1, 0x10, A0
+ ocicopy D0, 0x10, A1, 0x18, A0
+ ocicopy D0, 0x18, A1, 0x20, A0
+ ocicopy D0, 0x20, A1, 0x28, A0
+ ocicopy D0, 0x28, A1, 0x30, A0
+
+1:
+ halt
+
+ .epilogue gpe_get_chip_data
+
+/// \endcond
+
+
+////////////////////////////////////////////////////////////////////////////
+// gpe_get_mem_data()
+////////////////////////////////////////////////////////////////////////////
+
+/// \fn gpe_get_mem_data(GpeGetMemDataParms *parms);
+/// \brief Get memory (MCS/Centaur) data for a particular MCS/Centaur
+///
+/// This routine collects data for the MCS/Centaur named (by instance ID,
+/// (0...PGP_NCENTAUR -1)) in the \a collect field of the \a parms parameter,
+/// unless \a collect is -1 in which case the data collection is bypassed.
+/// Once data has been collected, if the \a update field of the a \parms is
+/// not -1 then that numbered Centaur will be "poked" to start the sensor
+/// cache update. Once data collection (if any) and "poking" (if any) are
+/// finished the parameter block is timestamped with the TOD (at the standard
+/// 2MHz). This means that the TOD timestamp marks the "poke" time (when data
+/// collection starts), not the data collection time.
+///
+/// This procedure requires that the global G_centaurConfiguration structure
+/// must be present and have been properly initialized by
+/// centaur_configuration_create(). The procedure returns a return code -
+/// Either 0 for success, or a non zero value for failure. The failure codes
+/// are documented here: \ref gpe_get_mem_data_rc. Since the parameter block
+/// is read and written by GPE code it is strongly recommended to allocate
+/// instances of this structure in non-cacheable data sections, with the
+/// caveat that data structures assigned to non-default data sections must
+/// always be initialized. For example:
+///
+/// \code
+///
+/// static GpeGetMemDataParms S_parms SECTION_ATTRIBUTE(".noncacheable") = {0};
+///
+/// \endcode
+///
+/// NB: SW273814 documents a request to be able to differentiate which of the 2
+/// Centaurs is responsible for a hard failure. That's why we take pains to
+/// set up the RC prior to collection/poking to enable recovery code to make
+/// this determination.
+#ifdef DOXYGEN_ONLY
+void gpe_get_mem_data(GpeGetMemDataParms *parms);
+#endif
+/// \cond
+
+ .global gpe_get_mem_data
+gpe_get_mem_data:
+
+ // At entry:
+ //
+ // ETR : parms
+ //
+ // Invariants:
+ //
+ // ETR : parms
+ // A1 : parms (except when scratched by subroutines, always restored)
+
+ // Begin by marking the procedure as having died
+
+ mr A1, ETR
+ sti GPEGETMEMDATAPARMS_RC, A1, GPE_GET_MEM_DATA_DIED
+
+ // Next check to make sure the G_centaurConfiguration is properly
+ // initialized (.configRc == 0).
+ //
+ // A1 : parms
+
+ la A0, G_centaurConfiguration
+ ld D0, CENTAUR_CONFIGURATION_CONFIG_RC, A0
+ braz D0, 1f
+
+ ls D0, GPE_GET_MEM_DATA_NOT_CONFIGURED
+ bra ggmdExit
+
+1:
+ // Set up the PBA for Centaur sensor cache access
+ //
+ // A1 : parms
+ // A0 : &G_centaurConfiguration ==> &G_centaurConfiguration.dataParms;
+
+ adds A0, A0, CENTAUR_CONFIGURATION_DATA_PARMS
+ bsr gpe_pba_reset
+ bsr gpe_pba_setup
+ mr A1, ETR # Re-establish invariant
+
+
+ // See if we're collecting data this pass. If so validate that the
+ // MCS/Centaur index is valid according to G_centaurConfiguration.
+ //
+ // A1 : parms
+
+ ld D0, GPEGETMEMDATAPARMS_COLLECT, A1
+ cmpibraeq D0, ggmdUpdate, -1
+
+ bsr ggmdDataSetup
+ mr A1, ETR # Re-establish invariant
+ braz D0, 1f
+
+ ls D0, GPE_GET_MEM_DATA_COLLECT_INVALID
+ bra ggmdExit
+
+1:
+ // A0 has the base address of the sensor cache as a PowerBus
+ // mapping. Load A1 with the user data pointer and collect the data.
+ //
+ // A1 : parms ==> &MemData
+
+ sti GPEGETMEMDATAPARMS_RC, A1, GPE_GET_MEM_DATA_SENSOR_CACHE_FAILED
+
+ ld D0, GPEGETMEMDATAPARMS_DATA, A1
+ mr A1, D0
+
+ ocicopy D0, 0x00, A0, 0x00, A1
+ ocicopy D0, 0x08, A0, 0x08, A1
+ ocicopy D0, 0x10, A0, 0x10, A1
+ ocicopy D0, 0x18, A0, 0x18, A1
+ ocicopy D0, 0x20, A0, 0x20, A1
+ ocicopy D0, 0x28, A0, 0x28, A1
+ ocicopy D0, 0x30, A0, 0x30, A1
+ ocicopy D0, 0x38, A0, 0x38, A1
+ ocicopy D0, 0x40, A0, 0x40, A1
+ ocicopy D0, 0x48, A0, 0x48, A1
+ ocicopy D0, 0x50, A0, 0x50, A1
+ ocicopy D0, 0x58, A0, 0x58, A1
+ ocicopy D0, 0x60, A0, 0x60, A1
+ ocicopy D0, 0x68, A0, 0x68, A1
+ ocicopy D0, 0x70, A0, 0x70, A1
+ ocicopy D0, 0x78, A0, 0x78, A1
+
+ mr A1, ETR # Re-establish invariant
+
+ sti GPEGETMEMDATAPARMS_RC, A1, GPE_GET_MEM_DATA_DIED
+
+ // See if we're poking Centaur this pass. If so validate that the
+ // MCS/Centaur index is valid according to G_centaurConfiguration.
+ //
+ // A1 : parms
+ggmdUpdate:
+
+ ld D0, GPEGETMEMDATAPARMS_UPDATE, A1
+ cmpibraeq D0, ggmdTimestamp, -1
+
+ bsr ggmdDataSetup
+ mr A1, ETR # Re-establish invariant
+ braz D0, 1f
+
+ ls D0, GPE_GET_MEM_DATA_UPDATE_INVALID
+ bra ggmdExit
+
+1:
+ // Poke it
+
+ sti GPEGETMEMDATAPARMS_RC, A1, GPE_GET_MEM_DATA_UPDATE_FAILED
+
+ ls D0, 0
+ std D0, 0, A0
+
+ sti GPEGETMEMDATAPARMS_RC, A1, GPE_GET_MEM_DATA_DIED
+
+ // Collect the timestamp and reduce the 64-bit 512MHz timestamp to a
+ // 32-bit 2MHz timestamp. Then we're out...
+ //
+ // A1 : parms
+ggmdTimestamp:
+
+ lpcs P0, TOD_VALUE_REG
+ ld D0, TOD_VALUE_REG, P0
+ extrdi D0, D0, 32, 24
+ std D0, GPEGETMEMDATAPARMS_PAD_TOD, A1
+
+
+ ////////////////////////////////////////////////////////////////////
+ // Not so fast... If this is Centaur DD1 then we did not actually
+ // collect the Centaur internal temperatures due to HW256773. So we
+ // will go collect them now "manually" by calling _gpe_scom_centaur
+ // with a hard-coded setup to collect SCOM 0x02050000. We then
+ // splice this result into the accumulated cache-line data.
+ //
+ // A1 : Parms
+ ////////////////////////////////////////////////////////////////////
+
+ // Nothing to do if we're not collecting data. Otherwise pull out the
+ // CFAM ID and compare for Centaur DD1
+
+ ld D0, GPEGETMEMDATAPARMS_COLLECT, A1
+ cmpibraeq D0, ggmdCleanExit, -1
+
+ sldi D0, D0, 3 # Multiply by 8 for a byte offset
+
+ la D1, G_centaurConfiguration
+ adds D1, D1, CENTAUR_CONFIGURATION_DEVICE_ID
+ add D0, D0, D1
+ mr A0, D0
+ ld D0, 0, A0
+ extrdi D0, D0, 32, 0
+
+ cmpibrane D0, ggmdCleanExit, CFAM_CHIP_ID_CENTAUR_10
+
+ // This is DD1. Set up the parameters and call _gpe_scom_centaur.
+ // Since we can only do 8-byte stores we read-modify-write the first
+ // entry of the scomList_t. Then call for the SCOM. If it failed set
+ // the failure code. All registers must be restored after the
+ // subroutine call.
+
+ la A0, G_ggmdHw256773
+ ld D0, SCOM_LIST_COMMAND, A0
+ ld D1, GPEGETMEMDATAPARMS_COLLECT, A1
+ scom_list_set_instance_number D0, D1
+ std D0, SCOM_LIST_COMMAND, A0
+
+ la A0, G_hw256773
+ bsr _gpe_scom_centaur
+
+ la A0, G_hw256773
+ mr A1, ETR
+
+ ld D0, GPE_SCOM_PARMS_RC_ERROR_INDEX, A0
+ gpe_scom_parms_get_rc D0, D0
+ braz D0, 1f
+
+ ls D0, GPE_GET_MEM_DATA_HW256773_FAILED
+ bra ggmdExit
+
+1:
+ // The SCOM succeeded. The data needs to be moved from the
+ // gpe_scom_centaur data into the sensor-cache data area. Since there
+ // are only 32 bits we need to read-modify-write the SRAM. This is
+ // doubleword 12 of the sensor cache. The 32 bits of the SCOM we need
+ // are the high-order bits, copied into the low-order bits of the
+ // sensor-cache doubleword. Finally fall through to the clean exit.
+
+ la A0, G_ggmdHw256773
+ ld D0, SCOM_LIST_DATA, A0
+
+ ld D1, GPEGETMEMDATAPARMS_DATA, A1
+ mr A0, D1
+ ld D1, 0x60, A0
+ rldimi D1, D0, 32, 32, 63
+ std D1, 0x60, A0
+
+
+ggmdCleanExit:
+ ls D0, 0
+ggmdExit:
+ std D0, GPEGETMEMDATAPARMS_RC, A1
+ halt
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // ggmdDataSetup
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // At entry:
+ //
+ // D0 : The Centaur instance number to set up
+ //
+ // At exit:
+ //
+ // A0 : On success, the OCI base address to use to access the
+ // sensor cache.
+ // D0 : 0 = Success; 1 = Failure - the caller will supply the
+ // correct error code back to the user.
+ //
+ // This routine checks the Centaur instance number for validity. If
+ // the instance number is valid then the PBA is programmed to access
+ // the sensor cache address. This requires reprogramming the PBA
+ // because part of the data address, which varies by Centaur, must be
+ // stored as the extended address field of the PBA slave control
+ // register. It is not necessary to reset the PBA slave for each data
+ // operation.
+ggmdDataSetup:
+
+ // Check the Centaur instance number (D0) for validity.
+
+ ls D1, PGP_NCENTAUR
+ sub D1, D0, D1
+ tfbult D1, 1f
+
+ ls D0, 1
+ ret # Centaur instance too big
+
+1:
+ // Check to make sure the Centaur is configured by testing the base
+ // address for 0. The instance number is first multiplied by 8 to
+ // create an array offset.
+
+ sldi D0, D0, 3
+ la D1, G_centaurConfiguration
+ adds D1, D1, CENTAUR_CONFIGURATION_BASE_ADDRESS
+ add D0, D0, D1
+ mr A0, D0
+ ld D0, 0, A0
+ branz D0, 1f
+
+ ls D0, 1
+ ret # Base address is 0
+
+1:
+ // We have the Centaur base address in D0, and convert it to the full
+ // PowerBus address for the inband sensor cache access. Bit 27 is set
+ // to indicate OCC (vs. FSP) access. Bit 28 is set to indicate a
+ // sensor cache access.
+
+ ori D0, D0, 0x0000001800000000
+
+#if 1
+ la A0, G_ggmd_lastDataAddress # Debug
+ std D0, 0, A0
+#endif
+
+ // The OCI address is always 0, decorated with the PBA BAR number.
+
+ la A0, (PBA_BAR_CENTAUR << 28)
+
+ // Bits 23:36 of the address go into the extended address field (35:
+ // 48) of the PBA slave control register by a read-modify-write
+ // operation. Note: We're using rldimi explicitly here - not an
+ // extended mnemonic - to save having to justify the data.
+
+ la A1, G_centaurConfiguration
+ ld D1, \
+ (CENTAUR_CONFIGURATION_DATA_PARMS + \
+ GPEPBAPARMS_SLVCTL_ADDRESS), \
+ A1
+ mr A1, D1
+ ld D1, 0, A1
+ rldimi D1, D0, 64 - (35 - 23), 35, 48
+ std D1, 0, A1
+
+#if 1
+ la A1, G_ggmd_lastSlaveControl # Debug
+ std D1, 0, A1
+ mr D1, A0
+ la A1, G_ggmd_lastOciAddress
+ std D1, 0, A1
+#endif
+
+ // Clear D0 to signal success and we're out
+
+ ls D0, 0
+ ret
+ .epilogue gpe_get_mem_data
+
+/// \endcond
+
+
+////////////////////////////////////////////////////////////////////////////
+// Global Data
+////////////////////////////////////////////////////////////////////////////
+
+
+
+/// \cond
+
+ .data.pore
+
+ // Data storage for gpe_get_core_data()
+
+core_data_parms:
+ .quad 0
+saved_emr:
+ .quad 0
+manual_emr:
+ .quad 0
+hw243646:
+#if 0
+ .quad 0x3 # Determined + Required
+#else
+ .quad 0x2 # Determined + Not Required
+#endif
+
+ // Used to debug the workaround for HW280375
+
+testHw280375Lfsr:
+ .quad 0xdeadbeef # Initial state of LFSR
+
+ // Debug/Info: Failure codes when sensor reads fail
+
+ .global G_ggcd_coreSensorFail
+G_ggcd_coreSensorFail:
+ .quad 0
+
+ .global G_ggcd_l3SensorFail
+G_ggcd_l3SensorFail:
+ .quad 0
+
+
+ // Debug only, the last values computed by ggmdDataSetup.
+
+ .global G_ggmd_lastDataAddress
+G_ggmd_lastDataAddress:
+ .quad 0
+
+ .global G_ggmd_lastSlaveControl
+G_ggmd_lastSlaveControl:
+ .quad 0
+
+ .global G_ggmd_lastOciAddress
+G_ggmd_lastOciAddress:
+ .quad 0
+
+
+ // Required for Centaur DD1. This is an assembler layout of a
+ // GpeScomParms structure pointing to a scomList_t structure to read
+ // Centaur SCOM 0x02050000. See the code comments for more details.
+
+ .global G_ggmdHw25773
+G_ggmdHw256773:
+ .long 0x02050000 # SCOM
+ .byte 0 # Reserved
+ .byte 0 # Error flags (output)
+ .byte 0 # Instance Number (input)
+ .byte GPE_SCOM_READ # Command
+ .quad 0 # Mask (unused)
+ .quad 0 # Data (output)
+
+ .global G_hw256773
+G_hw256773:
+ .long 0 # (32-bit addresses)
+ .long G_ggmdHw256773 # scomList
+ .long 1 # Entries in the scomList
+ .long 0 # Options
+ .long 0 # rc (output)
+ .long 0 # errorIndex (output)
+
+/// \endcond
diff --git a/src/lib/gpe_pba.c b/src/lib/gpe_pba.c
new file mode 100755
index 0000000..c3b0a00
--- /dev/null
+++ b/src/lib/gpe_pba.c
@@ -0,0 +1,148 @@
+// $Id: gpe_pba.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe_pba.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe.c
+/// \brief Generic PORE-GPE support procesures (outside of the kernel
+/// drivers).
+
+#include "ssx.h"
+#include "gpe.h"
+#include "gpe_pba.h"
+
+/// Create/initialize a GpePbaParms structure
+///
+/// \param parms A unused or uninitialized GpePbaParms structure
+///
+/// \param slave The PBA slave port to program. For production code this will
+/// normally be PBA_SLAVE_PORE_GPE, however for test/verification code it
+/// could be any PBA slave.
+///
+/// \param write_ttype One of PBA_WRITE_TTYPE_* (see pgp_pba.h). Use
+/// PBA_WRITE_TTYPE_DC (don't care) if the GPE application does not do writes.
+///
+/// \param write_tsize One of PBA_WRITE_TSIZE_* (see pgp_pba.h). The \a
+/// write_tsize is only relevant for \a write_ttype == PBA_WRITE_TTYPE_LCO_M,
+/// where the macro PBA_WRITE_TSIZE_CHIPLET() is used to specify the target
+/// chiplet, and \a write_ttype == PBA_WRITE_TTYPE_ATOMIC_RMW, where the \a
+/// write_tsize specifies the atomic operation. Otherwise use
+/// PBA_WRITE_TTYPE_DC (don't care).
+///
+/// \param read_ttype One of PBA_READ_TTYPE_* (see pgp_pba.h). Normally this
+/// will be PBA_READ_TTYPE_CL_READ_NC (or PBA_READ_TTYPE_DC if you don't
+/// care.)
+///
+/// \param flags Two flags are provided that override default
+/// behavior. GPE_PBA_PARMS_READ_INVALIDATE specifies read buffer invalidation
+/// after every read. This is always selected when the read Ttype is a
+/// cache-inhibited partial read, but may be optionally specified for test
+/// purposes.
+///
+/// Similarly, GPE_PBA_PARMS_DISABLE_WRITE_GATHER specifies that write
+/// gathering for write Ttype DMA partial write is disabled. Note that
+/// GPE_PBA_PARMS_DISABLE_WRITE_GATHER disables write gathering in the sense
+/// that writes pass through the PBA immediately without being buffered. This
+/// is different from using the PBA_WRITE_GATHER_TIMEOUT_DISABLE option to \a
+/// write_gather_timeout, which specifies that writes are gathered until an
+/// entire line is filled.
+///
+/// This API initializes the GpePbaParms structure used by every GPE program
+/// that accesses mainstore via PBA. It creates an image of a PBA_SLVCTL
+/// register to be applied under a mask.
+///
+/// \note Read buffer invalidation is always enforced for cache-inhibited
+/// partial reads. This also forces prefetching to be disabled for the
+/// slave. Our procedures currently do not support save/restore of prefetch
+/// controls as different tasks reprogram the PBA Slave. Thus any access of a
+/// shared slave that is also used to do CI_PR_RD will have prefetching
+/// disabled.
+///
+/// \retval 0 Success
+///
+/// \retval -GPE_INVALID_OBJECT The \a parms pointer is NULL (0) or othewise
+/// invalid.
+///
+/// \retval -GPE_INVALID_ARGUMENT One of the arguments is invalid in some way.
+
+int
+gpe_pba_parms_create(GpePbaParms *parms,
+ int slave,
+ int write_ttype,
+ int write_tsize,
+ int read_ttype)
+{
+ pba_slvctln_t *slvctl, *mask;
+ pba_slvrst_t* slvrst;
+ pba_slvrst_t* slvrst_in_progress;
+ uint64_t all1 = 0xffffffffffffffffull;
+
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((parms == 0), GPE_INVALID_OBJECT);
+ SSX_ERROR_IF((slave < 0) ||
+ (slave >= PBA_SLAVES),
+ GPE_INVALID_ARGUMENT);
+ }
+
+ parms->slave_id = slave;
+
+ slvctl = &(parms->slvctl);
+ mask = &(parms->mask);
+ slvrst = &(parms->slvrst);
+ slvrst_in_progress = &(parms->slvrst_in_progress);
+
+ parms->slvctl_address = PBA_SLVCTLN(slave);
+
+ slvrst->value = 0;
+ slvrst->fields.set = PBA_SLVRST_SET(slave);
+
+ slvrst_in_progress->value = 0;
+ slvrst_in_progress->fields.in_prog = PBA_SLVRST_IN_PROG(slave);
+
+ slvctl->value = 0;
+ mask->value = 0;
+
+ slvctl->fields.enable = 1;
+ mask->fields.enable = all1;
+
+ slvctl->fields.write_ttype = write_ttype;
+ mask->fields.write_ttype = all1;
+
+ slvctl->fields.write_tsize = write_tsize;
+ mask->fields.write_tsize = all1;
+
+ slvctl->fields.read_ttype = read_ttype;
+ mask->fields.read_ttype = all1;
+
+ if (read_ttype == PBA_READ_TTYPE_CI_PR_RD) {
+
+ slvctl->fields.buf_invalidate_ctl = 1;
+ mask->fields.buf_invalidate_ctl = all1;
+
+ slvctl->fields.read_prefetch_ctl = PBA_READ_PREFETCH_NONE;
+ mask->fields.read_prefetch_ctl = all1;
+
+ } else {
+
+ slvctl->fields.buf_invalidate_ctl = 0;
+ mask->fields.buf_invalidate_ctl = all1;
+ }
+
+ mask->value = ~(mask->value);
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/gpe_pba.h b/src/lib/gpe_pba.h
new file mode 100644
index 0000000..5f8ea2c
--- /dev/null
+++ b/src/lib/gpe_pba.h
@@ -0,0 +1,116 @@
+#ifndef __GPE_PBA_H__
+#define __GPE_PBA_H__
+
+// $Id: gpe_pba.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe_pba.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe_pba.h
+/// \brief PBA subroutines for PORE-GPE procedures
+
+// Error/Panic codes
+
+#define GPE_INVALID_OBJECT 0x00473001
+#define GPE_INVALID_ARGUMENT 0x00473002
+
+
+#ifndef __ASSEMBLER__
+
+/// Encapsulated PBA setup for GPE programs
+///
+/// All GPE programs that access mainstore via PBA utilize a common parameter
+/// structure that encapsulates the required setup. This is required due to
+/// the unusual architecture of the PBA which interprets OCI addresses and the
+/// associated PowerBus transaction type based on which OCI \e master issued
+/// the OCI transaction, not based on the OCI \a address (or PowerBus
+/// address). The final complication is that each OCI master is assigned a
+/// unique PBA "slave port", so any reprogramming must be done on the PBA
+/// registers associated with the particular port assigned to the particular
+/// PORE engine.
+///
+/// In product code the PBA slave port assignment for the PORE-GPE engines
+/// will be fixed; however this structure assumes the most general case and
+/// allows for an arbitraray and dynamic assignment, and even allows mainstore
+/// programs to run on the PORE-SLW. However the procedure that creates this
+/// structure (gpe_pba_parms_create()) must know which engine/port will run
+/// the program in order to set up the parameters.
+///
+/// The PBA software interface is not friendly for dynamic programming of the
+/// PBA slave setup, especially from the PORE. The slave setup is modifed by a
+/// read-modify-write under mask. gpa_pba_parms_create() does not allow
+/// specification of which read buffers, prefetch modes or write timeouts to
+/// use as these have global implications. Only the values that affect the
+/// particular mode can be programmed there (but of course can be later
+/// overridden if required).
+///
+/// Note that there is an assumption that PORE engines have exclusive access
+/// to their PBA ports. All GPE procedures that access the PowerBus follow a
+/// protocol that makes no assumptions about how the PBA is set up - they set
+/// up the PBA for their own use, then leave it to subsequent procedures to
+/// re-setup the PBA as necessary for subsequent use. Also note that only one
+/// GPE thread can be designated to run programs that access the PBA,
+/// as they share an OCI master ID, and hence a PBA slave port.
+///
+/// Another - perhaps obvious - complication has to do with PBA slave reset. A
+/// PORE engine executing from main memory can not modify the PBA slave read
+/// parameter setup, as this would corrupt the instruction stream. Currently
+/// GPE procedures that need to modify the PBA read parameter setup execute
+/// from SRAM, and the SLW executing from main memeory never changes its read
+/// setup.
+///
+/// This structure is read-only to the GPE routines that access it.
+
+typedef struct {
+
+ /// The 32-bit OCI address of the PBA_SLVCTLn register to set up
+ uint64_t slvctl_address;
+
+ /// An image of the relevant parts of the PBA_SLVCTLn register in effect
+ /// for this procedure
+ pba_slvctln_t slvctl;
+
+ /// The mask in effect for this update of the PBA_SLVCTL
+ pba_slvctln_t mask;
+
+ /// The value to write to the PBA_SLVRST register to reset the slave
+ pba_slvrst_t slvrst;
+
+ /// The bit to AND-poll to check for slave reset in progress
+ pba_slvrst_t slvrst_in_progress;
+
+ /// The slave id (0 - 3)
+ uint64_t slave_id;
+
+} GpePbaParms;
+
+int
+gpe_pba_parms_create(GpePbaParms *parms,
+ int slave,
+ int write_ttype,
+ int write_tsize,
+ int read_ttype);
+
+#endif /* __ASSEMBLER__ */
+
+// Parameter offset for GpePbaParms
+
+#define GPEPBAPARMS_SLVCTL_ADDRESS 0x00
+#define GPEPBAPARMS_SLVCTL 0x08
+#define GPEPBAPARMS_MASK 0x10
+#define GPEPBAPARMS_SLVRST 0x18
+#define GPEPBAPARMS_SLVRST_IN_PROGRESS 0x20
+#define GPEPBAPARMS_SLAVE_ID 0x28
+
+#define SIZEOF_GPEPBAPARMS 0x30
+
+
+// Flags for gpe_pba_parms_setup()
+
+#define GPE_PBA_PARMS_READ_INVALIDATE 0x01
+#define GPE_PBA_PARMS_DISABLE_WRITE_GATHER 0x02
+
+#endif /* __GPE_H__ */
diff --git a/src/lib/gpe_pba_pgas.pS b/src/lib/gpe_pba_pgas.pS
new file mode 100755
index 0000000..346234d
--- /dev/null
+++ b/src/lib/gpe_pba_pgas.pS
@@ -0,0 +1,110 @@
+// $Id: gpe_pba_pgas.pS,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe_pba_pgas.pS,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe_pba.pS
+/// \brief PBA subroutines for PORE-GPE procedures
+
+ .nolist
+#include "ssx.h"
+#include "pgas.h"
+#include "pgp_config.h"
+#include "gpe.h"
+#include "gpe_pba.h"
+ .list
+
+ .oci
+
+ .text.pore
+
+ // Reset a PBA slave from a GpePbaParms structure. A setup sequence
+ // looks like
+ //
+ // gpe_pba_reset
+ // gpe_pba_setup
+ //
+ // The subroutine gpe_pba_reset can also be called by itself to insure
+ // that all write data has been flushed to mainstore.
+ //
+ // Note that any PORE program that reads or writes Centaur will need
+ // to execute its code from SRAM since it is not possible to set up
+ // the slave for reading from Centaur while executing from main memory.
+ //
+ // Slave reset for PBA is a complex issue, especially in cases like
+ // this where the entity requesting the reset may be executing from
+ // main memory - i.e., continuing to read from the slave being
+ // reset. To work around potential issues the code that polls for
+ // reset is PowerBus cache-line aligned, and we re-hit the reset
+ // button each time we get an unsuccessful poll for the reset being
+ // done. This should guarantee that the slave will go to reset
+ // status as soon as any PowerBus blockages (if any) clear. For
+ // details see HW228485.
+ //
+ // At entry :
+ //
+ // A0 : The (constant) address of the GpePbaParms structure
+ //
+ // Clobbered:
+ //
+ // D0 : scratched
+ // D1 : scratched
+ // A1 : Holds PBA_SLVRST
+
+ .global gpe_pba_reset
+
+ .balign 128
+gpe_pba_reset:
+ la A1, PBA_SLVRST
+ ld D0, GPEPBAPARMS_SLVRST, A0
+ std D0, 0, A1
+
+ ld D0, GPEPBAPARMS_SLVRST_IN_PROGRESS, A0
+ ld D1, 0, A1
+ and D0, D0, D1
+ branz D0, gpe_pba_reset
+
+ ret
+
+ .epilogue gpe_pba_reset
+
+
+ // Set up a PBA slave from a GpePbaParms structure. A setup sequence
+ // looks like
+ //
+ // gpe_pba_reset
+ // gpe_pba_setup
+ //
+ // At entry :
+ //
+ // A0 : The (constant) address of the GpePbaParms structure
+ //
+ // Clobbered:
+ //
+ // D0 : scratch
+ // A1 : Holds PBA_SLVCTL address for the indicated slave
+
+
+ .global gpe_pba_setup
+gpe_pba_setup:
+
+ // Write the new SLVCTL value under MASK
+
+ ld D0, GPEPBAPARMS_SLVCTL_ADDRESS, A0
+ mr A1, D0
+
+ ld D0, 0, A1
+ ld D1, GPEPBAPARMS_MASK, A0
+ and D0, D0, D1
+
+ ld D1, GPEPBAPARMS_SLVCTL, A0
+ or D0, D0, D1
+
+ std D0, 0, A1
+
+ ret
+
+ .epilogue gpe_pba_setup
diff --git a/src/lib/gpe_scom.h b/src/lib/gpe_scom.h
new file mode 100644
index 0000000..3f8f26e
--- /dev/null
+++ b/src/lib/gpe_scom.h
@@ -0,0 +1,471 @@
+#ifndef __GPE_SCOM_H__
+#define __GPE_SCOM_H__
+
+// $Id: gpe_scom.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe_scom.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe_scom.h
+/// \brief Generic SCOM procedures for PORE-GPE
+///
+/// We provide 2 generic SCOM procedures for PORE-GPE, one for P8 SCOMs and
+/// another for Centaur SCOMS. The setup and control of the procedures is
+/// roughly modeled after the way the simple SCOM-ing programs were described
+/// and implemented by the P7 OCA unit. This facility was written primarily to
+/// support SCOM-ing Centaur from OCC (which requires a complex setup),
+/// however for some core applications it may also be simpler to use a generic
+/// procedure rather than creating a custom GPE program to read/write P8 SCOM
+/// registers.
+///
+/// SCOM programs are set up and controlled through a GpeScomParms
+/// structure. This structure contains overall control and status information,
+/// as well as a pointer to an array of scomList_t structures which decribes
+/// the program. Each entry of the scomList_t describes one of several
+/// operations that can be performed on a SCOM address including read, write,
+/// and read-modify-write. Special control-only entries are also supported
+/// including a NOP, a programmable wait delay, timestamping with the TOD and
+/// special "SYNC" commands for Centaur. For more on the commands and their
+/// actions please see \ref gpe_scom_commands.
+///
+/// Each scomList_t entry also includes a data field and a mask field. The
+/// data field contains the data to write for SCOM writes and
+/// read-modify-writes, holds the data returned for SCOM reads, or contains a
+/// pointer to a data vector for vector commands. The mask is used in the case
+/// of read-modify-write to indicate which bits of the SCOM to modify. Control
+/// commands may also interpret these fields in different ways.
+
+
+#ifndef __ASSEMBLER__
+
+/// A SCOM command descriptor for gpe_scom_centaur amd gpe_scom_p8.
+///
+/// For an introduction to the use of this structure and the procedures that
+/// use please see the commants for the file gpe_scom.h
+///
+/// The \a scom field is the full 32-bit SCOM address of the targeted SCOM,
+/// initialized by the caller. SCOM addresses for P8 core SCOMs can be
+/// created from the chiplet-0 address using the macro
+/// CORE_CHIPLET_ADDRESS(). Multicast addresses for P8 can be generated using
+/// the macro MC_ADDRESS(). The notions of internal "chiplets" and "multicast"
+/// are not supported for Centaur SCOM addreses, so for Centaur this is always
+/// a simple SCOM address. The procedure gpe_scom_centaur() does support an
+/// iterative notion of multicast however. Some special control commands do
+/// not use this field at all; see \ref gpe_scom_commands.
+///
+/// The \a errorFlags field contains error status associated with the
+/// (attempted) SCOM access. This field is set by the procedure. For futher
+/// informaton on error handling please see each individual procedure.
+///
+/// The \a instanceNumber field is currently only used by
+/// gpe_scom_centaur(). For further details please see the documentation for
+/// gpe_scom_centaur().
+///
+/// The \a commandType field is initialized by the caller. For command
+/// documentation see \ref gpe_scom_commands and the individual procedures.
+///
+/// The \a data field is used to hold write data for SCOM write and
+/// read-modify-write commands (including the "all" forms), contains the
+/// returned read data for scalar SCOM read commands, and contains a pointer
+/// to a data vector for vector commands. Other commands may also use the \a
+/// data field for other purposes as documented with each command.
+///
+/// The \a mask field contains a positive bit mask used to identify the fields
+/// to update for SCOM read-modify-write. Other commands may also use the \a
+/// mask field for other purposes as documented with each command.
+///
+/// \note Because this structure is read and written by the GPE engine it is
+/// strongly recommended to allocate instances of this structure in
+/// non-cacheable data sections, with the caveat that data structures assigned
+/// to non-default data sections must always be initialized. For example:
+///
+/// \code
+///
+/// static scomList_t S_scomList[10]
+/// SECTION_ATTRIBUTE(".noncacheable") = {0};
+///
+/// \endcode
+
+typedef struct {
+ union
+ {
+ struct {
+ uint32_t scom;
+ uint8_t reserved;
+ uint8_t errorFlags;
+ uint8_t instanceNumber;
+ uint8_t commandType;
+ };
+ uint64_t command;
+ };
+ uint64_t mask;
+ union
+ {
+ uint64_t data;
+ struct {
+ uint32_t unused;
+ uint64_t* pData;
+ };
+ };
+} scomList_t;
+
+#else // __ASSEMBLER__
+
+ // scomList_t structure offsets
+
+ .set SCOM_LIST_COMMAND, 0x0
+ .set SCOM_LIST_MASK, 0x8
+ .set SCOM_LIST_DATA, 0x10
+ .set SIZEOF_SCOM_LIST_T, 0x18
+
+ // PGAS macros to extract fields of the scomList_t command. The source
+ // and target must be data registers, and they can be the same data
+ // register.
+
+ .macro scom_list_get_scom, target:req, source:req
+ extrdi \target, \source, 32, 0
+ .endm
+
+ .macro scom_list_get_instance_number, target:req, source:req
+ extrdi \target, \source, 8, 48
+ .endm
+
+ .macro scom_list_get_command_type, target:req, source:req
+ extrdi \target, \source, 8, 56
+ .endm
+
+ // PGAS macros to update fields of the scomList_t command. The source
+ // and target must be different data registers. The target is the
+ // current value and is updated with the new field held
+ // right-justified in the source. The source register is effectively
+ // destroyed by these operations.
+
+ .macro scom_list_set_error_flags, target:req, source:req
+ insrdi \target, \source, 8, 40
+ .endm
+
+ .macro scom_list_set_instance_number, target:req, source:req
+ insrdi \target, \source, 8, 48
+ .endm
+
+#endif // __ASSEMBLER__
+
+/// \defgroup gpe_scom_commands GPE SCOM Procedure Commands
+///
+/// \note Command 0 is not defined on purpose to trap errors.
+/// @{
+
+/// No operation
+#define GPE_SCOM_NOP 1
+
+/// Read from SCOM, depositing read data into the \a data field of the
+/// scomList_t.
+#define GPE_SCOM_READ 2
+
+/// Write to SCOM, taking write data from the \a data field of the scomList_t.
+#define GPE_SCOM_WRITE 3
+
+/// Read-Modify-Write.
+///
+/// This operation first reads the SCOM. Bits under the \a mask field of the
+/// scomList_t are then cleared in the read data. The masked read data is then
+/// ORed with the contents of the \a data field of the scomList_t and the
+/// result is written back to the SCOM address.
+///
+/// \note This command \e does \e not apply the mask to the data from the \a
+/// data field of the scomList_t. The caller should do this (if necessary)
+/// when setting up the scomList_t.
+///
+/// \note The procedures do not provide a way to distinguish errors that may
+/// have occurred on the initial read vs. those that may have occurred on the
+/// subsequenct write.
+#define GPE_SCOM_RMW 4
+
+/// For gpe_scom_centaur(), the \a data field of the scomList_t contains a
+/// 32-bit pointer (cast to a uint64_t) to an array of PGP_NCENTAUR uint64_t
+/// values. SCOM read data for each configured Centaur (MCS) is deposited in
+/// this array. Array entries for unconfigured Centaur are zeroed.
+#define GPE_SCOM_READ_VECTOR 5
+
+/// For gpe_scom_centaur(), write the \a data field of the scomList_t to
+/// all configured Centaur. Currently unsupported for gpe_scom_p8().
+#define GPE_SCOM_WRITE_ALL 6
+
+/// For gpe_scom_centaur(), perform read-modify write for all configured
+/// Centaur. Currently unsupported for gpe_scom_p8().
+#define GPE_SCOM_RMW_ALL 7
+
+/// Programmable wait delay
+///
+/// This command simply waits for an interval of time specified by the \a data
+/// field of the scomList_t. Use the macro GPE_SCOM_WAIT_DELAY() to convert
+/// SSX (OCC timebase) ticks into the correct units for this command. For
+/// example use GPE_SCOM_WAIT_DELAY(SSX_MILLISECONDS(10)) to wait 10 ms.
+///
+/// \note This operation blocks the GPE from completing any other work until
+/// the delay is finished.
+///
+/// \note This time delay can not be implemented with extreme precision due to
+/// the lack of a programmable wait delay in the PORE architecture, plus
+/// procedure overhead, bus and bus interface contention, etc. For
+/// applications requiring extremely precise timing it will be best to code
+/// those by hand in PORE assembler and run them in a dedicated lab-only
+/// setting.
+#define GPE_SCOM_WAIT 8
+
+/// Issue a generic Centaur SYNC
+///
+/// This command is only valid for gpe_scom_centaur(). This command creates
+/// and issues a generic SYNC command to Centaur. The caller is completely
+/// responsible for creating the contents of the data packet sent as part of
+/// the Centaur SYNC. The data packet is taken verbatim from the \a data field
+/// of the scomList_t, and sent to the MCS designated as the SYNC MCS in the
+/// global G_centaurConfiguration. For further details see the comments with
+/// the procedure gpe_scom_centaur() and the CentaurConfiguration structure.
+#define GPE_SCOM_CENTAUR_SYNC 9
+
+/// Issue a Centaur SYNC to all configured Centaur
+///
+/// This command is only valid for gpe_scom_centaur(). This command creates
+/// and issues a SYNC command to all configured Centaur. The data packet is
+/// taken from the \a data field of the scomList_t, and sent to the MCS
+/// designated as the SYNC MCS in the global G_centaurConfiguration. The
+/// caller is responsible for setting the SYNC command bits (bits 8:N); The
+/// procedure will fill bits 0:7 with a mask of all configured Centaur. For
+/// further details see the comments with the procedure gpe_scom_centaur() and
+/// the CentaurConfiguration structure.
+#define GPE_SCOM_CENTAUR_SYNC_ALL 10
+
+/// Read the TOD clock
+///
+/// This command reads the TOD clock and deposits the value into the \a data
+/// field of the scomList_t.
+#define GPE_SCOM_TOD 11
+
+/// @}
+
+
+#ifndef __ASSEMBLER__
+
+/// \defgroup centaur_sync_commands Centaur SYNC Command Bits
+///
+/// The Centaur SYNC command is an 8-byte word written to a specific in-band
+/// address. SYNC commands are generated by the gpe_scom_centaur() procedure
+/// in response to the GPE_SCOM_CENTAUR_SYNC and GPE_SCOM_CENTAUR_SYNC_ALL
+/// commands (which see).
+///
+/// \note From the MCS Unit Workbook: Note that only the N/M Throttle sync
+/// command will be used operationally in P-series, although if will be
+/// possible to test all the sync commands in P-series lab testing. Z-series
+/// will use all specified sync command types. ... Valid combinations of bits
+/// (8:15) are: b00000000, bVVVVVV0V, and b00000010, where V = 0 or 1.
+///
+/// @{
+
+#define CENTAUR_GENERATE_REFRESH_COUNTER_SYNC 0x0080000000000000ull
+#define CENTAUR_RESET_CALIBRATION_COUNTER_1_SYNC 0x0040000000000000ull
+#define CENTAUR_RESET_CALIBRATION_COUNTER_2_SYNC 0x0020000000000000ull
+#define CENTAUR_RESET_CALIBRATION_COUNTER_3_SYNC 0x0010000000000000ull
+#define CENTAUR_RESET_N_M_THROTTLE_COUNTER_SYNC 0x0008000000000000ull
+#define CENTAUR_RESET_MB_TIMEBASE_SYNC 0x0004000000000000ull
+#define CENTAUR_SUPER_SYNC 0x0002000000000000ull
+#define CENTAUR_MYSTERY_SYNC 0x0001000000000000ull
+
+/// \todo Figure out what is the "mystery sync"
+
+/// @}
+
+
+/// Convert an SsxInterval to a delay specification for gpe_scom_*()
+
+// Yes, Virginia, the PORE engine takes 20 cycles to decrement and branch :(
+#define GPE_SCOM_WAIT_DELAY(x) ((x) / 20)
+
+
+/// Parameters for gpe_scom_centaur() and gpe_scom_p8().
+///
+/// A pointer to an initialized GpeScomParms structure is passed as the
+/// parameter to the GPE procedures gpe_scom_centaur() and gpe_scom_p8.
+///
+/// \note Because this structure is read and written by the GPE engine it is
+/// strongly recommended to allocate instances of this structure in
+/// non-cacheable data sections, with the caveat that data structures assigned
+/// to non-default data sections must always be initialized. For example:
+///
+/// \code
+///
+/// static GpeScomParms S_scomParms
+/// SECTION_ATTRIBUTE(".noncacheable") = {0};
+///
+/// \endcode
+
+typedef struct {
+
+ /// Input: The SCOM list
+ ///
+ /// This is a right-justfied pointer to an array of scomList_t structures
+ /// describing the sequence of commands to execute.
+ uint64_t scomList;
+
+ /// Input: The number of entries in the scomList.
+ ///
+ /// \note It is considered an error if \a entries is 0, under the
+ /// assumption that the caller must have neglected to initialize the
+ /// structure.
+ uint32_t entries;
+
+ /// Input: Procedure options
+ ///
+ /// An OR-mask of option flags; See \ref gpe_scom_options;
+ uint32_t options;
+
+ /// Output: The procedure return code
+ ///
+ /// This field will contain 0 in the event of a successful return, and a
+ /// non-zero value in the event of an error. See \ref gpe_scom_rc for
+ /// documentation of the possible return codes.
+ uint32_t rc;
+
+ /// Output: The index of the entry that failed
+ ///
+ /// In the event that \a rc != 0, this field will contain the 0-based
+ /// index of the \a scomList entry that was being processed at the time of
+ /// the failure, or -1 for failures associated with the parameters or
+ /// setup of the procedure.
+ int32_t errorIndex;
+
+} GpeScomParms;
+
+#else // __ASSEMBLER__
+
+ // Offsets into the GpeScomParms structure
+
+ .set GPE_SCOM_PARMS_SCOM_LIST, 0x00
+ .set GPE_SCOM_PARMS_ENTRIES_OPTIONS, 0x08
+ .set GPE_SCOM_PARMS_RC_ERROR_INDEX, 0x10
+
+ // PGAS macros to extract fields of the GpeScomParms. The source
+ // and target must be data registers, and they can be the same data
+ // register.
+
+ .macro gpe_scom_parms_get_entries, target:req, source:req
+ extrdi \target, \source, 32, 0
+ .endm
+
+ .macro gpe_scom_parms_get_options, target:req, source:req
+ extrdi \target, \source, 32, 32
+ .endm
+
+ .macro gpe_scom_parms_get_rc, target:req, source:req
+ extrdi \target, \source, 32, 0
+ .endm
+
+ // PGAS macros to update fields of the GpeScomParms. The source
+ // and target must be different data registers. The target is the
+ // current value and is updated with the new field held
+ // right-justified in the source. The source register is effectively
+ // destroyed by these operations.
+
+ .macro gpe_scom_parms_set_rc, target:req, source:req
+ insrdi \target, \source, 32, 0
+ .endm
+
+ .macro gpe_scom_parms_set_error_index, target:req, source:req
+ insrdi \target, \source, 32, 32
+ .endm
+
+#endif // __ASSEMBLER__
+
+
+/// \defgroup gpe_scom_rc Return Codes From GPE SCOM Procedures
+///
+/// @{
+
+/// Successful completion of a GPE SCOM program
+#define GPE_SCOM_SUCCESS 0
+
+/// An error occurred during setup of the PBA for Centaur access. If this
+/// error code is returned then the \a errorIndex field of the GpeScomParms
+/// structure will be set to -1.
+#define GPE_SCOM_SETUP_ERROR 1
+
+/// One of the fields of the GpeScomParms structure is invalid. In the case of
+/// gpe_scom_centaur(), this code may also be returned if there is a problem
+/// with the global structure G_centaurConfiguration. If this error code is
+/// returned then the \a errorIndex field of the GpeScomParms structure will
+/// be set to -1 if the error occurred before command processing begins.
+#define GPE_SCOM_INVALID_ARGUMENT 2
+
+/// The procedure died. Since GPE procedures do not trap errors by default
+/// they will typically die on the first hardware-detected error, and GPE
+/// error recovery procedures will clean up the failed job. If this error code
+/// is returned then the \a errorIndex field of the GpeScomParms structure
+/// will indicate the \a scomList entry being processed at the time of the
+/// failure.
+#define GPE_SCOM_DIED 3
+
+/// The \a commandType field of the scomList_t was not valid for the procedure.
+/// When this error is signalled then the \a errorIndex field of the
+/// GpeScomParms structure contains the index of the failing entry.
+#define GPE_SCOM_INVALID_COMMAND 4
+
+/// Signalled only by gpe_scom_centaur(), the \a instanceNumber field of the
+/// scomList_t did not index a valid (configured) Centaur. This error is only
+/// signalled by the GPE_SCOM_READ, GPE_SCOM_WRITE and GPE_SCOM_RMW commands
+/// that require a valid Centaur to be specified. When this error is signalled
+/// then the \a errorIndex field of the GpeScomParms structure contains the
+/// index of the failing entry.
+#define GPE_SCOM_INVALID_CENTAUR 5
+
+/// @}
+
+
+/// Execute a SCOM program for Centaur SCOMs
+///
+/// \param[in,out] io_parms A pointer to an initialized GpeScomParms
+/// structure. Since this structure is used both for input of parameterization
+/// and output of return codes it is imperitive that this structure is
+/// allocated in non-cacheable memory to avoid cache-related bugs. See the
+/// documentation for the fields of GpeScomParms for more information.
+///
+/// gpe_scom_centaur() is a GPE program that takes a pointer to an initialized
+/// GpeScomParms structure as input and executes the list of SCOMs and other
+/// commands. Return codes are returned in the GpeScomParms.
+///
+/// The following notes relate to the fields of the scomList_t structure when
+/// used by gpe_scom_centaur().
+///
+/// - \a instanceNumber : This field must be set to the index (0 - 7) of the
+/// Centaur (MCS) to access for the commands GPE_SCOM_READ, GPE_SCOM_WRITE and
+/// GPE_SCOM_RMW. This field is ignored by other commands.
+///
+/// - \a commandType : gpe_scom_centaur() supports the special command types
+/// GPE_SCOM_CENTAUR_SYNC and GPE_CENTAUR_SYNC_ALL as documented in \ref
+/// gpe_scom_commands.
+///
+/// - \a data : The commands GPE_SCOM_CENTAUR_SYNC and
+/// GPE_SCOM_CENTAUR_SYNC_ALL require a unique format for the \a data field as
+/// documented with the command.
+#ifdef DOXYGEN_ONLY
+void gpe_scom_centaur(GpeScomParms *io_parms);
+#endif
+
+#ifndef __ASSEMBLER__
+
+// Procedure entry points
+
+PoreEntryPoint gpe_scom_centaur;
+PoreEntryPoint gpe_scom_p8;
+
+// Debugging symbols
+
+extern uint64_t G_gsc_lastSlaveControl SECTION_ATTRIBUTE(".data.pore");
+extern uint64_t G_gsc_lastScomAddress SECTION_ATTRIBUTE(".data.pore");
+extern uint64_t G_gsc_lastOciAddress SECTION_ATTRIBUTE(".data.pore");
+
+#endif // __ASSEMBLER__
+
+#endif // __GPE_SCOM_H__
diff --git a/src/lib/gpe_scom.pS b/src/lib/gpe_scom.pS
new file mode 100644
index 0000000..2df1b78
--- /dev/null
+++ b/src/lib/gpe_scom.pS
@@ -0,0 +1,709 @@
+// $Id: gpe_scom.pS,v 1.2 2013/12/13 23:04:33 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe_scom.pS,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpe_scom.pS
+/// \brief Generic SCOM procedures for PORE-GPE
+
+ .nolist
+
+#include "ssx.h"
+#include "pgas.h"
+#include "pgp_config.h"
+#include "gpe.h"
+#include "gpe_pba.h"
+#include "gpe_scom.h"
+
+ .list
+
+ .oci
+ .text.pore
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Common Routines
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gsWait
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // The wait loop is implemented as a decrement and branch guaranteed
+ // to hit in the I-cache. This is used both by gpe_scom_centaur() and
+ // gpe_scom_p8().
+gsWait:
+ ld D0, SCOM_LIST_DATA, A1
+ braz D0, gsWaitDone
+ bra gsWaitLoop
+
+ .set PORE_INSTRUCTION_BUFFER_SIZE, 8 # Should be global?
+ .balign PORE_INSTRUCTION_BUFFER_SIZE
+gsWaitLoop:
+ subs D0, D0, 1
+ branz D0, gsWaitLoop
+
+gsWaitDone:
+ ret
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gsTod
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+gsTod:
+ lpcs P0, TOD_VALUE_REG
+ ld D0, TOD_VALUE_REG, P0
+ std D0, SCOM_LIST_DATA, A1
+ ret
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// gpe_scom_centaur
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+// gpe_scom_centaur() has 2 entry points: The first, gpe_scom_centaur(), is for
+// the "normal" case that the job is kicked off by the async drivers. The
+// second, _gpe_scom_centaur() is for use as a subroutine call.
+
+// Implementation note: Correctness requires that gpe_scom_centaur() maintins
+// strict control over the PBA slave as the command list is processed. At
+// entry the slave is reset, and then set up to do the cache-inibited partial
+// writes used for Centaur inband SCOM. Prior to every access the extended
+// address portion of the slave control register needs to be modified as it
+// contains part of the address that actually goes out on the PowerBus. For
+// reads there is no issue with setting the extended address at any
+// time. Since cache-inhibited partial reads are not prefetched, once a read
+// completes to the GPE the extended address is no longer in play. This is
+// not the case for writes. Just because a write completes on the OCI does not
+// mean that the write has completed at Centaur, and it is possible that
+// modifying the extended address before the write completes at Centaur can
+// cause a write to be corrrupted. The means that in general we need to reset
+// the slave prior to modifying the extended address to guarantee that any
+// outstanding write has made it to Centaur. As a run-time optimization we
+// only reset the slave after doing write operations.
+
+// At entry (gpe_scom_centaur):
+//
+// ETR : Contains a pointer to the GpeScomParms structure to interpret.
+//
+// At entry (_gpe_scom_centaur):
+//
+// A0 : Contains a pointer to the GpeScomParms structure to interpret.
+//
+// The caller should assume that all register state is destroyed by
+// calling _gpe_scom_centaur
+
+ .macro gscExit
+ la A0, gscCalledAsSubroutine
+ ld D0, 0, A0
+ braz D0, 4723948f
+ ret
+4723948:
+ halt
+ .endm
+
+
+ .global gpe_scom_centaur
+ .global _gpe_scom_centaur
+
+gpe_scom_centaur:
+ mr D0, ETR
+ ls D1, 0
+ bra gpe_scom_centaur_begin
+
+_gpe_scom_centaur:
+ mr D0, A0
+ ls D1, 1
+
+gpe_scom_centaur_begin:
+ la A0, gscParameters
+ std D0, 0, A0
+ la A0, gscCalledAsSubroutine
+ std D1, 0, A0
+ mr A1, D0
+
+ // Establish the "invalid argument" return code and check that the
+ // global centaur configuration is valid and the number of entries is
+ // non-zero and the pointer to the scomList is non-zero.
+
+ la A0, G_centaurConfiguration
+
+ ls D0, GPE_SCOM_INVALID_ARGUMENT
+ gpe_scom_parms_set_rc D1, D0
+ ls D0, -1
+ gpe_scom_parms_set_error_index D1, D0
+ std D1, GPE_SCOM_PARMS_RC_ERROR_INDEX, A1
+
+ ld D0, CENTAUR_CONFIGURATION_CONFIG_RC, A0
+ braz D0, 1f
+ gscExit # Configuration RC != 0 (Structure is invalid)
+
+1:
+ ld D0, GPE_SCOM_PARMS_ENTRIES_OPTIONS, A1
+ gpe_scom_parms_get_entries D1, D0
+ branz D1, 1f
+ gscExit # entries == 0
+
+1:
+ ld D0, GPE_SCOM_PARMS_SCOM_LIST, A1
+ branz D1, 1f
+ gscExit # scomList == 0
+
+1:
+ // Establish the "setup error" return code and error index for the PBA
+ // Slave reset, then reset the slave.
+ //
+ // At entry:
+ //
+ // A0 = &G_centaurConfiguration
+ // A1 = &GpeScomParms
+
+ ls D0, GPE_SCOM_SETUP_ERROR
+ gpe_scom_parms_set_rc D1, D0
+ ls D0, -1
+ gpe_scom_parms_set_error_index D1, D0
+ std D1, GPE_SCOM_PARMS_RC_ERROR_INDEX, A1
+
+ adds A0, A0, CENTAUR_CONFIGURATION_SCOM_PARMS
+ bsr gpe_pba_reset
+ bsr gpe_pba_setup
+
+
+ // Establish the "procedure died" return code, establish variables
+ // used during the iteration over the scomList, then begin iteration:
+ //
+ // GpeScomParms.[rc, errorIndex]
+ // CTR : The number of entries left to process.
+ // A1 : The address of the scomList_t being processed
+
+ la A0, gscParameters
+ ld D0, 0, A0
+ mr A0, D0
+
+ ls D0, GPE_SCOM_DIED
+ gpe_scom_parms_set_rc D1, D0
+ ls D0, 0
+ gpe_scom_parms_set_error_index D1, D0
+ std D1, GPE_SCOM_PARMS_RC_ERROR_INDEX, A0
+
+ ld D0, GPE_SCOM_PARMS_SCOM_LIST, A0
+ mr A1, D0
+
+ ld D0, GPE_SCOM_PARMS_ENTRIES_OPTIONS, A0
+ gpe_scom_parms_get_entries D0, D0
+ mr CTR, D0
+ loop gscLoop # We know CTR != 0, so this is a branch to
+ # gscLoop w/side effect of CTR--
+
+ // Loop over the scomList, dispatching the commands.
+ //
+ // Loop invariants:
+ //
+ // GpeScomParms.entries has the number of entries processed so
+ // far.
+ //
+ // A1 : The address of the scomList_t being processed
+ //
+ // CTR : Counting down the entries left to process.
+ //
+ // Command dispatch invariants
+ //
+ // A1 : Holds the pointer to the scomList being processed
+gscLoop:
+ ld D1, SCOM_LIST_COMMAND, A1
+ scom_list_get_command_type D0, D1
+
+ // Commands listed in rough order of expected use
+
+ cmpibraeq D0, gscReadVector, GPE_SCOM_READ_VECTOR
+ cmpibraeq D0, gscWriteAll, GPE_SCOM_WRITE_ALL
+ cmpibraeq D0, gscRMWAll, GPE_SCOM_RMW_ALL
+ cmpibraeq D0, gscRead, GPE_SCOM_READ
+ cmpibraeq D0, gscSyncAll, GPE_SCOM_CENTAUR_SYNC_ALL
+ cmpibraeq D0, gscWrite, GPE_SCOM_WRITE
+ cmpibraeq D0, gscRMW, GPE_SCOM_RMW
+ cmpibraeq D0, gscSync, GPE_SCOM_CENTAUR_SYNC
+ cmpibraeq D0, gscTod, GPE_SCOM_TOD
+ cmpibraeq D0, gscWait, GPE_SCOM_WAIT
+ cmpibraeq D0, gscContinue, GPE_SCOM_NOP
+
+ bra gscInvalidCommand
+
+
+ // Continue the loop. Update the index number and scomList pointer.
+gscContinue:
+ la A0, gscParameters
+ ld D0, 0, A0
+ mr A0, D0
+
+ ld D0, GPE_SCOM_PARMS_RC_ERROR_INDEX, A0
+ adds D0, D0, 1 # errorIndex is in low-order word
+ std D0, GPE_SCOM_PARMS_RC_ERROR_INDEX, A0
+
+ adds A1, A1, SIZEOF_SCOM_LIST_T
+
+ loop gscLoop
+
+ // We completed successfully. Set the final rc to 0 and halt.
+
+ ls D0, 0
+ std D0, GPE_SCOM_PARMS_RC_ERROR_INDEX, A0
+ gscExit
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscWrite
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // Do a single Centaur in-band SCOM write. The actual SCOM write is
+ // coded as a subroutine for use by the write-all as well.
+gscWrite:
+ ld D0, SCOM_LIST_COMMAND, A1
+ scom_list_get_instance_number D0, D0
+ bsr gscScomSetup
+ branz D0, gscInvalidCentaur
+
+ bsr gscWrite1
+ bsr gscResetSlave
+ bra gscContinue
+
+
+gscWrite1:
+ ld D0, SCOM_LIST_DATA, A1
+ std D0, 0, A0
+ ret
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscWriteAll
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // It is simplest here to simply unroll a loop that does the SCOM
+ // write for all Centaur indices that pass as being valid.
+gscWriteAll:
+ .set __CENTAUR__, 0
+ .rept PGP_NCENTAUR
+ ls D0, __CENTAUR__
+ bsr gscScomSetup
+ branz D0, 1f
+ bsr gscWrite1
+ bsr gscResetSlave
+1:
+ .set __CENTAUR__, __CENTAUR__ + 1
+ .endr
+
+ bra gscContinue
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscRMW
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // Do a single Centaur in-band SCOM read-modify-write. SCOM data is
+ // ANDed with the inverted mask, then the new data is OR-ed in and
+ // stored back to SCOM. The actual RMW is coded as a subroutine for
+ // use by the RMW-all as well.
+gscRMW:
+ ld D0, SCOM_LIST_COMMAND, A1
+ scom_list_get_instance_number D0, D0
+ bsr gscScomSetup
+ branz D0, gscInvalidCentaur
+
+ bsr gscRMW1
+ bsr gscResetSlave
+ bra gscContinue
+
+
+gscRMW1:
+ ld D0, 0, A0
+ ld D1, SCOM_LIST_MASK, A1
+ xori D1, D1, 0xffffffffffffffff
+ and D0, D0, D1
+ ld D1, SCOM_LIST_DATA, A1
+ or D0, D0, D1
+ std D0, 0, A0
+
+ ret
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscRMWAll
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // It is simplest here to simply unroll a loop that does the SCOM
+ // RMW for all Centaur indices that pass as being valid.
+gscRMWAll:
+ .set __CENTAUR__, 0
+ .rept PGP_NCENTAUR
+ ls D0, __CENTAUR__
+ bsr gscScomSetup
+ branz D0, 1f
+ bsr gscRMW1
+ bsr gscResetSlave
+1:
+ .set __CENTAUR__, __CENTAUR__ + 1
+ .endr
+
+ bra gscContinue
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscRead
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // Do a single Centaur in-band SCOM read
+gscRead:
+ ld D0, SCOM_LIST_COMMAND, A1
+ scom_list_get_instance_number D0, D0
+ bsr gscScomSetup
+ branz D0, gscInvalidCentaur
+
+ ld D0, 0, A0
+ std D0, SCOM_LIST_DATA, A1
+ bra gscContinue
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscReadVector
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // It is simplest here to simply unroll a loop that does the SCOM
+ // read for all Centaur indices that pass as being valid.
+gscReadVector:
+ .set __CENTAUR__, 0
+ .rept PGP_NCENTAUR
+ ls D0, __CENTAUR__
+ bsr gscScomSetup
+ ls D1, __CENTAUR__ * 8 # Byte offset
+ bsr gscReadVector1
+ .set __CENTAUR__, __CENTAUR__ + 1
+ .endr
+
+ bra gscContinue
+
+
+gscReadVector1:
+ // At entry, A1 points to the scomList_t, and D1 has the index of the
+ // Centaur being processed. If D0 == 0 then the read is indicated and
+ // A0 contains the address to dereference to accomplish the read. If
+ // D0 != 0, then the Centaur is invalid and we'll zero the data.
+
+ braz D0, 1f
+
+ // No read indicated. Load the data pointer, convert to an indexed
+ // address and store a 0. We can scratch A0 here.
+
+ ld D0, SCOM_LIST_DATA, A1
+ add D0, D0, D1
+ mr A0, D0
+ ls D0, 0
+ std D0, 0, A0
+ ret
+
+ // A read is indicated. Load the data pointer and convert to an
+ // indexed address in D1. Then load the SCOM data into D0 and store it
+ // back at the indexed address.
+1:
+ ld D0, SCOM_LIST_DATA, A1
+ add D1, D0, D1
+ ld D0, 0, A0
+ mr A0, D1
+ std D0, 0, A0
+ ret
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscSync
+ // gscSyncAll
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // These commands only differ in whether the user fills in the mask of
+ // valid Centaurs or the procedure fills in the mask of valid Centaurs
+ // from the global configuration. The extended address needed for the
+ // sync is stored in the global data structure, and it is only
+ // necessary to update the slave and store to the base address of the
+ // PBA BAR to accomplish the SYNC.
+gscSync:
+ bsr gscSyncSetup
+ ld D0, SCOM_LIST_DATA, A1
+ bra gscSyncContinue
+
+gscSyncAll:
+ bsr gscSyncSetup
+ la A0, G_centaurConfiguration
+ ld D0, CENTAUR_CONFIGURATION_CONFIG, A0
+ left_justify_centaur_config D0
+ ld D1, SCOM_LIST_DATA, A1
+ or D0, D0, D1
+ bra gscSyncContinue
+
+
+ // To set up the SYNC we only have to update the extended address
+ // field (bits 35:48) of the slave control register from the slave
+ // control register image held in the G_centaurConfiguration. We can't
+ // destroy A1 so it's a little tedious as we have to load the slave
+ // control register address twice.
+gscSyncSetup:
+ la A0, G_centaurConfiguration
+ ld D1, \
+ (CENTAUR_CONFIGURATION_SCOM_PARMS + \
+ GPEPBAPARMS_SLVCTL_ADDRESS), \
+ A0
+ mr A0, D1
+ ld D0, 0, A0
+
+ la A0, G_centaurConfiguration
+ ld D1, CENTAUR_CONFIGURATION_SYNC_SLAVE_CONTROL, A0
+ rldimi D0, D1, 0, 35, 48
+
+ la A0, G_centaurConfiguration
+ ld D1, \
+ (CENTAUR_CONFIGURATION_SCOM_PARMS + \
+ GPEPBAPARMS_SLVCTL_ADDRESS), \
+ A0
+ mr A0, D1
+ std D0, 0, A0
+
+ ret
+
+
+ // Once it's set up, simply issue a store to complete the sync. The
+ // caller has placed the correct data in D0.
+gscSyncContinue:
+ la A0, (PBA_BAR_CENTAUR << 28)
+ std D0, 0, A0
+ bsr gscResetSlave
+ bra gscContinue
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscWait
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+gscWait:
+ bsr gsWait
+ bra gscContinue
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscTod
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+gscTod:
+ bsr gsTod
+ bra gscContinue
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscScomSetup
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // At entry:
+ //
+ // A1 : The address of the scomList_t being processed
+ // D0 : The Centaur instance number to set up
+ //
+ // At exit:
+ //
+ // PBA : Programmed to do the SCOM
+ // A1 : The address of the scomList_t being processed
+ // A0 : On success, the OCI address to load/store to do the SCOM
+ // D0 : 0 = Success, otherwise an error code
+ //
+ // This routine checks the Centaur instance number for validity. If
+ // the instance number is valid then the PBA is programmed to access
+ // the SCOM address held in the scomList_t. This requires
+ // reprogramming the PBA because part of the SCOM address must be
+ // stored as the extended address field of the PBA slave control
+ // register. It is not necessary to reset the PBA slave for each SCOM
+ // operation. The way SCOM operations are set up they "complete
+ // immediately" in the PBA so there is no issue with lingering state.
+ //
+ // Note: this routine is written this way (separating setup from
+ // execution) to support the Centaur "multicast" and read-modify-write
+ // operations. The multicast loop simply tries all Centaur and ignores
+ // the ones that fail.
+gscScomSetup:
+
+ // Check the Centaur instance number (D0) for validity.
+
+ ls D1, PGP_NCENTAUR
+ sub D1, D0, D1
+ tfbult D1, 1f
+
+ ls D0, GPE_SCOM_INVALID_ARGUMENT
+ ret # Centaur instance too big
+
+1:
+ // Check to make sure the Centaur is configured by testing the base
+ // address for 0. The instance number is first multiplied by 8 to
+ // create an array offset.
+
+ rotldi D0, D0, 3
+ la D1, G_centaurConfiguration
+ adds D1, D1, CENTAUR_CONFIGURATION_BASE_ADDRESS
+ add D0, D0, D1
+ mr A0, D0
+ ld D0, 0, A0
+ branz D0, 1f
+
+ ls D0, GPE_SCOM_INVALID_ARGUMENT
+ ret # Base address is 0
+
+1:
+ // We have the Centaur base address in D0, and convert it to the full
+ // PowerBus address for the inband SCOM. Bit 27 is set to indicate OCC
+ // (vs. FSP) access. Bit 28 remains 0 to indicate a SCOM (vs. sensor
+ // cache) access. Bits 29:60 are the SCOM address. (The SCOM address
+ // is shifted up by 3 bit positions). We need to save A1 to SPRG0 to
+ // continue from here.
+
+ ori D0, D0, 0x0000001000000000
+ ld D1, SCOM_LIST_COMMAND, A1
+ scom_list_get_scom D1, D1
+ rotldi D1, D1, 3
+ or D0, D0, D1
+
+ mr SPRG0, A1
+
+#if 1
+ la A1, G_gsc_lastScomAddress # Debug
+ std D0, 0, A1
+#endif
+
+ // The low-order 27 bits of the PowerBus address are OR-ed with the
+ // PBA BAR base address and go into A0 as the returned OCI address.
+
+ andi D1, D0, 0x7ffffff
+ ori D1, D1, (PBA_BAR_CENTAUR << 28)
+ mr A0, D1
+
+ // Bits 23:36 of the address go into the extended address field (35:
+ // 48) of the PBA slave control register by a read-modify-write
+ // operation. Note: We're using rldimi explicitly here - not an
+ // extended mnemonic - to save having to justify the data.
+
+ la A1, G_centaurConfiguration
+ ld D1, \
+ (CENTAUR_CONFIGURATION_SCOM_PARMS + \
+ GPEPBAPARMS_SLVCTL_ADDRESS), \
+ A1
+ mr A1, D1
+ ld D1, 0, A1
+ rldimi D1, D0, 64 - (35 - 23), 35, 48
+ std D1, 0, A1
+
+#if 1
+ la A1, G_gsc_lastSlaveControl # Debug
+ std D1, 0, A1
+ mr D1, A0
+ la A1, G_gsc_lastOciAddress
+ std D1, 0, A1
+#endif
+
+ // Restore A1 to its invariant state, clear D0 to signal success and
+ // we're out
+
+ mr A1, SPRG0
+ ls D0, 0
+ ret
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscResetSlave
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // Reset the PBA slave after a write. This requires saving and
+ // restoring A1. To avoid PORE stack overflow we have to inline
+ // gpe_pba_reset() here. See the file gpe_pba_pgas.pS for comments on
+ // why the slave reset is written like this.
+
+gscResetSlave:
+ la A0, gscSaveA1
+ mr D0, A1
+ std D0, 0, A0
+
+ la A0, G_centaurConfiguration + CENTAUR_CONFIGURATION_SCOM_PARMS
+ bra gscGpePbaReset
+
+ .balign 128
+gscGpePbaReset:
+ la A1, PBA_SLVRST
+ ld D0, GPEPBAPARMS_SLVRST, A0
+ std D0, 0, A1
+
+ ld D0, GPEPBAPARMS_SLVRST_IN_PROGRESS, A0
+ ld D1, 0, A1
+ and D0, D0, D1
+ branz D0, gscGpePbaReset
+
+ la A0, gscSaveA1
+ ld D0, 0, A0
+ mr A1, D0
+
+ ret
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gscInvalidCommand
+ // gscInvalidCentaur
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //
+ // Set the rc field. The errorIndex has already been set.
+
+gscInvalidCommand:
+ ls D1, GPE_SCOM_INVALID_COMMAND
+ bra 1f
+gscInvalidCentaur:
+ ls D1, GPE_SCOM_INVALID_CENTAUR
+1:
+ la A0, gscParameters
+ ld D0, 0, A0
+ mr A0, D0
+
+ ld D0, GPE_SCOM_PARMS_RC_ERROR_INDEX, A0
+ gpe_scom_parms_set_rc D0, D1
+ std D0, GPE_SCOM_PARMS_RC_ERROR_INDEX, A0
+ gscExit
+
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // gpe_scom_centaur Global Data
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ .data.pore
+
+ // Set to 0/1 when gpe_scom_centaur() is called via
+ // gpe_scom_centaur (ASYNC) / _gpe_scom_centaur (Subroutine)
+
+gscCalledAsSubroutine:
+ .quad 0
+
+
+ // Used to store the parameter block pointer
+
+gscParameters:
+ .quad 0
+
+
+ // Used to store A1 during the inner loop when we need to reset the
+ // slave after a write
+
+gscSaveA1:
+ .quad 0
+
+
+ // Debug only, the last values computed by gscScomSetup.
+
+ .global G_gsc_lastSlaveControl
+G_gsc_lastSlaveControl:
+ .quad 0
+
+ .global G_gsc_lastScomAddress
+G_gsc_lastScomAddress:
+ .quad 0
+
+ .global G_gsc_lastOciAddress
+G_gsc_lastOciAddress:
+ .quad 0
diff --git a/src/lib/gpsm.c b/src/lib/gpsm.c
new file mode 100755
index 0000000..e2b71d6
--- /dev/null
+++ b/src/lib/gpsm.c
@@ -0,0 +1,600 @@
+// $Id: gpsm.c,v 1.2 2014/02/03 01:30:24 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpsm.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpsm.c
+/// \brief Global Pstate Mechanism procedures
+///
+/// \todo : Should we initialize any/all iVRM delays in gpsm_lpsa_install()?
+
+#include "ssx.h"
+#include "pstates.h"
+#include "gpe_control.h"
+#include "gpsm.h"
+#include "vrm.h"
+
+/// The semaphore used to block threads waiting for GPSM protocol actions
+
+SsxSemaphore G_gpsm_protocol_semaphore;
+
+
+////////////////////////////////////////////////////////////////////////////
+// Private Utilities
+////////////////////////////////////////////////////////////////////////////
+
+// The mechanical transition to Firmware Pstate Mode - Not a procedure
+
+static void
+_gpsm_fw_mode(void)
+{
+ pmc_mode_reg_t pmr;
+
+ pmr.value = in32(PMC_MODE_REG);
+ pmr.fields.enable_hw_pstate_mode = 0;
+ pmr.fields.enable_fw_auction_pstate_mode = 0;
+ pmr.fields.enable_fw_pstate_mode = 1;
+ out32(PMC_MODE_REG, pmr.value);
+}
+
+
+// The mechanical transition to Firmware Auction Pstate Mode - Not a procedure
+
+static void
+_gpsm_fw_auction_mode(void)
+{
+ pmc_mode_reg_t pmr;
+
+ pmr.value = in32(PMC_MODE_REG);
+ pmr.fields.enable_hw_pstate_mode = 0;
+ pmr.fields.enable_fw_auction_pstate_mode = 1;
+ pmr.fields.enable_fw_pstate_mode = 0;
+ out32(PMC_MODE_REG, pmr.value);
+}
+
+
+// The mechanical transition to Hardware Pstate Mode - Not a procedure.
+// Disable voltage change via safe_mode_without_spivid
+// before enter hw mode to prevent possible glitch that
+// hw momentarily flush turbo to pstate actual,
+// After enter hw mode, we will enable back the spivid
+
+static void
+_gpsm_hw_mode(void)
+{
+ pmc_mode_reg_t pmr;
+
+ if (!gpsm_dcm_slave_p()) {
+ pmr.value = in32(PMC_MODE_REG);
+ pmr.fields.safe_mode_without_spivid = 1;
+ out32(PMC_MODE_REG, pmr.value);
+ }
+
+ pmr.value = in32(PMC_MODE_REG);
+ pmr.fields.enable_hw_pstate_mode = 1;
+ pmr.fields.enable_fw_auction_pstate_mode = 0;
+ pmr.fields.enable_fw_pstate_mode = 0;
+ out32(PMC_MODE_REG, pmr.value);
+
+ if (!gpsm_dcm_slave_p()) {
+ pmr.value = in32(PMC_MODE_REG);
+ pmr.fields.safe_mode_without_spivid = 0;
+ out32(PMC_MODE_REG, pmr.value);
+ }
+
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Private Sub-Procedures
+////////////////////////////////////////////////////////////////////////////
+
+// By definition, quiescing the GPSM always leaves the system in firmware
+// Pstate mode. This is necessary for a consistent specification due to the
+// fact that in general, Hardware Pstate mode can not be quiesced without
+// leaving that mode.
+
+// To quiesce the GPSM in firmware or firmware auction mode requires waiting
+// for both the voltage and frequency changes to be complete. Note that they
+// will never be ongoing simultaneously. This predicate is used for all
+// firmware-mode quiesce, even though normally only one part or the other
+// (voltage/protocol) is active.
+//
+// Recall that PMC interrupts are level-low, so if ongoing status is clear,
+// the operation is ongoing.
+
+static int
+gpsm_fw_quiesce(void)
+{
+ int rc = 0;
+
+ if (!ssx_irq_status_get(PGP_IRQ_PMC_PROTOCOL_ONGOING)) {
+ ssx_irq_enable(PGP_IRQ_PMC_PROTOCOL_ONGOING);
+ rc = ssx_semaphore_pend(&G_gpsm_protocol_semaphore, SSX_WAIT_FOREVER);
+ }
+
+ if ((!rc) && !ssx_irq_status_get(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING)) {
+ ssx_irq_enable(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING);
+ rc = ssx_semaphore_pend(&G_gpsm_protocol_semaphore, SSX_WAIT_FOREVER);
+ }
+
+ if (!rc) {
+ _gpsm_fw_mode();
+ }
+
+ return rc;
+}
+
+
+// To quiesce the GPSM in hardware mode requires waiting for any ongoing
+// Pstate change to be complete. Note that there is no guarantee that this
+// condition will ever be true in general unless something external to PMC
+// ensures that Global bids stop coming in to the GPSM. An alternative used
+// here is to 'lock' the GPSM temporarily by setting the rail bounds min and
+// max to the current Global Pstate Actual. The GPSM will eventually quiesce
+// at the global actual, and we can safely move to Firmware Pstate mode and
+// release the lock.
+//
+// Recall that PMC 'ongoing' interrupts are level-low, so if ongoing status is
+// clear, the operation is ongoing.
+
+static int
+gpsm_hw_quiesce(void)
+{
+ int rc = 0;
+ pmc_rail_bounds_register_t prbr, original_prbr;
+ pmc_pstate_monitor_and_ctrl_reg_t ppmacr;
+
+ ppmacr.value = in32(PMC_PSTATE_MONITOR_AND_CTRL_REG);
+
+ original_prbr.value = prbr.value = in32(PMC_RAIL_BOUNDS_REGISTER);
+ prbr.fields.pmin_rail = ppmacr.fields.gpsa;
+ prbr.fields.pmax_rail = ppmacr.fields.gpsa;
+ out32(PMC_RAIL_BOUNDS_REGISTER, prbr.value);
+
+ rc = _gpsm_hw_quiesce();
+
+ if (!rc) {
+ _gpsm_fw_mode();
+ out32(PMC_RAIL_BOUNDS_REGISTER, original_prbr.value);
+ }
+
+ return rc;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Public Predicates
+////////////////////////////////////////////////////////////////////////////
+
+/// Is the Global Pstate Mechanism quiesced?
+///
+/// This predicate can only truly be answered 'true' if we are not in
+/// hardware Pstate mode.
+///
+/// \retval 0 Either we're in Hardware Pstate Mode, or a Voltage/Frequency
+/// operation is ongoing.
+///
+/// \retval 1 We're not in Hardware Pstate Mode and no Voltage/Frequency
+/// operation is ongoing.
+
+int
+gpsm_quiesced_p(void)
+{
+ return !(gpsm_hw_mode_p() ||
+ !ssx_irq_status_get(PGP_IRQ_PMC_PROTOCOL_ONGOING) ||
+ !ssx_irq_status_get(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING));
+}
+
+/// Predicate: Is the PMC in hardware Pstate mode?
+///
+/// \returns 0/1
+
+int
+gpsm_hw_mode_p(void)
+{
+ pmc_mode_reg_t pmr;
+
+ pmr.value = in32(PMC_MODE_REG);
+ return (pmr.fields.enable_hw_pstate_mode != 0);
+}
+
+
+/// Predicate: Is the PMC in firmware auction Pstate mode?
+///
+/// \returns 0/1
+
+int
+gpsm_fw_auction_mode_p(void)
+{
+ pmc_mode_reg_t pmr;
+
+ pmr.value = in32(PMC_MODE_REG);
+ return (pmr.fields.enable_fw_auction_pstate_mode != 0);
+}
+
+
+/// Predicate: Is the PMC in firmware Pstate mode?
+///
+/// \returns 0/1
+
+int
+gpsm_fw_mode_p(void)
+{
+ pmc_mode_reg_t pmr;
+
+ pmr.value = in32(PMC_MODE_REG);
+ return (pmr.fields.enable_fw_pstate_mode != 0);
+}
+
+
+/// Predicate: Is the chip configured as a DCM?
+///
+/// \returns 0/1
+
+int
+gpsm_dcm_mode_p(void)
+{
+ pmc_mode_reg_t pmc_mode_reg;
+ pmc_mode_reg.value = in32(PMC_MODE_REG);
+ return pmc_mode_reg.fields.enable_interchip_interface;
+}
+
+
+/// Predicate: Is the chip configured as a DCM Slave?
+///
+/// \returns 0/1
+
+int
+gpsm_dcm_master_p(void)
+{
+ pmc_mode_reg_t pmc_mode_reg;
+ pmc_mode_reg.value = in32(PMC_MODE_REG);
+ return
+ pmc_mode_reg.fields.enable_interchip_interface &&
+ pmc_mode_reg.fields.interchip_mode;
+}
+
+
+/// Predicate: Is the chip configured as a DCM Slave?
+///
+/// \returns 0/1
+
+int
+gpsm_dcm_slave_p(void)
+{
+ pmc_mode_reg_t pmc_mode_reg;
+ pmc_mode_reg.value = in32(PMC_MODE_REG);
+ return
+ pmc_mode_reg.fields.enable_interchip_interface &&
+ (pmc_mode_reg.fields.interchip_mode == 0);
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// Procedures
+////////////////////////////////////////////////////////////////////////////
+
+/// Recover the GlobalPstateTable object from the PMC
+///
+/// \note It is assumed that the pointer to the Global Pstate table installed
+/// in the PMC is actually a pointer to a complete GlobalPstateTable object
+/// (which contains a Global Pstate table as its first element).
+///
+/// \returns A pointer to the currently active GlobalPstateTable object.
+
+GlobalPstateTable*
+gpsm_gpst(void)
+{
+ pmc_parameter_reg1_t ppr1;
+
+ ppr1.value = in32(PMC_PARAMETER_REG1);
+ return (GlobalPstateTable*)
+ (ppr1.fields.ba_sram_pstate_table << GLOBAL_PSTATE_TABLE_ALIGNMENT);
+}
+
+
+/// Quiesce the GPSM to firmware mode from any other mode
+///
+/// At the exit of this procedure, the PMC will be in Firmware Pstate Mode and
+/// there will be no ongoing voltage or frequency transitions.
+int
+gpsm_quiesce(void)
+{
+ int rc;
+
+ if (gpsm_hw_mode_p()) {
+ rc = gpsm_hw_quiesce();
+ } else {
+ rc = gpsm_fw_quiesce();
+ }
+
+ return rc;
+}
+
+/// Quiesce the GPSM in Hardware Pstate Mode
+///
+/// In general there is no guarantee that the GPSM will ever quiesce, or
+/// remain quiesced in Hardware Pstate Mode unless something like the
+/// procedure in gpsm_hw_quiesce() is used. This procedure is provided for
+/// the benefit of applications that are in complete control of Pstates
+/// (including idle state Pstates) to simply wait for the Pstate protocol to
+/// quiesce, without quiescing and entering Firmware Pstate mode like
+/// gpsm_hw_quiesce().
+
+int
+_gpsm_hw_quiesce(void)
+{
+ int rc;
+
+ do {
+ rc = 0;
+
+ if (!gpsm_hw_mode_p()) {
+ rc = -GPSM_ILLEGAL_MODE_HW_QUIESCE;
+ break;
+ }
+
+ if (!ssx_irq_status_get(PGP_IRQ_PMC_PROTOCOL_ONGOING)) {
+ ssx_irq_enable(PGP_IRQ_PMC_PROTOCOL_ONGOING);
+ rc = ssx_semaphore_pend(&G_gpsm_protocol_semaphore,
+ SSX_WAIT_FOREVER);
+ if (rc) break;
+ }
+ } while (0);
+
+ return rc;
+}
+
+
+/// Change to GPSM firmware mode from any mode
+
+int
+gpsm_fw_mode(void)
+{
+ return gpsm_quiesce();
+}
+
+
+/// Change to GPSM firmware auction mode from any mode
+
+int
+gpsm_fw_auction_mode(void)
+{
+ int rc;
+
+ rc = gpsm_quiesce();
+ if (!rc) {
+ _gpsm_fw_auction_mode();
+ }
+ return rc;
+}
+
+
+/// Change to Hardware Pstate Mode
+///
+/// The (unchecked) assumption behind this procedure is that the caller has
+/// run through Pstate intialization and enablement, and the system is in a
+/// state where the entry to Hardware Pstate Mode is safe once the GPSM is
+/// quiesced.
+
+int
+gpsm_hw_mode(void)
+{
+ int rc;
+
+ TRACE_GPSM(TRACE_GPSM_HW_MODE);
+
+ rc = gpsm_quiesce();
+ if (!rc) {
+ _gpsm_hw_mode();
+ }
+ return rc;
+}
+
+
+/// The default GPSM auction procedure
+///
+/// The default auction returns the value of
+/// PMC_HARDWARE_AUCTION_PSTATE_REG.haps.
+
+Pstate
+gpsm_default_auction(void)
+{
+ pmc_hardware_auction_pstate_reg_t phapr;
+
+ phapr.value = in32(PMC_HARDWARE_AUCTION_PSTATE_REG);
+ return phapr.fields.haps;
+}
+
+
+/// Update a user-supplied vector of Pstates with the current Global bid of
+/// each core.
+///
+/// \param[out] o_bids A vector of Pstates; The vector must be large enough to
+/// hold the bid of every possible core.
+///
+/// This routine is provided for use by non-default Global Pstate auction
+/// procedures.
+
+void
+gpsm_get_global_bids(Pstate *o_bids)
+{
+ // This takes advantage of the implicit layout of the
+ // PMC_CORE_PSTATE_REG<n>.
+
+ uint32_t *bids32 = (uint32_t *)o_bids;
+
+ bids32[0] = in32(PMC_CORE_PSTATE_REG0);
+ bids32[1] = in32(PMC_CORE_PSTATE_REG1);
+ bids32[2] = in32(PMC_CORE_PSTATE_REG2);
+ bids32[3] = in32(PMC_CORE_PSTATE_REG3);
+}
+
+
+/// Update a current Global bid of each core from a user supplied vector.
+///
+/// \param[in] i_bids An array of Global Pstate bids.
+///
+/// This routine is provided for use by test procedures; there is likely no
+/// product-level energy management application for this procedure.
+
+void
+gpsm_set_global_bids(const Pstate *i_bids)
+{
+ // This takes advantage of the implicit layout of the
+ // PMC_CORE_PSTATE_REG<n>.
+
+ uint32_t *bids32 = (uint32_t *)i_bids;
+
+ out32(PMC_CORE_PSTATE_REG0, bids32[0]);
+ out32(PMC_CORE_PSTATE_REG1, bids32[1]);
+ out32(PMC_CORE_PSTATE_REG2, bids32[2]);
+ out32(PMC_CORE_PSTATE_REG3, bids32[3]);
+}
+
+
+/// Application-controlled Global Actual Broadcast
+///
+/// \param[in] i_pstate The Global Actual Pstate to broadcast
+///
+/// \param[in] i_entry A gpst_entry_t containing the information to be used by
+/// the iVRM. If iVRM are not enabled then \a entry can be initialized to 0.
+///
+/// This API is provided for advanced applications to have complete control
+/// over a firmware-mode Global Actual broadcast. There is no error
+/// checking. Most applications in Firware Pstate mode will use the
+/// higher-level gpsm_broadcast_global_actual() API.
+
+void
+_gpsm_broadcast_global_actual(const Pstate i_pstate,
+ const gpst_entry_t i_entry)
+{
+ pmc_pstate_monitor_and_ctrl_reg_t ppmacr;
+ pmc_eff_global_actual_voltage_reg_t pegavr;
+
+ ppmacr.value = 0;
+ ppmacr.fields.gpsa = i_pstate;
+ out32(PMC_PSTATE_MONITOR_AND_CTRL_REG, ppmacr.value);
+
+ pegavr.value = 0;
+ pegavr.fields.maxreg_vdd = i_entry.fields.maxreg_vdd;
+ pegavr.fields.maxreg_vcs = i_entry.fields.maxreg_vcs;
+ pegavr.fields.eff_evid_vdd = i_entry.fields.evid_vdd_eff;
+ pegavr.fields.eff_evid_vcs = i_entry.fields.evid_vcs_eff;
+ out32(PMC_EFF_GLOBAL_ACTUAL_VOLTAGE_REG, pegavr.value);
+
+ TRACE_GPSM(TRACE_GPSM_BROADCAST_GLOBAL_ACTUAL);
+}
+
+
+/// Broadcast the Global Actual Pstate in firmware Pstate mode.
+///
+/// \param[in] i_gpst An initialized GlobalPstateTable structure used to
+/// define the legal Pstate range, and to provide the voltage settings
+/// (maxreg_vxx and eff_evid_vxx) for the internal VRM.
+///
+/// \param[in] i_pstate The pstate specfiying the Global Actual Pstate to be
+/// broadast to the core chiplets.
+///
+/// \param[in] i_bias This is a signed bias used to obtain the voltage Pstate,
+/// <em> in addition to the \a undervolting_bias already built into the Pstate
+/// table </em>. The iVRM information sent with the Global Actual Pstate comes
+/// from the \a pstate - \a undervolting_bias + \a bias entry of the Pstate
+/// table.
+///
+/// This API can be used in firware Pstate mode to broadcast a Global Actual
+/// Pstate and iVRM settings to the core chiplets. The API also supports
+/// optional under/over-volting. The requested Pstate will be broadcast along
+/// with the voltage information from the associated Pstate table entry.
+///
+/// Under/over-volting is specified by setting the \a bias to a non-0
+/// (signed) value. For example, to undervfolt by one Pstate (if possible),
+/// call the API with \a bias = -1.
+///
+/// This API always waits for the Global Pstate Machine to quiesce before
+/// proceeding with the Global Actual broadcast. Therefore it can only be
+/// called from thread mode, or from a non-thread mode guaranteed by the
+/// caller to have quiesced.
+///
+/// \note The application can use the _gpsm_broadcast_global_actual() API for
+/// complete control over the information transmitted to the cores.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -GPST_PSTATE_CLIPPED_HIGH_GPSM_BGA The requested Pstate does not
+/// exist in the table. The maximum Pstate entry in the table has been
+/// broadcast as the voltage Pstate.
+///
+/// \retval -GPST_PSTATE_CLIPPED_LOW_GPSM_BGA The requested Pstate does not
+/// exist in the table. The minimum Pstate entry in the table has been
+/// broadcast as the voltage Pstate.
+///
+/// The following return codes are considered errors:
+///
+/// \retval -GPSM_INVALID_OBJECT The Global Pstate Table is either null (0) or
+/// otherwise invalid.
+///
+/// \retval -GPSM_INVALID_ARGUMENT One or more arguments are invalid or
+/// inconsistent in some way.
+///
+/// \retval -GPSM_ILLEGAL_MODE_BGA The PMC is not in firmware pstate mode.
+///
+/// This API may also return errors from the SSX semaphore operations that
+/// implement the wait for quiescence.
+
+int
+gpsm_broadcast_global_actual(const GlobalPstateTable* i_gpst,
+ const Pstate i_pstate,
+ const int i_bias)
+{
+ int rc, bias_rc, entry_rc;
+ gpst_entry_t entry;
+ Pstate voltage_pstate;
+
+ do {
+
+ if (!gpsm_fw_mode_p()) {
+ rc = GPSM_ILLEGAL_MODE_BGA;
+ break;
+ }
+
+ // Bias the pstate, fetch the Pstate entry, quiesce and broadcast.
+ // bias_pstate() only returns saturation warnings. These are turned
+ // into bounds warnings if necessary (indicating that the Pstate
+ // saturated but the PMAX or PMIN was also a legal entry in the
+ // table).
+
+ bias_rc = bias_pstate(i_pstate, i_bias, &voltage_pstate);
+ entry_rc = gpst_entry(i_gpst, voltage_pstate, 0, &entry);
+ if (entry_rc &&
+ (entry_rc != -GPST_PSTATE_CLIPPED_LOW_GPST_ENTRY) &&
+ (entry_rc != -GPST_PSTATE_CLIPPED_HIGH_GPST_ENTRY)) {
+ rc = entry_rc;
+ break;
+ }
+
+ rc = gpsm_quiesce();
+ if (rc) break;
+
+ _gpsm_broadcast_global_actual(i_pstate, entry);
+
+ if (entry_rc != 0) {
+ rc = entry_rc;
+ } else if (bias_rc == -PSTATE_OVERFLOW_BIAS_PS) {
+ rc = -GPST_PSTATE_CLIPPED_HIGH_GPSM_BGA;
+ } else if (bias_rc == -PSTATE_UNDERFLOW_BIAS_PS) {
+ rc = -GPST_PSTATE_CLIPPED_LOW_GPSM_BGA;
+ }
+ } while (0);
+
+ return rc;
+}
+
+
diff --git a/src/lib/gpsm.h b/src/lib/gpsm.h
new file mode 100755
index 0000000..5af2e8d
--- /dev/null
+++ b/src/lib/gpsm.h
@@ -0,0 +1,191 @@
+#ifndef __GPSM_H__
+#define __GPSM_H__
+
+// $Id: gpsm.h,v 1.2 2014/02/03 01:30:24 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpsm.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpsm.h
+/// \brief PgP Global Pstate Machine (Mechanism)
+
+#include "ssx.h"
+#include "gpe_control.h"
+#include "pgp_async.h"
+#include "pstates.h"
+
+// GPSM modes
+
+#define GPSM_MODE_HW 1
+#define GPSM_MODE_FW_AUCTION 2
+#define GPSM_MODE_FW 3
+
+// Misc./Error/Panic codes
+
+#define GPSM_INVALID_OBJECT 0x00477601
+#define GPSM_INVALID_ARGUMENT_GPST_INSTALL 0x00477602
+#define GPSM_INVALID_ARGUMENT_LPST_INSTALL 0x00477603
+#define GPSM_INVALID_ARGUMENT_RCLK_INSTALL 0x00477604
+#define GPSM_INVALID_ARGUMENT_EPSS 0x00477605
+#define GPSM_ILLEGAL_MODE_HW_QUIESCE 0x00477606
+#define GPSM_ILLEGAL_MODE_BGA 0x00477607
+#define GPSM_ILLEGAL_MODE_GPST_INSTALL 0x00477608
+#define GPSM_ILLEGAL_MODE_LPST_INSTALL 0x00477609
+#define GPSM_ILLEGAL_MODE_RCLK_INSTALL 0x0047760a
+#define GPSM_ILLEGAL_MODE_GPSM_INIT 0x0047760b
+#define GPSM_ILLEGAL_MODE_EPSM 0x0047760c
+#define GPSM_ILLEGAL_MODE_EPSS 0x0047760d
+#define GPSM_SYNC_ERROR 0x0047760e
+#define GPSM_PSTATE_CLIPPED 0x0047760f
+#define GPSM_BUG 0x00477610
+#define GPSM_CONFIGURATION_ERROR 0x00477611
+#define GPSM_ERROR_BREAK 0x00477612
+#define GPSM_INVALID_MAGIC 0x00477613
+#define GPSM_IVRM_CALIBRATION_TIMEOUT 0x00477614
+#define GPSM_IVRM_GROSS_OR_FINE 0x00477615
+#define GPSM_PSTATE_ENABLED 0x00477616
+#define GPSM_BABYSTEPPER_SYNC_TIMEOUT 0x00477617
+#ifndef __ASSEMBLER__
+
+// Lab/VBU/VPO debugging
+
+#if 0
+#include "trace.h"
+#define TRACE_GPSM(i_code) trace_tbl_bbbb(1, i_code, 0, 0, 0);
+#define TRACE_GPSM_B(i_code, i_b0) trace_tbl_bbbb(1, i_code, i_b0, 0, 0);
+#define TRACE_GPSM_H(i_code, i_h0) trace_tbl_bbh(1, i_code, 0, i_h0);
+#else
+#define TRACE_GPSM(i_code)
+#define TRACE_GPSM_B(i_code, i_b0)
+#define TRACE_GPSM_H(i_code, i_h0)
+#endif
+
+
+/// Information required by an SCM or a DCM master to be passed from
+/// gpsm_enable_pstates_master() to gpsm_enable_pstates_slave().
+
+typedef struct {
+
+ /// Indicates whether or not gpsm_enable_pstates_slave() should move the
+ /// voltage.
+ ///
+ /// If 0, it means that the master has already moved the voltage and only
+ /// the frequency needs to move. If 1, voltage is moved after frequency
+ /// moves.
+ int move_voltage;
+
+ /// The current and target external voltage settings as VRM11 VID codes.
+ Vid11 currentVdd, currentVcs, targetVdd, targetVcs;
+
+} GpsmEnablePstatesMasterInfo;
+
+
+/// A GpsmAuctionProcedure is any function of no arguments that returns a
+/// Pstate
+
+typedef Pstate (*GpsmAuctionProcedure)();
+
+extern SsxSemaphore G_gpsm_protocol_semaphore;
+
+extern uint8_t G_gpsm_initialized;
+
+// APIs defined in gpsm_init.c
+
+int
+gpsm_gpst_install(GlobalPstateTable* o_gpst,
+ const GlobalPstateTable* i_source);
+
+int
+gpsm_lpsa_install(const LocalPstateArray* i_lpsa,
+ const PstateOptions* i_options);
+
+int
+gpsm_resclk_install(const ResonantClockingSetup* i_resclk,
+ const GlobalPstateTable* i_gpst,
+ const PstateOptions* i_options);
+
+int
+gpsm_initialize(const PstateSuperStructure* i_pss,
+ GlobalPstateTable* o_gpst);
+
+int
+gpsm_enable_pstates_master(GpsmEnablePstatesMasterInfo* o_info,
+ Pstate* o_voltage_pstate,
+ Pstate* o_frequency_pstate);
+
+int
+gpsm_enable_pstates_slave(const GpsmEnablePstatesMasterInfo* i_info,
+ const Pstate i_voltage_pstate,
+ const Pstate i_frequency_pstate);
+
+// APIs defined in gpsm.c
+
+int
+gpsm_quiesced_p(void);
+
+int
+gpsm_hw_mode_p(void);
+
+int
+gpsm_fw_auction_mode_p(void);
+
+int
+gpsm_fw_mode_p(void);
+
+int
+gpsm_dcm_mode_p(void);
+
+int
+gpsm_dcm_master_p(void);
+
+int
+gpsm_dcm_slave_p(void);
+
+GlobalPstateTable*
+gpsm_gpst();
+
+int
+gpsm_quiesce(void);
+
+int
+_gpsm_hw_quiesce(void);
+
+int
+gpsm_fw_mode(void);
+
+int
+gpsm_fw_auction_mode(void);
+
+int
+gpsm_hw_mode(void);
+
+Pstate
+gpsm_default_auction(void);
+
+void
+gpsm_get_global_bids(Pstate* o_bids);
+
+void
+gpsm_set_global_bids(const Pstate* i_bids);
+
+void
+_gpsm_broadcast_global_actual(const Pstate i_pstate,
+ const gpst_entry_t i_entry);
+
+int
+gpsm_broadcast_global_actual(const GlobalPstateTable *i_gpst,
+ const Pstate i_pstate,
+ const int i_bias);
+
+int
+gpsm_set_pstate(const Pstate i_pstate);
+
+int
+gpsm_hold_auction(const GpsmAuctionProcedure i_procedure);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __GPSM_H__ */
diff --git a/src/lib/gpsm_dcm.c b/src/lib/gpsm_dcm.c
new file mode 100755
index 0000000..452f7cf
--- /dev/null
+++ b/src/lib/gpsm_dcm.c
@@ -0,0 +1,753 @@
+// $Id: gpsm_dcm.c,v 1.2 2014/02/03 01:30:24 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpsm_dcm.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpsm_dcm.h
+/// \brief PgP Global PState Machine (Mechanism) in Dual Chip Model
+
+#include "ssx.h"
+#include "pmc_dcm.h"
+#include "gpsm_dcm.h"
+#include "gpsm.h"
+
+/// Timeout object and methods
+
+typedef struct {
+ SsxTimebase timeout;
+} Timeout;
+
+static void
+timeout_start(Timeout* t, SsxInterval timeout_period)
+{
+ t->timeout = ssx_timebase_get() + timeout_period;
+}
+
+static int
+timeout_timed_out(Timeout* t)
+{
+ return ssx_timebase_get() > t->timeout;
+}
+
+
+/// Internal API : Send packet with timeout
+///
+/// \param hwPacket pointer to the packet to be sent
+///
+/// \param timeout_period The SSX timeout variable
+///
+/// This API sends \a hwPacket within \a timeout_period
+/// if timed out, the function returns an error code
+///
+/// \retval GPSM_DCM_SUCCESS
+///
+/// \retval GPSM_DCM_SEND_PACKET_TIMEOUT
+///
+
+static int
+_gpsm_dcm_send(PmcDcmPacket* hwPacket,
+ SsxInterval timeout_period)
+{
+ int rc = GPSM_DCM_SUCCESS;
+ Timeout timeout;
+
+ //set timeout
+ timeout_start(&timeout, timeout_period);
+
+ //try to send packet within timeout
+ while( (rc=pmc_dcm_send(hwPacket)) == PMC_DCM_OUTSTANDING_TRANSFER ) {
+ if( timeout_timed_out(&timeout)) {
+ rc = GPSM_DCM_SEND_PACKET_TIMEOUT;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/// Internal API : Receive packet with timeout
+///
+/// \param hwPacket pointer to the packet structure to receive
+///
+/// \param timeout_period The SSX timeout variable
+///
+/// This API receives a \a hwPacket within \a timeout
+/// if timed out, the function returns an error code
+///
+/// \retval GPSM_DCM_SUCCESS
+///
+/// \retval GPSM_DCM_RECV_PACKET_TIMEOUT
+///
+
+static int
+_gpsm_dcm_receive(PmcDcmPacket* hwPacket,
+ SsxInterval timeout_period)
+{
+ int rc = GPSM_DCM_SUCCESS;
+ Timeout timeout;
+
+ //set timeout
+ timeout_start(&timeout, timeout_period);
+
+ //try to receive packet within timeout
+ while( (rc=pmc_dcm_receive(hwPacket)) == PMC_DCM_RECEIVE_NOT_DETECTED ) {
+ if( timeout_timed_out(&timeout)) {
+ rc = GPSM_DCM_RECV_PACKET_TIMEOUT;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// High-level GPSM-DCM Interfaces
+////////////////////////////////////////////////////////////////////////////
+
+/// Abstract non-blocking send over the DCM interchip link
+///
+/// The GPSM-DCM abstract interface guarantees that the PMC-DCM link is always
+/// clear for use by the master sender. This API (which should be called from
+/// a thread context) transmits an abstract packet, then polls for the hardware
+/// ACK - which must always indicate that the packet was received. This ACK
+/// will always occur very quickly.
+///
+/// \param fwPacket a GpsmDcmPacket structure to be sent as part of the
+/// PmcDcmPacket/hwPacket of MSG type via PMC interchip link.
+/// The fwPacket includes a firmware command and 16 bits payload.
+/// The firmware command will be filled in the cmd_ext field of the
+/// hwPacket structure, and payload 0,1 will be filled in the
+/// corresponding slots also in hwPacket structure.
+/// This argument is provided by the caller and passed in as reference.
+///
+/// hwPacket:
+///
+/// cmd_code | cmd_ext | payload 0 | payload 1 | ECC
+/// [0:3] | [4:7] | [8:15] | [16:23] | [24:31]
+///
+/// fwPacket:
+///
+/// | command | payload 0 | payload 1 |
+/// | [4:7] | [8:15] | [16:23] |
+///
+/// firmware command:
+///
+/// GPSM_DCM_DATA 0 //0b0000
+/// GPSM_DCM_WRITE 1 //0b0001
+/// GPSM_DCM_ENABLE_PSTATES 2 //0b0010
+/// GPSM_DCM_ENTER_HW_PSTATE_MODE 3 //0b0011
+///
+/// This API implements the lower level pmc_dcm_send API to send a firmware
+/// command as part of the PMC interchip message packet.
+///
+/// This API is working under a default time out, if send cannot be completed
+/// within the default timeout period due to possible busy interchip link,
+/// the function will exit with returning an error code:
+/// \a GPSM_DCM_SEND_PACKET_TIMEOUT
+///
+/// Prerequisite: The enable_interchip_interface bit of PMC_MODE_REG
+/// must be set to enable the PMC interchip transfer
+/// and lower level PMC-DCM API is required to use this
+/// high level GPSM-DCM API.
+/// Also, the hardware must be in DCM setup.
+///
+/// Note: This API must be called by the DCM Master, meaning the firmware
+/// command can only be given by the master to the slave.
+/// Also the API will check if the firmware command to be sent is valid.
+///
+/// \retval SUCCESS
+///
+/// \retval GPSM_DCM_ARG_INVALID_OBJ_SND
+///
+/// \retval GPSM_DCM_PKT_INVALID_CMD_SND
+///
+/// \retval GPSM_DCM_CMD_NOT_FROM_MASTER
+///
+
+int
+gpsm_dcm_send(GpsmDcmPacket* fwPacket) {
+
+ int rc = GPSM_DCM_SUCCESS;
+ PmcDcmPacket hwPacket;
+
+ TRACE_GPSM_B(TRACE_GPSM_DCM_SEND, fwPacket->command);
+
+ do {
+
+ //check if argument is NULL
+ SSX_ERROR_IF_CHECK_API(
+ (fwPacket == 0),
+ GPSM_DCM_ARG_INVALID_OBJ_SND);
+
+ //check if firmware command is valid
+ SSX_ERROR_IF_CHECK_API(
+ (fwPacket->command >= GPSM_DCM_NUMBER_OF_COMMANDS ||
+ fwPacket->command == GPSM_IC_DATA),
+ GPSM_DCM_PKT_INVALID_CMD_SND);
+
+ //check if is dcm master, note only master can send command to slave
+ SSX_ERROR_IF_CHECK_API(
+ (!pmc_dcm_if_dcm_master()),
+ GPSM_DCM_CMD_NOT_FROM_MASTER);
+
+ //form hardware packet from given firmware packet
+ hwPacket.value = 0;
+ hwPacket.fields.cmd_code = PMC_IC_MSG_CC;
+ hwPacket.fields.cmd_ext = fwPacket->command;
+ hwPacket.fields.payload[0] = fwPacket->payload.u8[0];
+ hwPacket.fields.payload[1] = fwPacket->payload.u8[1];
+
+ //send hardware packet
+ rc = _gpsm_dcm_send(&hwPacket, GPSM_DCM_DEFAULT_TIMEOUT);
+
+ } while (0);
+
+ TRACE_GPSM(TRACE_GPSM_DCM_SENT);
+
+ return rc;
+}
+
+
+/// Abstract blocking/non-blocking receive over the DCM interchip link
+///
+/// \param fwPacket A GpsmDcmPacket structure as the part of the
+/// PmcDcmPacket/hwPacket received from PMC interchip link.
+/// This argument is passed by the caller as reference. The corresponding
+/// fields of the received packet will filled in this data structure.
+///
+/// \param timeout_period A SsxInterval variable for time out period
+///
+/// This API implements the lower level pmc_dcm_receive API to receive a firmware
+/// command as part of the PMC interchip message packet.
+///
+/// This API is working under a user given time out, if receive cannot be
+/// completed within the given timeout period,
+/// the function will exit with returning an error code:
+/// \a GPSM_DCM_RECV_PACKET_TIMEOUT
+///
+/// Prerequisite: The enable_interchip_interface bit of PMC_MODE_REG
+/// must be set to enable the PMC interchip transfer
+/// and lower level PMC-DCM API is required to use this
+/// high level GPSM-DCM API.
+/// Also, the hardware must be in DCM setup.
+///
+/// Note: This API must be called by the DCM Slave, meaning the firmware
+/// command can only be received by the slave.
+/// Also the API will check if the received firmware command is valid.
+//
+/// \retval GPSM_DCM_SUCCESS
+///
+/// \retval GPSM_DCM_ARG_INVALID_OBJ_RCV
+///
+/// \retval GPSM_DCM_CMD_SHOULD_TO_SLAVE
+///
+/// \retval GPSM_DCM_PKT_INVALID_CMD_RCV
+///
+
+int
+gpsm_dcm_receive(GpsmDcmPacket* fwPacket,
+ SsxInterval timeout_period) {
+
+ int rc = GPSM_DCM_SUCCESS;
+ PmcDcmPacket hwPacket;
+
+ TRACE_GPSM(TRACE_GPSM_DCM_RECEIVE);
+
+ do {
+
+ //check if argument is NULL
+ SSX_ERROR_IF_CHECK_API(
+ (fwPacket == 0),
+ GPSM_DCM_ARG_INVALID_OBJ_RCV);
+
+ //check if is dcm slave, note only slave receives command from master
+ SSX_ERROR_IF_CHECK_API(
+ (pmc_dcm_if_dcm_master()),
+ GPSM_DCM_CMD_SHOULD_TO_SLAVE);
+
+ //receive hardware packet
+ hwPacket.value = 0;
+ rc = _gpsm_dcm_receive(&hwPacket, timeout_period);
+ if( rc ) break;
+
+ //check if the received command is valid
+ fwPacket->command = hwPacket.fields.cmd_ext;
+ SSX_ERROR_IF_CHECK_API(
+ (fwPacket->command >= GPSM_DCM_NUMBER_OF_COMMANDS ||
+ fwPacket->command == 0),
+ GPSM_DCM_PKT_INVALID_CMD_RCV);
+
+ //load payload from hardware packet into firmware packet
+ fwPacket->payload.u8[0] = hwPacket.fields.payload[0];
+ fwPacket->payload.u8[1] = hwPacket.fields.payload[1];
+
+ } while (0);
+
+ TRACE_GPSM_B(TRACE_GPSM_DCM_RECEIVED, fwPacket->command);
+
+ return rc;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Generic communication using GPSM-DCM 'write' command
+////////////////////////////////////////////////////////////////////////////
+///
+/// These APIs allow applications to perform generic communication over the
+/// GPSM-DCM link using the GPSM-DCM 'write' command. Like all GPSM-DCM
+/// commands, communication is always controlled/initiated by the master. The
+/// infrastructure assumes that the master and slave applications argee on the
+/// maximum amount of data that may be transmitted generically as a single
+/// abstract transaction. It is legal for the data transmission size to be 0.
+///
+/// In the following APIs, the \a timeout parameter is a timeout for any
+/// single send/receive transaction to complete, not a timeout covering the
+/// entire send/receive. The timeout may be specified as SSX_WAIT_FOREVER to
+/// indicate no timeout.
+///
+/// One typical use of these APIs would be to implement a polled 'ping' of the
+/// slave from the master. This sequence might be implemented as follows:
+///
+/// - Master: Calls gpsm_dcm_write() with 0 size [ping]
+/// - Master: Blocks on gpsm_dcm_read [Wait for ping response]
+/// - Slave: GpsmSlaveControl.write_handler() is activated to handle the ping
+/// - Slave: write_handler() responds by calling gpsm_dcm_write()
+/// - Master: Unblocks and processes ping reqponse
+
+
+/// Send an arbitrary amount of data (max 2^16 - 1 bytes) using GPSM-DCM
+///
+/// This API is typically used by the master to initiate generic
+/// communication. When received by the slave the application-specific
+/// callback is activated on the slave to handle the write.
+/// The slave will only use this API when it is known that the master is
+/// expecting a communication from the slave and has blocked on a call of
+/// gpsm_dcm_read().
+///
+/// The receiver must be prepared to accept \a size bytes of data, otherwise
+/// the call will fail immediately.
+///
+/// \param buf The buffer contains the sending message prepared by the caller
+///
+/// \param size The size of a message, in number of bytes, given by the caller
+///
+/// \param timeout_period The SSX timeout variable
+///
+/// The firmware level API for sending a generic PMC interchip message
+/// This API sends the message by calling lower level API: pmc_dcm_send
+///
+/// The API times out upon \a timeout_period.
+///
+/// Prerequisite: The enable_interchip_interface bit of PMC_MODE_REG
+/// must be set to enable the PMC interchip transfer
+/// and lower level PMC-DCM API is required to use this
+/// high level GPSM-DCM API.
+/// Also, the hardware must be in DCM setup.
+///
+/// Note: When this API is called by the DCM Master,
+/// the slave will need to provide its own write_handler to process
+/// the receiving message, The counterpart gpsm_dcm_read API of this
+/// gpsm_dcm_write API is not designed for slave to read the master
+/// sending message.
+///
+/// \retval GPSM_DCM_SUCCESS
+///
+/// \retval GPSM_DCM_ARG_INVALID_OBJ_WRT
+///
+
+int
+gpsm_dcm_write(void* buf,
+ uint16_t size,
+ SsxInterval timeout_period)
+{
+ int rc = GPSM_DCM_SUCCESS;
+ PmcDcmPacket hwPacket;
+ GpsmDcmFastData fastData;
+
+ TRACE_GPSM_H(TRACE_GPSM_DCM_WRITE, size);
+
+ //setup send irq
+ ssx_irq_setup(PGP_IRQ_PMC_INTERCHIP_MSG_SEND_ONGOING,
+ SSX_IRQ_POLARITY_ACTIVE_LOW,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+ do {
+
+ //check if buffer is allocated
+ SSX_ERROR_IF_CHECK_API(
+ (buf == 0 && size != 0),
+ GPSM_DCM_ARG_INVALID_OBJ_WRT);
+
+ //form initial hardware packet as header packet
+ hwPacket.value = 0;
+ hwPacket.fields.cmd_code = PMC_IC_MSG_CC;
+ hwPacket.fields.cmd_ext = GPSM_IC_WRITE;
+ hwPacket.value += SET_PAYLOAD_FIELD(size);
+
+ //setup data structure for fast write handler
+ fastData.buffer_pointer = buf;
+ fastData.remaining_size = size;
+ ssx_semaphore_create(&(fastData.fast_semaphore), 0, 1);
+
+ //setup fast write handler for send irq
+ ssx_irq_handler_set(PGP_IRQ_PMC_INTERCHIP_MSG_SEND_ONGOING,
+ gpsm_dcm_fast_write,
+ (void*)(&fastData),
+ SSX_NONCRITICAL);
+
+ //send header packet
+ rc = _gpsm_dcm_send(&hwPacket, timeout_period);
+ if( rc ) break;
+
+ //enable interrupt and semaphore
+ ssx_irq_enable(PGP_IRQ_PMC_INTERCHIP_MSG_SEND_ONGOING);
+ ssx_semaphore_pend(&(fastData.fast_semaphore), timeout_period);
+
+ } while (0);
+
+ TRACE_GPSM(TRACE_GPSM_DCM_WRITE_COMPLETE);
+
+ return rc;
+}
+
+
+/// Receive a transmission from the slave
+///
+/// This API is only called on the master, as part of an application-specific
+/// protocol where a transmission is expected from the slave.
+///
+/// The call will fail immediately if the slave attempts to send more than \a
+/// buf_size bytes. The actual number of bytes received is returned as \a
+/// data_size.
+///
+/// \param buf The buffer for storing the incoming messages,
+/// return to caller as reference
+///
+/// \param buf_size The maximum size of the buffer, given by caller
+/// fail operation if data_size > buf_size
+///
+/// \param data_size The size of acutal receiving message,
+/// return to caller as refernce
+///
+/// \param timeout_period The SSX timeout variable
+///
+/// The firmware level API for receiving a PMC interchip message
+/// This API recevies the message by calling lower level API: pmc_dcm_receive
+/// and then checks \a buf_size and \a data_size for unexpected message size
+/// if the size overflow, the function will exit with returning an error code:
+/// \a GPSM_DCM_DAT_BIGGER_THAN_BUF
+/// The valid receive message will be placed into \a buf and return with
+/// the actual \a data_size. The API times out upon \a timeout.
+///
+/// Prerequisite: The enable_interchip_interface bit of PMC_MODE_REG
+/// must be set to enable the PMC interchip transfer
+/// and lower level PMC-DCM API is required to use this
+/// high level GPSM-DCM API.
+/// Also, the hardware must be in DCM setup.
+///
+/// Note: This API is only designed for master to read/receive a message from
+/// slave (slave will have its own write_handler). Therefore, this API
+/// can only called by DCM master, and the API will check if the received
+/// message is from a write command.
+///
+/// \retval GPSM_DCM_SUCCESS
+///
+/// \retval GPSM_DCM_ARG_INVALID_OBJ_RED
+///
+/// \retval GPSM_DCM_READ_RECV_NOT_WRITE
+///
+/// \retval GPSM_DCM_DAT_BIGGER_THAN_BUF
+///
+
+int
+gpsm_dcm_read(void* buf,
+ uint16_t buf_size,
+ uint16_t* data_size,
+ SsxInterval timeout_period)
+{
+ int rc = GPSM_DCM_SUCCESS;
+ PmcDcmPacket hwPacket;
+ GpsmDcmFastData fastData;
+
+ TRACE_GPSM(TRACE_GPSM_DCM_READ);
+
+ //setup receive irq
+ ssx_irq_setup(PGP_IRQ_PMC_INTERCHIP_MSG_RECV,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+
+ do {
+
+ //check if buffer is allocated
+ SSX_ERROR_IF_CHECK_API(
+ (buf == 0 && buf_size != 0),
+ GPSM_DCM_ARG_INVALID_OBJ_RED);
+
+ //try to receive the header packet
+ hwPacket.value = 0;
+ rc = _gpsm_dcm_receive(&hwPacket, timeout_period);
+ if( rc ) break;
+
+ //check if command code of header packet is valid
+ SSX_ERROR_IF_CHECK_API(
+ (hwPacket.fields.cmd_ext != GPSM_IC_WRITE),
+ GPSM_DCM_READ_RECV_NOT_WRITE);
+
+ //load size from header packet
+ *data_size = GET_PAYLOAD_FIELD(hwPacket.value);
+
+ //check if data size will fit in the buffer
+ if( *data_size > buf_size ) {
+ rc = GPSM_DCM_DAT_BIGGER_THAN_BUF;
+ break;
+ }
+
+ //check if data size is 0
+ if( *data_size == 0 )
+ break;
+
+ //setup data structure for fast read
+ fastData.buffer_pointer = buf;
+ fastData.remaining_size = *data_size;
+ ssx_semaphore_create(&(fastData.fast_semaphore), 0, 1);
+
+ //setup fast read handler for receive irq
+ ssx_irq_handler_set(PGP_IRQ_PMC_INTERCHIP_MSG_RECV,
+ gpsm_dcm_fast_read,
+ (void*)(&fastData),
+ SSX_NONCRITICAL);
+
+ //enable interrupt and semaphore
+ ssx_irq_enable(PGP_IRQ_PMC_INTERCHIP_MSG_RECV);
+ ssx_semaphore_pend(&(fastData.fast_semaphore), timeout_period);
+
+ } while (0);
+
+ TRACE_GPSM_H(TRACE_GPSM_DCM_READ_COMPLETE, *data_size);
+
+ return rc;
+}
+
+/// Method to sync between two chips using write/read API
+///
+/// This API can be called before a piece of application code to sync
+/// between master and slave to enter the same code block together
+/// as well as after a piece of code to sync on exiting the block of code
+///
+/// \param state use 0 for enter and use 1 for exit
+///
+/// \retval GPSM_DCM_SUCCESS
+///
+
+int
+gpsm_dcm_sync(int state)
+{
+ int rc = GPSM_DCM_SUCCESS;
+ int master = pmc_dcm_if_dcm_master();
+ uint16_t buf_size = sizeof(uint16_t);
+ uint16_t wbuf = 0x7962; //SYNC
+ uint16_t rbuf;
+ uint16_t size;
+ SsxMachineContext smc;
+
+ do {
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &smc);
+
+ if( master ^ state ) {
+ rc = gpsm_dcm_write((void*)&wbuf,buf_size,SSX_WAIT_FOREVER);
+ if(rc) break;
+ rc = gpsm_dcm_read((void*)&rbuf,buf_size,&size,SSX_WAIT_FOREVER);
+ if(rc) break;
+ } else {
+ rc = gpsm_dcm_read((void*)&rbuf,buf_size,&size,SSX_WAIT_FOREVER);
+ if(rc) break;
+ rc = gpsm_dcm_write((void*)&wbuf,buf_size,SSX_WAIT_FOREVER);
+ if(rc) break;
+ }
+
+ ssx_critical_section_exit(&smc);
+
+ } while (0);
+
+ return rc;
+}
+
+
+/// GPSM DCM Slave function
+///
+/// This function must be called from a thread, as if a command is available
+/// it may always be necessary for the thread to block during command
+/// execution. The \a wait argument indicates whether the caller is willing to
+/// wait for a command indefinitely, or prefers for gpsm_dcm_slave() to retun
+/// immediately if no command is available. \a wait would normally be non-0 if
+/// \a gpsm_dcm_slave() were used as a standalone thread body, and 0 if
+/// gpsm_dcm_slave() were called from another thread.
+///
+/// \param control The callback table structure that allows the user to
+/// implement callback function in addition to completion of each command.
+///
+/// \param wait The SsxInterval type timeout variable
+///
+/// This API is the control function running on a slave thread. The function
+/// will first try to receive a message from master, and then take the
+/// corresponding action according to the command in the message. Upon
+/// completion of the default action designed for each command, any user
+/// provided callback function for that command in the control structure will
+/// be called.
+///
+/// Prerequisite: This API must be called from a DCM slave SSX thread
+/// The enable_interchip_interface bit of PMC_MODE_REG
+/// must be set to enable the PMC interchip transfer
+/// and lower level PMC-DCM API is required to use this
+/// high level GPSM-DCM API.
+/// Also, the hardware must be in DCM setup.
+///
+/// Similar to other SSX drivers, the callback is always called regardless of
+/// whether the slave command succeeds or fails.
+///
+/// \retval 0 Success
+///
+/// \retval GPSM_DCM_SLAVE_TIMEOUT The call timed out before a packet was
+/// received from the master. The application may or may not treat this as an
+/// error.
+///
+/// \retval GPSM_DCM_SLAVE_ERROR In the event of a this return code, the
+/// application will need to query 3 return codes stored in the \a control
+/// structure to understand the source of the error. The \a
+/// control->protocol_rc contains the return code for all GPSM-DCM protocol
+/// actions, other than the simple timeout mentioned above. The \a
+/// control->slave_rc is the return code for the slave action commanded by the
+/// master. This is also the code sent back to the master as an
+/// acknowledgement. The control->callback_rc is the return code from the
+/// callback, if any.
+///
+/// The return value of the function is either 0,
+/// GPSM_DCM_SLAVE_TIMEOUT, or
+/// GPSM_DCM_SLAVE_ERROR.
+///
+
+int
+gpsm_dcm_slave(GpsmSlaveControl *control,
+ SsxInterval wait)
+{
+ GpsmDcmPacket fwPacket;
+ int rc, protocolRc, slaveRc, callbackRc;
+
+ TRACE_GPSM(TRACE_GPSM_DCM_SLAVE);
+
+ protocolRc = 0;
+ slaveRc = 0;
+ callbackRc = 0;
+
+ do {
+ protocolRc = gpsm_dcm_receive(&fwPacket, wait);
+ if(protocolRc) {
+ control->command = GPSM_IC_NO_COMMAND;
+ break;
+ }
+
+ control->command = fwPacket.command;
+
+ switch (fwPacket.command) {
+
+ case GPSM_IC_ENABLE_PSTATES:
+
+ slaveRc = gpsm_enable_pstates_slave(0,
+ fwPacket.payload.pstate[0],
+ fwPacket.payload.pstate[1]);
+
+ if(control->gpsm_dcm_callback_enable_pstates != 0) {
+ callbackRc =
+ control->gpsm_dcm_callback_enable_pstates(&fwPacket);
+ }
+
+ break;
+
+ case GPSM_IC_HW_PSTATE_MODE:
+
+ slaveRc = gpsm_hw_mode();
+
+ if(control->gpsm_dcm_callback_hw_pstate_mode != 0) {
+ callbackRc =
+ control->gpsm_dcm_callback_hw_pstate_mode(&fwPacket);
+ }
+
+ break;
+
+ case GPSM_IC_WRITE:
+ slaveRc = control->write_handler(control->buffer,
+ control->buffer_size,
+ control->write_arg);
+ break;
+ default:
+ slaveRc = GPSM_DCM_PKT_INVALID_CMD_RCV;
+ break;
+ }
+
+ if(fwPacket.command != GPSM_IC_WRITE) {
+ protocolRc = gpsm_dcm_write((void*)(&slaveRc),
+ sizeof(int),
+ SSX_WAIT_FOREVER);
+ }
+ } while(0);
+
+ control->protocol_rc = protocolRc;
+ control->slave_rc = slaveRc;
+ control->callback_rc = callbackRc;
+
+ if (protocolRc == GPSM_DCM_RECV_PACKET_TIMEOUT) {
+ rc = GPSM_DCM_SLAVE_TIMEOUT;
+ } else if (protocolRc || slaveRc || callbackRc) {
+ rc = GPSM_DCM_SLAVE_ERROR;
+ } else {
+ rc = 0;
+ }
+
+ TRACE_GPSM_B(TRACE_GPSM_DCM_SLAVE_COMPLETE, fwPacket.command);
+
+ return rc;
+}
+
+
+/// Master an abstract transaction with a return code response from the slave
+///
+/// \param fwPacket A legal, initalized GpsmDcmPacket. This packet may be of
+/// any type other than GPSM_IC_DATA or GPSM_IC_WRITE. The GPSM_IC_WRITE does
+/// not get a response from the slave.
+///
+/// \param slaveRc The return code from running the protocol action on the
+/// slave. This includes any return code from a callback installed on the
+/// slave. If the return value of the function is non-0 then \a slaveRc is
+/// considered undefined.
+///
+/// This API send \a fwPacket to the slave and blocks waiting for the slave to
+/// respond with the \a slaveRc. The return value of the API indicates any
+/// problems with sending the packet or receiving the response.
+
+int
+gpsm_dcm_master(GpsmDcmPacket* fwPacket, int* slaveRc)
+{
+ int rc;
+ uint16_t size;
+
+ do {
+
+ rc = gpsm_dcm_send(fwPacket);
+ if(rc) break;
+
+ rc = gpsm_dcm_read((void*)slaveRc,
+ sizeof(int),
+ &size,
+ SSX_WAIT_FOREVER);
+ if(rc) break;
+
+ //check if command_reply has correct size
+ SSX_ERROR_IF_CHECK_API((size != sizeof(int)),
+ GPSM_DCM_CMD_REPLY_NOT_INT);
+
+ }while(0);
+
+ return rc;
+}
diff --git a/src/lib/gpsm_dcm.h b/src/lib/gpsm_dcm.h
new file mode 100755
index 0000000..407ddbb
--- /dev/null
+++ b/src/lib/gpsm_dcm.h
@@ -0,0 +1,192 @@
+#ifndef __GPSM_DCM_H__
+#define __GPSM_DCM_H__
+
+// $Id: gpsm_dcm.h,v 1.2 2014/02/03 01:30:24 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpsm_dcm.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpsm_dcm.h
+/// \brief PgP Global PState Machine (Mechanism) in Dual Chip Model
+
+#include "pmc_dcm.h"
+
+/// GPSM-DCM Return Code
+#define GPSM_DCM_SUCCESS 0
+#define GPSM_DCM_ARG_INVALID_OBJ_SND 0x00326401 //ssx panic
+#define GPSM_DCM_ARG_INVALID_OBJ_RCV 0x00326402 //ssx panic
+#define GPSM_DCM_ARG_INVALID_OBJ_WRT 0x00326403 //ssx panic
+#define GPSM_DCM_ARG_INVALID_OBJ_RED 0x00326404 //ssx panic
+#define GPSM_DCM_PKT_INVALID_CMD_SND 0x00326405 //ssx panic
+#define GPSM_DCM_PKT_INVALID_CMD_RCV 0x00326406 //ssx panic
+#define GPSM_DCM_CMD_NOT_FROM_MASTER 0x00326407 //ssx panic
+#define GPSM_DCM_CMD_SHOULD_TO_SLAVE 0x00326408 //ssx panic
+#define GPSM_DCM_SEND_PACKET_TIMEOUT 0x00326409 //user handle
+#define GPSM_DCM_RECV_PACKET_TIMEOUT 0x0032640a //user handle
+#define GPSM_DCM_READ_RECV_NOT_WRITE 0x0032640b //ssx panic
+#define GPSM_DCM_READ_NOT_WRITE_DATA 0x0032640c //ssx panic
+#define GPSM_DCM_DAT_BIGGER_THAN_BUF 0x0032640d //user handle
+#define GPSM_DCM_CMD_REPLY_NOT_INT 0x0032640e //ssx panic
+#define GPSM_DCM_SLAVE_TIMEOUT 0x0032640f //user handle
+#define GPSM_DCM_SLAVE_ERROR 0x00326410 //user handle
+
+/// GPSM Interchip Command Code
+#define GPSM_IC_DATA 0 //0b0000
+#define GPSM_IC_WRITE 1 //0b0001
+#define GPSM_IC_ENABLE_PSTATES 2 //0b0010
+#define GPSM_IC_HW_PSTATE_MODE 3 //0b0011
+
+#define GPSM_DCM_NUMBER_OF_COMMANDS 4
+
+/// This is a special command return code returned by gpsm_dcm_slave() when it
+/// times out.
+#define GPSM_IC_NO_COMMAND GPSM_DCM_NUMBER_OF_COMMANDS
+
+
+/// Timeout Parameter
+#define GPSM_DCM_DEFAULT_TIMEOUT SSX_MICROSECONDS(15)
+
+#ifndef __ASSEMBLER__
+
+/// GPSM-DCM abstract packet
+
+typedef struct {
+ /// Firmware command
+ uint8_t command : 4;
+ union {
+ /// Used for Pstate-based protocols
+ Pstate pstate[2];
+ /// Generic byte data
+ uint8_t u8[2];
+ } payload;
+} GpsmDcmPacket;
+
+/// Data Structure for Fast Write/Read Handlers
+
+typedef struct {
+ void* buffer_pointer;
+ uint32_t remaining_size;
+ SsxSemaphore fast_semaphore;
+} GpsmDcmFastData;
+
+/// Data Structure for Sync Mehotds
+
+
+/// Abstract type of gpsm_dcm_slave() callbacks
+///
+/// The callback receives the (first) master packet of the exchange. The
+/// return code is passed back to the master.
+
+typedef int (*GpsmDcmSlaveCallback)(GpsmDcmPacket* fwPacket);
+
+
+/// Control structure for gpsm_dcm_slave()
+
+typedef struct {
+ /// Slave timeout when waiting for next packet to arrive in long commands.
+ SsxInterval timeout;
+
+ /// Callback called after "Enable Pstates" command
+ GpsmDcmSlaveCallback gpsm_dcm_callback_enable_pstates;
+
+ /// Callback called after "Enter HW Pstate Mode" command
+ GpsmDcmSlaveCallback gpsm_dcm_callback_hw_pstate_mode;
+
+ /// Callback for GPSM-DCM write command
+ ///
+ /// Will be called with the application-supplied buffer and the actual
+ /// size of the data transmission.
+ int (*write_handler)(void* buffer, uint16_t size, void* arg);
+
+ /// Application-supplied buffer for GPSM-DCM write commands
+ void* buffer;
+
+ /// Size of the application-supplied write buffer
+ uint16_t buffer_size;
+
+ /// Application-supplied generic argument to the write handler
+ void* write_arg;
+
+ /// Callback when slave detects timeout from master
+ GpsmDcmSlaveCallback timeout_handler;
+
+ /// The last command recieved by the slave.
+ int command;
+
+ /// Return code from gpsm_dcm protocol actions
+ int protocol_rc;
+
+ /// Return code from slave action in response to master command
+ int slave_rc;
+
+ /// Return code from the application specific callback, if any.
+ int callback_rc;
+
+} GpsmSlaveControl;
+
+////////////////////////////////////////////////////////////////////////////
+// High-level GPSM-DCM Interchip Communication Methods
+////////////////////////////////////////////////////////////////////////////
+
+int
+gpsm_dcm_send(GpsmDcmPacket* fwPacket);
+
+
+
+int
+gpsm_dcm_receive(GpsmDcmPacket* fwPacket,
+ SsxInterval timeout_period);
+
+
+////////////////////////////////////////////////////////////////////////////
+// Generic Data Communication using GPSM-DCM 'write' command
+////////////////////////////////////////////////////////////////////////////
+
+int
+gpsm_dcm_write(void* buf,
+ uint16_t size,
+ SsxInterval timeout_period);
+
+
+int
+gpsm_dcm_read(void* buf,
+ uint16_t buf_size,
+ uint16_t* data_size,
+ SsxInterval timeout_period);
+
+////////////////////////////////////////////////////////////////////////////
+// Fast Interrrupt Handlers for Data Transfer of GPSM-DCM 'write' command
+////////////////////////////////////////////////////////////////////////////
+
+SSX_IRQ_HANDLER(gpsm_dcm_fast_write);
+SSX_IRQ_HANDLER(gpsm_dcm_fast_read);
+
+////////////////////////////////////////////////////////////////////////////
+// Generic Synchronization Mechanism using GPSM-DCM 'write' command
+////////////////////////////////////////////////////////////////////////////
+
+int
+gpsm_dcm_sync(int state);
+
+////////////////////////////////////////////////////////////////////////////
+// The Control Method for Slave Thread
+////////////////////////////////////////////////////////////////////////////
+
+int
+gpsm_dcm_slave(GpsmSlaveControl *control,
+ SsxInterval wait);
+
+
+////////////////////////////////////////////////////////////////////////////
+// The Command Method for Master Thread
+////////////////////////////////////////////////////////////////////////////
+
+int
+gpsm_dcm_master(GpsmDcmPacket* fwPacket, int* slaveRc);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __GPSM_DCM_H__ */
diff --git a/src/lib/gpsm_dcm_fast_handler.S b/src/lib/gpsm_dcm_fast_handler.S
new file mode 100755
index 0000000..01cbb2d
--- /dev/null
+++ b/src/lib/gpsm_dcm_fast_handler.S
@@ -0,0 +1,147 @@
+// $Id: gpsm_dcm_fast_handler.S,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+
+/// \file gpsm_dcm_fast_handler.S
+/// \brief Assembler support for GPSM_DCM procedures
+/// \cond
+ .nolist
+#include "ssx.h"
+#include "pmc_dcm.h"
+#include "gpsm_dcm.h"
+ .list
+
+#define GPSM_IC_CONTINUOUS_DATA (PMC_IC_MSG_CC << 4 | GPSM_IC_DATA)
+
+ // The gpsm_dcm_write fast handler.
+
+ // Register use:
+ //
+ // R3 = Entry: void *arg; *arg -> GpsmDcmFast
+ // R4 = Entry: SsxIrqId irq; irq : constant
+ // R5 = Entry: int priority; priority -> data
+ // R6 = data_pointer
+ // R7 = remaining_size
+ // CR = <condition>
+ // LR = <return address>
+ // No other registers can be used, other than SPRG
+
+ .global_function gpsm_dcm_fast_write
+
+gpsm_dcm_fast_write:
+
+ _ssx_irq_status_clear %r4, %r6, %r7 //clear status first
+
+ lwz %r6, 0(%r3) //load data pointer
+ lwz %r7, 4(%r3) //load remaining size
+
+ cmpwi %r7, 0 //if size == 0
+ beq exit_write_handler //exit fast write
+ cmpwi %r7, 1 //if size == 1
+ beq load_one_byte //load only one byte
+
+ lhz %r5, 0(%r6) //otherwise load two bytes
+ addi %r6, %r6, 2 //data pointer+2
+ addi %r7, %r7,-2 //remaining size-2
+ b form_and_send_packet //then form and send packet
+
+load_one_byte:
+
+ lbz %r5, 0(%r6) //load one byte from buffer
+ addi %r6, %r6, 1 //data pointer+1
+ addi %r7, %r7,-1 //remaining size-1
+
+form_and_send_packet:
+
+ stw %r6, 0(%r3) //store updated data pointer
+ stw %r7, 4(%r3) //store updated remaining size
+
+ lis %r6, GPSM_IC_CONTINUOUS_DATA //load cmd code to upper bits
+ or %r5, %r5, %r6 //load data into lower bits
+ slwi %r5, %r5, 8 //packet<<8 to give ecc field
+ _stwi %r5, %r7, PMC_INTCHP_MSG_WDATA //send packet
+ blr //return
+
+exit_write_handler:
+
+ bl __ssx_irq_fast2full //convert fast to full irq handler
+ _ssx_irq_disable %r4, %r6, %r7 //disable this irq
+ addi %r3, %r3, 8 //argument pointer to semaphore
+ bl ssx_semaphore_post //post to that semaphore
+ b __ssx_irq_full_mode_exit //exit
+
+ .epilogue gpsm_dcm_fast_write
+
+
+
+ // The gpsm_dcm_read fast handler.
+
+ // Register use:
+ //
+ // R3 = Entry: void *arg; *arg -> GpsmDcmFast(data,size,semaphore)
+ // R4 = Entry: SsxIrqId irq; irq : constant
+ // R5 = Entry: int priority; priority -> data
+ // R6 = data_pointer
+ // R7 = remaining_size
+ // CR = <condition>
+ // LR = <return address>
+ // No other registers can be used, other than SPRG
+
+ .global_function gpsm_dcm_fast_read
+
+gpsm_dcm_fast_read:
+
+ _ssx_irq_status_clear %r4, %r6, %r7 //clear status first
+
+ lwz %r7, 4(%r3) //load remaining size
+ cmpwi %r7, 0 //if size == 0
+ beq exit_read_handler //then exit fast read
+
+ _lwzi %r6, %r7, PMC_INTCHP_MSG_RDATA //receive packet
+
+ extrwi %r5, %r6, 16, 8 //extract data to r5
+ extrwi %r6, %r6, 8, 0 //extract cmd code to r6
+ li %r7, GPSM_IC_CONTINUOUS_DATA //designated cmd code to r7
+
+ cmpw %r6, %r7 //compare and check cmd code
+ bne panic_read_packet //panic on wrong cmd code
+
+ lwz %r6, 0(%r3) //load data pointer
+ lwz %r7, 4(%r3) //load remaining size
+
+ cmpwi %r7, 1 //if only one byte left
+ beq store_one_byte //then store only one byte
+
+ sth %r5, 0(%r6) //otherwise store two bytes to buf
+ addi %r6, %r6, 2 //data pointer+2
+ addi %r7, %r7,-2 //remaining size-2
+ b check_read_status //check read status
+
+store_one_byte:
+
+ stb %r5, 0(%r6) //store one byte to buf
+ addi %r6, %r6, 1 //data pointer+1
+ addi %r7, %r7,-1 //remaining size-1
+
+check_read_status:
+
+ stw %r6, 0(%r3) //store updated data pointer
+ stw %r7, 4(%r3) //store updated remaining size
+
+ cmpwi %r7, 0 //if size == 0
+ beq exit_read_handler //then terminate fast read
+ blr //return if still data left
+
+exit_read_handler:
+
+ bl __ssx_irq_fast2full //convert fast to full irq handler
+ _ssx_irq_disable %r4, %r6, %r7 //disable this irq
+ addi %r3, %r3, 8 //argument pointer to semaphore
+ bl ssx_semaphore_post //post to that semaphore
+ b __ssx_irq_full_mode_exit //exit
+
+panic_read_packet:
+
+ SSX_PANIC(GPSM_DCM_READ_NOT_WRITE_DATA) //PANIC if cmd code is wrong
+
+ .epilogue gpsm_dcm_fast_read
+/// \endcond
+
diff --git a/src/lib/gpsm_init.c b/src/lib/gpsm_init.c
new file mode 100755
index 0000000..02ac786
--- /dev/null
+++ b/src/lib/gpsm_init.c
@@ -0,0 +1,1638 @@
+// $Id: gpsm_init.c,v 1.9 2014/06/10 19:14:57 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpsm_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file gpsm_init.c
+/// \brief Global Pstate Machine procedures only required to initialize Pstate
+/// and Pstate modes.
+///
+/// In OCC product firmware this code is only needed immediately after IPL to
+/// set up Pstate tables and enable Pstates. This code could be run from an
+/// applet or otherwise removed once Pstates are initialized. Note that this
+/// file cointains code only; some global variables referenced here are
+/// defined in gpsm.c, along with the run-time APIs for GPSM.
+///
+/// The following sequence of procedures is required to initialize the GPSM
+/// mechanism, enable Pstate mode, and further enable Hardware Pstate Mode.
+///
+/// \code
+///
+/// PstateSuperStructure* pss;
+/// GlobalPstateTable *gpst;
+/// GpsmEnablePstatesMasterInfo info;
+/// Pstate voltage_pstate, frequency_pstate;
+///
+/// gpsm_initialize(pss, gpst);
+/// gpsm_enable_pstates_master(&info, &voltage_pstate, &frequency_pstate);
+/// gpsm_enable_pstates_slave(&info, voltage_pstate, frequency_pstate);
+/// gpsm_hw_mode();
+///
+/// \endcode
+///
+/// Executing these procedures enables Pstate control of voltage and
+/// frequency, and leaves the chip quiesced in Firmware Pstate mode. These
+/// procedures initializes both central (PMC) and remote (PCB Slave) Pstate
+/// hardware to fully enable Pstate control of voltage and frequency.
+/// Carefully note the procedure sequence preconditions and postconditions.
+///
+/// In the case of a DCM environment, the DCM master must execute the sequence
+/// as follows:
+///
+/// \code
+///
+/// PstateSuperStructure* pss;
+/// GlobalPstateTable *gpst;
+/// GpsmEnablePstatesMasterInfo info;
+/// Pstate voltage_pstate, frequency_pstate;
+///
+/// gpsm_initialize(pss, gpst);
+/// gpsm_enable_pstates_master(&info, &voltage_pstate, &frequency_pstate);
+///
+/// <em> Send voltage_pstate and frequency_pstate to the slave and wait for
+/// confirmation that the procedure has completed. </em>
+///
+/// gpsm_enable_pstates_slave(&info, voltage_pstate, frequency_pstate);
+/// gpsm_hw_mode();
+///
+/// <em> Send command to the slave to execute gpsm_hw_mode() </em>
+///
+/// \endcode
+///
+/// The DCM slave executes the following sequence
+/// \code
+/// PstateSuperStructure* pss;
+/// GlobalPstateTable *gpst;
+/// Pstate voltage_pstate, frequency_pstate;
+///
+/// gpsm_initialize(pss, gpst);
+///
+/// <em> Receive voltage_pstate and frequency_pstate from the masterand wait for
+/// confirmation that the procedure has completed. </em>
+///
+/// gpsm_enable_pstates_slave(0, voltage_pstate, frequency_pstate);
+///
+/// <em> Wait for a command from the master to execute gpsm_hw_mode(). </em>
+///
+/// \endcode
+///
+/// <b> Preconditions </b>
+///
+/// - This sequence must be called from a thread as it must be able to block
+/// for the completion of GPSM events.
+///
+/// - The fundamental precondition is the assumption that any snapshot of the
+/// voltage/frequency state of the system yields a legal state. As long as
+/// this is true, then this sequence should never take the system to an
+/// illegal V/F state.
+///
+/// - CPM-DPLL mode should be disabled, and all undervolting controls are
+/// assumed to be at their nominal values. Correctness can not guaranteed
+/// otherwise.
+///
+/// - iVRM mode should be disabled prior to calling this procedure.
+/// Correctness can not be guaranteed otherwise.
+///
+///
+/// <b> Standard/Benign Postconditions after executing
+/// gpsm_enable_pstates_slave() </b>
+///
+/// - The system will be in Firmware Pstate Mode, using the Local and Global
+/// Pstate tables installed by gpsm_initialize(). Pstate 0 will be mapped to
+/// the nominal frequency (modulo rounding down) of the
+/// 'nominal_frequency_khz' field of the Global Pstate table.
+///
+/// - All core chiplet frequencies will be under the control of the PMCR Local
+/// Pstate.
+///
+/// - The Global Actual Pstate immediately prior to the final entry of Pstate
+/// mode is the Pstate that most closely matches an arbitrary snapshot of the
+/// system voltage during the execution of this procedure.
+///
+/// - The PMCR and PMICR are not modified, therefore the Global Pstate
+/// subsequent to the release of Hardware Pstate mode is arbitrary.
+///
+/// - The PMC_RAIL_BOUNDS register is set to the maximum legal bounds allowed
+/// by Global Pstate Table
+///
+/// - IVRM is setup and enabled if Local Pstate Table is installed.
+///
+/// - Resonant Clock is setup and enabled if Resonant Clock is installed.
+///
+/// <b> Side-Effects </b>
+///
+/// - The dpll_fmax and dpll_fmin fields of the FREQ_CTRL_REG in each core are
+/// set to an arbitrary value. The dpll_fmax_bias is set to the value of the
+/// 'dpll_fmax_bias' field of the \a gpst.
+///
+/// - The core-level PCBS_POWER_MANAGEMENT_BOUNDS_REG registers are
+/// set to the maximum legal bounds. This is required due to Pstate table
+/// constraints.
+///
+/// \todo - How to handle redundant SPIVID interfaces? Here we get the
+/// current volatge from interface 0.
+///
+/// \bug Check to make sure that the PMC_CORE_DECONFIGURATION_REG matches
+/// multicast group 1.
+///
+/// \bug Code marked with ** VBU ** is necessary for VBU/EPO simulation, needs
+/// to be scrubbed once this is working in VBU.
+
+#include "ssx.h"
+#include "ssx_io.h"
+#include "gpsm.h"
+#include "vrm.h"
+#include "heartbeat.h"
+#include "special_wakeup.h"
+
+// Debugging support
+
+#if 0
+#define _BREAK \
+ { \
+ fprintf(stderr, "%s:%d: _BREAK trapped error rc = 0x%08x (-0x%08x)\n", \
+ __FILE__, __LINE__, rc, -rc); \
+ SSX_PANIC(GPSM_ERROR_BREAK); \
+ }
+#else
+#define _BREAK break;
+#endif
+
+
+/// Flag set once gpsm_initialize() has been successfully completed.
+uint8_t G_gpsm_initialized = 0;
+
+
+/// Install a (new) Global Pstate Table
+///
+/// \param[out] o_gpst A pointer to a properly-aligned GlobalPstateTable
+///
+/// \param[in] i_source A pointer to an initialized source GlobalPstateTable
+/// that will be copied to \a gpst (if not in fact the same as \a gpst).
+///
+/// This procedure will likely only be called once, at initialization, and
+/// then only as part of the gpsm_initialize() procedure. The procedure:
+///
+/// - Copies the \a source to the \a gpst if required.
+///
+/// - Installs a pointer to the Global Pstate Table in the PMC hardware.
+///
+/// - Sets up the PMC Pstate clipping bounds.
+///
+/// - Sets up the Pstate stepping parameters from the GlobalPstateTable
+///
+/// - Clears the local undervolting register (via multicast) and sets the
+/// default undervolting bounds to the entire Local Pstate Table.
+///
+/// - Broadcasts the safe mode Pstate Psafe to the cores and clears the other
+/// fields of the PCBS_OCC_HEARTBEAT_REG, disabling the heartbeat timer.
+/// However the heartbeat timer must not have been active anyway.
+///
+/// \note This procedure does modify the rail bounds.
+///
+/// \note The caller is responsible for the mode-correctness of this
+/// procedure. This procedure must only be called when the PMC is in Firmware
+/// Pstate Mode.
+///
+/// \retval 0 Success
+///
+/// \retval -GPSM_INVALID_ARGUMENT_GPST_INSTALL The Global Pstate table argument
+/// was either NULL (0) or improperly aligned, or the \a source was NULL (0).
+///
+/// \retval -GPSM_ILLEGAL_MODE_GPST_INSTALL The PMC does not indicate that the
+// system is in Firmware Pstate Mode, or the heartbeat is enabled.
+
+int
+gpsm_gpst_install(GlobalPstateTable* o_gpst,
+ const GlobalPstateTable* i_source)
+{
+ pmc_occ_heartbeat_reg_t pohr;
+ pmc_parameter_reg0_t ppr0;
+ pmc_parameter_reg1_t ppr1;
+ pmc_global_pstate_bounds_reg_t pgpbr;
+ pmc_rail_bounds_register_t prbr;
+ pmc_undervolting_reg_t pur;
+ pcbs_occ_heartbeat_reg_t pcbsohr;
+
+ int rc;
+
+ TRACE_GPSM(TRACE_GPSM_GPST_INSTALL);
+
+ do {
+
+ // Optional bypass of the procedure
+
+ if (i_source->options.options & PSTATE_NO_INSTALL_GPST) {
+
+ rc = 0;
+ break;
+ }
+
+ // Check presence and alignment of the Pstate table, and proper Pstate
+ // and heartbeat modes.
+
+ if ((o_gpst == 0) ||
+ ((unsigned long)o_gpst % POW2_32(GLOBAL_PSTATE_TABLE_ALIGNMENT))) {
+ rc = -GPSM_INVALID_ARGUMENT_GPST_INSTALL;
+ _BREAK;
+ }
+
+ pohr.value = in32(PMC_OCC_HEARTBEAT_REG);
+ rc = getscom(MC_ADDRESS(PCBS_OCC_HEARTBEAT_REG,
+ MC_GROUP_EX, PCB_MULTICAST_OR),
+ &(pcbsohr.value));
+ if (rc) _BREAK;
+
+ if (!gpsm_fw_mode_p() || pohr.fields.pmc_occ_heartbeat_en
+ || pcbsohr.fields.occ_heartbeat_enable) {
+ rc = -GPSM_ILLEGAL_MODE_GPST_INSTALL;
+ _BREAK;
+ }
+
+
+ // Copy \a source to \a gpst if required, then install the Pstate
+ // table, Pvsafe and Pstate stepping parameters, and set the clipping
+ // bounds as well as the rail bounds
+
+ if ((o_gpst != i_source) &&
+ !(i_source->options.options & PSTATE_NO_COPY_GPST)) {
+
+ memcpy(o_gpst, i_source, sizeof(*o_gpst));
+ }
+
+ ppr1.value = in32(PMC_PARAMETER_REG1);
+ ppr1.fields.ba_sram_pstate_table =
+ (unsigned long)o_gpst >> GLOBAL_PSTATE_TABLE_ALIGNMENT;
+ ppr1.fields.pvsafe = i_source->pvsafe;
+
+ // This fix is added per SW260911
+ // Minimum Frequency in the system is given by MRW attribute
+ // PState Datablock procedure will read the attribute then
+ // convert it into pstate _pfloor_ and put it into
+ // Global Pstate Table. GPSM here consumes the value
+ // and set both lower bounds: pmin_rail(PMC) and pmin_clip(PCBS)
+ // and two safe pstates: pvsafe(PMc) and psafe(PCBS) to be
+ // _pfloor_ if _pfloor_ is higher than their default(gpst_pmin)
+ // so that we should never run with frequency below the floor
+ // even in safe mode
+ if (ppr1.fields.pvsafe < i_source->pfloor && i_source->pfloor != 0)
+ ppr1.fields.pvsafe = i_source->pfloor;
+
+ out32(PMC_PARAMETER_REG1, ppr1.value);
+
+ pgpbr.value = 0;
+ pgpbr.fields.gpsi_min = gpst_pmin(i_source) - PSTATE_MIN;
+ pgpbr.fields.gpst_number_of_entries_minus_one = i_source->entries - 1;
+ out32(PMC_GLOBAL_PSTATE_BOUNDS_REG, pgpbr.value);
+
+ ppr0.value = in32(PMC_PARAMETER_REG0);
+ ppr0.fields.pstate_stepsize = i_source->pstate_stepsize;
+ ppr0.fields.vrm_stepdelay_range = i_source->vrm_stepdelay_range;
+ ppr0.fields.vrm_stepdelay_value = i_source->vrm_stepdelay_value;
+ ppr0.fields.gpsa_timeout_value_sel = 1;
+ out32(PMC_PARAMETER_REG0, ppr0.value);
+
+ prbr.value = 0;
+ prbr.fields.pmin_rail = gpst_pmin(i_source)+1;
+ prbr.fields.pmax_rail = gpst_pmax(i_source);
+
+ // This fix is added per SW260911
+ // Minimum Frequency in the system is given by MRW attribute
+ // PState Datablock procedure will read the attribute then
+ // convert it into pstate _pfloor_ and put it into
+ // Global Pstate Table. GPSM here consumes the value
+ // and set both lower bounds: pmin_rail(PMC) and pmin_clip(PCBS)
+ // and two safe pstates: pvsafe(PMc) and psafe(PCBS) to be
+ // _pfloor_ if _pfloor_ is higher than their default(gpst_pmin)
+ // so that we should never run with frequency below the floor
+ // even in safe mode
+ if (prbr.fields.pmin_rail < i_source->pfloor && i_source->pfloor != 0)
+ prbr.fields.pmin_rail = i_source->pfloor;
+
+ out32(PMC_RAIL_BOUNDS_REGISTER, prbr.value);
+
+ // Clear the undervolting control, and set the undervolting range to
+ // the entire Global Pstate Table range.
+
+ pur.value = 0;
+ pur.fields.puv_min = gpst_pmin(i_source);
+ pur.fields.puv_max = gpst_pmax(i_source);
+ pur.fields.kuv_request = 0;
+ out32(PMC_UNDERVOLTING_REG, pur.value);
+
+
+ // Broadcast the safe mode Pstate Psafe to the cores, disabling the
+ // heartbeat (which must have been disabled anyway) and clearing any
+ // other heartbeat setup.
+
+ pcbsohr.value = 0;
+ pcbsohr.fields.psafe = i_source->psafe;
+
+ // This fix is added per SW260911
+ // Minimum Frequency in the system is given by MRW attribute
+ // PState Datablock procedure will read the attribute then
+ // convert it into pstate _pfloor_ and put it into
+ // Global Pstate Table. GPSM here consumes the value
+ // and set both lower bounds: pmin_rail(PMC) and pmin_clip(PCBS)
+ // and two safe pstates: pvsafe(PMc) and psafe(PCBS) to be
+ // _pfloor_ if _pfloor_ is higher than their default(gpst_pmin)
+ // so that we should never run with frequency below the floor
+ // even in safe mode
+ if (pcbsohr.fields.psafe < i_source->pfloor && i_source->pfloor != 0)
+ pcbsohr.fields.psafe = i_source->pfloor;
+
+ rc = putscom(MC_ADDRESS(PCBS_OCC_HEARTBEAT_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ pcbsohr.value);
+ if (rc) _BREAK;
+
+ rc = 0;
+
+ } while(0);
+
+ return rc;
+}
+
+
+/// Install a (new) Local Pstate Array
+///
+/// \param[in] i_lpsa A pointer to a LocalPstateArray to install in every
+/// configured core.
+///
+/// \param[in] i_options Options controlling the installation, or a NULL (0)
+/// pointer to indicate fully default behavior.
+///
+/// This procedure will likely only be called once, at initialization, and
+/// then only as part of the gpsm_initialize() procedure. The procedure:
+///
+/// - Power on PFET Voltage Reference Circuit
+///
+/// - Perform the binary search for IVRM Calibration
+///
+/// - Uploads the LocalPstateArray to every core using multicast.
+///
+/// - Sets up the Local Pstate table bounds in every core using multicast.
+///
+/// - Sets the step delay parameters for every core using multicast.
+///
+/// - Clears the local undervolting register (via multicast) and sets the
+/// default undervolting bounds to the entire Local Pstate Table.
+///
+/// - Setup IVRM delay parameters
+///
+/// - Enable IVRM
+///
+/// \note This procedure \e does \e not modify the rail bounds.
+///
+/// \note The caller is responsible for the mode-correctness of this
+/// procedure. This procedure must only be called when the iVRM are
+/// disabled, the DPLL is in "normal" (not CPM-DPLL) mode, and core heartbeats
+/// are disabled.
+///
+/// \retval 0 Success
+///
+/// \retval -GPSM_INVALID_ARGUMENT_LPST_INSTALL The Local Pstate array argument
+/// was NULL (0).
+///
+/// \retval -GPSM_ILLEGAL_MODE_LPST_INSTALL iVRM mode, CPM-DPLL mode, or the
+/// local heartbeat appears to be enabled in at least one core.
+///
+/// \retval -GPSM_IVRM_CALIBRATION_TIMEOUT, if IVRM Calibration does not
+/// complete in time.
+///
+/// \retval -GPSM_IVRM_GROSS_OR_FINE, if ivrm_gross_or_fine_err is set
+///
+/// \retval -GPSM_PSTATE_ENABLED, if pstate is enabled before enabling IVRM
+///
+/// \retval others This API may also return non-0 codes from
+/// getscom()/putscom()
+
+int
+gpsm_lpsa_install(const LocalPstateArray* i_lpsa,
+ const PstateOptions* i_options)
+{
+ pcbs_ivrm_control_status_reg_t picsr;
+ pcbs_dpll_cpm_parm_reg_t pdcpr;
+ pcbs_pstate_index_bound_reg_t ppibr;
+ pcbs_ivrm_vid_control_reg0_t pivcr0;
+ pcbs_ivrm_vid_control_reg1_t pivcr1;
+ pcbs_undervolting_reg_t pur;
+ pcbs_pmerr_reg_t ppr;
+ pcbs_pcbspm_mode_reg_t ppmr;
+ pmc_core_deconfiguration_reg_t pcdr;
+ ChipConfigCores cores, wakedup;
+ SsxTimebase timeout;
+ int i, rc, timeout_rc = 0;
+ uint32_t configured_cores;
+ int flag, core;
+
+ TRACE_GPSM(TRACE_GPSM_LPSA_INSTALL);
+
+ do {
+
+ // Optional bypass of this procedure
+
+ if ((i_options != 0) &&
+ (i_options->options & PSTATE_NO_INSTALL_LPSA)) {
+
+ rc = 0;
+ break;
+ }
+
+ // No LPST Install and IVRM Enable if there is no configued cores
+
+ configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG);
+ flag = 1;
+ for (core = 0; core < PGP_NCORES; core++, configured_cores <<= 1) {
+ if (!(configured_cores & 0x80000000)) continue;
+ flag = 0;
+ }
+ if (flag == 1) {
+ rc = 0;
+ break;
+ }
+
+ // Check the array for existence. Do an OR-combining multicast read
+ // to see if any of the cores have iVRM enabled, have the heartbeat
+ // enabled, or any cores are running in CPM-DPLL mode.
+
+ if (i_lpsa == 0) {
+ rc = -GPSM_INVALID_ARGUMENT_LPST_INSTALL;
+ _BREAK;
+ }
+ rc = getscom(MC_ADDRESS(PCBS_IVRM_CONTROL_STATUS_REG,
+ MC_GROUP_EX, PCB_MULTICAST_OR),
+ &(picsr.value));
+ if (rc) _BREAK;
+ rc = getscom(MC_ADDRESS(PCBS_DPLL_CPM_PARM_REG,
+ MC_GROUP_EX, PCB_MULTICAST_OR),
+ &(pdcpr.value));
+ if (rc) _BREAK;
+
+ if (picsr.fields.ivrm_fsm_enable ||
+ pdcpr.fields.cpm_filter_enable) {
+ rc = -GPSM_ILLEGAL_MODE_LPST_INSTALL;
+ _BREAK;
+ }
+
+ // In case cores are in deep winkle so that ivrm caliburation
+ // will fail, insert special wakeup first
+ pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG);
+ cores = ~pcdr.fields.core_chiplet_deconf_vector;
+ rc = occ_special_wakeup(1, cores, 25, &wakedup);
+ if (rc) _BREAK;
+
+ // Power on PFET Voltage Reference Circuit
+ picsr.fields.pvref_en = 1;
+ rc = putscom(MC_ADDRESS(PCBS_IVRM_CONTROL_STATUS_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ picsr.value);
+ if (rc) _BREAK;
+
+ // Wait 10us for circuit to power on
+ timeout = ssx_timebase_get() + SSX_MICROSECONDS(10);
+ while (ssx_timebase_get() < timeout) {;}
+
+ // Perform the binary search
+ picsr.fields.binsearch_cal_ena = 1;
+ rc = putscom(MC_ADDRESS(PCBS_IVRM_CONTROL_STATUS_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ picsr.value);
+ if (rc) _BREAK;
+
+ // Check IVRM Calibration is completed
+ // Poll for up to 100us for done before erroring out
+ timeout_rc = -GPSM_IVRM_CALIBRATION_TIMEOUT;
+ timeout = ssx_timebase_get() + SSX_MICROSECONDS(100);
+ while (ssx_timebase_get() < timeout) {
+ rc = getscom(MC_ADDRESS(PCBS_IVRM_CONTROL_STATUS_REG,
+ MC_GROUP_EX, PCB_MULTICAST_AND),
+ &(picsr.value));
+ if (rc) _BREAK;
+ if (picsr.fields.binsearch_cal_done) {
+ timeout_rc=0;
+ break;
+ }
+ }
+ if (timeout_rc||rc) _BREAK;
+
+ // IVRM Calibration complete, Clear binary search enable
+ picsr.fields.binsearch_cal_ena = 0;
+ rc = putscom(MC_ADDRESS(PCBS_IVRM_CONTROL_STATUS_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ picsr.value);
+ if (rc) _BREAK;
+
+ // Check if IVRM Gross or Fine Error is set after calibration!
+ rc = getscom(MC_ADDRESS(PCBS_PMERR_REG,
+ MC_GROUP_EX, PCB_MULTICAST_OR),
+ &(ppr.value));
+ if (rc) _BREAK;
+ if (ppr.fields.pcbs_ivrm_gross_or_fine_err) {
+ rc = -GPSM_IVRM_GROSS_OR_FINE;
+ _BREAK;
+ }
+
+ // Deassert Special Wakeup
+ rc = occ_special_wakeup(0, cores, 25, &wakedup);
+ if (rc) _BREAK;
+
+ // Upload the Local Pstate Array. The array is loaded via multicast,
+ // using the built-in auto-increment mechanism. Then upload the
+ // Pstate bounds register via multicast. Pstate clipping is not
+ // modified.
+
+ rc = putscom(MC_ADDRESS(PCBS_PSTATE_TABLE_CTRL_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ 0);
+ if (rc) _BREAK;
+
+ for (i = 0; i < LOCAL_PSTATE_ARRAY_ENTRIES+VDSVIN_ARRAY_ENTRIES; i++) {
+
+ if (i < LOCAL_PSTATE_ARRAY_ENTRIES) {
+ rc = putscom(MC_ADDRESS(PCBS_PSTATE_TABLE_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ i_lpsa->pstate[i].value);
+ if (rc) _BREAK;
+ } else {
+ rc = putscom(MC_ADDRESS(PCBS_PSTATE_TABLE_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ i_lpsa->vdsvin[i-LOCAL_PSTATE_ARRAY_ENTRIES].value);
+ if (rc) _BREAK;
+ }
+
+ }
+
+ ppibr.value = 0;
+ ppibr.fields.lpsi_min = lpst_pmin(i_lpsa) - PSTATE_MIN;
+ ppibr.fields.lpsi_entries_minus_1 = i_lpsa->entries - 1;
+ rc = putscom(MC_ADDRESS(PCBS_PSTATE_INDEX_BOUND_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ ppibr.value);
+ if (rc) _BREAK;
+
+
+ // Install the step delay parameters, then clear the undervolting
+ // control (applicable to the entire range) via multicast.
+
+ pivcr0.value = 0;
+ if (i_lpsa->stepdelay_rising)
+ pivcr0.fields.ivrm_req_pstate_stepdelay_rising =
+ i_lpsa->stepdelay_rising;
+ else
+ pivcr0.fields.ivrm_req_pstate_stepdelay_rising = 0xFF;
+ if (i_lpsa->stepdelay_lowering)
+ pivcr0.fields.ivrm_req_pstate_stepdelay_lowering =
+ i_lpsa->stepdelay_lowering;
+ else
+ pivcr0.fields.ivrm_req_pstate_stepdelay_lowering = 0XFF;
+ rc = putscom(MC_ADDRESS(PCBS_IVRM_VID_CONTROL_REG0,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ pivcr0.value);
+ if (rc) _BREAK;
+
+ ///bug need to determine where these values come from
+ pivcr1.value = 0;
+ pivcr1.fields.ivrm_stabilize_delay_run = 0x40;
+ pivcr1.fields.ivrm_stabilize_delay_idle = 0x40;
+ pivcr1.fields.ivrm_pfstr_prop_delay = 0x1E;
+ pivcr1.fields.ivrm_pfstrvalid_prop_delay = 0xFF;
+ pivcr1.fields.ivrm_vpump_poweron_time = 0xFF;
+ pivcr1.fields.ivrm_bypass_delay = 0x1E;
+ pivcr1.fields.pfet_vpump_enable_delay = 0x4E;
+ pivcr1.fields.ivrm_vid_vout_threshold = 0x00;
+ rc = putscom(MC_ADDRESS(PCBS_IVRM_VID_CONTROL_REG1,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ pivcr1.value);
+ if (rc) _BREAK;
+
+ pur.value = 0;
+ pur.fields.puv_min = lpst_pmin(i_lpsa);
+ pur.fields.puv_max = lpst_pmax(i_lpsa);
+ pur.fields.kuv = 0;
+ rc = putscom(MC_ADDRESS(PCBS_UNDERVOLTING_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ pur.value);
+ if (rc) _BREAK;
+
+ // Set pre_vret_pstate to Non-Functional Pstate
+ // \bug currently set to pmin, is it always same as psafe?
+ rc = getscom(MC_ADDRESS(PCBS_DPLL_CPM_PARM_REG,
+ MC_GROUP_EX, PCB_MULTICAST_OR),
+ &(pdcpr.value));
+ if (rc) _BREAK;
+ pdcpr.fields.pre_vret_pstate = lpst_pmin(i_lpsa);
+ rc = putscom(MC_ADDRESS(PCBS_DPLL_CPM_PARM_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ pdcpr.value);
+ if (rc) _BREAK;
+
+ // Checking that PStates are NOT enabled
+ rc = getscom(MC_ADDRESS(PCBS_PCBSPM_MODE_REG,
+ MC_GROUP_EX, PCB_MULTICAST_OR),
+ &(ppmr.value));
+ if (rc) _BREAK;
+ if (ppmr.fields.enable_pstate_mode) {
+ rc = -GPSM_PSTATE_ENABLED;
+ _BREAK;
+ }
+
+ // Enable I-VRM FSM
+ rc = getscom(MC_ADDRESS(PCBS_IVRM_CONTROL_STATUS_REG,
+ MC_GROUP_EX, PCB_MULTICAST_OR),
+ &(picsr.value));
+ if (rc) _BREAK;
+ picsr.fields.ivrm_fsm_enable = 1;
+ rc = putscom(MC_ADDRESS(PCBS_IVRM_CONTROL_STATUS_REG,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ picsr.value);
+ if (rc) _BREAK;
+
+ } while (0);
+
+ if (timeout_rc && !rc)
+ return timeout_rc;
+ else
+ return rc;
+}
+
+
+/// Install (new) Resonant Clocking Setup
+///
+/// \param[in] i_resclk A pointer to a ResonantClockingSetup to install in
+/// every configured core.
+///
+/// \param[in] i_options Options controlling the installation, or a NULL (0)
+/// pointer to indicate fully default behavior.
+///
+/// This procedure will likely only be called once, at initialization, and
+/// then only as part of the gpsm_initialize() procedure. The procedure:
+///
+/// - Initializes the Pstate resonance range limits in the register
+/// PCBS_RESONANT_CLOCK_CONTROL_REG1 by multicast.
+///
+/// - Setup parameters in PCBS_RESONANT_CLOCK_CONTROL_REG0 and turn on
+/// Resonant Clock in Hardware Pstate Mode.
+///
+/// \note The caller is responsible for the mode-correctness of this
+/// procedure. This procedure must only be called when resonant clocking is
+/// disabled and the controls are set for manual mode. Because of the way the
+/// resonant clocking controls are designed we must enable resonant clocking
+/// to update the Pstate bounds! After the bounds are updated resonant
+/// clocking is disabled again.
+///
+/// \retval 0 Success
+///
+/// \retval -GPSM_INVALID_ARGUMENT_RCLK_INSTALL The ResonantClockingSetup
+/// argument was NULL (0).
+///
+/// \retval -GPSM_ILLEGAL_MODE_RCLK_INSTALL Resonant clocking appears to be
+/// enabled or not in manual mode in at least one configured core.
+///
+/// \retval others This API may also return non-0 codes from
+/// getscom()/putscom()
+
+int
+gpsm_resclk_install(const ResonantClockingSetup* i_resclk,
+ const GlobalPstateTable* i_gpst,
+ const PstateOptions* i_options)
+{
+ ResonantClockingSetup d_resclk;
+ pcbs_resonant_clock_control_reg0_t prccr0;
+ pcbs_resonant_clock_control_reg1_t prccr1;
+ int rc;
+ uint32_t configured_cores;
+ int flag, core;
+
+ TRACE_GPSM(TRACE_GPSM_RESCLK_INSTALL);
+
+ do {
+
+ // Optional bypass of this procedure
+
+ if ((i_options != 0) &&
+ (i_options->options & PSTATE_NO_INSTALL_RESCLK)) {
+
+ rc = 0;
+ break;
+ }
+
+ // No Resonant Clock Install and Enable if there is no configued cores
+
+ configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG);
+ flag = 1;
+ for (core = 0; core < PGP_NCORES; core++, configured_cores <<= 1) {
+ if (!(configured_cores & 0x80000000)) continue;
+ flag = 0;
+ }
+ if (flag == 1) {
+ rc = 0;
+ break;
+ }
+
+ // Check the setup for existence. Do an AND-combining multicast read
+ // to see if any of the cores have resonant clocking enabled, or are
+ // not in manual mode.
+
+ if (i_resclk == 0) {
+ rc = -GPSM_INVALID_ARGUMENT_RCLK_INSTALL;
+ _BREAK;
+ }
+ rc = getscom(MC_ADDRESS(PCBS_RESONANT_CLOCK_CONTROL_REG0,
+ MC_GROUP_EX, PCB_MULTICAST_AND),
+ &(prccr0.value));
+ if (rc) _BREAK;
+
+ if (!prccr0.fields.resclk_dis || !prccr0.fields.resclk_control_mode) {
+ rc = -GPSM_ILLEGAL_MODE_RCLK_INSTALL;
+ _BREAK;
+ }
+
+
+ // Resonant clocking is specified such that it must be enabled (in a
+ // benign manual mode) in order to be set up.
+
+ // Enable resonant clocking in the GP3 register (AND), bit 22. Our
+ // Simics environment does not model the GP3->PRCCR0 connection
+ // currently, and does not enforce the register locks.
+
+ if (!SIMICS_ENVIRONMENT) {
+
+ rc = putscom(MC_ADDRESS(0x100f0013, MC_GROUP_EX,
+ PCB_MULTICAST_WRITE),
+ ~0x0000020000000000ull);
+ if (rc) _BREAK;
+ }
+
+ // Write the PCBS_RESONANT_CLOCK_CONTROL_REG1 with the
+ // Pstate setup, clearing all manual fields.
+
+ // If at least one resonant clocking parm was 0 in PstateSuperStructure
+ // write the register with default values
+ // Low Band : 2 GHZ to 3.2 GHz
+ // High Band : 3.2 GHZ - Up
+
+ gpst_frequency2pstate(i_gpst, 0, &(d_resclk.full_csb_ps));
+ gpst_frequency2pstate(i_gpst, 2000000, &(d_resclk.res_low_lower_ps));
+ gpst_frequency2pstate(i_gpst, 3200000, &(d_resclk.res_low_upper_ps));
+ gpst_frequency2pstate(i_gpst, 3200000, &(d_resclk.res_high_lower_ps));
+ gpst_frequency2pstate(i_gpst, 9999999, &(d_resclk.res_high_upper_ps));
+
+ prccr1.value = 0;
+ if (!(i_resclk->full_csb_ps &&
+ i_resclk->res_low_lower_ps &&
+ i_resclk->res_low_upper_ps &&
+ i_resclk->res_high_lower_ps &&
+ i_resclk->res_high_upper_ps)) {
+ prccr1.fields.full_csb_ps = d_resclk.full_csb_ps;
+ prccr1.fields.res_low_lower_ps = d_resclk.res_low_lower_ps;
+ prccr1.fields.res_low_upper_ps = d_resclk.res_low_upper_ps;
+ prccr1.fields.res_high_lower_ps = d_resclk.res_high_lower_ps;
+ prccr1.fields.res_high_upper_ps = d_resclk.res_high_upper_ps;
+ } else {
+ prccr1.fields.full_csb_ps = i_resclk->full_csb_ps;
+ prccr1.fields.res_low_lower_ps = i_resclk->res_low_lower_ps;
+ prccr1.fields.res_low_upper_ps = i_resclk->res_low_upper_ps;
+ prccr1.fields.res_high_lower_ps = i_resclk->res_high_lower_ps;
+ prccr1.fields.res_high_upper_ps = i_resclk->res_high_upper_ps;
+ }
+
+ ///bug need to determine where these values come from
+ prccr1.fields.nonres_csb_value_ti = 0xC;
+ prccr1.fields.full_csb_value_ti = 0xF;
+
+ rc = putscom(MC_ADDRESS(PCBS_RESONANT_CLOCK_CONTROL_REG1,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ prccr1.value);
+ if (rc) _BREAK;
+
+
+ // Disable resonant clocking in the GP3 register (OR), bit 22.
+
+ if (!SIMICS_ENVIRONMENT) {
+
+ rc = putscom(MC_ADDRESS(0x100f0014, MC_GROUP_EX,
+ PCB_MULTICAST_WRITE),
+ 0x0000020000000000ull);
+ if (rc) _BREAK;
+ }
+
+ // Enable resonant clock pstate hardware mode(control_mode = 0)
+ // Sync Pulse Width maximum value : 0x7 of nest/4 cycles
+ // Sync Delay maximum value : 0x7F of nest/4 cycles
+ // Sector Buffer Strength Instruction . Low Band : 0xAAA
+ // Sector Buffer Strength Instruction . High Band : 0xAAA
+
+ prccr0.fields.resclk_control_mode = 0;
+ prccr0.fields.resclk_sync_pw = 0x7;
+ prccr0.fields.res_sync_delay_cnt = 0x7F;
+ prccr0.fields.res_csb_str_instr_lo = 0xAAA;
+ prccr0.fields.res_csb_str_instr_hi = 0x1FF;
+
+ rc = putscom(MC_ADDRESS(PCBS_RESONANT_CLOCK_CONTROL_REG0,
+ MC_GROUP_EX, PCB_MULTICAST_WRITE),
+ prccr0.value);
+ if (rc) break;
+
+ // Enable resonant clocking in the GP3 register (AND), bit 22.
+ if (!SIMICS_ENVIRONMENT) {
+
+ rc = putscom(MC_ADDRESS(0x100f0013, MC_GROUP_EX,
+ PCB_MULTICAST_WRITE),
+ ~0x0000020000000000ull);
+ if (rc) break;
+ }
+
+ } while (0);
+
+ return rc;
+}
+
+
+/// Initialize the GPSM procedure mechanism
+///
+/// \param[in] i_pss A pointer to the PstateSuperStructure containing the
+/// Global and Local Pstate tables, plus resonant clocking setup and other
+/// options.
+///
+/// \param[out] o_gpst A pointer to a 1-KB aligned GlobalPstateTable which
+/// will be updated with a copy of the GlobalPstateTable from the
+/// PstateSuperStructure.
+///
+/// This API is designed to be called once at system initialization, to set up
+/// GPSM mechanisms, install the Global and Local Pstate tables, and set up
+/// resonant clocking from the PstateSuperStructure. At the entry of this
+/// procedure it is assumed that the system firmware has initialized the PMC
+/// mode register to either no mode, or to indicate Firmware Pstate Mode. It
+/// is further assumed that the core chiplets are in a state which will allow
+/// the Local Pstate tables and resonant clocking setup to be installed
+/// without affecting system stability. Such a state must be guaranteed at
+/// system initialization and after any OCC reset. If called from any other
+/// context the caller is responsible for ensuring that the system is in a
+/// state that will allow the procedure to run correctly.
+///
+/// This procedure does not enable Pstates or enter any Pstate mode, and does
+/// not alter any voltage or frequency settings. After the Pstate tables have
+/// been installed, Pstate mode is enabled by calls of
+/// gpsm_enable_pstates_master() and gpsm_enable_pstates_slave() as described
+/// in the commenst for gpsm_init.c.
+///
+/// The initialization of Pstates was split up into these three steps to best
+/// handle the initialization of the slave chip in a DCM. This procedure
+/// (gpsm_initialize()) can be called by the DCM slave whenever a
+/// PstateSuperStructure is available. By requirememt and convention this
+/// Pstate SuperStructure will be identical with the one installed by the DCM
+/// master.
+///
+/// The GPSM driver makes few assumptions about how the system firmware has
+/// set up the PMC, but does require some critical setup.
+///
+/// - It is assumed that for DCM configurations the system firmware will have
+/// set the PMC_MODE_REG.enable_interchip_interface (to indicate a DCM
+/// configuration), and set the PMC_MODE_REG.interchip_mode appropriately for
+/// the master and the slave.
+///
+/// - It is assumed that the PMC Core Deconfiguration register implies the
+/// same set of configured cores as the set included in the PCB multicast
+/// group covering all cores.
+///
+/// All GPSM procedures use the same semaphore, which is set by the interrupt
+/// handler for all GPSM interrupts. The GPSM driver claims the PMC protocol
+/// ongoing, voltage change ongoing, and PMC Sync interrupts.
+///
+/// Once the interrupts are set up, the GlobalPstateTable is copied from the
+/// PstateSuperStructure to its proper location and installed. Next, the
+/// Local Pstate tables and resonant clocking setup are installed into all
+/// cores by multicast SCOM.
+///
+/// \retval 0 Success
+///
+/// \retval -GPSM_INVALID_OBJECT Either the \a i_pss or \a o_gpst are NULL (0).
+///
+/// \retval -GPSM_INVALID_MAGIC The 'magic number' of the PstateSuperStructure
+/// is different from that expected.
+///
+/// \retval -GPSM_ILLEGAL_MODE_GPSM_INIT Either the PMC indicates a Pstate mode
+/// is active, one or more cores appear to have iVRM enabled, or one or more
+/// cores appear to have resonant clocking enabled.
+///
+/// \retval others This API may also return codes from gpsm_gpst_install(),
+/// gpsm_lpsa_install() and gpsm_resclk_install().
+
+int
+gpsm_initialize(const PstateSuperStructure* i_pss,
+ GlobalPstateTable* o_gpst)
+{
+ pmc_mode_reg_t pmr;
+ int rc;
+
+ TRACE_GPSM(TRACE_GPSM_INITIALIZE);
+
+ do {
+
+ // Check for a valid PstateSuperStructure and GlobalPstateTable
+
+ if ((i_pss == 0) || (o_gpst == 0)) {
+
+ rc = -GPSM_INVALID_OBJECT;
+ _BREAK;
+ }
+
+ if (i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD1 &&
+ i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD2 &&
+ i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD3 ) {
+
+ rc = -GPSM_INVALID_MAGIC;
+ _BREAK;
+ }
+
+
+ // Check/set up the PMC mode register
+
+ pmr.value = in32(PMC_MODE_REG);
+ if (pmr.fields.enable_hw_pstate_mode ||
+ pmr.fields.enable_fw_auction_pstate_mode) {
+ rc = -GPSM_ILLEGAL_MODE_GPSM_INIT;
+ _BREAK;
+ }
+ if (!pmr.fields.enable_fw_pstate_mode) {
+
+ pmr.fields.enable_fw_pstate_mode = 1;
+ out32(PMC_MODE_REG, pmr.value);
+ }
+
+ // ** VBU **
+ pmr.fields.halt_pstate_master_fsm = 0;
+ out32(PMC_MODE_REG, pmr.value);
+
+
+ // Initialize interrupt handling
+
+ ssx_semaphore_create(&G_gpsm_protocol_semaphore, 0, 1);
+
+ ssx_irq_disable(PGP_IRQ_PMC_PROTOCOL_ONGOING);
+ ssx_irq_disable(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING);
+ ssx_irq_disable(PGP_IRQ_PMC_SYNC);
+
+ ssx_irq_setup(PGP_IRQ_PMC_PROTOCOL_ONGOING,
+ SSX_IRQ_POLARITY_ACTIVE_LOW,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+
+ ssx_irq_setup(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING,
+ SSX_IRQ_POLARITY_ACTIVE_LOW,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+
+ ssx_irq_setup(PGP_IRQ_PMC_SYNC,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+
+
+ ssx_irq_handler_set(PGP_IRQ_PMC_PROTOCOL_ONGOING,
+ ssx_semaphore_post_handler,
+ (void *)(&G_gpsm_protocol_semaphore),
+ SSX_NONCRITICAL);
+
+ ssx_irq_handler_set(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING,
+ ssx_semaphore_post_handler,
+ (void *)(&G_gpsm_protocol_semaphore),
+ SSX_NONCRITICAL);
+
+ ssx_irq_handler_set(PGP_IRQ_PMC_SYNC,
+ ssx_semaphore_post_handler,
+ (void *)(&G_gpsm_protocol_semaphore),
+ SSX_NONCRITICAL);
+
+ // Install the Global Pstate table, Local Pstate Array and resonant
+ // clocking setup, using options contained in the PstateSuperStructure.
+
+ rc = gpsm_gpst_install(o_gpst, &(i_pss->gpst));
+ if (rc) _BREAK;
+
+ rc = gpsm_lpsa_install(&i_pss->lpsa,
+ &(i_pss->gpst.options));
+ if (rc) _BREAK;
+
+ rc = gpsm_resclk_install(&i_pss->resclk,
+ &(i_pss->gpst),
+ &(i_pss->gpst.options));
+ if (rc) _BREAK;
+
+ G_gpsm_initialized = 1;
+
+ } while (0);
+
+ return rc;
+}
+
+
+// Step voltage manually
+//
+// This API is only (?) used by gpsm_enable_pstates_master[slave](). It is
+// used to make a (hopefully) minor adjustment between the current voltage and
+// the target voltage associated with the initial Global Actual Pstate. In
+// cases where the current voltage is not represented in the new Pstate table,
+// this routine may take a long time as it will do many single-VID-code steps
+// as it gradually moves between the current and target voltages.
+//
+// Voltage change direction is determined by the difference in the Vdd VIDs,
+// and the alogorithm mimics the P7 PVID stepping protocol. If voltage is
+// going up, Vdd and Vcs slew together. If voltage is going down, Vdd slews
+// twice for every change in Vcs. Note that given a Vdd differential we can't
+// assume which way Vcs is moving.
+//
+// The use of Vcs offsets instead of straight-up VID codes in the hardware is
+// extremely confusing, especially since the offsets are defined in normal
+// order as opposed to VID codes which decrease as voltage increases.
+
+// Racall that the inputs are VID codes (lower VID --> higher voltage)
+
+static int
+_manual_step_voltage(const uint8_t i_currentVdd,
+ const uint8_t i_currentVcs,
+ const uint8_t i_targetVdd,
+ const uint8_t i_targetVcs)
+{
+ int rc, parity;
+ pmc_global_actual_voltage_reg_t pgavr;
+ uint8_t currentVdd, currentVcs;
+
+ TRACE_GPSM(TRACE_MANUAL_STEP_VOLTAGE);
+
+ do {
+
+ rc = 0;
+ currentVdd = i_currentVdd;
+ currentVcs = i_currentVcs;
+ parity = 1;
+
+ while ((currentVdd != i_targetVdd) &&
+ (currentVcs != i_targetVcs)) {
+
+ if (currentVdd > i_targetVdd) {
+
+ // Voltage going up, slew Vdd and Vcs together. Parity remains
+ // 1.
+
+ currentVdd--;
+
+ } else if (currentVdd > i_targetVdd) {
+
+ // Voltage going down, only slew Vcs every other time. Parity
+ // is inverted.
+
+ currentVdd++;
+ parity = 1 - parity;
+
+ } else {
+
+ // Vdd not moving, set parity so Vcs will move every time.
+
+ parity = 1;
+ }
+
+ if (parity) {
+ if (currentVcs < i_targetVcs) {
+ currentVcs++;
+ } else if (currentVcs > i_targetVcs) {
+ currentVcs--;
+ }
+ }
+
+ rc = gpsm_quiesce();
+ if (rc) _BREAK;
+
+ pgavr.value = 0;
+ pgavr.fields.evid_vdd = currentVdd;
+ pgavr.fields.evid_vcs = -((int)currentVcs - (int)currentVdd);
+ out32(PMC_GLOBAL_ACTUAL_VOLTAGE_REG, pgavr.value);
+ }
+ if (rc) _BREAK;
+
+ rc = gpsm_quiesce();
+ if (rc) _BREAK;
+
+ } while (0);
+
+ return rc;
+}
+
+
+// This is a 'prologue' sequence executed in each core chiplet during the
+// initialization of Pstates. The set of cores to operate on is taken from
+// the current value of the PMC_CORE_DECONFIGURATION_REG.
+//
+// At entry it assumed that iVRM and CPM-DPLL are disabled. It also clears
+// possible safe mode dails before enable pstate.
+//
+// At exit, the following will be true for all configured cores:
+//
+// - The core will be in DPLL frequency override mode with Fmin and Fmax set
+// to the frequency implied by the given Pstate in the given Pstate table with
+// 0 undervolting.
+//
+// - The Fmax bias of the core is set from the Pstate table.
+//
+// - The Fnom of the core is set from the Pstate table.
+//
+// - Pstate mode is enabled in the core and global requests are enabled.
+//
+// - The Local Actual Pstate is being controlled by the Pstate mechanism.
+//
+// - The PMCR will have been updated to the \a frequencyPstate (both global
+// and local) and the global bids (should be) consistent. Auto-override modes
+// in the PMCR are not modified.
+
+static int
+_enable_pstates_core_prologue(const GlobalPstateTable* i_gpst,
+ const Pstate i_frequency_pstate,
+ const gpst_entry_t i_entry)
+{
+ int rc, core;
+ unsigned int bogus;
+ uint32_t configured_cores;
+ DpllCode fNom, fPstate;
+ pcbs_pmgp1_reg_t pmgp1;
+ pcbs_freq_ctrl_reg_t pfcr;
+ pcbs_pcbspm_mode_reg_t ppmr;
+ pcbs_power_management_control_reg_t pmcr;
+ pcbs_power_management_bounds_reg_t ppmbr;
+ pcbs_pmc_vf_ctrl_reg_t ppvcr;
+
+ TRACE_GPSM(TRACE_ENABLE_PSTATES_CORE_PROLOGUE);
+
+ do {
+
+ /* In the event of no configured cores, FW requested to not error out */
+ //rc = -GPSM_CONFIGURATION_ERROR;
+ rc = 0;
+
+ // Do for each core chiplet...
+ configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG);
+
+ // Turn off possible safe mode so we can move pstate
+ pcbs_hb_config(0, configured_cores, 0, 0, 0, &bogus);
+ pmc_hb_config(0, 0, 0, &bogus);
+
+ for (core = 0; core < PGP_NCORES; core++, configured_cores <<= 1) {
+
+ if (!(configured_cores & 0x80000000)) continue;
+
+ // The 'nominal' frequency code may be biased per core. This
+ // should not under/over-flow.
+
+ fNom = i_gpst->pstate0_frequency_code[core];
+ rc = bias_frequency(fNom, i_frequency_pstate, &fPstate);
+ if (rc) _BREAK;
+
+
+ /// \bug HW Bug: Chicken-and-egg problem with frequency override
+ /// mode. We need a different HW control structure here. This
+ /// may glitch frequency.
+
+ // Initial PMGP1_REG setup
+ //
+ // - Force OCC control of the PM SPRS. This may have to be
+ // rethought if PHYP ever controls Pstates.
+ //
+ // - Enable DPLL frequency overrides
+
+ pmgp1.value = 0;
+ pmgp1.fields.pm_spr_override_en = 1;
+ pmgp1.fields.dpll_freq_override_enable = 1;
+
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG_OR, core),
+ pmgp1.value);
+ if (rc) _BREAK;
+
+
+ // Update Fmin, Fmax, Fmax bias and Pstate0 frequency.
+
+ pfcr.value = 0;
+ pfcr.fields.dpll_fmin = fPstate;
+ pfcr.fields.dpll_fmax = fPstate;
+ pfcr.fields.dpll_fmax_bias = i_gpst->dpll_fmax_bias[core];
+ pfcr.fields.frequ_at_pstate0 = fNom;
+
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_FREQ_CTRL_REG, core),
+ pfcr.value);
+ if (rc) _BREAK;
+
+
+ /// \bug HW BUG : PCBS_Power_Management_Bounds_reg hardware reset
+ /// is whack, violating the Pstate constraints. (HW216565).
+ /// Deferred to Venice. Not a problem for us, we always set up
+ /// this register.
+
+ // The PCBS clipping is initialized to the limits present in the
+ // _global_ Pstate table. This is necessary for correctness of
+ // the PCBS state machines. If fast-idle modes with retention are
+ // enabled this is also necessary to protect against trying to
+ // drop into non-functional Pstates required to be present in the
+ // _local_ pstate table.
+
+ // \bug Workaround, since pre_vret_pstate is set to pmin currently
+ // until pstate super structure and pstate data block procedure
+ // support an entry as non-functional pstate, need to set lower
+ // clip bound to be the pstate one above pmin to make pmin
+ // essentially a non-functional pstate for now
+
+ ppmbr.value = 0;
+ ppmbr.fields.pmin_clip = gpst_pmin(i_gpst)+1;
+ ppmbr.fields.pmax_clip = gpst_pmax(i_gpst);
+
+ // This fix is added per SW260911
+ // Minimum Frequency in the system is given by MRW attribute
+ // PState Datablock procedure will read the attribute then
+ // convert it into pstate _pfloor_ and put it into
+ // Global Pstate Table. GPSM here consumes the value
+ // and set both lower bounds: pmin_rail(PMC) and pmin_clip(PCBS)
+ // and two safe pstates: pvsafe(PMc) and psafe(PCBS) to be
+ // _pfloor_ if _pfloor_ is higher than their default(gpst_pmin)
+ // so that we should never run with frequency below the floor
+ // even in safe mode
+ if (ppmbr.fields.pmin_clip < i_gpst->pfloor && i_gpst->pfloor != 0)
+ ppmbr.fields.pmin_clip = i_gpst->pfloor;
+
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_POWER_MANAGEMENT_BOUNDS_REG,
+ core),
+ ppmbr.value);
+ if (rc) _BREAK;
+
+
+ // Now that we've locked the frequency and set valid clipping
+ // bounds, disable the local Pstate override and allow Global Acks
+ // and Pmax-Sync to propogate.
+
+ rc = getscom(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG, core),
+ &(pmgp1.value));
+ if (rc) _BREAK;
+
+ pmgp1.value = 0;
+ pmgp1.fields.enable_occ_ctrl_for_local_pstate_eff_req = 1;
+
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG_AND, core),
+ ~pmgp1.value);
+ if (rc) _BREAK;
+
+
+ // Setup PCBS_PMC_VF_CTRL_REG before enable Pstate
+
+ rc = getscom(CORE_CHIPLET_ADDRESS(PCBS_PMC_VF_CTRL_REG, core),
+ &(ppvcr.value));
+ if (rc) _BREAK;
+
+ ppvcr.fields.pglobal_actual = i_frequency_pstate;
+ ppvcr.fields.maxregvcs = i_entry.fields.maxreg_vdd;
+ ppvcr.fields.maxregvdd = i_entry.fields.maxreg_vcs;
+ ppvcr.fields.evidvcs_eff = i_entry.fields.evid_vdd_eff;
+ ppvcr.fields.evidvdd_eff = i_entry.fields.evid_vcs_eff;
+
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_PMC_VF_CTRL_REG, core),
+ ppvcr.value);
+ if (rc) _BREAK;
+
+
+ // Enable Pstate in PCB Slave
+
+ rc = getscom(CORE_CHIPLET_ADDRESS(PCBS_PCBSPM_MODE_REG, core),
+ &(ppmr.value));
+ if (rc) _BREAK;
+
+ ppmr.fields.enable_pstate_mode = 1;
+ ppmr.fields.enable_global_pstate_req = 1;
+ ppmr.fields.enable_pmc_pmax_sync_notification = 1;
+
+ // ** VBU **
+ ppmr.fields.dpll_lock_replacement_timer_mode_en = 1;
+
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_PCBSPM_MODE_REG, core),
+ ppmr.value);
+ if (rc) _BREAK;
+
+ // Update the PMCR to propagate the global bids
+
+ rc = getscom(CORE_CHIPLET_ADDRESS(PCBS_POWER_MANAGEMENT_CONTROL_REG,
+ core),
+ &(pmcr.value));
+ if (rc) _BREAK;
+
+ pmcr.fields.global_pstate_req = i_frequency_pstate;
+ pmcr.fields.local_pstate_req = i_frequency_pstate;
+
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_POWER_MANAGEMENT_CONTROL_REG,
+ core),
+ pmcr.value);
+ if (rc) _BREAK;
+ }
+ if (rc) _BREAK;
+
+ } while (0);
+
+ return rc;
+}
+
+
+// This is an 'epilogue' sequence executed in each core chiplet during the
+// enablement of Pstate mode. When this code is executed, the core is in
+// frequency override mode at (or below) the frequency of the Global Pstate
+// Actual. This procedure releases frequency override mode and core-level
+// Pstate operations commence.
+//
+// retval -GPSM_BABYSTEPPER_SYNC_TIMEOUT, if baby stepper sync
+// local_pstate_actual times out
+//
+static int
+_enable_pstates_core_epilogue(void)
+{
+ int rc = 0, timeout_rc = 0, core;
+ uint32_t configured_cores;
+ pcbs_pmgp1_reg_t pmgp1;
+ pcbs_power_management_status_reg_t ppmsr;
+ SsxTimebase timeout;
+
+ TRACE_GPSM(TRACE_ENABLE_PSTATES_CORE_EPILOGUE);
+
+ do {
+
+ configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG);
+ for (core = 0; core < PGP_NCORES; core++, configured_cores <<= 1) {
+
+ if (!(configured_cores & 0x80000000)) continue;
+
+ pmgp1.value = 0;
+ pmgp1.fields.dpll_freq_override_enable = 1;
+
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG_AND, core),
+ ~pmgp1.value);
+ if (rc) _BREAK;
+ }
+ if (rc) _BREAK;
+
+ // For Babystepper to catch up sync the local_pstate_actual
+ // Poll for up to 300us for done before erroring out
+
+ timeout_rc = -GPSM_BABYSTEPPER_SYNC_TIMEOUT;
+ timeout = ssx_timebase_get() + SSX_MICROSECONDS(300);
+ while (ssx_timebase_get() < timeout) {
+ rc = getscom(MC_ADDRESS(PCBS_POWER_MANAGEMENT_STATUS_REG,
+ MC_GROUP_EX, PCB_MULTICAST_AND),
+ &(ppmsr.value));
+ if (rc) _BREAK;
+ if (ppmsr.fields.local_pstate_actual ==
+ ppmsr.fields.global_pstate_actual) {
+ timeout_rc = 0;
+ break;
+ }
+ }
+ if (timeout_rc||rc) _BREAK;
+
+ } while(0);
+
+ if (timeout_rc && !rc)
+ return timeout_rc;
+ else
+ return rc;
+
+}
+
+
+/// Enable Pstates in Firmware Mode, initial Master-only phase
+///
+/// \param[out] o_info This structure is populated by this API for use
+/// by a DCM master in gpsm_enable_pstates_slave. The DCM slave does not
+/// require this information.
+///
+/// \param[out] o_voltage_pstate This parameter returns the Pstate
+/// corresponding to the current system voltage (or the closest safe
+/// approximation). This parameter must be communicated to the slave before
+/// the slave can call gpsm_enable_pstates_slave().
+///
+/// \param[out] o_frequency_pstate *DEPRECATED* This parameter returns the
+/// Pstate corresponding to the current system voltage (or the closest safe
+/// approximation). This parameter must be communicated to the slave before
+/// the slave can call gpsm_enable_pstates_slave().
+///
+/// \note This procedure is only called on an SCM or a DCM master. It will
+/// fail if called on a DCM slave.
+///
+/// \retval 0 Success
+///
+/// \returns All other return codes indicate an error.
+
+int
+gpsm_enable_pstates_master(GpsmEnablePstatesMasterInfo* o_info,
+ Pstate* o_voltage_pstate,
+ Pstate* o_frequency_pstate)
+{
+ int rc, search_rc;
+ GlobalPstateTable* gpst;
+ gpst_entry_t voltage_entry;
+
+ TRACE_GPSM(TRACE_GPSM_ENABLE_PSTATES_MASTER);
+
+ do {
+
+ if (gpsm_dcm_slave_p()) {
+ rc = -GPSM_ILLEGAL_MODE_EPSM;
+ _BREAK;
+ }
+
+ // Enter Firmware Pstate Mode. The gpsm_fw_mode() procedure
+ // guarantees that the GPSM is quiesced at this point. Recover a
+ // pointer to the Pstate table from PMC.
+
+ rc = gpsm_fw_mode();
+ if (rc) _BREAK;
+
+ gpst = gpsm_gpst();
+
+ // Map the current Vdd VID to a pstate in the new Pstate table.
+ //
+ // As an option (workaround, simulation hack), force the assumption
+ // that the current voltage corresponds to PMIN. This will not move
+ // the external voltage, however it will force the frequency down to
+ // the PMIN frequency prior to starting Pstate operations. It is
+ // always safe to change the Pstate from "PMIN", regardless of the
+ // actual external voltage, since the PMIN frequency is safe at any
+ // voltage.
+
+ if (!(gpst->options.options & PSTATE_FORCE_INITIAL_PMIN)) {
+
+ rc = vrm_voltage_read(SPIVRM_PORT(0),
+ VRM_RD_VDD_RAIL,
+ &(o_info->currentVdd));
+ if (rc) _BREAK;
+ rc = vrm_voltage_read(SPIVRM_PORT(0),
+ VRM_RD_VCS_RAIL,
+ &(o_info->currentVcs));
+ if (rc) _BREAK;
+
+ } else {
+
+ rc = gpst_entry(gpst, gpst_pmin(gpst), 0, &voltage_entry);
+ if (rc) {
+ SSX_PANIC(GPSM_BUG); /* This can't happen */
+ }
+
+ o_info->currentVdd = voltage_entry.fields.evid_vdd;
+ o_info->currentVcs = voltage_entry.fields.evid_vcs;
+ }
+
+ search_rc = gpst_vdd2pstate(gpst, o_info->currentVdd,
+ o_voltage_pstate, &voltage_entry);
+ if (search_rc &&
+ (search_rc != -GPST_PSTATE_CLIPPED_LOW_GPST_V2P) &&
+ (search_rc != -GPST_PSTATE_CLIPPED_HIGH_GPST_V2P)) {
+ rc = search_rc;
+ break;
+ }
+
+ o_info->targetVdd = voltage_entry.fields.evid_vdd;
+ o_info->targetVcs = voltage_entry.fields.evid_vcs;
+
+
+ // If the Pstate was 'clipped low', it indicates that the current
+ // voltage is lower than the lowest new Pstate. Therefore we need to
+ // manually step voltage up before locking in the Pmin frequency. If
+ // the Pstate was 'clipped high' it means that the current voltage is
+ // higher than the highest Pstate, and we need to lock frequency at
+ // the Pmax frequency prior to stepping voltage down. The unclipped
+ // case is lumped with the 'clipped low' case as this case might
+ // entail a slight rise of voltage. V/F stepping must be split across
+ // the calls of gpsm_enable_pstates_master[slave].
+
+ if ((search_rc == 0)||(search_rc = -GPST_PSTATE_CLIPPED_LOW_GPST_V2P)) {
+
+ rc = _manual_step_voltage(o_info->currentVdd, o_info->currentVcs,
+ o_info->targetVdd, o_info->targetVcs);
+ if (rc) _BREAK;
+
+ o_info->move_voltage = 0;
+
+ } else {
+
+ o_info->move_voltage = 1;
+
+ }
+ } while (0);
+
+ /// \todo The o_frequency_pstate parameter is no longer needed. It was
+ /// originally needed when the Pstate table had an undervolting bias.
+ *o_frequency_pstate = *o_voltage_pstate;
+
+ return rc;
+}
+
+
+/// Enable Pstates in Firmware Pstate Mode, final Master/Slave phase
+///
+/// \param[in] i_info This structure is populated by
+/// gpsm_enable_pstates_master(), and only required in an SCM or DCM master.
+/// When this API is called on a DCM slave the parameter may be passed as NULL
+/// (0).
+///
+/// \param[in] i_voltage_pstate This parameter is computed by
+/// gpsm_enable_pstates_master(), and is required in every case.
+///
+/// \param[in] i_frequency_pstate This parameter is computed by
+/// gpsm_enable_pstates_master(), and is required in every case.
+///
+/// \note This procedure is called in all cases as the final step in enabling
+/// Pstate mode: SCM, DCM master, DCM slave.
+///
+/// \retval 0 Success
+///
+/// \returns All other return codes indicate an error.
+
+int
+gpsm_enable_pstates_slave(const GpsmEnablePstatesMasterInfo* i_info,
+ const Pstate i_voltage_pstate,
+ const Pstate i_frequency_pstate)
+{
+ int rc;
+ GlobalPstateTable* gpst;
+ pmc_mode_reg_t pmr;
+ gpst_entry_t voltage_entry;
+
+ TRACE_GPSM(TRACE_GPSM_ENABLE_PSTATES_SLAVE);
+
+ do {
+
+ // Enter Firmware Pstate Mode. The gpsm_fw_mode() procedure
+ // guarantees that the GPSM is quiesced at this point for the slave;
+ // the master must already be quiesced. Recover a pointer to the
+ // Pstate table from PMC.
+
+ if (gpsm_dcm_slave_p()) {
+
+ rc = gpsm_fw_mode();
+ if (rc) _BREAK;
+
+ } else {
+
+ if (!i_info) {
+ rc = -GPSM_INVALID_ARGUMENT_EPSS;
+ _BREAK;
+
+ } else if (!gpsm_fw_mode_p() || !gpsm_quiesced_p()) {
+
+ rc = -GPSM_ILLEGAL_MODE_EPSS;
+ _BREAK;
+
+ }
+ }
+
+ gpst = gpsm_gpst();
+ gpst_entry(gpst, i_voltage_pstate, 0, &voltage_entry);
+
+ // Execute the core prologue. An SCM or DCM master may need to move
+ // voltage after the frequency move. Since this is guaranteed to be a
+ // safe downward move (otherwise we would have moved voltage already),
+ // it is safe for the DCM slave to go ahead and finish its Pstate
+ // setup before the master has moved the voltage.
+
+ rc = _enable_pstates_core_prologue(gpst, i_frequency_pstate,
+ voltage_entry);
+ if (rc) _BREAK;
+
+ if (!gpsm_dcm_slave_p()) {
+
+ rc = _manual_step_voltage(i_info->currentVdd, i_info->currentVcs,
+ i_info->targetVdd, i_info->targetVcs);
+ if (rc) _BREAK;
+ }
+
+
+ // The Voltage and Frequency state is now consistent in the cores and
+ // in PMC. Make sure that PMC modes are set correctly for Hardware
+ // Pstate Mode.
+
+ pmr.value = in32(PMC_MODE_REG);
+ pmr.fields.enable_pstate_voltage_changes = 1;
+ pmr.fields.enable_global_actual_pstate_forwarding = 1;
+ //pmr.fields.enable_pstate_stepping = 1;
+ out32(PMC_MODE_REG, pmr.value);
+
+
+ // Since we're in Firmware Pstate mode and all cores are
+ // frequency-locked, we can set the Global Actual without stepping -
+ // under the assumption that the caller has disabled iVRM prior to the
+ // call. The master has already computed the volatge_pstate. We
+ // allow the GPSM to quiesce before unlocking the core frequencies.
+
+ _gpsm_broadcast_global_actual(i_frequency_pstate, voltage_entry);
+
+ rc = gpsm_quiesce();
+ if (rc) _BREAK;
+
+ rc = _enable_pstates_core_epilogue();
+ if (rc) _BREAK;
+
+ } while (0);
+
+ return rc;
+}
+
diff --git a/src/lib/heartbeat.c b/src/lib/heartbeat.c
new file mode 100755
index 0000000..51be390
--- /dev/null
+++ b/src/lib/heartbeat.c
@@ -0,0 +1,328 @@
+// $Id: heartbeat.c,v 1.5 2014/07/16 18:07:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/heartbeat.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file heartbeat.c
+/// \brief PgP PMC/PCBS heartbeat configuration procedures
+
+#include "ssx.h"
+#include "heartbeat.h"
+
+/// Configure/Enable/Disable the pmc heartbeat register.
+///
+/// \param enable 1 = enable, 0 = disable, all other values will cause error.
+///
+/// \param req_time_us heartbeat interval time request (in microseconds).
+/// If the pmc does not detect a heartbeat within this time the pmc will
+/// set the corresponding fir bit and enter safe mode. This interval
+/// is the requested value. The return value will be the actual setting.
+/// The procedure well attempt to get as close to the requested time as possible
+/// without choosing a setting lower then requested.
+/// Legal values: 1-4194240 (us). Ignored if force = 1 or enable = 0
+///
+/// \param force 1 = force safe mode (debug), 0 = do not force, all other values
+/// will cause an error. enable = 0 and force = 1 will return an error
+///
+/// \param[out] o_time_us Actual configured time rounded down to the nearest us.
+/// This will be as close as the procedure could get to the requested time given
+/// the frequency and pulse time settings. Returns 0 if hearbeat was disabled or
+/// if safe mode was forced.
+///
+/// \retval 0 Success
+///
+/// \retval -HB_INVALID_ARGUMENT_PMC One of the arguments was invalid in
+/// some way
+
+int
+pmc_hb_config(unsigned int enable,
+ unsigned int req_time_us,
+ unsigned int force,
+ unsigned int *o_time_us
+ )
+
+{
+ pmc_parameter_reg0_t ppr0;
+ pmc_occ_heartbeat_reg_t pohr;
+ tpc_hpr2_t l_hpr2;
+ uint64_t divider, pulses, total_pulses, hp_freq;
+ int rc = 0;
+
+ // @dyd SW238882 fix
+ // remove req_time_us overflow check since the upper boundary of
+ // the req_time_us doesnt depand on certain static value but based on
+ // the value set in hang_pulse_2_reg at runtime.
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((enable > 1) ||
+ (force > 1) ||
+ ((req_time_us < 1) && enable && (! force)) ||
+ ((force == 1 && enable == 0)),
+ HB_INVALID_ARGUMENT_PMC);
+ }
+
+ do {
+
+ // in case firmware does not call ocb_timer_setup
+ // before calling this procedure to setup g_ocb_timer_divider
+ rc = getscom(TPC_HPR2, &l_hpr2.value);
+ if(rc) break;
+ g_ocb_timer_divider = 1 << l_hpr2.fields.hang_pulse_reg;
+
+ // calculation based on pmc_occ_heartbeat_reg defination
+ hp_freq = (__ssx_timebase_frequency_mhz/g_ocb_timer_divider);
+ if(hp_freq < 1)
+ hp_freq = 1;
+ total_pulses = (req_time_us * hp_freq);
+
+ // this may be an overkill for safety but no one should notice
+ if ((req_time_us*__ssx_timebase_frequency_mhz) % g_ocb_timer_divider) {
+ total_pulses++;
+ }
+
+ divider = 0;
+ // determine values for predivider and number of pulses.
+ if (force || (! enable)) { // predivider a don't care in this case
+ pulses = 0;
+ *o_time_us = 0;
+ } else {
+ // can count up to 2^16 pulses with no pre-divide, first determine
+ // minimum pre-divider needed
+ do {
+ divider++;
+ } while ((((divider << 16) - 1) / total_pulses) < 1);
+
+ // @dyd SW238882 fix
+ // underflow case
+ // since pmc heartbeat counter counts with nest_nclk/4
+ // instead of hang pulse when hangpulse_predivider==0,
+ // this procedure doesnt allow predivider to be set to
+ // zero as it is a special case which doesnt work with
+ // occ heartbeat time value calculated by this procedure.
+ // Given hangpulse_predivider = divider - 1,
+ // set divider to 2 if it is 1, zero not possible.
+ if (divider < 2) {
+ divider = 2;
+ //rc = HB_UNDERFLOW_DIVIDER_PMC;
+ //break;
+ }
+ // overflow case
+ // since hangpulse_predivider field is only 6 bit long,
+ // check the overflow first, set to maximum if larger.
+ if (divider > 64) {
+ divider = 64;
+ //rc = HB_OVERFLOW_DIVIDER_PMC;
+ //break;
+ }
+
+ // divider is determined, now setup number of pulses
+ pulses = total_pulses / divider;
+ if (total_pulses % divider) {
+ pulses++;
+ }
+
+ // @dyd SW238882 fix
+ // there is no underflow case for pulses, because pulses=0 as
+ // intended immediate timeout is allowed, plus no mathematical
+ // substraction from pulses is done; however there is an overflow
+ // case: the value of pulses doesnt fit into 16 bits HW field.
+ // Here we set pulses to the maximum value that HW allows,
+ // and use the o_time_us to feedback the caller this is done.
+ if (pulses > 0xFFFF) {
+ pulses = 0xFFFF;
+ //rc = HB_OVERFLOW_PULSES_PMC;
+ // break;
+ }
+
+ // calculating real timeout duration
+ // that this procedure is going to set
+ *o_time_us = (divider*pulses)/hp_freq;
+
+ // @dyd SW238882 fix
+ // in force == 0 && enable == 1 case
+ // disable heartbeat first before reset hang pulse predivider
+ // and new heartbeat time value to prevent immediate timeout.
+ // if force == 1 then it is intended to be immediate timeout anyway
+ // if enable == 0 then it is going to set this bit to zero anyway
+ pohr.value = 0;
+ pohr.fields.pmc_occ_heartbeat_en = 0;
+ if (cfam_id() == CFAM_CHIP_ID_MURANO_10) {
+ out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
+ }
+ out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
+ }
+
+ // Note through experiments, the divider=predivider+1 isnt always
+ // in effect in hardware due to missing last pulse in tight timing,
+ // some setup will end up with just divider=predivider; therefore,
+ // in order to not result unexpected heartbeat timeout, always
+ // set divider to predivider to be safe.
+ if (enable && (! force)) {
+ ppr0.value = in32(PMC_PARAMETER_REG0);
+ ppr0.fields.hangpulse_predivider = divider;
+ out32(PMC_PARAMETER_REG0, ppr0.value);
+ }
+
+ pohr.value = 0;
+ pohr.fields.pmc_occ_heartbeat_en = enable;
+ pohr.fields.pmc_occ_heartbeat_time = pulses;
+ // Due to Issue HW219480, the heartbeat register needs to be written
+ // Twice in order for the heartbeat count value to take correctly.
+ // Technically it would not be harmful to just double-write in
+ // every case, but this is currently written to only double-write
+ // if a Murano dd1.0 part is detected
+ if (cfam_id() == CFAM_CHIP_ID_MURANO_10) {
+ out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
+ }
+ out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
+
+ }while(0);
+ return rc;
+
+}
+
+
+
+/// Configure/Enable/Disable the pcbs heartbeat registers.
+///
+/// \param enable 1 = enable, 0 = disable, all other values will cause error.
+///
+/// \param cores Use this mask to select which cores to update. This routine
+/// will cross reference the current pmc deconfig vector and only update
+/// those cores that are both selected here and configured.
+///
+/// \param hb_reg 32-bit unsigned address of register to setup as the
+/// PCBS heartbeat register. This must be a PCBS address.
+/// Ignored unless enable = 1
+///
+/// \param req_time_us heartbeat interval time request (in microseconds).
+/// If the pcbs does not detect a heartbeat within this time the pcbs will
+/// set the corresponding fir bit and enter safe mode. This interval
+/// is the requested value. The return value will be the actual setting and
+/// the procedure will attempt go get as close to possible to this without
+/// choosing a setting lower then requested.
+/// Legal values: 1 - 16320 (ignored unless enable = 1)
+///
+/// \param force 1 = force safe mode (debug), 0 = do not force, all other values
+/// will cause an error. In PCBS, the force safe mode is not related to
+/// the heartbeat so forcing safe mode while also enabling the heartbeat
+/// is allowed.
+///
+/// \param[out] o_time_us Actual configured time in us. This represents the
+/// actual setting rounded down to the nearest us. 0 if heartbeat was disabled.
+///
+/// \retval 0 Success
+
+/// \retval -HB_INVALID_ARGUMENT_PCBS One of the arguments was invalid in
+/// some way
+///
+/// \retval others This API may also return non-0 codes from
+/// getscom()/putscom()
+
+
+int
+pcbs_hb_config(unsigned int enable,
+ ChipConfigCores cores,
+ uint32_t hb_reg,
+ unsigned int req_time_us,
+ unsigned int force,
+ unsigned int *o_time_us)
+{
+ pcbs_occ_heartbeat_reg_t pohr;
+ pcbs_pmgp1_reg_t pp1r;
+ pmc_core_deconfiguration_reg_t pcdr;
+ uint32_t reg_offset;
+ uint32_t pp1r_addr;
+ uint64_t pp1r_data;
+ ChipConfigCores core_list;
+ ChipConfigCores deconfig;
+ int core;
+ int rc = 0;
+ unsigned int pulses;
+
+ reg_offset = hb_reg - PCBS_PIB_BASE;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((enable > 1) ||
+ ((reg_offset > 0xFF) && enable) ||
+ ((req_time_us < 64) && enable) ||
+ ((req_time_us > 16320) && enable) ||
+ (force > 1),
+ HB_INVALID_ARGUMENT_PCBS);
+ }
+
+
+ do {
+
+ // calculation based on pcbs_occ_heartbeat_reg defination
+ pulses = req_time_us/64;
+ if (req_time_us % 64) {
+ pulses++;
+ }
+
+ // @dyd SW238882 fix
+ // overflow handling: HW only allows 8 bits in the field.
+ // set pulses to maximum allowed value in HW if it overflows,
+ // and o_time_us will feedback to caller this is done.
+ if (pulses > 0xFF) {
+ pulses = 0xFF;
+ //rc = HB_PULSES_OVERFLOW_PCBS;
+ //break;
+ }
+ // underflow case, pulses cannot be zero due to undefined HW behavior
+ if (pulses < 1) {
+ pulses = 1;
+ //rc = HB_PULSES_UNDERFLOW_PCBS;
+ //break;
+ }
+
+ pp1r.value = 0;
+ pp1r.fields.force_safe_mode = 1;
+ if (force) {
+ pp1r_addr = PCBS_PMGP1_REG_OR;
+ pp1r_data = pp1r.value;
+ } else {
+ pp1r_addr = PCBS_PMGP1_REG_AND;
+ pp1r_data = ~(pp1r.value);
+ }
+
+ pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG);
+ deconfig = pcdr.fields.core_chiplet_deconf_vector;
+
+ pohr.value = 0;
+ pohr.fields.occ_heartbeat_enable = enable;
+ pohr.fields.occ_heartbeat_time = pulses;
+ pohr.fields.occ_heartbeat_reg_addr_offset = reg_offset;
+
+ if (enable) {
+ *o_time_us = pulses * 64;
+ } else {
+ *o_time_us = 0;
+ }
+
+ do {
+ core_list = cores & (~deconfig);
+ for (core = 0; core < PGP_NCORES; core++, core_list <<= 1) {
+ if (core_list & 0x8000) {
+ // read modify write to preserve psafe
+ rc = getscom(CORE_CHIPLET_ADDRESS(PCBS_OCC_HEARTBEAT_REG,
+ core), &pohr.value);
+ if (rc) break;
+ pohr.fields.occ_heartbeat_enable = enable;
+ pohr.fields.occ_heartbeat_time = pulses;
+ pohr.fields.occ_heartbeat_reg_addr_offset = reg_offset;
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_OCC_HEARTBEAT_REG,
+ core), pohr.value);
+ if (rc) break;
+ rc = putscom(CORE_CHIPLET_ADDRESS(pp1r_addr, core),
+ pp1r_data);
+ if (rc) break;
+ }
+ }
+ } while (0);
+
+ }while(0);
+ return rc;
+}
diff --git a/src/lib/heartbeat.h b/src/lib/heartbeat.h
new file mode 100755
index 0000000..6c8616b
--- /dev/null
+++ b/src/lib/heartbeat.h
@@ -0,0 +1,46 @@
+#ifndef __HEARTBEAT_H__
+#define __HEARTBEAT_H__
+
+// $Id: heartbeat.h,v 1.3 2014/02/12 05:48:48 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/heartbeat.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file heartbeat.h
+/// \brief PgP PMC/PCBS heartbeat configuration procedures
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#define HB_INVALID_ARGUMENT_PMC 0x00482801
+#define HB_INVALID_ARGUMENT_PCBS 0x00482802
+#define HB_UNDERFLOW_DIVIDER_PMC 0x00482803
+#define HB_OVERFLOW_DIVIDER_PMC 0x00482804
+#define HB_OVERFLOW_PULSES_PMC 0x00482805
+#define HB_OVERFLOW_PULSES_PCBS 0x00482806
+#define HB_UNDERFLOW_PULSES_PCBS 0x00482807
+
+int
+pmc_hb_config(unsigned int enable,
+ unsigned int req_time_us,
+ unsigned int force,
+ unsigned int *o_time_us);
+
+int
+pcbs_hb_config(unsigned int enable,
+ ChipConfigCores cores,
+ uint32_t hb_reg,
+ unsigned int req_time_us,
+ unsigned int force,
+ unsigned int *o_time_us);
+
+
+
+#endif /* __ASEMBLER__ */
+
+
+#endif /* __HEARTBEAT_H__ */
diff --git a/src/lib/libfiles.mk b/src/lib/libfiles.mk
new file mode 100755
index 0000000..55773a4
--- /dev/null
+++ b/src/lib/libfiles.mk
@@ -0,0 +1,57 @@
+# $Id: libfiles.mk,v 1.5 2014/06/26 12:51:16 cmolsen Exp $
+# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/libfiles.mk,v $
+# @file libofiles.mk
+#
+# @brief mk for libssx.a object files
+#
+# @page ChangeLogs Change Logs
+# @section ofiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/11/2012 Makefile ODE support
+# @at007 alvinwan 05/25/2012 Use complex method for linking pore and PPC objects
+#
+# @endverbatim
+#
+##########################################################################
+# INCLUDES
+##########################################################################
+
+C-SOURCES = \
+ assert.c \
+ ctype.c \
+ ctype_table.c \
+ fgetc.c \
+ gpe_pba.c \
+ gpsm.c \
+ gpsm_dcm.c \
+ gpsm_init.c \
+ heartbeat.c \
+ memcpy.c \
+ memset.c \
+ pmc_dcm.c \
+ polling.c \
+ printf.c \
+ pstates.c \
+ puts.c \
+ simics_stdio.c \
+ special_wakeup.c \
+ sprintf.c \
+ ssx_dump.c \
+ ssx_io.c \
+ stdlib.c \
+ strcasecmp.c \
+ strdup.c \
+ string.c \
+ string_stream.c \
+ strtox.c \
+ time.c \
+ vrm.c \
+
+S-SOURCES = gpsm_dcm_fast_handler.S
+
+LIBSSX_OBJECTS = $(C-SOURCES:.c=.o) $(S-SOURCES:.S=.o)
diff --git a/src/lib/libgpefiles.mk b/src/lib/libgpefiles.mk
new file mode 100755
index 0000000..3f4efe1
--- /dev/null
+++ b/src/lib/libgpefiles.mk
@@ -0,0 +1,30 @@
+# $Id: libgpefiles.mk,v 1.3 2014/06/26 12:48:31 cmolsen Exp $
+# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/libgpefiles.mk,v $
+# @file libgpefiles.mk
+#
+# @brief mk for libssx.a gpe object files
+#
+# @page ChangeLogs Change Logs
+# @section libgpefiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @at007 alvinwan 05/25/2012 Use complex method for linking pore and PPC objects
+#
+# @endverbatim
+#
+##########################################################################
+# INCLUDES
+##########################################################################
+pS-SOURCES = \
+ gpe_control.pS \
+ gpe_data.pS \
+ gpe_scom.pS \
+ gpe_pba_pgas.pS
+
+LIB_PSOBJECTS = ${pS-SOURCES:.pS=.o}
+
+
diff --git a/src/lib/libssx.h b/src/lib/libssx.h
new file mode 100755
index 0000000..2bdffd4
--- /dev/null
+++ b/src/lib/libssx.h
@@ -0,0 +1,20 @@
+#ifndef __LIBSSX_H__
+#define __LIBSSX_H__
+
+// $Id: libssx.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/libssx.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file libssx.h
+/// \brief Header definitions with no other obvious home
+
+// Kernel panics
+
+#define ASSERTION_FAILURE 0x00542701
+#define ERROR_EXIT 0x00542702
+
+#endif // __LIBSSX_H__
diff --git a/src/lib/memcpy.c b/src/lib/memcpy.c
new file mode 100755
index 0000000..ab508ea
--- /dev/null
+++ b/src/lib/memcpy.c
@@ -0,0 +1,78 @@
+// $Id: memcpy.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/memcpy.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file memcpy.c
+/// \brief The memcpy() function
+
+#include "ssx.h"
+
+/// The memcpy() function copies \a n bytes from memory area \a src to memory
+/// area \a dest. The memory areas should not overlap. Use memmove(3) if the
+/// memory areas do overlap. The memcpy() function returns a pointer to dest.
+
+// This implementation should work well for both 32-bit and 64-bit machines,
+// assuming they can handle unaligned accesses. The implementation assumes that
+// it is better to avoid the loop setup overhead by a test and branch for
+// cases where loops can be bypassed.
+
+//void *
+//memcpy(void *dest, const void *src, size_t n)
+//{
+// while(n--) {
+// *dest++ = *src++;
+// }
+//
+// return s;
+//}
+
+void *
+memcpy(void *dest, const void *src, size_t n)
+{
+ uint8_t *d8, *s8;
+ uint64_t *d64, *s64;
+ size_t doublewords, octawords;
+
+ // First copy memory 32 bytes at a time.
+
+ d64 = (uint64_t *)dest;
+ s64 = (uint64_t *)src;
+ octawords = n / 32;
+ if (octawords) {
+ n -= octawords * 32;
+ while(octawords--) {
+ *d64++ = *s64++;
+ *d64++ = *s64++;
+ *d64++ = *s64++;
+ *d64++ = *s64++;
+ }
+ }
+
+ // Now set memory 8 bytes at a time. This might actually be better done
+ // explicitly rather than as a loop because the maximum loop count is 3
+ // here.
+
+ doublewords = n / 8;
+ if (doublewords) {
+ n -= doublewords * 8;
+ while (doublewords--) {
+ *d64++ = *s64++;
+ }
+ }
+
+ // Finally finish any remaining memory bytewise
+
+ if (n) {
+ d8 = (uint8_t *)d64;
+ s8 = (uint8_t *)s64;
+ while (n--) {
+ *d8++ = *s8++;
+ }
+ }
+
+ return dest;
+}
diff --git a/src/lib/memset.c b/src/lib/memset.c
new file mode 100755
index 0000000..98fdda2
--- /dev/null
+++ b/src/lib/memset.c
@@ -0,0 +1,118 @@
+// $Id: memset.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/memset.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file memset.c
+/// \brief The memset() function
+
+#include "ssx.h"
+
+/// The memset() function fills the first \a n bytes of the memory area
+/// pointed to by \a s with the constant byte \a c. The memset() function
+/// returns a pointer to the memory area \a s.
+///
+/// Note that memset() is optimized for setting large memory areas, and
+/// entails quite a bit of overhead to do this efficiently. If a memory area
+/// consists of a small number of basic data types (e.g., integers) it is
+/// probably more time-efficient to set the memory directly with a for loop
+/// (or unrolled loop).
+
+// This implementation should work well for both 32-bit and 64-bit
+// machines. The implementation assumes that it is worthwhile to align memory
+// pointers and do as much as possible using aligned addresses. [This doesn't
+// seem to matter on an X86 server processor, however]. It also assumes that
+// it is better to avoid the loop setup overhead by a test and branch for
+// cases where loops can be bypassed.
+
+//void *
+//memset(void *s, int c, size_t n)
+//{
+// uint8_t byte = (uint8_t)c;
+// uint8_t *p = (uint8_t *)s;
+//
+// while(n--) {
+// *p++ = byte;
+// }
+//
+// return s;
+//}
+
+void *
+memset(void *s, int c, size_t n)
+{
+ uint8_t byte, *p8;
+ uint32_t word;
+ uint64_t doubleword, *p64;
+ size_t bytes, doublewords, octawords;
+
+ // Any initial memory segment not aligned to an 8-byte boundary is set
+ // bytewise.
+
+ byte = (uint8_t)c;
+ p8 = (uint8_t *)s;
+
+ bytes = MIN(n, (unsigned long)s % 8);
+ if (bytes) {
+ n -= bytes;
+ while (bytes--) {
+ *p8++ = byte;
+ }
+ }
+
+ // Short requests are finshed here as well.
+
+ if (n < 8) {
+ while (n--) {
+ *p8++ = byte;
+ }
+ return s;
+ }
+
+ // We have at least 8 bytes of memory aligned on an 8-byte boundary. A
+ // doubleword initializer is created.
+
+ word = (byte << 8) | byte;
+ word = (word << 16) | word;
+ doubleword = ((uint64_t)word << 32) | word;
+
+ // First set memory 32 bytes at a time.
+
+ p64 = (uint64_t *)p8;
+ octawords = n / 32;
+ if (octawords) {
+ n -= octawords * 32;
+ while(octawords--) {
+ *p64++ = doubleword;
+ *p64++ = doubleword;
+ *p64++ = doubleword;
+ *p64++ = doubleword;
+ }
+ }
+
+ // Now set memory 8 bytes at a time. This might actually be better done
+ // explicitly rather than as a loop because the maximum loop count is 3
+ // here.
+
+ doublewords = n / 8;
+ if (doublewords) {
+ n -= doublewords * 8;
+ while (doublewords--) {
+ *p64++ = doubleword;
+ }
+ }
+
+ // Finally finish any remaining memory bytewise
+
+ p8 = (uint8_t *)p64;
+ if (n) {
+ while (n--) {
+ *p8++ = byte;
+ }
+ }
+
+ return s;
+}
diff --git a/src/lib/pgas.h b/src/lib/pgas.h
new file mode 100755
index 0000000..bdd3ba1
--- /dev/null
+++ b/src/lib/pgas.h
@@ -0,0 +1,1153 @@
+#ifndef __PGAS_H__
+#define __PGAS_H__
+
+#define __PGAS__
+
+// $Id: pgas.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pgas.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+// ** WARNING : This file is maintained as part of the OCC firmware. Do **
+// ** not edit this file in the PMX area, the hardware procedure area, **
+// ** or the PoreVe area as any changes will be lost. **
+
+/// \file pgas.h
+/// \brief Pore GAS
+///
+/// PGAS is documented in a seperate standalone document entitled <em> PGAS :
+/// PORE GAS (GNU Assembler) User's and Reference Manual </em>.
+///
+/// This file defines support macros for the GNU PORE assembler, and the PORE
+/// inline assembler and disassebler which follow the PGAS assembly syntax.
+/// If the compile swith PGAS_PPC is defined in the environment then pgas.h
+/// includes pgas_ppc.h which transforms a PowerPC assembler into an assembler
+/// for PORE.
+
+// These are the opcodes and mnemonics as defined by the PORE hardware
+// manual. Many of them will change names slightly in PGAS.
+
+#define PORE_OPCODE_NOP 0x0f
+#define PORE_OPCODE_WAIT 0x01
+#define PORE_OPCODE_TRAP 0x02
+#define PORE_OPCODE_HOOK 0x4f
+
+#define PORE_OPCODE_BRA 0x10
+#define PORE_OPCODE_BRAZ 0x12
+#define PORE_OPCODE_BRANZ 0x13
+#define PORE_OPCODE_BRAI 0x51
+#define PORE_OPCODE_BSR 0x14
+#define PORE_OPCODE_BRAD 0x1c
+#define PORE_OPCODE_BSRD 0x1d
+#define PORE_OPCODE_RET 0x15
+#define PORE_OPCODE_CMPBRA 0x56
+#define PORE_OPCODE_CMPNBRA 0x57
+#define PORE_OPCODE_CMPBSR 0x58
+#define PORE_OPCODE_LOOP 0x1f
+
+#define PORE_OPCODE_ANDI 0x60
+#define PORE_OPCODE_ORI 0x61
+#define PORE_OPCODE_XORI 0x62
+
+#define PORE_OPCODE_AND 0x25
+#define PORE_OPCODE_OR 0x26
+#define PORE_OPCODE_XOR 0x27
+
+#define PORE_OPCODE_ADD 0x23
+#define PORE_OPCODE_ADDI 0x24
+#define PORE_OPCODE_SUB 0x29
+#define PORE_OPCODE_SUBI 0x28
+#define PORE_OPCODE_NEG 0x2a
+
+#define PORE_OPCODE_COPY 0x2c
+#define PORE_OPCODE_ROL 0x2e
+
+#define PORE_OPCODE_LOAD20 0x30
+#define PORE_OPCODE_LOAD64 0x71
+#define PORE_OPCODE_SCR1RD 0x32
+#define PORE_OPCODE_SCR1RDA 0x73
+#define PORE_OPCODE_SCR2RD 0x36
+#define PORE_OPCODE_SCR2RDA 0x77
+#define PORE_OPCODE_WRI 0x78
+#define PORE_OPCODE_BS 0x74
+#define PORE_OPCODE_BC 0x75
+#define PORE_OPCODE_SCR1WR 0x39
+#define PORE_OPCODE_SCR2WR 0x3a
+#define PORE_OPCODE_SCAND 0x7c
+
+
+// These are the PGAS versions of the PORE opcodes used in the legacy PGAS_PPC
+// assembler and the current PORE inline assembler/disassembler.
+
+#define PGAS_OPCODE_NOP PORE_OPCODE_NOP
+#define PGAS_OPCODE_WAITS PORE_OPCODE_WAIT
+#define PGAS_OPCODE_TRAP PORE_OPCODE_TRAP
+#define PGAS_OPCODE_HOOKI PORE_OPCODE_HOOK
+
+#define PGAS_OPCODE_BRA PORE_OPCODE_BRA
+#define PGAS_OPCODE_BRAZ PORE_OPCODE_BRAZ
+#define PGAS_OPCODE_BRANZ PORE_OPCODE_BRANZ
+#define PGAS_OPCODE_BRAI PORE_OPCODE_BRAI
+#define PGAS_OPCODE_BSR PORE_OPCODE_BSR
+#define PGAS_OPCODE_BRAD PORE_OPCODE_BRAD
+#define PGAS_OPCODE_BSRD PORE_OPCODE_BSRD
+#define PGAS_OPCODE_RET PORE_OPCODE_RET
+#define PGAS_OPCODE_CMPIBRAEQ PORE_OPCODE_CMPBRA
+#define PGAS_OPCODE_CMPIBRANE PORE_OPCODE_CMPNBRA
+#define PGAS_OPCODE_CMPIBSREQ PORE_OPCODE_CMPBSR
+#define PGAS_OPCODE_LOOP PORE_OPCODE_LOOP
+
+#define PGAS_OPCODE_ANDI PORE_OPCODE_ANDI
+#define PGAS_OPCODE_ORI PORE_OPCODE_ORI
+#define PGAS_OPCODE_XORI PORE_OPCODE_XORI
+
+#define PGAS_OPCODE_AND PORE_OPCODE_AND
+#define PGAS_OPCODE_OR PORE_OPCODE_OR
+#define PGAS_OPCODE_XOR PORE_OPCODE_XOR
+
+#define PGAS_OPCODE_ADD PORE_OPCODE_ADD
+#define PGAS_OPCODE_ADDS PORE_OPCODE_ADDI
+#define PGAS_OPCODE_SUB PORE_OPCODE_SUB
+#define PGAS_OPCODE_SUBS PORE_OPCODE_SUBI
+#define PGAS_OPCODE_NEG PORE_OPCODE_NEG
+
+#define PGAS_OPCODE_MR PORE_OPCODE_COPY
+#define PGAS_OPCODE_ROLS PORE_OPCODE_ROL
+
+#define PGAS_OPCODE_LS PORE_OPCODE_LOAD20
+#define PGAS_OPCODE_LI PORE_OPCODE_LOAD64
+#define PGAS_OPCODE_LD0 PORE_OPCODE_SCR1RD /* Used by LD */
+#define PGAS_OPCODE_LD0ANDI PORE_OPCODE_SCR1RDA /* Used by LDANDI */
+#define PGAS_OPCODE_LD1 PORE_OPCODE_SCR2RD /* Used by LD */
+#define PGAS_OPCODE_LD1ANDI PORE_OPCODE_SCR2RDA /* Used by LDANDI */
+#define PGAS_OPCODE_STI PORE_OPCODE_WRI
+#define PGAS_OPCODE_STD0 PORE_OPCODE_SCR1WR /* Used by STD */
+#define PGAS_OPCODE_STD1 PORE_OPCODE_SCR2WR /* Used by STD */
+#define PGAS_OPCODE_SCAND PORE_OPCODE_SCAND
+
+#ifdef IGNORE_HW274735
+
+// BSI and BCI are normally redacted due to HW274735. See also pgas.h
+
+#define PGAS_OPCODE_BSI PORE_OPCODE_BS
+#define PGAS_OPCODE_BCI PORE_OPCODE_BC
+
+#endif // IGNORE_HW274735
+
+// These are the programmer-visible register names as defined by the PORE
+// hardware manual. All of these names (except the PC) appear differently in
+// the PGAS syntax, in some cases to reduce confusion, in other cases just to
+// have more traditional short mnemonics.
+
+#define PORE_REGISTER_PRV_BASE_ADDR0 0x0
+#define PORE_REGISTER_PRV_BASE_ADDR1 0x1
+#define PORE_REGISTER_OCI_BASE_ADDR0 0x2
+#define PORE_REGISTER_OCI_BASE_ADDR1 0x3
+#define PORE_REGISTER_SCRATCH0 0x4
+#define PORE_REGISTER_SCRATCH1 0x5
+#define PORE_REGISTER_SCRATCH2 0x6
+#define PORE_REGISTER_ERROR_MASK 0x7
+#define PORE_REGISTER_EXE_TRIGGER 0x9
+#define PORE_REGISTER_DATA0 0xa
+#define PORE_REGISTER_PC 0xe
+#define PORE_REGISTER_IBUF_ID 0xf
+
+
+// PgP IBUF_ID values
+
+#define PORE_ID_GPE0 0x00
+#define PORE_ID_GPE1 0x01
+#define PORE_ID_SLW 0x08
+#define PORE_ID_SBE 0x04
+
+
+// Condition Codes
+
+#define PORE_CC_UGT 0x8000
+#define PORE_CC_ULT 0x4000
+#define PORE_CC_SGT 0x2000
+#define PORE_CC_SLT 0x1000
+#define PORE_CC_C 0x0800
+#define PORE_CC_V 0x0400
+#define PORE_CC_N 0x0200
+#define PORE_CC_Z 0x0100
+
+
+// Memory Spaces
+
+#define PORE_SPACE_UNDEFINED 0xffff
+#define PORE_SPACE_OCI 0x8000
+#define PORE_SPACE_PNOR 0x800b
+#define PORE_SPACE_OTPROM 0x0001
+#define PORE_SPACE_SEEPROM 0x800c
+#define PORE_SPACE_PIBMEM 0x0008
+
+
+#ifdef __ASSEMBLER__
+
+////////////////////////////////////////////////////////////////////////////
+// PGAS Base Assembler Support
+////////////////////////////////////////////////////////////////////////////
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Condition Codes
+ //////////////////////////////////////////////////////////////////////
+
+ .set CC_UGT, PORE_CC_UGT
+ .set CC_ULT, PORE_CC_ULT
+ .set CC_SGT, PORE_CC_SGT
+ .set CC_SLT, PORE_CC_SLT
+ .set CC_C, PORE_CC_C
+ .set CC_V, PORE_CC_V
+ .set CC_N, PORE_CC_N
+ .set CC_Z, PORE_CC_Z
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Utility Macros
+ //////////////////////////////////////////////////////////////////////
+
+ // 'Undefine' PowerPC mnemonics to trap programming errors
+
+ .macro ..undefppc1, i
+ .ifnc \i, ignore
+ .macro \i, args:vararg
+ .error "This is a PowerPC opcode - NOT a PGAS opcode or extended mnemonic"
+ .endm
+ .endif
+ .endm
+
+ .macro .undefppc, i0, i1=ignore, i2=ignore, i3=ignore
+ ..undefppc1 \i0
+ ..undefppc1 \i1
+ ..undefppc1 \i2
+ ..undefppc1 \i3
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Argument Checking Macros
+ //////////////////////////////////////////////////////////////////////
+ //
+ // These macros remain in the final pgas.h file because 1) they are
+ // required for some PGAS pseudo-ops, and 2) to support robust
+ // assembler macro definitions.
+
+ // Check an unsigned immediate for size
+
+ .macro ..checku, x:req, bits:req, err="Unsigned value too large"
+
+ .if (((\bits) <= 0) || ((\bits) > 63))
+ .error "The number of bits must be in the range 0 < bits < 64"
+ .endif
+
+ .iflt (\x)
+ .error "An unsigned value is required here"
+ .endif
+
+ .ifgt ((\x) - (0xffffffffffffffff >> (64 - (\bits))))
+ .error "\err"
+ .endif
+
+ .endm
+
+ // Check unsigned 16/22-bit immediates for size
+ //
+ // In general, PGAS can check immediate values for size restrictions,
+ // but unfortunately is not able to check address offset immediates for
+ // range.
+
+ .macro ..check_u16, u16
+ ..checku (\u16), 16, "Unsigned immediate is larger than 16 bits"
+ .endm
+
+ .macro ..check_u24, u24
+ ..checku (\u24), 24, "Unsigned immediate is larger than 24 bits"
+ .endm
+
+ // Check a 16/20/22-bit signed immediate for size
+
+ .macro ..check_s16, s16
+ .iflt \s16
+ .iflt \s16 + 0x8000
+ .error "Immediate value too small for a signed 16-bit field"
+ .endif
+ .else
+ .ifgt \s16 - 0x7fff
+ .error "Immediate value too large for a signed 16-bit field"
+ .endif
+ .endif
+ .endm
+
+ .macro ..check_s20, s20
+ .iflt \s20
+ .iflt \s20 + 0x80000
+ .error "Immediate value too small for a signed 20-bit field"
+ .endif
+ .else
+ .ifgt \s20 - 0x7ffff
+ .error "Immediate value too large for a signed 20-bit field"
+ .endif
+ .endif
+ .endm
+
+ .macro ..check_s22, s22
+ .iflt \s22
+ .iflt \s22 + 0x200000
+ .error "Immediate value too small for a signed 22-bit field"
+ .endif
+ .else
+ .ifgt \s22 - 0x1fffff
+ .error "Immediate value too large for a signed 22-bit field"
+ .endif
+ .endif
+ .endm
+
+ // Check a putative SCOM address for bits 0 and 8:11 == 0.
+
+ .macro ..check_scom, address
+ .if ((\address) & 0x80f00000)
+ .error "Valid SCOM addresses must have bits 0 and 8:11 equal to 0."
+ .endif
+ .endm
+
+ // A register required to be D0
+
+ .macro ..d0, reg
+ .if (\reg != D0)
+ .error "Data register D0 is required here"
+ .endif
+ .endm
+
+ // A register pair required to be D0, D1 in order
+
+ .macro ..d0d1, reg1, reg2
+ .if (((\reg1) != D0) && ((\reg2) != D1))
+ .error "Register-Register ALU operations are only defined on the source pair D0, D1"
+ .endif
+ .endm
+
+ // A register pair required to be D0, D1 in any order
+ .macro ..dxdy, reg1, reg2, err="Expecting D0, D1 in either order"
+ .if !((((\reg1) == D0) && ((\reg2) == D1)) || \
+ (((\reg1) == D1) && ((\reg2) == D0)))
+ .error "\err"
+ .endif
+ .endm
+
+ // A register pair required to be A0, A1 in any order
+ .macro ..axay, reg1, reg2, err="Expecting A0, A1 in either order"
+ .if !((((\reg1) == A0) && ((\reg2) == A1)) || \
+ (((\reg1) == A1) && ((\reg2) == A0)))
+ .error "\err"
+ .endif
+ .endm
+
+ // A register pair required to be the same register
+
+ .macro ..same, dest, src
+ .if ((\dest) != (\src))
+ .error "PGAS requires the src and dest register of ADDS/SUBS to be explicit and identical"
+ .endif
+ .endm
+
+ // A "Data" register
+
+ .macro ..data, reg:req, err="Expecting a 'Data' register"
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .error "\err"
+ .endif
+ .endif
+ .endm
+
+ // An "Address" register
+
+ .macro ..address, reg:req, err=:"Expecting an 'Address' register"
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .error "\err"
+ .endif
+ .endif
+ .endm
+
+ // A "Pervasive Chiplet ID" register
+
+ .macro ..pervasive_chiplet_id, reg:req, err="Expecting a 'Pervasive Chiplet ID' register"
+ .if (\reg != P0)
+ .if (\reg != P1)
+ .error "\err"
+ .endif
+ .endif
+ .endm
+
+ // A "Branch Compare Data" register
+
+ .macro ..branch_compare_data, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != CTR)
+ .error "Expecting a 'Branch Compare Data' register"
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "LS Destination" register; Also the set for ADDS/SUBS
+
+ .macro ..ls_destination, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != P0)
+ .if (\reg != P1)
+ .if (\reg != CTR)
+ .error "Expecting an 'LS Destination' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "LI Destination" register
+
+ .macro ..li_destination, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != CTR)
+ .error "Expecting an 'LI Destination' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "LIA Destination" register
+
+ .macro ..lia_destination, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != TBAR)
+ .error "Expecting an 'LIA Destination' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "MR Source" register
+
+ .macro ..mr_source, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != P0)
+ .if (\reg != P1)
+ .if (\reg != CTR)
+ .if (\reg != PC)
+ .if (\reg != ETR)
+ .if (\reg != SPRG0)
+ .if (\reg != IFR)
+ .if (\reg != EMR)
+ .error "Expecting an 'MR Source' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "MR Destination" register
+
+ .macro ..mr_destination, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != P0)
+ .if (\reg != P1)
+ .if (\reg != CTR)
+ .if (\reg != PC)
+ .if (\reg != ETR)
+ .if (\reg != SPRG0)
+ .if (\reg != EMR)
+ .error "Expecting an 'MR Destination' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // PORE address spaces
+ //////////////////////////////////////////////////////////////////////
+
+ // The ..set_address_space pseudo-op defines the default address
+ // space. It must be defined in order to use BRAA, BRAIA, BSR and
+ // CMPIBSR. Pseudo-ops are provided to set the default space of the
+ // program. Note that code assembled for PNOR will also work in the
+ // OCI space in the Sleep/Winkle engine.
+
+ .macro ..set_default_space, s
+ ..check_u16 (\s)
+ .set _PGAS_DEFAULT_SPACE, (\s)
+ .endm
+
+ .macro ..check_default_space
+ .if (_PGAS_DEFAULT_SPACE == PORE_SPACE_UNDEFINED)
+ .error "The PGAS default address space has not been defined"
+ .endif
+ .endm
+
+ ..set_default_space PORE_SPACE_UNDEFINED
+
+ .macro .oci
+ ..set_default_space PORE_SPACE_OCI
+ .endm
+
+ .macro .pnor
+ ..set_default_space PORE_SPACE_PNOR
+ .endm
+
+ .macro .seeprom
+ ..set_default_space PORE_SPACE_SEEPROM
+ .endm
+
+ .macro .otprom
+ ..set_default_space PORE_SPACE_OTPROM
+ .endm
+
+ .macro .pibmem
+ ..set_default_space PORE_SPACE_PIBMEM
+#ifndef PGAS_PPC
+ .pibmem_port (PORE_SPACE_PIBMEM & 0xf)
+#else
+ // NB: PGAS_PPC does not support relocatable PIBMEM addressing
+#endif
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Address-Generation Pseudo Ops
+ //////////////////////////////////////////////////////////////////////
+
+ // .QUADA, .QUADIA
+
+ .macro .quada, offset:req
+ ..check_default_space
+ .long _PGAS_DEFAULT_SPACE
+ .long (\offset)
+ .endm
+
+ .macro .quadia, space:req, offset:req
+ ..check_u16 (\space)
+ .long (\space)
+ .long (\offset)
+ .endm
+
+ //////////////////////////////////////////////////////////////////////
+ // Bug workarounds
+ //////////////////////////////////////////////////////////////////////
+
+#ifndef IGNORE_HW274735
+
+ // HW274735 documents that BC and BS are broken for the PORE-GPE0/1
+ // pair. This bug is unfixed in POWER8, and by default we require BSI
+ // and BCI to be implemented as macros on all engines. For
+ // compatability we continue to require that dx == D0.
+
+ .macro bsi, dx:req, offset:req, base:req, imm:req
+ ..d0 (\dx)
+ ld D0, (\offset), (\base)
+ ori D0, D0, (\imm)
+ std D0, (\offset), (\base)
+ .endm
+
+ .macro bci, dx:req, offset:req, base:req, imm:req
+ ..d0 (\dx)
+ ldandi D0, (\offset), (\base), ~(\imm)
+ std D0, (\offset), (\base)
+ .endm
+
+#endif // IGNORE_HW274735
+
+ //////////////////////////////////////////////////////////////////////
+ // "A"- and "IA"-form Instructions
+ //////////////////////////////////////////////////////////////////////
+
+ // BRAA (Branch Address) is a 'long branch' to an address in the
+ // default memory space.
+
+ .macro braa, offset:req
+ braia _PGAS_DEFAULT_SPACE, (\offset)
+ .endm
+
+ // LA (Load Address) loads the full address of an address in the
+ // default memory space.
+
+ .macro la, dest:req, offset:req
+ lia (\dest), _PGAS_DEFAULT_SPACE, (\offset)
+ .endm
+
+ // STA (Store Address) stores the full address of an address in the
+ // default memory space.
+
+ .macro sta, mem_offset:req, base:req, addr_offset:req
+ stia (\mem_offset), (\base), _PGAS_DEFAULT_SPACE, (\addr_offset)
+ .endm
+
+ // BSRIA is a subroutine branch into another memory space. This has to
+ // be emulated by a local subroutine branch and a BRAIA.
+
+ .macro bsria, space:req, offset:req
+ bsr 27742f
+ bra 27743f
+27742:
+ braia (\space), (\offset)
+27743:
+ .endm
+
+
+////////////////////////////////////////////////////////////////////////////
+// Extended Mnemonics, Macros and Special Cases
+////////////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////
+ // TFB<c> - Test flags and branch conditionally
+ //////////////////////////////////////////////////////////////////////'
+
+ .macro ..tfb, dest, target, flags
+ ..data (\dest)
+ mr (\dest), IFR
+ andi (\dest), (\dest), (\flags)
+ branz (\dest), (\target)
+ .endm
+
+ .macro ..tfbn dest, target, flags
+ ..data (\dest)
+ mr (\dest), IFR
+ andi (\dest), (\dest), (\flags)
+ braz (\dest), (\target)
+ .endm
+
+ .macro tfbcs, dest:req, target:req
+ ..tfb (\dest), (\target), CC_C
+ .endm
+
+ .macro tfbcc, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_C
+ .endm
+
+ .macro tfbvs, dest:req, target:req
+ ..tfb (\dest), (\target), CC_V
+ .endm
+
+ .macro tfbvc, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_V
+ .endm
+
+ .macro tfbns, dest:req, target:req
+ ..tfb (\dest), (\target), CC_N
+ .endm
+
+ .macro tfbnc, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_N
+ .endm
+
+ .macro tfbeq, dest:req, target:req
+ ..tfb (\dest), (\target), CC_Z
+ .endm
+
+ .macro tfbne, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_Z
+ .endm
+
+ .macro tfbult, dest:req, target:req
+ ..tfb (\dest), (\target), CC_ULT
+ .endm
+
+ .macro tfbule, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_UGT
+ .endm
+
+ .macro tfbuge, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_ULT
+ .endm
+
+ .macro tfbugt, dest:req, target:req
+ ..tfb (\dest), (\target), CC_UGT
+ .endm
+
+ .macro tfbslt, dest:req, target:req
+ ..tfb (\dest), (\target), CC_SLT
+ .endm
+
+ .macro tfbsle, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_SGT
+ .endm
+
+ .macro tfbsge, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_SLT
+ .endm
+
+ .macro tfbsgt, dest:req, target:req
+ ..tfb (\dest), (\target), CC_SGT
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // TEB[N]<eng> - Test Engine and branch if [not] engine.
+ //////////////////////////////////////////////////////////////////////
+ //
+ // All but GPE0 use a 1-hot code.
+
+ .macro tebgpe0, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), 0xf
+ braz (\dest), (\target)
+ .endm
+
+ .macro tebgpe1, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_GPE1
+ branz (\dest), (\target)
+ .endm
+
+ .macro tebslw, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_SLW
+ branz (\dest), (\target)
+ .endm
+
+ .macro tebsbe, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_SBE
+ branz (\dest), (\target)
+ .endm
+
+
+ .macro tebngpe0, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), 0xf
+ branz (\dest), (\target)
+ .endm
+
+ .macro tebngpe1, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_GPE1
+ braz (\dest), (\target)
+ .endm
+
+ .macro tebnslw, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_SLW
+ braz (\dest), (\target)
+ .endm
+
+ .macro tebnsbe, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_SBE
+ braz (\dest), (\target)
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // EXTRPRC - Extract and right-justify the PIB/PCB return code
+ // TPRCB[N]Z - Test PIB return code and branch if [not] zero
+ // TPRCBGT - Test PIB return code and branch if greater-than
+ // TPRCBLE - Test PIB return code and branch if less-then or equal
+ //////////////////////////////////////////////////////////////////////
+ //
+ // To support cases where PORE code expects or must explicitly handle
+ // non-0 PIB return codes, the PIB return code and parity indication
+ // are stored in bits 32 (parity) and 33-35 (return code) of the IFR.
+ // These macros extract the four PIB/PCB status bits from the IFR and
+ // right-justifies them into the data register provided. For EXTRPRC
+ // that is the total function of the macro. The TPRCB[N]Z macros
+ // provide a simple non-destructive test and branch for zero (success)
+ // and non-zero (potential problem) codes after the extraction.
+ //
+ // In complex error handling scenarios one would typically compare the
+ // PIB return code against an upper-bound, e.g., the offline response
+ // (0x2), and then take further action. If the parity error bit is set
+ // then this would produce an aggregate "return code" higher than any
+ // that one would typically want to ignore. The TPRCBGT/TPRCBLE macros
+ // provide this function; however the test destroys the extracted
+ // return code so that if further analysis is required the code will
+ // need to be a extracted again.
+ //////////////////////////////////////////////////////////////////////
+
+ .macro extrprc, dest:req
+ ..data (\dest)
+ mr (\dest), IFR
+ extrdi (\dest), (\dest), 4, 32
+ .endm
+
+ .macro tprcbz, dest:req, target:req
+ extrprc (\dest)
+ braz (\dest), (\target)
+ .endm
+
+ .macro tprcbnz, dest:req, target:req
+ extrprc (\dest)
+ branz (\dest), (\target)
+ .endm
+
+ .macro tprcbgt, dest:req, target:req, bound:req
+ extrprc (\dest)
+ subs (\dest), (\dest), (\bound)
+ tfbugt (\dest), (\target)
+ .endm
+
+ .macro tprcble, dest:req, target:req, bound:req
+ extrprc (\dest)
+ subs (\dest), (\dest), (\bound)
+ tfbule (\dest), (\target)
+ .endm
+
+ //////////////////////////////////////////////////////////////////////
+ // LPCS - Load Pervasive Chiplet from Scom address
+ //////////////////////////////////////////////////////////////////////
+
+ .macro lpcs, dest:req, scom:req
+ ..pervasive_chiplet_id (\dest)
+ ..check_scom (\scom)
+ ls (\dest), (((\scom) >> 24) & 0x7f)
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Shift/Mask extended mnemonics
+ //////////////////////////////////////////////////////////////////////
+
+ // All of the 'dot-dot' macros assume that error and identity
+ // checking has been done on the arguments already.
+
+ // The initial register-register rotate. If the incoming shift amount
+ // is 0 then the instruction generated is a simple MR.
+
+ .macro ..rotlrr, ra, rs, sh
+
+ .if (\sh) >= 32
+ rols (\ra), (\rs), 32
+ ..rotlr (\ra), ((\sh) - 32)
+ .elseif (\sh) >= 16
+ rols (\ra), (\rs), 16
+ ..rotlr (\ra), ((\sh) - 16)
+ .elseif (\sh) >= 8
+ rols (\ra), (\rs), 8
+ ..rotlr (\ra), ((\sh) - 8)
+ .elseif (\sh) >= 4
+ rols (\ra), (\rs), 4
+ ..rotlr (\ra), ((\sh) - 4)
+ .elseif (\sh) >= 1
+ rols (\ra), (\rs), 1
+ ..rotlr (\ra), ((\sh) - 1)
+ .else
+ mr (\ra), (\rs)
+ .endif
+
+ .endm
+
+
+ // Subsequent rotation of the same register. The SH should never be 0
+ // here.
+
+ .macro ..rotlr, ra, sh
+
+ .if (\sh) >= 32
+ rols (\ra), (\ra), 32
+ ..rotlr (\ra), ((\sh) - 32)
+ .elseif (\sh) >= 16
+ rols (\ra), (\ra), 16
+ ..rotlr (\ra), ((\sh) - 16)
+ .elseif (\sh) >= 8
+ rols (\ra), (\ra), 8
+ ..rotlr (\ra), ((\sh) - 8)
+ .elseif (\sh) >= 4
+ rols (\ra), (\ra), 4
+ ..rotlr (\ra), ((\sh) - 4)
+ .elseif (\sh) >= 1
+ rols (\ra), (\ra), 1
+ ..rotlr (\ra), ((\sh) - 1)
+
+ .endif
+
+ .endm
+
+
+ // RLDINM RA, RS, SH, MB, ME
+ //
+ // Defined as if there were an equivalent PowerPC instruction. The
+ // 'word' forms of the PowerPC instructions and extended mnemonics are
+ // undefined in order to catch programming typos.
+
+ .undefppc rlwinm, extrwi, rotlwi, rotrwi
+ .undefppc slwi, srwi
+
+ .macro rldinm, ra:req, rs:req, sh:req, mb:req, me:req
+
+ .if ((\sh) < 0) || ((\sh) > 63)
+ .error "SH must be in the range 0..63"
+ .endif
+ .if ((\mb) < 0) || ((\mb) > 63)
+ .error "MB must be in the range 0..63"
+ .endif
+ .if ((\me) < 0) || ((\me) > 63)
+ .error "ME must be in the range 0..63"
+ .endif
+
+ .if (((\mb) == 0) && ((\me) == 63) || ((\me) == ((\mb) - 1)))
+
+ // The mask is effectively 0..63, i.e., no mask. This is a
+ // simple rotate.
+
+ ..rotlrr (\ra), (\rs), (\sh)
+
+ .else
+
+ // We need a mask step. However if SH == 0 and RA == RS we can
+ // bypass the rotate step.
+
+ .if ((\sh) != 0) || ((\ra) != (\rs))
+ ..rotlrr (\ra), (\rs), (\sh)
+ .endif
+ .if ((\mb) <= (\me))
+
+ // This is a straightforward masking operation with a
+ // single mask.
+
+ andi (\ra), (\ra), ((0xffffffffffffffff >> (\mb)) & (0xffffffffffffffff << (63 - (\me))))
+ .else
+
+ // This is a wrapped mask.
+ // It is created as 2 masks OR-ed together - 0-ME and MB-63
+
+ andi (\ra), (\ra), (((0xffffffffffffffff >> 0) & (0xffffffffffffffff << (63 - (\me)))) | ((0xffffffffffffffff >> (\mb)) & (0xffffffffffffffff << (63 - 63))))
+ .endif
+
+ .endif
+
+ .endm
+
+ // RLDINM Extended Mnemonics
+ //
+ // Defined as if they were equivalent to PowerPC 32-bit extended
+ // mnemonics
+
+ .macro extldi, ra:req, rs:req, n:req, b:req
+ .if ((\n) < 0)
+ .error "EXTLDI requires N > 0"
+ .endif
+ rldinm (\ra), (\rs), (\b), 0, ((\n) - 1)
+ .endm
+
+ .macro extrdi, ra:req, rs:req, n:req, b:req
+ .if ((\n) < 0)
+ .error "EXTRDI requires N > 0"
+ .endif
+ rldinm (\ra), (\rs), (((\b) + (\n)) % 64), (64 - (\n)), 63
+ .endm
+
+ .macro rotldi, ra:req, rs:req, n:req
+ rldinm (\ra), (\rs), (\n), 0, 63
+ .endm
+
+
+ .macro rotrdi, ra:req, rs:req, n:req
+ rldinm (\ra), (\rs), (64 - (\n)), 0, 63
+ .endm
+
+
+ .macro sldi, ra:req, rs:req, n:req
+ rldinm (\ra), (\rs), (\n), 0, (63 - (\n))
+ .endm
+
+
+ .macro srdi, ra:req, rs:req, n:req
+ rldinm (\ra), (\rs), (64 - (\n)), (\n), 63
+ .endm
+
+
+ // RLDIMI RA, RS, SH, MB, ME
+ //
+ // Defined as if there were an equivalent PowerPC instruction. The
+ // 'word' forms of the PowerPC instructions and extended mnemonics are
+ // undefined in order to catch programming typos.
+ //
+ // Note that unlike the PowerPC instructions, here RLDIMI must destroy
+ // RS by masking and shifting it, and RA and RS may not be the same
+ // register.
+
+ .undefppc rlwimi, inslwi, insrwi
+
+ .macro rldimi, ra:req, rs:req, sh:req, mb:req, me:req
+
+ ..dxdy (\ra), (\rs)
+
+ // SH error checks are done by rldinm
+
+ .if (((\mb) == 0) && ((\me) == 63) || ((\me) == ((\mb) - 1)))
+
+ // The mask is effectively 0..63, i.e., no mask. This is a
+ // simple rotate of RS into RA
+
+ rotldi (\ra), (\rs), (\sh)
+
+ .else
+
+ // Rotate RS and AND with mask
+
+ rldinm (\rs), (\rs), (\sh), (\mb), (\me)
+
+ // Mask out the significant bits of RS, clear that section of
+ // RA, and logical OR RS into RA
+
+ .if ((\mb) <= (\me))
+
+ // This is a straightforward masking operation with a
+ // single mask.
+
+ andi (\ra), (\ra), \
+ (~((0xffffffffffffffff >> (\mb)) & (0xffffffffffffffff << (63 - (\me)))))
+ .else
+
+ // This is a wrapped mask.
+ // It is created as 2 masks OR-ed together - 0-ME and MB-63
+
+ andi (\ra), (\ra), \
+ (~(((0xffffffffffffffff >> 0) & (0xffffffffffffffff << (63 - (\me)))) | \
+ ((0xffffffffffffffff >> (\mb)) & (0xffffffffffffffff << (63 - 63)))))
+ .endif
+
+ or (\ra), D0, D1
+
+ .endif
+
+ .endm
+
+ // RLDIMI Extended Mnemonics
+ //
+ // Defined as if they were equivalent to PowerPC 32-bit extended
+ // mnemonics
+
+ .macro insldi, ra:req, rs:req, n:req, b:req
+ .if ((\n) < 0)
+ .error "INSLDI requires N > 0"
+ .endif
+ rldimi (\ra), (\rs), (64 - (\b)), (\b), ((\b) + (\n) - 1)
+ .endm
+
+ .macro insrdi, ra:req, rs:req, n:req, b:req
+ .if ((\n) < 0)
+ .error "INSRDI requires N > 0"
+ .endif
+ rldimi (\ra), (\rs), (64 - (\b) - (\n)), (\b), ((\b) + (\n) - 1)
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // .HOOK
+ //////////////////////////////////////////////////////////////////////
+
+ // The PoreVe (PORE Virtual Environment) is a PORE simulation
+ // environment that allows the programmer to embed C/C++ code into the
+ // PORE assembler source code, and arranges for the C/C++ code to be
+ // executed in-line with the PORE assembly code. Instances of the
+ // .hook macro are inserted into the assembler input by the
+ // hook_extractor script, to mark the locations where hooks are
+ // present. The hook reference is a string that combines the source
+ // file name with an index number to uniquely identify the hook.
+ //
+ // .hook <file name>_<sequence number>
+ //
+ // The .hook macro marks the location of each hook in the relocatable
+ // binaries with special symbols. The symbol name includes the hook
+ // reference, which is used to locate the hook in the HookManager
+ // symbol table. Because hooks can be defined in macros, a hook that
+ // appears once in a source file may appear multiple times in the
+ // final binary. For this reason each hook must also be tagged with a
+ // unique index number to avoid symbol name collisions. The
+ // complexity of the .hook macro is due to the necessity to decode a
+ // dynamic symbol value (_PGAS_HOOK_INDEX) into its binary string form
+ // to create the unique symbol name. The final hook symbol has the
+ // form:
+ //
+ // __hook__<unique>_<reference>
+ //
+ // where <unique> is a binary string. It is then straightforward to
+ // locate these symbols in the 'nm' output of the final link and
+ // create a map of final addresses to the hook routine to call (the
+ // <reference>) before executing the instruction at that address.
+ //
+ // Note: The maximum nesting depth of the recursive ..hook_helper
+ // macro is log2(index), and the assembler supports nesting of at
+ // least 32 which is much more than sufficient.
+
+ .set _PGAS_HOOK_INDEX, 0
+
+ .macro .hook, reference:req
+ .set _PGAS_HOOK_INDEX, (_PGAS_HOOK_INDEX + 1)
+ ..hook_helper _PGAS_HOOK_INDEX, "", \reference
+ .endm
+
+ .macro ..hook_helper, index, unique, reference
+ .ifeq \index
+ __hook__\unique\()_\reference\():
+ .elseif (\index % 2)
+ ..hook_helper (\index / 2), 1\unique, \reference
+ .else
+ ..hook_helper (\index / 2), 0\unique, \reference
+ .endif
+ .endm
+
+
+////////////////////////////////////////////////////////////////////////////
+// Help for Conversion from Old to New PGAS syntax
+////////////////////////////////////////////////////////////////////////////
+
+ .macro loadp, arg:vararg
+ .error "PGAS now implements 'lpcs' rather then 'loadp'"
+ .endm
+
+ .macro loadx, arg:vararg
+ .error "PGAS now implements 'la' rather than 'loadx'"
+ .endm
+
+#endif // __ASSEMBLER__
+
+#ifdef PGAS_PPC
+#include "pgas_ppc.h"
+#endif
+
+#endif // __PGAS_H__
diff --git a/src/lib/pgas_ppc.h b/src/lib/pgas_ppc.h
new file mode 100755
index 0000000..6771e4b
--- /dev/null
+++ b/src/lib/pgas_ppc.h
@@ -0,0 +1,529 @@
+#ifndef __PGAS_PPC_H__
+#define __PGAS_PPC_H__
+
+// $Id: pgas_ppc.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pgas_ppc.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+// ** WARNING : This file is maintained as part of the OCC firmware. Do **
+// ** not edit this file in the PMX area, the hardware procedure area, **
+// ** or the PoreVe area as any changes will be lost. **
+
+/// \file pgas_ppc.h
+/// \brief Legacy PGAS assembler implemented as PowerPC assembler macros.
+///
+/// PGAS is documented in a seperate standalone document entitled <em> PGAS :
+/// PORE GAS (GNU Assembler) User's and Reference Manual </em>.
+///
+/// This file contains the legacy PGAS assembler, which was first implemented
+/// as this set of assembler macros for the PowerPC assembler. This file is
+/// included into pgas.h if the compile switch PGAS_PPC is defined in the
+/// compile environment.
+
+#ifdef __ASSEMBLER__
+
+////////////////////////////////////////////////////////////////////////////
+// PGAS Base Assembler
+////////////////////////////////////////////////////////////////////////////
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Symbolic Register Mnemonics
+ //////////////////////////////////////////////////////////////////////
+ //
+ // PGAS uses gas symbols for register mnemonics so that they will
+ // appear as-is in assembler listings, but we can still do arithmetic
+ // on the mnemonics in the PGAS macros.
+
+ .set P0, PORE_REGISTER_PRV_BASE_ADDR0
+ .set P1, PORE_REGISTER_PRV_BASE_ADDR1
+ .set A0, PORE_REGISTER_OCI_BASE_ADDR0
+ .set A1, PORE_REGISTER_OCI_BASE_ADDR1
+ .set CTR, PORE_REGISTER_SCRATCH0
+ .set D0, PORE_REGISTER_SCRATCH1
+ .set D1, PORE_REGISTER_SCRATCH2
+ .set EMR, PORE_REGISTER_ERROR_MASK
+ .set ETR, PORE_REGISTER_EXE_TRIGGER
+ .set SPRG0, PORE_REGISTER_DATA0
+ .set PC, PORE_REGISTER_PC
+ .set IFR, PORE_REGISTER_IBUF_ID
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Core Instruction Set
+ //////////////////////////////////////////////////////////////////////
+
+ // The final construction of an instruction word. The opcode is a
+ // 7-bit value and the operand is always a 24-bit value. Note that the
+ // parity bit is always 0.
+
+ .macro ..instruction, opcode, operand
+ .long (\opcode << 25) | (\operand)
+ .endm
+
+ // NOP, TRAP, RET
+
+ .macro nop
+ ..instruction PGAS_OPCODE_NOP, 0
+ .endm
+
+ .macro trap
+ ..instruction PGAS_OPCODE_TRAP, 0
+ .endm
+
+ .macro ret
+ ..instruction PGAS_OPCODE_RET, 0
+ .endm
+
+ // WAITS, HALT, HOOKI
+
+ .macro waits, u24:req
+ ..check_u24 (\u24)
+ .if ((\u24) == 0)
+ .error "PGAS does not allow WAITS 0; Use HALT if the intention is to halt"
+ .endif
+ ..instruction PGAS_OPCODE_WAITS, (\u24)
+ .endm
+
+ .macro halt
+ ..instruction PGAS_OPCODE_WAITS, 0
+ .endm
+
+ .macro hooki, u24:req, imm:req
+ ..check_u24 (\u24)
+ ..instruction PGAS_OPCODE_HOOKI, (\u24)
+ .quad (\imm)
+ .endm
+
+ .macro wait, args:vararg
+ .error "PGAS implements the 'waits' mnemonic instead of PORE 'wait'"
+ .endm
+
+ .macro hook, args:vararg
+ .error "PGAS implements the 'hooki' mnemonic instead of PORE 'hook'"
+ .endm
+
+ // BRA, LOOP
+ //
+ // Note that all branch offsets in PORE are WORD offsets, so the byte
+ // offsets computed by the underlying assembler need to be divided by
+ // 4. Unfortunately PGAS is not able to check whether the offsets fit
+ // in the allowed space.
+
+ .macro ..bra, opcode, target
+ ..instruction \opcode, ((((\target) - $) / 4) & 0xffffff)
+ .endm
+
+ .macro bra, target:req
+ ..bra PGAS_OPCODE_BRA, (\target)
+ .endm
+
+ .macro loop, target:req
+ ..bra PGAS_OPCODE_LOOP, (\target)
+ .endm
+
+ // BRAZ, BRANZ
+
+ .macro ..brac, opcode, src, target
+ ..branch_compare_data (\src)
+ ..instruction \opcode, ((\src << 20) | ((((\target) - $) / 4) & 0xfffff))
+ .endm
+
+ .macro braz, src:req, target:req
+ ..brac PGAS_OPCODE_BRAZ, (\src), (\target)
+ .endm
+
+ .macro branz, src:req, target:req
+ ..brac PGAS_OPCODE_BRANZ, (\src), (\target)
+ .endm
+
+ // CMPIBRAEQ, CMPIBRANE
+
+ .macro ..cmpibra, opcode, src, target, imm
+ ..d0 (\src)
+ ..instruction \opcode, ((((\target) - $) / 4) & 0xffffff)
+ .quad (\imm)
+ .endm
+
+ .macro cmpibraeq, src:req, target:req, imm:req
+ ..cmpibra PGAS_OPCODE_CMPIBRAEQ, (\src), (\target), (\imm)
+ .endm
+
+ .macro cmpibrane, src:req, target:req, imm:req
+ ..cmpibra PGAS_OPCODE_CMPIBRANE, (\src), (\target), (\imm)
+ .endm
+
+ .macro cmpbra, args:vararg
+ .error "PGAS implements the 'cmpibraeq' mnemonic instead of PORE 'cmpbra'"
+ .endm
+
+ .macro cmpnbra, args:vararg
+ .error "PGAS implements the 'cmpibrane' mnemonic instead of PORE 'cmpnbra'"
+ .endm
+
+ // BRAD, BSRD
+
+ .macro ..brad, opcode, src
+ ..data (\src)
+ ..instruction \opcode, ((\src) << 20)
+ .endm
+
+ .macro brad, src:req
+ ..brad PGAS_OPCODE_BRAD, (\src)
+ .endm
+
+ .macro bsrd, src:req
+ ..brad PGAS_OPCODE_BSRD, (\src)
+ .endm
+
+ // ANDI, ORI, XORI
+
+ .macro ..ilogic, opcode, dest, src, imm
+ ..data (\dest)
+ ..data (\src)
+ ..instruction \opcode, (((\dest) << 20) | ((\src) << 16))
+ .quad \imm
+ .endm
+
+ .macro andi, dest:req, src:req, imm:req
+ ..ilogic PGAS_OPCODE_ANDI, (\dest), (\src), (\imm)
+ .endm
+
+ .macro ori, dest:req, src:req, imm:req
+ ..ilogic PGAS_OPCODE_ORI, (\dest), (\src), (\imm)
+ .endm
+
+ .macro xori, dest:req, src:req, imm:req
+ ..ilogic PGAS_OPCODE_XORI, (\dest), (\src), (\imm)
+ .endm
+
+ // AND, OR, XOR, ADD, SUB
+
+ .macro ..alurr, opcode, dest, src1, src2
+ ..data (\dest)
+ ..d0d1 (\src1), (\src2)
+ ..instruction \opcode, ((\dest) << 20)
+ .endm
+
+ .macro and, dest:req, src1:req, src2:req
+ ..alurr PGAS_OPCODE_AND, (\dest), (\src1), (\src2)
+ .endm
+
+ .macro or, dest:req, src1:req, src2:req
+ ..alurr PGAS_OPCODE_OR, (\dest), (\src1), (\src2)
+ .endm
+
+ .macro xor, dest:req, src1:req, src2:req
+ ..alurr PGAS_OPCODE_XOR, (\dest), (\src1), (\src2)
+ .endm
+
+ .macro add, dest:req, src1:req, src2:req
+ ..alurr PGAS_OPCODE_ADD, (\dest), (\src1), (\src2)
+ .endm
+
+ .macro sub, dest:req, src1:req, src2:req
+ ..alurr PGAS_OPCODE_SUB, (\dest), (\src1), (\src2)
+ .endm
+
+ // ADDS, SUBS
+
+ .macro ..inc, opcode, dest, src, short
+ ..check_s16 (\short)
+ ..ls_destination (\dest)
+ ..same (\dest), (\src)
+ ..instruction (\opcode), (((\dest) << 20) | ((\short) & 0xffff))
+ .endm
+
+ .macro adds, dest:req, src:req, short:req
+ ..inc PGAS_OPCODE_ADDS, (\dest), (\src), (\short)
+ .endm
+
+ .macro subs, dest:req, src:req, short:req
+ ..inc PGAS_OPCODE_SUBS, (\dest), (\src), (\short)
+ .endm
+
+ .macro addi, args:vararg
+ .error "PGAS implements the 'adds' mnemonic instead of PORE 'addi'"
+ .endm
+
+ .macro subi, args:vararg
+ .error "PGAS implements the 'subs' mnemonic instead of PORE 'subi'"
+ .endm
+
+ // NEG
+
+ .macro neg, dest:req, src:req
+ ..data (\dest)
+ ..data (\src)
+ ..instruction PGAS_OPCODE_NEG, (((\dest) << 20) | ((\src) << 16))
+ .endm
+
+ // MR
+
+ .macro mr, dest:req, src:req
+ ..mr_destination (\dest)
+ ..mr_source (\src)
+ ..instruction PGAS_OPCODE_MR, (((\dest) << 20) | ((\src) << 16))
+ .endm
+
+ .macro copy, args:vararg
+ .error "PGAS implents the 'mr' mnemonic instead of PORE 'copy'"
+ .endm
+
+ // ROLS
+
+ .macro rols, dest:req, src:req, short:req
+ ..data (\dest)
+ ..data (\src)
+ .if ((\short) != 1)
+ .if ((\short) != 4)
+ .if ((\short) != 8)
+ .if ((\short) != 16)
+ .if ((\short) != 32)
+ .error "The legal ROLS shift amounts are 1, 4, 8, 16 and 32"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ ..instruction PGAS_OPCODE_ROLS, (((\dest) << 20) | ((\src) << 16) | (\short))
+ .endm
+
+ .macro rol, args:vararg
+ .error "PGAS implements the 'rols' mnemonic instead of PORE 'rol'"
+ .endm
+
+ // LS
+
+ .macro ls, dest:req, short:req
+ ..ls_destination (\dest)
+ ..check_s20 (\short)
+ ..instruction PGAS_OPCODE_LS, (((\dest) << 20) | ((\short) & 0xfffff))
+ .endm
+
+ .macro load20, args:vararg
+ .error "PGAS implements the 'ls' mnemonic instead of PORE 'load20'"
+ .endm
+
+ // LI, LIA
+
+ .macro ..li, dest:req
+ ..li_destination (\dest)
+ ..instruction PGAS_OPCODE_LI, ((\dest) << 20)
+ .endm
+
+ .macro li, dest:req, imm:req
+ ..li (\dest)
+ .quad (\imm)
+ .endm
+
+ .macro lia, dest:req, space:req, offset:req
+ ..lia_destination (\dest)
+ ..li (\dest)
+ .quadia (\space), (\offset)
+ .endm
+
+ .macro load64, args:vararg
+ .error "PGAS implements the 'li' mnemonic instead of PORE 'load64'"
+ .endm
+
+ // LD, LDANDI, STD, STI, STIA, BSI, BCI
+ //
+ // For LD, LDANDI, and STD, PGAS does not expose the underlying
+ // register-specific opcodes but only provides the general form.
+ //
+ // The base register is used to determine if this is a load/store from
+ // the pervasive or memory address spaces. For memory space accesses
+ // the offset is a 22-bit unsigned value, and the final ima24 is
+ //
+ // 1<reg 0/1><offset>
+ //
+ // PGAS will not assemble relocatable offsets, and checks that offsets
+ // fit in 24 bits.
+ //
+ // For pervasive accesses, it is assumed that the offset provided is a
+ // 32-bit SCOM address. Here the final ima24 is
+ //
+ // 0<reg 0/1>00<port><local_address>
+ //
+ // PGAS checks that the 32-bit SCOM address looks like a SCOM address
+ // in that SCOM adresses are required to have bits 0 and 8:11 == 0.
+ //
+ // Note that memory and pervasive base registers use a 0/1 encoding
+ // here, not the 4-bit encoding used elsewhere in the ISA. The bit
+ // appearing in the instruction is the low-order bit of the register
+ // encoding.
+
+ .macro ..pervasive_ima24, opcode, offset, base
+ ..check_scom (\offset)
+ ..instruction (\opcode), ((((\base) % 2) << 22) | ((\offset) & 0x3fffff))
+ .endm
+
+ .macro ..memory_ima24, opcode, offset, base
+ ..check_u24 (\offset)
+ .if ((\offset) % 8)
+ .error "The memory space offset is not a multiple of 8 - assumed alignment error"
+ .endif
+ ..instruction (\opcode), (0x800000 | (((\base) % 2) << 22) | ((\offset) & 0x3fffff))
+ .endm
+
+ .macro ..ima24, opcode, offset, base
+ .if ((\base == P0) || ((\base == P1)))
+ ..pervasive_ima24 (\opcode), (\offset), (\base)
+ .elseif ((\base == A0) || ((\base == A1)))
+ ..memory_ima24 (\opcode), (\offset), (\base)
+ .else
+ .error "Expecting either a 'Pervasive Chiplet ID' or an 'Address' register"
+ .endif
+ .endm
+
+ .macro ..ima24_select, opcode0, opcode1, dest, offset, base
+ ..data (\dest)
+ .if ((\dest) == D0)
+ ..ima24 (\opcode0), (\offset), (\base)
+ .else
+ ..ima24 (\opcode1), (\offset), (\base)
+ .endif
+ .endm
+
+ .macro ld, dest:req, offset:req, base:req
+ ..ima24_select PGAS_OPCODE_LD0, PGAS_OPCODE_LD1, (\dest), (\offset), (\base)
+ .endm
+
+ .macro ldandi, dest:req, offset:req, base:req, imm:req
+ ..ima24_select PGAS_OPCODE_LD0ANDI, PGAS_OPCODE_LD1ANDI, (\dest), (\offset), (\base)
+ .quad (\imm)
+ .endm
+
+ .macro std, dest:req, offset:req, base:req
+ ..ima24_select PGAS_OPCODE_STD0, PGAS_OPCODE_STD1, (\dest), (\offset), (\base)
+ .endm
+
+ .macro sti, offset:req, base:req, imm:req
+ ..ima24 PGAS_OPCODE_STI, (\offset), (\base)
+ .quad (\imm)
+ .endm
+
+ .macro stia, offset:req, base:req, space:req, addr:req
+ ..ima24 PGAS_OPCODE_STI, (\offset), (\base)
+ .quadia (\space), (\addr)
+ .endm
+
+ .macro ..bsi, opcode, dest, offset, base, imm
+ ..d0 (\dest)
+ ..ima24 (\opcode), (\offset), (\base)
+ .quad (\imm)
+ .endm
+
+#ifdef IGNORE_HW274735
+
+ // BSI and BCI are normally redacted due to HW274735. See also pgas.h
+
+ .macro bsi, dest:req, offset:req, base:req, imm:req
+ ..bsi PGAS_OPCODE_BSI, (\dest), (\offset), (\base), (\imm)
+ .endm
+
+ .macro bci, dest:req, offset:req, base:req, imm:req
+ ..bsi PGAS_OPCODE_BCI, (\dest), (\offset), (\base), (\imm)
+ .endm
+
+#endif // IGNORE_HW274735
+
+ .macro scr1rd, args:vararg
+ .error "PGAS implements the 'ld' mnemonic instead of the PORE 'scr1rd'"
+ .endm
+
+ .macro scr2rd, args:vararg
+ .error "PGAS implements the 'ld' mnemonic instead of the PORE 'scr2rd'"
+ .endm
+
+ .macro scr1rda, args:vararg
+ .error "PGAS implements the 'ldandi' mnemonic instead of the PORE 'scr1rda'"
+ .endm
+
+ .macro scr2rda, args:vararg
+ .error "PGAS implements the 'ldandi' mnemonic instead of the PORE 'scr2rda'"
+ .endm
+
+ .macro scr1wr, args:vararg
+ .error "PGAS implements the 'std' mnemonic instead of the PORE 'scr1wr'"
+ .endm
+
+ .macro scr2wr, args:vararg
+ .error "PGAS implements the 'std' mnemonic instead of the PORE 'scr2wr'"
+ .endm
+
+ .macro wri, args:vararg
+ .error "PGAS implements the 'sti' mnemonic instead of the PORE 'wri'"
+ .endm
+
+ .macro bs, args:vararg
+ .error "PGAS implements the 'bsi' mnemonic instead of the PORE 'bs'"
+ .endm
+
+ .macro bc, args:vararg
+ .error "PGAS implements the 'bci' mnemonic instead of the PORE 'bc'"
+ .endm
+
+ // SCAND
+ //
+ // The 24-bit operand here is
+ //
+ // <update><capture>000000<length>
+
+ .macro scand, update:req, capture:req, length:req, select:req, offset:req
+ .if (((\update) != 0) && ((\update) != 1))
+ .error "SCAND requires a binary value for 'update'"
+ .endif
+ .if (((\capture) != 0) && ((\capture) != 1))
+ .error "SCAND requires a binary value for 'capture'"
+ .endif
+ ..check_u16 (\length)
+ ..instruction PGAS_OPCODE_SCAND, ((\update << 23) | (\capture << 22) | (\length))
+ .long (\select)
+ .long (\offset)
+ .endm
+
+ // BRAIA, BSR, CMPIBSREQ
+ //
+ // In order to support separate compilation in PGAS programs being
+ // linked with the PowerPC linker it is necessary to implement BSR and
+ // CMPIBSREQ in terms of BRAIA. These instructions require that the
+ // default address space have been defined. The BSR instructions
+ // first take a short local subroutine branch to create a stack frame,
+ // then use BRAIA to branch to the (relocatable) target address. The
+ // return from the subroutine then branches around the BRAIA to
+ // complete the sequence.
+
+ .macro braia, space:req, offset:req
+ ..instruction PGAS_OPCODE_BRAI, 0
+ .quadia (\space), (\offset)
+ .endm
+
+ .macro ..bsr, target
+ ..bra PGAS_OPCODE_BSR, (\target)
+ .endm
+
+ .macro bsr, target:req
+ ..check_default_space
+ ..bsr (. + 8)
+ bra (. + 16)
+ braia _PGAS_DEFAULT_SPACE, (\target)
+ .endm
+
+ .macro cmpibsreq, src:req, target:req, imm:req
+ ..d0 (\src)
+ ..check_default_space
+ cmpibrane (\src), (. + 32), (\imm)
+ ..bsr (. + 8)
+ bra (. + 16)
+ braia _PGAS_DEFAULT_SPACE, (\target)
+ .endm
+
+#endif // __ASSEMBLER__
+
+#endif // __PGAS_PPC_H__
diff --git a/src/lib/pgp_config.h b/src/lib/pgp_config.h
new file mode 100755
index 0000000..f4041d4
--- /dev/null
+++ b/src/lib/pgp_config.h
@@ -0,0 +1,108 @@
+#ifndef __PGP_CONFIG_H__
+#define __PGP_CONFIG_H__
+
+// $Id: pgp_config.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pgp_config.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_config.h
+/// \brief Chip configuration data structures for PgP OCC procedures
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/// A bitmask defining a chip configuration
+///
+/// Since we are using the conventional big-endian notation, any use of these
+/// bitmasks requires that the data being tested is of this type - otherwise
+/// the masks won't work.
+///
+/// Layout:
+///
+/// Bits 0:15 - Core chiplet 0..15 is configured
+/// Bits 16:23 - MCS 0..7 is configured
+/// Bits 24:31 - Centaur 0..7 is configured
+
+typedef uint64_t ChipConfig;
+typedef uint16_t ChipConfigCores;
+typedef uint8_t ChipConfigMcs;
+typedef uint8_t ChipConfigCentaur;
+
+
+/// Convert a ChipConfig into a mask suitable for use as the 32-bit chiplet
+/// mask argument of a PORE wakeup program.
+
+static inline uint32_t
+pore_exe_mask(ChipConfig config)
+{
+ return (uint32_t)((config >> 32) & 0xffff0000);
+}
+
+/// Left justify and mask core chiplet configuration into a uint32_t
+
+static inline uint32_t
+left_justify_core_config(ChipConfig config)
+{
+ return (uint32_t)((config >> 32) & 0xffff0000);
+}
+
+/// Left justify and mask MCS configuration into a uint32_t
+
+static inline uint32_t
+left_justify_mcs_config(ChipConfig config)
+{
+ return (uint32_t)((config >> 16) & 0xff000000);
+}
+
+/// Left justify and mask Centaur configuration into a uint32_t
+
+static inline uint32_t
+left_justify_centaur_config(ChipConfig config)
+{
+ return (uint32_t)((config >> 8) & 0xff000000);
+}
+
+#endif // __ASSEMBLER__
+
+
+#define CHIP_CONFIG_CORE_BASE 0
+#define CHIP_CONFIG_CORE(n) \
+ ((0x8000000000000000ull >> CHIP_CONFIG_CORE_BASE) >> (n))
+
+#define CHIP_CONFIG_MCS_BASE 16
+#define CHIP_CONFIG_MCS(n) \
+ ((0x8000000000000000ull >> CHIP_CONFIG_MCS_BASE) >> (n))
+
+#define CHIP_CONFIG_CENTAUR_BASE 24
+#define CHIP_CONFIG_CENTAUR(n) \
+ ((0x8000000000000000ull >> CHIP_CONFIG_CENTAUR_BASE) >> (n))
+
+
+// PGAS macros to left justify configuration groups, allowing each member to
+// be tested in a loop that rotates the data (d) register left on each loop,
+// assuming standard big-endian bit assignments. The macros mask off all other
+// configuration bits so the destination register can also be tested for
+// 0/non-0 to determine if any of a configuration class are selected.
+
+#ifdef __PGAS__
+
+ .macro left_justify_core_config, d
+ extldi (\d), (\d), PGP_NCORES, CHIP_CONFIG_CORE_BASE
+ .endm
+
+ .macro left_justify_mcs_config, d
+ extldi (\d), (\d), PGP_NMCS, CHIP_CONFIG_MCS_BASE
+ .endm
+
+ .macro left_justify_centaur_config, d
+ extldi (\d), (\d), PGP_NCENTAUR, CHIP_CONFIG_CENTAUR_BASE
+ .endm
+
+#endif /* __PGAS__ */
+
+#endif /* __PGP_CONFIG_H__ */
diff --git a/src/lib/pmc_dcm.c b/src/lib/pmc_dcm.c
new file mode 100755
index 0000000..a0f7d82
--- /dev/null
+++ b/src/lib/pmc_dcm.c
@@ -0,0 +1,425 @@
+// $Id: pmc_dcm.c,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pmc_dcm.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pmc_dcm.c
+/// \brief Genertic PMC Interhchip Communication Mechanism
+
+#include "ssx.h"
+#include "pmc_dcm.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Low-level PMC-DCM Interfaces
+////////////////////////////////////////////////////////////////////////////
+
+/// Non-blocking transmission of a packet over the PMC-DCM interface
+///
+/// Note: Locking/synchronization of the PMC-DCM interface is the
+/// responsibility of the application.
+///
+/// \param hwPacket A PmcDcmPacket structure to be sent via PMC interchip link
+/// This argument is provided by the caller and passed in as reference.
+///
+/// \code
+/// hwPacket:
+///
+/// cmd_code | cmd_ext | payload 0 | payload 1 | ECC
+/// [0:3] | [4:7] | [8:15] | [16:23] | [24:31]
+///
+/// cmd_code:
+/// PMC_IC_GPA_CC | 1 | 0b0001 | Global PState Actual | Master to Slave
+/// PMC_IC_GPA_ACK_CC | 2 | 0b0010 | Global PState Ack | Slave to Master
+/// PMC_IC_GAR_CC | 3 | 0b0011 | Global Actual Request | Slave to Master
+/// PMC_IC_PING_CC | 4 | 0b0100 | Ping | Master to Slave
+/// PMC_IC_PING_ACK_CC | 6 | 0b0110 | Ping Acknowledge | Slave to Master
+/// PMC_IC_MSG_CC | 8 | 0b1000 | Message | Bidirectional
+/// PMC_IC_MSG_NACK_CC | 10 | 0b1010 | Message NACK | Bidirectional
+/// PMC_IC_MSG_ACK_CC | 11 | 0b1011 | Message ACK | Bidirectional
+/// PMC_IC_ERROR_CC | 12 | 0b1111 | Error | Slave to Master
+/// \endcode
+///
+/// This API sends command to another chip through the PMC interchip wire
+/// in DCM setup. The message will be sent out by writing the packet value
+/// to the regisiter: PMC_INTCHP_MSG_WDATA
+///
+/// It also checks the interchip_ga_ongoing and interchip_msg_send_ongoing
+/// bits of PMC_INTCHP_STATUS_REG to detect if the channel is free
+/// If the channel is busy, the function will exit with returning
+/// an error code \a PMC_DCM_OUTSTANDING_TRANSFER
+///
+/// Prerequisite: The enable_interchip_interface bit of PMC_MODE_REG
+/// must be set to enable the PMC interchip transfer
+/// Also, the hardware must be in DCM setup
+///
+/// Note: This API can be used to send any valid command over the link
+/// however, both command code and corresponding direction of transfer
+/// will be checked to ensure correctness of the protocol. Upon
+/// attempt to send an invalid command or an unexpected direction
+/// of transfering certain command will cause this API to abort
+/// which indicates a HW/FW bug
+///
+/// \retval PMC_DCM_SUCCESS
+///
+/// \retval PMC_DCM_ARG_NULL_OBJECT_SEND
+///
+/// \retval PMC_DCM_INTCHP_DISABLED_SEND
+///
+/// \retval PMC_DCM_OUTSTANDING_TRANSFER
+///
+/// \retval PMC_DCM_INVALID_COMMAND_CODE
+///
+
+int
+pmc_dcm_send(PmcDcmPacket* hwPacket)
+{
+ int rc = PMC_DCM_SUCCESS;
+
+ do {
+
+ // check if reference packet is null
+ SSX_ERROR_IF_CHECK_API(
+ (hwPacket == 0),
+ PMC_DCM_ARG_NULL_OBJECT_SEND);
+
+ // check if interchip transfer is enabled on this chip
+ SSX_ERROR_IF_CHECK_API(
+ (pmc_dcm_if_interchip_interface_enabled() == 0),
+ PMC_DCM_INTCHP_DISABLED_SEND);
+
+ //check if command code is valid and direction of transfer is valid
+ rc = pmc_dcm_check_ic_command((int)hwPacket->fields.cmd_code);
+ if( rc ) break;
+
+ // check if the interchip channel is busy
+ if( pmc_dcm_if_channel_busy() ) {
+ rc = PMC_DCM_OUTSTANDING_TRANSFER;
+ break;
+ }
+
+ // send out the command
+ _pmc_dcm_send(&hwPacket->value);
+
+ } while (0);
+
+ return rc;
+}
+
+/// Non-blocking reception of a packet from the PMC-DCM interface
+///
+/// Note: Locking/synchronization of the PMC-DCM interface is the
+/// responsibility of the application.
+///
+/// \param hwPacket A PmcDcmPacket structure passed by the caller
+/// as reference to receive the message sent from PMC interchip link
+///
+/// This API receives the message from the PMC interchip wire
+/// by reading the register: PMC_INTCHP_MSG_RDATA
+///
+/// It checks the interchip_msg_recv_detected bit of
+/// PMC_INTCHP_STATUS_REG to know if there is a new message
+/// If no new message is detected, the receive function will
+/// exit with returning an error code \a PMC_DCM_RECEIVE_NOT_DETECTRD
+///
+/// Prerequisite: The enable_interchip_interface bit of PMC_MODE_REG
+/// must be set to enable the PMC interchip transfer
+/// Also, the hardware must be in DCM setup
+///
+/// Note: only MSG type message or cmd code should be received
+/// otherwise function aborts and indicates a hardware bug
+///
+/// \retval PMC_DCM_SUCCESS
+///
+/// \retval PMC_DCM_ARG_NULL_OBJECT_RECV
+///
+/// \retval PMC_DCM_INTCHP_DISABLED_RECV
+///
+/// \retval PMC_DCM_RECEIVE_NOT_DETECTRD
+///
+/// \retval PMC_DCM_RECEIVE_NOT_MSG_TYPE
+///
+
+int
+pmc_dcm_receive(PmcDcmPacket* hwPacket)
+{
+ int rc = PMC_DCM_SUCCESS;
+
+ do {
+
+ //check if reference packet is null
+ SSX_ERROR_IF_CHECK_API(
+ (hwPacket == 0),
+ PMC_DCM_ARG_NULL_OBJECT_RECV);
+
+ // check if interchip transfer is enabled on this chip
+ SSX_ERROR_IF_CHECK_API(
+ (!pmc_dcm_if_interchip_interface_enabled()),
+ PMC_DCM_INTCHP_DISABLED_RECV);
+
+ // check if there is a new incoming message
+ if( !pmc_dcm_if_new_message() ) {
+ rc = PMC_DCM_RECEIVE_NOT_DETECTED;
+ break;
+ }
+
+ // receive the new message
+ _pmc_dcm_receive(&hwPacket->value);
+
+ // check if the command is MSG type
+ SSX_ERROR_IF_CHECK_API(
+ (hwPacket->fields.cmd_code != PMC_IC_MSG_CC),
+ PMC_DCM_RECEIVE_NOT_MSG_TYPE);
+
+ } while (0);
+
+ return rc;
+}
+
+
+
+/// Internal API : Send data without error checking
+///
+/// \param value 32 bits data to be sent
+///
+/// This API send the interchip data by writing register:
+/// PMC_INTCHP_MSG_WDATA
+///
+/// \retval NONE
+///
+
+void
+_pmc_dcm_send(uint32_t *value)
+{
+ out32(PMC_INTCHP_MSG_WDATA, *value);
+}
+
+
+/// Internal API : Receive data without error checking
+///
+/// \param value 32 bits data to be received
+///
+/// This API receive the interchip data by reading register:
+/// PMC_INTCHP_MSG_RDATA
+///
+/// \retval NONE
+///
+
+void
+_pmc_dcm_receive(uint32_t *value)
+{
+ *value = in32(PMC_INTCHP_MSG_RDATA);
+}
+
+/// This API tells if the given command is a valid pmc interchip command
+/// and if the command is given by the designated source
+///
+/// \param cmd_code the command code
+///
+/// \param rc the return code back to caller
+///
+/// \code
+/// cmd_code:
+///
+/// PMC_IC_GPA_CC | 1 | 0b0001 | Global PState Actual | Master to Slave
+/// PMC_IC_GPA_ACK_CC | 2 | 0b0010 | Global PState Ack | Slave to Master
+/// PMC_IC_GAR_CC | 3 | 0b0011 | Global Actual Request | Slave to Master
+/// PMC_IC_PING_CC | 4 | 0b0100 | Ping | Master to Slave
+/// PMC_IC_PING_ACK_CC | 6 | 0b0110 | Ping Acknowledge | Slave to Master
+/// PMC_IC_MSG_CC | 8 | 0b1000 | Message | Bidirectional
+/// PMC_IC_MSG_NACK_CC | 10 | 0b1010 | Message NACK | Bidirectional
+/// PMC_IC_MSG_ACK_CC | 11 | 0b1011 | Message ACK | Bidirectional
+/// PMC_IC_ERROR_CC | 12 | 0b1111 | Error | Slave to Master
+/// \endcode
+///
+/// \retval PMC_DCM_INTCHP_CMD_ONLY_MTOS
+///
+/// \retval PMC_DCM_INTCHP_CMD_ONLY_STOM
+///
+/// \retval PMC_DCM_INVALID_COMMAND_CODE
+///
+
+int
+pmc_dcm_check_ic_command(int cmd_code)
+{
+ //note:certain command can only be transferred from master to slave
+ // or from slave to master or bidirectional.
+ if( cmd_code == PMC_IC_GPA_CC ||
+ cmd_code == PMC_IC_PING_CC ) {
+ //those commands can only be sent from master to slave
+ SSX_ERROR_IF_CHECK_API(
+ (!pmc_dcm_if_dcm_master()),
+ PMC_DCM_INTCHP_CMD_ONLY_MTOS);
+ } else if( cmd_code == PMC_IC_GPA_ACK_CC ||
+ cmd_code == PMC_IC_GAR_CC ||
+ cmd_code == PMC_IC_PING_ACK_CC ||
+ cmd_code == PMC_IC_ERROR_CC ) {
+ //those commands can only be sent from slave to master
+ SSX_ERROR_IF_CHECK_API(
+ (pmc_dcm_if_dcm_master()),
+ PMC_DCM_INTCHP_CMD_ONLY_STOM);
+ } else if( !(cmd_code == PMC_IC_MSG_CC ||
+ cmd_code == PMC_IC_MSG_NACK_CC ||
+ cmd_code == PMC_IC_MSG_ACK_CC) ) {
+ //those commands are bidirectional
+ //none of above, invalid command
+ SSX_ERROR_IF_CHECK_API(
+ 0,
+ PMC_DCM_INVALID_COMMAND_CODE);
+ }
+ return PMC_DCM_SUCCESS;
+}
+
+
+
+/// This API tells if the current chip is the DCM master or slave
+///
+/// \param NONE
+///
+/// The DCM master/slave is configured as the interchip_mode bit in register:
+/// PMC_MODE_REG
+///
+/// \retval 1 Master
+///
+/// \retval 0 Slave
+///
+
+int
+pmc_dcm_if_dcm_master()
+{
+ pmc_mode_reg_t pmc_mode_reg;
+ pmc_mode_reg.value = in32(PMC_MODE_REG);
+ return pmc_mode_reg.fields.enable_interchip_interface &&
+ pmc_mode_reg.fields.interchip_mode;
+}
+
+/// This API sets the current chip to be the DCM master or slave
+///
+/// \param master if 1 then set to master otherwise slave
+///
+/// The DCM master/slave is configured as the interchip_mode bit in register:
+/// PMC_MODE_REG
+///
+/// \retval NONE
+///
+
+void
+pmc_dcm_set_interchip_mode(int master)
+{
+ pmc_mode_reg_t pmc_mode_reg;
+ pmc_mode_reg.value = in32(PMC_MODE_REG);
+ pmc_mode_reg.fields.enable_interchip_interface = 1;
+ if( master == 0 )
+ pmc_mode_reg.fields.interchip_mode = 0;
+ else
+ pmc_mode_reg.fields.interchip_mode = 1;
+ out32(PMC_MODE_REG, pmc_mode_reg.value);
+}
+
+/// This API tells if the current chip is enabled with interchip interface
+///
+/// \param NONE
+///
+/// The DCM master/slave is configured as the enable_interchip_interface bit
+/// in register: PMC_MODE_REG
+///
+/// Note: set this bit is required for any interchip communication
+///
+/// \retval 1 Enabled
+///
+/// \retval 0 Disabled
+///
+
+int
+pmc_dcm_if_interchip_interface_enabled()
+{
+ pmc_mode_reg_t pmc_mode_reg;
+ pmc_mode_reg.value = in32(PMC_MODE_REG);
+ return pmc_mode_reg.fields.enable_interchip_interface;
+}
+
+/// This API sets the current chip to be enabled with interchip interface
+///
+/// \param enable if 1 then interface enabled otherwise disabled
+///
+/// The DCM master/slave is configured as the enable_interchip_interface bit
+/// in register: PMC_MODE_REG
+///
+/// \retval NONE
+///
+
+void
+pmc_dcm_set_interchip_interface(int enable)
+{
+ pmc_mode_reg_t pmc_mode_reg;
+ pmc_mode_reg.value = in32(PMC_MODE_REG);
+ if( enable == 0 )
+ pmc_mode_reg.fields.enable_interchip_interface = 0;
+ else
+ pmc_mode_reg.fields.enable_interchip_interface = 1;
+ out32(PMC_MODE_REG, pmc_mode_reg.value);
+}
+
+
+/// This API tells if the interchip channel is busy for outgoing communication
+///
+/// \param NONE
+///
+/// depends on bits: interchip_ga_ongoing and interchip_msg_send_ongoing
+/// in register: PMC_INTCHP_STATUS_REG
+///
+/// \retval 1 Busy
+///
+/// \retval 0 Free
+///
+
+int
+pmc_dcm_if_channel_busy()
+{
+ pmc_intchp_status_reg_t pmc_intchp_status_reg;
+ pmc_intchp_status_reg.value = in32(PMC_INTCHP_STATUS_REG);
+ return pmc_intchp_status_reg.fields.interchip_msg_send_ongoing;
+ //return (pmc_intchp_status_reg.fields.interchip_ga_ongoing ||
+ // pmc_intchp_status_reg.fields.interchip_msg_send_ongoing);
+}
+
+/// This API tells if there is a new message arrived from the interchip wire
+///
+/// \param NONE
+///
+/// if bit interchip_msg_recv_detected in register: PMC_INTCHP_STATUS_REG
+/// is set then new message otherwise none
+///
+/// \retval 1 New Message
+///
+/// \retval 0 NO New Message
+///
+
+int
+pmc_dcm_if_new_message()
+{
+ pmc_intchp_status_reg_t pmc_intchp_status_reg;
+ pmc_intchp_status_reg.value = in32(PMC_INTCHP_STATUS_REG);
+ return pmc_intchp_status_reg.fields.interchip_msg_recv_detected;
+}
+
+/// This API initializes the DCM setup
+///
+/// \param master_or_slave configure the current chip to be master or slave
+///
+/// for current chip
+/// 1) enable interchip interface
+/// 2) configure to be DCM master or slave
+///
+/// Note: one chip has to be master and one chip has to be slave
+///
+/// \retval NONE
+///
+
+void
+pmc_dcm_init(int master_or_slave)
+{
+ pmc_dcm_set_interchip_mode(master_or_slave);
+}
diff --git a/src/lib/pmc_dcm.h b/src/lib/pmc_dcm.h
new file mode 100755
index 0000000..3141aec
--- /dev/null
+++ b/src/lib/pmc_dcm.h
@@ -0,0 +1,102 @@
+#ifndef __PMC_DCM_H__
+#define __PMC_DCM_H__
+
+// $Id: pmc_dcm.h,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pmc_dcm.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pmc_dcm.h
+/// \brief Generic PMC Interhchip Communication Mechanism
+
+
+/// PMC-DCM Return Code
+#define PMC_DCM_SUCCESS 0
+#define PMC_DCM_ARG_NULL_OBJECT_SEND 0x00326501 //ssx panic
+#define PMC_DCM_ARG_NULL_OBJECT_RECV 0x00326501 //ssx panic
+#define PMC_DCM_INTCHP_DISABLED_SEND 0x00326502 //ssx panic
+#define PMC_DCM_INTCHP_DISABLED_RECV 0x00326502 //ssx panic
+#define PMC_DCM_OUTSTANDING_TRANSFER 0x00326503 //user handle
+#define PMC_DCM_INTCHP_CMD_ONLY_MTOS 0x00326504 //ssx panic
+#define PMC_DCM_INTCHP_CMD_ONLY_STOM 0x00326504 //ssx panic
+#define PMC_DCM_INVALID_COMMAND_CODE 0x00326505 //ssx panic
+#define PMC_DCM_RECEIVE_NOT_DETECTED 0x00326506 //user handle
+#define PMC_DCM_RECEIVE_NOT_MSG_TYPE 0x00326507 //ssx panic
+
+/// PMC Interchip Command Code
+#define PMC_IC_GPA_CC 1 //0b0001
+#define PMC_IC_GPA_ACK_CC 2 //0b0010
+#define PMC_IC_GAR_CC 3 //0b0011
+#define PMC_IC_PING_CC 4 //0b0100
+#define PMC_IC_PING_ACK_CC 6 //0b0110
+#define PMC_IC_MSG_CC 8 //0b1000
+#define PMC_IC_MSG_NACK_CC 10 //0b1010
+#define PMC_IC_MSG_ACK_CC 11 //0b1011
+#define PMC_IC_ERROR_CC 15 //0b1111
+
+#ifndef __ASSEMBLER__
+
+/// PMC-DCM low-level (hardware) packet
+
+typedef union PmcInterchipPacket {
+ uint32_t value;
+ struct {
+ /// Hardware command code
+ uint8_t cmd_code : 4;
+ /// Hardware command extension; GPSM-DCM command code
+ uint8_t cmd_ext : 4;
+ /// Payload. The plan of record is to use payload[2] as HW-generated ECC.
+ uint8_t payload[3];
+ } fields;
+} PmcDcmPacket;
+
+/// Macro to set and get payload field
+#define SET_PAYLOAD_FIELD(value) (value << 8) & 0xFFFF00
+#define GET_PAYLOAD_FIELD(value) (value & 0xFFFF00) >> 8
+
+
+/// low-level PMC-DCM interchip communication methods
+
+int
+pmc_dcm_send(PmcDcmPacket* hwPacket);
+
+int
+pmc_dcm_receive(PmcDcmPacket* hwPacket);
+
+void
+_pmc_dcm_send(uint32_t *value);
+
+void
+_pmc_dcm_receive(uint32_t *value);
+
+int
+pmc_dcm_check_ic_command(int cmd_code);
+
+int
+pmc_dcm_if_dcm_master();
+
+void
+pmc_dcm_set_interchip_mode(int master);
+
+int
+pmc_dcm_if_interchip_interface_enabled();
+
+void
+pmc_dcm_set_interchip_interface(int enable);
+
+int
+pmc_dcm_if_channel_busy();
+
+int
+pmc_dcm_if_new_message();
+
+void
+pmc_dcm_init(int master_or_slace);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PMC_DCM_H__ */
+
diff --git a/src/lib/polling.c b/src/lib/polling.c
new file mode 100644
index 0000000..42e9fef
--- /dev/null
+++ b/src/lib/polling.c
@@ -0,0 +1,73 @@
+// $Id: polling.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/polling.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file polling.c
+/// \brief Library APIs for polling
+
+#include "polling.h"
+
+int
+polling(int* o_rc,
+ int (*i_condition)(void* io_arg, int* o_satisfied),
+ void* io_arg,
+ SsxInterval i_timeout,
+ SsxInterval i_sleep)
+{
+ SsxTimebase start;
+ int rc, pollRc, timed_out, done;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((i_condition == 0), POLLING_ERROR);
+ }
+
+ start = ssx_timebase_get();
+ timed_out = 0;
+
+ do {
+ pollRc = i_condition(io_arg, &done);
+ if (pollRc) {
+ rc = POLLING_CONDITION;
+ break;
+ }
+ if (done) {
+ rc = 0;
+ break;
+ }
+ if (timed_out) {
+ rc = POLLING_TIMEOUT;
+ break;
+ }
+ if (i_sleep != 0) {
+ rc = ssx_sleep(i_sleep);
+ if (rc) {
+ break;
+ }
+ }
+ timed_out =
+ ((i_timeout != SSX_WAIT_FOREVER) &&
+ ((ssx_timebase_get() - start) >= i_timeout));
+
+ } while (1);
+
+ if (o_rc) {
+ *o_rc = pollRc;
+ }
+
+ return rc;
+}
+
+
+void
+busy_wait(SsxInterval i_interval)
+{
+ SsxTimebase start;
+
+ start = ssx_timebase_get();
+ while ((ssx_timebase_get() - start) < i_interval);
+}
+
diff --git a/src/lib/polling.h b/src/lib/polling.h
new file mode 100644
index 0000000..b719ac6
--- /dev/null
+++ b/src/lib/polling.h
@@ -0,0 +1,94 @@
+#ifndef __POLLING_H__
+#define __POLLING_H__
+
+// $Id: polling.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/polling.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file polling.c
+/// \brief Library APIs for polling and busy-waiting
+
+#include "ssx.h"
+
+// Return/Panic codes
+
+#define POLLING_TIMEOUT 0x00765501
+#define POLLING_ERROR 0x00765502
+#define POLLING_CONDITION 0x00765503
+
+
+#ifndef __ASSEMBLER__
+
+/// Poll for a condition or a timeout with optional sleep
+///
+/// \param[out] o_rc The last return code from calling \a i_condition. This
+/// will only be valid if the return code from polling() is
+/// POLLING_CONDITION. This argument may be passed as NULL (0) if the caller
+/// does not require this information.
+///
+/// \param[in] i_condition A function of two arguments, returning an integer
+/// return code - 0 for success, non-0 for failure. The first argument is a
+/// private state or parameter variable. The second argument is used to
+/// return the truth value of the \a i_condition predicate (0 for false, non-0
+/// for true), and is only considered if the return value of \a i_condition is
+/// 0.
+///
+/// \param[in,out] io_arg The private argument of the \a condition function.
+///
+/// \param[in] i_timeout The maximum amount of time to poll the \a condition
+/// before declaring a timeout. The special value SSX_WAIT_FOREVER can be
+/// used to specify polling without timeout.
+///
+/// \param[in] i_sleep If non-0 at entry, then the thread will sleep for this
+/// interval between polls of the condition. Otherwise the polling is
+/// continuous. polling() can only be called with i_sleep non-0 from a
+/// thread context (since interrupt contexts can not block).
+///
+/// polling() implements a generic polling protocol for conditions that can
+/// not be recognized as interrupt events. polling() polls the \a i_condition
+/// until either an error is encountered, the condition is true, or the
+/// polling times out as measured by the SSX timebase. Whenever a timeout is
+/// detected the condition is polled once more to exclude false timeouts that
+/// may have been caused by thread preemption.
+///
+/// The \a i_sleep A non-0 value of \a i_sleep specifies that the thread
+/// should sleep for the given interval between polling tries instead of
+/// polling continuously. A non-0 \a i_sleep argument is only legal in thread
+/// contexts.
+///
+/// \retval 0 Success; The condition was satisfied prior to the timeout.
+///
+/// \retval POLLING_TIMEOUT A timeout was detected before the condition became
+/// valid.
+///
+/// \retval POLLING_ERROR This code is returned if any of the arguments of
+/// polling() are invalid.
+///
+/// \retval POLLING_CONDITION This code is returned if the \a i_condition
+/// function returns a non-0 return code.
+///
+/// If the embedded call of ssx_sleep() fails for some reason then the return
+/// code will be the code returned by ssx_sleep().
+int
+polling(int* o_rc,
+ int (*i_condition)(void* io_arg, int* o_satisfied),
+ void* io_arg,
+ SsxInterval i_timeout,
+ SsxInterval i_sleep);
+
+
+/// A busy-wait loop
+///
+/// \param[in] i_interval The interval of time to busy-wait. The actual
+/// interval may be more than this if the thread is interrupted. If called
+/// from a context with interrupts disabled the timing should be very precise.
+void
+busy_wait(SsxInterval i_interval);
+
+#endif // __ASSEMBLER__
+
+#endif // __POLLING_H__
diff --git a/src/lib/pore_hooks.h b/src/lib/pore_hooks.h
new file mode 100755
index 0000000..f278acb
--- /dev/null
+++ b/src/lib/pore_hooks.h
@@ -0,0 +1,171 @@
+#ifndef __PORE_HOOKS_H__
+#define __PORE_HOOKS_H__
+
+// $Id: pore_hooks.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pore_hooks.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pore_hooks.h
+/// \brief Support for PORE hooks in Simics
+///
+/// Our Simics model of the PORE supports "hooks", that is, special forms of
+/// comments that include C++ code that is extracted and made available at
+/// simulation time in the Simics environment.
+///
+/// Besides hooks that do simple printf() type tracing, logging and tracing
+/// hooks are also provided that make use of the Simics log-level facility.
+/// This allows precise control over which PORE objects are logged/traced, and
+/// at which level.
+///
+/// In the Simics environment, hook routines have the following prototype:
+///
+/// void f(const PoreAddress& i_address,
+/// const HookType i_type,
+/// PoreSimics& io_pore);
+
+// Define the "1-liner" syntax
+
+#define HOOK_MARKER HOOK_INSERT_MARKER(#,#)
+#define HOOK_INSERT_MARKER(x,y) x##y##1@
+
+
+/// \defgroup standard_io_hooks Standard I/O Logging and Tracing Hooks
+///
+/// Standard I/O printing. The *TRACE* forms prefix the output with the file
+/// name and line number.
+///
+/// @{
+
+#define PORE_PRINTF(...) HOOK_MARKER printf(__VA_ARGS__);
+
+#define PORE_FPRINTF(stream, ...) HOOK_MARKER fprintf(stream, __VA_ARGS__);
+
+#define PORE_TRACEF(fmt, ...) \
+ HOOK_MARKER printf("%s:d:" fmt, __FILE__, __LINE__, ##__VA_ARGS__);
+
+#define PORE_FTRACEF(stream, fmt, ...) \
+ HOOK_MARKER printf(stream, "%s:d:" fmt, __FILE__, __LINE__, ##__VA_ARGS__);
+
+/// @}
+
+/// \defgroup quickie_debugging_prints Quickie Debugging Print Hooks
+///
+/// Quickie debugging prints. You provide a register name and string (w/o
+/// newline), the macro formats the data.
+///
+/// @{
+
+#define PORE_PRINT_REG(msg, reg, fmt, fn) \
+ PORE_PRINTF(msg " : " #reg " = " FMT_##fmt "\n", fn)
+
+#define PORE_TRACE_REG(msg, reg, fmt, fn) \
+ PORE_TRACEF(msg " : " #reg " = " FMT_##fmt "\n", fn)
+
+#define PORE_PRINT_D0(msg) PORE_PRINT_REG(msg, D0, DX, d0())
+#define PORE_PRINT_D1(msg) PORE_PRINT_REG(msg, D1, DX, d1())
+#define PORE_PRINT_A0(msg) PORE_PRINT_REG(msg, A0, AX, a0())
+#define PORE_PRINT_A1(msg) PORE_PRINT_REG(msg, A1, AX, a1())
+#define PORE_PRINT_P0(msg) PORE_PRINT_REG(msg, P0, PX, p0())
+#define PORE_PRINT_P1(msg) PORE_PRINT_REG(msg, P1, PX, p1())
+#define PORE_PRINT_CTR(msg) PORE_PRINT_REG(msg, CTR, CTR, ctr())
+#define PORE_PRINT_SPRG0(msg) PORE_PRINT_REG(msg, SPRG0, SPRG0, sprg0())
+#define PORE_PRINT_STATUS(msg) PORE_PRINT_REG(msg, STATUS, STATUS, status())
+#define PORE_PRINT_CONTROL(msg) PORE_PRINT_REG(msg, CONTROL, CONTROL, control())
+
+#define PORE_TRACE_D0(msg) PORE_TRACE_REG(msg, D0, DX, d0())
+#define PORE_TRACE_D1(msg) PORE_TRACE_REG(msg, D1, DX, d1())
+#define PORE_TRACE_A0(msg) PORE_TRACE_REG(msg, A0, AX, a0())
+#define PORE_TRACE_A1(msg) PORE_TRACE_REG(msg, A1, AX, a1())
+#define PORE_TRACE_P0(msg) PORE_TRACE_REG(msg, P0, PX, p0())
+#define PORE_TRACE_P1(msg) PORE_TRACE_REG(msg, P1, PX, p1())
+#define PORE_TRACE_CTR(msg) PORE_TRACE_REG(msg, CTR, CTR, ctr())
+#define PORE_TRACE_SPRG0(msg) PORE_TRACE_REG(msg, SPRG0, SPRG0, sprg0())
+#define PORE_TRACE_STATUS(msg) PORE_TRACE_REG(msg, STATUS, STATUS, status())
+#define PORE_TRACE_CONTROL(msg) PORE_TRACE_REG(msg, CONTROL, CONTROL, control())
+
+/// @}
+
+/// \defgroup simics_style_logging Simics-style Logging Hooks
+///
+/// Simics-style logging. All of these will produce a Simics prefix detailing
+/// the unit that failed. The *_TRACE_* forms add the file name and line number
+/// to the Simics info, print a newline and then format the trace message on
+/// the following line.
+///
+/// @{
+
+#define SIM_LOG_INFO(level, group, ...) HOOK_MARKER \
+ SIM_log_info(level, io_pore.d_log, group, __VA_ARGS__);
+
+#define SIM_LOG_ERROR(group, ...) HOOK_MARKER \
+ SIM_log_error(io_pore.d_log, group, __VA_ARGS__);
+
+#define SIM_TRACE_INFO(level, group, fmt, ...) HOOK_MARKER \
+ SIM_log_info(level, io_pore.d_log, group, \
+ "%s:%d\n" fmt, __FILE__, __LINE__,## __VA_ARGS__);
+
+#define SIM_TRACE_ERROR(group, fmt, ...) HOOK_MARKER \
+ SIM_log_error(io_pore.d_log, group, \
+ "%s:%d\n" fmt, __FILE__, __LINE__, ##__VA_ARGS__);
+
+/// @}
+
+/// \defgroup vcl_style_3_level_printing VCL-style 3-Level Logging Hooks
+///
+/// Define VCL-style 3-level logging and tracing, with programmable Simics
+/// log-level selection. All logs are controlled by (?) group 0. Note that
+/// setting the Simics log-level to 4 produces gobs of output from every part
+/// of the system, however here at the debug level of 3 we only get messages
+/// from hooks.
+///
+/// @{
+
+#ifndef SIMICS_LOG_LEVEL_OUTPUT
+#define SIMICS_LOG_LEVEL_OUTPUT 1
+#endif
+
+#ifndef SIMICS_LOG_LEVEL_INFO
+#define SIMICS_LOG_LEVEL_INFO 2
+#endif
+
+#ifndef SIMICS_LOG_LEVEL_DEBUG
+#define SIMICS_LOG_LEVEL_DEBUG 3
+#endif
+
+#define PORE_LOG_OUTPUT(...) SIM_LOG_INFO(SIMICS_LOG_LEVEL_OUTPUT, 0, __VA_ARGS__)
+#define PORE_LOG_INFO(...) SIM_LOG_INFO(SIMICS_LOG_LEVEL_INFO, 0, __VA_ARGS__)
+#define PORE_LOG_DEBUG(...) SIM_LOG_INFO(SIMICS_LOG_LEVEL_DEBUG, 0, __VA_ARGS__)
+
+#define PORE_LOG_ERROR(...) SIM_LOG_ERROR(0, __VA_ARGS__)
+
+#define PORE_TRACE_OUTPUT(...) SIM_TRACE_INFO(SIMICS_LOG_LEVEL_OUTPUT, 0, __VA_ARGS__)
+#define PORE_TRACE_INFO(...) SIM_TRACE_INFO(SIMICS_LOG_LEVEL_INFO, 0, __VA_ARGS__)
+#define PORE_TRACE_DEBUG(...) SIM_TRACE_INFO(SIMICS_LOG_LEVEL_DEBUG, 0, __VA_ARGS__)
+
+#define PORE_TRACE_ERROR(...) SIM_TRACE_ERROR(0, __VA_ARGS__)
+
+/// @}
+
+/// Break Simics simulation
+#define SIM_BREAK_SIMULATION(msg) \
+ HOOK_MARKER SIM_break_simulation(msg); io_pore.dumpAll();
+
+
+/// A PORE Assertion
+#define PORE_ASSERT(assertion) \
+ HOOK_MARKER \
+ if (!(assertion)) { \
+ SIM_log_error(io_pore.d_log, 0, \
+ "Assertion below failed\n" #assertion); \
+ SIM_break_simulation("Assertion failure"); \
+ }
+
+
+/// Dump the PORE state
+#define PORE_DUMP(...) LOG_OUTPUT(__VA_ARGS__) io_pore.dumpAll();
+
+#endif // __PORE_HOOKS_H__
diff --git a/src/lib/printf.c b/src/lib/printf.c
new file mode 100755
index 0000000..96f08f3
--- /dev/null
+++ b/src/lib/printf.c
@@ -0,0 +1,679 @@
+// $Id: printf.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/printf.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file printf.c
+/// \brief Clean-room implementation of printf() functions for SSX I/O
+///
+/// For licensing reasons we are required to create our own version of the
+/// printf() family of functions. This implementation was created without
+/// reference to or inclusion of any licensed or copyrighted code.
+///
+/// The functions defined in this file have prototypes, behavior and return
+/// values as defined by C language standards. In the event of an error a
+/// negative value is returned, generally corresponding to a standard Unix
+/// 'errno' code. Note that SSX does not support either an application- or
+/// per-thread 'errno', so the only record of any error is the \a error field
+/// of the stream. Also note that SSX may be configured to cause a panic if an
+/// error is detected rather than returning an error code.
+///
+/// This implementation defines a limited but useful subset of the C standard
+/// for format control. This implementation includes the following:
+///
+/// - \b c, \b d, \b i, \b n, \b p, \b s, \b u, \b x, and \b X conversion
+/// specifiers, as well as '%%' to output a single '%'
+///
+/// - \b #, \b 0, \b ' ' and \b + flag characters
+///
+/// - Decimal field width specifiers including * (but indirect field widths
+/// must be positive as left-justification is not supported)
+///
+/// - Decimal precision specifiers (currently only apply to %s formats, may be
+/// indirect using *)
+///
+/// - \b l, \b ll and \b z length modifiers
+///
+/// \b Notes:
+///
+/// \a If a \c p conversion specifier is used without any flags (\c '%p'), the
+/// \c p conversion is interptered as if it were \c 0x%08lx for 32-bit address
+/// machines and \c 0x%016llx for 64-bit address machines. The GCC builtin
+/// format checker gives warnings about '0' flag characters for \c p
+/// conversion specifiers, so there is otherwise no 'un-warned' way to get
+/// this preferred (by some) format of pointer values. If you do include
+/// explicit flags (e.g., \c %30p) they will be processed as expected.
+///
+/// Similar to how printf() behaves on an X86-Linux machine, a null pointer
+/// will print as "(null)" with the %s format (unless the precision specifier
+/// precludes it) and "(nil)" with the %p format.
+///
+/// Note that calling formatted I/O functions on non-blocking streams may fail
+/// with the -EAGAIN error, and there is no clean way to restart these
+/// calls. Calling formatted (or any) I/O functions on blocking streams from
+/// interrupt contexts in SSX is also likely to fail intermittently since
+/// interrupt contexts can not block in SSX.
+///
+/// \todo I'd really like to implement the '-' flag for
+/// left-justification. Implementing the precision specifer for integers
+/// should be done for completeness.
+
+#include "ssx.h"
+#include "ssx_io.h"
+
+// Formatting options
+
+#define OPTION_ALTERNATE 0x0001
+#define OPTION_PAD_ZERO 0x0002
+#define OPTION_PLUS_SIGN 0x0004
+#define OPTION_FIELD_WIDTH 0x0008
+#define OPTION_PRECISION 0x0010
+#define OPTION_LONG 0x0020
+#define OPTION_LONG_LONG 0x0040
+#define OPTION_SIZE_T 0x0080
+#define OPTION_UPPERCASE 0x0100
+#define OPTION_HEX 0x0200
+#define OPTION_SPACE 0x0400
+
+
+// Generate padding if required, returning the total number of pad characters
+// output or a negative error code. The 'nchars' argument is the number of
+// non-pad characters to be output by the caller.
+
+#define PAD_SIZE 8
+static const char zeros[PAD_SIZE] = {'0', '0', '0', '0', '0', '0', '0', '0'};
+static const char blanks[PAD_SIZE] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
+
+static ssize_t
+pad(FILE *stream, size_t nchars, int options, size_t width)
+{
+ const char *padchars;
+ size_t chars, written;
+ int rc;
+
+ if (!(options & OPTION_FIELD_WIDTH) || (nchars >= width)) {
+ return 0;
+ }
+ chars = width - nchars;
+ if (options & OPTION_PAD_ZERO) {
+ padchars = zeros;
+ } else {
+ padchars = blanks;
+ }
+ while (chars) {
+ rc = swrite(stream, (void *)padchars, MIN(chars, PAD_SIZE), &written);
+ if (rc < 0) return rc;
+ chars -= written;
+ }
+ return width - nchars;
+}
+
+
+// Format a character
+
+static ssize_t
+format_char(FILE *stream, unsigned char c, int options, size_t width)
+{
+ ssize_t padchars, nchars;
+ int rc;
+
+ padchars = pad(stream, 1, options, width);
+ if (padchars < 0) return padchars;
+ nchars = padchars + 1;
+ rc = swrite(stream, (void *)(&c), 1, 0);
+ if (rc < 0) return rc;
+ return nchars;
+}
+
+
+// Format a string
+//
+// If the string is the NULL pointer then normally "(null)" is printed
+// unless the precision is < 6, in which case the empty string is printed.
+// The specification leaves it as undefined what happens if a string requests
+// 0 padding; Here we always pad with blanks (although GCC/PowerPC catches
+// this as an error).
+
+static ssize_t
+format_string(FILE *stream, const char *s, int options,
+ size_t width, size_t precision)
+{
+ size_t len;
+ ssize_t padchars, nchars;
+ int rc;
+
+ if (s == 0) {
+ if ((options & OPTION_PRECISION) && (precision < 6)) {
+ s = "";
+ } else {
+ s = "(null)";
+ }
+ }
+
+ len = strlen(s);
+ if (options & OPTION_PRECISION) {
+ len = MIN(len, precision);
+ }
+
+ options &= ~OPTION_PAD_ZERO;
+ padchars = pad(stream, len, options, width);
+ if (padchars < 0) return padchars;
+ nchars = padchars + len;
+ rc = swrite(stream, (void *)s, len, 0);
+ if (rc < 0) return rc;
+ return nchars;
+}
+
+
+// Format an integer - signed and unsigned. A 64-bit integer (assumed to be
+// the longest we'll see) has 20 decimal digits. An extra space is reserved
+// for the sign. If zero-padding is specified, the sign will be output
+// separately.
+
+static const char lower[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+static const char upper[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+static ssize_t
+format_int(FILE *stream, long long int lli, int options, size_t width)
+{
+ char digits[21];
+ int rc, k, ndigits, negative, positive, i;
+ ssize_t output;
+
+ negative = (lli < 0);
+ positive = (lli > 0);
+
+ // Unpack the integer to characters. The code is optimized for 32-bit
+ // machines where 64-bit division is not built in. The first part of the
+ // loop handles integers requiring a 64-bit divide, the second loop
+ // handles 32-bit integers.
+
+ if (lli == 0) {
+ digits[20] = '0';
+ k = 20;
+ } else if (negative) {
+ for (k = 21;
+ lli != (int)lli;
+ digits[--k] = lower[-(lli % 10)], lli = lli / 10);
+ for (i = (int)lli;
+ i != 0;
+ digits[--k] = lower[-(i % 10)], i = i / 10);
+ } else {
+ for (k = 21;
+ lli != (int)lli;
+ digits[--k] = lower[lli % 10], lli = lli / 10);
+ for (i = (int)lli;
+ i != 0;
+ digits[--k] = lower[i % 10], i = i / 10);
+ }
+
+ ndigits = 21 - k;
+
+ // Handle other options and output
+
+ output = 0;
+ if (options & OPTION_PAD_ZERO) {
+
+ if (negative) {
+ rc = swrite(stream, "-", 1, 0);
+ if (rc < 0) return rc;
+ output++;
+ } else if (positive) {
+ if (options & OPTION_PLUS_SIGN) {
+ rc = swrite(stream, "+", 1, 0);
+ if (rc < 0) return rc;
+ output++;
+ } else if (options & OPTION_SPACE) {
+ rc = swrite(stream, " ", 1, 0);
+ if (rc < 0) return rc;
+ output++;
+ }
+ }
+ rc = pad(stream, ndigits + output, options, width);
+ if (rc < 0) return rc;
+ output += rc;
+ rc = swrite(stream, &(digits[k]), ndigits, 0);
+ if (rc < 0) return rc;
+ output += ndigits;
+
+ } else {
+
+ if (negative) {
+ digits[--k] = '-';
+ ndigits++;
+ } else if (positive) {
+ if (options & OPTION_PLUS_SIGN) {
+ digits[--k] = '+';
+ ndigits++;
+ } else if (options & OPTION_SPACE) {
+ digits[--k] = ' ';
+ ndigits++;
+ }
+ }
+ rc = pad(stream, ndigits, options, width);
+ if (rc < 0) return rc;
+ output += rc;
+ rc = swrite(stream, &(digits[k]), ndigits, 0);
+ if (rc < 0) return rc;
+ output += ndigits;
+ }
+
+ return output;
+}
+
+
+static ssize_t
+format_unsigned(FILE *stream, unsigned long long ull, int options, size_t width)
+{
+ char digits[21], *alternate;
+ const char *xchars;
+ int rc, k, ndigits, zero;
+ unsigned u;
+ ssize_t output;
+
+ zero = (ull == 0);
+
+ // Determine hex case and alternate string
+
+ alternate = 0;
+ if (options & OPTION_HEX) {
+ if (options & OPTION_UPPERCASE) {
+ xchars = upper;
+ if (options & OPTION_ALTERNATE) {
+ alternate = "0X";
+ }
+ } else {
+ xchars = lower;
+ if (options & OPTION_ALTERNATE) {
+ alternate = "0x";
+ }
+ }
+ } else {
+ xchars = lower;
+ }
+
+ // Unpack the unsigned integer to characters. The Hex conversions are
+ // easier since they can be done with shift and mask rather than
+ // divison. The code is optimized for a 32-bit machine where 64-bit
+ // division is not built-in.
+
+ if (zero) {
+ digits[20] = '0';
+ k = 20;
+ } else if (options & OPTION_HEX) {
+ for (k = 21;
+ ull != (unsigned)ull;
+ digits[--k] = xchars[ull & 0xf], ull = ull >> 4);
+ for (u = (unsigned)ull;
+ u != 0;
+ digits[--k] = xchars[u & 0xf], u = u >> 4);
+ } else {
+ for (k = 21;
+ ull != (unsigned)ull;
+ digits[--k] = xchars[ull % 10], ull = ull / 10);
+ for (u = (unsigned)ull;
+ u != 0;
+ digits[--k] = xchars[u % 10], u = u / 10);
+ }
+
+ ndigits = 21 - k;
+
+ // Handle other options and output
+
+ output = 0;
+ if (options & OPTION_PAD_ZERO) {
+
+ if (!zero && alternate) {
+ rc = swrite(stream, (void *)alternate, 2, 0);
+ if (rc < 0) return rc;
+ output += 2;
+ }
+ rc = pad(stream, ndigits + output, options, width);
+ if (rc < 0) return rc;
+ output += rc;
+ rc = swrite(stream, &(digits[k]), ndigits, 0);
+ if (rc < 0) return rc;
+ output += ndigits;
+
+ } else {
+
+ if (!zero && alternate) {
+ output += 2;
+ }
+ rc = pad(stream, ndigits + output, options, width);
+ if (rc < 0) return rc;
+ output += rc;
+ if (!zero && alternate) {
+ rc = swrite(stream, alternate, 2, 0);
+ if (rc < 0) return rc;
+ output += 2;
+ }
+ rc = swrite(stream, &(digits[k]), ndigits, 0);
+ if (rc < 0) return rc;
+ output += ndigits;
+ }
+
+ return output;
+}
+
+
+int
+vfprintf(FILE *stream, const char *format, va_list argp)
+{
+ const char *fmt, *scan;
+ int rc, total_chars, options, done;
+ size_t width, precision;
+
+ int arg_i, *arg_pi;
+ long int arg_li;
+ long long int arg_lli;
+ ssize_t arg_zi;
+ unsigned arg_u;
+ unsigned long arg_lu;
+ unsigned long long arg_llu;
+ size_t arg_zu;
+ char *arg_s;
+
+ total_chars = 0;
+
+ fmt = format;
+ while (*fmt) {
+
+ // Scan until '%' or the end of the format, then output the text.
+
+ scan = fmt;
+ while (*scan && (*scan != '%')) {
+ scan++;
+ }
+ if (scan != fmt) {
+ rc = swrite(stream, fmt, scan - fmt, 0);
+ if (rc < 0) return rc;
+ total_chars += scan - fmt;
+ }
+ fmt = scan;
+ if (!*fmt) {
+ return total_chars;
+ }
+ fmt++;
+
+ // We got a '%'. Check for %% and %n.
+
+ switch (*fmt) {
+ case '\0':
+ SSX_IO_ERROR(stream, EINVAL);
+ break;
+ case '%':
+ rc = swrite(stream, "%", 1, 0);
+ if (rc < 0) return rc;
+ total_chars++;
+ fmt++;
+ continue;
+ case 'n':
+ arg_pi = va_arg(argp, int *);
+ *arg_pi = total_chars;
+ fmt++;
+ continue;
+ }
+
+ // Collect padding options, if any. Left justification is not
+ // implemeted.
+
+ options = 0;
+ done = 0;
+ do {
+ switch (*fmt) {
+ case '\0':
+ SSX_IO_ERROR(stream, EINVAL);
+ break;
+ case '#':
+ options |= OPTION_ALTERNATE;
+ break;
+ case '0':
+ options |= OPTION_PAD_ZERO;
+ break;
+ case '+':
+ options |= OPTION_PLUS_SIGN;
+ break;
+ case ' ':
+ options |= OPTION_SPACE;
+ break;
+ case '-':
+ SSX_IO_ERROR(stream, EINVAL); // Left just. not impl.
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ if (!done) {
+ fmt++;
+ }
+ } while (!done);
+
+ // Collect the field width, if specified. A negative precision
+ // specified as an argument indicates left justification (not
+ // implemented).
+
+ width = 0;
+ if (isdigit(*fmt)) {
+ options |= OPTION_FIELD_WIDTH;
+ for (; isdigit(*fmt); fmt++) {
+ width = (width * 10) + (*fmt - '0');
+ }
+ } else if (*fmt == '*') {
+ fmt++;
+ options |= OPTION_FIELD_WIDTH;
+ arg_i = va_arg(argp, int);
+ if (arg_i < 0) {
+ SSX_IO_ERROR(stream, EINVAL); // Left just. not impl.
+ }
+ width = arg_i;
+ }
+
+ // Collect the precision, if specified. By standard specification an
+ // empty or negative precision is interpreted as 0.
+
+ precision = 0;
+ if (*fmt == '.') {
+ fmt++;
+ options |= OPTION_PRECISION;
+ if (isdigit(*fmt)) {
+ for(; isdigit(*fmt); fmt++) {
+ precision = (precision * 10) + (*fmt - '0');
+ }
+ } else if (*fmt == '*') {
+ fmt++;
+ arg_i = va_arg(argp, int);
+ if (arg_i < 0) {
+ arg_i = 0;
+ }
+ precision = arg_i;
+ }
+ }
+
+ // Collect length modifiers.
+
+ done = 0;
+ do {
+ switch (*fmt) {
+ case '\0':
+ SSX_IO_ERROR(stream, EINVAL);
+ break;
+ case 'l':
+ if (options & OPTION_LONG) {
+ options &= ~OPTION_LONG;
+ options |= OPTION_LONG_LONG;
+ } else if (options & OPTION_LONG_LONG) {
+ SSX_IO_ERROR(stream, EINVAL);
+ } else {
+ options |= OPTION_LONG;
+ }
+ if (options & OPTION_SIZE_T) {
+ SSX_IO_ERROR(stream, EINVAL);
+ }
+ break;
+ case 'z':
+ if ((options & OPTION_LONG) || (options & OPTION_LONG_LONG)) {
+ SSX_IO_ERROR(stream, EINVAL);
+ }
+ options |= OPTION_SIZE_T;
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ if (!done) {
+ fmt++;
+ }
+ } while (!done);
+
+ // Use the conversion specifier to format the next argument
+
+ switch (*fmt) {
+
+ case 'c':
+ arg_i = va_arg(argp, int);
+ rc = format_char(stream, (unsigned char)arg_i, options, width);
+ if (rc < 0) return rc;
+ total_chars++;
+ break;
+
+ case 'd':
+ case 'i':
+ if (options & OPTION_LONG) {
+ arg_li = va_arg(argp, long int);
+ rc = format_int(stream, (long long int)arg_li, options,
+ width);
+ } else if (options & OPTION_LONG_LONG) {
+ arg_lli = va_arg(argp, long long int);
+ rc = format_int(stream, (long long int)arg_lli, options,
+ width);
+ } else if (options & OPTION_SIZE_T) {
+ arg_zi = va_arg(argp, ssize_t);
+ rc = format_int(stream, (long long int)arg_zi, options,
+ width);
+ } else {
+ arg_i = va_arg(argp, int);
+ rc = format_int(stream, (long long int)arg_i, options,
+ width);
+ }
+ if (rc < 0) return rc;
+ total_chars += rc;
+ break;
+
+ case 'p':
+ arg_lu = va_arg(argp, unsigned long);
+ options |= (OPTION_ALTERNATE | OPTION_HEX);
+ if (!(options & OPTION_PAD_ZERO) &&
+ !(options & OPTION_FIELD_WIDTH)) {
+ options |= (OPTION_PAD_ZERO | OPTION_FIELD_WIDTH);
+ width = (2 * sizeof(unsigned long)) + 2; /* 0x........ */
+ }
+ if (arg_lu == 0) {
+ options &= ~OPTION_PRECISION;
+ rc = format_string(stream, "(nil)", options, width, precision);
+ } else {
+ rc = format_unsigned(stream, (unsigned long long)arg_lu,
+ options, width);
+ }
+ if (rc < 0) return rc;
+ total_chars += rc;
+ break;
+
+ case 's':
+ arg_s = va_arg(argp, char *);
+ rc = format_string(stream, arg_s, options, width, precision);
+ if (rc < 0) return rc;
+ total_chars += rc;
+ break;
+
+ case 'X':
+ options |= OPTION_UPPERCASE;
+ case 'x':
+ options |= OPTION_HEX;
+ case 'u':
+ if (options & OPTION_LONG) {
+ arg_lu = va_arg(argp, unsigned long);
+ rc = format_unsigned(stream, (unsigned long long)arg_lu,
+ options, width);
+ } else if (options & OPTION_LONG_LONG) {
+ arg_llu = va_arg(argp, unsigned long long);
+ rc = format_unsigned(stream, (unsigned long long)arg_llu,
+ options, width);
+ } else if (options & OPTION_SIZE_T) {
+ arg_zu = va_arg(argp, size_t);
+ rc = format_unsigned(stream, (unsigned long long)arg_zu,
+ options, width);
+ } else {
+ arg_u = va_arg(argp, unsigned);
+ rc = format_unsigned(stream, (unsigned long long )arg_u,
+ options, width);
+ }
+ if (rc < 0) return rc;
+ total_chars += rc;
+ break;
+
+ default:
+ SSX_IO_ERROR(stream, EINVAL);
+ break;
+ }
+
+ fmt++;
+ }
+
+ return total_chars;
+}
+
+
+int
+vprintf(const char *format, va_list argp)
+{
+ return vfprintf(stdout, format, argp);
+}
+
+
+int
+fprintf(FILE *stream, const char *format, ...)
+{
+ va_list argp;
+ int rc;
+
+ va_start(argp, format);
+ rc = vfprintf(stream, format, argp);
+ va_end(argp);
+ return rc;
+}
+
+
+int
+printf(const char *format, ...)
+{
+ va_list argp;
+ int rc;
+
+ va_start(argp, format);
+ rc = vfprintf(stdout, format, argp);
+ va_end(argp);
+ return rc;
+}
+
+
+int
+printk(const char *format, ...)
+{
+ va_list argp;
+ int rc;
+
+ va_start(argp, format);
+ rc = vfprintf(ssxout, format, argp);
+ va_end(argp);
+ return rc;
+}
+
diff --git a/src/lib/pstates.c b/src/lib/pstates.c
new file mode 100755
index 0000000..958b9e1
--- /dev/null
+++ b/src/lib/pstates.c
@@ -0,0 +1,410 @@
+// $Id: pstates.c,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pstates.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pstates.c
+/// \brief Pstate routines required by OCC product firmware
+
+#include "ssx.h"
+#include "pgp_common.h"
+#include "pstates.h"
+
+/// Validate a VRM11 VID code
+///
+/// \param vid A VRM11 VID
+///
+/// \retval 0 The VID is valid
+///
+/// \retval -VID11_UNDERFLOW_VID11_VALIDATE The Vid code is a low 'power off'
+/// VID (0 or 1)
+///
+/// \retval -VID11_OVERFLOW_VID11_VALIDATE The Vid code is a high 'power off'
+/// VID (0xfe or 0xff)
+
+int
+vid11_validate(Vid11 vid)
+{
+ int rc;
+
+ if (vid < VID11_MIN) {
+
+ rc = -VID11_UNDERFLOW_VID11_VALIDATE;
+
+ } else if (vid > VID11_MAX) {
+
+ rc = -VID11_OVERFLOW_VID11_VALIDATE;
+
+ } else {
+
+ rc = 0;
+
+ }
+
+ return rc;
+}
+
+
+/// Bias a Pstate with saturation
+///
+/// \param pstate The initial Pstate to bias
+///
+/// \param bias The signed bias amount
+///
+/// \param biased_pstate The final biased Pstate
+///
+/// This API adds a signed bias to the \a pstate and returns the saturated sum
+/// as \a biased_pstate. Any application that biases Pstates should use this
+/// API rather than simple addition/subtraction.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -PSTATE_OVERFLOW_BIAS_PS The biased Pstate saturated at PSTATE_MAX.
+///
+/// \retval -PSTATE_UNDERFLOW_BIAS_PS The biased Pstate saturated at PSTATE_MIN.
+
+int
+bias_pstate(Pstate pstate, int bias, Pstate* biased_pstate)
+{
+ int rc, int_pstate;
+
+ int_pstate = (int)pstate + bias;
+ if (int_pstate != (Pstate)int_pstate) {
+ if (bias < 0) {
+ *biased_pstate = PSTATE_MIN;
+ rc = -PSTATE_UNDERFLOW_BIAS_PS;
+ } else {
+ *biased_pstate = PSTATE_MAX;
+ rc = -PSTATE_OVERFLOW_BIAS_PS;
+ }
+ } else {
+ *biased_pstate = int_pstate;
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+/// Bias a DPLL frequency code with saturation and bounds checking
+///
+/// \param fcode The initial frequency code to bias
+///
+/// \param bias The signed bias amount
+///
+/// \param biased_fcode The final biased frequency code
+///
+/// This API adds a signed bias to the \a fcode and returns the saturated and
+/// bounded sum as \a biased_fcode. Any application that biases frequency
+/// codes should use this API rather than simple addition/subtraction.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -DPLL_OVERFLOW The biased frequency code saturated at DPLL_MAX.
+///
+/// \retval -DPLL_UNDERFLOW1 The biased frequency code saturated at DPLL_MIN.
+///
+/// \retval -DPLL_UNDERFLOW2 The biased frequency code saturated at DPLL_MIN.
+
+int
+bias_frequency(DpllCode fcode, int bias, DpllCode* biased_fcode)
+{
+ int rc;
+ unsigned uint_fcode;
+
+ uint_fcode = (unsigned)fcode + bias;
+ if (uint_fcode != (DpllCode)uint_fcode) {
+ if (bias < 0) {
+ *biased_fcode = DPLL_MIN;
+ rc = -DPLL_UNDERFLOW1;
+ } else {
+ *biased_fcode = DPLL_MAX;
+ rc = -DPLL_OVERFLOW;
+ }
+ } else if (uint_fcode < DPLL_MIN) {
+ *biased_fcode = DPLL_MIN;
+ rc = -DPLL_UNDERFLOW2;
+ } else {
+ *biased_fcode = uint_fcode;
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+/// Bias a VRM11 VID code with saturation and bounds checking
+///
+/// \param vid The initial vid code to bias
+///
+/// \param bias The signed bias amount
+///
+/// \param biased_vid The final biased VID code
+///
+/// This API adds a signed bias to the \a vid and returns the saturated and
+/// bounded sum as \a biased_vid. Any application that biases VID codes
+/// should use this API rather than simple addition/subtraction.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -VID11_OVERFLOW_BIAS_VID11 The biased VID code saturated
+/// at VID11_MAX.
+///
+/// \retval -VID11_UNDERFLOW_BIAS_VID11 The biased VID code saturated
+/// at VID11_MIN.
+
+int
+bias_vid11(Vid11 vid, int bias, Vid11* biased_vid)
+{
+ int rc;
+ unsigned uint_vid;
+
+ uint_vid = (unsigned)vid + bias;
+ if (uint_vid != (DpllCode)uint_vid) {
+ if (bias < 0) {
+ *biased_vid = VID11_MIN;
+ rc = -VID11_UNDERFLOW_BIAS_VID11;
+ } else {
+ *biased_vid = VID11_MAX;
+ rc = -VID11_OVERFLOW_BIAS_VID11;
+ }
+ } else {
+
+ rc = vid11_validate(uint_vid);
+ *biased_vid = uint_vid;
+
+ }
+
+ return rc;
+}
+
+
+/// Retrieve an entry from the Global Pstate Table abstraction
+///
+/// \param gpst An initialized GlobalPstateTable structure.
+///
+/// \param pstate The Pstate index of the entry to fetch
+///
+/// \param bias This is a signed bias. The entry searched is the \a pstate +
+/// \a bias entry.
+///
+/// \param entry A pointer to a gpst_entry_t to hold the returned data.
+///
+/// This routine functions similar to PMC harwdare. When a Pstate is
+/// requested the index is first biased (under/over-volted) and clipped to the
+/// defined bounds, then the Pstate entry is returned.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -GPST_PSTATE_CLIPPED_HIGH_GPST_ENTRY The requested Pstate does not
+/// exist in the table. The maximum Pstate entry in the table has been returned.
+///
+/// \retval -GPST_PSTATE_CLIPPED_LOW_GPST_ENTRY The requested Pstate does not
+/// exist in the table. The minimum Pstate entry in the table has been returned.
+///
+/// The following return codes are considered errors:
+///
+/// \retval -GPST_INVALID_OBJECT_GPST_ENTRY The Global Pstate Table is
+/// either null (0) or otherwise invalid.
+
+int
+gpst_entry(const GlobalPstateTable *gpst,
+ const Pstate pstate,
+ int bias,
+ gpst_entry_t *entry)
+{
+ int rc, index;
+ Pstate biased_pstate;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(gpst == 0, GPST_INVALID_OBJECT_GPST_ENTRY);
+ }
+
+ rc = bias_pstate(pstate, bias, &biased_pstate);
+
+ if ((rc == -PSTATE_UNDERFLOW_BIAS_PS) || (pstate < gpst_pmin(gpst))) {
+
+ rc = -GPST_PSTATE_CLIPPED_LOW_GPST_ENTRY;
+ index = 0;
+
+ } else if ((rc == -PSTATE_OVERFLOW_BIAS_PS) || (pstate > gpst_pmax(gpst))) {
+
+ rc = -GPST_PSTATE_CLIPPED_HIGH_GPST_ENTRY;
+ index = gpst->entries - 1;
+
+ } else {
+
+ rc = 0;
+ index = pstate - gpst_pmin(gpst);
+
+ }
+
+ *entry = gpst->pstate[index];
+
+ return rc;
+}
+
+
+/// Translate a Vdd VID code to the closest Pstate in a Global Pstate table.
+///
+/// \param gpst The GlobalPstateTable to search
+///
+/// \param vdd A VID code representing an external VDD voltage
+///
+/// \param pstate The Pstate most closely matching the \a vid.
+///
+/// \param entry The GlobalPstateTable entry of the returned \a pstate.
+///
+/// This routine assumes that Pstate voltages increase monotonically from
+/// lower to higher Pstates. The algorithm operates from lowest to highest
+/// voltage, scanning until the Pstate voltage is >= the VID voltage. Thus
+/// the algorithm effectively rounds up voltage (unless clipped at the highest
+/// Pstate).
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -GPST_PSTATE_CLIPPED_HIGH_GPST_V2P The requested voltage does not
+/// exist in the table. The highest legal Pstate is returned.
+///
+/// \retval -GPST_PSTATE_CLIPPED_LOW_GPST_V2P The requested voltage does not
+/// exist in the table. The lowest legal Pstate in the table is returned.
+///
+/// The following return codes are considered errors:
+///
+/// \retval -VRM_INVALID_VOLTAGE The \a vid is invalid.
+///
+/// \retval -GPST_INVALID_OBJECT_GPST_V2P The \a gpst argument is NULL (0).
+
+// Recall that VID codes _decrease_ as voltage _increases_
+
+int
+gpst_vdd2pstate(const GlobalPstateTable* gpst,
+ const Vid11 vdd,
+ Pstate* pstate,
+ gpst_entry_t* entry)
+{
+ size_t i;
+ int rc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(gpst == 0, GPST_INVALID_OBJECT_GPST_V2P);
+ }
+
+ do {
+ rc =vid11_validate(vdd);
+ if (rc) break;
+
+ // Search for the Pstate that contains (close to) the requested
+ // voltage, then handle special cases.
+
+ for (i = 0; i < gpst->entries; i++) {
+ if (gpst->pstate[i].fields.evid_vdd <= vdd) {
+ break;
+ }
+ }
+
+ if (i == gpst->entries) {
+
+ *pstate = gpst_pmax(gpst);
+ *entry = gpst->pstate[i - 1];
+ rc = -GPST_PSTATE_CLIPPED_HIGH_GPST_V2P;
+
+ } else if ((i == 0) && (gpst->pstate[i].fields.evid_vdd < vdd)) {
+
+ *pstate = gpst_pmin(gpst);
+ *entry = gpst->pstate[0];
+ rc = -GPST_PSTATE_CLIPPED_LOW_GPST_V2P;
+
+ } else {
+
+ rc = bias_pstate(gpst_pmin(gpst), i, pstate);
+ if (rc) break;
+
+ *entry = gpst->pstate[i];
+ }
+ } while (0);
+ return rc;
+}
+
+
+/// Translate a frequency in KHz to the closest Pstate in a Global Pstate
+/// table.
+///
+/// \param gpst The GlobalPstateTable to search
+///
+/// \param frequency_khz The frequency in KHz
+///
+/// \param pstate The Pstate most closely matching the frequency, rounded down
+/// (towards lower Pstates).
+///
+///
+/// Note that the Pstate returned may or may not be represented in the Pstate
+/// table. This means that it may be higher that the highest legal frequency
+/// or lower than the lowest frequency represented in the Pstate table.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -PSTATE_OVERFLOW_GPST_F2P The requested frequency translates to an
+/// unrepresentable Pstate. PSTATE_MAX (127) is returned.
+///
+/// \retval -PSTATE_UNDERFLOW_GPST_F2P The requested frequency translates to an
+/// unrepresentable Pstate. PSTATE_MIN (-128) is returned.
+int
+gpst_frequency2pstate(const GlobalPstateTable* gpst,
+ const uint32_t frequency_khz,
+ Pstate* pstate)
+{
+ int rc;
+ int32_t intPstate;
+
+ // Compute the Pstate and round down
+
+ intPstate =
+ (int32_t)(frequency_khz - gpst->pstate0_frequency_khz) /
+ (int32_t)gpst->frequency_step_khz;
+
+ if (intPstate < 0) {
+
+ if (((int32_t)(frequency_khz - gpst->pstate0_frequency_khz) %
+ (int32_t)gpst->frequency_step_khz) != 0) {
+
+ intPstate--;
+ }
+ }
+
+
+ // Clip to legal Pstate type values
+
+ if (intPstate < PSTATE_MIN) {
+
+ *pstate = PSTATE_MIN;
+ rc = -PSTATE_UNDERFLOW_GPST_F2P;
+
+ } else if (intPstate > PSTATE_MAX) {
+
+ *pstate = PSTATE_MAX;
+ rc = -PSTATE_OVERFLOW_GPST_F2P;
+
+ } else {
+
+ *pstate = intPstate;
+ rc = 0;
+ }
+
+ return rc;
+}
diff --git a/src/lib/pstates.h b/src/lib/pstates.h
new file mode 100755
index 0000000..3e4b1c9
--- /dev/null
+++ b/src/lib/pstates.h
@@ -0,0 +1,601 @@
+#ifndef __PSTATES_H__
+#define __PSTATES_H__
+
+// $Id: pstates.h,v 1.3 2014/05/27 15:35:05 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pstates.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pstates.h
+/// \brief Pstate structures and support routines for OCC product firmware
+
+#include "pgp_common.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Global and Local Pstate Tables
+////////////////////////////////////////////////////////////////////////////
+
+/// The Global Pstate Table must be 1KB-aligned in SRAM. The alignment is
+/// specified in the traditional log2 form.
+#define GLOBAL_PSTATE_TABLE_ALIGNMENT 10
+
+/// The Global Pstate table has 128 * 8-byte entries
+#define GLOBAL_PSTATE_TABLE_ENTRIES 128
+
+/// The Local Pstate table has 32 x 64-bit entries
+#define LOCAL_PSTATE_ARRAY_ENTRIES 32
+
+/// The VDS/VIN table has 32 x 64-bit entries
+#define VDSVIN_ARRAY_ENTRIES 64
+
+/// The VRM-11 VID base voltage in micro-Volts
+#define VRM11_BASE_UV 1612500
+
+/// The VRM-11 VID step as an unsigned number (micro-Volts)
+#define VRM11_STEP_UV 6250
+
+/// The iVID base voltage in micro-Volts
+#define IVID_BASE_UV 600000
+
+/// The iVID step as an unsigned number (micro-Volts)
+#define IVID_STEP_UV 6250
+
+/// CPM Inflection Points
+#define CPM_RANGES 8
+
+// Error/Panic codes for support routines
+
+#define VRM11_INVALID_VOLTAGE 0x00876101
+
+#define PSTATE_OVERFLOW_BIAS_PS 0x00778a01
+#define PSTATE_UNDERFLOW_BIAS_PS 0x00778a02
+#define PSTATE_OVERFLOW_GPST_F2P 0x00778a03
+#define PSTATE_UNDERFLOW_GPST_F2P 0x00778a04
+
+#define PSTATE_LT_PSTATE_MIN 0x00778a05
+#define PSTATE_GT_PSTATE_MAX 0x00778a06
+
+#define DPLL_OVERFLOW 0x00d75501
+#define DPLL_UNDERFLOW1 0x00d75502
+#define DPLL_UNDERFLOW2 0x00d75503
+
+#define VID11_OVERFLOW_VID11_VALIDATE 0x00843101
+#define VID11_OVERFLOW_BIAS_VID11 0x00843102
+#define VID11_UNDERFLOW_VID11_VALIDATE 0x00843103
+#define VID11_UNDERFLOW_BIAS_VID11 0x00843104
+
+#define GPST_INVALID_OBJECT_GPST_ENTRY 0x00477801
+#define GPST_INVALID_OBJECT_GPST_V2P 0x00477802
+#define GPST_INVALID_ARGUMENT 0x00477803
+#define GPST_INVALID_ENTRY 0x00477804
+#define GPST_PSTATE_CLIPPED_HIGH_GPSM_BGA 0x00477805
+#define GPST_PSTATE_CLIPPED_LOW_GPSM_BGA 0x00477806
+#define GPST_PSTATE_CLIPPED_HIGH_GPST_ENTRY 0x00477807
+#define GPST_PSTATE_CLIPPED_LOW_GPST_ENTRY 0x00477808
+#define GPST_PSTATE_CLIPPED_HIGH_GPST_V2P 0x00477809
+#define GPST_PSTATE_CLIPPED_LOW_GPST_V2P 0x0047780a
+#define GPST_BUG 0x0047780b
+#define GPST_PSTATE_GT_GPST_PMAX 0x0047780c
+
+#define LPST_INVALID_OBJECT 0x00477901
+#define LPST_GPST_WARNING 0x00477902
+#define LPST_INCR_CLIP_ERROR 0x00477903
+
+/// PstateSuperStructure Magic Number
+///
+/// This magic number identifies a particular version of the
+/// PstateSuperStructure and its substructures. The version number should be
+/// kept up to date as changes are made to the layout or contents of the
+/// structure.
+
+#define PSTATE_SUPERSTRUCTURE_MAGIC 0x5053544154453033ull /* PSTATE03 */
+#define PSTATE_SUPERSTRUCTURE_GOOD1 0x5053544154453031ull /* PSTATE01 */
+#define PSTATE_SUPERSTRUCTURE_GOOD2 0x5053544154453032ull /* PSTATE02 */
+#define PSTATE_SUPERSTRUCTURE_GOOD3 0x5053544154453033ull /* PSTATE03 */
+
+
+/// \defgroup pstate_options Pstate Options
+///
+/// These are flag bits for the \a options field of the PstateOptions
+/// structure.
+///
+/// @{
+
+/// gpsm_gpst_install() - Bypass copying the Pstate table from the
+/// PstateSuperStructure into the aligned global location.
+#define PSTATE_NO_COPY_GPST 0x01
+
+/// gpsm_gpst_install() - Bypass Global Pstate Table installation and setup.
+#define PSTATE_NO_INSTALL_GPST 0x02
+
+/// gpsm_lpsa_install() - Bylass Local Pstate Array installation and setup
+#define PSTATE_NO_INSTALL_LPSA 0x04
+
+/// gpsm_resclk_install - Bypass resonant clocking Pstate limit setup
+#define PSTATE_NO_INSTALL_RESCLK 0x08
+
+/// gpsm_enable_pstates() - Force the system to the minimum Pstate at
+/// initialization
+///
+/// This mode is added as a workaround for the case that the SPIVID interface
+/// is not working correctly during initial bringup. This forces Pstate mode
+/// to come up at a low frequency.
+#define PSTATE_FORCE_INITIAL_PMIN 0x10
+
+/// @}
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/// A Global Pstate Table Entry, in the form of a packed 'firmware register'
+///
+/// Global Pstate table entries are referenced by OCC firmware, for example
+/// in procedures that do 'manual' Pstate manipulation.
+
+typedef union gpst_entry {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t evid_vdd : 8;
+ uint64_t evid_vcs : 8;
+ uint64_t reserved16 : 1;
+ uint64_t evid_vdd_eff : 7;
+ uint64_t reserved24 : 1;
+ uint64_t evid_vcs_eff : 7;
+ uint64_t reserved32 : 1;
+ uint64_t maxreg_vdd : 7;
+ uint64_t reserved40 : 1;
+ uint64_t maxreg_vcs : 7;
+ uint64_t reserved48 : 8;
+ uint64_t ecc : 8;
+#else
+ uint64_t ecc : 8;
+ uint64_t reserved48 : 8;
+ uint64_t maxreg_vcs : 7;
+ uint64_t reserved40 : 1;
+ uint64_t maxreg_vdd : 7;
+ uint64_t reserved32 : 1;
+ uint64_t evid_vcs_eff : 7;
+ uint64_t reserved24 : 1;
+ uint64_t evid_vdd_eff : 7;
+ uint64_t reserved16 : 1;
+ uint64_t evid_vcs : 8;
+ uint64_t evid_vdd : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+
+} gpst_entry_t;
+
+
+/// A Local Pstate Table Entry, in the form of a packed 'firmware register'
+///
+/// This structure is provided for reference only; Currently the OCC firmware
+/// does not manupulate Local Pstate table entries, however it is possible
+/// that future lab applications will require this.
+
+typedef union lpst_entry {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivid_vdd : 7;
+ uint64_t ivid_vcs : 7;
+ uint64_t vdd_core_pwrratio : 6;
+ uint64_t vcs_core_pwrratio : 6;
+ uint64_t vdd_eco_pwrratio : 6;
+ uint64_t vcs_eco_pwrratio : 6;
+ uint64_t ps1_vid_incr : 3;
+ uint64_t ps2_vid_incr : 3;
+ uint64_t ps3_vid_incr : 3;
+ uint64_t reserved47 : 7;
+ uint64_t inc_step : 3;
+ uint64_t dec_step : 3;
+ uint64_t reserved60 : 4;
+#else
+ uint64_t reserved60 : 4;
+ uint64_t dec_step : 3;
+ uint64_t inc_step : 3;
+ uint64_t reserved47 : 7;
+ uint64_t ps3_vid_incr : 3;
+ uint64_t ps2_vid_incr : 3;
+ uint64_t ps1_vid_incr : 3;
+ uint64_t vcs_eco_pwrratio : 6;
+ uint64_t vdd_eco_pwrratio : 6;
+ uint64_t vcs_core_pwrratio : 6;
+ uint64_t vdd_core_pwrratio : 6;
+ uint64_t ivid_vcs : 7;
+ uint64_t ivid_vdd : 7;
+#endif // _BIG_ENDIAN
+ } fields;
+
+} lpst_entry_t;
+
+
+/// A VDS/VIN table Entry
+
+typedef union vdsvin_entry {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivid0 : 7;
+ uint64_t ivid1 : 7;
+ uint64_t reserved14 : 2;
+ uint64_t pfet0 : 5;
+ uint64_t pfet1 : 5;
+ uint64_t pfet2 : 5;
+ uint64_t pfet3 : 5;
+ uint64_t pfet4 : 5;
+ uint64_t pfet5 : 5;
+ uint64_t pfet6 : 5;
+ uint64_t pfet7 : 5;
+ uint64_t reserved_56 : 8;
+#else
+ uint64_t reserved_56 : 8;
+ uint64_t pfet7 : 5;
+ uint64_t pfet6 : 5;
+ uint64_t pfet5 : 5;
+ uint64_t pfet4 : 5;
+ uint64_t pfet3 : 5;
+ uint64_t pfet2 : 5;
+ uint64_t pfet1 : 5;
+ uint64_t pfet0 : 5;
+ uint64_t reserved14 : 2;
+ uint64_t ivid1 : 7;
+ uint64_t ivid0 : 7;
+#endif // _BIG_ENDIAN
+ } fields;
+} vdsvin_entry_t;
+
+/// Standard options controlling Pstate setup and GPSM procedures
+
+typedef struct {
+
+ /// Option flags; See \ref pstate_options
+ uint32_t options;
+
+ /// Pad structure to 8 bytes. Could also be used for other options later.
+ uint32_t pad;
+
+} PstateOptions;
+
+
+/// An abstract Global Pstate table
+///
+/// The GlobalPstateTable is an abstraction of a set of voltage/frequency
+/// operating points along with hardware limits. Besides the hardware global
+/// Pstate table, the abstract table contains enough extra information to make
+/// it the self-contained source for setting up and managing voltage and
+/// frequency in either Hardware or Firmware Pstate mode.
+///
+/// When installed in PMC, Global Pstate table indices are adjusted such that
+/// the defined Pstates begin with table entry 0. The table need not be full -
+/// the \a pmin and \a entries fields define the minimum and maximum Pstates
+/// represented in the table. However at least 1 entry must be defined to
+/// create a legal table.
+///
+/// Note that Global Pstate table structures to be mapped into PMC hardware
+/// must be 1KB-aligned. This requirement is fullfilled by ensuring that
+/// instances of this structure are 1KB-aligned.
+
+typedef struct {
+
+ /// The Pstate table
+ gpst_entry_t pstate[GLOBAL_PSTATE_TABLE_ENTRIES];
+
+ /// Pstate options
+ ///
+ /// The options are included as part of the GlobalPstateTable so that they
+ /// are available to all procedures after gpsm_initialize().
+ PstateOptions options;
+
+ /// The frequency associated with Pstate[0] in KHz
+ uint32_t pstate0_frequency_khz;
+
+ /// The frequency step in KHz
+ uint32_t frequency_step_khz;
+
+ /// The DPLL frequency code corresponding to Pstate 0
+ ///
+ /// This frequency code is installed in the PCB Slave as the DPLL Fnom
+ /// when the Pstate table is activated. Normally this frequency code is
+ /// computed as
+ ///
+ /// pstate0_frequency_khz / frequency_step_khz
+ ///
+ /// however it may be replaced by any other code as a way to
+ /// transparently bias frequency on a per-core basis.
+ DpllCode pstate0_frequency_code[PGP_NCORES];
+
+ /// The DPLL Fmax bias
+ ///
+ /// This bias value (default 0, range -8 to +7 frequency ticks) is
+ /// installed when the Pstate table is installed. The value is allowed to
+ /// vary per core. This bias value will usually be set to a small
+ /// positive number to provide a small amount of frequency headroom for
+ /// the CPM-DPLL voltage control algorithm.
+ ///
+ /// \bug Hardware currently specifies this field as unsigned for the
+ /// computation of frequency stability in
+ /// dpll_freqout_mode_en. (HW217404). This issue will be fixed in
+ /// Venice. Since we never plan to use this mode no workaround or
+ /// mitigation is provided by GPSM procedures.
+
+ int8_t dpll_fmax_bias[PGP_NCORES];
+
+ /// The number of entries defined in the table.
+ uint8_t entries;
+
+ /// The minimum Pstate in the table
+ ///
+ /// Note that gpsi_min = pmin - PSTATE_MIN, gpsi_max = pmin + entries - 1.
+ Pstate pmin;
+
+ /// The "Safe" Global Pstate
+ ///
+ /// This Pstate is installed in the PMC and represents the safe-mode
+ /// voltage.
+ Pstate pvsafe;
+
+ /// The "Safe" Local Pstate
+ ///
+ /// This Pstate is installed in the PCB Slaves and represents the
+ /// safe-mode frequency.
+ Pstate psafe;
+
+ /// Step size of Global Pstate steps
+ uint8_t pstate_stepsize;
+
+ /// The exponent of the exponential encoding of Pstate stepping delay
+ uint8_t vrm_stepdelay_range;
+
+ /// The significand of the exponential encoding of Pstate stepping delay
+ uint8_t vrm_stepdelay_value;
+
+ /// The Pstate for minimum core frequency in the system, defined by MRW
+ uint8_t pfloor;
+
+} GlobalPstateTable;
+
+
+/// This macro creates a properly-aligned Global Pstate table structure as a
+/// static initialization.
+
+#define GLOBAL_PSTATE_TABLE(x) \
+ GlobalPstateTable x \
+ ALIGNED_ATTRIBUTE(POW2_32(GLOBAL_PSTATE_TABLE_ALIGNMENT)) \
+ SECTION_ATTRIBUTE(".noncacheable") \
+ = {.entries = 0}
+
+
+/// An opaque Local Pstate Array
+///
+/// An array local to each core contains the Local Pstate Table, Vds table and
+/// Vin table. The array contents are presented to OCC firmware as an opaque
+/// set of 96 x 64-bit entries which are simply installed verbatim into each
+/// core. Every core stores the same table.
+///
+/// When installed in the core, Local Pstate table indices are adjusted such
+/// that the defined Pstates begin with table entry 0. The table need not be
+/// full - the \a pmin and \a entries fields define the minimum and maximum
+/// Pstates represented in the table. However at least 1 entry must be
+/// defined to create a legal table.
+
+typedef struct {
+
+ /// The vdsvin table contents
+ vdsvin_entry_t vdsvin[VDSVIN_ARRAY_ENTRIES];
+
+ /// The local pstate table contents
+ lpst_entry_t pstate[LOCAL_PSTATE_ARRAY_ENTRIES];
+
+ /// The number of entries defined in the Local Pstate Table
+ uint8_t entries;
+
+ /// The minimum Pstate in the Local Pstate table
+ ///
+ /// Note that lpsi_min = pmin - PSTATE_MIN, lpsi_max = pmin + entries - 1.
+ Pstate pmin;
+
+ /// Pstate step delay for rising iVRM voltages
+ uint8_t stepdelay_rising;
+
+ /// Pstate step delay for falling iVRM voltages
+ uint8_t stepdelay_lowering;
+
+ /// Pad structure to 8-byte alignment
+ uint8_t pad[4];
+
+} LocalPstateArray;
+
+
+/// Resonant Clocking setup parameters
+///
+/// All Pstate parameters are specified in terms of Pstates as defined in the
+/// current PstateSuperStructure.
+
+typedef struct {
+
+ /// Full Clock Sector Buffer Pstate
+ Pstate full_csb_ps;
+
+ /// Low-Frequency Resonant Lower Pstate
+ Pstate res_low_lower_ps;
+
+ /// Low-Frequency Resonant Upper Pstate
+ Pstate res_low_upper_ps;
+
+ /// High-Frequency Resonant Lower Pstate
+ Pstate res_high_lower_ps;
+
+ /// High-Frequency Resonant Upper Pstate
+ Pstate res_high_upper_ps;
+
+ /// Pad structure to 8-byte alignment
+ uint8_t pad[3];
+
+} ResonantClockingSetup;
+
+/// CPM Pstate ranges per mode
+///
+/// These Pstate range specifications apply to all chiplets operating in the
+/// same mode.
+
+typedef union {
+
+ /// Forces alignment
+ uint64_t quad[2];
+
+ struct {
+
+ /// Lower limit of each CPM calibration range
+ ///
+ /// The entries in this table are Pstates representing the
+ /// lowest-numbered (lowest-voltage) Pstate of each range. This is the
+ /// inflection point between range N and range N+1.
+ Pstate inflectionPoint[CPM_RANGES];
+
+ /// The number of ranges valid in the \a inflectionPoint table
+ ///
+ /// Validity here is defined by the original characterization
+ /// data. Whether or not OCC will use any particular range is managed
+ /// by OCC.
+ uint8_t validRanges;
+
+ /// The Pstate corresponding to the upper limit of range 0.
+ ///
+ /// This is the "CPmax" for the mode. The "CPmin" for this
+ /// mode is the value of inflectionPoint[valid_ranges - 1].
+ Pstate pMax;
+
+ uint8_t pad[6];
+ };
+
+} CpmPstateModeRanges;
+
+
+/// The layout of the data created by the Pstate table creation firmware
+///
+/// This structure is only used for passing Pstate data from the FSP into OCC,
+/// therefore there is no alignment requirement. The \gpst member is copied
+/// to an aligned location, and the \a lpsa and \a resclk members are directly
+/// installed in hardware.
+///
+/// Both the master and slave OCCs (in DCM-mode) install their Pstate tables
+/// independently via the API gpsm_initialize(). At that point the
+/// PstateSuperStructure can be discarded.
+
+typedef struct {
+
+ /// Magic Number
+ uint64_t magic;
+
+ /// Global Pstate Table
+ GlobalPstateTable gpst;
+
+ /// Local Pstate Array
+ LocalPstateArray lpsa;
+
+ /// Resonant Clocking Setup
+ ResonantClockingSetup resclk;
+
+ /// CPM Pstate ranges
+ CpmPstateModeRanges cpmranges;
+
+} PstateSuperStructure;
+
+
+int
+vid11_validate(Vid11 vid);
+
+int
+bias_pstate(Pstate pstate, int bias, Pstate* biased_pstate);
+
+int
+bias_frequency(DpllCode fcode, int bias, DpllCode* biased_fcode);
+
+int
+bias_vid11(Vid11 vid, int bias, Vid11* biased_fcode);
+
+int
+gpst_entry(const GlobalPstateTable* gpst,
+ const Pstate pstate,
+ const int bias,
+ gpst_entry_t* entry);
+
+int
+gpst_frequency2pstate(const GlobalPstateTable* gpst,
+ const uint32_t frequency_khz,
+ Pstate* pstate);
+
+int
+gpst_vdd2pstate(const GlobalPstateTable* gpst,
+ const uint8_t vdd,
+ Pstate* pstate,
+ gpst_entry_t* entry);
+
+
+/// Return the Pmin value associated with a GlobalPstateTable
+static inline Pstate
+gpst_pmin(const GlobalPstateTable* gpst)
+{
+ return gpst->pmin;
+}
+
+
+/// Return the Pmax value associated with a GlobalPstateTable
+static inline Pstate
+gpst_pmax(const GlobalPstateTable* gpst)
+{
+ return (int)(gpst->pmin) + (int)(gpst->entries) - 1;
+}
+
+/// Return the Pmin value associated with a LocalPstateTable
+static inline Pstate
+lpst_pmin(const LocalPstateArray* lpsa)
+{
+ return lpsa->pmin;
+}
+
+
+/// Return the Pmax value associated with a GlobalPstateTable
+static inline Pstate
+lpst_pmax(const LocalPstateArray* lpsa)
+{
+ return (int)(lpsa->pmin) + (int)(lpsa->entries) - 1;
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PSTATES_H__ */
diff --git a/src/lib/puts.c b/src/lib/puts.c
new file mode 100755
index 0000000..ab24d6b
--- /dev/null
+++ b/src/lib/puts.c
@@ -0,0 +1,95 @@
+// $Id: puts.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/puts.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file puts.c
+/// \brief Implementation of puts(), fputs(), putchar(), fputc()
+///
+/// The implementations of these APIs are split out to save code space for
+/// applications that do not require them.
+
+#include "ssx_io.h"
+
+
+/// Put a character to a stream
+///
+/// The fputc() function writes the byte specified by \a c (converted to an
+/// unsigned char) to the stream pointed to by \a stream. On success, fputc()
+/// returns the value written, i.e., the \c unsigned \c char form of \a c.
+///
+/// The POSIX standard fputc() returns EOF on error; this version returns the
+/// negative error code of the underlying I/O error, which will also be set in
+/// the \a error field of the \a stream. Note that SSX may also be configured
+/// to panic in the event of an I/O error.
+
+int
+fputc(int c, FILE *stream)
+{
+ unsigned char uc = (unsigned char)c;
+ int rc = swrite(stream, (void *)(&uc), 1, 0);
+ if (rc < 0) {
+ return rc;
+ } else {
+ return uc;
+ }
+}
+
+
+/// Put a string to a stream
+///
+/// The fputs() function writes the null-terminated string \a s to the stream
+/// pointed to by \a stream. The terminating null byte is not written. On
+/// success, fputs() returns 0.
+///
+/// The POSIX standard fputc() returns EOF on error; this version returns the
+/// negative error code of the underlying I/O error, which will also be set in
+/// the \a error field of the \a stream. Note that SSX may also be configured
+/// to panic in the event of an I/O error.
+
+int
+fputs(const char *s, FILE *stream)
+{
+ return swrite(stream, s, strlen(s), 0);
+}
+
+/// Put a string to \c stdout
+///
+/// The puts() function writes the null-terminated string \a s followed by a
+/// newline to \a stdout. The terminating null byte is not written. On
+/// success, puts() returns 0.
+///
+/// The POSIX standard fputc() returns EOF on error; this version returns the
+/// negative error code of the underlying I/O error, which will also be set in
+/// the \a error field of the \a stream. Note that SSX may also be configured
+/// to panic in the event of an I/O error.
+
+int
+puts(const char *s)
+{
+ int rc = fputs(s, stdout);
+ if (rc < 0) {
+ return rc;
+ } else {
+ rc = fputc('\n', stdout);
+ if (rc < 0) {
+ return rc;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+/// Put a character to \a stdout.
+///
+/// \c putchar(c) is equivalent to <c> fputc(c, stdout) </c>.
+
+int
+putchar(int c)
+{
+ return fputc(c, stdout);
+}
diff --git a/src/lib/simics_stdio.c b/src/lib/simics_stdio.c
new file mode 100755
index 0000000..5c276a2
--- /dev/null
+++ b/src/lib/simics_stdio.c
@@ -0,0 +1,150 @@
+// $Id: simics_stdio.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/simics_stdio.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file simics_stdio.c
+/// \brief SSX I/O drivers for Simics stdio streams
+///
+/// The Simics 'stdio' component is a pseudo serial port for I/O to stdio,
+/// stdout and stderr, as well as to other configurable streams. Each virtual
+/// file potentially has a read port, write port and flush port.
+///
+/// The write ports accept 1, 2 and 4-byte transactions on a 32-bit OCI
+/// address and write the data to the associated stream. Writing any value to
+/// the flush port flushes the output stream. The input ports are not yet
+/// implemented.
+
+#include "ssx.h"
+#include "simics_stdio.h"
+
+
+SimicsStdio simics_stdin;
+SimicsStdio simics_stdout;
+SimicsStdio simics_stderr;
+
+int
+simics_stdio_sread(FILE *stream, void *buf, size_t count, size_t *read)
+{
+ SSX_PANIC(ENXIO);
+ return -ENXIO;
+}
+
+
+int
+simics_stdio_swrite(FILE *stream, const void *buf,
+ size_t count, size_t *written)
+{
+ SimicsStdio *simics = (SimicsStdio *)stream;
+ size_t n;
+
+ n = count;
+ while (n) {
+ if (n >= 4) {
+ out32(simics->write_address, *((uint32_t *)buf));
+ buf += 4;
+ n -= 4;
+ } else if (n >= 2) {
+ out16(simics->write_address, *((uint16_t *)buf));
+ buf += 2;
+ n -= 2;
+ } else {
+ out8(simics->write_address, *((uint8_t *)buf));
+ buf++;
+ n--;
+ }
+ }
+
+ *written = count;
+
+ return 0;
+}
+
+
+ssize_t
+simics_stdio_fflush(FILE *stream)
+{
+ SimicsStdio *simics = (SimicsStdio *)stream;
+
+ out8(simics->flush_address, 0);
+ return 0;
+}
+
+
+/// Create a SimicsStdio stream
+///
+/// Any of the \a read_address, \a write_address or \a flush_address which are
+/// non-0 specify that the stream supports the associated method. The Simics
+/// I/O drivers do not require locking.
+
+int
+simics_stdio_create(SimicsStdio* stream,
+ SsxAddress read_address,
+ SsxAddress write_address,
+ SsxAddress flush_address)
+{
+ FILE *base = (FILE *)stream;
+ int rc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(stream == 0, EBADF);
+ }
+
+ rc = FILE_create((FILE*)stream, 0);
+
+ if (!rc) {
+
+ stream->read_address = read_address;
+ if (read_address != 0) {
+ base->sread = simics_stdio_sread;
+ }
+
+ stream->write_address = write_address;
+ if (write_address != 0) {
+ base->swrite = simics_stdio_swrite;
+ }
+
+ stream->flush_address = flush_address;
+ if (flush_address != 0) {
+ base->fflush = simics_stdio_fflush;
+ }
+ }
+
+ return rc;
+}
+
+
+int
+simics_stdin_create(SimicsStdio *stream)
+{
+ return simics_stdio_create(stream, SIMICS_STDIN, 0, 0);
+}
+
+
+int
+simics_stdout_create(SimicsStdio *stream)
+{
+ return simics_stdio_create(stream, 0, SIMICS_STDOUT, SIMICS_STDOUT_FLUSH);
+}
+
+int
+simics_stderr_create(SimicsStdio *stream)
+{
+ return simics_stdio_create(stream, 0, SIMICS_STDERR, SIMICS_STDERR_FLUSH);
+}
+
+int
+simics_stdfile_create(SimicsStdio *stream, int fn)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((fn < 0) > (fn >= SIMICS_STDFILE_STREAMS), EBADF);
+ }
+
+ return simics_stdio_create(stream,
+ SIMICS_STDFILE_READ(fn),
+ SIMICS_STDFILE_WRITE(fn),
+ SIMICS_STDFILE_FLUSH(fn));
+}
diff --git a/src/lib/simics_stdio.h b/src/lib/simics_stdio.h
new file mode 100755
index 0000000..abbfe26
--- /dev/null
+++ b/src/lib/simics_stdio.h
@@ -0,0 +1,69 @@
+#ifndef __SIMICS_STDIO_H__
+#define __SIMICS_STDIO_H__
+
+// $Id: simics_stdio.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/simics_stdio.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file simics_stdio.h
+/// \brief SSX I/O implementations for Simics stdio streams
+
+#include "ssx_io.h"
+#include "simics_stdio_addresses.h"
+#include "string.h"
+
+/// A FILE structure for a Simics fake stdio stream
+
+typedef struct {
+
+ /// The base class
+ FILE stream;
+
+ /// The MMIO address of the Simics read port for the stream
+ SsxAddress read_address;
+
+ /// The MMIO address of the Simics write port for the stream
+ SsxAddress write_address;
+
+ /// The MMIO address of the Simics device for flushing the stream;
+ SsxAddress flush_address;
+
+} SimicsStdio;
+
+extern SimicsStdio simics_stdin;
+extern SimicsStdio simics_stdout;
+extern SimicsStdio simics_stderr;
+
+int
+simics_stdio_create(SimicsStdio* stream,
+ SsxAddress read_address,
+ SsxAddress write_address,
+ SsxAddress flush_address);
+
+int
+simics_stdin_create(SimicsStdio *stream);
+
+int
+simics_stdout_create(SimicsStdio *stream);
+
+int
+simics_stderr_create(SimicsStdio *stream);
+
+int
+simics_stdfile_create(SimicsStdio *stream, int fn);
+
+int
+simics_stdio_sread(FILE *stream, void *buf, size_t count, size_t *read);
+
+int
+simics_stdio_swrite(FILE *stream, const void *buf,
+ size_t count, size_t *written);
+
+int
+simics_stdio_sflush(FILE *stream);
+
+#endif /* __SIMICS_STDIO_H__ */
diff --git a/src/lib/simics_stdio_addresses.h b/src/lib/simics_stdio_addresses.h
new file mode 100755
index 0000000..9f7d886
--- /dev/null
+++ b/src/lib/simics_stdio_addresses.h
@@ -0,0 +1,67 @@
+#ifndef __SIMICS_STDIO_ADDRESSES_H__
+#define __SIMICS_STDIO_ADDRESSES_H__
+
+// $Id: simics_stdio_addresses.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/simics_stdio_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file simics_stdio_adresses.h
+/// \brief MMIO addresses and offsets of the Simics fake stdio model
+///
+/// The Simics 'stdio' component is a pseudo serial port for I/O to stdio,
+/// stdout and stderr, as well as to other configurable streams. Each virtual
+/// file potentially has a read port, write port and flush port.
+///
+/// The write ports accept 1, 2 and 4-byte transactions on a 32-bit OCI
+/// address and write the data to the associated stream. Writing any value to
+/// the flush port flushes the output stream. The input ports are not yet
+/// implemented.
+
+// -*- This header is maintained as part of the PMX Simics model. -*-
+// -*- Do not edit in the SSX library as your edits will be lost. -*-
+
+#define SIMICS_STDIO_BASE 0x40060000
+
+#define SIMICS_STDIN_OFFSET 0x00
+#define SIMICS_STDOUT_OFFSET 0x04
+#define SIMICS_STDOUT_FLUSH_OFFSET 0x08
+#define SIMICS_STDERR_OFFSET 0x0c
+#define SIMICS_STDERR_FLUSH_OFFSET 0x10
+
+#define SIMICS_STDFILE_0_OFFSET 0x14
+#define SIMICS_STDFILE_1_OFFSET 0x20
+#define SIMICS_STDFILE_2_OFFSET 0x2c
+#define SIMICS_STDFILE_3_OFFSET 0x38
+
+#define SIMICS_STDFILE_STREAMS 4
+
+#define SIMICS_STDIN (SIMICS_STDIO_BASE + SIMICS_STDIN_OFFSET)
+#define SIMICS_STDOUT (SIMICS_STDIO_BASE + SIMICS_STDOUT_OFFSET)
+#define SIMICS_STDOUT_FLUSH (SIMICS_STDIO_BASE + SIMICS_STDOUT_FLUSH_OFFSET)
+#define SIMICS_STDERR (SIMICS_STDIO_BASE + SIMICS_STDERR_OFFSET)
+#define SIMICS_STDERR_FLUSH (SIMICS_STDIO_BASE + SIMICS_STDERR_FLUSH_OFFSET)
+
+#define SIMICS_STDFILE_READ_OFFSET(fn) \
+ (SIMICS_STDFILE_0_OFFSET + (12 * fn) + 0x00)
+
+#define SIMICS_STDFILE_WRITE_OFFSET(fn) \
+ (SIMICS_STDFILE_0_OFFSET + (12 * fn) + 0x04)
+
+#define SIMICS_STDFILE_FLUSH_OFFSET(fn) \
+ (SIMICS_STDFILE_0_OFFSET + (12 * fn) + 0x08)
+
+#define SIMICS_STDFILE_READ(fn) \
+ (SIMICS_STDIO_BASE + SIMICS_STDFILE_READ_OFFSET(fn))
+
+#define SIMICS_STDFILE_WRITE(fn) \
+ (SIMICS_STDIO_BASE + SIMICS_STDFILE_WRITE_OFFSET(fn))
+
+#define SIMICS_STDFILE_FLUSH(fn) \
+ (SIMICS_STDIO_BASE + SIMICS_STDFILE_FLUSH_OFFSET(fn))
+
+
+#endif /* __SIMICS_STDIO_ADDRESSES_H__ */
diff --git a/src/lib/special_wakeup.c b/src/lib/special_wakeup.c
new file mode 100644
index 0000000..59e3274
--- /dev/null
+++ b/src/lib/special_wakeup.c
@@ -0,0 +1,149 @@
+// $Id: special_wakeup.c,v 1.4 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/special_wakeup.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file special_wakeup.c
+/// \brief Container for special wakeup related procedures
+
+#include "special_wakeup.h"
+
+uint32_t G_special_wakeup_count[PGP_NCORES] = {0};
+
+/// Enter or clear special wakeup for a core
+///
+/// \param set 1 = set, 0 = clear, all other values will cause an error.
+///
+/// \param cores = mask of cores to set/clear special wakeup.
+///
+/// \param[out] o_timeouts. Mask of cores that timed out before special wakeup
+/// complete was observed.
+///
+/// \retval 0 Success
+///
+/// \retval -SPWU_INVALID_ARGUMENT One of the arguments was invalid in some way
+///
+/// \retval others This API may also return non-0 codes from
+/// getscom()/putscom()
+///
+/// If getscom/putscom rc = 0, the state of the global special_wakeup counts
+/// may no longer be valid.
+///
+
+int
+occ_special_wakeup(int set,
+ ChipConfigCores cores,
+ int timeout_ms,
+ ChipConfigCores *o_timeouts)
+
+{
+
+ pmc_core_deconfiguration_reg_t pcdr;
+ pcbs_pmgp0_reg_t pmgp0;
+ pcbs_pmspcwkupocc_reg_t ppr;
+ ChipConfigCores core_list;
+ ChipConfigCores awake_list = 0;
+ ChipConfigCores success_list = 0;
+ ChipConfigCores poll_list = 0;
+ ChipConfigCores timeout_list = 0;
+ int rc, poll_count, core;
+ int time = 0;
+ int bad_clear;
+
+ // get pmc deconfig vector
+ pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG);
+
+ core_list = cores;
+ bad_clear = 0;
+ if (! set) {
+ for (core = 0; core < PGP_NCORES; core++, core_list <<=1) {
+ if (core_list & (0x1 << (PGP_NCORES - 1))) {
+ if (G_special_wakeup_count[core] == 0) {
+ bad_clear = 1;
+ }
+ }
+ }
+ }
+
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF( (set < 0) ||
+ (set > 1) ||
+ (bad_clear) ||
+ (pcdr.fields.core_chiplet_deconf_vector & cores),
+ SPWU_INVALID_ARGUMENT);
+ }
+
+ do {
+ ppr.value = 0;
+ if (set) {
+ // If count is currently zero, set the bit and increment count.
+ // Otherwise, just increment count
+ core_list = cores;
+ for (core = 0; core < PGP_NCORES; core++, core_list <<=1) {
+ if (core_list & (0x1 << (PGP_NCORES - 1))) {
+ if (! G_special_wakeup_count[core]) {
+ ppr.fields.occ_special_wakeup = 1;
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_PMSPCWKUPOCC_REG, core), ppr.value);
+ poll_list |= (0x1 << (PGP_NCORES - 1 - core));
+ }
+ if (rc) break; // break for loop
+ ++G_special_wakeup_count[core];
+ success_list |= (0x1 << (PGP_NCORES - 1 - core));
+ }
+ }
+ if (rc) break;
+
+ // poll special_wkup_done bit.
+ poll_count = 0;
+ while ((poll_list != awake_list) && (time < timeout_ms)) {
+ if (! poll_count) {
+ ssx_sleep(SSX_MICROSECONDS(2));
+ ++poll_count;
+ } else {
+ ssx_sleep(SSX_MILLISECONDS(5));
+ time += 5;
+ }
+ core_list = poll_list & (~awake_list);
+ for (core = 0; core < PGP_NCORES; core++, core_list <<=1) {
+ if (core_list & (0x1 << (PGP_NCORES - 1))) {
+ rc = getscom(CORE_CHIPLET_ADDRESS(PCBS_PMGP0_REG, core), &pmgp0.value);
+ if (rc) break;
+ if (pmgp0.fields.special_wkup_done) {
+ awake_list |= (0x1 << (PGP_NCORES - 1 - core));
+ } else {
+ if (time >= timeout_ms) {
+ timeout_list |= (0x1<<(PGP_NCORES-1-core));
+ }
+ }
+ }
+ }
+ }
+ } else { // clear special wakeup
+ core_list = cores;
+ for (core = 0; core < PGP_NCORES; core++, core_list <<=1) {
+ if (core_list & (0x1 << (PGP_NCORES - 1))) {
+ if (G_special_wakeup_count[core] == 1) {
+ ppr.fields.occ_special_wakeup = 0;
+ rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_PMSPCWKUPOCC_REG, core), ppr.value);
+ }
+ if (rc) break;
+ --G_special_wakeup_count[core];
+ success_list |= (0x1 << (PGP_NCORES - 1 - core));
+ }
+ }
+ if (rc) break;
+ }
+ } while (0);
+
+ // bad rc recovery (recovery of counts, etc?)
+
+ *o_timeouts = timeout_list;
+ return rc;
+
+}
+
+
diff --git a/src/lib/special_wakeup.h b/src/lib/special_wakeup.h
new file mode 100644
index 0000000..88b8ec0
--- /dev/null
+++ b/src/lib/special_wakeup.h
@@ -0,0 +1,32 @@
+#ifndef __SPECIAL_WAKEUP_H__
+#define __SPECIAL_WAKEUP_H__
+
+// $Id: special_wakeup.h,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/special_wakeup.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file special_wakeup.h
+/// \brief Container for special wakeup related procedures
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+#include "pgp_config.h"
+#include "ssx.h"
+
+#define SPWU_INVALID_ARGUMENT 0x00779801
+
+extern uint32_t G_special_wakeup_count[PGP_NCORES];
+
+int
+occ_special_wakeup(int set,
+ ChipConfigCores cores,
+ int timeout_ms,
+ ChipConfigCores *o_timeouts);
+
+#endif /* __ASEMBLER__ */
+#endif /* __SPECIAL_WAKEUP_H__ */
diff --git a/src/lib/sprintf.c b/src/lib/sprintf.c
new file mode 100755
index 0000000..458cd39
--- /dev/null
+++ b/src/lib/sprintf.c
@@ -0,0 +1,112 @@
+// $Id: sprintf.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/sprintf.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file sprintf.c \brief Implementations of sprintf() and snprintf() using
+/// StringStream.
+
+#include "ssx.h"
+#include "ssx_io.h"
+#include "string_stream.h"
+
+
+// sprintf() is easy - just blindly copy in the data.
+
+static int
+sprintf_swrite(FILE *stream, const void *buf, size_t size, size_t *written)
+{
+ StringStream *string = (StringStream *)stream;
+
+ memcpy((void *)(&(string->data[string->next_write])), buf, size);
+ string->next_write += size;
+ *written = size;
+ return 0;
+}
+
+
+// snprintf() requires that bytes that won't fit in the array are simply
+// discarded, but still accounted for. Note that vfprintf() is doing the
+// high-level accounting.
+
+static int
+snprintf_swrite(FILE *stream, const void *buf, size_t size, size_t *written)
+{
+ StringStream *string = (StringStream *)stream;
+
+ size_t to_write = MIN(size, string->size - string->next_write - 1);
+
+ memcpy((void *)(&(string->data[string->next_write])), buf, to_write);
+ string->next_write += to_write;
+ *written = size;
+ return 0;
+}
+
+
+// We use a StringStream to implement [v]sprintf() and [v]snprintf(). Once
+// the formatting is finished the NULL terminator is added.
+
+int
+vsprintf(char *str, const char *format, va_list argp)
+{
+ ssize_t rc;
+ StringStream stream;
+
+ _string_stream_create(&stream, str, 1, 0, sprintf_swrite);
+ rc = vfprintf((FILE *)(&stream), format, argp);
+ stream.data[stream.next_write] = 0;
+ return rc;
+}
+
+
+
+int
+sprintf(char *str, const char *format, ...)
+{
+ va_list argp;
+ ssize_t rc;
+
+ va_start(argp, format);
+ rc = vsprintf(str, format, argp);
+ va_end(argp);
+
+ return rc;
+}
+
+
+int
+vsnprintf(char *str, size_t size, const char *format, va_list argp)
+{
+ ssize_t rc;
+ StringStream stream;
+
+ if (size == 0) {
+ return 0;
+ }
+
+ _string_stream_create(&stream, str, size, 0, snprintf_swrite);
+ rc = vfprintf((FILE *)(&stream), format, argp);
+ stream.data[stream.next_write] = 0;
+ return rc;
+}
+
+
+int
+snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list argp;
+ ssize_t rc;
+
+ if (size == 0) {
+ return 0;
+ }
+
+ va_start(argp, format);
+ rc = vsnprintf(str, size, format, argp);
+ va_end(argp);
+
+ return rc;
+}
diff --git a/src/lib/ssx_dump.c b/src/lib/ssx_dump.c
new file mode 100644
index 0000000..93ce1ea
--- /dev/null
+++ b/src/lib/ssx_dump.c
@@ -0,0 +1,209 @@
+// $Id: ssx_dump.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ssx_dump.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_dump.c
+/// \brief Routines for dumping SSX kernel data structures
+///
+/// \note This is a quick hack to help solve a P8 bringup issue. This code is
+/// PPC405 (OCC) specific, i.e., not "portable" SSX. Ideally this type of dump
+/// would be implemented in an external debugging tool as well, however it's
+/// simplest to implement here in the execution context.
+
+#include "ssx_dump.h"
+
+#define SSX_DUMP_UNIMPLEMENTED 0x00d86701
+
+static const char* _threadState[] = {
+ 0,
+ "Suspended Runnable",
+ "Mapped",
+ "Suspended Blocked",
+ "Completed",
+ "Deleted",
+};
+
+static const char* _threadFlags[] = {
+ 0,
+ "Semaphore Pend",
+ "Timer Pend",
+ "Timer Pend | Semaphore Pend",
+ "Timed Out",
+ "Timed Out | Semaphore Pend",
+ "Timed Out | Timer Pend",
+ "Timed Out | Timer Pend | Semaphore Pend",
+};
+
+
+static void
+_dumpTimer(FILE* stream, SsxTimer* timer)
+{
+ fprintf(stream,
+ "-- Timer @ %p\n"
+ "-- Deque.previous = %p\n"
+ "-- Deque.next = %p\n"
+ "-- Timeout = 0x%016llx\n"
+ "-- Period = 0x%016llx\n"
+ "-- Callback = %p\n"
+ "-- Arg = %p\n"
+ "-- Options = 0x%02x\n",
+ timer,
+ timer->deque.previous,
+ timer->deque.next,
+ timer->timeout,
+ (unsigned long long)(timer->period),
+ timer->callback,
+ timer->arg,
+ timer->options);
+}
+
+
+static void
+_dumpThread(FILE* stream, SsxThread* thread)
+{
+ SsxThreadContext* threadCtx;
+ SsxThreadContextFullIrq* threadCtxIrq;
+ uint32_t srr[4], lr, sp;
+
+ fprintf(stream,
+ "-- Thread mapped at priority %d (%p)\n"
+ "-- Thread state = %s (%d)\n"
+ "-- Thread flags = %s (0x%02x)\n"
+ "-- Saved Stack Pointer = %p\n",
+ thread->priority, thread,
+ _threadState[thread->state], thread->state,
+ _threadFlags[thread->flags], thread->flags,
+ (void*)thread->saved_stack_pointer);
+
+ if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) {
+
+ fprintf(stream,
+ "-- Semaphore = %p\n",
+ (void*)thread->semaphore);
+ }
+ fprintf(stream,
+ "---------------------------------------------\n");
+
+ if (thread->flags & SSX_THREAD_FLAG_TIMER_PEND) {
+
+ _dumpTimer(stream, &(thread->timer));
+ fprintf(stream,
+ "---------------------------------------------\n");
+ }
+
+ if ((thread == ssx_current()) && !__ssx_kernel_context_any_interrupt()) {
+
+ fprintf(stream,
+ "-- This thread is executing ssx_dump()\n");
+
+ } else {
+
+ if (thread == ssx_current()) {
+
+ // This is the interrupted thread, and only has its volatile
+ // context saved. The thread stack pointer is stored in a global
+ // kernel variable.
+
+ if (__ssx_kernel_context_critical_interrupt()) {
+
+ SSX_PANIC(SSX_DUMP_UNIMPLEMENTED);
+ srr[0] = srr[1] = srr[2] = srr[3] = lr = sp = 0; /* For GCC */
+
+ } else {
+
+ threadCtxIrq =
+ (SsxThreadContextFullIrq*)__ssx_saved_sp_noncritical;
+ srr[0] = threadCtxIrq->srr0;
+ srr[1] = threadCtxIrq->srr1;
+ srr[2] = threadCtxIrq->srr2;
+ srr[3] = threadCtxIrq->srr3;
+ lr = threadCtxIrq->lr;
+ sp = threadCtxIrq->r1;
+ }
+ } else {
+
+ // This is a fully swapped-out thread. The context is saved in
+ // at the stored stack pointer.
+
+ threadCtx = (SsxThreadContext*)(thread->saved_stack_pointer);
+ srr[0] = threadCtx->srr0;
+ srr[1] = threadCtx->srr1;
+ srr[2] = threadCtx->srr2;
+ srr[3] = threadCtx->srr3;
+ lr = threadCtx->lr;
+ sp = ((uint32_t*)threadCtx->r1)[0];
+ }
+
+ fprintf(stream,
+ "-- SRR0: 0x%08x SRR1: 0x%08x "
+ "SRR2: 0x%08x SRR3: 0x%08x\n"
+ "-- LR: 0x%08x\n",
+ srr[0], srr[1], srr[2], srr[3],
+ lr);
+
+ fprintf(stream,
+ "---------------------------------------------\n");
+
+ // Unwind the stack
+
+ while (sp != 0) {
+
+ fprintf(stream,
+ "-- SP: 0x%08x *LR*:0x%08x\n",
+ sp, ((uint32_t*)sp)[1]);
+ sp = ((uint32_t*)sp)[0];
+ }
+ }
+}
+
+
+
+
+void
+ssx_dump(FILE* stream, int options)
+{
+ int i, sep;
+ SsxThread* thread;
+
+ fprintf(stream,
+ "------------------------------------------------------------\n");
+ fprintf(stream,
+ "-- SSX Kernel Dump @ 0x%016llx\n"
+ "-- USPRG0 = 0x%08x\n"
+ "-- __ssx_run_queue = 0x%08x\n",
+ ssx_timebase_get(),
+ mfspr(SPRN_USPRG0),
+ __ssx_run_queue);
+ fprintf(stream,
+ "------------------------------------------------------------\n");
+
+ sep = 0;
+
+ for (i = 0; i < SSX_THREADS; i++) {
+
+ ssx_thread_at_priority(i, &thread);
+ if (thread) {
+ if (sep) {
+ fprintf(stream,
+ "*********************************************\n");
+ }
+ _dumpThread(stream, thread);
+ sep = 1;
+ }
+ }
+
+ fprintf(stream,
+ "------------------------------------------------------------\n");
+}
+
+
+
+
+
+
+
+
diff --git a/src/lib/ssx_dump.h b/src/lib/ssx_dump.h
new file mode 100644
index 0000000..17455c0
--- /dev/null
+++ b/src/lib/ssx_dump.h
@@ -0,0 +1,58 @@
+#ifndef __SSX_DUMP_H__
+#define __SSX_DUMP_H__
+
+// $Id: ssx_dump.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ssx_dump.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_dump.h
+/// \brief Routines for dumping SSX kernel data structures
+
+#include "ssx.h"
+
+/// \defgroup ssx_dump_options Options for ssx_dump()
+///
+/// No options are currently specified.
+///
+/// @{
+
+/// @}
+
+#ifndef __ASSEMBLER__
+
+/// Dump the kernel state
+///
+/// \param i_stream The stream to receive the dump. If the dump is being
+/// generated prior to a kernel panic then this would typically be \a ssxout,
+/// the stream used by printk.
+///
+/// \param i_options AN OR-mask of option flags; See \ref ssx_dump_options
+///
+/// The SSX kernel dump produces a formatted snapshot of the state of the
+/// kernel and the mapped threads. This API does not manipulate the machine
+/// context; If it is required to produce a precise snapshot then the caller
+/// will need to make the call from a critical section.
+///
+/// The following information is standard in the dump
+///
+/// - The interrupt and thread state of the kernel
+/// - The state of each thread
+/// - A stack trace for each thread
+///
+/// Options : TBD
+///
+/// \bug There are likely several bugs in the current implementation due to
+/// the assumption that the code is being called from a state in which the
+/// kernel context is not changing. We don't have time to code and test the
+/// most general implementation now. To guarantee correct operation the API
+/// must currently be called from an SSX_CRITICAL critical section.
+void
+ssx_dump(FILE* stream, int options);
+
+#endif // __ASSEMBLER__
+
+#endif // __SSX_DUMP_H__
diff --git a/src/lib/ssx_io.c b/src/lib/ssx_io.c
new file mode 100755
index 0000000..e69dcbe
--- /dev/null
+++ b/src/lib/ssx_io.c
@@ -0,0 +1,311 @@
+// $Id: ssx_io.c,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ssx_io.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_io.c
+/// \brief SSX analog-replacement for C \<stdio.h\> and \<unistd.h\> functions
+///
+/// The SSX library provides simple analogs for I/O functions found in the
+/// typical C libraries and Posix standards. I/O is not considered part of the
+/// SSX kernel per-se - I/O is implemented by the application creating I/O
+/// abstractions and drivers using the simple SSX kernel services. [However,
+/// the ssx_io library does provide a printk() function for use by kernel
+/// drivers, so the lines are not completely clear.]
+///
+/// This library provides a FILE structure or 'base class' to represent a
+/// character stream. Abstractions for different devices will 'derive' a
+/// subclass from this base class by including the FILE as the first member of
+/// the subclass, and then likely adding more data members. The FILE
+/// structure contains pointers to the routines that implement I/O operations
+/// for derived classes. There is no requiremengt that a stream type implement
+/// every possible stream operation. If an unsupported operation is invoked
+/// on a stream then the call will simply return -ENXIO, unless otherwise
+/// specified.
+///
+/// The generic I/O calls use the same error-handling protocol as used by the
+/// SSX kernel services. A configuration setting (\c SSX_ERROR_CHECK_API)
+/// determines if error checks are made at all, and another setting (\c
+/// SSX_ERROR_PANIC) determines whether the presence of a fatal error causes a
+/// bad return code or an immediate panic.
+///
+/// The following errors are never considered fatal errors:
+///
+/// \b EOF Used to signal end-of-file
+///
+/// \b EAGAIN Used to signal that an operation was made to a non-blocking
+/// stream and the call would block.
+///
+/// Following are the specifications and requirements for the stream methods
+/// that implement a stream type.
+///
+/// <b> int sread(FILE *stream, void *buf, size_t count, size_t *read) </b>
+///
+/// The low-level read() function is named sread() here due to differences in
+/// the prototype and semantics from the Unix counterpart. The sread()
+/// functions attempts to read \a count bytes from the \a stream into \a buf,
+/// sets the number of bytes read, and returns either 0 for success or a
+/// negative error code. The only reason that sread() may terminate without
+/// reading \a count bytes is if sread() also returns a negative return
+/// code.
+///
+/// The device-specific sread() function may assume that the \a stream, \a buf
+/// and \a read parameters are non-NULL at entry, and the \a count is greater
+/// than 0. These conditions are checked/guaranteed by the generic interface.
+///
+/// <b> int swrite(FILE *stream, void *buf, size_t count, size_t *written) </b>
+///
+/// The low-level write() function is named swrite() here due to differences
+/// in the prototype and semantics from the Unix counterpart. The swrite()
+/// function attempts to writes \a count bytes from buf to the \a stream, sets
+/// the number of bytes written, and returns either 0 for success or a
+/// negative error code. The only reason that swrite() may terminate without
+/// writing \a count bytes is if write() also returns a negative return
+/// code.
+///
+/// The device-specific swrite() function may assume that the \a stream, \a
+/// buf and \a written parameters are non-NULL at entry, and the \a count is
+/// greater than 0. These conditions are checked/guaranteed by the generic
+/// interface.
+///
+/// <b> int fflush(FILE *stream) </b>
+///
+/// SSX implements the fflush() call, even though the semantics are slightly
+/// different from the Posix standard. The Posix fflush() returns either 0
+/// for success, or EOF to indicate an error. Here, fflush() returns negative
+/// 'errno' codes directly in the event of errors. The Posix standard
+/// specifies that calling fflush() with a NULL \a stream causes all open
+/// files to be flushed - here it returns the -EBADF error.
+///
+/// The stream-specific fflush() implementation should return one of the
+/// 'errno' codes specified by the Posix standard in the event of
+/// problems.
+
+#include "ssx.h"
+#include "ssx_io.h"
+
+/// Initialize an SSX I/O FILE structure
+///
+/// \param file A pointer to an uninitialized FILE
+///
+/// \param flags Flags for the generic FILE
+///
+/// This API is designed to be called from "constructors of classes derived
+/// from FILE", e.g., the StringStream. The generic FILE structure is
+/// cleared, and the flags are installed and other initialization based on the
+/// flags is performed. The subclass constructors then install function
+/// pointers for any of the FILE functions that they implement.
+///
+/// \retval 0 Success
+///
+/// \retval -FILE_INVALID_OBJECT The \a file pointer is null (0).
+///
+/// \retval -FILE_INVALID_ARGUMENT The \a flags are not valid.
+
+int
+FILE_create(FILE* file, int flags)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(file == 0, FILE_INVALID_OBJECT);
+ SSX_ERROR_IF(flags & ~SSX_FILE_VALID_FLAGS, FILE_INVALID_ARGUMENT);
+ SSX_ERROR_IF(__builtin_popcount(flags & SSX_FILE_OP_LOCK_OPTIONS) > 1,
+ FILE_INVALID_ARGUMENT);
+ }
+ memset((void*)file, 0, sizeof(FILE));
+ file->flags = flags;
+ ssx_semaphore_create(&(file->fop_sem), 1, 1);
+ return 0;
+}
+
+
+/// Assign an error code to a stream, returning a non-zero value for errors
+/// considered fatal.
+
+int
+ssx_io_error_set(FILE *stream, int code)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(stream == 0, EBADF);
+ }
+ stream->error = code;
+ if ((code == EOF) ||
+ (code == EAGAIN)) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+
+static int
+null_stream_sread(FILE *stream, void *buf, size_t count, size_t *read)
+{
+ *read = 0;
+ ssx_io_error_set(stream, EOF);
+ return EOF;
+}
+
+
+static int
+null_stream_swrite(FILE *stream, const void *buf, size_t count, size_t *written)
+{
+ *written = count;
+ return 0;
+}
+
+
+static int
+null_stream_fflush(FILE *stream)
+{
+ return 0;
+}
+
+
+/// A null stream; equivalent to Unix /dev/null
+///
+/// This stream is statically initialized as it is required to be assigned to
+/// \a ssxout at load time. The NULL stream does not require any locking.
+
+FILE _null_stream = {
+ .sread = null_stream_sread,
+ .swrite = null_stream_swrite,
+ .fflush = null_stream_fflush,
+ .error = 0,
+ .flags = 0
+};
+
+
+// It's up to the application to initialize the standard streams if it wishes
+// to use them. Reading or writing a NULL stream will signal an error.
+
+FILE *stdin = 0;
+FILE *stdout = 0;
+FILE *stderr = 0;
+
+/// Stream used by printk()
+///
+/// \a ssxout is the stream used by printk(). \a ssxout \e must be assigned
+/// to a non-blocking stream as it may be called from interrupt handlers. \a
+/// ssxout defaults to _null_stream, the equivalent of Unix' /dev/null.
+
+FILE *ssxout = &_null_stream;
+
+
+/// /dev/null for SSX
+FILE* ssxnull = &_null_stream;
+
+
+/// Lock low-level file operations
+///
+/// The decision on if and how low-level FILE operations needs to be locked is
+/// made by the class derived from FILE, and may also require an argument
+/// about its intended use. The minimum bar is always correctness. The next
+/// bar is whether the application allows data from multiple writers to be
+/// intermixed, or allows multiple readers to access the same input stream.
+///
+/// A device like the StringStream used to implement sprintf() and snprintf()
+/// does not require locking at all because it is only called from a single
+/// context. String streams that implement circular buffers must be locked if
+/// there is the possibility of multiple readers or writers, and the wrapping
+/// buffer always needs to be locked.
+///
+/// The lock implemented here is a lock on the low-level stream operations
+/// sread(), swrite() and fflush().
+
+#define LOCK_FILE_OPERATION(stream, operation) \
+ ({ \
+ int __rc; \
+ SsxMachineContext __ctx = SSX_THREAD_MACHINE_CONTEXT_DEFAULT; /* GCC */ \
+ if ((stream)->flags & SSX_FILE_OP_LOCK_OPTIONS) { \
+ if ((stream)->flags & SSX_FILE_OP_LOCK_CRITICAL) { \
+ ssx_critical_section_enter(SSX_CRITICAL, &__ctx); \
+ } else if ((stream)->flags & SSX_FILE_OP_LOCK_NONCRITICAL) { \
+ ssx_critical_section_enter(SSX_NONCRITICAL, &__ctx); \
+ } else { \
+ ssx_semaphore_pend(&((stream)->fop_sem), SSX_WAIT_FOREVER); \
+ } \
+ } \
+ __rc = (operation); \
+ if ((stream)->flags & SSX_FILE_OP_LOCK_OPTIONS) { \
+ if ((stream)->flags & (SSX_FILE_OP_LOCK_CRITICAL | \
+ SSX_FILE_OP_LOCK_NONCRITICAL)) { \
+ ssx_critical_section_exit(&__ctx); \
+ } else { \
+ ssx_semaphore_post(&((stream)->fop_sem)); \
+ } \
+ } \
+ __rc; \
+ })
+
+
+/// Call the sread() operation of a stream
+
+int
+sread(FILE *stream, void *buf, size_t count, size_t *read)
+{
+ ssize_t rc;
+ size_t _read;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((stream == 0), EBADF);
+ SSX_IO_ERROR_IF(stream, (stream->sread == 0), ENXIO);
+ SSX_IO_ERROR_IF(stream, (buf == 0), EINVAL);
+ }
+ if (count == 0) {
+ if (read != 0) {
+ *read = 0;
+ }
+ return 0;
+ }
+ rc = LOCK_FILE_OPERATION(stream, stream->sread(stream, buf, count, &_read));
+ if (read != 0) {
+ *read = _read;
+ }
+ return rc;
+}
+
+
+/// Call the swrite() operation of a stream
+
+ssize_t
+swrite(FILE *stream, const void *buf, size_t count, size_t *written)
+{
+ ssize_t rc;
+ size_t _written;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((stream == 0), EBADF);
+ SSX_IO_ERROR_IF(stream, (stream->swrite == 0), ENXIO);
+ SSX_IO_ERROR_IF(stream, (buf == 0), EINVAL);
+ }
+ if (count == 0) {
+ rc = 0;
+ _written = 0;
+ } else {
+ rc = LOCK_FILE_OPERATION(stream,
+ stream->swrite(stream, buf, count, &_written));
+ }
+ if (written != 0) {
+ *written = _written;
+ }
+ return rc;
+}
+
+
+/// Call the fflush() operation of the stream
+
+int
+fflush(FILE *stream)
+{
+ int rc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_IO_ERROR_IF(stream, (stream == 0), EBADF);
+ SSX_IO_ERROR_IF(stream, (stream->fflush == 0), ENXIO);
+ }
+ rc = LOCK_FILE_OPERATION(stream, stream->fflush(stream));
+ return rc;
+}
diff --git a/src/lib/ssx_io.h b/src/lib/ssx_io.h
new file mode 100755
index 0000000..794fe5d
--- /dev/null
+++ b/src/lib/ssx_io.h
@@ -0,0 +1,204 @@
+#ifndef __SSX_IO_H__
+#define __SSX_IO_H__
+
+// $Id: ssx_io.h,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ssx_io.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_io.h
+/// \brief SSX analog-replacement for C <stdio.h> and <unistd.h> functions
+
+#if !defined(_STDIO_H) && !defined(_UNISTD_H)
+
+#include "ssx_macros.h"
+#include "ssx_api.h"
+
+#include "ctype.h"
+#include "errno.h"
+#include "string.h"
+
+#define EOF -1
+
+#define FILE_INVALID_OBJECT 0x00345301
+#define FILE_INVALID_ARGUMENT 0x00345302
+
+#ifndef __ASSEMBLER__
+
+#include <stdarg.h>
+
+/// The SSX implementation of the FILE structure
+
+typedef struct FILE {
+
+ /// The sread() method
+ int (*sread)(struct FILE *stream, void *buf,
+ size_t count, size_t *read);
+
+ /// The swrite() method
+ int (*swrite)(struct FILE *stream, const void *buf,
+ size_t count, size_t *written);
+
+ /// The fflush() method
+ int (*fflush)(struct FILE *stream);
+
+ /// The last error code encountered
+ ///
+ /// This field is not set in the event of an error panic.
+ int error;
+
+ /// SSX file/stream flags; See \ref ssx_file_flags
+ int flags;
+
+ /// The semaphore used to lock low-level file operations if required.
+ SsxSemaphore fop_sem;
+
+ /// The number of newline characters read by fgetc.
+ ///
+ /// This variable supports an SSX extension to <stdio.h>, the flines()
+ /// API. flines() returns the number of newline characters read by
+ /// fgetc(). This counter does not count newline characters read using
+ /// sread() on the stream directly.
+ size_t lines;
+
+ /// The character pushed back by ungetc()
+ ///
+ /// If a character is back the flag SSX_FILE_HAS_CHARACTER will be
+ /// set. Note that characters pushed back with ungetc() are not returned
+ /// by any subsequent sread() call on the stream, so it is best not to mix
+ /// sread() and fgetc().
+ unsigned char character;
+
+} FILE;
+
+
+/// \defgroup ssx_file_flags SSX File/Stream Flags
+/// @{
+
+/// Low-level access is locked by an SSX_CRITICAL critical section
+#define SSX_FILE_OP_LOCK_CRITICAL 0x1
+
+/// Low-level access is locked by an SSX_NONCRITICAL critical section
+#define SSX_FILE_OP_LOCK_NONCRITICAL 0x2
+
+/// Low-level access is locked by a semaphore
+#define SSX_FILE_OP_LOCK_SEMAPHORE 0x4
+
+/// Mask of all locking options;
+#define SSX_FILE_OP_LOCK_OPTIONS 0x7
+
+/// The FILE has a character pushed back by ungetc()
+#define SSX_FILE_HAS_CHARACTER 0xf
+
+/// All valid flags
+#define SSX_FILE_VALID_FLAGS 0xf
+
+/// @}
+
+
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+
+/// SSX kernel output stream
+///
+/// This stream implements the printk() API. It must be a non-blocking stream
+/// so that it can be used in interrupt contexts.
+
+extern FILE *ssxout;
+
+extern FILE *ssxnull;
+
+int
+FILE_create(FILE *stream, int flags);
+
+int
+sread(FILE *stream, void *buf, size_t count, size_t *read);
+
+int
+swrite(FILE *stream, const void *buf, size_t count, size_t *written);
+
+int
+fflush(FILE *stream);
+
+int
+vfprintf(FILE *stream, const char *format, va_list argp)
+ __attribute__ ((format (printf, 2, 0)));
+
+int
+vprintf(const char *format, va_list argp)
+ __attribute__ ((format (printf, 1, 0)));
+
+int
+fprintf(FILE *stream, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+int
+printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+
+int
+printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+
+int
+vsprintf(char *str, const char *format, va_list argp)
+ __attribute__ ((format (printf, 2, 0)));
+
+int
+sprintf(char *str, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+int
+vsnprintf(char *str, size_t size, const char *format, va_list argp)
+ __attribute__ ((format (printf, 3, 0)));
+
+int
+snprintf(char *str, size_t size, const char *format, ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+int
+fputc(int c, FILE *stream);
+
+int
+fputs(const char *s, FILE *stream);
+
+int
+puts(const char *s);
+
+int
+putchar(int c);
+
+int
+fgetc(FILE* stream);
+
+int
+ungetc(int c, FILE* stream);
+
+size_t
+flines(FILE* stream);
+
+int
+ssx_io_error_set(FILE *stream, int code);
+
+/// Handle I/O errors including panic configurations
+#define SSX_IO_ERROR_IF(stream, condition, code) \
+ do { \
+ if (condition) { \
+ if (ssx_io_error_set(stream, code) && SSX_ERROR_PANIC) { \
+ SSX_PANIC(code); \
+ } else { \
+ return -(code); \
+ } \
+ } \
+ } while (0)
+
+#define SSX_IO_ERROR(stream, code) SSX_IO_ERROR_IF((stream), 1, (code))
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* !defined(_STDIO_H) && !defined(_UNISTD_H) */
+
+#endif /* __SSX_IO_H__ */
diff --git a/src/lib/stdlib.c b/src/lib/stdlib.c
new file mode 100755
index 0000000..2dcc009
--- /dev/null
+++ b/src/lib/stdlib.c
@@ -0,0 +1,91 @@
+// $Id: stdlib.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/stdlib.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file stdlib.c
+/// \brief Functions from <stdlib.h>
+///
+/// \note The strtoX() APIs are defined in strtox.[ch]
+
+#include "ssx.h"
+#include "ctype.h"
+#include "libssx.h"
+#include <stdlib.h>
+
+
+/// Convert a string to a long integer - base 10 only
+///
+/// atol(str) is defined here as strtol(str, 0, 10) in sympathy with the POSIX
+/// standard. Note that by specification "atol() does not detect
+/// errors", however here it will behave the same as the strtol() call just
+/// mentioned.
+
+long
+atol(const char *str)
+{
+ return strtol(str, 0, 10);
+}
+
+
+/// Convert a string to an integer - base 10 only
+///
+/// atoi(str) is defined here as strtol(str, 0, 10) in sympathy with the POSIX
+/// standard. Note that by specification "atoi() does not detect errors",
+/// however in this implementation the long integer returned by the strtol()
+/// call just mentioned is simply converted to an int.
+
+int
+atoi(const char *str)
+{
+ return strtol(str, 0, 10);
+}
+
+
+/// 'Exit' an application
+///
+/// An SSX application can not really 'exit'. By convention, exit(0) is the
+/// same as ssx_halt(). Calling exit() with a non-zero code causes a kernel
+/// panic - the exit code will be found in R3 on PowerPC.
+///
+/// Note that to exit a thread, the thread can either return from the thread
+/// entry routine or explicitly call ssx_complete(). exit() was implemented
+/// to allow porting of the EEMBC benchmarks.
+
+void
+exit(int status)
+{
+ if (status) {
+ SSX_PANIC(ERROR_EXIT);
+ }
+ ssx_halt();
+}
+
+
+/// Compute the absolute value of the integer argument
+int
+abs(int i)
+{
+ return ((i < 0) ? -i : i);
+}
+
+
+/// Compute the absolute value of the long integer argument
+long int
+labs(long int i)
+{
+ return ((i < 0) ? -i : i);
+}
+
+
+/// Compute the absolute value of the long long integer argument
+long long int
+llabs(long long int i)
+{
+ return ((i < 0) ? -i : i);
+}
+
+
diff --git a/src/lib/strcasecmp.c b/src/lib/strcasecmp.c
new file mode 100644
index 0000000..361a387
--- /dev/null
+++ b/src/lib/strcasecmp.c
@@ -0,0 +1,66 @@
+// $Id: strcasecmp.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/strcasecmp.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file strcasecmp.c
+/// \brief Implementation of strcasecmp() and strncasecmp()
+///
+/// These routines are rarely used, hence broken out into a separate file to
+/// save code space for most applications.
+
+#include "ssx.h"
+#include "string.h"
+
+/// Compare two strings ignoring case
+///
+/// The strcasecmp() function compares the two strings \a s1 and \a s2,
+/// ignoring the case of the characters. It returns an integer less than,
+/// equal to, or greater than zero if \a s1 is found, respectively, to be less
+/// than, to match, or be greater than \a s2.
+
+int
+strcasecmp(const char* s1, const char* s2)
+{
+ int rc;
+
+ if (s1 == s2) {
+ rc = 0;
+ } else {
+ while(*s1 && (tolower(*s1) == tolower(*s2))) {
+ s1++;
+ s2++;
+ }
+ rc = *((unsigned char *)s1) - *((unsigned char *)s2);
+ }
+ return rc;
+}
+
+
+/// Compare a portion of two strings ignoring case
+///
+/// The strncmp() function compares at most the first \n characters of the two
+/// strings \a s1 and \a s2, ignoring the case of the characters. It returns
+/// an integer less than, equal to, or greater than zero if (the prefix of) \a
+/// s1 is found, respectively, to be less than, to match, or be greater than
+/// (the prefix of) \a s2.
+
+int
+strncasecmp(const char* s1, const char* s2, size_t n)
+{
+ int rc;
+
+ if ((s1 == s2) || (n == 0)) {
+ rc = 0;
+ } else {
+ while(*s1 && (tolower(*s1) == tolower(*s2)) && n--) {
+ s1++;
+ s2++;
+ }
+ rc = *((unsigned char *)s1) - *((unsigned char *)s2);
+ }
+ return rc;
+}
diff --git a/src/lib/strdup.c b/src/lib/strdup.c
new file mode 100755
index 0000000..c6ac04c
--- /dev/null
+++ b/src/lib/strdup.c
@@ -0,0 +1,39 @@
+// $Id: strdup.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/strdup.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file strdup.c
+/// \brief Functions from <string.h> that require malloc()
+///
+/// These APIs are split from string.c for the benefit of applications like
+/// OCC FW that don't use malloc().
+
+#include <stdlib.h>
+#include <string.h>
+
+/// Duplicate a string
+///
+/// \param s The string to duplicate
+///
+/// The strdup() function returns a pointer to a new string which is a
+/// duplicate of the input string \a s. Memory for the new string is obtained
+/// with malloc(), and can be freed with free().
+///
+/// \returns The strdup() function returns a pointer to the duplicated string,
+/// or NULL (0) if insufficient memory was available.
+
+char *
+strdup(const char* s)
+{
+ char* dup;
+
+ dup = (char*)malloc(strlen(s) + 1);
+ if (dup != 0) {
+ strcpy(dup, s);
+ }
+ return dup;
+}
diff --git a/src/lib/string.c b/src/lib/string.c
new file mode 100755
index 0000000..81d1778
--- /dev/null
+++ b/src/lib/string.c
@@ -0,0 +1,168 @@
+// $Id: string.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/string.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file string.c
+/// \brief strlen(), strcmp() etc. functions
+
+#include "ssx.h"
+#include "string.h"
+
+/// Compute the length of a string
+///
+/// The strlen() function calculates the length of the string \a s, not
+/// including the terminating \b '\0' character. The strlen() function
+/// returns the number of characters in \a s.
+
+size_t
+strlen(const char *s)
+{
+ const char *p = s;
+
+ while (*p) {
+ p++;
+ }
+
+ return p - s;
+}
+
+
+/// Compare two strings
+///
+/// The strcmp() function compares the two strings \a s1 and \a s2. It
+/// returns an integer less than, equal to, or greater than zero if \a s1 is
+/// found, respectively, to be less than, to match, or be greater than \a s2.
+
+int
+strcmp(const char* s1, const char* s2)
+{
+ int rc;
+
+ if (s1 == s2) {
+ rc = 0;
+ } else {
+ while(*s1 && (*s1 == *s2)) {
+ s1++;
+ s2++;
+ }
+ rc = *((unsigned char *)s1) - *((unsigned char *)s2);
+ }
+ return rc;
+}
+
+
+/// Compare a portion of two strings
+///
+/// The strncmp() function compares at most the first \n characters of the two
+/// strings \a s1 and \a s2. It returns an integer less than, equal to, or
+/// greater than zero if (the prefix of) \a s1 is found, respectively, to be
+/// less than, to match, or be greater than (the prefix of) \a s2.
+
+int
+strncmp(const char* s1, const char* s2, size_t n)
+{
+ int rc;
+
+ if ((s1 == s2) || (n == 0)) {
+ rc = 0;
+ } else {
+ while(*s1 && (*s1 == *s2) && n--) {
+ s1++;
+ s2++;
+ }
+ rc = *((unsigned char *)s1) - *((unsigned char *)s2);
+ }
+ return rc;
+}
+
+
+/// Copy a string
+///
+/// The strcpy() function copies the string pointed to by \a src (including
+/// the terminating null character) to the array pointed to by \a dest. The
+/// strings may not overlap, and the destination string \a dest must be large
+/// enough to receive the copy.
+///
+/// The strcpy() function return a pointer to the destination string \a dest.
+
+char *
+strcpy(char *dest, const char *src)
+{
+ char *rv = dest;
+
+ while (*src) {
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+
+ return rv;
+}
+
+
+/// Safely copy all or part of a string
+///
+/// The strncpy() function copies the string pointed to by \a src (including
+/// the terminating null character) to the array pointed to by \a dest, except
+/// that no more than \a n bytes of \a src are copied. This, if there is no
+/// null byte among the first \a n bytes of \a src, the result will not be
+/// null-terminated. In the case where the length of \a src is less than \a n,
+/// the remainder of \a dest will be padded with null bytes. The strings may
+/// not overlap.
+///
+/// The strncpy() function return a pointer to the destination string \a dest.
+
+char *
+strncpy(char *dest, const char *src, size_t n)
+{
+ char *rv = dest;
+
+ while (*src && n--) {
+ *dest++ = *src++;
+ }
+ memset(dest, 0, n);
+
+ return rv;
+}
+
+
+/// Compare two memory areas
+///
+/// The memcmp() function compares the first \a n bytes of the memory areas \a
+/// s1 and \a s2. It returns an integer less than, equal to, or greater than
+/// zero if \a s1 is found, respectively, to be less than, to match, or be
+/// greater than \a s2.
+int
+memcmp(const void* s1, const void* s2, size_t n)
+{
+ unsigned char *p1, *p2;
+ int rc;
+
+ p1 = (unsigned char*) s1;
+ p2 = (unsigned char*) s2;
+
+ if (s1 == s2) {
+
+ rc = 0;
+
+ } else {
+
+ while (n && (*p1 == *p2)) {
+ n--;
+ p1++;
+ p2++;
+ }
+
+ if (n == 0) {
+ rc = 0;
+ } else {
+ rc = (*p1 - *p2);
+ }
+ }
+
+ return rc;
+}
+
diff --git a/src/lib/string.h b/src/lib/string.h
new file mode 100755
index 0000000..2376463
--- /dev/null
+++ b/src/lib/string.h
@@ -0,0 +1,64 @@
+#ifndef __STRING_H__
+#define __STRING_H__
+
+// $Id: string.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/string.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file string.h
+/// \brief Replacement for <string.h>
+///
+/// The SSX library does not implement the entire <string.h> function.
+/// However the real reason for this header was the finding that under certain
+/// optimization modes, we were geting errors from the default <string.h>
+/// supplied with the MPC environment. So we created this replacement that
+/// only calls out what is implemented, exactly as it is implemented for SSX.
+
+#ifndef __ASSEMBLER__
+
+#include <stddef.h>
+
+// APIs inmplemented by string.c
+
+size_t
+strlen(const char *s);
+
+int
+strcmp(const char* s1, const char* s2);
+
+int
+strncmp(const char* s1, const char* s2, size_t n);
+
+int
+strcasecmp(const char* s1, const char* s2);
+
+int
+strncasecmp(const char* s1, const char* s2, size_t n);
+
+char *
+strcpy(char *dest, const char *src);
+
+char *
+strncpy(char *dest, const char *src, size_t n);
+
+void *
+memcpy(void *dest, const void *src, size_t n);
+
+void *
+memset(void *s, int c, size_t n);
+
+int
+memcmp(const void* s1, const void* s2, size_t n);
+
+// APIs implemented by strdup.c
+
+char *
+strdup(const char* s);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __STRING_H__ */
diff --git a/src/lib/string_stream.c b/src/lib/string_stream.c
new file mode 100755
index 0000000..f3b1889
--- /dev/null
+++ b/src/lib/string_stream.c
@@ -0,0 +1,386 @@
+// $Id: string_stream.c,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/string_stream.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file string_stream.c
+/// \brief Implementations of string streams.
+///
+/// \bug Need to work out overwrite/multiple-write protection.
+
+#include "ssx.h"
+#include "string_stream.h"
+
+
+// 'Flush' a string stream by making it empty
+
+static int
+string_stream_fflush(FILE* stream)
+{
+ StringStream* string = (StringStream*) stream;
+
+ string->next_read = 0;
+ string->next_write = 0;
+ string->flags &= ~STRING_STREAM_FULL;
+ return 0;
+}
+
+
+// Read the remaining tail (if any) of the circular buffer, assuming the
+// buffer is not empty.
+
+static size_t
+read_tail(StringStream* string, void* buf, size_t size)
+{
+ size_t read, remainder;
+
+ read = 0;
+ if (string->next_read >= string->next_write) {
+
+ remainder = string->size - string->next_read;
+ read = MIN(size, remainder);
+ memcpy(buf, (void *)(&(string->data[string->next_read])), read);
+ if (read != remainder) {
+ string->next_read += read;
+ } else {
+ string->next_read = 0;
+ }
+ }
+ return read;
+}
+
+
+// Read the area (if any) from the read pointer to the write pointer
+
+static size_t
+read_head(StringStream* string, void* buf, size_t size)
+{
+ size_t read, remainder;
+
+ read = 0;
+ if (string->next_write > string->next_read) {
+
+ remainder = string->next_write - string->next_read;
+ read = MIN(size, remainder);
+ memcpy(buf, (void *)(&(string->data[string->next_read])), read);
+ string->next_read += read;
+ }
+ return read;
+}
+
+
+// Read as much data as possible from a circular buffer. Return -EAGAIN if the
+// buffer would underflow.
+
+static int
+string_stream_sread(FILE* stream, void* buf, size_t size, size_t* read)
+{
+ StringStream *string = (StringStream *)stream;
+ size_t were_read;
+ int rc;
+
+ if ((string->next_read == string->next_write) &&
+ !(string->flags & STRING_STREAM_FULL)) {
+ were_read = 0;
+ } else {
+ were_read = read_tail(string, buf, size);
+ if (were_read != size) {
+ were_read += read_head(string, buf + were_read, size - were_read);
+ }
+ }
+ if (were_read != 0) {
+ string->flags &= ~STRING_STREAM_FULL;
+ }
+ *read = were_read;
+ if (were_read < size) {
+ rc = -EAGAIN;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+
+
+
+// Write the remaining tail (if any) of the circular buffer, assuming the
+// buffer is not full.
+
+static size_t
+write_tail(StringStream* string, const void* buf, size_t size)
+{
+ size_t written, remainder;
+
+ written = 0;
+ if (string->next_write >= string->next_read) {
+
+ remainder = string->size - string->next_write; // string->size is the size of the stream(our buffer)
+ written = MIN(size, remainder);
+ // memcpy(void *dest, const void *src, size_t n) from /lib/memcpy.c
+ memcpy((void *)(&(string->data[string->next_write])), buf, written);
+ if (written != remainder) {
+ string->next_write += written;
+ } else {
+ string->next_write = 0;
+ }
+ }
+ return written;
+}
+
+// Write the area (if any) from the write pointer to the read pointer
+
+static size_t
+write_head(StringStream* string, const void* buf, size_t size)
+{
+ size_t written, remainder;
+
+ written = 0;
+ if (string->next_read > string->next_write) {
+
+ remainder = string->next_read - string->next_write;
+ written = MIN(size, remainder);
+ memcpy((void *)(&(string->data[string->next_write])), buf, written);
+ string->next_write += written;
+ }
+ return written;
+}
+
+
+// Write as much data as possible to a circular buffer. Return -EAGAIN if the
+// buffer would overflow.
+
+static int
+circular_swrite(FILE* stream, const void* buf, size_t size, size_t* written)
+{
+ StringStream *string = (StringStream *)stream;
+ size_t wrote;
+ int rc;
+
+ if (string->flags & STRING_STREAM_FULL) {
+ wrote = 0;
+ } else {
+ wrote = write_tail(string, buf, size);
+ if (wrote != size) {
+ wrote += write_head(string, buf + wrote, size - wrote);
+ }
+ }
+ if ((wrote != 0) && (string->next_read == string->next_write)) {
+ string->flags |= STRING_STREAM_FULL;
+ }
+ *written = wrote;
+ if (wrote < size) {
+ rc = -EAGAIN;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+
+// Effectively write all data to a circular buffer with wrapping semantics.
+
+static int
+wrapping_swrite(FILE* stream, const void* buf, size_t size, size_t* written)
+{
+ StringStream *string = (StringStream *)stream;
+ size_t wrote;
+ int rc;
+
+ if (size >= string->size) { // If size of data >= size of buffer
+
+ // If the amount of data will fill or overflow the entire buffer size
+ // then we effectively fill the buffer with the final bytes of data.
+
+ string->next_read = 0;
+ string->next_write = 0;
+ string->flags |= STRING_STREAM_FULL;
+ memcpy((void *)string->data, buf + (size - string->size), size);
+
+ } else {
+
+ // If the string is not full, try to fill it with the
+ // circular_swrite().
+
+ if (string->flags & STRING_STREAM_FULL) {
+ wrote = 0;
+ rc = -EAGAIN;
+ } else {
+ rc = circular_swrite(stream, buf, size, &wrote);
+ }
+ if (rc) {
+
+ // The string is full and we need to overflow. We know that size
+ // is less than the buffer size, and the next_read == next_write.
+ // Mark the stream not full so a new circular write will work, and
+ // at the end reset the full condition.
+
+ string->flags &= ~STRING_STREAM_FULL;
+ rc = circular_swrite(stream, buf + wrote, size - wrote, &wrote);
+ if (rc) {
+ SSX_PANIC(STRING_STREAM_BUG);
+ }
+ string->next_read = string->next_write;
+ string->flags |= STRING_STREAM_FULL;
+ }
+ }
+ *written = size;
+ return 0;
+}
+
+
+static int
+linear_swrite(FILE* stream, const void* buf, size_t size, size_t* written)
+{
+ // buf and size correspond to the data we are passing to our own buffer
+ uint32_t bit_0_mask = 0x80000000;
+ StringStream *string = (StringStream *)stream;
+ size_t wrote = 0; // right aligned
+ // int rc;
+ uint32_t num_bytes_written;
+ // uint32_t register_contents;
+
+
+ //if (wrote != size) {
+ // register_contents = in32(PMC_PORE_SCRATCH_REG1);
+ // register_contents = register_contents & bit_0_mask;
+
+ //if (!register_contents) {
+ // Before writing to SRAM, flush everything so it will write to the top
+ // of the buffer each time
+ string_stream_fflush(stream);
+
+ // Write printk statement to SRAM
+ // wrote will contain the number of bytes written
+
+ wrote += write_tail(string, buf + wrote, size - wrote);
+ // if wrote != size, tell Tcl to read the whole buffer, When Tcl is done loop back to write_tail
+ // buf= buf+wrote
+ // size= size - wrote
+ // continue loop until size = 0
+
+ // Sync
+ eieio();
+
+ // Store "wrote" to register
+ // Set bit 0 to 1
+ // out32(addr, data)
+ num_bytes_written = (uint32_t)wrote | bit_0_mask;
+ out32( PMC_PORE_SCRATCH_REG1 , num_bytes_written );
+
+ // Sync
+ eieio();
+ //}
+ //}
+
+ // outside of loop, set *written = wrote (which is equal to size once all data has been copied to our buffer)
+ *written = wrote;
+ return 0;
+
+}
+
+
+int
+_string_stream_create(StringStream* stream,
+ void* buf, size_t size, int flags,
+ int (*swrite)(FILE* stream,
+ const void* buf,
+ size_t size,
+ size_t* written))
+{
+ FILE* file = (FILE*)stream;
+ int rc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((stream == 0) ||
+ ((buf == 0) && (size != 0)),
+ STRING_STREAM_INVALID_ARGUMENT);
+ }
+
+ rc = FILE_create(file, flags);
+
+ if (!rc) {
+ file->swrite = swrite;
+ file->sread = string_stream_sread;
+ file->fflush = string_stream_fflush;
+ stream->data = buf;
+ stream->size = size;
+ stream->next_read = 0;
+ stream->next_write = 0;
+ stream->flags = 0;
+ }
+ return rc;
+}
+
+
+int
+circular_stream_create(CircularStream* stream,
+ void* buf, size_t size, int flags)
+{
+ return _string_stream_create(stream, buf, size, flags, circular_swrite);
+}
+
+
+int
+wrapping_stream_create(CircularStream* stream,
+ void* buf, size_t size, int flags)
+{
+ return _string_stream_create(stream, buf, size, flags, wrapping_swrite);
+}
+
+
+int
+linear_stream_create(CircularStream* stream,
+ void* buf, size_t size, int flags)
+{
+ FILE* file = (FILE*)stream;
+ int rc;
+
+ rc = _string_stream_create(stream, buf, size, flags, linear_swrite);
+ if (!rc) {
+
+ file->sread = NULL;
+ // Write to register where location of buffer is
+ out32( PMC_PORE_SCRATCH_REG1, (uint32_t)buf);
+ }
+ return rc;
+}
+
+
+// InputStream uses string_stream_sread(), however returns EOF once all data
+// has been read.
+
+static int
+input_stream_sread(FILE* stream, void* buf, size_t size, size_t* read)
+{
+ int rc;
+
+ rc = string_stream_sread(stream, buf, size, read);
+ if (rc == -EAGAIN) {
+ rc = EOF;
+ }
+
+ return rc;
+}
+
+
+// For simplicity (and ease of maintainence) we create a normal string stream
+// then overwrite a few key fields.
+
+int
+input_stream_create(StringStream* stream, void* buf, size_t size, int flags)
+{
+ int rc;
+
+ rc = _string_stream_create(stream, buf, size, flags, 0);
+ if (!rc) {
+ stream->stream.sread = input_stream_sread;
+ stream->stream.fflush = 0;
+ stream->flags = STRING_STREAM_FULL;
+ }
+ return rc;
+}
+
+
diff --git a/src/lib/string_stream.h b/src/lib/string_stream.h
new file mode 100755
index 0000000..939489c
--- /dev/null
+++ b/src/lib/string_stream.h
@@ -0,0 +1,253 @@
+#ifndef __STRING_STREAM_H__
+#define __STRING_STREAM_H__
+
+// $Id: string_stream.h,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/string_stream.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file string_stream.h
+/// \brief Implementations of string streams.
+
+#include "ssx_io.h"
+
+/// A string stream
+///
+/// This structure is used for the public CircularStream and WrappingStream
+/// types, as well as for the library-internal types used to implement
+/// sprintf() and snprintf().
+
+typedef struct {
+
+ /// The base class
+ FILE stream;
+
+ /// Data storage - provided by the creator
+ uint8_t *data;
+
+ /// The size of the data storage
+ size_t size;
+
+ /// The index of the next byte to write
+ size_t next_write;
+
+ /// The index of the next byte to read
+ size_t next_read;
+
+ /// Stream flags, see \ref string_stream_flags
+ int flags;
+
+} StringStream;
+
+
+/// A StringStream with circular buffer semantics
+///
+/// The swrite() method copies the input data to the stream buffer, which is
+/// treated as a circular buffer. If the swrite() would overflow the buffer,
+/// then as much data as possible is written and swrite returns -EAGAIN. In
+/// all cases swrite() returns the number of bytes actually written to the
+/// buffer.
+///
+/// The sread() method copies data from the StringStream circular buffer to
+/// the caller's buffer until either the caller's request is satisfied or all
+/// of the immediately available data has been read from the buffer. If the
+/// caller's request can not be immediately granted then as much data as
+/// possible is copied and sread() returns -EAGAIN. In all cases sread()
+/// returns the number of bytes actually read from the buffer.
+///
+/// The fflush() method marks the buffer as empty, effectively losing any data
+/// currently stored in the buffer.
+
+typedef StringStream CircularStream;
+
+
+/// A StringStream with wrapping circular buffer semantics
+///
+/// The swrite() method copies the input data to the stream buffer, which is
+/// treated as a circular buffer. If the swrite() would overflow the buffer,
+/// then unread data is overwritten with new data. If the size of the
+/// swrite() exceeds the buffer length then the effect is simply to fill the
+/// buffer with the final bytes of the caller's data. swrite() always returns
+/// the number of bytes requested to be written.
+///
+/// The sread() method copies data from the StringStream circular buffer to
+/// the caller's buffer until either the caller's request is satisfied or all
+/// of the immediately available data has been read from the buffer. If the
+/// caller's request can not be immediately granted then as much data as
+/// possible is copied and sread() returns -EAGAIN. In all cases sread()
+/// returns the number of bytes actually read from the buffer.
+///
+/// The fflush() method marks the buffer as empty, effectively losing any data
+/// currently stored in the buffer.
+
+typedef StringStream WrappingStream;
+
+
+/// Create a StringStream
+///
+/// \param stream The StringStream to initialize
+///
+/// \param buf The stream data buffer
+///
+/// \param size The size of the data buffer in bytes
+///
+/// \param flags Flags for FILE_create()
+///
+/// \param swrite The function to be installed as the swrite() function for
+/// the underlying FILE object. The sread() and fflush() functions are fixed.
+///
+/// This API initializes a StringStream structure for use in I/O operations.
+/// This API will typically only be used by the creation functions of specific
+/// StringStream types.
+///
+/// \retval 0 Success
+///
+/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0)
+/// or \a buf is NULL(0) and \a size is non-0.
+
+int
+_string_stream_create(StringStream* stream,
+ void* buf, size_t size, int flags,
+ int (*swrite)(FILE* stream,
+ const void* buf,
+ size_t size,
+ size_t* written));
+
+/// Create a CircularStream
+///
+/// \param stream The CircularStream to initialize
+///
+/// \param buf The stream data buffer
+///
+/// \param size The size of the data buffer in bytes
+///
+/// \param flags Flags for FILE_create()
+///
+/// This API initializes a CircularStream structure for use in I/O
+/// operations. Once created, the pointer to the CircularStream stream can be
+/// cast to a FILE* and used for sread(), swrite(), fflush() and fprintf()
+/// operations.
+///
+/// \retval 0 Success
+///
+/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0)
+/// or \a buf is NULL(0) and \a size is non-0.
+
+int
+circular_stream_create(CircularStream* stream,
+ void* buf, size_t size, int flags);
+
+
+/// Create a WrappingStream
+///
+/// \param stream The WrappingStream to initialize
+///
+/// \param buf The stream data buffer
+///
+/// \param size The size of the data buffer in bytes
+///
+/// \param flags Flags for FILE_create()
+///
+/// This API initializes a WrappingStream structure for use in I/O
+/// operations. Once created, the pointer to the WrappingStream stream can be
+/// cast to a FILE* and used for sread(), swrite(), fflush() and fprintf()
+/// operations.
+///
+/// \retval 0 Success
+///
+/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0)
+/// or \a buf is NULL(0) and \a size is non-0.
+
+int
+wrapping_stream_create(CircularStream* stream,
+ void* buf, size_t size, int flags);
+
+
+/// Create a LinearStream
+///
+/// \param stream The LinearStream to initialize
+///
+/// \param buf The stream data buffer
+///
+/// \param size The size of the data buffer in bytes
+///
+/// \param flags Flags for FILE_create()
+///
+/// This API initializes a LinearStream structure for use in I/O
+/// operations. Once created, the pointer to the WrappingStream stream can be
+/// cast to a FILE* and used for sread(), swrite(), fflush() and fprintf()
+/// operations.
+///
+/// \retval 0 Success
+///
+/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0)
+/// or \a buf is NULL(0) and \a size is non-0.
+
+
+int
+linear_stream_create(CircularStream* stream,
+ void* buf, size_t size, int flags);
+
+
+/// A StringStream used as a read-only input stream
+///
+/// This is a CircualarStream created with a full buffer and without a write
+/// method. It uses a special read method that returns EOF once the buffer is
+/// empty rather than -EAGAIN.
+
+typedef StringStream InputStream;
+
+
+/// Create an InputStream
+///
+/// \param stream The InputStream to initialize
+///
+/// \param buf The stream data buffer.
+///
+/// \param size The size of the readable portion of the data buffer in bytes
+///
+/// \param flags Flags for FILE_create()
+///
+/// This API initializes an InputStream structure for use in input operations.
+/// The stream data buffer contains \a size bytes of data which can be read.
+/// Once created, the pointer to the InputStream stream can be cast to a FILE*
+/// and used for sread(), fgetc() and ungetc() operations. Neither fflush()
+/// nor swrite() are supported on this class of stream. The read operations
+/// will succeed until \a size bytes have been returned from the stream, at
+/// which point the stream will return EOF on any subsequent reads.
+///
+/// \retval 0 Success
+///
+/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0)
+/// or \a buf is NULL(0) and \a size is non-0.
+
+int
+input_stream_create(InputStream* stream,
+ void* buf, size_t size, int flags);
+
+
+/// \defgroup string_stream_flags StringStream Flags
+///
+/// @{
+
+/// The StringStream is full
+#define STRING_STREAM_FULL 0x1
+
+/// @}
+
+
+/// \defgroup string_stream_codes StringStream Error/Panic Codes
+///
+/// @{
+
+/// A bug was detected in a StringStream function
+#define STRING_STREAM_BUG 0x00787701
+#define STRING_STREAM_INVALID_ARGUMENT 0x00787702
+
+/// @}
+
+
+#endif // __STRING_STREAM_H__
diff --git a/src/lib/strtox.c b/src/lib/strtox.c
new file mode 100755
index 0000000..d901158
--- /dev/null
+++ b/src/lib/strtox.c
@@ -0,0 +1,593 @@
+// $Id: strtox.c,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/strtox.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file strtox.c
+/// \brief Implementation of strtol(), strtoul(), strtoll() and strtoull()
+///
+/// <b> Standard String Conversion Routines </b>
+///
+/// This file contains implementaions of strtol(), strtoul(), strtoll() and
+/// strtoull(). These APIs are all called as
+///
+/// \code
+/// strtoX(const char* str, char** endptr, int base)
+/// \endcode
+///
+/// where X is
+///
+/// - l : Convert to a long integer
+/// - ul : Convert to an unsigned long integer
+/// - ll : Convert to a long long integer
+/// - ull : Convert to an unsigned long long integer
+///
+/// \param str The string to convert
+///
+/// \param endptr If non-null, will be set to a pointer to the portion of the
+/// string following the convertable portion. If no conversion is performed
+/// then the original \a str is returned here.
+///
+/// \param base Either 0 to indicate that the base should be derived from
+/// radix markers in the string, or a number in the range 2 to 36 inclusive.
+///
+/// The APIs convert the initial portion of the string pointed to by \a str to
+/// an integer, which is either a long integer (strtol), an unsigned long
+/// (strtoul()), a long long (strtoll), or an unsigned long long
+/// (strtoull). First, the APIs decompose the input string into three parts:
+///
+/// - An initial, possibly empty, sequence of white-space characters (as
+/// specified by isspace())
+///
+/// - A subject sequence interpreted as an integer represented in some radix
+/// determined by the value of \a base
+///
+/// - A final string of one or more unrecognized characters, including the
+/// terminating null byte of the input string.
+///
+/// The APIs then attempt to convert the subject sequence to an integer of the
+/// required type and returns the result.
+///
+/// If the value of \a base is 0, the expected form of the subject sequence is
+/// that of a decimal constant, octal constant, or hexadecimal constant, any
+/// of which may be preceded by a '+' or '-' sign. A decimal constant begins
+/// with a non-zero digit, and consists of a sequence of decimal digits. An
+/// octal constant consists of the prefix '0' optionally followed by a
+/// sequence of the digits '0' to '7' only. A hexadecimal constant consists of
+/// the prefix 0x or 0X followed by a sequence of the decimal digits and
+/// letters 'a' (or 'A' ) to 'f' (or 'F' ) with values 10 to 15 respectively.
+///
+/// If the value of \a base is between 2 and 36, the expected form of the
+/// subject sequence is a sequence of letters and digits representing an
+/// integer with the radix specified by base, optionally preceded by a '+' or
+/// '-' sign. The letters from 'a' (or 'A' ) to 'z' (or 'Z' ) inclusive are
+/// ascribed the values 10 to 35; only letters whose ascribed values are less
+/// than that of base are permitted. If the value of base is 16, the
+/// characters 0x or 0X may optionally precede the sequence of letters and
+/// digits, following the sign if present.
+///
+/// The subject sequence is defined as the longest initial subsequence of the
+/// input string, starting with the first non-white-space character that is of
+/// the expected form. The subject sequence contains no characters if the
+/// input string is empty or consists entirely of white-space characters, or if
+/// the first non-white-space character is other than a sign or a permissible
+/// letter or digit.
+///
+/// If the subject sequence has the expected form and the value of base is 0,
+/// the sequence of characters starting with the first digit will be
+/// interpreted as an integer constant. If the subject sequence has the
+/// expected form and the value of base is between 2 and 36, it will be used
+/// as the base for conversion, ascribing to each letter its value as given
+/// above. If the subject sequence begins with a minus sign, the value
+/// resulting from the conversion will be negated. A pointer to the final
+/// string will be stored in the object pointed to by \a endptr, provided that
+/// \a endptr is not a null pointer.
+///
+/// If the subject sequence is empty or does not have the expected form, no
+/// conversion is performed; the value of \a str is stored in the object
+/// pointed to by \a endptr, provided that \a endptr is not a null pointer.
+///
+/// Note that the unsigned APIs silently convert signed representations into
+/// the equivalent unsigned number.
+///
+/// Since 0, (L)LONG_MIN and (U)(L)LONG_MAX are returned on error and are
+/// also valid returns on success, there is no way for an SSX application to
+/// determine whether the conversion succeeded or failed (since SSX does not
+/// support \a errno). For this reason it is recommended that SSX-only
+/// applications use the underlying APIs _strtol(), _strtoul(), _strtoll() and
+/// _strtoull(), or even better the extended APIs strtoi32(), strtou32(),
+/// strtoi64() or strtou64() discussed further below.
+///
+/// Upon successful completion, strtoX() returns the converted
+/// value, if any. If no conversion could be performed or there was an error
+/// in the base specification, 0 is returned.
+///
+/// If the correct value is outside the range of representable values,
+/// (L)LONG_MIN or (U)(L)LONG_MAX will be returned (according to the sign
+/// and type of the value).
+///
+/// Note: This specification is adapted from IEEE Std. 10003.1, 2003 Edition
+///
+///
+/// <b> Underlying APIs </b>
+///
+/// The APIs underlying the standard APIs are all called as
+///
+/// \code
+/// int _strtoX(const char* str, char** endptr, int radix, <type>* value)
+/// \endcode
+///
+/// where X is
+///
+/// - l : Convert to a long integer
+/// - ul : Convert to an unsigned long integer
+/// - ll : Convert to a long long integer
+/// - ull : Convert to an unsigned long long integer
+///
+/// \param str The string to convert
+///
+/// \param endptr If non-null, will be set to a pointer to the portion of the
+/// string following the convertable portion. If no conversion is performed
+/// then the original \a str is returned here.
+///
+/// \param base Either 0 to indicate that the base should be derived from
+/// radix markers in the string, or a number in the range 2 to 36 inclusive.
+///
+/// \param value The converted value, returned as the return value of the
+/// standard API.
+///
+/// The return value of the underlying APIs is one of the following
+///
+/// \retval 0 Success
+///
+/// \retval -STRTOX_NO_CONVERSION_EMPTY No conversion was performed because the
+/// string was effectively empty.
+///
+/// \retval -STRTOX_NO_CONVERSION_PARSE No conversion was performed because the
+/// string did not parse as an integer.
+///
+/// \retval -STRTOX_INVALID_ARGUMENT No conversion was performed because the
+/// \a base specification was not valid.
+///
+/// \retval -STRTOX_UNDERFLOW_STRTOL1 Conversion resulted in underflow
+///
+/// \retval -STRTOX_UNDERFLOW_STRTOL2 Conversion resulted in underflow
+///
+/// \retval -STRTOX_UNDERFLOW_STRTOLL1 Conversion resulted in underflow
+///
+/// \retval -STRTOX_UNDERFLOW_STRTOLL2 Conversion resulted in underflow
+///
+/// \retval -STRTOX_OVERFLOW_STRTOL1 Conversion resulted in overflow
+///
+/// \retval -STRTOX_OVERFLOW_STRTOL2 Conversion resulted in overflow
+///
+/// \retval -STRTOX_OVERFLOW_STRTOLL1 Conversion resulted in overflow
+///
+/// \retval -STRTOX_OVERFLOW_STRTOLL2 Conversion resulted in overflow
+///
+///
+/// <b> Extended APIs </b>
+///
+/// The extended APIs are the preferred way to do portable integer
+/// conversion. These APIs are all called as
+///
+/// \code
+/// int strtoX(const char* str, char** endptr, int radix, <type>* value)
+/// \endcode
+///
+/// where X is
+///
+/// - i32 : Convert to an int32_t
+/// - u32 : Convert to a uint32_t
+/// - i64 : Convert to an int64_t
+/// - u64 : Convert to a uint64_t
+///
+/// \param str The string to convert
+///
+/// \param endptr If non-null, will be set to a pointer to the portion of the
+/// string following the convertable portion. If no conversion is performed
+/// then the original \a str is returned here.
+///
+/// \param base Either 0 to indicate that the base should be derived from
+/// radix markers in the string, or a number in the range 2 to 36 inclusive.
+///
+/// \param value The converted value
+///
+/// The return value of the underlying APIs is one of the following
+///
+/// \retval 0 Success
+///
+/// \retval -STRTOX_NO_CONVERSION_EMPTY No conversion was performed because the
+/// string was effectively empty.
+///
+/// \retval -STRTOX_NO_CONVERSION_PARSE No conversion was performed because the
+/// string did not parse as an integer.
+///
+/// \retval -STRTOX_INVALID_ARGUMENT No conversion was performed because the
+/// \a base specification was not valid.
+///
+/// \retval -STRTOX_UNDERFLOW_STRTOL1 Conversion resulted in underflow
+///
+/// \retval -STRTOX_UNDERFLOW_STRTOL2 Conversion resulted in underflow
+///
+/// \retval -STRTOX_UNDERFLOW_STRTOLL1 Conversion resulted in underflow
+///
+/// \retval -STRTOX_UNDERFLOW_STRTOLL2 Conversion resulted in underflow
+///
+/// \retval -STRTOX_OVERFLOW_STRTOL1 Conversion resulted in overflow
+///
+/// \retval -STRTOX_OVERFLOW_STRTOL2 Conversion resulted in overflow
+///
+/// \retval -STRTOX_OVERFLOW_STRTOLL1 Conversion resulted in overflow
+///
+/// \retval -STRTOX_OVERFLOW_STRTOLL2 Conversion resulted in overflow
+///
+
+#include "ssx.h"
+#include "ctype.h"
+#include "libssx.h"
+#include "strtox.h"
+
+
+// Skip whitespace
+
+static const char *
+skip_whitespace(const char *s)
+{
+ while (isspace(*s)) {
+ s++;
+ }
+ return s;
+}
+
+// Pick up a +/- sign. This is a predicate returning 1 if the value is
+// negated.
+
+static int
+sign(const char** s)
+{
+ if (**s == '+') {
+ (*s)++;
+ return 0;
+ } else if (**s == '-') {
+ (*s)++;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+// Look for a radix mark (0, 0[xX]). The string pointer is advanced if it is a
+// hex mark (0[xX]), but not for a simple '0' which could be either the start
+// of an octal constant or simply the number 0. The return value is either 8,
+// 10 or 16.
+
+static int
+radix_mark(const char** s)
+{
+ const char* p = *s;
+
+ if (p[0] == '0') {
+ if ((p[1] == 'x') || (p[1] == 'X')) {
+ *s += 2;
+ return 16;
+ } else {
+ return 8;
+ }
+ } else {
+ return 10;
+ }
+}
+
+
+// Parse a character as a radix-base digit. Return the value of the digit or
+// -1 if it is not a legal digit for the radix.
+
+static int
+parse_digit(char c, int radix)
+{
+ if (isdigit(c)) {
+ if ((c - '0') < radix) {
+ return c - '0';
+ } else {
+ return -1;
+ }
+ } else if (radix <= 10) {
+ return -1;
+ } else {
+ if (islower(c)) {
+ if ((c - 'a') < (radix - 10)) {
+ return c - 'a' + 10;
+ } else {
+ return -1;
+ }
+ } else if (isupper(c)) {
+ if ((c - 'A') < (radix - 10)) {
+ return c - 'A' + 10;
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ }
+}
+
+
+// The most basic API is strtox(), which converts a string to an unsigned long
+// long. All of the base APIs are written in terms of this. This is legal due
+// to the fact that conversion is defined to continue even in the event of
+// overflow. This API may return the codes STRTOX_NO_CONVERSION_EMPTY,
+// STRTOX_NO_CONVERSION_PARSE or STRTOX_INVALID_ARGUMENT,
+// which the standard APIs always convert to a 0
+// return value. Otherwise the flags 'overflow' and 'negative' are used by
+// the base APIs to determine how to handle special cases.
+
+static int
+strtox(const char *str, char **endptr, int base,
+ unsigned long long* value, int* negative, int* overflow)
+{
+ const char* s;
+ unsigned long long new;
+ int rc, radix, digit;
+
+
+ do {
+
+ s = str;
+ *value = 0;
+ *negative = 0;
+ *overflow = 0;
+
+ // Initial error checks
+
+ if ((base != 0) && ((base < 2) || (base > 36))) {
+ rc = STRTOX_INVALID_ARGUMENT;
+ break;
+ }
+
+ // Skip whitespace
+
+ s = skip_whitespace(s);
+ if (*s == '\0') {
+ rc = STRTOX_NO_CONVERSION_EMPTY;
+ break;
+ }
+
+ // Process a +/- sign. Only one is allowed.
+
+ *negative = sign(&s);
+
+ // Look for a radix mark. Note that if base == 16 this will cause the
+ // skip of a leading 0 in the string not followed by [xX], but that's
+ // OK because it doesn't change the result of the conversion.
+
+ if (base == 0) {
+ radix = radix_mark(&s);
+ } else {
+ radix = base;
+ if (radix == 16) {
+ radix_mark(&s);
+ }
+ }
+
+ // Parse. Note that once overflow is detected we continue to parse
+ // (but ignore the data).
+
+ rc = STRTOX_NO_CONVERSION_PARSE;
+
+ while ((digit = parse_digit(*s, radix)) >= 0) {
+ s++;
+ if (!*overflow) {
+ rc = 0;
+ new = (*value * radix) + digit;
+ if (new < *value) {
+ *overflow = 1;
+ } else {
+ *value = new;
+ }
+ }
+ }
+ } while(0);
+
+ if (endptr) {
+ if (rc == 0) {
+ *endptr = (char*)s;
+ } else {
+ *endptr = (char*)str;
+ }
+ }
+
+ return rc;
+}
+
+
+/// See documentation for the file strtox.c
+int
+_strtol(const char* str, char** endptr, int base, long* value)
+{
+ int rc, negative, overflow;
+ unsigned long long value_ull;
+
+ rc = strtox(str, endptr, base, &value_ull, &negative, &overflow);
+ if (rc) {
+ *value = 0;
+ } else {
+ if (overflow || (value_ull != (unsigned long)value_ull)) {
+ if (negative) {
+ rc = STRTOX_UNDERFLOW_STRTOL1;
+ *value = LONG_MIN;
+ } else {
+ rc = STRTOX_OVERFLOW_STRTOL1;
+ *value = LONG_MAX;
+ }
+ } else if (negative) {
+ if (value_ull > ((unsigned long long)LONG_MAX + 1ull)) {
+ rc = STRTOX_UNDERFLOW_STRTOL2;
+ *value = LONG_MIN;
+ } else {
+ *value = ~value_ull + 1;
+ }
+ } else if (value_ull > (unsigned long long)LONG_MAX) {
+ rc = STRTOX_OVERFLOW_STRTOL2;
+ *value = LONG_MAX;
+ } else {
+ *value = value_ull;
+ }
+ }
+ return rc;
+}
+
+
+/// See documentation for the file strtox.c
+int
+_strtoll(const char* str, char** endptr, int base, long long* value)
+{
+ int rc, negative, overflow;
+ unsigned long long value_ull;
+
+ rc = strtox(str, endptr, base, &value_ull, &negative, &overflow);
+ if (rc) {
+ *value = 0;
+ } else {
+ if (overflow) {
+ if (negative) {
+ rc = STRTOX_UNDERFLOW_STRTOLL1;
+ *value = LLONG_MIN;
+ } else {
+ rc = STRTOX_OVERFLOW_STRTOLL1;
+ *value = LLONG_MAX;
+ }
+ } else if (negative) {
+ if (value_ull > ((unsigned long long)LLONG_MAX + 1ull)) {
+ rc = STRTOX_UNDERFLOW_STRTOLL2;
+ *value = LLONG_MIN;
+ } else {
+ *value = ~value_ull + 1;
+ }
+ } else if (value_ull > (unsigned long long)LLONG_MAX) {
+ rc = STRTOX_OVERFLOW_STRTOLL2;
+ *value = LLONG_MAX;
+ } else {
+ *value = value_ull;
+ }
+ }
+ return rc;
+}
+
+
+/// See documentation for the file strtox.c
+int
+_strtoul(const char* str, char** endptr, int base, unsigned long* value)
+{
+ int rc, negative, overflow;
+ unsigned long long value_ull;
+
+ rc = strtox(str, endptr, base, &value_ull, &negative, &overflow);
+ if (rc) {
+ *value = 0;
+ } else {
+ if (overflow || (value_ull != (unsigned long)value_ull)) {
+ rc = STRTOX_OVERFLOW_STRTOUL;
+ *value = ULONG_MAX;
+ } else {
+ *value = value_ull;
+ if (negative) {
+ *value = ~*value + 1;
+ }
+ }
+ }
+ return rc;
+}
+
+/// See documentation for the file strtox.c
+int
+_strtoull(const char* str, char** endptr, int base, unsigned long long* value)
+{
+ int rc, negative, overflow;
+
+ rc = strtox(str, endptr, base, value, &negative, &overflow);
+ if (rc) {
+ *value = 0;
+ } else {
+ if (overflow) {
+ rc = STRTOX_OVERFLOW_STRTOULL;
+ *value = ULLONG_MAX;
+ } else {
+ if (negative) {
+ *value = ~*value + 1;
+ }
+ }
+ }
+ return rc;
+}
+
+
+/// See documentation for the file strtox.c
+long int
+strtol(const char* str, char** endptr, int base)
+{
+ long int value;
+
+ _strtol(str, endptr, base, &value);
+ return value;
+}
+
+
+/// See documentation for the file strtox.c
+long long int
+strtoll(const char* str, char** endptr, int base)
+{
+ long long int value;
+
+ _strtoll(str, endptr, base, &value);
+ return value;
+}
+
+
+/// See documentation for the file strtox.c
+unsigned long int
+strtoul(const char* str, char** endptr, int base)
+{
+ unsigned long int value;
+
+ _strtoul(str, endptr, base, &value);
+ return value;
+}
+
+
+/// See documentation for the file strtox.c
+unsigned long long int
+strtoull(const char* str, char** endptr, int base)
+{
+ unsigned long long int value;
+
+ _strtoull(str, endptr, base, &value);
+ return value;
+}
+
+
+#if (__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ <= 1))
+
+/// Internal version of strtol()
+///
+/// ppcnf-mcp5 (GCC 4.1) requires that the entry point __strtol_internal() be
+/// present at certain optimization levels. This is equivalent to strtol()
+/// except that it takes an extra argument that must be == 0. The \a group
+/// parameter is supposed to control locale-specific thousands grouping.
+
+long int
+__strtol_internal(const char* str, char** endptr, int base, int group)
+{
+ if (group != 0) {
+ SSX_PANIC(STRTOX_INVALID_ARGUMENT_STRTOL);
+ }
+ return strtol(str, endptr, base);
+}
+
+#endif
+
diff --git a/src/lib/strtox.h b/src/lib/strtox.h
new file mode 100755
index 0000000..b005ca9
--- /dev/null
+++ b/src/lib/strtox.h
@@ -0,0 +1,127 @@
+#ifndef __STRTOX_H__
+#define __STRTOX_H__
+
+// $Id: strtox.h,v 1.2 2014/02/03 01:30:25 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/strtox.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file strtox.h
+/// \brief Underlying and extended APIs that support strtoX macros
+///
+/// See the Doxygen comments of the file strtox.c for descriptions of the
+/// facilities provided by this header.
+
+#ifndef __ASSEMBLER__
+
+#include <limits.h>
+
+// Error codes
+
+#define STRTOX_NO_CONVERSION_EMPTY 0x00787901
+#define STRTOX_NO_CONVERSION_PARSE 0x00787902
+#define STRTOX_INVALID_ARGUMENT 0x00787903
+#define STRTOX_INVALID_ARGUMENT_STRTOL 0x00787904
+#define STRTOX_UNDERFLOW_STRTOL1 0x00787905
+#define STRTOX_UNDERFLOW_STRTOL2 0x00787906
+#define STRTOX_UNDERFLOW_STRTOLL1 0x00787907
+#define STRTOX_UNDERFLOW_STRTOLL2 0x00787908
+#define STRTOX_OVERFLOW_STRTOL1 0x00787909
+#define STRTOX_OVERFLOW_STRTOL2 0x0078790a
+#define STRTOX_OVERFLOW_STRTOLL1 0x0078790b
+#define STRTOX_OVERFLOW_STRTOLL2 0x0078790c
+#define STRTOX_OVERFLOW_STRTOUL 0x0078790d
+#define STRTOX_OVERFLOW_STRTOULL 0x0078790e
+
+// Earlier GCC configurations (ppcnf-mcp5-gcc) are not configured to define
+// these standard constants, which exist in the include tree under various
+// switches and configuration settings (from <limits.h>). They are defined by
+// default in later standard cross builds however (GCC 4.5, 4.6). However we
+// always assume that (long long) is a 64-bit type. It's likely that this is
+// the only place these constant will be used (as they are defined as the
+// values for under/overflow of strtoX() conversions), however it may be
+// necessary in the future to move these #defines somewhere else.
+
+#ifndef LLONG_MIN
+# define LLONG_MIN (0x8000000000000000ll)
+#endif
+
+#ifndef LLONG_MAX
+# define LLONG_MAX (0x7fffffffffffffffll)
+#endif
+
+#ifndef ULLONG_MAX
+# define ULLONG_MAX (0xffffffffffffffffull)
+#endif
+
+int
+_strtol(const char* str, char** endptr, int base, long* value);
+
+int
+_strtoul(const char* str, char** endptr, int base, unsigned long* value);
+
+int
+_strtoll(const char* str, char** endptr, int base, long long* value);
+
+int
+_strtoull(const char* str, char** endptr, int base, unsigned long long* value);
+
+
+// The way the sizeof(long) is discovered by default depends on which version
+// of gcc/cpp we're using as these macros are predefined by cpp.
+
+#if (__SIZEOF_LONG__ == 4) || (__LONG_MAX__ == 2147483647L)
+
+/// See documentation for the file strtox.c
+static inline int
+strtoi32(const char* str, char** endptr, int base, int32_t* value)
+{
+ long int value_l;
+ int rc;
+
+ rc = _strtol(str, endptr, base, &value_l);
+ *value = value_l;
+ return rc;
+}
+
+/// See documentation for the file strtox.c
+static inline int
+strtou32(const char* str, char** endptr, int base, uint32_t* value)
+{
+ unsigned long int value_ul;
+ int rc;
+
+ rc = _strtoul(str, endptr, base, &value_ul);
+ *value = value_ul;
+ return rc;
+}
+
+#else
+
+#error "No port of strtox.h yet for systems with sizeof(long) != 4"
+
+#endif
+
+// It is assumed that long long is always 64 bits; There is no standard macro
+// for this size constant
+
+/// See documentation for the file strtox.c
+static inline int
+strtoi64(const char* str, char** endptr, int base, int64_t* value)
+{
+ return _strtoll(str, endptr, base, value);
+}
+
+/// See documentation for the file strtox.c
+static inline int
+strtou64(const char* str, char** endptr, int base, uint64_t* value)
+{
+ return _strtoull(str, endptr, base, value);
+}
+
+#endif // __ASSEMBLER__
+
+#endif // __STRTOX_H__
diff --git a/src/lib/time.c b/src/lib/time.c
new file mode 100755
index 0000000..bc1f2e7
--- /dev/null
+++ b/src/lib/time.c
@@ -0,0 +1,58 @@
+// $Id: time.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/time.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file time.c
+/// \brief Implementation of functions from <time.h>
+///
+/// The following standard APIs are currently supported:
+///
+/// - clock_gettime() with the single clock id CLOCK_REALTIME
+///
+/// Since SSX does not currently have any per-thread CPU time statistics, we
+/// can not implement process-CPU-time-based APIs like the simple clock() or
+/// clock_gettime() with CLOCK_REALTIME.
+
+#include "ssx.h"
+#include <errno.h>
+#include <time.h>
+
+/// Get time from a timer
+///
+/// \param clock_id This must be the constant CLOCK_REALTIME defined in
+/// <time.h>.
+///
+/// \param tp A pointer to a struct timespec populated by this API.
+///
+/// Although the Posix standard requires that clock_gettime() support
+/// CLOCK_REALTIME, CLOCK_REALTIME measures standard Unix time (seconds since
+/// the epoch) which is not available to SSX. SSX currently only supports
+/// CLOCK_MONOTONIC, which is derived from the SSX timebase.
+///
+/// \returns Either 0 for success, or -EINVAL in the event of an invalid
+/// argument (unrecognized \a clock_id, NULL \a tp pointer).
+
+int
+clock_gettime(clockid_t clock_id, struct timespec* tp)
+{
+ int rc;
+ SsxTimebase now;
+
+ if ((clock_id != CLOCK_MONOTONIC) || (tp == 0)) {
+ rc = -EINVAL;
+ } else {
+
+ now = ssx_timebase_get();
+ tp->tv_sec = now / SSX_TIMEBASE_FREQUENCY_HZ;
+ tp->tv_nsec =
+ ((now % SSX_TIMEBASE_FREQUENCY_HZ) * 1000000000) /
+ SSX_TIMEBASE_FREQUENCY_HZ;
+ rc = 0;
+ }
+
+ return rc;
+}
diff --git a/src/lib/vrm.c b/src/lib/vrm.c
new file mode 100755
index 0000000..57f19fa
--- /dev/null
+++ b/src/lib/vrm.c
@@ -0,0 +1,394 @@
+// $Id: vrm.c,v 1.2 2014/02/03 01:30:26 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/vrm.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file vrm.c
+/// \brief PgP SPIVRM procedures
+
+#include "vrm.h"
+
+// The semaphore used to block threads waiting for o2s operations to complete
+
+static SsxSemaphore o2s_protocol_semaphore;
+
+
+/// o2s_initialize follows the steps for setting up the o2s bridge as outlined
+/// In the Energy Management spec (PMC section)
+int
+o2s_initialize()
+{
+ pmc_o2s_ctrl_reg0a_t pocr0a;
+ pmc_o2s_ctrl_reg0b_t pocr0b;
+ pmc_o2s_ctrl_reg1_t pocr1;
+
+
+ ssx_semaphore_create(&o2s_protocol_semaphore, 0, 1);
+
+ ssx_irq_disable(PGP_IRQ_OCI2SPIVID_ONGOING);
+
+ ssx_irq_setup(PGP_IRQ_OCI2SPIVID_ONGOING,
+ SSX_IRQ_POLARITY_ACTIVE_LOW,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+
+ ssx_irq_handler_set(PGP_IRQ_OCI2SPIVID_ONGOING,
+ ssx_semaphore_post_handler,
+ (void *)(&o2s_protocol_semaphore),
+ SSX_NONCRITICAL);
+
+ pocr0a.value = in32(PMC_O2S_CTRL_REG0A);
+ pocr0a.fields.o2s_frame_size = 32;
+ pocr0a.fields.o2s_out_count1 = 32;
+ pocr0a.fields.o2s_in_delay1 = 0x3F;
+ pocr0a.fields.o2s_in_count1 = 0;
+ out32(PMC_O2S_CTRL_REG0A, pocr0a.value);
+
+ pocr0b.value = in32(PMC_O2S_CTRL_REG0B);
+ pocr0b.fields.o2s_out_count2 = 0;
+ pocr0b.fields.o2s_in_delay2 = 0;
+ pocr0b.fields.o2s_in_count2 = 32;
+ out32(PMC_O2S_CTRL_REG0B, pocr0b.value);
+
+ pocr1.value = in32(PMC_O2S_CTRL_REG1);
+ pocr1.fields.o2s_bridge_enable = 1;
+ pocr1.fields.o2s_cpol = 0;
+ pocr1.fields.o2s_cpha = 0;
+ pocr1.fields.o2s_clock_divider = 29; // 10 MHz(?)
+ pocr1.fields.o2s_nr_of_frames = 1; // 2 frames
+ out32(PMC_O2S_CTRL_REG1, pocr1.value);
+
+ return 0;
+
+}
+
+/// similar to o2s_intialize, but for the automated spivid fsm
+/// \param vrm_select A 3-bit vector of VRM selected for the operation.
+///
+/// NOTE: The spivid is normally initialized by Host Boot
+///
+/// \retval 0 Success
+int
+spivid_initialize(int vrm_select)
+{
+ pmc_spiv_ctrl_reg0a_t pocr0a;
+ pmc_spiv_ctrl_reg0b_t pocr0b;
+ pmc_spiv_ctrl_reg1_t pocr1;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((vrm_select <= 0) ||
+ (vrm_select > 0x7),
+ VRM_INVALID_ARGUMENT_INIT);
+ }
+
+
+ pocr0a.value = in32(PMC_SPIV_CTRL_REG0A);
+ pocr0a.fields.spivid_frame_size = 32;
+ pocr0a.fields.spivid_out_count1 = 32;
+ pocr0a.fields.spivid_in_delay1 = 0x3F;
+ pocr0a.fields.spivid_in_count1 = 0;
+ out32(PMC_SPIV_CTRL_REG0A, pocr0a.value);
+
+ pocr0b.value = in32(PMC_SPIV_CTRL_REG0B);
+ pocr0b.fields.spivid_out_count2 = 0;
+ pocr0b.fields.spivid_in_delay2 = 0;
+ pocr0b.fields.spivid_in_count2 = 32;
+ out32(PMC_SPIV_CTRL_REG0B, pocr0b.value);
+
+ pocr1.value = in32(PMC_SPIV_CTRL_REG1);
+ pocr1.fields.spivid_fsm_enable = 1;
+ pocr1.fields.spivid_cpol = 0;
+ pocr1.fields.spivid_cpha = 0;
+ pocr1.fields.spivid_clock_divider = 29; // 10 MHz(?)
+ pocr1.fields.spivid_port_enable = vrm_select;
+ out32(PMC_SPIV_CTRL_REG1, pocr1.value);
+
+ return 0;
+
+}
+
+
+// Start an O2S transaction and poll for completion. Optionally return the
+// input data.
+
+static void
+o2s_start_poll(uint64_t out, uint64_t *in)
+{
+
+ out32(PMC_O2S_WDATA_REG, out >> 32);
+
+ if (!ssx_irq_status_get(PGP_IRQ_OCI2SPIVID_ONGOING)) {
+ ssx_irq_enable(PGP_IRQ_OCI2SPIVID_ONGOING);
+ ssx_semaphore_pend(&o2s_protocol_semaphore, SSX_WAIT_FOREVER);
+ }
+
+
+ if (in != 0) {
+ *in = in32(PMC_O2S_RDATA_REG);
+ }
+}
+
+
+/// Write a voltage using the O2S bridge
+///
+/// \param vrm_select A 3-bit vector of VRM selected for the operation.
+///
+/// \param vdd_vid The VRM-11 VID code for Vdd.
+///
+/// \param vcs_offset The signed offset (Vdiff) equal to Vcs - Vdd expressed
+/// in VRM-11 VID units.
+///
+/// \param phases The number of phases enabled.
+///
+/// This is a polling CPU procedure that writes a new voltage to a set of one
+/// or more VRM then does a status read to make sure it succeeded.
+///
+/// \retval 0 Success
+///
+/// \retval -VRM_INVALID_ARGUMENT_VWRITE One of the arguments was invalid in
+/// some way.
+///
+/// \retval -O2S_BUSY_VRM_VOLTAGE_WRITE The O2S bridge is currently busy
+///
+/// \retval -O2S_READ_NOT_READY A 'read not ready' condition occurred on the
+/// status read.
+///
+/// \retval -O2S_WRITE_NOT_VALID The voltage write was invalid
+///
+/// \retval -O2S_ECC_ERROR An ECC error occurred
+///
+/// \todo We need to understand what the firmware is expected to do when the
+/// 'read not ready' or other error responses come back. Here they will
+/// likely panic.
+
+int
+vrm_voltage_write(int vrm_select,
+ uint8_t vdd_vid,
+ int8_t vcs_offset,
+ int phases)
+{
+ int i, port;
+ uint64_t result;
+ pmc_o2s_ctrl_reg1_t pocr;
+ pmc_o2s_status_reg_t posr;
+ vrm_write_transaction_t vwt;
+ vrm_write_resp_t vwr;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((vrm_select <= 0) ||
+ (vrm_select > 0x7) ||
+ (phases < 0) ||
+ (phases > 0xf),
+ VRM_INVALID_ARGUMENT_VWRITE);
+ }
+
+ // Check for O2S busy
+
+ posr.value = in32(PMC_O2S_STATUS_REG);
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(posr.fields.o2s_ongoing, O2S_BUSY_VRM_VOLTAGE_WRITE);
+ }
+
+ // Use O2S to set voltage and read status, one port at a time.
+
+ for (i = 0; i < SPIVRM_NPORTS; i++) {
+
+ port = vrm_select & SPIVRM_PORT(i);
+ if (port != 0) {
+
+ // Set the (singular) O2S port
+
+ pocr.value = in32(PMC_O2S_CTRL_REG1);
+ pocr.fields.o2s_port_enable = port;
+ out32(PMC_O2S_CTRL_REG1, pocr.value);
+
+ // Create and initiate a voltage write command
+
+ vwt.value = 0;
+ vwt.fields.command = VRM_WRITE_VOLTAGE;
+ vwt.fields.vdd_vid = vdd_vid;
+ vwt.fields.vcs_offset = vcs_offset;
+ vwt.fields.phase_enable = phases;
+
+
+ o2s_start_poll(vwt.value, &result);
+ // Check the status
+ vwr.value = result << 32;
+
+ // results are duplicated 3x, using first byte for checking
+
+ SSX_ERROR_IF(vwr.fields.write_status0 == 0x00, O2S_READ_NOT_READY);
+ SSX_ERROR_IF(vwr.fields.write_status0 == 0x55, O2S_WRITE_ECC_ERROR);
+ SSX_ERROR_IF(vwr.fields.write_status0 != 0xAA, O2S_WRITE_NOT_VALID);
+ }
+ }
+ return 0;
+}
+
+/// Read VRM state using the O2S bridge
+///
+/// \param vrm_select A 3-bit vector of VRM selected for the operation.
+/// This procedure only allows 1 VRM to be selected.
+///
+/// \param vrail A 4-bit value for selecting a voltage rail
+///
+/// \param[out] o_vid The resulting 8-bit VRM-11 encoded voltage ID
+///
+///
+/// \retval 0 Success
+///
+/// \retval -VRM_INVALID_ARGUMENT_SREAD One of the arguments was invalid in some
+/// way.
+///
+/// \retval -O2S_BUSY_VRM_READ_STATE The O2S bridge is currently busy
+///
+
+int
+vrm_read_state(int vrm_select,
+ int *mnp1,
+ int *mn,
+ int *vfan,
+ int *vovertmp)
+{
+ int i, port;
+ uint64_t result;
+ pmc_o2s_status_reg_t posr;
+ pmc_o2s_ctrl_reg1_t pocr;
+ vrm_read_state_t vrs;
+ vrm_read_state_resp_t vrsr;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((!((vrm_select == SPIVRM_PORT(0)) ||
+ (vrm_select == SPIVRM_PORT(1)) ||
+ (vrm_select == SPIVRM_PORT(2)))),
+ VRM_INVALID_ARGUMENT_SREAD);
+ }
+
+
+ // Check for O2S busy
+
+ posr.value = in32(PMC_O2S_STATUS_REG);
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(posr.fields.o2s_ongoing, O2S_BUSY_VRM_READ_STATE);
+ }
+
+ // Use O2S to read voltage for selected rail.
+
+ for (i = 0; i < SPIVRM_NPORTS; i++) {
+
+ port = vrm_select & SPIVRM_PORT(i);
+ if (port != 0) {
+
+ // Set the (singular) O2S port
+
+ pocr.value = in32(PMC_O2S_CTRL_REG1);
+ pocr.fields.o2s_port_enable = port;
+ out32(PMC_O2S_CTRL_REG1, pocr.value);
+
+ // Create and initiate a voltage read command
+
+ vrs.value = 0;
+ vrs.fields.command = VRM_READ_STATE;
+
+
+ o2s_start_poll(vrs.value, &result);
+ // Check the status
+ vrsr.value = result << 32;
+
+ // results are duplicated 3x, returning first byte
+ *mnp1 = vrsr.fields.minus_nplus1_0;
+ *mn = vrsr.fields.minus_n0;
+ *vfan = vrsr.fields.vrm_fan0;
+ *vovertmp = vrsr.fields.vrm_overtemp0;
+
+ }
+ }
+ return 0;
+}
+
+
+/// Read a voltage using the O2S bridge
+///
+/// \param vrm_select A 3-bit vector of VRM selected for the operation.
+/// This procedure only allows 1 VRM to be selected.
+///
+/// \param vrail A 4-bit value for selecting a voltage rail
+///
+/// \param[out] o_vid The resulting 8-bit VRM-11 encoded voltage ID
+///
+///
+/// \retval 0 Success
+///
+/// \retval -VRM_INVALID_ARGUMENT_VREAD One of the arguments was invalid in some
+/// way.
+///
+/// \retval -O2S_BUSY_VRM_VOLTAGE_READ The O2S bridge is currently busy
+///
+
+int
+vrm_voltage_read(int vrm_select,
+ uint8_t vrail,
+ uint8_t *o_vid)
+{
+ int i, port;
+ uint64_t result;
+ pmc_o2s_status_reg_t posr;
+ pmc_o2s_ctrl_reg1_t pocr;
+ vrm_read_voltage_t vrv;
+ vrm_read_voltage_resp_t vrvr;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((!((vrm_select == SPIVRM_PORT(0)) ||
+ (vrm_select == SPIVRM_PORT(1)) ||
+ (vrm_select == SPIVRM_PORT(2)))) ||
+ (vrail > (SPIVRM_NRAILS - 1)),
+ VRM_INVALID_ARGUMENT_VREAD);
+ }
+
+
+ // Check for O2S busy
+
+ posr.value = in32(PMC_O2S_STATUS_REG);
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(posr.fields.o2s_ongoing, O2S_BUSY_VRM_VOLTAGE_READ);
+ }
+
+ // Use O2S to read voltage for selected rail.
+
+ for (i = 0; i < SPIVRM_NPORTS; i++) {
+
+ port = vrm_select & SPIVRM_PORT(i);
+ if (port != 0) {
+
+ // Set the (singular) O2S port
+
+ pocr.value = in32(PMC_O2S_CTRL_REG1);
+ pocr.fields.o2s_port_enable = port;
+ out32(PMC_O2S_CTRL_REG1, pocr.value);
+
+ // Create and initiate a voltage read command
+
+ vrv.value = 0;
+ vrv.fields.command = VRM_READ_VOLTAGE;
+ vrv.fields.rail = vrail;
+
+
+ o2s_start_poll(vrv.value, &result);
+ // Check the status
+ vrvr.value = result << 32;
+
+ // results are duplicated 3x, returning first byte
+ *o_vid = vrvr.fields.vid0;
+ }
+ }
+ return 0;
+}
+
+
+
+
diff --git a/src/lib/vrm.h b/src/lib/vrm.h
new file mode 100755
index 0000000..2efea4d
--- /dev/null
+++ b/src/lib/vrm.h
@@ -0,0 +1,59 @@
+#ifndef __VRM_H__
+#define __VRM_H__
+
+// $Id: vrm.h,v 1.2 2014/02/03 01:30:26 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/vrm.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file vrm.h
+/// \brief PgP SPIVRM procedures
+
+#include "ssx.h"
+
+#ifndef __ASSEMBLER__
+
+int
+o2s_initialize();
+
+int
+spivid_initialize();
+
+
+int
+vrm_voltage_write(int vrm_select,
+ uint8_t vdd_vid,
+ int8_t vcs_offset,
+ int phases);
+
+int
+vrm_read_state(int vrm_select,
+ int *mnp1,
+ int *mn,
+ int *vfan,
+ int *vovertmp);
+
+int
+vrm_voltage_read(int vrm_select,
+ uint8_t vrail,
+ uint8_t *o_vid);
+
+#endif /* __ASEMBLER__ */
+
+// Error/panic codes
+
+#define O2S_BUSY_VRM_VOLTAGE_READ 0x00627001
+#define O2S_BUSY_VRM_VOLTAGE_WRITE 0x00627002
+#define O2S_BUSY_VRM_READ_STATE 0x00627003
+#define O2S_READ_NOT_READY 0x00627004
+#define O2S_WRITE_NOT_VALID 0x00627005
+#define O2S_WRITE_ECC_ERROR 0x00627006
+#define VRM_INVALID_ARGUMENT_VREAD 0x00627007
+#define VRM_INVALID_ARGUMENT_VWRITE 0x00627008
+#define VRM_INVALID_ARGUMENT_SREAD 0x00627009
+#define VRM_INVALID_ARGUMENT_INIT 0x0062700a
+
+#endif /* __VRM_H__ */
diff --git a/src/occ/Makefile b/src/occ/Makefile
new file mode 100755
index 0000000..9a9f975
--- /dev/null
+++ b/src/occ/Makefile
@@ -0,0 +1,104 @@
+# $Id$
+
+# @file Makefile
+#
+# @brief Makefile occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+include cfiles.mk
+include gpefiles.mk
+include debug_trace.mk
+
+APP = occ
+APP_INCLUDES += -I../ssx
+APP_INCLUDES += -I../lib
+APP_INCLUDES += -I./incl
+APP_INCLUDES += -I./trac
+APP_INCLUDES += -I./async
+APP_INCLUDES += -I./errl
+APP_INCLUDES += -I./gpe
+APP_INCLUDES += -I./thread
+APP_INCLUDES += -I./aplt
+APP_INCLUDES += -I./aplt/incl
+APP_INCLUDES += -I./rtls
+APP_INCLUDES += -I./dcom
+APP_INCLUDES += -I./sensor
+APP_INCLUDES += -I./pss
+APP_INCLUDES += -I./proc
+APP_INCLUDES += -I./cent
+APP_INCLUDES += -I./cmdh
+APP_INCLUDES += -I./amec
+APP_INCLUDES += -I.
+APP_INCLUDES += -I../occ
+APP_INCLUDES += -I../../occ
+APP_INCLUDES += -I./timer
+
+export APP_INCLUDES
+
+D += -DOCC_FIRMWARE=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DOCC=1 \
+ -DNONCACHEABLE_SUPPORT=1 \
+ -DUSE_SSX_APP_CFG_H=1
+#D = -DVERIFICATION=1 \
+ -DSSX_STACK_CHECK=0 \
+ -DINITIALIZE_PMC=0 \
+ -DINITIALIZE_SIMICS_IO=0 \
+ -DINITIALIZE_RTX_IO=1 \
+ -DINITIALIZE_PBA=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DSSX_KERNEL_TRACE_ENABLE=1
+
+# If this makefile is called as "make NO_TRAC_STRINGS=1" then trace strings
+# won't be built into the image. This will be used for metrics regarded to the
+# realistic OCC Code Size. Note that "make clean" must be run before this define
+# will be picked up by the compiler, otherwise previously compiled objects will
+# be used. You can also see the space used by strings by running:
+# strings occ.bin | \grep "ERR\|INF\|IMP" | sed 's/^...: %s: //g' | wc -m
+ifdef NO_TRAC_STRINGS
+D += -DNO_TRAC_STRINGS=1 # @th002a
+endif
+
+# @pb009a - Added define to be used to enable/disable debug traces
+# usage to enable debug traces: "make OCC_DBG_TRACE=1"
+# @rc001d - remove OCC_DBG_TRACE 01/16/2012 - trace debug improvement
+
+
+# Added define to be used to enable/disable OCC_ALONE simics model
+# supported components. The only components not supported on occ_alone
+# is FSP & PHYP, so this will be used to fake out all commands we need
+# from FSP, and automatically go ACTIVE.
+# usage: "make FSPLESS_SIMICS=1" to enable this mode
+ifdef FSPLESS_SIMICS # @th029c
+D += -DFSPLESS_SIMICS=1
+endif
+
+# Added define to be used to enable GCOV based code coverage tools.
+# For now, this only works in the "occ" source files, not ssx or lib.
+# usage: "make GCOV_CODE_COVERAGE=1"
+ifdef GCOV_CODE_COVERAGE # @th029a
+D += -DGCOV_CODE_COVERAGE=1
+endif
+
+SOURCES = ${all_cfiles} ${all_gpefiles}
+MODE = validation
+
+PGP_ASYNC_SUPPORT = 1
+
+include ./app.mk
+
+pgas:
+ $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10' ${all_gpefiles}
diff --git a/src/occ/amec/amec_amester.c b/src/occ/amec/amec_amester.c
new file mode 100755
index 0000000..2c8690f
--- /dev/null
+++ b/src/occ/amec/amec_amester.c
@@ -0,0 +1,1502 @@
+/******************************************************************************
+// @file amec_amester.c
+// @brief Amester interface
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_amester_c amec_amester.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @at003 alvinwan 03/19/2012 New file. Add amester interface.
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @at008 alvinwan 08/09/2012 Support AME Pass Thru command from TMGT
+ * @ry001 853436 ronda 09/14/2012 Added Amester sub command support (phase one)
+ * @gs014 903552 gjsilva 10/22/2013 Support for Amester parameter interface
+ * @mw584 mware 11/30/2013 Changed freq250us to be freqa2ms. Added IPMI command to set analytics scheduling.
+ * @mw643 mware 03/02/2014 Added IPMI command to control analytics thread modes.
+ * @gs027 918066 gjsilva 03/12/2014 Added trace buffer engine
+ * @mw662 mware 03/25/2014 Added IPMI command to control and read CPM calibration information.
+ * @mw671 933716 mware 05/17/2014 Added IPMI command to set the ambient temperature and fan speed sensors.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include <rtls.h>
+#include <occ_service_codes.h> // for SSX_GENERIC_FAILURE
+#include <sensor.h>
+#include <amec_smh.h>
+#include <amec_master_smh.h>
+#include <amec_amester.h>
+#include <amec_sys.h> // @mw531
+#include <trac.h> // For traces
+#include <appletManager.h>
+#include <sensorQueryList.h>
+#include <proc_data.h>
+#include <amec_parm.h>
+#include <string.h>
+#include <occ_sys_config.h>
+#include <dcom.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+///Maximum size of trace buffer
+#define AMEC_TB_2MS_SIZE_BYTES 8192
+#define AMEC_TB_250US_SIZE_BYTES 8192
+#define AMEC_TB_SIZE_BYTES (AMEC_TB_250US_SIZE_BYTES + AMEC_TB_2MS_SIZE_BYTES)
+
+///Maximum number of trace buffers we will support
+#define AMEC_MAX_NUM_TB 2
+
+///Maximum size of config info for 1 trace buffer
+#define AMEC_TB_CONFIG_SIZE (MAX_SENSOR_NAME_SZ + 4)
+#define MAX_NUM_CHIPS MAX_NUM_OCC
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Each trace buffer should be aligned to 128 bytes in main memory because the
+// block copy engine only copies multiples of 128 byte units.
+// Make this a power of 2 (bytes) in size and aligned to 4 bytes.
+DMA_BUFFER(UINT8 g_amec_tb_bytes[AMEC_TB_SIZE_BYTES]);
+
+// Array that maintains a list of all trace buffers built.
+// NOTE: Must be in same order as AMEC_TB_ENUM
+DMA_BUFFER(amec_tb_t g_amec_tb_list[AMEC_MAX_NUM_TB]) = {
+ //trace 2ms
+ [AMEC_TB_2MS] = {
+ "trace2ms", // name
+ AMEFP(500,0), // freq
+ (UINT8*)(UINT32)g_amec_tb_bytes, // bytes
+ AMEC_TB_2MS_SIZE_BYTES, // size
+ 0, // entry_size
+ 0, // entry_n
+ 0, // write
+ 0, // read
+ 0, // sensors_n
+ 0, // parm_n
+ {0}, // sensors_field[]
+ {0}, // sensors_num[]
+ {0} // parms_num[]
+ },
+ // trace 250us
+ [AMEC_TB_250US] = {
+ "trace250us", // name
+ AMEFP(4000,0), // freq
+ (UINT8*)(UINT32)g_amec_tb_bytes+AMEC_TB_2MS_SIZE_BYTES, // bytes
+ AMEC_TB_250US_SIZE_BYTES, //size
+ 0, // entry_size
+ 0, // entry_n
+ 0, // write
+ 0, // read
+ 0, // sensors_n
+ 0, // parm_n
+ {0}, // sensors_field[]
+ {0}, // sensors_num[]
+ {0} // parms_num[]
+ }
+};
+
+//Throw a compiler error when the enum and array are not both updated
+STATIC_ASSERT((AMEC_TB_NUMBER_OF_TRACES != (sizeof(g_amec_tb_list)/sizeof(amec_tb_t))));
+
+///=1 signals a trace is being taken
+UINT8 g_amec_tb_record=0;
+///=1 signals continuous tracing
+UINT8 g_amec_tb_continuous=0; //CL273
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+// Function Specification
+//
+// Name: amester_get_sensor_info
+//
+// Description: Returns name, units, update frequency, and scalefactor for a sensor
+//
+//
+// Flow: FN=
+//
+// Task Flags:
+//
+// End Function Specification
+static uint8_t amester_get_sensor_info( uint8_t* o_resp, uint16_t* io_resp_length, const uint8_t i_type, const uint16_t i_sensor)
+{
+ uint8_t l_rc = COMPCODE_NORMAL; // assume no error
+ sensor_t * l_sensor_ptr = NULL;
+ uint16_t l_numOfSensors = 1;
+ sensor_info_t l_sensorInfo;
+ errlHndl_t l_err = NULL;
+ OCC_APLT_STATUS_CODES l_status = 0;
+ uint16_t l_resp_length = 0;
+
+ do
+ {
+ // Check o_resp and io_resp_length pointers
+ if( (o_resp == NULL) ||
+ (io_resp_length == NULL) )
+ {
+ l_rc = COMPCODE_UNSPECIFIED;
+ break;
+ }
+
+ l_resp_length = *io_resp_length;
+ *io_resp_length = 0;
+
+ if (i_sensor >= MAX_AMEC_SENSORS )
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ l_sensor_ptr = getSensorByGsid(i_sensor);
+ if(l_sensor_ptr == NULL)
+ {
+ // Didn't find it
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ querySensorListAppletArg_t l_querySensorListAppletArg = {
+ i_sensor, // i_startGsid
+ 0, // i_present
+ SENSOR_TYPE_ALL, // i_type
+ SENSOR_LOC_ALL, // i_loc
+ &l_numOfSensors, // io_numOfSensors
+ NULL, // o_sensors
+ &l_sensorInfo // o_sensorInfoPtr
+ };
+
+
+ //Call sensor query list applet
+ runApplet(OCC_APLT_SNSR_QUERY, // Applet enum Name
+ &l_querySensorListAppletArg, // Applet arguments
+ TRUE, // Blocking call?
+ NULL, // Applet finished semaphore
+ &l_err, // Error log handle
+ &l_status); // Error status
+
+ if( NULL != l_err)
+ {
+ // Query failure, it should not happens
+ TRAC_ERR("Failed to run OCC_APLT_SNSR_QUERY applet. Error status is : 0x%x", l_status);
+
+ // commit error log
+ commitErrl( &l_err );
+
+ l_rc = COMPCODE_UNSPECIFIED;
+ break;
+ }
+
+ switch (i_type)
+ {
+ case AME_INFO_NAME:
+ {
+ char *src = l_sensorInfo.name;
+ char *dest = (char*)o_resp;
+ uint16_t l_length = strlen(src)+1; // add string terminator
+
+ // Check length
+ if(l_resp_length < l_length)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+ // Copy string
+ strcpy( dest, src );
+ *io_resp_length = l_length;
+ break;
+ }
+
+ case AME_INFO_UNITS:
+ {
+ char *src = l_sensorInfo.sensor.units;
+ char *dest = (char*)o_resp;
+ uint16_t l_length = strlen(src)+1; // add string terminator
+
+ // Check length
+ if(l_resp_length < l_length)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ // Copy string
+ strcpy( dest, src );
+ *io_resp_length = l_length;
+ break;
+ }
+
+ case AME_INFO_FREQ:
+ {
+ uint16_t l_length = sizeof( uint32_t);
+
+ // Check length
+ if(l_resp_length < l_length)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ *((uint32_t *)o_resp) = l_sensorInfo.sensor.freq;
+ *io_resp_length = l_length;
+ break;
+ }
+
+ case AME_INFO_SCALE:
+ {
+ uint16_t l_length = sizeof( uint32_t);
+
+ // Check length
+ if(l_resp_length < l_length)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ *((uint32_t *)o_resp) = l_sensorInfo.sensor.scalefactor;
+ *io_resp_length = l_length;
+ break;
+ }
+
+ case AME_INFO_ALL: //Added for AME API 2.16
+ {
+ char *src = NULL;
+ char *dest = (char*)o_resp;
+ uint16_t l_length = strlen(l_sensorInfo.name) + 1 +\
+ strlen(l_sensorInfo.sensor.units) + 1 + \
+ sizeof(uint32_t) + sizeof(uint32_t);
+ // Check length
+ if(l_resp_length < l_length)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ src = l_sensorInfo.name;
+ // Copy string
+ strcpy( dest, src );
+ dest += strlen(src)+1; // add string terminator
+
+ src = l_sensorInfo.sensor.units;
+ // Copy string
+ strcpy( dest, src );
+ dest += strlen(src)+1; // add string terminator
+
+ *((uint32_t *)dest) = l_sensorInfo.sensor.freq;
+ dest+= 4;
+
+ *((uint32_t *)dest) = l_sensorInfo.sensor.scalefactor;
+ dest+= 4;
+
+ *io_resp_length = (uint8_t) ((uint32_t)dest - (uint32_t)o_resp);
+ break;
+ }
+
+ default:
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ } // End of switch case
+ } while (0);
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: amester_api
+//
+// Description: amester entry point for ipmicommand 0x3C
+//
+//
+// Flow: FN=
+//
+// Task Flags:
+//
+// End Function Specification
+uint8_t amester_api( const IPMIMsg_t * i_msg,
+ uint16_t * io_resp_length,
+ uint8_t * o_resp )
+{
+ uint8_t l_rc = COMPCODE_NORMAL;
+ uint8_t l_temp_buffer[ sizeof(sensor_info_t) ];
+ sensor_t *l_sensor_ptr = NULL;
+ uint16_t l_sensor_id = 0; // sensor id
+ uint16_t l_sensor_count = 0; // sensor count
+ uint8_t l_sensor_type = 0; // sensor type
+ uint16_t l_maxlen = 0, l_retlen = 0; // for echo command and 0xff command
+ uint16_t l_resp_length = *io_resp_length;
+ sensorrec_t SensorInfo;
+
+ switch( i_msg->au8CmdData_ptr[0] )
+ {
+ // commands 0x01 ~ 0x1B are DEPRECATED except 0x07, 0x0A
+
+ case 0x07: // Get Multiple Sensor Data
+ {
+ uint16_t l_in; // input pointer
+ uint16_t l_out=0; // output pointer
+ char *t;
+ int k;
+ l_rc = COMPCODE_NORMAL;; // assume no error
+
+ // Process each sensor in turn
+ for (l_in = 1; l_in + 1 < i_msg->u8CmdDataLen; l_in=l_in+2)
+ {
+ // exit when a return message is filled. -1 is for IPMI return code
+ if (l_out + AME_SDRS > IPMI_MAX_MSG_SIZE - 1) break;
+
+ // Get the next sensor
+ l_sensor_id = CONVERT_UINT8_ARRAY_UINT16(i_msg->au8CmdData_ptr[l_in],
+ i_msg->au8CmdData_ptr[l_in+1]);
+ l_sensor_ptr = getSensorByGsid(l_sensor_id);
+ if(l_sensor_ptr == NULL)
+ {
+ // Mark which sensor number does not exist
+ o_resp[0] = (uint8_t)(l_in >> 8);
+ o_resp[1] = (uint8_t)(l_in);
+ *io_resp_length = 2;
+ l_rc = COMPCODE_DEST_UNAVAILABLE;
+ break;
+ }
+
+ /* Get a snap-shot of this sensors registers */
+ /* This copy is required so the bytes in each field are self-consistent
+ since the AME interrupt can modify them at any time. Note that it is
+ possible that the fields are not consistent with each other, but this
+ is how Amester has always been. Use traces to get a consistent view.*/
+ SensorInfo.timestamp=G_current_tick;
+ SensorInfo.updates=l_sensor_ptr->update_tag;
+ SensorInfo.accumulated_value=l_sensor_ptr->accumulator;
+ SensorInfo.value=l_sensor_ptr->sample;
+ SensorInfo.value_min=l_sensor_ptr->sample_min;
+ SensorInfo.value_max=l_sensor_ptr->sample_max;
+ memcpy(&SensorInfo.status,&l_sensor_ptr->status,sizeof(uint16_t));
+ SensorInfo.test=0; //TODO: This field is not supported for now. Maybe need to change in the future.
+
+ // Copy to output buffer.
+ t=(char *)&SensorInfo;
+ for (k=0;k<AME_SDRS;k++) o_resp[l_out++]=*t++;
+
+ *io_resp_length = l_out;
+
+ } // for each sensor
+
+ break;
+ };
+
+ case 0x0a: // Get API version
+ o_resp[0] = AME_API_MAJ;
+ o_resp[1] = AME_API_MIN; //TODO: should change AME_API_MIN to 26 in phase 2 if Amester tool souce is updated
+ *io_resp_length = 2;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ //----------------------------------------------------------------------
+ // AME 2.16 commands
+ //----------------------------------------------------------------------
+ case 0x1c: // AME component level constants
+ // Goal is to allow 1 IPMI to get a bunch of important data at startup.
+ // Dramatically speedup Amester initialization
+
+ // Check length
+ if(l_resp_length < AME_COMPONENT_LEVEL_RSPCMD_LEN)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ o_resp[0] = AME_API_MAJ;
+ o_resp[1] = AME_API_MIN;
+ o_resp[2] = AME_VERSION_MAJ;
+ o_resp[3] = AME_VERSION_MIN;
+ o_resp[4] = CONVERT_UINT16_UINT8_HIGH(AME_YEAR);
+ o_resp[5] = CONVERT_UINT16_UINT8_LOW(AME_YEAR);
+ o_resp[6] = AME_MONTH;
+ o_resp[7] = AME_DAY;
+ o_resp[8] = CONVERT_UINT16_UINT8_HIGH(G_amec_sensor_count);
+ o_resp[9] = CONVERT_UINT16_UINT8_LOW(G_amec_sensor_count);
+ o_resp[10] = AMEC_TB_NUMBER_OF_TRACES;
+ *io_resp_length = AME_COMPONENT_LEVEL_RSPCMD_LEN;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ case 0x1d:
+
+ // Check length
+ if(l_resp_length < 2)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ o_resp[0] = 0;
+ o_resp[1] = 0;
+ *io_resp_length = 2;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ //Clear min/max fields in all sensors.
+ case 0x21:
+ l_sensor_ptr = NULL;
+ l_sensor_count = G_amec_sensor_count;
+
+ // clear min/max
+ uint16_t i = 0;
+ for( i = 0;i < l_sensor_count; i++)
+ {
+ l_sensor_ptr = getSensorByGsid(i);
+ sensor_clear_minmax(l_sensor_ptr);
+ }
+ *io_resp_length = 0;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ case 0x25: // Get sensors info
+ l_rc = COMPCODE_NORMAL;
+ l_sensor_type = i_msg->au8CmdData_ptr[3];
+ l_sensor_count = G_amec_sensor_count;
+ l_sensor_id = CONVERT_UINT8_ARRAY_UINT16( i_msg->au8CmdData_ptr[1],
+ i_msg->au8CmdData_ptr[2] );
+ uint16_t j = 0;
+ uint16_t l_final_length = 0;
+
+ for( j = l_sensor_id; j < l_sensor_count; j++)
+ {
+ *io_resp_length = sizeof(sensor_info_t);
+ l_rc = amester_get_sensor_info(l_temp_buffer,io_resp_length,l_sensor_type,j);
+ if(l_rc != COMPCODE_NORMAL)
+ {
+ l_final_length = 0;
+ break;
+ }
+
+ // max response length is IPMI_MAX_MSG_SIZE
+ if( ((l_final_length+(*io_resp_length)) < IPMI_MAX_MSG_SIZE) &&
+ ((l_final_length+(*io_resp_length)) < l_resp_length ) ) // @at008a
+ {
+ memcpy( o_resp, l_temp_buffer, *io_resp_length); // Copy to final output buffer
+ o_resp += (*io_resp_length);
+ l_final_length = l_final_length+(*io_resp_length);
+ }
+ else
+ {
+ break;
+ }
+ }
+ *io_resp_length = l_final_length;
+ break;
+
+ // Trace buffer commands
+ // Get trace buffer configuration
+ case 0x30:
+ amec_tb_cmd_info(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Configure TB
+ case 0x31:
+ amec_tb_cmd_set_config(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Read TB
+ // Input is an index into the buffer.
+ // Output is a full-sized response, possibly wrapping around at end of buffer.
+ case 0x32:
+ amec_tb_cmd_read(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Start recording TB
+ case 0x33:
+ amec_tb_cmd_start_recording(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Stop recording TB
+ case 0x34:
+ amec_tb_cmd_stop_recording(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Get sensor table, not support
+ case 0x35: //Not support
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+
+ // Get SCOM table, not support
+ case 0x36: //Not support
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+
+ // Return all configurable parameters for a trace
+ case 0x3f:
+ amec_tb_cmd_get_config(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Get number of parameters
+ case 0x40:
+ amec_parm_get_number(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Return configuration of parameters starting with a given guid
+ case 0x41:
+ amec_parm_get_config(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Read parameter
+ case 0x42:
+ amec_parm_read(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Write parameter
+ case 0x43:
+ amec_parm_write(i_msg,o_resp,io_resp_length,&l_rc);
+ break;
+
+ // Partition management
+ case 0x50: //Not support
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+
+ // Note: Amester uses the echo command to figure out how much data it is
+ // allowed to send in 1 message to OCC.
+ case 0xfe: //echo
+ l_maxlen = IPMI_MAX_MSG_SIZE - 1; // -1 for completion code
+ l_retlen = l_maxlen;
+
+ // Pick the smaller of the input length and max output length.
+ if (i_msg->u8CmdDataLen < l_maxlen)
+ {
+ l_retlen = i_msg->u8CmdDataLen;
+ }
+
+ // Check length
+ if(l_resp_length < l_retlen)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ l_rc = COMPCODE_NORMAL; /* assume no error */
+ // Copy back as much of the input message as possible.
+ memcpy( o_resp, i_msg->au8CmdData_ptr, l_retlen);
+ *io_resp_length = l_retlen;
+ break;
+
+ // Note: Amester uses this command to find out the maximum length output
+ // message OCC supports.
+ case 0xff:
+ l_maxlen = IPMI_MAX_MSG_SIZE - 1; // -1 for completion code
+
+ if (i_msg->u8CmdDataLen == 3)
+ {
+ l_maxlen = CONVERT_UINT8_ARRAY_UINT16( i_msg->au8CmdData_ptr[1],
+ i_msg->au8CmdData_ptr[2]);
+ }
+
+ if (l_maxlen > IPMI_MAX_MSG_SIZE -1)
+ {
+ l_maxlen = IPMI_MAX_MSG_SIZE -1;
+ }
+
+ // Check length
+ if(l_resp_length < l_maxlen)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ l_rc = COMPCODE_NORMAL; /* assume no error */
+ for (i = 0; i<l_maxlen; i++)
+ {
+ o_resp[i] = i;
+ }
+ *io_resp_length = l_maxlen;
+ break;
+
+ default:
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ }
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: amester_manual_throttle
+//
+// Description: Amester interface entry point for ipmicommand 0x3B
+//
+//
+// Flow: FN=
+//
+// Task Flags:
+//
+// End Function Specification
+uint8_t amester_manual_throttle( const IPMIMsg_t * i_msg,
+ uint16_t * io_resp_length,
+ uint8_t * o_resp )
+
+{
+ /*------------------------------------------------------------------------*/
+ /* Local variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc,temp1,temp2; // @mw531
+ uint16_t l_resp_length = *io_resp_length;
+ uint16_t i,j,cc,idx,temp16;
+ uint16_t k; // @mw581
+ uint32_t temp32a;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ switch (i_msg->au8CmdData_ptr[0])
+ {
+ case 0x03: // CPU(s) Present Bit Mask
+ // The CPU Present Bit Mask is now being generated by the
+ // PROC component of OCC.
+
+ // Check length
+ if(l_resp_length < 2)
+ {
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ o_resp[0] = CONVERT_UINT32_UINT8_UPPER_HIGH( G_present_hw_cores);
+ o_resp[1] = CONVERT_UINT32_UINT8_UPPER_LOW( G_present_hw_cores);
+ *io_resp_length = 2;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ case 0x04: // Get last throttle value sent to CPU 0. DEPRECATED.
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+
+ case 0x05: // Get AME enable/disable flag (old style interface...do not use), not support
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+
+ case 0x06: // Get new PTVR (Power Threshold Vector Request), not support
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+
+ case 0x07: // Write individual AME parameters
+ switch (i_msg->au8CmdData_ptr[1])
+ {
+ case 22: // parameter 22: Analytics parameters @mw584
+ {
+ g_amec->analytics_group=i_msg->au8CmdData_ptr[2]; // Set group
+ g_amec->analytics_chip=i_msg->au8CmdData_ptr[3]; // Select which chip to analyze
+ g_amec->analytics_option=i_msg->au8CmdData_ptr[4]; // Select which option
+ g_amec->analytics_total_chips=i_msg->au8CmdData_ptr[5]; // Select total number of chips
+ g_amec->analytics_slot=i_msg->au8CmdData_ptr[6]; // Select time slot to read data
+ o_resp[0]=i_msg->au8CmdData_ptr[2];
+ o_resp[1]=i_msg->au8CmdData_ptr[3];
+ o_resp[2]=i_msg->au8CmdData_ptr[4];
+ o_resp[3]=i_msg->au8CmdData_ptr[5];
+ o_resp[4]=i_msg->au8CmdData_ptr[6];
+ *io_resp_length=5;
+ l_rc = COMPCODE_NORMAL;
+ break;
+ }
+
+ case 23: // parameter 23: CPM calibration parameters @mw662
+ {
+ // g_amec->cpms_enabled=i_msg->au8CmdData_ptr[2]; // Enable CPMs
+ o_resp[0]=i_msg->au8CmdData_ptr[2];
+ *io_resp_length=1;
+ l_rc = COMPCODE_NORMAL;
+ break;
+ }
+
+
+ case 24: // parameter 24: set ambient and fan speed sensors @mw671
+ {
+ // Set ambient temperature (8 bits)
+ temp16=(uint16_t)i_msg->au8CmdData_ptr[2];
+ sensor_update(AMECSENSOR_PTR(TEMPAMBIENT), temp16);
+ // Set average fan speed (16 bits)
+ temp16=((uint16_t)i_msg->au8CmdData_ptr[3]<<8)+(uint16_t)i_msg->au8CmdData_ptr[4];
+ sensor_update(AMECSENSOR_PTR(FANSPEEDAVG), temp16);
+ o_resp[0]=i_msg->au8CmdData_ptr[2];
+ o_resp[1]=i_msg->au8CmdData_ptr[3];
+ o_resp[2]=i_msg->au8CmdData_ptr[3];
+ *io_resp_length=3;
+ l_rc = COMPCODE_NORMAL;
+ break;
+ }
+
+ case 29: // parameter 29: Control vector recording modes and stream rates.
+ {
+ g_amec->stream_vector_rate=255; // First step is to set an invalid rate so no recording done at all
+ g_amec->stream_vector_mode=0; // Also is to assure NO recording during parameter changes
+ g_amec->stream_vector_group=i_msg->au8CmdData_ptr[4]; // Choose group #
+ g_amec->write_stream_index=(uint32_t)CONVERT_UINT8_ARRAY_UINT16(i_msg->au8CmdData_ptr[5],i_msg->au8CmdData_ptr[6]);
+ g_amec->stream_vector_delay=(uint32_t)CONVERT_UINT8_ARRAY_UINT16(i_msg->au8CmdData_ptr[7],i_msg->au8CmdData_ptr[8]);
+ g_amec->stream_vector_mode=i_msg->au8CmdData_ptr[2]; // Choose mode
+
+ switch (g_amec->stream_vector_group)
+ {
+ case 44: // $mw581 group 44 decimal (amec_analytics support)
+ g_amec->stream_vector_map[0]=0; // Leave space for 250usec time stamp
+ k = 1;
+ for (i=0; i<=46; i++)
+ {
+ g_amec->stream_vector_map[k++] = &g_amec->analytics_array[i];
+ }
+ //gpEMP->stream_vector_map[48]=(void *) 0xffffffff; // Termination of partial vector
+ g_amec->analytics_group=44;
+ g_amec->analytics_bad_output_count=2; // drop first 2 frames of output @mw587
+ break;
+
+ default:
+ break;
+ }
+
+ // Final step is to set a valid rate to begin recording at
+ g_amec->stream_vector_rate=i_msg->au8CmdData_ptr[3]; // Choose stream rate
+ g_amec->recordflag=1; // Recording is now valid
+ *io_resp_length = 1;
+ l_rc = COMPCODE_NORMAL;
+ break;
+ }
+
+ case 64: // support for THREADMODE group 44 recording // $mw643
+ g_amec->analytics_threadmode=i_msg->au8CmdData_ptr[2];
+ g_amec->analytics_threadcountmax=i_msg->au8CmdData_ptr[3];
+ o_resp[0]=i_msg->au8CmdData_ptr[2];
+ o_resp[1]=i_msg->au8CmdData_ptr[3];
+ *io_resp_length=2;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ default:
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ break;
+
+ case 0x08: // Read individual AME parameters
+ switch (i_msg->au8CmdData_ptr[1])
+ {
+ case 0x08: // parameter 8: Set histogram copy interval in msec (4 bytes)
+ o_resp[0] = (uint8_t)(AME_HISTOGRAM_COPY_INTERVAL>>24);
+ o_resp[1] = (uint8_t)(AME_HISTOGRAM_COPY_INTERVAL>>16);
+ o_resp[2] = (uint8_t)(AME_HISTOGRAM_COPY_INTERVAL>>8);
+ o_resp[3] = (uint8_t)(AME_HISTOGRAM_COPY_INTERVAL);
+ *io_resp_length = 4;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ case 22: // parameter 22: Analytics parameters @mw584
+ o_resp[0]=g_amec->analytics_group;
+ o_resp[1]=g_amec->analytics_chip;
+ o_resp[2]=g_amec->analytics_option;
+ o_resp[3]=g_amec->analytics_total_chips;
+ o_resp[4]=g_amec->analytics_slot;
+ *io_resp_length=5;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ case 23: // parameter 23: CPM parameters @mw662
+ // o_resp[0]=g_amec->cpms_enabled;
+ // o_resp[1]=g_amec->cpm_active_core;
+ // o_resp[2]=g_amec->cpm_cal_state;
+ // o_resp[3]=g_amec->cpm_core_state;
+ // o_resp[4]=g_amec->cpm_measure_state;
+ // o_resp[5]=g_amec->cpm_cal_count;
+ *io_resp_length=6;
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ case 29: // parameter 29: Stream recording control parameters
+ o_resp[0]=(uint8_t)(g_amec->stream_vector_mode);
+ o_resp[1]=(uint8_t)(g_amec->stream_vector_rate);
+ o_resp[2]=(uint8_t)(g_amec->write_stream_index>>8);
+ o_resp[3]=(uint8_t)(g_amec->write_stream_index & 0xff);
+ o_resp[4]=(uint8_t)(g_amec->stream_vector_delay>>8);
+ o_resp[5]=(uint8_t)(g_amec->stream_vector_delay & 0xff);
+ *io_resp_length=6;
+ l_rc=COMPCODE_NORMAL;
+ break;
+
+ case 37: // parameter 37: Read out (IPMI_MAX_MSG_SIZE-2*STREAM_VECTOR_SIZE) byte vector from
+ // streaming buffer
+ g_amec->read_stream_index=(uint32_t)((i_msg->au8CmdData_ptr[2]<<8)+i_msg->au8CmdData_ptr[3]);
+ temp1=i_msg->au8CmdData_ptr[4];
+ temp2=i_msg->au8CmdData_ptr[5];
+ if (g_amec->read_stream_index > (STREAM_BUFFER_SIZE-10*STREAM_VECTOR_SIZE_EX))
+ {
+ o_resp[0]=i_msg->au8CmdData_ptr[2];
+ *io_resp_length=1;
+ l_rc=COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+ if (temp1 > 1) // No averaging is allowed when using large read sizes
+ {
+ o_resp[0]=i_msg->au8CmdData_ptr[4];
+ *io_resp_length=1;
+ l_rc=COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+ if (temp2 > 0)
+ {
+ o_resp[0]=i_msg->au8CmdData_ptr[5];
+ *io_resp_length=1;
+ l_rc=COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+ if (g_amec->write_stream_index >= g_amec->read_stream_index)
+ {
+ temp32a=g_amec->write_stream_index-g_amec->read_stream_index;
+ }
+ else
+ {
+ temp32a=STREAM_BUFFER_SIZE+g_amec->write_stream_index-g_amec->read_stream_index;
+ }
+ if (temp32a < 10*STREAM_VECTOR_SIZE_EX)
+ {
+ o_resp[0]=1; // Indicate insufficient data, but return a zero return code
+ *io_resp_length=STREAM_VECTOR_SIZE_EX+3; // # of bytes (STREAM_VECTOR_SIZE is in 16 bit words)
+ l_rc=COMPCODE_NORMAL;
+ break;
+ }
+ o_resp[0]=0; // Indicate sufficient data
+ i=0;
+ j=10*STREAM_VECTOR_SIZE_EX;
+ cc=3; // Begin just past return code and time stamp
+
+ for(idx = i; idx < j; idx++) // Skip first 1 entry: either write_index and time stamp
+ {
+ temp16 = (uint16_t)g_amec->ptr_stream_buffer[g_amec->read_stream_index + idx];
+ o_resp[cc] = (temp16 >> 8);
+ o_resp[cc + 1] = (temp16 & 0xff);
+ cc = cc + 2; // output index
+ }
+ if(i_msg->au8CmdData_ptr[7] == 0)
+ {
+ temp16 = g_amec->ptr_stream_buffer[g_amec->read_stream_index]; // Send back time stamp
+ } else
+ {
+ temp16 = g_amec->write_stream_index; // Send back write stream index
+ }
+ o_resp[1] = (uint8_t)(temp16 >> 8);
+ o_resp[2] = (uint8_t)(temp16 & 0xff);
+ *io_resp_length = 3 + 2 * (10 * STREAM_VECTOR_SIZE_EX); // # of bytes (STREAM_VECTOR_SIZE_EX is in 16 bit words) $mw134
+ l_rc = COMPCODE_NORMAL;
+ break;
+
+ case 64: // support for THREADMODE group 44 recording $mw643
+ o_resp[0]=(uint8_t)(g_amec->analytics_threadmode);
+ o_resp[1]=(uint8_t)(g_amec->analytics_threadcountmax);
+ *io_resp_length=2;
+ l_rc=COMPCODE_NORMAL;
+ break;
+
+ default:
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ }
+ break;
+
+ default:
+ *io_resp_length = 0;
+ l_rc = COMPCODE_PARAM_OUT_OF_RANGE;
+ break;
+ } // end of switch
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: AMEC_entry_point
+//
+// Description: Amester interface entry point
+//
+//
+// Flow: FN=
+//
+// Task Flags:
+//
+// End Function Specification
+uint8_t amester_entry_point( const IPMIMsg_t * i_msg,
+ uint16_t * io_resp_length,
+ uint8_t * o_resp)
+
+{
+ uint8_t l_rc = COMPCODE_NORMAL;
+
+ do
+ {
+ if( (i_msg == NULL) ||
+ (io_resp_length == NULL) ||
+ (o_resp == NULL) )
+ {
+ l_rc = COMPCODE_UNSPECIFIED;
+ break;
+ }
+
+ switch (i_msg->u8Cmd)
+ {
+ case 0x3C:
+ l_rc = amester_api( i_msg, io_resp_length, o_resp);
+ break;
+
+ case 0x3B:
+ l_rc = amester_manual_throttle( i_msg, io_resp_length, o_resp);
+ break;
+
+ default:
+ l_rc = COMPCODE_CMD_UNKNOWN;
+ break;
+ }
+ } while (0);
+
+ return l_rc;
+}
+
+amec_tb_t* AMEC_tb_get_by_guid(const AMEC_TB_GUID i_guid)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_tb_t* l_tb_ptr = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ if(i_guid > AMEC_TB_NUMBER_OF_TRACES)
+ {
+ //TRACE(g_trac_amec,"E>amec_tb_get_by_guid:Invalid GUID (%d) max GUID supported at the moment is (%d)",i_guid,g_amec_tb_count);
+ break;
+ }
+ //traces are arranged in an array by GUID
+ l_tb_ptr = &g_amec_tb_list[i_guid];
+
+ } while( 0 );
+
+ return l_tb_ptr;
+}
+
+//
+// Commands that run during AME interrupt time
+//
+void amec_tb_record(const AMEC_TB_GUID i_guid)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT8 *l_w; // pointer for tracebuffer writing
+ UINT16 l_i;
+ sensor_t *l_s;
+ UINT32 l_totalbytes;
+ amec_parm_t *l_parm;
+ UINT8 *l_src_ptr;
+ AMEC_PARM_GUID l_parm_guid;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Record OCA from last 32 ms
+ if (G_dcom_slv_inbox_rx.tb_record)
+ {
+ // Check for valid tb write entry index
+ if (g_amec_tb_list[i_guid].write < g_amec_tb_list[i_guid].entry_n)
+ {
+ l_w = g_amec_tb_list[i_guid].bytes + g_amec_tb_list[i_guid].write * g_amec_tb_list[i_guid].entry_size;
+ // Write the tracked sensors
+ for (l_i=0; l_i< g_amec_tb_list[i_guid].sensors_n; l_i++)
+ {
+ l_s = getSensorByGsid(g_amec_tb_list[i_guid].sensors_num[l_i]);
+ switch (g_amec_tb_list[i_guid].sensors_field[l_i])
+ {
+ case 0: {//value
+ *l_w++ = (UINT8)(l_s->sample >> 8);
+ *l_w++ = (UINT8)(l_s->sample);
+ break;
+ }
+ case 1: {//min
+ *l_w++ = (UINT8)(l_s->sample_min >> 8);
+ *l_w++ = (UINT8)(l_s->sample_min);
+ break;
+ }
+ case 2: {//max
+ *l_w++ = (UINT8)(l_s->sample_max >> 8);
+ *l_w++ = (UINT8)(l_s->sample_max);
+ break;
+ }
+ case 3: {//accumulator
+ *l_w++ = (UINT8)(l_s->accumulator >> 24);
+ *l_w++ = (UINT8)(l_s->accumulator >> 16);
+ *l_w++ = (UINT8)(l_s->accumulator >> 8);
+ *l_w++ = (UINT8)(l_s->accumulator);
+ break;
+ }
+ case 4: {//update tag
+ *l_w++ = (UINT8)(l_s->update_tag >> 24);
+ *l_w++ = (UINT8)(l_s->update_tag >> 16);
+ *l_w++ = (UINT8)(l_s->update_tag >> 8);
+ *l_w++ = (UINT8)(l_s->update_tag);
+ break;
+ }
+ case 5: {//test (not available in POWER8)
+ *l_w++ = (UINT8)0;
+ *l_w++ = (UINT8)0;
+ break;
+ }
+ case 6: {//rcnt
+ *l_w++ = (UINT8)(g_amec->r_cnt >> 24);
+ *l_w++ = (UINT8)(g_amec->r_cnt >> 16);
+ *l_w++ = (UINT8)(g_amec->r_cnt >> 8);
+ *l_w++ = (UINT8)(g_amec->r_cnt);
+ break;
+ }
+ default:
+ break;
+ }
+ } // write sensors
+
+ // Write the tracked parameters
+ for (l_i=0; l_i< g_amec_tb_list[i_guid].parm_n; l_i++)
+ {
+ l_parm_guid = g_amec_tb_list[i_guid].parm_num[l_i];
+ if (g_amec_parm_list[l_parm_guid].preread)
+ amec_parm_preread(l_parm_guid); // get latest version
+ l_parm =&g_amec_parm_list[l_parm_guid]; //cl185
+ l_totalbytes = l_parm->length * l_parm->vector_length;
+ l_src_ptr = l_parm->value_ptr;
+ while(l_totalbytes--) {
+ *l_w++ = *l_src_ptr++;
+ }
+ }
+
+ // Advance the write pointer and decide if recording should stop
+ g_amec_tb_list[i_guid].write++; // Signal this entry is ready for reading
+ if(g_amec_tb_list[i_guid].write >= g_amec_tb_list[i_guid].entry_n)
+ {
+ if(g_amec_tb_continuous)
+ {
+ // Start at beginning of trace
+ g_amec_tb_list[i_guid].write = 0;
+ }
+ else
+ {
+ // Stop recording if this trace is configured
+ if (g_amec_tb_list[i_guid].entry_n) g_amec_tb_record = 0;
+ }
+ }
+ } // valid write index
+ } // end if(record)}
+}
+
+
+// Get tb config. Pack as many traces as possible
+void amec_tb_cmd_info(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ AMEC_TB_GUID l_id; // trace id
+ UINT16 l_j; // size of return message
+ CHAR *l_src; //pointer for copying name
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ l_id = (AMEC_TB_GUID) i_psMsg->au8CmdData_ptr[1];
+ l_j = 0; // write index byte for response
+
+ for (; l_id < AMEC_TB_NUMBER_OF_TRACES; l_id++)
+ {
+ if (l_j + AMEC_TB_CONFIG_SIZE >= IPMI_MAX_MSG_SIZE) break; // end of response buffer
+
+ l_src= g_amec_tb_list[l_id].name;
+ while (*l_src != 0)
+ {
+ o_pu8Resp[l_j++] = *l_src++;
+ } /* copy string up until \0 */
+ o_pu8Resp[l_j++] = '\0'; /* add string terminator */
+
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_tb_list[l_id].freq>>24);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_tb_list[l_id].freq>>16);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_tb_list[l_id].freq>>8);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_tb_list[l_id].freq);
+ // has_scoms field from POWER7 is always 0 on POWER8
+ o_pu8Resp[l_j++] = 0;
+ }
+ *o_pu16RespLength=l_j;
+ *o_retval=COMPCODE_NORMAL;
+ return;
+}
+
+
+void amec_tb_cmd_set_config(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ UINT8 l_i;
+ UINT16 l_sensors_n;
+ UINT16 l_oca_n;
+ UINT16 l_num_index;
+ UINT16 l_field_index;
+ UINT16 l_oca_index;
+ UINT8 l_valid_sockets=0;
+ UINT32 l_socket_bitmap=0;
+ UINT16 l_parm_n;
+ UINT16 l_parm_index;
+ amec_parm_t *l_parm;
+ UINT8 l_count;
+ amec_tb_t *l_trace;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ *o_retval=COMPCODE_NORMAL;
+
+ //Stop recording while setting up a trace.
+ g_amec_tb_record = 0;
+
+ // 0. Parse input
+ l_trace = AMEC_tb_get_by_guid(i_psMsg->au8CmdData_ptr[1]);
+ l_sensors_n = CONVERT_UINT8_ARRAY_UINT16(
+ i_psMsg->au8CmdData_ptr[2],
+ i_psMsg->au8CmdData_ptr[3]
+ );
+ l_parm_n = CONVERT_UINT8_ARRAY_UINT16(
+ i_psMsg->au8CmdData_ptr[4],
+ i_psMsg->au8CmdData_ptr[5]
+ );
+ l_oca_n = CONVERT_UINT8_ARRAY_UINT16(
+ i_psMsg->au8CmdData_ptr[6],
+ i_psMsg->au8CmdData_ptr[7]
+ );
+ l_socket_bitmap = CONVERT_UINT8_ARRAY_UINT32(
+ i_psMsg->au8CmdData_ptr[8],
+ i_psMsg->au8CmdData_ptr[9],
+ i_psMsg->au8CmdData_ptr[10],
+ i_psMsg->au8CmdData_ptr[11]
+ );
+
+ if (l_sensors_n > AMEC_TB_SENSORS_MAX) {
+ *o_retval=COMPCODE_PARAM_OUT_OF_RANGE;
+ o_pu8Resp[0] = 0; // mark second byte is bad.
+ o_pu8Resp[1] = 2; // mark second byte is bad.
+ *o_pu16RespLength = 2;
+ break;
+ }
+
+ if (l_parm_n > AMEC_TB_PARM_MAX) {
+ *o_retval=COMPCODE_PARAM_OUT_OF_RANGE;
+ o_pu8Resp[0] = 0; // mark fourth byte is bad.
+ o_pu8Resp[1] = 4; //
+ *o_pu16RespLength = 2;
+ }
+
+ if (l_oca_n > OCA_MAX_ENTRIES) {
+ *o_retval=COMPCODE_PARAM_OUT_OF_RANGE;
+ o_pu8Resp[0] = 0; // mark sixth byte is bad
+ o_pu8Resp[1] = 6;
+ *o_pu16RespLength = 2;
+ break;
+ }
+
+ // Count valid sockets
+ l_count = l_socket_bitmap;
+ while (l_count) {
+ if (l_count & 0x01) {l_valid_sockets++;}
+ l_count >>= 1;
+ }
+ if (l_valid_sockets > MAX_NUM_CHIPS) {l_valid_sockets = MAX_NUM_CHIPS;}
+
+ l_trace->entry_size = 0;
+
+ // Set pointers to input
+ l_num_index = 12; // start of sensor numbers
+ l_field_index = 12 + 2*l_sensors_n; // start of sensor fields
+ l_parm_index = l_field_index + l_sensors_n; // start of parameters
+ l_oca_index = l_parm_index + 2*l_parm_n; // start of SCOMs
+
+ // Read sensor configuration
+ for (l_i=0; l_i<l_sensors_n; l_i++) {
+ l_trace->sensors_num[l_i] = CONVERT_UINT8_ARRAY_UINT16(
+ i_psMsg->au8CmdData_ptr[l_num_index],
+ i_psMsg->au8CmdData_ptr[l_num_index+1]
+ );
+ l_trace->sensors_field[l_i] = i_psMsg->au8CmdData_ptr[l_field_index];
+
+ if (l_trace->sensors_num[l_i] >= G_amec_sensor_count) {
+ *o_retval=COMPCODE_PARAM_OUT_OF_RANGE;
+ o_pu8Resp[0] = (UINT8)(l_num_index>>8); // mark which byte input is bad
+ o_pu8Resp[1] = (UINT8)(l_num_index); // mark which byte input is bad
+ *o_pu16RespLength = 2;
+ break;
+ }
+
+ if (l_trace->sensors_field[l_i] > 6) {
+ *o_retval=COMPCODE_PARAM_OUT_OF_RANGE;
+ o_pu8Resp[0] = (UINT8)(l_field_index>>8); // mark which byte input is bad
+ o_pu8Resp[1] = (UINT8)(l_field_index); // mark which byte input is bad
+ *o_pu16RespLength = 2;
+ return;
+ }
+
+ switch (l_trace->sensors_field[l_i]) {
+ case 0: // value
+ case 1: // min
+ case 2: // max
+ l_trace->entry_size += 2;
+ break;
+ case 3: //acc
+ l_trace->entry_size += 4;
+ break;
+ case 4: //updates
+ l_trace->entry_size += 4;
+ break;
+ case 5: //test
+ l_trace->entry_size += 2;
+ break;
+ case 6: //rcnt
+ l_trace->entry_size += 4;
+ break;
+ default:
+ break;
+ }
+
+ l_num_index += 2;
+ l_field_index++;
+ }
+
+ if (*o_retval) break;
+
+ // Record number of sensors in this trace
+ l_trace->sensors_n = l_sensors_n;
+
+ // Read Parameter configuration
+ for (l_i=0; l_i<l_parm_n; l_i++) {
+ l_trace->parm_num[l_i] = CONVERT_UINT8_ARRAY_UINT16(
+ i_psMsg->au8CmdData_ptr[l_parm_index],
+ i_psMsg->au8CmdData_ptr[l_parm_index+1]
+ );
+
+ if (l_trace->parm_num[l_i] >= AMEC_PARM_NUMBER_OF_PARAMETERS) { //cl185
+ *o_retval=COMPCODE_PARAM_OUT_OF_RANGE;
+ o_pu8Resp[0] = (UINT8)(l_parm_index>>8); // mark which byte input is bad
+ o_pu8Resp[1] = (UINT8)(l_parm_index); // mark which byte input is bad
+ *o_pu16RespLength = 2;
+ break;
+ }
+ l_parm = &g_amec_parm_list[l_trace->parm_num[l_i]]; //cl185
+ l_trace->entry_size += l_parm->length * l_parm->vector_length;
+ l_parm_index += 2;
+
+ }
+
+ if (*o_retval) break;
+
+ // Record this number of parameters in the trace
+ l_trace->parm_n = l_parm_n;
+
+ l_trace->entry_n = l_trace->size/l_trace->entry_size;
+ l_trace->read = 0;
+ l_trace->write = 0;
+
+ *o_pu16RespLength = 0;
+ } while (0);
+
+ return;
+}
+
+void amec_tb_cmd_start_recording(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval)
+{
+ g_amec_tb_record = 1;
+ *o_pu16RespLength = 0;
+ *o_retval=COMPCODE_NORMAL;
+}
+
+void amec_tb_cmd_stop_recording(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval)
+{
+ g_amec_tb_record = 0;
+ *o_pu16RespLength = 0;
+ *o_retval=COMPCODE_NORMAL;
+}
+
+
+void amec_tb_cmd_read(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_tb_t *l_trace;
+ UINT16 l_i=0; // output index
+ UINT16 l_maxresponse = IPMI_MAX_MSG_SIZE - 1; // -1 since return code is 1B
+ UINT32 l_j; // index to copy from
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ *o_retval=COMPCODE_NORMAL; /* assume no error */
+
+ // Parse input command
+ l_trace = AMEC_tb_get_by_guid(i_psMsg->au8CmdData_ptr[1]);
+ if (l_trace == NULL) {
+ *o_retval=COMPCODE_PARAM_OUT_OF_RANGE;
+ *o_pu16RespLength = 0;
+ break;
+ }
+ l_j = CONVERT_UINT8_ARRAY_UINT32(
+ i_psMsg->au8CmdData_ptr[2],
+ i_psMsg->au8CmdData_ptr[3],
+ i_psMsg->au8CmdData_ptr[4],
+ i_psMsg->au8CmdData_ptr[5]
+ );
+
+ // Copy bytes to be read into response buffer
+ for (l_i=0; l_i < l_maxresponse; l_i++, l_j++){
+ if (l_j >= l_trace->size) {l_j = 0;} // wrap around to beginning of buffer.
+ o_pu8Resp[l_i]=l_trace->bytes[l_j];
+ }
+ *o_pu16RespLength = l_i;
+ } while (0);
+}
+
+
+void amec_tb_cmd_get_config(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_tb_t *l_trace;
+ UINT8 l_i = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ *o_retval = COMPCODE_NORMAL;
+
+ l_trace = AMEC_tb_get_by_guid(i_psMsg->au8CmdData_ptr[1]);
+ if (l_trace == NULL) {
+ *o_retval=COMPCODE_PARAM_OUT_OF_RANGE;
+ *o_pu16RespLength = 0;
+ break;
+ }
+
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->bytes>>24);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->bytes>>16);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->bytes>>8);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->bytes);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->size>>24);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->size>>16);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->size>>8);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->size);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->entry_size>>24);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->entry_size>>16);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->entry_size>>8);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->entry_size);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->entry_n>>24);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->entry_n>>16);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->entry_n>>8);
+ o_pu8Resp[l_i++] = (UINT8)(l_trace->entry_n);
+ // 32-bit oca_offset field is always 0 on POWER8
+ o_pu8Resp[l_i++] = 0;
+ o_pu8Resp[l_i++] = 0;
+ o_pu8Resp[l_i++] = 0;
+ o_pu8Resp[l_i++] = 0;
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->write>>24);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->write>>16);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->write>>8);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->write);
+ // 32-bit write_oca field is always 0 on POWER8
+ o_pu8Resp[l_i++] = 0;
+ o_pu8Resp[l_i++] = 0;
+ o_pu8Resp[l_i++] = 0;
+ o_pu8Resp[l_i++] = 0;
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->read>>24);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->read>>16);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->read>>8);
+ o_pu8Resp[l_i++] = (UINT8)((UINT32)l_trace->read);
+ o_pu8Resp[l_i++] = l_trace->sensors_n;
+ o_pu8Resp[l_i++] = l_trace->parm_n;
+ // oca_n field from POWER7 is always 0 on POWER8
+ o_pu8Resp[l_i++] = 0;
+
+ // FIXME: this should move to another command
+ o_pu8Resp[l_i++] = g_amec_tb_record;
+ o_pu8Resp[l_i++] = g_amec_tb_continuous;
+ o_pu8Resp[l_i++] = (UINT8)((UINT16)AMEC_TB_SENSORS_MAX);
+ o_pu8Resp[l_i++] = (UINT8)((UINT16)OCA_MAX_ENTRIES);
+ o_pu8Resp[l_i++] = (UINT8)(MAX_NUM_CHIPS);
+ o_pu8Resp[l_i++] = (UINT8)(AMEC_TB_PARM_MAX);
+ *o_pu16RespLength = l_i;
+
+ } while (0);
+}
diff --git a/src/occ/amec/amec_amester.h b/src/occ/amec/amec_amester.h
new file mode 100755
index 0000000..23ac87b
--- /dev/null
+++ b/src/occ/amec/amec_amester.h
@@ -0,0 +1,398 @@
+/******************************************************************************
+// @file amec_amester.h
+// @brief OCC AMEC AMESTER header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_amester_h amec_amester.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @at003 alvinwan 03/19/2012 New file. Add amester interface.
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @at008 alvinwan 08/09/2012 Support AME Pass Thru command from TMGT
+ * @ry001 853436 ronda 09/14/2012 Added Amester sub command support (phase one)
+ * @th034 879027 thallet 04/18/2013 Bumped Amester API version number
+ * @mw531 mware 06/22/2013 Added stream vector recording support.
+ * @mw533 mware 06/27/2013 Increased stream vector buffer from 3,840 bytes to 38,400 bytes.
+ * @mw624 mware 01/24/2014 Decreased stream vector buffer back to 3840 bytes.
+ * @mw627 mware 01/27/2014 Temporarily increase the stream vector buffer size to 64 entries (*96=6,144 bytes.)
+ * @mw642 918066 mware 02/26/2014 Reduced stream vector buffer size down
+ * @gs037 933716 gjsilva 07/31/2014 Fix memory bandwidth sensor resolution
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_AMESTER_H
+#define _AMEC_AMESTER_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+/* Define Completion Codes (IPMI 1.5 Table 5-2) */
+#define COMPCODE_NORMAL 0x00
+#define COMPCODE_NODE_BUSY 0xC0
+#define COMPCODE_CMD_UNKNOWN 0xC1
+#define COMPCODE_CMD_INVALID_FOR_LUN 0xC2
+#define COMPCODE_TIMEOUT 0xC3
+#define COMPCODE_OUT_OF_SPACE 0xC4
+#define COMPCODE_RESERVATION_CANCELLED 0xC5
+#define COMPCODE_REQ_DATA_TRUNCATED 0xC6
+#define COMPCODE_REQ_DATA_LEN_INVALID 0xC7
+#define COMPCODE_REQ_LEN_LIMIT_EXCEEDED 0xC8
+#define COMPCODE_PARAM_OUT_OF_RANGE 0xC9
+#define COMPCODE_REQ_BYTE_CNT_ERR 0xCA
+#define COMPCODE_OBJ_ABSENT 0xCB
+#define COMPCODE_REQ_FIELD_INVALID 0xCC
+#define COMPCODE_CMD_ILL_FOR_SEN 0xCD
+#define COMPCODE_RESP_UNAVAILABLE 0xCE
+#define COMPCODE_REQ_DUPLICATE 0xCF
+#define COMPCODE_SDR_REPO_IN_UPD 0xD0
+#define COMPCODE_FW_IN_UPD 0xD1
+#define COMPCODE_INIT_IN_PROGRESS 0xD2
+#define COMPCODE_DEST_UNAVAILABLE 0xD3
+#define COMPCODE_WRONG_PRIV 0xD4
+#define COMPCODE_CUR_NOT_SUPPORT 0xD5
+#define COMPCODE_UNSPECIFIED 0xFF
+
+#define IPMI_MAX_MSG_SIZE 1024
+#define AMEC_AME_CMD_HEADER_SZ 2 // @at008a
+
+// *****************************************************************************
+// Begin: Autonomic Management of Energy (AME) Equates
+// Malcolm Ware Austin Research Lab
+#define AME_API_MAJ 2 // API version major
+#define AME_API_MIN 26 // API version minor
+
+#define AME_VERSION_MAJ 6 // Major Version (e.g. Ver. 1.4 has MAJ=1)
+#define AME_VERSION_MIN 82 // Minor Version (e.g. Ver. 1.4 has MIN=4)
+
+#define AME_YEAR 2014 // Year of Release (e.g. 2006)
+#define AME_MONTH 7 // Month of Release (e.g. September=9)
+#define AME_DAY 28 // Day of Release
+
+#define AME_SDRS 22 // AME Sensor Data Record Size: 18 bytes
+
+/* AME data types for AME_GetInfo_*() functions */
+#define AME_INFO_NAME 0
+#define AME_INFO_FREQ 1
+#define AME_INFO_UNITS 2
+#define AME_INFO_SCALE 3
+#define AME_INFO_KIND 4
+#define AME_INFO_ALL 5
+
+#define COMMON_MAX_MTU_SIZE 2056
+
+// The command response length
+#define AME_COMPONENT_LEVEL_RSPCMD_LEN 11
+
+// Histogram copy interval in milliseconds (default to 8 seconds)
+#define AME_HISTOGRAM_COPY_INTERVAL 8000
+
+// WARNING -> STREAM_BUFFER_SIZE must be a perfect multiple of the vector size.
+#define STREAM_VECTOR_SIZE 32 // # of 16 bit elements in a stream vector-> must be a power of 2
+#define SHIFT_VECTOR_SIZE 5 // Log base 2 of STREAM_VECTOR_SIZE for shifting
+#define INJECTION_BUFFER_SIZE 32 // Size of injection buffer (must be a power of 2)
+#define STREAM_VECTOR_SIZE_EX 48 // # of 16 bit elements in a stream vector
+#define STREAM_BUFFER_SIZE (8*10*STREAM_VECTOR_SIZE_EX) // Stream buffer size in 16 bit samples for recording real time data to stream to Amester $mw642
+#define MAX_SENSORS_ANALYTICS 76 //Maximum sensors making up the analytics group 44
+#define MSA MAX_SENSORS_ANALYTICS
+
+#define OCA_MAX_ENTRIES 0 // no POWER7 OCA on POWER8
+#define AMEC_TB_SENSORS_MAX 40
+#define AMEC_TB_PARM_MAX 40
+
+/**************************************************************************//**
+ * @brief Macro for dividing two UINT32
+ *
+ * @param I_NUM The numerator of the division.
+ * @param I_DEN The denominator of the division.
+ * @return A 32-bit value with the quotient of the division.
+ */
+#define UTIL_DIV32(I_NUM, I_DEN) (((UINT32)(I_NUM)) / ((UINT32)(I_DEN)))
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+typedef struct
+{
+ /** The IPMI command ID */
+ uint8_t u8Cmd;
+ /** The IPMI command data length */
+ uint16_t u8CmdDataLen;
+ /** the IPMI command data (including completion code) */
+ uint8_t *au8CmdData_ptr;
+} IPMIMsg_t;
+
+typedef struct sensorrec
+{
+ uint32_t timestamp;
+ uint32_t updates;
+ uint32_t accumulated_value;
+ uint16_t value;
+ uint16_t value_min;
+ uint16_t value_max;
+ uint16_t status; // bit 0, LSB: calibration complete on this sensor (=1);
+ // no calibration complete (=0)
+ // bit 1: histogram gets updated (=1);
+ // histogram is frozen (=0)
+ // bit 2: histogram gets reset (=1);
+ // histogram not being reset (=0)
+ // WARNING -> bit 2 only takes effect when bit 1
+ // is toggled high. As soon as the histogram of
+ // interest is reset, bit 2 is cleared to a 0
+ // automatically. It is expected that the
+ // external entity will carry out a reset, first
+ // by setting bit 1 to a 0 to freeze updating,
+ // then set bit 2 to a 1 to enable a reset, and
+ // then set bit 1 to a 1 to enable a reset and
+ // immediate updating again from a known state
+ // of 0 in all counters.
+ // bit 3: select buffering area to be a time series
+ // trace (=1) or a histogram (=0) (msw324)
+ // bit 4: if set to 1, time series trigger is armed;
+ // if =0, trigger happened (msw354)
+ // bit 5: if set to 1, then time series buffer trace
+ // ptr was reset to 0; this bit is set to 0
+ // whenever the next histogram snapshot interval
+ // arrives. If the bit stays at 0, and the
+ // next histogram snapshot interval arrives,
+ // then the update tag is not incremented. This
+ // allows for much shorter intervals when using
+ // exclusively time series modes for all the
+ // sensors with a buffer because the Amester
+ // never sees the update tag keep getting
+ // incremented once the recording of each time
+ // trace is completed. msw357
+ // bit 6: if set to 1, this forces all sensor snapshots
+ // to occur simultaneously in time msw366
+ // This is important for histograms to be
+ // compared. if set to 0, snapshots will be
+ // spreadout with one done every 64msec once
+ // the snap-shot interval is finished. This
+ // flattens out the cycles for a large number
+ // of sensors being monitored for time-tracing
+ // where the contents of the histogram/time
+ // trace buffer aren't changing once the trace
+ // has finished recording, so snapshotting all
+ // these sensors at the same time instant
+ // is not essential. Normally, if all histograms
+ // are in use, set this bit to 1. If all
+ // time-series are in used, set this to 0. If
+ // mixed, be very careful about the choice!
+ // bits 11 to 13:
+ // encodes function to be performed in creating a vector
+ // sensor's sample_reg output.
+ // 000 -> find max of vector elements
+ // 001 -> find min of vector elements
+ // 010 -> find average of vector elements
+ // 011 to 111 are available for new functions.
+ // bit 14:if set to 1, high resolution mode is used for
+ // histograms and tracing on all vector
+ // sensors. All samples of the vector pass
+ // through add_histogram routine every time
+ // the vector is updated. if set to 0, low
+ // resolution mode is used, and only sample_reg
+ // (latest max or min of the vector) is passed
+ // through add_histogram every time.
+ // bit 15:if set to 1, this is an AME vector sensor.
+ // if set to 0, this is a normal AME scalar
+ // sensor.
+
+ uint16_t test; // msw366
+ // if bit 15 is set to 1 in the status register, the
+ // test register can only be used to support
+ // the vector sensor. In this mode, the high 8
+ // bits are used to hold two 4 bit
+ // indices of minimum values. The low 8 bits are
+ // used to hold two 4 bit indices of
+ // maximum values. Vector sensors can only hold
+ // up to 12 elements, so each 4 bit index
+ // can point to the vector index of interest.
+ // Here is a summary of what each 4 bit field
+ // shows:
+ // bits 15-12: index of minimum vector sensor
+ // value seen for all time (since
+ // last reset)
+ // bits 11-8: index of minimum vector sensor
+ // value seen for the latest time
+ // instant
+ // bits 7-4: index of maximum vector sensor
+ // value seen for all time (since
+ // last reset)
+ // bits 3-0: index of maximum vector sensor
+ // value seen for the latest time
+ // instant
+ // Vector sensors should not be longer than 12
+ // elements because one can only guard out
+ // up to 12 elements with the vector sensor
+ // enable mask and to avoid extreme cycle spikes.
+ // A RESET of this sensor will cause the test
+ // register (high and low bytes) to be set to
+ // 0xFF.
+ // if bit 15 is set to 0 in the status register, this
+ // register can be used to store anything.
+} sensorrec_t;
+
+typedef UINT8 AMEC_TB_GUID;
+typedef UINT16 AMEC_SENSOR_GUID;
+
+typedef enum
+{
+ AMEC_TB_2MS, // GUID for 2ms trace
+ AMEC_TB_250US, // GUID for 250us trace
+ AMEC_TB_NUMBER_OF_TRACES // Number of trace buffers supported
+} AMEC_TB_ENUM;
+
+typedef struct amec_tb
+{
+ // Constant properties
+
+ ///Trace name
+ CHAR* name;
+ ///Update Frequency
+ UINT32 freq;
+
+ // Configurable properaties
+
+ ///Pointer to raw bytes for trace buffer
+ UINT8* bytes;
+ ///Number of raw bytes
+ UINT32 size; /* Number of raw bytes. crl220 */
+ ///Number of bytes in 1 trace record. Used to increment write pointer.
+ UINT32 entry_size;
+ ///Number of records that fit in the trace buffer. (0 to n-1 can be used)
+ UINT32 entry_n;
+ ///Record number to write next for sensor data
+ UINT32 write;
+ ///Record number for next read (not used yet)
+ UINT32 read;
+ ///Number of sensors tracked in tb
+ UINT8 sensors_n;
+ ///Number of paramters tracked in tb
+ UINT8 parm_n;
+ ///List of corresponding sensor fields tracked in this trace buffer
+ UINT8 sensors_field[AMEC_TB_SENSORS_MAX];
+ ///List of sensors tracked in this trace buffer
+ AMEC_SENSOR_GUID sensors_num[AMEC_TB_SENSORS_MAX];
+ ///List of parameters tracked
+ uint16_t parm_num[AMEC_TB_PARM_MAX];
+
+} amec_tb_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+//Amester interface entry point
+uint8_t amester_entry_point( const IPMIMsg_t * i_msg,
+ uint16_t * o_resp_length,
+ uint8_t * o_resp);
+
+/**
+ * @brief Write sensor data to trace record
+ * @param i_trace The trace to write
+ *
+ * Called periodically to write next trace record with
+ * sensor data.
+ *
+ */
+void amec_tb_record(const AMEC_TB_GUID i_guid);
+
+/**
+ * @brief Get global information on traces (names, frequencies)
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Get a list of all available trace buffers in TPMD
+ * and their frequencies.
+ *
+ */
+void amec_tb_cmd_info(const IPMIMsg_t * i_psMsg, UINT8 *o_pu8Resp,UINT16 *o_pu16RespLength,UINT8 *o_retval);
+
+/**
+ * @brief Set the configuration of a trace (which sensors to trace)
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Set the configuration of a trace. Choose which sensors
+ * and SCOMs to trace. Choose size of trace buffer memory.
+ *
+ */
+void amec_tb_cmd_set_config(const IPMIMsg_t *i_psMsg, UINT8 *o_pu8Resp,UINT16 *o_pu16RespLength,UINT8 *o_retval);
+
+/**
+ * @brief Begin recording all configured traces
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Start recording traces.
+ *
+ */
+void amec_tb_cmd_start_recording(const IPMIMsg_t *i_psMsg,UINT8 *o_pu8Resp,UINT16 *o_pu16RespLength,UINT8 *o_retval);
+
+/**
+ * @brief Stop recording all traces
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Stop recording traces.
+ *
+ */
+void amec_tb_cmd_stop_recording(const IPMIMsg_t *i_psMsg,UINT8 *o_pu8Resp,UINT16 *o_pu16RespLength,UINT8 *o_retval);
+
+/**
+ * @brief Get bytes from trace buffer memory
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Returns a maximum size packet starting at a given
+ * index
+ *
+ */
+void amec_tb_cmd_read(const IPMIMsg_t *i_psMsg,UINT8 *o_pu8Resp,UINT16 *o_pu16RespLength,UINT8 *o_retval);
+
+/**
+ * @brief Returns configuration of a trace
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Returns configuration of a trace.
+ *
+ */
+void amec_tb_cmd_get_config(const IPMIMsg_t *i_psMsg,UINT8 *o_pu8Resp,UINT16 *o_pu16RespLength,UINT8 *o_retval);
+
+#endif
diff --git a/src/occ/amec/amec_analytics.c b/src/occ/amec/amec_analytics.c
new file mode 100755
index 0000000..7ae9857
--- /dev/null
+++ b/src/occ/amec/amec_analytics.c
@@ -0,0 +1,624 @@
+/******************************************************************************
+// @file amec_analytics.c
+// @brief Analytics function for AMEC
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_analytics_c amec_analytics.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @mw581 mware 11/11/2013 Migrated from POWER7+ TPMD to POWER8 OCC.
+ * @mw583 mware 11/25/2013 Added Group 81 support.
+ * @mw584 mware 11/30/2013 Changed freqa250us to freqa2ms.
+ * @mw585 mware 12/03/2013 Fixed scaling issues for only accumulating every 1/8th of the time.
+ * @mw586 mware 12/04/2013 Added forcing pstate0 on each call until PowerKVM boots properly.
+ * Updated TOD sensors. Fixed bulk power sensor. Include ssx.h.
+ * @mw587 mware 12/20/2013 Fixed bug with using cores 0 to 15 to force pstate max/min clipping.
+ * Also, fixed bug in that needs to set PRBR chip register pstate max/min rails.
+ * @mw633 mware 01/09/2014 Removed forcing of pstate0. Done elsewhere. Removed cpm sensor access.
+ * @mw635 mware 01/11/2014 Changed to collect Centaur 4 and 5 per socket, not 6 and 7.
+ * @mw636 mware 01/11/2014 Properly use stream_rate in computing averages.
+ * Temporarily remove reading of TODclocks due to limited cycles in OCC.
+ * @mw637 mware 02/16/2014 Started using configuration data to only capture data for configured cores.
+ * Only try frequency of configured core first.
+ * @mw638 mware 02/16/2014 Proper average of 250usec power samples for group 44.
+ * @mw639 mware 02/16/2014 Proper average of all 250usec samples for group 44 and usage of configured cores.
+ * @mw640 mware 02/17/2014 Fixed bugs in averaging 250usec sensors.
+ * @mw641 mware 02/23/2014 Added 64msec averaging support and changed g44_avg to be 32 bits due to overflows.
+ * @mw642 mware 02/26/2014 Changed to use the CPM 32 bit area to hold 2 more Centaur's worth of memory read/write sensors.
+ * @mw655 mware 03/11/2014 No TODclock sensor updates here. Done in amec_sensors_core.c.
+ * @mw671 mware 05/27/2014 Added other threadmode options including finish counter, L4 read/write counters.
+ * @mw672 mware 06/25/2014 Temporarily patch around L4 output for last few cores.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <amec_amester.h>
+#include <amec_sys.h>
+#include <proc_data.h>
+#include <ssx.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+void amec_analytics_sb_recording(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t temp16 = 0;
+ uint8_t k = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Increment the internal counter here per 250us tick
+ g_amec->r_cnt++;
+
+ // Need to have reached modulo time interval to record output and also just
+ // after the analytics_slot was reached.
+ temp16 = g_amec->r_cnt - g_amec->analytics_slot;
+ temp16 = ((1<<g_amec->stream_vector_rate)-1) & temp16;
+
+ if ((temp16 == 0) && (g_amec->recordflag == 1)) // @mw581
+ {
+ if (g_amec->stream_vector_mode == 0) // If zero, see if timer running prior to beginning a capture
+ {
+ if (g_amec->stream_vector_delay > 1)
+ {
+ g_amec->stream_vector_delay = g_amec->stream_vector_delay - 1;
+ } else
+ {
+ if (g_amec->stream_vector_delay == 1)
+ {
+ g_amec->stream_vector_mode = 1; // Turn on 1 shot recording
+ g_amec->write_stream_index = 0; // Reset to start of buffer
+ g_amec->stream_vector_delay = 0; // Disable any further delays
+
+ // support L4 state machine and tracing being synchronized
+ if (g_amec->reset_prep != 0)
+ {
+ g_amec->cent_l4_state[g_amec->probe_l4_centaur] = 0; // Start with L4 state machine set to first state (L4_S0)
+ g_amec->cent_l4_ipl_state[g_amec->probe_l4_centaur] = 0; // Start with L4 IPL state machine set to first state (IPL_L4_S0)
+ g_amec->reset_prep = 0; // Turn off indicator of TMGT wanting to reset the OCC, which will start L4 state machine
+ g_amec->l4_powerdown_requestm = 1; // Raise indicator that the master OCC wants to carry out an L4 power down
+ }
+ }
+ }
+ } else
+ {
+ // Check is discarding initial frames due to analytics data getting averaged
+ if (g_amec->analytics_bad_output_count == 0) // @mw587
+ {
+ // Stream buffer recording function done every 250usec * 2^(stream_vector_rate) @mw587
+ g_amec->ptr_stream_buffer[g_amec->write_stream_index] = (uint16_t)g_amec->r_cnt;
+ g_amec->write_stream_index++;
+ // WARNING -> The size of the vector recorded must be a precise multiple
+ // of the size of the entire stream buffer.
+ for (k = 1; k < STREAM_VECTOR_SIZE_EX; k++)
+ {
+ if (g_amec->stream_vector_map[k] == (void *)0xffffffff)
+ {
+ k = STREAM_VECTOR_SIZE_EX; // Terminate as partial vector complete
+ } else
+ {
+ temp16 = *((uint16_t * )(g_amec->stream_vector_map[k]));
+ g_amec->ptr_stream_buffer[g_amec->write_stream_index] = (uint16_t)temp16;
+ g_amec->write_stream_index++;
+ }
+ }
+ if (g_amec->write_stream_index >= STREAM_BUFFER_SIZE)
+ {
+ g_amec->write_stream_index = 0; // Reset to start of buffer
+ if (g_amec->stream_vector_mode == 1)
+ {
+ // If single shot, just rotate write ptr in last record
+ g_amec->write_stream_index = STREAM_BUFFER_SIZE - STREAM_VECTOR_SIZE_EX;
+ }
+ }
+ } else
+ {
+ g_amec->analytics_bad_output_count--; // decrement bad output counter @mw587
+ }
+ }
+ }
+}
+
+void amec_analytics_main(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t i = 0;
+ uint8_t j = 0;
+ uint8_t k = 0;
+ uint8_t l = 0;
+ uint8_t m = 0; // @mw637
+ uint16_t temp16 = 0;
+ uint16_t tempreg = 0;
+ uint32_t temp32 = 0;
+ uint32_t tempaccum = 0; // @mw638
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ g_amec->packednapsleep[0] = (g_amec->proc[0].winkcnt2ms.sample<<8) +
+ g_amec->proc[0].sleepcnt2ms.sample; // $mw416
+ g_amec->packednapsleep[1] = (g_amec->proc[1].winkcnt2ms.sample<<8) +
+ g_amec->proc[1].sleepcnt2ms.sample; // $mw416
+ g_amec->packednapsleep[2] = (g_amec->proc[2].winkcnt2ms.sample<<8) +
+ g_amec->proc[2].sleepcnt2ms.sample; // $mw416
+ g_amec->packednapsleep[3] = (g_amec->proc[3].winkcnt2ms.sample<<8) +
+ g_amec->proc[3].sleepcnt2ms.sample; // $mw416
+
+ switch (g_amec->analytics_group)
+ {
+ case 44: // Group 44 @mw583 added 10 new entries at the start
+
+ // Every 2msec (250usec * 2^stream_rate, default stream_rate=3), perform averaging of sensors.
+ // Averaging is required because many sensors are updated every
+ // 2msec and if they aren't properly averaged, those updates
+ // are lost in the final analytics output.
+ // The analytics group should be a correct average of the higher
+ // frequency sensor updates.
+ // @mw641 (wait until OCC master collects all chips data) // for (i=0; i<MAX_NUM_CHIP_MODULES;i++)
+ for (i=0; i<1; i++)
+ {
+ g_amec->g44_avg[(i*MSA)+0] = (UINT32)g_amec->sys.todclock0.sample; // ptr to high 16 bits of 48bit TOD clock
+ g_amec->g44_avg[(i*MSA)+2] = (UINT32)g_amec->sys.todclock1.sample; // ptr to middle 16 bits of 48 bit TOD clock
+ g_amec->g44_avg[(i*MSA)+4] = (UINT32)g_amec->sys.todclock2.sample; // ptr to low 16 bits of 48 bit TOD clock
+
+ tempaccum=g_amec->sys.pwr250us.src_accum_snapshot; // load pwr250us accum from last 2msec @mw638
+ g_amec->sys.pwr250us.src_accum_snapshot = g_amec->sys.pwr250us.accumulator; // save current accum state for next 2msec
+ tempaccum=g_amec->sys.pwr250us.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum=tempaccum>>3; // divide by 8
+ g_amec->g44_avg[(i*MSA)+6] = g_amec->g44_avg[(i*MSA)+6] +
+ tempaccum;
+
+ tempaccum=g_amec->sys.pwr250usgpu.src_accum_snapshot; // load pwr250usgpu accum from last 2msec @mw654
+ g_amec->sys.pwr250usgpu.src_accum_snapshot = g_amec->sys.pwr250usgpu.accumulator; // save current accum state for next 2msec
+ tempaccum=g_amec->sys.pwr250usgpu.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum=tempaccum>>3; // divide by 8
+ g_amec->g44_avg[(i*MSA)+8] = g_amec->g44_avg[(i*MSA)+8] +
+ tempaccum;
+
+ tempaccum=g_amec->proc[i].pwr250us.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[i].pwr250us.src_accum_snapshot = g_amec->proc[i].pwr250us.accumulator; // save current accum state for next 2msec
+ tempaccum=g_amec->proc[i].pwr250us.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum=tempaccum>>3; // divide by 8
+ g_amec->g44_avg[(i*MSA)+10] = g_amec->g44_avg[(i*MSA)+10] +
+ tempaccum;
+
+ tempaccum=g_amec->proc[i].pwr250usvdd.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[i].pwr250usvdd.src_accum_snapshot = g_amec->proc[i].pwr250usvdd.accumulator; // save current accum state for next 2msec
+ tempaccum=g_amec->proc[i].pwr250usvdd.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum=tempaccum>>3;
+ g_amec->g44_avg[(i*MSA)+11] = g_amec->g44_avg[(i*MSA)+11] +
+ tempaccum;
+
+ tempaccum=g_amec->proc[i].vrm[0].volt250us.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[i].vrm[0].volt250us.src_accum_snapshot = g_amec->proc[i].vrm[0].volt250us.accumulator; // save current accum state for next 2msec
+ tempaccum=g_amec->proc[i].vrm[0].volt250us.accumulator - tempaccum; // total accumulation over 2msec
+ temp32 = tempaccum<<3; // Pi, Vdd
+ tempreg = 4000;
+ // Convert voltage from 100uV resolution to 6.25mV resolution
+ tempreg = (UINT16)(UTIL_DIV32(temp32, tempreg));
+ g_amec->g44_avg[(i*MSA)+12] = g_amec->g44_avg[(i*MSA)+12] + (UINT32)tempreg;
+
+ tempaccum=g_amec->proc[i].vrm[1].volt250us.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[i].vrm[1].volt250us.src_accum_snapshot = g_amec->proc[i].vrm[1].volt250us.accumulator; // save current accum state for next 2msec
+ tempaccum=g_amec->proc[i].vrm[1].volt250us.accumulator - tempaccum; // total accumulation over 2msec
+ temp32 = tempaccum<<3; // Pi, Vcs
+ tempreg = 4000;
+ // Convert voltage from 100uV resolution to 6.25mV resolution
+ tempreg = (UINT16)(UTIL_DIV32(temp32, tempreg));
+ g_amec->g44_avg[(i*MSA)+13] = g_amec->g44_avg[(i*MSA)+13] +
+ (UINT32)tempreg;
+
+ tempaccum=g_amec->proc[i].cur250usvdd.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[i].cur250usvdd.src_accum_snapshot = g_amec->proc[i].cur250usvdd.accumulator; // save current accum state for next 2msec
+ tempaccum=g_amec->proc[i].cur250usvdd.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum=tempaccum>>3;
+ g_amec->g44_avg[(i*MSA)+14] = g_amec->g44_avg[(i*MSA)+14] +
+ tempaccum/100; // @mw640 @mw641
+
+ g_amec->g44_avg[(i*MSA)+15] = g_amec->g44_avg[(i*MSA)+15] +
+ (UINT32)g_amec->proc[i].temp2ms.sample; // hottest processor core temperature (average??)
+ g_amec->g44_avg[(i*MSA)+16] = g_amec->g44_avg[(i*MSA)+16] +
+ (UINT32)(g_amec->proc[i].memctl[4].mrd2ms.sample/78); // memory read bandwidth @mw635
+ g_amec->g44_avg[(i*MSA)+17] = g_amec->g44_avg[(i*MSA)+17] +
+ (UINT32)(g_amec->proc[i].memctl[4].mwr2ms.sample/78); // memory write bandwidth @mw635
+ g_amec->g44_avg[(i*MSA)+18] = g_amec->g44_avg[(i*MSA)+18] +
+ (UINT32)(g_amec->proc[i].memctl[5].mrd2ms.sample/78); // memory read bandwidth @mw635
+ g_amec->g44_avg[(i*MSA)+19] = g_amec->g44_avg[(i*MSA)+19] +
+ (UINT32)(g_amec->proc[i].memctl[5].mwr2ms.sample/78); // memory write bandwidth @mw635
+
+ g_amec->g44_avg[(i*MSA)+20] = g_amec->g44_avg[(i*MSA)+20] |
+ (UINT32)g_amec->proc[i].winkcnt2ms.sample; // winkle bitmap for all cores (OR of all 2msec)
+ g_amec->g44_avg[(i*MSA)+21] = g_amec->g44_avg[(i*MSA)+21] |
+ (UINT32)g_amec->proc[i].sleepcnt2ms.sample; // sleep bitmap for all cores (OR of all 2msec)
+
+ g_amec->g44_avg[(i*MSA)+22] = g_amec->g44_avg[(i*MSA)+22] +
+ (UINT32)(g_amec->proc[i].memctl[6].mrd2ms.sample/78); // memory read bandwidth @mw642
+ g_amec->g44_avg[(i*MSA)+23] = g_amec->g44_avg[(i*MSA)+23] +
+ (UINT32)(g_amec->proc[i].memctl[6].mwr2ms.sample/78); // memory write bandwidth @mw642
+ g_amec->g44_avg[(i*MSA)+24] = g_amec->g44_avg[(i*MSA)+24] +
+ (UINT32)(g_amec->proc[i].memctl[7].mrd2ms.sample/78); // memory read bandwidth @mw642
+ g_amec->g44_avg[(i*MSA)+25] = g_amec->g44_avg[(i*MSA)+25] +
+ (UINT32)(g_amec->proc[i].memctl[7].mwr2ms.sample/78); // memory write bandwidth @mw642
+
+ // Search for minimum CPM value per core rather than average
+ // @mw633 for (j=0; j<8; j++)
+ // {
+ // if (g_amec->proc[i].core[j].cpm2ms.sample < g_amec->g44_avg[(i*MSA)+12+j])
+ // {
+ // // remember new minimum CPM value for this core
+ // g_amec->g44_avg[(i*MSA)+22+j] = g_amec->proc[i].core[j].cpm2ms.sample;
+ // }
+ // }
+
+ m=0; // counter for actual configured # of cores - 1.
+ for (j=0; j<12; j++) // @mw637 WARNING: Only 8 cores are allowed to be configured per OCC chip
+ {
+ if (CORE_PRESENT(j)) // @mw637
+ {
+ //average frequency for this core
+ g_amec->g44_avg[(i*MSA)+30+m] = g_amec->g44_avg[(i*MSA)+30+m] +
+ (UINT32)g_amec->proc[i].core[j].freqa2ms.sample/28;
+ m++; // increment configured core counter
+ if (m > 7) j=12; // @mw637 safeguard in case more than 8 configured cores.
+ }
+ }
+
+ m=0; // counter for actual configured # of cores - 1.
+ for (j=0; j<12; j++) // @mw639 WARNING: Only 8 cores are allowed to be configured per OCC chip
+ {
+ if (CORE_PRESENT(j)) // @mw639
+ {
+ tempreg = 0; // keeps track of maximum thread utilization for this core
+ temp32 = 0; // keeps track of average thread utilization for this core for non-zero threads (threadmode=0) or all threads (threadmode=1) or no average (threadmode=2)
+ temp16 = 0; // keeps track of non-zero threads
+ for (k=0; k < g_amec->analytics_threadcountmax; k++) // $mw455
+ {
+ if (tempreg < g_amec->proc[i].core[j].thread[k].util2ms_thread) // @mw643
+ {
+ tempreg = g_amec->proc[i].core[j].thread[k].util2ms_thread;
+ }
+ if ((0 < g_amec->proc[i].core[j].thread[k].util2ms_thread) || (g_amec->analytics_threadmode != 0)) // $mw455
+ {
+ // accumulate for computing average
+ temp32 = temp32 + g_amec->proc[i].core[j].thread[k].util2ms_thread;
+ // increment counter of threads
+ temp16 = temp16+1; // $mw434
+ }
+ }
+ g_amec->g44_avg[(i*MSA)+38+m] = g_amec->g44_avg[(i*MSA)+38+m] +
+ (UINT32)(g_amec->proc[i].core[j].util2ms.sample/50); // accumulate util sensor that feeds IPS and DPS algorithms for this core $mw434
+
+ if (g_amec->analytics_threadmode == 2) // $mw459
+ {
+ temp16 = tempreg; // Store maximum of all the threads on this core
+ }
+ if (g_amec->analytics_threadmode < 2) // $mw459
+ {
+ if (temp16 > 0)
+ {
+ temp16 = (UINT16)(UTIL_DIV32(temp32, temp16)); // compute average utilization of all non-zero threads (threadmode=0) or all threads (threadmode=1)
+ }
+ }
+ if (g_amec->analytics_threadmode == 3) // @mw671
+ {
+ // accumulate average finish latency counter for this core // @mw671
+ temp16 = ((g_amec->proc[i].core[j].mcpifi2ms.sample) >>1);
+ }
+ if (g_amec->analytics_threadmode == 4) // @mw671
+ {
+ if ((m&1) == 0) // Capture L4 read traffic
+ {
+ temp16 = g_amec->proc[0].memctl[(m/2)+4].centaur.portpair[0].perf.l4rd2ms;
+ temp16 = temp16 + g_amec->proc[0].memctl[(m/2)+4].centaur.portpair[1].perf.l4rd2ms;
+ temp16 = temp16 >> 1;
+ }
+ else
+ {
+ temp16 = g_amec->proc[0].memctl[(m/2)+4].centaur.portpair[0].perf.l4wr2ms;
+ temp16 = temp16 + g_amec->proc[0].memctl[(m/2)+4].centaur.portpair[1].perf.l4wr2ms;
+ temp16 = temp16 >> 1;
+ }
+ }
+
+ g_amec->g44_avg[(i * MSA) + 46 + m] = g_amec->g44_avg[(i * MSA) + 46 + m] +
+ (UINT32)(temp16 / 50); // accumulate average utilization or individual threads for this core or finish latency counter or L4 read/write counters // @mw671
+ g_amec->g44_avg[(i * MSA) + 54 + m] = g_amec->g44_avg[(i * MSA) + 54 + m] +
+ (UINT32)(g_amec->proc[i].core[j].ips2ms.sample / 50); // accumulate average MIPS for this core
+ g_amec->g44_avg[(i * MSA) + 62 + m] = g_amec->g44_avg[(i * MSA) + 62 + m] +
+ (UINT32)g_amec->proc[i].core[j].temp2ms.sample; // accumulate average temperature for this core
+ g_amec->g44_avg[(i * MSA) + 70 + m] = g_amec->g44_avg[(i * MSA) + 70 + m] +
+ (UINT32)((g_amec->proc[i].core[j].cmbw2ms.sample) / 78); // accumulate average memory bandwidth for this core
+ temp16 = ((g_amec->proc[i].core[j].mcpifd2ms.sample) / 100); // accumulate average busy latency counter for this core // @mw654
+ g_amec->g44_avg[(i * MSA) + 78 + m] = g_amec->g44_avg[(i * MSA) + 78 + m] + (UINT32)temp16;
+ m++; // increment configured core counter
+ if (m > 7) j = 12; // @mw637 safeguard in case more than 8 configured cores.
+ }
+ } // End loop processing each core
+ } // End loop processing each chip
+
+ // Determine when to update final analytics_array @mw585
+ temp16 = g_amec->r_cnt - g_amec->analytics_slot;
+ temp16 = ((1<<g_amec->stream_vector_rate)-1) & temp16;
+
+ // Have we completed this interval so that we can output? @mw585
+ if (temp16 == 0)
+ {
+ // Now, update Group 44 analytics packed array
+ switch (g_amec->analytics_thermal_offset)
+ {
+ case 0:
+ tempreg = (g_amec->sys.tempambient.sample) << 8; // upper byte
+ tempreg = tempreg | 0x8000; // Turn on MSBit for temporal frame sync
+ break;
+
+ case 1: // $mw439
+ if (g_amec->mst_ips_parms.active == 0) // Begin: $mw671
+ {
+ // tempreg = G_ips_entry_count; // If not in IPS, return entry count
+ tempreg = 0; // If not in IPS mode, return 0
+ }
+ else
+ {
+ tempreg = 127; // If in IPS, return constant indicating in IPS mode
+ }
+ if (tempreg > 127) tempreg = 127; // Saturate at 7 bit limit (508 seconds) // $mw440
+ tempreg = (tempreg) << 8; // upper byte
+ break;
+
+ case 2:
+ tempreg=(g_amec->mst_ips_parms.active)<<8; // upper byte */
+ break;
+
+ case 3:
+ tempreg = (g_amec->fan.fanspeedavg.sample / 100) << 8; // upper byte (100 RPM resolution)
+ break;
+
+ case 4:
+ tempreg = (g_amec->proc[0].temp2msdimm.sample) << 8; // upper byte
+ break;
+
+ case 5:
+ tempreg = (g_amec->proc[0].temp2mscent.sample) << 8; // upper byte
+ break;
+
+ case 6:
+ // tempreg=(g_amec->proc[2].temp2msdimm.sample)<<8; // upper byte @mw641
+ tempreg = 0;
+ break;
+
+ case 7:
+ // tempreg=(g_amec->proc[2].temp2mscent.sample)<<8; // upper byte @mw641
+ tempreg = 0;
+ break;
+
+ default:
+ break;
+
+ }
+ g_amec->analytics_thermal_offset = 0x7 &
+ (g_amec->analytics_thermal_offset + 1); // modulo 8
+
+ tempaccum = g_amec->fan.pwr250usfan.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->fan.pwr250usfan.src_accum_snapshot = g_amec->fan.pwr250usfan.accumulator; // save current accum state for next 2msec
+ tempaccum = g_amec->fan.pwr250usfan.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum = tempaccum >> g_amec->stream_vector_rate; // @mw640
+
+ tempreg = tempreg | (0xff & ((UINT16)tempaccum));
+ g_amec->analytics_array[5] = tempreg;
+
+ tempaccum = g_amec->io.pwr250usio.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->io.pwr250usio.src_accum_snapshot = g_amec->io.pwr250usio.accumulator; // save current accum state for next 2msec
+ tempaccum = g_amec->io.pwr250usio.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum = tempaccum >> g_amec->stream_vector_rate; // @mw640
+
+ tempreg = ((UINT16)tempaccum) << 8; // upper byte
+
+ tempaccum = g_amec->storage.pwr250usstore.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->storage.pwr250usstore.src_accum_snapshot = g_amec->storage.pwr250usstore.accumulator; // save current accum state for next 2msec
+ tempaccum = g_amec->storage.pwr250usstore.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum = tempaccum >> g_amec->stream_vector_rate; // @mw640
+
+ tempreg = tempreg | (0xff & ((UINT16)tempaccum));
+ g_amec->analytics_array[6] = tempreg;
+
+ tempaccum = g_amec->proc[0].pwr250usmem.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[0].pwr250usmem.src_accum_snapshot = g_amec->proc[0].pwr250usmem.accumulator; // save current accum state for next 2msec
+ tempaccum = g_amec->proc[0].pwr250usmem.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum = tempaccum >> g_amec->stream_vector_rate; // @mw640
+
+ tempreg = ((UINT16)tempaccum) << 8; // upper byte
+
+ tempaccum = g_amec->proc[1].pwr250usmem.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[1].pwr250usmem.src_accum_snapshot = g_amec->proc[1].pwr250usmem.accumulator; // save current accum state for next 2msec
+ tempaccum = g_amec->proc[1].pwr250usmem.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum = tempaccum >> g_amec->stream_vector_rate; // @mw640
+ tempaccum = 0; // @mw641 force to 0 until master OCC collects
+
+ tempreg = tempreg | (0xff & ((UINT16)tempaccum));
+ g_amec->analytics_array[7] = tempreg;
+
+ tempaccum = g_amec->proc[2].pwr250usmem.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[2].pwr250usmem.src_accum_snapshot = g_amec->proc[2].pwr250usmem.accumulator; // save current accum state for next 2msec
+ tempaccum = g_amec->proc[2].pwr250usmem.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum = tempaccum >> g_amec->stream_vector_rate; // @mw640
+ tempaccum = 0; // @mw641 force to 0 until master OCC collects
+
+ tempreg = ((UINT16)tempaccum) << 8; // upper byte
+
+ tempaccum = g_amec->proc[3].pwr250usmem.src_accum_snapshot; // load accumulator from last 2msec @mw639
+ g_amec->proc[3].pwr250usmem.src_accum_snapshot = g_amec->proc[3].pwr250usmem.accumulator; // save current accum state for next 2msec
+ tempaccum = g_amec->proc[3].pwr250usmem.accumulator - tempaccum; // total accumulation over 2msec
+ tempaccum = tempaccum >> g_amec->stream_vector_rate; // @mw640
+ tempaccum = 0; // @mw641 force to 0 until master OCC collects
+
+ tempreg = tempreg | (0xff & ((UINT16)tempaccum));
+ g_amec->analytics_array[8] = tempreg;
+
+ // Now begins the per processor unique data
+ tempreg = (g_amec->analytics_total_chips) << 8; // upper byte
+ tempreg = tempreg | (0xff & (g_amec->analytics_chip)); // which chip is outputting this interval?
+ g_amec->analytics_array[9] = tempreg;
+ j = g_amec->analytics_chip; // select which chip to process
+
+ if (g_amec->analytics_option == 0)
+ {
+ k = 0; // Default to no shift, if user didn't enter analytics_total_chips (set to 0)
+ if (g_amec->analytics_total_chips == 1) k = g_amec->stream_vector_rate - 3; // (2msec * 2^k) is shift for averaging interval (16msec) @mw636
+ if (g_amec->analytics_total_chips == 2) k = g_amec->stream_vector_rate - 2; // (2msec * 2^k) is shift for averaging interval (32msec) @mw636
+ if (g_amec->analytics_total_chips == 4) k = g_amec->stream_vector_rate - 1; // (2msec * 2^k) is shift for averaging interval (64msec) @mw636
+ if (g_amec->analytics_total_chips == 8) k = g_amec->stream_vector_rate; // (2msec * 2^k) is shift for averaging interval (128msec)@mw636
+ }
+ if (g_amec->analytics_option == 1)
+ {
+ k = g_amec->stream_vector_rate - 3; // (2msec * 2^k) is shift for averaging interval (16msec) @mw636
+ }
+
+ l = 12; // index offset @mw583 (was 2)
+
+ g_amec->analytics_array[0] = (UINT16)g_amec->g44_avg[(j * MSA) + 0]; // todclock1 (hi 16 bits, no averaging)
+ g_amec->analytics_array[1] = (UINT16)g_amec->g44_avg[(j * MSA) + 2]; // todclock1 (medium 16 bits, no averaging)
+ g_amec->analytics_array[2] = (UINT16)g_amec->g44_avg[(j * MSA) + 4]; // todclock1 (lo 16 bits, no averaging)
+
+ g_amec->analytics_array[3] = (UINT16)(g_amec->g44_avg[(j * MSA) + 6] >> k); // the first two averages are 16 bits
+ g_amec->g44_avg[(j * MSA) + 6] = 0; // reset average for this sensor to 0
+ g_amec->analytics_array[4] = (UINT16)(g_amec->g44_avg[(j * MSA) + 8] >> k); // the first two averages are 16 bits
+ g_amec->g44_avg[(j * MSA) + 8] = 0; // reset average for this sensor to 0
+ g_amec->analytics_array[10] = (UINT16)(g_amec->g44_avg[(j * MSA) + 10] >> k); // the first two averages are 16 bits
+ g_amec->g44_avg[(j * MSA) + 10] = 0; // reset average for this sensor to 0
+ g_amec->analytics_array[11] = (UINT16)(g_amec->g44_avg[(j * MSA) + 11] >> k); // the first two averages are 16 bits
+ g_amec->g44_avg[(j * MSA) + 11] = 0; // reset average for this sensor to 0
+
+ for (i = 12; i <= 15; i++)
+ {
+ temp16 = (UINT16)(g_amec->g44_avg[(j * MSA) + l] >> k);
+ tempreg = temp16 << 8; // upper byte
+ temp16 = (UINT16)(g_amec->g44_avg[(j * MSA) + l + 1] >> k);
+ tempreg = tempreg | (0xff & temp16);
+ g_amec->analytics_array[i] = tempreg;
+ g_amec->g44_avg[(j * MSA) + l] = 0; // Reset average for this sensor to 0
+ g_amec->g44_avg[(j * MSA) + l + 1] = 0; // Reset average for this sensor to 0
+
+ l = l + 2;
+ }
+
+ // Now copy over sleep and nap sensors.
+ // WARNING--> no division as these sensors are "OR"ed together
+ // every 32msec: "OR" keeps deepest state reached
+ temp16 = (UINT16)g_amec->g44_avg[(j * MSA) + l];
+ tempreg = temp16 << 8; // upper byte
+ temp16 = (UINT16)g_amec->g44_avg[(j * MSA) + l + 1];
+ tempreg = tempreg | (0xff & temp16);
+ g_amec->analytics_array[i] = tempreg;
+ g_amec->g44_avg[(j * MSA) + l] = 0; // Reset all indicators of cores napping to begin next N intervals
+ g_amec->g44_avg[(j * MSA) + l + 1] = 0; // Reset all indicators of cores sleeping to begin next N intervals
+ i = i + 1;
+ l = l + 2;
+
+ // Now process CPM data...instead of computing the average, the
+ // worst case (minimum) CPM value was maintained. Just copy it
+ // over. Then reset each CPM to be 15 (maximum value) to start next
+ // monitoring interval
+ // for (i=17; i<=18; i++)
+ // {
+ // tempreg=(UINT16)g_amec->g44_avg[(j*MSA)+l]<<12; // hi nybble
+ // tempreg=tempreg | ((0xf & ((UINT16)g_amec->g44_avg[(j*MSA)+l+1]))<<8); // mid-hi nybble $mw435
+ // tempreg=tempreg | ((0xf & ((UINT16)g_amec->g44_avg[(j*MSA)+l+2]))<<4); // mid-lo nybble $mw435
+ // tempreg=tempreg | ((0xf & ((UINT16)g_amec->g44_avg[(j*MSA)+l+3]))); // lo nybble
+ // g_amec->analytics_array[i]=tempreg;
+ // g_amec->g44_avg[(j*MSA)+l] = 15; // Reset all CPM indicators to 15
+ // g_amec->g44_avg[(j*MSA)+l+1] = 15; // Reset all CPM indicators to 15
+ // g_amec->g44_avg[(j*MSA)+l+2] = 15; // Reset all CPM indicators to 15
+ // g_amec->g44_avg[(j*MSA)+l+3] = 15; // Reset all CPM indicators to 15
+ // l=l+4;
+ // }
+
+ // @mw642 (process last 2 Centaurs' memory bandwidth sensors
+ for (i = 17; i <= 18; i++)
+ {
+ temp16 = (UINT16)(g_amec->g44_avg[(j * MSA) + l] >> k);
+ tempreg = temp16 << 8; // upper byte
+ temp16 = (UINT16)(g_amec->g44_avg[(j * MSA) + l + 1] >> k);
+ tempreg = tempreg | (0xff & temp16);
+ g_amec->analytics_array[i] = tempreg;
+ g_amec->g44_avg[(j * MSA) + l] = 0; // Reset average for this sensor to 0
+ g_amec->g44_avg[(j * MSA) + l + 1] = 0; // Reset average for this sensor to 0
+ l = l + 2;
+ }
+
+ for (i = 19; i <= 46; i++)
+ {
+ temp16 = (UINT16)(g_amec->g44_avg[(j * MSA) + l] >> k);
+ tempreg = temp16 << 8; // upper byte
+ temp16 = (UINT16)(g_amec->g44_avg[(j * MSA) + l + 1] >> k);
+ tempreg = tempreg | (0xff & temp16);
+ g_amec->analytics_array[i] = tempreg;
+ g_amec->g44_avg[(j * MSA) + l] = 0; // Reset average for this sensor to 0
+ g_amec->g44_avg[(j * MSA) + l + 1] = 0; // Reset average for this sensor to 0
+
+ l = l + 2;
+ }
+
+ // Final processing for Group 44: determine if cycling through all
+ // chips or just monitoring one chip
+ if (g_amec->analytics_option == 0)
+ {
+ g_amec->analytics_chip++;
+
+ if (g_amec->analytics_chip >= g_amec->analytics_total_chips)
+ {
+ g_amec->analytics_chip = 0; // loop back to chip 0 again
+ }
+ }
+
+ } // @mw585
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/* End */
+/*----------------------------------------------------------------------------*/
diff --git a/src/occ/amec/amec_analytics.h b/src/occ/amec/amec_analytics.h
new file mode 100755
index 0000000..d5b5ffd
--- /dev/null
+++ b/src/occ/amec/amec_analytics.h
@@ -0,0 +1,34 @@
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_controller_centaur_h amec_controller_centaur.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- --------------------------------------
+ * @mw582 mware 11/20/2013 New file
+ *
+ * @endverbatim
+ */
+
+#ifndef _AMEC_ANALYTICS_H
+#define _AMEC_ANALYTICS_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Defines/Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Function Declarations */
+/*----------------------------------------------------------------------------*/
+
+// Function that enables stream buffer recording
+void amec_analytics_sb_recording(void);
+
+// Function that is called by AMEC State Machine for analytics
+void amec_analytics_main(void);
+
+#endif // _AMEC_ANALYTICS_H
diff --git a/src/occ/amec/amec_controller.c b/src/occ/amec/amec_controller.c
new file mode 100644
index 0000000..ed7c1ab
--- /dev/null
+++ b/src/occ/amec/amec_controller.c
@@ -0,0 +1,444 @@
+/******************************************************************************
+// @file amec_controller.c
+// @brief Amester interface
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_controller_c amec_controller.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @ry002 862116 ronda 11/26/2012 Thermal controller for processor
+ * @ry003 870734 ronda 02/20/2013 Thermal controller for memory
+ * @ry004 872358 ronda 02/28/2013 Update function description
+ * @fk001 879727 fmkassem 04/16/2013 Power capping support.
+ * @cl001 lefurgy 07/24/2013 Fix overflow in l_throttle
+ * @gs009 897228 gjsilva 08/28/2013 Fix sensor name for proc thermal control
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <sensor.h>
+#include <amec_sys.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern uint8_t G_dimm_temp_expired_bitmap;
+extern uint8_t G_cent_temp_expired_bitmap;
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+// Function Specification
+//
+// Name: amec_controller_proc_thermal
+//
+// Description: This function implements the Proportional Controller for the
+// processor thermal control. Although it doesn't return any
+// results, it populates the thermal vote in the field
+// g_amec->thermalproc.speed_request.
+//
+//
+// Flow: 5-13-13 FN=amec_thrm_proc_control.odg
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_controller_proc_thermal()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_thermal_winner = 0;
+ uint16_t l_residue = 0;
+ uint16_t l_old_residue = 0;
+ int16_t l_error = 0;
+ int16_t l_cpu_speed = 0;
+ int16_t l_throttle_chg = 0;
+ int32_t l_throttle = 0; // @cl001
+ sensor_t * l_sensor = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // Get TEMP2MSP0PEAK sensor, which is hottest core temperature in OCC processor
+ l_sensor = getSensorByGsid(TEMP2MSP0PEAK);
+
+ // Use the highest temperature of all processors in 0.1 degrees C
+ l_thermal_winner = l_sensor->sample * 10;
+
+ // Check if there is an error
+ if (g_amec->thermalproc.setpoint == l_thermal_winner)
+ return;
+
+ // Calculate the thermal control error
+ l_error = g_amec->thermalproc.setpoint - l_thermal_winner;
+
+ // TODO: Get with Malcolm to migrate to 16-bit multiply
+ // Proportional Controller for the thermal control loop
+ l_throttle = (int32_t) l_error * g_amec->thermalproc.Pgain;
+ l_residue = (uint16_t) l_throttle;
+ l_throttle_chg = (int16_t) (l_throttle >> 16);
+
+ if ((int16_t) l_throttle_chg > (int16_t) g_amec->sys.speed_step_limit)
+ {
+ l_throttle_chg = g_amec->sys.speed_step_limit;
+ }
+ else
+ {
+ if ((int16_t) l_throttle_chg < ((int16_t) (-g_amec->sys.speed_step_limit)))
+ {
+ l_throttle_chg = (int16_t)(-g_amec->sys.speed_step_limit);
+ }
+ }
+
+ // Calculate the new thermal CPU speed request
+ l_cpu_speed = g_amec->thermalproc.speed_request +
+ (int16_t) l_throttle_chg * g_amec->sys.speed_step;
+
+ // Proceed with residue summation to correctly follow set-point
+ l_old_residue = g_amec->thermalproc.total_res;
+ g_amec->thermalproc.total_res += l_residue;
+ if (g_amec->thermalproc.total_res < l_old_residue)
+ {
+ l_cpu_speed += g_amec->sys.speed_step;
+ }
+
+ // Enforce actuator saturation limits
+ if (l_cpu_speed > g_amec->sys.max_speed)
+ l_cpu_speed = g_amec->sys.max_speed;
+ if (l_cpu_speed < g_amec->sys.min_speed)
+ l_cpu_speed = g_amec->sys.min_speed;
+
+ // Generate the new thermal speed request
+ g_amec->thermalproc.speed_request = l_cpu_speed;
+ // Calculate frequency request based on thermal speed request
+ g_amec->thermalproc.freq_request = amec_controller_speed2freq(
+ g_amec->thermalproc.speed_request,
+ g_amec->sys.fmax); // @fk001m
+}
+
+//*************************************************************************
+// Function Specification
+//
+// Name: amec_controller_dimm_thermal
+//
+// Description: This function implements the Proportional Controller for the
+// DIMM thermal control. Although it doesn't return any
+// results, it populates the thermal vote in the field
+// g_amec->thermaldimm.speed_request.
+//
+//
+// Flow: 2-15-13 FN=amec_thrm_dimm_control.odg
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_controller_dimm_thermal()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_thermal_winner = 0;
+ uint16_t l_residue = 0;
+ uint16_t l_old_residue = 0;
+ int16_t l_error = 0;
+ int16_t l_mem_speed = 0;
+ int16_t l_throttle_chg = 0;
+ int32_t l_throttle = 0;
+ sensor_t * l_sensor = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // Get TEMP2MSDIMM sensor value
+ l_sensor = getSensorByGsid(TEMP2MSDIMM);
+
+ if(G_dimm_temp_expired_bitmap) //gm016
+ {
+ //we were not able to read one or more dimm temperatures.
+ //Assume temperature is at the setpoint plus 1 degree C.
+ l_thermal_winner = g_amec->thermaldimm.setpoint + 10;
+ }
+ else
+ {
+ // Use the highest temperature of all DIMMs in 0.1 degrees C
+ l_thermal_winner = l_sensor->sample * 10;
+ }
+
+ // Check if there is an error
+ if (g_amec->thermaldimm.setpoint == l_thermal_winner)
+ return;
+
+ // Calculate the thermal control error
+ l_error = g_amec->thermaldimm.setpoint - l_thermal_winner;
+
+ // Proportional Controller for the thermal control loop based on DIMM
+ // temperatures
+ l_throttle = (int32_t) l_error * g_amec->thermaldimm.Pgain;
+ l_residue = (uint16_t) l_throttle;
+ l_throttle_chg = (int16_t) (l_throttle >> 16);
+
+ if ((int16_t) l_throttle_chg > AMEC_MEMORY_SPEED_CHANGE_LIMIT)
+ {
+ l_throttle_chg = AMEC_MEMORY_SPEED_CHANGE_LIMIT;
+ }
+ else
+ {
+ if ((int16_t) l_throttle_chg < (-AMEC_MEMORY_SPEED_CHANGE_LIMIT))
+ {
+ l_throttle_chg = -AMEC_MEMORY_SPEED_CHANGE_LIMIT;
+ }
+ }
+
+ // Calculate the new thermal speed request for DIMMs
+ l_mem_speed = g_amec->thermaldimm.speed_request +
+ (int16_t) l_throttle_chg * AMEC_MEMORY_STEP_SIZE;
+
+ // Proceed with residue summation to correctly follow set-point
+ l_old_residue = g_amec->thermaldimm.total_res;
+ g_amec->thermaldimm.total_res += l_residue;
+ if (g_amec->thermaldimm.total_res < l_old_residue)
+ {
+ l_mem_speed += AMEC_MEMORY_STEP_SIZE;
+ }
+
+ // Enforce actuator saturation limits
+ if (l_mem_speed > AMEC_MEMORY_MAX_STEP)
+ l_mem_speed = AMEC_MEMORY_MAX_STEP;
+ if (l_mem_speed < AMEC_MEMORY_MIN_STEP)
+ l_mem_speed = AMEC_MEMORY_MIN_STEP;
+
+ // Generate the new thermal speed request
+ g_amec->thermaldimm.speed_request = (uint16_t) l_mem_speed;
+}
+
+
+//*************************************************************************
+// Function Specification
+//
+// Name: amec_controller_centaur_thermal
+//
+// Description: This function implements the Proportional Controller for the
+// centaur thermal control. Although it doesn't return any
+// results, it populates the thermal vote in the field
+// g_amec->thermalcent.speed_request.
+//
+//
+// Flow: 2-15-13 FN=amec_thrm_centaur_control.odg
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_controller_centaur_thermal()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_thermal_winner = 0;
+ uint16_t l_residue = 0;
+ uint16_t l_old_residue = 0;
+ int16_t l_error = 0;
+ int16_t l_mem_speed = 0;
+ int16_t l_throttle_chg = 0;
+ int32_t l_throttle = 0;
+ sensor_t * l_sensor = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // Get TEMP2MSCENT sensor value
+ l_sensor = getSensorByGsid(TEMP2MSCENT);
+
+ if(G_cent_temp_expired_bitmap) //gm016
+ {
+ //we were not able to get a valid temperature. Assume it is 1 degree
+ //over the setpoint.
+ l_thermal_winner = g_amec->thermalcent.setpoint + 10;
+ }
+ else
+ {
+ // Use the highest temperature of all Centaur in 0.1 degrees C
+ l_thermal_winner = l_sensor->sample * 10;
+ }
+
+ // Check if there is an error
+ if (g_amec->thermalcent.setpoint == l_thermal_winner)
+ return;
+
+ // Calculate the thermal control error
+ l_error = g_amec->thermalcent.setpoint - l_thermal_winner;
+
+ // Proportional Controller for the thermal control loop based on CENTAUR
+ // temperatures
+ l_throttle = (int32_t) l_error * g_amec->thermalcent.Pgain;
+ l_residue = (uint16_t) l_throttle;
+ l_throttle_chg = (int16_t) (l_throttle >> 16);
+
+ if ((int16_t) l_throttle_chg > AMEC_MEMORY_SPEED_CHANGE_LIMIT)
+ {
+ l_throttle_chg = AMEC_MEMORY_SPEED_CHANGE_LIMIT;
+ }
+ else
+ {
+ if ((int16_t) l_throttle_chg < (-AMEC_MEMORY_SPEED_CHANGE_LIMIT))
+ {
+ l_throttle_chg = -AMEC_MEMORY_SPEED_CHANGE_LIMIT;
+ }
+ }
+
+ // Calculate the new thermal speed request for Centaurs
+ l_mem_speed = g_amec->thermalcent.speed_request +
+ (int16_t) l_throttle_chg * AMEC_MEMORY_STEP_SIZE;
+
+ // Proceed with residue summation to correctly follow set-point
+ l_old_residue = g_amec->thermalcent.total_res;
+ g_amec->thermalcent.total_res += l_residue;
+ if (g_amec->thermalcent.total_res < l_old_residue)
+ {
+ l_mem_speed += AMEC_MEMORY_STEP_SIZE;
+ }
+
+ // Enforce actuator saturation limits
+ if (l_mem_speed > AMEC_MEMORY_MAX_STEP)
+ l_mem_speed = AMEC_MEMORY_MAX_STEP;
+ if (l_mem_speed < AMEC_MEMORY_MIN_STEP)
+ l_mem_speed = AMEC_MEMORY_MIN_STEP;
+
+ // Generate the new thermal speed request
+ g_amec->thermalcent.speed_request = (uint16_t) l_mem_speed;
+}
+
+// Function Specification
+//
+// Name: amec_controller_vrhotproc
+//
+// Description: This function implements a Single-step Controller for the
+// processor VRHOT signal. Although it doesn't return any
+// results, it populates the frequency vote in the field
+// g_amec->vrhotproc.freq_request
+//
+//
+// End Function Specification
+void amec_controller_vrhotproc()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ int16_t l_cpu_speed = 0;
+ int16_t l_throttle_chg = 0;
+ sensor_t *l_sensor = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // Get VRHOT sensor, which is really a counter of consecutive times the
+ // VRHOT signal has been asserted
+ l_sensor = getSensorByGsid(VRHOT250USPROC);
+
+ // Single-step controller:
+ // If sensor VRHOT250USPROC is above the set-point, we need to step down.
+ // Else, do a single step up.
+ if (l_sensor->sample >= g_amec->vrhotproc.setpoint)
+ {
+ l_throttle_chg = (int16_t)(-1);
+ }
+ else
+ {
+ l_throttle_chg = (int16_t)(1);
+ }
+
+ // Calculate the new VRHOTPROC speed request
+ l_cpu_speed = g_amec->vrhotproc.speed_request +
+ (int16_t) l_throttle_chg * g_amec->sys.speed_step;
+
+ // Never allow negative speed requests
+ if (l_cpu_speed < 0)
+ {
+ l_cpu_speed = 0;
+ }
+
+ // Enforce actuator saturation limits
+ if (l_cpu_speed > g_amec->sys.max_speed)
+ {
+ l_cpu_speed = g_amec->sys.max_speed;
+ }
+ if (l_cpu_speed < g_amec->sys.min_speed)
+ {
+ l_cpu_speed = g_amec->sys.min_speed;
+ }
+
+ // Generate the new VRHOTPROC frequency request
+ g_amec->vrhotproc.speed_request = l_cpu_speed;
+ g_amec->vrhotproc.freq_request =
+ amec_controller_speed2freq(g_amec->vrhotproc.speed_request,
+ g_amec->sys.fmax);
+
+}
+
+
+// Function Specification
+//
+// Name: amec_controller_speed2freq
+//
+// Description: Helper function to convert speed to MHz.
+//
+// Flow: FN= None
+//
+// End Function Specification
+uint16_t amec_controller_speed2freq (const uint16_t i_speed, const uint16_t i_fmax)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_tempreg = 0;
+ uint16_t l_temp16 = 0;
+ uint32_t l_temp32 = 0;
+ uint16_t l_freq = 0;
+ uint32_t l_divide32[2] = {0, 0};
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ l_temp16 = i_fmax;
+ l_tempreg = (uint16_t)i_speed;
+ l_temp32 = ((uint32_t)l_tempreg)*((uint32_t)l_temp16);
+ l_temp16 = (uint16_t)1000;
+ l_divide32[1] = (uint32_t)l_temp16;
+ l_divide32[0] = (uint32_t)l_temp32;
+ l_divide32[0] /= l_divide32[1];
+ l_temp32 = l_divide32[0];
+ l_freq = (uint16_t)l_temp32; /* freq will always fit in 16 bits */
+
+ return l_freq;
+}
diff --git a/src/occ/amec/amec_controller.h b/src/occ/amec/amec_controller.h
new file mode 100644
index 0000000..d6d2fa4
--- /dev/null
+++ b/src/occ/amec/amec_controller.h
@@ -0,0 +1,135 @@
+/******************************************************************************
+// @file amec_controller.h
+// @brief OCC AMEC Controller Structure
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section amec_controller.h AMEC_CONTROLLER.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @ry002 ronda 11/20/2012 New File
+ * @ry003 870734 ronda 02/20/2013 Thermal controller for memory
+ * @gs012 903325 gjsilva 10/18/2013 Log Processor OT errors
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_CONTROLLER_H
+#define _AMEC_CONTROLLER_H
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Defines */
+/*----------------------------------------------------------------------------*/
+// Maximum speed supported for memory controllers (100.0%)
+#define AMEC_MEMORY_MAX_STEP 1000
+
+// Minimum speed supported for memory controllers (1.0%)
+#define AMEC_MEMORY_MIN_STEP 10
+
+// Step size for increasing or decreasing memory speed (1.0%)
+#define AMEC_MEMORY_STEP_SIZE 10
+
+// Limit value on speed change to avoid overflow of the controller
+#define AMEC_MEMORY_SPEED_CHANGE_LIMIT (UINT16_MAX/4)/AMEC_MEMORY_STEP_SIZE
+
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+///Controller Model
+typedef struct amec_controller
+{
+ ///Over-temperature error for FRU callout (in degrees C)
+ uint8_t ot_error;
+ ///Setpoint or reference for the controller
+ uint16_t setpoint;
+ ///Proportional gain of the controller
+ uint16_t Pgain;
+ ///Theoretical controller residue summation
+ uint16_t total_res;
+ ///Final speed request of the controller
+ uint16_t speed_request;
+ ///Final frequency request of the controller
+ uint16_t freq_request;
+ ///Expiration time for a temperature reading (in seconds)
+ uint8_t temp_timeout;
+}amec_controller_t;
+
+
+/*----------------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief Thermal Control Loop.
+ *
+ * This function implements the Proportional Controller for the thermal
+ * control loop. Although it doesn't return any results, it populates the
+ * thermal vote in the field g_amec->thermalproc.speed_request.
+ *
+ * @return No return from this function.
+ */
+void amec_controller_proc_thermal();
+
+/**
+ * @brief Thermal Control Loop based on Centaur
+ * temperatures.
+ *
+ * This function implements a Proportional Controller for the
+ * thermal control loop based on Centaur temperatures.
+ * Although it doesn't return any results, it populates the
+ * thermal vote in the field g_amec->thermalcent.speed_request.
+ *
+ * @return No return from this function.
+ */
+void amec_controller_centaur_thermal();
+
+
+/**
+ * @brief Thermal Control Loop based on DIMM temperatures.
+ *
+ * This function implements a Proportional Controller for the
+ * thermal control loop based on DIMM temperatures. Although it
+ * doesn't return any results, it populates the thermal vote in
+ * the field g_amec->thermaldimm.speed_request.
+ *
+ * @return No return from this function.
+ */
+void amec_controller_dimm_thermal();
+
+
+/**
+ * @brief Helper function to convert speed to MHz
+ *
+ * This function converts a given speed in percentage (%) to a
+ * frequency in MHz.
+ *
+ * @param i_speed Input speed in percentage (0% - 100%)
+ * @param i_fmax Maximum frequency of the system
+ *
+ * @return Equivalent frequency in MHz
+ */
+uint16_t amec_controller_speed2freq (const uint16_t i_speed, const uint16_t i_fmax);
+
+
+void amec_controller_vrhotproc();
+
+
+#endif //_AMEC_CONTROLLER_H
diff --git a/src/occ/amec/amec_data.c b/src/occ/amec/amec_data.c
new file mode 100755
index 0000000..ac0d694
--- /dev/null
+++ b/src/occ/amec/amec_data.c
@@ -0,0 +1,507 @@
+/******************************************************************************
+// @file amec_data.c
+// @brief Amec Data Import/Export Handling
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_data_c amec_data.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th015 thallet 08/03/2012 New file
+ * @gs001 gsilva 08/03/2012 New file
+ * @fk001 879727 fmkassem 04/16/2013 OCC powercap support.
+ * @gs008 894661 gjsilva 08/08/2013 Initial support for DPS-FP mode
+ * @gs010 899888 gjsilva 09/24/2013 Process data format 0x13 from TMGT
+ * @gs012 903325 gjsilva 10/18/2013 Log Processor OT errors
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs019 908218 gjsilva 12/04/2013 Support cooling request architecture
+ * @rt004 908817 tapiar 12/11/2013 Update global data mask when master
+ * code posts it to slave code (via data_write_pcap)
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @gm017 909636 milesg 12/17/2013 Changes from mem throttle review
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h>
+#include "sensor.h"
+#include "rtls.h"
+#include "occ_sys_config.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "dcom.h"
+#include "proc_data.h"
+#include "proc_data_control.h"
+#include "amec_smh.h"
+#include "amec_slave_smh.h"
+#include <trac.h>
+#include "amec_sys.h"
+#include "sensor_enum.h"
+#include "amec_service_codes.h"
+#include <amec_sensors_core.h>
+#include <amec_sensors_power.h>
+#include <amec_sensors_fw.h>
+#include <amec_data.h>
+#include <amec_freq.h>
+#include <thrm_thread.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
+// Function Specification
+//
+// Name: AMEC_data_write_fcurr
+//
+// Description:
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ //UINT16 l_freq_nom = 0;
+ OCC_MODE l_mode = i_mode;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // We'll never actually get a dynamic power save data package so just
+ // use turbo as our mode if in dynamic power save since it
+ // will have appropriate frequency.
+ if((i_mode == OCC_MODE_DYN_POWER_SAVE) ||
+ (i_mode == OCC_MODE_DYN_POWER_SAVE_FP))
+ {
+ l_mode = OCC_MODE_TURBO;
+ }
+
+ // If we're active we need to load this new range into DVFS MIN/MAX
+ if(CURRENT_STATE() == OCC_STATE_ACTIVE)
+ {
+ // Use i_mode here since this function understands turbo
+ l_err = amec_set_freq_range(i_mode);
+
+ if(l_err)
+ {
+ // E>AMEC_data_write_fcurr: Error in call to amec_control_set_freq_range() i_mode:0x%X l_freq:%u
+ //TRACE2(g_trac_amec,2118718763,i_mode,l_freq);
+ //break;
+ }
+ }
+
+ return l_err;
+}
+
+// Function Specification
+//
+// Name: AMEC_data_write_thrm_thresholds
+//
+// Description: This function loads data from the Thermal Control Threshold
+// data packet (format 0x13) into g_amec structure. This function should be
+// called when OCC goes active or changes modes or goes in/out of Acoustic
+// mode (ITE-only mode).
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+errlHndl_t AMEC_data_write_thrm_thresholds(const OCC_MODE i_mode)
+{
+
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ cmdh_thrm_thresholds_t *l_data = NULL;
+ cmdh_thrm_thresholds_set_t *l_frudata = NULL;
+ uint8_t l_dvfs_temp = 0;
+ uint8_t l_error = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ // Retrieve the thermal control threshold data
+ l_err = DATA_get_thrm_thresholds(&l_data);
+ if(l_err)
+ {
+ TRAC_ERR("AMEC_data_write_thrm_thresholds: Error retrieving thermal control threshold data");
+ break;
+ }
+
+ // Notify thermal thread to update its local copy of the thermal thresholds
+ THRM_thread_update_thresholds();
+
+ l_frudata = l_data->data;
+
+ // TODO: Need to check if acoustic mode has been enabled (ITE-only mode)
+
+ // Store the processor thermal data
+ if(i_mode == OCC_MODE_NOMINAL)
+ {
+ l_dvfs_temp = l_frudata[DATA_FRU_PROC].dvfs;
+ l_error = l_frudata[DATA_FRU_PROC].error;
+ }
+ else
+ {
+ l_dvfs_temp = l_frudata[DATA_FRU_PROC].pm_dvfs;
+ if(i_mode == OCC_MODE_TURBO) //gm016
+ {
+ //Need to log an error if we dvfs in static turbo mode (for mfg)
+ l_error = l_dvfs_temp;
+ }
+ else
+ {
+ l_error = l_frudata[DATA_FRU_PROC].pm_error;
+ }
+ }
+ // Store the DVFS thermal setpoint in 0.1 degrees C
+ g_amec->thermalproc.setpoint = l_dvfs_temp * 10;
+ // Store the error temperature for OT detection
+ g_amec->thermalproc.ot_error = l_error;
+ // Store the temperature timeout value
+ g_amec->thermalproc.temp_timeout = l_frudata[DATA_FRU_PROC].max_read_timeout;
+
+ TRAC_INFO("AMEC_data_write_thrm_thresholds: Setting %u as DVFS setpoint for processor",
+ l_dvfs_temp);
+
+ // Store the Centaur thermal data
+ if(i_mode == OCC_MODE_NOMINAL)
+ {
+ l_dvfs_temp = l_frudata[DATA_FRU_CENTAUR].dvfs;
+ l_error = l_frudata[DATA_FRU_CENTAUR].error;
+ }
+ else
+ {
+ l_dvfs_temp = l_frudata[DATA_FRU_CENTAUR].pm_dvfs;
+ if(i_mode == OCC_MODE_TURBO) //gm016
+ {
+ //Need to log an error if we throttle in static turbo mode (for mfg)
+ l_error = l_dvfs_temp;
+ }
+ else
+ {
+ l_error = l_frudata[DATA_FRU_CENTAUR].pm_error;
+ }
+ }
+
+ // Store the DVFS thermal setpoint in 0.1 degrees C
+ g_amec->thermalcent.setpoint = l_dvfs_temp * 10;
+ // Store the error temperature for OT detection
+ g_amec->thermalcent.ot_error = l_error;
+ // Store the temperature timeout value
+ g_amec->thermalcent.temp_timeout = l_frudata[DATA_FRU_CENTAUR].max_read_timeout;
+
+ TRAC_INFO("AMEC_data_write_thrm_thresholds: Setting %u as DVFS setpoint for Centaur",
+ l_dvfs_temp);
+
+ // Store the DIMM thermal data
+ if(i_mode == OCC_MODE_NOMINAL)
+ {
+ l_dvfs_temp = l_frudata[DATA_FRU_DIMM].dvfs;
+ l_error = l_frudata[DATA_FRU_DIMM].error;
+ }
+ else
+ {
+ l_dvfs_temp = l_frudata[DATA_FRU_DIMM].pm_dvfs;
+ if(i_mode == OCC_MODE_TURBO) //gm016
+ {
+ //Need to log an error if we throttle in static turbo mode (for mfg)
+ l_error = l_dvfs_temp;
+ }
+ else
+ {
+ l_error = l_frudata[DATA_FRU_DIMM].pm_error;
+ }
+ }
+ // Store the DVFS thermal setpoint in 0.1 degrees C
+ g_amec->thermaldimm.setpoint = l_dvfs_temp * 10;
+ // Store the error temperature for OT detection
+ g_amec->thermaldimm.ot_error = l_error;
+ // Store the temperature timeout value
+ g_amec->thermaldimm.temp_timeout = l_frudata[DATA_FRU_DIMM].max_read_timeout;
+
+ TRAC_INFO("AMEC_data_write_thrm_thresholds: Setting %u as DVFS setpoint for DIMM",
+ l_dvfs_temp);
+
+ // Store the VRM thermal data
+ g_amec->proc[0].vrfan_error_count = l_frudata[DATA_FRU_VRM].sample_error_count;
+ g_amec->vrhotproc.setpoint = l_frudata[DATA_FRU_VRM].error_count;
+
+ TRAC_INFO("AMEC_data_write_thrm_thresholds: Setting %u as DVFS setpoint for VRHOT",
+ g_amec->vrhotproc.setpoint);
+
+ } while(0);
+
+ return l_err;
+}
+
+// Function Specification
+//
+// Name: AMEC_data_write_ips_config
+//
+// Description: This function loads data from the IPS Config data packet
+// (format 0x11) into g_amec structure. This function should only by called by
+// Master OCC firmware.
+//
+//
+// Thread: RealTime Loop
+//
+// End Function Specification
+errlHndl_t AMEC_data_write_ips_cnfg(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ cmdh_ips_config_data_t *l_data = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ // Retrieve the thermal control threshold data
+ l_err = DATA_get_ips_cnfg(&l_data);
+ if(l_err)
+ {
+ TRAC_ERR("AMEC_data_write_ips_cnfg: Error retrieving IPS config data");
+ break;
+ }
+
+ // Store Idle Power Saver settings for AMEC
+ // Delay times should be stored in number of samples
+ g_amec->mst_ips_parms.entry_delay = l_data->iv_delayTimeforEntry *
+ AMEC_DPS_SAMPLING_RATE;
+ g_amec->mst_ips_parms.exit_delay = l_data->iv_delayTimeforExit *
+ AMEC_DPS_SAMPLING_RATE;
+
+ // Utilization thresholds should be stored in hundredths of a percent
+ g_amec->mst_ips_parms.entry_threshold = l_data->iv_utilizationForEntry * 100;
+ g_amec->mst_ips_parms.exit_threshold = l_data->iv_utilizationForExit * 100;
+
+ // Enable/disable Idle Power Saver
+ g_amec->mst_ips_parms.enable = l_data->iv_ipsEnabled;
+
+ } while(0);
+
+ return l_err;
+}
+
+// Function Specification
+//
+// Name: AMEC_data_change
+//
+// Description:
+//
+//
+// Flow: 03/04/13 FN= amec_data_change
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+errlHndl_t AMEC_data_change(const uint32_t i_data_mask)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ // UINT32 l_req_data = 0;
+ // OCC_STATE l_cur_state = OCC_STATE_NOCHANGE;
+ OCC_MODE l_cur_mode = OCC_MODE_NOCHANGE;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ //l_cur_state = CURRENT_STATE();
+ l_cur_mode = CURRENT_MODE();
+
+ //If we received the frequency from TMGT
+ if(i_data_mask & DATA_MASK_FREQ_PRESENT)
+ {
+ // I>AMEC_data_change: We are active and receieved new freq packet!
+ //TRACE0(g_trac_amec,1905158999);
+ l_err = AMEC_data_write_fcurr(l_cur_mode);
+ //if(l_err)
+ //{
+ // E>AMEC_data_change: Error writing freq data! i_state_mask:0x%X i_mode:0x%X l_req_data:0x%X
+ // TRACE3(g_trac_amec,2446643683,
+ // l_cur_state,
+ // l_cur_mode,
+ // l_req_data);
+ //}
+ }
+ else if(i_data_mask & DATA_MASK_THRM_THRESHOLDS)
+ {
+ l_err = AMEC_data_write_thrm_thresholds(l_cur_mode);
+
+ if(l_err)
+ {
+ TRAC_ERR("AMEC_data_change: Error writing thermal threshold data!");
+ }
+ }
+ else if(i_data_mask & DATA_MASK_IPS_CNFG)
+ {
+ l_err = AMEC_data_write_ips_cnfg();
+
+ if(l_err)
+ {
+ TRAC_ERR("AMEC_data_change: Error writing IPS config data!");
+ }
+ }
+
+ return l_err;
+}
+
+//////////////////////////
+// Function Specification
+//
+// Name: amec_data_write_pcap
+//
+// Description: Function called by slave interrupt handler to collect pcap
+// data sent by Master OCC.
+// If a new packet is received from Master, it will be written to
+// G_sysConfigData.pcap, and g_amec->pcap will be updated too.
+// Otherwise nothing happens.
+//
+//
+// Flow: 04/16/13 FN= amec_data_write_pcap
+//
+// Thread: Interrupt Handler
+//
+// Changedby: @fk001a
+//
+// End Function Specification
+void amec_data_write_pcap(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ static uint8_t L_pcap_data_count = 0;
+ uint16_t l_customer = 0;
+ uint16_t l_system = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //Check if Master sent a new packet of data.
+ if(L_pcap_data_count != G_dcom_slv_inbox_doorbell_rx.pcap.pcap_data_count)
+ {
+ //Update counter
+ L_pcap_data_count = G_dcom_slv_inbox_doorbell_rx.pcap.pcap_data_count;
+
+ //Copy pcap data received from Master OCC to G_sysConfigData
+ memcpy(&(G_sysConfigData.pcap),&(G_dcom_slv_inbox_doorbell_rx.pcap),
+ sizeof(pcap_config_data_t));
+
+ //Affects ITE ONLY: Check if it's ok (1) to exit the oversubscribed state
+ if(1 == G_sysConfigData.pcap.unthrottle)
+ {
+ //Clear throttle flag
+ g_amec->oversub_status.cmeThrottleLatchAmec = 0;
+ }
+
+ //Check node power cap requested by customer/system.
+ // 0 means there is no pcap for that parameter.
+ if(0 == G_sysConfigData.pcap.current_pcap)
+ {
+ l_customer = 0xFFFF;
+ }
+ else
+ {
+ l_customer = G_sysConfigData.pcap.current_pcap;
+ }
+
+ //Check fixed node power cap required by the system.
+ // 0 means there is no pcap for that parameter.
+ if(0 == G_sysConfigData.pcap.system_pcap)
+ {
+ l_system = 0xFFFF;
+ }
+ else
+ {
+ l_system = G_sysConfigData.pcap.system_pcap;
+ }
+
+ //Set the normal node pcap to the least of both system and customer pcap.
+ if(l_customer < l_system)
+ {
+ g_amec->pcap.norm_node_pcap = l_customer;
+ }
+ else
+ {
+ g_amec->pcap.norm_node_pcap = l_system;
+ }
+
+ ///////////////////////////////
+ //Set the oversubscription pcap
+ if(0 != G_sysConfigData.pcap.oversub_pcap)
+ {
+ g_amec->pcap.ovs_node_pcap = G_sysConfigData.pcap.oversub_pcap;
+ }
+ else
+ {
+ g_amec->pcap.ovs_node_pcap = G_sysConfigData.pcap.hard_min_pcap;
+ }
+
+ //Oversubscription pcap can NOT be higher than a customer set pcap.
+ if(g_amec->pcap.ovs_node_pcap > l_customer)
+ {
+ g_amec->pcap.ovs_node_pcap = l_customer;
+ }
+
+ // update data mask notifying we got pcap information @rt004a
+ extern data_cnfg_t * G_data_cnfg;
+ G_data_cnfg->data_mask |= DATA_MASK_PCAP_PRESENT;
+ TRAC_IMP("amec_data_write: PCAP Config data: pcap[%d]: data_mask[%x]", g_amec->pcap.norm_node_pcap, G_data_cnfg->data_mask);
+ }
+}
diff --git a/src/occ/amec/amec_data.h b/src/occ/amec/amec_data.h
new file mode 100755
index 0000000..73f8657
--- /dev/null
+++ b/src/occ/amec/amec_data.h
@@ -0,0 +1,81 @@
+/******************************************************************************
+// @file amec_data.h
+// @brief AMEC Data header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_data_h amec_data.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th015 thallet 08/03/2012 New file
+ * @gs001 gsilva 08/03/2012 New file
+ * @fk001 879727 fmkassem 04/16/2013 OCC powercap support
+ * @gs010 899888 gjsilva 09/24/2013 Process data format 0x13 from TMGT
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef _AMEC_DATA_H
+#define _AMEC_DATA_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+#include <amec_smh.h>
+#include <errl.h>
+#include <mode.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// This is used to change the current Freq data AMEC
+// is using
+errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode);
+
+// This is used to store the thermal thresholds AMEC is using
+errlHndl_t AMEC_data_write_thrm_thresholds(const OCC_MODE i_mode);
+
+// This is used to store the IPS config data AMEC is using
+errlHndl_t AMEC_data_write_ips_cnfg(void);
+
+// This is used to notify AMEC that there is a change
+// to the configuration data
+errlHndl_t AMEC_data_change(const uint32_t i_data_mask);
+
+// Writes pcap data sent by master to slave accessable structure.
+void amec_data_write_pcap();
+
+#endif
+
diff --git a/src/occ/amec/amec_dps.c b/src/occ/amec/amec_dps.c
new file mode 100755
index 0000000..4ac6921
--- /dev/null
+++ b/src/occ/amec/amec_dps.c
@@ -0,0 +1,371 @@
+/******************************************************************************
+ * @file amec_dps.c
+ * @brief AMEC Dynamic Power Saving (DPS) Algorithms
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_dps_c amec_dps.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @ly001 853751 lychen 09/17/2012 Initial Revision
+ * @ry002 862116 ronda 11/26/2012 Moved speed to freq conversion function
+ * @gs009 897228 gjsilva 08/28/2013 Enablement of DPS-FP Mode
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ *
+ * @endverbatim
+ *
+ ******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <common_types.h>
+#include <occ_sys_config.h>
+#include <proc_data.h>
+#include <amec_sys.h>
+#include <amec_perfcount.h>
+#include <amec_part.h>
+#include <amec_dps.h>
+#include <sensor.h>
+#include <amec_controller.h>
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Internal Function Prototypes */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Code */
+/*----------------------------------------------------------------------------*/
+
+// Function Specification
+//
+// Name: amec_dps_update_core_util
+//
+// Description: Update per-core utilization variables.
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_dps_update_core_util(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_temp16 = 0;
+ uint8_t l_tempreg = 0;
+ uint8_t l_idx = 0;
+ amec_core_perf_counter_t* l_perf = NULL;
+ amec_part_t *l_part = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // We no longer support the gpEMP structure in OCC firmware.
+ // If g_amec->fw.dps_no_update_flag=1, no updating is allowed
+ if (!g_amec->fw.dps_no_update_flag)
+ {
+ // Update moving average of util_slack and util_active for all cores
+ for(l_idx=0; l_idx<MAX_NUM_CORES; l_idx++)
+ {
+ if (!CORE_PRESENT(l_idx))
+ {
+ continue; //nothing to do if the core's disabled
+ }
+
+ l_part = amec_part_find_by_core(&g_amec->part_config, l_idx);
+
+ // If this core doesn't belong to a core group, then do nothing
+ if (l_part == NULL)
+ {
+ continue;
+ }
+
+ // Get pointer to the perf struc of this core
+ l_perf = &g_amec->proc[0].core[l_idx].core_perf;
+
+ l_perf->ptr_putUtilslack--; // Decrement put pointer
+ if (l_perf->ptr_putUtilslack > TWO_TO_THE_POWER_OF_FIFTEEN)
+ {
+ // Wrap circular pointer. WARNING -> buffer size must be a
+ // power of 2
+ l_perf->ptr_putUtilslack &= (MAX_UTIL_SLACK_AVG_LEN-1);
+ }
+
+ // Locate oldest sample associated with 32-bit moving average
+ // WARNING -> we need to read this sample first in case entire
+ // buffer is used which would result in the write overwriting the
+ // oldest sample we need to read.
+ l_temp16=(uint16_t)(l_perf->ptr_putUtilslack+l_part->dpsalg.sample_count_util) & (MAX_UTIL_SLACK_AVG_LEN-1);
+ l_tempreg=l_perf->ptr_util_slack_avg_buffer[l_temp16];
+ // Bleed off oldest sample from moving average
+ l_perf->util_slack_accumulator = l_perf->util_slack_accumulator-(uint32_t)l_tempreg;
+ l_tempreg=l_perf->ptr_util_active_avg_buffer[l_temp16];
+ // Bleed off oldest sample from moving average
+ l_perf->util_active_accumulator = l_perf->util_active_accumulator-(uint32_t)l_tempreg;
+ // Add in newest sample into moving average
+ l_tempreg = l_perf->util_slack_core_counter;
+ l_perf->util_slack_accumulator = l_perf->util_slack_accumulator+(uint32_t)l_tempreg;
+ // Write new sample into buffer.
+ l_perf->ptr_util_slack_avg_buffer[l_perf->ptr_putUtilslack]=l_tempreg;
+ // Add in newest sample into moving average
+ l_tempreg = l_perf->util_active_core_counter;
+ l_perf->util_active_accumulator = l_perf->util_active_accumulator+(uint32_t)l_tempreg;
+ // Write new sample into buffer.
+ l_perf->ptr_util_active_avg_buffer[l_perf->ptr_putUtilslack]=l_tempreg;
+
+ // Reset counters every 2msec
+ l_perf->util_active_core_counter=0;
+ l_perf->util_slack_core_counter=0;
+ }
+ }
+}
+
+// Function Specification
+//
+// Name: amec_dps_partition_update_sensors
+//
+// Description: Update utilization sensors for a core group.
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_dps_partition_update_sensors(const uint16_t i_part_id)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_core_perf_counter_t* l_perf = NULL;
+ uint16_t l_core_index = 0;
+ uint8_t l_idx = 0;
+ uint32_t l_cg_active_accumulator = 0;
+ uint32_t l_cg_slack_accumulator = 0;
+ uint16_t l_cg_util_slack_perc = 0;
+ uint32_t l_divide32[2] = {0, 0};
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ for (l_idx=0; l_idx<g_amec->part_config.part_list[i_part_id].ncores; l_idx++)
+ {
+ l_core_index = g_amec->part_config.part_list[i_part_id].core_list[l_idx];
+ l_perf = &g_amec->proc[0].core[l_core_index % MAX_NUM_CORES].core_perf;
+
+ // Sum accumulators for core group
+ l_cg_active_accumulator += l_perf->util_active_accumulator;
+ l_cg_slack_accumulator += l_perf->util_slack_accumulator;
+ }
+
+ if (l_cg_active_accumulator == 0)
+ {
+ // Check for divide by zero
+ l_cg_util_slack_perc=16384; // if no active cores, set slack=100%
+ }
+ else
+ {
+ l_divide32[1]=(uint32_t)l_cg_active_accumulator;
+ l_divide32[0]=(uint32_t)l_cg_slack_accumulator<<14; // *16384 because 16384=1.0
+ l_divide32[0] /= l_divide32[1];
+ l_cg_util_slack_perc=(uint16_t)(l_divide32[0]);
+ }
+
+ // Update the sensor of the utilization slack
+ sensor_update(&g_amec->part_config.part_list[i_part_id].util2msslack, l_cg_util_slack_perc);
+}
+
+// Function Specification
+//
+// Name: amec_dps_partition_alg
+//
+// Description: DPS algorithm function.
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_dps_partition_alg(const uint16_t i_part_id)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_core_perf_counter_t* l_perf = NULL;
+ uint16_t l_freq = 0;
+ uint16_t l_core_index = 0;
+ uint16_t l_idx = 0;
+ uint16_t l_tempreg = 0;
+ uint16_t l_temp16 = 0;
+ uint32_t l_divide32[2] = {0, 0};
+ OCC_INTERNAL_MODE l_part_policy = 0xFF;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Begin: Switch on dps_type of the core group
+ switch (g_amec->part_config.part_list[i_part_id].dpsalg.type)
+ {
+ case 0x00:
+ // Type 0 algorithm: no dynamic power savings enabled
+ for (l_idx=0; l_idx<g_amec->part_config.part_list[i_part_id].ncores; l_idx++)
+ {
+ l_core_index = g_amec->part_config.part_list[i_part_id].core_list[l_idx];
+ l_perf = &g_amec->proc[0].core[l_core_index % MAX_NUM_CORES].core_perf;
+ l_perf->dps_freq_request = UINT16_MAX;
+ }
+ break;
+
+ case 41:
+ // Type 41 algorithm
+ // l_tempreg=measure of slack over gamma time interval on a per core basis
+ l_tempreg = (uint16_t)g_amec->part_config.part_list[i_part_id].util2msslack.sample;
+ // Convert to 10000 is equivalent to 100.00% utilization.
+ l_divide32[1]=(uint32_t)53687;
+ l_divide32[0]=(uint32_t)l_tempreg<<15;
+ l_divide32[0] /= l_divide32[1];
+ // l_tempreg is level of utilization using per core info
+ l_tempreg=10000-(uint16_t)(l_divide32[0]);
+
+ l_temp16 = g_amec->part_config.part_list[i_part_id].dpsalg.util_speed_request;
+ if (l_tempreg > g_amec->part_config.part_list[i_part_id].dpsalg.alpha_up)
+ {
+ l_temp16 = g_amec->part_config.part_list[i_part_id].dpsalg.util_speed_request +
+ g_amec->part_config.part_list[i_part_id].dpsalg.step_up;
+ }
+ else
+ {
+ if (l_tempreg < g_amec->part_config.part_list[i_part_id].dpsalg.alpha_down)
+ {
+ l_temp16 = g_amec->part_config.part_list[i_part_id].dpsalg.util_speed_request -
+ g_amec->part_config.part_list[i_part_id].dpsalg.step_down;
+ }
+ }
+
+ // Now limit final speed in l_temp16 to be between allowed speeds.
+ if (l_temp16 > g_amec->sys.max_speed)
+ {
+ l_temp16 = g_amec->sys.max_speed;
+ }
+ // Use the lower boundary based on the power policy of the core group
+ l_part_policy = g_amec->part_config.part_list[i_part_id].es_policy;
+ if (l_temp16 < g_amec->part_mode_freq[l_part_policy].min_speed)
+ {
+ l_temp16 = g_amec->part_mode_freq[l_part_policy].min_speed;
+ }
+
+ // Generate vote for utilization
+ g_amec->part_config.part_list[i_part_id].dpsalg.util_speed_request = l_temp16;
+ l_freq = amec_controller_speed2freq(l_temp16, g_amec->part_mode_freq[l_part_policy].fmax);
+ g_amec->part_config.part_list[i_part_id].dpsalg.freq_request = l_freq;
+
+ for (l_idx=0; l_idx<g_amec->part_config.part_list[i_part_id].ncores; l_idx++)
+ {
+ l_core_index = g_amec->part_config.part_list[i_part_id].core_list[l_idx];
+ l_perf = &g_amec->proc[0].core[l_core_index % MAX_NUM_CORES].core_perf;
+ l_perf->dps_freq_request = l_freq;
+ }
+ // End algorithm type 41
+ break;
+
+ default:
+ break;
+ }
+ // End: Switch on dps_type
+}
+
+// Function Specification
+//
+// Name: amec_dps_main
+//
+// Description: Main DPS function.
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_dps_main(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_idx = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // First, update the utilization variables for all cores
+ amec_dps_update_core_util();
+
+ // Loop through all core groups and apply energy-savings policy
+ for (l_idx=0; l_idx<AMEC_PART_MAX_PART; l_idx++)
+ {
+ if (!g_amec->part_config.part_list[l_idx].valid)
+ {
+ continue;
+ }
+
+ if (g_amec->part_config.part_list[l_idx].ncores == 0)
+ {
+ continue;
+ }
+
+ switch (g_amec->part_config.part_list[l_idx].es_policy)
+ {
+ case OCC_INTERNAL_MODE_DPS:
+ case OCC_INTERNAL_MODE_DPS_MP:
+ amec_dps_partition_update_sensors(l_idx);
+ amec_dps_partition_alg(l_idx);
+ break;
+
+ default:
+ // No energy-savings policy: DPS vote is already disabled when
+ // policy first selected for partition or core ownership
+ // changes (amec_part.c)
+ break;
+ }
+ }
+
+ // For GA1, we need to send the Fwish to the Master OCC
+ if ((g_amec->part_config.part_list[0].es_policy == OCC_INTERNAL_MODE_DPS) ||
+ (g_amec->part_config.part_list[0].es_policy == OCC_INTERNAL_MODE_DPS_MP))
+ {
+ // If this core group policy is one of the DPS modes, then send the
+ // frequency request from the DPS algorithm
+ G_dcom_slv_outbox_tx.fwish =
+ g_amec->part_config.part_list[0].dpsalg.freq_request;
+ }
+ else
+ {
+ // Else, send the nominal frequency of the system
+ G_dcom_slv_outbox_tx.fwish =
+ g_amec->part_mode_freq[OCC_INTERNAL_MODE_NOM].fmax;
+ }
+ // We also need to send the Factual to the Master OCC
+ for (l_idx=0; l_idx<MAX_NUM_CORES; l_idx++)
+ {
+ // Find the first valid core and send its frequency
+ if (CORE_PRESENT(l_idx))
+ {
+ G_dcom_slv_outbox_tx.factual =
+ AMECSENSOR_ARRAY_PTR(FREQ250USP0C0,l_idx)->sample;
+ break;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/* End */
+/*----------------------------------------------------------------------------*/
diff --git a/src/occ/amec/amec_dps.h b/src/occ/amec/amec_dps.h
new file mode 100755
index 0000000..fe2b005
--- /dev/null
+++ b/src/occ/amec/amec_dps.h
@@ -0,0 +1,117 @@
+/******************************************************************************
+ * @file amec_dps.h
+ * @brief AMEC Dynamic Power Saving (DPS) Algorithms Header File
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_dps_h amec_dps.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @ly001 853751 lychen 09/17/2012 Initial Revision
+ * @ry002 862116 ronda 11/26/2012 Moved speed to freq conversion function
+ *
+ * @endverbatim
+ *
+ ******************************************************************************/
+
+#ifndef _AMEC_DPS_H
+#define _AMEC_DPS_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Defines */
+/*----------------------------------------------------------------------------*/
+#define TWO_TO_THE_POWER_OF_FIFTEEN 32768
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+///DPS Algorithm Model
+typedef struct amec_dps
+{
+ ///Frequency request for core voting box
+ uint16_t freq_request;
+ ///Utilization speed request
+ uint16_t util_speed_request;
+ ///Utilization threshold for moving down in frequency (low side)
+ uint16_t tlutil;
+ ///Step size for going up in speed
+ uint16_t step_up;
+ ///Step size for going down in speed
+ uint16_t step_down;
+ ///Number of utilization samples in sliding window
+ uint16_t sample_count_util;
+ ///Epsilon used for determining if a core is active (units of 0.01%)
+ uint16_t epsilon_perc;
+ ///Threshold for going up in frequency
+ uint16_t alpha_up;
+ ///Threshold for going down in frequency
+ uint16_t alpha_down;
+ ///8-bit mask for dynamic power save type (=0:none active)
+ uint8_t type;
+}amec_dps_t;
+
+/*----------------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------------*/
+
+
+/**
+ * @brief Update per-core utilization variables.
+ *
+ * This function updates all the per-core utilization variables. These
+ * variables are used to populate the slack sensors.
+ *
+ * @param void
+ * @return void
+ */
+void amec_dps_update_core_util(void);
+
+/**
+ * @brief Update utilization sensors for a core group.
+ *
+ * This function updates the utilization (slack) sensors for a
+ * given core group.
+ *
+ * @param i_part_id ID of the core group
+ * @return void
+ */
+void amec_dps_partition_update_sensors(const uint16_t i_part_id);
+
+/**
+ * @brief DPS algorithm function.
+ *
+ * This function implements the different DPS algorithms for a
+ * given core group.
+ *
+ * @param i_part_id ID of the core group
+ * @return void
+ */
+void amec_dps_partition_alg(const uint16_t i_part_id);
+
+/**
+ * @brief Main DPS function.
+ *
+ * This function is the entry-point for running DPS algorithms
+ * and is aware of the different core groups defined.
+ *
+ * @param void
+ * @return void
+ */
+void amec_dps_main(void);
+
+#endif /* #ifndef _AMEC_DPS_H */
diff --git a/src/occ/amec/amec_external.h b/src/occ/amec/amec_external.h
new file mode 100755
index 0000000..e4517ed
--- /dev/null
+++ b/src/occ/amec/amec_external.h
@@ -0,0 +1,66 @@
+/******************************************************************************
+// @file amec_external.h
+// @brief OCC AMEC External header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_external_h amec_external.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 11/08/2011 New file
+ * @rc001 rickylie 01/02/2011 Moved debug trace defines to trac.h
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_EXTERNAL_H
+#define _AMEC_EXTERNAL_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// task for amec master code
+void task_amec_master( task_t *i_self);
+
+// task for amec slave code
+void task_amec_slave( task_t *i_self);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_AMEC_EXTERNAL_H
diff --git a/src/occ/amec/amec_freq.c b/src/occ/amec/amec_freq.c
new file mode 100755
index 0000000..5e48ad5
--- /dev/null
+++ b/src/occ/amec/amec_freq.c
@@ -0,0 +1,1092 @@
+/******************************************************************************
+// @file amec_freq.c
+// @brief Amec Frequency Handling
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_freq_c amec_freq.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th015 thallet 08/03/2012 New file
+ * @gs001 gsilva 08/03/2012 New file
+ * @th017 thallet 08/30/2012 Added the sensor update in votebox
+ * @ai001 853751 ailutsar 09/12/2012 Support for per-core frequency votes
+ * @ry002 862116 ronda 11/16/2012 Support thermal controller for processor
+ * @ry003 870734 ronda 02/20/2013 Thermal controller for memory
+ * @ry004 ronda 02/27/2013 Added slave memory voting box
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @fk001 879727 fmkassem 04/16/2013 Power capping support.
+ * @gs007 888247 gjsilva 06/19/2013 OCC mnfg support for frequency distribution
+ * @cl001 lefurgy 07/24/2013 Fix overflow in l_throttle
+ * @gm004 892961 milesg 07/25/2013 Support memory auto slewing
+ * @gs008 894661 gjsilva 08/08/2013 Initial support for DPS-FP mode
+ * @at016 891144 alvinwan 06/10/2013 OCC Power Cap Testing
+ * @gs009 897228 gjsilva 08/28/2013 Enablement of DPS-FP Mode
+ * @rt001 897459 tapiar 08/21/2013 health monitor changes
+ * @rt002 901927 tapiar 10/01/2013 fix src tags
+ * @gs014 903552 gjsilva 10/22/2013 Support for Amester parameter interface
+ * @gm012 905097 milesg 10/31/2013 enhanced power cap tracing
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @rt003 905677 tapiar 11/07/2013 revamp trace/error log for frequency limited due
+ * system pcap scenario
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @gs018 907196 gjsilva 11/20/2013 Base support for soft frequency boundaries
+ * @at019 908390 alvinwan 12/05/2013 Disable DPS algorithms from running in Sapphire
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @at020 908666 alvinwan 12/16/2013 Oversubscription Error Handling
+ * @at022 910758 alvinwan 01/08/2014 B1812A33 logged while in DPS mode
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ * @wb003 920760 wilbryan 03/24/2014 Update SRCs to match TPMD SRCs
+ * @wb004 922138 wilbryan 04/03/2014 Ensure timely pstate completion
+ * @gs036 931408 gjsilva 07/09/2014 Do not log 2A61 in DPS-FP mode
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h>
+#include "sensor.h"
+#include "rtls.h"
+#include "occ_sys_config.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "dcom.h"
+#include "proc_data.h"
+#include "proc_data_control.h"
+#include "amec_smh.h"
+#include "amec_slave_smh.h"
+#include <trac.h>
+#include "amec_sys.h"
+#include "sensor_enum.h"
+#include "amec_service_codes.h"
+#include <amec_sensors_core.h>
+#include <amec_sensors_power.h>
+#include <amec_sensors_fw.h>
+#include <amec_data.h>
+#include <amec_freq.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern uint8_t G_cent_temp_expired_bitmap;
+extern uint8_t G_dimm_temp_expired_bitmap;
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+BOOLEAN G_non_dps_power_limited = FALSE; //@rt001a
+uint8_t G_amec_kvm_throt_reason = NO_THROTTLE; //gm025
+uint16_t G_time_until_freq_check = FREQ_CHG_CHECK_TIME; // @wb004
+
+// >> gitprep
+// Moved following two structures because of multiple definitions error
+
+//FFDC SCOM addresses as requested by Greg Still in defect SW247927 -- gm031
+const uint32_t G_pmc_ffdc_scom_addrs[] =
+{
+ PMC_LFIR_ERR_REG,
+ PMC_LFIR_ERR_MASK_REG,
+ OCB_OCCLFIR,
+ PBA_FIR
+};
+
+//FFDC OCI addresses as requested by Greg Still in defect SW247927 -- gm031
+const uint32_t G_pmc_ffdc_oci_addrs[] =
+{
+ PMC_MODE_REG,
+ PMC_PSTATE_MONITOR_AND_CTRL_REG,
+ PMC_RAIL_BOUNDS_REGISTER,
+ PMC_PARAMETER_REG0,
+ PMC_PARAMETER_REG1,
+ PMC_EFF_GLOBAL_ACTUAL_VOLTAGE_REG,
+ PMC_STATUS_REG,
+ PMC_INTCHP_CTRL_REG1,
+ PMC_INTCHP_CTRL_REG4,
+ PMC_INTCHP_STATUS_REG,
+ PMC_INTCHP_COMMAND_REG,
+ PMC_INTCHP_PSTATE_REG,
+ PMC_SPIV_CTRL_REG0A,
+ PMC_SPIV_CTRL_REG0B,
+ PMC_SPIV_CTRL_REG1,
+ PMC_SPIV_CTRL_REG2,
+ PMC_SPIV_CTRL_REG3,
+ PMC_SPIV_CTRL_REG4,
+ PMC_SPIV_STATUS_REG,
+ PMC_SPIV_COMMAND_REG,
+ PMC_O2S_CTRL_REG0A,
+ PMC_O2S_CTRL_REG0B,
+ PMC_O2S_CTRL_REG1,
+ PMC_O2S_CTRL_REG2,
+ PMC_O2S_CTRL_REG4,
+ PMC_O2S_STATUS_REG,
+ PMC_O2S_COMMAND_REG,
+ PMC_O2S_WDATA_REG,
+ 0 //0 marks last OCI address
+};
+// << gitprep
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
+// Function Specification
+//
+// Name: amec_set_freq_range
+//
+// Description: Set the frequency range for AMEC
+// This function will run on mode changes and cnfg_data changes
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+errlHndl_t amec_set_freq_range(const OCC_MODE i_mode)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ uint16_t l_freq_min = 0;
+ uint16_t l_freq_max = 0;
+ uint32_t l_temp = 0;
+ amec_mode_freq_t l_ppm_freq[OCC_INTERNAL_MODE_MAX_NUM] = {{0}};
+ //uint16_t l_freq_nom = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // First set to Max Freq Range for this mode
+ if( VALID_MODE(i_mode) )
+ {
+ l_freq_min = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+ l_freq_max = G_sysConfigData.sys_mode_freq.table[i_mode];
+ }
+
+ // If SMS is set then TMGT wants us to pin to frequency which
+ // corresponds to input mode. They will use this function
+ // when powering off and they wish to have us bring the system
+ // back up to real nominal frequency (without being impacted
+ // by power caps or thermal actuations)
+ if(CURRENT_SMS() == SMGR_SMS_STATIC_VF_CHANGE_REQ)
+ {
+ // I>amec_control_set_freq_range: Request that we pin freq to %u for mode 0x%X
+ //TRACE2(g_trac_amec,1775283132,l_freq_max,i_mode);
+
+ l_freq_min = l_freq_max;
+ }
+
+ g_amec->sys.fmin = l_freq_min;
+ g_amec->sys.fmax = l_freq_max;
+
+ TRAC_INFO("amec_set_freq_range: Mode[0x%02x] Fmin[%u] Fmax[%u]",
+ i_mode,
+ l_freq_min,
+ l_freq_max);
+
+ // Now determine the max frequency for the PPM structure
+ l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL];
+ l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_DYN_POWER_SAVE];
+ l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_DYN_POWER_SAVE_FP];
+
+ // Determine the min frequency for the PPM structure. This Fmin should
+ // always be set to the system Fmin
+ l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+ l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+ l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+
+ // Determine the min speed allowed for DPS power policies (this is needed
+ // by the DPS algorithms)
+ l_temp = (l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmin * 1000)/l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax;
+ l_ppm_freq[OCC_INTERNAL_MODE_DPS].min_speed = l_temp;
+
+ l_temp = (l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmin * 1000)/l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmax;
+ l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].min_speed = l_temp;
+
+ // Copy the PPM frequency information into g_amec
+ memcpy(g_amec->part_mode_freq, l_ppm_freq, sizeof(l_ppm_freq));
+
+ TRAC_INFO("amec_set_freq_range: PPM Fmin[%u] Fnom[%u] Fmax[%u] min_speed[%u]",
+ l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmin,
+ l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmax,
+ l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax,
+ l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].min_speed);
+
+ return l_err;
+}
+
+
+
+// Function Specification
+//
+// Name: amec_slv_voting_box
+//
+// Description: Slave OCC's voting box that decides the frequency request.
+// This function will run every tick.
+//
+//
+// Flow: 10/22/13 FN= amec_slv_voting_box.odg
+//
+// Thread: RealTime Loop
+//
+// Changedby: @fk001c
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_voting_box(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t k = 0;
+ uint16_t l_chip_fmax = g_amec->sys.fmax;
+ uint16_t l_core_freq = 0;
+ uint32_t l_chip_reason = 0; //@rt001c
+ uint32_t l_core_reason = 0; //@rt001c
+ uint8_t l_kvm_throt_reason = NO_THROTTLE; //gm025
+ amec_part_t *l_part = NULL;
+ bool l_freq_req_changed = FALSE; // @wb004
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Voting Box for CPU speed.
+ // This function implements the voting box to decide which input gets the right
+ // to actuate the system.
+
+ //Reset the maximum core frequency requested prior to recalculation.
+ g_amec->proc[0].core_max_freq = 0;
+
+ // PPB_FMAX
+ if(g_amec->proc[0].pwr_votes.ppb_fmax < l_chip_fmax)
+ {
+ l_chip_fmax = g_amec->proc[0].pwr_votes.ppb_fmax;
+ l_chip_reason = AMEC_VOTING_REASON_PPB;
+ l_kvm_throt_reason = POWERCAP; //gm025
+ }
+
+ // PMAX_CLIP_FREQ
+ if(g_amec->proc[0].pwr_votes.pmax_clip_freq < l_chip_fmax)
+ {
+ l_chip_fmax = g_amec->proc[0].pwr_votes.pmax_clip_freq;
+ l_chip_reason = AMEC_VOTING_REASON_PMAX;
+ l_kvm_throt_reason = POWER_SUPPLY_FAILURE; //gm025
+ }
+
+ //THERMALPROC.FREQ_REQUEST
+ //Thermal controller input based on processor temperature
+ if(g_amec->thermalproc.freq_request < l_chip_fmax)
+ {
+ l_chip_fmax = g_amec->thermalproc.freq_request;
+ l_chip_reason = AMEC_VOTING_REASON_PROC_THRM;
+ l_kvm_throt_reason = CPU_OVERTEMP; //gm025
+ }
+
+ // Controller request based on VRHOT signal from processor regulator
+ if(g_amec->vrhotproc.freq_request < l_chip_fmax)
+ {
+ l_chip_fmax = g_amec->vrhotproc.freq_request;
+ l_chip_reason = AMEC_VOTING_REASON_VRHOT_THRM;
+ l_kvm_throt_reason = CPU_OVERTEMP; //gm025
+ }
+
+ // CONN_OC_VOTE
+ if(g_amec->proc[0].pwr_votes.conn_oc_vote < l_chip_fmax)
+ {
+ l_chip_fmax = g_amec->proc[0].pwr_votes.conn_oc_vote;
+ l_chip_reason = AMEC_VOTING_REASON_CONN_OC;
+ l_kvm_throt_reason = OVERCURRENT; //gm025
+ }
+
+ for (k=0; k<MAX_NUM_CORES; k++)
+ {
+ if(CORE_PRESENT(k))
+ {
+ l_core_freq = l_chip_fmax;
+ l_core_reason = l_chip_reason;
+
+ // Disable DPS in KVM // @at019a
+ if(!G_sysConfigData.system_type.kvm)
+ {
+ l_part = amec_part_find_by_core(&g_amec->part_config, k);
+
+ // Check frequency request generated by DPS algorithms
+ if(g_amec->proc[0].core[k].core_perf.dps_freq_request < l_core_freq)
+ {
+ l_core_freq = g_amec->proc[0].core[k].core_perf.dps_freq_request;
+ l_core_reason = AMEC_VOTING_REASON_UTIL;
+ }
+
+ // Adjust frequency based on soft frequency boundaries
+ if(l_part != NULL)
+ {
+ if(l_core_freq < l_part->soft_fmin)
+ {
+ // Before enforcing a soft Fmin, make sure we don't
+ // have a thermal or power emergency
+ if(!(l_chip_reason & (AMEC_VOTING_REASON_PROC_THRM |
+ AMEC_VOTING_REASON_VRHOT_THRM |
+ AMEC_VOTING_REASON_PPB |
+ AMEC_VOTING_REASON_PMAX |
+ AMEC_VOTING_REASON_CONN_OC))) //gm025
+ {
+ l_core_freq = l_part->soft_fmin;
+ l_core_reason = AMEC_VOTING_REASON_SOFT_MIN;
+ }
+ }
+ else if(l_core_freq > l_part->soft_fmax)
+ {
+ l_core_freq = l_part->soft_fmax;
+ l_core_reason = AMEC_VOTING_REASON_SOFT_MAX;
+ }
+ }
+ }
+
+ if(CURRENT_MODE() == OCC_MODE_NOMINAL)
+ {
+ // PROC_PCAP_NOM_VOTE
+ if(g_amec->proc[0].pwr_votes.proc_pcap_nom_vote < l_core_freq)
+ {
+ l_core_freq = g_amec->proc[0].pwr_votes.proc_pcap_nom_vote;
+ l_core_reason = AMEC_VOTING_REASON_PWR;
+ l_kvm_throt_reason = POWERCAP; //gm025
+ }
+ }
+ else
+ {
+ // PROC_PCAP_VOTE
+ if(g_amec->proc[0].pwr_votes.proc_pcap_vote < l_core_freq)
+ {
+ l_core_freq = g_amec->proc[0].pwr_votes.proc_pcap_vote;
+ l_core_reason = AMEC_VOTING_REASON_PWR;
+ l_kvm_throt_reason = POWERCAP; //gm025
+ }
+ }
+
+ // Check IPS frequency request sent by Master OCC
+ if(g_amec->slv_ips_freq_request != 0)
+ {
+ if(g_amec->slv_ips_freq_request < l_core_freq)
+ {
+ l_core_freq = g_amec->slv_ips_freq_request;
+ l_core_reason = AMEC_VOTING_REASON_IPS;
+ }
+ }
+
+ // Override frequency with request from Master OCC
+ if(g_amec->foverride_enable)
+ {
+ if(g_amec->foverride != 0)
+ {
+ // Override the frequency on all cores if Master OCC sends
+ // a non-zero request
+ l_core_freq = g_amec->foverride;
+ l_core_reason = AMEC_VOTING_REASON_OVERRIDE;
+ }
+ }
+
+ //Make sure the frequency is not less then the system min
+ if(l_core_freq < g_amec->sys.fmin)
+ {
+ l_core_freq = g_amec->sys.fmin;
+ }
+
+ // Override frequency via Amester parameter interface
+ if (g_amec->proc[0].parm_f_override_enable &&
+ g_amec->proc[0].parm_f_override[k] > 0)
+ {
+ l_core_freq = g_amec->proc[0].parm_f_override[k];
+ l_core_reason = AMEC_VOTING_REASON_OVERRIDE_CORE;
+ }
+
+ // @wb004 -- If frequency has changed, set the flag
+ if ( (l_core_freq != g_amec->proc[0].core[k].f_request) ||
+ (l_core_freq != g_amec->sys.fmax))
+ {
+ l_freq_req_changed = TRUE;
+ }
+
+ //STORE core frequency and reason
+ g_amec->proc[0].core[k].f_request = l_core_freq;
+ g_amec->proc[0].core[k].f_reason = l_core_reason;
+
+ // Update the Amester parameter telling us the reason. Needed for
+ // parameter array.
+ g_amec->proc[0].parm_f_reason[k] = l_core_reason;
+
+ //@rt001a @at022c
+ //CURRENT_MODE() may be OCC_MODE_NOCHANGE because STATE change is processed
+ //before MODE change
+ if ((CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE) &&
+ (CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE_FP) &&
+ (CURRENT_MODE() != OCC_MODE_NOCHANGE) &&
+ (l_core_reason & NON_DPS_POWER_LIMITED))
+ {
+ G_non_dps_power_limited = TRUE;
+ }
+ else
+ {
+ G_non_dps_power_limited = FALSE;
+ }
+
+ // Update the sensor telling us what the requested frequency is
+ sensor_update( AMECSENSOR_ARRAY_PTR(FREQ250USP0C0,k),
+ (uint16_t) g_amec->proc[0].core[k].f_request); // @th017
+
+#if 0
+ /// TODO: This can be deleted if deemed useless
+ /// This trace that can be used to debug the voting
+ /// box an control loops. It will trace the reason why a
+ /// controller is lowering the freq, but will only do it once in a
+ /// row for the specific freq it wants to control to. It assumes
+ /// that all cores will be controlled to same freq.
+ if(l_chip_fmax != g_amec->sys.fmax){
+ static uint16_t L_trace = 0;
+ if(l_chip_fmax != L_trace){
+ L_trace = l_chip_fmax;
+ TRAC_INFO("Core: %d, Freq: %d, Reason: %d",k,l_core_freq,l_core_reason);
+ }
+ }
+#endif
+
+ if(l_core_freq > g_amec->proc[0].core_max_freq)
+ {
+ g_amec->proc[0].core_max_freq = l_core_freq;
+ }
+ }
+ else
+ {
+ l_core_freq = 0;
+ l_core_reason = 0;
+ }
+ }//End of for loop
+
+ // @wb004 -- Check if the frequency is going to be changing
+ if( l_freq_req_changed == TRUE )
+ {
+ G_time_until_freq_check = FREQ_CHG_CHECK_TIME;
+ }
+ else if (G_time_until_freq_check != 0)
+ {
+ G_time_until_freq_check--;
+ }
+
+ //convert POWERCAP reason to POWER_SUPPLY_FAILURE if ovs/failsafe is asserted -- gm025
+ if((l_kvm_throt_reason == POWERCAP) &&
+ (AMEC_INTF_GET_FAILSAFE() || AMEC_INTF_GET_OVERSUBSCRIPTION()))
+ {
+ l_kvm_throt_reason = POWER_SUPPLY_FAILURE;
+ }
+
+ //check if we need to update the throttle reason in homer -- gm025
+ if(G_sysConfigData.system_type.kvm &&
+ (l_kvm_throt_reason != G_amec_kvm_throt_reason))
+ {
+ //Notify dcom thread to update the table
+ G_amec_kvm_throt_reason = l_kvm_throt_reason;
+ ssx_semaphore_post(&G_dcomThreadWakeupSem);
+ }
+
+}
+
+// Function Specification
+//
+// Name: amec_slv_freq_smh
+//
+// Description: Slave OCC's frequency state machine.
+// This function will run every tick.
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_freq_smh(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t k = 0;
+ int8_t l_pstate = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ for (k=0; k<MAX_NUM_CORES; k++)
+ {
+ switch (g_amec->proc[0].core[k].f_sms)
+ {
+ case AMEC_CORE_FREQ_IDLE_STATE:
+ // Translate frequency request into a Pstate
+ l_pstate = proc_freq2pstate(g_amec->proc[0].core[k].f_request);
+
+ // Fall through
+ case AMEC_CORE_FREQ_PROCESS_STATE:
+ if(G_sysConfigData.system_type.kvm) //gm025
+ {
+ // update core bounds on kvm systems
+ proc_set_core_bounds(gpst_pmin(&G_global_pstate_table) + 1, (Pstate) l_pstate, k);
+ }
+ else
+ {
+ // update core pstate request on non-kvm systems
+ proc_set_core_pstate((Pstate) l_pstate, k);
+ }
+ break;
+ }
+ }
+
+}
+
+// Function Specification
+//
+// Name: amec_slv_freq_smh
+//
+// Description: Slave OCC's voting box that decides the memory speed request.
+// This function will run every tick.
+//
+//
+// Flow: 2-20-12 FN=amec_slv_mem_voting_box.odg
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_mem_voting_box(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT16 l_vote;
+ UINT8 l_reason;
+ static INT16 l_slew_step = AMEC_MEMORY_STEP_SIZE;
+ static bool L_throttle_traced = FALSE;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Start with max allowed speed
+ l_vote = AMEC_MEMORY_MAX_STEP;
+ l_reason = AMEC_MEM_VOTING_REASON_INIT;
+
+ // Check vote from Centaur thermal control loop
+ if (l_vote > g_amec->thermalcent.speed_request)
+ {
+ l_vote = g_amec->thermalcent.speed_request;
+ l_reason = AMEC_MEM_VOTING_REASON_CENT;
+ }
+
+ // Check vote from DIMM thermal control loop
+ if (l_vote > g_amec->thermaldimm.speed_request)
+ {
+ l_vote = g_amec->thermaldimm.speed_request;
+ l_reason = AMEC_MEM_VOTING_REASON_DIMM;
+ }
+
+ // Check if memory autoslewing is enabled - gm004
+ if (g_amec->mnfg_parms.mem_autoslew)
+ {
+ //check if we've reached the max setting and need to start going down
+ if(g_amec->mem_speed_request >= AMEC_MEMORY_MAX_STEP)
+ {
+ g_amec->mnfg_parms.mem_slew_counter++;
+ l_slew_step = -AMEC_MEMORY_STEP_SIZE;
+ }
+
+ //check if we've reached the min setting and need to start going up
+ else if(g_amec->mem_speed_request <= AMEC_MEMORY_MIN_STEP)
+ {
+ g_amec->mnfg_parms.mem_slew_counter++;
+ l_slew_step = AMEC_MEMORY_STEP_SIZE;
+ }
+
+ l_vote = g_amec->mem_speed_request + l_slew_step;
+ l_reason = AMEC_MEM_VOTING_REASON_SLEW;
+ }
+
+ // Store final vote and vote reason in g_amec
+ g_amec->mem_throttle_reason = l_reason;
+ g_amec->mem_speed_request = l_vote;
+
+ //trace changes in memory throttling -- gm016
+ if(l_reason != AMEC_MEM_VOTING_REASON_INIT)
+ {
+ if(!L_throttle_traced)
+ {
+ L_throttle_traced = TRUE;
+ TRAC_INFO("Memory is being throttled. reason[%d] vote[%d] cent_expired[0x%02x] dimm_expired[0x%02x]",
+ l_reason,
+ l_vote,
+ G_cent_temp_expired_bitmap,
+ G_dimm_temp_expired_bitmap);
+ }
+ }
+ else
+ {
+ if(L_throttle_traced)
+ {
+ L_throttle_traced = FALSE;
+ TRAC_INFO("Memory is no longer being throttled");
+ }
+ }
+ return;
+}
+
+// @rt001a
+// Function Specification
+//
+// Name: amec_slv_check_perf
+//
+// Description: Slave OCC's Detect and log degraded performance errors
+// This function will run every tick.
+//
+//
+// Flow: 4-16-13 FN=amec_slv_check_perf.odg
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_check_perf(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ static BOOLEAN l_prev_failsafe_state = FALSE;
+ static BOOLEAN l_prev_ovs_state = FALSE;
+ static BOOLEAN l_prev_pcap_state = FALSE;
+ static ERRL_SEVERITY l_pcap_sev = ERRL_SEV_PREDICTIVE;
+ static BOOLEAN l_throttle_traced = FALSE;
+ static uint64_t l_time = 0; //@rt003a
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // @wb004 -- Verify that cores are at proper frequency
+ amec_verify_pstate();
+
+ do
+ {
+ // was frequency limited by power ?
+ if ( G_non_dps_power_limited != TRUE )
+ {
+ if(l_throttle_traced)
+ {
+ TRAC_INFO("Frequency not limited by power algorithms anymore");
+ l_throttle_traced = FALSE;
+ }
+ // we are done break and return
+ break;
+ }
+
+ // frequency limited due to failsafe condition ?
+ if ( AMEC_INTF_GET_FAILSAFE() == TRUE )
+ {
+ if ( l_prev_failsafe_state == TRUE)
+ {
+ // we are done break and return
+ break;
+ }
+ else
+ {
+ // log this error ONLY ONCE per IPL
+ l_prev_failsafe_state = TRUE;
+
+ TRAC_ERR("Frequency limited due to failsafe condition(mode:%d, state:%d)",
+ CURRENT_MODE(), CURRENT_STATE()); // @at022c
+ l_throttle_traced = TRUE;
+ l_time = ssx_timebase_get(); //rt003a
+
+ // log error that calls out OVS procedure
+ // set error severity to RRL_SEV_PREDICTIVE
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_SLAVE_CHECK_PERFORMANCE
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 Previous FailSafe State
+ * @userdata4 ERC_AMEC_SLAVE_FAILSAFE_STATE
+ * @devdesc Frequency limited due to failsafe condition
+ */
+ errlHndl_t l_errl = createErrl(AMEC_SLAVE_CHECK_PERFORMANCE, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_AMEC_SLAVE_FAILSAFE_STATE,//Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity // @at020a
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_prev_failsafe_state, //userdata1
+ 0); //userdata2
+
+
+ addCalloutToErrl( l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_OVERSUBSCRIPTION,
+ ERRL_CALLOUT_PRIORITY_HIGH
+ );
+
+
+ // and sets the consolidate action flag
+ setErrlActions( l_errl, ERRL_ACTIONS_CONSOLIDATE_ERRORS );
+
+ // Commit Error
+ commitErrl(&l_errl);
+
+ // we are done lets break
+ break;
+ }
+ }
+
+
+ // frequency limited due to oversubscription condition ?
+ if ( AMEC_INTF_GET_OVERSUBSCRIPTION() == TRUE )
+ {
+ if ( l_prev_ovs_state == TRUE)
+ {
+ // we are done break and return
+ break;
+ }
+ else
+ {
+ // log this error ONLY ONCE per IPL
+ l_prev_ovs_state = TRUE;
+
+ TRAC_ERR("Frequency limited due to oversubscription condition(mode:%d, state:%d)",
+ CURRENT_MODE(), CURRENT_STATE()); // @at022c
+ l_throttle_traced = TRUE;
+ l_time = ssx_timebase_get(); //@rt003a
+
+ // log error that calls out OVS procedure
+ // set error severity to RRL_SEV_PREDICTIVE
+
+ // @wb003 -- Updated the RC to match the actual RC passed to createErrl()
+ /* @
+ * @errortype
+ * @moduleid AMEC_SLAVE_CHECK_PERFORMANCE
+ * @reasoncode OVERSUB_LIMIT_ALERT
+ * @userdata1 Previous OVS State
+ * @userdata4 ERC_AMEC_SLAVE_OVS_STATE
+ * @devdesc Frequency limited due to oversubscription condition
+ */
+ errlHndl_t l_errl = createErrl(AMEC_SLAVE_CHECK_PERFORMANCE, //modId
+ OVERSUB_LIMIT_ALERT, //reasoncode // @at020c
+ ERC_AMEC_SLAVE_OVS_STATE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity // @at020c
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_prev_ovs_state, //userdata1
+ 0); //userdata2
+
+
+ addCalloutToErrl( l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_OVERSUBSCRIPTION,
+ ERRL_CALLOUT_PRIORITY_HIGH
+ );
+
+
+ // and sets the consolidate action flag
+ setErrlActions( l_errl, ERRL_ACTIONS_CONSOLIDATE_ERRORS );
+
+ // Commit Error
+ commitErrl(&l_errl);
+
+ // we are done lets break
+ break;
+ }
+ }
+
+ uint16_t l_snrBulkPwr = AMECSENSOR_PTR(PWR250US)->sample; //@rt003a
+
+ // frequency limited due to system power cap condition ?
+ if (( l_snrBulkPwr > (G_sysConfigData.pcap.system_pcap - PDROP_THRESH) ) //@rt003c
+ &&
+ ( G_sysConfigData.pcap.current_pcap == 0 ))
+ {
+ if ( l_prev_pcap_state == TRUE)
+ {
+ // we are done break and return
+ break;
+ }
+ else
+ {
+ //@rt003c log this error ONLY ONCE per IPL
+ l_prev_pcap_state = TRUE;
+
+ TRAC_ERR("Frequency limited due to power cap condition(mode:%d, state:%d)",
+ CURRENT_MODE(), CURRENT_STATE()); // @at022c
+
+ TRAC_ERR("SnrBulkPwr %d > Sys Pcap %d ",l_snrBulkPwr,
+ G_sysConfigData.pcap.system_pcap ); //@rt003c @at022c
+
+ TRAC_ERR("SnrFanPwr %d, SnrIOPwr %d, SnrStoragePwr %d, SnrGpuPrw %d ",
+ AMECSENSOR_PTR(PWR250USFAN)->sample,
+ AMECSENSOR_PTR(PWR250USIO)->sample,
+ AMECSENSOR_PTR(PWR250USSTORE)->sample,
+ AMECSENSOR_PTR(PWR250USGPU)->sample );
+
+ TRAC_ERR("SnrProcPwr 0 %d, SnrProcPwr 1 %d, SnrProcPwr 2 %d, SnrProcPwr 3 %d",
+ g_amec->proc_snr_pwr[0],
+ g_amec->proc_snr_pwr[1],
+ g_amec->proc_snr_pwr[2],
+ g_amec->proc_snr_pwr[3] ); //@rt003a
+
+ TRAC_ERR("SnrMemPwr 0 %d, SnrMemPwr 1 %d, SnrMemPwr 2 %d, SnrMemPwr 3 %d",
+ g_amec->mem_snr_pwr[0],
+ g_amec->mem_snr_pwr[1],
+ g_amec->mem_snr_pwr[2],
+ g_amec->mem_snr_pwr[3] ); //@rt003a
+
+
+ l_throttle_traced = TRUE;
+ l_time = ssx_timebase_get();
+
+ // log error that calls out firmware and APSS procedure
+ // set error severity to l_pcap_sev
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_SLAVE_CHECK_PERFORMANCE
+ * @reasoncode PCAP_THROTTLE_POWER_LIMIT
+ * @userdata1 Current Sensor Bulk Power
+ * @userdata2 System PCAP
+ * @userdata4 ERC_AMEC_SLAVE_POWERCAP
+ * @devdesc Frequency limited due to PowerCap condition
+ */
+ errlHndl_t l_errl = createErrl(AMEC_SLAVE_CHECK_PERFORMANCE, //modId
+ PCAP_THROTTLE_POWER_LIMIT, //reasoncode @rt003c
+ ERC_AMEC_SLAVE_POWERCAP, //Extended reason code
+ l_pcap_sev, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_snrBulkPwr, //userdata1 @rt003c
+ G_sysConfigData.pcap.system_pcap);//userdata2 @rt003c
+
+
+ addCalloutToErrl( l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH
+ );
+
+ addCalloutToErrl( l_errl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.apss_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH
+ );
+
+
+ // and sets the consolidate action flag
+ setErrlActions( l_errl, ERRL_ACTIONS_CONSOLIDATE_ERRORS );
+
+ // then l_pcap_sev to informational
+ l_pcap_sev = ERRL_SEV_INFORMATIONAL;
+
+ // Commit Error
+ commitErrl(&l_errl);
+
+ // we are done lets break
+ break;
+ }
+ }
+
+ // trottle trace to every 3600 seconds (1hr = 3600000) @rt003c
+ if(!l_throttle_traced && ( DURATION_IN_MS_UNTIL_NOW_FROM(l_time) > 3600000 ) )
+ {
+ TRAC_INFO("Frequency power limited due to transient condition: PowerLimited=%x, FailSafe=%x, OverSubScription=%x CurrentBulkPwr=%x",
+ G_non_dps_power_limited, AMEC_INTF_GET_FAILSAFE(), AMEC_INTF_GET_OVERSUBSCRIPTION(), l_snrBulkPwr );
+ l_throttle_traced = TRUE;
+
+ l_time = ssx_timebase_get();
+ }
+ }
+ while( 0 );
+
+ return;
+}
+
+// @wb004
+// Verifies that each core is at the correct frequency
+// after they have had time to stabilize
+void amec_verify_pstate()
+{
+ uint8_t l_core = 0;
+ int8_t l_pstate_from_fmax = 0;
+ gpe_bulk_core_data_t * l_core_data_ptr;
+ pmc_pmsr_ffcdc_data_t l_pmc_pmsr_ffdc;
+ errlHndl_t l_err = NULL;
+
+ if ( (G_time_until_freq_check == 0) &&
+ ( CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE ) &&
+ ( CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE_FP ) &&
+ (!G_sysConfigData.system_type.kvm))
+ {
+ // Reset the counter
+ G_time_until_freq_check = FREQ_CHG_CHECK_TIME;
+
+ // Convert fmax to the corresponding pstate
+ l_pstate_from_fmax = proc_freq2pstate(g_amec->sys.fmax);
+
+ for( l_core = 0; l_core < MAX_NUM_CORES; l_core++ )
+ {
+ // If the core isn't present, skip it
+ if(!CORE_PRESENT(l_core))
+ {
+ l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core].value = 0;
+ continue;
+ }
+
+ // Get pointer to core data
+ l_core_data_ptr = proc_get_bulk_core_data_ptr(l_core);
+
+ // Get the core's pmsr data
+ l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core] = l_core_data_ptr->pcb_slave.pmsr;
+
+ // Verify that the core is running at the correct frequency
+ // If not, log an error
+ if( (l_pstate_from_fmax != l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core].fields.local_pstate_actual) &&
+ (l_pstate_from_fmax > l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core].fields.pv_min) &&
+ (l_err == NULL) )
+ {
+ TRAC_ERR("Frequency mismatch in core %d: actual_ps[%d] req_ps[%d] fmax[%d] mode[%d].",
+ l_core,
+ l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core].fields.local_pstate_actual,
+ l_pstate_from_fmax,
+ g_amec->sys.fmax,
+ CURRENT_MODE());
+
+ fill_pmc_ffdc_buffer(&l_pmc_pmsr_ffdc.pmc_ffcdc_data);
+
+ /* @
+ * @moduleid AMEC_VERIFY_FREQ_MID
+ * @reasonCode TARGET_FREQ_FAILURE
+ * @severity ERRL_SEV_PREDICTIVE
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc A core is not running at the expected frequency
+ */
+ l_err = createErrl( AMEC_VERIFY_FREQ_MID, // i_modId,
+ TARGET_FREQ_FAILURE, // i_reasonCode,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL, // tracDesc_t i_trace,
+ DEFAULT_TRACE_SIZE, // i_traceSz,
+ 0, // i_userData1,
+ 0); // i_userData2
+
+ //Add firmware callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ //Add processor callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ }
+ }
+
+ if( l_err != NULL)
+ {
+ //Add our register dump to the error log
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*) &l_pmc_pmsr_ffdc,
+ sizeof(l_pmc_pmsr_ffdc),
+ ERRL_USR_DTL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ REQUEST_RESET(l_err);
+ }
+ }
+}
+
+// @wb004 -- Moved from main.c
+// gm031
+// Fills in a pmc ffdc buffer with lots of PMC related OCI and SCOM registers
+void fill_pmc_ffdc_buffer(pmc_ffdc_data_t* i_ffdc_ptr)
+{
+ int i;
+ uint32_t l_rc, l_addr, l_data32;
+ uint64_t l_data64;
+
+ //clear out the entire buffer
+ memset(i_ffdc_ptr, 0, sizeof(pmc_ffdc_data_t));
+
+ //first get the OCI accessible FFDC data
+ for(i = 0; i < sizeof(G_pmc_ffdc_oci_addrs)/sizeof(uint32_t); i++)
+ {
+ l_addr = G_pmc_ffdc_oci_addrs[i];
+ if(l_addr)
+ {
+ l_data32 = in32(l_addr);
+ }
+ else
+ {
+ //leave an entry with all zero address and data for eye catcher
+ break;
+ }
+
+ //store address along with data for easier parsing
+ i_ffdc_ptr->oci_regs[i].addr = l_addr;
+ i_ffdc_ptr->oci_regs[i].data = l_data32;
+ }
+
+ //then get the SCOM accessible FFDC data
+ for(i = 0; i < sizeof(G_pmc_ffdc_scom_addrs)/sizeof(uint32_t); i++)
+ {
+ l_addr = G_pmc_ffdc_scom_addrs[i];
+ l_rc = (uint32_t)_getscom(l_addr, &l_data64, SCOM_TIMEOUT);
+ if(l_rc)
+ {
+ //indicate there was a scom failure in collecting the data
+ l_data64 = 0xFEEDB0B000000000ull;
+
+ //store rc in lower word
+ l_data64 |= l_rc;
+ }
+
+ //store address along with data for easier parsing
+ i_ffdc_ptr->scom_regs[i].addr = l_addr;
+ i_ffdc_ptr->scom_regs[i].data = l_data64;
+ }
+}
diff --git a/src/occ/amec/amec_freq.h b/src/occ/amec/amec_freq.h
new file mode 100755
index 0000000..b8e9e8e
--- /dev/null
+++ b/src/occ/amec/amec_freq.h
@@ -0,0 +1,186 @@
+/******************************************************************************
+// @file amec_freq.h
+// @brief AMEC frequency header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_freq_h amec_freq.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th015 thallet 08/03/2012 New file
+ * @gs001 gsilva 08/03/2012 New file
+ * @ry002 862116 ronda 12/06/2012 Added enum to store voting box reason codes
+ * @ry003 870734 ronda 02/20/2013 Thermal controller for memory
+ * @ry004 872358 ronda 02/27/2013 Added memory voting box
+ * @fk001 879727 fmkassem 04/16/2013 Power capping support.
+ * @gm004 892961 milesg 07/25/2013 Support memory auto slewing
+ * @rt001 897459 tapiar 08/21/2013 Update amec voting enums to a bitmaskSupport memory auto slewing
+ * @gs014 903552 gjsilva 10/22/2013 Support for Amester parameter interface
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @wb004 922138 wilbryan 04/03/2014 Ensure timely pstate completion
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef _AMEC_FREQ_H
+#define _AMEC_FREQ_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <ssx.h>
+#include "occ_sys_config.h"
+#include <ssx_app_cfg.h>
+#include <amec_smh.h>
+#include <mode.h>
+#include <errl.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+// >> gitprep
+extern const uint32_t G_pmc_ffdc_scom_addrs[4];
+extern const uint32_t G_pmc_ffdc_oci_addrs[29];
+// << gitprep
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define FREQ_CHG_CHECK_TIME 4000 // @wb004
+
+// This is used by the Frequency State Machine
+typedef enum
+{
+ AMEC_CORE_FREQ_IDLE_STATE = 0x00,
+ AMEC_CORE_FREQ_PROCESS_STATE = 0x01,
+}amec_freq_write_state_t;
+
+// This is reason code used by Voting box amec_slv_voting_box
+typedef enum
+{
+ // @rt001c
+ AMEC_VOTING_REASON_INIT = 0x00000000,
+ AMEC_VOTING_REASON_PHYP = 0x00000001,
+ AMEC_VOTING_REASON_PLPM = 0x00000002,
+ AMEC_VOTING_REASON_LEGACY = 0x00000004,
+ AMEC_VOTING_REASON_SOFT_MIN = 0x00000008,
+ AMEC_VOTING_REASON_SOFT_MAX = 0x00000010,
+ AMEC_VOTING_REASON_CORE_CAP = 0x00000020,
+ AMEC_VOTING_REASON_PROC_THRM = 0x00000040,
+ AMEC_VOTING_REASON_GXHB_THRM = 0x00000080,
+ AMEC_VOTING_REASON_VRHOT_THRM = 0x00000100,
+ AMEC_VOTING_REASON_OVER_CURRENT = 0x00000200,
+ AMEC_VOTING_REASON_OVERRIDE = 0x00000400,
+ AMEC_VOTING_REASON_CORE_GRP_MIN = 0x00000800,
+ AMEC_VOTING_REASON_PWR = 0x00001000, // @fk001a
+ AMEC_VOTING_REASON_PPB = 0x00002000,
+ AMEC_VOTING_REASON_PMAX = 0x00004000,
+ AMEC_VOTING_REASON_UTIL = 0x00008000,
+ AMEC_VOTING_REASON_CONN_OC = 0x00010000,
+ AMEC_VOTING_REASON_OVERRIDE_CORE = 0x00020000,
+ AMEC_VOTING_REASON_IPS = 0x00040000,
+}amec_freq_voting_reason_t;
+
+// rt001a
+#define NON_DPS_POWER_LIMITED ( AMEC_VOTING_REASON_PWR | \
+ AMEC_VOTING_REASON_PPB | \
+ AMEC_VOTING_REASON_PMAX \
+ )
+
+
+// rt001a
+extern BOOLEAN G_non_dps_power_limited;
+
+// This is reason code used by Voting box amec_slv_mem_voting_box
+typedef enum
+{
+ AMEC_MEM_VOTING_REASON_INIT = 0,
+ AMEC_MEM_VOTING_REASON_CENT = 1,
+ AMEC_MEM_VOTING_REASON_DIMM = 2,
+ AMEC_MEM_VOTING_REASON_SLEW = 3, //gm004
+}amec_mem_voting_reason_t;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+#define PMC_FFDC_OCI_ADDRS_SIZE sizeof(G_pmc_ffdc_oci_addrs) // @wb004
+#define PMC_FFDC_SCOM_ADDRS_SIZE sizeof(G_pmc_ffdc_scom_addrs) // @wb004
+
+// @wb004 -- Moved the following three structures for accessibility
+
+// scom ffdc format
+typedef struct __attribute__ ((packed))
+{
+ uint32_t addr;
+ uint64_t data;
+} pmc_ffdc_scom_entry_t;
+
+// OCI ffdc format
+typedef struct
+{
+ uint32_t addr;
+ uint32_t data;
+} pmc_ffdc_oci_entry_t;
+
+//PMC FFDC format for user detail section of error log -- gm031
+typedef struct
+{
+ pmc_ffdc_oci_entry_t oci_regs[PMC_FFDC_OCI_ADDRS_SIZE/sizeof(uint32_t)];
+ pmc_ffdc_scom_entry_t scom_regs[PMC_FFDC_SCOM_ADDRS_SIZE/sizeof(uint32_t)];
+} pmc_ffdc_data_t;
+
+// @wb004
+typedef struct
+{
+ pcbs_power_management_status_reg_t data[MAX_NUM_CORES];
+} pmsr_ffdc_data_t;
+
+// @wb004
+typedef struct
+{
+ pmc_ffdc_data_t pmc_ffcdc_data;
+ pmsr_ffdc_data_t pmsr_ffdc_data;
+} pmc_pmsr_ffcdc_data_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void fill_pmc_ffdc_buffer(pmc_ffdc_data_t* i_ffdc_ptr); // @wb004
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Used to set the freq range that amec can control between.
+errlHndl_t amec_set_freq_range(const OCC_MODE i_mode);
+
+// Voting box for handling slave freq votes
+void amec_slv_voting_box(void);
+
+// Amec Frequency State Machine
+void amec_slv_freq_smh(void);
+
+// Voting box for handling slave memory freq votes
+void amec_slv_mem_voting_box(void);
+
+// Amec Detect and log degraded performance errors
+void amec_slv_check_perf(void);
+
+// Verifies that each core is at the correct frequency
+void amec_verify_pstate();
+
+
+#endif
+
diff --git a/src/occ/amec/amec_health.c b/src/occ/amec/amec_health.c
new file mode 100755
index 0000000..406de58
--- /dev/null
+++ b/src/occ/amec/amec_health.c
@@ -0,0 +1,1037 @@
+/******************************************************************************
+// @file amec_health.c
+// @brief Health monitor for OCC firmware.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section amec_health_c amec_health.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @gs012 903325 gjsilva 09/26/2013 Created
+ * 903325 gjsilva 10/24/2013 Minor changes from code review
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gm015 907601 milesg 12/06/2013 L4 Bank Delete circumvention and centaur i2c recovery
+ * @gm017 909636 milesg 12/17/2013 Memory fan control
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ * @gm028 911670 milesg 02/27/2014 Fixed compile fails from stradale
+ * @gs028 917695 gjsilva 03/04/2014 Check if cores are in a sleep state
+ * @gm038 926761 milesg 05/16/2014 Centaur temp timeout not logged
+ * @gm039 922963 milesg 05/28/2014 Fixed trace
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "amec_health.h"
+#include "amec_sys.h"
+#include "amec_service_codes.h"
+#include "occ_service_codes.h"
+#include <centaur_data.h>
+#include <thrm_thread.h>
+#include <proc_data.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern thrm_fru_data_t G_thrm_fru_data[DATA_FRU_MAX];
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Have we already called out the dimm for overtemp (bitmap of dimms)?
+cent_sensor_flags_t G_dimm_overtemp_logged_bitmap = {0};
+
+// Have we already called out the dimm for timeout (bitmap of dimms)?
+cent_sensor_flags_t G_dimm_timeout_logged_bitmap = {0};
+
+// Are any dimms currently in the timedout state (bitmap of centaurs)?
+// Note: this only tells you which centaur, not which dimm.
+uint8_t G_dimm_temp_expired_bitmap = 0;
+
+// Have we already called out the centaur for timeout (bitmap of centaurs)?
+uint8_t G_cent_timeout_logged_bitmap = 0;
+
+// Have we already called out the centaur for overtemp (bitmap of centaurs)?
+uint8_t G_cent_overtemp_logged_bitmap = 0;
+
+// Are any dimms currently in the timedout state (bitmap of centaurs)?
+uint8_t G_cent_temp_expired_bitmap = 0;
+
+// Array to store the update tag of each core's temperature sensor
+uint32_t G_core_temp_update_tag[MAX_NUM_CORES] = {0};
+
+//*************************************************************************
+// Function Declarations
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+uint64_t amec_mem_get_huid(uint8_t i_cent, uint8_t i_dimm)
+{
+ uint64_t l_huid;
+
+ if(i_dimm == 0xff)
+ {
+ //we're being asked for a centaur huid
+ l_huid = G_sysConfigData.centaur_huids[i_cent];
+ }
+ else
+ {
+ //we're being asked for a dimm huid
+ l_huid = G_sysConfigData.dimm_huids[i_cent][i_dimm];
+ if(!l_huid)
+ {
+ //if we don't have a valid dimm huid, use the
+ //centaur huid.
+ //FIXME: this will not work for ISDIMMS.
+ l_huid = G_sysConfigData.centaur_huids[i_cent];
+ }
+ }
+ return l_huid;
+}
+
+//If i_dimm is 0xff it is assumed that the caller wishes to
+//mark the centaur as being logged. Otherwise, it is assumed
+//that the dimm should be marked.
+void amec_mem_mark_logged(uint8_t i_cent,
+ uint8_t i_dimm,
+ uint8_t* i_clog_bitmap,
+ uint8_t* i_dlog_bitmap)
+{
+ if(i_dimm == 0xff)
+ {
+ //mark the centaur as being called out.
+ *i_clog_bitmap |= CENTAUR0_PRESENT_MASK >> i_cent;
+ }
+ else
+ {
+ //mark the dimm as being called out.
+ *i_dlog_bitmap |= DIMM_SENSOR0 >> i_dimm;
+ }
+}
+
+void amec_health_check_dimm_temp()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_ot_error, l_cur_temp, l_max_temp;
+ sensor_t *l_sensor;
+ uint32_t l_cent, l_dimm;
+ uint32_t l_callouts_count = 0;
+ uint8_t l_new_callouts;
+ uint64_t l_huid;
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Check to see if any dimms have reached the error temperature that
+ // haven't been called out already
+ if(G_dimm_overtemp_bitmap.bigword == G_dimm_overtemp_logged_bitmap.bigword)
+ {
+ return;
+ }
+
+ l_ot_error = g_amec->thermaldimm.ot_error;
+ l_sensor = getSensorByGsid(TEMP2MSDIMM);
+ l_cur_temp = l_sensor->sample;
+ l_max_temp = l_sensor->sample_max;
+ TRAC_ERR("amec_health_check_dimm_temp: DIMM reached error temp[%d]. cur_max[%d], hist_max[%d]",
+ l_ot_error,
+ l_cur_temp,
+ l_max_temp);
+
+ //iterate over all centaurs
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+ //only callout a dimm if it hasn't been called out already
+ l_new_callouts = G_dimm_overtemp_bitmap.bytes[l_cent] ^
+ G_dimm_overtemp_logged_bitmap.bytes[l_cent];
+
+ //skip to next centaur if no new callouts for this one
+ if(!l_new_callouts)
+ {
+ continue;
+ }
+
+ //find the dimm(s) that need to be called out behind this centaur
+ for(l_dimm = 0; l_dimm < NUM_DIMMS_PER_CENTAUR; l_dimm++)
+ {
+ if(!(l_new_callouts & (DIMM_SENSOR0 >> l_dimm)))
+ {
+ continue;
+ }
+
+ l_huid = amec_mem_get_huid(l_cent, l_dimm);
+
+ amec_mem_mark_logged(l_cent,
+ l_dimm,
+ &G_cent_overtemp_logged_bitmap,
+ &G_dimm_overtemp_logged_bitmap.bytes[l_cent]);
+
+ //If we don't have an error log for the callout, create one
+ if(!l_err)
+ {
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_DIMM_TEMP
+ * @reasoncode DIMM_ERROR_TEMP
+ * @userdata1 Maximum dimm temperature
+ * @userdata2 Dimm temperature threshold
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Memory DIMM(s) exceeded maximum safe
+ * temperature.
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_DIMM_TEMP, //modId
+ DIMM_ERROR_TEMP, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_max_temp, //userdata1
+ l_ot_error); //userdata2
+
+ // Callout the "over temperature" procedure
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_OVER_TEMPERATURE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ l_callouts_count = 1;
+ }
+
+ // Callout dimm
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ l_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ l_callouts_count++;
+
+ //If we've reached the max # of callouts for an error log
+ //commit the error log
+ if(l_callouts_count == ERRL_MAX_CALLOUTS)
+ {
+ commitErrl(&l_err);
+ }
+
+ //If we found all of the callouts for this centaur, go to the next one
+ if(!l_new_callouts)
+ {
+ break;
+ }
+ }//iterate over dimms
+ }//iterate over centaurs
+
+ if(l_err)
+ {
+ commitErrl(&l_err);
+ }
+}
+
+void amec_health_check_cent_temp()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_ot_error, l_cur_temp, l_max_temp;
+ sensor_t *l_sensor;
+ uint32_t l_cent;
+ uint32_t l_callouts_count = 0;
+ uint8_t l_new_callouts;
+ uint64_t l_huid;
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Check to see if any centaurs have reached the error temperature that
+ // haven't been called out already
+ l_new_callouts = G_cent_overtemp_bitmap ^ G_cent_overtemp_logged_bitmap;
+ if(!l_new_callouts)
+ {
+ return;
+ }
+
+ l_ot_error = g_amec->thermalcent.ot_error;
+ l_sensor = getSensorByGsid(TEMP2MSCENT);
+ l_cur_temp = l_sensor->sample;
+ l_max_temp = l_sensor->sample_max;
+ TRAC_ERR("amec_health_check_cent_temp: Centaur reached error temp[%d]. cur_max[%d], hist_max[%d] bitmap[0x%02X]",
+ l_ot_error,
+ l_cur_temp,
+ l_max_temp,
+ l_new_callouts);
+
+ //find the centaur(s) that need to be called out
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+ if(!(l_new_callouts & (CENTAUR0_PRESENT_MASK >> l_cent)))
+ {
+ continue;
+ }
+
+ l_huid = amec_mem_get_huid(l_cent, 0xff);
+
+ amec_mem_mark_logged(l_cent,
+ 0xff,
+ &G_cent_overtemp_logged_bitmap,
+ &G_dimm_overtemp_logged_bitmap.bytes[l_cent]);
+
+ //If we don't have an error log for the callout, create one
+ if(!l_err)
+ {
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_CENT_TEMP
+ * @reasoncode CENT_ERROR_TEMP
+ * @userdata1 Maximum centaur temperature
+ * @userdata2 Centaur temperature threshold
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Centaur memory controller(s) exceeded maximum safe
+ * temperature.
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_CENT_TEMP, //modId
+ CENT_ERROR_TEMP, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_max_temp, //userdata1
+ l_ot_error); //userdata2
+
+ // Callout the "over temperature" procedure
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_OVER_TEMPERATURE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ l_callouts_count = 1;
+ }
+
+ // Callout centaur
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ l_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ l_callouts_count++;
+
+ //If we've reached the max # of callouts for an error log
+ //commit the error log
+ if(l_callouts_count == ERRL_MAX_CALLOUTS)
+ {
+ commitErrl(&l_err);
+ }
+
+ }//iterate over centaurs
+
+ if(l_err)
+ {
+ commitErrl(&l_err);
+ }
+}
+
+void amec_health_check_dimm_timeout()
+{
+ static cent_sensor_flags_t L_temp_update_bitmap_prev = {0};
+ cent_sensor_flags_t l_need_inc, l_need_clr, l_temp_update_bitmap;
+ uint8_t l_dimm, l_cent;
+ fru_temp_t* l_fru;
+ errlHndl_t l_err = NULL;
+ uint32_t l_callouts_count = 0;
+ uint64_t l_huid;
+ static bool L_ran_once = FALSE;
+
+ do
+ {
+ //For every dimm sensor there are 3 cases to consider
+ //
+ //1) sensor is enabled and not updated (need to increment timer and check for timeout)
+ //2) sensor is enabled and updated but wasn't updated on previous check (need to clear timer)
+ //3) sensor is enabled and updated and was updated on previous check (do nothing)
+
+ //Grab snapshot of G_dimm_temp_updated_bitmap and clear it
+ l_temp_update_bitmap.bigword = G_dimm_temp_updated_bitmap.bigword;
+ G_dimm_temp_updated_bitmap.bigword = 0;
+
+ //check if we need to increment any timers (haven't been updated in the last second)
+ l_need_inc.bigword = G_cent_enabled_sensors.bigword & ~l_temp_update_bitmap.bigword;
+
+ //check if we need to clear any timers (updated now but not updated previously)
+ l_need_clr.bigword = l_temp_update_bitmap.bigword & ~L_temp_update_bitmap_prev.bigword;
+
+ //save off the previous bitmap of updated sensors for next time
+ L_temp_update_bitmap_prev.bigword = l_temp_update_bitmap.bigword;
+
+ //only go further if we actually have work to do here.
+ if(!l_need_inc.bigword && !l_need_clr.bigword)
+ {
+ //nothing to do
+ break;
+ }
+
+
+ //iterate across all centaurs incrementing dimm sensor timers as needed
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+ //any dimm timers behind this centaur need incrementing?
+ if(!l_need_inc.bytes[l_cent])
+ {
+ //all dimm sensors were updated for this centaur. Clear the dimm timeout bit for this centaur.
+ if(G_dimm_temp_expired_bitmap & (CENTAUR0_PRESENT_MASK >> l_cent))
+ {
+ G_dimm_temp_expired_bitmap &= ~(CENTAUR0_PRESENT_MASK >> l_cent);
+ TRAC_INFO("All dimm sensors for centaur %d have been updated", l_cent);
+ }
+ continue;
+ }
+
+ //There's at least one dimm requiring an increment, find the dimm
+ for(l_dimm = 0; l_dimm < NUM_DIMMS_PER_CENTAUR; l_dimm++)
+ {
+ //not this one, go to next one
+ if(!(l_need_inc.bytes[l_cent] & (DIMM_SENSOR0 >> l_dimm)))
+ {
+ continue;
+ }
+
+ //we found one.
+ l_fru = &g_amec->proc[0].memctl[l_cent].centaur.dimm_temps[l_dimm];
+
+ //increment timer
+ l_fru->sample_age++;
+
+ //handle wrapping
+ if(!l_fru->sample_age)
+ {
+ l_fru->sample_age = -1;
+ }
+
+ //info trace each transition to not having a new temperature
+ if(l_fru->sample_age == 1)
+ {
+ TRAC_INFO("Failed to read dimm temperature on cent[%d] dimm[%d] temp[%d] flags[0x%02X]",
+ l_cent, l_dimm, l_fru->cur_temp, l_fru->flags);
+ }
+
+ //check if the temperature reading is still useable
+ if(g_amec->thermaldimm.temp_timeout == 0xff ||
+ l_fru->sample_age < g_amec->thermaldimm.temp_timeout)
+ {
+ continue;
+ }
+
+ //temperature has expired. Notify control algorithms which centaur.
+ if(!(G_dimm_temp_expired_bitmap & (CENTAUR0_PRESENT_MASK >> l_cent)))
+ {
+ G_dimm_temp_expired_bitmap |= CENTAUR0_PRESENT_MASK >> l_cent;
+ TRAC_ERR("Timed out reading dimm temperature sensor on cent %d.",
+ l_cent);
+ }
+
+ //If we've already logged an error for this FRU go to the next one.
+ if(G_dimm_timeout_logged_bitmap.bytes[l_cent] & (DIMM_SENSOR0 >> l_dimm))
+ {
+ continue;
+ }
+
+ TRAC_ERR("Timed out reading dimm temperature on cent[%d] dimm[%d] temp[%d] flags[0x%02X]",
+ l_cent, l_dimm, l_fru->cur_temp, l_fru->flags);
+
+ if(!l_err)
+ {
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_DIMM_TIMEOUT
+ * @reasoncode FRU_TEMP_TIMEOUT
+ * @userdata1 timeout value in seconds
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to read a memory DIMM temperature
+ *
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_DIMM_TIMEOUT, //modId
+ FRU_TEMP_TIMEOUT, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ g_amec->thermaldimm.temp_timeout, //userdata1
+ 0); //userdata2
+
+ l_callouts_count = 0;
+ }
+
+ //Get the HUID for the dimm
+ l_huid = amec_mem_get_huid(l_cent, l_dimm);
+
+ // Callout dimm
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ l_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ l_callouts_count++;
+
+ //If we've reached the max # of callouts for an error log
+ //commit the error log
+ if(l_callouts_count == ERRL_MAX_CALLOUTS)
+ {
+ commitErrl(&l_err);
+ }
+
+ //Mark dimm as logged so we don't log it more than once
+ amec_mem_mark_logged(l_cent,
+ l_dimm,
+ &G_cent_timeout_logged_bitmap,
+ &G_dimm_timeout_logged_bitmap.bytes[l_cent]);
+ } //iterate over all dimms
+
+ } //iterate over all centaurs
+
+ if(l_err)
+ {
+ commitErrl(&l_err);
+ }
+
+ //skip clearing if no dimms need it
+ if(!l_need_clr.bigword)
+ {
+ break;
+ }
+
+ //iterate across all centaurs clearing dimm sensor timers as needed
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+
+ if(!l_need_clr.bytes[l_cent])
+ {
+ continue;
+ }
+
+ //iterate over all dimms
+ for(l_dimm = 0; l_dimm < NUM_DIMMS_PER_CENTAUR; l_dimm++)
+ {
+ //not this one, go to next one
+ if(!(l_need_clr.bytes[l_cent] & (DIMM_SENSOR0 >> l_dimm)))
+ {
+ continue;
+ }
+
+ //we found one.
+ l_fru = &g_amec->proc[0].memctl[l_cent].centaur.dimm_temps[l_dimm];
+
+ //clear timer
+ l_fru->sample_age = 0;
+
+ //info trace each time we recover
+ if(L_ran_once)
+ {
+ TRAC_INFO("DIMM temperature collection has resumed on cent[%d] dimm[%d] temp[%d]",
+ l_cent, l_dimm, l_fru->cur_temp);
+ }
+
+ }//iterate over all dimms
+
+ }//iterate over all centaurs
+ }while(0);
+ L_ran_once = TRUE;
+ G_thrm_fru_data[DATA_FRU_DIMM].read_failure = G_dimm_temp_expired_bitmap; //gm017
+}
+
+
+void amec_health_check_cent_timeout()
+{
+ static uint8_t L_temp_update_bitmap_prev = 0;
+ uint8_t l_need_inc, l_need_clr, l_temp_update_bitmap;
+ uint8_t l_cent;
+ fru_temp_t* l_fru;
+ errlHndl_t l_err = NULL;
+ uint32_t l_callouts_count = 0;
+ uint64_t l_huid;
+ static bool L_ran_once = FALSE;
+
+ do
+ {
+ //For every centaur sensor there are 3 cases to consider
+ //
+ //1) centaur is present and not updated (need to increment timer and check for timeout)
+ //2) centaur is present and updated but wasn't updated on previous check (need to clear timer)
+ //3) centaur is present and updated and was updated on previous check (do nothing)
+
+
+ //Grab snapshot of G_cent_temp_update_bitmap and clear it
+ l_temp_update_bitmap = G_cent_temp_updated_bitmap;
+ G_cent_temp_updated_bitmap = 0;
+
+ //check if we need to increment any timers
+ l_need_inc = G_present_centaurs & ~l_temp_update_bitmap;
+
+ //check if we need to clear any timers
+ l_need_clr = l_temp_update_bitmap & ~L_temp_update_bitmap_prev;
+
+ //only go further if we actually have work to do here.
+ if(!l_need_inc && !l_need_clr)
+ {
+ //nothing to do
+ break;
+ }
+
+ //save off the previous bitmap of updated sensors
+ L_temp_update_bitmap_prev = l_temp_update_bitmap;
+
+ //iterate across all centaurs incrementing timers as needed
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+ //does this centaur timer need incrementing?
+ if(!(l_need_inc & (CENTAUR0_PRESENT_MASK >> l_cent)))
+ {
+ //temperature was updated for this centaur. Clear the timeout bit for this centaur.
+ if(G_cent_temp_expired_bitmap & (CENTAUR0_PRESENT_MASK >> l_cent))
+ {
+ G_cent_temp_expired_bitmap &= ~(CENTAUR0_PRESENT_MASK >> l_cent);
+ TRAC_INFO("centaur %d temps have been updated", l_cent);
+ }
+ continue;
+ }
+
+ //This centaur requires an increment
+ l_fru = &g_amec->proc[0].memctl[l_cent].centaur.centaur_hottest;
+
+ //increment timer
+ l_fru->sample_age++;
+
+ //handle wrapping
+ if(!l_fru->sample_age)
+ {
+ l_fru->sample_age = -1;
+ }
+
+ //info trace each transition to not having a new temperature
+ if(l_fru->sample_age == 1)
+ {
+ TRAC_INFO("Failed to read centaur temperature on cent[%d] temp[%d] flags[0x%02X]", //gm039
+ l_cent, l_fru->cur_temp, l_fru->flags);
+ }
+
+ //check if the temperature reading is still useable
+ if(g_amec->thermalcent.temp_timeout == 0xff ||
+ l_fru->sample_age < g_amec->thermalcent.temp_timeout)
+ {
+ continue;
+ }
+
+ //temperature has expired. Notify control algorithms which centaur.
+ if(!(G_cent_temp_expired_bitmap & (CENTAUR0_PRESENT_MASK >> l_cent)))
+ {
+ G_cent_temp_expired_bitmap |= CENTAUR0_PRESENT_MASK >> l_cent;
+ TRAC_ERR("Timed out reading centaur temperature sensor on cent %d",
+ l_cent);
+ }
+
+ //If we've already logged an error for this FRU go to the next one.
+ if(G_cent_timeout_logged_bitmap & (CENTAUR0_PRESENT_MASK >> l_cent)) //gm038
+ {
+ continue;
+ }
+
+ TRAC_ERR("Timed out reading centaur temperature on cent[%d] temp[%d] flags[0x%02X]",
+ l_cent, l_fru->cur_temp, l_fru->flags);
+
+ if(!l_err)
+ {
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_CENT_TIMEOUT
+ * @reasoncode FRU_TEMP_TIMEOUT
+ * @userdata1 timeout value in seconds
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to read a centaur memory controller
+ * temperature
+ *
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_CENT_TIMEOUT, //modId
+ FRU_TEMP_TIMEOUT, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ g_amec->thermalcent.temp_timeout, //userdata1
+ 0); //userdata2
+
+ l_callouts_count = 0;
+ }
+
+ //Get the HUID for the centaur
+ l_huid = amec_mem_get_huid(l_cent, 0xff);
+
+ // Callout centaur
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ l_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ l_callouts_count++;
+
+ //If we've reached the max # of callouts for an error log
+ //commit the error log
+ if(l_callouts_count == ERRL_MAX_CALLOUTS)
+ {
+ commitErrl(&l_err);
+ }
+
+ //Mark centaur as logged so we don't log it more than once
+ amec_mem_mark_logged(l_cent,
+ 0xff,
+ &G_cent_timeout_logged_bitmap,
+ &G_dimm_timeout_logged_bitmap.bytes[l_cent]);
+ } //iterate over all centaurs
+
+ if(l_err)
+ {
+ commitErrl(&l_err);
+ }
+
+ //skip clearing timers if no centaurs need it
+ if(!l_need_clr)
+ {
+ break;
+ }
+
+ //iterate across all centaurs clearing timers as needed
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+ //not this one, go to next one
+ if(!(l_need_clr & (CENTAUR0_PRESENT_MASK >> l_cent)))
+ {
+ continue;
+ }
+
+ //we found one.
+ l_fru = &g_amec->proc[0].memctl[l_cent].centaur.centaur_hottest;
+
+ //clear timer
+ l_fru->sample_age = 0;
+
+ //info trace each time we recover
+ if(L_ran_once)
+ {
+ TRAC_INFO("centaur temperature collection has resumed on cent[%d] temp[%d]",
+ l_cent, l_fru->cur_temp);
+ }
+
+ }//iterate over all centaurs
+ }while(0);
+ L_ran_once = TRUE;
+ G_thrm_fru_data[DATA_FRU_CENTAUR].read_failure = G_cent_temp_expired_bitmap; //gm017
+}
+
+
+// Function Specification
+//
+// Name: amec_health_check_proc_temp
+//
+// Description: This function checks if the proc temperature has
+// exceeded the error temperature as define in data format 0x13.
+//
+//
+// Flow: 10/18/13 FN=amec_health_check_proc_temp.odg
+//
+// End Function Specification
+void amec_health_check_proc_temp()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_ot_error;
+ static uint32_t l_error_count = 0;
+ static BOOLEAN l_ot_error_logged = FALSE;
+ sensor_t *l_sensor;
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ // Get TEMP2MSP0PEAK sensor, which is hottest core temperature
+ // in OCC processor
+ l_sensor = getSensorByGsid(TEMP2MSP0PEAK);
+ l_ot_error = g_amec->thermalproc.ot_error;
+
+ // Check to see if we exceeded our error temperature
+ if (l_sensor->sample > l_ot_error)
+ {
+ // Increment the error counter for this FRU
+ l_error_count++;
+
+ // Trace and log error the first time this occurs
+ if (l_error_count == AMEC_HEALTH_ERROR_TIMER)
+ {
+ // Have we logged an OT error for this FRU already?
+ if (l_ot_error_logged == TRUE)
+ {
+ break;
+ }
+
+ l_ot_error_logged = TRUE;
+
+ TRAC_ERR("amec_health_check_error_temp: processor has exceeded OT error! temp[%u] ot_error[%u]",
+ l_sensor->sample,
+ l_ot_error);
+
+ // Log an OT error
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_PROC_TEMP
+ * @reasoncode PROC_ERROR_TEMP
+ * @userdata1 0
+ * @userdata2 Fru peak temperature sensor
+ * @devdesc Processor FRU has reached error temperature
+ * threshold and is called out in this error log.
+ *
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_PROC_TEMP,
+ PROC_ERROR_TEMP,
+ ERC_AMEC_PROC_ERROR_OVER_TEMPERATURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ 0,
+ l_sensor->sample_max);
+
+ // Callout the Ambient procedure
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_OVER_TEMPERATURE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // Callout to processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ // Commit Error
+ commitErrl(&l_err);
+ }
+ }
+ else
+ {
+ // Trace that we have now dropped below the error threshold
+ if (l_error_count >= AMEC_HEALTH_ERROR_TIMER)
+ {
+ TRAC_INFO("amec_health_check_proc_temp: We have dropped below error threshold for processors. error_count[%u]",
+ l_error_count);
+ }
+
+ // Reset the error counter for this FRU
+ l_error_count = 0;
+ }
+ }while (0);
+
+}
+
+// Function Specification
+//
+// Name: amec_health_check_proc_temp_timeout
+//
+// Description: This function checks if OCC has failed to read the processor
+// temperature and if it has exceeded the maximum allowed number of retries.
+//
+//
+// End Function Specification
+void amec_health_check_proc_timeout()
+{
+
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ sensor_t *l_sensor = NULL;
+ BOOLEAN l_core_fail_detected = FALSE;
+ static uint32_t L_read_fail_cnt = 0;
+ uint8_t i = 0;
+ uint8_t l_bad_core_index = 0;
+ gpe_bulk_core_data_t *l_core_data_ptr = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ for(i=0; i<MAX_NUM_CORES; i++)
+ {
+ if(!CORE_PRESENT(i))
+ {
+ // If this core is not present, move on
+ continue;
+ }
+
+ // Check if this core's temperature sensor has been updated
+ l_sensor = AMECSENSOR_ARRAY_PTR(TEMP2MSP0C0,i);
+ if (l_sensor->update_tag == G_core_temp_update_tag[i])
+ {
+ // If the update tag is not changing, then this core's
+ // temperature sensor is not being updated.
+ l_core_fail_detected = TRUE;
+ l_bad_core_index = i;
+ }
+
+ // Take a snapshot of the update tag
+ G_core_temp_update_tag[i] = l_sensor->update_tag;
+ }
+
+ // Have we found at least one core that has reading failures?
+ if(!l_core_fail_detected)
+ {
+ // We were able to read all cores' temperature sensors so clear our
+ // counter
+ L_read_fail_cnt = 0;
+ }
+ else
+ {
+ // We've failed to read a core's temperature sensor so increment
+ // our counter
+ L_read_fail_cnt++;
+
+ // Check if we have reached the maximum read time allowed
+ if((L_read_fail_cnt == g_amec->thermalproc.temp_timeout) &&
+ (g_amec->thermalproc.temp_timeout != 0xFF))
+ {
+ TRAC_ERR("Timed out reading processor temperature on core_index[%u]",
+ l_bad_core_index);
+
+ // Get pointer to core data
+ l_core_data_ptr = proc_get_bulk_core_data_ptr(l_bad_core_index);
+
+ // Trace some critical registers to understand this error better
+ TRAC_ERR("OHA_Status_Reg[0x%08X] PM_State_Hist_Reg[0x%08X]",
+ l_core_data_ptr->oha.oha_ro_status_reg.words.low_order,
+ l_core_data_ptr->pcb_slave.pm_history.words.high_order);
+ TRAC_ERR("SensorV0[0x%016X] SensorV1[0x%016X]",
+ l_core_data_ptr->dts_cpm.sensors_v0.value,
+ l_core_data_ptr->dts_cpm.sensors_v1.value);
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_PROC_TIMEOUT
+ * @reasoncode PROC_TEMP_TIMEOUT
+ * @userdata1 timeout value in seconds
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to read processor temperature.
+ *
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_PROC_TIMEOUT, //modId
+ PROC_TEMP_TIMEOUT, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ g_amec->thermalproc.temp_timeout, //userdata1
+ 0); //userdata2
+
+ // Callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ // Commit error log and request reset
+ REQUEST_RESET(l_err);
+ }
+ }
+ }while(0);
+}
+
+// Function Specification
+//
+// Name: amec_health_check_proc_vrhot
+//
+// Description: This function checks if VRHOT signal from processor regulator
+// has been asserted. The VRHOT signal is actually derived in firmware: if
+// VR_FAN signal is assserted and the 'fans_full_speed' GPIO is ON, then OCC
+// will considered VR_HOT as being asserted.
+//
+// End Function Specification
+void amec_health_check_proc_vrhot()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ static BOOLEAN L_error_logged = FALSE;
+ sensor_t *l_sensor;
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Get VRHOT50USPROC sensor
+ l_sensor = getSensorByGsid(VRHOT250USPROC);
+
+ // Check to see if we have exceeded our ERROR_COUNT
+ if(l_sensor->sample >= g_amec->vrhotproc.setpoint)
+ {
+ // We have reached the number of successive VRHOT samples allowed. Need
+ // to log an error (only once per OCC reset).
+ if(!L_error_logged)
+ {
+ L_error_logged = TRUE;
+
+ TRAC_ERR("amec_health_check_proc_vrhot: VRHOT has been asserted! num_samples[%u]",
+ l_sensor->sample);
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_PROC_VRHOT
+ * @reasoncode VRM_ERROR_TEMP
+ * @userdata1 VRHOT error threshold
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc VRHOT signal has been asserted long enough to
+ * exceed its error threshold.
+ *
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_PROC_VRHOT,
+ VRM_ERROR_TEMP,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ g_amec->vrhotproc.setpoint,
+ 0);
+
+ // Callout the Ambient procedure
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_OVER_TEMPERATURE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // Callout backplane
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.backplane_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ // Commit Error
+ commitErrl(&l_err);
+ }
+ }
+}
diff --git a/src/occ/amec/amec_health.h b/src/occ/amec/amec_health.h
new file mode 100755
index 0000000..6414860
--- /dev/null
+++ b/src/occ/amec/amec_health.h
@@ -0,0 +1,47 @@
+/**
+ * @file amec_health.h
+ * @brief Header file for OCC Health Monitor.
+ *
+ *
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_mnfg_intf_h cmdh_mnfg_intf.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- --------- ----------------------------------
+ * @gs012 903325 gjsilva 09/26/2013 Created
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ *
+ * @endverbatim
+ */
+#ifndef AMEC_HEALTH_H
+#define AMEC_HEALTH_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "cmdh_fsp_cmds_datacnfg.h"
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// Error threshold check is done every 16msec. Error timer is 5x16 = 80msec
+#define AMEC_HEALTH_ERROR_TIMER 5
+
+/*******************************************************************/
+/* Function Definitions */
+/*******************************************************************/
+
+void amec_health_check_proc_temp(void);
+void amec_health_check_proc_timeout(void);
+void amec_health_check_proc_vrhot();
+void amec_health_check_cent_temp(void);
+void amec_health_check_cent_timeout(void);
+void amec_health_check_dimm_temp(void);
+void amec_health_check_dimm_timeout(void);
+
+#endif
diff --git a/src/occ/amec/amec_init.c b/src/occ/amec/amec_init.c
new file mode 100755
index 0000000..7031eb0
--- /dev/null
+++ b/src/occ/amec/amec_init.c
@@ -0,0 +1,426 @@
+/******************************************************************************
+// @file amec_init.c
+// @brief OCC AMEC Initialization
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section amec_init.c AMEC_INIT.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th005 thallet 11/18/2011 Added this file
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @th00b thallet 02/28/2012 Added functions to init vector sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @gs001 gsilva 08/03/2012 Added g_amec init function
+ * @ly001 853751 lychen 09/17/2012 Support DPS algorithm
+ * @ry002 822116 ronda 11/26/2012 Support thermal controller for processor
+ * @ry003 870734 ronda 02/20/2013 Thermal controller for memory
+ * @fk001 879727 fmkassem 04/16/2013 PCAP support.
+ * @cl001 lefurgy 07/24/2013 Fix thermal control loop
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm008 SW226989 milesg 09/30/2013 Sapphire initial support
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ * @mw641 918066 mware 02/23/2014 g44_avg changed to 32 bits. Altered zeroing out of array at init.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <amec_sys.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include <rtls.h>
+#include <occ_sys_config.h>
+#include <occ_service_codes.h> // for SSX_GENERIC_FAILURE
+#include <trac.h>
+#include "state.h"
+#include "amec_service_codes.h"
+#include <amec_sys.h>
+#include <proc_data.h>
+#include <sensor.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// We can initialize amec system structure to all zeros
+amec_sys_t g_amec_sys = {0}; //@gm008
+
+// Initialize g_amec to point to g_amec_sys
+// We use this pointer to keep the amec code as similar to TPMD
+amec_sys_t * g_amec = &g_amec_sys;
+
+// GPE Request Structure that is used to measure the worst case GPE timings
+PoreFlex G_gpe_nop_request[NUM_GPE_ENGINES]; // @th00a
+
+extern PoreEntryPoint GPE_pore_nop; // @th00a
+extern void amec_slv_update_gpe_sensors(uint8_t i_gpe_engine); // @th00a
+extern void amec_slv_update_gpe_sensors(uint8_t i_gpe_engine); // @th00a
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+void amec_vectorize_core_sensor(sensor_t * l_sensor,
+ vectorSensor_t * l_vector,
+ const VECTOR_SENSOR_OP l_op,
+ uint16_t l_sensor_elem_array_gsid)
+{
+#define VECTOR_CREATE_FAILURE 1
+#define VECTOR_ADD_ELEM_FAILURE 2
+
+ int l_idx = 0; // Used to index the for loops for vector create
+ int l_rc = 0; // Indicates failure to add a sensor to vector
+ uint16_t l_gsid = 0xFFFF;
+ errlHndl_t l_err = NULL;
+
+ do
+ {
+ // Grab GSID for errl in case of failure
+ l_gsid = l_sensor->gsid;
+
+ // Vectorize the sensor
+ sensor_vectorize(l_sensor,
+ l_vector,
+ l_op);
+
+ // If vectorize worked, add elements to the vector sensor
+ if(NULL != l_sensor->vector)
+ {
+ // Loop through cores
+ for(l_idx=0; l_idx<MAX_NUM_CORES; l_idx++)
+ {
+ // Add elements to the vector sensor
+ sensor_vector_elem_add(l_sensor->vector,
+ l_idx,
+ AMECSENSOR_ARRAY_PTR(l_sensor_elem_array_gsid,l_idx));
+ // If core is not present, disable this vector element
+ if(!CORE_PRESENT(l_idx))
+ {
+ sensor_vector_elem_enable(l_sensor->vector,
+ l_idx,
+ 0 /* Disable */);
+ }
+ }
+
+ // Sanity check, we should have MAX_NUM_CORES entries in
+ // vector sensor
+ if(l_sensor->vector->size != MAX_NUM_CORES)
+ {
+ // Set l_rc and break out so that we can create an errl
+ l_rc = VECTOR_ADD_ELEM_FAILURE;
+ break;
+ }
+ }
+ else
+ {
+ // Set l_rc and break out so that we can create an errl
+ l_rc = VECTOR_CREATE_FAILURE;
+ break;
+ }
+ }while(0);
+
+ if(l_rc)
+ {
+ //If fail to create pore flex object then there is a problem.
+ TRAC_ERR("Failed to vectorize sensor[0x%x, 0x%x]", l_gsid, l_rc );
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_VECTORIZE_FW_SENSORS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 return code
+ * @userdata2 gsid of failed sensor
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware failure in call to vectorize sensor
+ */
+ l_err = createErrl(
+ AMEC_VECTORIZE_FW_SENSORS, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL,//TODO: create trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ l_gsid //userdata2
+ );
+
+ REQUEST_RESET(l_err); //gm06
+ }
+}
+
+void amec_init_vector_sensors(void)
+{
+
+#define VECTOR_CREATE_FAILURE 1
+#define VECTOR_ADD_ELEM_FAILURE 2
+
+ //-----------------------------------------------------
+ // TEMP2MSP0 Vector Sensor
+ //-----------------------------------------------------
+ amec_vectorize_core_sensor(AMECSENSOR_PTR(TEMP2MSP0),
+ &g_amec_sys.proc[0].temp2ms_vector,
+ VECTOR_OP_AVG,
+ TEMP2MSP0C0);
+
+ //-----------------------------------------------------
+ // FREQA2MSP0 Vector Sensor
+ //-----------------------------------------------------
+ amec_vectorize_core_sensor(AMECSENSOR_PTR(FREQA2MSP0), // @mw626
+ &g_amec_sys.proc[0].freqa2ms_vector,
+ VECTOR_OP_AVG,
+ FREQA2MSP0C0);
+
+ //-----------------------------------------------------
+ // IPS2MSP0 Vector Sensor
+ //-----------------------------------------------------
+ amec_vectorize_core_sensor(AMECSENSOR_PTR(IPS2MSP0),
+ &g_amec_sys.proc[0].ips2ms_vector,
+ VECTOR_OP_AVG,
+ IPS2MSP0C0);
+
+ //-----------------------------------------------------
+ // TEMP2MSP0PEAK Vector Sensor
+ //-----------------------------------------------------
+ amec_vectorize_core_sensor(AMECSENSOR_PTR(TEMP2MSP0PEAK),
+ &g_amec_sys.proc[0].temp2mspeak_vector,
+ VECTOR_OP_MAX,
+ TEMP2MSP0C0);
+
+ //-----------------------------------------------------
+ // UTIL2MSP0 Vector Sensor
+ //-----------------------------------------------------
+ amec_vectorize_core_sensor(AMECSENSOR_PTR(UTIL2MSP0),
+ &g_amec_sys.proc[0].util2ms_vector,
+ VECTOR_OP_AVG,
+ UTIL2MSP0C0);
+
+#if 0 //TODO: Re-enable with error checking when centaur support is added
+ int l_rc = 0, l_idx = 0, l_idx2 = 0; // Used to index the for loops for vector create
+ //-----------------------------------------------------
+ // MEMSP2MSP0 Vector Sensor
+ //-----------------------------------------------------
+ sensor_vectorize(AMECSENSOR_PTR(MEMSP2MSP0),
+ &g_amec_sys.proc[0].memsp2ms_vector,
+ VECTOR_OP_MIN);
+
+ for(l_idx=0; l_idx<MAX_NUM_MEM_CONTROLLERS; l_idx++)
+ {
+ for(l_idx2=0; l_idx2<NUM_PORT_PAIRS_PER_CENTAUR; l_idx2++)
+ {
+ sensor_vector_elem_add(AMECSENSOR_PTR(MEMSP2MSP0)->vector,
+ l_idx,
+ AMECSENSOR_2D_ARRAY_PTR(MEMSP2MSPM0C0P0,l_idx, l_idx2));
+ }
+ }
+#endif
+}
+
+// Function Specification
+//
+// Name: amec_init_gamec_struct
+//
+// Description: Perform initialization of g_amec structure
+//
+// Flow: --/--/-- FN=a
+//
+// End Function Specification
+void amec_init_gamec_struct(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_idx = 0; // @ly001a
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Defaul the frequency range to something safe
+ g_amec->sys.fmin = 2000;
+ g_amec->sys.fmax = 2000;
+ g_amec->sys.max_speed = 1000; // @ly001a
+
+ g_amec->sys.min_speed = 400;
+ g_amec->sys.speed_step = 10;
+ g_amec->sys.speed_step_limit = (uint16_t)((65535/4)/(g_amec->sys.speed_step));
+
+ // Initialize thermal controller for processor
+ g_amec->thermalproc.setpoint = 850; // @cl001 change to 850 = 85.0 C
+ g_amec->thermalproc.Pgain = 1000;
+ g_amec->thermalproc.speed_request = 1000;
+ g_amec->thermalproc.freq_request = -1; //unconstrained frequency vote
+ g_amec->thermalproc.total_res = 0;
+
+ // Initialize thermal controller based on DIMM temperatures
+ g_amec->thermaldimm.setpoint = 850; //In 0.1 degrees C @cl001 change to 850 = 85.0 C
+ g_amec->thermaldimm.Pgain = 30000;
+ g_amec->thermaldimm.speed_request = AMEC_MEMORY_MAX_STEP;
+
+ // Initialize thermal controller based on Centaur temperatures
+ g_amec->thermalcent.setpoint = 850; //In 0.1 degrees C @cl001 change to 850 = 85.0 C
+ g_amec->thermalcent.Pgain = 30000;
+ g_amec->thermalcent.speed_request = AMEC_MEMORY_MAX_STEP;
+
+ // Initialize controler based on VRHOT signal from processor regulator
+ g_amec->vrhotproc.setpoint = 100;
+ g_amec->vrhotproc.freq_request = -1;
+ g_amec->vrhotproc.speed_request = 1000;
+
+ // @ly001a - start
+ // Initialize partition information
+ amec_part_init();
+
+ // Initialize performace counter
+ for (l_idx=0; l_idx<MAX_NUM_CORES; l_idx++)
+ {
+ amec_core_perf_counter_ctor(&g_amec->proc[0].core[l_idx].core_perf, 0, l_idx);
+ }
+ // @ly001a - end
+
+ //Initialize processor fields
+ g_amec->proc[0].core_max_freq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
+
+ //Initialize processor power votes
+ g_amec->proc[0].pwr_votes.pmax_clip_freq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
+
+ //Initialize stream buffer recording parameters
+ g_amec->recordflag=0; // Never enable recording until requested via Amester API call
+ g_amec->r_cnt=0; // Reset counter of 250us ticks
+ g_amec->ptr_stream_buffer = &g_amec->stream_buffer[0];
+ g_amec->stream_vector_mode=0; // No recording yet
+ g_amec->stream_vector_delay=0; // Delay in msec before recording can begin
+ g_amec->stream_vector_rate=0xff; // Invalid setting: requires IPMI command to select initial rate
+
+ //Initialize analytics parameters
+ g_amec->analytics_group=44; // Default to analytics Group 44 $mw431
+ g_amec->analytics_chip=0; // Default to which chip to perform analytics on $mw417
+ g_amec->analytics_bad_output_count=0; // Number of frames to discard before recording analytics output @mw587
+ g_amec->analytics_total_chips=MAX_NUM_CHIP_MODULES; // Default to do all chips in the system $mw418
+ g_amec->analytics_threadmode=1; // Default is average of all N threads $mw470 (may be altered with IPMI command)
+ g_amec->analytics_threadcountmax=4; // Default is 4 threads per core $mw459 (may be altered with IPMI command)
+ g_amec->analytics_total_chips=4; // For Tuleta force to only 2 DCM sockets, 4 chips
+ g_amec->analytics_option=1; // =0 means cycle through all chips, =1 means only work with analytics_chip
+ g_amec->analytics_thermal_offset=0; // Reset offset to 0 for thermal output group
+ g_amec->analytics_slot=4; // Time slot associated with when the amec_analytics function is called (out of 8 slots) @mw586
+ // Set entire averaging buffer to zero $mw417
+ memset (&g_amec->g44_avg, 0, 4*(MAX_SENSORS_ANALYTICS*MAX_NUM_CHIP_MODULES)); // @mw641
+}
+
+// Function Specification
+//
+// Name: amec_slave_init
+//
+// Description: Perform initialization of any/all AMEC Slave Functions
+//
+// Flow: 2/01/12 FN=amec_slave_init
+//
+// End Function Specification
+
+void amec_slave_init()
+{
+ errlHndl_t l_err = NULL; // Error handler
+ int rc = 0; // Return code
+ int rc2 = 0; // Return code
+
+ // Set the GPE Request Pointers to NULL in case the create fails.
+ G_fw_timing.gpe0_timing_request = NULL;
+ G_fw_timing.gpe1_timing_request = NULL;
+
+ // Initializes the GPE routine that will be used to measure the worst case
+ // timings for GPE0
+ rc = pore_flex_create( &G_gpe_nop_request[0], //gpe_req for the task
+ &G_pore_gpe0_queue, //queue
+ (void *) GPE_pore_nop, //entry point
+ (uint32_t) NULL, //parm for the task
+ SSX_WAIT_FOREVER, //no timeout
+ (AsyncRequestCallback) amec_slv_update_gpe_sensors, //callback
+ (void *) GPE_ENGINE_0, //callback argument
+ ASYNC_CALLBACK_IMMEDIATE ); //options
+
+ // Initializes the GPE routine that will be used to measure the worst case
+ // timings for GPE1
+ rc2 = pore_flex_create( &G_gpe_nop_request[1], //gpe_req for the task
+ &G_pore_gpe1_queue, //queue
+ (void *)GPE_pore_nop, //entry point
+ (uint32_t) NULL, //parm for the task
+ SSX_WAIT_FOREVER, //no timeout
+ (AsyncRequestCallback) amec_slv_update_gpe_sensors, //callback
+ (void *) GPE_ENGINE_1, //callback argument
+ ASYNC_CALLBACK_IMMEDIATE ); //options
+
+ // If we couldn't create the poreFlex objects, there must be a major problem
+ // so we will log an error and halt OCC.
+ if( rc || rc2 )
+ {
+ //If fail to create pore flex object then there is a problem.
+ TRAC_ERR("Failed to create GPE duration poreFlex object[0x%x, 0x%x]", rc, rc2 );
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_INITIALIZE_FW_SENSORS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 return code - gpe0
+ * @userdata2 return code - gpe1
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure to create PORE-GPE poreFlex object for FW timing
+ * analysis.
+ *
+ */
+ l_err = createErrl(
+ AMEC_INITIALIZE_FW_SENSORS, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //TODO: create trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ rc2 //userdata2
+ );
+
+ REQUEST_RESET(l_err); //gm06
+
+ }
+ else
+ {
+ // Everything was successful, so set FW timing pointers to these
+ // GPE Request objects
+ G_fw_timing.gpe0_timing_request = &G_gpe_nop_request[0];
+ G_fw_timing.gpe1_timing_request = &G_gpe_nop_request[1];
+ }
+
+ // Initialize Vector Sensors for AMEC use
+ amec_init_vector_sensors(); // @th00b
+
+ // Initialize AMEC internal parameters
+ amec_init_gamec_struct();
+}
+
diff --git a/src/occ/amec/amec_master_smh.c b/src/occ/amec/amec_master_smh.c
new file mode 100755
index 0000000..45fa7b3
--- /dev/null
+++ b/src/occ/amec/amec_master_smh.c
@@ -0,0 +1,1114 @@
+/******************************************************************************
+// @file amec_master_smh.c
+// @brief Master State Machine
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_master_smh_c amec_master_smh.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 11/08/2011 New file
+ * @rc001 rickylie 01/10/2012 Added trac.h
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gs006 884384 gjsilva 05/30/2013 Support for mnfg auto-slewing function
+ * @gs007 888247 gjsilva 06/19/2013 OCC mnfg support for frequency distribution
+ * @db001 897459 deepthib 08/03/2013 Power cap mismatch & under pcap functions
+ * @rt001 903366 tapiar 10/23/2013 Add more trace in case power cap mismatch occurs
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @rt004 908817 tapiar 12/11/2013 Expand G_active_slave_pcaps arrray to also carry
+ * valid pcap byte from slaves
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @wb003 920760 wilbryan 03/27/2014 Update SRCs to match TPMD SRCs
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include "rtls.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "sensor.h"
+#include "amec_smh.h"
+#include "amec_master_smh.h"
+#include <trac.h> // For traces
+#include "amec_sys.h"
+#include "amec_service_codes.h" //For AMEC_MST_CHECK_PCAPS_MATCH @db001a
+#include "dcom.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//Power cap mismatch threshold set to 8 ticks (2 milliseconds) @db001a
+#define PCAPS_MISMATCH_THRESHOLD 8
+
+//Power cap failure threshold set to 32 (ticks) @db001a
+#define PCAP_FAILURE_THRESHOLD 32
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+smh_state_t G_amec_mst_state = {AMEC_INITIAL_STATE,
+ AMEC_INITIAL_STATE,
+ AMEC_INITIAL_STATE};
+
+//Array that stores active power cap values of all OCCs @db001a
+slave_pcap_info_t G_slave_active_pcaps[MAX_OCCS] = {{0}}; //@rt004c
+
+//OCC Power cap mismatch count @db001a
+uint8_t G_pcaps_mismatch_count = 0;
+
+//OCC over power cap count @db001a
+uint8_t G_over_cap_count = 0;
+
+//Array that stores the exit counts for the IPS algorithm
+uint32_t G_ips_exit_count[MAX_OCCS][MAX_CORES] = {{0}};
+//Array that stores the entry counts for the IPS algorithm
+uint32_t G_ips_entry_count = 0;
+
+//Soft Fmin to be sent to Slave OCCs
+uint16_t G_mst_soft_fmin = 0;
+//Soft Fmax to be sent to Slave OCCs
+uint16_t G_mst_soft_fmax = 0xFFFF;
+//Counter of committed violations by the Slave OCCs
+uint8_t G_mst_violation_cnt[MAX_OCCS] = {0};
+
+// --------------------------------------------------------
+// AMEC Master State 6.1 Substate Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 128ms.
+//
+const smh_tbl_t amec_mst_state_6_1_sub_substate_table[AMEC_SMH_STATES_PER_LVL] =
+{
+ {amec_mst_sub_substate_6_1_0, NULL},
+ {amec_mst_sub_substate_6_1_1, NULL},
+ {amec_mst_sub_substate_6_1_2, NULL},
+ {amec_mst_sub_substate_6_1_3, NULL},
+ {amec_mst_sub_substate_6_1_4, NULL},
+ {amec_mst_sub_substate_6_1_5, NULL},
+ {amec_mst_sub_substate_6_1_6, NULL},
+ {amec_mst_sub_substate_6_1_7, NULL},
+};
+
+// --------------------------------------------------------
+// AMEC Master State 0 Substate Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 16ms.
+//
+// The 2 States are interleaved so each one runs every 4ms.
+//
+const smh_tbl_t amec_mst_state_0_substate_table[AMEC_SMH_STATES_PER_LVL] =
+{
+ {amec_mst_substate_0_0, NULL},
+ {amec_mst_substate_0_1, NULL},
+ {amec_mst_substate_0_0, NULL},
+ {amec_mst_substate_0_1, NULL},
+ {amec_mst_substate_0_0, NULL},
+ {amec_mst_substate_0_1, NULL},
+ {amec_mst_substate_0_0, NULL},
+ {amec_mst_substate_0_1, NULL},
+};
+
+// --------------------------------------------------------
+// AMEC Master State 3 Substate Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 16ms.
+//
+// The 2 States are interleaved so each one runs every 4ms.
+//
+const smh_tbl_t amec_mst_state_3_substate_table[AMEC_SMH_STATES_PER_LVL] =
+
+{
+ {amec_mst_substate_3_0, NULL},
+ {amec_mst_substate_3_1, NULL},
+ {amec_mst_substate_3_0, NULL},
+ {amec_mst_substate_3_1, NULL},
+ {amec_mst_substate_3_0, NULL},
+ {amec_mst_substate_3_1, NULL},
+ {amec_mst_substate_3_0, NULL},
+ {amec_mst_substate_3_1, NULL},
+};
+
+// --------------------------------------------------------
+// AMEC Master State 6 Substate Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 16ms.
+//
+// SubState1: 8 Sub-substates (128ms/sub-substate)
+//
+const smh_tbl_t amec_mst_state_6_substate_table[AMEC_SMH_STATES_PER_LVL] =
+{
+ {amec_mst_substate_6_0, NULL},
+ {amec_mst_substate_6_1, amec_mst_state_6_1_sub_substate_table},
+ {amec_mst_substate_6_2, NULL},
+ {amec_mst_substate_6_3, NULL},
+ {amec_mst_substate_6_4, NULL},
+ {amec_mst_substate_6_5, NULL},
+ {amec_mst_substate_6_6, NULL},
+ {amec_mst_substate_6_7, NULL},
+};
+
+// --------------------------------------------------------
+// Main AMEC Master State Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 2ms.
+//
+// State0: 2 Substates (4ms/substate)
+// State3: 2 Substates (4ms/substate)
+// State6: 8 Substates (16ms/substate)
+//
+const smh_tbl_t amec_mst_state_table[AMEC_SMH_STATES_PER_LVL] =
+{
+ {amec_mst_state_0, amec_mst_state_0_substate_table},
+ {amec_mst_state_1, NULL},
+ {amec_mst_state_2, NULL},
+ {amec_mst_state_3, amec_mst_state_3_substate_table},
+ {amec_mst_state_4, NULL},
+ {amec_mst_state_5, NULL},
+ {amec_mst_state_6, amec_mst_state_6_substate_table},
+ {amec_mst_state_7, NULL},
+};
+
+// This sets up the function pointer that will be called to update the
+// fw timings when the AMEC master State Machine finishes.
+smh_state_timing_t G_amec_mst_state_timings = {amec_mst_update_smh_sensors};
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: amec_mst_update_smh_sensors
+//
+// Description: Update the sensor
+//
+// Flow: FN=None
+//
+// End Function Specification
+void amec_mst_update_smh_sensors(int i_smh_state, uint32_t i_duration)
+{
+ // Update the duration in the fw timing table
+ if(G_fw_timing.amess_state != i_smh_state)
+ {
+ AMEC_DBG("Mismatch between Master and Slave AMEC states\n");
+ }
+
+ G_fw_timing.amess_dur += i_duration; // @th00a
+}
+
+// Function Specification
+//
+// Name: amec_master_auto_slew
+//
+// Description: This function executes the auto-slewing of frequency based on
+// manufacturing parameters.
+//
+//
+// Flow: 06/19/13 FN= amec_master_auto_slew
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_master_auto_slew(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ static int8_t l_direction = 1;
+ uint16_t l_freq = 0;
+ static uint16_t l_step_delay = 0;
+ static bool l_first_time_enable = TRUE;
+ static bool l_first_time_disable = FALSE;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // Check if auto-slewing has been enabled
+ if (g_amec->mnfg_parms.auto_slew)
+ {
+ // Is this the first time we are enabling auto-slewing?
+ if (l_first_time_enable)
+ {
+ // Need to start the auto-slew from fmax
+ g_amec->mnfg_parms.foverride = g_amec->mnfg_parms.fmax;
+
+ // Reset the delay counter and reset the direction
+ l_step_delay = g_amec->mnfg_parms.delay;
+ l_direction = 1;
+
+ l_first_time_enable = FALSE;
+ l_first_time_disable = TRUE;
+
+ // Break out now to give it some time to get to fmax
+ break;
+ }
+ }
+ else
+ {
+ // Is this the first time we are disabling auto-slewing?
+ if (l_first_time_disable)
+ {
+ // Clear the frequency override parameter
+ g_amec->mnfg_parms.foverride = 0;
+
+ l_first_time_enable = TRUE;
+ l_first_time_disable = FALSE;
+ }
+
+ // We are done, break
+ break;
+ }
+
+ // If we've made it this far, then we are running auto-slew. First,
+ // check if our delay counter has expired.
+ if (l_step_delay != 0)
+ {
+ // Decrement our delay counter and exit
+ l_step_delay--;
+ break;
+ }
+
+ // Our delay counter has expired, reset it to its original value
+ l_step_delay = g_amec->mnfg_parms.delay;
+
+ // Now, generate a new frequency override
+ l_freq = g_amec->mnfg_parms.foverride -
+ (l_direction * g_amec->mnfg_parms.fstep);
+
+ if (l_freq <= g_amec->mnfg_parms.fmin)
+ {
+ // We've reached an edge, increment our counter
+ g_amec->mnfg_parms.slew_counter++;
+
+ // Change direction of the auto-slew
+ l_direction = -l_direction;
+
+ // Clip frequency to fmin
+ l_freq = g_amec->mnfg_parms.fmin;
+ }
+ else if (l_freq >= g_amec->mnfg_parms.fmax)
+ {
+ // We've reached an edge, increment our counter
+ g_amec->mnfg_parms.slew_counter++;
+
+ // Change direction of the auto-slew
+ l_direction = -l_direction;
+
+ // Clip frequency to fmax
+ l_freq = g_amec->mnfg_parms.fmax;
+ }
+ g_amec->mnfg_parms.foverride = l_freq;
+
+ }while(0);
+
+ return;
+}
+
+// @db001a
+// Function Specification
+//
+// Name: amec_mst_check_pcaps_match
+//
+// Description: This function checks for mismatch in power caps between
+// occs for 8 consecutive ticks.
+//
+//
+// Flow: 04/6/2013 FN= amec_mst_check_pcaps_match
+//
+// End Function Specification
+void amec_mst_check_pcaps_match(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_chip_id;
+ bool l_prev_pcap_valid = FALSE;
+ uint16_t l_prev_pcap = 0;
+ bool l_pcap_mismatch = FALSE;
+ errlHndl_t l_err = NULL;
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //Loop through all occs
+ for(l_chip_id = 0; l_chip_id < MAX_OCCS; l_chip_id++)
+ {
+ //if occ is present && its pcap data is considered valid @rt004c
+ if((G_sysConfigData.is_occ_present & (1<< l_chip_id)) &&
+ (G_slave_active_pcaps[l_chip_id].pcap_valid != 0))
+ {
+ //TRAC_INFO(" occ[%d]: pcap[%d] valid(%d)",
+ // l_chip_id, G_slave_active_pcaps[l_chip_id].active_pcap, G_slave_active_pcaps[l_chip_id].pcap_valid );
+
+ //Initialize l_prev_pcap to the first valid/present occ's power cap
+ if(!l_prev_pcap_valid)
+ {
+ //TRAC_INFO("First present occ - power cap info[%d]=%d(%d)",
+ // l_chip_id, G_slave_active_pcaps[l_chip_id].active_pcap, G_slave_active_pcaps[l_chip_id].pcap_valid ); //@rt001a
+
+ l_prev_pcap = G_slave_active_pcaps[l_chip_id].active_pcap;
+ l_prev_pcap_valid = TRUE;
+ }
+ else
+ {
+ //If there is mismatch between OCCs power caps, increment mismatch
+ // count
+ if(l_prev_pcap != G_slave_active_pcaps[l_chip_id].active_pcap)
+ {
+ G_pcaps_mismatch_count++;
+ l_pcap_mismatch = TRUE;
+
+ TRAC_INFO("Mismatch in OCC power cap values: mismatch cnt=%d pcap=%d vs compared pcap[%d]=%d(%d)",
+ G_pcaps_mismatch_count, l_prev_pcap, l_chip_id, G_slave_active_pcaps[l_chip_id].active_pcap,
+ G_slave_active_pcaps[l_chip_id].pcap_valid); //@rt001a
+
+ //If mismatch occurs for 8 consecutive ticks
+ //i.e 8 * 250 microsecs = 2 milliseconds,then reset occ
+ if(G_pcaps_mismatch_count >= PCAPS_MISMATCH_THRESHOLD)
+ {
+ TRAC_ERR("Mismatch in OCC power cap values: pcap=%d, slave_active_pcap[%d]=%d(%d)",
+ l_prev_pcap, l_chip_id, G_slave_active_pcaps[l_chip_id].active_pcap,
+ G_slave_active_pcaps[l_chip_id].pcap_valid); //@rt001c
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_MST_CHECK_PCAPS_MATCH
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 First OCC Power cap
+ * @userdata2 Mismatch OCC Power cap
+ * @devdesc Internal max power limits mismatched
+ *
+ */
+
+ l_err = createErrl( AMEC_MST_CHECK_PCAPS_MATCH,
+ INTERNAL_FAILURE,
+ ERC_AMEC_PCAPS_MISMATCH_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_prev_pcap,
+ G_slave_active_pcaps[l_chip_id].active_pcap);
+
+ //Callout to OVS
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE, // @wb001
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ //Callout to APSS
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.apss_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ //Callout to DPSS
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.dpss_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ //Reset OCC
+ REQUEST_RESET(l_err);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ //If there was no power cap mismatch between occ's,then reset count to zero
+ if(!l_pcap_mismatch)
+ {
+ G_pcaps_mismatch_count = 0;
+ }
+}
+
+
+// @db001a
+// Function Specification
+//
+// Name: amec_mst_check_under_pcap
+//
+// Description: This function checks if there is failure in maintaining power
+// cap value.
+//
+//
+// Flow: 04/16/2013 FN= amec_mst_check_under_pcap
+//
+// End Function Specification
+
+void amec_mst_check_under_pcap(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Check if ppb_fmax = Fmin and PWR250US > Node power cap and
+ // Node power cap >= hard_min_pcap
+ if((g_amec->proc[0].pwr_votes.ppb_fmax == g_amec->sys.fmin) &&
+ (AMECSENSOR_PTR(PWR250US)->sample > g_amec->pcap.active_node_pcap) &&
+ (g_amec->pcap.active_node_pcap >= G_sysConfigData.pcap.hard_min_pcap))
+ {
+
+ G_over_cap_count++;
+
+ //Log error and reset OCC if count >= 32 (ticks)
+ if(G_over_cap_count >= PCAP_FAILURE_THRESHOLD)
+ {
+ TRAC_ERR("Failure to maintain power cap: Power Cap = %d ,"
+ "PWR250US = %d ,PWR250USP0 = %d ,PWR250USFAN = %d ,"
+ "PWR250USMEM0 = %d",g_amec->pcap.active_node_pcap,
+ AMECSENSOR_PTR(PWR250US)->sample,
+ AMECSENSOR_PTR(PWR250USP0)->sample,
+ AMECSENSOR_PTR(PWR250USFAN)->sample,
+ AMECSENSOR_PTR(PWR250USMEM0)->sample);
+
+ TRAC_ERR("PWR250USIO = %d , PWR250USSTORE = %d, PWR250USGPU = %d",
+ AMECSENSOR_PTR(PWR250USIO)->sample,
+ AMECSENSOR_PTR(PWR250USSTORE)->sample,
+ AMECSENSOR_PTR(PWR250USGPU)->sample);
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_MST_CHECK_UNDER_PCAP
+ * @reasoncode POWER_CAP_FAILURE
+ * @userdata1 Power Cap
+ * @userdata2 PWR250US (Node Power)
+ * @devdesc Failure to maintain max power limits
+ *
+ */
+
+ l_err = createErrl( AMEC_MST_CHECK_UNDER_PCAP,
+ POWER_CAP_FAILURE, // @wb003 -- Match TPMD
+ ERC_AMEC_UNDER_PCAP_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ g_amec->pcap.active_node_pcap,
+ AMECSENSOR_PTR(PWR250US)->sample);
+
+ //Callout to firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ //Callout to APSS
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.apss_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ //Reset OCC
+ REQUEST_RESET(l_err);
+
+ }
+ }
+ else
+ {
+ //Decrement count if node power under power cap value
+ if(G_over_cap_count > 0)
+ {
+ G_over_cap_count--;
+ }
+ }
+
+ return;
+}
+
+// Function Specification
+//
+// Name: amec_mst_ips_main
+//
+// Description: This function executes the Idle Power Saver (IPS)
+// algorithm.
+//
+//
+// Flow: FN=
+//
+// End Function Specification
+void amec_mst_ips_main(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t i = 0;
+ uint16_t j = 0;
+ uint16_t l_time_interval = 0;
+ uint16_t l_core_count = 0;
+ uint16_t l_entry_core_count = 0;
+ BOOLEAN l_exit = FALSE;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ // If IPS is disabled, no need to execute the algorithm
+ if (g_amec->mst_ips_parms.enable == 0)
+ {
+ // Reset the following parameters
+ g_amec->mst_ips_parms.active = 0;
+ G_ips_entry_count = 0;
+ g_amec->mst_ips_parms.freq_request = g_amec->sys.fmax;
+
+ break;
+ }
+
+ // We made it here, so that means IPS is enabled.
+ l_time_interval = AMEC_DPS_SAMPLING_RATE * AMEC_IPS_AVRG_INTERVAL;
+
+ // If IPS is active, check if the exit criteria has been met
+ if (g_amec->mst_ips_parms.active == 1)
+ {
+ // Useful trace for debugging
+ //TRAC_INFO("DBG_IPS: IPS is active! exit_countp0c5[%u]",
+ // G_ips_exit_count[0][5]);
+
+ for (i=0; i<MAX_OCCS; i++)
+ {
+ if (!(G_sysConfigData.is_occ_present & (1<<i)))
+ {
+ // This OCC is not present, just move along
+ continue;
+ }
+
+ for (j=0; j<MAX_CORES; j++)
+ {
+ // Check if this core's normalized utilization has exceeded
+ // the exit threshold
+ if (G_dcom_slv_outbox_rx[i].nutil3sp0cy[j] >=
+ g_amec->mst_ips_parms.exit_threshold)
+ {
+ // Increment our exit count by the number of samples
+ // used to average utilization (default is 3 seconds)
+ G_ips_exit_count[i][j] += l_time_interval;
+
+ if (G_ips_exit_count[i][j] >=
+ g_amec->mst_ips_parms.exit_delay)
+ {
+ // Found one core that meets the exit criteria!
+ l_exit = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ // If the normalized utilization of this core is below
+ // the exit threshold, reset its exit count
+ G_ips_exit_count[i][j] = 0;
+ }
+ }
+
+ if (l_exit)
+ {
+ break;
+ }
+ }
+
+ // If we found a core that meets the exit criteria, then exit IPS
+ // active state
+ if (l_exit)
+ {
+ g_amec->mst_ips_parms.active = 0;
+ G_ips_entry_count = 0;
+ // A special request of 0 frequency will inform the slaves to
+ // ignore the IPS request from the master
+ g_amec->mst_ips_parms.freq_request = 0;
+
+ TRAC_INFO("amec_mst_ips_main: We have exited IPS active state! exit_count[%u] freq_request[%u]",
+ G_ips_exit_count[i][j], g_amec->mst_ips_parms.freq_request);
+ }
+ }
+ else //IPS is inactive, check if entry criteria has been met
+ {
+ // Useful trace for debugging
+ //TRAC_INFO("DBG_IPS: IPS is inactive! entry_count[%u]",
+ // G_ips_entry_count);
+
+ for (i=0; i<MAX_OCCS; i++)
+ {
+ if (!(G_sysConfigData.is_occ_present & (1<<i)))
+ {
+ // This OCC is not present, just move along
+ continue;
+ }
+
+ for (j=0; j<MAX_CORES; j++)
+ {
+ l_core_count++;
+
+ // Note: cores that are not present will return a zero
+ // utilization, thus fulfilling the check below
+ if (G_dcom_slv_outbox_rx[i].nutil3sp0cy[j] <
+ g_amec->mst_ips_parms.entry_threshold)
+ {
+ // Count how many cores have a normalized utilization
+ // below the entry threshold
+ l_entry_core_count++;
+ }
+ else
+ {
+ // Reset the entry count since we found a core that
+ // has a utilization >= entry threshold
+ G_ips_entry_count = 0;
+ }
+ }
+ }
+
+ // All cores have a utilization lower than the entry threshold
+ if (l_entry_core_count == l_core_count)
+ {
+ // Increment the entry count by the number of samples used to
+ // average utilization (default is 3 seconds)
+ G_ips_entry_count += l_time_interval;
+
+ if (G_ips_entry_count >= g_amec->mst_ips_parms.entry_delay)
+ {
+ // We have met the entry criteria, move IPS state to active
+ g_amec->mst_ips_parms.active = 1;
+
+ for (i=0; i<MAX_OCCS; i++)
+ {
+ if (!(G_sysConfigData.is_occ_present & (1<<i)))
+ {
+ continue;
+ }
+ for (j=0; j<MAX_CORES; j++)
+ {
+ G_ips_exit_count[i][j] = 0;
+ }
+ }
+
+ g_amec->mst_ips_parms.freq_request =
+ G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+
+ TRAC_INFO("amec_mst_ips_main: We have entered IPS active state! entry_count[%u] freq_request[%u]",
+ G_ips_entry_count, g_amec->mst_ips_parms.freq_request);
+ }
+ }
+ }
+ }while(0);
+}
+
+uint8_t AMEC_mst_get_ips_active_status()
+{
+ return g_amec->mst_ips_parms.active;
+}
+
+// Function Specification
+//
+// Name: amec_mst_gen_soft_freq
+//
+// Description: This function executes the algorithm that generates the soft
+// frequency boundaries to be sent to the Slave OCCs. This is the strategy
+// to be used for P8 GA1.
+//
+// End Function Specification
+void amec_mst_gen_soft_freq(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t i = 0;
+ uint16_t l_ftarget = 0;
+ uint16_t l_fdelta = 0;
+ uint16_t l_lowest_fwish = 0;
+ uint16_t l_highest_fwish = 0;
+ BOOLEAN l_need_reset = FALSE;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // First, check if frequency delta has been enabled
+ if (G_mst_tunable_parameter_table_ext[7].adj_value == 0)
+ {
+ // If it hasn't been enabled, then use the full frequency range and
+ // break
+ G_mst_soft_fmin = 0x0000;
+ G_mst_soft_fmax = 0xFFFF;
+
+ break;
+ }
+
+ // Use the frequency delta sent by the customer
+ l_fdelta = (G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL] *
+ G_mst_tunable_parameter_table_ext[8].adj_value/2) / 100;
+
+ // Check if all OCCs are operating inside the soft frequency boundaries
+ for (i=0; i<MAX_OCCS; i++)
+ {
+ // Ignore OCCs that are sending zeros for factual or fwish
+ if ((G_dcom_slv_outbox_rx[i].factual == 0) ||
+ (G_dcom_slv_outbox_rx[i].fwish == 0))
+ {
+ continue;
+ }
+
+ // Compare factual against the soft frequency boundaries
+ if ((G_dcom_slv_outbox_rx[i].factual < G_mst_soft_fmin) ||
+ (G_dcom_slv_outbox_rx[i].factual > G_mst_soft_fmax))
+ {
+ G_mst_violation_cnt[i]++;
+ }
+ else
+ {
+ G_mst_violation_cnt[i] = 0;
+ }
+
+ // Now check if the violation count has exceeded the threshold
+ if (G_mst_violation_cnt[i] > 3)
+ {
+ // The new target frequency is the violator's factual
+ l_need_reset = TRUE;
+ l_ftarget = G_dcom_slv_outbox_rx[i].factual;
+ }
+ }
+
+ // If all OCCs are inside the soft frequency boundaries, select the
+ // target frequeny based on the power mode
+ if (!l_need_reset)
+ {
+ if ((CURRENT_MODE() == OCC_MODE_DYN_POWER_SAVE) ||
+ (CURRENT_MODE() == OCC_MODE_DYN_POWER_SAVE_FP))
+ {
+ // For DPS and DPS-FP modes, calculate the highest Fwish sent
+ // by all slave OCCs
+ l_highest_fwish = 0;
+ for (i=0; i<MAX_OCCS; i++)
+ {
+ // Ignore OCCs that are sending zeros for factual or fwish
+ if ((G_dcom_slv_outbox_rx[i].factual == 0) ||
+ (G_dcom_slv_outbox_rx[i].fwish == 0))
+ {
+ continue;
+ }
+ if (G_dcom_slv_outbox_rx[i].fwish > l_highest_fwish)
+ {
+ l_highest_fwish = G_dcom_slv_outbox_rx[i].fwish;
+ }
+ }
+
+ // If the highest Fwish is in range, go for it. Otherwise, step
+ // towards it in small steps
+ if ((l_highest_fwish >= G_mst_soft_fmin) &&
+ (l_highest_fwish <= G_mst_soft_fmax))
+ {
+ l_ftarget = l_highest_fwish;
+ }
+ else if (l_highest_fwish > G_mst_soft_fmax)
+ {
+ // Fwish is too high for range, step up (new target is the
+ // old soft Fmax)
+ l_ftarget = G_mst_soft_fmax;
+ }
+ else
+ {
+ // Fwish is too low for range, step down (new target is the
+ // old soft Fmin)
+ l_ftarget = G_mst_soft_fmin;
+ }
+ }
+ else
+ {
+ // For other system power modes, calculate the lowest Fwish sent
+ // by all slave OCCs
+ l_lowest_fwish = 0xFFFF;
+ for (i=0; i<MAX_OCCS; i++)
+ {
+ // Ignore OCCs that are sending zeros for factual or fwish
+ if ((G_dcom_slv_outbox_rx[i].factual == 0) ||
+ (G_dcom_slv_outbox_rx[i].fwish == 0))
+ {
+ continue;
+ }
+ if ((G_dcom_slv_outbox_rx[i].fwish < l_lowest_fwish) &&
+ (G_dcom_slv_outbox_rx[i].fwish != 0))
+ {
+ l_lowest_fwish = G_dcom_slv_outbox_rx[i].fwish;
+ }
+ }
+
+ // If the lowest Fwish is in range, go for it. Otherwise, step
+ // towards it in small steps
+ if ((l_lowest_fwish >= G_mst_soft_fmin) &&
+ (l_lowest_fwish <= G_mst_soft_fmax))
+ {
+ l_ftarget = l_lowest_fwish;
+ }
+ else if (l_lowest_fwish > G_mst_soft_fmax)
+ {
+ // Fwish is too high for range, step up (new target is the
+ // old soft Fmax)
+ l_ftarget = G_mst_soft_fmax;
+ }
+ else
+ {
+ // Fwish is too low for range, step down (new target is the
+ // old soft Fmin)
+ l_ftarget = G_mst_soft_fmin;
+ }
+ }
+ }
+
+ // Calculate the new soft frequency boundaries
+ G_mst_soft_fmin = l_ftarget - l_fdelta;
+ G_mst_soft_fmax = l_ftarget + l_fdelta;
+
+ } while(0);
+}
+
+
+// Function Specification
+//
+// Name: amec_mst_cmmon_tasks_pre
+//
+// Description: master common tasks pre function
+//
+//
+// Flow: FN= amec_mst_common_tasks_pre
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_mst_common_tasks_pre(void)
+{
+ AMEC_DBG("\tAMEC Master Pre-State Common\n");
+
+ // ------------------------------------------------------
+ //
+ // ------------------------------------------------------
+
+
+ // ------------------------------------------------------
+ //
+ // ------------------------------------------------------
+}
+
+
+// Function Specification
+//
+// Name: amec_mst_cmmon_tasks_post
+//
+// Description: master common tasks post function
+//
+//
+// Flow: FN= amec_mst_common_tasks_post
+//
+// End Function Specification
+void amec_mst_common_tasks_post(void)
+{
+ AMEC_DBG("\tAMEC Master Post-State Common\n");
+
+ // Only execute if OCC is in the active state
+ if ( IS_OCC_STATE_ACTIVE() )
+ {
+ // Call the OCC auto-slew function
+ amec_master_auto_slew();
+
+ //@db001a
+ //Call OCC pcaps mismatch function @db001a
+ amec_mst_check_pcaps_match();
+
+ //Call check under power cap function @db001a
+ amec_mst_check_under_pcap();
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: amec_mst_state_0 ~ amec_mst_state_7
+//
+// Description: master state 0 ~ 7 functions
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_mst_state_0(void){AMEC_DBG("\tAMEC Master State 0\n");}
+void amec_mst_state_1(void){AMEC_DBG("\tAMEC Master State 1\n");}
+void amec_mst_state_2(void){AMEC_DBG("\tAMEC Master State 2\n");}
+void amec_mst_state_3(void){AMEC_DBG("\tAMEC Master State 3\n");}
+void amec_mst_state_4(void){AMEC_DBG("\tAMEC Master State 4\n");}
+
+void amec_mst_state_5(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ static uint16_t l_counter = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ AMEC_DBG("\tAMEC Master State 5\n");
+
+ // Only execute if OCC is in the active state
+ if ( IS_OCC_STATE_ACTIVE() )
+ {
+ // Increment our local counter
+ l_counter++;
+
+ // Is it time to run the Idle Power Saver algorithm? (default is 3sec)
+ if (l_counter == AMEC_DPS_SAMPLING_RATE * AMEC_IPS_AVRG_INTERVAL)
+ {
+ l_counter = 0;
+ amec_mst_ips_main();
+ }
+ }
+}
+
+void amec_mst_state_6(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ AMEC_DBG("\tAMEC Master State 6\n");
+
+ if ( IS_OCC_STATE_ACTIVE() )
+ {
+ amec_mst_gen_soft_freq();
+ }
+}
+
+void amec_mst_state_7(void){AMEC_DBG("\tAMEC Master State 7\n");}
+
+// Function Specification
+//
+// Name: amec_mst_substate_0_0
+// amec_mst_substate_0_1
+//
+// Description: master substate amec_mst_substate_0_0
+// master substate amec_mst_substate_0_1
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_mst_substate_0_0(void){AMEC_DBG("\tAMEC Master SubState 0.0\n");}
+void amec_mst_substate_0_1(void){AMEC_DBG("\tAMEC Master SubState 0.1\n");}
+
+// Function Specification
+//
+// Name: amec_mst_substate_6_0
+// amec_mst_substate_6_1
+// amec_mst_substate_6_2
+// amec_mst_substate_6_3
+// amec_mst_substate_6_4
+// amec_mst_substate_6_5
+// amec_mst_substate_6_6
+// amec_mst_substate_6_7
+//
+// Description: master substate amec_mst_substate_6_0
+// master substate amec_mst_substate_6_1
+// master substate amec_mst_substate_6_2
+// master substate amec_mst_substate_6_3
+// master substate amec_mst_substate_6_4
+// master substate amec_mst_substate_6_5
+// master substate amec_mst_substate_6_6
+// master substate amec_mst_substate_6_7
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_mst_substate_6_0(void){AMEC_DBG("\tAMEC Master State 6.0\n");}
+void amec_mst_substate_6_1(void){AMEC_DBG("\tAMEC Master State 6.1\n");}
+void amec_mst_substate_6_2(void){AMEC_DBG("\tAMEC Master State 6.2\n");}
+void amec_mst_substate_6_3(void){AMEC_DBG("\tAMEC Master State 6.3\n");}
+void amec_mst_substate_6_4(void){AMEC_DBG("\tAMEC Master State 6.4\n");}
+void amec_mst_substate_6_5(void){AMEC_DBG("\tAMEC Master State 6.5\n");}
+void amec_mst_substate_6_6(void){AMEC_DBG("\tAMEC Master State 6.6\n");}
+void amec_mst_substate_6_7(void){AMEC_DBG("\tAMEC Master State 6.7\n");}
+
+// Function Specification
+//
+// Name: amec_mst_substate_3_0
+// amec_mst_substate_3_1
+//
+// Description: master substate amec_mst_substate_3_0
+// master substate amec_mst_substate_3_1
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_mst_substate_3_0(void){AMEC_DBG("\tAMEC Master State 3.0\n");}
+void amec_mst_substate_3_1(void){AMEC_DBG("\tAMEC Master State 3.1\n");}
+
+
+// Function Specification
+//
+// Name: amec_mst_substate_6_1_0
+// amec_mst_substate_6_1_1
+// amec_mst_substate_6_1_2
+// amec_mst_substate_6_1_3
+// amec_mst_substate_6_1_4
+// amec_mst_substate_6_1_5
+// amec_mst_substate_6_1_6
+// amec_mst_substate_6_1_7
+//
+// Description: master substate amec_mst_substate_6_1_0
+// master substate amec_mst_substate_6_1_1
+// master substate amec_mst_substate_6_1_2
+// master substate amec_mst_substate_6_1_3
+// master substate amec_mst_substate_6_1_4
+// master substate amec_mst_substate_6_1_5
+// master substate amec_mst_substate_6_1_6
+// master substate amec_mst_substate_6_1_7
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_mst_sub_substate_6_1_0(void){AMEC_DBG("\tAMEC Master State 6.1.0\n");}
+void amec_mst_sub_substate_6_1_1(void){AMEC_DBG("\tAMEC Master State 6.1.1\n");}
+void amec_mst_sub_substate_6_1_2(void){AMEC_DBG("\tAMEC Master State 6.1.2\n");}
+void amec_mst_sub_substate_6_1_3(void){AMEC_DBG("\tAMEC Master State 6.1.3\n");}
+void amec_mst_sub_substate_6_1_4(void){AMEC_DBG("\tAMEC Master State 6.1.4\n");}
+void amec_mst_sub_substate_6_1_5(void){AMEC_DBG("\tAMEC Master State 6.1.5\n");}
+void amec_mst_sub_substate_6_1_6(void){AMEC_DBG("\tAMEC Master State 6.1.6\n");}
+void amec_mst_sub_substate_6_1_7(void){AMEC_DBG("\tAMEC Master State 6.1.7\n");}
+
diff --git a/src/occ/amec/amec_master_smh.h b/src/occ/amec/amec_master_smh.h
new file mode 100755
index 0000000..bc3e47f
--- /dev/null
+++ b/src/occ/amec/amec_master_smh.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+// @file amec_master_smh.h
+// @brief OCC AMEC Master SMH header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_master_smh_h amec_master_smh.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 11/08/2011 New file
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gs006 884384 gjsilva 05/30/2013 Support for mnfg auto-slewing function
+ * @db001 897459 deepthib 08/03/2013 Power cap mismatch & under pcap functions
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @rt004 908817 tapiar 12/11/2013 Expand G_active_slave_pcaps arrray to also carry
+ * valid pcap byte from slaves
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_MASTER_SMH_H
+#define _AMEC_MASTER_SMH_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+#include <amec_smh.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define AMEC_MST_STATE() AMEC_STATE(&G_amec_mst_state);
+#define AMEC_MST_SUBSTATE() AMEC_SUBSTATE(&G_amec_mst_state);
+#define AMEC_MST_SUB_SUBSTATE() AMEC_SUB_SUBSTATE(&G_amec_mst_state);
+
+#define AMEC_MST_STATE_NEXT() AMEC_STATE_NEXT(&G_amec_mst_state);
+#define AMEC_MST_SUBSTATE_NEXT() AMEC_SUBSTATE_NEXT(&G_amec_mst_state);
+#define AMEC_MST_SUB_SUBSTATE_NEXT() AMEC_SUB_SUBSTATE_NEXT(&G_amec_mst_state);
+
+#define AMEC_MST_SET_MNFG_FMIN(a) AMEC_MST_CUR_MNFG_FMIN() = a
+#define AMEC_MST_SET_MNFG_FMAX(a) AMEC_MST_CUR_MNFG_FMAX() = a
+#define AMEC_MST_SET_MNFG_FSTEP(a) g_amec->mnfg_parms.fstep = a
+#define AMEC_MST_SET_MNFG_DELAY(a) g_amec->mnfg_parms.delay = a
+#define AMEC_MST_START_AUTO_SLEW() g_amec->mnfg_parms.auto_slew = 1
+#define AMEC_MST_STOP_AUTO_SLEW() g_amec->mnfg_parms.auto_slew = 0
+#define AMEC_MST_CUR_SLEW_COUNT() g_amec->mnfg_parms.slew_counter
+#define AMEC_MST_CUR_MNFG_FMIN() g_amec->mnfg_parms.fmin
+#define AMEC_MST_CUR_MNFG_FMAX() g_amec->mnfg_parms.fmax
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+extern const smh_tbl_t amec_mst_state_table[AMEC_SMH_STATES_PER_LVL];
+extern smh_state_t G_amec_mst_state;
+extern smh_state_timing_t G_amec_mst_state_timings;
+
+typedef struct
+{
+ uint16_t active_pcap;
+ uint8_t pcap_valid;
+ uint8_t reserved;
+}slave_pcap_info_t;
+
+extern slave_pcap_info_t G_slave_active_pcaps[MAX_OCCS]; //@db001a @rt004c
+extern uint8_t G_pcaps_mismatch_count; //@db001a
+extern uint8_t G_over_cap_count; //@db001a
+extern uint16_t G_mst_soft_fmin;
+extern uint16_t G_mst_soft_fmax;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void amec_mst_update_smh_sensors(int i_smh_state, uint32_t i_duration);
+
+// PRE: master common tasks
+void amec_mst_common_tasks_pre(void);
+// POST: master common tasks
+void amec_mst_common_tasks_post(void);
+
+// Master auto-slewing function
+void amec_master_auto_slew(void);
+// OCC Power cap mismatch function @db001a
+void amec_mst_check_pcaps_match(void);
+// Check if under power cap function @db001a
+void amex_mst_check_under_pcap(void);
+// Idle Power Saver main algorithm
+void amec_mst_ips_main(void);
+// Get the current Idle Power Saver active status
+uint8_t AMEC_mst_get_ips_active_status();
+void amec_mst_gen_soft_freq(void);
+
+// Master States
+void amec_mst_state_0(void);
+void amec_mst_state_1(void);
+void amec_mst_state_2(void);
+void amec_mst_state_3(void);
+void amec_mst_state_4(void);
+void amec_mst_state_5(void);
+void amec_mst_state_6(void);
+void amec_mst_state_7(void);
+
+// Master SubState 0
+void amec_mst_substate_0_0(void);
+void amec_mst_substate_0_1(void);
+void amec_mst_substate_0_4(void);
+void amec_mst_substate_0_7(void);
+
+// Master SubState 3
+void amec_mst_substate_3_0(void);
+void amec_mst_substate_3_1(void);
+void amec_mst_substate_3_2(void);
+void amec_mst_substate_3_6(void);
+void amec_mst_substate_3_7(void);
+
+// Master Sub-SubState 3
+void amec_mst_sub_substate_3_0_0(void);
+void amec_mst_sub_substate_3_0_1(void);
+void amec_mst_sub_substate_3_0_7(void);
+
+// Master SubState 6
+void amec_mst_substate_6_0(void);
+void amec_mst_substate_6_1(void);
+void amec_mst_substate_6_2(void);
+void amec_mst_substate_6_3(void);
+void amec_mst_substate_6_4(void);
+void amec_mst_substate_6_5(void);
+void amec_mst_substate_6_6(void);
+void amec_mst_substate_6_7(void);
+
+void amec_mst_substate_3_0(void);
+void amec_mst_substate_3_1(void);
+
+void amec_mst_sub_substate_6_1_0(void);
+void amec_mst_sub_substate_6_1_1(void);
+void amec_mst_sub_substate_6_1_2(void);
+void amec_mst_sub_substate_6_1_3(void);
+void amec_mst_sub_substate_6_1_4(void);
+void amec_mst_sub_substate_6_1_5(void);
+void amec_mst_sub_substate_6_1_6(void);
+void amec_mst_sub_substate_6_1_7(void);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif
diff --git a/src/occ/amec/amec_oversub.c b/src/occ/amec/amec_oversub.c
new file mode 100755
index 0000000..2b967b7
--- /dev/null
+++ b/src/occ/amec/amec_oversub.c
@@ -0,0 +1,272 @@
+/******************************************************************************
+// @file amec_oversub.c
+// @brief Over-subscription
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_oversub_c amec_oversub.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+ * @th028 867841 thallet 01/22/2013 Trace in oversubscription causes panic
+ * @fk001 879727 fmkassem 04/16/2013 PCAP support.
+ * @at020 908666 alvinwan 12/16/2013 Oversubscription Error Handling
+ * @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+ * @gm026 916029 milesg 02/17/2014 revert back to auto2 mode without reading GPIO's
+ * @gm041 928150 milesg 06/02/2014 add callout for mfg oversubscription elog
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+
+#include <occ_common.h>
+#include <trac.h>
+#include <amec_sys.h>
+#include <proc_pstate.h>
+#include <dcom.h>
+#include <occ_sys_config.h>
+#include <amec_service_codes.h>
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define OVERSUB_REASON_DELAY_4MS 16 // 4ms (unit is 250us)
+#define OVERSUB_REASON_COUNT_TIMEOUT 2
+#define OVERSUB_REASON_DETERMINED 1
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
+
+
+// Function Specification
+//
+// Name: amec_oversub_pmax_clip
+//
+// Description: Set Pmax_Clip in PMC to lowest Pstate
+//
+//
+// Flow: FN=
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_oversub_pmax_clip(Pstate i_pstate)
+{
+ pmc_rail_bounds_register_t prbr;
+
+ // Set Pmax_Clip in PMC to lowest Pstate
+ prbr.value = in32(PMC_RAIL_BOUNDS_REGISTER);
+ prbr.fields.pmax_rail = i_pstate; //@fk001c
+ out32(PMC_RAIL_BOUNDS_REGISTER, prbr.value);
+}
+
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+// Function Specification
+//
+// Name: amec_oversub_isr
+//
+// Description: Oversubscription ISR
+//
+// Flow: FN=
+//
+// Task Flags:
+//
+// Note: This function is only ever called from Critical interrupt context
+//
+// End Function Specification
+
+void amec_oversub_isr(void)
+{
+ static uint32_t l_isr_count = 0;
+ static uint8_t l_polarity = SSX_IRQ_POLARITY_ACTIVE_LOW; // Default is low
+ uint8_t l_cur_polarity = l_polarity;
+
+ l_isr_count++;
+
+ // SSX_IRQ_POLARITY_ACTIVE_LOW means over-subscription is active
+ if(l_polarity == SSX_IRQ_POLARITY_ACTIVE_LOW)
+ {
+ // If RTL doesn't control it, do it here
+ if(g_amec->oversub_status.oversubLatchAmec == 0)
+ {
+ // Set PMC Pmax_clip to Pmin and throttle all Cores via OCI write to PMC
+ amec_oversub_pmax_clip(gpst_pmin(&G_global_pstate_table)); //@fk001c
+ // TODO: Throttle all Centaurs via PORE-GPE by setting 'Emergency Throttle'
+
+ g_amec->oversub_status.oversubReasonLatchCount = OVERSUB_REASON_DELAY_4MS;
+ }
+
+ // Set oversubPinLive and oversubActiveTime
+ g_amec->oversub_status.oversubPinLive = 1;
+ g_amec->oversub_status.oversubActiveTime = ssx_timebase_get();
+
+ // Setup the IRQ
+ ssx_irq_setup(PGP_IRQ_EXTERNAL_TRAP,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+ l_polarity = SSX_IRQ_POLARITY_ACTIVE_HIGH;
+
+ }
+ else // over-subscription is inactive
+ {
+ // Clear oversubPinLive
+ g_amec->oversub_status.oversubPinLive = 0;
+
+ // Set oversubInActiveTime
+ g_amec->oversub_status.oversubInactiveTime = ssx_timebase_get();
+
+ // Setup the IRQ
+ ssx_irq_setup(PGP_IRQ_EXTERNAL_TRAP,
+ SSX_IRQ_POLARITY_ACTIVE_LOW,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+
+ l_polarity = SSX_IRQ_POLARITY_ACTIVE_LOW;
+ }
+
+ // Trace Oversub Event, Polarity and ISR count
+ TRAC_INFO("Oversub IRQ - Polarity (low active):%d, oversubPinLive: %d, count: %d)", l_cur_polarity, g_amec->oversub_status.oversubPinLive, l_isr_count);
+
+}
+
+// Function Specification
+//
+// Name: amec_oversub_check
+//
+// Description: Oversubscription check called in
+// amec_slv_common_tasks_pre()
+//
+//
+// Flow: FN=
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_oversub_check(void)
+{
+ //uint8_t l_cme_pin = G_sysConfigData.apss_gpio_map.cme_throttle_n; //gm026
+ uint8_t l_cme_pin_value = 1; // low active, so set default to high
+ static BOOLEAN l_prev_ovs_state = FALSE; // oversub happened // @at020a
+
+ // Get CME Pin state
+ // No longer reading gpio from APSS in GA1 due to instability in APSS composite mode -- gm026
+ //apss_gpio_get(l_cme_pin, &l_cme_pin_value); // @at020a
+
+ // Check CME Pin? OR CME Oversub Mnfg Active
+ if( (l_cme_pin_value == 0) ||
+ (g_amec->oversub_status.cmeThrottlePinMnfg == 1) )
+ {
+ g_amec->oversub_status.cmeThrottlePinLive = 1;
+ g_amec->oversub_status.cmeThrottleLatchAmec = 1;
+ }
+ else
+ {
+ // Do not clear cmeThrottleLatchAmec.
+ // That will only be done via the PowerCa command from TMGT.
+ g_amec->oversub_status.cmeThrottlePinLive = 0;
+ }
+
+ // @at020a - start
+ // oversubscription condition happened?
+ if ( AMEC_INTF_GET_OVERSUBSCRIPTION() == TRUE )
+ {
+ if ( l_prev_ovs_state != TRUE)
+ {
+ l_prev_ovs_state = TRUE;
+
+ TRAC_ERR("Oversubscription condition happened");
+ /* @
+ * @errortype
+ * @moduleid AMEC_SLAVE_CHECK_PERFORMANCE
+ * @reasoncode OVERSUB_ALERT
+ * @userdata1 Previous OVS State
+ * @userdata4 ERC_AMEC_SLAVE_OVS_STATE
+ * @devdesc Oversubscription condition happened
+ */
+ errlHndl_t l_errl = createErrl(AMEC_SLAVE_CHECK_PERFORMANCE,//modId
+ OVERSUB_ALERT, //reasoncode
+ ERC_AMEC_SLAVE_OVS_STATE, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_prev_ovs_state, //userdata1
+ 0); //userdata2
+
+ // set the mfg action flag (allows callout to be added to info error)
+ setErrlActions(l_errl, ERRL_ACTIONS_MANUFACTURING_ERROR);
+
+ // add the oversubscription symbolic callout -- gm041
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_OVERSUBSCRIPTION,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // Commit Error
+ commitErrl(&l_errl);
+ }
+ }
+ else
+ {
+ l_prev_ovs_state = FALSE;
+ }
+ // @at020a - end
+
+
+
+ // TODO: Set any more oversub based on APSS GPIO Pins (i.e. Orlena 12V OC pins)
+
+ // Figure out the over-subscription reason
+ if(g_amec->oversub_status.oversubReasonLatchCount > 1)
+ {
+ // Try to figure out why we throttled based on APSS GPIO pins
+ if( g_amec->oversub_status.oversubReasonLatchCount == OVERSUB_REASON_COUNT_TIMEOUT)
+ {
+ g_amec->oversub_status.oversubReason = INDETERMINATE;
+ g_amec->oversub_status.oversubReasonLatchCount = OVERSUB_REASON_DETERMINED;
+
+ TRAC_INFO("Oversub (oversubReason: %d)", g_amec->oversub_status.oversubReason );
+ }
+ else
+ {
+ // If we can figure out why oversub happened, set oversubReason to valide enum value
+ // then set oversubReasonLatchCount = 1
+
+ // If we can't figure it out, decrease oversubReasonLatchCount and we will try again in 250us
+ g_amec->oversub_status.oversubReasonLatchCount--; // The unit of oversubReasonLatchCount is 250us
+
+ }
+ }
+
+}
diff --git a/src/occ/amec/amec_oversub.h b/src/occ/amec/amec_oversub.h
new file mode 100755
index 0000000..1dc61e8
--- /dev/null
+++ b/src/occ/amec/amec_oversub.h
@@ -0,0 +1,139 @@
+/******************************************************************************
+// @file amec_oversub.c
+// @brief Over-subscription
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_oversub_h amec_oversub.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+ * @gs004 883829 gjsilva 05/21/2013 Emulate oversubscription macro
+ * @fk001 879727 fmkassem 04/16/2013 PCAP support.
+ * @at020 908666 alvinwan 12/16/2013 Oversubscription Error Handling
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_OVERSUB_H
+#define _AMEC_OVERSUB_H
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <occ_sys_config.h> // @at010a Added for sys config access
+#include <dcom.h>
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Defines */
+/*----------------------------------------------------------------------------*/
+// @at020c
+#define AMEC_INTF_GET_OVERSUBSCRIPTION() \
+(G_sysConfigData.failsafe_enabled ? g_amec->oversub_status.cmeThrottlePinLive : \
+ (g_amec->oversub_status.oversubPinLive || G_dcom_slv_inbox_rx.emulate_oversub))
+
+#define AMEC_INTF_GET_OVERSUBSCRIPTION_EMULATION() g_amec->oversub_status.oversubPinMnfg
+
+// @at020c
+#define AMEC_INTF_GET_FAILSAFE() \
+(G_sysConfigData.failsafe_enabled ? g_amec->oversub_status.oversubPinLive : 0)
+
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+typedef enum oversub_reason
+{
+ PENDING_OR_INVALID = 0x00,
+ FANS_FULL_SPEED = 0x01,
+ FAN_ERRROR = 0x02,
+ FAN_WARNING = 0x03,
+ ITE_FAILSAFE = 0x04,
+
+ INDETERMINATE = 0xFF
+}oversub_reason_t;
+
+typedef struct oversub_status
+{
+ // Way to emulate oversub for MNFG or Developers
+ uint32_t oversubPinMnfg : 1;
+
+ // Live Status of oversub Pin
+ uint32_t oversubPinLive : 1;
+
+ // AMEC status of oversub pin, so it doesn't
+ // change mid-RTL
+ uint32_t oversubLatchAmec : 1;
+
+ // Used for SRC logging of performance loss,
+ // need to have countdown b/c we don't get
+ // APSS gpio signals as quick as we get
+ // oversub.
+ uint8_t oversubReasonLatchCount;
+ oversub_reason_t oversubReason;
+
+ // For debug, tracks time oversub last went inactive
+ SsxTimebase oversubInactiveTime;
+
+ // For debug, tracks time oversub last went active
+ SsxTimebase oversubActiveTime;
+
+ // Live status of CME throttle pin, doesn't change mid-RTL
+ uint32_t cmeThrottlePinLive :1;
+
+ // Status of CME Throttle, doesn't get cleared until MM/TMGT
+ // tells us to clear it/un-throttle.
+ uint32_t cmeThrottleLatchAmec :1;
+
+ // Way to emulate cmeThrottle for MNFG or Developers
+ uint32_t cmeThrottlePinMnfg :1;
+}oversub_status_t;
+
+
+/*----------------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief Oversubscription ISR
+ *
+ * This function
+ *
+ * @return No return from this function.
+ */
+void amec_oversub_isr(void);
+
+
+/**
+ * @brief Oversubscription check
+ *
+ * This function
+ *
+ * @return No return from this function.
+ */
+void amec_oversub_check(void);
+
+/**
+ * @brief Oversubscription set Pmax clip
+ *
+ * This function will set the pmax clip register
+ *
+ * @return No return from this function
+ */
+void amec_oversub_pmax_clip(Pstate i_pstate);
+
+bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value);
+
+#endif //_AMEC_OVERSUB_H
diff --git a/src/occ/amec/amec_parm.c b/src/occ/amec/amec_parm.c
new file mode 100755
index 0000000..0235cf5
--- /dev/null
+++ b/src/occ/amec/amec_parm.c
@@ -0,0 +1,302 @@
+/******************************************************************************
+// @file amec_parm.c
+// @brief OCC Amester parameter interface.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section amec_parm_c amec_parm.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @cl002 903552 lefurgy 08/02/2013 Created
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h>
+#include <amec_parm.h>
+#include <string.h>
+#include <stdlib.h>
+#include <occ_common.h>
+#include <amec_amester.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+///Array that maintains a list of all parameters built
+extern amec_parm_t g_amec_parm_list[];
+
+//*************************************************************************
+// Function Declarations
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+void amec_parm_get_number(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ o_pu8Resp[0] = (UINT8)(AMEC_PARM_NUMBER_OF_PARAMETERS>>8);
+ o_pu8Resp[1] = (UINT8)(AMEC_PARM_NUMBER_OF_PARAMETERS);
+
+ *o_pu16RespLength=2;
+ *o_retval=COMPCODE_NORMAL;
+
+ return;
+}
+
+
+void amec_parm_get_config(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ AMEC_PARM_GUID l_id; // parameter id
+ UINT16 l_j; // index into return message
+ UINT16 l_length = 0; // response length
+ CHAR *l_src; //pointer for copying name
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ l_id = (AMEC_PARM_GUID) CONVERT_UINT8_ARRAY_UINT16(
+ i_psMsg->au8CmdData_ptr[1],
+ i_psMsg->au8CmdData_ptr[2]);
+ l_j = 0; // write index byte for response
+
+ for (; l_id < AMEC_PARM_NUMBER_OF_PARAMETERS; l_id++)
+ {
+ if (l_j + strlen(g_amec_parm_list[l_id].name) + 1 + 10 >= IPMI_MAX_MSG_SIZE)
+ {
+ // +1 = null terminator in name.
+ // +10 = type, mode, vector_length, length (optional)
+ break; // hit end of response buffer
+ }
+
+ // Copy name into output buffer
+ l_src = g_amec_parm_list[l_id].name;
+ do
+ {
+ o_pu8Resp[l_j++] = *l_src;
+ } while (*l_src++ != 0); /* copy string until \0 */
+
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].type);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].mode);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].vector_length>>24);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].vector_length>>16);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].vector_length>>8);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].vector_length);
+
+ // If base type is unstructured data or string, send length
+ if (g_amec_parm_list[l_id].type == AMEC_PARM_TYPE_STRING ||
+ g_amec_parm_list[l_id].type == AMEC_PARM_TYPE_RAW)
+ {
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].length>>24);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].length>>16);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].length>>8);
+ o_pu8Resp[l_j++] = (UINT8)(g_amec_parm_list[l_id].length);
+ }
+
+ // update length of response parameter just copied
+ l_length = l_j;
+ }
+ *o_pu16RespLength=l_length;
+ *o_retval=COMPCODE_NORMAL;
+ return;
+}
+
+
+void amec_parm_read(const IPMIMsg_t *const i_psMsg,
+ UINT8 *const o_pu8Resp,
+ UINT16 *const o_pu16RespLength,
+ UINT8 *const o_retval)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ AMEC_PARM_GUID l_id;
+ UINT16 i=0; // output index
+ UINT16 l_maxresponse = IPMI_MAX_MSG_SIZE - 1; // -1 since return code is 1B
+ UINT8 *l_src_ptr; // pointer to first byte of data
+ UINT8 *l_end_ptr; // mark end of data
+ UINT32 b; // start byte
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ *o_retval = COMPCODE_NORMAL; /* assume no error */
+
+ // Parse input command
+ // Get the byte offset
+ b = CONVERT_UINT8_ARRAY_UINT32(
+ i_psMsg->au8CmdData_ptr[1],
+ i_psMsg->au8CmdData_ptr[2],
+ i_psMsg->au8CmdData_ptr[3],
+ i_psMsg->au8CmdData_ptr[4]);
+
+ // Get parameter id
+ l_id = CONVERT_UINT8_ARRAY_UINT16(
+ i_psMsg->au8CmdData_ptr[5],
+ i_psMsg->au8CmdData_ptr[6]);
+
+ if (l_id >= AMEC_PARM_NUMBER_OF_PARAMETERS)
+ {
+ *o_retval = COMPCODE_PARAM_OUT_OF_RANGE;
+ *o_pu16RespLength = 0;
+ break;
+ }
+
+ if (g_amec_parm_list[l_id].preread)
+ {
+ amec_parm_preread(l_id);
+ }
+
+ // Copy value to output buffer
+ // Set src to first byte to send back
+ l_src_ptr = g_amec_parm_list[l_id].value_ptr + b;
+
+ // Set end pointer 1 beyond last byte to send. It is limited either
+ // on the value size, or the IPMI message size.
+ l_end_ptr = g_amec_parm_list[l_id].value_ptr
+ + (g_amec_parm_list[l_id].vector_length * g_amec_parm_list[l_id].length);
+ if (l_src_ptr + l_maxresponse < l_end_ptr)
+ {
+ l_end_ptr = l_src_ptr + l_maxresponse;
+ }
+
+ while ((UINT32)l_src_ptr < (UINT32)l_end_ptr)
+ {
+ //Copy next byte to output
+ o_pu8Resp[i++] = (UINT8)*l_src_ptr++;
+ }
+
+ *o_pu16RespLength = i;
+
+ } while (FALSE);
+}
+
+
+void amec_parm_write(const IPMIMsg_t *const i_psMsg,
+ UINT8 *const o_pu8Resp,
+ UINT16 *const o_pu16RespLength,
+ UINT8 *const o_retval)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ AMEC_PARM_GUID l_id;
+ UINT16 i=0; // output index
+ UINT8 *l_dest_ptr = NULL; // malloc(sizeof(l_dest_ptr)); // pointer to first byte of data
+ UINT8 *l_start_ptr; // mark end of data
+ UINT8 *l_end_ptr = NULL;//malloc(sizeof(l_end_ptr)); // mark end of data
+ UINT32 b; // start byte
+ UINT32 l_bytes = 0; // number of bytes written
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ *o_retval = COMPCODE_NORMAL; /* assume no error */
+
+ // Parse input command
+ // Get parameter id
+ l_id = CONVERT_UINT8_ARRAY_UINT16(
+ i_psMsg->au8CmdData_ptr[1],
+ i_psMsg->au8CmdData_ptr[2]);
+
+ // Get the starting byte of element
+ b = CONVERT_UINT8_ARRAY_UINT32(
+ i_psMsg->au8CmdData_ptr[3],
+ i_psMsg->au8CmdData_ptr[4],
+ i_psMsg->au8CmdData_ptr[5],
+ i_psMsg->au8CmdData_ptr[6]);
+
+ if (l_id >= AMEC_PARM_NUMBER_OF_PARAMETERS)
+ {
+ *o_retval = COMPCODE_PARAM_OUT_OF_RANGE;
+ *o_pu16RespLength = 0;
+ break;
+ }
+
+ i = 7; // start of data to write in input buffer
+
+ // Check if read-only
+ if (g_amec_parm_list[l_id].mode & AMEC_PARM_MODE_READONLY)
+ {
+ *o_retval = COMPCODE_WRONG_PRIV;
+ *o_pu16RespLength = 0;
+ break;
+ }
+
+ l_start_ptr = g_amec_parm_list[l_id].value_ptr + b;
+ l_dest_ptr = l_start_ptr;
+ // Set end pointer 1 beyond last byte to send. It is limited either
+ // on the value size, or the IPMI message size.
+ l_end_ptr = g_amec_parm_list[l_id].value_ptr
+ + (g_amec_parm_list[l_id].vector_length * g_amec_parm_list[l_id].length);
+
+ // Copy value from input buffer
+ while ((UINT32)l_dest_ptr < (UINT32)l_end_ptr
+ && i < i_psMsg->u8CmdDataLen)
+ {
+ *l_dest_ptr++ = i_psMsg->au8CmdData_ptr[i++];
+ }
+
+ l_bytes = l_dest_ptr - l_start_ptr;
+
+ // Return number of bytes written
+ *o_pu16RespLength = 4;
+ o_pu8Resp[0] = (UINT8)(l_bytes >> 24);
+ o_pu8Resp[1] = (UINT8)(l_bytes >> 16);
+ o_pu8Resp[2] = (UINT8)(l_bytes >> 8);
+ o_pu8Resp[3] = (UINT8)(l_bytes);
+
+ // Run post-write routine only if last byte of parameter was written
+ // Some long parameters require multiple write calls due to IPMI
+ // message limits, so we only call the postwrite routine when the
+ // last byte of the parameter is written.
+ if (l_dest_ptr == l_end_ptr && g_amec_parm_list[l_id].postwrite)
+ {
+ amec_parm_postwrite(l_id);
+ }
+
+ } while (FALSE);
+}
+
+/*----------------------------------------------------------------------------*/
+/* End */
+/*----------------------------------------------------------------------------*/
diff --git a/src/occ/amec/amec_parm.h b/src/occ/amec/amec_parm.h
new file mode 100755
index 0000000..8c5aa86
--- /dev/null
+++ b/src/occ/amec/amec_parm.h
@@ -0,0 +1,202 @@
+/**
+ * @file amec_parm.h
+ * @brief Header file for AMEC Parameter interface.
+ *
+ *
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_parm_h amec_parm.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- --------- ----------------------------------
+ * @cl002 903552 lefurgy 08/02/2013 Created
+ * @gs018 907196 gjsilva 11/20/2013 Base support for soft frequency boundaries
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ *
+ * @endverbatim
+ */
+
+/*
+ This interface takes named memory objects (such as global variables)
+ and makes them accessible to Amester parameter for reading and
+ writing. Any memory location may become an Amester parameter.
+
+ To add a parameter,
+ 1. Add a new parameter id number in the AMEC_PARM_ENUM below.
+ 2. In the same position, add the parameter to g_amec_parm_list in
+ amec_parm_table.c
+ There are macros that help in adding a parameter to the table.
+ The macro typically takes a) the parameter id, b) a string name,
+ and c) a pointer to the memory location.
+*/
+
+#ifndef _AMEC_PARM_H
+#define _AMEC_PARM_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <amec_amester.h>
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// List of all parameters
+// NOTE: The parameters must be in the same order as g_amec_parm_list[] in
+// amec_parm_table.c
+typedef enum
+{
+ PARM_SYS_FMAX,
+ PARM_SYS_FMIN,
+ PARM_GPST,
+ PARM_PSTATE_MHZ,
+ PARM_FREQ_REASON,
+ PARM_FREQ_OR,
+ PARM_FREQ_OR_EN,
+ PARM_SYS_THRM_SP,
+ PARM_SYS_THRM_GAIN,
+ PARM_SYS_THRM_RES,
+ PARM_SYS_THRM_SPEED,
+ PARM_SYS_THRM_FREQ,
+ PARM_SOFT_FMIN,
+ PARM_SOFT_FMAX,
+ PARM_TOD,
+ AMEC_PARM_NUMBER_OF_PARAMETERS
+} AMEC_PARM_ENUM;
+
+typedef enum
+{
+ AMEC_PARM_TYPE_UINT8 = 0,
+ AMEC_PARM_TYPE_UINT16,
+ AMEC_PARM_TYPE_UINT32,
+ AMEC_PARM_TYPE_UINT64,
+ AMEC_PARM_TYPE_INT8,
+ AMEC_PARM_TYPE_INT16,
+ AMEC_PARM_TYPE_INT32,
+ AMEC_PARM_TYPE_INT64,
+ AMEC_PARM_TYPE_STRING,
+ AMEC_PARM_TYPE_RAW
+
+} AMEC_PARM_TYPE_ENUM;
+
+#define AMEC_PARM_MODE_NORMAL (0x00)
+#define AMEC_PARM_MODE_READONLY (0x01)
+
+// Length includes null byte terminator. 15 readable characters are allowed.
+#define AMEC_PARM_NAME_LENGTH 16
+
+typedef struct amec_parm_s
+{
+ /// name of parameter
+ CHAR name[AMEC_PARM_NAME_LENGTH];
+ /// value_ptr: pointer to data
+ UINT8 *value_ptr;
+ /// number of bytes in base data
+ UINT32 length;
+ /// vector_length is the number of items in the array pointed by value ptr.
+ UINT32 vector_length;
+ /// Type of data
+ UINT8 type : 4;
+ /// Mode of data (read-write, read-only, etc.)
+ UINT8 mode : 1;
+ /// If preread is 1, call amec_parm_preread(GUID) before reading parameter value.
+ UINT8 preread : 1;
+ /// If postwrite is 1, call amec_parm_postwrite(GUID) before reading parameter value.
+ UINT8 postwrite : 1;
+} amec_parm_t;
+
+typedef UINT16 AMEC_PARM_GUID;
+
+extern amec_parm_t g_amec_parm_list[];
+
+/*******************************************************************/
+/* Function Definitions */
+/*******************************************************************/
+
+/**
+ * @brief Get number of parameters
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Return number of parameters tracked by TPMD
+ *
+ */
+void amec_parm_get_number(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval);
+
+/**
+ * @brief Get parameter configuration (names, types, size, etc.)
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Get the configuration of the parameters (names, size, type, etc.)
+ *
+ */
+void amec_parm_get_config(const IPMIMsg_t *i_psMsg,
+ UINT8 *o_pu8Resp,
+ UINT16 *o_pu16RespLength,
+ UINT8 *o_retval);
+
+/**
+ * @brief Get parameter value
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Read a parameter value
+ *
+ */
+void amec_parm_read(const IPMIMsg_t *const i_psMsg,
+ UINT8 *const o_pu8Resp,
+ UINT16 *const o_pu16RespLength,
+ UINT8 *const o_retval);
+
+/**
+ * @brief Set a parameter value
+ * @param i_psMsg IPMI command
+ * @param o_pu8Resp Response string
+ * @param o_pu8RespLength Response string length
+ * @param o_retval Command response error code (=0 pass)
+ *
+ * Write a value to a parameter
+ *
+ */
+void amec_parm_write(const IPMIMsg_t *const i_psMsg,
+ UINT8 *const o_pu8Resp,
+ UINT16 *const o_pu16RespLength,
+ UINT8 *const o_retval);
+
+/**
+ * @brief Update parameter value before reading
+ * @param i_parm_guid The parameter number
+ *
+ * Some parameters need to be updated before reading.
+ * For example, a parameter that points to double-buffered
+ * that may be at a new memory location each time the
+ * parameter is examined.
+ * This routine only needs to be called when the parameter
+ * has a 'preread' field with a value of 1.
+ */
+void amec_parm_preread(AMEC_PARM_GUID i_parm_guid);
+
+/**
+ * @brief Update parameter value before reading
+ * @param i_parm_guid The parameter number
+ *
+ * Some parameters trigger actions after writing.
+ * This routine only needs to be called when the parameter
+ * has been written and has a 'postwrite' field with a value of 1.
+ */
+void amec_parm_postwrite(AMEC_PARM_GUID i_parm_guid);
+
+#endif
diff --git a/src/occ/amec/amec_parm_table.c b/src/occ/amec/amec_parm_table.c
new file mode 100755
index 0000000..042e222
--- /dev/null
+++ b/src/occ/amec/amec_parm_table.c
@@ -0,0 +1,160 @@
+/******************************************************************************
+// @file amec_parm_table.c
+// @brief OCC Amester parameter table.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section amec_parm_table_c amec_parm_table.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @cl002 903552 lefurgy 08/02/2013 Created
+ * @gs018 907196 gjsilva 11/20/2013 Base support for soft frequency boundaries
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h> //STATIC_ASSERT macro
+#include <amec_parm.h>
+#include <amec_sys.h>
+#include <proc_pstate.h> //global pstate table parameter
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+// Macros for parameters based on simple variables (read-write, not vectors)
+/**
+ * @brief Create or update a parameter
+ *
+ * @param i_name Name of parameter. If this name is the name of an
+ * existing parameter, then the existing parameter fields
+ * will be updated
+ * @param i_vaule A pointer to the bytes representing the value of the parameter
+ * @param i_length The length in bytes of the parameter value
+ * @param n The number of elements if this parameter is a vector, otherwise = 1.
+ */
+#define AMEC_PARM_UINT8(i_num, i_name, i_value) \
+ [i_num] = {i_name,(void*)i_value,1,1,AMEC_PARM_TYPE_UINT8,0}
+#define AMEC_PARM_UINT16(i_num, i_name, i_value) \
+ [i_num] = {i_name,(void*)i_value,2,1,AMEC_PARM_TYPE_UINT16,0}
+#define AMEC_PARM_UINT32(i_num, i_name, i_value) \
+ [i_num] = {i_name,(void*)i_value,4,1,AMEC_PARM_TYPE_UINT32,0}
+#define AMEC_PARM_UINT64(i_num, i_name, i_value) \
+ [i_num] = {i_name,(void*)i_value,8,1,AMEC_PARM_TYPE_UINT64,0}
+#define AMEC_PARM_INT8(i_num, i_name, i_value) \
+ [i_num] = {i_name,(void*)i_value,1,1,AMEC_PARM_TYPE_INT8,0}
+#define AMEC_PARM_INT16(i_num, i_name, i_value) \
+ [i_num] = {i_name,(void*)i_value,2,1,AMEC_PARM_TYPE_INT16,0}
+#define AMEC_PARM_INT32(i_num, i_name, i_value) \
+ [i_num] = {i_name,(void*)i_value,4,1,AMEC_PARM_TYPE_INT32,0}
+#define AMEC_PARM_INT64(i_num, i_name, i_value) \
+ [i_num] = {i_name,(void*)i_value,8,1,AMEC_PARM_TYPE_IN64,0}
+#define AMEC_PARM_STRING(i_num, i_name, i_value, i_length) \
+ [i_num] = {i_name,(void*)i_value,i_length,1,AMEC_PARM_TYPE_STRING,0}
+#define AMEC_PARM_RAW(i_num, i_name, i_value, i_length) \
+ [i_num] = {i_name,(void*)i_value,i_length,1,AMEC_PARM_TYPE_RAW,0}
+
+//Use these macros when the parameter is an array of values.
+#define AMEC_PARM_UINT8_ARRAY(i_num, i_name, i_value, n) \
+ [i_num] = {i_name,(void*)i_value,1,n,AMEC_PARM_TYPE_UINT8,0}
+#define AMEC_PARM_UINT16_ARRAY(i_num, i_name, i_value, n) \
+ [i_num] = {i_name,(void*)i_value,2,n,AMEC_PARM_TYPE_UINT16,0}
+#define AMEC_PARM_UINT32_ARRAY(i_num, i_name, i_value, n) \
+ [i_num] = {i_name,(void*)i_value,4,n,AMEC_PARM_TYPE_UINT32,0}
+#define AMEC_PARM_UINT64_ARRAY(i_num, i_name, i_value, n) \
+ [i_num] = {i_name,(void*)i_value,8,n,AMEC_PARM_TYPE_UINT64,0}
+#define AMEC_PARM_INT8_ARRAY(i_num, i_name, i_value, n) \
+ [i_num] = {i_name,(void*)i_value,1,n,AMEC_PARM_TYPE_INT8,0}
+#define AMEC_PARM_INT16_ARRAY(i_num, i_name, i_value, n) \
+ [i_num] = {i_name,(void*)i_value,2,n,AMEC_PARM_TYPE_INT16,0}
+#define AMEC_PARM_INT32_ARRAY(i_num, i_name, i_value, n) \
+ [i_num] = {i_name,(void*)i_value,4,n,AMEC_PARM_TYPE_INT32,0}
+#define AMEC_PARM_INT64_ARRAY(i_num, i_name, i_value, n) \
+ [i_num] = {i_name,(void*)i_value,8,n,AMEC_PARM_TYPE_IN64,0}
+#define AMEC_PARM_STRING_ARRAY(i_num, i_name, i_value, i_length, n) \
+ [i_num] = {i_name,(void*)i_value,i_length,n,AMEC_PARM_TYPE_STRING,0}
+#define AMEC_PARM_RAW_ARRAY(i_num, i_name, i_value, i_length, n) \
+ [i_num] = {i_name,(void*)i_value,i_length,n,AMEC_PARM_TYPE_RAW,0}
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+extern amec_sys_t g_amec_sys;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// This is the list of all parameters seen by Amester
+//
+// Note: The parameters must be in the same order as in AMEC_PARM_ENUM
+// in amec_parm.h
+//
+// Future optimization: This table could be placed in main memory, not
+// the SRAM tank, since slow access to it is OK.
+amec_parm_t g_amec_parm_list[] = {
+ // System fmin and fmax
+ AMEC_PARM_UINT16(PARM_SYS_FMAX,"sys_fmax",&g_amec_sys.sys.fmax),
+ AMEC_PARM_UINT16(PARM_SYS_FMIN,"sys_fmin",&g_amec_sys.sys.fmin),
+
+ // Global Pstate table
+ AMEC_PARM_RAW(PARM_GPST,"gpst",&G_global_pstate_table,sizeof(GlobalPstateTable)),
+ // MHz per pstate
+ AMEC_PARM_UINT32(PARM_PSTATE_MHZ,"pstate_mhz",&G_mhz_per_pstate),
+ // frequency reason code per-core
+ AMEC_PARM_UINT32_ARRAY(PARM_FREQ_REASON,"freq_reason",g_amec_sys.proc[0].parm_f_reason,MAX_NUM_CORES),
+ // frequency override speed in MHz per-core
+ AMEC_PARM_UINT16_ARRAY(PARM_FREQ_OR,"freq_or",g_amec_sys.proc[0].parm_f_override,MAX_NUM_CORES),
+ // frequency override enable bit (1=active)
+ AMEC_PARM_UINT8(PARM_FREQ_OR_EN,"freq_or_en",&g_amec_sys.proc[0].parm_f_override_enable),
+
+ // Thermal controller parameters
+ AMEC_PARM_UINT16(PARM_SYS_THRM_SP,"sys_thrm_sp",&g_amec_sys.thermalproc.setpoint),
+ AMEC_PARM_UINT16(PARM_SYS_THRM_GAIN,"sys_thrm_gain",&g_amec_sys.thermalproc.Pgain),
+ AMEC_PARM_UINT16(PARM_SYS_THRM_RES,"sys_thrm_res",&g_amec_sys.thermalproc.total_res),
+ AMEC_PARM_UINT16(PARM_SYS_THRM_SPEED,"sys_thrm_speed",&g_amec_sys.thermalproc.speed_request),
+ AMEC_PARM_UINT16(PARM_SYS_THRM_FREQ,"sys_thrm_freq",&g_amec_sys.thermalproc.freq_request),
+
+ // Partition related parameters
+ AMEC_PARM_UINT16(PARM_SOFT_FMIN,"part_soft_fmin",&g_amec_sys.part_config.part_list[0].soft_fmin),
+ AMEC_PARM_UINT16(PARM_SOFT_FMAX,"part_soft_fmax",&g_amec_sys.part_config.part_list[0].soft_fmax),
+ AMEC_PARM_RAW(PARM_TOD,"apss_tod",&G_dcom_slv_inbox_doorbell_rx.tod,8),
+};
+
+//Throw a compiler error when the enum and array are not both updated
+STATIC_ASSERT((AMEC_PARM_NUMBER_OF_PARAMETERS != (sizeof(g_amec_parm_list)/sizeof(amec_parm_t))));
+
+void amec_parm_preread(AMEC_PARM_GUID i_parm_guid)
+{
+ switch (i_parm_guid)
+ {
+ default:
+ break;
+ }
+}
+
+void amec_parm_postwrite(AMEC_PARM_GUID i_parm_guid)
+{
+ switch (i_parm_guid)
+ {
+ default:
+ break;
+ }
+}
diff --git a/src/occ/amec/amec_part.c b/src/occ/amec/amec_part.c
new file mode 100755
index 0000000..75ba84c
--- /dev/null
+++ b/src/occ/amec/amec_part.c
@@ -0,0 +1,475 @@
+/******************************************************************************
+ * @file amec_part.c
+ * @brief Partition Level Power Management
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_part_c amec_part.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @ly001 853751 lychen 09/17/2012 Initial Revision
+ * @ly002 860316 lychen 11/07/2012 Rename adding a core group function
+ * @gs008 894661 gjsilva 08/08/2013 Initial support for DPS-FP mode
+ * @gs009 897228 gjsilva 08/28/2013 Enablement of DPS-FP Mode
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @gs018 907196 gjsilva 11/20/2013 Base support for soft frequency boundaries
+ * @gs031 924042 gjsilva 04/21/2014 Support for DPS-FP mode in Brazos
+ * @gs037 933716 gjsilva 07/31/2014 Fix alpha_up and alpha_down resolution
+ *
+ * @endverbatim
+ *
+ ******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <common_types.h>
+#include <mode.h>
+#include <amec_sys.h>
+#include <amec_part.h>
+#include <trac.h>
+#include <dcom.h>
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Internal Function Prototypes */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Code */
+/*----------------------------------------------------------------------------*/
+
+// Given partition id, return pointer to existing partition or NULL
+static amec_part_t* amec_part_find_by_id(amec_part_config_t* i_config,
+ const uint8_t i_id)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_part_t *l_part = NULL;
+ uint16_t l_idx = 0;
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ for (l_idx=0; l_idx<AMEC_PART_MAX_PART; l_idx++)
+ {
+ if (i_config->part_list[l_idx].id == i_id && i_config->part_list[l_idx].valid)
+ {
+ l_part = &(i_config->part_list[l_idx]);
+ break;
+ }
+ }
+
+ return l_part;
+}
+
+// Function Specification
+//
+// Name: amec_isr_speed_to_freq
+//
+// Description: Given a core, return a valid partition that owns it, or NULL.
+//
+// Flow: FN= None
+//
+// End Function Specification
+amec_part_t* amec_part_find_by_core(amec_part_config_t* i_config,
+ const uint16_t i_core_index)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_part_t *l_part = NULL;
+ uint16_t l_part_index = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ if (i_core_index >= MAX_NUM_CORES)
+ {
+ break; // illegal core number
+ }
+ l_part_index = i_config->core2part[i_core_index];
+ if (l_part_index >= AMEC_PART_MAX_PART)
+ {
+ break; // illegal partition number
+ }
+ if (i_config->part_list[l_part_index].valid)
+ {
+ l_part = (amec_part_t*) &(i_config->part_list[l_part_index]);
+ }
+ } while(0);
+
+ return l_part;
+}
+
+// @ly002c
+// Function Specification
+//
+// Name: amec_part_add
+//
+// Description: Add a core group.
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_part_add(uint8_t i_id)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_part_t *l_part;
+ uint16_t l_idx = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ l_part = (amec_part_t*) amec_part_find_by_id(&g_amec->part_config,
+ i_id);
+ if (l_part != NULL)
+ {
+ break; // Partition already exists
+ }
+
+ // Find new slot
+ for (l_idx=0; l_idx<AMEC_PART_MAX_PART; l_idx++)
+ {
+ if (!g_amec->part_config.part_list[l_idx].valid)
+ {
+ l_part = &g_amec->part_config.part_list[l_idx];
+ break;
+ }
+ }
+
+ if (l_part == NULL)
+ {
+ // This should never happen, since table should be large enough
+ // to hold as many partitions as can be created on system.
+ break;
+ }
+
+ // Enter new partition into table with default values
+ l_part->id = i_id;
+ l_part->valid = 1; //Mark them as valid
+ l_part->ncores = 0; //No cores
+ for (l_idx=0; l_idx<AMEC_PART_NUM_CORES; l_idx++)
+ {
+ l_part->core_list[l_idx] = AMEC_PART_NUM_CORES;
+ }
+
+ // TODO: For now, create a single partition with all cores assigned to it
+ // until we write the interface to talk to PHYP
+ if (i_id == 0)
+ {
+ l_part->ncores = MAX_NUM_CORES;
+ for (l_idx=0; l_idx<MAX_NUM_CORES; l_idx++)
+ {
+ l_part->core_list[l_idx] = l_idx;
+ }
+ }
+
+ // Set default soft frequency boundaries to use full frequency range
+ l_part->soft_fmin = 0x0000;
+ l_part->soft_fmax = 0xFFFF;
+
+ // Set default values for DPS parameters (Favor Energy)
+ l_part->dpsalg.step_up = 8;
+ l_part->dpsalg.step_down = 8;
+ l_part->dpsalg.tlutil = 9800;
+ l_part->dpsalg.sample_count_util = 4;
+ l_part->dpsalg.epsilon_perc = 1800;
+ l_part->dpsalg.alpha_up = 9999;
+ l_part->dpsalg.alpha_down = 9999;
+ l_part->dpsalg.type = 0; //No algorithm is selected yet
+ l_part->dpsalg.freq_request = UINT16_MAX;
+
+ l_part->es_policy = OCC_INTERNAL_MODE_MAX_NUM;
+ l_part->follow_sysmode = TRUE;
+ }
+ while (0);
+
+ return;
+}
+
+void amec_part_init()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_idx = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // Initial core to partition mapping. Cores point to an invalid core group
+ // id.
+ // TODO: For now, we assume a single partition (id 0) with all cores
+ // assigned to it. Once the PHYP interface has been written, we can remove
+ // this assumption.
+ for (l_idx=0; l_idx<MAX_NUM_CORES; l_idx++)
+ {
+ g_amec->part_config.core2part[l_idx] = 0; // AMEC_PART_INVALID_ID;
+ }
+
+ for (l_idx=0; l_idx<AMEC_PART_MAX_PART; l_idx++)
+ {
+ // Creating all possible partitions
+ amec_part_add(l_idx); // @ly002c
+
+ g_amec->part_config.part_list[l_idx].dpsalg.util_speed_request = g_amec->sys.fmax;
+ }
+}
+
+void amec_part_update_dps_parameters(amec_part_t* io_part)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // If partition doesn't exist, just exit
+ if (io_part == NULL)
+ {
+ return;
+ }
+
+ // Check to see if parameter values have been overwritten by user
+ if (g_amec->slv_dps_param_overwrite == TRUE)
+ {
+ // Then, exit right away
+ return;
+ }
+
+ // By default, let's use the DPS-Favor Energy settings
+ io_part->dpsalg.step_up = 8;
+ io_part->dpsalg.step_down = 8;
+ io_part->dpsalg.tlutil = 9800;
+ io_part->dpsalg.sample_count_util = 4;
+ io_part->dpsalg.epsilon_perc = 1800;
+ io_part->dpsalg.alpha_up = 9990;
+ io_part->dpsalg.alpha_down = 9990;
+ io_part->dpsalg.type = 41;
+
+ // If core group policy is DPS-Favor Performance, then write those settings
+ if (io_part->es_policy == OCC_INTERNAL_MODE_DPS_MP)
+ {
+ io_part->dpsalg.step_up = 1000;
+ io_part->dpsalg.step_down = 8;
+ io_part->dpsalg.tlutil = 1000;
+ io_part->dpsalg.sample_count_util = 1;
+ io_part->dpsalg.epsilon_perc = 0;
+ io_part->dpsalg.alpha_up = 9990;
+ io_part->dpsalg.alpha_down = 9990;
+ io_part->dpsalg.type = 41;
+
+ // Check if this is a multi-node system (e.g., Brazos)
+ if (G_sysConfigData.system_type.single == 0)
+ {
+ // These parameter values will result in static turbo frequency
+ io_part->dpsalg.alpha_down = 0;
+ io_part->dpsalg.tlutil = 0;
+
+ TRAC_IMP("Multi-node system found! Updating DPS-FP parameters: single_node_bit[%u] alpha_down[%u] tlutil[%u]",
+ G_sysConfigData.system_type.single,
+ io_part->dpsalg.alpha_down,
+ io_part->dpsalg.tlutil);
+ }
+ }
+}
+
+void amec_part_update_perf_settings(amec_part_t* io_part)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t j = 0;
+ uint16_t l_core_index = 0;
+ amec_core_perf_counter_t* l_perf;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // If partition doesn't exist, just exit
+ if (io_part == NULL)
+ {
+ return;
+ }
+
+ switch (io_part->es_policy)
+ {
+ case OCC_INTERNAL_MODE_DPS:
+ case OCC_INTERNAL_MODE_DPS_MP:
+ // These policies require that we reset the internal performance
+ // settings of the cores in the partition
+ for (j=0; j<io_part->ncores; j++)
+ {
+ l_core_index = io_part->core_list[j];
+ l_perf = &g_amec->proc[0].core[l_core_index % MAX_NUM_CORES].core_perf;
+
+ memset(l_perf->ptr_util_slack_avg_buffer, 0, 2*MAX_UTIL_SLACK_AVG_LEN);
+ memset(l_perf->ptr_util_active_avg_buffer, 0, 2*MAX_UTIL_SLACK_AVG_LEN);
+ l_perf->util_active_core_counter = 0;
+ l_perf->util_slack_core_counter = 0;
+ l_perf->util_slack_accumulator = 0;
+ l_perf->util_active_accumulator = 0;
+ l_perf->ptr_putUtilslack = 0;
+ }
+ break;
+
+ default:
+ // For all other policies, reset the DPS frequency request
+ for (j=0; j<io_part->ncores; j++)
+ {
+ l_core_index = io_part->core_list[j];
+ g_amec->proc[0].core[l_core_index % MAX_NUM_CORES]
+ .core_perf.dps_freq_request = UINT16_MAX;
+ }
+ break;
+ }
+}
+
+void AMEC_part_update_sysmode_policy(OCC_MODE i_occ_internal_mode)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t i = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ for (i=0; i<AMEC_PART_MAX_PART; i++)
+ {
+ // If a core group is not valid, skip it
+ if (!g_amec->part_config.part_list[i].valid)
+ {
+ continue;
+ }
+ // If a core group has no cores assigned, skip it
+ if (g_amec->part_config.part_list[i].ncores == 0)
+ {
+ continue;
+ }
+
+ // If a core group is not following the system power mode, skip it
+ if (!g_amec->part_config.part_list[i].follow_sysmode)
+ {
+ continue;
+ }
+
+ // Set power mode for this core group to the system power mode
+ switch (i_occ_internal_mode)
+ {
+ case OCC_MODE_NOMINAL:
+ g_amec->part_config.part_list[i].es_policy = OCC_INTERNAL_MODE_NOM;
+ break;
+
+ case OCC_MODE_DYN_POWER_SAVE:
+ g_amec->part_config.part_list[i].es_policy = OCC_INTERNAL_MODE_DPS;
+ break;
+
+ case OCC_MODE_DYN_POWER_SAVE_FP:
+ g_amec->part_config.part_list[i].es_policy = OCC_INTERNAL_MODE_DPS_MP;
+ break;
+
+ default:
+ g_amec->part_config.part_list[i].es_policy = OCC_INTERNAL_MODE_UNDEFINED;
+ break;
+ }
+
+ // Update the DPS parameters based on the power policy
+ if ((g_amec->part_config.part_list[i].es_policy == OCC_INTERNAL_MODE_DPS) ||
+ (g_amec->part_config.part_list[i].es_policy == OCC_INTERNAL_MODE_DPS_MP))
+ {
+ amec_part_update_dps_parameters(&(g_amec->part_config.part_list[i]));
+ }
+
+ // Update internal performance settings for this partition
+ amec_part_update_perf_settings(&(g_amec->part_config.part_list[i]));
+
+ // Useful trace for debug
+ //TRAC_INFO("AMEC_part_update_sysmode_policy: Core_group[%u] Num_cores[%u] ES_policy[0x%02x]",
+ // i, g_amec->part_config.part_list[i].ncores,
+ // g_amec->part_config.part_list[i].es_policy);
+ }
+}
+
+void AMEC_part_overwrite_dps_parameters(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t i = 0;
+ uint16_t j = 0;
+ uint16_t l_core_index = 0;
+ amec_part_t* l_part = NULL;
+ amec_core_perf_counter_t* l_perf = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ for (i=0; i<AMEC_PART_MAX_PART; i++)
+ {
+ // If a core group is not valid, skip it
+ if (!g_amec->part_config.part_list[i].valid)
+ {
+ continue;
+ }
+ // If a core group has no cores assigned, skip it
+ if (g_amec->part_config.part_list[i].ncores == 0)
+ {
+ continue;
+ }
+
+ // Overwrite the DPS parameters based on values sent by Master OCC
+ l_part = &(g_amec->part_config.part_list[i]);
+ l_part->dpsalg.alpha_up = G_dcom_slv_inbox_rx.alpha_up;
+ l_part->dpsalg.alpha_down = G_dcom_slv_inbox_rx.alpha_down;
+ l_part->dpsalg.sample_count_util = G_dcom_slv_inbox_rx.sample_count_util;
+ l_part->dpsalg.step_up = G_dcom_slv_inbox_rx.step_up;
+ l_part->dpsalg.step_down = G_dcom_slv_inbox_rx.step_down;
+ l_part->dpsalg.epsilon_perc = G_dcom_slv_inbox_rx.epsilon_perc;
+ l_part->dpsalg.tlutil = G_dcom_slv_inbox_rx.tlutil;
+
+ // Update internal performance settings for each core on this partition
+ for (j=0; j<l_part->ncores; j++)
+ {
+ l_core_index = l_part->core_list[j];
+ l_perf = &g_amec->proc[0].core[l_core_index % MAX_NUM_CORES].core_perf;
+
+ memset(l_perf->ptr_util_slack_avg_buffer, 0, 2*MAX_UTIL_SLACK_AVG_LEN);
+ memset(l_perf->ptr_util_active_avg_buffer, 0, 2*MAX_UTIL_SLACK_AVG_LEN);
+ l_perf->util_active_core_counter = 0;
+ l_perf->util_slack_core_counter = 0;
+ l_perf->util_slack_accumulator = 0;
+ l_perf->util_active_accumulator = 0;
+ l_perf->ptr_putUtilslack = 0;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/* End */
+/*----------------------------------------------------------------------------*/
diff --git a/src/occ/amec/amec_part.h b/src/occ/amec/amec_part.h
new file mode 100755
index 0000000..21b68e1
--- /dev/null
+++ b/src/occ/amec/amec_part.h
@@ -0,0 +1,177 @@
+/******************************************************************************
+ * @file amec_parm.h
+ * @brief AMEC Parameter Header File
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_parm_h amec_parm.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @ly001 853751 lychen 09/17/2012 Initial Revision
+ * @ly002 860316 lychen 11/07/2012 Rename adding a core group function
+ * @gs008 894661 gjsilva 08/08/2013 Initial support for DPS-FP mode
+ * @gs009 897228 gjsilva 08/28/2013 Enablement of DPS-FP Mode
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @gs018 907196 gjsilva 11/20/2013 Base support for soft frequency boundaries
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ *
+ * @endverbatim
+ *
+ ******************************************************************************/
+
+#ifndef _AMEC_PART_H
+#define _AMEC_PART_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <mode.h>
+#include <sensor.h>
+#include <occ_sys_config.h>
+#include <amec_dps.h>
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Defines */
+/*----------------------------------------------------------------------------*/
+
+// Number of cores in system
+#define AMEC_PART_NUM_CORES (MAX_NUM_OCC * MAX_NUM_CORES)
+
+// On a given OCC, only 12 partitions can be defined
+#define AMEC_PART_MAX_PART MAX_NUM_CORES
+
+// Invalid core group ID
+#define AMEC_PART_INVALID_ID 0xFF
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+
+typedef struct amec_part
+{
+ ///Flag to indicate if the core group should follow the system power policy
+ BOOLEAN follow_sysmode;
+ ///EnergyScale power savings policy
+ OCC_INTERNAL_MODE es_policy;
+ ///Total number of cores in this core group.
+ uint8_t ncores;
+ ///List of cores group. Indices 0 to ncores-1 are valid. Valid values: 0 to
+ ///AMEC_PART_NUM_CORES-1.
+ uint8_t core_list[AMEC_PART_NUM_CORES];
+ ///Partition ID
+ uint8_t id;
+ ///Valid bit (=1 in use, =0 not in use)
+ uint8_t valid;
+ ///Soft min frequency boundary sent by PHYP
+ uint16_t soft_fmin;
+ ///Soft max frequency boundary sent by PHYP
+ uint16_t soft_fmax;
+ ///Power saving state
+ amec_dps_t dpsalg;
+ ///slack utilization sensor
+ sensor_t util2msslack;
+} amec_part_t;
+
+/**
+ * @struct amec_part_config_t
+ * @brief Partition Configuration Structure
+ *
+ * Main structure that contains the partition configuration for PLPM work.
+ */
+typedef struct amec_part_config
+{
+ ///Data structure holding core to partition mapping. The value
+ ///AMEC_PART_INVALID_ID means that a core is not mapped to a partition. A
+ ///value less than that means core is mapped to that partition index.
+ uint16_t core2part[MAX_NUM_CORES];
+
+ ///Data structure holding all active partitions (core groups)
+ amec_part_t part_list[AMEC_PART_MAX_PART];
+} amec_part_config_t;
+
+/*----------------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief Given a core, return a valid partition that owns it, or NULL.
+ * @param i_config Pointer to partition configuration
+ * @param i_core_index The core number 0 to AMEC_PART_NUM_CORES - 1
+ *
+ * @return Valid pointer to partition that owns core, else NULL.
+ */
+amec_part_t* amec_part_find_by_core(amec_part_config_t* i_config,
+ const uint16_t i_core_index);
+
+/**
+ * @brief Add a core group.
+ *
+ * This function adds a new core group and should only be called within the
+ * AMEC ISR.
+ *
+ * @param i_id Core group ID that needs to be added
+ *
+ * @return void
+ */
+void amec_part_add(uint8_t i_id); // @ly002c
+
+/**
+ * @brief Add a core group.
+ *
+ * @return void
+ */
+void amec_part_init(void);
+
+/**
+ * @brief Update the parameter values depending on the DPS mode
+ * that has been selected (Favor Energy or Favor
+ * Performance).
+ *
+ * @param io_part A valid partition descriptor
+ *
+ * @return void
+ */
+void amec_part_update_dps_parameter(amec_part_t* io_part);
+
+/**
+ * @brief Update the internal performance settings for those
+ * cores that belong to the input partition.
+ *
+ * @param io_part A valid partition descriptor
+ *
+ * @return void
+ */
+void amec_part_update_perf_settings(amec_part_t* io_part);
+
+/**
+ * @brief Update the power mode on all core groups that are following the
+ * system mode.
+ *
+ * @param i_occ_internal_mode OCC internal system mode
+ *
+ * @return void
+ */
+void AMEC_part_update_sysmode_policy(OCC_MODE i_occ_internal_mode);
+
+/**
+ * @brief Overwrite the tunable parameters used by the DPS algorithms
+ * whenever the Master OCC sends them.
+ *
+ * @param void
+ *
+ * @return void
+ */
+void AMEC_part_overwrite_dps_parameters(void);
+
+#endif //_AMEC_PART_H
diff --git a/src/occ/amec/amec_pcap.c b/src/occ/amec/amec_pcap.c
new file mode 100755
index 0000000..a4d3ee6
--- /dev/null
+++ b/src/occ/amec/amec_pcap.c
@@ -0,0 +1,572 @@
+/******************************************************************************
+// @file amec_pcap.c
+// @brief Amec power cap Handling
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_pcap_c amec_pcap.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @fk001 879727 fmkassem 04/16/2013 New file
+ * @gm003 879727 milesg 07/01/2013 Changes from review
+ * @at016 891144 alvinwan 06/10/2013 OCC Power Cap Testing
+ * @gm012 905097 milesg 10/31/2013 Enhanced pcap tracing
+ * @rt004 908817 tapiar 12/11/2013 Update valid pcap field for this
+ * occ, to be used by master pcap matching
+ * @at020 908666 alvinwan 12/16/2013 Oversubscription Error Handling
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "amec_pcap.h"
+#include "amec_sys.h"
+#include "amec_service_codes.h"
+#include <occ_common.h>
+#include <occ_sys_config.h>
+#include <dcom.h>
+#include <trac.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define PPB_NOM_DROP_DELAY 4 //ticks
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//Number of ticks to wait before dropping below nominal frequency
+#define PWR_SETTLED_TICKS 4
+//Number of watts power must be below the node power cap before raising
+//ppb_fmax
+#define PDROP_THRESH 0 //TODO: need better value.
+//Number of MHz to raise the proc_pcap_vote for every watt of available power
+//(DCM value should be less than SCM)
+#define PROC_MHZ_PER_WATT 28 //TODO: need better value.
+//Number of MHz to raise ppb_fmax per watt of available power. Depends on
+//number of procs in node.
+#define NODE_MHZ_PER_WATT() \
+ (G_sysConfigData.sys_num_proc_present == 0? \
+ 1: \
+ ((PROC_MHZ_PER_WATT/G_sysConfigData.sys_num_proc_present) == 0? \
+ 1: \
+ PROC_MHZ_PER_WATT/G_sysConfigData.sys_num_proc_present))
+
+//Frequency_step_khz (from global pstate table)/1000
+uint32_t G_mhz_per_pstate=0; //TODO: Maybe there's a better value to initilize it to.
+
+uint8_t G_over_pcap_count=0;
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+//////////////////////////
+// Function Specification
+//
+// Name: amec_pmax_clip_controller
+//
+// Description: Calculate the pmax_clip_freq vote. Initialized to Turbo.
+//
+//
+// Flow: 02/28/13 FN= amec_pmax_clip_controller
+//
+// Thread: Real Time Loop
+//
+// Changedby: @fk001a
+//
+// End Function Specification
+void amec_pmax_clip_controller(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_fturbo = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
+ uint32_t l_pmax_clip_freq = g_amec->proc[0].pwr_votes.pmax_clip_freq;
+ Pstate l_pstate = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //Note: quickPowerDrop interrupts will not preempt the real time loop
+ // interrupt. No locking is needed between the two interrupts.
+ //Note: quickPowerDropLatchAmec represents the failsafe signal on ITEs and
+ // oversubscription signal on non-ITEs.
+
+ // @at020c - start
+ // See the oversub event and control oversub in AMEC
+ if(AMEC_INTF_GET_OVERSUBSCRIPTION()&&
+ (g_amec->oversub_status.oversubLatchAmec==FALSE) )
+ {
+ // ISR already did it but still need to do it again here due to l_pmax_clip_freq is incorrect
+ l_pmax_clip_freq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+ g_amec->oversub_status.oversubLatchAmec = TRUE;
+ }
+ else if( !AMEC_INTF_GET_OVERSUBSCRIPTION() )
+ {
+ // AMEC doesn't control it and let ISR do it
+ g_amec->oversub_status.oversubLatchAmec = FALSE;
+ }
+ // @at020c - end
+
+ if(l_pmax_clip_freq < l_fturbo)
+ {
+ l_pmax_clip_freq += G_mhz_per_pstate;
+
+ if(l_pmax_clip_freq > l_fturbo)
+ {
+ l_pmax_clip_freq = l_fturbo;
+ }
+
+ //call proc_freq2pstate
+ l_pstate = proc_freq2pstate(l_pmax_clip_freq);
+
+ //Set the pmax_clip register via OCI write.
+ amec_oversub_pmax_clip(l_pstate);
+ }
+
+
+
+ g_amec->proc[0].pwr_votes.pmax_clip_freq = l_pmax_clip_freq;
+
+}
+
+//////////////////////////
+// Function Specification
+//
+// Name: amec_pcap_calc
+//
+// Description:
+//
+//
+// Flow: 02/27/13 FN= amec_pcap_calc
+//
+// Thread: Real Time Loop
+//
+// Changedby: @fk001a
+//
+// End Function Specification
+void amec_pcap_calc(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ bool l_failsafe_state = AMEC_INTF_GET_FAILSAFE();
+ bool l_oversub_state = 0; // @at016c
+ uint16_t l_node_pwr = AMECSENSOR_PTR(PWR250US)->sample;
+ uint16_t l_p0_pwr = AMECSENSOR_PTR(PWR250USP0)->sample;
+ int32_t l_avail_power = 0;
+ uint32_t l_proc_fraction = 0;
+ static uint32_t L_prev_node_pcap = 0; //gm003
+ static bool l_apss_error_traced = FALSE;
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //TRAC_INFO("amec_pcap_calc: Calculate active_node_pcap, and nom_pcap_fmin.");
+ l_oversub_state = AMEC_INTF_GET_OVERSUBSCRIPTION(); // @at016a
+
+ //Set the active_node_pcap in g_amec.
+ if(TRUE == l_failsafe_state)
+ {
+ //Set active_node_pcap to soft min pcap since failsafe is on
+ g_amec->pcap.active_node_pcap = G_sysConfigData.pcap.soft_min_pcap;
+ }
+ else if(TRUE == l_oversub_state)
+ {
+ g_amec->pcap.active_node_pcap = g_amec->pcap.ovs_node_pcap;
+ }
+ else
+ {
+ g_amec->pcap.active_node_pcap = g_amec->pcap.norm_node_pcap;
+ }
+
+ //Trace whenever the node pcap changes -- gm003
+ if(L_prev_node_pcap != g_amec->pcap.active_node_pcap)
+ {
+ TRAC_IMP("amec_pcap_calc: Node pcap set to %d watts.",
+ g_amec->pcap.active_node_pcap);
+ L_prev_node_pcap = g_amec->pcap.active_node_pcap;
+
+ // set this pcap as valid (needed by master for comparison) @rt004c
+ g_amec->pcap_valid = 1;
+ }
+
+ l_avail_power = g_amec->pcap.active_node_pcap - l_node_pwr;
+ if(l_node_pwr != 0)
+ {
+ l_proc_fraction = ((uint32_t)(l_p0_pwr) << 16)/l_node_pwr;
+ if(l_apss_error_traced)
+ {
+ TRAC_ERR("PCAP: PWR250US sensor is no longer 0.");
+ l_apss_error_traced = FALSE;
+ }
+ }
+ else
+ {
+ if(!l_apss_error_traced)
+ {
+ TRAC_ERR("PCAP: PWR250US sensor is showing a value of 0.");
+ l_apss_error_traced = TRUE;
+ }
+ }
+
+ g_amec->pcap.active_proc_pcap = l_p0_pwr + ((l_proc_fraction * l_avail_power) >> 16);
+
+ //TRAC_INFO("PCAP: calculated active proc pcap: avail_power[0x%X],proc_fraction[0x%X],"
+ // "active_proc_pcap[0x%X].",l_avail_power,l_proc_fraction,g_amec->pcap.active_proc_pcap);
+
+
+ //NOTE: Power capping will not affect nominal cores unless a customer power cap is set below the
+ // max pcap or oversubscription occurs.
+ // However, nominal cores will drop below nominal if ppb_fmax drops below nominal.
+ if(g_amec->pcap.active_node_pcap < G_sysConfigData.pcap.max_pcap)
+ {
+ g_amec->proc[0].pwr_votes.nom_pcap_fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+ }
+ else
+ {
+ g_amec->proc[0].pwr_votes.nom_pcap_fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL];
+ }
+}
+
+//////////////////////////
+// Function Specification
+//
+// Name: amec_pcap_controller
+//
+// Description:
+//
+//
+// Flow: 02/27/13 FN= amec_pcap_controller
+//
+// Thread: Real Time Loop
+//
+// Changedby: @fk001a
+//
+// End Function Specification
+void amec_pcap_controller(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ int32_t l_power_avail = 0;
+ int32_t l_proc_pcap_vote = g_amec->proc[0].pwr_votes.proc_pcap_vote; // @at016c
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ l_power_avail = g_amec->pcap.active_proc_pcap - AMECSENSOR_PTR(PWR250USP0)->sample;
+
+ if(l_proc_pcap_vote > g_amec->proc[0].pwr_votes.nom_pcap_fmin)
+ {
+ l_proc_pcap_vote = g_amec->proc[0].core_max_freq +
+ (PROC_MHZ_PER_WATT * l_power_avail);
+ }
+ else
+ {
+ l_proc_pcap_vote += (PROC_MHZ_PER_WATT * l_power_avail);
+ }
+
+ if(l_proc_pcap_vote > G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO])
+ {
+ l_proc_pcap_vote = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
+ }
+
+ if(l_proc_pcap_vote < G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY])
+ {
+ l_proc_pcap_vote = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+ }
+
+ //Power capping for nominal cores is not allowed to drop frequency below nom_pcap_fmin
+ if(l_proc_pcap_vote < g_amec->proc[0].pwr_votes.nom_pcap_fmin)
+ {
+ g_amec->proc[0].pwr_votes.proc_pcap_nom_vote = g_amec->proc[0].pwr_votes.nom_pcap_fmin;
+ }
+ else
+ {
+ g_amec->proc[0].pwr_votes.proc_pcap_nom_vote = l_proc_pcap_vote;
+ }
+
+ g_amec->proc[0].pwr_votes.proc_pcap_vote = l_proc_pcap_vote;
+}
+
+//////////////////////////
+// Function Specification
+//
+// Name: amec_ppb_fmax_calc
+//
+// Description:
+//
+//
+// Flow: 02/27/13 FN= amec_ppb_fmax_calc
+//
+// Thread: Real Time Loop
+//
+// Changedby: @fk001a
+//
+// End Function Specification
+void amec_ppb_fmax_calc(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ int32_t l_power_avail = 0;
+ bool l_continue = TRUE; //Used to break from code if needed.
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //Set the slaves local copy of ppb_fmax to that received from Master OCC.
+ g_amec->proc[0].pwr_votes.ppb_fmax = G_dcom_slv_inbox_doorbell_rx.ppb_fmax;
+ // For debug
+ sensor_update( AMECSENSOR_PTR(PROBE250US0), g_amec->proc[0].pwr_votes.ppb_fmax);
+
+ //CALCULATION done by MASTER OCC only.
+ if(OCC_MASTER == G_occ_role)
+ {
+
+ //Power available is the ActiveNodePower - PowerDropThreshold - ActualPwr
+ l_power_avail = g_amec->pcap.active_node_pcap - PDROP_THRESH - AMECSENSOR_PTR(PWR250US)->sample;
+
+ //Note: The PWR250US value is read over the SPI bus, which has no error detection. In order to prevent a
+ //single bad SPI transfer from causing OCC to lower nominal core frequencies, we require the power to be over
+ //the pcap for PPB_NOM_DROP_DELAY ticks before lowering PPB Fmax below Fnom.
+ if((g_amec->proc[0].pwr_votes.ppb_fmax == G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL])
+ && (l_power_avail <=0))
+ {
+ if(G_over_pcap_count < PPB_NOM_DROP_DELAY)
+ {
+ G_over_pcap_count++;
+ l_continue = FALSE;
+ }
+ }
+ else
+ {
+ G_over_pcap_count = 0;
+ }
+
+ //Only run once every 4 ticks (1ms) to allow time for power hogging chips
+ //to drop power and power starved chips to raise power.
+ if(l_continue && (0 == (G_current_tick & 0x3)))
+ {
+ if(l_power_avail <= 0)
+ {
+ G_sysConfigData.master_ppb_fmax -= G_mhz_per_pstate;
+ }
+ else
+ {
+ G_sysConfigData.master_ppb_fmax += NODE_MHZ_PER_WATT() * l_power_avail;
+ }
+
+ if(G_sysConfigData.master_ppb_fmax > G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO])
+ {
+ G_sysConfigData.master_ppb_fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
+ }
+
+ if(G_sysConfigData.master_ppb_fmax < G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY])
+ {
+ G_sysConfigData.master_ppb_fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+ }
+ }
+ }//End of Master code
+
+}
+//////////////////////////
+// Function Specification
+//
+// Name: amec_conn_oc_controller
+//
+// Description: Handle Over Current. Useful on ITE system only.
+// Design uses 2 step procedure when OC is detected.
+// 1) Lower all cores to Fnom
+// 2) If still asserted after PWR_SETTLED_TICKS, lower all cores to Fmin
+//
+//
+// Flow: 02/28/13 FN= amec_conn_oc_controller
+//
+// Thread: Real Time Loop
+//
+// Changedby: @fk001a
+//
+// End Function Specification
+void amec_conn_oc_controller(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ static uint8_t L_asserted_count = 0;
+ static bool L_error_logged = FALSE;
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //If no overcurrent pins are set, then set vote to Turbo
+ if(G_conn_oc_pins_bitmap == 0)
+ {
+ g_amec->proc[0].pwr_votes.conn_oc_vote = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
+ }
+ else
+ {
+ //Check if any of the OC gpio pins are set.
+ //TODO:fk001 Not certain which gpio byte and pins are for the oc pins. This is needed for ITEs,
+ //therefore set them when packet4 from TMGT is redifined to include oc data.
+ if((G_conn_oc_pins_bitmap & ~(G_apss_pwr_meas.gpio[0])) == 0)
+ {
+ //Reset counter
+ L_asserted_count = 0;
+
+ g_amec->proc[0].pwr_votes.conn_oc_vote += G_mhz_per_pstate;
+
+ //Verify that vote is not greater than turbo.
+ if(g_amec->proc[0].pwr_votes.conn_oc_vote > G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO])
+ {
+ g_amec->proc[0].pwr_votes.conn_oc_vote = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
+ }
+ }
+ else if(L_asserted_count < PWR_SETTLED_TICKS)
+ {
+ g_amec->proc[0].pwr_votes.conn_oc_vote = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL];
+ L_asserted_count++;
+
+ //Log an informational error
+ TRAC_ERR("Connector overcurrent pins still asserted. Count=%i.",L_asserted_count);
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_PCAP_CONN_OC_CONTROLLER
+ * @reasoncode CONNECTOR_OC_PINS_WARNING
+ * @userdata1 OC pin bitmap
+ * @userdata2 APSS power measure gpio state
+ * @devdesc The connector overcurrent pins are still asserted.
+ *
+ */
+
+ //TODO:fk001 ADD ACTION FLAG for manufacturing error to log it as predictive. !!!!!
+ if(!L_error_logged) //only log this error once -- gm003
+ {
+ L_error_logged = TRUE;
+ l_err = createErrl(
+ AMEC_PCAP_CONN_OC_CONTROLLER, //modId
+ CONNECTOR_OC_PINS_WARNING, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_conn_oc_pins_bitmap, //userdata1
+ G_apss_pwr_meas.gpio[0] //userdata2
+ );
+
+ commitErrl( &l_err);
+ }
+ }
+ else //Asserted count reached or exceeded PWR_SETTLED_TICKS.
+ {
+ g_amec->proc[0].pwr_votes.conn_oc_vote = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+
+ if(CURRENT_MODE() == OCC_MODE_NOMINAL)
+ {
+ //Log a predictive error
+ TRAC_ERR("Connector overcurrent pins still asserted after max ticks. Logging error.");
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_PCAP_CONN_OC_CONTROLLER
+ * @reasoncode CONNECTOR_OC_PINS_FAILURE
+ * @userdata1 OC pin bitmap
+ * @userdata2 APSS power measure gpio state
+ * @devdesc The connector overcurrent pins are asserted for too long.
+ *
+ */
+
+ l_err = createErrl(
+ AMEC_PCAP_CONN_OC_CONTROLLER, //modId
+ CONNECTOR_OC_PINS_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_conn_oc_pins_bitmap, //userdata1
+ G_apss_pwr_meas.gpio[0] //userdata2
+ );
+
+
+ commitErrl( &l_err);
+
+ //Request safe mode without retries.
+ //TODO: add code to request OCC_MODE_SAFE with no retries.
+ }
+ }
+
+ }
+
+
+
+
+}
+
+//////////////////////////
+// Function Specification
+//
+// Name: amec_power_control
+//
+// Description:
+//
+//
+// Flow: 02/27/13 FN= amec_power_control
+//
+// Thread: Real Time Loop
+//
+// Changedby: @fk001a
+//
+// End Function Specification
+void amec_power_control(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Call amec pmax clip controller to control the Pmax_clip register setting
+ // and voting box input.
+ amec_pmax_clip_controller();
+
+ // Calculate the power cap for the processor and the power capping limit
+ // for nominal cores.
+ amec_pcap_calc();
+
+ // Calculate the voting box input frequency for staying with the current pcap
+ amec_pcap_controller();
+
+ // Calculate the performance preserving bounds voting box input frequency.
+ amec_ppb_fmax_calc();
+
+ // Check for connector overcurrent condition and calculate voting box input frequency.
+ amec_conn_oc_controller();
+
+}
+
diff --git a/src/occ/amec/amec_pcap.h b/src/occ/amec/amec_pcap.h
new file mode 100755
index 0000000..3dcb921
--- /dev/null
+++ b/src/occ/amec/amec_pcap.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+// @file amec_pcap.h
+// @brief AMEC power cap header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_pcap_h amec_pcap.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @fk001 879727 fmkassem 04/24/2013 New file
+ * @rt001 897459 tapiar 08/20/2013 moved PDROP_THRESH to .h
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef _AMEC_PCAP_H
+#define _AMEC_PCAP_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <errl.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//Number of watts power must be below the node power cap before raising
+//ppb_fmax
+#define PDROP_THRESH 0 //TODO: need better value.
+
+//Structure used in g_amec
+typedef struct amec_pcap
+{
+ uint16_t ovs_node_pcap; //Oversub node power cap in 1W units
+ uint16_t norm_node_pcap; //Normal node power cap in 1W units
+ uint16_t active_node_pcap; //Currently active node power cap in 1W units
+ uint16_t active_proc_pcap; //Currently active proc power cap in 1W units
+} amec_pcap_t;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Calls all power control algorithms
+void amec_power_control();
+
+#endif
+
diff --git a/src/occ/amec/amec_perfcount.c b/src/occ/amec/amec_perfcount.c
new file mode 100755
index 0000000..3f28b29
--- /dev/null
+++ b/src/occ/amec/amec_perfcount.c
@@ -0,0 +1,134 @@
+/******************************************************************************
+ * @file amec_perfcount.c
+ * @brief AMEC Performance Counter Code
+ *
+ * Structure Definition / Helper Functions for Performance Counter Calculations
+ *
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_perfcount_c amec_perfcount.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @ly001 853751 lychen 09/17/2012 Initial Revision
+ *
+ * @endverbatim
+ *
+ ******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <string.h>
+#include <common_types.h>
+#include <sensor.h>
+#include <amec_sys.h>
+#include <amec_part.h>
+#include <amec_perfcount.h>
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Code */
+/*----------------------------------------------------------------------------*/
+
+// Function Specification
+//
+// Name: amec_calc_dps_util_counters
+//
+// Description: Calculate the performance counter for a core.
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_calc_dps_util_counters(const uint8_t i_core_id)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ amec_part_t *l_part = NULL;
+ amec_core_perf_counter_t *l_perf = NULL;
+ sensor_ptr_t l_sensor = NULL;
+ uint16_t l_utilization = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ l_perf = &g_amec->proc[0].core[i_core_id].core_perf;
+ // Read sensor for this core
+ l_sensor = AMECSENSOR_ARRAY_PTR(UTIL2MSP0C0, i_core_id);
+ l_utilization = l_sensor->sample;
+ l_part = amec_part_find_by_core(&g_amec->part_config, i_core_id);
+
+ // Type 41 input: Check if core's utilization is within
+ // epsilon of the slack threshold: if yes declare the core
+ // active
+ if (l_part != NULL)
+ {
+ if (l_utilization > (l_part->dpsalg.tlutil - l_part->dpsalg.epsilon_perc))
+ {
+ // indicate core is active
+ l_perf->util_active_core_counter++;
+
+ if (l_utilization < l_part->dpsalg.tlutil)
+ {
+ // indicate core has some slack
+ l_perf->util_slack_core_counter++;
+ }
+ }
+ }
+}
+
+// Function Specification
+//
+// Name: amec_core_perf_counter_ctor
+//
+// Description: Build the performance counter for a core.
+//
+// Flow: FN= None
+//
+// End Function Specification
+amec_core_perf_counter_t* amec_core_perf_counter_ctor(amec_core_perf_counter_t* i_this_ptr,
+ const uint8_t i_proc_id,
+ const uint8_t i_core_id)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //zero everything out, regardless of when we were called
+ memset(i_this_ptr, 0x00, sizeof(amec_core_perf_counter_t));
+
+ // Create space for per-core active and slack counts (for DPS #41 algorithm)
+ memset(i_this_ptr->ptr_util_slack_avg_buffer, 0,
+ (uint32_t)(2*MAX_UTIL_SLACK_AVG_LEN));
+ memset(i_this_ptr->ptr_util_active_avg_buffer, 0,
+ (uint32_t)(2*MAX_UTIL_SLACK_AVG_LEN));
+
+ // DPS frequency request. Choose highest performance by default.
+ i_this_ptr->dps_freq_request = UINT16_MAX; // input to core freq voting box
+
+ //pass out i_this_ptr in case we're allocating this dynamically
+ return i_this_ptr;
+}
+
+/*----------------------------------------------------------------------------*/
+/* End */
+/*----------------------------------------------------------------------------*/
diff --git a/src/occ/amec/amec_perfcount.h b/src/occ/amec/amec_perfcount.h
new file mode 100755
index 0000000..44c8d0e
--- /dev/null
+++ b/src/occ/amec/amec_perfcount.h
@@ -0,0 +1,90 @@
+/******************************************************************************
+ * @file amec_perfcount.h
+ * @brief AMEC Internal headers / structures
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_perfcount_h amec_perfcount.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @ly001 853751 lychen 09/17/2012 Initial Revision
+ *
+ * @endverbatim
+ *
+ ******************************************************************************/
+
+#ifndef _AMEC_PERFCOUNT_H
+#define _AMEC_PERFCOUNT_H
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Defines */
+/*----------------------------------------------------------------------------*/
+#define MAX_UTIL_SLACK_AVG_LEN 64 // Max # of samples in utilization slack averaging buffer
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+
+/// Core Performance Counter Model
+typedef struct amec_core_perf_counter
+{
+ ///32-bit accumulator of util_slack counter
+ uint32_t util_slack_accumulator;
+ ///32-bit accumulator of util_active counter
+ uint32_t util_active_accumulator;
+ ///Circular buffer pointer to put Utilslack signal
+ uint16_t ptr_putUtilslack;
+ ///Frequency request
+ uint16_t dps_freq_request;
+ ///32-bit pointer to utilization slack averaging buffer
+ uint8_t ptr_util_slack_avg_buffer[2*MAX_UTIL_SLACK_AVG_LEN];
+ ///32-bit pointer to utilization active averaging buffer
+ uint8_t ptr_util_active_avg_buffer[2*MAX_UTIL_SLACK_AVG_LEN];
+ ///8-bit counter of cores that are active (utilization>CPU_utilization_threshold)
+ uint8_t util_active_core_counter;
+ ///8-bit counter of cores with slack (utilization<type 1 alg UTIL tlutil)
+ uint8_t util_slack_core_counter;
+}amec_core_perf_counter_t;
+
+/*----------------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief Calculate the performance counter for a core
+ * @param i_core_id Core ID that this struct belongs on
+ *
+ * @return void
+ */
+void amec_calc_dps_util_counters(const uint8_t i_core_id);
+
+/**
+ * @brief Build the performance counter for a core
+ * @param this_ptr perf counter we wish to set up. NULL if you
+ * wish to allocate one dynamically. A pointer
+ * will be returned.
+ * @param i_proc_id Processor ID that this struct belongs on
+ * @param i_core_id Core ID that this struct belongs on
+ *
+ * @return amec_core_perf_counter_t* on success, NULL if an
+ * error
+ */
+amec_core_perf_counter_t* amec_core_perf_counter_ctor(amec_core_perf_counter_t* i_this_ptr,
+ const uint8_t i_proc_id,
+ const uint8_t i_core_id);
+
+#endif
diff --git a/src/occ/amec/amec_sensors_centaur.c b/src/occ/amec/amec_sensors_centaur.c
new file mode 100644
index 0000000..7fa6b4d
--- /dev/null
+++ b/src/occ/amec/amec_sensors_centaur.c
@@ -0,0 +1,703 @@
+/******************************************************************************
+// @file amec_sensors_centaur.c
+// @brief AMEC Centaur Sensor Calculations
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_sensors_centaur_c amec_sensors_centaur.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- --------------------------------------
+ * @th00X thallet 08/15/2012 New file
+ * @th026 865074 thallet 12/21/2012 Updated Centaur sensors
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gm015 907601 milesg 12/06/2013 L4 Bank Delete circumvention and centaur i2c recovery
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @gm039 922963 milesg 05/28/2014 Handle centaur nest LFIR 6
+ * @mw633 933716 mware 07/29/2014 Increased maintenance command threshold to 12 from 8
+ *
+ * @endverbatim
+ */
+
+/******************************************************************************/
+/* includes */
+/******************************************************************************/
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include "sensor.h"
+#include "rtls.h"
+#include "occ_sys_config.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "dcom.h"
+#include "centaur_data.h"
+#include "amec_smh.h"
+#include "amec_slave_smh.h"
+#include <trac.h>
+#include "amec_sys.h"
+#include "sensor_enum.h"
+#include "amec_service_codes.h"
+#include <amec_sensors_centaur.h>
+
+/******************************************************************************/
+/* Globals */
+/******************************************************************************/
+cent_sensor_flags_t G_dimm_overtemp_bitmap = {0};
+cent_sensor_flags_t G_dimm_temp_updated_bitmap = {0};
+uint8_t G_cent_overtemp_bitmap = 0;
+uint8_t G_cent_temp_updated_bitmap = 0;
+extern uint8_t G_centaur_needs_recovery;
+extern uint8_t G_centaur_nest_lfir6; //gm039
+
+/******************************************************************************/
+/* Forward Declarations */
+/******************************************************************************/
+void amec_update_dimm_dts_sensors(MemData * i_sensor_cache, uint8_t i_centaur);
+void amec_update_centaur_dts_sensors(MemData * i_sensor_cache, uint8_t i_centaur);
+void amec_perfcount_getmc( MemData * i_sensor_cache, uint8_t i_centaur); // @th026
+
+
+
+// Function Specification
+//
+// Name: amec_update_dimm_dts_sensors
+//
+// Description: Updates sensors taht have data grabbed by the fast core data
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_centaur_sensors(uint8_t i_centaur)
+{
+ if(CENTAUR_PRESENT(i_centaur))
+ {
+ MemData * l_sensor_cache = cent_get_centaur_data_ptr(i_centaur);
+ if(CENTAUR_UPDATED(i_centaur)) //gm016
+ {
+ amec_update_dimm_dts_sensors(l_sensor_cache, i_centaur);
+ amec_update_centaur_dts_sensors(l_sensor_cache, i_centaur);
+ }
+ amec_perfcount_getmc(l_sensor_cache, i_centaur); // @th026
+ CLEAR_CENTAUR_UPDATED(i_centaur);
+ }
+
+}
+
+// Function Specification
+//
+// Name: amec_update_dimm_dts_sensors
+//
+// Description: Updates sensors taht have data grabbed by the fast core data
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_dimm_dts_sensors(MemData * i_sensor_cache, uint8_t i_centaur)
+{
+#define MIN_VALID_DIMM_TEMP 1
+#define MAX_VALID_DIMM_TEMP 125 //according to Mike Pardiek
+#define MAX_MEM_TEMP_CHANGE 2
+ uint32_t k, l_hottest_dimm_temp;
+ uint16_t l_dts[NUM_DIMMS_PER_CENTAUR] = {0};
+ uint32_t l_hottest_dimm_loc = NUM_DIMMS_PER_CENTAUR;
+ uint32_t l_sens_status;
+ int32_t l_dimm_temp, l_prev_temp;
+ static uint8_t L_ran_once[MAX_NUM_CENTAURS] = {FALSE};
+
+ // so we will need to convert them before they are used in loop below.
+ for(k=0; k < NUM_DIMMS_PER_CENTAUR; k++)
+ {
+ if(!CENTAUR_SENSOR_ENABLED(i_centaur, k))
+ {
+ continue;
+ }
+
+ l_sens_status = i_sensor_cache->scache.dimm_thermal_sensor[k].fields.status;
+ fru_temp_t* l_fru = &g_amec->proc[0].memctl[i_centaur].centaur.dimm_temps[k];
+
+ l_dimm_temp = i_sensor_cache->scache.dimm_thermal_sensor[k].fields.temperature;
+ l_prev_temp = l_fru->cur_temp;
+ if(!l_prev_temp)
+ {
+ l_prev_temp = l_dimm_temp;
+ }
+
+ //Check DTS status bits.
+ if(l_sens_status == DIMM_SENSOR_STATUS_VALID_NEW)
+ {
+ //make sure temperature is within a 'reasonable' range.
+ if(l_dimm_temp < MIN_VALID_DIMM_TEMP ||
+ l_dimm_temp > MAX_VALID_DIMM_TEMP)
+ {
+ //set a flag so that if we end up logging an error we have something to debug why
+ l_fru->flags |= FRU_TEMP_OUT_OF_RANGE;
+ l_dts[k] = l_prev_temp;
+ }
+ else
+ {
+
+ //don't allow temp to change more than is reasonable for 2ms
+ if(l_dimm_temp > (l_prev_temp + MAX_MEM_TEMP_CHANGE))
+ {
+ l_dts[k] = l_prev_temp + MAX_MEM_TEMP_CHANGE;
+ if(!l_fru->flags)
+ {
+ TRAC_INFO("dimm temp rose faster than reasonable: cent[%d] dimm[%d] prev[%d] cur[%d]",
+ i_centaur, k, l_prev_temp, l_dimm_temp);
+ l_fru->flags |= FRU_TEMP_FAST_CHANGE;
+ }
+ }
+ else if (l_dimm_temp < (l_prev_temp - MAX_MEM_TEMP_CHANGE))
+ {
+ l_dts[k] = l_prev_temp - MAX_MEM_TEMP_CHANGE;
+ if(!l_fru->flags)
+ {
+ TRAC_INFO("dimm temp fell faster than reasonable: cent[%d] dimm[%d] prev[%d] cur[%d]",
+ i_centaur, k, l_prev_temp, l_dimm_temp);
+ l_fru->flags |= FRU_TEMP_FAST_CHANGE;
+ }
+ }
+ else //reasonable amount of change occurred
+ {
+ l_dts[k] = l_dimm_temp;
+ l_fru->flags &= ~FRU_TEMP_FAST_CHANGE;
+ }
+
+ //Notify thermal thread that temperature has been updated
+ G_dimm_temp_updated_bitmap.bytes[i_centaur] |= DIMM_SENSOR0 >> k;
+
+ //clear error flags
+ l_fru->flags &= FRU_TEMP_FAST_CHANGE;
+ }
+ }
+ else //status was VALID_OLD, ERROR, or STALLED
+ {
+ //convert status number to a flag
+ uint8_t l_status_flag = 1 << l_sens_status;
+
+ if(L_ran_once[i_centaur])
+ {
+ //Trace the error if we haven't traced it already for this sensor
+ if((l_sens_status != DIMM_SENSOR_STATUS_VALID_OLD) &&
+ !(l_status_flag & l_fru->flags))
+ {
+ TRAC_INFO("Centaur%d sensor%d error: %d", i_centaur, k, l_sens_status);
+ }
+
+ l_fru->flags |= l_status_flag;
+ }
+
+ //use last temperature
+ l_dts[k] = l_prev_temp;
+
+ //request recovery (disable and re-enable sensor cache collection) -- gm015
+ if(l_sens_status == DIMM_SENSOR_STATUS_ERROR)
+ {
+ G_centaur_needs_recovery |= CENTAUR0_PRESENT_MASK >> i_centaur;
+ }
+ }
+
+ //Check if at or above the error temperature
+ if(l_dts[k] >= g_amec->thermaldimm.ot_error)
+ {
+ //Set a bit so that this dimm can be called out by the thermal thread
+ G_dimm_overtemp_bitmap.bytes[i_centaur] |= 1 << k;
+ }
+
+
+ }
+
+ // Find hottest temperature from all DIMMs for this centaur
+ for(l_hottest_dimm_temp = 0, k = 0; k < NUM_DIMMS_PER_CENTAUR; k++)
+ {
+ if(l_dts[k] > l_hottest_dimm_temp)
+ {
+ l_hottest_dimm_temp = l_dts[k];
+ l_hottest_dimm_loc = k;
+ }
+ g_amec->proc[0].memctl[i_centaur].centaur.dimm_temps[k].cur_temp = l_dts[k];
+ }
+
+ amec_centaur_t* l_centaur_ptr = &g_amec->proc[0].memctl[i_centaur].centaur;
+
+ //only update location if hottest dimm temp is greater than previous maximum
+ if(l_hottest_dimm_temp > l_centaur_ptr->tempdimmax.sample_max)
+ {
+ sensor_update(&l_centaur_ptr->locdimmax, l_hottest_dimm_loc);
+ }
+
+ //update the max dimm temperature sensor for this centaur
+ sensor_update(&l_centaur_ptr->tempdimmax, l_hottest_dimm_temp);
+
+ L_ran_once[i_centaur] = TRUE;
+ AMEC_DBG("Centaur[%d]: HotDimm=%d\n",i_centaur,l_hottest_dimm_temp);
+}
+
+
+// Function Specification
+//
+// Name: amec_update_centaur_dts_sensors
+//
+// Description: Updates sensors taht have data grabbed by the fast core data
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_centaur_dts_sensors(MemData * i_sensor_cache, uint8_t i_centaur)
+{
+#define MIN_VALID_CENT_TEMP 1
+#define MAX_VALID_CENT_TEMP 125 //according to Mike Pardiek
+#define CENT_SENSOR_STATUS_VALID 0x0001
+#define CENT_SENSOR_TEMP_MASK 0xfff0
+
+ uint16_t l_dts, l_sens_value0, l_sens_value1;
+ uint16_t l_sens_status0, l_sens_status1, l_sens_status;
+ uint16_t l_sens_temp0, l_sens_temp1, l_cent_temp;
+ int32_t l_prev_temp;
+ static uint8_t L_ran_once[MAX_NUM_CENTAURS] = {FALSE};
+
+ l_sens_value0 = i_sensor_cache->scache.centaur_thermal_sensor[0].value;
+ l_sens_value1 = i_sensor_cache->scache.centaur_thermal_sensor[1].value;
+ l_sens_status0 = l_sens_value0 & CENT_SENSOR_STATUS_VALID;
+ l_sens_status1 = l_sens_value1 & CENT_SENSOR_STATUS_VALID;
+ l_sens_temp0 = (l_sens_status0)? (l_sens_value0 & CENT_SENSOR_TEMP_MASK) >> 4:
+ 0;
+ l_sens_temp1 = (l_sens_status1)? (l_sens_value1 & CENT_SENSOR_TEMP_MASK) >> 4:
+ 0;
+ l_sens_status = l_sens_status0 | l_sens_status1;
+ l_cent_temp = (l_sens_temp0 > l_sens_temp1)? l_sens_temp0: l_sens_temp1;
+
+ fru_temp_t* l_fru = &g_amec->proc[0].memctl[i_centaur].centaur.centaur_hottest;
+
+ l_prev_temp = l_fru->cur_temp;
+ if(!l_prev_temp)
+ {
+ l_prev_temp = l_cent_temp;
+ }
+
+ //Check DTS status bits and NEST LFIR bit 6 for a valid temperature.
+ if(l_sens_status == CENT_SENSOR_STATUS_VALID &&
+ !(G_centaur_nest_lfir6 & (CENTAUR0_PRESENT_MASK >> i_centaur))) //gm039
+ {
+ //make sure temperature is within a 'reasonable' range.
+ if(l_cent_temp < MIN_VALID_CENT_TEMP ||
+ l_cent_temp > MAX_VALID_CENT_TEMP)
+ {
+ //set a flag so that if we end up logging an error we have something to debug why
+ l_fru->flags |= FRU_TEMP_OUT_OF_RANGE;
+ l_dts = l_prev_temp;
+ }
+ else
+ {
+
+ //don't allow temp to change more than is reasonable for 2ms
+ if(l_cent_temp > (l_prev_temp + MAX_MEM_TEMP_CHANGE))
+ {
+ l_dts = l_prev_temp + MAX_MEM_TEMP_CHANGE;
+ if(!l_fru->flags)
+ {
+ TRAC_INFO("centaur temp rose faster than reasonable: cent[%d] prev[%d] cur[%d]",
+ i_centaur, l_prev_temp, l_cent_temp);
+ l_fru->flags |= FRU_TEMP_FAST_CHANGE;
+ }
+ }
+ else if (l_cent_temp < (l_prev_temp - MAX_MEM_TEMP_CHANGE))
+ {
+ l_dts = l_prev_temp - MAX_MEM_TEMP_CHANGE;
+ if(!l_fru->flags)
+ {
+ TRAC_INFO("centaur temp fell faster than reasonable: cent[%d] prev[%d] cur[%d]",
+ i_centaur, l_prev_temp, l_cent_temp);
+ l_fru->flags |= FRU_TEMP_FAST_CHANGE;
+ }
+ }
+ else //reasonable amount of change occurred
+ {
+ l_dts = l_cent_temp;
+ l_fru->flags &= ~FRU_TEMP_FAST_CHANGE;
+ }
+
+ //Notify thermal thread that temperature has been updated
+ G_cent_temp_updated_bitmap |= CENTAUR0_PRESENT_MASK >> i_centaur;
+
+ //clear error flags
+ l_fru->flags &= FRU_TEMP_FAST_CHANGE;
+ }
+ }
+ else //status was INVALID
+ {
+ if(L_ran_once[i_centaur])
+ {
+ //Trace the error if we haven't traced it already for this sensor
+ //and this wasn't only caused by LFIR[6] (which is traced elsewhere).
+ if(!(l_fru->flags & FRU_SENSOR_STATUS_INVALID) &&
+ !(l_sens_status == CENT_SENSOR_STATUS_VALID)) //gm039
+ {
+ TRAC_INFO("Centaur%d temp invalid. nest_lfir6=0x%02x", i_centaur, G_centaur_nest_lfir6); //gm039
+ }
+
+ l_fru->flags |= FRU_SENSOR_STATUS_INVALID;
+
+ if(G_centaur_nest_lfir6 & (CENTAUR0_PRESENT_MASK >> i_centaur)) //gm039
+ {
+ l_fru->flags |= FRU_SENSOR_CENT_NEST_FIR6;
+ }
+ }
+
+ //use last temperature
+ l_dts = l_prev_temp;
+ }
+
+ L_ran_once[i_centaur] = TRUE;
+
+ //Check if at or above the error temperature
+ if(l_dts >= g_amec->thermalcent.ot_error)
+ {
+ //Set a bit so that this dimm can be called out by the thermal thread
+ G_cent_overtemp_bitmap |= (CENTAUR0_PRESENT_MASK >> i_centaur);
+ }
+
+ // Update Interim Data - later this will get picked up to form centaur sensor
+ g_amec->proc[0].memctl[i_centaur].centaur.centaur_hottest.cur_temp = l_dts;
+
+ AMEC_DBG("Centaur[%d]: HotCentaur=%d\n",i_centaur,l_dts);
+}
+
+
+// Function Specification
+//
+// Name: amec_update_centaur_temp_sensors
+//
+// Description: Updates sensors that have data grabbed by the centaur
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_centaur_temp_sensors(void)
+{
+ uint32_t k, l_hot;
+
+ // ------------------------------------------------------
+ // Find hottest temperature from all centaurs for this P8 chip
+ // ------------------------------------------------------
+ for(l_hot = 0, k=0; k < MAX_NUM_CENTAURS; k++)
+ {
+ if(g_amec->proc[0].memctl[k].centaur.centaur_hottest.cur_temp > l_hot)
+ {
+ l_hot = g_amec->proc[0].memctl[k].centaur.centaur_hottest.cur_temp;
+ }
+ }
+ sensor_update(&g_amec->proc[0].temp2mscent,l_hot);
+ AMEC_DBG("HotCentaur=%d\n",l_hot);
+
+ // ------------------------------------------------------
+ // Find hottest temperature from all DIMMs for this P8 chip
+ // ------------------------------------------------------
+ for(l_hot = 0, k=0; k < MAX_NUM_CENTAURS; k++)
+ {
+ if(g_amec->proc[0].memctl[k].centaur.tempdimmax.sample > l_hot)
+ {
+ l_hot = g_amec->proc[0].memctl[k].centaur.tempdimmax.sample;
+ }
+ }
+ sensor_update(&g_amec->proc[0].temp2msdimm,l_hot);
+ AMEC_DBG("HotDimm=%d\n",l_hot);
+}
+
+
+// Function Specification
+//
+// Name: amec_perfcount_getmc
+//
+// Description: Updates sensors that have data grabbed by the centaur
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_perfcount_getmc( MemData * i_sensor_cache,
+ uint8_t i_centaur)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT32 tempu = 0;
+ UINT32 templ = 0;
+ UINT32 temp32new = 0;
+ UINT32 temp32 = 0;
+ UINT16 tempreg = 0;
+ UINT16 tempreg2 = 0;
+ uint8_t i_mc_id = 0;
+ #define AMECSENSOR_PORTPAIR_PTR(sensor_base,idx,idx2) \
+ (&(g_amec->proc[0].memctl[idx].centaur.portpair[idx2].sensor_base))
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ MemData * l_sensor_cache = i_sensor_cache;
+
+ for(i_mc_id=0; i_mc_id<2; i_mc_id++)
+ {
+ if (i_mc_id == 0)
+ {
+ tempu = l_sensor_cache->scache.mba01_rd;
+ templ = l_sensor_cache->scache.mba01_wr;
+ }
+ else
+ {
+ tempu = l_sensor_cache->scache.mba23_rd;
+ templ = l_sensor_cache->scache.mba23_wr;
+ }
+
+ // ----------------------------------------------------
+ // Interim Calculation: MWR2MSP0Mx (0.01 Mrps) Memory write requests per sec
+ // ----------------------------------------------------
+
+ // Extract write bandwidth
+ temp32new = (templ); // left shift into top 20 bits of 32 bits
+
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.wr_cnt_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.wr_cnt_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.memwrite2ms = tempreg;
+
+ // ----------------------------------------------------
+ // Interim Calculation: MRD2MSP0Mx (0.01 Mrps) Memory read requests per sec
+ // ----------------------------------------------------
+
+ // Extract read bandwidth
+ temp32new = (tempu); // left shift into top 20 bits of 32 bits
+
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.rd_cnt_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.rd_cnt_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.memread2ms = tempreg;
+
+ // Go after second MC performance counter (power ups and activations)
+ if (i_mc_id == 0)
+ {
+ tempu = l_sensor_cache->scache.mba01_act;
+ templ = l_sensor_cache->scache.mba01_powerups;
+ }
+ else
+ {
+ tempu = l_sensor_cache->scache.mba23_act;
+ templ = l_sensor_cache->scache.mba23_powerups;
+ }
+
+ // ----------------------------------------------------
+ // Sensor: MPU2MSP0Mx (0.01 Mrps) Memory power-up requests per sec
+ // ----------------------------------------------------
+ // Extract power up count
+ temp32new = (templ); // left shift into top 20 bits of 32 bits
+
+ // For DD1.0, we only have 1 channel field that we use; DD2.0 we need to add another channel
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.pwrup_cnt_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.pwrup_cnt_accum = temp32new; // Save latest accumulator away for next time
+ tempreg=(UINT16)(temp32>>12); // Select upper 20 bits
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.pwrup_cnt=(UINT16)tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(mpu2ms,i_centaur,i_mc_id), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MAC2MSP0Mx (0.01 Mrps) Memory activation requests per sec
+ // ----------------------------------------------------
+ // Extract activation count
+ temp32 = templ;
+ temp32 += tempu;
+
+ temp32new = (temp32); // left shift into top 20 bits of 32 bits
+ // For DD1.0, we only have 1 channel field that we use; DD2.0 we need to add another channel
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.act_cnt_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.act_cnt_accum = temp32new; // Save latest accumulator away for next time
+ tempreg=(UINT16)(temp32>>12); // Select lower 16 of 20 bits
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.act_cnt=(UINT16)tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(mac2ms,i_centaur,i_mc_id), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MTS2MS (count) Last received Timestamp (frame count) from Centaur
+ // ----------------------------------------------------
+ // Extract framecount (clock is 266.6666666MHz * 0.032 / 4096)=2083.
+ temp32new = l_sensor_cache->scache.frame_count;
+
+ // For DD1.0, we only have 1 channel field that we use; DD2.0 we need to add another channel
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.fr2_cnt_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.fr2_cnt_accum = temp32new; // Save latest accumulator away for next time
+ tempreg=(UINT16)(temp32>>12); // Select upper 20 bits
+
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.fr2_cnt=(UINT16)tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(mts2ms,i_centaur,i_mc_id), tempreg);
+
+ if (i_mc_id == 0)
+ {
+ tempu = l_sensor_cache->scache.mba01_cache_hits_rd;
+ templ = l_sensor_cache->scache.mba01_cache_hits_wr;
+ }
+ else
+ {
+ tempu = l_sensor_cache->scache.mba23_cache_hits_rd;
+ templ = l_sensor_cache->scache.mba23_cache_hits_wr;
+ }
+ // ----------------------------------------------------
+ // Sensor: M4RD2MS (0.01 Mrps) Memory cached (L4) read requests per sec
+ // ----------------------------------------------------
+ temp32new = (tempu); // left shift into top 20 bits of 32 bits
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.l4_rd_cnt_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.l4_rd_cnt_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+ tempreg2 = g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.memread2ms;
+ // Firmware workaround for hardware bug: hits - memreads ~= hits @mw565
+ tempreg = tempreg - tempreg2;
+ // Deal with maintenance commands or quantization in counters being off by 12 and force to 0 // @mw565 @mw633
+ if ((tempreg > 32767) || (tempreg <= 12))
+ {
+ tempreg=0;
+ }
+
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.l4rd2ms = tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(m4rd2ms,i_centaur,i_mc_id), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: M4WR2MS (0.01 Mrps) Memory cached (L4) write requests per sec
+ // ----------------------------------------------------
+ temp32new = (templ); // left shift into top 20 bits of 32 bits
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.l4_wr_cnt_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.l4_wr_cnt_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+
+ tempreg2 = g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.memwrite2ms;
+ // Firmware workaround for hardware bug: hits - memwrites ~= hits @mw565
+ tempreg = tempreg - tempreg2;
+ // Deal with maintenance commands or quantization in counters being off by 12 and force to 0 // @mw565 @mw633
+ if ((tempreg > 32767) || (tempreg <= 12))
+ {
+ tempreg=0;
+ }
+
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.l4wr2ms = tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(m4wr2ms,i_centaur,i_mc_id), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MIRB2MS (0.01 Mevents/s) Memory Inter-request arrival idle intervals
+ // ----------------------------------------------------
+ temp32new = (i_mc_id == 0) ? l_sensor_cache->scache.mba01_intreq_arr_cnt_base : l_sensor_cache->scache.mba23_intreq_arr_cnt_base;
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.intreq_base_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.intreq_base_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.mirb2ms = tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(mirb2ms,i_centaur,i_mc_id), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MIRL2MS (0.01 Mevents/s) Memory Inter-request arrival idle intervals longer than low threshold
+ // ----------------------------------------------------
+ temp32new = (i_mc_id == 0) ? l_sensor_cache->scache.mba01_intreq_arr_cnt_low : l_sensor_cache->scache.mba23_intreq_arr_cnt_low;
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.intreq_low_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.intreq_low_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.mirl2ms = tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(mirl2ms,i_centaur,i_mc_id), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MIRM2MS (0.01 Mevents/s) Memory Inter-request arrival idle intervals longer than medium threshold
+ // ----------------------------------------------------
+ temp32new = (i_mc_id == 0) ? l_sensor_cache->scache.mba01_intreq_arr_cnt_med : l_sensor_cache->scache.mba23_intreq_arr_cnt_med;
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.intreq_med_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.intreq_med_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.mirm2ms = tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(mirm2ms,i_centaur,i_mc_id), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MIRH2MS (0.01 Mevents/s) Memory Inter-request arrival idle intervals longer than high threshold
+ // ----------------------------------------------------
+ temp32new = (i_mc_id == 0) ? l_sensor_cache->scache.mba01_intreq_arr_cnt_high : l_sensor_cache->scache.mba23_intreq_arr_cnt_high;
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.intreq_high_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.intreq_high_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+ g_amec->proc[0].memctl[i_centaur].centaur.portpair[i_mc_id].perf.mirh2ms = tempreg;
+ sensor_update(AMECSENSOR_PORTPAIR_PTR(mirh2ms,i_centaur,i_mc_id), tempreg);
+ }
+
+ // ----------------------------------------------------
+ // Sensor: MIRC2MS (0.01 Mevents/s) Memory Inter-request arrival idle interval longer than programmed threshold
+ // ----------------------------------------------------
+ temp32new = l_sensor_cache->scache.intreq_arr_cnt_high_latency;
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.perf.intreq_highlatency_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.perf.intreq_highlatency_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+ g_amec->proc[0].memctl[i_centaur].centaur.perf.mirc2ms = tempreg;
+ sensor_update((&(g_amec->proc[0].memctl[i_centaur].centaur.mirc2ms)), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MLP2MS (events/s) Number of LP2 exits
+ // ----------------------------------------------------
+ temp32new = l_sensor_cache->scache.lp2_exits;
+ temp32 = temp32new - g_amec->proc[0].memctl[i_centaur].centaur.perf.lp2exit_accum;
+ g_amec->proc[0].memctl[i_centaur].centaur.perf.lp2exit_accum = temp32new; // Save latest accumulator away for next time
+
+ // Read every 2 ms....to convert to 0.01 Mrps = ((2ms read * 500)/10000)
+ tempreg = ((temp32*5)/100);
+ g_amec->proc[0].memctl[i_centaur].centaur.perf.mlp2_2ms = tempreg;
+ sensor_update((&(g_amec->proc[0].memctl[i_centaur].centaur.mlp2ms)), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MRD2MSP0Mx (0.01 Mrps) Memory read requests per sec
+ // ----------------------------------------------------
+ //AMEC_SENSOR_UPDATE(io_mc_ptr->chpair[i_mc_id].memread32ms, tempreg);
+ tempreg = g_amec->proc[0].memctl[i_centaur].centaur.portpair[0].perf.memread2ms;
+ tempreg += g_amec->proc[0].memctl[i_centaur].centaur.portpair[1].perf.memread2ms;
+ sensor_update( (&(g_amec->proc[0].memctl[i_centaur].mrd2ms)), tempreg);
+
+ // ----------------------------------------------------
+ // Sensor: MWR2MSP0Mx (0.01 Mrps) Memory write requests per sec
+ // ----------------------------------------------------
+ //sensor_update(AMECSENSOR_ARRAY_PTR(MRD2MSP0M0,), tempreg )
+ tempreg = g_amec->proc[0].memctl[i_centaur].centaur.portpair[0].perf.memwrite2ms;
+ tempreg += g_amec->proc[0].memctl[i_centaur].centaur.portpair[1].perf.memwrite2ms;
+ sensor_update( (&(g_amec->proc[0].memctl[i_centaur].mwr2ms)), tempreg);
+
+
+ return;
+}
+
+
diff --git a/src/occ/amec/amec_sensors_centaur.h b/src/occ/amec/amec_sensors_centaur.h
new file mode 100644
index 0000000..f24fb68
--- /dev/null
+++ b/src/occ/amec/amec_sensors_centaur.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+// @file amec_sensors_centaur.h
+// @brief OCC AMEC Sensors Derived from Centaur
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section amec_sensors_centaur.h AMEC_SENSORS_CENTAUR.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th018 852950 thallet 09/12/2012 Added Centaur thermal readings
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_SENSORS_CENTAUR_H
+#define _AMEC_SENSORS_CENTAUR_H
+
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void amec_update_centaur_sensors(uint8_t i_centaur);
+void amec_update_centaur_temp_sensors(void);
+
+
+#endif
+
diff --git a/src/occ/amec/amec_sensors_core.c b/src/occ/amec/amec_sensors_core.c
new file mode 100755
index 0000000..46ad0d4
--- /dev/null
+++ b/src/occ/amec/amec_sensors_core.c
@@ -0,0 +1,886 @@
+/******************************************************************************
+// @file amec_sensors_core.c
+// @brief AMEC Core Sensor Calculations
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_sensors_core_c amec_sensors_core.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- --------------------------------------
+ * @th00b thallet 02/24/2012 New file
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th00f thallet 06/27/2012 Changed to use CoreData as provided by HW team
+ * @ly001 853751 lychen 09/17/2012 Support DPS algorithm
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @cl007 907196 lefurgy 11/15/2013 Fix freqa and ips sensors
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @gs022 910702 gjsilva 01/13/2014 Update thermal data if cores are in deep sleep
+ * 910702 gjsilva 01/14/2014 Changes from code review
+ * @gs024 912700 gjsilva 01/22/2014 Identify fast/deep winkle states
+ * @sb100 916174 sbroyles 02/17/2014 Literal updates for SSX import of release20140214
+ * @sb055 911966 sbroyles 02/27/2014 Fixed wrong mask after import
+ * @gs028 917695 gjsilva 03/04/2014 Check if cores are in a sleep state
+ * 917695 gjsilva 03/05/2014 Changes from code review
+ * @mw656 mware 03/11/2014 Fixed TODclock sensors
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ * @mw664 mware 03/26/2014 Fixed TOD clock sensors to use apss_tod
+ * @gs029 919478 gjsilva 03/26/2014 Fixed wrong values for sleep/winkle counters
+ * @gs030 921720 gjsilva 04/04/2014 Fixed high values in utilization sensors
+ * @sbpde 922027 sbroyles 04/04/2014 Skip updates on empath errors.
+ * @mw682 933716 mware 07/28/2014 Changed MCPIFD to be NOTBZE and MCPIFI to be NOTFIN.
+ *
+ * @endverbatim
+ */
+
+/******************************************************************************/
+/* includes */
+/******************************************************************************/
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include "sensor.h"
+#include "rtls.h"
+#include "occ_sys_config.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "dcom.h"
+#include "proc_data.h"
+#include "amec_smh.h"
+#include "amec_slave_smh.h"
+#include <trac.h>
+#include "amec_sys.h"
+#include "sensor_enum.h"
+#include "amec_service_codes.h"
+#include <amec_sensors_core.h>
+#include "amec_perfcount.h" // @ly001a
+
+/******************************************************************************/
+/* Globals */
+/******************************************************************************/
+
+
+/******************************************************************************/
+/* Forward Declarations */
+/******************************************************************************/
+void amec_calc_dts_sensors(gpe_bulk_core_data_t * i_core_data_ptr, uint8_t i_core);
+//void amec_calc_cpm_sensors(gpe_bulk_core_data_t * i_core_data_ptr, uint8_t i_core); //CPM - Commented out as requested by Malcolm
+void amec_calc_freq_and_util_sensors(gpe_bulk_core_data_t * i_core_data_ptr, uint8_t i_core);
+void amec_calc_ips_sensors(gpe_bulk_core_data_t * i_core_data_ptr, uint8_t i_core);
+void amec_calc_spurr(uint8_t i_core);
+
+
+// Function Specification
+//
+// Name: amec_update_fast_core_data_sensors
+//
+// Description: Updates sensors taht have data grabbed by the fast core data
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_fast_core_data_sensors(void)
+{
+ // ------------------------------------------------------
+ // Update Fast Core Data Sensors
+ // ------------------------------------------------------
+ // SensorNameCx = PCBS Local Pstate Freq Target (per core)
+ // TODclock = TOD Clock?
+
+ // @mw656 Need to comment this out because l_tod is always zero, which messes
+ // up proper sensor updates. Proper updating is done below in the core level
+ // sensor updates.
+ //gpe_fast_core_data_t * l_core = proc_get_fast_core_data_ptr(); // @mw656
+ // uint32_t l_tod = l_core->tod;
+
+ //if( l_core != NULL)
+ //{
+ // GPEtickdur0 = duration of last tick's PORE-GPE0 duration
+ // sensor_update( AMECSENSOR_PTR(TODclock0), CONVERT_UINT32_UINT8_UPPER_HIGH(l_tod) );
+ // sensor_update( AMECSENSOR_PTR(TODclock1), CONVERT_UINT32_UINT16_MIDDLE(l_tod) );
+ // sensor_update( AMECSENSOR_PTR(TODclock2), ((uint16_t) (CONVERT_UINT32_UINT8_LOWER_LOW(l_tod))) << 8);
+ //}
+
+ // TODO: Don't know what to update from the PCBS LPstate Target Freq Status Reg
+ //for(int i=0; i++; i<MAX_NUM_HW_CORES)
+ //{
+ // sensor_update(&sensor,
+ // G_read_fast_core_data_ptr->core_data[i].pcbs_lpstate_freq_target_sr);
+ //}
+}
+
+
+// Function Specification
+//
+// Name: amec_update_proc_core_sensors
+//
+// Description: Update all the sensors for a given proc
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_proc_core_sensors(uint8_t i_core)
+{
+ gpe_bulk_core_data_t * l_core_data_ptr;
+ int i;
+ uint16_t l_temp16 = 0; // @mw656
+ uint32_t l_temp32 = 0; // @mw656
+
+ // Make sure the core is present, and that it has updated
+ // data.
+ if(CORE_PRESENT(i_core) && CORE_UPDATED(i_core))
+ {
+ // Clear flag indicating core was updated by proc task
+ CLEAR_CORE_UPDATED(i_core);
+
+ // Get pointer to core data
+ l_core_data_ptr = proc_get_bulk_core_data_ptr(i_core);
+
+ //-------------------------------------------------------
+ // Thermal Sensors & Calc
+ //-------------------------------------------------------
+ amec_calc_dts_sensors(l_core_data_ptr, i_core);
+
+ //-------------------------------------------------------
+ //CPM - Commented out as requested by Malcolm
+ // ------------------------------------------------------
+ // amec_calc_cpm_sensors(l_core_data_ptr, i_core);
+
+ //-------------------------------------------------------
+ // Util / Freq
+ //-------------------------------------------------------
+ // >> @sbpde
+ // Skip this update if there was an empath collection error
+ if (!CORE_EMPATH_ERROR(i_core))
+ {
+ amec_calc_freq_and_util_sensors(l_core_data_ptr,i_core);
+ }
+ // << @sbpde
+
+ // @ly001a - start
+ //-------------------------------------------------------
+ // Performance counter - This function should be called
+ // after amec_calc_freq_and_util_sensors().
+ //-------------------------------------------------------
+ amec_calc_dps_util_counters(i_core);
+ // @ly001a - end
+
+ //-------------------------------------------------------
+ // IPS
+ //-------------------------------------------------------
+ // >> @sbpde
+ // Skip this update if there was an empath collection error
+ if (!CORE_EMPATH_ERROR(i_core))
+ {
+ amec_calc_ips_sensors(l_core_data_ptr,i_core);
+ }
+ // << @sbpde
+
+ //-------------------------------------------------------
+ // SPURR
+ //-------------------------------------------------------
+ amec_calc_spurr(i_core);
+
+ // ------------------------------------------------------
+ // Update PREVIOUS values for next time
+ // ------------------------------------------------------
+ g_amec->proc[0].core[i_core].prev_PC_RAW_Th_CYCLES = l_core_data_ptr->per_thread[0].raw_cycles; // @th00f
+
+ // >> @sbpde
+ // Skip empath updates if there was an empath collection error on this core
+ if (!CORE_EMPATH_ERROR(i_core))
+ {
+ g_amec->proc[0].core[i_core].prev_PC_RAW_CYCLES = l_core_data_ptr->empath.raw_cycles; // @th00f
+ g_amec->proc[0].core[i_core].prev_PC_RUN_CYCLES = l_core_data_ptr->empath.run_cycles; // @th00f
+ g_amec->proc[0].core[i_core].prev_PC_COMPLETED = l_core_data_ptr->empath.completion;
+ g_amec->proc[0].core[i_core].prev_PC_DISPATCH = l_core_data_ptr->empath.dispatch;
+ g_amec->proc[0].core[i_core].prev_tod_2mhz = l_core_data_ptr->empath.tod_2mhz;
+ g_amec->proc[0].core[i_core].prev_FREQ_SENS_BUSY = l_core_data_ptr->empath.freq_sens_busy; // @mw644
+ g_amec->proc[0].core[i_core].prev_FREQ_SENS_FINISH = l_core_data_ptr->empath.freq_sens_finish; // @mw644
+ }
+ // << @sbpde
+
+ for(i=0; i<MAX_THREADS_PER_CORE; i++)
+ {
+ g_amec->proc[0].core[i_core].thread[i].prev_PC_RUN_Th_CYCLES = l_core_data_ptr->per_thread[i].run_cycles; // @th00f
+ }
+
+ // Final step is to update TOD sensors
+ // Extract 32 bits with 16usec resolution
+ l_temp32 = (uint32_t)(G_dcom_slv_inbox_doorbell_rx.tod>>13);
+ l_temp16 = (uint16_t)(l_temp32);
+ // low 16 bits is 16usec resolution with 512MHz TOD clock
+ sensor_update( AMECSENSOR_PTR(TODclock0), l_temp16);
+ l_temp16 = (uint16_t)(l_temp32>>16);
+ // mid 16 bits is 1.05sec resolution with 512MHz TOD clock
+ sensor_update( AMECSENSOR_PTR(TODclock1), l_temp16);
+ l_temp16 = (uint16_t)(G_dcom_slv_inbox_doorbell_rx.tod>>45);
+ // hi 3 bits in 0.796 day resolution with 512MHz TOD clock
+ sensor_update( AMECSENSOR_PTR(TODclock2), l_temp16);
+ }
+}
+
+
+// Function Specification
+//
+// Name: amec_calc_dts_sensors
+//
+// Description: Called every 2ms/core
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// End Function Specification
+void amec_calc_dts_sensors(gpe_bulk_core_data_t * i_core_data_ptr, uint8_t i_core)
+{
+#define DTS_PER_CORE 4
+#define DTS_INVALID_MASK 0x0C00
+
+ uint32_t k, l_core_avg, l_core_hot, l_sensor_count;
+ uint32_t l_oha_status_reg = 0;
+ uint32_t l_pm_state_hist_reg = 0;
+ uint16_t l_dts[DTS_PER_CORE];
+ BOOLEAN l_update_sensor = FALSE;
+
+
+ // Build up array of DTS values
+ // DTS sensors are in the format of uint64_t dts0 : 12;
+ // uint64_t thermal_trip0 : 2;
+ // uint64_t spare0 : 1;
+ // uint64_t valid0 : 1;
+ //
+ // so we will need to convert them before they are used in loop below.
+ l_dts[0] = i_core_data_ptr->dts_cpm.sensors_v0.fields.dts0; // @th00f
+ l_dts[1] = i_core_data_ptr->dts_cpm.sensors_v0.fields.dts1; // @th00f
+ l_dts[2] = i_core_data_ptr->dts_cpm.sensors_v0.fields.dts2; // @th00f
+ l_dts[3] = i_core_data_ptr->dts_cpm.sensors_v1.fields.dts4; // @th00f
+
+ // Read the low-order bytes of the OHA Status register
+ l_oha_status_reg = i_core_data_ptr->oha.oha_ro_status_reg.words.low_order;
+
+ // Read the high-order bytes of PM State History register for this core
+ l_pm_state_hist_reg = i_core_data_ptr->pcb_slave.pm_history.words.high_order;
+
+ // Check if we were able to collect core data
+ if(l_oha_status_reg & CORE_DATA_CORE_SENSORS_COLLECTED) // @sb100
+ {
+ // Check if all DTS readings in the core are valid. The field sensors_v0
+ // contains core-related data
+ if(i_core_data_ptr->dts_cpm.sensors_v0.fields.valid0 ||
+ i_core_data_ptr->dts_cpm.sensors_v0.fields.valid1 ||
+ i_core_data_ptr->dts_cpm.sensors_v0.fields.valid2)
+ {
+ l_update_sensor = TRUE;
+ }
+ }
+ // Check if we were able to collect L3 data
+ if(l_oha_status_reg & CORE_DATA_L3_SENSORS_COLLECTED) // @sb100
+ {
+ // Check if DTS reading in the L3 is valid. The field sensors_v1 contains
+ // L3-related data
+ if(i_core_data_ptr->dts_cpm.sensors_v1.fields.valid4)
+ {
+ l_update_sensor = TRUE;
+ }
+ }
+ // Check if this core has been in fast winkle OR deep winkle
+ if(((l_pm_state_hist_reg & OCC_PM_STATE_MASK) == OCC_PAST_FAST_WINKLE) ||
+ ((l_pm_state_hist_reg & OCC_PM_STATE_MASK) == OCC_PAST_DEEP_WINKLE))
+ {
+ l_update_sensor = TRUE;
+ }
+
+ // Update the thermal sensor associated with this core
+ if(l_update_sensor)
+ {
+ //calculate average temperature from all DTS's for this core
+ for(l_sensor_count = DTS_PER_CORE, l_core_hot = 0,
+ l_core_avg = 0, k = 0;
+ k < DTS_PER_CORE; k++)
+ {
+ //Hardware bug workaround: Temperatures reaching 0 degrees C
+ //can show up as negative numbers. To fix this, we discount
+ //values that have the 2 MSB's set.
+ if((l_dts[k] & DTS_INVALID_MASK) == DTS_INVALID_MASK)
+ {
+ l_dts[k] = 0;
+ }
+
+ l_core_avg += l_dts[k];
+ if(l_dts[k] > l_core_hot)
+ {
+ l_core_hot = l_dts[k];
+ }
+ // Assume 0 degrees to mean bad sensor and
+ // don't let it bring the average reading down.
+ else if(l_dts[k] == 0)
+ {
+ l_sensor_count--;
+ }
+ }
+
+ if(l_sensor_count == DTS_PER_CORE)
+ {
+ //For the common case,
+ //compiler converts this to a fast multiplication operation
+ //when one of the operands is a constant.
+ l_core_avg /= DTS_PER_CORE;
+ }
+ else if(l_sensor_count) //prevent div by 0 if all sensors are zero
+ {
+ //otherwise, use the slower division routine
+ //when both operands are unknown at compile time.
+ l_core_avg /= l_sensor_count;
+ }
+
+ // Update sensors & Interim Data
+ sensor_update( AMECSENSOR_ARRAY_PTR(TEMP2MSP0C0,i_core), l_core_avg);
+ g_amec->proc[0].core[i_core].dts_hottest = l_core_hot;
+ }
+}
+
+
+//CPM - Commented out as requested by Malcolm
+//
+// End Function Specification
+/* void amec_calc_cpm_sensors(gpe_bulk_core_data_t * i_core_data_ptr, uint8_t i_core)
+{
+#define CPM_PER_CORE 4
+
+ uint32_t k, l_cpm_min = 0xffffffff;
+ uint16_t l_cpm[CPM_PER_CORE];
+
+ l_cpm[0] = i_core_data_ptr->dts_cpm.sensors_v8.fields.encoded_cpm0; // @th00f
+ l_cpm[1] = i_core_data_ptr->dts_cpm.sensors_v8.fields.encoded_cpm1; // @th00f
+ l_cpm[2] = i_core_data_ptr->dts_cpm.sensors_v8.fields.encoded_cpm2; // @th00f
+ l_cpm[3] = i_core_data_ptr->dts_cpm.sensors_v9.fields.encoded_cpm4; // @th00f
+
+ //calculate min CPM from all CPM's for this core
+ for(k = 0; k < CPM_PER_CORE; k++)
+ {
+ if(l_cpm[k] < l_cpm_min)
+ {
+ l_cpm_min = l_cpm[k];
+ }
+ }
+
+ sensor_update( AMECSENSOR_ARRAY_PTR(CPM2MSP0C0,i_core), l_cpm_min);
+}
+*/
+
+// Function Specification
+//
+// Name: amec_calc_freq_and_util_sensors
+//
+// Description: Called every 2ms/core
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// End Function Specification
+void amec_calc_freq_and_util_sensors(gpe_bulk_core_data_t * i_core_data_ptr, uint8_t i_core)
+{
+ BOOLEAN l_core_sleep_winkle = FALSE;
+ uint32_t l_pm_state_hist_reg = 0;
+ uint32_t temp32 = 0;
+ uint32_t temp32a = 0;
+ uint16_t temp16 = 0;
+ uint16_t temp16a = 0;
+ uint16_t l_core_util = 0;
+ uint16_t l_core_freq = 0;
+ uint16_t l_time_interval = 0;
+ uint32_t l_cycles2ms = 0;
+ int i;
+
+ // Read the high-order bytes of PM State History register for this core
+ l_pm_state_hist_reg = i_core_data_ptr->pcb_slave.pm_history.words.high_order;
+
+ // If core is in fast/deep sleep mode or fast/winkle mode, then set a flag
+ // indicating this
+ if(l_pm_state_hist_reg & OCC_PAST_CORE_CLK_STOP)
+ {
+ l_core_sleep_winkle = TRUE;
+ }
+
+ // ------------------------------------------------------
+ // Per Core Frequency
+ // ------------------------------------------------------
+ // <amec_formula>
+ // Result: Calculated Core Frequency
+ // Sensor: FREQA2MSP0C0
+ // Timescale: 2ms
+ // Units: MHz
+ // Min/Max: 0/6000 (UPPER_LIMIT_PROC_FREQ_MHZ=6000)
+ // Formula: cyc_delta = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-2ms])
+ // time_delta = (TOD[t=now] - TOD[t=-2ms])
+ // frequency(MHz) = (cyc_delta / time_delta) * (2M TOD ticks / 1 second)
+ // = (2 * cyc_delta) / time_delta
+ // </amec_formula>
+
+ // Compute Delta in PC_RAW_CYCLES
+ temp32 = i_core_data_ptr->empath.raw_cycles; // @th00f
+ temp32a = g_amec->proc[0].core[i_core].prev_PC_RAW_CYCLES;
+ temp32 = l_cycles2ms = temp32 - temp32a;
+
+ // @cl007 fix freqa
+ if( (cfam_id() == CFAM_CHIP_ID_MURANO_10)
+ || (cfam_id() == CFAM_CHIP_ID_MURANO_11)
+ || (cfam_id() == CFAM_CHIP_ID_MURANO_12) )
+ {
+ temp32a = AMEC_US_PER_SMH_PERIOD; // using fixed 2000 us is showing 3% error.
+ temp32 = temp32 / temp32a;
+ }
+ else
+ {
+ temp32a = (i_core_data_ptr->empath.tod_2mhz -
+ g_amec->proc[0].core[i_core].prev_tod_2mhz);
+ temp32 = (2 * temp32) / temp32a;
+ }
+
+ // TODO: Remove this once we have the OHA Power Proxy legacy mode stuff working.
+ if(temp32 < UPPER_LIMIT_PROC_FREQ_MHZ)
+ {
+ // Update Sensor for this core
+ if(l_core_sleep_winkle)
+ {
+ l_core_freq = 0;
+ }
+ else
+ {
+ l_core_freq = (uint16_t) temp32;
+ }
+ sensor_update( AMECSENSOR_ARRAY_PTR(FREQA2MSP0C0,i_core), l_core_freq);
+ }
+
+ // ------------------------------------------------------
+ // Per Core Utilization
+ // ------------------------------------------------------
+ // <amec_formula>
+ // Result: Calculated Core Utilization
+ // Sensor: UTIL2MSP0C0
+ // Timescale: 2ms
+ // Units: 0.01 %
+ // Min/Max: 0/10000 (0/100%)
+ // Formula: cyc_delta = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-2ms])
+ // run_delta = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-2ms])
+ //
+ // UTIL(in %) = run_delta / cyc_delta
+ // </amec_formula>
+
+ // Compute Delta in PC_RUN_CYCLES
+ temp32 = i_core_data_ptr->empath.run_cycles; // @th00f
+ temp32a = g_amec->proc[0].core[i_core].prev_PC_RUN_CYCLES;
+ temp32 = temp32 - temp32a;
+
+ temp32 = temp32 >> 8; // Drop non-significant bits
+ temp16 = (uint16_t) temp32; // Cast to uint16 for mult below
+ temp16a = 10000; // Mult * 10000 to get finer resolution for 0.01%
+ temp32 = ((uint32_t)temp16a)*((uint32_t)temp16);
+
+ temp32a = l_cycles2ms; // Get Raw cycles
+ temp32a = temp32a >> 8; // Drop non-significant bits
+
+ // Calculate Utilization
+ temp32 = temp32 / temp32a;
+ if(temp32a == 0) // Prevent a divide by zero
+ {
+ temp32 = 0;
+ }
+
+ // Update Sensor for this core
+ if(l_core_sleep_winkle)
+ {
+ l_core_util = 0;
+ }
+ else
+ {
+ l_core_util = (uint16_t) temp32;
+ }
+ sensor_update(AMECSENSOR_ARRAY_PTR(UTIL2MSP0C0, i_core), l_core_util);
+
+
+ // ------------------------------------------------------
+ // Per Thread Utilization
+ // ------------------------------------------------------
+ // <amec_formula>
+ // Result: Calculated Core Utilization
+ // Sensor: None
+ // Timescale: 2ms
+ // Units: 0.01 %
+ // Min/Max: 0/10000 (0/100%)
+ // Formula: cyc_delta = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-2ms])
+ // run_delta = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-2ms])
+ //
+ // UTIL(in %) = run_delta / cyc_delta
+ // </amec_formula>
+
+ // Get RAW CYCLES for Thread
+ temp32 = i_core_data_ptr->per_thread[0].raw_cycles; // @th00f
+ temp32a = g_amec->proc[0].core[i_core].prev_PC_RAW_Th_CYCLES;
+ temp32 = l_cycles2ms = temp32 - temp32a;
+
+ for(i=0; i<MAX_THREADS_PER_CORE; i++)
+ {
+ // Get Run Counters for Thread
+ temp32 = i_core_data_ptr->per_thread[i].run_cycles; // @th00f
+ temp32a = g_amec->proc[0].core[i_core].thread[i].prev_PC_RUN_Th_CYCLES;
+ temp32 = temp32 - temp32a;
+
+ temp32 = temp32 >> 8; // Drop non-significant bits
+ temp16 = (uint16_t) temp32; // Cast to uint16 for mult below
+ temp16a = 10000; // Mult * 10000 to get finer resolution for 0.01%
+ temp32 = ((uint32_t)temp16a)*((uint32_t)temp16);
+
+ temp32a = l_cycles2ms;
+ temp32a = temp32a >> 8; // Drop non-significant bits
+
+ // Calculate Utilization
+ temp32 = temp32 / temp32a;
+ g_amec->proc[0].core[i_core].thread[i].util2ms_thread = (uint16_t) temp32;
+ }
+
+ // No sensors to update for perThread Util
+
+ // ------------------------------------------------------
+ // Per Core Sleep/Winkle Count
+ // ------------------------------------------------------
+
+ // Get Current Idle State of Chiplet
+ // The SLEEPCNT and WINKLECNT sensors are updated in amec_slv_state_0() function
+ temp16 = CONVERT_UINT64_UINT16_UPPER(i_core_data_ptr->pcb_slave.pm_history.value);
+ temp16 = temp16 & 0xE000;
+ temp16 = temp16 >> 13;
+ switch(temp16)
+ {
+ case 0: break; // Run State
+ case 1: break; // Special Wakeup
+ case 2: break; // Nap
+ case 3: SETBIT(g_amec->proc[0].sleep_cnt,i_core); break; // Legacy Sleep
+ case 4: SETBIT(g_amec->proc[0].sleep_cnt,i_core); break; // Fast Sleep
+ case 5: SETBIT(g_amec->proc[0].sleep_cnt,i_core); break; // Deep Sleep
+ case 6: SETBIT(g_amec->proc[0].winkle_cnt,i_core); break; // Fast Winkle
+ case 7: SETBIT(g_amec->proc[0].winkle_cnt,i_core); break; // Deep Winkle
+ }
+
+ // ------------------------------------------------------
+ // Core Memory Hierarchy C LPARx Utilization counters
+ // ------------------------------------------------------
+ for(i=0; i<4; i++)
+ {
+ // Extract the utilization counter
+ temp32 = i_core_data_ptr->per_partition_memory.count[i];
+
+ // Convert counter to 0.01 Mrps resolution. Since we access every 2 ms:
+ // ((2ms read * 500) / 10000)
+ temp32a = temp32 - g_amec->proc[0].core[i_core].prev_lpar_mem_cnt[i];
+ g_amec->proc[0].core[i_core].prev_lpar_mem_cnt[i] = temp32;
+ temp32 = (temp32a * 5) / 100;
+
+ // Store the bandwidth for this LPAR
+ g_amec->proc[0].core[i_core].membw[i] = (uint16_t)temp32;
+ }
+
+ // Sum up all the memory bandwidth data from the LPARs
+ temp32 = g_amec->proc[0].core[i_core].membw[0] +
+ g_amec->proc[0].core[i_core].membw[1] +
+ g_amec->proc[0].core[i_core].membw[2] +
+ g_amec->proc[0].core[i_core].membw[3];
+
+ // Divide by two due to a bug in the hardware
+ temp32 = temp32/2;
+
+ // Update Sensor for this core
+ sensor_update( AMECSENSOR_ARRAY_PTR(CMBW2MSP0C0,i_core), (uint16_t) temp32);
+
+ // ------------------------------------------------------
+ // Core Stall counters
+ // ------------------------------------------------------
+ temp32 = i_core_data_ptr->empath.freq_sens_busy;
+ temp32a = g_amec->proc[0].core[i_core].prev_FREQ_SENS_BUSY;
+ temp32 = temp32 - temp32a;
+ temp32 = temp32 >> 8;
+
+ // Update Sensor for this core
+ sensor_update( AMECSENSOR_ARRAY_PTR(NOTBZE2MSP0C0,i_core), (uint16_t) temp32);
+
+ temp32 = i_core_data_ptr->empath.freq_sens_finish;
+ temp32a = g_amec->proc[0].core[i_core].prev_FREQ_SENS_FINISH;
+ temp32 = temp32 - temp32a;
+ temp32 = temp32 >> 8;
+
+ // Update Sensor for this core
+ sensor_update( AMECSENSOR_ARRAY_PTR(NOTFIN2MSP0C0,i_core), (uint16_t) temp32);
+
+ // ------------------------------------------------------
+ // Per Core Normalized Average Utilization
+ // ------------------------------------------------------
+ // <amec_formula>
+ // Result: Calculated Normalized Average Core Utilization
+ // Sensor: NUTIL3SP0C0
+ // Timescale: 2ms (3s rolling average)
+ // Units: 0.01 %
+ // Min/Max: 0/10000 (0/100%)
+ // </amec_formula>
+
+ // Determine the time interval for the rolling average calculation
+ l_time_interval = AMEC_DPS_SAMPLING_RATE * AMEC_IPS_AVRG_INTERVAL;
+
+ // Increment our sample count but prevent it from wrapping
+ if(g_amec->proc[0].core[i_core].sample_count < UINT16_MAX)
+ {
+ g_amec->proc[0].core[i_core].sample_count++;
+ }
+
+ if(g_amec->proc[0].core[i_core].sample_count == l_time_interval)
+ {
+ // Increase resolution of the UTIL accumulator by two decimal places
+ temp32 = AMECSENSOR_ARRAY_PTR(UTIL2MSP0C0,i_core)->accumulator * 100;
+ // Calculate average utilization of this core
+ temp32 = temp32 / g_amec->proc[0].core[i_core].sample_count;
+ g_amec->proc[0].core[i_core].avg_util = temp32;
+
+ // Increase resolution of the FREQA accumulator by two decimal places
+ temp32 = AMECSENSOR_ARRAY_PTR(FREQA2MSP0C0,i_core)->accumulator * 100; // @mw626
+ // Calculate average frequency of this core
+ temp32 = temp32 / g_amec->proc[0].core[i_core].sample_count;
+ g_amec->proc[0].core[i_core].avg_freq = temp32;
+ }
+
+ if(g_amec->proc[0].core[i_core].sample_count > l_time_interval)
+ {
+ // Calculate average utilization for this core
+ temp32 = (uint32_t) g_amec->proc[0].core[i_core].avg_util;
+ temp32 = temp32 * (l_time_interval-1);
+ temp32 = temp32 + l_core_util*100;
+ g_amec->proc[0].core[i_core].avg_util = temp32 / l_time_interval;
+
+ //if(g_amec->proc[0].core[i_core].avg_util > 9000)
+ //{ This rounds up only!
+ //g_amec->proc[0].core[i_core].avg_util = (temp32+ (1500-1)) / 1500;
+ //}
+
+ // Calculate average frequency for this core
+ temp32 = (uint32_t) g_amec->proc[0].core[i_core].avg_freq;
+ temp32 = temp32 * (l_time_interval-1);
+ temp32 = temp32 + l_core_freq*100;
+ g_amec->proc[0].core[i_core].avg_freq = temp32 / l_time_interval;
+ }
+
+ // Calculate the normalized utilization for this core
+ if(g_amec->proc[0].core[i_core].avg_freq != 0)
+ {
+ // First, revert back to the original resolution of the sensors
+ temp32 = g_amec->proc[0].core[i_core].avg_util / 100;
+ temp32a = g_amec->proc[0].core[i_core].avg_freq / 100;
+
+ // Compute now the normalized utilization as follows:
+ // Normalized utilization = (Average_utilization)/(Average_frequency) * Fnom
+ // Note: The 100000 constant is to increase the precision of our division
+ temp32 = (temp32 * 100000) / temp32a;
+ temp32 = (temp32 * G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]) / 100000;
+
+ // Update sensor for this core
+ if(l_core_sleep_winkle)
+ {
+ sensor_update(AMECSENSOR_ARRAY_PTR(NUTIL3SP0C0, i_core), 0);
+ }
+ else
+ {
+ sensor_update(AMECSENSOR_ARRAY_PTR(NUTIL3SP0C0, i_core), (uint16_t)temp32);
+ }
+ }
+}
+
+
+void amec_calc_ips_sensors(gpe_bulk_core_data_t * i_core_data_ptr, uint8_t i_core)
+{
+#define TWO_PWR_24_MASK 0x00FFFFFF
+#define TWO_PWR_20_MASK 0x000FFFFF
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ INT32 cyc1 = 0; //cycle counts
+ INT32 cyc2 = 0;
+ UINT32 fin1 = 0; //finished instruction counts
+ UINT32 fin2 = 0;
+ INT32 disp1 = 0; //dispatched instruction counts
+ INT32 disp2 = 0;
+ UINT32 temp32 = 0;
+ UINT32 ticks_2mhz = 0; // IPS sensor interval in 2mhz ticks
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Get Run Cycles
+ cyc1 = i_core_data_ptr->empath.run_cycles; // @th00f
+ cyc2 = g_amec->proc[0].core[i_core].prev_PC_RUN_CYCLES;
+ cyc2 = cyc1 - cyc2;
+ // since we are doing 24-bit unsigned math, we need to account for the
+ // overflow case. If this occurs, we mask off the "overflow" to make it behave
+ // like a 32-bit subtraction overflow would.
+ // @cl007 This looks bogus...the counters are supposed to be 32-bit
+ // since we are doing 24-bit unsigned math, we need to account for the
+ // overflow case. If this occurs, we mask off the "overflow" to make it behave
+ // like a 32-bit subtraction overflow would.
+ //if ( cyc2 < 0 )
+ //{
+ // cyc2 &= TWO_PWR_24_MASK;
+ //}
+
+ //AMEC_PERFCNT_PERFSCOM_GET_CNTA(fin1, l_scom_ptr->scom_prev);
+ fin1 = i_core_data_ptr->empath.completion; // @th00f
+ //AMEC_PERFCNT_PERFSCOM_GET_CNTA(fin2, l_scom_ptr->scom_current);
+ fin2 = g_amec->proc[0].core[i_core].prev_PC_COMPLETED;
+ fin2 = fin1 - fin2;
+ // see the above 2^24 comment
+ // cl007 Is this counting every completed instruction or 1 of every 16?
+ // Why are we masking 20 bits of a 32-bit counter?
+ //if ( fin2 < 0 )
+ //{
+ // fin2 &= TWO_PWR_20_MASK;
+ //}
+
+ //AMEC_PERFCNT_PERFSCOM_GET_CNTB(disp1, l_scom_ptr->scom_prev);
+ disp1 = i_core_data_ptr->empath.dispatch; // @th00f
+ //AMEC_PERFCNT_PERFSCOM_GET_CNTB(disp2, l_scom_ptr->scom_current);
+ disp2 = g_amec->proc[0].core[i_core].prev_PC_DISPATCH;
+ disp2 = disp1 - disp2;
+ //see the above 2^24 comment
+ if ( disp2 < 0 )
+ {
+ disp2 &= TWO_PWR_20_MASK;
+ }
+
+ // ------------------------------------------------------
+ // Per Core IPC Calculation
+ // ------------------------------------------------------
+ // <amec_formula>
+ // Result: Calculated Instructions per Cycle
+ // Sensor: None
+ // Timescale: 2ms
+ // Units: 0.01 IPC
+ // Min/Max: ?
+ // Formula: ipc_delta = (INST_COMPLETE[t=now] - INST_COMPLETE[t=-2ms])
+ // run_cycles = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-2ms])
+ // 100 = Convert 0.01 DPC
+ //
+ // IPC(in 0.01 IPC) = (ipc_delta * 100) / run_cycles
+ // </amec_formula>
+ temp32 = (fin2 * 100); // In units of IPS
+ temp32 = temp32 / cyc2; // In units of 0.01 DPC
+ g_amec->proc[0].core[i_core].ipc = temp32;
+
+
+ // ------------------------------------------------------
+ // Per Core DPC Calculation
+ // ------------------------------------------------------
+ // <amec_formula>
+ // Result: Calculated dispatched Instructions per Cycle
+ // Sensor: None
+ // Timescale: 2ms
+ // Units: 0.2Mips
+ // Min/Max: ?
+ // Formula: dpc_delta = (INST_DISPATCH[t=now] - INST_DISPATCH[t=-2ms])
+ // run_cycles = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-2ms])
+ // 100 = Convert 0.01 DPC
+ //
+ // DPC(in 0.01DPC) = (dpc_delta * 100) / run_cycles
+ // </amec_formula>
+ temp32 = (disp2 * 100); // In units of IPS
+ temp32 = temp32 / cyc2; // In units of 0.01 DPC
+ g_amec->proc[0].core[i_core].dpc = temp32;
+
+ // ------------------------------------------------------
+ // Per Core DPS Calculation
+ // ------------------------------------------------------
+ // <amec_formula>
+ // Result: Calculated dispatched Instructions per Second
+ // Sensor: None
+ // Timescale: 2ms
+ // Units: 0.2Mips
+ // Min/Max: ?
+ // Formula: dps_delta = (INST_DISPATCH[t=now] - INST_DISPATCH[t=-2ms])
+ // 500 = # of 2ms periods in 1 second
+ // 50,000 = Convert IPS to 0.2MIPS
+ //
+ // DPS(in 0.2Mips) = (dps_delta * 500) / 50,000
+ // </amec_formula>
+ temp32 = (disp2 * AMEC_SMH_PERIODS_IN_1SEC); // In untis of IPS
+ temp32 = temp32 / 50000; // In units of 0.2Mips (max 327675 Mips for uint16_t)
+ g_amec->proc[0].core[i_core].dps = temp32;
+
+ // ------------------------------------------------------
+ // Per Core IPS Calculation
+ // ------------------------------------------------------
+ // <amec_formula>
+ // Result: Calculated Instructions per Second
+ // Sensor: IPS2MSP0C0
+ // Timescale: 2ms
+ // Units: 0.2Mips
+ // Min/Max: ?
+ // Formula:
+ // comp_delta = (INST_COMPLETE[t=now] - INST_COMPLETE[t=-2ms])
+ // ticks_delta = (TOD[t=now] - TOD[t=-2ms])
+ // MIPS = comp_delta (insns/interval) * (1 interval per ticks_delta 2mhz ticks) * (2M 2mhz ticks / s) / 1M
+ // = (2* fin2) / ticks_2mhz
+ // Note: For best resolution do multiply first and division last.
+ // </amec_formula>
+
+ //cl007 fix ips calculation
+ ticks_2mhz = i_core_data_ptr->empath.tod_2mhz -
+ g_amec->proc[0].core[i_core].prev_tod_2mhz;
+ temp32 = (fin2 << 1) / ticks_2mhz;
+ sensor_update( AMECSENSOR_ARRAY_PTR(IPS2MSP0C0,i_core), (uint16_t) temp32);
+}
+
+
+// Function Specification
+//
+// Name: amec_calc_spurr
+//
+// Description: Do SPURR calculation. Must run after FreqA is calculated.
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_calc_spurr(uint8_t i_core)
+{
+ uint16_t l_actual_freq = AMECSENSOR_ARRAY_PTR(FREQA2MSP0C0, i_core)->sample; // @mw626
+ uint16_t l_nominal = 2790;
+ uint32_t temp32;
+
+ // Sanity Check on Freq
+ if(l_actual_freq < UPPER_LIMIT_PROC_FREQ_MHZ)
+ {
+ temp32 = ((uint32_t) (l_actual_freq * 1000) / l_nominal);
+
+ // Scale for SPURR Register (64 = Nominal, 32 = Nom-50%)
+ temp32 = (temp32 * 64) / 1000;
+
+ sensor_update( AMECSENSOR_ARRAY_PTR(SPURR2MSP0C0,i_core), (uint16_t) temp32);
+ }
+}
+
+
diff --git a/src/occ/amec/amec_sensors_core.h b/src/occ/amec/amec_sensors_core.h
new file mode 100755
index 0000000..eb805db
--- /dev/null
+++ b/src/occ/amec/amec_sensors_core.h
@@ -0,0 +1,55 @@
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_sensors_core_h amec_sensors_core.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- --------------------------------------
+ * @th00b thallet 02/24/2012 New file
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gs024 912700 gjsilva 01/22/2014 Identify fast/deep winkle states
+ * @gs028 917695 gjsilva 03/04/2014 Check if cores are in a sleep state
+ * 917695 gjsilva 03/05/2014 Changes from code review
+ *
+ * @endverbatim
+ */
+
+#ifndef _AMEC_SENSORS_CORE_H
+#define _AMEC_SENSORS_CORE_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+#include "amec_external.h"
+#include <occ_sys_config.h>
+
+
+/*----------------------------------------------------------------------------*/
+/* Defines/Constants */
+/*----------------------------------------------------------------------------*/
+// See bit definition of PM State History Register for OCC
+#define OCC_PM_STATE_MASK 0x1F000000 //Mask bits 0:2 of the register
+#define OCC_PAST_FAST_SLEEP 0x18000000 //Core has been in fast sleep
+#define OCC_PAST_DEEP_SLEEP 0x1C000000 //Core has been in deep sleep
+#define OCC_PAST_FAST_WINKLE 0x1E000000 //Core has been in fast winkle
+#define OCC_PAST_DEEP_WINKLE 0x1F000000 //Core has been in deep winkle
+#define OCC_PAST_CORE_CLK_STOP 0x08000000 //Core has been in an idle state with core clocks stopped
+
+/*----------------------------------------------------------------------------*/
+/* Structures */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Function Declarations */
+/*----------------------------------------------------------------------------*/
+void amec_update_fast_core_data_sensors(void);
+
+void amec_update_proc_core_sensors(uint8_t i_core);
+
+
+
+#endif // _AMEC_SENSORS_CORE_H
diff --git a/src/occ/amec/amec_sensors_fw.c b/src/occ/amec/amec_sensors_fw.c
new file mode 100755
index 0000000..2967b51
--- /dev/null
+++ b/src/occ/amec/amec_sensors_fw.c
@@ -0,0 +1,221 @@
+// @file amec_sensors_fw.c
+// @brief AMEC FW Sensor Calculations
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_sensors_power_c amec_sensors_power.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- --------------------------------------
+ * @th00b thallet 02/24/2012 New file
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @gm008 SW226989 milesg 09/30/2013 Sapphire initial support
+ * @gm030 917444 milesg 03/06/2014 Add FFDC for GPE jobs timing out
+ *
+ * @endverbatim
+ */
+
+/******************************************************************************/
+/* Includes */
+/******************************************************************************/
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include "sensor.h"
+#include "rtls.h"
+#include "occ_sys_config.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "dcom.h"
+#include "proc_data.h"
+#include "amec_smh.h"
+#include "amec_slave_smh.h"
+#include <trac.h>
+#include "amec_sys.h"
+#include "sensor_enum.h"
+#include "amec_service_codes.h"
+#include <amec_sensors_fw.h>
+
+
+// Function Specification
+//
+// Name: amec_slv_update_smh_sensors
+//
+// Description: Update FW Sensors with Amec Slave Timings.
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_slv_update_smh_sensors(int i_smh_state, uint32_t i_duration)
+{
+ // Update the duration in the fw timing table
+ G_fw_timing.amess_state = i_smh_state;
+ G_fw_timing.amess_dur = i_duration;
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_update_gpe_sensors
+//
+// Description: Update FW Sensors with GPE Engine Timings. Called from
+// callback on GPE routine completion.
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_slv_update_gpe_sensors(uint8_t i_gpe_engine)
+{
+ // Update the duration in the fw timing table
+ G_fw_timing.gpe_dur[i_gpe_engine] = DURATION_IN_US_UNTIL_NOW_FROM(G_fw_timing.rtl_start_gpe);
+}
+
+
+// Function Specification
+//
+// Name: amec_update_fw_sensors
+//
+// Description: Updates sensors related to the OCC FW Timings
+//
+//
+// Flow: 02/01/2012 FN= amec_update_fw_sensors
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+#define MAX_CONSEC_TRACE 4
+void amec_update_fw_sensors(void)
+{
+ errlHndl_t l_err = NULL;
+ int rc = 0;
+ int rc2 = 0;
+ static bool l_first_call = TRUE;
+ bool l_gpe0_idle, l_gpe1_idle; //gm030
+ static int L_consec_trace_count = 0; //gm030
+
+ // ------------------------------------------------------
+ // Update OCC Firmware Sensors from last tick
+ // ------------------------------------------------------
+ int l_last_state = G_fw_timing.amess_state;
+ // RTLtickdur = duration of last tick's RTL ISR (max = 250us)
+ sensor_update( AMECSENSOR_PTR(RTLtickdur), G_fw_timing.rtl_dur);
+ // AMEintdur = duration of last tick's AMEC portion of RTL ISR
+ sensor_update( AMECSENSOR_PTR(AMEintdur), G_fw_timing.ameint_dur);
+ // AMESSdurX = duration of last tick's AMEC state
+ if(l_last_state >= NUM_AMEC_SMH_STATES)
+ {
+ // Sanity check. Trace this out, even though it should never happen.
+ TRAC_INFO("AMEC State Invalid, Sensor Not Updated");
+ }
+ else
+ {
+ // AMESSdurX = duration of last tick's AMEC state
+ sensor_update( AMECSENSOR_ARRAY_PTR(AMESSdur0, l_last_state), G_fw_timing.amess_dur);
+ }
+
+ // ------------------------------------------------------
+ // Kick off GPE programs to track WorstCase time in GPE
+ // and update the sensors.
+ // ------------------------------------------------------
+ if( (NULL != G_fw_timing.gpe0_timing_request)
+ && (NULL != G_fw_timing.gpe1_timing_request) )
+ {
+ //Check if both GPE engines were able to complete the last GPE job on the queue
+ //within 1 tick.
+ l_gpe0_idle = async_request_is_idle(&G_fw_timing.gpe0_timing_request->request); //gm030
+ l_gpe1_idle = async_request_is_idle(&G_fw_timing.gpe1_timing_request->request); //gm030
+ if(l_gpe0_idle && l_gpe1_idle)
+ {
+ //reset the consecutive trace count
+ L_consec_trace_count = 0;
+
+ //Both GPE engines finished on time. Now check if they were successful too.
+ if( async_request_completed(&(G_fw_timing.gpe0_timing_request->request))
+ && async_request_completed(&(G_fw_timing.gpe1_timing_request->request)) )
+ {
+ // GPEtickdur0 = duration of last tick's PORE-GPE0 duration
+ sensor_update( AMECSENSOR_PTR(GPEtickdur0), G_fw_timing.gpe_dur[0]);
+ // GPEtickdur1 = duration of last tick's PORE-GPE1 duration
+ sensor_update( AMECSENSOR_PTR(GPEtickdur1), G_fw_timing.gpe_dur[1]);
+ }
+ else
+ {
+ //This case is expected on the first call of the function. After that,
+ //this should not happen.
+ if(!l_first_call) //@gm008
+ {
+ //Note: FFDC for this case is gathered by each task responsible for
+ // a GPE job.
+ TRAC_INFO("GPE task idle but GPE task did not complete");
+ }
+ l_first_call = FALSE;
+ }
+
+ // Update Time used to measure GPE duration.
+ G_fw_timing.rtl_start_gpe = G_fw_timing.rtl_start;
+
+ // Schedule the GPE Routines that will run and update the worst
+ // case timings (via callback) after they complete. These GPE
+ // routines are the last GPE routines added to the queue
+ // during the RTL tick.
+ rc = pore_flex_schedule(G_fw_timing.gpe0_timing_request);
+ rc2 = pore_flex_schedule(G_fw_timing.gpe1_timing_request);
+
+ if(rc || rc2)
+ {
+ /* @
+ * @errortype
+ * @moduleid AMEC_UPDATE_FW_SENSORS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 return code - gpe0
+ * @userdata2 return code - gpe1
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure to schedule PORE-GPE poreFlex object for FW timing
+ * analysis.
+ */
+ l_err = createErrl(
+ AMEC_UPDATE_FW_SENSORS, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ rc2); //userdata2
+
+ // commit error log
+ commitErrl( &l_err );
+ }
+ }
+ else if(L_consec_trace_count < MAX_CONSEC_TRACE) //gm030
+ {
+ uint64_t l_dbg1;
+
+ // gm030
+ // Reset will eventually be requested due to not having power measurement
+ // data after X ticks, but add some additional FFDC to the trace that
+ // will tell us what GPE job is currently executing.
+ if(!l_gpe0_idle)
+ {
+ l_dbg1 = in64(PORE_GPE0_DBG1);
+ TRAC_ERR("GPE0 programs did not complete within one tick. DBG1[0x%08x%08x]",
+ l_dbg1 >> 32,
+ l_dbg1 & 0x00000000ffffffffull);
+ }
+ if(!l_gpe1_idle)
+ {
+ l_dbg1 = in64(PORE_GPE1_DBG1);
+ TRAC_ERR("GPE1 programs did not complete within one tick. DBG1[0x%08x%08x]",
+ l_dbg1 >> 32,
+ l_dbg1 & 0x00000000ffffffffull);
+ }
+ L_consec_trace_count++;
+ }
+ }
+}
+
+
+
diff --git a/src/occ/amec/amec_sensors_fw.h b/src/occ/amec/amec_sensors_fw.h
new file mode 100755
index 0000000..144aa68
--- /dev/null
+++ b/src/occ/amec/amec_sensors_fw.h
@@ -0,0 +1,46 @@
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_sensors_fw_h amec_sensors_fw.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- --------------------------------------
+ * @th00b thallet 02/24/2012 New file
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ *
+ * @endverbatim
+ */
+
+#ifndef _AMEC_SENSORS_FW_H
+#define _AMEC_SENSORS_FW_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+#include "amec_external.h"
+
+
+/*----------------------------------------------------------------------------*/
+/* Defines/Constants */
+/*----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------*/
+/* Function Declarations */
+/*----------------------------------------------------------------------------*/
+// Function that updates the AMEC interim structures with AMEC State Durations
+void amec_slv_update_smh_sensors(int i_smh_state, uint32_t i_duration);
+
+// Function that updates the AMEC interim structures with GPE Engine Durations
+void amec_slv_update_gpe_sensors(uint8_t i_gpe_engine);
+
+// Function that updates the AMEC FW sensors
+void amec_update_fw_sensors(void);
+
+
+#endif // _AMEC_SENSORS_FW_H
diff --git a/src/occ/amec/amec_sensors_power.c b/src/occ/amec/amec_sensors_power.c
new file mode 100755
index 0000000..5c4923f
--- /dev/null
+++ b/src/occ/amec/amec_sensors_power.c
@@ -0,0 +1,574 @@
+/******************************************************************************
+// @file amec_sensors_power.c
+// @brief AMEC Power Sensor Calculations
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_sensors_power_c amec_sensors_power.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- --------------------------------------
+ * thallet 02/24/2012 New file
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th019 835007 thallet 09/11/2012 Added power sensors
+ * @th044 892742 thallet 07/24/2013 Added module ID
+ * @ly008 894646 lychen 08/08/2013 Fix bugs in OCC handling of APSS tables for Brazos/Orlena
+ * @at016 891144 alvinwan 06/10/2013 OCC Power Cap Testing
+ * @sb000 905048 sbroyles 10/28/2013 Add tags for code cleanup,
+ * see RTC task 73327.
+ * @rt003 905677 tapiar 11/07/2013 save of proc/mem sensor data
+ * @sb001 906360 sbroyles 11/12/2013 Resolve fix tags
+ * @fk004 907588 fmkassem 11/27/2013 Add support for snapshot buffer.
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ * @mw634 mware 02/09/2014 Added in call to amec_controller_centaur for stream recording
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ * @gm026 916029 milesg 02/17/2014 revert back to auto2 mode without reading GPIO's
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ * @gm034 920562 milesg 03/28/2014 fix voltage sensors
+ * @endverbatim
+ */
+
+/******************************************************************************/
+/* Includes */
+/******************************************************************************/
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include "sensor.h"
+#include "rtls.h"
+#include "occ_sys_config.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "dcom.h"
+#include "proc_data.h"
+#include "amec_smh.h"
+#include "amec_slave_smh.h"
+#include <trac.h>
+#include "amec_sys.h"
+#include "sensor_enum.h"
+#include "amec_service_codes.h"
+#include <amec_sensors_power.h>
+#include <cmdh_snapshot.h> //@fk004a
+#include <vrm.h>
+#include "amec_oversub.h"
+
+// This holds the converted ADC Reads
+uint32_t G_lastValidAdcValue[MAX_APSS_ADC_CHANNELS] = {0};
+
+extern thrm_fru_data_t G_thrm_fru_data[DATA_FRU_MAX];
+
+#define ADC_CONVERTED_VALUE(i_chan) \
+ ((i_chan < MAX_APSS_ADC_CHANNELS) ? G_lastValidAdcValue[i_chan] : 0)
+
+// Function Specification
+//
+// Name: amec_sensor_from_apss_adc
+//
+// Description: Calculates sensor from raw ADC value
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+uint32_t amec_value_from_apss_adc(uint8_t i_chan)
+{
+ uint16_t l_raw = 0;
+ uint32_t l_temp = 0;
+ uint32_t l_gain = 0;
+ uint32_t l_offset = 0;
+
+ if(i_chan != SYSCFG_INVALID_ADC_CHAN)
+ {
+ /*
+ * @sb001 Several changes made under this tag, see occ810 version 1.9
+ * for previous version.
+ * The APSS value is in mV or mA depending on the channel and the raw
+ * reading from the APSS must be decoded using the following info:
+ *
+ * APSS LSB: Vref/4096
+ * Full scale: (Vref - LSB) = 0xFFF
+ * Midscale: Vref/2 = 0x800
+ * Midscale - 1 LSB: Vref/2 - 1 LSB, 0x7FF
+ * Zero: 0V, 0x000
+ * Any voltage at or above Vref will will result in an ADC channel value
+ * of 0xFFF
+ *
+ * Our APSS has Vref pinned to 2.048 V
+ * LSB: 0.5 mV (minimum ADC resolution)
+ * Full scale: 2047.5 mV (0xFFF)
+ * Midscale: 1024 mV (0x800)
+ * Zero: 0V, 0x000
+ *
+ * To get the right mV reading from the raw APSS data all we need to do
+ * is divide the raw 12 bit ADC code by 2. The same logic applies if
+ * the channel is measuring power in mA.
+ *
+ * If there is an offset it will bein mV or mA depending upon the sensor
+ * and it needs to be added or subtracted from the raw value depending
+ * on it's signedness. Negative offsets are stored in 2's complement
+ * form.
+ *
+ * The gain values will be multiplied by 1000 in TMGT before being sent
+ * in the sysconfig packet. Raw gain from the MRW values are in A/V and
+ * TMGT will multiply this by 1000 before sending in the sysconfig
+ * packet to preserve precision. That makes the gain units mA/V.
+ *
+ * To apply the gain multiply the sysconfig value against the converted
+ * APSS voltage.
+ *
+ * Applying the gain to the converted APSS data gives (mV . mA)/V so we
+ * divide by 1000 to reduce the result to mA. This is the unit that
+ * is returned to the caller. For example:
+ * raw APSS value: 0x800
+ * converted value: raw/2 = 1024 mV
+ * gain from MRW: 10.00 A/V
+ * Converted gain: 10,000 mA/V
+ * gain adjusted output: 1024mV * 10,000 mA/V = 10,240,000 (mV . mA)/V
+ * Reduced value: adjusted/1000 = 10,240 mA
+ *
+ * Note that in the case of the remote ground and 12V sense the gain
+ * values are in V/V so the returned value is actually in mVs.
+ *
+ * Max returnable value is 4,294,967,295 mA or approx. 4.3 MA
+ */
+
+ // Get ADC Mapping calibration info for this entity.
+ l_gain = G_sysConfigData.apss_cal[i_chan].gain;
+ l_offset = G_sysConfigData.apss_cal[i_chan].offset;
+
+ // Read Raw Value in mA (divide masked channel data by 2)
+ l_raw = (G_dcom_slv_inbox_rx.adc[i_chan] & APSS_12BIT_ADC_MASK)/2;
+ // Apply offset and gain
+ if (l_offset & 0x80000000)
+ {
+ // Negative offset
+ l_raw -= (~l_offset + 1);
+ }
+ else
+ {
+ l_raw += l_offset;
+ }
+
+ l_temp = ((uint32_t)l_raw * l_gain);
+ // Reduce value back to mA or mV
+ l_temp /= 1000;
+ }
+
+ AMEC_DBG("APSS ADC info: chan=%d, raw=0x%04x, offset=%d, gain=%d calibrated output=%d\n",
+ i_chan, l_raw, l_offset, l_gain, l_temp);
+
+ return l_temp;
+}
+
+
+// Function Specification
+//
+// Name: amec_update_apss_sensors
+//
+// Description: Calculates sensor from raw ADC value
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_apss_sensors(void)
+{
+ /*
+ * @sb001 Removed fake apss config data, do not reuse, the old hardcoded
+ * values will not work with the new code used in processing APSS channel
+ * data. See occ810 version 1.9 of this file for the hardcoded values that
+ * were removed.
+ * Code is in place to receive command code 0x21 SET CONFIG DATA from the
+ * FSP which should popluate the ADC and GPIO maps as well as the APSS
+ * calibration data for all 16 ADC channels.
+ */
+
+ // ------------------------------------------------------
+ // APSS Data Collection & Sensorization
+ // ------------------------------------------------------
+
+ // Need to check to make sure APSS data has been received
+ // via slave inbox first
+ if(G_slv_inbox_received)
+ {
+ uint8_t l_proc = G_pob_id.module_id;
+ uint32_t temp32 = 0;
+ uint8_t l_idx = 0;
+ uint32_t l_bulk_current_sum = 0;
+
+ // ----------------------------------------------------
+ // Convert all ADC Channels immediately
+ // ----------------------------------------------------
+ for(l_idx=0; l_idx < MAX_APSS_ADC_CHANNELS; l_idx++)
+ {
+ // These values returned are gain adjusted. The APSS readings for
+ // the remote ground and 12V sense are returned in mVs, all other
+ // readings are treated as mAs.
+ G_lastValidAdcValue[l_idx] = amec_value_from_apss_adc(l_idx);
+
+ // Add up all channels now, we will subtract ones later that don't
+ // count towards the system power
+ l_bulk_current_sum += G_lastValidAdcValue[l_idx];
+ }
+
+ // ----------------------------------------------------
+ // Convert 12Vsense into interim value - this has to happen first
+ // ----------------------------------------------------
+ uint32_t l_bulk_voltage = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.sense_12v);
+
+ // ----------------------------------------------------
+ // Convert Raw Vdd/Vcs/Vio/Vpcie Power from APSS into sensors
+ // ----------------------------------------------------
+ // Some sensor values are in Watts so after getting the mA readings we
+ // multiply by the bulk voltage (mVs) which requires us to then divide
+ // by 1000000 to get W (A.V), ie.
+ // divide by 1000 to get it back to milliUnits (0.001)
+ // divide by 10000 to get it to centiUnits (0.01)
+ // divide by 100000 to get it to deciUnits (0.1)
+ // divide by 1000000 to get it to Units (1)
+ #define ADCMULT_TO_UNITS 1000000 // @at016a
+ #define ADCMULT_ROUND ADCMULT_TO_UNITS/2 // @mw580
+ uint32_t l_vdd = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vdd[l_proc]);
+ uint32_t l_vcs_vio_vpcie = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vcs_vio_vpcie[l_proc]);
+ temp32 = ((l_vcs_vio_vpcie + l_vdd) * l_bulk_voltage)/ADCMULT_TO_UNITS; // @at016c
+ sensor_update(AMECSENSOR_PTR(PWR250USP0), (uint16_t) temp32);
+ // Save off the combined power from all modules
+ //@rt003a
+ for (l_idx=0; l_idx < MAX_NUM_CHIP_MODULES; l_idx++)
+ {
+ uint32_t l_vd = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vdd[l_idx]);
+ uint32_t l_vpcie = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.vcs_vio_vpcie[l_idx]);
+ g_amec->proc_snr_pwr[l_idx] = ((l_vpcie + l_vd) * l_bulk_voltage)/ADCMULT_TO_UNITS;
+ }
+
+ // All readings from APSS come back as milliUnits, so if we want
+ // to convert one, we need to
+ // divide by 1 to get it back to milliUnits (0.001)
+ // divide by 10 to get it to centiUnits (0.01)
+ // divide by 100 to get it to deciUnits (0.1)
+ // divide by 1000 to get it to Units (1)
+ #define ADCSINGLE_TO_CENTIUNITS 100 // @mw580
+ // Vdd has both a power and a current sensor, we convert the Vdd power
+ // to Watts and the current to centiAmps
+ temp32 = ((l_vdd * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @at016c @mw580
+ sensor_update( AMECSENSOR_PTR(PWR250USVDD0), (uint16_t)temp32);
+ temp32 = (l_vdd)/ADCSINGLE_TO_CENTIUNITS; // Current is in 0.01 Amps,
+ sensor_update( AMECSENSOR_PTR(CUR250USVDD0), l_vdd);
+ temp32 = ((l_vcs_vio_vpcie * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @at016c @mw580
+ sensor_update( AMECSENSOR_PTR(PWR250USVCS0), (uint16_t)temp32);
+
+ // ----------------------------------------------------
+ // Convert Other Raw Misc Power from APSS into sensors
+ // ----------------------------------------------------
+
+ // Fans
+ temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.fans[0]);
+ temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.fans[1]);
+ temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @at016c @mw580
+ sensor_update( AMECSENSOR_PTR(PWR250USFAN), (uint16_t)temp32);
+
+ // I/O
+ temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[0]);
+ temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[1]);
+ temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.io[2]);
+ temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @at016c @mw580
+ sensor_update( AMECSENSOR_PTR(PWR250USIO), (uint16_t)temp32);
+
+ // Memory
+ temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.memory[l_proc]);
+ temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @at016c @mw580
+ sensor_update( AMECSENSOR_PTR(PWR250USMEM0), (uint16_t)temp32);
+ // Save off the combined power from all memory
+ //@rt003a
+ for (l_idx=0; l_idx < MAX_NUM_CHIP_MODULES; l_idx++)
+ {
+ uint32_t l_temp = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.memory[l_idx]);
+ g_amec->mem_snr_pwr[l_idx] = ((l_temp * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @mw580
+ }
+
+ // Storage/Media
+ temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.storage_media[0]);
+ temp32 += ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.storage_media[1]);
+ temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @at016c @mw580
+ sensor_update( AMECSENSOR_PTR(PWR250USSTORE), (uint16_t)temp32);
+
+ // GPU adapter
+ temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.gpu);
+ temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS;
+ sensor_update( AMECSENSOR_PTR(PWR250USGPU), (uint16_t)temp32);
+
+ // ----------------------------------------------------
+ // Convert Raw Bulk Power from APSS into sensors
+ // ----------------------------------------------------
+ // We don't get this adc channel in Tuleta, we have to add it manually.
+ // With valid sysconfig data the code here should automatically use what
+ // is provided by the APSS if it is available, or manually sum it up if not.
+ temp32 = ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.total_current_12v);
+ temp32 = ((temp32 * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @at016c @mw580
+
+ // To calculated the total 12V current based on a sum of all ADC channels,
+ // Subract adc channels that don't measure power
+ l_bulk_current_sum -= ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.sense_12v);
+ l_bulk_current_sum -= ADC_CONVERTED_VALUE(G_sysConfigData.apss_adc_map.remote_gnd);
+
+ // If we don't have a ADC channel that measures the bulk 12v power, use
+ // the ADC sum instead
+ if(0 == temp32)
+ {
+ temp32 = ((l_bulk_current_sum * l_bulk_voltage)+ADCMULT_ROUND)/ADCMULT_TO_UNITS; // @at016c @mw580
+ }
+ sensor_update(AMECSENSOR_PTR(PWR250US), (uint16_t)temp32);
+
+ //@fk004a - Calculate average frequency of all OCCs.
+ uint32_t l_allOccAvgFreqOver250us = 0;
+ uint8_t l_presentOCCs = 0;
+ uint8_t l_occCount = 0;
+
+ // Add up the average freq from all OCCs.
+ for (l_occCount = 0; l_occCount < MAX_OCCS; l_occCount++)
+ {
+ if (G_sysConfigData.is_occ_present & (1<< l_occCount))
+ {
+ l_allOccAvgFreqOver250us += G_dcom_slv_outbox_rx[l_occCount].freqa2msp0;
+ l_presentOCCs++;
+ }
+ }
+ //Calculate average of all the OCCs.
+ l_allOccAvgFreqOver250us /= l_presentOCCs;
+
+ // @fk004a
+ // Save the max and min pwr250us sensors and keep
+ // an accumulator of the average frequency over 30 seconds.
+ if (g_pwr250us_over30sec.count == 0)
+ {
+ //The counter has been reset, therefore initialize the stored values.
+ g_pwr250us_over30sec.max = (uint16_t) temp32;
+ g_pwr250us_over30sec.min = (uint16_t) temp32;
+ g_pwr250us_over30sec.freqaAccum = l_allOccAvgFreqOver250us;
+
+ }
+ else
+ {
+ //Check for max.
+ if (temp32 > g_pwr250us_over30sec.max)
+ {
+ g_pwr250us_over30sec.max = (uint16_t) temp32;
+ }
+ //Check for min.
+ if (temp32 < g_pwr250us_over30sec.min)
+ {
+ g_pwr250us_over30sec.min = (uint16_t) temp32;
+ }
+ //Average frequency accumulator.
+ g_pwr250us_over30sec.freqaAccum += l_allOccAvgFreqOver250us;
+
+ }
+
+ //Count of number of updates.
+ g_pwr250us_over30sec.count++;
+
+ // ----------------------------------------------------
+ // Clear Flag to indicate that AMEC has received the data.
+ // ----------------------------------------------------
+ G_slv_inbox_received = FALSE;
+ }
+ else
+ {
+ // Skip it...AMEC Health Monitor will figure out we didn't
+ // update this sensor.
+ }
+}
+
+
+// Function Specification
+//
+// Name: amec_update_vrm_sensors
+//
+// Description: Updates sensors that use data from the VRMs
+// (e.g., VR_FAN, FANS_FULL_SPEED, VR_HOT).
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_vrm_sensors(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ int l_rc = 0;
+ int l_vrfan = 0;
+ int l_softoc = 0;
+ int l_minus_np1_regmode = 0;
+ int l_minus_n_regmode = 0;
+ static uint8_t L_error_count = 0;
+ uint8_t l_pin = 0;
+ uint8_t l_pin_value = 1; // active low, so set default to high
+ uint8_t l_vrhot_count = 0;
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Check if we have access to SPIVID. In DCMs only Master OCC has access to
+ // the SPIVID.
+ if (G_dcm_occ_role == OCC_DCM_MASTER)
+ {
+ // VR_FAN and SOFT_OC come from SPIVID
+ l_rc = vrm_read_state(SPIVRM_PORT(0),
+ &l_minus_np1_regmode,
+ &l_minus_n_regmode,
+ &l_vrfan,
+ &l_softoc);
+
+ if (l_rc == 0)
+ {
+ // Update the VR_FAN sensor
+ sensor_update( AMECSENSOR_PTR(VRFAN250USPROC), (uint16_t)l_vrfan );
+
+ // Clear our error count and the 'read failure' flag (since we can
+ // read VR_FAN signal)
+ L_error_count = 0;
+ G_thrm_fru_data[DATA_FRU_VRM].read_failure = 0;
+
+ // Obtain the 'fan_full_speed' GPIO from APSS
+ l_pin = G_sysConfigData.apss_gpio_map.fans_full_speed;
+
+ // No longer reading gpio from APSS in GA1 due to instability in APSS composite mode -- gm026
+ //apss_gpio_get(l_pin, &l_pin_value);
+
+ // VR_HOT sensor is a counter of number of times the VRHOT signal
+ // has been asserted
+ l_vrhot_count = AMECSENSOR_PTR(VRHOT250USPROC)->sample;
+
+ // Check if VR_FAN is asserted AND if 'fans_full_speed' GPIO is ON.
+ // Note that this GPIO is active low.
+ if (AMECSENSOR_PTR(VRFAN250USPROC)->sample && !(l_pin_value))
+ {
+ // VR_FAN is asserted and 'fans_full_speed' GPIO is ON,
+ // then increment our VR_HOT counter
+ if (l_vrhot_count < g_amec->vrhotproc.setpoint)
+ {
+ l_vrhot_count++;
+ }
+ }
+ else
+ {
+ // Reset our VR_HOT counter
+ l_vrhot_count = 0;
+ }
+ sensor_update(AMECSENSOR_PTR(VRHOT250USPROC), l_vrhot_count);
+ }
+ else
+ {
+ // Increment our error count
+ L_error_count++;
+
+ // Don't allow the error count to wrap
+ if (L_error_count == 0)
+ {
+ L_error_count = 0xFF;
+ }
+
+ // Log an error if we exceeded our number of fail-to-read sensor
+ if ((L_error_count == g_amec->proc[0].vrfan_error_count) &&
+ (g_amec->proc[0].vrfan_error_count != 0xFF))
+ {
+ TRAC_ERR("amec_update_vrm_sensors: Failed to read VR_FAN for %u consecutive times!",
+ L_error_count);
+
+ // Also, inform the thermal thread to send a cooling request
+ G_thrm_fru_data[DATA_FRU_VRM].read_failure = 1;
+
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_VRFAN_TIMEOUT
+ * @reasoncode VRM_VRFAN_TIMEOUT
+ * @userdata1 timeout value
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to read VR_FAN signal from regulator.
+ *
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_VRFAN_TIMEOUT, //modId
+ VRM_VRFAN_TIMEOUT, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ g_amec->thermaldimm.temp_timeout, //userdata1
+ 0); //userdata2
+
+ // Callout backplane for this VRM error
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.backplane_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ // Commit the error
+ commitErrl(&l_err);
+ }
+ }
+ }
+
+ if( 1 )
+ {
+ sensor_update( AMECSENSOR_PTR(VRFAN250USMEM), 0 );
+ sensor_update( AMECSENSOR_PTR(VRHOT250USMEM), 0 );
+ }
+}
+
+// Function Specification
+//
+// Name: amec_update_external_voltage
+//
+// Description: Measure actual external voltage
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_update_external_voltage()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint32_t l_data = 0;
+ uint16_t l_temp = 0;
+ uint16_t l_vdd = 0;
+ uint16_t l_vcs = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // Collect the external voltage data
+ l_data = in32(PMC_GLOBAL_ACTUAL_VOLTAGE_REG); //gm034 (at malcolm's request)
+
+ // Extract the Vdd vid code and convert to voltage
+ l_temp = (l_data & 0xFF000000) >>24;
+ l_vdd = 16125 - ((uint32_t)l_temp * 625)/10;
+
+ // Extract the Vcs vid code and convert to voltage
+ l_temp = (l_data & 0x00FF0000) >>16;
+ l_vcs = 16125 - ((uint32_t)l_temp * 625)/10;
+
+ sensor_update( AMECSENSOR_PTR(VOLT250USP0V0), (uint16_t) l_vdd);
+ sensor_update( AMECSENSOR_PTR(VOLT250USP0V1), (uint16_t) l_vcs);
+}
diff --git a/src/occ/amec/amec_sensors_power.h b/src/occ/amec/amec_sensors_power.h
new file mode 100755
index 0000000..f0bb3eb
--- /dev/null
+++ b/src/occ/amec/amec_sensors_power.h
@@ -0,0 +1,48 @@
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_sensors_power_h amec_sensors_power.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- --------------------------------------
+ * @th00b thallet 02/24/2012 New file
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ *
+ * @endverbatim
+ */
+
+#ifndef _AMEC_SENSORS_POWER_H
+#define _AMEC_SENSORS_POWER_H
+
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+#include "amec_external.h"
+
+/*----------------------------------------------------------------------------*/
+/* Defines/Constants */
+/*----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------*/
+/* Function Declarations */
+/*----------------------------------------------------------------------------*/
+
+// Function that is called by AMEC State Machine that will update the AMEC
+// sensors for data that comes from the APSS (Power Data from APSS ADCs)
+void amec_update_apss_sensors(void);
+
+// Function that is called by AMEC State Machine that will update the AMEC
+// sensors for data that comes from the SPIVID chip (VR_FAN, SoftOC)
+void amec_update_vrm_sensors(void);
+
+// Function that is called by AMEC State Machine that will update the AMEC
+// sensors for external voltage measurement
+void amec_update_external_voltage(void);
+
+#endif // _AMEC_SENSORS_POWER_H
diff --git a/src/occ/amec/amec_service_codes.h b/src/occ/amec/amec_service_codes.h
new file mode 100755
index 0000000..27423ab
--- /dev/null
+++ b/src/occ/amec/amec_service_codes.h
@@ -0,0 +1,77 @@
+/**
+ * @file amec_service_codes.h
+ * @brief Error codes for amec component.
+ *
+ *
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _amec_service_codes_h amec_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- -------- -----------------------------------
+ * @th00a thallet 02/03/2012 Created
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @at008 alvinwan 08/09/2012 Support AME Pass Thru command from TMGT
+ * @fk001 879727 fmkassem 04/16/2013 PCAP support.
+ * @db001 897459 deepthib 08/20/2013 pcap mismatch/under pcap support
+ * @rt001 897459 tapiar 08/20/2013 slave performance check support
+ * @gs012 903325 gjsilva 10/18/2013 Log Processor OT errors
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ *
+ * @endverbatim
+ */
+
+#ifndef _AMEC_SERVICE_CODES_H_
+#define _AMEC_SERVICE_CODES_H_
+/*----------------------------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------------------------*/
+#include <comp_ids.h>
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Defines */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Typedef / Enum */
+/*----------------------------------------------------------------------------*/
+enum occAmecModuleId
+{
+ AMEC_INITIALIZE_FW_SENSORS = AMEC_COMP_ID | 0x00,
+ AMEC_UPDATE_FW_SENSORS = AMEC_COMP_ID | 0x01, // @nh001c
+ AMEC_VECTORIZE_FW_SENSORS = AMEC_COMP_ID | 0x02, // @nh001a
+ AMEC_AMESTER_INTERFACE = AMEC_COMP_ID | 0x03, // @at008a
+ AMEC_PCAP_CONN_OC_CONTROLLER = AMEC_COMP_ID | 0x04, // @fk001a
+ AMEC_MST_CHECK_PCAPS_MATCH = AMEC_COMP_ID | 0x05, // @db001a
+ AMEC_MST_CHECK_UNDER_PCAP = AMEC_COMP_ID | 0x06, // @db001a
+ AMEC_SLAVE_CHECK_PERFORMANCE = AMEC_COMP_ID | 0x07, // @rt001a
+ AMEC_HEALTH_CHECK_PROC_TEMP = AMEC_COMP_ID | 0x08, // @gs012a
+ AMEC_HEALTH_CHECK_DIMM_TEMP = AMEC_COMP_ID | 0x09,
+ AMEC_HEALTH_CHECK_CENT_TEMP = AMEC_COMP_ID | 0x10,
+ AMEC_HEALTH_CHECK_DIMM_TIMEOUT = AMEC_COMP_ID | 0x11,
+ AMEC_HEALTH_CHECK_CENT_TIMEOUT = AMEC_COMP_ID | 0x12,
+ AMEC_HEALTH_CHECK_VRFAN_TIMEOUT = AMEC_COMP_ID | 0x13, // @gs020a
+ AMEC_HEALTH_CHECK_PROC_TIMEOUT = AMEC_COMP_ID | 0x14, // @gs021a
+ AMEC_HEALTH_CHECK_PROC_VRHOT = AMEC_COMP_ID | 0x15, // @gs023a
+};
+
+/*----------------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------------*/
+
+#endif /* #ifndef _AMEC_SERVICE_CODES_H_ */
+
diff --git a/src/occ/amec/amec_slave_smh.c b/src/occ/amec/amec_slave_smh.c
new file mode 100755
index 0000000..cee61dc
--- /dev/null
+++ b/src/occ/amec/amec_slave_smh.c
@@ -0,0 +1,669 @@
+/******************************************************************************
+// @file amec_slave_smh.c
+// @brief Slave State Machine
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_slave_smh_c amec_slave_smh.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 11/08/2011 New file
+ * @rc001 rickylie 01/10/2012 Added trac.h
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/12 Changed every function for the
+ * Reading/Calc of AMEC Sensors
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gs001 gjsilva 08/03/2012 Added AMEC Slave Vote & SMH
+ * @th018 852950 thallet 09/12/2012 Added Centaur thermal readings
+ * @gs002 854460 gjsilva 09/25/2012 Support for slave state machine
+ * @ly001 853751 lychen 09/17/2012 Initial Revision
+ * @ry002 862112 ronda 11/26/2012 Support thermal controller for processor
+ * @th026 865074 thallet 12/21/2012 Updated Centaur sensors
+ * @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+ * @ry003 870734 ronda 02/20/2013 Thermal controller for memory
+ * @fk001 879727 fmkassem 04/16/2013 OCC powercap support.
+ * @rt001 897459 tapiar 08/19/2013 Upd: add slave performance check
+ * @gs012 903325 gjsilva 10/18/2013 Log Processor OT errors
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @mw633 918066 mware 01/09/2014 Added call to amec_analytics every 2msec in state 3.
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ * @gm027 917208 milesg 02/25/2014 removed redundant (unvalidated) call to amec_data_write_pcap
+ * @gs042 942940 gjsilva 10/24/2014 Support for data packets in BMC-based systems
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include "sensor.h"
+#include "rtls.h"
+#include "occ_sys_config.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "dcom.h"
+#include "proc_data.h"
+#include "proc_data_control.h"
+#include "amec_smh.h"
+#include "amec_slave_smh.h"
+#include <trac.h>
+#include "amec_sys.h"
+#include "sensor_enum.h"
+#include "amec_service_codes.h"
+#include <amec_sensors_core.h>
+#include <amec_sensors_power.h>
+#include <amec_sensors_centaur.h>
+#include <amec_sensors_fw.h>
+#include <amec_freq.h>
+#include <amec_data.h>
+#include <centaur_data.h>
+#include <amec_amester.h>
+#include <amec_oversub.h> // @at010a
+#include <amec_health.h>
+#include <amec_analytics.h> // @mw633
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern dcom_slv_inbox_t G_dcom_slv_inbox_rx;
+extern uint8_t G_vrm_present;
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+smh_state_t G_amec_slv_state = {AMEC_INITIAL_STATE,
+ AMEC_INITIAL_STATE,
+ AMEC_INITIAL_STATE};
+
+// Number of ticks for periodically updating VRM-related data
+#define AMEC_UPDATE_VRM_TICKS 4000
+
+
+// --------------------------------------------------------
+// AMEC Slave State 6 Substate Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 16ms.
+//
+// No Substates
+//
+const smh_tbl_t amec_slv_state_6_substate_table[AMEC_SMH_STATES_PER_LVL] =
+{
+ {amec_slv_substate_6_0, NULL},
+ {amec_slv_substate_6_1, NULL},
+ {amec_slv_substate_6_2, NULL},
+ {amec_slv_substate_6_3, NULL},
+ {amec_slv_substate_6_4, NULL},
+ {amec_slv_substate_6_5, NULL},
+ {amec_slv_substate_6_6, NULL},
+ {amec_slv_substate_6_7, NULL},
+};
+
+// --------------------------------------------------------
+// AMEC Slave State 7 Substate Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 16ms.
+//
+// No Substates
+//
+const smh_tbl_t amec_slv_state_7_substate_table[AMEC_SMH_STATES_PER_LVL] =
+{
+ {amec_slv_substate_7_0, NULL},
+ {amec_slv_substate_7_1, NULL},
+ {amec_slv_substate_7_2, NULL},
+ {amec_slv_substate_7_3, NULL},
+ {amec_slv_substate_7_4, NULL},
+ {amec_slv_substate_7_5, NULL},
+ {amec_slv_substate_7_6, NULL},
+ {amec_slv_substate_7_7, NULL},
+};
+
+// --------------------------------------------------------
+// Main AMEC Slave State Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 2ms.
+//
+// No Substates
+//
+const smh_tbl_t amec_slv_state_table[AMEC_SMH_STATES_PER_LVL] =
+{
+ {amec_slv_state_0, NULL},
+ {amec_slv_state_1, NULL},
+ {amec_slv_state_2, NULL},
+ {amec_slv_state_3, NULL},
+ {amec_slv_state_4, NULL},
+ {amec_slv_state_5, NULL},
+ {amec_slv_state_6, amec_slv_state_6_substate_table},
+ {amec_slv_state_7, amec_slv_state_7_substate_table},
+};
+
+
+// This sets up the function pointer that will be called to update the
+// fw timings when the AMEC Slave State Machine finishes.
+smh_state_timing_t G_amec_slv_state_timings = {amec_slv_update_smh_sensors};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: amec_slv_common_tasks_pre
+//
+// Description: Runs all the functions that need to run pre-AMEC-State-Machine
+// This function will run every tick.
+//
+//
+// Flow: 03/04/13 FN= amec_slv_common_tasks_pre
+//
+// Thread: RealTime Loop
+//
+// Changedby: @..., @fk001c
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_common_tasks_pre(void)
+{
+ static uint16_t L_counter = 0;
+
+ AMEC_DBG("\tAMEC Slave Pre-State Common\n");
+
+ // Update the FW Worst Case sensors every tick
+ amec_update_fw_sensors();
+
+ // Update the fast core data sensors every tick
+ amec_update_fast_core_data_sensors();
+
+ // Update the sensors that come from the APSS every tick
+ amec_update_apss_sensors();
+
+ // Call the stream buffer recording function
+ amec_analytics_sb_recording();
+
+ // Update the sensors that come from the VRM
+ L_counter++;
+ if (L_counter == AMEC_UPDATE_VRM_TICKS)
+ {
+ if (G_vrm_present)
+ {
+ amec_update_vrm_sensors();
+ }
+ L_counter = 0;
+ }
+
+ // Update the external voltage sensors
+ amec_update_external_voltage();
+
+ // Over-subscription check
+ amec_oversub_check(); // @at010a
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_cmmon_tasks_post
+//
+// Description: Runs all the functions that need to run post-AMEC-State-Machine
+// This function will run every tick.
+//
+//
+// Flow: 02/26/13 FN= amec_slv_common_tasks_post
+//
+// Thread: RealTime Loop
+//
+// Changedby: @..., @fk001c
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_common_tasks_post(void)
+{
+ AMEC_DBG("\tAMEC Slave Post-State Common\n");
+
+ // Only execute if OCC is in the active state
+ if ( IS_OCC_STATE_ACTIVE() ) // @gs001
+ {
+ // Call amec_power_control
+ amec_power_control();
+ // Call the OCC slave's voting box
+ amec_slv_voting_box();
+
+ // Call the frequency state machine
+ amec_slv_freq_smh();
+
+ // Call the OCC slave's memory voting box
+ amec_slv_mem_voting_box();
+
+ // Call the OCC slave's performance check @rt001a
+ amec_slv_check_perf();
+
+ // Call the 250us trace recording if it has been configured via Amester.
+ // If not configured, this call will return immediately.
+ amec_tb_record(AMEC_TB_250US);
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_state_0
+//
+// Description: AMEC Slave State Machine State
+//
+//
+// Flow: FN=
+//
+// End Function Specification
+void amec_slv_state_0(void)
+{
+ AMEC_DBG("\tAMEC Slave State 0\n");
+
+ //-------------------------------------------------------
+ // Update Proc Core sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_proc_core_sensors(CORE_0);
+ amec_update_proc_core_sensors(CORE_8);
+
+ //-------------------------------------------------------
+ // Update Centaur sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_centaur_sensors(CENTAUR_0); // @th026
+
+
+ //-------------------------------------------------------
+ // Update Sleep Count & Winkle Count Sensors
+ //-------------------------------------------------------
+ sensor_update(AMECSENSOR_PTR(SLEEPCNT2MSP0),
+ __builtin_popcount( g_amec->proc[0].sleep_cnt));
+ g_amec->proc[0].sleep_cnt = 0;
+
+ sensor_update(AMECSENSOR_PTR(WINKCNT2MSP0),
+ __builtin_popcount(g_amec->proc[0].winkle_cnt));
+ g_amec->proc[0].winkle_cnt = 0;
+
+
+ //-------------------------------------------------------
+ // Update vector sensors
+ //-------------------------------------------------------
+ sensor_vector_update(AMECSENSOR_PTR(TEMP2MSP0), 1);
+ sensor_vector_update(AMECSENSOR_PTR(TEMP2MSP0PEAK),1);
+ sensor_vector_update(AMECSENSOR_PTR(FREQA2MSP0), 1); // @mw626
+ sensor_vector_update(AMECSENSOR_PTR(IPS2MSP0), 1);
+ sensor_vector_update(AMECSENSOR_PTR(UTIL2MSP0), 1);
+
+ // Call the trace function for 2ms tracing if it has been configured via
+ // Amester. If not configured, this call will return immediately.
+ amec_tb_record(AMEC_TB_2MS);
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_state_1
+//
+// Description: AMEC Slave State Machine State
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_state_1(void)
+{
+ AMEC_DBG("\tAMEC Slave State 1\n");
+
+ //-------------------------------------------------------
+ // Update Proc Core sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_proc_core_sensors(CORE_1);
+ amec_update_proc_core_sensors(CORE_9);
+
+ //-------------------------------------------------------
+ // Update Centaur sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_centaur_sensors(CENTAUR_1);
+
+ //-------------------------------------------------------
+ // Update Proc Level Centaur/DIMM Temperature sensors
+ //-------------------------------------------------------
+ amec_update_centaur_temp_sensors();
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_state_2
+//
+// Description: AMEC Slave State Machine State
+//
+//
+// Flow: FN=
+//
+// End Function Specification
+void amec_slv_state_2(void)
+{
+ AMEC_DBG("\tAMEC Slave State 2\n");
+
+ //-------------------------------------------------------
+ // Update Proc Core sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_proc_core_sensors(CORE_2);
+ amec_update_proc_core_sensors(CORE_10);
+
+ //-------------------------------------------------------
+ // Update Centaur sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_centaur_sensors(CENTAUR_2);
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_state_3
+//
+// Description: AMEC Slave State Machine State
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_state_3(void)
+{
+ AMEC_DBG("\tAMEC Slave State 3\n");
+
+ //-------------------------------------------------------
+ // Update Proc Core sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_proc_core_sensors(CORE_3);
+ amec_update_proc_core_sensors(CORE_11);
+
+ //-------------------------------------------------------
+ // Update Centaur sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_centaur_sensors(CENTAUR_3);
+
+ //-------------------------------------------------------
+ // Perform amec_analytics (set amec_analytics_slot to 3)
+ //-------------------------------------------------------
+ amec_analytics_main();
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_state_4
+//
+// Description: AMEC Slave State Machine State
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_state_4(void)
+{
+ AMEC_DBG("\tAMEC Slave State 4\n");
+
+ //-------------------------------------------------------
+ // Update Proc Core sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_proc_core_sensors(CORE_4);
+
+ //-------------------------------------------------------
+ // Update Centaur sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_centaur_sensors(CENTAUR_4);
+
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_state_5
+//
+// Description: AMEC Slave State Machine State
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_state_5(void)
+{
+ AMEC_DBG("\tAMEC Slave State 5\n");
+
+ //-------------------------------------------------------
+ // Update Proc Core sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_proc_core_sensors(CORE_5);
+
+ //-------------------------------------------------------
+ // Update Centaur sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_centaur_sensors(CENTAUR_5);
+
+ //-------------------------------------------------------
+ // Update partition sensors for DPS algorithms (for this tick)
+ //-------------------------------------------------------
+ amec_dps_main(); // @ly001a
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_state_6
+//
+// Description: AMEC Slave State Machine State
+//
+//
+// Flow: FN=
+//
+// Thread: RealTime Loop
+//
+// Task Flags:
+//
+// End Function Specification
+void amec_slv_state_6(void)
+{
+ AMEC_DBG("\tAMEC Slave State 6\n");
+
+ //-------------------------------------------------------
+ // Update Proc Core sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_proc_core_sensors(CORE_6);
+
+ //-------------------------------------------------------
+ // Update Centaur sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_centaur_sensors(CENTAUR_6);
+}
+
+
+// Function Specification
+//
+// Name: amec_slv_state_7
+//
+// Description: AMEC Slave State Machine State
+//
+//
+// Flow: FN=
+//
+// End Function Specification
+void amec_slv_state_7(void)
+{
+ AMEC_DBG("\tAMEC Slave State 7\n");
+
+ //-------------------------------------------------------
+ // Update Proc Core sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_proc_core_sensors(CORE_7);
+
+ //-------------------------------------------------------
+ // Update Centaur sensors (for this tick)
+ //-------------------------------------------------------
+ amec_update_centaur_sensors(CENTAUR_7);
+}
+
+// Function Specification
+//
+// Name: amec_slv_substate_6_0
+// amec_slv_substate_6_1
+// amec_slv_substate_6_2
+// amec_slv_substate_6_3
+// amec_slv_substate_6_4
+// amec_slv_substate_6_5
+// amec_slv_substate_6_6
+// amec_slv_substate_6_7
+//
+// Description: slave substate amec_slv_substate_6_0
+// slave substate amec_slv_substate_6_1
+// slave substate amec_slv_substate_6_2
+// slave substate amec_slv_substate_6_3
+// slave substate amec_slv_substate_6_4
+// slave substate amec_slv_substate_6_5
+// slave substate amec_slv_substate_6_6
+// slave substate amec_slv_substate_6_7
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_slv_substate_6_0(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ AMEC_DBG("\tAMEC Slave State 6.0\n");
+
+ // Call processor-based thermal controller
+ amec_controller_proc_thermal();
+}
+
+void amec_slv_substate_6_1(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ AMEC_DBG("\tAMEC Slave State 6.1\n");
+
+ // Call controller on VRHOT signal from processor regulator
+ amec_controller_vrhotproc();
+}
+
+void amec_slv_substate_6_2(void){AMEC_DBG("\tAMEC Slave State 6.2\n");}
+void amec_slv_substate_6_3(void){AMEC_DBG("\tAMEC Slave State 6.3\n");}
+void amec_slv_substate_6_4(void){AMEC_DBG("\tAMEC Slave State 6.4\n");}
+void amec_slv_substate_6_5(void){AMEC_DBG("\tAMEC Slave State 6.5\n");}
+void amec_slv_substate_6_6(void){AMEC_DBG("\tAMEC Slave State 6.6\n");}
+void amec_slv_substate_6_7(void){AMEC_DBG("\tAMEC Slave State 6.7\n");}
+
+// Function Specification
+//
+// Name: amec_slv_substate_7_0
+// amec_slv_substate_7_1
+// amec_slv_substate_7_2
+// amec_slv_substate_7_3
+// amec_slv_substate_7_4
+// amec_slv_substate_7_5
+// amec_slv_substate_7_6
+// amec_slv_substate_7_7
+//
+// Description: slave substate amec_slv_substate_7_0
+// slave substate amec_slv_substate_7_1
+// slave substate amec_slv_substate_7_2
+// slave substate amec_slv_substate_7_3
+// slave substate amec_slv_substate_7_4
+// slave substate amec_slv_substate_7_5
+// slave substate amec_slv_substate_7_6
+// slave substate amec_slv_substate_7_7
+//
+// Flow: FN= None
+//
+// End Function Specification
+void amec_slv_substate_7_0(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ AMEC_DBG("\tAMEC Slave State 7.0\n");
+
+ // Call memory thermal controller based on DIMM temperature
+ amec_controller_dimm_thermal();
+
+ // Call memory thermal controller based on Centaur temperature
+ amec_controller_centaur_thermal();
+}
+
+void amec_slv_substate_7_1(void){AMEC_DBG("\tAMEC Slave State 7.1\n");}
+void amec_slv_substate_7_2(void){AMEC_DBG("\tAMEC Slave State 7.2\n");}
+void amec_slv_substate_7_3(void){AMEC_DBG("\tAMEC Slave State 7.3\n");}
+void amec_slv_substate_7_4(void){AMEC_DBG("\tAMEC Slave State 7.4\n");}
+void amec_slv_substate_7_5(void){AMEC_DBG("\tAMEC Slave State 7.5\n");}
+void amec_slv_substate_7_6(void){AMEC_DBG("\tAMEC Slave State 7.6\n");}
+
+void amec_slv_substate_7_7(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ AMEC_DBG("\tAMEC Slave State 7.7\n");
+
+ // Call health monitor to check for processor error temperature conditions
+ amec_health_check_proc_temp();
+}
diff --git a/src/occ/amec/amec_slave_smh.h b/src/occ/amec/amec_slave_smh.h
new file mode 100755
index 0000000..8b34dc3
--- /dev/null
+++ b/src/occ/amec/amec_slave_smh.h
@@ -0,0 +1,110 @@
+/******************************************************************************
+// @file amec_slave_smh.h
+// @brief Slave State Machine header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_slave_smh_h amec_slave_smh.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 11/08/2011 New file
+ * @rc001 rickylie 01/10/2012 Added trac.h
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th00a thallet 02/09/2012 G_ added as per codign convention
+ * @gs002 854460 gjsilva 09/25/2012 Support for slave state machine
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_SLAVE_SMH_H
+#define _AMEC_SLAVE_SMH_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+#include <amec_smh.h>
+#include <amec_amester.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define AMEC_SLV_STATE() AMEC_STATE(&G_amec_slv_state);
+#define AMEC_SLV_SUBSTATE() AMEC_SUBSTATE(&G_amec_slv_state);
+#define AMEC_SLV_SUB_SUBSTATE() AMEC_SUB_SUBSTATE(&G_amec_slv_state);
+
+#define AMEC_SLV_STATE_NEXT() AMEC_STATE_NEXT(&G_amec_slv_state);
+#define AMEC_SLV_SUBSTATE_NEXT() AMEC_SUBSTATE_NEXT(&G_amec_slv_state);
+#define AMEC_SLV_SUB_SUBSTATE_NEXT() AMEC_SUB_SUBSTATE_NEXT(&G_amec_slv_state);
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+extern const smh_tbl_t amec_slv_state_table[AMEC_SMH_STATES_PER_LVL];
+extern smh_state_t G_amec_slv_state;
+extern smh_state_timing_t G_amec_slv_state_timings;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// PRE: slave common tasks
+void amec_slv_common_tasks_pre(void);
+// POST: slave common tasks
+void amec_slv_common_tasks_post(void);
+
+// Slave States
+void amec_slv_state_0(void);
+void amec_slv_state_1(void);
+void amec_slv_state_2(void);
+void amec_slv_state_3(void);
+void amec_slv_state_4(void);
+void amec_slv_state_5(void);
+void amec_slv_state_6(void);
+void amec_slv_state_7(void);
+
+// Slave SubState 6
+void amec_slv_substate_6_0(void);
+void amec_slv_substate_6_1(void);
+void amec_slv_substate_6_2(void);
+void amec_slv_substate_6_3(void);
+void amec_slv_substate_6_4(void);
+void amec_slv_substate_6_5(void);
+void amec_slv_substate_6_6(void);
+void amec_slv_substate_6_7(void);
+
+// Slave SubState 7
+void amec_slv_substate_7_0(void);
+void amec_slv_substate_7_1(void);
+void amec_slv_substate_7_2(void);
+void amec_slv_substate_7_3(void);
+void amec_slv_substate_7_4(void);
+void amec_slv_substate_7_5(void);
+void amec_slv_substate_7_6(void);
+void amec_slv_substate_7_7(void);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif
diff --git a/src/occ/amec/amec_smh.h b/src/occ/amec/amec_smh.h
new file mode 100755
index 0000000..bac28ef
--- /dev/null
+++ b/src/occ/amec/amec_smh.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+// @file amec_smh.h
+// @brief OCC AMEC SMH header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_smh_h amec_smh.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 11/08/2011 New file
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/2012 Added defines for scalable tick times
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_SMH_H
+#define _AMEC_SMH_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+#include "amec_external.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+#define AMEC_STATE(i_state) (i_state->state);
+#define AMEC_SUBSTATE(i_state) (i_state->substate);
+#define AMEC_SUB_SUBSTATE(i_state) (i_state->sub_substate);
+
+#define AMEC_STATE_NEXT(i_state) i_state->state++; i_state->state %= AMEC_SMH_STATES_PER_LVL;
+#define AMEC_SUBSTATE_NEXT(i_state) i_state->substate++; i_state->substate %= AMEC_SMH_STATES_PER_LVL;
+#define AMEC_SUB_SUBSTATE_NEXT(i_state) i_state->sub_substate++; i_state->sub_substate %= AMEC_SMH_STATES_PER_LVL;
+
+#define AMEC_INITIAL_STATE 0
+
+#define AMEC_SMH_STATES_PER_LVL 8
+
+// Number of uS in 1 RTL tick (250=250us)
+#define AMEC_US_PER_TICK MICS_PER_TICK
+// Number of uS in 1 full period of the AMEC State Machine (2000=2mS, 8 RTL ticks)
+#define AMEC_US_PER_SMH_PERIOD (AMEC_SMH_STATES_PER_LVL * MICS_PER_TICK)
+// Number of <AMEC_US_PER_SMH_PERIOD> that happen in 1 second
+#define AMEC_SMH_PERIODS_IN_1SEC (10000000 / AMEC_US_PER_SMH_PERIOD)
+
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+// Each State table (including Substates) will take up 64 bytes
+// of SRAM space.
+typedef struct smh_tbl
+{
+ void (*state)();
+ const struct smh_tbl * substate;
+} smh_tbl_t;
+
+typedef struct
+{
+ uint8_t state;
+ uint8_t substate;
+ uint8_t sub_substate;
+} smh_state_t;
+
+typedef struct
+{
+ void (*update_sensor)(int, uint32_t);
+} smh_state_timing_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void amec_generic_smh(const smh_tbl_t * i_smh_tbl, smh_state_t * i_smh_state, smh_state_timing_t * i_smh_timing);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_AMEC_SMH_H
diff --git a/src/occ/amec/amec_sys.h b/src/occ/amec/amec_sys.h
new file mode 100755
index 0000000..d86cca8
--- /dev/null
+++ b/src/occ/amec/amec_sys.h
@@ -0,0 +1,742 @@
+/******************************************************************************
+// @file amec_sys.h
+// @brief OCC AMEC System Structure
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section amec_sys.h AMEC_SYS.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th005 thallet 11/23/2011 New File
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/2012 Added Vector Sensors
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gs001 gsilva 08/03/2012 Added frequency points & freq SMH
+ * @th018 852950 thallet 09/12/2012 Added Centaur thermal readings
+ * @ly001 853751 lychen 09/17/2012 Support DPS algorithm
+ * @ry002 862116 ronda 11/26/2012 Support thermal controller for processor
+ * @th026 865074 thallet 12/21/2012 Updated Centaur sensors
+ * @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+ * @ry003 870734 ronda 02/20/2013 Thermal controller for memory
+ * @ry004 872358 ronda 02/27/2013 Added global memory speed request and throttle reason
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @gs006 884384 gjsilva 05/30/2013 Support for mnfg auto-slewing function
+ * @fk001 879727 fmkassem 04/16/2013 PCAP support.
+ * @gm004 892961 milesg 07/25/2013 Support memory auto slewing
+ * @gs008 894661 gjsilva 08/08/2013 Initial support for DPS-FP mode
+ * @rt001 897459 tapiar 08/09/2013 Update reason codes to be uint32_t
+ * @gm008 SW226989 milesg 09/30/2013 Sapphire initial support
+ * @gs014 903552 gjsilva 10/22/2013 Support for Amester parameter interface
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @rt003 905677 tapiar 11/07/2013 save of proc/mem sensor data into g_amec
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @cl007 907196 lefurgy 11/15/2013 Fix freqa and ips sensors
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @rt004 908817 tapiar 12/11/2013 Add valid pcap field to g_amec to be used
+ * by slaves when their pcap is valid
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ * @mw644 918066 mware 03/07/2014 Added data to enable freq_sens_busy and freq_sens_finish.
+ * @gs029 919478 gjsilva 03/26/2014 Fixed wrong values for sleep/winkle counters
+ * @gm039 922963 milesg 05/28/2014 Handle centaur nest LFIR 6
+ * @gs043 943177 gjsilva 10/30/2014 Support for mem data packets in BMC-based systems
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _AMEC_SYS_H
+#define _AMEC_SYS_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <sensor.h>
+#include <occ_sys_config.h>
+#include <amec_part.h> // @ly001a
+#include <amec_perfcount.h> // @ly001a
+#include <mode.h> // @ly001a
+#include <amec_controller.h>
+#include <amec_oversub.h> // @at010a
+#include <amec_amester.h> // @mw626
+#include <amec_pcap.h> // @fk001
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// This is an arbitrary number of FW probes for use internally.
+#define NUM_AMEC_FW_PROBES 8
+
+// Number of States in the AMEC State Machine (should always be 8)
+#define NUM_AMEC_SMH_STATES 8
+
+// Number of PORE-GPE Engines
+#define NUM_GPE_ENGINES 2
+#define GPE_ENGINE_0 0
+#define GPE_ENGINE_1 1
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//-------------------------------------------------------------
+// FW Sub-structure
+//-------------------------------------------------------------
+typedef struct
+{
+ // Sensors
+ sensor_t ameintdur;
+ sensor_t amessdur[NUM_AMEC_SMH_STATES];
+ sensor_t gpetickdur[NUM_GPE_ENGINES]; // @th00a
+ sensor_t prcdupdatedur;
+ sensor_t probe250us[NUM_AMEC_FW_PROBES];
+
+ // DPS update flag
+ uint8_t dps_no_update_flag; // 8 bit flag: =1, no updating allowed; =0, updating is allowed // @ly001a
+
+} amec_fw_t;
+
+
+//-------------------------------------------------------------
+// Fan Sub-structure
+//-------------------------------------------------------------
+typedef struct
+{
+ // Sensors
+ sensor_t fanspeedavg;
+ sensor_t pwr250usfan;
+
+} amec_fans_t;
+
+//-------------------------------------------------------------
+// IO Sub-structure
+//-------------------------------------------------------------
+typedef struct
+{
+ // Sensors
+ sensor_t pwr250usio;
+
+} amec_io_t;
+
+//-------------------------------------------------------------
+// Storage Sub-structure
+//-------------------------------------------------------------
+typedef struct
+{
+ // Sensors
+ sensor_t pwr250usstore;
+
+} amec_store_t;
+
+//-------------------------------------------------------------
+// Proc Sub-structure
+//-------------------------------------------------------------
+
+typedef struct
+{
+ // Sensors
+ sensor_t uvolt250us;
+ sensor_t volt250us;
+
+} amec_vrm_t;
+
+
+typedef struct
+{
+ uint32_t wr_cnt_accum;
+ uint32_t rd_cnt_accum;
+ uint32_t pwrup_cnt_accum;
+ uint32_t act_cnt_accum;
+ uint32_t fr2_cnt_accum;
+ uint32_t l4_rd_cnt_accum;
+ uint32_t l4_wr_cnt_accum;
+ uint32_t intreq_base_accum;
+ uint32_t intreq_low_accum;
+ uint32_t intreq_med_accum;
+ uint32_t intreq_high_accum;
+
+ uint16_t fr2_cnt;
+ uint16_t act_cnt;
+ uint16_t pwrup_cnt;
+ uint16_t memwrite2ms;
+ uint16_t memread2ms;
+ uint16_t l4wr2ms;
+ uint16_t l4rd2ms;
+ uint16_t mirb2ms;
+ uint16_t mirl2ms;
+ uint16_t mirm2ms;
+ uint16_t mirh2ms;
+
+} amec_chpair_perf_counter_t;
+
+//convenient format for storing throttle settings - gm016
+typedef union
+{
+ uint32_t word32;
+ struct
+ {
+ uint32_t mba_n: 16;
+ uint32_t chip_n: 16;
+ };
+} amec_cent_mem_speed_t;
+
+typedef struct
+{
+ // Sensors
+ sensor_t mac2ms;
+ sensor_t mpu2ms;
+ sensor_t mirb2ms;
+ sensor_t mirl2ms;
+ sensor_t mirm2ms;
+ sensor_t mirh2ms;
+ sensor_t mts2ms;
+ sensor_t memsp2ms;
+ sensor_t m4rd2ms;
+ sensor_t m4wr2ms;
+
+ amec_chpair_perf_counter_t perf;
+
+ // The most recent throttle value sent to this MBA
+ // This is used to only send values to the centaur when it changes.
+ amec_cent_mem_speed_t last_mem_speed_sent;
+} amec_portpair_t;
+
+typedef struct
+{
+ uint32_t intreq_highlatency_accum;
+ uint32_t lp2exit_accum;
+
+ uint16_t mirc2ms;
+ uint16_t mlp2_2ms;
+} amec_centaur_perf_counter_t;
+
+#define FRU_SENSOR_STATUS_STALLED 0x01
+#define FRU_SENSOR_STATUS_ERROR 0x02
+#define FRU_SENSOR_STATUS_VALID_OLD 0x04
+#define FRU_TEMP_OUT_OF_RANGE 0x08
+#define FRU_SENSOR_STATUS_INVALID 0x10 //centaur only
+#define FRU_TEMP_FAST_CHANGE 0x20
+#define FRU_SENSOR_CENT_NEST_FIR6 0x40 //centaur only -- gm039
+
+typedef struct
+{
+ uint8_t cur_temp;
+ uint8_t sample_age;
+ uint8_t flags;
+ // Sensor ID for reporting temperature to BMC
+ uint16_t temp_sid;
+}fru_temp_t;
+
+typedef struct
+{
+ // Sub-structures under Centaur
+ union
+ {
+ amec_portpair_t portpair[NUM_PORT_PAIRS_PER_CENTAUR];
+ amec_portpair_t mba[NUM_PORT_PAIRS_PER_CENTAUR];
+ }; // @th031 - Just a different name to refer to same thing
+
+ // Sensors
+ sensor_t mlp2ms;
+ sensor_t mirc2ms;
+
+ //hottest dimm temperature behind this centaur
+ sensor_t tempdimmax;
+
+ //which of the 8 dimm temperatures was the hottest temperature
+ //(only changes when the max of tempdimmax changes)
+ sensor_t locdimmax;
+
+ // Current dimm tempuratures
+ fru_temp_t dimm_temps[NUM_DIMMS_PER_CENTAUR];
+
+ // Hottest centaur temperature for this centaur
+ fru_temp_t centaur_hottest;
+
+ // Sensor ID for reporting temperature to BMC
+ uint16_t temp_sid;
+
+ amec_centaur_perf_counter_t perf;
+
+} amec_centaur_t;
+
+typedef struct
+{
+ // Sub-structures under MemCtl
+ amec_centaur_t centaur;
+
+ // Sensors
+ sensor_t mrd2ms;
+ sensor_t mwr2ms;
+
+} amec_memctl_t;
+
+typedef struct
+{
+ //-----------------------------------
+ // Previous Tick Data
+ //-----------------------------------
+ uint32_t prev_PC_RUN_Th_CYCLES;
+
+ //-----------------------------------
+ // Calculations & Interim Data
+ //-----------------------------------
+ uint16_t util2ms_thread;
+
+} amec_core_thread_t;
+
+typedef struct
+{
+ // Sub-structures under Core
+ amec_core_perf_counter_t core_perf; // @ly001c
+ amec_core_thread_t thread[MAX_THREADS_PER_CORE];
+
+ //-----------------------------------
+ // Sensors
+ //-----------------------------------
+// sensor_t cpm2ms; //CPM - Commented out as requested by Malcolm
+ sensor_t freq250us;
+ sensor_t freqa2ms; // @mw626
+ sensor_t ips2ms;
+ sensor_t mcpifd2ms;
+ sensor_t mcpifi2ms;
+ sensor_t spurr2ms;
+ sensor_t temp2ms;
+ sensor_t util2ms;
+ sensor_t nutil3s;
+ sensor_t mstl2ms;
+ sensor_t cmt2ms;
+ sensor_t cmbw2ms;
+ sensor_t ppic;
+ sensor_t pwrpx250us;
+
+ //-----------------------------------
+ // Previous Tick Data
+ //-----------------------------------
+ uint32_t prev_PC_RAW_CYCLES;
+ uint32_t prev_PC_RUN_CYCLES;
+ uint32_t prev_PC_DISPATCH;
+ uint32_t prev_PC_COMPLETED;
+ uint32_t prev_PC_RAW_Th_CYCLES;
+ uint32_t prev_tod_2mhz;
+ uint32_t prev_lpar_mem_cnt[4];
+ uint32_t prev_FREQ_SENS_BUSY;
+ uint32_t prev_FREQ_SENS_FINISH;
+
+ //-----------------------------------
+ // Calculations & Interim Data
+ //-----------------------------------
+ // Dispatched Instructions per Second
+ uint16_t dps;
+ // Dispatched Instruction per Cycle
+ uint16_t dpc;
+ // Instructions per Cycle
+ uint16_t ipc;
+ // Hottest DTS sensor per core
+ uint16_t dts_hottest;
+ // Counter of number of samples for calculating average utilization & frequency
+ uint16_t sample_count;
+ // Array of memory bandwidth for each LPAR
+ uint16_t membw[4];
+
+ // Average utilization over a fixed time interval
+ uint32_t avg_util;
+ // Average frequency over a fixed time interval
+ uint32_t avg_freq;
+
+ // ---------------------------------
+ // Frequency State Machine variables
+ // ---------------------------------
+ // Frequency request generated by the voting box
+ uint16_t f_request;
+ // Reason for the frequency request generated by the voting box
+ uint32_t f_reason; // @rt001c
+ // Current state of this core frequency state machine
+ uint8_t f_sms;
+
+} amec_core_t;
+
+//-------------------------------------------------------------
+// System-wide Sub-structure
+//-------------------------------------------------------------
+typedef struct
+{
+ // Sensors
+ //sensor_t fake_sensor[NUM_OCCS];
+ //
+} amec_master_t;
+
+
+//-------------------------------------------------------------
+// System-wide Sub-structure
+//-------------------------------------------------------------
+typedef struct
+{
+ // System Sensors
+ sensor_t tempambient;
+ sensor_t altitude;
+ sensor_t pwr250us;
+ sensor_t pwr250usgpu;
+
+ sensor_t vrfan250usmem;
+ sensor_t vrhot250usmem;
+ sensor_t vrfan250usproc;
+ sensor_t vrhot250usproc;
+
+ // Chip Sensors
+ sensor_t todclock0;
+ sensor_t todclock1;
+ sensor_t todclock2;
+
+ // Minimum Frequency that can be set in the current policy
+ uint16_t fmin;
+
+ // Maximum Frequency that can be set in the current policy
+ uint16_t fmax;
+
+ // Maximum speed in current policy
+ uint16_t max_speed; // @ly001a
+
+ // Minimum speed in current policy
+ uint16_t min_speed;
+
+ // Speed step size
+ uint16_t speed_step;
+
+ // Speed step limit
+ uint16_t speed_step_limit;
+} amec_systemwide_t;
+
+//@fk001a
+
+//Structure Defined in amec_slv_voting_box.odg
+typedef struct
+{
+ //Maximum frequency allowed on this chip by the
+ //performance preserving boundary algorithm. Set by amec_ppb_fmax_calc
+ uint16_t ppb_fmax;
+
+ //Maximum frequency allowed on this chip by the Pmax_clip register.
+ //Set by amec_pmax_clip_controller.
+ uint16_t pmax_clip_freq;
+
+ //Maximum frequency allowed on this chip by the power capping algorithm for
+ //non-nominal cores. Set by amec_pcap_controller.
+ uint16_t proc_pcap_vote;
+
+ //Minimum frequency that power capping is allowed to lower a nominal
+ //core to. Set by amec_pcap_calc.
+ uint16_t nom_pcap_fmin;
+
+ //Maximum frequency allowed on this chip by the power capping algorithm for
+ //nominal cores. Set by amec_pcpa_controller.
+ uint16_t proc_pcap_nom_vote;
+
+ //Maximum frequency allowed on this chip by the connector overcurrent algorithm.
+ //Set by amec_conn_oc_controller.
+ uint16_t conn_oc_vote;
+} amec_proc_pwr_votes_t;
+
+//-------------------------------------------------------------
+// Proc Structure
+//-------------------------------------------------------------
+typedef struct
+{
+ // Sub-structures under Proc
+ amec_core_t core[MAX_NUM_CORES];
+ amec_memctl_t memctl[MAX_NUM_MEM_CONTROLLERS];
+ amec_vrm_t vrm[NUM_PROC_VRMS];
+ amec_proc_pwr_votes_t pwr_votes; // @fk001a
+ //amec_vrm_t memvrm[];
+
+ // Processor Sensors
+ sensor_t freqa2ms; // @mw626
+ vectorSensor_t freqa2ms_vector; // @th00b @mw626
+ sensor_t ips2ms;
+ vectorSensor_t ips2ms_vector; // @th00b
+ sensor_t memsp2ms;
+ vectorSensor_t memsp2ms_vector; // @th00b
+ sensor_t pwr250us;
+ sensor_t pwr250usvdd;
+ sensor_t cur250usvdd;
+ sensor_t pwr250usvcs;
+ sensor_t pwr250usmem;
+ sensor_t sleepcnt2ms;
+ sensor_t winkcnt2ms;
+ sensor_t sp250us;
+ sensor_t temp2ms;
+ vectorSensor_t temp2ms_vector; // @th00b
+ sensor_t temp2mspeak;
+ vectorSensor_t temp2mspeak_vector; // @th00b
+ sensor_t util2ms;
+ vectorSensor_t util2ms_vector; // @th00b
+
+ // Memory Summary Sensors
+ sensor_t temp2mscent;
+ sensor_t temp2msdimm;
+ sensor_t memsp2ms_tls;
+
+ // Error count for failing to read VR_FAN signal
+ uint8_t vrfan_error_count;
+
+ // Calculations & Interim Data
+ uint16_t sleep_cnt;
+ uint16_t winkle_cnt;
+
+ uint16_t core_max_freq; // Maximum requested freq for all cores on chip. @fk001a
+
+ // Parameters used through Amester interface
+ // Note: keep core arrays here, not in per-cores structure so one parameter
+ // can be used to pass array.
+ uint32_t parm_f_reason[MAX_NUM_CORES]; // per-core frequency reason
+ uint16_t parm_f_override[MAX_NUM_CORES]; // per-core frequency override in MHz
+ uint8_t parm_f_override_enable; // enable using the frequency override
+
+} amec_proc_t;
+
+
+
+//-------------------------------------------------------------
+// Mode Freq Structure // @ly001a
+//-------------------------------------------------------------
+typedef struct amec_mode_freq
+{
+ uint16_t fmin;
+ uint16_t fmax;
+ ///Minimum speed allowed based on fmin/fmax ratio
+ uint16_t min_speed;
+} amec_mode_freq_t;
+
+
+//-------------------------------------------------------------
+// Parameters for manufacturing commands
+//-------------------------------------------------------------
+typedef struct amec_mnfg
+{
+ ///Auto-slewing flag: enable=1, disable=0
+ uint8_t auto_slew;
+ ///Minimum frequency in MHz for auto-slewing
+ uint16_t fmin;
+ ///Maximum frequency in MHz for auto-slewing
+ uint16_t fmax;
+ ///Step size in MHz for auto-slewing
+ uint16_t fstep;
+ ///Additional delay in ticks for auto-slewing
+ uint16_t delay;
+ ///Frequency override to be sent to all slave OCCs
+ uint16_t foverride;
+ ///Counter of times we reached fmin or fmax
+ uint16_t slew_counter;
+ ///memory auto-slewing flag: enable=1, disable=0
+ bool mem_autoslew; //gm004
+ ///memory slewing count
+ uint32_t mem_slew_counter; //gm004
+} amec_mnfg_t;
+
+//-------------------------------------------------------------
+// Parameters for Idle Power Save (IPS) mode
+//-------------------------------------------------------------
+typedef struct amec_ips
+{
+ ///Enable/Disable IPS (=0:disable; =1:enable)
+ uint8_t enable;
+ ///Current 'active' state of IPS (=0:inactive; =1:active)
+ uint8_t active;
+ ///IPS frequency request to be sent to all OCC Slaves
+ uint16_t freq_request;
+ ///Utilization threshold to enter idle condition (in hundreth of a percent)
+ uint16_t entry_threshold;
+ ///Utilization threshold to exit idle condition (in hundreth of a percent)
+ uint16_t exit_threshold;
+ ///Delay time to enter idle condition (in number of samples)
+ uint32_t entry_delay;
+ ///Delay time to exit idle condition (in number of samples)
+ uint32_t exit_delay;
+}amec_ips_t;
+
+
+//-------------------------------------------------------------
+//
+// AMEC/OCC Overall System Structure -- g_amec
+//
+// Description, etc...
+//
+//
+//-------------------------------------------------------------
+typedef struct
+{
+ //---------------------------------------------------------
+ //
+ // System Management Settings
+ //
+ //---------------------------------------------------------
+ // Global memory throttle reason
+ uint8_t mem_throttle_reason;
+ // Global memory speed request
+ uint16_t mem_speed_request;
+
+ // Flag to enable frequency override in the voting box
+ uint8_t foverride_enable;
+ // Override frequency to be used by the voting box
+ uint16_t foverride;
+ // Idle Power Saver frequency request sent by Master OCC
+ uint16_t slv_ips_freq_request;
+ // Flag to indicate that the DPS parameters were overwritten by user
+ BOOLEAN slv_dps_param_overwrite;
+
+ //---------------------------------------------------------
+ //
+ // Physical Structure
+ //
+ //---------------------------------------------------------
+ // Bulk Power Data
+ //amec_bulk_t bulk;
+
+ // IO Data
+ amec_io_t io;
+
+ // Storage Data
+ amec_store_t storage;
+
+ // Fan Data
+ amec_fans_t fan;
+
+ // Perf Data
+ //amec_perf_t perf;
+
+ // Overall System Data
+ amec_systemwide_t sys;
+
+ // Processor Card Data
+ // - This is an array of 1. This was initialized this way
+ // in the hopes of perhaps reusing some code from TPMD
+ // where there were multiple proc chips per TPMD.
+ amec_proc_t proc[NUM_PROC_CHIPS_PER_OCC];
+
+ // OCC Firmware Data
+ amec_fw_t fw;
+
+ // AMEC Misc (Non-System-Heirachy) Data
+ //amec_amecfw_t fw_amec;
+
+ // Sensors on master for calculations across multiple OCCs
+ //amec_master_t mstr;
+
+ // Partition Information
+ amec_part_config_t part_config; // @ly001a
+ // Mode frequency table indexed by mode
+ amec_mode_freq_t part_mode_freq[OCC_INTERNAL_MODE_MAX_NUM]; // @ly001a
+
+ //---------------------------------------------------------
+ //
+ // Control Systems
+ //
+ //---------------------------------------------------------
+ // Thermal Controller based on processor temperatures
+ amec_controller_t thermalproc;
+ // Thermal Controller based on Centaur temperatures
+ amec_controller_t thermalcent;
+ // Thermal Controller based on DIMM temperatures
+ amec_controller_t thermaldimm;
+ // Thermal Controller based on VRHOT signal from processor VRM
+ amec_controller_t vrhotproc;
+
+ // Oversubscription Status
+ oversub_status_t oversub_status; // @at010a
+
+ // Parameters for manufacturing commands
+ amec_mnfg_t mnfg_parms;
+
+ // Parameters for Idle Power Save (IPS) mode
+ amec_ips_t mst_ips_parms;
+
+ // PowerCap Data
+ amec_pcap_t pcap; //fk001a
+
+ // Save off proc and mem sensor data for debug usage @rt003a
+ uint16_t proc_snr_pwr[MAX_NUM_CHIP_MODULES];
+ uint16_t mem_snr_pwr[MAX_NUM_CHIP_MODULES];
+
+ // save off when pcap is considered valid @rt004a
+ uint8_t pcap_valid;
+
+ //---------------------------------------------------------
+ //
+ // Parameters for analytics function
+ //
+ //---------------------------------------------------------
+ uint32_t r_cnt; // 32 bit counter of 250usec ticks @mw622
+ void *stream_vector_map[STREAM_VECTOR_SIZE_EX]; // array holding sensor ptrs for writing to stream vector
+ uint16_t *ptr_stream_buffer; // 32 bit ptr to streaming buffer which contains 16 bit elements
+ uint32_t write_stream_index; // 32 bit index for next write into streaming buffer
+ uint32_t read_stream_index; // 32 bit index for next read from streaming buffer
+ uint16_t stream_buffer[STREAM_BUFFER_SIZE]; // stream buffer for vector recordings
+ uint8_t recordflag; // initially 0 until recording is valid
+ uint16_t stream_vector_delay; // 16 bit delay in msec before stream vector records (set to 0 to avoid delay)
+ uint8_t stream_vector_mode; // 8 bit mode control for stream vector mode:
+ // 0=stop recording
+ // 1=record unconditionally from begin to end of buffer, then stop
+ // 2=record unconditionally forever
+ // 3=record until a checkstop event is detected
+ uint8_t stream_vector_rate; // 8 bit mode control for stream vector recording: 0=fastest sampling on platform: (250usec on OCC), (250us*2^7=32msec on TPMD); 7=32msec
+ uint8_t stream_vector_group; // 8 bit group # that selects which group of sensors to record as a vector
+ uint8_t reset_prep; // input from TMGT to signal a reset of the OCC is desired (!=0)
+ uint16_t cent_l4_state[MAX_NUM_CENTAURS]; // holds current state of L4 state machine for Centaur k
+ uint16_t cent_l4_ipl_state[MAX_NUM_CENTAURS];// holds current state of L4 IPL state machine for Centaur k
+ uint8_t l4_powerdown_requestm; // input from OCC master to signal a desire to power down the L4s (!=0)
+ uint16_t probe_l4_centaur; // indicates which of the L4 Centaurs is being monitored by probe.
+
+ uint32_t g44_avg[MAX_NUM_CHIP_MODULES*MAX_SENSORS_ANALYTICS]; // $mw417 @mw641
+ uint16_t analytics_group; // parameter driven selection of analytics group $mw412
+ uint8_t analytics_chip; // parameter to select which chip to monitor analytics on $mw417
+ uint8_t analytics_option; // parameter to select which analytics options (=0 just selected chip) $mw417
+ uint8_t analytics_bad_output_count; // 8 bit value used to throw away frames until good output has been averaged in amec_analytics buffer outputs @mw587
+ uint8_t analytics_total_chips; // Total number of chips used in analytics sensor capture
+ uint8_t analytics_thermal_offset; // Current offset in cyclic thermal group output (8 in cycle)
+ uint8_t analytics_threadmode; // Selects which type of Group 44 averaging is done on per thread data: default=0 (average of non-zero thread utilizations), =1 (average of N), =2 (max of N) $mw457
+ uint8_t analytics_threadcountmax; // Has the maximum number of threads per core for this processor architecture or for SMT modes. Default=4 on P7+.
+ uint8_t analytics_slot; // Which of 8 time slots that amec_analytics is called in
+ uint16_t analytics_array[48]; // Used to hold selected analytics group $mw412
+ uint16_t packednapsleep[MAX_NUM_CHIP_MODULES]; // for group 44 support core bit maps of their napping cores (upper byte) and sleeping cores (lower byte) $mw374
+ uint16_t total_memory_power; // holds the sum of all the memory power sensors (32msec) $mw371
+
+ //---------------------------------------------------------
+ //
+ // Global Sensors
+ //
+ //---------------------------------------------------------
+
+} amec_sys_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+extern amec_sys_t * g_amec;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void amec_slave_init(void) INIT_SECTION; // @th00a
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif
diff --git a/src/occ/amec/amec_tasks.c b/src/occ/amec/amec_tasks.c
new file mode 100755
index 0000000..f837fb5
--- /dev/null
+++ b/src/occ/amec/amec_tasks.c
@@ -0,0 +1,297 @@
+/******************************************************************************
+// @file amec_tasks.c
+// @brief AMEC State Machine Tasks
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _amec_tasks_c amec_tasks.c
+ * @verbatim
+ * @th00a thallet 02/03/12 Worst case FW timings in AMEC Sensors
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 11/08/2011 New file
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <errl.h> // Error logging
+#include <trac.h> // Error logging
+#include "rtls.h"
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include "amec_smh.h"
+#include "amec_master_smh.h"
+#include "amec_slave_smh.h"
+#include "amec_sys.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+/* rotate x to the left by s bits */
+uint8_t _rotl8(uint8_t val, uint8_t shift)
+{
+ return (val << shift) | (val >> (8 - shift));
+}
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: amec_generic_smh
+//
+// Description: Generic State Machine that allows for 8 states per level,
+// with 3 levels.
+// If State Machine gets called/incremented every 250us,
+// - Each function entry in Level 0 table runs every 2ms,
+// - Each function entry in Level 1 table will run every 16ms,
+// - Each function entry in Level 2 table will run every 128ms.
+//
+// Anything longer than that will need to be taken care of
+// inside of the states themselves.
+//
+// NULL entries are allowed, for both state functions and
+// for pointers to substate tables.
+// - If a state does not have substates, it should have NULL
+// in the substate table for the substate table pointer.
+// - If a state does not wish to run a function, it should have
+// NULL in the substate table for the function pointer.
+// - A state can have substates without having a function that
+// runs (i.e. NULL in function pointer, but valid in substate
+// table pointer)
+//
+// In addition, if i_smh_timing is not NULL and points to a
+// smh_state_timing_t structure, this state machine will grab
+// the SSX timings of each "Level 0" state and store the longest
+// time in each state in that structure.
+//
+// Flow: 11/8/11 FN=amec_generic_smh
+//
+// End Function Specification
+void amec_generic_smh(const smh_tbl_t * i_smh_tbl,
+ smh_state_t * i_smh_state,
+ smh_state_timing_t * i_smh_timing)
+{
+ uint64_t l_start = ssx_timebase_get();
+ uint8_t l_state = 0;
+
+ // ----------------------------------------------------
+ // AMEC State Machine States
+ // ----------------------------------------------------
+ if(NULL != i_smh_tbl)
+ {
+ // Read AMEC State Machine "State"
+ l_state = AMEC_STATE(i_smh_state);
+
+ AMEC_DBG("SMH: AMEC State: [%d] Mask: [%02x]\n",l_state,i_smh_state->state);
+
+ // check if state value makes sense
+ if ( l_state >= NUM_AMEC_SMH_STATES ) // @th00a
+ {
+ TRAC_ERR("SMH: Invalid AMEC State: [%d] Mask: [%02x]\n",l_state,i_smh_state->state);
+
+ // TODO how to handle this situation?
+ // for now exiting function
+ return;
+ }
+
+ // If there is a function to run for this state (!NULL), run it
+ if(NULL != i_smh_tbl[(l_state)].state)
+ {
+ // Call into AMEC State (i.e State 6)
+ (*(i_smh_tbl[(l_state)].state))();
+ }
+
+ // ----------------------------------------------------
+ // AMEC State Machine Substates
+ // ----------------------------------------------------
+ if(NULL != i_smh_tbl[l_state].substate)
+ {
+ // Read AMEC State Machine "Substate"
+ uint8_t l_substate = AMEC_SUBSTATE(i_smh_state);
+
+ AMEC_DBG("\tSMH: AMEC Sub State: %d Mask: %02x\n",l_substate,i_smh_state->substate);
+
+ // check if sub state value makes sense
+ if ( l_substate >= NUM_AMEC_SMH_STATES ) // @th00a
+ {
+ TRAC_ERR("SMH: Invalid AMEC Sub State: [%d] Mask: [%02x]\n",l_substate,i_smh_state->substate);
+
+ // TODO how to handle this situation?
+ // for now exiting function
+ return;
+ }
+
+ // Set up pointer to sub-state table
+ const smh_tbl_t * l_sub_state_tbl = i_smh_tbl[l_state].substate;
+
+ // If there is a function to run for this substate (!NULL), run it
+ if(NULL != (l_sub_state_tbl+l_substate)->state)
+ {
+ // Call into AMEC Substate (i.e State 6.1)
+ (*((l_sub_state_tbl+l_substate)->state))();
+ }
+
+ // ----------------------------------------------------
+ // AMEC State Machine Sub-substates
+ // ----------------------------------------------------
+ if(NULL != (l_sub_state_tbl+l_substate)->substate)
+ {
+ // Read AMEC State Machine "Sub-Substate"
+ uint8_t l_sub_substate = AMEC_SUB_SUBSTATE(i_smh_state);
+
+ AMEC_DBG("\t\tSMH: AMEC Sub Sub State: %d Mask: %02x\n",l_sub_substate,i_smh_state->sub_substate);
+
+ // check if sub sub state value makes sense
+ if ( l_sub_substate >= NUM_AMEC_SMH_STATES ) // @th00a
+ {
+ TRAC_ERR("SMH: Invalid AMEC Sub State: [%d] Mask: [%02x]\n",l_sub_substate,i_smh_state->substate);
+
+ // TODO how to handle this situation?
+ // for now exiting function
+ return;
+ }
+
+ // Set up pointer to sub-state table
+ const smh_tbl_t * l_sub_substate_tbl = (l_sub_state_tbl+l_substate)->substate;
+
+ // If there is a function to run for this sub-substate (!NULL), run it
+ if(NULL != (l_sub_substate_tbl+l_sub_substate)->state)
+ {
+ // Call into AMEC Sub-Substate (i.e State 6.1.3)
+ (*((l_sub_substate_tbl+l_sub_substate)->state))();
+ }
+ }
+ }
+ }
+
+ // ------------------------------------------------------
+ // Increment the state(s) of the AMEC State Machine
+ // ------------------------------------------------------
+
+ //check if i_smh_state is not null ?? TODO
+ // Bump the states as final undertaking before task ends
+ i_smh_state->state = AMEC_STATE_NEXT(i_smh_state);
+ if(AMEC_INITIAL_STATE == i_smh_state->state)
+ {
+ // Only bump the substate when "state" has wrapped
+ i_smh_state->substate = AMEC_SUBSTATE_NEXT(i_smh_state);
+ if(AMEC_INITIAL_STATE == i_smh_state->substate)
+ {
+ // Only bump the substate when "state" & "substate" have wrapped
+ i_smh_state->sub_substate = AMEC_SUB_SUBSTATE_NEXT(i_smh_state);
+ }
+ }
+
+ // ------------------------------------------------------
+ // Update the max timing of this state(s) of the AMEC State Machine
+ // ------------------------------------------------------
+ if((NULL != i_smh_timing) && (NULL != i_smh_timing->update_sensor))
+ {
+ // Calculate the duration of the state
+ uint64_t l_state_duration = DURATION_IN_US_UNTIL_NOW_FROM(l_start); // @th00a
+
+ // Make a function call to update sensor with duration
+ (*((i_smh_timing)->update_sensor))(l_state,(uint32_t)l_state_duration);
+ }
+}
+
+
+// Function Specification
+//
+// Name: task_amec_master
+//
+// Description: Purpose of this function is to run all the AMEC "master-only" code
+//
+//
+// Flow: 11/8/11 FN=task_amec_master
+//
+// Task Flags: RTL_FLAG_MSTR
+// RTL_FLAG_OBS
+// RTL_FLAG_ACTIVE
+// RTL_FLAG_MSTR_READY
+// RTL_FLAG_NO_APSS
+// RTL_FLAG_RUN
+//
+// End Function Specification
+void task_amec_master( task_t *i_self)
+{
+ uint64_t l_start = ssx_timebase_get(); // @th00a
+
+ amec_mst_common_tasks_pre();
+
+ amec_generic_smh( amec_mst_state_table, &G_amec_mst_state, &G_amec_mst_state_timings );
+
+ amec_mst_common_tasks_post();
+
+ // Add the time that this master task took to the total AMEC int task time,
+ // which already contains the slave task duration
+ G_fw_timing.ameint_dur += DURATION_IN_US_UNTIL_NOW_FROM(l_start); // @th00a
+}
+
+
+// Function Specification
+//
+// Name: task_amec_slave
+//
+// Description: Purpose of this function is to run all the AMEC "slave-only" code
+//
+//
+// Flow: 11/8/11 FN=task_amec_slave
+//
+// Task Flags: RTL_FLAG_MSTR
+// RTL_FLAG_NONMSTR
+// RTL_FLAG_OBS
+// RTL_FLAG_ACTIVE
+// RTL_FLAG_MSTR_READY
+// RTL_FLAG_NO_APSS
+// RTL_FLAG_RUN
+//
+//
+// End Function Specification
+void task_amec_slave( task_t *i_self)
+{
+ uint64_t l_start = ssx_timebase_get(); // @th00a
+
+ amec_slv_common_tasks_pre();
+
+ amec_generic_smh( amec_slv_state_table, &G_amec_slv_state, &G_amec_slv_state_timings );
+
+ amec_slv_common_tasks_post();
+
+ // Set the total AMEC int task time for this tick, to the duration of the slave tasks.
+ G_fw_timing.ameint_dur = DURATION_IN_US_UNTIL_NOW_FROM(l_start); // @th00a
+}
+
+
diff --git a/src/occ/aplt/aplt_service_codes.h b/src/occ/aplt/aplt_service_codes.h
new file mode 100755
index 0000000..31cf78d
--- /dev/null
+++ b/src/occ/aplt/aplt_service_codes.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+// @file aplt_service_codes.h
+// @brief Error codes for aplt component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _aplt_service_codes_h aplt_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 08/16/2010 Created new file
+ * @pb009 pbavari 10/20/2011 Added APLT_MID_INIT_APPLET_ADDR
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @rt001 901927 tapiar 10/01/2013 Add new/missing module ids
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _APLT_SERVICE_CODES_H_
+#define _APLT_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum apltModuleId
+{
+ APLT_MID_INIT_APPLET_MNGR = APLT_COMP_ID | 0x00,
+ APLT_MID_RUN_APPLET = APLT_COMP_ID | 0x01,
+ APLT_MID_START_APPLET = APLT_COMP_ID | 0x02,
+ APLT_MNGR_THREAD = APLT_COMP_ID | 0x03,
+ APLT_MID_INIT_APPLET_ADDR = APLT_COMP_ID | 0x04,
+
+ TEST_APLT_MODID_ERRLTEST = APLT_COMP_ID | 0xF0, //@nh001a @rt001c
+ TEST_APLT_MODID_SENSORTEST = APLT_COMP_ID | 0xF1, //@rt001a
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _APLT_SERVICE_CODES_H_ */
diff --git a/src/occ/aplt/appletManager.c b/src/occ/aplt/appletManager.c
new file mode 100755
index 0000000..6d3c1b8
--- /dev/null
+++ b/src/occ/aplt/appletManager.c
@@ -0,0 +1,1371 @@
+/******************************************************************************
+// @file appletManager.c
+// @brief OCC Applet Manager
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _appletManager_c appletManager.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * tapiar 08/15/2011 Created applet manager
+ * @pb004 pbavari 09/12/2011 Test Applet support
+ * @02 tapiar 10/03/2011 Changed BOOLEAN to bool
+ * @pb009 pbavari 10/20/2011 Added mmu_map/unmap to
+ * initAppletManager function
+ * @pb00A pbavari 11/15/2011 Changed applets base address and
+ * other misc. fixes
+ * @th006 thallet 11/21/2011 RESET_REQUEST substituted for todo's
+ * @pb00B pbavari 12/13/2011 Fixed runApplet non-blocking call
+ * @dw000 dwoodham 12/13/2011 Update applet verification
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @pb00F pbavari 06/11/2012 Added pgp.h for applet address defines
+ * @at005 alvinwan 05/03/2012 Fix Compile Errors/Warnings in mcp7 gcc compile
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th013 thallet 07/24/2012 Minor changes for VPO/HW compile
+ * @ai002 ailutsar 07/24/2012 Fix data tlb miss in startApplet
+ * @th029 thallet 01/23/2013 Enable version check on test Applets
+ * @th032 thallet 04/16/2013 Tuleta HW Bringup Fixes
+ * @th041 887656 thallet 06/17/2013 OCC Crash when accessing a full size applet
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+ * @rt001 901927 tapiar 10/01/2013 Fix src tags
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include <trac_interface.h>
+#include <appletManager.h>
+#include <aplt_service_codes.h>
+#include <occ_service_codes.h>
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <thread.h>
+#include <trac.h>
+#include <errl.h>
+#include <state.h>
+#include "pba_firmware_registers.h"
+#include "pgp_pba.h"
+#include "pgp_async.h"
+#include "ppc405_mmu.h"
+#include "pgp.h"
+#include "cmdh_fsp.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+//@pb009a - Added
+#define TEST_APPLET_ADDR (uint32_t)&_APPLET1_SECTION_BASE
+#define PRDT_APPLET_ADDR (uint32_t)&_APPLET0_SECTION_BASE
+#define TEST_APPLET_MAX_SIZE (uint32_t)&_APPLET1_SECTION_SIZE
+#define PRDT_APPLET_MAX_SIZE (uint32_t)&_APPLET0_SECTION_SIZE // @dw000a
+#define APPLET_IMG_SIZE_ALIGN 256 // @dw000a
+#define APPLET_RO_SIZE_ALIGN 1024 // @dw000a
+#define SRAM_START_ADDRESS 0xFFF80000
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+typedef struct
+{
+ // Running Semaphore (tells user if there is an applet running)
+ SsxSemaphore Running;
+ // Wake up Semaphore (wakes up the applet manager thread)
+ SsxSemaphore Wakeup;
+ // Finished Semaphore (tells caller, if blocking, when applet is done)
+ SsxSemaphore Finished;
+} ApltSem_t;
+
+// @th029 - Moved ApltAddress_t to header file
+
+//@pb00Ba - Added callerSem to hold caller semaphore parameter to the
+// runApplet call. This semaphore will be used by startApplet to notify
+// user of completion of the applet execution
+// Applet information structure
+// @pb00Ba - Added status to get back error status from startApplet and
+// return it to the caller for the blocking call.
+struct ApltInfo
+{
+ void * param;
+ bool isBlocking;
+ OCC_APLT appId;
+ OCC_APLT previousAppId;
+ errlHndl_t errorHandle;
+ // Applet has readonly and writable sections
+ Ppc405MmuMap mmuMapWritePermission; //@ai002c
+ Ppc405MmuMap mmuMapReadPermission; //@ai002a
+ SsxSemaphore * callerSem;
+ OCC_APLT_STATUS_CODES status;
+} __attribute__ ((__packed__));
+
+typedef struct ApltInfo ApltInfo_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// Global semaphores for product and test applet
+ApltSem_t G_ApltSemaphore;
+ApltSem_t G_TestApltSemaphore;
+
+// Applet Id global array
+ApltAddress_t G_ApltAddressTable[ OCC_APLT_LAST];
+
+//@pb00Ba - added callerSem and status
+// Global product applet information with defaults
+ApltInfo_t G_ApltInfo =
+{
+ .param = NULL,
+ .isBlocking = FALSE,
+ .appId = OCC_APLT_INVALID,
+ .previousAppId = OCC_APLT_INVALID,
+ .errorHandle = NULL,
+ .mmuMapWritePermission = 0, //@ai002c
+ .mmuMapReadPermission = 0, //@ai002a
+ .callerSem = NULL,
+ .status = OCC_APLT_SUCCESS
+};
+
+//@pb00Ba - added callerSem and status
+// Global test applet information with defaults
+ApltInfo_t G_TestApltInfo =
+{
+ .param = NULL,
+ .isBlocking = FALSE,
+ .appId = OCC_APLT_INVALID,
+ .previousAppId = OCC_APLT_INVALID,
+ .errorHandle = NULL,
+ .mmuMapWritePermission = 0, //@ai002c
+ .mmuMapReadPermission = 0, //@ai002a
+ .callerSem = NULL,
+ .status = OCC_APLT_SUCCESS
+};
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// Have to have this declaration here so the pre-processor handles the
+// section attribute correctly.
+errlHndl_t initAppletAddr( void ) INIT_SECTION; // @dw000a
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// >@dw000c
+// Function Specification
+//
+// Name: initAppletAddr
+//
+// Description: initialize the Applet address by traversing through OCC signed
+// image in main memory
+//
+// Flow: 10/24/11 FN=initAppletAddr
+// Flow: 12/09/11 FN=initAppletAddr
+//
+// End Function Specification
+errlHndl_t initAppletAddr( void )
+{
+ errlHndl_t l_err = NULL;
+ // 1. Applets count = OCC_APLT_TEST
+ // 2. Start reading header addresses
+ // 3. Skip first 2 ( boot, main ) addresses
+ imageHdr_t *l_bootLoaderHeader = (void *) 0;
+ imageHdr_t *l_mainAppHeader = (void *)l_bootLoaderHeader +
+ l_bootLoaderHeader-> image_size;
+ imageHdr_t *l_appHeader = (void *) l_mainAppHeader +
+ l_mainAppHeader->image_size;
+
+ // 4. Save off each applet start address and size to global applet array
+ // 5. Verify before saving off info (save off only valid addresses)
+ uint32_t l_cnt = 0;
+ bool l_foundInvalid = FALSE;
+
+ for (; l_cnt < OCC_APLT_TEST ; l_cnt++ )
+ {
+ // Enable if debug is neeed:
+ // TRAC_INFO("%s: Validating applet %d; address: %p", __FUNCTION__, l_cnt, l_appHeader);
+
+ // 5a. Value of l_appHeader should be reasonable.
+ // Means that image sizes should be non-zero.
+ // TODO: Check l_appHeader vs. max. sane memory address.
+ if( l_bootLoaderHeader-> image_size == 0 )
+ {
+ l_foundInvalid = TRUE;
+ TRAC_ERR("Bad image size in boot loader header. applet count: %d", l_cnt);
+ break;
+ }
+ else if( l_mainAppHeader->image_size == 0 )
+ {
+ l_foundInvalid = TRUE;
+ TRAC_ERR("Bad image size in main app header. applet count: %d", l_cnt);
+ break;
+ }
+
+ // 5b. sram_repair_reserved holds APLT_MAGIC_NUMBER
+ uint8_t l_magic_num[SRAM_REPAIR_RESERVE_SZ] = APLT_MAGIC_NUMBER; // Identifies this as a production applet
+ int i=0;
+
+ for(; i < SRAM_REPAIR_RESERVE_SZ; i++)
+ {
+ if(l_appHeader->sram_repair_reserved[i] != l_magic_num[i])
+ {
+ l_foundInvalid = TRUE;
+ break;
+ }
+ }
+ if(l_foundInvalid == TRUE)
+ {
+#ifndef NO_TRAC_STRINGS
+ uint32_t l_srr_0 = CONVERT_UINT8_ARRAY_UINT32(l_appHeader->sram_repair_reserved[0],
+ l_appHeader->sram_repair_reserved[1],
+ l_appHeader->sram_repair_reserved[2],
+ l_appHeader->sram_repair_reserved[3]); // @at005c
+
+ uint32_t l_srr_1 = CONVERT_UINT8_ARRAY_UINT32(l_appHeader->sram_repair_reserved[4],
+ l_appHeader->sram_repair_reserved[5],
+ l_appHeader->sram_repair_reserved[6],
+ l_appHeader->sram_repair_reserved[7]); // @at005c
+
+ uint32_t l_srr_2 = CONVERT_UINT8_ARRAY_UINT32(l_appHeader->sram_repair_reserved[8],
+ l_appHeader->sram_repair_reserved[9],
+ l_appHeader->sram_repair_reserved[10],
+ l_appHeader->sram_repair_reserved[11]); // @at005c
+
+ uint32_t l_srr_3 = CONVERT_UINT8_ARRAY_UINT32(l_appHeader->sram_repair_reserved[12],
+ l_appHeader->sram_repair_reserved[13],
+ l_appHeader->sram_repair_reserved[14],
+ l_appHeader->sram_repair_reserved[15]); // @at005c
+
+ TRAC_ERR("wrong magic number. applet count: %d, header addr: %p, magic no: 0x%08x%08x%08x%08x",
+ l_cnt, l_appHeader, l_srr_0, l_srr_1, l_srr_2, l_srr_3);
+#endif
+ break;
+ }
+
+ // 5c. verify that aplt_id < OCC_APLT_TEST
+ if( l_appHeader->aplt_id >= OCC_APLT_TEST )
+ {
+ l_foundInvalid = TRUE;
+ TRAC_ERR("applet ID out of range. applet count: %d, header addr: %p, id: %d",
+ l_cnt, l_appHeader, l_appHeader->aplt_id);
+ break;
+ }
+
+ // 5d. 0 < image_size <= PRDT_APPLET_MAX_SIZE
+ if( (l_appHeader->image_size == 0) || (l_appHeader->image_size > PRDT_APPLET_MAX_SIZE) )
+ {
+ l_foundInvalid = TRUE;
+ TRAC_ERR("bad image_size. applet count: %d, applet ID: 0x%02x, header addr: %p, image_size: %d, avail space: %d",
+ l_cnt, l_appHeader->aplt_id, l_appHeader, l_appHeader->image_size, PRDT_APPLET_MAX_SIZE);
+ break;
+ }
+
+ // 5e. image_size is APPLET_IMG_SIZE_ALIGN byte aligned
+ if( (l_appHeader->image_size % APPLET_IMG_SIZE_ALIGN) > 0 )
+ {
+ l_foundInvalid = TRUE;
+ TRAC_ERR("image size not aligned. applet count: %d, applet ID: 0x%02x, header addr: %p, image_size: %d",
+ l_cnt, l_appHeader->aplt_id, l_appHeader, l_appHeader->image_size);
+ break;
+ }
+
+ // 5f. readonly_size is APPLET_RO_SIZE_ALIGN byte aligned
+ if( (l_appHeader->readonly_size % APPLET_RO_SIZE_ALIGN) > 0 )
+ {
+ l_foundInvalid = TRUE;
+ TRAC_ERR("readonly size not aligned. applet count: %d, applet ID: 0x%02x, header addr: %p, readonly_size: %d",
+ l_cnt, l_appHeader->aplt_id, l_appHeader, l_appHeader->readonly_size);
+ break;
+ }
+
+ // Each applet is loaded at address PRDT_APPLET_ADDR, and executed on-demand.
+
+ // 5g. start_addr == the applet load address in SRAM
+ if( l_appHeader->start_addr != PRDT_APPLET_ADDR )
+ {
+ l_foundInvalid = TRUE;
+ TRAC_ERR("bad start_addr. applet count: %d, applet ID: 0x%02x, header addr: %p, expected addr: 0x%08x, actual addr: 0x%08x",
+ l_cnt, l_appHeader->aplt_id, l_appHeader, PRDT_APPLET_ADDR, l_appHeader->start_addr);
+ break;
+ }
+
+ // 5h. ep_addr is between the header and the end of the applet image
+ uint32_t l_ep_addr_min = PRDT_APPLET_ADDR + sizeof(imageHdr_t); // Lowest entry point an applet can reference
+ uint32_t l_ep_addr_max = PRDT_APPLET_ADDR + l_appHeader->image_size; // Upper bound on applet entry point
+
+ if( (l_appHeader->ep_addr < l_ep_addr_min) || (l_appHeader->ep_addr >= l_ep_addr_max) )
+ {
+ l_foundInvalid = TRUE;
+ TRAC_ERR("entry point out of range. applet count: %d, applet ID: 0x%02x, header addr: %p, ep_addr: 0x%08x, ep_range: 0x%08x - 0x%08x",
+ l_cnt, l_appHeader->aplt_id, l_appHeader, l_appHeader->ep_addr, l_ep_addr_min, l_ep_addr_max);
+ break;
+ }
+
+ // 5i. we haven't already seen this applet before
+ // (note the '!' at the start of the test condition)
+ if( !((G_ApltAddressTable[l_appHeader->aplt_id].iv_aplt_address == 0x00000000) &&
+ (G_ApltAddressTable[l_appHeader->aplt_id].iv_size == 0x00000000)) )
+ {
+ // This entry in the global table is not in its initialized state.
+ l_foundInvalid = TRUE;
+ TRAC_ERR("Duplicate applet. applet count: %d, applet ID: 0x%02x, header addr: %p",
+ l_cnt, l_appHeader->aplt_id, l_appHeader);
+ break;
+ }
+
+ // The gauntlet is run. This image is good.
+
+ // Load the G_ApltAddressTable.
+ G_ApltAddressTable[l_appHeader->aplt_id].iv_aplt_address = (uint32_t)l_appHeader;
+ G_ApltAddressTable[l_appHeader->aplt_id].iv_size = l_appHeader->image_size;
+
+ // Jump to the next applet.
+ l_appHeader = (void *) l_appHeader + l_appHeader->image_size;
+
+ } // end for loop
+
+ // did we find any problems?
+ if ( l_foundInvalid )
+ {
+ // We will want to return the ID of the failing applet in our error log,
+ // if that ID exists. Otherwise, return the "invalid" ID.
+ uint16_t l_errApltId = OCC_APLT_INVALID;
+
+ if( l_appHeader )
+ {
+ l_errApltId = l_appHeader->aplt_id;
+ }
+
+ /* @
+ * @errortype
+ * @moduleid APLT_MID_INIT_APPLET_ADDR
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 failing applet ID
+ * @userdata2 failing applet main store address
+ * @userdata4 ERC_APLT_INIT_FAILURE
+ * @devdesc Internal initialization failure in energy management
+ */
+ l_err = createErrl(APLT_MID_INIT_APPLET_ADDR, //modId
+ INTERNAL_FAILURE, //reasoncode //@ nh001c
+ ERC_APLT_INIT_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_errApltId, //userdata1
+ (uint32_t)l_appHeader); //userdata2
+
+ // @wb001 -- Callout to firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ else
+ {
+ // No problems with any production applets.
+ // 6. Save off the test applet start address and size to global applet array
+ G_ApltAddressTable[OCC_APLT_TEST].iv_aplt_address = (uint32_t)l_appHeader;
+ G_ApltAddressTable[OCC_APLT_TEST].iv_size = TEST_APPLET_MAX_SIZE;
+ }
+
+ // @ai002a
+ // copy SSX mmu map to ApltInfo structure
+ // startApplet() will use it to clear tlb entry
+ G_ApltInfo.mmuMapWritePermission = G_applet0_mmu_map;
+ G_TestApltInfo.mmuMapWritePermission = G_applet1_mmu_map;
+
+ // Clear SSX mmu map.
+ // The original tlb indexes may point to different SRAM regions when OCC runs
+ // mmu map/unmap several times.
+ G_applet0_mmu_map = 0;
+ G_applet1_mmu_map = 0;
+
+ return l_err;
+}
+// <@dw000c
+
+// Function Specification
+//
+// Name: initAppletManager
+//
+// Description: initialize the Applet Manager, called by main
+//
+// Flow: 10/31/11 FN=initAppletManager
+//
+// End Function Specification
+void initAppletManager( void )
+{
+ errlHndl_t l_rc = NULL;
+ Ppc405MmuMap l_mmuMap;
+ bool l_mmuUnmap = FALSE;
+ do
+ {
+ // initialized all the semaphores applet manager controls
+ // create the Running Semaphore, starting at 1 with a max count of 1
+ int l_ssxrc1 = ssx_semaphore_create(&G_ApltSemaphore.Running, 1, 1);
+ // create the Wake Up Semaphore, starting at 0 with a max count of 1
+ int l_ssxrc2 = ssx_semaphore_create(&G_ApltSemaphore.Wakeup, 0, 1);
+ // create the Finished Semaphore, starting at 0 with a max count of 1
+ int l_ssxrc3 = ssx_semaphore_create(&G_ApltSemaphore.Finished, 0, 1);
+ // create the Running Semaphore, starting at 1 with a max count of 1
+ int l_ssxrc4 = ssx_semaphore_create(&G_TestApltSemaphore.Running, 1, 1);
+ // create the Wake Up Semaphore, starting at 0 with a max count of 1
+ int l_ssxrc5 = ssx_semaphore_create(&G_TestApltSemaphore.Wakeup, 0, 1);
+ // create the Finished Semaphore, starting at 0 with a max count of 1
+ int l_ssxrc6 = ssx_semaphore_create(&G_TestApltSemaphore.Finished, 0,1);
+ // check for any errors from initializing our semaphores
+ // NOTE: Applet Global Array list is left empty if semaphores
+ // are not initialized correctly
+ if (( l_ssxrc1 != SSX_OK ) || ( l_ssxrc2 != SSX_OK ) ||
+ ( l_ssxrc3 != SSX_OK ) || ( l_ssxrc4 != SSX_OK ) ||
+ ( l_ssxrc5 != SSX_OK ) || ( l_ssxrc6 != SSX_OK ))
+ {
+ TRAC_INFO("Running Semaphore SsxRc[0x%08X]", -l_ssxrc1 );
+ TRAC_INFO("Wakeup Semaphore SsxRc[0x%08X]", -l_ssxrc2 );
+ TRAC_INFO("Finished Semaphore SsxRc[0x%08X]", -l_ssxrc3 );
+ TRAC_INFO("Running Test Semaphore SsxRc[0x%08X]", -l_ssxrc4);
+ TRAC_INFO("Wakeup Test Semaphore SsxRc[0x%08X]", -l_ssxrc5 );
+ TRAC_INFO("Finished Test Semaphore SsxRc[0x%08X]", -l_ssxrc6 );
+
+ /* @
+ * @errortype
+ * @moduleid APLT_MID_INIT_APPLET_MNGR
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Create Running product aplt semaphore rc
+ * @userdata2 Create Finished product aplt semaphore rc
+ * @userdata4 ERC_CREATE_SEM_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ l_rc = createErrl(APLT_MID_INIT_APPLET_MNGR, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ ERC_CREATE_SEM_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_ssxrc1, //userdata1
+ l_ssxrc3); //userdata2
+ break;
+ }
+
+ CHECKPOINT(APP_SEMS_CREATED);
+
+ // Map mainstore to oci space so that we can walk through
+ // OCC signed image to get applet addresses
+ int l_ssxRc = ppc405_mmu_map(0, //Mainstore address 0x0
+ 0, //OCI address 0x0
+ 1048576, //Max size = 1 Mb
+ 0, // TLB hi flags
+ 0, // TLB lo flags
+ &l_mmuMap);// map pointer
+
+ if ( l_ssxRc != SSX_OK )
+ {
+ TRAC_ERR("mmu map failure SsxRc[0x%08X]", -l_ssxRc );
+
+ /* @
+ * @errortype
+ * @moduleid APLT_MID_INIT_APPLET_MNGR
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 MMU map return code
+ * @userdata4 ERC_MMU_MAP_FAILURE
+ * @devdesc Failure mapping OCI space
+ */
+ l_rc = createErrl(APLT_MID_INIT_APPLET_MNGR, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ ERC_MMU_MAP_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_ssxRc, //userdata1
+ 0); //userdata2
+ break;
+ }
+
+ CHECKPOINT(APP_MEM_MAPPED);
+
+ // set to indicate to do mmu unmap after we are done using it.
+ l_mmuUnmap = TRUE;
+
+ // Traverse through OCC signed image to get applet address
+ l_rc = initAppletAddr();
+
+ CHECKPOINT(APP_ADDR_INITIALIZED);
+
+ if( NULL != l_rc)
+ {
+ TRAC_ERR("Failure initializing applet addresses");
+ break;
+ }
+
+ }while(FALSE);
+
+ if( TRUE == l_mmuUnmap)
+ {
+ CHECKPOINT(APP_MEM_UNMAP);
+
+ // Unmap mmu mapping for main store to oci space.
+ // NOTE: This needs to be unmapped because 1) PowerBus disruptions
+ // could leave OCC hung for several uS if main memory accessed at
+ // some later point. 2) Any thing accessing address 0 should result
+ // in 405 exception so need to unmap it.
+ int l_ssxRc = ppc405_mmu_unmap(&l_mmuMap);
+
+ if ( l_ssxRc != SSX_OK )
+ {
+ TRAC_ERR("mmu unmap failure SsxRc[0x%08X]", -l_ssxRc );
+
+ /* @
+ * @errortype
+ * @moduleid APLT_MID_INIT_APPLET_MNGR
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 MMU unmap return code
+ * @userdata4 ERC_MMU_UNMAP_FAILURE
+ * @devdesc Failure unmapping OCI space
+ */
+ errlHndl_t l_err = createErrl(APLT_MID_INIT_APPLET_MNGR, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ ERC_MMU_UNMAP_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_ssxRc, //userdata1
+ 0); //userdata2
+ // If there were not previous errors, return this error to the
+ // caller. Otherwise, log this error and return previous error to
+ // the caller.
+ if( l_rc == NULL)
+ {
+ l_rc = l_err;
+ deleteErrl(&l_err);
+ }
+ else
+ {
+ commitErrl(&l_err);
+ }
+ }
+ }
+
+ if( NULL != l_rc )
+ {
+ REQUEST_RESET(l_rc); // @gm006
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: runApplet
+//
+// Description: run an Applet
+//
+// Flow: 06/06/11 FN=runApplet
+// Flow: 12/15/11 FN=runApplet
+//
+// End Function Specification
+void runApplet( OCC_APLT i_applet,
+ void * i_parms,
+ bool i_block,
+ SsxSemaphore *io_appletComplete,
+ errlHndl_t *o_errHndl,
+ OCC_APLT_STATUS_CODES *o_status )
+{
+ uint32_t l_reasonCode = 0;
+ uint32_t l_extReasonCode = 0; // @nh001a
+ int l_ssxrc = 0;
+ bool l_postStartFailure = FALSE;
+
+ // Depending on applet id use product or test applet globals
+ ApltSem_t * l_sem =
+ (i_applet == OCC_APLT_TEST? &G_TestApltSemaphore : &G_ApltSemaphore);
+ ApltInfo_t * l_info =
+ (i_applet == OCC_APLT_TEST? &G_TestApltInfo : &G_ApltInfo);
+
+ //Block other runApplet caller until this request is complete
+ l_ssxrc = ssx_semaphore_pend(&l_sem->Running, SSX_WAIT_FOREVER);
+
+ if ( l_ssxrc != SSX_OK )
+ {
+ /*
+ * @errortype
+ * @moduleid APLT_MID_RUN_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Failing applet ID
+ * @userdata2 Caller parameter to determine block or not.
+ * @userdata4 ERC_RUNNING_SEM_PENDING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ TRAC_ERR("Running Semaphore Pending Failure on blocking caller: SsxRc[0x%08X]", -l_ssxrc );
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_RUNNING_SEM_PENDING_FAILURE; // @nh001a
+ l_info->status = OCC_APLT_PRE_START_FAILURE;
+ }
+ else
+ {
+ // First save off all the Globals
+
+ // Save off the current Applet user wants to run
+ l_info->appId = i_applet;
+
+ // Save off whether or not we are blocking on this applet execution
+ l_info->isBlocking = i_block;
+
+ // save off pointer to parameters
+ l_info->param = i_parms;
+
+ //@pb00Ba - Point callerSem to the caller passed in semaphore
+ l_info->callerSem = io_appletComplete;
+
+ // clean out the handle
+ l_info->errorHandle = NULL;
+
+ l_info->status = OCC_APLT_SUCCESS;
+
+ // This happens too often, we cannot trace it
+ // TRAC_INFO("Waking up the Applet Manager Thread" );
+
+ // Post wakeup semaphore so that applet manager can start
+ // applet
+ l_ssxrc = ssx_semaphore_post( &l_sem->Wakeup );
+ if ( l_ssxrc != SSX_OK )
+ {
+ /*
+ * @errortype
+ * @moduleid APLT_MID_RUN_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Failing applet ID
+ * @userdata2 Caller parameter to determine block or not.
+ * @userdata4 ERC_WAKEUP_SEM_POSTING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ TRAC_ERR("Wakeup Semaphore Post Failure: SsxRc[0x%08X]", -l_ssxrc );
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_WAKEUP_SEM_POSTING_FAILURE; // @nh001a
+
+ //post on Running Semaphore so that user can retry
+ l_ssxrc = ssx_semaphore_post( &l_sem->Running );
+ if ( l_ssxrc != SSX_OK )
+ {
+ /*
+ * @errortype
+ * @moduleid APLT_MID_RUN_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Failing applet ID
+ * @userdata2 Caller parameter to determine block or not.
+ * @userdata4 ERC_RUNNING_SEM_POSTING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ TRAC_ERR("Error posting the Applet running semaphore rc=[%08X]",l_ssxrc);
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_RUNNING_SEM_POSTING_FAILURE; // @nh001a
+ }
+ // set rc to failed to start
+ l_info->status = OCC_APLT_PRE_START_FAILURE;
+ }
+ // is caller expecting us to block then wait for finished semaphore
+ // to be posted. Finished semaphore is posted after applet execution
+ // is done.
+ else if ( i_block )
+ {
+ l_ssxrc = ssx_semaphore_pend(&l_sem->Finished, SSX_WAIT_FOREVER);
+ if ( l_ssxrc != SSX_OK )
+ {
+ /*
+ * @errortype
+ * @moduleid APLT_MID_RUN_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Failing applet ID
+ * @userdata2 Caller parameter to determine block or not.
+ * @userdata4 ERC_FINISHED_SEM_PENDING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ TRAC_ERR("Finished Semaphore Pending Failure: SsxRc[0x%08X]", -l_ssxrc );
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_FINISHED_SEM_PENDING_FAILURE; // @nh001a
+ // set flag to return post start failure status
+ l_postStartFailure = TRUE;
+ }
+ }
+ }
+
+ if ( (l_reasonCode != 0) && (o_errHndl != NULL))
+ {
+ // TODO use correct trace
+ tracDesc_t l_trace = NULL;
+ // Error from runApplet
+ *o_errHndl = createErrl(APLT_MID_RUN_APPLET, //modId
+ l_reasonCode, //reasoncode // @nh001c
+ l_extReasonCode, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_applet, //userdata1
+ i_block); //userdata2
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(*o_errHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ }
+ else if ( (l_info->errorHandle) && (o_errHndl != NULL))
+ {
+ // Error handle from start applet
+ *o_errHndl = l_info->errorHandle;
+ }
+
+ // set the status if requested by caller.
+ if( o_status != NULL )
+ {
+ if(l_postStartFailure == TRUE )
+ {
+ *o_status = OCC_APLT_POST_START_FAILURE;
+ }
+ else
+ {
+ // Return status to the caller
+ *o_status = l_info->status;
+ }
+ }
+
+ //Running, Finished/user passed in semaphore is posted by start applet
+};
+
+
+// Function Specification
+//
+// Name: startApplet
+//
+// Description: Start Applet
+//
+// Flow: 06/30/11 FN=startApplet
+// Flow: 12/15/11 FN=startApplet
+//
+// End Function Specification
+void startApplet( const OCC_APLT_TYPE i_isTestAplt )
+{
+ errlHndl_t l_rc = NULL;
+ int l_ssxrc = 0;
+ uint32_t l_reasonCode = 0;
+ uint32_t l_extReasonCode = 0; // @nh001a
+ // Depending on i_isTestAplt use product or test applet globals
+ ApltInfo_t * l_info =
+ (i_isTestAplt == TRUE ? &G_TestApltInfo : &G_ApltInfo);
+ ApltSem_t * l_sem =
+ (i_isTestAplt == TRUE ? &G_TestApltSemaphore : &G_ApltSemaphore);
+
+ OCC_APLT_STATUS_CODES l_status = OCC_APLT_SUCCESS;
+
+ // Get defaut applet section size for mmu @ai002
+ size_t l_applet_section_size =
+ (i_isTestAplt == TRUE ? (size_t)&_APPLET1_SECTION_SIZE : (size_t)&_APPLET0_SECTION_SIZE); // @th041
+
+ // For storing applet readonly size, this value is located in applet header in SRAM.
+ // The value should be stored in another place before unmapping the applet memory region.
+ size_t l_applet_readonly_size = 0;
+
+ // 1. set tlb protection to write to SRAM:
+ // currently already writable
+
+ do
+ {
+ // Get SRAM applet address depending on the applet type
+ uint32_t l_apltSramAddress =
+ (i_isTestAplt == TRUE? TEST_APPLET_ADDR: PRDT_APPLET_ADDR);
+
+ // Set header to point to SRAM address
+ imageHdr_t * l_apltHeader = (void *) l_apltSramAddress; // @th029
+ imageHdr_t *l_mainAppHeader = (void *) SRAM_START_ADDRESS; // @th029
+
+ // This happens too often, we cannot trace it
+ //TRAC_INFO("Attempting to run applet at address [0x%08X], size: 0x%x",
+ // G_ApltAddressTable[l_info->appId].iv_aplt_address,
+ // G_ApltAddressTable[l_info->appId].iv_size);
+
+ // check that we are not calling what is already saved off
+ // @dw000c re-load the test applet every time since they all use the same applet ID.
+ if ( (l_info->appId == OCC_APLT_TEST) || (l_info->appId != l_info->previousAppId) )
+ {
+ // @ai002a
+ // 1a. check applet read-only/executable permissions, unmap it if existed.
+ // whole applet memory region in SRAM should be free first, then set it to
+ // writable for copyimage and calculate checksum.
+ if ( l_info->mmuMapReadPermission != 0 )
+ {
+ l_ssxrc = ppc405_mmu_unmap(&l_info->mmuMapReadPermission);
+
+ if(l_ssxrc)
+ {
+ TRAC_ERR("Error unmapping/changing permissions on applet text/data section rc=[%08X]", -l_ssxrc);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_MMU_UNMAP_APPLET_READ_FAILURE
+ * @devdesc Failure unmapping applet read-only/executable permissions
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_MMU_UNMAP_APPLET_READ_FAILURE; // @ai002
+
+ // bail out
+ break;
+ }
+ }
+
+ // 1b. check applet writable section permissions, unmap it if existed
+ // whole applet memory region in SRAM should be free first, then set it to
+ // writable for copyimage and calculate checksum.
+ if ( l_info->mmuMapWritePermission != 0 )
+ {
+ l_ssxrc = ppc405_mmu_unmap(&l_info->mmuMapWritePermission);
+
+ if(l_ssxrc)
+ {
+ TRAC_ERR("Error unmapping/changing permissions on applet text/data section rc=[%08X]", -l_ssxrc);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_MMU_UNMAP_APPLET_WRITE_FAILURE
+ * @devdesc Failure unmapping applet rwdata section permissions
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_MMU_UNMAP_APPLET_WRITE_FAILURE; // @ai002
+
+ // bail out
+ break;
+ }
+ }
+
+ //1c. set SRAM applet region to writeable for copying image and calculating checksum
+
+ l_ssxrc = ppc405_mmu_map(
+ l_apltSramAddress, //
+ l_apltSramAddress, //
+ l_applet_section_size, // set whole applet including writable section
+ 0, //
+ TLBLO_WR,
+ &l_info->mmuMapWritePermission
+ );
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("Error mapping SRAM with execute permissions rc=[%08X]",l_ssxrc);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_MMU_MAP_APPLET_OVERWRITE_FAILURE
+ * @devdesc Failure mapping applet memory region permissions
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_MMU_MAP_APPLET_OVERWRITE_FAILURE; // @ai002
+ break;
+ }
+
+ // 2. read applet header info
+ // 3. copy applet image to SRAM using DMA
+
+ BceRequest pba_copy;
+ l_ssxrc = bce_request_create(&pba_copy, // block copy object
+ &G_pba_bcde_queue, // mainstore to sram copy engine
+ G_ApltAddressTable[l_info->appId].iv_aplt_address, // mainstore applet address
+ l_apltSramAddress, // sram applet starting address
+ G_ApltAddressTable[l_info->appId].iv_size, // size of applet
+ SSX_WAIT_FOREVER, // no timeout
+ 0, // no call back
+ 0, // no call back arguments
+ ASYNC_REQUEST_BLOCKING); // blocking request
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("PBA request create failure rc=[%08X]",l_ssxrc);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE; // @nh001a
+ break;
+ }
+
+ // actual copying
+ l_ssxrc = bce_request_schedule(&pba_copy);
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("PBA request schedule failure rc=[%08X]",l_ssxrc);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc Failure to copy applet image using DMA
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE; // @nh001a
+ break;
+ }
+
+ // --------------------------------------------------
+ // Verify the applet version matches the main version
+ // --------------------------------------------------
+ // @th029A - whole if statement
+ if(l_mainAppHeader->version != l_apltHeader->version)
+ {
+ TRAC_ERR("Applet not loaded b/c of version mismatch Main[%08x]:Applet[%08x]",
+ l_mainAppHeader->version, l_apltHeader->version);
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_APLT_START_VERSION_MISMATCH
+ * @devdesc Internal failure in energy management
+ */
+ l_reasonCode = INTERNAL_FAILURE;
+ l_extReasonCode = ERC_APLT_START_VERSION_MISMATCH;
+ break;
+
+ }
+
+ // 3b. invalidate the data cache
+ // ie: clean up data cache in case stuff is left
+ // from previous applet
+ dcache_invalidate((void *) l_apltHeader, l_applet_section_size); // @th032
+
+ // 4. Verify checksum of applet
+ uint32_t l_counter = 0;
+ uint8_t * l_srcPtr = (uint8_t *) (l_apltHeader);
+ uint32_t l_checksum = 0;
+ uint32_t l_headerChecksum = l_apltHeader->checksum;
+
+ while (l_counter < l_apltHeader->image_size )
+ {
+ l_checksum += (*(l_srcPtr + l_counter));
+ l_counter = l_counter + 1;
+ if( l_counter == (uint32_t)(offsetof(imageHdr_t,checksum)))
+ {
+ l_counter = ((uint32_t)(offsetof(imageHdr_t,checksum)) +
+ sizeof(l_apltHeader->checksum));
+ }
+ }//end while loop
+
+ if ( l_checksum != l_headerChecksum )
+ {
+ //error
+ TRAC_ERR("Checksum verification failure header chksum=[%08X] calculated chksum =[%08X] ",
+ l_headerChecksum, l_checksum);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_APLT_START_CHECKSUM_MISMATCH
+ * @devdesc Internal failure in energy management
+ */
+ l_reasonCode = INTERNAL_FAILURE; // @nh001c
+ l_extReasonCode = ERC_APLT_START_CHECKSUM_MISMATCH; // @nh001a
+ break;
+ }
+
+ // 5. flush complete I cache
+ // ie: ensure execution of current applet is clean
+ icache_invalidate_all();
+
+
+
+ // 5a. flush part of data cache
+ // ie: clean up data cache in case stuff is left
+ // from previous applet
+ // TODO: need to ensure this will work correctly on HW
+ // may require tweaking, based on results
+ dcache_invalidate((void *)l_apltHeader->zero_data_addr,
+ l_apltHeader->zero_data_size );
+
+ // size of readonly section is located in applet memory section
+ // get it for next step to protect text and data section
+ l_applet_readonly_size = l_apltHeader->readonly_size; // @ai002a
+
+ // 5b. unmap (remove permissions) on SRAM applet after copying applet image.
+ // permissions should be set correctly in SRAM rodata/rwdata section in next step.
+ if ( l_info->mmuMapWritePermission != 0 ) // @ai002a
+ {
+ l_ssxrc = ppc405_mmu_unmap(&(l_info->mmuMapWritePermission));
+
+ if(l_ssxrc)
+ {
+ TRAC_ERR("Error unmapping/changing permissions on SRAM applet section rc=[%08X]", -l_ssxrc);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_MMU_UNMAP_APPLET_OVERWRITE_FAILURE
+ * @devdesc Failure unmapping applet memory region permissions
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_MMU_UNMAP_APPLET_OVERWRITE_FAILURE; // @ai002
+
+ // bail out
+ break;
+ }
+ }
+
+ // 6 mapping mmu tlb permission (read-only section and writable section)
+ // 6a. protect applet text in SRAM (tlbie)
+ l_ssxrc = ppc405_mmu_map(
+ l_apltSramAddress,
+ l_apltSramAddress,
+ l_applet_readonly_size, // protect the text and data section // @ai002c
+ 0,
+ TLBLO_EX,
+ &(l_info->mmuMapReadPermission)
+ );
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("Error mapping SRAM with execute permissions rc=[%08X]",l_ssxrc);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_MMU_MAP_APPLET_READ_FAILURE
+ * @devdesc Failure mapping applet read-only/executable permissions
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_MMU_MAP_APPLET_READ_FAILURE; // @ai002
+ break;
+ }
+
+ // 6b. map applet rwdata section in SRAM as writable (tlbie)
+ // @ai002a
+ if(0 != l_apltHeader->boot_writeable_size)
+ {
+ l_ssxrc = ppc405_mmu_map(
+ l_apltHeader->boot_writeable_addr,
+ l_apltHeader->boot_writeable_addr,
+ l_apltHeader->boot_writeable_size,
+ 0,
+ TLBLO_WR, // set rwdata section to write permission
+ &(l_info->mmuMapWritePermission)
+ );
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("Error mapping SRAM with execute permissions rc=[%08X]",l_ssxrc);
+
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Applet start status
+ * @userdata4 ERC_MMU_MAP_APPLET_WRITE_FAILURE
+ * @devdesc Failure mapping applet rwdata section permissions
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_MMU_MAP_APPLET_WRITE_FAILURE; // @ai002
+ break;
+ }
+ }
+
+ // save off current applet being run (already copied) into previous
+ // ie: cache applet id
+ // NOTE: This is done here, to ensure the full set up is always completed
+ // before saving off the current applet id into previous applet id var
+ l_info->previousAppId = l_info->appId;
+
+ }//end if
+
+ // 7. Copy entry point address from applet header
+ // and start executing from that address
+ errlHndl_t (*execute_app)(void *) =(void *) l_apltHeader->ep_addr;
+ errlHndl_t l_applog = (*execute_app)(l_info->param);
+ // check if applet return an error log
+ if ( l_applog )
+ {
+ TRAC_ERR("Error found from applet function see error @%p",l_applog);
+
+ if ( l_info->isBlocking )
+ {
+ // if applet caller wanted us to block
+ // save off the error and status
+ l_info->errorHandle = l_applog;
+ l_info->status = OCC_APLT_EXECUTE_FAILURE;
+ }
+ else
+ {
+ // non blocker, so commit the error
+ commitErrl(&l_applog);
+ }
+ }
+
+ }while(0); // end of do while loop
+
+ // All the error at this point setting reason code is before executing
+ // applet so set the status to pre start failure.
+ if( l_reasonCode != 0)
+ {
+ l_status = OCC_APLT_PRE_START_FAILURE;
+ // TODO use correct trace
+ tracDesc_t l_trace = NULL;
+
+ l_rc = createErrl(APLT_MID_START_APPLET, //modId
+ l_reasonCode, //reasoncode // @nh001c
+ l_extReasonCode, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_status, //userdata1
+ 0); //userdata2
+
+ // @wb001 -- Callout to firmware
+ addCalloutToErrl(l_rc,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ if ((l_info->isBlocking ) && (l_info->errorHandle == NULL))
+ {
+ // Return error to caller for blocking call and
+ // there is no error executing applet
+ l_info->errorHandle = l_rc;
+ l_rc = NULL;
+ }
+ else
+ {
+ // commit log for the non-blocking call OR there is
+ // error executing applet
+ commitErrl(&l_rc);
+ }
+ }
+
+ if( (l_info->isBlocking) && (l_info->status == OCC_APLT_SUCCESS))
+ {
+ // Get status only if call is blocking AND no error executing applet
+ l_info->status = l_status;
+ }
+ // @pb00B - Moved posting of semaphores outside of while loop so that
+ // in the error paths semaphores gets posted and not blocked forever.
+ // 8. post on Finished Semaphore if caller wanted us to block them
+ if ( l_info->isBlocking )
+ {
+ l_ssxrc = ssx_semaphore_post( &l_sem->Finished );
+
+ if ( l_ssxrc != SSX_OK )
+ {
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata4 ERC_FINISHED_SEM_POSTING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ TRAC_ERR("Error posting the Applet finished semaphore rc=[%08X]",l_ssxrc);
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_FINISHED_SEM_POSTING_FAILURE; // @nh001a
+ }
+ }
+ // If caller passed in semaphore post it as caller might be blocked on
+ // this semaphore.
+ else if( l_info->callerSem != NULL)
+ {
+ l_ssxrc = ssx_semaphore_post( l_info->callerSem);
+
+ if ( l_ssxrc != SSX_OK )
+ {
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata4 ERC_CALLER_SEM_POSTING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ TRAC_ERR("Error posting the Applet complete semaphore rc=[%08X]",l_ssxrc);
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_CALLER_SEM_POSTING_FAILURE; // @nh001a
+ }
+ }
+
+ // 8a. post on Running Semaphore
+ l_ssxrc = ssx_semaphore_post( &l_sem->Running );
+ if ( l_ssxrc != SSX_OK )
+ {
+ /*
+ * @errortype
+ * @moduleid APLT_MID_START_APPLET
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata4 ERC_RUNNING_SEM_POSTING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ TRAC_ERR("Error posting the Applet running semaphore rc=[%08X]",l_ssxrc);
+ l_reasonCode = SSX_GENERIC_FAILURE; // @nh001c
+ l_extReasonCode = ERC_RUNNING_SEM_POSTING_FAILURE; // @nh001a
+ }
+
+ if( l_reasonCode != 0)
+ {
+ // TODO use correct trace
+ tracDesc_t l_trace = NULL;
+
+ l_rc = createErrl(APLT_MID_START_APPLET, //modId
+ l_reasonCode, //reasoncode // @nh001c
+ l_extReasonCode, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ // @wb001 -- Callout to firmware
+ addCalloutToErrl(l_rc,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // Error posting semaphores so commit it.
+ commitErrl(&l_rc);
+ }
+}
+
+
+// Function Specification
+//
+// Name: App_thread_routine
+//
+// Description: Applet Thread
+//
+// Flow: 06/06/11 FN=App_thread_routine
+//
+// End Function Specification
+void App_thread_routine(void *i_arg)
+{
+ // This happens too often, we cannot trace it
+ //TRAC_INFO("Started ...");
+
+ errlHndl_t l_errl = NULL;
+ OCC_APLT_TYPE l_type = APLT_TYPE_INVALID;
+ // TODO use correct trace
+ tracDesc_t l_trace = NULL;
+
+ if( i_arg == NULL)
+ {
+ TRAC_ERR("Invalid parameter");
+ /*
+ * @errortype
+ * @moduleid APLT_MNGR_THREAD
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 APLT_TYPE_INVALID
+ * @userdata4 ERC_INVALID_INPUT_DATA
+ * @devdesc Internal failure in energy management
+ */
+ l_errl = createErrl(APLT_MNGR_THREAD, //modId
+ INTERNAL_FAILURE, //reasoncode // @nh001c
+ ERC_INVALID_INPUT_DATA, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_type, //userdata1
+ 0); //userdata2
+
+ // @wb001 -- Callout to firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ // commit log
+ commitErrl( &l_errl );
+ //TODO: should we reset OCC?
+ }
+ else
+ {
+ l_type = *((OCC_APLT_TYPE*)i_arg);
+
+ while( 1 )
+ {
+ // This happens too often, we cannot trace it
+ //TRAC_INFO("ApltType: [0x%x] Waiting ...", l_type);
+
+ int l_ssxrc = SSX_OK;
+
+ if( APLT_TYPE_PRODUCT == l_type)
+ {
+ l_ssxrc = ssx_semaphore_pend(&G_ApltSemaphore.Wakeup,
+ SSX_WAIT_FOREVER);
+ }
+ else
+ {
+ l_ssxrc = ssx_semaphore_pend(&G_TestApltSemaphore.Wakeup,
+ SSX_WAIT_FOREVER);
+
+ }
+
+ if ( l_ssxrc != SSX_OK )
+ {
+ TRAC_ERR("WakeUp Semaphore Failure SsxRc[0x%08X]", -l_ssxrc );
+
+ /*
+ * @errortype
+ * @moduleid APLT_MNGR_THREAD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Semaphore pend return code
+ * @userdata2 Applet type input from caller
+ * @userdata4 ERC_WAKEUP_SEM_PENDING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ l_errl = createErrl(APLT_MNGR_THREAD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ ERC_WAKEUP_SEM_PENDING_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ -l_ssxrc, //userdata1
+ l_type); //userdata2
+
+ // commit log
+ REQUEST_RESET(l_errl); // @gm006
+ break;
+ }
+
+ startApplet(l_type);
+
+ } // end while loop
+ }
+
+ TRAC_IMP("Applet Thread Routine [%d] Ended Unexpectedly.", l_type); // @tgh32
+}
+
+
diff --git a/src/occ/aplt/appletManager.h b/src/occ/aplt/appletManager.h
new file mode 100755
index 0000000..ec4cfe2
--- /dev/null
+++ b/src/occ/aplt/appletManager.h
@@ -0,0 +1,127 @@
+/******************************************************************************
+// @file appletManager.h
+// @brief OCC Applet Manager header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _appletManager_h appletManager.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * tapiar 07/15/2011 Created applet manager methods
+ * @pb004 pbavari 09/12/2011 Test Applet and initialization
+ * section support
+ * @02 tapiar 10/03/2011 Changed BOOLEAN to bool
+ * @pb009 pbavari 10/20/2011 Return void for initAppletManager
+ * @pb00A pbavari 11/14/2011 Moved out sensor_init from applet
+ * @th005 thallet 11/23/2011 Added querySensorList applet
+ * @pb00B pbavari 12/13/2011 Fixed runApplet non-blocking call
+ * @dw000 dwoodham 12/13/2011 Moved OCC_APLT to incl/appletId.h
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @pb00F pbavari 06/11/2012 Removed redefinition of applet address
+ * @th029 thallet 01/23/2013 Moved struct & extern from c file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _appletManager_H
+#define _appletManager_H
+
+/** \defgroup OCC Applet Manager Component
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include "errl.h"
+#include <appletId.h> // @dw000a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// @dw000d Moved OCC_APLT to incl/appletId.h
+
+//@pb00B - Changed to have more specific status codes
+// These are the status codes that the applet manager code may return.
+typedef enum
+{
+ OCC_APLT_SUCCESS = 0x00,
+ OCC_APLT_PRE_START_FAILURE = 0x01,
+ OCC_APLT_POST_START_FAILURE = 0x02,
+ OCC_APLT_EXECUTE_FAILURE = 0x03,
+
+} OCC_APLT_STATUS_CODES;
+
+// Applet types
+typedef enum
+{
+ APLT_TYPE_PRODUCT = 0x00,
+ APLT_TYPE_TEST = 0x01,
+ APLT_TYPE_INVALID = 0xFF
+}OCC_APLT_TYPE;
+
+//@pb004m - moved ApltAddress_t to appletManager.c as it was used internally
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+// Applet address/size structure
+typedef struct
+{
+ uint32_t iv_aplt_address;
+ uint32_t iv_size;
+
+} ApltAddress_t; // @th029a
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// Currently NOT externalized, only used in appletManager.c
+
+// Used as a way to pass in parameters to each applet
+// Applet Manager will copy arguments passed in into this
+// global and pass them to applet
+//extern void * G_ApltParms;
+
+extern ApltAddress_t G_ApltAddressTable[ OCC_APLT_LAST ]; // @th029a
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+//@pb00Bc - changed to return void as return code and o_status was returning
+// same thing. This way caller can avoid checking for return code and o_status
+// which were same.
+/* run an applet */
+void runApplet(
+ const OCC_APLT i_applet,
+ void * i_parms,
+ const bool i_block,
+ SsxSemaphore *io_appletComplete,
+ errlHndl_t *o_errHndl,
+ OCC_APLT_STATUS_CODES * o_status);
+
+/* initialize the applet manager */
+//@pb004c - Changed to add init section
+//@pb009c - Changed to return void similar to other calls from main thread
+void initAppletManager( void ) INIT_SECTION;
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_appletManager_H
diff --git a/src/occ/aplt/incl/appletId.h b/src/occ/aplt/incl/appletId.h
new file mode 100755
index 0000000..742ddcf
--- /dev/null
+++ b/src/occ/aplt/incl/appletId.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+// @file appletId.h
+// @brief Applet ID numbers
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensorQueryList.h SENSORQUERYLIST.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @dw000 dwoodham 12/13/2011 New file
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th00d thallet 04/25/2012 Added CMDH Debug Applet
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _APPLET_ID_H
+#define _APPLET_ID_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// Original code & comments from occ/aplt/appletManager.h
+// These are the current applets which exist.
+//@pb004a - Added OCC_APLT_RTL_INIT,OCC_APLT_APSS_INIT,OCC_APLT_SNSR_INIT and
+// OCC_APLT_TEST
+//@pb00Ad - Removed sensor init applet init as it is not an applet anymore.
+typedef enum
+{
+ OCC_APLT_APSS_INIT = 0x00,
+ OCC_APLT_SNSR_QUERY = 0x01,
+ OCC_APLT_CMDH_DBUG = 0x02,
+ OCC_APLT_TEST,
+ OCC_APLT_LAST,
+ OCC_APLT_INVALID = 0xFF
+} OCC_APLT;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif // _APPLET_ID_H
diff --git a/src/occ/aplt/incl/cmdhDbugCmd.h b/src/occ/aplt/incl/cmdhDbugCmd.h
new file mode 100755
index 0000000..d0d0886
--- /dev/null
+++ b/src/occ/aplt/incl/cmdhDbugCmd.h
@@ -0,0 +1,78 @@
+/******************************************************************************
+// @file cmdhDbugCmd.h
+// @brief Header Applet Args -- CMDH Debug Command
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section cmdhDbugCmd.h CMDHDBUGCMD.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th00d thallet 04/22/2011 New file
+ * @nh004 864941 neilhsu 12/20/2012 Support get/delete errl & added trace info
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _CMDHDBUGCMD_H
+#define _CMDHDBUGCMD_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <cmdh_fsp.h>
+#include <cmdh_fsp_cmds.h> // @nh004a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+// Structure that is passed into cmdhDbugcmd applet
+// when it is called
+typedef struct
+{
+ cmdh_fsp_cmd_t * i_cmd_ptr;
+ cmdh_fsp_rsp_t * io_rsp_ptr;
+} cmdhDbugCmdAppletArg_t;
+
+
+/**
+ * @struct cmdh_dbug_inject_errl_query_t;
+ * @brief Used by debug applet to create elog, version 0.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ char comp[OCC_TRACE_NAME_SIZE];
+}cmdh_dbug_inject_errl_query_t; // @nh004a
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif
+
diff --git a/src/occ/aplt/incl/sensorQueryList.h b/src/occ/aplt/incl/sensorQueryList.h
new file mode 100755
index 0000000..0e4fa6f
--- /dev/null
+++ b/src/occ/aplt/incl/sensorQueryList.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+// @file sensorQueryList.h
+// @brief Header Applet Args -- Query Sensor List for AMESTER or MNFG
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensorQueryList.h SENSORQUERYLIST.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th005 thallet 11/22/2011 New file
+ * @rc003 rickylie 02/07/2012 Verify & Clean Up OCC Headers & Comments
+ * @at003 alvinwan 03/19/2012 Add o_sensorInfoPtrs to querySensorListAppletArg_t
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gm002 885429 milesg 04/30/2013 change location/type to 16 bit bitmasks
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _SENSORQUERYLIST_H
+#define _SENSORQUERYLIST_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+// Structure that is passed into querySensorList applet
+// when it is called
+typedef struct
+{
+ uint16_t i_startGsid;
+ uint8_t i_present;
+ uint16_t i_type; //gm002
+ uint16_t i_loc; //gm002
+ uint16_t * io_numOfSensors;
+ sensorQueryList_t * o_sensors;
+ sensor_info_t * o_sensorInfoPtrs; //@at002A
+} querySensorListAppletArg_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif
+
diff --git a/src/occ/app.mk b/src/occ/app.mk
new file mode 100755
index 0000000..e50e465
--- /dev/null
+++ b/src/occ/app.mk
@@ -0,0 +1,257 @@
+# $Id$
+
+# @file app.mk
+#
+# @brief mk occ application
+#
+# This Makefile is included-ed into application Makefiles and
+# encapsulates the steps necessary to create application images.
+#
+# The application Makefile (user) must define the following variables:
+#
+# APP - The name of the application
+# SOURCES - The list of local source files that implement the
+# application.
+#
+# The application Makefile (user) may optionally define the following
+# variables:
+#
+# D - The value of $(D) is appended to DEFS defined by ssx.mk
+#
+# MODE - The following modes are recognized:
+#
+# validation - (Default) An application that requires all SSX
+# services.
+#
+# firmware - An interrupt only configuration.
+#
+# The make process creates the following files:
+#
+# $(APP).out - The PowerPC-ELF version of the application
+# $(APP).bin - A binary SRAM image of the application
+# $(APP).map - The linker map of the application
+#
+# @page ChangeLogs Change Logs
+# @section app.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb000 pbavari 07/11/2011 Added imageHdrScript usage
+# @dw001 dwoodham 08/23/2011 Migrate to OCC version of linkocc.cmd
+# @pb006 pbavari 09/16/2011 Display size support
+# @pb00D pbavari 02/21/2012 Support for using GNU assembler for GPE files
+# @at007 alvinwan 05/25/2012 Use complex method for linking pore and PPC objects
+# @at009 859308 alvinwan 10/15/2012 Added tracepp support
+# @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+#
+# @endverbatim
+#
+
+
+
+#*******************************************************************************
+# mk variable Declaration
+#*******************************************************************************
+
+OCC = .
+SSX = ../ssx
+LIB = ../lib
+PGP = $(SSX)/pgp
+SSXDIR = $(SSX)/ssx
+PPC405 = $(SSX)/ppc405
+BOOTLOADER = ../occBootLoader
+
+ifeq "$(MODE)" "firmware"
+SSX_TIMER_SUPPORT = 0
+SSX_THREAD_SUPPORT = 0
+endif
+#*******************************************************************************
+# Export
+#*******************************************************************************
+export SSX_TIMER_SUPPORT
+export SSX_THREAD_SUPPORT
+export PPC405_MMU_SUPPORT
+export PGP_ASYNC_SUPPORT
+
+#*******************************************************************************
+# Flags
+#*******************************************************************************
+
+INCLUDES += -I$(OCC) -I$(LIB)
+
+include $(PGP)/ssx.mk
+include $(PGP)/ssxpgpfiles.mk
+include $(SSXDIR)/ssxssxfiles.mk
+include $(PPC405)/ssxppc405files.mk
+include $(LIB)/libgpefiles.mk
+
+# >> gitprep
+# Disable this for GNU builds
+# @at007a - If it's for OCC_FIRMWARE and non-PGAS_PPC build, the library gpefiles needs to be taken out of libssx.a
+#all_gpefiles += $(if $(filter -DOCC_FIRMWARE=1,$(DEFS)),\
+# $(if $(PGAS_PPC),,${addprefix ../lib/,${LIB_PSOBJECTS}}),\
+# )
+#
+# Use this instead:
+all_gpefiles += ${addprefix ../lib/,${LIB_PSOBJECTS}}
+# << gitprep
+
+GPE_OBJECTS = ${all_gpefiles}
+OCC_OBJECTS = ${occ_cfiles} ${occ_Sfiles}
+OBJECTS = ${GPE_OBJECTS} ${OCC_OBJECTS}
+
+# >> gitprep
+# Need full paths to all .o files for commands that follow
+LDFLAGS = \
+ -L $(SSX)/ssx \
+ -L $(SSX)/ppc32 \
+ -L $(SSX)/ppc405 \
+ -L $(SSX)/pgp \
+ -L $(OCC) \
+ -L $(LIB) \
+ -L $(OCC)/amec \
+ -L $(OCC)/aplt \
+ -L $(OCC)/cent \
+ -L $(OCC)/cmdh \
+ -L $(OCC)/dcom \
+ -L $(OCC)/errl \
+ -L $(OCC)/gpe \
+ -L $(OCC)/proc \
+ -L $(OCC)/pss \
+ -L $(OCC)/rtls \
+ -L $(OCC)/sensor \
+ -L $(OCC)/thread \
+ -L $(OCC)/timer \
+ -L $(OCC)/trac \
+ -lssx -lppc32 --oformat=elf32-powerpc -melf32ppc
+# << gitprep
+
+# @pb00Da - Added for linking files compiled using gnu assembler
+LDARGS = --no-warn-mismatch --accept-unknown-input-arch
+# @pb00Dc - Changed to use GCC-DEFS instead of DEFS so that different defines
+# can be used for compiling .S and .pS files
+GCC-DEFS += $(D)
+
+#*******************************************************************************
+# compilation
+#*******************************************************************************
+# @pb000a - Added $(BOOTLOADER)/imageHdrScript usage for building occ image
+# @dw001c - Use OCC version of linkscript vs. the PGP version.
+# @th029c - Added CFLAGS to OCC files if GCove is enabled and add md5sum as
+# version (first 4 bytes)
+ifdef GCOV_CODE_COVERAGE
+${occ_cfiles}: CFLAGS += -fprofile-arcs -ftest-coverage
+endif
+
+# >> gitprep
+# Disable for GNU builds
+#ifdef PGAS_PPC
+#all: $(OBJECTS) libssx.a
+# $(MAKE) -w -C $(PGP) DEFS="$(DEFS)" -e
+# $(CPP) -P $(DEFS) < $(OCC)/linkocc.cmd > linkscript
+# $(LD) $(OBJECTS) \
+# -Tlinkscript $(LDFLAGS) $(LDARGS) -Map $(APP).map -Bstatic -o $(APP).out
+#else
+# << gitprep
+
+# @at007a - Use complex method for linking pore and PPC objects
+all: $(OBJECTS) libssx.a
+# >> gitprep
+# add -w to inhibit all warnings
+ $(MAKE) -w -C $(PGP) DEFS="$(DEFS)" -e
+# << gitprep
+ $(CPP) -P $(DEFS) < $(OCC)/linkocc.cmd > linkscript
+
+ # Create gpe binary with symbols undefined
+ # First stage link, no ppc syms yet. Link with -noinhibit-exec to prevent
+ # undefined syms killing output. This binary won't be located at the
+ # correct base address, but can reasonably be assumed to be the correct
+ # size. (If it isn't the right size, then iterate over another link stage.)
+ $(PORE-LD) -o gpe_1.out $(GPE_OBJECTS) -noinhibit-exec -Map gpe_1.map -e 0
+ $(PORE-OBJCOPY) -O binary gpe_1.out gpe_1.bin
+
+ # Insert gpe binary to occ
+ # Don't link with -zmuldefs here so we get an error if PORE symbols
+ # clash with PowerPC ones.
+# >> gitprep
+# $(OCC_OBJECTS) does nothing
+# $(LD) -o occ_1.out $(OCC_OBJECTS) -R gpe_1.out \
+# -Tlinkscript $(LDFLAGS) $(LDARGS) -Map occ_1.map -Bstatic -b binary gpe_1.bin
+ $(LD) -o occ_1.out -R gpe_1.out \
+ -Tlinkscript $(LDFLAGS) $(LDARGS) -Map occ_1.map -Bstatic -b binary gpe_1.bin
+# << gitprep
+ # Find the address of gpe binary and create gpe binary with symbols relocated
+ # Find where pore binary was placed. The symbol we look for
+ # incorporates the name of the binary we linked above.
+ # Second stage link of pore object at the correct address (from symbols above)
+ # now gets ppc syms added from occ_1.out, -z muldefs stops multiple def
+ # errors when we get pore symbols from occ_1.out too
+ pore_base=`nm occ_1.out | grep _binary_gpe_1_bin_start | sed -e s', .*,,'`;$(PORE-LD) -o gpe.out \
+ $(GPE_OBJECTS) -Ttext $$pore_base --no-warn-mismatch --accept-unknown-input-arch -R occ_1.out -z muldefs -Map gpe.map -e 0
+ $(PORE-OBJCOPY) -O binary gpe.out gpe.bin
+
+ # Insert the gpe binary to occ and relocate the symbols in occ
+ # Create gep_2.out that is used by OCC_OBJECTS to relocate the symboles in occ
+ # so we have all symboles relocated in both OCC_OBJECTS and gpe.bin
+# >> gitprep
+# Add noinhibit
+ pore_base=`nm occ_1.out | grep _binary_gpe_1_bin_start | sed -e s', .*,,'`;$(PORE-LD) -o gpe_2.out \
+ $(GPE_OBJECTS) -Ttext $$pore_base --no-warn-mismatch --accept-unknown-input-arch -noinhibit-exec -Map gpe_2.map -e 0
+# << gitprep
+
+# >> gitprep
+# $(OCC_OBJECTS) does nothing
+# $(LD) -o occ.out $(OCC_OBJECTS) -R gpe_2.out \
+# -Tlinkscript $(LDFLAGS) $(LDARGS) -Map occ.map -Bstatic -b binary gpe.bin
+ $(LD) -o occ.out -R gpe_2.out \
+ -Tlinkscript $(LDFLAGS) $(LDARGS) -Map occ.map -Bstatic -b binary gpe.bin
+# << gitprep
+
+#endif
+# >> gitprep
+# Specify source object format as elf32-powerpc
+ $(OBJCOPY) -I elf32-powerpc -O binary $(APP).out $(APP).bin
+# << gitprep
+ $(OBJDUMP) -D $(APP).out > $(APP).dis
+ $(BOOTLOADER)/imageHdrScript $(APP).bin `md5sum $(APP).out | cut -c 1-4`
+
+libssx.a:
+ $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e
+
+.PHONY : combineImage
+combineImage:
+ $(BOOTLOADER)/imageHdrScript $(APP).bin combineImage
+ $(BOOTLOADER)/imageHdrScript $(APP).out displaySize
+
+#*******************************************************************************
+# clean
+#*******************************************************************************
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map *.hash linkscript
+ rm -f ./*/*.o ./*/*.d ./*/*.d.* ./*/*.hash
+
+.PHONY : clean_all
+clean_all:
+ $(MAKE) clean
+ $(MAKE) -C $(PGP) clean
+
+#*******************************************************************************
+# Doxygen
+#*******************************************************************************
+
+.PHONY : doc
+doc:
+ doxygen doc/Doxyfile
+
+#*******************************************************************************
+# .d file creation
+#*******************************************************************************
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(OBJECTS:.o=.d)
+endif
diff --git a/src/occ/arl_test.c b/src/occ/arl_test.c
new file mode 100755
index 0000000..89750e1
--- /dev/null
+++ b/src/occ/arl_test.c
@@ -0,0 +1,234 @@
+/******************************************************************************
+// @file arl_test.c
+// @brief OCC main arl_test
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section arl_test.c ARL_TEST.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * mware 10/21/2011 Created initial version.
+ * @mw010 mware 10/23/2011 Added code to inject per thread
+ * SCOM data to test per thread sensors on P8.
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include "arl_test_data.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Strustures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+#ifdef AMEC_ARL_TEST_COMPILE
+sOCCData_t gOCC = {0};
+sRTLData_t gRTL = {0};
+
+sOCCData_t * gpOCC = &gOCC;
+sRTLData_t * gpRTL = &gRTL;
+#endif
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: arl_test
+//
+// Description: Perform any needed mode changes
+//
+// Flow: FN=None
+//
+// End Function Specification
+void arl_test(void)
+{
+#ifdef AMEC_ARL_TEST_COMPILE
+ UINT8 i = 0;
+ UINT32 temp32 = 0;
+ UINT32 temp32a = 0;
+ UINT16 temp16 = 0;
+ UINT16 temp16a = 0;
+
+
+ //gpRTL->cycles250usincrement = CYCLES_INC; // hard coded to correspond to 4GHz and the # of cycles every 250usec
+ gpRTL->cycles250us = gpRTL->cycles250us + gpRTL->cycles250usincrement;
+
+ // Inject raw cycle counter (currently based on 4GHz core frequency)
+ gpOCC->SCOM_ARRAY[INDEX_PC_RAW]=gpRTL->cycles250us;
+
+ // Compute differential in raw PC cycles
+ temp32 = gpOCC->SCOM_ARRAY[INDEX_PC_RAW];
+ temp32a = gpRTL->scom_prev_PC_RAW_250us;
+ temp32 = temp32 - temp32a;
+
+ // Convert to frequency for this core
+ temp32 = temp32 << 8; // Shift left 8 bits (raw value is < 2^24)
+ temp32a = 64000; // Divide by 64000 to convert to frequency sensor in 1MHz increments
+ temp32 = temp32 / temp32a;
+ gpRTL->FREQ250USP0C0=(UINT16)temp32; // Write to frequency sensor
+
+
+ // $mw010 Begin: Debug code to inject data into SCOMs for per thread information
+
+ for (i=0; i<MAX_THREADS; i++)
+ {
+ temp32 = gpRTL->utilcounter[i]+gpRTL->utilincrement[i];
+ gpRTL->utilcounter[i]=temp32;
+ gpOCC->SCOM_ARRAY[INDEX_PC_RUN_T0+i]=temp32;
+ }
+
+
+
+ // $mw010 End: Debug code to inject data into SCOMs for per thread information
+
+ /////////////////////////////////////////////////////////////////////////
+ // Begin: 2ms state machine
+ /////////////////////////////////////////////////////////////////////////
+
+ switch (gpOCC->AME_sm_cnt)
+ {
+
+ //////////////////////////////////////////////////////////////////////////
+ // Begin: Perform State 0 of EMPATH 2msec State Machine
+ //////////////////////////////////////////////////////////////////////////
+ case 0x00:
+
+ // This state processes core 0's per thread utilization SCOMs
+
+ // $mw010 Begin: Code to read SCOM_ARRAY and convert into actual per thread utilization sensors
+
+ // First step is to calculate how many raw cycles went by in the core during the last 2msec
+
+ temp32 = gpOCC->SCOM_ARRAY[INDEX_PC_RAW];
+ temp32a = gpRTL->scom_prev_PC_RAW_2ms;
+ gpRTL->cycles2ms = temp32 - temp32a; // Compute 32 bit differential between SCOM reads now and previous 2msec
+
+ for (i=0; i<MAX_THREADS; i++)
+ {
+ temp32 = gpOCC->SCOM_ARRAY[INDEX_PC_RUN_T0+i]; // Read 32 bit SCOM value for this thread (free running)
+ temp32a = gpRTL->scom_prev_thread[i]; // Read previous 32 bit SCOM value from 32msec ago
+ temp32 = temp32 - temp32a; // Compute 32 bit differential between SCOM reads now and previous 2msec
+ temp32 = temp32 >> 8; // Limit to 16 bits (highest count is < 2^24)
+ temp16 = (UINT16)temp32;
+ temp16a = 10000; // 10000 = 100.00%
+ temp32 = ((UINT32)temp16a)*((UINT32)temp16); // scale by 10000
+ temp32a = gpRTL->cycles2ms;
+ temp32a = temp32a >> 8; // Limit to 16 bits
+ temp32 = temp32 / temp32a;
+ gpRTL->util2ms_thread[i]=(UINT16)temp32;
+ }
+
+
+ // Last step is to remember current SCOMs in scom_prev_thread array for next time
+ for (i=0; i<MAX_THREADS; i++)
+ {
+ gpRTL->scom_prev_thread[i] = gpOCC->SCOM_ARRAY[INDEX_PC_RUN_T0+i];
+ }
+
+ gpRTL->scom_prev_PC_RAW_2ms = gpOCC->SCOM_ARRAY[INDEX_PC_RAW]; // Capture raw cycle count for usage in the next 2msec
+
+ // $mw010 End: Code to read SCOM_ARRAY and convert into actual per thread utilization sensors
+
+
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Begin: Perform State 1 of EMPATH 2msec State Machine
+ //////////////////////////////////////////////////////////////////////////
+ case 0x01:
+
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Begin: Perform State 2 of EMPATH 2msec State Machine
+ //////////////////////////////////////////////////////////////////////////
+ case 0x02:
+
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Begin: Perform State 3 of EMPATH 2msec State Machine
+ //////////////////////////////////////////////////////////////////////////
+ case 0x03:
+
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Begin: Perform State 4 of EMPATH 2msec State Machine
+ //////////////////////////////////////////////////////////////////////////
+ case 0x04:
+
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Begin: Perform State 5 of EMPATH 2msec State Machine
+ //////////////////////////////////////////////////////////////////////////
+ case 0x05:
+
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Begin: Perform State 6 of EMPATH 2msec State Machine
+ //////////////////////////////////////////////////////////////////////////
+ case 0x06:
+
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Begin: Perform State 7 of EMPATH 2msec State Machine
+ //////////////////////////////////////////////////////////////////////////
+ case 0x07:
+
+ break;
+
+ }
+
+
+ // Capture raw cycle count to use in next 250us
+ gpRTL->scom_prev_PC_RAW_250us = gpOCC->SCOM_ARRAY[INDEX_PC_RAW]; // Capture raw cycle count for usage in the next 250us
+
+ // Increment AME state machine counter using modulo AME_SM_TICK
+ gpOCC->AME_sm_cnt = (UINT8) ((gpOCC->AME_sm_cnt + 1) & (AME_SM_TICKS - 1));
+
+
+ // Always increment AME time on every call to ISR
+ gpOCC->r_cnt++;
+
+ // Insert ARL Test Code Here
+ //printf("ARL Test Code\n");
+
+#endif
+}
+
+
diff --git a/src/occ/arl_test_data.h b/src/occ/arl_test_data.h
new file mode 100755
index 0000000..5d14577
--- /dev/null
+++ b/src/occ/arl_test_data.h
@@ -0,0 +1,115 @@
+/******************************************************************************
+// @file arl_test_data.h
+// @brief arl_test_data header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section arl_test_data.h ARL_TEST_DATA.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * mware 10/21/2011 Created initial version.
+ * @mw010 mware 10/23/2011 Added code to inject per thread
+ * SCOM data to test per thread sensors on P8.
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _arl_test_data_h
+#define _arl_test_data_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// Uncomment this to enable the ARL Test Code
+//#define AMEC_ARL_TEST_COMPILE 1
+
+#ifdef AMEC_ARL_TEST_COMPILE
+typedef uint32_t UINT32;
+typedef uint16_t UINT16;
+typedef uint8_t UINT8;
+
+#define MAX_THREADS 8
+// Begin: SCOM_ARRAY offsets
+// The following is an offset into a 32 bit array that contains the SCOM values read by the OCC
+// Later, the order will likely change to reflect the order in which the SCOMs are written into local OCC memory
+// by the GUPI program that is reading them from the physical SCOM registers and depositing them into OCC memory.
+#define INDEX_PC_RUN_T0 0
+#define INDEX_PC_RUN_T1 1
+#define INDEX_PC_RUN_T2 2
+#define INDEX_PC_RUN_T3 3
+#define INDEX_PC_RUN_T4 4
+#define INDEX_PC_RUN_T5 5
+#define INDEX_PC_RUN_T6 6
+#define INDEX_PC_RUN_T7 7
+#define INDEX_PC_RAW 8
+// End: SCOM_ARRAY offsets
+#define MAX_INDICES 9 // equal to the total number of SCOM_ARRAY entries
+
+#define CYCLES_INC 1000000 // cycles increment: corresponds to the # of core cycles every 250usec (currently set to correspond to 4GHz core)
+#define AME_SM_TICKS 8 // Basic state machine modulo 8 (8*250usec = 2msec)
+
+
+
+typedef struct
+{
+ UINT32 r_cnt; // 32 bit time stamp counting interrupt ticks
+ UINT32 SCOM_ARRAY[MAX_INDICES]; // Array of SCOM values (32 bits each) read by the GUPI program and placed into OCC SRAM
+ UINT8 AME_sm_cnt; // Underlying AME state machine counter (modulo 8)
+} sOCCData_t;
+
+typedef struct
+{
+ UINT32 cycles250us; // base cycle counter counting each tick of the core's clock
+ UINT32 cycles250usincrement; // amount to increment base cycles by every 250usec
+ UINT32 cycles2ms; // computes cycles every 2msec using PC_RAW SCOM register
+ UINT32 scom_prev_PC_RAW_250us; // Remembers previous SCOM value for PC_RAW SCOM register 250us ago
+ UINT32 scom_prev_PC_RAW_2ms; // Remembers previous SCOM value for PC_RAW SCOM register 2msec ago
+ UINT32 scom_prev_thread[MAX_THREADS]; // Remembers previous SCOM value for each thread
+ UINT32 utilcounter[MAX_THREADS]; // base counter for synthesizing per thread utilization (value written to SCOMs every 250usec)
+ UINT32 utilincrement[MAX_THREADS]; // increment for synthesizing per thread utilization (cycles per 250usec with run latch on)
+ UINT16 util2ms_thread[MAX_THREADS]; // array of utilization sensors for P0 Core 0 (0.01% increments)
+ UINT16 FREQ250USP0C0; // actual frequency sensor for P0 Core 0 (1MHz increments)
+
+} sRTLData_t;
+
+extern sOCCData_t gOCC;
+extern sRTLData_t gRTL;
+
+extern sOCCData_t * gpOCC;
+extern sRTLData_t * gpRTL;
+
+#endif
+//*************************************************************************
+// Strustures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_arl_test_data_h
diff --git a/src/occ/cent/centaur_control.c b/src/occ/cent/centaur_control.c
new file mode 100755
index 0000000..1a154fd
--- /dev/null
+++ b/src/occ/cent/centaur_control.c
@@ -0,0 +1,698 @@
+/******************************************************************************
+// @file centaur_control.c
+// @brief Control of Centaur Chips/Procedures/Data.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _centaur_control_c centaur_control.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @th045 893135 thallet 07/26/2013 Updated for new Centaur Procedures
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @rt001 901927 tapiar 10/03/2013 Fix src tags
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @gm017 909636 milesg 12/17/2013 Changes from mem throttle review
+ * @gm023 913865 milesg 01/31/2014 Centaur GPE times out
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "centaur_control.h"
+#include "centaur_data.h"
+#include "pgp_async.h"
+#include "threadSch.h"
+#include "pmc_register_addresses.h"
+#include "centaur_data_service_codes.h"
+#include "occ_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "apss.h"
+#include "state.h"
+#include "gpe_scom.h"
+#include "centaur_firmware_registers.h"
+#include "centaur_register_addresses.h"
+#include "amec_sys.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// Used for Centaur Initialization of Registers
+typedef enum
+{
+ NM_THROTTLE_MBA01 = 0,
+ NM_THROTTLE_MBA23 = 1,
+ MBS_THROTTLE_SYNC = 2,
+ NUM_CENT_THROTTLE_SCOMS = 3,
+} eCentaurThrottleRegs;
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//Pore flex request for the GPE job that is used for centaur init.
+PoreFlex G_centaur_control_pore_req;
+GPE_BUFFER(GpeScomParms G_centaur_control_reg_parms);
+GPE_BUFFER(scomList_t G_centaurThrottle[NUM_CENT_THROTTLE_SCOMS]);
+
+//Centaur structures used for task data pointers.
+centaur_control_task_t G_centaur_control_task =
+{
+ .startCentaur = 0, // First Centaur
+ .prevCentaur = 7, // Previous Centaur written to
+ .curCentaur = 0, // Current Centaur
+ .endCentaur = 7, // Last Centaur
+ .traceThresholdFlags = 0, // Trace Throttle Flags
+};
+
+// Per-MBA N/M Throttle Register "M & N" Values
+centaur_throttle_t G_centaurThrottleLimits[MAX_NUM_CENTAURS][NUM_MBAS_PER_CENTAUR];
+
+//bitmap of configured MBA's (2 per centaur, lsb is centaur 0/mba 0)
+uint16_t G_configured_mbas = 0;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+//gm016
+//////////////////////////
+// Function Specification
+//
+// Name: centaurThrottle_convert2Numerator
+//
+// Description: Converts a throttle percentage into an 'N' value that can
+// be written to the hardware.
+//
+//
+// Flow: ???? FN= ????
+//
+// Thread: RTL
+//
+// End Function Specification
+uint16_t centaurThrottle_convert2Numerator(uint16_t i_throttle, uint8_t i_cent, uint8_t i_mba)
+{
+#define CENTAUR_THROTTLE_100_PERCENT_VALUE 1000
+
+ uint32_t l_nvalue = 0;
+ centaur_throttle_t* l_mba = &G_centaurThrottleLimits[i_cent][i_mba];
+
+ if(MBA_CONFIGURED(i_cent, i_mba))
+ {
+ // Convert the throttle ( actually in units of 0.1 %) to a "N" value
+ l_nvalue = (l_mba->max_n_per_mba * i_throttle) /
+ CENTAUR_THROTTLE_100_PERCENT_VALUE;
+
+ //Clip to per-mba min and max values
+ if(l_nvalue < l_mba->min_n_per_mba)
+ {
+ l_nvalue = l_mba->min_n_per_mba;
+ }
+ if(l_nvalue > l_mba->max_n_per_mba)
+ {
+ l_nvalue = l_mba->max_n_per_mba;
+ }
+ }
+
+ return (uint16_t)l_nvalue;
+}
+
+//////////////////////////
+// Function Specification
+//
+// Name: cent_update_nlimits
+//
+// Description: Updates the memory throttle settings for;
+// 1) new settings from FSP
+// 2) change to/from TURBO or DPS mode
+// 3) enter/exit oversubscription
+//
+//
+// Flow: ???? FN= ????
+//
+// Thread: RTL
+//
+// End Function Specification
+#define CENT_TRACE_THROTTLE_DELAY 8
+void cent_update_nlimits(uint32_t i_cent)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ static uint32_t L_trace_throttle_count = 0;
+ uint16_t l_mba01_mba_maxn, l_mba01_chip_maxn, l_mba23_mba_maxn, l_mba23_chip_maxn;
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ centaur_throttle_t* l_active_limits01 =
+ &G_centaurThrottleLimits[i_cent][0];
+ centaur_throttle_t* l_active_limits23 =
+ &G_centaurThrottleLimits[i_cent][1];
+ mem_throt_config_data_t* l_state_limits01 =
+ &G_sysConfigData.mem_throt_limits[i_cent][0];
+ mem_throt_config_data_t* l_state_limits23 =
+ &G_sysConfigData.mem_throt_limits[i_cent][1];
+
+ //Minimum N value is not state dependent
+ l_active_limits01->min_n_per_mba = l_state_limits01->min_ot_n_per_mba;
+ l_active_limits23->min_n_per_mba = l_state_limits23->min_ot_n_per_mba;
+
+ //oversubscription?
+ if(AMEC_INTF_GET_OVERSUBSCRIPTION())
+ {
+ l_mba01_mba_maxn = l_state_limits01->ovs_n_per_mba;
+ l_mba01_chip_maxn = l_state_limits01->ovs_n_per_chip;
+ l_mba23_mba_maxn = l_state_limits23->ovs_n_per_mba;
+ l_mba23_chip_maxn = l_state_limits23->ovs_n_per_chip;
+ }
+ else if(CURRENT_MODE() == OCC_MODE_NOMINAL)
+ {
+ l_mba01_mba_maxn = l_state_limits01->nom_n_per_mba;
+ l_mba01_chip_maxn = l_state_limits01->nom_n_per_chip;
+ l_mba23_mba_maxn = l_state_limits23->nom_n_per_mba;
+ l_mba23_chip_maxn = l_state_limits23->nom_n_per_chip;
+ }
+ else //DPS, TURBO, FFO, and SPS modes will use these settings
+ {
+ l_mba01_mba_maxn = l_state_limits01->turbo_n_per_mba;
+ l_mba01_chip_maxn = l_state_limits01->turbo_n_per_chip;
+ l_mba23_mba_maxn = l_state_limits23->turbo_n_per_mba;
+ l_mba23_chip_maxn = l_state_limits23->turbo_n_per_chip;
+ }
+
+ l_active_limits01->max_n_per_chip = l_mba01_chip_maxn;
+ l_active_limits23->max_n_per_chip = l_mba23_chip_maxn;
+
+ //Trace when the MBA max N value changes
+ if((l_mba01_mba_maxn != l_active_limits01->max_n_per_mba) ||
+ (l_mba23_mba_maxn != l_active_limits23->max_n_per_mba))
+ {
+ l_active_limits01->max_n_per_mba = l_mba01_mba_maxn;
+ l_active_limits23->max_n_per_mba = l_mba23_mba_maxn;
+
+ //Don't trace every MBA changing, just one
+ if(!L_trace_throttle_count)
+ {
+ L_trace_throttle_count = CENT_TRACE_THROTTLE_DELAY;
+ TRAC_IMP("New MBA throttle max|min N values: mba01[0x%08x], mba23[0x%08x]",
+ (uint32_t)((l_mba01_mba_maxn << 16) | l_active_limits01->min_n_per_mba),
+ (uint32_t)((l_mba23_mba_maxn << 16) | l_active_limits23->min_n_per_mba));
+ break;
+ }
+ }
+
+ if(L_trace_throttle_count)
+ {
+ L_trace_throttle_count--;
+ }
+
+ }while(0);
+}
+
+
+// Function Specification
+//
+// Name: task_centaur_control
+//
+// Description: Collect centaur data. The task is used for centaur data
+// collection
+//
+// Flow: 02/27/13 FN=task_centaur_control
+//
+// End Function Specification
+#define CENTAUR_CONTROL_SCOM_TIMEOUT 16 //wait up to 16 ticks before logging timeout failure
+void task_centaur_control( task_t * i_task )
+{
+ errlHndl_t l_err = NULL; // Error handler
+ int rc = 0; // Return code
+ uint32_t l_cent;
+ amec_centaur_t *l_cent_ptr = NULL;
+ static uint8_t L_scom_timeout[MAX_NUM_CENTAURS] = {0}; //track # of consecutive failures
+ static bool L_gpe_scheduled = FALSE;
+ static uint8_t L_gpe_fail_logged = 0;
+ static bool L_gpe_idle_traced = FALSE;
+ static bool L_gpe_had_1_tick = FALSE;
+
+ // Pointer to the task data structure
+ centaur_control_task_t * l_centControlTask =
+ (centaur_control_task_t *) i_task->data_ptr;
+
+
+ // Pointer to parameter field for GPE request
+ GpeScomParms * l_parms =
+ (GpeScomParms *)(l_centControlTask->gpe_req.parameter);
+
+ do
+ {
+ l_cent = l_centControlTask->curCentaur;
+ l_cent_ptr = &g_amec->proc[0].memctl[l_cent].centaur;
+
+ //First, check to see if the previous GPE request still running
+ //A request is considered idle if it is not attached to any of the
+ //asynchronous request queues
+ if( !(async_request_is_idle(&l_centControlTask->gpe_req.request)) )
+ {
+ L_scom_timeout[l_cent]++;
+ //This can happen due to variability in when the task runs
+ if(!L_gpe_idle_traced && L_gpe_had_1_tick)
+ {
+ TRAC_INFO("task_centaur_control: GPE is still running. cent[%d]", l_cent);
+ l_centControlTask->traceThresholdFlags |= CENTAUR_CONTROL_GPE_STILL_RUNNING;
+ L_gpe_idle_traced = TRUE;
+ }
+ L_gpe_had_1_tick = TRUE;
+ break;
+ }
+ else
+ {
+ //Request is idle
+ L_gpe_had_1_tick = FALSE;
+ if(L_gpe_idle_traced)
+ {
+ TRAC_INFO("task_centaur_control: GPE completed. cent[%d]", l_cent);
+ L_gpe_idle_traced = FALSE;
+ }
+ }
+
+ //check scom status
+ if(L_gpe_scheduled)
+ {
+ if(!async_request_completed(&l_centControlTask->gpe_req.request) || l_parms->rc)
+ {
+
+ if(!(L_gpe_fail_logged & (CENTAUR0_PRESENT_MASK >> l_cent)))
+ {
+ L_gpe_fail_logged |= CENTAUR0_PRESENT_MASK >> l_cent;
+ TRAC_ERR("task_centaur_control: gpe_scom_centaur failed. l_cent=%d rc=%x, index=0x%08x", l_cent, l_parms->rc, l_parms->errorIndex);
+
+ /* @
+ * @errortype
+ * @moduleid CENT_TASK_CONTROL_MOD
+ * @reasoncode CENT_SCOM_ERROR
+ * @userdata1 rc - Return code of scom operation
+ * @userdata2 index of scom operation that failed
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC access to centaur failed
+ */
+ l_err = createErrl(
+ CENT_TASK_CONTROL_MOD, // modId
+ CENT_SCOM_ERROR, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_PREDICTIVE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ l_parms->rc, // userdata1
+ l_parms->errorIndex // userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &(l_centControlTask->gpe_req.ffdc), //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ //callout the centaur
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.centaur_huids[l_cent],
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ //callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ commitErrl(&l_err);
+ }//if(l_gpe_fail_logged & (CENTAUR0_PRESENT_MASK >> l_cent))
+
+ //Request failed. Keep count of failures and request a reset if we reach a
+ //max retry count
+ L_scom_timeout[l_cent]++;
+ if(L_scom_timeout[l_cent] == CENTAUR_CONTROL_SCOM_TIMEOUT)
+ {
+ break;
+ }
+
+ }//if(!async_request_completed(&l_centControlTask->gpe_req.request) || l_parms->rc)
+ else
+ {
+ //request completed successfully. reset the timeout.
+ L_scom_timeout[l_cent] = 0;
+ }
+ }//if(L_gpe_scheduled)
+
+ //The previous GPE job completed. Now get ready for the next job.
+ L_gpe_scheduled = FALSE;
+
+ //Update current centaur if we didn't fail
+ if ( l_cent >= l_centControlTask->endCentaur )
+ {
+ l_cent = l_centControlTask->startCentaur;
+ }
+ else
+ {
+ l_cent++;
+ }
+ l_centControlTask->curCentaur = l_cent;
+ l_cent_ptr = &g_amec->proc[0].memctl[l_cent].centaur;
+
+ //If centaur is not present or neither MBA is configured then skip it.
+ if(!CENTAUR_PRESENT(l_cent) ||
+ (!MBA_CONFIGURED(l_cent, 0) && !MBA_CONFIGURED(l_cent, 1)))
+ {
+ break;
+ }
+
+ //update min/max settings for both MBA's according to ovs and mode
+ cent_update_nlimits(l_cent);
+
+ //calculate new N values
+ centaur_mba_farb3qn_t l_mbafarbq;
+ uint16_t l_mba01_n_per_mba =
+ centaurThrottle_convert2Numerator(g_amec->mem_speed_request, l_cent, 0);
+ uint16_t l_mba23_n_per_mba =
+ centaurThrottle_convert2Numerator(g_amec->mem_speed_request, l_cent, 1);
+ uint16_t l_mba01_n_per_chip = G_centaurThrottleLimits[l_cent][0].max_n_per_chip;
+ uint16_t l_mba23_n_per_chip = G_centaurThrottleLimits[l_cent][1].max_n_per_chip;
+ amec_cent_mem_speed_t l_mba01_speed;
+ amec_cent_mem_speed_t l_mba23_speed;
+
+ //combine chip and mba settings (16 bit) in to a single 32bit value
+ l_mba01_speed.mba_n = l_mba01_n_per_mba;
+ l_mba01_speed.chip_n = l_mba01_n_per_chip;
+ l_mba23_speed.mba_n = l_mba23_n_per_mba;
+ l_mba23_speed.chip_n = l_mba23_n_per_chip;
+
+
+ // Check if the throttle value has been updated since the last
+ // time we sent it. If it has, then send a new value, otherwise
+ // do nothing.
+ if ( ( l_mba01_speed.word32 == l_cent_ptr->portpair[0].last_mem_speed_sent.word32 ) &&
+ ( l_mba23_speed.word32 == l_cent_ptr->portpair[1].last_mem_speed_sent.word32 )
+ )
+ {
+ break;
+ }
+
+ //TRAC_INFO("task_centaur_control: New centaur[%d] throttle values mba01[0x%08x], mba23[0x%08x], throt[%d] ",
+ // l_cent,
+ // l_mba01_speed.word32,
+ // l_mba23_speed.word32,
+ // g_amec->mem_speed_request);
+
+ /// Set up Centuar Scom Registers - array of Scoms
+ /// [0]: N/M Throttle MBA01
+ /// [1]: N/M Throttle MBA23
+ /// [2]: MB SYNC
+
+ //only write to MBA01 if configured
+ if(MBA_CONFIGURED(l_cent, 0))
+ {
+ /// [0]: Set up N/M throttle MBA01
+ G_centaurThrottle[NM_THROTTLE_MBA01].commandType = GPE_SCOM_RMW;
+ G_centaurThrottle[NM_THROTTLE_MBA01].instanceNumber = l_cent;
+ // Set up value to be written
+ l_mbafarbq.fields.cfg_nm_n_per_mba = l_mba01_n_per_mba;
+ l_mbafarbq.fields.cfg_nm_n_per_chip = l_mba01_n_per_chip;
+ G_centaurThrottle[NM_THROTTLE_MBA01].data = l_mbafarbq.value;
+ }
+ else
+ {
+ G_centaurThrottle[NM_THROTTLE_MBA01].commandType = GPE_SCOM_NOP;
+ }
+
+ //only write to MBA23 if configured
+ if(MBA_CONFIGURED(l_cent, 1))
+ {
+ /// [1]: Set up N/M throttle MBA23
+ G_centaurThrottle[NM_THROTTLE_MBA23].commandType = GPE_SCOM_RMW;
+ G_centaurThrottle[NM_THROTTLE_MBA23].instanceNumber = l_cent;
+ // Set up value to be written
+ l_mbafarbq.fields.cfg_nm_n_per_mba = l_mba23_n_per_mba;
+ l_mbafarbq.fields.cfg_nm_n_per_chip = l_mba23_n_per_chip;
+ G_centaurThrottle[NM_THROTTLE_MBA23].data = l_mbafarbq.value;
+ }
+ else
+ {
+ G_centaurThrottle[NM_THROTTLE_MBA23].commandType = GPE_SCOM_NOP;
+ }
+
+
+ /// [2]: Set up the SYNC
+ ///
+ /// See Section 2.1.4.1 Centaur Sync Operations in the
+ /// Pgp Memory Controller Workbook to determine how to fill
+ /// in the data field:
+ /// https://farm0125.rtp.stglabs.ibm.com/ServerASIC/Centaur/PgP_MCS_Unit/MC_Workbook?action=AttachFile&do=get&target=p8mc_dd1_wb_061213.pdf
+ /// 0:7 select mask of MCS units
+ /// 8:15 select the sync type (12 = N/M throttle)
+ /// 57:63 must be zeros to address DW0 in cacheline
+ //G_centaurThrottle[MBS_THROTTLE_SYNC].commandType = GPE_SCOM_NOP;
+ G_centaurThrottle[MBS_THROTTLE_SYNC].commandType = GPE_SCOM_CENTAUR_SYNC_ALL;
+ G_centaurThrottle[MBS_THROTTLE_SYNC].data = CENTAUR_RESET_N_M_THROTTLE_COUNTER_SYNC |
+ CENTAUR_MYSTERY_SYNC; //This is the "PC" sync bit
+
+ /// Set up GPE parameters
+ l_parms->scomList = (uint32_t) (&G_centaurThrottle);
+ l_parms->entries = 3;
+ l_parms->options = 0;
+ l_parms->rc = 0;
+ l_parms->errorIndex = 0;
+
+ // Update the last sent throttle value, this will get
+ // cleared if the GPE does not complete successfully.
+ l_cent_ptr->portpair[0].last_mem_speed_sent.word32 = l_mba01_speed.word32;
+ l_cent_ptr->portpair[1].last_mem_speed_sent.word32 = l_mba23_speed.word32;
+
+
+ // Pore flex schedule gpe_scom_centaur
+ // Check pore_flex_schedule return code if error
+ // then request OCC reset.
+ rc = pore_flex_schedule( &(l_centControlTask->gpe_req) );
+ if( rc )
+ {
+ //Error in schedule gpe get centaur data
+ TRAC_ERR("task_centaur_control: Failed to schedule gpe rc=%x", rc);
+
+ /* @
+ * @errortype
+ * @moduleid CENT_TASK_CONTROL_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 rc - Return code of failing function
+ * @userdata2 0
+ * @userdata4 ERC_CENTAUR_PORE_FLEX_SCHEDULE_FAILURE
+ * @devdesc OCC Failed to schedule a GPE job for centaur
+ */
+ l_err = createErrl(
+ CENT_TASK_CONTROL_MOD, // modId
+ SSX_GENERIC_FAILURE, // reasoncode
+ ERC_CENTAUR_PORE_FLEX_SCHEDULE_FAILURE, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ rc, // userdata1
+ l_parms->rc // userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &(l_centControlTask->gpe_req.ffdc), //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ REQUEST_RESET(l_err); //This will add a firmware callout for us
+ break;
+ }
+
+ L_gpe_scheduled = TRUE;
+ } while(0);
+
+ if(L_scom_timeout[l_cent] == CENTAUR_CONTROL_SCOM_TIMEOUT)
+ {
+ TRAC_ERR("task_centaur_control: Timeout scomming centaur[%d]", l_cent);
+ /* @
+ * @errortype
+ * @moduleid CENT_TASK_CONTROL_MOD
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 centaur number
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Timed out trying to set the memory throttle settings
+ * throttle settings.
+ */
+ l_err = createErrl(
+ CENT_TASK_CONTROL_MOD, // modId
+ INTERNAL_FAILURE, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_PREDICTIVE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ l_cent, // userdata1
+ 0 // userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &(l_centControlTask->gpe_req.ffdc), //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ //callout the centaur
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.centaur_huids[l_cent],
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ //callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ REQUEST_RESET(l_err);
+ }
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: centaur_control_init
+//
+// Description: Do one-time setup for centaur control task
+//
+//
+//
+// Precondition: We must have determined the present centuars already
+//
+// Flow: 02/27/13 FN=init_task_centaur_control
+//
+// End Function Specification
+void centaur_control_init( void )
+{
+ errlHndl_t l_err = NULL;
+ int l_rc_gpe = 0;
+ centaur_mba_farb3qn_t l_mbafarbq;
+
+ do
+ {
+ //initialize the active throttle limits
+ memset(G_centaurThrottleLimits, 0, sizeof(G_centaurThrottleLimits));
+
+ //Do one-time setup items for the task here.
+
+ //--------------------------------------------------
+ // Set up Centuar Regs
+ // [0]: for MBAFARBQ0
+ // [1]: for MBAFARBQ1
+ //--------------------------------------------------
+ //
+ G_centaurThrottle[NM_THROTTLE_MBA01].scom = CENTAUR_MBA_FARB3Q0;
+ G_centaurThrottle[NM_THROTTLE_MBA23].scom = CENTAUR_MBA_FARB3Q1;
+ l_mbafarbq.value = 0;
+ l_mbafarbq.fields.cfg_nm_n_per_mba = -1; //all bits set
+ l_mbafarbq.fields.cfg_nm_n_per_chip = -1; //all bits set
+ G_centaurThrottle[NM_THROTTLE_MBA01].mask = l_mbafarbq.value;
+ G_centaurThrottle[NM_THROTTLE_MBA23].mask = l_mbafarbq.value;
+
+ // Set up GPE parameters
+ G_centaur_control_reg_parms.rc = 0;
+ G_centaur_control_reg_parms.entries = 0;
+ G_centaur_control_reg_parms.scomList = (uint32_t) (&G_centaurThrottle[0]);
+ G_centaur_control_reg_parms.options = 0;
+ G_centaur_control_reg_parms.errorIndex = 0;
+
+ //--------------------------------------------------
+ // Initializes PoreFlex for Centaur Control Task, but
+ // doesn't actually run anything until RTL
+ //--------------------------------------------------
+ l_rc_gpe = pore_flex_create(
+ &G_centaur_control_task.gpe_req, // gpe_req for the task
+ &G_pore_gpe1_queue, // queue
+ gpe_scom_centaur, // entry point
+ (uint32_t) &G_centaur_control_reg_parms, // parm for the task
+ SSX_WAIT_FOREVER, // gm023
+ NULL, // callback
+ NULL, // callback argument
+ 0 ); // options
+ if(l_rc_gpe)
+ {
+ break;
+ }
+
+ }
+ while(0);
+
+
+ if( l_rc_gpe )
+ {
+ //If fail to create pore flex object then there is a problem.
+ TRAC_ERR("centaur_control_init: Failed to initialize centaur control task [l_rc_gpe=0x%x]", l_rc_gpe);
+
+ /* @
+ * @errortype
+ * @moduleid CENTAUR_INIT_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 l_rc_gpe - Return code of failing function
+ * @userdata2 0
+ * @userdata4 ERC_CENTAUR_PORE_FLEX_CREATE_FAILURE
+ * @devdesc Failed to initialize GPE routine
+ */
+ l_err = createErrl(
+ CENTAUR_INIT_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ ERC_CENTAUR_PORE_FLEX_CREATE_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc_gpe, //userdata1
+ 0 //userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &G_centaur_control_pore_req.ffdc, //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ REQUEST_RESET(l_err); //@gm006
+ }
+
+ return;
+}
+
+
+
+
diff --git a/src/occ/cent/centaur_control.h b/src/occ/cent/centaur_control.h
new file mode 100755
index 0000000..3fae595
--- /dev/null
+++ b/src/occ/cent/centaur_control.h
@@ -0,0 +1,100 @@
+/******************************************************************************
+// @file centaur_control.h
+// @brief Centaur external control functions & data.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _centaur_control_h centaur_control.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @gm004 892961 milesg 07/25/2013 Removed centaur_control_init from init section
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _CENTAUR_CONTROL_H
+#define _CENTAUR_CONTROL_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <ssx.h>
+#include "rtls.h"
+#include "gpe_data.h"
+#include "occ_sys_config.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+typedef enum
+{
+ CENTAUR_CONTROL_GPE_STILL_RUNNING = 0x01,
+ CENTAUR_CONTROL_RESERVED_1 = 0x02,
+ CENTAUR_CONTROL_RESERVED_2 = 0x04,
+ CENTAUR_CONTROL_RESERVED_3 = 0x08,
+ CENTAUR_CONTROL_RESERVED_4 = 0x10,
+ CENTAUR_CONTROL_RESERVED_5 = 0x20,
+ CENTAUR_CONTROL_RESERVED_6 = 0x40,
+ CENTAUR_CONTROL_RESERVED_7 = 0x80,
+} eCentaurControlTraceFlags;
+
+//Centaur data collect structures used for task data pointers
+struct centaur_control_task {
+ uint8_t startCentaur;
+ uint8_t prevCentaur;
+ uint8_t curCentaur;
+ uint8_t endCentaur;
+ uint8_t traceThresholdFlags;
+ PoreFlex gpe_req;
+} __attribute__ ((__packed__));
+typedef struct centaur_control_task centaur_control_task_t;
+
+//per mba throttle values -- gm016
+typedef struct
+{
+ uint16_t max_n_per_mba; //mode and OVS dependent, from config data
+ uint16_t max_n_per_chip; //mode and OVS dependent, from config data
+ uint16_t min_n_per_mba; //from config data
+ uint16_t m;
+} centaur_throttle_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//Global centaur structures used for task data pointers
+extern centaur_control_task_t G_centaur_control_task;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//Collect centaur data for all centaur in specified range
+void task_centaur_control( task_t * i_task );
+
+//Initialize structures for collecting centaur data.
+//void centaur_control_init( void ) INIT_SECTION;
+void centaur_control_init( void ); //gm004
+
+#endif //_CENTAUR_CONTROL_H
+
diff --git a/src/occ/cent/centaur_data.c b/src/occ/cent/centaur_data.c
new file mode 100755
index 0000000..64181ad
--- /dev/null
+++ b/src/occ/cent/centaur_data.c
@@ -0,0 +1,1194 @@
+/******************************************************************************
+// @file centaur_data.c
+// @brief Collection & Initialization of Centaur Chips/Procedures/Data.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _centaur_data_c centaur_data.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th00c thallet 03/14/2012 Created
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th012 thallet 07/17/2012 Changed centaur procedure to get
+ * MCS BaseAddress automatically
+ * @th013 thallet 07/17/2012 SW150201: OCC VPO: inbound scom
+ * @th016 thallet 08/13/2012 Change tor only 4 Centaurs possible on Murano
+ * @th018 852950 thallet 09/12/2012 Added Centaur thermal readings
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @th045 893135 thallet 07/26/2013 Updated for new Centaur Procedures
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @rt001 901927 tapiar 10/03/2013 Fix src tags
+ * @gm012 905097 milesg 10/31/2013 Fix Centaur enablement
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gm015 907601 milesg 12/06/2013 L4 Bank Delete circumvention and centaur i2c recovery
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @gm019 910509 milesg 01/10/2014 Memory corruption problem
+ * @gm022 908890 milesg 01/23/2014 Enable centaur deadman timer
+ * @gm023 913865 milesg 01/31/2014 Centaur GPE times out
+ * @gm039 922963 milesg 05/28/2014 Handle centaur nest LFIR 6
+ * @gm041 928150 milesg 06/02/2014 log error in mfg if centaur lfir[6] bit is set
+ * @gm042 917016 milesg 06/04/2014 add delay between centaur i2c recovery operations
+ * @gs038 935559 gjsilva 08/26/2014 Support new RCs from gpe_get_mem_data procedure
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "centaur_data.h"
+#include "centaur_control.h"
+#include "pgp_async.h"
+#include "threadSch.h"
+#include "pmc_register_addresses.h"
+#include "centaur_data_service_codes.h"
+#include "occ_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "apss.h"
+#include "state.h"
+#include "gpe_scom.h"
+#include "centaur_firmware_registers.h"
+#include "centaur_register_addresses.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// Enumerated list of possible centaur operations -- gm039
+typedef enum
+{
+ L4_LINE_DELETE,
+ READ_NEST_LFIR6,
+ READ_THERM_STATUS,
+ RESET_DTS_FSM,
+ DISABLE_SC,
+ CLEAR_NEST_LFIR6,
+ ENABLE_SC,
+ NUM_CENT_OPS
+}cent_ops_enum;
+
+
+#define MBCCFGQ_REG ((uint32_t)0x0201140ful)
+#define LINE_DELETE_ON_NEXT_CE ((uint64_t)0x0080000000000000ull)
+#define SCAC_CONFIG_REG ((uint32_t)0x020115ceul)
+#define SCAC_MASTER_ENABLE ((uint64_t)0x8000000000000000ull)
+#define CENT_NEST_LFIR_REG ((uint32_t)0x0204000aul)
+#define CENT_NEST_LFIR_AND_REG ((uint32_t)0x0204000bul)
+#define CENT_NEST_LFIR6 ((uint64_t)0x0200000000000000ull)
+#define CENT_THRM_CTRL_REG ((uint32_t)0x02050012ul)
+#define CENT_THRM_CTRL4 ((uint64_t)0x0800000000000000ull)
+#define CENT_THRM_STATUS_REG ((uint32_t)0x02050013ul)
+#define CENT_THRM_PARITY_ERROR26 ((uint64_t)0x0000002000000000ull)
+#define CENT_MAX_DEADMAN_TIMER 0xf
+#define CENT_DEADMAN_TIMER_2SEC 0x8
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+//Global array of centaur data buffers
+GPE_BUFFER(MemData G_centaur_data[NUM_CENTAUR_DATA_BUFF +
+ NUM_CENTAUR_DOUBLE_BUF +
+ NUM_CENTAUR_DATA_EMPTY_BUF]);
+
+//pore request for scoming centaur registers
+PoreFlex G_cent_scom_req;
+
+//input/output parameters for gpe_scom_centaur()
+GPE_BUFFER(GpeScomParms G_cent_scom_gpe_parms);
+
+//scom command list entry
+GPE_BUFFER(scomList_t G_cent_scom_list_entry[NUM_CENT_OPS]); //gm039
+
+//buffer for storing output from running gpe_scom_centaur()
+GPE_BUFFER(uint64_t G_cent_scom_data[MAX_NUM_CENTAURS]) = {0};
+
+cent_sensor_flags_t G_cent_enabled_sensors = {0};
+
+//Global array of centaur data pointers
+MemData * G_centaur_data_ptrs[MAX_NUM_CENTAURS] = { &G_centaur_data[0],
+ &G_centaur_data[1], &G_centaur_data[2], &G_centaur_data[3],
+ &G_centaur_data[4], &G_centaur_data[5], &G_centaur_data[6],
+ &G_centaur_data[7]};
+
+//Global structures for gpe get mem data parms
+GPE_BUFFER(GpeGetMemDataParms G_centaur_data_parms);
+
+//Pore flex request for the GPE job that is used for centaur init.
+PoreFlex G_centaur_reg_pore_req;
+
+//Centaur structures used for task data pointers.
+centaur_data_task_t G_centaur_data_task = {
+ .start_centaur = 0,
+ .current_centaur = 0,
+ .end_centaur = 7,
+ .prev_centaur = 7,
+ .centaur_data_ptr = &G_centaur_data[8]
+};
+
+//AMEC needs to know when data for a centaur has been collected.
+uint32_t G_updated_centaur_mask = 0;
+
+//Global G_present_centaurs is bitmask of all centaurs
+//(1 = present, 0 = not present. Core 0 has the most significant bit)
+uint32_t G_present_centaurs = 0;
+
+// Latch for a Trace Entry
+uint8_t G_centaur_queue_not_idle_traced = 0;
+
+// bitmap of centaurs requiring i2c recovery -- gm015
+uint8_t G_centaur_needs_recovery = 0;
+
+// bitmap of centaurs that have NEST LFIR6 asserted...
+// This tells amec code to treat the centaur temperature as invalid
+uint8_t G_centaur_nest_lfir6 = 0; //gm039
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: cent_recovery
+//
+// Description: i2c recovery procedure and other hw workarounds
+//
+// Flow: ??? FN= ???
+//
+// End Function Specification
+
+//number of times in a row we must go without needing i2c recovery
+//before we declare success and allow tracing again
+#define I2C_REC_TRC_THROT_COUNT 8
+
+//threshold of times LFIR6 is asserted (up/down counter) before tracing
+#define NEST_LFIR6_MAX_COUNT 4
+
+//number of SC polls to wait between i2c recovery attempts (see SW248695) -- gm042
+#define CENT_SC_MAX_INTERVAL 32
+
+void cent_recovery(uint32_t i_cent) //gm015
+{
+ int l_rc = 0;
+ errlHndl_t l_err = NULL;
+ uint32_t l_prev_cent = G_cent_scom_list_entry[L4_LINE_DELETE].instanceNumber; //gm039
+ uint8_t l_cent_mask = CENTAUR0_PRESENT_MASK >> l_prev_cent; //gm039
+ static bool L_not_idle_traced = FALSE;
+ static uint8_t L_cent_callouts = 0;
+ static bool L_gpe_scheduled = FALSE;
+ static uint8_t L_i2c_rec_trc_throt = 0;
+ static bool L_gpe_had_1_tick = FALSE;
+ static uint8_t L_nest_lfir6_count[MAX_NUM_CENTAURS] = {0};
+ static uint8_t L_nest_lfir6_traced = 0;
+ static uint8_t L_nest_lfir6_logged = 0; //gm041
+ static uint8_t L_i2c_recovery_delay[MAX_NUM_CENTAURS] = {0}; //gm042
+
+ do
+ {
+ //First, check to see if the previous GPE request is still running.
+ //A request is considered idle if it is not attached to any of the
+ //asynchronous request queues.
+ if( !(async_request_is_idle(&G_cent_scom_req.request)) )
+ {
+ //This can happen due to variability in when the task runs from
+ //one tick to another. Only trace if it has had a full tick.
+ if(!L_not_idle_traced && L_gpe_had_1_tick)
+ {
+ TRAC_INFO("cent_recovery: Centaur recovery GPE is still running. cent[%d], entries[%d], state[0x%08x]",
+ l_prev_cent, //gm039
+ G_cent_scom_gpe_parms.entries,
+ G_cent_scom_req.request.state);
+ L_not_idle_traced = TRUE;
+ }
+ L_gpe_had_1_tick = TRUE;
+ break;
+ }
+ else
+ {
+ //Request is idle
+ L_gpe_had_1_tick = FALSE;
+ //allow the trace again if it's idle
+ if(L_not_idle_traced)
+ {
+ TRAC_INFO("cent_recovery: GPE completed. cent[%d],",
+ l_prev_cent); //gm039
+ L_not_idle_traced = FALSE;
+ }
+ }
+
+ //Request completed
+
+ //Check for failure and log an error if we haven't already logged one for this centaur
+ //but keep retrying.
+ if(L_gpe_scheduled &&
+ (!async_request_completed(&G_cent_scom_req.request) || G_cent_scom_gpe_parms.rc) &&
+ (!(L_cent_callouts & l_cent_mask))) //gm039
+ {
+ //Mark the centaur as being called out
+ L_cent_callouts |= l_cent_mask; //gm039
+
+ // There was an error doing the recovery scoms
+ TRAC_ERR("cent_recovery: gpe_scom_centaur failed. rc[0x%08x] cent[%d] entries[%d] errorIndex[0x%08X]",
+ G_cent_scom_gpe_parms.rc,
+ l_prev_cent, //gm039
+ G_cent_scom_gpe_parms.entries,
+ G_cent_scom_gpe_parms.errorIndex);
+
+ /* @
+ * @errortype
+ * @moduleid CENT_RECOVERY_MOD
+ * @reasoncode CENT_SCOM_ERROR
+ * @userdata1 rc - Return code of failing scom
+ * @userdata2 index of failing scom
+ * @userdata4 0
+ * @devdesc OCC to Centaur communication failure
+ */
+ l_err = createErrl(
+ CENT_RECOVERY_MOD, //modId
+ CENT_SCOM_ERROR, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_cent_scom_gpe_parms.rc, //userdata1
+ G_cent_scom_gpe_parms.errorIndex //userdata2
+ );
+
+ //dump ffdc contents collected by ssx
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &(G_cent_scom_req.ffdc), //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ //callout the centaur
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.centaur_huids[l_prev_cent], //gm039
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ //callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+ commitErrl(&l_err);
+ }
+
+#if 0 //set this to 1 for testing hard failures
+ if(CURRENT_TICK > 120000)
+ {
+ G_cent_scom_list_entry[READ_NEST_LFIR6].data = CENT_NEST_LFIR6;
+ }
+#endif
+
+ // check the centaur nest lfir register for parity errors from thermal (bit 6)
+ // NOTE: recovery will occur 8 ticks from now so that all entries target the
+ // same centaur in a given tick (simplifies callouts) -- gm039
+ if(G_cent_scom_list_entry[READ_NEST_LFIR6].data & CENT_NEST_LFIR6)
+ {
+ //Increment the per-centaur LFIR[6] threshold counter
+ if(L_nest_lfir6_count[l_prev_cent] < NEST_LFIR6_MAX_COUNT)
+ {
+ L_nest_lfir6_count[l_prev_cent]++;
+
+ //log an error the first time we see this. Error will be predictive
+ //if mfg mode ipl and informational otherwise -- gm041
+ if(!(L_nest_lfir6_logged & l_cent_mask))
+ {
+ //only log error once
+ L_nest_lfir6_logged |= l_cent_mask;
+
+ TRAC_ERR("cent_recovery: NEST LFIR[6] was asserted on cent[%d] lfir[%08x%08x], thrm_stat[%08x%08x]",
+ l_prev_cent,
+ (uint32_t)(G_cent_scom_list_entry[READ_NEST_LFIR6].data >> 32),
+ (uint32_t)(G_cent_scom_list_entry[READ_NEST_LFIR6].data),
+ (uint32_t)(G_cent_scom_list_entry[READ_THERM_STATUS].data >> 32),
+ (uint32_t)(G_cent_scom_list_entry[READ_THERM_STATUS].data));
+
+ //only log the error if the thermal parity error is being masked (per Mike Pardeik)
+ if(G_cent_scom_list_entry[READ_THERM_STATUS].data & CENT_THRM_PARITY_ERROR26)
+ {
+ /* @
+ * @errortype
+ * @moduleid CENT_RECOVERY_MOD
+ * @reasoncode CENT_LFIR_ERROR
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Centaur has an unexpected FIR bit set
+ */
+ l_err = createErrl(
+ CENT_RECOVERY_MOD, //modId
+ CENT_LFIR_ERROR, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ //force severity to predictive if mfg ipl (allows callout to be added to info error)
+ setErrlActions(l_err, ERRL_ACTIONS_MANUFACTURING_ERROR);
+
+ //add centaur callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.centaur_huids[l_prev_cent],
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ commitErrl(&l_err);
+ }
+ }
+
+ //Trace if it looks like a hard failure (error will be logged if we time out later)
+ if((L_nest_lfir6_count[l_prev_cent] == NEST_LFIR6_MAX_COUNT) &&
+ !(L_nest_lfir6_traced & l_cent_mask))
+ {
+ //one-time trace of hitting the threshold
+ TRAC_IMP("cent_recovery: NEST LFIR[6] count reached thresh[%d]. cent[%d] scom[%08x%08x]",
+ NEST_LFIR6_MAX_COUNT,
+ l_prev_cent,
+ (uint32_t)(G_cent_scom_list_entry[READ_NEST_LFIR6].data >> 32),
+ (uint32_t)(G_cent_scom_list_entry[READ_NEST_LFIR6].data));
+ L_nest_lfir6_traced |= l_cent_mask;
+ }
+ }
+
+ G_centaur_nest_lfir6 |= l_cent_mask;
+ }
+ else
+ {
+ //decrement the per-centaur LFIR[6] threshold counter
+ if(L_nest_lfir6_count[l_prev_cent] > 0)
+ {
+ L_nest_lfir6_count[l_prev_cent]--;
+ }
+
+ G_centaur_nest_lfir6 &= ~l_cent_mask;
+ }
+
+ //Now we can start working on the next centaur (i_cent) -- gm039
+ l_cent_mask = CENTAUR0_PRESENT_MASK >> i_cent;
+
+ //reset for next pass
+ L_gpe_scheduled = FALSE;
+
+ //check if this centaur requires lfir6 recovery -- gm039
+ if(G_centaur_nest_lfir6 & l_cent_mask)
+ {
+ //Set the command type from GPE_SCOM_NOP to GPE_SCOM_RMW
+ //these entries will reset the centaur DTS FSM and clear LFIR 6
+ //if recovery worked, LFIR 6 should remain cleared.
+ G_cent_scom_list_entry[RESET_DTS_FSM].commandType = GPE_SCOM_WRITE;
+ G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = GPE_SCOM_WRITE;
+ }
+ else
+ {
+ //these ops aren't needed so disable them
+ G_cent_scom_list_entry[RESET_DTS_FSM].commandType = GPE_SCOM_NOP;
+ G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = GPE_SCOM_NOP;
+ }
+
+ //Decrement the delay counter for centaur i2c recovery -- gm042
+ if(L_i2c_recovery_delay[i_cent])
+ {
+ L_i2c_recovery_delay[i_cent]--;
+ }
+ //check if this centaur requires i2c recovery (dimm sensor has error status bit set)
+ if(G_centaur_needs_recovery & l_cent_mask) //gm039
+ {
+ //If the delay time is up, do the i2c recovery -- gm042
+ if(!L_i2c_recovery_delay[i_cent])
+ {
+ if(!L_i2c_rec_trc_throt)
+ {
+ TRAC_INFO("cent_recovery: Performing centaur i2c recovery procedure. required bitmap = 0x%02X", G_centaur_needs_recovery);
+ }
+
+ //restart the recovery delay -- gm042
+ L_i2c_recovery_delay[i_cent] = CENT_SC_MAX_INTERVAL;
+
+ //don't allow tracing for at least I2C_REC_TRC_THROT_COUNT calls to this function
+ //where we didn't require i2c recovery
+ L_i2c_rec_trc_throt = I2C_REC_TRC_THROT_COUNT;
+
+ //clear the request for i2c recovery here
+ G_centaur_needs_recovery &= ~l_cent_mask; //gm039
+
+ //Set the command type from GPE_SCOM_NOP to GPE_SCOM_RMW
+ //these entries will disable and re-enable the centuar sensor cache
+ //which will also cause the i2c master to be reset -- gm039
+ G_cent_scom_list_entry[DISABLE_SC].commandType = GPE_SCOM_RMW;
+ G_cent_scom_list_entry[ENABLE_SC].commandType = GPE_SCOM_RMW;
+ }
+ }
+ else
+ {
+ //Centaur didn't require i2c recovery so decrement the throttle count if
+ //not already 0.
+ if(L_i2c_rec_trc_throt)
+ {
+ L_i2c_rec_trc_throt--;
+
+ //Trace on transition from 1 to 0 only
+ if(!L_i2c_rec_trc_throt)
+ {
+ TRAC_INFO("cent_recovery: Centaur i2c recovered on all present centaurs");
+ }
+ }
+
+ //these ops aren't needed so disable them -- gm039
+ G_cent_scom_list_entry[DISABLE_SC].commandType = GPE_SCOM_NOP;
+ G_cent_scom_list_entry[ENABLE_SC].commandType = GPE_SCOM_NOP;
+ }
+
+ //Set the target centaur for all ops
+ G_cent_scom_list_entry[L4_LINE_DELETE].instanceNumber = i_cent;
+ G_cent_scom_list_entry[READ_NEST_LFIR6].instanceNumber = i_cent;
+ G_cent_scom_list_entry[READ_THERM_STATUS].instanceNumber = i_cent;
+ G_cent_scom_list_entry[RESET_DTS_FSM].instanceNumber = i_cent;
+ G_cent_scom_list_entry[CLEAR_NEST_LFIR6].instanceNumber = i_cent;
+ G_cent_scom_list_entry[DISABLE_SC].instanceNumber = i_cent;
+ G_cent_scom_list_entry[ENABLE_SC].instanceNumber = i_cent;
+
+ // Set up GPE parameters
+ G_cent_scom_gpe_parms.rc = 0;
+ G_cent_scom_gpe_parms.entries = NUM_CENT_OPS; //gm039
+ G_cent_scom_gpe_parms.scomList = (uint32_t) (&G_cent_scom_list_entry[0]);
+ G_cent_scom_gpe_parms.options = 0;
+ G_cent_scom_gpe_parms.errorIndex = 0;
+
+
+ // Submit Pore GPE without blocking
+ l_rc = pore_flex_schedule(&G_cent_scom_req);
+ if(l_rc)
+ {
+ TRAC_ERR("cent_recovery: pore_flex_schedule failed. rc = 0x%08x", l_rc);
+ /* @
+ * @errortype
+ * @moduleid CENT_RECOVERY_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 rc - Return code of failing function
+ * @userdata2 0
+ * @userdata4 0
+ * @devdesc Internal failure (code bug)
+ */
+ l_err = createErrl(
+ CENT_RECOVERY_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ 0 //userdata2
+ );
+
+ REQUEST_RESET(l_err);
+ break;
+ }
+ L_gpe_scheduled = TRUE;
+
+ }while(0);
+}
+
+// Function Specification
+//
+// Name: task_centaur_data
+//
+// Description: Collect centaur data. The task is used for centaur data
+// collection
+//
+// Flow: 03/17/12 FN=task_centaur_data
+//
+// End Function Specification
+void task_centaur_data( task_t * i_task )
+{
+ errlHndl_t l_err = NULL; // Error handler
+ int rc = 0; // Return code
+ MemData * l_temp = NULL;
+ centaur_data_task_t * l_centaur_data_ptr = (centaur_data_task_t *)i_task->data_ptr;
+ GpeGetMemDataParms * l_parms = (GpeGetMemDataParms *)(l_centaur_data_ptr->gpe_req.parameter);
+ static bool L_gpe_scheduled = FALSE;
+ static bool L_gpe_error_logged = FALSE;
+ static bool L_gpe_had_1_tick = FALSE;
+
+ do
+ {
+ // ------------------------------------------
+ // Centaur Data Task Variable Initial State
+ // ------------------------------------------
+ // ->current_centaur: the one that was just 'written' to last tick to
+ // kick off the sensor cache population in the
+ // centaur. It will be 'read from' during this tick.
+ //
+ // ->prev_centaur: the one that was 'read from' during the last tick
+ // and will be used to update the
+ // G_updated_centaur_mask during this tick.
+ //
+ // ->centaur_data_ptr: points to G_centaur_data_ptrs[] for
+ // the centaur that is referenced by prev_centaur
+ // (the one that was just 'read')
+
+ //First, check to see if the previous GPE request still running
+ //A request is considered idle if it is not attached to any of the
+ //asynchronous request queues
+ if( !(async_request_is_idle(&l_centaur_data_ptr->gpe_req.request)) )
+ {
+ //This may happen due to variability in the time that this
+ //task runs. Don't trace on the first occurrence.
+ if( !G_centaur_queue_not_idle_traced && L_gpe_had_1_tick)
+ {
+ TRAC_INFO("task_centaur_data: GPE is still running");
+ G_centaur_queue_not_idle_traced = TRUE;
+ }
+ L_gpe_had_1_tick = TRUE;
+ break;
+ }
+ else
+ {
+ //Request is idle
+ L_gpe_had_1_tick = FALSE;
+ if( G_centaur_queue_not_idle_traced)
+ {
+ TRAC_INFO("task_centaur_data: GPE completed");
+ G_centaur_queue_not_idle_traced = FALSE;
+ }
+ }
+
+ //Need to complete collecting data for all assigned centaurs from
+ //previous interval and tick 0 is the current tick before collect data again.
+ if( (l_centaur_data_ptr->current_centaur == l_centaur_data_ptr->end_centaur)
+ && ((CURRENT_TICK & (MAX_NUM_TICKS - 1)) != 0) )
+ {
+ CENT_DBG("Did not collect centaur data. Need to wait for tick.");
+ break;
+ }
+
+ //Check to see if the previous GPE request has succeeded.
+ //A request is not considered complete until both the engine job
+ //has finshed without error and any callback has run to completion.
+ if(L_gpe_scheduled)
+ {
+ //Per Bishop, If the request is idle but not completed then there was an error
+ //(as long as the request was scheduled).
+ if(!async_request_completed(&l_centaur_data_ptr->gpe_req.request) || l_parms->rc )
+ {
+ //log an error the first time this happens but keep on truckin.
+ //eventually, we will timeout on the dimm & centaur temps not being updated
+ //and fans will go to max speed (probably won't be able to throttle for
+ //same reason we can't access the centaur here).
+ if(!L_gpe_error_logged)
+ {
+ L_gpe_error_logged = TRUE;
+
+ // There was an error collecting the centaur sensor cache
+ TRAC_ERR("task_centaur_data: gpe_get_mem_data failed. rc=0x%08x%08x, cur=%d, prev=%d",
+ (uint32_t)(l_parms->rc >> 32),
+ (uint32_t)(l_parms->rc),
+ l_centaur_data_ptr->current_centaur,
+ l_centaur_data_ptr->prev_centaur);
+ /* @
+ * @errortype
+ * @moduleid CENT_TASK_DATA_MOD
+ * @reasoncode CENT_SCOM_ERROR
+ * @userdata1 l_parms->rc
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to get centaur data
+ */
+ l_err = createErrl(
+ CENT_TASK_DATA_MOD, //modId
+ CENT_SCOM_ERROR, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_parms->rc, //userdata1
+ 0 //userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &(l_centaur_data_ptr->gpe_req.ffdc), //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ //Callouts depend on the return code of the gpe_get_mem_data procedure
+ if(l_parms->rc == GPE_GET_MEM_DATA_DIED)
+ {
+ //callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ }
+ else if(l_parms->rc == GPE_GET_MEM_DATA_SENSOR_CACHE_FAILED)
+ {
+ //callout the previous centaur if present
+ if(CENTAUR_PRESENT(l_centaur_data_ptr->prev_centaur))
+ {
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.centaur_huids[l_centaur_data_ptr->prev_centaur],
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+
+ //callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ }
+ else if(l_parms->rc == GPE_GET_MEM_DATA_UPDATE_FAILED)
+ {
+ //callout the current centaur if present
+ if(CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur))
+ {
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.centaur_huids[l_centaur_data_ptr->current_centaur],
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+
+ //callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ }
+ else
+ {
+ //callout the firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_MED);
+ }
+
+ commitErrl(&l_err);
+ }
+
+ }
+ else
+ {
+ //If the previous GPE request succeeded then swap l_centaur_data_ptr
+ //with the global one. The gpe routine will write new data into
+ //a buffer that is not being accessed by the RTLoop code.
+ l_temp = l_centaur_data_ptr->centaur_data_ptr;
+ l_centaur_data_ptr->centaur_data_ptr =
+ G_centaur_data_ptrs[l_centaur_data_ptr->current_centaur];
+ G_centaur_data_ptrs[l_centaur_data_ptr->prev_centaur] = l_temp; // @th013
+
+ //Centaur data has been collected so set the bit in global mask.
+ //AMEC code will know which centaur to update sensors for. AMEC is
+ //reponsible for clearing the bit later on.
+ // prev centaur is the one that was just 'read from' in the last tick
+ if( CENTAUR_PRESENT(l_centaur_data_ptr->prev_centaur) ) // @th013
+ {
+ G_updated_centaur_mask |= CENTAUR_BY_MASK(l_centaur_data_ptr->prev_centaur);
+ }
+ }
+ }//if(L_gpe_scheduled)
+
+ // If the centaur is not present, then we need to point to the empty G_centaur_data
+ // so that we don't use old/stale data from a leftover G_centaur_data
+ // (this is very handy for debug...)
+ if( !CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur))
+ {
+ G_centaur_data_ptrs[l_centaur_data_ptr->current_centaur] = &G_centaur_data[9];
+ }
+
+ //Update current centaur
+ if ( l_centaur_data_ptr->current_centaur >= l_centaur_data_ptr->end_centaur )
+ {
+ l_centaur_data_ptr->prev_centaur = l_centaur_data_ptr->current_centaur; // @th013
+ l_centaur_data_ptr->current_centaur = l_centaur_data_ptr->start_centaur;
+ }
+ else
+ {
+ l_centaur_data_ptr->prev_centaur = l_centaur_data_ptr->current_centaur; // @th013
+ l_centaur_data_ptr->current_centaur++;
+ }
+
+ // ------------------------------------------
+ // Centaur Data Task Variable State Changed
+ // ------------------------------------------
+ // ->current_centaur: the one that will be 'written' to in order to
+ // kick off the sensor cache population in the
+ // centaur.
+ //
+ // ->prev_centaur: the one that will be 'read from', meaning have
+ // the sensor cache transferred from the Centaur
+ // to l_centaur_data_ptr->centaur_data_ptr
+ //
+ // ->centaur_data_ptr: points to G_centaur_data_ptrs[] for
+ // the centaur that is referenced by prev_centaur
+ // (the one that will be 'read')
+
+ //If centaur is not present then skip it. This task assigned to this centaur will
+ //be idle during this time it would have collected the data.
+ if( CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur)
+ || CENTAUR_PRESENT(l_centaur_data_ptr->prev_centaur) ) // @th013
+ {
+ // Setup the 'get centaur data' parms
+ // ->config controls which Centaur we are reading from
+ if( CENTAUR_PRESENT(l_centaur_data_ptr->prev_centaur) ){ // @th013
+ // If prev centaur is present, do the read of the sensor cache
+ l_parms->collect = l_centaur_data_ptr->prev_centaur;
+ }
+ else{
+ // If prev centaur is not present, don't do the read of the sensor cache.
+ l_parms->collect = -1;
+ }
+
+ // ->config_update controls which Centaur we are writing to
+ if( CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur) ){ // @th013
+ // If cur centaur is present, do the write to kick off the sensor cache collect
+ l_parms->update = l_centaur_data_ptr->current_centaur;
+ }
+ else{
+ // If cur centaur is not present, don't do the write to kick off the sensor cache collect
+ l_parms->update = -1;
+ }
+
+ l_parms->data = (uint32_t) l_centaur_data_ptr->centaur_data_ptr;
+ l_parms->rc = 0;
+
+ // Pore flex schedule gpe_get_mem_data
+ // Check pore_flex_schedule return code if error
+ // then request OCC reset.
+ rc = pore_flex_schedule( &(l_centaur_data_ptr->gpe_req) );
+ if(rc)
+ {
+ TRAC_ERR("task_centaur_data: pore_flex_schedule failed for centaur data collection. rc=%d", rc);
+ /* @
+ * @errortype
+ * @moduleid CENT_TASK_DATA_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 rc - Return code of failing function
+ * @userdata2 0
+ * @userdata4 ERC_CENTAUR_PORE_FLEX_SCHEDULE_FAILURE
+ * @devdesc Failed to get centaur data
+ */
+ l_err = createErrl(
+ CENT_TASK_DATA_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ ERC_CENTAUR_PORE_FLEX_SCHEDULE_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ l_parms->rc //userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &(l_centaur_data_ptr->gpe_req.ffdc), //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ REQUEST_RESET(l_err); //this will add firmware callout
+ break;
+ }
+
+ L_gpe_scheduled = TRUE;
+ }
+
+ } while(0);
+
+ //handle centaur i2c recovery requests and centaur workaround -- gm015
+ if(CENTAUR_PRESENT(l_centaur_data_ptr->current_centaur))
+ {
+ cent_recovery(l_centaur_data_ptr->current_centaur);
+ }
+ return;
+}
+
+#define CENTAUR_SENSCACHE_ENABLE 0x020115CC
+// Function Specification
+//
+// Name: cent_get_enabled_sensors
+//
+// Description: Reads
+//
+// Flow: ??? FN= ???
+//
+// End Function Specification
+int cent_get_enabled_sensors()
+{
+ int l_rc = 0;
+ unsigned int l_cent;
+
+ do
+ {
+ // Set up scom list entry (there's only 1)
+ G_cent_scom_list_entry[0].scom = CENTAUR_SENSCACHE_ENABLE; //scom address
+ G_cent_scom_list_entry[0].commandType = GPE_SCOM_READ_VECTOR; //scom operation to perform
+ G_cent_scom_list_entry[0].instanceNumber = 0; //Ignored for READ_VECTOR operation
+ G_cent_scom_list_entry[0].pData = (uint64_t *) G_cent_scom_data; //scom data will be stored here
+
+ // Set up GPE parameters
+ G_cent_scom_gpe_parms.rc = 0;
+ G_cent_scom_gpe_parms.entries = 1;
+ G_cent_scom_gpe_parms.scomList = (uint32_t) (&G_cent_scom_list_entry[0]);
+ G_cent_scom_gpe_parms.options = 0;
+ G_cent_scom_gpe_parms.errorIndex = 0;
+
+ //Initializes PoreFlex
+ l_rc = pore_flex_create( &G_cent_scom_req, // gpe_req for the task
+ &G_pore_gpe1_queue, // queue
+ gpe_scom_centaur, // entry point
+ (uint32_t) &G_cent_scom_gpe_parms, // parm for the task
+ SSX_SECONDS(2), // timeout
+ NULL, // callback
+ NULL, // callback argument
+ ASYNC_REQUEST_BLOCKING ); // options
+ if(l_rc)
+ {
+ TRAC_ERR("cent_get_enabled_sensors: pore_flex_create failed. rc = 0x%08x", l_rc);
+ break;
+ }
+
+ // Submit Pore GPE and wait for completion
+ l_rc = pore_flex_schedule(&G_cent_scom_req);
+ if(l_rc)
+ {
+ TRAC_ERR("cent_get_enabled_sensors: pore_flex_schedule failed. rc = 0x%08x", l_rc);
+ break;
+ }
+
+ //consolidate scom data into a smaller, cacheable 8 byte buffer
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+ G_cent_enabled_sensors.bytes[l_cent] = ((uint8_t*)(&G_cent_scom_data[l_cent]))[0];
+ }
+
+ TRAC_IMP("bitmap of enabled dimm temperature sensors: 0x%08X %08X",
+ G_cent_enabled_sensors.words[0],
+ G_cent_enabled_sensors.words[1]);
+ }while(0);
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: centaur_init
+//
+// Description: Initialize procedures for collecting centaur data. It
+// needs to be run in occ main and before RTLoop started.
+// This will also initialize the centaur watchdog.
+//
+// Flow: 03/17/12 FN=centaur_init
+//
+// End Function Specification
+void centaur_init( void )
+{
+ errlHndl_t l_err = NULL; // Error handler
+ int rc = 0; // Return code
+ int l_jj = 0; // Indexer
+ static scomList_t L_scomList[2] SECTION_ATTRIBUTE(".noncacheable");
+ static GpeScomParms L_centaur_reg_parms SECTION_ATTRIBUTE(".noncacheable");
+
+ do
+ {
+ /// Initialize Centaur & Centaur Data Structures
+ /// This needs to run before RTLoop starts as init needs to be
+ /// done before task to collect centaur data starts.
+
+ TRAC_INFO("centaur_init: Initializing Centaur ... " );
+
+ /// Before anything else, we need to call this procedure to
+ /// determine which Centaurs are out there, their config info.
+ /// and Type/EC Level
+
+ rc = centaur_configuration_create();
+ if( rc )
+ {
+ TRAC_ERR("centaur_init: Centaur Config Create failed with rc=0x%08x ", rc );
+ break;
+ }
+
+ /// Set up Centaurs present global variable for use by OCC
+ /// looping though the bitmask.
+
+ G_present_centaurs = 0;
+ for(l_jj=0; l_jj<MAX_NUM_CENTAURS; l_jj++)
+ {
+ // Check if this centaur is even possible to be present
+ // by ANDing it against ALL_CENTAURS_MASK in this macro
+
+ if( CENTAUR_BY_MASK(l_jj) ) // @th016
+ {
+ if( G_centaurConfiguration.baseAddress[l_jj] )
+ {
+ // G_cent_ba is != 0, so a valid Bar Address was found
+ // This means there is a VALID centaur there.
+ G_present_centaurs |= (CENTAUR0_PRESENT_MASK >> l_jj);
+
+ // Trace out the CFAM Chip ID, which includes Type & EC
+ TRAC_INFO("centaur_init: Centaur[%d] Found, Chip Id=0x%08x",l_jj, mb_id(l_jj));
+ }
+ }
+ }
+
+ TRAC_IMP("centaur_init: G_present_centaurs = 0x%08x", G_present_centaurs);
+
+ //initialize global bitmap of enabled centaur temperature sensors (for dimms)
+ rc = cent_get_enabled_sensors();
+
+ // Set up recovery scom list entries
+ G_cent_scom_list_entry[L4_LINE_DELETE].scom = MBCCFGQ_REG; //scom address
+ G_cent_scom_list_entry[L4_LINE_DELETE].commandType = GPE_SCOM_RMW; //scom operation to perform
+ G_cent_scom_list_entry[L4_LINE_DELETE].mask = LINE_DELETE_ON_NEXT_CE; //mask of bits to chagne
+ G_cent_scom_list_entry[L4_LINE_DELETE].data = LINE_DELETE_ON_NEXT_CE; //scom data (always set the bit)
+
+ //one time init for reading LFIR6 -- gm039
+ G_cent_scom_list_entry[READ_NEST_LFIR6].scom = CENT_NEST_LFIR_REG; //scom address
+ G_cent_scom_list_entry[READ_NEST_LFIR6].commandType = GPE_SCOM_READ; //scom operation to perform
+ G_cent_scom_list_entry[READ_NEST_LFIR6].mask = 0; //mask (not used for reads)
+ G_cent_scom_list_entry[READ_NEST_LFIR6].data = 0; //scom data (initialize to 0)
+
+ //one time init for reading centaur thermal status register -- gm041
+ G_cent_scom_list_entry[READ_THERM_STATUS].scom = CENT_THRM_STATUS_REG; //scom address
+ G_cent_scom_list_entry[READ_THERM_STATUS].commandType = GPE_SCOM_READ; //scom operation to perform
+ G_cent_scom_list_entry[READ_THERM_STATUS].mask = 0; //mask (not used for reads)
+ G_cent_scom_list_entry[READ_THERM_STATUS].data = 0; //scom data (initialize to 0)
+
+ //one time init to reset the centaur dts FSM -- gm039
+ G_cent_scom_list_entry[RESET_DTS_FSM].scom = CENT_THRM_CTRL_REG; //scom address
+ G_cent_scom_list_entry[RESET_DTS_FSM].commandType = GPE_SCOM_NOP; //init to no-op (only runs if needed)
+ G_cent_scom_list_entry[RESET_DTS_FSM].mask = 0; //mask (not used for writes)
+ G_cent_scom_list_entry[RESET_DTS_FSM].data = CENT_THRM_CTRL4; //scom data (sets bit4)
+
+ //one time init to clear centaur NEST LFIR 6 -- gm039
+ G_cent_scom_list_entry[CLEAR_NEST_LFIR6].scom = CENT_NEST_LFIR_AND_REG; //scom address
+ G_cent_scom_list_entry[CLEAR_NEST_LFIR6].commandType = GPE_SCOM_NOP; //init to no-op (only runs if needed)
+ G_cent_scom_list_entry[CLEAR_NEST_LFIR6].mask = 0; //mask (not used for writes)
+ G_cent_scom_list_entry[CLEAR_NEST_LFIR6].data = ~CENT_NEST_LFIR6; //scom data
+
+ //one time init to disable centaur sensor cache
+ G_cent_scom_list_entry[DISABLE_SC].scom = SCAC_CONFIG_REG; //scom address
+ G_cent_scom_list_entry[DISABLE_SC].commandType = GPE_SCOM_NOP; //init to no-op (only runs if needed)
+ G_cent_scom_list_entry[DISABLE_SC].mask = SCAC_MASTER_ENABLE; //mask of bits to chagne
+ G_cent_scom_list_entry[DISABLE_SC].data = 0; //scom data (disable sensor cache)
+
+ //one time init to enable centaur sensor cache
+ G_cent_scom_list_entry[ENABLE_SC].scom = SCAC_CONFIG_REG; //scom address
+ G_cent_scom_list_entry[ENABLE_SC].commandType = GPE_SCOM_NOP; //init to no-op (only runs if needed)
+ G_cent_scom_list_entry[ENABLE_SC].mask = SCAC_MASTER_ENABLE; //mask of bits to chagne
+ G_cent_scom_list_entry[ENABLE_SC].data = SCAC_MASTER_ENABLE; //scom data (enable sensor cache)
+
+
+
+ /// Set up Centuar Scom Registers - array of Scoms
+ /// [0]: Setup deadman timer
+ /// NOTE: According to Irving Baysah, centaur spec is incorrect by a factor of 16.
+ /// max timeout is about 2 seconds.
+
+ L_scomList[0].scom = CENTAUR_MBSCFGQ;
+ L_scomList[0].commandType = GPE_SCOM_RMW_ALL;
+
+ centaur_mbscfgq_t l_mbscfg;
+ l_mbscfg.value = 0;
+
+ //set up the mask bits
+ l_mbscfg.fields.occ_deadman_timer_sel = CENT_MAX_DEADMAN_TIMER;
+ L_scomList[0].mask = l_mbscfg.value;
+
+ //set up the data bits
+ l_mbscfg.fields.occ_deadman_timer_sel = CENT_DEADMAN_TIMER_2SEC;
+ L_scomList[0].data = l_mbscfg.value;
+
+ /// Set up Centuar Scom Registers - array of Scoms
+ /// [1]: clear the emergency throttle bit
+
+ L_scomList[1].scom = CENTAUR_MBSEMERTHROQ;
+ L_scomList[1].commandType = GPE_SCOM_RMW_ALL;
+
+ centaur_mbsemerthroq_t l_mbs_et;
+ l_mbs_et.value = 0;
+
+ //set up the data
+ L_scomList[1].data = l_mbs_et.value;
+
+ //set up the mask
+ l_mbs_et.fields.emergency_throttle_ip = 1;
+ L_scomList[1].mask = l_mbs_et.value;
+
+ L_centaur_reg_parms.scomList = (uint32_t) (&L_scomList[0]);
+ L_centaur_reg_parms.entries = 2;
+ L_centaur_reg_parms.options = 0;
+ L_centaur_reg_parms.rc = 0;
+ L_centaur_reg_parms.errorIndex = 0;
+
+ //Initialize PoreFlex
+ rc = pore_flex_create( &G_centaur_reg_pore_req, //gpe_req for the task
+ &G_pore_gpe1_queue, //queue
+ gpe_scom_centaur, //entry point
+ (uint32_t) &L_centaur_reg_parms, //parm for the task
+ SSX_SECONDS(5), //no timeout
+ NULL, //callback
+ NULL, //callback argument
+ ASYNC_REQUEST_BLOCKING ); //options
+ if(rc)
+ {
+ TRAC_ERR("centaur_init: pore_flex_create failed for G_centaur_reg_pore_req. rc = 0x%08x", rc);
+ break;
+ }
+
+ // Submit Pore GPE and wait for completion
+ rc = pore_flex_schedule(&G_centaur_reg_pore_req);
+
+ // Check for errors on Scom
+ if(rc || L_centaur_reg_parms.rc)
+ {
+ TRAC_ERR("centaur_init: gpe_scom_centaur failure. rc = 0x%08x, gpe_rc = 0x%08x, index = 0x%08x",
+ rc,
+ L_centaur_reg_parms.rc,
+ L_centaur_reg_parms.errorIndex);
+ if(!rc)
+ {
+ rc = L_centaur_reg_parms.rc;
+ }
+ break;
+ }
+
+ /// Set up the OCC Centuar Data Collection Procedure
+ /// Includes initializing the centaur procedure parameters
+ /// to gather the 'centaur' data, but we will set them to
+ /// invalid (-1) util the task sets them up
+
+ G_centaur_data_parms.rc = 0;
+ G_centaur_data_parms.collect = -1;
+ G_centaur_data_parms.update = -1;
+ G_centaur_data_parms.data = 0;
+
+ //Initializes existing PoreFlex object for centaur data
+ rc = pore_flex_create( &G_centaur_data_task.gpe_req, //gpe_req for the task
+ &G_pore_gpe1_queue, //queue
+ gpe_get_mem_data, //entry point
+ (uint32_t) &G_centaur_data_parms, //parm for the task
+ SSX_WAIT_FOREVER, //gm023
+ NULL, //callback
+ NULL, //callback argument
+ 0 ); //options
+
+ if(rc)
+ {
+ TRAC_ERR("centaur_init: pore_flex_create failed for G_centaur_data_task.gpe_req. rc = 0x%08x", rc);
+ break;
+ }
+
+ //Initialize existing PoreFlex object for centaur recovery
+ rc = pore_flex_create( &G_cent_scom_req, // gpe_req for the task
+ &G_pore_gpe1_queue, // queue
+ gpe_scom_centaur, // entry point
+ (uint32_t) &G_cent_scom_gpe_parms, // parm for the task
+ SSX_WAIT_FOREVER, // gm023
+ NULL, // callback
+ NULL, // callback argument
+ 0); // options
+ if(rc)
+ {
+ TRAC_ERR("centaur_init: pore_flex_create failed for G_cent_scom_req. rc = 0x%08x", rc);
+ break;
+ }
+
+ /// Initialization complete, Centaur Control & Data Collection
+ /// Tasks can now run
+
+ } while(0);
+
+ if( rc )
+ {
+
+ /* @
+ * @errortype
+ * @moduleid CENTAUR_INIT_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 rc - Return code of failing function
+ * @userdata2 Return code of failing GPE
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to initialize Centaurs
+ */
+ l_err = createErrl(
+ CENTAUR_INIT_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ L_centaur_reg_parms.rc //userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &G_centaur_reg_pore_req.ffdc, //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ REQUEST_RESET(l_err);
+ }
+ else
+ {
+ // Only initalize the control structures if we haven't had
+ // any errors yet
+ centaur_control_init();
+ }
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: cent_get_centaur_data_ptr
+//
+// Description: Returns a pointer to the most up-to-date centaur data for
+// the centaur associated with the specified OCC centaur id.
+// Returns NULL for centaur ID outside the range of 0 to 7.
+//
+// Flow: FN=None
+//
+// End Function Specification
+MemData * cent_get_centaur_data_ptr( const uint8_t i_occ_centaur_id )
+{
+ //The caller needs to send in a valid OCC centaur id. Since type is uchar
+ //so there is no need to check for case less than 0.
+ //If centaur id is invalid then returns NULL.
+ if( i_occ_centaur_id < MAX_NUM_CENTAURS )
+ {
+ //Returns a pointer to the most up-to-date centaur data.
+ return G_centaur_data_ptrs[i_occ_centaur_id];
+ }
+ else
+ {
+ //Core id outside the range
+ TRAC_ERR("cent_get_centaur_data_ptr: Invalid OCC centaur id [0x%x]", i_occ_centaur_id);
+ return( NULL );
+ }
+}
+
diff --git a/src/occ/cent/centaur_data.h b/src/occ/cent/centaur_data.h
new file mode 100755
index 0000000..8715940
--- /dev/null
+++ b/src/occ/cent/centaur_data.h
@@ -0,0 +1,180 @@
+/******************************************************************************
+// @file centaur_data.h
+// @brief Centaur external functions & data.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _centaur_data_h centaur_data.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th00c thallet 03/14/2012 Created
+ * @th013 thallet 07/17/2012 SW150201: OCC VPO: inbound scom
+ * @th016 thallet 08/13/2012 Only 4 Centaurs possible on Murano
+ * @th018 852950 thallet 09/12/2012 Added Centaur thermal readings
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @th032 thallet 04/26/2013 Centaur Bringup Changes
+ * @th045 893135 thallet 07/26/2013 Updated for new Centaur Procedures
+ * @gm004 892961 milesg 07/25/2013 Removed centaur_init from init section
+ * @gm012 905097 milesg 10/31/2013 Fix Centaur enablement
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gm015 907601 milesg 12/06/2013 L4 Bank Delete circumvention and centaur i2c recovery
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _CENTAUR_DATA_H
+#define _CENTAUR_DATA_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <ssx.h>
+#include "rtls.h"
+#include "gpe_data.h"
+#include "occ_sys_config.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// Mask that is used by procedure to specify which centaurs are present
+#define ALL_CENTAURS_MASK 0x000000ff // @th016
+#define ALL_CENTAURS_MASK_GPE 0x000000ff00000000ull // @th016
+// Centaur0, used by OCC
+#define CENTAUR0_PRESENT_MASK 0x00000080ul
+#define CENTAUR0_PRESENT_MASK_GPE 0x0000008000000000ull
+
+// Used for specifing buffer allocations
+#define NUM_CENTAUR_DATA_BUFF MAX_NUM_CENTAURS
+#define NUM_CENTAUR_DOUBLE_BUF 1
+#define NUM_CENTAUR_DATA_EMPTY_BUF 1
+
+// Specify a command BAR addresses for all centaur operations
+#define CENTAUR_MEM_DATA_BAR MEM_DATA_BAR_SELECT_1 // @th032
+
+// Enum for specifying each Centaur
+enum eOccCentaurs
+{
+ CENTAUR_0 = 0,
+ CENTAUR_1 = 1,
+ CENTAUR_2 = 2,
+ CENTAUR_3 = 3,
+ CENTAUR_4 = 4,
+ CENTAUR_5 = 5,
+ CENTAUR_6 = 6,
+ CENTAUR_7 = 7,
+};
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+//Returns 0 if the specified centaur is not present. Otherwise, returns none-zero.
+#define CENTAUR_PRESENT(occ_cent_id) \
+ ((CENTAUR0_PRESENT_MASK >> occ_cent_id) & G_present_centaurs)
+
+//Returns 0 if the specified centaur is not updated. Otherwise, returns none-zero.
+#define CENTAUR_UPDATED(occ_cent_id) \
+ ((CENTAUR0_PRESENT_MASK >> occ_cent_id) & G_updated_centaur_mask)
+
+//Returns 0 if the specified centaur is not updated. Otherwise, returns none-zero.
+#define CLEAR_CENTAUR_UPDATED(occ_cent_id) \
+ G_updated_centaur_mask &= ~(CENTAUR0_PRESENT_MASK >> occ_cent_id)
+
+//Returns the bitmask for the passed in Centaur (uint32_t)
+#define CENTAUR_BY_MASK(occ_cent_id) \
+ ((CENTAUR0_PRESENT_MASK >> occ_cent_id) & ALL_CENTAURS_MASK)
+
+//Returns the bitmask for the passed in Centaur (uint64_t)
+#define CENTAUR_BY_MASK_GPE(occ_cent_id) \
+ (((uint64_t) CENTAUR0_PRESENT_MASK_GPE >> occ_cent_id) & ALL_CENTAURS_MASK_GPE)
+
+#define DIMM_SENSOR0 0x80
+
+#define CENTAUR_SENSOR_ENABLED(occ_cent_id, sensor_num) \
+ (G_cent_enabled_sensors.bytes[occ_cent_id] & (DIMM_SENSOR0 >> (sensor_num)))
+
+#define MBA_CONFIGURED(occ_cent_id, mba_num) \
+ (G_configured_mbas & (1 << ((occ_cent_id * 2) + mba_num)))
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//Centaur data collect structures used for task data pointers
+struct centaur_data_task {
+ uint8_t start_centaur;
+ uint8_t current_centaur;
+ uint8_t end_centaur;
+ uint8_t prev_centaur; // @th013
+ MemData * centaur_data_ptr;
+ PoreFlex gpe_req;
+} __attribute__ ((__packed__));
+typedef struct centaur_data_task centaur_data_task_t;
+
+typedef union
+{
+ uint64_t bigword;
+ uint32_t words[2];
+ uint8_t bytes[8];
+}cent_sensor_flags_t;
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//Global centaur structures used for task data pointers
+extern centaur_data_task_t G_centaur_data_task;
+
+//Global is bitmask of centaurs
+extern uint32_t G_present_centaurs;
+
+//AMEC needs to know when data for a centaur has been collected.
+extern uint32_t G_updated_centaur_mask;
+
+//global bitmap of enabled dimm sensors
+extern cent_sensor_flags_t G_cent_enabled_sensors;
+
+//global bitmap of dimms that have ever gone over the error temperature
+extern cent_sensor_flags_t G_dimm_overtemp_bitmap;
+
+//global bitmap of dimms temps that have been updated
+extern cent_sensor_flags_t G_dimm_temp_updated_bitmap;
+
+//global bitmap of centaurs that have ever gone over the error temperature
+extern uint8_t G_cent_overtemp_bitmap;
+
+//global bitmap of centaur temperatures that have been updated
+extern uint8_t G_cent_temp_updated_bitmap;
+
+//bitmap of configured MBA's (2 per centaur, lsb is centaur0/mba0)
+extern uint16_t G_configured_mbas;
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//Collect centaur data for all centaur in specified range
+void task_centaur_data( task_t * i_task );
+
+//Initialize structures for collecting centaur data.
+//void centaur_init( void ) INIT_SECTION;
+void centaur_init( void ); //gm004
+
+//handles centaur i2c recovery and other workarounds
+void cent_recovery(uint32_t i_cent);
+
+//Returns a pointer to the most up-to-date centaur data for the centaur
+//associated with the specified OCC centaur id.
+MemData * cent_get_centaur_data_ptr( const uint8_t i_centaur_id );
+
+#endif //_CENTAUR_DATA_H
+
diff --git a/src/occ/cent/centaur_data_service_codes.h b/src/occ/cent/centaur_data_service_codes.h
new file mode 100755
index 0000000..2634efb
--- /dev/null
+++ b/src/occ/cent/centaur_data_service_codes.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+// @file centaur_data_service_codes.h
+// @brief Error codes for cent component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _centaur_data_service_codes_h centaur_data_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th00c thallet 03/14/2012 Created
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @gm015 907601 milesg 12/06/2013 L4 Bank Delete circumvention and centaur i2c recovery
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _CENTAUR_DATA_SERVICE_CODES_H_
+#define _CENTAUR_DATA_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum centModuleId
+{
+ CENT_TASK_DATA_MOD = CENT_COMP_ID | 0x00,
+ CENTAUR_INIT_MOD = CENT_COMP_ID | 0x01,
+ CENT_TASK_CONTROL_MOD = CENT_COMP_ID | 0x02,
+ CENT_RECOVERY_MOD = CENT_COMP_ID | 0x03,
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _CENTAUR_DATA_SERVICE_CODES_H_ */
diff --git a/src/occ/cfiles.mk b/src/occ/cfiles.mk
new file mode 100755
index 0000000..e1935a8
--- /dev/null
+++ b/src/occ/cfiles.mk
@@ -0,0 +1,107 @@
+# @file cfiles.mk
+#
+# @brief mk for c-object files for occ application
+#
+# @page ChangeLogs Change Logs
+# @section cfiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/11/2012 Makefile ODE support
+# @th00c thallet 04/23/2012 Centaur files
+# @th022 thallet 10/04/2012 Dcom & CnfgData additions
+# @at009 859308 alvinwan 10/15/2012 Added tracepp support
+# @ry002 862116 ronda 11/26/2012 Support thermal controller for processor
+# @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+# @gs004 883829 gjsilva 05/21/2013 Support for manufacturing commands
+# @fk001 879727 fmkassem 04/16/2013 OCC powercap support.
+# @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+# @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+# @gs012 903325 gjsilva 09/26/2013 Add health monitor files
+# @gs014 903552 gjsilva 10/22/2013 Support for Amester parameter interface
+# 905504 sbroyles 11/06/2013 Added homer.c
+# @rt004 905638 tapiar 11/13/2013 Support for Tunable Parameters
+# @gs019 908218 gjsilva 12/04/2013 Support cooling request architecture
+# @fk004 907588 fmkassem 11/25/2013 Add support for snapshot buffer.
+# 916980 sbroyles 03/10/2014 Added ffdc.c
+# @gs027 918066 gjsilva 03/12/2014 Added amec_analytics.c
+# @gm033 920448 milesg 03/26/2014 added scom.c
+# @endverbatim
+#
+
+##########################################################################
+# Object files
+##########################################################################
+
+occ_CFILES = \
+ amec/amec_init.c \
+ amec/amec_tasks.c \
+ amec/amec_slave_smh.c \
+ amec/amec_master_smh.c \
+ amec/amec_sensors_core.c \
+ amec/amec_sensors_centaur.c \
+ amec/amec_sensors_power.c \
+ amec/amec_sensors_fw.c \
+ amec/amec_data.c \
+ amec/amec_freq.c \
+ amec/amec_amester.c \
+ amec/amec_dps.c \
+ amec/amec_part.c \
+ amec/amec_perfcount.c \
+ amec/amec_controller.c \
+ amec/amec_oversub.c \
+ amec/amec_pcap.c \
+ amec/amec_health.c \
+ amec/amec_parm.c \
+ amec/amec_parm_table.c \
+ amec/amec_analytics.c \
+ aplt/appletManager.c \
+ cent/centaur_data.c \
+ cent/centaur_control.c \
+ cmdh/cmdh_fsp.c \
+ cmdh/cmdh_thread.c \
+ cmdh/cmdh_fsp_cmds.c \
+ cmdh/cmdh_fsp_cmds_datacnfg.c \
+ cmdh/cmdh_mnfg_intf.c \
+ cmdh/cmdh_tunable_parms.c \
+ cmdh/cmdh_snapshot.c \
+ cmdh/ffdc.c \
+ dcom/dcom.c \
+ dcom/dcom_thread.c \
+ dcom/dcomSlaveTx.c \
+ dcom/dcomSlaveRx.c \
+ dcom/dcomMasterTx.c \
+ dcom/dcomMasterRx.c \
+ errl/errl.c \
+ proc/proc_data.c \
+ proc/proc_data_control.c \
+ proc/proc_pstate.c \
+ pss/apss.c \
+ pss/dpss.c \
+ rtls/rtls_tables.c \
+ rtls/rtls.c \
+ sensor/sensor.c \
+ sensor/sensor_table.c \
+ thread/threadSch.c \
+ thread/chom.c \
+ thread/thrm_thread.c \
+ timer/timer.c \
+ trac/trac_interface.c \
+ occ_sys_config.c \
+ arl_test.c \
+ state.c \
+ reset.c \
+ mode.c \
+ main.c \
+ scom.c \
+ homer.c \
+ occbuildname.c \
+
+occ_SFILES = cmdh/ll_ffdc.S
+
+occ_cfiles = ${occ_CFILES:.c=.o}
+occ_Sfiles = ${occ_SFILES:.S=.o}
+
diff --git a/src/occ/cmdh/cmdh_fsp.c b/src/occ/cmdh/cmdh_fsp.c
new file mode 100755
index 0000000..908cb27
--- /dev/null
+++ b/src/occ/cmdh/cmdh_fsp.c
@@ -0,0 +1,1421 @@
+/******************************************************************************
+// @file cmdh_fsp.c
+// @brief Command Handling for FSP Communication.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_fsp_c cmdh_fsp.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 04/05/2012 Created
+ * @th013 thallet 07/24/2012 Minor changes for VPO/HW compile
+ * @at008 alvinwan 08/09/2012 Support AME Pass Thru command from TMGT
+ * @th022 thallet 10/08/2012 Moved data commands to separate file
+ * @nh004 864941 neilhsu 12/20/2012 Support get/delete errl & added trace info
+ * @th033 878894 thallet 04/17/2013 Mnfg AVP Support
+ * @th036 881677 thallet 05/06/2013 New TMGT Poll Command Support
+ * @gs004 883829 gjsilva 05/21/2013 Support for manufacturing commands
+ * @th037 thallet 05/28/2013 Do PCONLY Special Wakeup before accessing SCRATCH7
+ * @th038 thallet 06/03/2013 Disable Centaur since it isn't ready on HW yet
+ * @th039 887066 thallet 06/11/2013 Fix the way that command handler attentions work
+ * @jh002 887903 joshych 06/17/2013 Support Get Field Debug Data command
+ * @th042 892056 thallet 07/19/2013 Send OCC to safe mode if first APSS GPE fails
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+ * @rt001 901927 tapiar 10/03/2013 Fix src tags
+ * @rt004 905638 tapiar 11/13/2013 Support for Tunable Parameters
+ * @gs019 908218 gjsilva 12/04/2013 Support cooling request architecture
+ * @fk004 907588 fmkassem 11/22/2013 OCC snapshot support.
+ * @sb012 910394 sbroyles 01/10/2014 More FFDC updates
+ * @gm020 912611 milesg 01/21/2014 Add special wakeup for scom'ing core chiplets
+ * @sbscr 919662 sbroyles 03/17/2014 Change SCR7 to SCR3
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @gm033 920448 milesg 03/26/2014 use getscom/putscom ffdc wrapper
+ * @gs041 942203 gjsilva 10/17/2014 Support for HTMGT/BMC interface
+ * @gs042 942940 gjsilva 10/24/2014 Support for data packets in BMC-based systems
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "special_wakeup.h"
+#include "cmdh_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "dcom.h"
+#include "occ_common.h"
+#include "state.h"
+#include "cmdh_fsp.h"
+#include "cmdh_fsp_cmds.h"
+#include "cmdh_mnfg_intf.h"
+#include "cmdh_tunable_parms.h" //@rt004a
+#include "cmdh_snapshot.h" //@fk004a
+#include "scom.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// OCB Channel Setup Defines
+const int OCB_CHANNEL_FSP_LINEAR = 0;
+const int OCB_CHANNEL_FSP_DOORBELL = 1;
+const int ALLOW_UNTRUSTED_ACCESS = 1;
+
+
+// Do not change this without changing size of FSP Command Buffer
+// (and vice versa). The Linear window requires an alignment on
+// a power of 2 boundry, and linear window registers require this
+// to be expressed as a Log
+const int LOG_SIZEOF_FSP_CMD_BUFFER = 12; // 4096 = 2**12
+
+// Given to OCC from HWSV team, sent in FSI2Host Mailbox1 Message
+const uint32_t OCC_MSG_QUEUE_ID = 0x80000007;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// The OCB Device Driver request that OCC uses to receive a doorbell from
+// FSP
+OcbRequest G_fsp_doorbell_ocb_request;
+
+// Semaphore used to alert CMDH thread that a message was received from TMGT
+SsxSemaphore G_cmdh_fsp_wakeup_thread;
+
+// Buffers for the command being sent between FSP & OCC. This needs to be in
+// noncacheable space, or needs cache invalidate/flush to be run appropriately
+// This also needs to have the alignment sync'd up with the size of FSP
+// Command Buffer, and LOG_SIZEOF_FSP_CMD_BUFFER
+LINEAR_WINDOW_WR_BUFFER(fsp_cmd_t G_fsp_cmd);
+LINEAR_WINDOW_RD_BUFFER(fsp_rsp_t G_fsp_rsp);
+
+// This holds the pointers to the command & response buffers, and to the
+// doorbell placeholder data.
+fsp_msg_t G_fsp_msg = {
+ .cmd = (fsp_cmd_t *) CMDH_LINEAR_WINDOW_BASE_ADDRESS,
+ .rsp = (fsp_rsp_t *) CMDH_OCC_RESPONSE_BASE_ADDRESS,
+};
+
+// This determines whether or not OCC can use MBOX for attentions
+eFsi2HostMboxState G_fsi2host_mbox_ready = FSI2HOST_MBOX_NOT_USEABLE; // @th033
+
+// Temporary storage used by our SSX_PANIC macro
+uint32_t __occ_panic_save_r3;
+uint32_t __occ_panic_save_r4;
+uint32_t __occ_panic_save_r5;
+uint32_t __occ_panic_save_msr; // @sb012
+
+// Storage for commands coming from HTMGT
+DMA_BUFFER( fsp_cmd_t G_htmgt_cmd_buffer ) = {{{{0}}}};
+// Storage for responses sent to HTMGT
+DMA_BUFFER( fsp_rsp_t G_htmgt_rsp_buffer ) = {{{{0}}}};
+// Storage for responses sent to BMC
+cmdh_fsp_rsp_t G_tmp_rsp_buffer = {{0}};
+
+// This determines how OCC will send an interrupt to Host:
+// 0x00 = use FSI2MBOX; 0x01 = use PSIHB complex
+uint8_t G_occ_interrupt_type = 0x00;
+
+//*************************************************************************
+// Function Declarations
+//*************************************************************************
+errlHndl_t cmdh_processTmgtRequest (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr);
+
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: notifyCmdhWakeupCondition
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void notifyCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond)
+{
+ G_cmdh_thread_wakeup_mask |= i_cond;
+ ssx_semaphore_post(&G_cmdh_fsp_wakeup_thread);
+}
+
+
+// Function Specification
+//
+// Name: clearCmdhWakeupCondition
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void clearCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond)
+{
+ G_cmdh_thread_wakeup_mask &= ~i_cond;
+}
+
+
+// Function Specification
+//
+// Name: notifyFspDoorbellReceived
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void notifyFspDoorbellReceived(void * i_arg)
+{
+ notifyCmdhWakeupCondition(CMDH_WAKEUP_FSP_COMMAND);
+}
+
+
+// Function Specification
+//
+// Name: cmdh_thread_wait_for_wakeup
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+int cmdh_thread_wait_for_wakeup(void)
+{
+ int l_rc;
+
+ // Check if we already have a pending wait for a doorbell,
+ // if we do, don't schedule another one, that would result
+ // in either undefined behavior or a race condition
+ if(async_request_is_idle(&G_fsp_doorbell_ocb_request.request))
+ {
+ CMDH_DBG("Waiting for FSP Doorbell...\n");
+ ocb_request_schedule(&G_fsp_doorbell_ocb_request);
+ }
+
+ // Wait for someone to wakeup this thread - @th039 changed to WAIT_FOREVER
+ l_rc = ssx_semaphore_pend(&G_cmdh_fsp_wakeup_thread, SSX_WAIT_FOREVER);
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_fsp_fsi2host_mbox_wait4free
+//
+// Description: Checks the OR of all of the SCRATCH7 core scoms on the
+// processor, and waits up to 90 <TBD> seconds for hostboot
+// to signal they are off the fsi2host mbox by clearing the
+// SCRATCH7 scom from 'hostboot' to all zeros.
+//
+// @sbscr Moving the mbox check from scratch register 7 to scratch register 3.
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+int cmdh_fsp_fsi2host_mbox_wait4free(void)
+{
+/// PC SCRATCH_REGISTER_7, used for locking FSI2HOST MBOX
+//#define PC_SCR7 0x1001328a
+
+// >> @sbscr
+// Scratch register 3
+#define PC_SCR3 0x10013286
+// << @sbscr
+
+/// Hostboot writes 'hostboot' as its magic number
+#define HOSTBOOT_RUNNING 0x686f7374626f6f74ULL
+
+/// Dan Crowell says -- I would say at least 1 min to be safe
+#define FSI2HOST_TIMEOUT_IN_SECONDS 90
+
+#define SWAKEUP_TIMEOUT_MS 25 //use 25ms timeout (same as used in gpsm code)
+
+ uint64_t l_payload = 0;
+ int rc,rc2 = 0;
+ int l_do_once = 0;
+ int l_timeout = FSI2HOST_TIMEOUT_IN_SECONDS;
+ ChipConfigCores l_cores, l_swup_timedout;
+ pmc_core_deconfiguration_reg_t l_pcdr;
+ bool l_disable_swup;
+ errlHndl_t l_errl;
+ bool l_swakeup_failure = FALSE;
+
+
+ // query configured cores for special wakeup -- gm020
+ l_pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG);
+ l_cores = ~l_pcdr.fields.core_chiplet_deconf_vector;
+
+ while(0 != l_timeout)
+ {
+ /// Decrement Timeout Timer
+ l_timeout--;
+
+ l_disable_swup = FALSE;
+ /// Enable special wakeup so following getscom doesn't
+ /// fail with CHIPLET_OFFLINE error on sleeping cores -- gm020
+ rc2 = occ_special_wakeup(TRUE,
+ l_cores,
+ SWAKEUP_TIMEOUT_MS,
+ &l_swup_timedout);
+ if(rc2 || l_swup_timedout)
+ {
+ TRAC_ERR("cmdh_fsp_fsi2host_mbox_wait4free: enable occ_special_wakeup failed with rc=%d, timeout=0x%04x, cores=0x%04x",
+ rc2, l_swup_timedout, l_cores);
+
+ l_swakeup_failure = TRUE;
+ break;
+ }
+
+ l_disable_swup = TRUE;
+
+ /// Read from all cores & OR together so we don't have
+ /// to figure out which is the hostboot 'master'
+ rc = getscom_ffdc(MC_ADDRESS(PC_SCR3,
+ MC_GROUP_EX_CORE, PCB_MULTICAST_OR),
+ &l_payload, NULL); //errors committed internally -- gm033
+
+ if (rc) {
+ TRAC_INFO("PC_SCR3 getscom fail rc=%x",rc); // @sbscr
+ break;
+ }
+
+ if (HOSTBOOT_RUNNING == l_payload)
+ {
+ /// Hostboot is still running on the Mailbox
+ if(0 == l_do_once)
+ {
+ l_do_once = 1;
+ TRAC_INFO("HostBoot is on FSI2HOST mailbox...waiting for them to get off");
+ }
+ }
+ else if(0 == l_payload)
+ {
+ /// Hostboot is off the mailbox
+ rc = 0;
+ break;
+ }
+ else
+ {
+ /// This is maybe an error, but probably not. Especially in AVP
+ /// mode. // @th038
+ ///
+ /// Trace what we see in case someone tries to blame us for a defect.
+ TRAC_INFO("Hostboot is off FSI2HOST mbox, but PC_SCR3 = 0x%08x_%08x", // @sbscr
+ (uint32_t) ((l_payload & 0xFFFFFFFF00000000ULL) >> 32),
+ (uint32_t) ((l_payload & 0x00000000FFFFFFFFULL) >> 0));
+
+ // Return success
+ rc = 0;
+ break;
+ }
+
+ if(l_disable_swup) //gm020
+ {
+ l_disable_swup = FALSE;
+ /// clear special wakeup while we sleep
+ rc2 = occ_special_wakeup(FALSE,
+ l_cores,
+ SWAKEUP_TIMEOUT_MS,
+ &l_swup_timedout);
+ if(rc2)
+ {
+ TRAC_ERR("cmdh_fsp_fsi2host_mbox_wait4free: clear occ_special_wakeup failed with rc=%d, cores=0x%04x",
+ rc2, l_cores);
+ l_swakeup_failure = TRUE;
+ break;
+ }
+ }
+
+
+ /// Wait for 1 second until we try again
+ ssx_sleep(SSX_SECONDS(1));
+ }
+
+ //make sure we clear special wakeup before exiting this function -- gm020
+ if(l_disable_swup)
+ {
+ rc2 = occ_special_wakeup(FALSE,
+ l_cores,
+ SWAKEUP_TIMEOUT_MS,
+ &l_swup_timedout);
+ if(rc2)
+ {
+ TRAC_ERR("cmdh_fsp_fsi2host_mbox_wait4free: clear occ_special_wakeup failed with rc=%d, cores=0x%04x",
+ rc2, l_cores);
+ l_swakeup_failure = TRUE;
+ }
+ }
+
+ if( 0 == l_timeout )
+ {
+ rc = -1;
+ }
+
+ //Since cores can be left in an unknown state after special wakeup fails
+ //Log an error and request a reset to possibly clean up the special wakeup -- gm020
+ if(l_swakeup_failure)
+ {
+ /* @
+ * @errortype
+ * @moduleid CMDH_FSP_FSI2HOST_MBOX_WAIT4FREE
+ * @reasoncode INTERNAL_HW_FAILURE
+ * @userdata1 rc - Return code of failing function
+ * @userdata2 bitmap of cores that timed out
+ * @userdata4 0
+ * @devdesc Failed to enable OCC special wakeup
+ */
+ l_errl = createErrl(
+ CMDH_FSP_FSI2HOST_MBOX_WAIT4FREE, // modId
+ INTERNAL_HW_FAILURE, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ rc2, // userdata1
+ l_swup_timedout // userdata2
+ );
+
+ REQUEST_RESET(l_errl);
+ if(!rc)
+ {
+ rc = -1;
+ }
+ }
+
+ return rc;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_fsp_init
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_fsp_init(void)
+{
+ int l_rc;
+ errlHndl_t l_errlHndl = NULL;
+ mbox_data_area_regs_t l_mbox_msg;
+
+ CHECKPOINT(INIT_OCB);
+
+ // ----------------------------------------------------
+ // Initialize OCB Channels
+ // ----------------------------------------------------
+ // The channel initialization is mostly done by SSX
+ // or by HostBoot, but there are a couple things OCC
+ // needs to do
+
+ // Create OCB Request for doorbell
+ ssx_semaphore_create(&G_cmdh_fsp_wakeup_thread,0,0);
+
+ ocb_request_create(&G_fsp_doorbell_ocb_request,
+ &G_ocb_read_queue[1],
+ (uint64_t *) &G_fsp_msg.doorbell[0],
+ 8,
+ SSX_WAIT_FOREVER,
+ (AsyncRequestCallback)notifyFspDoorbellReceived,
+ (void *)NULL,
+ ASYNC_CALLBACK_NONCRITICAL);
+
+ ocb_request_schedule(&G_fsp_doorbell_ocb_request);
+
+ CHECKPOINT(OCB_INITIALIZED);
+
+ // ----------------------------------------------------
+ // Open Up Linear Window for FSP Communication
+ // ----------------------------------------------------
+#if 0
+ ocb_allow_untrusted_initialize(OCB_CHANNEL_FSP_LINEAR,
+ ALLOW_UNTRUSTED_ACCESS);
+
+ ocb_linear_window_initialize(OCB_CHANNEL_FSP_LINEAR,
+ CMDH_LINEAR_WINDOW_BASE_ADDRESS,
+ LOG_SIZEOF_FSP_CMD_BUFFER);
+#endif
+
+ if(G_occ_interrupt_type == 0x00)
+ {
+ // ----------------------------------------------------
+ // Initialize FSI2Host Mailbox1 -- Attentions to FSP
+ // ----------------------------------------------------
+ l_rc = cmdh_fsp_fsi2host_mbox_wait4free(); // @th033
+ if(l_rc)
+ {
+ CHECKPOINT_FLAG(CF_FSI_MB_TIMEOUT);
+
+ G_fsi2host_mbox_ready = FSI2HOST_MBOX_NOT_USEABLE;
+
+ TRAC_ERR("Timeout waiting for HostBoot to get off FSI2HOST mailbox. rc=%d", l_rc);
+
+ /* @
+ * @errortype
+ * @moduleid CMDH_FSI2HOST_MBOX_UNAVAIL
+ * @reasoncode EXTERNAL_INTERFACE_FAILURE
+ * @userdata1 l_rc - Return code of failing function
+ * @userdata2 0
+ * @userdata4 ERC_CMDH_MBOX_REQST_FAILURE
+ * @devdesc Failed to get permission to use fsi2host mbox
+ */
+ l_errlHndl = createErrl(
+ CMDH_FSI2HOST_MBOX_UNAVAIL, // modId
+ EXTERNAL_INTERFACE_FAILURE, // reasoncode
+ ERC_CMDH_MBOX_REQST_FAILURE, // Extended reason code
+ ERRL_SEV_PREDICTIVE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ l_rc, // userdata1
+ 0 // userdata2
+ );
+ }
+ else
+ {
+ CHECKPOINT(INIT_FSI_HOST_MBOX);
+ TRAC_INFO("HostBoot is off FSI2HOST mailbox."); // @th033
+
+ /// Initialize the FSI2HOST MBOX
+ memset(&l_mbox_msg.word[0],0,sizeof(l_mbox_msg));
+ l_mbox_msg.fields.msg_id = 0;
+ l_mbox_msg.fields.msg_queue_id = OCC_MSG_QUEUE_ID;
+ l_mbox_msg.fields.msg_payload.fsp_cmd_buffer_addr = CMDH_LINEAR_WINDOW_BASE_ADDRESS;
+ l_mbox_msg.fields.msg_payload.fsp_rsp_buffer_addr = CMDH_OCC_RESPONSE_BASE_ADDRESS;
+ l_mbox_msg.fields.msg_payload.occ_id = G_pob_id.chip_id;
+
+ do
+ {
+ // Initialize Headers -- Hardware Provided Header Area not used
+ // scom errors will be committed internally -- gm033
+ l_rc = putscom_ffdc(MAILBOX_1_HEADER_COMMAND_0_A_REGADDR, 0x0000000000000000ull, NULL);
+ if(l_rc)
+ {
+ break;
+ }
+ l_rc = putscom_ffdc(MAILBOX_1_HEADER_COMMAND_1_A_REGADDR, 0x0000000000000000ull, NULL);
+ if(l_rc)
+ {
+ break;
+ }
+ l_rc = putscom_ffdc(MAILBOX_1_HEADER_COMMAND_2_A_REGADDR, 0x0000000000000000ull, NULL);
+ if(l_rc)
+ {
+ break;
+ }
+
+ // Initialize Data Area -- 64 bytes
+ // Message ID & Message Queue ID
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_0_REGADDR, ((uint64_t) l_mbox_msg.fields.msg_id << 32), NULL);//l_mbox_msg.word[0]);
+ if(l_rc)
+ {
+ break;
+ }
+ // Command Type & Flags
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_1_REGADDR, ((uint64_t) l_mbox_msg.fields.msg_queue_id << 32), NULL);//l_mbox_msg.word[1]);
+ if(l_rc)
+ {
+ break;
+ }
+ // Data[0]
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_2_REGADDR, ((uint64_t) l_mbox_msg.fields.msg_payload.type << 32), NULL); //l_mbox_msg.word[2]);
+ if(l_rc)
+ {
+ break;
+ }
+ // Data[1]
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_3_REGADDR, ((uint64_t) l_mbox_msg.fields.msg_payload.flags << 32), NULL); //l_mbox_msg.word[3]);
+ if(l_rc)
+ {
+ break;
+ }
+ // (Void *) Extra Data
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_4_REGADDR, ((uint64_t) l_mbox_msg.fields.msg_payload.fsp_cmd_buffer_addr << 32), NULL); //l_mbox_msg.word[4]);
+ if(l_rc)
+ {
+ break;
+ }
+ // Unused
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_5_REGADDR, ((uint64_t) l_mbox_msg.fields.msg_payload.fsp_rsp_buffer_addr << 32), NULL);
+ if(l_rc)
+ {
+ break;
+ }
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_6_REGADDR, ((uint64_t) l_mbox_msg.fields.msg_payload.occ_id << 32), NULL);
+ if(l_rc)
+ {
+ break;
+ }
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_7_REGADDR, 0x0000000000000000ull, NULL);
+ if(l_rc)
+ {
+ break;
+ }
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_8_REGADDR, 0x0000000000000000ull, NULL);
+ if(l_rc)
+ {
+ break;
+ }
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_9_REGADDR, 0x0000000000000000ull, NULL);
+ if(l_rc)
+ {
+ break;
+ }
+
+ G_fsi2host_mbox_ready = FSI2HOST_MBOX_INITIALIZED; // @th033
+ CHECKPOINT(FSI_HOST_MBOX_INITIALIZED);
+ }while(0);
+ }
+ }
+ else if(G_occ_interrupt_type == 0x01)
+ {
+ // FIXME: For Phas 4 of Habanero, need to init this path
+ }
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_fsp_attention
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+int cmdh_fsp_attention_withRetry(uint32_t i_type, int i_timeout_in_ms)
+{
+#define CMDH_RETRY_ATTENTION_INTERVAL_MS 10
+ int l_timeoutLimit = (i_timeout_in_ms / CMDH_RETRY_ATTENTION_INTERVAL_MS);
+ int l_timeout = 0;
+ int l_alert_rc = 0;
+ int l_rc = 0;
+
+ // Try to send an alert to FSP every second until timeout is
+ // reached, or alert is successfully sent.
+ for(l_timeout=0; l_timeout < l_timeoutLimit; l_timeout++)
+ {
+ // Signal to TMGT that OCC has a response ready
+ l_alert_rc = cmdh_fsp_attention( OCC_ALERT_FSP_RESP_READY );
+
+ if(OCC_ALERT_SUCCESS == l_alert_rc)
+ {
+ // Attention successfully sent
+ break;
+ }
+ else if(OCC_ALERT_LAST_ATTN_NOT_COMPLETE == l_alert_rc)
+ {
+ // If we couldn't send the alert b/c FSP hasn't processed the last
+ // one, wait one second, then try again.
+ ssx_sleep(SSX_MILLISECONDS(CMDH_RETRY_ATTENTION_INTERVAL_MS));
+ }
+ else
+ {
+ // Must have been a PIB Error
+ TRAC_ERR("PIB Error on Attention (Type %d) to FSP. rc=0x%x",
+ i_type, l_alert_rc);
+ // TODO: Create Error Log?
+ break;
+ }
+ }
+ if(l_timeoutLimit == l_timeout)
+ {
+ TRAC_INFO("Timeout on Attention (Type %d) to FSP. rc=0x%x",
+ i_type, l_alert_rc);
+ l_rc = -1;
+ }
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_fsp_attention
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+int cmdh_fsp_attention(uint32_t i_type)
+{
+ doorbl_stsctrl_reg_t l_status;
+ mbox_data_area_regs_t l_mbox_msg;
+ int l_rc = OCC_ALERT_SUCCESS;
+ errlHndl_t l_err = NULL;
+
+ do
+ {
+ // Don't send attentions if the FSI2HOST Mailbox isn't ours
+ if( FSI2HOST_MBOX_NOT_USEABLE == G_fsi2host_mbox_ready ){break;} // @th033
+
+ // Read Status Register for checks below
+ l_rc = getscom_ffdc(MAILBOX_1_DOORBELL_STS_CTRL_REGADDR, (uint64_t *) &l_status.doubleword, &l_err);
+ if(l_rc)
+ {
+ break;
+ }
+
+ if (l_status.lbus_slaveA_pending)
+ {
+ // Can't send alert, FSP hasn't handled last attention yet
+ l_rc = OCC_ALERT_LAST_ATTN_NOT_COMPLETE;
+
+ // Return from function with error rc, and let caller try again.
+ break;
+ }
+ else
+ {
+ // No attention in progress to FSP, we are allowed send one
+ if (0 == l_status.xup)
+ {
+ // FSP should have set this, but didn't...
+ // TODO: Ignore? Log Error? Valid Case? Abort sending another attention?
+ }
+
+ // Set Attention Command Type = OCC_ALERT_FSP_SERVICE_REQD, Flags = 0
+ l_mbox_msg.fields.msg_payload.type = i_type;
+
+ // Send Command Type & Flags to Mailbox Register
+ l_rc = putscom_ffdc(MAILBOX_1_DATA_AREA_A_2_REGADDR, ((uint64_t) l_mbox_msg.fields.msg_payload.type << 32), &l_err); //l_mbox_msg.word[2]);
+ if(l_rc){break;}
+
+ // Set Attention Interrupt by setting "LBUS slave-A Pending (bit 28, intel notation)"
+ l_status.lbus_slaveA_pending = 1;
+ l_status.lbus_slaveA_data_cnt = 0x28;
+ // Clear Xup bit, it is set by FSP when it reads the OCC interrupt Mailbox
+ l_status.xup = 0;
+ // Write Status out to Doorbell Status/Control 1
+ l_rc = putscom_ffdc(MAILBOX_1_DOORBELL_STS_CTRL_REGADDR, (uint64_t) l_status.doubleword, &l_err);
+ if(l_rc){break;}
+
+ CMDH_DBG("Sent Attention to FSP: Type[0x%x]\n",i_type);
+ }
+ }while(0);
+
+ if(l_err)
+ {
+ //can't commit errors from this function since committing an error will
+ //cause another call to raise an attention and we could eventually run
+ //out of stack space -- gm033
+ deleteErrl(&l_err);
+ }
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: checksum16
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint16_t checksum16(uint8_t * i_data, const uint16_t i_len)
+{
+ uint8_t * l_data = i_data;
+ uint16_t l_len = 0;
+ uint16_t l_cksm = 0;
+
+ for(l_len=0; l_len<i_len; l_len++)
+ {
+ l_cksm += *l_data;
+ l_data++;
+ }
+
+ return l_cksm;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_build_errl_rsp
+//
+// Description: This function is to be used to handle as many as possible
+// error log scenerios that come up during a TMGT->OCC
+// command execution, resulting in the correct "Error Response
+// Data Packet"
+//
+// It is to be placed in the error path, and pass in the bad RC
+// that should be sent to TMGT, and/or the errlHndl to go along
+// with it.
+//
+// If a errlHndl containing an error log is passed in, that log
+// will be used, and no generic structure will be generated.
+//
+// If the errlHndl that is passed in to this function is
+// INVALID_ERR_HNDL, then this function will use that as the
+// error log.
+//
+// ...However...
+//
+// It is valid (and encouraged, when appropriate) to pass in an
+// empty/NULL errlHndl, which will then be filled in with the
+// generic error log, containing:
+// - The passed in Return Code to TMGT (modified if SUCCESS)
+// - The first 32 bytes of the passed in command as data in
+// the user details area of the error log
+//
+// This function then generates the "Error Response Data Packet"
+// response to TMGT, including the "error log id" in the response
+// automatically.
+//
+// This function will only update the response RC if it is
+// currently set to success, or if the errl passed in is
+// NULL. If the response rc is set, and there is an error
+// log, it is assumed this function has already been called,
+// and we won't overwrite the previous error response.
+//
+// Interface Architecture: TMGT to OCC -- contains further
+// details on the "Error Response Data Packet."
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+// @th036 - rewrote this function
+void cmdh_build_errl_rsp(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr,
+ ERRL_RC i_rc,
+ errlHndl_t * io_errlHndl)
+{
+ errl_generic_resp_t * l_errl_rsp_ptr = (errl_generic_resp_t *) o_rsp_ptr;
+ errlHndl_t * l_errlHndlPtr = io_errlHndl;
+ uint8_t l_reason;
+
+ /// Make sure there is a error log pointer passed in so we don't
+ /// dereference a NULL pointer
+ if(NULL != l_errlHndlPtr)
+ {
+ /// Check if we need to update the return code, we only need to update this
+ /// if no one has previously set it to an error rc due to a error log
+ if( (ERRL_RC_SUCCESS == l_errl_rsp_ptr->rc) || (NULL == *l_errlHndlPtr) )
+ {
+ if( (i_rc == ERRL_RC_SUCCESS) || (i_rc == ERRL_RC_CONDITIONAL_SUCCESS) )
+ {
+ // We can't return success in an error packet, change the
+ // return code to INTERNAL FAIL, because it must have been
+ // a code bug.
+ l_errl_rsp_ptr->rc = ERRL_RC_INTERNAL_FAIL;
+ }
+ else
+ {
+ l_errl_rsp_ptr->rc = i_rc;
+ }
+ }
+
+ /// If no error log was passed in to this function, create one
+ if(NULL == *l_errlHndlPtr)
+ {
+ /* @
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 1st 4 bytes of command that had the failure
+ * @userdata2 Return Code of command that failed
+ * @userdata4 ERC_CMDH_INTERNAL_FAILURE
+ * @devdesc A Valid FSP to OCC command failed
+ */
+ /* @
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 1st 4 bytes of command that had the failure
+ * @userdata2 Return Code of command that failed
+ * @userdata4 ERC_CMDH_INTERNAL_FAILURE
+ * @devdesc FSP to OCC packet is invalid
+ */
+ //For invalid data, use INVALID_INPUT_DATA reason code. Use INTERNAL_FAILURE otherwise.
+ l_reason = (i_rc == ERRL_RC_INVALID_DATA)? INVALID_INPUT_DATA: INTERNAL_FAILURE; //@gm006
+ *l_errlHndlPtr = createErrl(
+ CMDH_GENERIC_CMD_FAILURE, //modId
+ l_reason, //reasoncode
+ ERC_CMDH_INTERNAL_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity //@wb001
+ NULL, //TODO: create trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ CONVERT_UINT8_ARRAY_UINT32(i_cmd_ptr->cmd_type,
+ i_cmd_ptr->data[0],
+ i_cmd_ptr->data[1],
+ i_cmd_ptr->data[2]), //userdata1
+ i_rc //userdata2
+ );
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(*l_errlHndlPtr,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ /// Copy in the first 32 bytes of the command that was sent
+ addUsrDtlsToErrl(*l_errlHndlPtr, //io_err
+ (uint8_t *) i_cmd_ptr, //i_dataPtr,
+ 32, //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+ }
+
+ /// Fill out the response lod_id with the error id
+ l_errl_rsp_ptr->log_id = getErrlLogId(*l_errlHndlPtr);
+ }
+ else
+ {
+ /// This is a firmware bug, TMGT will see it is a bad RC,
+ /// with no error log, pick up on this, and log its own error
+ l_errl_rsp_ptr->log_id = 0; //ERRL_SLOT_INVALID
+ l_errl_rsp_ptr->rc = ERRL_RC_INTERNAL_FAIL;
+ }
+
+ l_errl_rsp_ptr->data_length[0] = 0;
+ l_errl_rsp_ptr->data_length[1] = 1;
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_fsp_cmd_hndler
+//
+// Description:
+//
+//
+//
+//
+// Flow: 09/23/14 FN= cmdh_fsp_cmd_hndler.odg
+//
+// End Function Specification
+errlHndl_t cmdh_fsp_cmd_hndler(void)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_errlHndl = NULL;
+ uint16_t l_cksm = 0;
+ uint16_t l_data_len = 0;
+ uint16_t l_cmd_len = 0;
+ uint8_t l_sender_id = 0;
+ uint8_t l_attn_type = 0;
+ int l_ssxrc = SSX_OK;
+ uint32_t l_reasonCode = 0;
+ uint32_t l_extReasonCode = 0;
+ uint32_t l_userdata2 = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ // Extract the sender ID and the attention type from doorbell
+ l_sender_id = G_fsp_msg.doorbell[0];
+ l_attn_type = G_fsp_msg.doorbell[1];
+
+ // Validate the sender ID and the attention type
+ if(((l_sender_id != ATTN_SENDER_ID_FSP) &&
+ (l_sender_id != ATTN_SENDER_ID_HTMGT) &&
+ (l_sender_id != ATTN_SENDER_ID_BMC)) ||
+ (l_attn_type != ATTN_TYPE_CMD_WRITE))
+ {
+ TRAC_ERR("Attention received with invalid values: sender_id[0x%02X] attn_type[0x%02X]",
+ l_sender_id,
+ l_attn_type);
+
+ /* @
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode EXTERNAL_INTERFACE_FAILURE
+ * @userdata1 Sender id
+ * @userdata2 Attention type
+ * @userdata4 ERC_CMDH_INVALID_ATTN_DATA
+ * @devdesc Received an attention with invalid values
+ */
+ l_errlHndl = createErrl(
+ CMDH_GENERIC_CMD_FAILURE, //modId
+ EXTERNAL_INTERFACE_FAILURE, //reasoncode
+ ERC_CMDH_INVALID_ATTN_DATA, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_sender_id, //userdata1
+ l_attn_type); //userdata2
+
+ break;
+ }
+
+ // Determine which buffer to read based on the sender ID
+ if(l_sender_id == ATTN_SENDER_ID_HTMGT)
+ {
+ // Need to read command data from HOMER
+ BceRequest pba_copy;
+
+ // Set up a copy request
+ l_ssxrc = bce_request_create(&pba_copy, // block copy object
+ &G_pba_bcde_queue, // mainstore to sram copy engine
+ OCC_HTMGT_CMD_OFFSET_HOMER, // mainstore address
+ (uint32_t) &G_htmgt_cmd_buffer, // sram starting address
+ (size_t) sizeof(G_htmgt_cmd_buffer), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // no call back
+ NULL, // no call back arguments
+ ASYNC_REQUEST_BLOCKING); // blocking request
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_fsp_cmd_hndler: BCE request create failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata2 Internal function check-point
+ * @userdata4 ERC_BCE_REQ_CREATE_READ_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQ_CREATE_READ_FAILURE;
+ l_userdata2 = 0x01;
+ break;
+ }
+
+ // Do actual copying
+ l_ssxrc = bce_request_schedule(&pba_copy);
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_fsp_cmd_hndler: BCE request schedule failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata2 Internal function check-point
+ * @userdata4 ERC_BCE_REQ_SCHED_READ_FAILURE
+ * @devdesc Failed to copy data by using DMA
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQ_SCHED_READ_FAILURE;
+ l_userdata2 = 0x02;
+ break;
+ }
+
+ // Zero out the response buffer, only update the return status of 'In Progress'
+ G_htmgt_rsp_buffer.fields.seq = 0x00;
+ G_htmgt_rsp_buffer.fields.cmd_type = 0x00;
+ G_htmgt_rsp_buffer.fields.rc = ERRL_RC_CMD_IN_PROGRESS;
+ G_htmgt_rsp_buffer.fields.data_length[0] = 0;
+ G_htmgt_rsp_buffer.fields.data_length[1] = 1;
+ G_htmgt_rsp_buffer.fields.data[0] = 0x00;
+
+ // Need to write the response to HOMER. Set up a copy request
+ l_ssxrc = bce_request_create(&pba_copy, // block copy object
+ &G_pba_bcue_queue, // sram to mainstore copy engine
+ OCC_HTMGT_RSP_OFFSET_HOMER, // mainstore address
+ (uint32_t) &G_htmgt_rsp_buffer, // sram starting address
+ (size_t) sizeof(G_htmgt_rsp_buffer), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // no call back
+ NULL, // no call back arguments
+ ASYNC_REQUEST_BLOCKING); // blocking request
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_fsp_cmd_hndler: BCE request create failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata2 Internal function check-point
+ * @userdata4 ERC_BCE_REQ_CREATE_INPROG_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQ_CREATE_INPROG_FAILURE;
+ l_userdata2 = 0x03;
+ break;
+ }
+
+ // Do actual copying
+ l_ssxrc = bce_request_schedule(&pba_copy);
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_fsp_cmd_hndler: BCE request schedule failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata2 Internal function check-point
+ * @userdata4 ERC_BCE_REQ_SCHED_INPROG_FAILURE
+ * @devdesc Failed to copy data by using DMA
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQ_SCHED_INPROG_FAILURE;
+ l_userdata2 = 0x04;
+ break;
+ }
+
+ // Determine the command length
+ l_data_len = CONVERT_UINT8_ARRAY_UINT16(G_htmgt_cmd_buffer.fields.data_length[0],
+ G_htmgt_cmd_buffer.fields.data_length[1]);
+ l_cmd_len = l_data_len + CMDH_FSP_SEQ_CMD_SIZE + CMDH_FSP_DATALEN_SIZE;
+
+ // Make sure that the command length isn't > max command length
+ // before we calculate the checksum
+ if(l_cmd_len > CMDH_FSP_CMD_SIZE)
+ {
+ l_cmd_len = CMDH_FSP_CMD_SIZE;
+ }
+
+ // Verify the command checksum
+ l_cksm = checksum16(&G_htmgt_cmd_buffer.byte[0], l_cmd_len);
+ if(l_cksm != CONVERT_UINT8_ARRAY_UINT16(G_htmgt_cmd_buffer.byte[l_cmd_len],
+ G_htmgt_cmd_buffer.byte[l_cmd_len+1]))
+ {
+ TRAC_ERR("Checksum Error! Expected[0x%04X] Received[0x%02X%02X] Command Length[%u]",
+ l_cksm,
+ G_htmgt_cmd_buffer.byte[l_cmd_len],
+ G_htmgt_cmd_buffer.byte[l_cmd_len+1],
+ l_cmd_len);
+
+ G_htmgt_rsp_buffer.fields.rc = ERRL_RC_CHECKSUM_FAIL;
+ G_htmgt_rsp_buffer.fields.data_length[0] = 0;
+ G_htmgt_rsp_buffer.fields.data_length[1] = 1;
+ G_htmgt_rsp_buffer.fields.data[0] = 0x00; //No error log
+ }
+ else
+ {
+ // Command is responsible for RC, Data Len, Data
+ l_errlHndl = cmdh_processTmgtRequest(&G_htmgt_cmd_buffer.fields,
+ &G_htmgt_rsp_buffer.fields);
+ }
+
+ // Prepare the final response
+ // Copy the sequence number and command type to response
+ G_htmgt_rsp_buffer.fields.seq = G_htmgt_cmd_buffer.fields.seq;
+ G_htmgt_rsp_buffer.fields.cmd_type = G_htmgt_cmd_buffer.fields.cmd_type;
+
+ // Calculate length of response
+ l_data_len = CONVERT_UINT8_ARRAY_UINT16(G_htmgt_rsp_buffer.fields.data_length[0],
+ G_htmgt_rsp_buffer.fields.data_length[1]);
+ l_cmd_len = l_data_len + CMDH_FSP_SEQ_CMD_RC_SIZE + CMDH_FSP_DATALEN_SIZE;
+
+ // Add checksum
+ l_cksm = checksum16(&G_htmgt_rsp_buffer.byte[0], l_cmd_len);
+ G_htmgt_rsp_buffer.byte[l_cmd_len] = CONVERT_UINT16_UINT8_HIGH(l_cksm);
+ G_htmgt_rsp_buffer.byte[l_cmd_len+1] = CONVERT_UINT16_UINT8_LOW(l_cksm);
+
+ // Need to write the final response to HOMER. Set up a copy request
+ l_ssxrc = bce_request_create(&pba_copy, // block copy object
+ &G_pba_bcue_queue, // sram to mainstore copy engine
+ OCC_HTMGT_RSP_OFFSET_HOMER, // mainstore address
+ (uint32_t) &G_htmgt_rsp_buffer, // sram starting address
+ (size_t) sizeof(G_htmgt_rsp_buffer), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // no call back
+ NULL, // no call back arguments
+ ASYNC_REQUEST_BLOCKING); // blocking request
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_fsp_cmd_hndler: BCE request create failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata2 Internal function check-point
+ * @userdata4 ERC_BCE_REQ_CREATE_WRITE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQ_CREATE_WRITE_FAILURE;
+ l_userdata2 = 0x05;
+ break;
+ }
+
+ // Do actual copying
+ l_ssxrc = bce_request_schedule(&pba_copy);
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_fsp_cmd_hndler: BCE request schedule failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata2 Internal function check-point
+ * @userdata4 ERC_BCE_REQ_SCHED_WRITE_FAILURE
+ * @devdesc Failed to copy data by using DMA
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQ_SCHED_WRITE_FAILURE;
+ l_userdata2 = 0x06;
+ break;
+ }
+ }
+ else
+ {
+ // The doorbell is coming from either TMGT or BMC. In either case,
+ // prepare a response with a return status of 'In Progress'
+ G_fsp_msg.rsp->fields.rc = ERRL_RC_CMD_IN_PROGRESS;
+
+ // Get Command Data Field Length
+ l_data_len = CONVERT_UINT8_ARRAY_UINT16(G_fsp_msg.cmd->fields.data_length[0],
+ G_fsp_msg.cmd->fields.data_length[1]);
+ l_cmd_len = l_data_len + CMDH_FSP_SEQ_CMD_SIZE + CMDH_FSP_DATALEN_SIZE;
+
+ // Make sure that the message isn't > max message size before we do checksum
+ if(l_cmd_len > CMDH_FSP_CMD_SIZE)
+ {
+ l_cmd_len = CMDH_FSP_CMD_SIZE;
+ }
+
+ // Verify Command Checksum
+ l_cksm = checksum16(&G_fsp_msg.cmd->byte[0],(l_cmd_len));
+ if(l_cksm != CONVERT_UINT8_ARRAY_UINT16(G_fsp_msg.cmd->byte[l_cmd_len],
+ G_fsp_msg.cmd->byte[l_cmd_len+1]))
+ {
+ TRAC_ERR("Checksum Error! Expected[0x%04X] Received[0x%02X%02X]",
+ l_cksm,
+ G_fsp_msg.cmd->byte[l_cmd_len],
+ G_fsp_msg.cmd->byte[l_cmd_len+1]);
+
+ if(l_sender_id == ATTN_SENDER_ID_BMC)
+ {
+ G_tmp_rsp_buffer.rc = ERRL_RC_CHECKSUM_FAIL;
+ }
+ else
+ {
+ G_fsp_msg.rsp->fields.rc = ERRL_RC_CHECKSUM_FAIL;
+ }
+ G_fsp_msg.rsp->fields.data_length[0] = 0;
+ G_fsp_msg.rsp->fields.data_length[1] = 1;
+ G_fsp_msg.rsp->fields.data[0] = 0x00; //No error log
+ // You could create an errl here, but is that really necessary?
+ // TMGT will know that the command didn't work...
+ }
+ else
+ {
+ if(l_sender_id == ATTN_SENDER_ID_BMC)
+ {
+ // If the sender is BMC, use a temporary buffer to store the
+ // response since the return code should be updated last.
+ // Command is responsible for RC, Data Len, Data
+ l_errlHndl = cmdh_processTmgtRequest (&G_fsp_msg.cmd->fields,
+ &G_tmp_rsp_buffer);
+
+ // Write response data in SRAM except for return code
+ G_fsp_msg.rsp->fields.data_length[0] = G_tmp_rsp_buffer.data_length[0];
+ G_fsp_msg.rsp->fields.data_length[1] = G_tmp_rsp_buffer.data_length[1];
+ memcpy(&G_fsp_msg.rsp->fields.data[0], &G_tmp_rsp_buffer.data[0], sizeof(CMDH_FSP_RSP_DATA_SIZE));
+ }
+ else
+ {
+ // Command is responsible for RC, Data Len, Data
+ l_errlHndl = cmdh_processTmgtRequest (&G_fsp_msg.cmd->fields,
+ &G_fsp_msg.rsp->fields);
+ }
+ }
+
+ // Finish Building Response
+ // Copy the sequence number and command type to the response
+ G_fsp_msg.rsp->fields.seq = G_fsp_msg.cmd->fields.seq;
+ G_fsp_msg.rsp->fields.cmd_type = G_fsp_msg.cmd->fields.cmd_type;
+
+ // Calculate Length of Command
+ l_data_len = CONVERT_UINT8_ARRAY_UINT16(G_fsp_msg.rsp->fields.data_length[0],
+ G_fsp_msg.rsp->fields.data_length[1]);
+ l_cmd_len = l_data_len + CMDH_FSP_SEQ_CMD_RC_SIZE + CMDH_FSP_DATALEN_SIZE;
+
+ // Add checksum
+ l_cksm = checksum16(&G_fsp_msg.rsp->byte[0],(l_cmd_len));
+ G_fsp_msg.rsp->byte[l_cmd_len] = CONVERT_UINT16_UINT8_HIGH(l_cksm);
+ G_fsp_msg.rsp->byte[l_cmd_len+1] = CONVERT_UINT16_UINT8_LOW(l_cksm);
+
+ // FIXME: Do we really need this?
+ // Set an ACK on doorbell (sanity check)
+ //G_fsp_msg.doorbell[0] |= 0x80;
+
+ // Last thing is to copy the return code in SRAM if the sender is BMC
+ if(l_sender_id == ATTN_SENDER_ID_BMC)
+ {
+ G_fsp_msg.rsp->fields.rc = G_tmp_rsp_buffer.rc;
+ }
+ }
+
+ }while(0);
+
+ if(l_ssxrc != SSX_OK)
+ {
+ l_errlHndl = createErrl(
+ CMDH_GENERIC_CMD_FAILURE, //modId
+ l_reasonCode, //reasoncode
+ l_extReasonCode, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ 0, //Trace Size
+ -l_ssxrc, //userdata1
+ l_userdata2); //userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+
+ return l_errlHndl;
+}
+
+// Function Specification
+//
+// Name: cmdh_processTmgtRequest
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_processTmgtRequest (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr)
+{
+ errlHndl_t l_err = NULL;
+ uint8_t l_cmd_type = i_cmd_ptr->cmd_type;
+
+ // Clear the Fields that the commands are responsible for
+ i_rsp_ptr->data_length[0] = 0;
+ i_rsp_ptr->data_length[1] = 0;
+ i_rsp_ptr->rc = ERRL_RC_SUCCESS;
+
+ // Run command function based on cmd_type
+ switch(l_cmd_type)
+ {
+ case CMDH_POLL:
+ l_err = cmdh_tmgt_poll (i_cmd_ptr,i_rsp_ptr); // @th036
+ break;
+
+ case CMDH_QUERYFWLEVEL:
+ cmdh_tmgt_query_fw (i_cmd_ptr,i_rsp_ptr);
+ break;
+
+ case CMDH_DEBUGPT:
+ cmdh_dbug_cmd (i_cmd_ptr,i_rsp_ptr);
+ break;
+
+ case CMDH_SETMODESTATE:
+ l_err = cmdh_tmgt_setmodestate(i_cmd_ptr,i_rsp_ptr);
+ break;
+
+ case CMDH_SETCONFIGDATA:
+ l_err = DATA_store_cnfgdata (i_cmd_ptr,i_rsp_ptr);
+ break;
+
+ case CMDH_CLEARERRL:
+ l_err = cmdh_clear_elog(i_cmd_ptr, i_rsp_ptr); //@nh004c
+ break;
+
+ case CMDH_AME_PASS_THROUGH:
+ l_err = cmdh_amec_pass_through(i_cmd_ptr,i_rsp_ptr); // @at008
+ break;
+
+ case CMDH_GETERRL:
+ l_err = cmdh_get_elog(i_cmd_ptr,i_rsp_ptr); //@nh004a
+ break;
+
+ case CMDH_RESET_PREP:
+ l_err = cmdh_reset_prep(i_cmd_ptr,i_rsp_ptr); // @th036
+ break;
+
+ case CMDH_GET_COOLING_REQUEST:
+ l_err = cmdh_get_cooling_request(i_cmd_ptr,i_rsp_ptr);
+ break;
+
+ case CMDH_MFG_TEST_CMD:
+ cmdh_mnfg_test_parse(i_cmd_ptr,i_rsp_ptr); //@gs004a
+ break;
+
+ case CMDH_GET_FIELD_DEBUG_DATA:
+ l_err = cmdh_tmgt_get_field_debug_data(i_cmd_ptr,i_rsp_ptr); // @jh002a
+ break;
+
+ case CMDH_TUNABLE_PARMS: //@rt004a
+ l_err = cmdh_tunable_parms(i_cmd_ptr,i_rsp_ptr);
+ break;
+ case CMDH_SNAPSHOT_SYNC:
+ l_err = cmdh_snapshot_sync(i_cmd_ptr,i_rsp_ptr); //@fk004a
+ break;
+ case CMDH_GET_SNAPSHOT_BUFFER:
+ l_err = cmdh_get_snapshot_buffer(i_cmd_ptr,i_rsp_ptr); //@fk004a
+ break;
+
+ //case CMDH_PWREXECPT:
+ case CMDH_SET_THERMAL_THROTTLE:
+ case CMDH_READ_STATUS_REG:
+ case CMDH_GET_THROTTLE_VALUE:
+ case CMDH_GET_CPU_TEMPS:
+ case CMDH_FOM:
+ default:
+ TRAC_INFO("Invalid or unsupported command 0x%02x",l_cmd_type);
+
+ // -----------------------------------------------
+ // Generate error response packet
+ // -----------------------------------------------
+ cmdh_build_errl_rsp(i_cmd_ptr, i_rsp_ptr, ERRL_RC_INVALID_CMD, &l_err); // @th042
+
+ break;
+ } //end switch
+
+ return l_err;
+}
+
+
diff --git a/src/occ/cmdh/cmdh_fsp.h b/src/occ/cmdh/cmdh_fsp.h
new file mode 100755
index 0000000..8e2d9b1
--- /dev/null
+++ b/src/occ/cmdh/cmdh_fsp.h
@@ -0,0 +1,516 @@
+// @file cmdh_fsp.h
+// @brief Command Handling for FSP Communication.
+
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_fsp_h cmdh_fsp.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 04/05/2012 Created
+ * @th022 thallet 10/08/2012 Moved data commands to separate file
+ * @th036 881677 thallet 05/06/2013 New Poll Command Support
+ * @th039 887066 thallet 06/11/2013 FSP Comm Improvements for Attn
+ * @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
+ * @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+ * @sb002 908891 sbroyles 12/09/2013 FFDC updates
+ * @gm022 908890 milesg 01/23/2014 Halt OCC on OCCLFIR[38]
+ * @gs041 942203 gjsilva 10/17/2014 Support for HTMGT/BMC interface
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef _CMDH_FSP_H
+#define _CMDH_FSP_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "cmdh_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "occ_common.h"
+#include "state.h"
+
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// Register Addresses for Mailbox 1 Doorbell Status/Control
+#define MAILBOX_1_DOORBELL_STS_CTRL_REGADDR 0x00050020
+
+// Register Addresses for (unused) Mailbox 1 Header Buffer
+#define MAILBOX_1_HEADER_COMMAND_BASE 0x00050021
+#define MAILBOX_1_HEADER_COMMAND_0_A_REGADDR (0 + MAILBOX_1_HEADER_COMMAND_BASE)
+#define MAILBOX_1_HEADER_COMMAND_1_A_REGADDR (1 + MAILBOX_1_HEADER_COMMAND_BASE)
+#define MAILBOX_1_HEADER_COMMAND_2_A_REGADDR (2 + MAILBOX_1_HEADER_COMMAND_BASE)
+
+// Register Addresses for Mailbox 1 Data Buffer
+#define MAILBOX_1_DATA_AREA_A_BASE 0x00050040
+#define MAILBOX_1_DATA_AREA_A_0_REGADDR (0 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_1_REGADDR (1 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_2_REGADDR (2 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_3_REGADDR (3 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_4_REGADDR (4 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_5_REGADDR (5 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_6_REGADDR (6 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_7_REGADDR (7 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_8_REGADDR (8 + MAILBOX_1_DATA_AREA_A_BASE)
+#define MAILBOX_1_DATA_AREA_A_9_REGADDR (9 + MAILBOX_1_DATA_AREA_A_BASE)
+
+// Command/Response Common: DataLength Field Size - 2 bytes
+#define CMDH_FSP_DATALEN_SIZE 2
+// Command/Response Common: Checksum Field Size - 2 bytes
+#define CMDH_FSP_CHECKSUM_SIZE 2
+
+// Command: Full Buffer Size - 4 kB
+#define CMDH_FSP_CMD_SIZE 4096
+// Command: Seq + Cmd - 2 bytes
+#define CMDH_FSP_SEQ_CMD_SIZE 2
+// Command: Maximum "Data" Field Length
+#define CMDH_FSP_CMD_DATA_SIZE (CMDH_FSP_CMD_SIZE - \
+ CMDH_FSP_DATALEN_SIZE - \
+ CMDH_FSP_CHECKSUM_SIZE - \
+ CMDH_FSP_SEQ_CMD_SIZE )
+
+// Response: Full Buffer Size - 4 kB
+#define CMDH_FSP_RSP_SIZE 4096
+// Response: Seq + Cmd + RC - 3 bytes
+#define CMDH_FSP_SEQ_CMD_RC_SIZE 3
+// Response: Maximum "Data" Field Length
+#define CMDH_FSP_RSP_DATA_SIZE (CMDH_FSP_RSP_SIZE - \
+ CMDH_FSP_DATALEN_SIZE - \
+ CMDH_FSP_CHECKSUM_SIZE - \
+ CMDH_FSP_SEQ_CMD_RC_SIZE )
+
+// Sender IDs of an attention to the OCC
+#define ATTN_SENDER_ID_FSP 0x01
+#define ATTN_SENDER_ID_HTMGT 0x10
+#define ATTN_SENDER_ID_BMC 0x20
+
+// Attention type of an attention to the OCC
+#define ATTN_TYPE_CMD_WRITE 0x01
+
+// OCC/HTMGT command buffer offset in HOMER
+#define OCC_HTMGT_CMD_OFFSET_HOMER 0x001EE000
+// OCC/HTMGT response buffer offset in HOMER
+#define OCC_HTMGT_RSP_OFFSET_HOMER 0x001EF000
+
+/**
+ * @enum eFspAlertType
+ * @brief Typedef of the various alerts that OCC can send TMGT
+ */
+typedef enum
+{
+ ///OCC has a response ready for TMGT to come get
+ OCC_ALERT_FSP_RESP_READY = 1,
+ ///OCC alert to TMGT that it needs to poll OCC
+ OCC_ALERT_FSP_SERVICE_REQD = 2,
+ ///OCC alert to TMGT that it sees a checkstop
+ OCC_ALERT_SYS_CHECKSTOP = 3,
+} eFspAlertType;
+
+/**
+ * @enum eFsi2HostMboxState
+ * @brief States for OCC using the Mailbox for Attn
+ */
+typedef enum
+{
+ FSI2HOST_MBOX_NOT_USEABLE = 0,
+ FSI2HOST_MBOX_INITIALIZED = 1,
+} eFsi2HostMboxState; // @th036
+
+/**
+ * @enum eCmdhWakeupThreadMask
+ * @brief Typedef of the various reasons why the cmdh thread wakes up
+ */
+typedef enum
+{
+ /// Success, alert was sent
+ CMDH_WAKEUP_REASON_NONE = 0x00000000,
+ CMDH_WAKEUP_FSP_COMMAND = 0x00000001,
+ CMDH_WAKEUP_FSP_ATTENTION_ALERT = 0x00000002,
+ CMDH_WAKEUP_FSP_CHECKSTOP_ALERT = 0x00000004,
+} eCmdhWakeupThreadMask;
+
+
+/**
+ * @enum eFspAlertRc
+ * @brief Typedef of the various errors that can happen on alerts
+ */
+typedef enum
+{
+ /// Success, alert was sent
+ OCC_ALERT_SUCCESS = 0,
+
+ ///SCOM Failure, Return PCB Error code
+ OCC_ALERT_SCOM_FAILURE_RSVD_0 = 1, // Resource Occupied
+ OCC_ALERT_SCOM_FAILURE_RSVD_1 = 2, // Chiplet Offline
+ OCC_ALERT_SCOM_FAILURE_RSVD_2 = 3, // Partial Good
+ OCC_ALERT_SCOM_FAILURE_RSVD_4 = 4, // Address Error
+ OCC_ALERT_SCOM_FAILURE_RSVD_5 = 5, // Clock Error
+ OCC_ALERT_SCOM_FAILURE_RSVD_6 = 6, // Packet Error
+ OCC_ALERT_SCOM_FAILURE_RSVD_7 = 7, // Timeout
+
+ ///Failure due to lbus_slaveA_pending bit being set
+ /// (meaning that FSP hasn't gotten last message)
+ OCC_ALERT_LAST_ATTN_NOT_COMPLETE = 8,
+} eFspAlertRc;
+
+
+/**
+ * @enum ERRL_RC
+ * @brief Typedef of the various 1-byte error codes that a return packet may
+ * contain. Returning any value except for "Success" or "Conditional
+ * success" requires that the return packet to TMGT be an
+ * errl_generic_resp_t packet.
+ */
+typedef enum
+{
+ ///Success
+ ERRL_RC_SUCCESS = 0x00,
+ ///Command was accepted and processed, however more processing may be needed
+ ERRL_RC_CONDITIONAL_SUCCESS = 0x01,
+ ///The command type is invalid
+ ERRL_RC_INVALID_CMD = 0x11,
+ ///The command data length is invalid for the particular command
+ ERRL_RC_INVALID_CMD_LEN = 0x12,
+ ///The command data has an invalid value for a field
+ ERRL_RC_INVALID_DATA = 0x13,
+ ///The command packet checksum is not correct
+ ERRL_RC_CHECKSUM_FAIL = 0x14,
+ ///An error occurred within the TPMF to prevent the command processing
+ ERRL_RC_INTERNAL_FAIL = 0x15,
+ ///The OCC cannot accept the command in its present state
+ ERRL_RC_INVALID_STATE = 0x16,
+ ///This is a panic response
+ ERRL_RC_PANIC = 0xE0,
+ ///This is a checkpoint response
+ ERRL_RC_INIT_CHCKPNT = 0xE1,
+ /// @sb002 Halting due to OCC watchdog timer expiration
+ ERRL_RC_WDOG_TIMER = 0xE2,
+ /// @sb002 Halting due to OCB timer expiration
+ ERRL_RC_OCB_TIMER = 0xE3,
+ /// @gm022 Halting due to unmasked OCCLFIR bit being set (see OISR0 bit 2)
+ ERRL_RC_OCC_HW_ERROR = 0xE4,
+ ///The command is being processed by OCC
+ ERRL_RC_CMD_IN_PROGRESS = 0xFF,
+} ERRL_RC;
+
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+#define CMDH_DATALEN_FIELD_UINT16(cmdOrRspPtr) \
+ (CONVERT_UINT8_ARRAY_UINT16(cmdOrRspPtr->data_length[0], \
+ cmdOrRspPtr->data_length[1]))
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+/**
+ * @struct cmdh_fsp_cmd_header
+ * @brief Faking out an inheritable anonymous struct definition, so it works
+ * with the same syntax that is used in C11 version of the C-standard
+ * Contains TMGT command common fields (seq, cmd, data_len)
+ */
+#define cmdh_fsp_cmd_header \
+ __attribute__ ((packed)) { \
+ uint8_t seq; \
+ uint8_t cmd_type; \
+ uint8_t data_length[CMDH_FSP_DATALEN_SIZE]; \
+ }
+
+/**
+ * @struct cmdh_fsp_cmd_header_t
+ * @brief Contains TMGT command common fields (seq, cmd, data_len)
+ *
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+} cmdh_fsp_cmd_header_t;
+
+/**
+ * @struct cmdh_fsp_cmd_t
+ * @brief Contains TMGT command fields
+ *
+ */
+typedef struct __attribute__ ((packed))
+{
+ /// Response header that is the same for all commands..seq,cmd,rc,etc
+ struct cmdh_fsp_cmd_header;
+ /// Data bytes (here it is the max data size)
+ uint8_t data[CMDH_FSP_CMD_DATA_SIZE];
+ /// 2 bytes reserved for Checksum, although the checksum usually doesn't
+ /// actually go here in practice
+ uint8_t __checksum_rsvd[CMDH_FSP_CHECKSUM_SIZE];
+}cmdh_fsp_cmd_t;
+
+
+/**
+ * @struct cmdh_fsp_rsp_header
+ * @brief Faking out an inheritable anonymous struct definition, so it works
+ * with the same syntax that is used in C11 version of the C-standard
+ * Contains TMGT command common fields (seq, cmd, rc, data_len)
+ */
+#define cmdh_fsp_rsp_header \
+ __attribute__ ((packed)) { \
+ uint8_t seq; \
+ uint8_t cmd_type; \
+ uint8_t rc; \
+ uint8_t data_length[CMDH_FSP_DATALEN_SIZE]; \
+ }
+
+/**
+ * @struct cmdh_fsp_rsp_header_t
+ * @brief Contains TMGT command common fields (seq, cmd, rc, data_len)
+ *
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+} cmdh_fsp_rsp_header_t;
+
+
+/**
+ * @struct cmdh_fsp_rsp_t
+ * @brief Contains TMGT command response fields
+ *
+ */
+typedef struct __attribute__ ((packed))
+{
+ /// Response header that is the same for all commands..seq,cmd,rc,etc
+ struct cmdh_fsp_rsp_header;
+ /// Data bytes (here it is the max data size)
+ uint8_t data[CMDH_FSP_RSP_DATA_SIZE];
+ /// 2 bytes reserved for Checksum, although the checksum usually doesn't
+ /// actually go here in practice
+ uint8_t __checksum_rsvd[CMDH_FSP_CHECKSUM_SIZE];
+}cmdh_fsp_rsp_t;
+
+/**
+ * @struct fsp_cmd_t
+ * @brief Contains "data" fields needed to receive/parse a command from TMGT
+ *
+ */
+typedef struct
+{
+ union
+ {
+ /// Accessible as response fields split up..seq, cmd, etc
+ cmdh_fsp_cmd_t fields;
+ /// Accessible as byte array for checksum, etc.
+ uint8_t byte[CMDH_FSP_CMD_SIZE];
+ };
+} fsp_cmd_t;
+
+/**
+ * @struct fsp_rsp_t
+ * @brief Contains "data" fields needed to respond to a command from TMGT
+ *
+ */
+typedef struct
+{
+ union
+ {
+ /// Accessible as response fields split up..seq, cmd, rc, etc
+ cmdh_fsp_rsp_t fields;
+ /// Accessible as byte array for checksum, etc.
+ uint8_t byte[CMDH_FSP_CMD_SIZE];
+ };
+} fsp_rsp_t;
+
+/**
+ * @struct fsp_msg_t
+ * @brief Contains "data" needed to handle a command to/from TMGT
+ *
+ */
+typedef struct __attribute__ ((packed))
+{
+ /// Pointer to FSP->OCC Command Buffer
+ fsp_cmd_t * cmd;
+ /// Pointer to FSP->OCC Response Buffer
+ fsp_rsp_t * rsp;
+ /// Placeholder for the 8 bytes of doorbell data that is automatically
+ /// sent as part of the doorbell from FSP
+ uint8_t doorbell[8];
+} fsp_msg_t;
+
+extern fsp_msg_t G_fsp_msg;
+
+//---------------------------------------------------------
+// Generic Error Response
+//---------------------------------------------------------
+/**
+ * @struct errl_generic_resp
+ * @brief Typedef of a generic failure response packet to TMGT. Any command
+ * handler may return this packet in place of its normal return packet.
+ */
+typedef struct errl_generic_resp {
+ /// Header that is the same for any TMGT response
+ struct cmdh_fsp_rsp_header;
+ /// Any non-zero value indicates the log id associated with a TPMF error log
+ uint8_t log_id;
+ /// Command Checksum, supplied by CMDH
+ uint8_t checksum[2];
+} errl_generic_resp_t;
+
+
+//---------------------------------------------------------
+// Mailbox Register Definition
+//---------------------------------------------------------
+/**
+ * @struct doorbl_stsctrl_reg_t
+ * @brief Breakdown of the Mailbox1 Status/Control Reg, which OCC uses
+ * to alert TMGT.
+ */
+typedef struct
+{
+ union
+ {
+ struct {
+#if 1
+ uint64_t permission_to_send :1;
+ uint64_t abort :1;
+ uint64_t lbus_slaveA_pending :1;
+ uint64_t pib_slaveB_pending :1;
+ uint64_t _reserved_1 :1;
+ uint64_t xdn :1;
+ uint64_t xup :1;
+ uint64_t _reserved_2 :1;
+ uint64_t lbus_slaveA_hdr_cnt :4;
+ uint64_t lbus_slaveA_data_cnt :8;
+ uint64_t pib_slaveB_hdr_cnt :4;
+ uint64_t pib_slaveB_data_cnt :8;
+ uint64_t _reserved_0 :32;
+#else
+ uint64_t _reserved_0 :32;
+ uint64_t lbus_slaveA_data_cnt :8;
+ uint64_t lbus_slaveA_hdr_cnt :4;
+ uint64_t pib_slaveB_data_cnt :8;
+ uint64_t pib_slaveB_hdr_cnt :4;
+ uint64_t _reserved_2 :1;
+ uint64_t xup :1;
+ uint64_t xdn :1;
+ uint64_t _reserved_1 :1;
+ uint64_t pib_slaveB_pending :1;
+ uint64_t lbus_slaveA_pending :1;
+ uint64_t abort :1;
+ uint64_t permission_to_send :1;
+#endif
+ };
+ uint64_t doubleword;
+ };
+} doorbl_stsctrl_reg_t;
+
+/**
+ * @struct mbox_payload_t
+ * @brief Breakdown of the Mailbox1 Data, which OCC uses to alert TMGT.
+ * This is the actual data that TMGT can get from the mailbox
+ * when it is notified of an alert.
+ */
+typedef struct mbox_payload
+{
+ /// This is the command type OCC uses to tell TMGT if this was a
+ /// Response Ready, or Service Required (eFspAlertType)
+ uint32_t type;
+ union
+ {
+ struct
+ {
+ /// Unused: 0 -> async, 1 -> sync.
+ uint32_t __reserved__async:1;
+ /// Unused: This is for internal hostboot use.
+ uint32_t __reserved__mbox_sync:1;
+ /// Unused
+ uint32_t __reserved__unused:30;
+ };
+ uint32_t flags;
+ };
+ union
+ {
+ struct
+ {
+ /// "Write" Buffer Address (from TMGT perspective)
+ uint32_t fsp_cmd_buffer_addr;
+ /// "Read" Buffer Address (from TMGT perspective)
+ uint32_t fsp_rsp_buffer_addr;
+ /// Unused
+ uint8_t _reserved[7];
+ /// Sanity check on OCC Id (should match up with HUID)
+ uint8_t occ_id;
+ };
+ uint64_t data[2];
+ };
+ /// If extra_data != NULL, data[1] is required to have size of extra_data (in bytes)
+ uint64_t extra_data;
+} mbox_payload_t;
+
+/**
+ * @struct mbox_msg_t
+ * @brief Breakdown of the Full Mailbox1, which OCC uses to alert TMGT.
+ * This is the actual data that HWSV gets from the PIB, which it
+ * then uses to notify TMGT of an alert, and sends TMGT the msg_payload
+ */
+typedef struct
+{
+ /// Unused: Identifier assigned by originating endpoint for correlating
+ /// sync message responses.
+ uint32_t msg_id;
+ /// FSI2HOST Assigned Queue ID. 0x80000000 - 0xFFFFFFFF = FSP msg_queue,
+ /// 0x0 - 0x80000000 = Hostboot msg_queue. 0x80000007 = OCC
+ uint32_t msg_queue_id;
+ /// Message Payload (what TMGT gets)
+ mbox_payload_t msg_payload;
+} mbox_msg_t;
+
+/**
+ * @struct mbox_data_area_regs_t
+ * @brief Union of the Full Mailbox1, which OCC uses to alert TMGT.
+ * Since the data is SCOM'd, we want to parse it by uint64_t's
+ * to do the scom, and fill it out using the mbox_msg_t.
+ */
+typedef union
+{
+ /// Parsed out fields the way OCC & TMGT interpret them
+ mbox_msg_t fields;
+ /// Words used in putscoms
+ uint64_t word[8];
+} mbox_data_area_regs_t;
+
+
+/*******************************************************************/
+/* Globals */
+/*******************************************************************/
+extern eFsi2HostMboxState G_fsi2host_mbox_ready; // @th036
+extern eCmdhWakeupThreadMask G_cmdh_thread_wakeup_mask; // @th039
+extern fsp_cmd_t G_htmgt_cmd_buffer;
+extern fsp_rsp_t G_htmgt_rsp_buffer;
+
+/*******************************************************************/
+/* Function Prototypes */
+/*******************************************************************/
+int cmdh_fsp_attention(uint32_t i_type);
+int cmdh_fsp_attention_withRetry(uint32_t i_type, int i_timeout_in_ms); // @th039
+
+void notifyCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond); // @th039
+void clearCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond); // @th039
+int cmdh_thread_wait_for_wakeup(void); // @th039
+
+errlHndl_t cmdh_fsp_cmd_hndler(void);
+
+errlHndl_t cmdh_fsp_init(void);
+
+void cmdh_build_errl_rsp(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr,
+ ERRL_RC i_rc,
+ errlHndl_t * io_errlHndl); // @th036
+
+#endif
+
diff --git a/src/occ/cmdh/cmdh_fsp_cmds.c b/src/occ/cmdh/cmdh_fsp_cmds.c
new file mode 100755
index 0000000..a9dac60
--- /dev/null
+++ b/src/occ/cmdh/cmdh_fsp_cmds.c
@@ -0,0 +1,1841 @@
+/******************************************************************************
+// @file cmdh_fsp_cmds.c
+// @brief Command Handling for FSP Communication.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_fsp_cmds_c cmdh_fsp_cmds.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 04/05/2012 Created
+ * @th013 thallet 07/24/2012 Minor changes for VPO/HW compile
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th014 thallet 08/02/2012 SMS was returning rc=0x15
+ * @th015 thallet 08/03/2012 Changes to notify AMEC of data changes
+ * @at008 alvinwan 08/09/2012 Support AME Pass Thru command from TMGT
+ * @th022 thallet 10/03/2012 Changes for OCC coming up as slave
+ * @ai006 863413 ailutsar 11/28/2012 Update occtool to grab a full trace log from OCC
+ * @nh004 864941 neilhsu 12/20/2012 Support get/delete errl & added trace info
+ * @th029 thallet 01/23/2013 Test Applet stats & function via FSP commands
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @gs003 878457 gjsilva 04/17/2013 Support for get_sensor option
+ * @th032 thallet 04/16/2013 Tuleta HW Bringup
+ * @th036 881677 thallet 05/06/2013 New Poll Command Support
+ * @jh001 881996 joshych 05/07/2013 Support SRAM error log format
+ * @gm002 885429 milesg 05/30/2013 Support for 16 bit type and location
+ * @jh002 887903 joshych 06/17/2013 Support Get Field Debug Data command
+ * @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
+ * @th043 892554 thallet 07/23/2013 Automatic Nominal/Active state change
+ * @th046 894648 thallet 08/08/2013 Automatic Nominal/Active state change mod
+ * @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+ * @cc001 897953 cjcain 09/06/2013 Removed Automatic Nominal/Active state change
+ * @gs013 901118 gjsilva 10/11/2013 Support for RESET_PREP command from TMGT
+ * @rt001 902613 tapiar 10/17/2013 IPS poll response info
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @rc006 906038 rickylie 11/11/2013 OCC: Investigate/Test OCC Tracing
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gs019 908218 gjsilva 12/04/2013 Support cooling request architecture
+ * @jh009 908383 joshych 12/04/2013 Generate error logs when required for Reset Prep command
+ * @at019 908390 alvinwan 12/05/2013 Disable DPS algorithms from running in Sapphire
+ * @ly010 908832 lychen 12/09/2013 Sapphire update status for reset
+ * @gm017 909636 milesg 12/17/2013 commented out too much trace
+ * @gm021 912805 milesg 01/21/2014 Support for test applets
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ * @wb000 916142 wilbryan 02/18/2014 Support "DVFS due to OT/Power" bits in OCC poll response
+ * @gm029 917998 milesg 03/06/2014 Send slave inbox while in standby state
+ * @fk009 942864 fmkassem 09/22/2014 BMC/HTMGT Poll command 0x10 support
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "cmdh_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "dcom.h"
+#include "occ_common.h"
+#include "state.h"
+#include "cmdh_fsp_cmds.h"
+#include "cmdhDbugCmd.h"
+#include "appletManager.h"
+#include "gpsm.h"
+#include "pstates.h"
+#include "proc_pstate.h"
+#include "gpe_data.h"
+#include "centaur_data.h"
+#include <amec_data.h>
+#include "amec_amester.h" // @at008a
+#include "amec_service_codes.h" // @at008a
+#include "amec_freq.h" // @wb000
+#include "amec_sys.h" // @wb000
+#include "sensor.h"
+#include "sensorQueryList.h"
+#include "chom.h" // @jh005a
+#include "amec_master_smh.h"
+#include "thrm_thread.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+// We need to have a small structure in non-Applet space to keep track
+// of success & failures when running test applets. This needs to be
+// kept as small as possible.
+typedef struct
+{
+ uint16_t successful; // Number of Sucessful Test Applets
+ uint16_t failed; // Number of Failed Test Applets
+ uint16_t total; // Total Number of Test Applets
+ SsxTimebase duration; // Total Duration of Test Applets
+ errlHndl_t errlHndl; // Holds the first failure's errlHndl
+} testAppletStats_t; // @th029a
+
+testAppletStats_t G_testAppletStats = {0}; /// @th029a
+
+// This table contains tunable parameter information that can be exposed to
+// customers (only Master OCC should access/control this table)
+cmdh_tunable_param_table_t G_mst_tunable_parameter_table[CMDH_DEFAULT_TUNABLE_PARAM_NUM] =
+{
+ {1, "Utilization threshold for increasing frequency", 3, 0, 999, 0, 1000},
+ {2, "Utilization threshold for decreasing frequency", 3, 0, 999, 0, 1000},
+ {3, "Number of samples for computing utilization statistics", 4, 0, 4, 1, 1024},
+ {4, "Step size for going up in frequency", 3, 0, 8, 1, 1000},
+ {5, "Step size for going down in frequency", 3, 0, 8, 1, 1000},
+ {6, "Delta percentage for determining active cores", 2, 0, 18, 0, 100 },
+ {7, "Utilization threshold to determine active cores with slack", 3, 0, 980, 0, 1000},
+ {8, "Enable/disable frequency delta between cores", 0, 0, 0, 0, 1 },
+ {9, "Maximum frequency delta between cores", 2, 0, 10, 10, 100 },
+};
+
+// The first two columns of this table are the default tunable parameter values
+// and mutipliers.
+cmdh_tunable_param_table_ext_t G_mst_tunable_parameter_table_ext[CMDH_DEFAULT_TUNABLE_PARAM_NUM] =
+{
+ {999, 10, 9990},
+ {999, 10, 9990},
+ {4, 1, 4 },
+ {8, 1, 8 },
+ {8, 1, 8 },
+ {18, 100, 1800},
+ {980, 10, 980 },
+ {0, 1, 0 },
+ {10, 1, 10 },
+};
+
+// Flag to indicate that new tunable parameter values need to be written
+// (=0: no new values available; =1: new values need to be written; =2: restore defaults)
+uint8_t G_mst_tunable_parameter_overwrite = 0;
+
+extern thrm_fru_data_t G_thrm_fru_data[DATA_FRU_MAX];
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: cmdh_tmgt_poll
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_tmgt_poll (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ cmdh_poll_query_t * l_poll_cmd = (cmdh_poll_query_t *) i_cmd_ptr;
+ errlHndl_t l_errlHndl = NULL;
+ ERRL_RC l_rc = ERRL_RC_INTERNAL_FAIL;
+ uint8_t k = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ if(l_poll_cmd->version == CMDH_POLL_BASE_VERSION)
+ {
+ cmdh_poll_resp_v0_t * l_poll_rsp = (cmdh_poll_resp_v0_t *) o_rsp_ptr;
+
+ memset(l_poll_rsp,0,(size_t)sizeof(cmdh_poll_resp_v0_t));
+
+ l_poll_rsp->status.word = SMGR_validate_get_valid_states();
+ l_poll_rsp->ext_status.word = 0;
+ l_poll_rsp->ext_status.cooling_request = THRM_thread_get_cooling_request();
+
+ l_poll_rsp->occ_pres_mask = G_sysConfigData.is_occ_present;
+ l_poll_rsp->config_data = DATA_request_cnfgdata();
+ l_poll_rsp->state = CURRENT_STATE();
+ l_poll_rsp->ips_status.word = 0;
+
+ // @at019a - start
+ if( G_sysConfigData.system_type.kvm )
+ {
+ l_poll_rsp->mode = G_occ_external_req_mode_kvm;
+ }
+ else
+ {
+ l_poll_rsp->mode = CURRENT_MODE();
+ }
+ // @at019a - end
+
+ // @wb000 - start
+ l_poll_rsp->ext_status.dvfs_due_to_ot = 0;
+ l_poll_rsp->ext_status.dvfs_due_to_pwr = 0;
+
+ for ( k = 0; k < MAX_NUM_CORES; k++ )
+ {
+ uint32_t l_freq_reason = g_amec->proc[0].core[k].f_reason;
+ if ( l_freq_reason & (AMEC_VOTING_REASON_PROC_THRM | AMEC_VOTING_REASON_VRHOT_THRM) )
+ {
+ l_poll_rsp->ext_status.dvfs_due_to_ot = 1;
+ }
+
+ if ( l_freq_reason & (AMEC_VOTING_REASON_PPB | AMEC_VOTING_REASON_PMAX | AMEC_VOTING_REASON_PWR) )
+ {
+ l_poll_rsp->ext_status.dvfs_due_to_pwr = 1;
+ }
+ }
+ // @wb000 - end
+
+ // @rt001a
+ l_poll_rsp->ips_status.ips_enabled = G_ips_config_data.iv_ipsEnabled;
+ l_poll_rsp->ips_status.ips_active = AMEC_mst_get_ips_active_status();
+
+
+ l_poll_rsp->errl_id = getOldestErrlID();
+ l_poll_rsp->errl_address = getErrlOCIAddrByID(l_poll_rsp->errl_id);
+ l_poll_rsp->errl_length = getErrlLengthByID(l_poll_rsp->errl_id);
+
+ l_poll_rsp->data_length[0] = CONVERT_UINT16_UINT8_HIGH(CMDH_POLL_RESP_LEN_V0);
+ l_poll_rsp->data_length[1] = CONVERT_UINT16_UINT8_LOW(CMDH_POLL_RESP_LEN_V0);
+ l_rc = ERRL_RC_SUCCESS;
+ l_poll_rsp->rc = ERRL_RC_SUCCESS;
+
+ // TODO: Clear flag indicating we sent a 'poll request' to TMGT
+ }
+ else if (l_poll_cmd->version == CMDH_POLL_VERSION10)
+ {
+ l_rc = cmdh_poll_v10(o_rsp_ptr);
+ }
+ else
+ {
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+ } while(0);
+
+ if(l_rc)
+ {
+ /// Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errlHndl);
+ }
+
+
+ return l_errlHndl;
+}
+
+//@fk009a
+// Function Specification
+//
+// Name: cmdh_poll_v10
+//
+// Description: Used for version 0x10 poll calls from BMC/HTMGT.
+//
+// End Function Specification
+
+ERRL_RC cmdh_poll_v10(cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ ERRL_RC l_rc = ERRL_RC_INTERNAL_FAIL;
+ uint8_t k, i = 0;
+ cmdh_poll_sensor_db_t l_sensorHeader;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //Clear response buffer
+ memset(o_rsp_ptr, 0, (size_t)sizeof(cmdh_fsp_rsp_t));
+
+ //Set pointer to start of o_rsp_ptr
+ cmdh_poll_resp_v10_fixed_t * l_poll_rsp = (cmdh_poll_resp_v10_fixed_t *) o_rsp_ptr;
+
+ //Byte 1
+ l_poll_rsp->status.word = SMGR_validate_get_valid_states(); //TODO: Need to set FIR master?
+ //Byte 2
+ l_poll_rsp->ext_status.word = 0; //TODO: what values to set for memthrotOT and n power?
+
+ for ( k = 0; k < MAX_NUM_CORES; k++ )
+ {
+ uint32_t l_freq_reason = g_amec->proc[0].core[k].f_reason;
+ if ( l_freq_reason & (AMEC_VOTING_REASON_PROC_THRM | AMEC_VOTING_REASON_VRHOT_THRM) )
+ {
+ l_poll_rsp->ext_status.dvfs_due_to_ot = 1;
+ }
+
+ if ( l_freq_reason & (AMEC_VOTING_REASON_PPB | AMEC_VOTING_REASON_PMAX | AMEC_VOTING_REASON_PWR) )
+ {
+ l_poll_rsp->ext_status.dvfs_due_to_pwr = 1;
+ }
+ }
+
+ //Byte 3
+ l_poll_rsp->occ_pres_mask = G_sysConfigData.is_occ_present;
+ //Byte 4
+ l_poll_rsp->config_data = DATA_request_cnfgdata();
+ //Byte 5
+ l_poll_rsp->state = CURRENT_STATE();
+ //Byte 6 - 7 reserved.
+ //Byte 8:
+ l_poll_rsp->errl_id = getOldestErrlID();
+ //Byte 9 - 12:
+ l_poll_rsp->errl_address = getErrlOCIAddrByID(l_poll_rsp->errl_id);
+ //Byte 13 - 14:
+ l_poll_rsp->errl_length = getErrlLengthByID(l_poll_rsp->errl_id);
+ //Byte 15 - 16: reserved.
+ //Byte 17 - 32 (16 bytes): OCC level
+ memcpy( (void *) l_poll_rsp->occ_level, (void *) &G_occ_buildname[0], 16);
+ //Byte 33 - 38:
+ char l_sensor_ec[6] = "SENSOR";
+ memcpy( (void *) l_poll_rsp->sensor_ec, (void *) &l_sensor_ec[0], (size_t) sizeof(l_sensor_ec));
+ //Byte 39:
+ l_poll_rsp->sensor_dblock_count = 0;
+ //Byte 40:
+ l_poll_rsp->sensor_dblock_version = 0x01; //Currently only 0x01 is supported.
+
+ //TODO add sensor data at o_rsp_buffer location after sizeof cmdh_poll_resp_v10_fixed_t
+ uint16_t l_rsp_index = CMDH_POLL_RESP_LEN_V10;
+
+ //fmk009 - TODO improvement: Run applet to obtain list of sensors to return and generate the
+ // list dynamically instead.
+
+ //Static list of sensors to return. TEMP, FREQ, and Power
+ uint16_t l_tempSensors[]={TEMP2MSP0C0,TEMP2MSP0C1,TEMP2MSP0C2,TEMP2MSP0C3,TEMP2MSP0C4,TEMP2MSP0C5,TEMP2MSP0C6,TEMP2MSP0C7,TEMP2MSP0C8,TEMP2MSP0C9,TEMP2MSP0C10,TEMP2MSP0C11};
+ uint8_t l_tempSensorCount = sizeof(l_tempSensors)/sizeof(uint16_t);
+ uint16_t l_freqSensors[]={FREQA2MSP0C0,FREQA2MSP0C1,FREQA2MSP0C2,FREQA2MSP0C3,FREQA2MSP0C4,FREQA2MSP0C5,FREQA2MSP0C6,FREQA2MSP0C7,FREQA2MSP0C8,FREQA2MSP0C9,FREQA2MSP0C10,FREQA2MSP0C11};
+ uint8_t l_freqSensorCount = sizeof(l_tempSensors)/sizeof(uint16_t);
+ uint16_t l_powrSensors[]={PWR250US,PWR250USFAN,PWR250USIO,PWR250USSTORE,PWR250USGPU,PWR250USP0,PWR250USVDD0,PWR250USVCS0,PWR250USMEM0};
+ uint8_t l_powrSensorCount = sizeof(l_powrSensors)/sizeof(uint16_t);
+
+ ////////////////////////////////////////
+ //Generate datablock header for temp sensors and sensor data.
+ memset((void*) &l_sensorHeader, 0, (size_t)sizeof(cmdh_poll_sensor_db_t));
+ memcpy ((void *) &(l_sensorHeader.eyecatcher[0]), SENSOR_TEMP, 4);
+ l_sensorHeader.format = 0xbb; //???what is this supposed to be?
+ l_sensorHeader.length = sizeof(cmdh_poll_temp_sensor_t);
+ l_sensorHeader.count = 0;
+ if (l_tempSensorCount)
+ {
+ //Generate sensor list.
+ cmdh_poll_temp_sensor_t l_sensorlist[l_tempSensorCount];
+ for (i = 0; i < l_tempSensorCount; i++)
+ {
+ if (1) //G_amec_sensor_list[l_tempSensors[i]]->ipmi_sid != 0) //??? Do we only report those that have ipmisid and value?
+ {
+ l_sensorlist[l_sensorHeader.count].id = G_amec_sensor_list[l_tempSensors[i]]->ipmi_sid;
+ l_sensorlist[l_sensorHeader.count].value = G_amec_sensor_list[l_tempSensors[i]]->sample;
+ l_sensorHeader.count++;
+ }
+ }
+ //Write data to resp buffer if any.
+ if (l_sensorHeader.count)
+ {
+ uint8_t l_sensordataSz = l_sensorHeader.count * l_sensorHeader.length;
+ //Copy header to response buffer.
+ memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), &l_sensorHeader, sizeof(l_sensorHeader));
+ //Increment index into response buffer.
+ l_rsp_index += sizeof(l_sensorHeader);
+ //Copy sensor data into response buffer.
+ memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), l_sensorlist, l_sensordataSz);
+ //Increment index into response buffer.
+ l_rsp_index += l_sensordataSz;
+
+ l_poll_rsp->sensor_dblock_count +=1;
+ }
+ }
+
+ //TRAC_IMP("Added Temp Sensors. Current size of response: %i. count of tempsensors:%i.", l_rsp_index,
+ // l_sensorHeader.count);
+
+
+ ////////////////////////////////////////
+ //Generate datablock header for freq sensors and sensor data.
+ memset((void*) &l_sensorHeader, 0, (size_t)sizeof(cmdh_poll_sensor_db_t));
+ memcpy ((void *) &(l_sensorHeader.eyecatcher[0]), SENSOR_FREQ, 4);
+ l_sensorHeader.format = 0xff; //???what is this supposed to be?
+ l_sensorHeader.length = sizeof(cmdh_poll_freq_sensor_t);
+ l_sensorHeader.count = 0;
+ if (l_freqSensorCount)
+ {
+ //Generate sensor list.
+ cmdh_poll_freq_sensor_t l_sensorlist[l_freqSensorCount];
+ for (i = 0; i < l_freqSensorCount; i++)
+ {
+ if (1) //G_amec_sensor_list[l_freqSensors[i]]->ipmi_sid != 0) //??? Do we only report those that have ipmisid and value?
+ {
+ l_sensorlist[l_sensorHeader.count].id = G_amec_sensor_list[l_freqSensors[i]]->ipmi_sid;
+ l_sensorlist[l_sensorHeader.count].value = G_amec_sensor_list[l_freqSensors[i]]->sample;
+ l_sensorHeader.count++;
+ }
+ }
+ //Write data to outbuffer if any.
+ if (l_sensorHeader.count)
+ {
+ uint8_t l_sensordataSz = l_sensorHeader.count * l_sensorHeader.length;
+ //Copy header to response buffer.
+ memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), &l_sensorHeader, sizeof(l_sensorHeader));
+ //Increment index into response buffer.
+ l_rsp_index += sizeof(l_sensorHeader);
+ //Copy sensor data into response buffer.
+ memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), l_sensorlist, l_sensordataSz);
+ //Increment index into response buffer.
+ l_rsp_index += l_sensordataSz;
+
+ l_poll_rsp->sensor_dblock_count +=1;
+ }
+
+ }
+
+ //TRAC_IMP("Added Freq Sensors. Current size of response: %i. count of freqsensors:%i.", l_rsp_index,
+ // l_sensorHeader.count);
+
+
+ ////////////////////////////////////////
+ //Generate datablock header for power sensors and sensor data. RETURNED by MASTER ONLY.
+ if (G_occ_role == OCC_MASTER)
+ {
+ memset((void*) &l_sensorHeader, 0, (size_t)sizeof(cmdh_poll_sensor_db_t));
+ memcpy ((void *) &(l_sensorHeader.eyecatcher[0]), SENSOR_POWR, 4);
+ l_sensorHeader.format = 0xff; //???what is this supposed to be?
+ l_sensorHeader.length = sizeof(cmdh_poll_power_sensor_t);
+ l_sensorHeader.count = 0;
+ if (l_powrSensorCount)
+ {
+ //Generate sensor list.
+ cmdh_poll_power_sensor_t l_sensorlist[l_powrSensorCount];
+ for (i = 0; i < l_powrSensorCount; i++)
+ {
+ if (1) //G_amec_sensor_list[l_powrSensors[i]]->ipmi_sid != 0) //??? Do we only report those that have ipmisid and value?
+ {
+ l_sensorlist[l_sensorHeader.count].id = G_amec_sensor_list[l_powrSensors[i]]->ipmi_sid;
+ l_sensorlist[l_sensorHeader.count].current = G_amec_sensor_list[l_powrSensors[i]]->sample;
+ l_sensorlist[l_sensorHeader.count].accumul = G_amec_sensor_list[l_powrSensors[i]]->accumulator;
+ l_sensorlist[l_sensorHeader.count].update_tag = G_amec_sensor_list[l_powrSensors[i]]->update_tag;
+ l_sensorHeader.count++;
+
+ }
+ }
+ //Write data to outbuffer if any.
+ if (l_sensorHeader.count)
+ {
+ uint8_t l_sensordataSz = l_sensorHeader.count * l_sensorHeader.length;
+ //Copy header to response buffer.
+ memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), &l_sensorHeader, sizeof(l_sensorHeader));
+ //Increment index into response buffer.
+ l_rsp_index += sizeof(l_sensorHeader);
+ //Copy sensor data into response buffer.
+ memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), l_sensorlist, l_sensordataSz);
+ //Increment index into response buffer.
+ l_rsp_index += l_sensordataSz;
+
+ l_poll_rsp->sensor_dblock_count +=1;
+ }
+ }
+
+ //TRAC_IMP("Added Pwr Sensors. Current size of response: %i. count of powrsensors:%i.", l_rsp_index,
+ // l_sensorHeader.count);
+ }
+
+
+ //fk009a - TODO add PowerCap data.!!!
+
+
+ l_poll_rsp->data_length[0] = CONVERT_UINT16_UINT8_HIGH(l_rsp_index);
+ l_poll_rsp->data_length[1] = CONVERT_UINT16_UINT8_LOW(l_rsp_index);
+ l_rc = ERRL_RC_SUCCESS;
+ l_poll_rsp->rc = ERRL_RC_SUCCESS;
+
+ return l_rc;
+}
+
+
+
+
+// Function Specification
+//
+// Name: cmdh_tmgt_query_fw
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void cmdh_tmgt_query_fw (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ cmdh_fw_resp_t * l_fw_data = (cmdh_fw_resp_t *) o_rsp_ptr;
+
+ l_fw_data->rc = ERRL_RC_SUCCESS;
+ l_fw_data->data_length[0] = 0;
+ l_fw_data->data_length[1] = CMDH_FW_QUERY_RESP_LEN;
+
+ // Copy the buildname into the response
+ memcpy( (void *) l_fw_data->fw_level,
+ (void *) &G_occ_buildname[0],
+ (size_t) CMDH_FW_QUERY_RESP_LEN); // @th022
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_reset_prep_t
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_reset_prep (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ cmdh_reset_prep_t * l_cmd_ptr = (cmdh_reset_prep_t *) i_cmd_ptr;
+ errlHndl_t l_errlHndl = NULL;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+ bool l_ffdc = FALSE; // @jh009a
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ o_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ o_rsp_ptr->data_length[0] = 0;
+ o_rsp_ptr->data_length[1] = 0;
+
+ do
+ {
+ // Command Length Check - make sure we at least have a version number
+ if( CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) < CMDH_RESET_PREP_MIN_DATALEN)
+ {
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ // Version Number Check
+ if(l_cmd_ptr->version != CMDH_RESET_PREP_VERSION)
+ {
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ TRAC_IMP("cmdh_reset_prep: Prep for reset command received! reason[0x%.2X]",
+ l_cmd_ptr->reason);
+
+ // Command Handling
+ switch( l_cmd_ptr->reason )
+ {
+ case CMDH_PREP_NONFAILURE:
+ // No FFDC Error Log Needed
+ l_rc = ERRL_RC_SUCCESS;
+ break;
+
+ case CMDH_PREP_FAILON_THISOCC:
+ l_ffdc = TRUE; // @jh009a
+ l_rc = ERRL_RC_SUCCESS;
+ break;
+
+ case CMDH_PREP_FAILON_OTHEROCC:
+ // If OCC is master, we may want to generate FFDC log
+ if (G_occ_role == OCC_MASTER) // @jh009a
+ {
+ l_ffdc = TRUE;
+ }
+ l_rc = ERRL_RC_SUCCESS;
+ break;
+
+ case CMDH_PREP_FAILON_OTHERNODE:
+ // No FFDC Error Log Needed
+ l_rc = ERRL_RC_SUCCESS;
+ break;
+
+ default:
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // @jh009a - start
+ // Generate FFDC error log if required
+ if (TRUE == l_ffdc)
+ {
+ /* @
+ * @errortype
+ * @moduleid DATA_GET_RESET_PREP_ERRL
+ * @reasoncode PREP_FOR_RESET
+ * @userdata1 reset reason
+ * @userdata2 0
+ * @userdata4 0
+ * @devdesc Generate error log for ResetPrep command
+ */
+ l_errlHndl = createErrl(
+ DATA_GET_RESET_PREP_ERRL, //modId
+ PREP_FOR_RESET, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ CMDH_RESET_PREP_TRACE_SIZE, //Trace Size
+ l_cmd_ptr->reason, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ if (l_errlHndl != NULL)
+ {
+ commitErrl(&l_errlHndl);
+ }
+ }
+ // @jh009a - end
+ if (G_sysConfigData.system_type.kvm && isSafeStateRequested())
+ {
+ //Notify dcom thread to update sapphire table
+ ssx_semaphore_post(&G_dcomThreadWakeupSem); //gm025
+ }
+ if (CURRENT_STATE() != OCC_STATE_STANDBY)
+ {
+ // Put OCC in stand-by state
+ l_errlHndl = SMGR_set_state(OCC_STATE_STANDBY);
+ }
+
+ if(l_errlHndl)
+ {
+ // Commit error log for the failed transition
+ commitErrl(&l_errlHndl);
+ TRAC_ERR("cmdh_reset_prep: Failed to transition to stand-by state!");
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ }
+ else
+ {
+ // Prevent the OCC from going back to the original state it was
+ // prior to the reset prep command
+ if (G_occ_role == OCC_MASTER)
+ {
+ G_occ_external_req_state = OCC_STATE_STANDBY;
+ }
+ }
+
+ } while(0);
+
+ o_rsp_ptr->rc = l_rc;
+
+ if(ERRL_RC_SUCCESS != l_rc)
+ {
+ // Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errlHndl);
+ }
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_tmgt_query_fw
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_clear_elog (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr) // @nh004c
+{
+ cmdh_clear_elog_query_t *l_cmd_ptr = (cmdh_clear_elog_query_t *) i_cmd_ptr;
+ uint8_t l_SlotNum = ERRL_INVALID_SLOT;
+ errlHndl_t l_err = INVALID_ERR_HNDL;
+ errlHndl_t l_oci_address = INVALID_ERR_HNDL;
+
+ o_rsp_ptr->data_length[0] = 0;
+ o_rsp_ptr->data_length[1] = 0;
+
+ // Get Errl Array index
+ l_SlotNum = getErrSlotNumByErrId(l_cmd_ptr->elog_id);
+
+ // Get ERRL address
+ l_oci_address = (errlHndl_t)getErrSlotOCIAddr(l_SlotNum);
+
+ if ((l_oci_address != NULL) && // jh001c
+ (l_oci_address != INVALID_ERR_HNDL))
+ {
+ // clear only one Errl by ID
+ l_err = deleteErrl(&l_oci_address);
+ }
+
+ if (l_err == NULL)
+ {
+ o_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ }
+ else
+ {
+ /// Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err); // @th036
+ }
+
+ return l_err;
+}
+
+// @ai006a
+// Function Specification
+//
+// Name: cmdh_dbug_get_trace
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void cmdh_dbug_get_trace (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ UINT l_rc = 0; // @rc006a
+ UINT l_trace_buffer_size = CMDH_FSP_RSP_SIZE-CMDH_DBUG_FSP_RESP_LEN-8; // @rc006a - tmgt reserved 8 bytes
+ UINT16 l_trace_size = 0;
+ cmdh_dbug_get_trace_query_t *l_get_trace_query_ptr = (cmdh_dbug_get_trace_query_t*) i_cmd_ptr;
+ cmdh_dbug_get_trace_resp_t *l_get_trace_resp_ptr = (cmdh_dbug_get_trace_resp_t*) o_rsp_ptr;
+
+ // @rc006c - get trace data
+ tracDesc_t l_trace_ptr = TRAC_get_td((char *)l_get_trace_query_ptr->comp);
+ l_rc = TRAC_get_buffer_partial(l_trace_ptr, l_get_trace_resp_ptr->data,&l_trace_buffer_size);
+ l_trace_size = l_trace_buffer_size;
+ if(l_rc==0)
+ {
+ o_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ o_rsp_ptr->data_length[0] = CONVERT_UINT16_UINT8_HIGH(l_trace_size);
+ o_rsp_ptr->data_length[1] = CONVERT_UINT16_UINT8_LOW(l_trace_size);
+ }
+ else
+ {
+ o_rsp_ptr->rc = ERRL_RC_INTERNAL_FAIL;
+ o_rsp_ptr->data_length[0] = 0;
+ o_rsp_ptr->data_length[1] = 0;
+ }
+}
+
+// Function Specification
+//
+// Name: cmdh_dbug_get_ame_sensor
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void cmdh_dbug_get_ame_sensor (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_type = 0;
+ uint16_t l_location = 0;
+ uint16_t i = 0;
+ uint16_t l_resp_data_length = 0;
+ uint16_t l_num_of_sensors = CMDH_DBUG_MAX_NUM_SENSORS;
+ cmdh_dbug_get_sensor_query_t *l_cmd_ptr = (cmdh_dbug_get_sensor_query_t*) i_cmd_ptr;
+ cmdh_dbug_get_sensor_resp_t *l_resp_ptr = (cmdh_dbug_get_sensor_resp_t*) o_rsp_ptr;
+ sensorQueryList_t l_sensor_list[CMDH_DBUG_MAX_NUM_SENSORS];
+ sensor_t *l_sensor_ptr = NULL;
+ errlHndl_t l_err = NULL;
+ OCC_APLT_STATUS_CODES l_status = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // Do sanity check on the function inputs
+ if ((NULL == i_cmd_ptr) || (NULL == o_rsp_ptr))
+ {
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ // Capture user inputs
+ l_type = l_cmd_ptr->type;
+ l_location = l_cmd_ptr->location;
+ TRAC_INFO("dbug_get_ame_sensor: Type[0x%04x] Location[0x%04x]",
+ l_type,
+ l_location);
+
+ // Initialize the Applet arguments
+ querySensorListAppletArg_t l_applet_arg = {
+ 0, // i_startGsid - start with sensor 0x0000
+ 0, // i_present
+ l_type, // i_type - passed by the caller
+ l_location, // i_loc - passed by the caller
+ &l_num_of_sensors, // io_numOfSensors
+ l_sensor_list, // o_sensors
+ NULL // o_sensorInfoPtr
+ };
+
+ // Call the sensor query list applet
+ runApplet(OCC_APLT_SNSR_QUERY,
+ &l_applet_arg,
+ TRUE,
+ NULL,
+ &l_err,
+ &l_status);
+
+ if (NULL != l_err)
+ {
+ // Query failure, this should not happen
+ TRAC_ERR("dbug_get_ame_sensor: Failed to run OCC_APLT_SNSR_QUERY applet. Error status is: 0x%x",
+ l_status);
+
+ // Commit error log
+ commitErrl(&l_err);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ else
+ {
+ TRAC_INFO("dbug_get_ame_sensor: Numbers of sensors found[%u]",
+ l_num_of_sensors);
+
+ if (l_num_of_sensors > CMDH_DBUG_MAX_NUM_SENSORS)
+ {
+ // Got too many sensors back, need to truncate the list
+ TRAC_INFO("dbug_get_ame_sensor: Got too many sensors back[%u]. Truncating number of sensors to %u",
+ l_num_of_sensors,
+ CMDH_DBUG_MAX_NUM_SENSORS);
+
+ l_num_of_sensors = CMDH_DBUG_MAX_NUM_SENSORS;
+ }
+
+ // Populate the response data packet
+ l_resp_ptr->num_sensors = l_num_of_sensors;
+ for (i=0; i<l_num_of_sensors; i++)
+ {
+ l_resp_ptr->sensor[i].gsid = l_sensor_list[i].gsid;
+ l_resp_ptr->sensor[i].sample = l_sensor_list[i].sample;
+ strcpy(l_resp_ptr->sensor[i].name, l_sensor_list[i].name);
+
+ // Capture the min and max value for this sensor
+ l_sensor_ptr = getSensorByGsid(l_sensor_list[i].gsid);
+ if (l_sensor_ptr == NULL)
+ {
+ TRAC_INFO("dbug_get_ame_sensor: Didn't find sensor with gsid[0x%.4X]. Min/Max values won't be accurate.",
+ l_sensor_list[i].gsid);
+
+ // Didn't find this sensor, just continue
+ continue;
+ }
+ l_resp_ptr->sensor[i].sample_min = l_sensor_ptr->sample_min;
+ l_resp_ptr->sensor[i].sample_max = l_sensor_ptr->sample_max;
+ l_resp_ptr->sensor[i].ipmi_sid = l_sensor_ptr->ipmi_sid; //@fk009a
+ }
+ }
+
+ }while(0);
+
+ // Populate the response data header
+ l_resp_data_length = sizeof(cmdh_dbug_get_sensor_resp_t) -
+ CMDH_DBUG_FSP_RESP_LEN;
+ o_rsp_ptr->rc = l_rc;
+ o_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0];
+ o_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1];
+}
+
+// Function Specification
+//
+// Name: cmdh_dbug_peek
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void cmdh_dbug_peek (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ cmdh_dbug_peek_t * l_cmd_ptr = (cmdh_dbug_peek_t*) i_cmd_ptr;
+ uint32_t l_len = l_cmd_ptr->size;
+ uint8_t l_type = l_cmd_ptr->type;
+ uint32_t l_addr = l_cmd_ptr->oci_address;
+
+ static Ppc405MmuMap L_mmuMapHomer;
+ static Ppc405MmuMap L_mmuMapCommon;
+
+
+ switch(l_type)
+ {
+ case 0x01: // OCI Direct Read
+ // Make sure we don't overflow our response buffer
+ l_len = (l_len > CMDH_FSP_RSP_DATA_SIZE ) ? CMDH_FSP_RSP_DATA_SIZE : l_len;
+
+ // Read the data
+ memcpy( (void *) &o_rsp_ptr->data[0],
+ (void *) l_addr,
+ (size_t) l_len );
+ break;
+
+ case 0x02: // DMA Read
+ // Make sure we don't overflow our response buffer
+ l_len = (l_len > CMDH_FSP_RSP_DATA_SIZE ) ? CMDH_FSP_RSP_DATA_SIZE : l_len;
+
+ // TODO: didn't do anything, respond with zero bytes
+ l_len = 0;
+ break;
+
+ case 0x03: // Invalidate Cache
+ //dcache_invalidate( (void *) l_addr, l_len );
+ l_len = 0;
+ break;
+
+ case 0x04: // Flush Cache
+ dcache_flush( (void *) l_addr, l_len );
+ l_len = 0;
+ break;
+
+ case 0x05: // MMU Map Mainstore
+ // Map mainstore to oci space so that we can peek at it
+
+ // HOMER Image
+ ppc405_mmu_map(0x00000000, // Mainstore address (BAR0, offset 0)
+ 0x00000000, // OCI address 0x0 (BAR0)
+ 0x400000, // Size = 4 MB
+ 0, // TLB hi flags
+ 0, // TLB lo flags
+ &L_mmuMapHomer); // map pointer
+
+ // COMMON Image = Communal OCC Memory Map On Node
+ ppc405_mmu_map(0x30000000, // Mainstore address (BAR3, offset 0)
+ 0x30000000, // OCI address 0x30000000
+ 0x00800000, // Size = 8 MB
+ 0, // TLB hi flags
+ 0, // TLB lo flags
+ &L_mmuMapCommon); // map pointer
+ l_len = 0;
+ break;
+ case 0x06: // MMU UnMap Mainstore
+ // HOMER Image
+ ppc405_mmu_unmap(&L_mmuMapHomer);
+
+ // COMMON Image = Communal OCC Memory Map On Node
+ ppc405_mmu_unmap(&L_mmuMapCommon);
+
+ l_len = 0;
+ break;
+
+ default:
+ // Didn't do anything, respond with zero bytes
+ l_len = 0;
+ break;
+ }
+
+ o_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ o_rsp_ptr->data_length[0] = CONVERT_UINT16_UINT8_HIGH(l_len);
+ o_rsp_ptr->data_length[1] = CONVERT_UINT16_UINT8_LOW(l_len);
+}
+
+
+// Function Specification
+//
+// Name: cmdh_get_elog
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_get_elog (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr) // @nh004a
+{
+ uint8_t l_lastID = getOldestErrlID();
+ uint8_t l_SlotNum = 0;
+ errlHndl_t l_errlHndl = INVALID_ERR_HNDL;
+
+ cmdh_get_elog_resp_t *l_rsp_ptr = (cmdh_get_elog_resp_t *) o_rsp_ptr;
+
+ l_rsp_ptr->data_length[0] = 0;
+ l_rsp_ptr->data_length[1] = CMDH_GET_ELOG_RESP_LEN;
+
+ // Get slot num of last-Get-Err-log, return ERRL_INVALID_SLOT if not found
+ l_SlotNum = getErrSlotNumByErrId(l_lastID);
+
+ if (l_SlotNum != ERRL_INVALID_SLOT)
+ {
+ // clear error handle
+ l_errlHndl = NULL;
+
+ l_rsp_ptr->rc = ERRL_RC_SUCCESS;
+
+ // Get and return OCI address of last-Get-Err-log, return NULL if not found
+ l_rsp_ptr->oci_address = getErrSlotOCIAddr(l_SlotNum);
+ l_rsp_ptr->elog_id = l_lastID;
+ }
+ else
+ {
+ l_errlHndl = NULL;
+
+ l_rsp_ptr->rc = ERRL_RC_CONDITIONAL_SUCCESS;
+
+ // no data should be returned
+ l_rsp_ptr->oci_address = 0;
+ l_rsp_ptr->elog_id = 0;
+ }
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: dbug_parse_cmd
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void cmdh_dbug_cmd (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = 0;
+ uint8_t l_sub_cmd = 0;
+ uint8_t l_block_num = 0; // @th029a
+ errl_generic_resp_t * l_err_rsp_ptr = (errl_generic_resp_t *) o_rsp_ptr;
+ errlHndl_t l_errl = NULL;
+ //uint32_t l_addr = 0;
+ //uint8_t l_temp = 0;
+ OCC_APLT_STATUS_CODES l_status = OCC_APLT_SUCCESS;
+ cmdhDbugCmdAppletArg_t l_applet_args;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Sub Command for debug is always first byte of data
+ l_sub_cmd = i_cmd_ptr->data[0];
+
+ /// Tracing based on Debug Sub-Command
+ switch (l_sub_cmd)
+ {
+ // ----------------------------------------------------
+ // NOTE: This for for TRACING only, any actual command
+ // handling goes in the switch statement below.
+ // ----------------------------------------------------
+ case DBUG_GET_TRACE: // FALLTHROUGH
+ case DBUG_GET_AME_SENSOR: // FALLTHROUGH
+ // Don't trace that we got these debug commands, they happen too
+ // often, or are not destructive when they do occur.
+ break;
+
+ default:
+ // Trace the rest of the debug commands.
+ TRAC_INFO("Debug Command: Sub:0x%02x\n", l_sub_cmd);
+ break;
+ }
+
+ /// Act on Debug Sub-Command
+ switch ( l_sub_cmd )
+ {
+ // ------------------------------------------------
+ // Run debug sub-commands that **cannot** use applets
+ // ------------------------------------------------
+ case DBUG_GET_AME_SENSOR:
+ // This can't use an applet because it needs to run
+ // an applet to get the data
+ cmdh_dbug_get_ame_sensor(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case DBUG_FSP_ATTN:
+ // This is so small that we don't need to run it from an
+ // applet
+ break;
+
+ case DBUG_GET_TRACE: // @ai006a
+ // Get trace buffer SRAM address
+ cmdh_dbug_get_trace(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case DBUG_CLEAR_TRACE: // @ai006a
+ // Call clear trace function
+ TRAC_reset_buf();
+ o_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ break;
+
+ case DBUG_PEEK:
+ cmdh_dbug_peek(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case DBUG_FLUSH_DCACHE:
+ // This is so small that we don't need to run it from an
+ // applet
+ dcache_flush_all();
+ break;
+
+ case DBUG_GEN_CHOM_LOG: // @jh005a
+ chom_force_gen_log();
+ break;
+
+ case 0xE0: // Run Test Applet // @th029a - whole case
+ // TODO: Come in and clean this up later
+#define TEST_APPLET_MAX_BLOCK_NUMBER 8
+#define TEST_APPLET_START_APPLET 0xFF
+#define TEST_APPLET_GET_STATS 0xFE
+#define TEST_APPLET_RESET_STATS 0xFD
+
+ // We need to waste the OCC SRAM space to start these applets, but
+ // lets try to use up as little code as possible
+
+ // Get the 2kB "Block Number" as passed in as the second data
+ // byte of the command.
+ l_block_num = i_cmd_ptr->data[1];
+
+ // If the block number that was passed is a valid data block,
+ // then copy the passed data into Main Memory
+ if(l_block_num < TEST_APPLET_MAX_BLOCK_NUMBER)
+ {
+ BceRequest pba_copy;
+ int l_ssxrc = SSX_OK;
+ // Calculate Address in Main Memory where we will put this block
+ uint32_t l_addr_in_mem = ( G_ApltAddressTable[OCC_APLT_TEST].iv_aplt_address
+ + (l_block_num*2048));
+ // Can't copy to last 1024 bytes of SRAM
+ size_t l_size = (l_block_num == 0x07) ? 1024 : 2048;
+
+ TRAC_INFO("uploading %d bytes of test applet block %d from 0x%08x to 0x%08x",
+ l_size, l_block_num, &i_cmd_ptr->data[124], l_addr_in_mem);
+
+ // Set up copy request
+ l_ssxrc = bce_request_create(
+ &pba_copy, // block copy object
+ &G_pba_bcue_queue, // mainstore to sram copy engine
+ l_addr_in_mem, // mainstore address
+ (uint32_t) &i_cmd_ptr->data[124], // sram starting address
+ (size_t) l_size, // size of copy
+ SSX_SECONDS(5), // no timeout
+ NULL, // call back
+ NULL, // call back arguments
+ ASYNC_REQUEST_BLOCKING // callback mask
+ );
+
+ // Don't log error. We are in a debug path, not product code.
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("CMDH Test Applet: PBA request create failure rc=[%08X]",l_ssxrc);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ // Do actual copying
+ l_ssxrc = bce_request_schedule(&pba_copy);
+
+ // Don't log error. We are in a debug path, not product code.
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("CMDH Test Applet: PBA request schedule failure rc=[%08X]",l_ssxrc);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ }
+ else if(l_block_num == TEST_APPLET_START_APPLET)
+ {
+ TRAC_INFO("Starting test applet");
+ OCC_APLT_STATUS_CODES l_status = OCC_APLT_SUCCESS;
+ errlHndl_t l_errl = NULL;
+ //SsxTimebase l_start = ssx_timebase_get();
+
+ // ------------------------------------------
+ // Start Applet, and return
+ // \_ Applet will auto-checksum itself, and
+ // fail w/ errlHndl if it doesn't match
+ // ------------------------------------------
+ runApplet(OCC_APLT_TEST, // Applet enum Name
+ NULL, // Applet arguments
+ FALSE, // Blocking call?
+ NULL, // Applet finished semaphore
+ &l_errl, // Error log handle
+ &l_status); // Error status
+
+ // Increment total after it completes, fail or not
+ //G_testAppletStats.total++;
+ //G_testAppletStats.duration += (ssx_timebase_get() - l_start);
+
+ if( (NULL != l_errl) || (l_status != OCC_APLT_SUCCESS))
+ {
+ TRAC_ERR("Test applet failure. status=%d", l_status);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ // ------------------------------------
+ // Test Failed
+ // ------------------------------------
+
+ // Copy returned errl into testcase global if there isn't
+ // anything in there already.
+ //if(NULL == G_testAppletStats.errlHndl){
+ // G_testAppletStats.errlHndl = l_errl;
+ //}
+
+ // Increment Testcase failed counter
+ //G_testAppletStats.failed++;
+ }
+ else
+ {
+ TRAC_INFO("Test applet started");
+ // ------------------------------------
+ // Test Success
+ // ------------------------------------
+
+ // Increment Testcase success counter
+ //G_testAppletStats.successful++;
+ }
+ }
+ else if(l_block_num == TEST_APPLET_GET_STATS)
+ {
+ TRAC_INFO("Get applet stats");
+ // Get Applet Test Stats
+ }
+ else if(l_block_num == TEST_APPLET_RESET_STATS)
+ {
+ TRAC_INFO("Resetting applet stats");
+ // Reset Applet Test Stats
+ G_testAppletStats.total = 0;
+ G_testAppletStats.duration = 0;
+ G_testAppletStats.failed = 0;
+ G_testAppletStats.errlHndl = NULL;
+ G_testAppletStats.successful = 0;
+ }
+ else
+ {
+ TRAC_ERR("Unrecognized applet command. l_block_num = %d", l_block_num);
+ l_rc = ERRL_RC_INVALID_DATA;
+ }
+ break;
+
+ // ------------------------------------------------
+ // Run debug sub-commands that can use applets
+ // ------------------------------------------------
+ case DBUG_READ_SCOM:
+ case DBUG_PUT_SCOM:
+ case DBUG_POKE:
+ case DBUG_SET_PEXE_EVENT:
+ case DBUG_DUMP_THEMAL:
+ case DBUG_DUMP_POWER:
+ case DBUG_DUMP_RAW_AD:
+ case DBUG_MEM_PWR_CTL:
+ case DBUG_PERFCOUNT:
+ case DBUG_TEST_INTF:
+ case DBUG_SET_BUS_SPEED:
+ case DBUG_FAN_CONTROL:
+ case DBUG_INJECT_ERRL:
+ case DBUG_IIC_READ:
+ case DBUG_IIC_WRITE:
+ case DBUG_GPIO_READ:
+ case DBUG_CALCULATE_MAX_DIFF:
+ case DBUG_FORCE_ELOG:
+ case DBUG_SWITCH_PHASE:
+ case DBUG_INJECT_ERR:
+ case DBUG_VERIFY_V_F:
+ case DBUG_DUMP_PPM_DATA:
+ case DBUG_CENTAUR_SENSOR_CACHE:
+ case DBUG_DUMP_PROC_DATA:
+
+ l_applet_args.i_cmd_ptr = (cmdh_fsp_cmd_t *) i_cmd_ptr;
+ l_applet_args.io_rsp_ptr = o_rsp_ptr;
+
+ runApplet(OCC_APLT_CMDH_DBUG, // Applet enum Name
+ &l_applet_args, // Applet arguments
+ TRUE, // Blocking call?
+ NULL, // Applet finished semaphore
+ &l_errl, // Error log handle
+ &l_status); // Error status
+
+ if( (NULL != l_errl) || (l_status != OCC_APLT_SUCCESS))
+ {
+ TRAC_ERR("Debug command applet returned error: l_status: 0x%x", l_status);
+ // commit & delete. CommitErrl handles NULL error log handle
+ commitErrl( &l_errl );
+ }
+ break;
+ default:
+ l_rc = ERRL_RC_INVALID_DATA; //should NEVER get here...
+ break;
+ } //end switch
+
+ // We don't do errors in DBUG, as a safety check make sure the response is valid.
+ if ( l_rc )
+ {
+ l_err_rsp_ptr->rc = l_rc;
+ l_err_rsp_ptr->data_length[0] = 0;
+ l_err_rsp_ptr->data_length[1] = 1;
+ }
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_base_setmodestate_cmdh
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_tmgt_setmodestate(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ errlHndl_t l_errlHndl = NULL;
+ smgr_setmodestate_v0_query_t* l_cmd_ptr = (smgr_setmodestate_v0_query_t *)i_cmd_ptr;
+ ERRL_RC l_rc = ERRL_RC_INTERNAL_FAIL;
+ SsxInterval l_timeout = SSX_SECONDS(15); // @th043
+ SsxTimebase l_start = ssx_timebase_get(); // @at015a
+ OCC_STATE l_pre_state = CURRENT_STATE(); // @at015a
+ OCC_MODE l_pre_mode = CURRENT_MODE(); // @at015a
+
+ // @at019a
+ // SAPPHIRE only accepts DPS-FE mode. In case OCC gets other modes, it should accept the request
+ // and keep reporting back that it is in that mode.
+ if(G_sysConfigData.system_type.kvm)
+ {
+ l_pre_mode = G_occ_external_req_mode_kvm;
+ }
+
+ do
+ {
+ // -------------------------------------------------
+ // Check Command & Function Inputs
+ // -------------------------------------------------
+ // Function Inputs Sanity Check
+ if( (NULL == i_cmd_ptr) || (NULL == o_rsp_ptr) )
+ {
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ // Command Version Check
+ if(l_cmd_ptr->version != SMGR_SMS_CMD_VERSION)
+ {
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // Command Length Check
+ if( CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) !=
+ (sizeof(smgr_setmodestate_v0_query_t) - sizeof(cmdh_fsp_cmd_header_t)))
+ {
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ // Can't send this command to a slave
+ if( OCC_SLAVE == G_occ_role ) // @th032
+ {
+ l_rc = ERRL_RC_INVALID_CMD;
+ break;
+ }
+
+ // -------------------------------------------------
+ // Act on State & Mode Changes
+ // -------------------------------------------------
+ TRAC_INFO("SMS Mode=%d, State=%d\n",l_cmd_ptr->occ_mode, l_cmd_ptr->occ_state);
+
+ G_occ_external_req_mode = l_cmd_ptr->occ_mode;
+ G_occ_external_req_state = l_cmd_ptr->occ_state;
+
+ // TODO: Should we have a way to transition state even if
+ // master slave comm isn't working?
+ // if(){
+ // G_occ_master_state = l_cmd_ptr->occ_state;
+ // G_occ_master_mode = l_cmd_ptr->occ_mode;
+ // }
+
+ // We need to wait and see if all Slaves correctly make it to state/mode.
+ // TODO: Also, if all slaves can't go to this mode (based on their state),
+ // we need to return PRESENT_STATE_PROHIBITS and do nothing.
+ // @at015a - start
+ do
+ {
+ uint8_t l_slv_idx = 0;
+ uint8_t l_occ_passed_num = 0;
+ uint8_t l_occ_num = G_occ_num_present;
+ uint8_t l_occ_bitmap_present = G_sysConfigData.is_occ_present;
+ uint8_t l_occ_bitmap_succeeded = 0;
+
+ for(l_slv_idx=0; l_slv_idx < MAX_OCCS; l_slv_idx++)
+ {
+ // Check if the occ exists
+ if( (0x01<<l_slv_idx) & l_occ_bitmap_present )
+ {
+ // Check if occ reaches the requested state/mode
+ if( ( (G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[0] == G_occ_external_req_state)
+ || (G_occ_external_req_state == OCC_STATE_NOCHANGE) ) &&
+ ( (G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[1] == G_occ_external_req_mode)
+ || (G_occ_external_req_mode == OCC_MODE_NOCHANGE) ) )
+ {
+ l_occ_bitmap_succeeded |= (0x01<<l_slv_idx);
+ l_occ_passed_num++;
+ }
+ }
+ }
+
+ if(l_occ_num <= l_occ_passed_num)
+ {
+ /// This means that all present OCCs have reached the desired state/mode
+ TRAC_INFO("cmdh_tmgt_setmodestate: changed state from %d to %d, mode from %d to %d",
+ l_pre_state, G_occ_external_req_state, l_pre_mode, G_occ_external_req_mode);
+ l_rc = ERRL_RC_SUCCESS;
+ break;
+ }
+ else
+ {
+ // check time and break out if we reached limit
+ if ( ((ssx_timebase_get() - l_start) > l_timeout))
+ {
+ TRAC_ERR("cmdh_tmgt_setmodestate: time out waiting for all slave occ (expected:%d, passed:%d)",
+ l_occ_num, l_occ_passed_num);
+ /* @
+ * @errortype
+ * @moduleid CMDH_GENERIC_CMD_FAILURE
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 OCC present bitmap
+ * @userdata2 OCC succeeded bitmap
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Timed out trying to reach requested power mode/state
+ */
+ l_errlHndl = createErrl(
+ CMDH_GENERIC_CMD_FAILURE, //modId
+ INTERNAL_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity -- gm029
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_occ_bitmap_present, //userdata1
+ l_occ_bitmap_succeeded //userdata2
+ );
+ addCalloutToErrl(l_errlHndl, //gm029
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ else
+ {
+ // Give OCCs a chance to get to active state. This
+ // timeout is arbitrary, but there's no point in making
+ // it too small.
+ ssx_sleep(SSX_MILLISECONDS(100)); // @th043
+ }
+ }
+
+ }while( 1 );
+ // @at015a - end
+
+ }while(0);
+
+ if(l_rc)
+ {
+
+ /// Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errlHndl); // @th036
+ }
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_amec_pass_through
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_amec_pass_through(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_errlHndl = NULL;
+ IPMIMsg_t l_IPMImsg;
+ uint8_t l_rc = 0;
+ uint16_t l_rsp_data_length = CMDH_FSP_RSP_DATA_SIZE;
+ errl_generic_resp_t* l_err_resp_ptr = (errl_generic_resp_t*)o_rsp_ptr;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+
+ // Function Inputs Sanity Check
+ if( (NULL == i_cmd_ptr) || (NULL == o_rsp_ptr) )
+ {
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ // Byte0 is ipmi command number
+ l_IPMImsg.u8Cmd = i_cmd_ptr->data[0];
+
+ //set the ipmi command data size, byte0 and byte1 is ipmi header
+ l_IPMImsg.u8CmdDataLen = CONVERT_UINT8_ARRAY_UINT16( i_cmd_ptr->data_length[0],
+ i_cmd_ptr->data_length[1])
+ - AMEC_AME_CMD_HEADER_SZ;
+
+ // Set the ipmi command data buffer
+ l_IPMImsg.au8CmdData_ptr = (uint8_t *)&i_cmd_ptr->data[AMEC_AME_CMD_HEADER_SZ];
+
+ // Call the amester entry point
+ l_rc = amester_entry_point( &l_IPMImsg,
+ &l_rsp_data_length,
+ o_rsp_ptr->data);
+
+ if(COMPCODE_NORMAL != l_rc)
+ {
+ TRAC_ERR("amester_entry_point failured, rc (ipmi completion code) = %d", l_rc);
+
+ // Per comment from Charles, just put the rc in the return packet and return success
+ l_rsp_data_length = 1;
+ o_rsp_ptr->data[0] = l_rc;
+ l_rc = ERRL_RC_SUCCESS;
+ }
+
+ //protect IPMI from overflowing a buffer
+ if(l_rsp_data_length > IPMI_MAX_MSG_SIZE)
+ {
+ TRAC_ERR("amester_entry_point returned too much data. Got back %d bytes, but we only support sending %d bytes to IPMI",
+ l_rsp_data_length, IPMI_MAX_MSG_SIZE);
+ /* @
+ * @errortype
+ * @moduleid AMEC_AMESTER_INTERFACE
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 response data length
+ * @userdata2 max data length
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc amester_entry_point returned too much data.
+ */
+ l_errlHndl = createErrl(
+ AMEC_AMESTER_INTERFACE, //modId
+ INTERNAL_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //TODO: create trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rsp_data_length, //userdata1
+ IPMI_MAX_MSG_SIZE //userdata2
+ );
+
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ // Set response rc and length
+ o_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ o_rsp_ptr->data_length[0] = ((uint8_t *)&l_rsp_data_length)[0];
+ o_rsp_ptr->data_length[1] = ((uint8_t *)&l_rsp_data_length)[1];
+
+ }while(0);
+
+ if(l_rc)
+ {
+ l_err_resp_ptr->data_length[0] = 0;
+ l_err_resp_ptr->data_length[1] = 1;
+ l_err_resp_ptr->rc = l_rc;
+
+ if(l_errlHndl)
+ {
+ l_err_resp_ptr->log_id = l_errlHndl->iv_entryId;
+ }
+ else
+ {
+ l_err_resp_ptr->log_id = 0;
+ }
+ }
+
+ return l_errlHndl;
+}
+
+// @jh002a
+// Function Specification
+//
+// Name: cmdh_tmgt_get_field_debug_data
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_tmgt_get_field_debug_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t i = 0;
+ UINT l_rtLen = 0;
+ uint16_t l_num_of_sensors = CMDH_FIELD_MAX_NUM_SENSORS;
+ sensorQueryList_t l_sensor_list[CMDH_FIELD_MAX_NUM_SENSORS];
+ sensor_t *l_sensor_ptr = NULL;
+ errlHndl_t l_err = NULL;
+ OCC_APLT_STATUS_CODES l_status = 0;
+ cmdh_get_field_debug_data_resp_t *l_resp_ptr = (cmdh_get_field_debug_data_resp_t*) o_rsp_ptr;
+ uint16_t l_rsp_data_length = 0;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ // Function Inputs Sanity Check
+ if( (NULL == i_cmd_ptr) || (NULL == o_rsp_ptr) )
+ {
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ // Add occ infomation so that we know where the debug data from
+ l_resp_ptr->occ_node = G_pob_id.node_id;
+ l_resp_ptr->occ_id = 0; // TODO:add occ id info
+ l_resp_ptr->occ_role = G_occ_role;
+
+ // copy trace data
+ l_rtLen = CMDH_FIELD_TRACE_DATA_SIZE;
+ TRAC_get_buffer_partial(TRAC_get_td("ERR"), l_resp_ptr->trace_err, &l_rtLen);
+
+ l_rtLen = CMDH_FIELD_TRACE_DATA_SIZE;
+ TRAC_get_buffer_partial(TRAC_get_td("INF"), l_resp_ptr->trace_inf, &l_rtLen);
+
+ // Initialize the Applet arguments
+ // TODO: Set "present" to 0 for testing (since no sensor presented now)
+ querySensorListAppletArg_t l_applet_arg = {
+ 0, // i_startGsid - start with sensor 0x0000
+ 0, // i_present
+ (AMEC_SENSOR_TYPE_POWER| // i_type
+ AMEC_SENSOR_TYPE_TEMP),
+ AMEC_SENSOR_LOC_ALL, // i_loc
+ &l_num_of_sensors, // io_numOfSensors
+ l_sensor_list, // o_sensors
+ NULL // o_sensorInfoPtr
+ };
+
+ // Call the sensor query list applet
+ runApplet(OCC_APLT_SNSR_QUERY,
+ &l_applet_arg,
+ TRUE,
+ NULL,
+ &l_err,
+ &l_status);
+
+ if (NULL != l_err)
+ {
+ // Query failure, this should not happen
+ TRAC_ERR("get_field_debug_data: Failed to run OCC_APLT_SNSR_QUERY applet. Error status is: 0x%x",
+ l_status);
+
+ // Commit error log
+ commitErrl(&l_err);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ else
+ {
+ TRAC_INFO("get_field_debug_data: Numbers of sensors found[%u]",
+ l_num_of_sensors);
+
+ // Populate the response data packet
+ l_resp_ptr->num_sensors = l_num_of_sensors;
+ for (i=0; i<l_num_of_sensors; i++)
+ {
+ l_resp_ptr->sensor[i].gsid = l_sensor_list[i].gsid;
+ l_resp_ptr->sensor[i].sample = l_sensor_list[i].sample;
+ strcpy(l_resp_ptr->sensor[i].name, l_sensor_list[i].name);
+
+ // Capture the min and max value for this sensor
+ l_sensor_ptr = getSensorByGsid(l_sensor_list[i].gsid);
+ if (l_sensor_ptr == NULL)
+ {
+ TRAC_INFO("get_field_debug_data: Unable to find sensor with gsid[0x%.4X]. Values won't be accurate.",
+ l_sensor_list[i].gsid);
+
+ // Didn't find this sensor, just continue
+ continue;
+ }
+ l_resp_ptr->sensor[i].sample_min = l_sensor_ptr->sample_min;
+ l_resp_ptr->sensor[i].sample_max = l_sensor_ptr->sample_max;
+ }
+ }
+ // -------------------------------------------------
+ // Build Response Packet
+ // -------------------------------------------------
+ // Populate the response data header
+ l_rsp_data_length = (sizeof(cmdh_get_field_debug_data_resp_t) - CMDH_DBUG_FSP_RESP_LEN);
+ l_resp_ptr->data_length[0] = ((uint8_t *)&l_rsp_data_length)[0];
+ l_resp_ptr->data_length[1] = ((uint8_t *)&l_rsp_data_length)[1];
+ l_resp_ptr->rc = l_rc;
+
+ } while(0);
+
+ if (l_rc)
+ {
+ /// Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_err);
+ }
+
+ return l_err;
+}
+
+// Function Specification
+//
+// Name: cmdh_get_cooling_request
+//
+// Description:
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_get_cooling_request(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_errlHndl = NULL;
+ cmdh_get_cooling_resp_t *l_resp_ptr = (cmdh_get_cooling_resp_t*) o_rsp_ptr;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_rsp_data_length = 0;
+ uint16_t l_max_increment = 0;
+ uint8_t l_fru_winner = DATA_FRU_MAX;
+ uint8_t i = 0;
+ uint8_t j = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ // Command Length Check - make sure we at least have a version number
+ if( CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) < CMDH_GET_COOLING_MIN_DATALEN)
+ {
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ // Version Number Check
+ if(i_cmd_ptr->data[0] != CMDH_GET_COOLING_VERSION)
+ {
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ //too much trace -- gm017
+ //TRAC_INFO("cmdh_get_cooling_request: Get Cooling Request command received! version[0x%.2X]",
+ // i_cmd_ptr->data[0]);
+
+ // Loop through all Zones
+ for (i=0; i<THRM_MAX_NUM_ZONES; i++)
+ {
+ // For each Zone, determine which FRU is requesting the maximum
+ // increment value
+ l_max_increment = 0;
+ l_fru_winner = DATA_FRU_MAX;
+ for (j=0; j<DATA_FRU_MAX; j++)
+ {
+ if (G_thrm_fru_data[j].FanIncZone[i] > l_max_increment)
+ {
+ l_max_increment = G_thrm_fru_data[j].FanIncZone[i];
+ l_fru_winner = j;
+ }
+ }
+ l_resp_ptr->zone_data[i].increment_value = l_max_increment;
+ l_resp_ptr->zone_data[i].comp_type = l_fru_winner;
+ l_resp_ptr->zone_data[i].reason = 0x00; //Always hardcoded to 0x00
+ }
+
+ // Populate the response data header
+ l_rsp_data_length = (sizeof(cmdh_get_cooling_resp_t) - CMDH_DBUG_FSP_RESP_LEN);
+ l_resp_ptr->data_length[0] = ((uint8_t *)&l_rsp_data_length)[0];
+ l_resp_ptr->data_length[1] = ((uint8_t *)&l_rsp_data_length)[1];
+ l_resp_ptr->rc = l_rc;
+
+ }while(0);
+
+ if(ERRL_RC_SUCCESS != l_rc)
+ {
+ // Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errlHndl);
+ }
+
+ return l_errlHndl;
+}
diff --git a/src/occ/cmdh/cmdh_fsp_cmds.h b/src/occ/cmdh/cmdh_fsp_cmds.h
new file mode 100755
index 0000000..5b9ca52
--- /dev/null
+++ b/src/occ/cmdh/cmdh_fsp_cmds.h
@@ -0,0 +1,725 @@
+/******************************************************************************
+// @file cmdh_fsp_cmds.h
+// @brief Command Handling for FSP Communication.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_fsp_cmds_h cmdh_fsp_cmds_h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * thallet 04/05/2012 Created
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @at008 alvinwan 08/09/2012 Support AME Pass Thru command from TMGT
+ * @th022 thallet 10/08/2012 Moved CNFG Data commands to diff file
+ * @ai006 863413 ailutsar 11/28/2012 Update occtool to grab a full trace log from OCC
+ * @nh004 864941 neilhsu 12/20/2012 Support get/delete errl & added trace info
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @gs003 878457 gjsilva 04/17/2013 Support for get_sensor option
+ * @th032 thallet 04/16/2013 Tuleta HW Bringup
+ * @th036 881677 thallet 05/06/2013 New Poll Command Support
+ * @gm002 885429 milesg 05/30/2013 support for 16 bit type and location
+ * @jh002 887903 joshych 06/17/2013 Support Get Field Debug Data command
+ * @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
+ * @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+ * @rc006 906038 rickylie 11/11/2013 OCC: Investigate/Test OCC Tracing
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @rt004 905638 tapiar 11/13/2013 Tunable parameters
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gs019 908218 gjsilva 12/04/2013 Support cooling request architecture
+ * @jh009 908383 joshych 12/04/2013 Generate error logs when required for Reset Prep command
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @wb000 916142 wilbryan 02/18/2014 Support "DVFS due to OT/Power" bits in OCC poll response
+ * @fk009 942864 fmkassem 09/22/2014 BMC/HTMGT Poll command 0x10 support
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _CMDH_FSP_CMDS_H
+#define _CMDH_FSP_CMDS_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "cmdh_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "occ_common.h"
+#include "state.h"
+#include "cmdh_fsp.h"
+#include "gpsm.h"
+#include "pstates.h"
+#include "cmdh_fsp_cmds_datacnfg.h"
+#include "sensor.h"
+#include "thrm_thread.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+/**
+ * @enum eCmdhCommands
+ * @brief Enum of the various commands that TMGT may send to OCC
+ */
+typedef enum
+{
+ CMDH_POLL = 0x00,
+ CMDH_QUERYFWLEVEL = 0x01,
+ CMDH_GETERRL = 0x10,
+ CMDH_CLEARERRL = 0x12,
+ CMDH_SETMODESTATE = 0x20,
+ CMDH_SETCONFIGDATA = 0x21,
+ CMDH_SET_THERMAL_THROTTLE = 0x23,
+ CMDH_RESET_PREP = 0x25,
+ CMDH_SNAPSHOT_SYNC = 0x26,
+ CMDH_READ_STATUS_REG = 0x31,
+ CMDH_GET_THROTTLE_VALUE = 0x32,
+ CMDH_GET_CPU_TEMPS = 0x33,
+ CMDH_GET_COOLING_REQUEST = 0x34,
+ CMDH_GET_SNAPSHOT_BUFFER = 0x35,
+ CMDH_DEBUGPT = 0x40,
+ CMDH_AME_PASS_THROUGH = 0x41,
+ CMDH_GET_FIELD_DEBUG_DATA = 0x42,
+ CMDH_MFG_TEST_CMD = 0x53,
+ CMDH_FOM = 0x54,
+ CMDH_TUNABLE_PARMS = 0x60,
+} eCmdhCommands;
+
+//@fk009a
+#define SENSOR_TEMP "TEMP"
+#define SENSOR_FREQ "FREQ"
+#define SENSOR_POWR "POWR"
+#define SENSOR_CAPS "CAPS"
+
+//---------------------------------------------------------
+// Poll Command
+//---------------------------------------------------------
+
+// Length of Poll Response
+#define CMDH_POLL_RESP_LEN_V0 16 // version 0x00 is 16 bytes.
+#define CMDH_POLL_RESP_LEN_V10 40 // version 0x10 has at least 40 bytes. //@fk009a
+// Poll Version 0
+#define CMDH_POLL_BASE_VERSION 0x00
+#define CMDH_POLL_VERSION10 0x10 //@fk009a
+
+/**
+ * @struct cmdh_poll_query_t
+ * @brief Struct used to parse Poll Cmd
+ */
+typedef struct __attribute__ ((packed)) cmdh_poll_query
+{
+ /// Standard TMGT
+ struct cmdh_fsp_cmd_header;
+ /// Poll Version
+ uint8_t version;
+}cmdh_poll_query_t;
+
+/**
+ * @struct cmdh_poll_resp_v0_t
+ * @brief Response packet used for Poll Cmd
+ */
+typedef struct __attribute__ ((packed)) cmdh_poll_resp_v0
+{
+ /// Standard TMGT
+ struct cmdh_fsp_rsp_header;
+ /// Status
+ union
+ {
+ struct
+ {
+ uint8_t master_occ : 1;
+ uint8_t _reserved_6 : 1;
+ uint8_t _reserved_5 : 1;
+ uint8_t status_changed : 1;
+ uint8_t oversubscribed : 1;
+ uint8_t _reserved_2 : 1;
+ uint8_t obs_ready : 1;
+ uint8_t active_ready : 1;
+ };
+ uint8_t word;
+ } status;
+ /// Extended Status
+ union
+ {
+ struct
+ {
+ uint8_t dvfs_due_to_ot : 1; /// @wb000
+ uint8_t dvfs_due_to_pwr : 1; /// @wb000
+ uint8_t _reserved_5 : 1; ///
+ uint8_t _reserved_4 : 1; ///
+ uint8_t _reserved_3 : 1; ///
+ uint8_t sync_request : 1; /// In TMGT to TPMF interface spec, but not needed yet
+ uint8_t _reserved_1 : 1; ///
+ uint8_t cooling_request : 1; /// 1:new fan speed, 0:no new fan speed
+ };
+ uint8_t word;
+ } ext_status;
+ /// OCCs Present
+ uint8_t occ_pres_mask;
+ /// Config Data Requested
+ uint8_t config_data;
+ /// Current OCC State
+ uint8_t state;
+ /// Current OCC Mode
+ uint8_t mode;
+ /// Current Idle Power Saver Status
+ union
+ {
+ struct
+ {
+ uint8_t _reserved_7 : 1; ///
+ uint8_t _reserved_6 : 1; ///
+ uint8_t _reserved_5 : 1; ///
+ uint8_t _reserved_4 : 1; ///
+ uint8_t _reserved_3 : 1; ///
+ uint8_t _reserved_2 : 1; ///
+ uint8_t ips_active : 1; ///
+ uint8_t ips_enabled : 1; ///
+ };
+ uint8_t word;
+ } ips_status;
+ /// Error Log ID
+ uint8_t errl_id;
+ /// Error Log Start Address
+ uint32_t errl_address;
+ /// Error Log Length
+ uint16_t errl_length;
+ /// Reserved
+ uint8_t _reserved[2];
+ /// Checksum
+ uint8_t checksum[2];
+}cmdh_poll_resp_v0_t;
+
+/**
+ * @struct cmdh_poll_resp_v10_t
+ * @brief Response packet used for Poll Cmd
+ */
+typedef struct __attribute__ ((packed)) cmdh_poll_resp_v10
+{
+ /// Standard TMGT
+ struct cmdh_fsp_rsp_header;
+ /// BYTE 1: Status
+ union
+ {
+ struct
+ {
+ uint8_t master_occ : 1; /// 1 => master, 0 => slave
+ uint8_t fir_master : 1; /// 1 => fir master.
+ uint8_t _reserved_5 : 1;
+ uint8_t _reserved_4 : 1;
+ uint8_t attn_enabled : 1; /// 1 => Attentions from OCC to Host are enabled.
+ uint8_t _reserved_2 : 1;
+ uint8_t obs_ready : 1; /// 1 => OCC received all data to support obs state.
+ uint8_t active_ready : 1; /// 1 => OCC received all data to support active state.
+ };
+ uint8_t word;
+ } status;
+ /// BYTE 2: Extended Status
+ union
+ {
+ struct
+ {
+ uint8_t dvfs_due_to_ot : 1; /// 1 => OCC clipped max Pstate due to an over temp.
+ uint8_t dvfs_due_to_pwr : 1; /// 1 => OCC clipped max Psate due to reaching pcap limit.
+ uint8_t mthrot_due_to_ot: 1; /// 1 => OCC throttled memory due to an over temp.
+ uint8_t n_power : 1; /// 1 => Server running without redundant power.
+ uint8_t _reserved_3 : 1;
+ uint8_t _reserved_2 : 1;
+ uint8_t _reserved_1 : 1;
+ uint8_t _reserved_0 : 1;
+ };
+ uint8_t word;
+ } ext_status;
+ /// BYTE 3: OCCs Present
+ uint8_t occ_pres_mask;
+ /// BYTE 4: Config Data Requested
+ uint8_t config_data;
+ /// BYTE 5: Current OCC State
+ uint8_t state;
+ /// BYTE 6 - 7: Reserved
+ uint8_t _reserved_6;
+ uint8_t _reserved_7;
+ /// BYTE 8: Error Log ID
+ uint8_t errl_id;
+ /// BYTES 9 - 12: Error Log Start Address
+ uint32_t errl_address;
+ /// BYTES 13 - 14: Error Log Length
+ uint16_t errl_length;
+ /// BYTES 15 - 16: Reserved
+ uint8_t _reserved_15;
+ uint8_t _reserved_16;
+ /// BYTES 17 - 32 (16 bytes): OCC Code Level - ASCII string of OCC build level currently running.
+ uint8_t occ_level[16];
+ /// BYTES 33 - 38 (6 bytes): ASCII eye catcher "SENSOR"
+ uint8_t sensor_ec[6];
+ /// BYTE 39: Number of sensor data blocks
+ uint8_t sensor_dblock_count;
+ /// BYTE 40: Sensor Data Block Header Version
+ uint8_t sensor_dblock_version;
+ ///No need to include the 2 bytes for checksum since they get added prior to sending
+ ///data back to tmgt.
+}cmdh_poll_resp_v10_fixed_t;
+
+
+//@fk009a
+typedef struct __attribute__ ((packed)) cmdh_poll_sensor_datablock
+{
+ uint8_t eyecatcher[4];
+ uint8_t reserved;
+ uint8_t format;
+ uint8_t length;
+ uint8_t count;
+} cmdh_poll_sensor_db_t;
+
+//@fk009a
+typedef struct __attribute__ ((packed)) cmdh_poll_temp_sensor
+{
+ uint16_t id; //Sensor id.
+ uint16_t value; //current temperature sensor reading in degrees C
+} cmdh_poll_temp_sensor_t;
+
+//@fk009a
+typedef struct __attribute__ ((packed)) cmdh_poll_freq_sensor
+{
+ uint16_t id; //Id to represent the frequency.
+ uint16_t value; //current frequency in MHZ
+} cmdh_poll_freq_sensor_t;
+
+//@fk009a
+//Only available from master occ.
+typedef struct __attribute__ ((packed)) cmdh_poll_powr_sensor
+{
+ uint16_t id; //Sensor id - to represent the power.
+ uint32_t update_tag; //Count of number of 250us samples represented by accumulator.
+ uint32_t accumul; //Accumulation of 250us power readings
+ uint16_t current; //Most recent 250us reading in watts.
+} cmdh_poll_power_sensor_t;
+
+//@fk009a
+//Only available from master occ.
+typedef struct __attribute__ ((packed)) cmdh_poll_caps_sensor
+{
+ cmdh_poll_sensor_db_t header; //Only one entry for powercap.
+ uint16_t current; //Current power cap in 1W units.
+ uint16_t system; //Current system power in 1W units.
+ uint16_t max; //Maximum power cap in 1W units.
+ uint16_t min; //Minimum power cap in 1W units.
+ uint16_t user; //Power cap set by user in 1W units.
+} cmdh_poll_pcaps_sensor_t;
+
+
+
+//---------------------------------------------------------
+// Query FW Level Command
+//---------------------------------------------------------
+/**
+ * @struct cmdh_fw_resp_t
+ * @brief Response packet used for Query Firmware Level Cmd
+ */
+#define CMDH_FW_QUERY_RESP_LEN 16
+typedef struct __attribute__ ((packed)) cmdh_fw_resp
+{
+ /// Standard TMGT
+ struct cmdh_fsp_rsp_header;
+ /// Firmware Level (4 bytes)
+ uint8_t fw_level[CMDH_FW_QUERY_RESP_LEN];
+ /// Checksum
+ uint8_t checksum[2];
+}cmdh_fw_resp_t;
+
+
+//---------------------------------------------------------
+// Set Mode And State Command
+//---------------------------------------------------------
+/**
+ * @struct smgr_setmodestate_v0_query
+ * @brief Query packet used by the FSP for setting the TPMF
+ * state, version 0.
+ */
+struct smgr_setmodestate_v0_query
+{
+ /// Standard TMGT
+ struct cmdh_fsp_cmd_header;
+ ///Version
+ uint8_t version;
+ ///New state from OCC_STATE_*
+ uint8_t occ_state;
+ ///New mode from OCC_MODE_*
+ uint8_t occ_mode;
+} __attribute__ ((__packed__));
+typedef struct smgr_setmodestate_v0_query smgr_setmodestate_v0_query_t;
+#define SMGR_SETMODESTATE_CMD_LEN 3
+
+/**
+ * @struct smgr_setmodestate_resp
+ * @brief Complete Response packet for a set mode / state command
+ */
+#define SMGR_SETMODESTATE_RESP_LEN 0
+typedef cmdh_fsp_rsp_t smgr_setmodestate_resp_t;
+
+///Set-mode-state TMGT command version
+#define SMGR_SMS_CMD_VERSION 0
+
+
+//---------------------------------------------------------
+// Clear Elog Command
+//---------------------------------------------------------
+/**
+ * @struct cmdh_clear_elog_query_t;
+ * @brief Used by TMGT to clear elog data state, version 0.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t elog_id;
+}cmdh_clear_elog_query_t;
+
+
+//---------------------------------------------------------
+// Get Elog Command
+//---------------------------------------------------------
+/**
+ * @struct cmdh_get_elog_resp_t;
+ * @brief Used by TMGT to response occ elog data, version 0.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint32_t oci_address;
+ uint8_t elog_id;
+}cmdh_get_elog_resp_t; // @nh004a
+#define CMDH_GET_ELOG_RESP_LEN 5 // @nh004a
+
+//---------------------------------------------------------
+// Reset Prep
+//---------------------------------------------------------
+
+// Minimum Data Length for Reset Prep Command
+#define CMDH_RESET_PREP_MIN_DATALEN 1
+
+// Version 0
+#define CMDH_RESET_PREP_VERSION 0
+
+/// Reason
+typedef enum
+{
+ /// Non-failure. Code update, external user request (i.e. to load
+ /// new pState table). No FFDC error logs should be generated.
+ CMDH_PREP_NONFAILURE = 0x00,
+ /// Failure detected on this OCC. FFDC error log should be generated.
+ CMDH_PREP_FAILON_THISOCC = 0x01,
+ /// Failure detected on a different OCC within same node.
+ /// FFDC log is optional, if this OCC is master OCC it may want to
+ /// generate FFDC log.
+ CMDH_PREP_FAILON_OTHEROCC = 0x02,
+ /// Failure detected on a different OCC in different node. No
+ /// FFDC error log should be generated. Current assumption is that an
+ /// OCC in a different node should never be reason for an OCC failure.
+ CMDH_PREP_FAILON_OTHERNODE = 0x03,
+} eCmdhResetPrepReason;
+
+#define CMDH_RESET_PREP_TRACE_SIZE 3072 // @jh009a
+
+/**
+ * @struct cmdh_reset_prep_t
+ * @brief Struct used to parse Reset Prep Command
+ */
+typedef struct __attribute__ ((packed)) cmdh_reset_prep
+{
+ /// Standard TMGT
+ struct cmdh_fsp_cmd_header;
+ /// Poll Version
+ uint8_t version;
+ /// Reason
+ uint8_t reason;
+}cmdh_reset_prep_t;
+
+
+//---------------------------------------------------------
+// Get Cooling Request
+//---------------------------------------------------------
+
+// Minimum Data Length for Get Cooling Request Command
+#define CMDH_GET_COOLING_MIN_DATALEN 1
+
+// Version 0
+#define CMDH_GET_COOLING_VERSION 0
+
+typedef struct cmdh_get_cooling_data
+{
+ // Maximum increment value for this zone
+ uint16_t increment_value;
+ // Component type that is driving the increment for this zone
+ uint8_t comp_type;
+ // Currently not used, hardcode to 0x00 (see TMGT-OCC Interface Spec v2.0)
+ uint8_t reason;
+}cmdh_get_cooling_data_t;
+
+/**
+ * @struct cmdh_get_cooling_resp_t;
+ * @brief Used by OCC to respond to "GET_COOLING_REQUEST" cmd
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ // Zone data array
+ cmdh_get_cooling_data_t zone_data[THRM_MAX_NUM_ZONES];
+ // Checksum
+ uint8_t checksum[2];
+}cmdh_get_cooling_resp_t;
+
+
+//---------------------------------------------------------
+// Debug Command
+//---------------------------------------------------------
+///Max string length of trace component name
+#define OCC_TRACE_NAME_SIZE 4 // @ai006a
+
+/**
+ * @enum DBUG_CMD
+ * @brief Enum of the various Debug commands that may be sent to OCC
+ * over the TMGT<->OCC interface.
+ */
+typedef enum
+{
+ DBUG_READ_SCOM = 0x01,
+ DBUG_PUT_SCOM = 0x02,
+ DBUG_GET_TRACE = 0x03,
+ DBUG_CLEAR_TRACE = 0x04,
+ // free = 0x05,
+ DBUG_SET_PEXE_EVENT = 0x06,
+ DBUG_GET_AME_SENSOR = 0x07,
+ // free = 0x08,
+ DBUG_PEEK = 0x09,
+ DBUG_POKE = 0x0A,
+ DBUG_DUMP_THEMAL = 0x0B,
+ DBUG_DUMP_POWER = 0x0C,
+ DBUG_DUMP_RAW_AD = 0x0D,
+ DBUG_DVFS_SLEW = 0x0E,
+ DBUG_MEM_PWR_CTL = 0x0F,
+ DBUG_PERFCOUNT = 0x10,
+ DBUG_TEST_INTF = 0x11,
+ DBUG_SET_BUS_SPEED = 0x12,
+ DBUG_FAN_CONTROL = 0x13,
+ DBUG_INJECT_ERRL = 0x14,
+ DBUG_IIC_READ = 0x15,
+ DBUG_IIC_WRITE = 0x16,
+ DBUG_GPIO_READ = 0x17,
+ DBUG_FSP_ATTN = 0x18,
+ DBUG_CALCULATE_MAX_DIFF = 0x19,
+ DBUG_FORCE_ELOG = 0x1A,
+ DBUG_SWITCH_PHASE = 0x1B,
+ DBUG_INJECT_ERR = 0x1C,
+ DBUG_VERIFY_V_F = 0x1D,
+ DBUG_DUMP_PPM_DATA = 0x1E,
+
+ DBUG_FLUSH_DCACHE = 0x20,
+ DBUG_INVALIDATE_DCACHE = 0x21,
+ DBUG_CENTAUR_SENSOR_CACHE = 0x22,
+ DBUG_DUMP_PROC_DATA = 0x23,
+ DBUG_GEN_CHOM_LOG = 0x24, // @jh005a
+} DBUG_CMD;
+
+// @ai006a - start
+/**
+ * @struct cmdh_dbug_get_trace_query_t;
+ * @brief Used by OCC tool to get trace, version 0.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ int8_t sub_cmd;
+ int16_t size_request;
+ int8_t comp[OCC_TRACE_NAME_SIZE];
+}cmdh_dbug_get_trace_query_t;
+
+/**
+ * @struct cmdh_dbug_get_trace_resp_t;
+ * @brief Used by OCC to response "get trace" cmd, version 0.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint8_t data[0]; // @rc006c
+}cmdh_dbug_get_trace_resp_t;
+
+#define CMDH_DBUG_GET_TRACE_RESP_LEN 6 // size_request(2) and occ_comp_sram_offset(4)
+// @ai006a - end
+
+/**
+ * @struct cmdh_dbug_get_sensor_query_t
+ * @brief Used by occtool to get AME sensor data
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint16_t type;
+ uint16_t location;
+}cmdh_dbug_get_sensor_query_t;
+
+typedef struct cmdh_dbug_sensor_list
+{
+ char name[MAX_SENSOR_NAME_SZ];
+ uint16_t gsid;
+ uint16_t sample;
+ uint16_t sample_min;
+ uint16_t sample_max;
+ uint16_t ipmi_sid; //@fk009a
+}cmdh_dbug_sensor_list_t;
+
+// Max number of sensors that can be returned with cmdh_dbug_get_ame_sensor command
+#define CMDH_DBUG_MAX_NUM_SENSORS 50
+// Size of standard response header (5 bytes) plus checksum (2 bytes)
+#define CMDH_DBUG_FSP_RESP_LEN 7
+
+/**
+ * @struct cmdh_dbug_get_sensor_resp_t
+ * @brief Used by OCC firmware to respond
+ * "cmdh_dbug_get_ame_sensor" debug command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint16_t num_sensors;
+ cmdh_dbug_sensor_list_t sensor[CMDH_DBUG_MAX_NUM_SENSORS];
+ uint8_t filler;
+ uint16_t checksum;
+}cmdh_dbug_get_sensor_resp_t;
+
+// @jh002 - start
+// Size of trace data for a trace buffer
+#define CMDH_FIELD_TRACE_DATA_SIZE 1024
+// Max number of sensors for field debug data
+#define CMDH_FIELD_MAX_NUM_SENSORS 50
+
+/**
+ * @struct cmdh_get_field_debug_resp_t;
+ * @brief Used by OCC to response "GET_FIELD_DEBUG_DATA" cmd
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ // OCC node
+ uint8_t occ_node;
+ // OCC id
+ uint8_t occ_id;
+ // OCC role
+ uint8_t occ_role;
+ // ERR trace
+ char trace_err[CMDH_FIELD_TRACE_DATA_SIZE];
+ // INF trace
+ char trace_inf[CMDH_FIELD_TRACE_DATA_SIZE];
+ // Number of Sensors
+ uint16_t num_sensors;
+ // Sensors list
+ cmdh_dbug_sensor_list_t sensor[CMDH_FIELD_MAX_NUM_SENSORS];
+ // Checksum
+ uint8_t checksum[2];
+}cmdh_get_field_debug_data_resp_t;
+
+/**
+ * @struct cmdh_get_field_debug_data_query_t
+ * @brief Used by TMGT to get field debug data
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t version;
+}cmdh_get_field_debug_data_query_t;
+// @jh002 -end
+
+
+/**
+ * @struct cmdh_dbug_peek_t;
+ * @brief Used by OCC to debug on real hardware
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t type;
+ uint16_t size;
+ uint32_t oci_address;
+}cmdh_dbug_peek_t;
+
+
+//---------------------------------------------------------
+// Tunable Parameter Command
+//---------------------------------------------------------
+// Default number of tunable parameters available
+// NOTE: update this value if any new tunable parameter is added into the table
+#define CMDH_DEFAULT_TUNABLE_PARAM_NUM 9
+// Max size for string containing the tunable parameter name
+#define CMDH_TUNABLE_PARAM_NAME_MAX_SIZE 60
+
+typedef struct cmdh_tunable_param_table
+{
+ uint8_t id;
+ char name[CMDH_TUNABLE_PARAM_NAME_MAX_SIZE];
+ uint8_t unit_type;
+ uint16_t flag;
+ uint16_t value;
+ uint16_t min;
+ uint16_t max;
+}cmdh_tunable_param_table_t;
+
+typedef struct cmdh_tunable_param_table_ext
+{
+ ///Default value for this parameter
+ uint16_t def_value;
+ ///Multiplier to convert the input value to correct internal resolution
+ uint16_t multiplier;
+ ///Adjusted value for this parameter (adjusted for internal resolution)
+ uint16_t adj_value;
+}cmdh_tunable_param_table_ext_t;
+
+extern uint8_t G_mst_tunable_parameter_overwrite; //@rt004a
+extern cmdh_tunable_param_table_ext_t G_mst_tunable_parameter_table_ext[CMDH_DEFAULT_TUNABLE_PARAM_NUM]; //@rt004a
+extern cmdh_tunable_param_table_t G_mst_tunable_parameter_table[CMDH_DEFAULT_TUNABLE_PARAM_NUM]; //@rt004a
+/*******************************************************************/
+/* Function Definitions */
+/*******************************************************************/
+
+errlHndl_t cmdh_tmgt_setmodestate(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr);
+
+void cmdh_dbug_cmd (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr);
+
+errlHndl_t cmdh_tmgt_poll (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr); // @th036
+
+ERRL_RC cmdh_poll_v10 (cmdh_fsp_rsp_t * i_rsp_ptr); //@fk009a
+
+errlHndl_t cmdh_clear_elog (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr); // @nh004c
+
+void cmdh_tmgt_query_fw (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr);
+
+errlHndl_t cmdh_amec_pass_through(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr);
+errlHndl_t cmdh_get_elog(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr); //@nh004a
+
+errlHndl_t cmdh_reset_prep(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr); // @th036
+
+errlHndl_t cmdh_tmgt_get_field_debug_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr); // @jh002
+
+errlHndl_t cmdh_get_cooling_request(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+#endif
+
diff --git a/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.c
new file mode 100755
index 0000000..c7d260a
--- /dev/null
+++ b/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.c
@@ -0,0 +1,2452 @@
+/******************************************************************************
+// @file cmdh_fsp_cmds_datacnfg.c
+// @brief Command Handling for FSP Communication CNFG DATA commands.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_fsp_cmds_datacnfg_c cmdh_fsp_cmds_datacnfg.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th022 thallet 10/03/2012 Created
+ * @at013 878755 alvinwan 04/17/2013 OCC power capping implementation
+ * @th032 thallet 04/15/2013 Tuleta HW Bringup
+ * @th036 881654 thallet 05/06/2013 New Poll Command Support
+ * @at014 882077 alvinwan 05/09/2013 Support APSS and System Config data from TMGT
+ * @ly007 882183 lychen 05/21/2013 Send APSS and System Configuration commands to OCC
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @fk001 879727 fmkassem 04/16/2013 OCC powercap support.
+ * @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
+ * @jh004 889884 joshych 07/24/2013 Support CPM param and updated frequency packet
+ * @ly008 894646 lychen 08/08/2013 Fix bugs in OCC handling of APSS tables for Brazos/Orlena
+ * @gs008 894661 gjsilva 08/08/2013 Initial support for DPS-FP mode
+ * @th046 894648 thallet 08/08/2013 Fix a coreq issue with TMGT
+ * @at017 895284 alvinwan 08/13/2013 Fix Poll status active ready bit
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gs010 899888 gjsilva 09/24/2013 Process data format 0x13 from TMGT
+ * @gm008 SW226989 milesg 09/30/2013 Sapphire initial support
+ * @gs011 900661 gjsilva 09/30/2013 Make data format 0x13 required to go active
+ * @rt001 901927 tapiar 09/24/2013 remove cpm support format 0x1E
+ * Fix src tags
+ * @rt002 902613 tapiar 10/10/2013 Support format 0x11 (IPS)
+ * @gm011 903410 milesg 10/22/2013 Support OCC_BACKUP_MASTER
+ * @gm012 905097 milesg 10/31/2013 support mem throttle & mem config packets
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs019 908218 gjsilva 12/04/2013 Support cooling request architecture
+ * @rt004 908817 tapiar 12/11/2013 Add apps as part of required data
+ * Skip pcap and freq data configs on slaves
+ * Remove updating global mask for pcap data
+ * so that it happens in slave code (write_data_pcap)
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ * @gm028 911670 milesg 02/27/2014 Fixed compile errors from stradale
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ * @fk008 942864 fmkassem 09/15/2014 BMC - APSS config data
+ * @gs042 942940 gjsilva 10/24/2014 Support for data packets in BMC-based systems
+ * @gs043 943177 gjsilva 10/30/2014 Support for mem data packets in BMC-based systems
+ * @ms001 943532 spinler 10/30/2014 Version 0x10 of frequency config data packet
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "cmdh_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "dcom.h"
+#include "occ_common.h"
+#include "state.h"
+#include "cmdh_fsp_cmds.h"
+#include "cmdhDbugCmd.h"
+#include "appletManager.h"
+#include "gpsm.h"
+#include "pstates.h"
+#include "proc_pstate.h"
+#include <amec_data.h>
+#include "amec_amester.h"
+#include "amec_service_codes.h"
+#include "amec_sys.h"
+#include <centaur_data.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define FREQ_FORMAT_PWR_MODE_NUM 6
+#define FREQ_FORMAT_BYTES_PER_MODE 3
+#define FREQ_FORMAT_BASE_DATA_SZ (sizeof(cmdh_store_mode_freqs_t) - sizeof(cmdh_fsp_cmd_header_t))
+#define FREQ_FORMAT_10_NUM_FREQS 3
+
+#define DATA_FREQ_VERSION_0 0
+#define DATA_FREQ_VERSION_10 0x10
+
+#define DATA_PCAP_VERSION_0 0
+#define DATA_PCAP_VERSION_10 0x10
+
+#define DATA_SYS_VERSION_0 0
+#define DATA_SYS_VERSION_10 0x10
+
+#define DATA_APSS_VERSION 0 // @at014a
+#define DATA_APSS_VERSION10 0x10 // @fk008a
+
+#define DATA_THRM_THRES_VERSION_1 1
+#define DATA_THRM_THRES_VERSION_10 0x10
+#define THRM_THRES_BASE_DATA_SZ_1 4
+#define THRM_THRES_BASE_DATA_SZ_10 3
+
+#define DATA_IPS_VERSION 0 // @rt002a
+
+#define DATA_MEM_CFG_VERSION_1 1
+#define DATA_MEM_CFG_VERSION_10 0x10
+
+#define DATA_MEM_THROT_VERSION_1 1
+#define DATA_MEM_THROT_VERSION_10 0x10
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//
+typedef struct data_req_table
+{
+ uint32_t mask;
+ uint8_t format;
+} data_req_table_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//
+data_cnfg_t G_data_cnfg_static_obj = {0};
+
+//
+data_cnfg_t * G_data_cnfg = &G_data_cnfg_static_obj;
+
+//
+const data_req_table_t G_data_pri_table[] =
+{
+ {DATA_MASK_SYS_CNFG, DATA_FORMAT_SYS_CNFG}, //Need this first so we can use correct huid's for callouts -- gm037
+ {DATA_MASK_APSS_CONFIG, DATA_FORMAT_APSS_CONFIG}, //need apss config data prior to role data -- gm037
+ {DATA_MASK_SET_ROLE, DATA_FORMAT_SET_ROLE},
+ {DATA_MASK_MEM_CFG, DATA_FORMAT_MEM_CFG},
+ {DATA_MASK_PSTATE_SUPERSTRUCTURE, DATA_FORMAT_PSTATE_SUPERSTRUCTURE},
+ {DATA_MASK_FREQ_PRESENT, DATA_FORMAT_FREQ}, //@gm006
+ {DATA_MASK_PCAP_PRESENT, DATA_FORMAT_POWER_CAP}, // @at013a
+ {DATA_MASK_THRM_THRESHOLDS, DATA_FORMAT_THRM_THRESHOLDS}, //@gs011
+ {DATA_MASK_MEM_THROT, DATA_FORMAT_MEM_THROT},
+};
+
+
+// rt002a
+// TODO: temporarily saving this off here not sure
+// it it belongs somewhere more appropriate
+cmdh_ips_config_data_t G_ips_config_data = {0};
+
+bool G_mem_monitoring_allowed = FALSE;
+
+// Global flag that indicates if VRMs are present. In the context of BMC-based
+// systems, if OCC doesn't get any VRM thermal control thresholds (data packet
+// 0x13), it should not attempt to talk to the VRMs. In the context of
+// FSP-based systems, then we assume VRMs are always present.
+uint8_t G_vrm_present = 1;
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
+// Function Specification
+//
+// Name: DATA_get_present_cnfgdata
+//
+// Description: Accessor function for external access
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint32_t DATA_get_present_cnfgdata(void)
+{
+ return G_data_cnfg->data_mask;
+}
+
+errlHndl_t DATA_get_thrm_thresholds(cmdh_thrm_thresholds_t **o_thrm_thresh)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ if(G_data_cnfg->data_mask & DATA_MASK_THRM_THRESHOLDS)
+ {
+ *o_thrm_thresh = &(G_data_cnfg->thrm_thresh);
+ }
+ else
+ {
+ TRAC_ERR("DATA_get_thrm_thresholds: Thermal Threshold data is unavailable! data_mask[0x%X]",
+ G_data_cnfg->data_mask);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_GET_THRM_THRESHOLDS
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 data mask showing which data OCC has received
+ * @userdata4 ERC_CMDH_THRM_DATA_MISSING
+ * @devdesc Someone is asking for the thermal control threholds
+ * and OCC hasn't received them yet from the FSP!
+ */
+ l_err = createErrl(DATA_GET_THRM_THRESHOLDS,
+ INTERNAL_FAILURE,
+ ERC_CMDH_THRM_DATA_MISSING,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_data_cnfg->data_mask,
+ 0);
+ }
+
+ return l_err;
+}
+
+errlHndl_t DATA_get_ips_cnfg(cmdh_ips_config_data_t **o_ips_cnfg)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ if(G_data_cnfg->data_mask & DATA_MASK_IPS_CNFG)
+ {
+ *o_ips_cnfg = &G_ips_config_data;
+ }
+ else
+ {
+ TRAC_ERR("DATA_get_ips_cnfg: IPS Config data is unavailable! data_mask[0x%X]",
+ G_data_cnfg->data_mask);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_GET_IPS_DATA
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 data mask showing which data OCC has received
+ * @userdata4 ERC_CMDH_IPS_DATA_MISSING
+ * @devdesc Someone is asking for the Idle Power Save config data
+ * and OCC hasn't received them yet from the FSP!
+ */
+ l_err = createErrl(DATA_GET_IPS_DATA,
+ INTERNAL_FAILURE,
+ ERC_CMDH_IPS_DATA_MISSING,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_data_cnfg->data_mask,
+ 0);
+ }
+
+ return l_err;
+}
+
+// Function Specification
+//
+// Name: DATA_request_cnfgdata
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t DATA_request_cnfgdata ()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_req = 0x00; //data to ask for
+ uint16_t i = 0;
+ uint16_t l_array_size = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ l_array_size = sizeof(G_data_pri_table) / sizeof(data_req_table_t);
+
+ for(i=0;i<l_array_size;i++)
+ {
+ //Skip requesting memory throttle values if memory monitoring
+ //is not being allowed by TMGT.
+ if((G_data_pri_table[i].format == DATA_FORMAT_MEM_THROT) &&
+ !G_mem_monitoring_allowed)
+ {
+ continue;
+ }
+
+ //Skip whenever we are trying to request pcap or freq as a slave @rt004a
+ if(((G_data_pri_table[i].format == DATA_FORMAT_POWER_CAP) ||
+ (G_data_pri_table[i].format == DATA_FORMAT_FREQ)) &&
+ (G_occ_role == OCC_SLAVE))
+ {
+ continue;
+ }
+
+ // Go through priority table and request first data found which has
+ // not been provided
+ if(!(G_data_cnfg->data_mask & G_data_pri_table[i].mask))
+ {
+ l_req = G_data_pri_table[i].format;
+ break;
+ }
+ }
+
+ return(l_req);
+}
+
+
+// Functior Specification
+//
+// Name: data_store_freq_data
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ errlHndl_t l_err = NULL;
+ uint16_t l_req_freq;
+ cmdh_store_mode_freqs_t* l_cmdp = (cmdh_store_mode_freqs_t*)i_cmd_ptr;
+ uint8_t* l_buf = ((uint8_t*)(l_cmdp)) + sizeof(cmdh_store_mode_freqs_t);
+ uint16_t l_data_length;
+ uint32_t l_mode_data_sz;
+ uint32_t i;
+ uint16_t l_freq = 0;
+ uint8_t l_mode = 0;
+ uint8_t l_count = FREQ_FORMAT_PWR_MODE_NUM; // @jh004a
+ uint16_t l_table[OCC_MODE_COUNT] = {0};
+
+ do
+ {
+ l_data_length = CMDH_DATALEN_FIELD_UINT16(l_cmdp);
+ l_mode_data_sz = l_data_length - FREQ_FORMAT_BASE_DATA_SZ;
+
+ //Sanity Checks
+ //if the datapacket is bigger than what we can store, OR
+ //if the version doesn't equal what we expect, OR
+ //if the expected data length does not agree with the actual data length, OR
+ //the format is 0x10 and we don't have room for the 3 2B frequencies
+ if((l_data_length < FREQ_FORMAT_BASE_DATA_SZ) ||
+ ((l_cmdp->version != DATA_FREQ_VERSION_0) && (l_cmdp->version != DATA_FREQ_VERSION_10)) ||
+ ((DATA_FREQ_VERSION_10 == l_cmdp->version) && (l_mode_data_sz != (FREQ_FORMAT_10_NUM_FREQS * 2))))
+
+ {
+ TRAC_ERR("Invalid Frequency Data packet: data_length[%u] version[%u] l_count[%u] l_mode_data_sz[%u]",
+ l_data_length, l_cmdp->version, l_count, l_mode_data_sz);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ if(OCC_MASTER != G_occ_role) //gm037
+ {
+ // We want to ignore this cnfg data if we are not the master.
+ break;
+ }
+
+ if (DATA_FREQ_VERSION_0 == l_cmdp->version)
+ {
+
+ // parse the packed 3-byte data entries and store them
+ // in the global data structure.
+ for(i = 0; i < l_mode_data_sz; i += FREQ_FORMAT_BYTES_PER_MODE)
+ {
+ l_mode = l_buf[i];
+ l_freq = (l_buf[i+1] << 8 | l_buf[i+2]);
+
+ if(l_mode == OCC_MODE_NOMINAL && !l_freq) //@gm006
+ {
+ TRAC_ERR("Received a frequency of 0 MHZ for nominal");
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ if(l_mode >= OCC_MODE_COUNT)
+ {
+ TRAC_ERR("Unrecognized frequency mode=%d ",
+ l_mode);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ // FFO Mode Checks - only need to verify when *in* FFO mode
+ if( ( OCC_MODE_FFO == CURRENT_MODE() )
+ && ( OCC_MODE_FFO == l_mode ) )
+ {
+ l_req_freq = l_freq;
+ // Check and make sure that FFO freq >= Fmin, if not, log an error.
+ if( l_freq < l_table[OCC_MODE_MIN_FREQUENCY] )
+ {
+ l_freq = l_table[OCC_MODE_MIN_FREQUENCY];
+ }
+ //// Check and make sure that FFO freq <= Fmax, if not, log an error.
+ else if ( l_freq > l_table[OCC_MODE_TURBO] )
+ {
+ l_freq = l_table[OCC_MODE_TURBO];
+ }
+
+ // log an error if we could not honor the requested FFO frequency, but keep going.
+ if(l_req_freq != l_freq)
+ {
+ TRAC_ERR("FFO Freq out of range. request=%d, limit=%d ",
+ l_req_freq, l_freq);
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_FREQ_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 requested frequency
+ * @userdata2 frequency used
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC recieved an invalid FFO frequency
+ */
+ l_err = createErrl(DATA_STORE_FREQ_DATA,
+ INVALID_INPUT_DATA,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_req_freq,
+ l_freq);
+ commitErrl(&l_err);
+ }
+ }
+
+ // Set the frequency for the passed in mode
+ TRAC_INFO("Mode %d frequency set: %d MHz",l_mode, l_freq);
+ l_table[l_mode] = l_freq;
+
+ // If the mode is Turbo, also stored that frequency for DPS modes
+ if(l_mode == OCC_MODE_TURBO)
+ {
+ l_table[OCC_MODE_DYN_POWER_SAVE] = l_freq;
+ l_table[OCC_MODE_DYN_POWER_SAVE_FP] = l_freq;
+ }
+ }
+ }
+ else //Version 0x10 - OpenPower
+ {
+ //First Nominal Freq, then Max Freq, then Min Freq, which we'll
+ //store under the existing enums.
+
+ l_freq = (l_buf[0] << 8 | l_buf[1]);
+ l_table[OCC_MODE_NOMINAL] = l_freq;
+
+ TRAC_INFO("Nominal frequency = %d", l_freq);
+
+ l_freq = (l_buf[2] << 8 | l_buf[3]);
+ l_table[OCC_MODE_TURBO] = l_freq;
+
+ TRAC_INFO("Max frequency = %d", l_freq);
+
+ l_freq = (l_buf[4] << 8 | l_buf[5]);
+ l_table[OCC_MODE_PWRSAVE] = l_freq;
+ l_table[OCC_MODE_MIN_FREQUENCY] = l_freq;
+
+ TRAC_INFO("Min frequency = %d", l_freq);
+
+ }
+
+ }while(0);
+
+ // Change Data Request Mask to indicate we got this data
+ if(!l_err && (G_occ_role == OCC_MASTER)) //gm037
+ {
+ //copy all of the frequency updates to the global and notify
+ //dcom of the new frequenies.
+ memcpy(G_sysConfigData.sys_mode_freq.table, l_table, sizeof(l_table));
+ G_sysConfigData.sys_mode_freq.update_count++;
+ G_data_cnfg->data_mask |= DATA_MASK_FREQ_PRESENT;
+ }
+ return l_err;
+}
+
+// @at014a - start
+// Function Specification
+//
+// Name: apss_store_adc_channel
+//
+// Description:
+//
+//
+//
+//
+//
+// End Function Specification
+errlHndl_t apss_store_adc_channel(const eApssAdcChannelAssignments i_func_id, const uint8_t i_channel_num )
+{
+ errlHndl_t l_err = NULL;
+
+ // Check function ID and channel number
+ if ( (i_func_id >= NUM_ADC_ASSIGNMENT_TYPES) ||
+ (i_channel_num >= MAX_APSS_ADC_CHANNELS) )
+ {
+ TRAC_ERR("apss_store_adc_channel: Invalid function ID or channel number (id:0x%x, channel:%d)", i_func_id, i_channel_num);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_APSS_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 function ID
+ * @userdata2 channel number
+ * @userdata4 ERC_APSS_ADC_OUT_OF_RANGE_FAILURE
+ * @devdesc Invalid function ID or channel number
+ */
+ l_err = createErrl(DATA_STORE_APSS_DATA,
+ INVALID_INPUT_DATA,
+ ERC_APSS_ADC_OUT_OF_RANGE_FAILURE,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ (uint32_t)i_func_id,
+ (uint32_t)i_channel_num);
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ else
+ {
+ uint8_t *l_adc_function=NULL;
+ switch (i_func_id)
+ {
+ case ADC_RESERVED:
+ // Do nothing
+ break;
+
+ case ADC_MEMORY_PROC_0:
+ case ADC_MEMORY_PROC_1:
+ case ADC_MEMORY_PROC_2:
+ case ADC_MEMORY_PROC_3:
+ l_adc_function = &G_sysConfigData.apss_adc_map.memory[i_func_id-ADC_MEMORY_PROC_0];
+ break;
+
+ case ADC_VDD_PROC_0:
+ case ADC_VDD_PROC_1:
+ case ADC_VDD_PROC_2:
+ case ADC_VDD_PROC_3:
+ l_adc_function = &G_sysConfigData.apss_adc_map.vdd[i_func_id-ADC_VDD_PROC_0];
+ break;
+
+ case ADC_VCS_VIO_VPCIE_PROC_0:
+ case ADC_VCS_VIO_VPCIE_PROC_1:
+ case ADC_VCS_VIO_VPCIE_PROC_2:
+ case ADC_VCS_VIO_VPCIE_PROC_3:
+ l_adc_function = &G_sysConfigData.apss_adc_map.vcs_vio_vpcie[i_func_id-ADC_VCS_VIO_VPCIE_PROC_0];
+ break;
+
+ case ADC_IO_A:
+ case ADC_IO_B:
+ case ADC_IO_C:
+ l_adc_function = &G_sysConfigData.apss_adc_map.io[i_func_id-ADC_IO_A];
+ break;
+
+ case ADC_FANS_A:
+ case ADC_FANS_B:
+ l_adc_function = &G_sysConfigData.apss_adc_map.fans[i_func_id-ADC_FANS_A];
+ break;
+
+ case ADC_STORAGE_A:
+ case ADC_STORAGE_B:
+ l_adc_function = &G_sysConfigData.apss_adc_map.storage_media[i_func_id-ADC_STORAGE_A];
+ break;
+
+ case ADC_12V_SENSE:
+ l_adc_function = &G_sysConfigData.apss_adc_map.sense_12v; // @ly008c
+ break;
+
+ case ADC_GND_REMOTE_SENSE:
+ l_adc_function = &G_sysConfigData.apss_adc_map.remote_gnd;
+ break;
+
+ case ADC_TOTAL_SYS_CURRENT:
+ l_adc_function = &G_sysConfigData.apss_adc_map.total_current_12v;
+ break;
+ // @ly008a - start
+ case ADC_MEM_CACHE:
+ l_adc_function = &G_sysConfigData.apss_adc_map.mem_cache;
+ break;
+ // @ly008a - end
+
+ case ADC_GPU_SENSE:
+ l_adc_function = &G_sysConfigData.apss_adc_map.gpu;
+ break;
+
+ default:
+ // It should never happen
+ TRAC_ERR("apss_store_gpio_pin: Invalid function ID: 0x%x", i_func_id);
+ break;
+ }
+
+ if(NULL != l_adc_function)
+ {
+ // Check if this function already have ADC channel assigned
+ if( SYSCFG_INVALID_ADC_CHAN == *l_adc_function)
+ {
+ *l_adc_function = i_channel_num;
+ }
+ else
+ {
+
+ TRAC_ERR("apss_store_adc_channel: Function ID is duplicated (id:0x%x, channel:%d)", i_func_id, i_channel_num);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_APSS_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 function ID
+ * @userdata2 channel number
+ * @userdata4 ERC_APSS_ADC_DUPLICATED_FAILURE
+ * @devdesc Function ID is duplicated
+ */
+ l_err = createErrl(DATA_STORE_APSS_DATA,
+ INVALID_INPUT_DATA,
+ ERC_APSS_ADC_DUPLICATED_FAILURE,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ (uint32_t)i_func_id,
+ (uint32_t)i_channel_num);
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ }
+ }
+
+ return l_err;
+}
+
+// @fk008a
+// Function Specification
+//
+// Name: apss_store_ipmi_sensor_id
+//
+// Description: Writes the given ipmi sensor ID provided by tmgt to the
+// associated power sensor.
+//
+// End Function Specification
+void apss_store_ipmi_sensor_id(const apss_cfg_adc_v10_t *i_adc)
+{
+ //Get current processor id.
+ uint8_t l_proc = G_pob_id.module_id;
+
+ switch (i_adc->assignment)
+ {
+ case ADC_RESERVED:
+ // Do nothing
+ break;
+ case ADC_MEMORY_PROC_0:
+ case ADC_MEMORY_PROC_1:
+ case ADC_MEMORY_PROC_2:
+ case ADC_MEMORY_PROC_3:
+ if (l_proc == (i_adc->assignment - ADC_MEMORY_PROC_0))
+ {
+ AMECSENSOR_PTR(PWR250USMEM0)->ipmi_sid = i_adc->ipmisensorId;
+ }
+ break;
+
+ case ADC_VDD_PROC_0:
+ case ADC_VDD_PROC_1:
+ case ADC_VDD_PROC_2:
+ case ADC_VDD_PROC_3:
+ if (l_proc == (i_adc->assignment - ADC_VDD_PROC_0))
+ {
+ AMECSENSOR_PTR(PWR250USVDD0)->ipmi_sid = i_adc->ipmisensorId;
+ }
+
+ break;
+
+ case ADC_VCS_VIO_VPCIE_PROC_0:
+ case ADC_VCS_VIO_VPCIE_PROC_1:
+ case ADC_VCS_VIO_VPCIE_PROC_2:
+ case ADC_VCS_VIO_VPCIE_PROC_3:
+ if (l_proc == (i_adc->assignment - ADC_VCS_VIO_VPCIE_PROC_0))
+ {
+ AMECSENSOR_PTR(PWR250USVCS0)->ipmi_sid = i_adc->ipmisensorId;
+ }
+ break;
+
+ case ADC_IO_A:
+ case ADC_IO_B:
+ case ADC_IO_C:
+ if (i_adc->ipmisensorId != 0)
+ {
+ AMECSENSOR_PTR(PWR250USIO)->ipmi_sid = i_adc->ipmisensorId;
+ }
+ break;
+
+ case ADC_FANS_A:
+ case ADC_FANS_B:
+ if (i_adc->ipmisensorId != 0)
+ {
+ AMECSENSOR_PTR(PWR250USFAN)->ipmi_sid = i_adc->ipmisensorId;
+ }
+ break;
+
+ case ADC_STORAGE_A:
+ case ADC_STORAGE_B:
+ if (i_adc->ipmisensorId != 0)
+ {
+ AMECSENSOR_PTR(PWR250USSTORE)->ipmi_sid = i_adc->ipmisensorId;
+ }
+ break;
+
+ case ADC_12V_SENSE:
+ //None
+ break;
+
+ case ADC_GND_REMOTE_SENSE:
+ //None
+ break;
+
+ case ADC_TOTAL_SYS_CURRENT:
+ //None
+ break;
+ case ADC_MEM_CACHE:
+ //None
+ break;
+
+ case ADC_GPU_SENSE:
+ if (i_adc->ipmisensorId != 0)
+ {
+ AMECSENSOR_PTR(PWR250USGPU)->ipmi_sid = i_adc->ipmisensorId;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+// Function Specification
+//
+// Name: apss_store_gpio_pin
+//
+// Description:
+//
+//
+//
+//
+//
+// End Function Specification
+errlHndl_t apss_store_gpio_pin(const eApssGpioAssignments i_func_id, const uint8_t i_gpio_num )
+{
+ errlHndl_t l_err = NULL;
+
+ // Check function ID and channel number
+ if ( (i_func_id >= NUM_GPIO_ASSIGNMENT_TYPES) ||
+ ( i_gpio_num >= (MAX_APSS_GPIO_PORTS*NUM_OF_APSS_PINS_PER_GPIO_PORT) ) )
+ {
+ TRAC_ERR("apss_store_gpio_pin: Invalid function ID or gpio number (id:0x%x, pin:%d)", i_func_id, i_gpio_num);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_APSS_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 function ID
+ * @userdata2 gpio number
+ * @userdata4 ERC_APSS_GPIO_OUT_OF_RANGE_FAILURE
+ * @devdesc Invalid function ID or gpio number
+ */
+ l_err = createErrl(DATA_STORE_APSS_DATA,
+ INVALID_INPUT_DATA,
+ ERC_APSS_GPIO_OUT_OF_RANGE_FAILURE,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ (uint32_t)i_func_id,
+ (uint32_t)i_gpio_num);
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ else
+ {
+ uint8_t *l_gpio_function = NULL;
+ switch (i_func_id)
+ {
+ case GPIO_RESERVED:
+ // Do nothing
+ break;
+
+ case GPIO_FAN_WATCHDOG_ERROR:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.fans_watchdog_error;
+ break;
+
+ case GPIO_FAN_FULL_SPEED:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.fans_full_speed;
+ break;
+
+ case GPIO_FAN_ERROR:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.fans_error;
+ break;
+
+ case GPIO_FAN_RESERVED:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.fans_reserved;
+ break;
+
+ case GPIO_VR_HOT_MEM_PROC_0:
+ case GPIO_VR_HOT_MEM_PROC_1:
+ case GPIO_VR_HOT_MEM_PROC_2:
+ case GPIO_VR_HOT_MEM_PROC_3:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.vr_fan[i_func_id-GPIO_VR_HOT_MEM_PROC_0];
+ break;
+ // @ly007a - start
+ case GPIO_CENT_EN_VCACHE0:
+ case GPIO_CENT_EN_VCACHE1:
+ case GPIO_CENT_EN_VCACHE2:
+ case GPIO_CENT_EN_VCACHE3:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.cent_en_vcache[i_func_id-GPIO_CENT_EN_VCACHE0];
+ break;
+
+ case CME_THROTTLE_N:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.cme_throttle_n;
+ break;
+
+ case GND_OC_N:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.gnd_oc_n;
+ break;
+
+ case DOM_A_OC_LATCH:
+ case DOM_B_OC_LATCH:
+ case DOM_C_OC_LATCH:
+ case DOM_D_OC_LATCH:
+ l_gpio_function = &G_sysConfigData.apss_gpio_map.dom_oc_latch[i_func_id-DOM_A_OC_LATCH];
+ break;
+ // @ly007a - end
+ default:
+ // It should never happen
+ TRAC_ERR("apss_store_gpio_pin: Invalid function ID: 0x%x", i_func_id);
+ break;
+ }
+
+ if(NULL != l_gpio_function)
+ {
+ // Check if this function already have ADC channel assigned
+ if( SYSCFG_INVALID_PIN == *l_gpio_function)
+ {
+ *l_gpio_function = i_gpio_num;
+ }
+ else
+ {
+
+ TRAC_ERR("apss_store_gpio_pin: Function ID is duplicated (id:0x%x, pin:%d)", i_func_id, i_gpio_num);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_APSS_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 function ID
+ * @userdata2 gpio number
+ * @userdata4 ERC_APSS_GPIO_DUPLICATED_FAILURE
+ * @devdesc Invalid function ID or channel number
+ */
+ l_err = createErrl(DATA_STORE_APSS_DATA,
+ INVALID_INPUT_DATA,
+ ERC_APSS_GPIO_DUPLICATED_FAILURE,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ (uint32_t)i_func_id,
+ (uint32_t)i_gpio_num);
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ }
+ }
+
+ return l_err;
+}
+
+//@fk008a
+// Function Specification
+//
+// Name: data_store_apss_config_v00
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_apss_config_v00(const cmdh_apss_config_v00_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ errlHndl_t l_err = NULL;
+
+ uint16_t l_channel = 0, l_port = 0, l_pin = 0;
+
+ // Set to default value
+ memset(&G_sysConfigData.apss_adc_map, SYSCFG_INVALID_ADC_CHAN, sizeof(G_sysConfigData.apss_adc_map));
+ memset(&G_sysConfigData.apss_gpio_map, SYSCFG_INVALID_PIN, sizeof(G_sysConfigData.apss_gpio_map));
+
+ // ADC channels info
+ for(l_channel=0;(l_channel < MAX_APSS_ADC_CHANNELS) && (NULL == l_err);l_channel++)
+ {
+ G_sysConfigData.apss_cal[l_channel].gnd_select = i_cmd_ptr->adc[l_channel].gnd_select;
+ G_sysConfigData.apss_cal[l_channel].gain = i_cmd_ptr->adc[l_channel].gain;
+ G_sysConfigData.apss_cal[l_channel].offset = i_cmd_ptr->adc[l_channel].offset;
+
+ // Assign the ADC channel
+ l_err = apss_store_adc_channel(i_cmd_ptr->adc[l_channel].assignment, l_channel);
+
+ }
+
+ if(NULL == l_err)
+ {
+ // GPIO Ports
+ for(l_port=0;(l_port < MAX_APSS_GPIO_PORTS) && (NULL == l_err);l_port++)
+ {
+ // GPIO mode
+ G_sysConfigData.apssGpioPortsMode[l_port] = i_cmd_ptr->gpio[l_port].mode;
+
+ // For each pin
+ for(l_pin=0; (l_pin < NUM_OF_APSS_PINS_PER_GPIO_PORT) && (NULL == l_err);l_pin++)
+ {
+ // Assign the GPIO number
+ l_err = apss_store_gpio_pin( i_cmd_ptr->gpio[l_port].assignment[l_pin],
+ (l_port*NUM_OF_APSS_PINS_PER_GPIO_PORT)+l_pin);
+
+ // @fk001a
+ // @sb000 FIXME #cmdh_fsp_cmds_datacnfg_c_001
+ // This is only needed for an ITE which would have an OC
+ // sensor for a chassis power connector
+ // Assign this global the correct pins when the oc pins are passed in.
+ G_conn_oc_pins_bitmap = 0x0000;
+ }
+
+ }
+
+ if(NULL == l_err)
+ {
+ // Change Data Request Mask to indicate we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_APSS_CONFIG;
+ TRAC_IMP("Got valid APSS Config data via TMGT");
+ }
+ }
+
+ return l_err;
+}
+
+
+//@fk008a
+// Function Specification
+//
+// Name: data_store_apss_config_v10
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_apss_config_v10(const cmdh_apss_config_v10_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ errlHndl_t l_err = NULL;
+
+ uint16_t l_channel = 0, l_port = 0, l_pin = 0;
+
+ // Set to default value
+ memset(&G_sysConfigData.apss_adc_map, SYSCFG_INVALID_ADC_CHAN, sizeof(G_sysConfigData.apss_adc_map));
+ memset(&G_sysConfigData.apss_gpio_map, SYSCFG_INVALID_PIN, sizeof(G_sysConfigData.apss_gpio_map));
+
+ // ADC channels info
+ for(l_channel=0;(l_channel < MAX_APSS_ADC_CHANNELS) && (NULL == l_err);l_channel++)
+ {
+ G_sysConfigData.apss_cal[l_channel].gnd_select = i_cmd_ptr->adc[l_channel].gnd_select;
+ G_sysConfigData.apss_cal[l_channel].gain = i_cmd_ptr->adc[l_channel].gain;
+ G_sysConfigData.apss_cal[l_channel].offset = i_cmd_ptr->adc[l_channel].offset;
+
+ // Assign the ADC channels
+ l_err = apss_store_adc_channel(i_cmd_ptr->adc[l_channel].assignment, l_channel);
+ if (l_err == NULL)
+ {
+ //Write sensor IDs to the powr sensors.
+ if (i_cmd_ptr->adc[l_channel].ipmisensorId != 0)
+ {
+ apss_store_ipmi_sensor_id(&(i_cmd_ptr->adc[l_channel]));
+ }
+ }
+
+ }
+
+ if(NULL == l_err)
+ {
+
+ // GPIO Ports
+ for(l_port=0;(l_port < MAX_APSS_GPIO_PORTS) && (NULL == l_err);l_port++)
+ {
+ // GPIO mode
+ G_sysConfigData.apssGpioPortsMode[l_port] = i_cmd_ptr->gpio[l_port].mode;
+
+ // For each pin
+ for(l_pin=0; (l_pin < NUM_OF_APSS_PINS_PER_GPIO_PORT) && (NULL == l_err);l_pin++)
+ {
+ // Assign the GPIO number
+ l_err = apss_store_gpio_pin( i_cmd_ptr->gpio[l_port].assignment[l_pin],
+ (l_port*NUM_OF_APSS_PINS_PER_GPIO_PORT)+l_pin);
+
+ // @fk001a
+ // @sb000 FIXME #cmdh_fsp_cmds_datacnfg_c_001
+ // This is only needed for an ITE which would have an OC
+ // sensor for a chassis power connector
+ // Assign this global the correct pins when the oc pins are passed in.
+ G_conn_oc_pins_bitmap = 0x0000;
+ }
+
+ }
+
+ if(NULL == l_err)
+ {
+ // Change Data Request Mask to indicate we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_APSS_CONFIG;
+ TRAC_IMP("Got valid APSS Config data via TMGT");
+ }
+ }
+
+ return l_err;
+}
+
+
+//@fk008c
+// Function Specification
+//
+// Name: data_store_apss_config
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_apss_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ errlHndl_t l_err = NULL;
+ //Temporarly cast to version 0x10 struct just to get version number.
+ cmdh_apss_config_v10_t *l_cmd_ptr = (cmdh_apss_config_v10_t *)i_cmd_ptr;
+ uint16_t l_data_length = CMDH_DATALEN_FIELD_UINT16(l_cmd_ptr); //Command length
+ uint32_t l_v00_data_sz = sizeof(cmdh_apss_config_v00_t) - sizeof(cmdh_fsp_cmd_header_t);
+ uint32_t l_v10_data_sz = sizeof(cmdh_apss_config_v10_t) - sizeof(cmdh_fsp_cmd_header_t);
+
+ if(!( ((l_cmd_ptr->version == DATA_APSS_VERSION) && (l_v00_data_sz == l_data_length)) ||
+ ((l_cmd_ptr->version == DATA_APSS_VERSION10) && (l_v10_data_sz == l_data_length)) ) )
+ {
+ TRAC_ERR("data_store_apss_config: Invalid System Data packet. Given Version:0x%X",
+ l_cmd_ptr->version);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_APSS_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 data size
+ * @userdata2 packet version
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC recieved an invalid data packet from the FSP
+ */
+ l_err = createErrl(DATA_STORE_APSS_DATA,
+ INVALID_INPUT_DATA,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_data_length,
+ (uint32_t)l_cmd_ptr->version);
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ else if (l_cmd_ptr->version == DATA_APSS_VERSION) //Version 0
+ {
+ l_err = data_store_apss_config_v00((cmdh_apss_config_v00_t *)i_cmd_ptr, o_rsp_ptr);
+ } else //Version 0x10
+ {
+ l_err = data_store_apss_config_v10(l_cmd_ptr, o_rsp_ptr);
+ }
+
+ return l_err;
+}
+
+
+// @at014a - end
+
+
+// Function Specification
+//
+// Name: data_store_pstate_super
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_pstate_super(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ // Cast the command to the struct for this format
+ cmdh_store_cnfgdata_pstatess_t * l_cmd_ptr = (cmdh_store_cnfgdata_pstatess_t *)i_cmd_ptr;
+
+ do
+ {
+ // Command Length Check - make sure we have all the data
+ if( CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) < CMDH_CNFGDATA_PSTATESS_DATALEN)
+ {
+ TRAC_ERR("data_store_pstate_super: Invalid command length! expected[%u] received[%u]",
+ CMDH_CNFGDATA_PSTATESS_DATALEN,
+ CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr));
+
+ // Build Error Response packet, it will get 'rebuilt' later, but
+ // we are doing this here to generate the errlHndl
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_CMD_LEN, &l_errlHndl);
+ break;
+ }
+
+ // Only initialize Pstate once
+ if( G_gpsm_initialized == 0 ) // @at017a
+ {
+ // Initialze Pstate Table from PstateSuperStructure passed in
+ // via the DATA in this command.
+ l_errlHndl = proc_gpsm_pstate_initialize(&l_cmd_ptr->pstatess);
+ }
+
+ if(NULL == l_errlHndl)
+ {
+ // Change Data Request Mask to indicate we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_PSTATE_SUPERSTRUCTURE;
+ }
+ } while(0);
+
+ return l_errlHndl;
+}
+
+// Function Specification
+//
+// Name: data_store_role
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_role(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_errlHndl = NULL;
+ uint8_t l_old_role = G_occ_role;
+ uint8_t l_new_role = OCC_SLAVE;
+ uint8_t l_fir_master = 0x00;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // Cast the command to the struct for this format
+ cmdh_set_role_t * l_cmd_ptr = (cmdh_set_role_t *)i_cmd_ptr;
+
+ // With BMC-based systems, there is a FIR Master bit
+ l_fir_master = l_cmd_ptr->role >> 7;
+
+ // Mask off the FIR Master bit
+ l_new_role = l_cmd_ptr->role & 0x7F;
+
+
+ // Must be in standby state before we can change roles
+ if ( CURRENT_STATE() == OCC_STATE_STANDBY )
+ {
+ if( OCC_MASTER == l_new_role )
+ {
+ G_occ_role = OCC_MASTER;
+
+ // Run master initializations if we just became master
+ extern void master_occ_init(void);
+ master_occ_init();
+
+ // Turn off anything slave related since we are a master
+ rtl_clr_run_mask_deferred(RTL_FLAG_NOTMSTR);
+ rtl_set_run_mask_deferred(RTL_FLAG_MSTR);
+
+ // Allow APSS tasks to run on OCC master -- gm037
+ rtl_clr_run_mask_deferred(RTL_FLAG_APSS_NOT_INITD);
+
+ TRAC_IMP("OCC Role set to Master via TMGT");
+
+ // Change Data Request Mask to indicate we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_SET_ROLE;
+
+ // Make sure return code is success
+ l_rc = ERRL_RC_SUCCESS;
+ }
+ else if( (OCC_SLAVE == l_new_role ) ||
+ (OCC_BACKUP_MASTER == l_new_role)) //gm011
+ {
+ if(OCC_MASTER == l_old_role)
+ {
+ G_occ_role = OCC_SLAVE;
+
+ // Turn off anything master related since we are a slave
+ rtl_clr_run_mask_deferred(RTL_FLAG_MSTR);
+ rtl_set_run_mask_deferred(RTL_FLAG_NOTMSTR);
+
+ // Slave code will automatically recognize we no longer
+ // have a master.
+ }
+ //else{
+ // We must not have changed roles. This is allowed.
+ // Specifically, when TMGT tells each OCC it's role
+ // after reset.}
+
+ //If this is a backup master occ, we need to be checking the APSS health -- gm037
+ if(OCC_BACKUP_MASTER == l_new_role)
+ {
+ OCC_APLT_STATUS_CODES l_status = OCC_APLT_SUCCESS;
+
+ //initialize APSS communication on the backup OCC (retries internally)
+ runApplet(OCC_APLT_APSS_INIT, // Applet enum name
+ NULL, // Applet arguments
+ TRUE, // Blocking call?
+ NULL, // Applet finished semaphore
+ &l_errlHndl, // Error log handle
+ &l_status); // Error status
+
+ if(l_errlHndl || (l_status != OCC_APLT_SUCCESS))
+ {
+ //don't request due to a backup apss failure. Just log the error.
+ TRAC_ERR("APSS init applet returned error: l_status: 0x%x", l_status);
+ commitErrl(&l_errlHndl);
+ }
+
+ //Allow APSS tasks to run on OCC backup
+ rtl_clr_run_mask_deferred(RTL_FLAG_APSS_NOT_INITD);
+ TRAC_IMP("OCC Role set to Backup Master via TMGT");
+ }
+ else
+ {
+ //NOTE: slave initialization is done on all
+ // OCC's during OCC initialization.
+ TRAC_IMP("OCC Role set to Slave via TMGT");
+ }
+
+ // Change Data Request Mask to indicate we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_SET_ROLE;
+
+ // Make sure return code is success
+ l_rc = ERRL_RC_SUCCESS;
+
+ }
+ else
+ {
+ TRAC_ERR("OCC Role from FSP is not recognized by OCC. role = %d", l_new_role);
+
+ l_rc = ERRL_RC_INVALID_DATA;
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_GENERIC_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 Reason input data failed
+ * @userdata2 Requested role
+ * @userdata4 ERC_INVALID_INPUT_DATA
+ * @devdesc Bad config data passed to OCC
+ */
+ l_errlHndl = createErrl(DATA_STORE_GENERIC_DATA, //modId
+ INVALID_INPUT_DATA, //reasoncode
+ ERC_INVALID_INPUT_DATA, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ l_new_role); //userdata2
+ }
+ }
+ else
+ {
+ TRAC_ERR("Role change requested while OCC is not in standby state. role= %d, state= %d", l_new_role, CURRENT_STATE());
+
+ l_rc = ERRL_RC_INVALID_STATE;
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_GENERIC_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 Reason input data failed
+ * @userdata2 current state
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Bad config data passed to OCC
+ */
+ l_errlHndl = createErrl(DATA_STORE_GENERIC_DATA, //modId
+ INVALID_INPUT_DATA, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ CURRENT_STATE()); //userdata2
+ }
+
+ if( ERRL_RC_SUCCESS != l_rc )
+ {
+ // Send back an error response to TMGT
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errlHndl); // @th036
+ }
+
+ return l_errlHndl;
+}
+
+// Function Specification
+//
+// Name: data_store_power_cap
+//
+// Description: This function should only be run by MASTER OCC when
+// power cap data is received from TMGT.
+//
+//
+//
+// Flow: 04/03/13 FN=data_store_format7.odg
+//
+// Changedby: @at013a @fk001c
+//
+// End Function Specification
+errlHndl_t data_store_power_cap(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ // Cast the command to the struct for this format
+ cmdh_pcap_config_t * l_cmd_ptr = (cmdh_pcap_config_t *)i_cmd_ptr;
+ uint16_t l_data_length = 0;
+ uint32_t l_pcap_data_sz = 0;
+ static uint8_t L_pcap_count = 0;
+ bool l_invalid_input = TRUE; //Assume bad input
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ l_data_length = CONVERT_UINT8_ARRAY_UINT16(l_cmd_ptr->data_length[0], l_cmd_ptr->data_length[1]);
+
+ // Check version and length
+ if(l_cmd_ptr->version == DATA_PCAP_VERSION_0)
+ {
+ l_pcap_data_sz = sizeof(cmdh_pcap_config_t) - sizeof(cmdh_fsp_cmd_header_t);
+ if(l_pcap_data_sz == l_data_length)
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+ else if(l_cmd_ptr->version == DATA_PCAP_VERSION_10)
+ {
+ l_pcap_data_sz = sizeof(cmdh_pcap_config_v10_t) - sizeof(cmdh_fsp_cmd_header_t);
+ if(l_pcap_data_sz == l_data_length)
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+
+ // This is the master OCC and packet data length and version are valid?
+ // TMGT should never send this packet to a slave OCC.
+ // if the is not master, OR
+ // if the version doesn't equal what we expect, OR
+ // if the expected data length does not agree with the actual data length...
+ if((OCC_MASTER != G_occ_role) || l_invalid_input)
+ {
+ TRAC_ERR("data_store_power_cap: Invalid Pcap Data packet! OCC_role[%d] Version[0x%02X] Data_size[%u]",
+ G_occ_role, l_cmd_ptr->version, l_data_length);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_PCAP_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 data size
+ * @userdata2 packet version (Bytes 0-1) / role (Bytes 2-3)
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC recieved an invalid data packet from the FSP or OCC role is not MASTER
+ */
+ l_err = createErrl(DATA_STORE_PCAP_DATA,
+ INVALID_INPUT_DATA,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL,
+ 0,
+ l_data_length,
+ ((uint32_t)l_cmd_ptr->version)<<16 | G_occ_role);
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ }
+ else
+ {
+ if(l_cmd_ptr->version == DATA_SYS_VERSION_0)
+ {
+ // Copy power cap data into G_master_pcap_data
+ memcpy(&G_master_pcap_data, &l_cmd_ptr->pcap_config, sizeof(cmdh_pcap_config_data_t));
+ }
+ else if(l_cmd_ptr->version == DATA_SYS_VERSION_10)
+ {
+ // Copy data
+ cmdh_pcap_config_v10_t * l_cmd2_ptr = (cmdh_pcap_config_v10_t *)i_cmd_ptr;
+ G_master_pcap_data.soft_min_pcap = l_cmd2_ptr->pcap_config.min_pcap;
+ G_master_pcap_data.hard_min_pcap = l_cmd2_ptr->pcap_config.min_pcap;
+ G_master_pcap_data.max_pcap = l_cmd2_ptr->pcap_config.sys_max_pcap;
+ G_master_pcap_data.oversub_pcap = l_cmd2_ptr->pcap_config.oversub_pcap;
+ G_master_pcap_data.system_pcap = l_cmd2_ptr->pcap_config.sys_max_pcap;
+ G_master_pcap_data.unthrottle = 0;
+
+ // NOTE: The customer power cap will be set via a separate command
+ // from BMC/HTMGT.
+ }
+
+ // The last byte in G_master_pcap_data is a counter that needs to be incremented.
+ // It tells the master and slave code that there is new
+ // pcap data. This should not be incremented until
+ // after the packet data has been copied into
+ // G_master_pcap_data.
+ L_pcap_count++;
+ G_master_pcap_data.pcap_data_count = L_pcap_count;
+
+ // Change Data Request Mask to indicate we got this data
+ //G_data_cnfg->data_mask |= DATA_MASK_PCAP_PRESENT;
+ //will update data mask when slave code acquires data @rt004d
+ TRAC_IMP("data store pcap: Got valid PCAP Config data via TMGT. Count:%i, Data Cfg mask[%x]",G_master_pcap_data.pcap_data_count, G_data_cnfg->data_mask);
+ }
+
+ return l_err;
+}
+
+// @at014a - start
+// Function Specification
+//
+// Name: data_store_sys_config
+//
+// Description:
+//
+//
+//
+//
+// Flow: None
+//
+// End Function Specification
+errlHndl_t data_store_sys_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ // Cast the command to the struct for this format
+ cmdh_sys_config_t * l_cmd_ptr = (cmdh_sys_config_t *)i_cmd_ptr;
+ uint16_t l_data_length = 0;
+ uint32_t l_sys_data_sz = 0;
+ bool l_invalid_input = TRUE; //Assume bad input
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ l_data_length = CMDH_DATALEN_FIELD_UINT16(l_cmd_ptr);
+
+ // Check length and version
+ if(l_cmd_ptr->version == DATA_SYS_VERSION_0)
+ {
+ l_sys_data_sz = sizeof(cmdh_sys_config_t) - sizeof(cmdh_fsp_cmd_header_t);
+ if(l_sys_data_sz == l_data_length)
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+ else if(l_cmd_ptr->version == DATA_SYS_VERSION_10)
+ {
+ l_sys_data_sz = sizeof(cmdh_sys_config_v10_t) - sizeof(cmdh_fsp_cmd_header_t);
+ if(l_sys_data_sz == l_data_length)
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+
+ if(l_invalid_input)
+ {
+ TRAC_ERR("data_store_sys_config: Invalid System Data packet! Version[0x%02X] Data_size[%u]",
+ l_cmd_ptr->version,
+ l_data_length);
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_SYS_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 data size
+ * @userdata2 packet version
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC recieved an invalid data packet from the FSP
+ */
+ l_err = createErrl(DATA_STORE_SYS_DATA,
+ INVALID_INPUT_DATA,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_data_length,
+ (uint32_t)l_cmd_ptr->version);
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ else
+ {
+ if(l_cmd_ptr->version == DATA_SYS_VERSION_0)
+ {
+ // Copy data
+ G_sysConfigData.system_type.byte = l_cmd_ptr->sys_config.system_type; //@gm008
+ G_sysConfigData.proc_huid = l_cmd_ptr->sys_config.proc_huid;
+ G_sysConfigData.backplane_huid = l_cmd_ptr->sys_config.backplane_huid;
+ G_sysConfigData.apss_huid = l_cmd_ptr->sys_config.apss_huid;
+ G_sysConfigData.dpss_huid = l_cmd_ptr->sys_config.dpss_huid;
+ }
+ else if(l_cmd_ptr->version == DATA_SYS_VERSION_10)
+ {
+ // Copy data
+ cmdh_sys_config_v10_t * l_cmd2_ptr = (cmdh_sys_config_v10_t *)i_cmd_ptr;
+ G_sysConfigData.system_type.byte = l_cmd2_ptr->sys_config.system_type;
+ G_sysConfigData.backplane_huid = l_cmd2_ptr->sys_config.backplane_sid;
+ G_sysConfigData.apss_huid = l_cmd2_ptr->sys_config.apss_sid;
+
+ //FIXME: Need to store the sensor IDs
+ }
+
+ // Change Data Request Mask to indicate we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_SYS_CNFG;
+ TRAC_IMP("Got valid System Config data via TMGT for system type: 0x%02X", l_cmd_ptr->sys_config.system_type);
+ }
+
+ return l_err;
+}
+// @at014a - end
+
+// Function Specification
+//
+// Name: data_store_thrm_thresholds
+//
+// Description: Store the thermal control thresholds sent by TMGT. This data is
+// sent to all OCCs.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_thrm_thresholds(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ cmdh_thrm_thresholds_t* l_cmd_ptr = (cmdh_thrm_thresholds_t*)i_cmd_ptr;
+ uint16_t i = 0;
+ uint16_t l_data_length = 0;
+ uint16_t l_exp_data_length = 0;
+ uint8_t l_frutype = 0;
+ cmdh_thrm_thresholds_v10_t* l_cmd2_ptr = (cmdh_thrm_thresholds_v10_t*)i_cmd_ptr;
+ uint8_t l_num_data_sets = 0;
+ bool l_invalid_input = TRUE; //Assume bad input
+ bool l_vrm_frutype = FALSE;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ l_data_length = CMDH_DATALEN_FIELD_UINT16(l_cmd_ptr);
+
+ // Sanity checks on input data, break if:
+ // * data packet is smaller than the base size, OR
+ // * the version doesn't match what we expect, OR
+ // * the actual data length does not match the expected data length.
+ if(l_cmd_ptr->version == DATA_THRM_THRES_VERSION_1)
+ {
+ l_num_data_sets = l_cmd_ptr->num_data_sets;
+ l_exp_data_length = THRM_THRES_BASE_DATA_SZ_1 +
+ (l_num_data_sets * sizeof(cmdh_thrm_thresholds_set_t));
+
+ if((l_exp_data_length == l_data_length) &&
+ (l_data_length >= THRM_THRES_BASE_DATA_SZ_1))
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+ else if(l_cmd_ptr->version == DATA_THRM_THRES_VERSION_10)
+ {
+ l_num_data_sets = l_cmd2_ptr->num_data_sets;
+ l_exp_data_length = THRM_THRES_BASE_DATA_SZ_10 +
+ (l_num_data_sets * sizeof(cmdh_thrm_thresholds_set_v10_t));
+
+ if((l_exp_data_length == l_data_length) &&
+ (l_data_length >= THRM_THRES_BASE_DATA_SZ_10))
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+
+ if(l_invalid_input)
+ {
+ TRAC_ERR("data_store_thrm_thresholds: Invalid Thermal Control Threshold Data packet: data_length[%u] version[0x%02X] num_data_sets[%u]",
+ l_data_length,
+ l_cmd_ptr->version,
+ l_num_data_sets);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ if(l_cmd_ptr->version == DATA_THRM_THRES_VERSION_1)
+ {
+ // Store the base data
+ G_data_cnfg->thrm_thresh.version = l_cmd_ptr->version;
+ G_data_cnfg->thrm_thresh.fan_control_loop_time = l_cmd_ptr->fan_control_loop_time;
+ G_data_cnfg->thrm_thresh.num_data_sets = l_cmd_ptr->num_data_sets;
+
+ // Store the FRU related data
+ for(i=0; i<l_cmd_ptr->num_data_sets; i++)
+ {
+ // Get the FRU type
+ l_frutype = l_cmd_ptr->data[i].fru_type;
+
+ if((l_frutype >= 0) && (l_frutype < DATA_FRU_MAX))
+ {
+ // Copy FRU data
+ memcpy((void *)&G_data_cnfg->thrm_thresh.data[l_frutype],
+ (void *)&l_cmd_ptr->data[i],
+ sizeof(cmdh_thrm_thresholds_set_t));
+
+ // Useful trace for debugging
+ //TRAC_INFO("data_store_thrm_thresholds: FRU_type[0x%.2X] T_control[%u] DVFS[%u]",
+ // G_data_cnfg->thrm_thresh.data[l_frutype].fru_type,
+ // G_data_cnfg->thrm_thresh.data[l_frutype].t_control,
+ // G_data_cnfg->thrm_thresh.data[l_frutype].dvfs);
+ }
+ else
+ {
+ // We got an invalid FRU type
+ TRAC_ERR("data_store_thrm_thresholds: Received an invalid FRU type[0x%.2X] max_FRU_number[0x%.2X]",
+ l_frutype,
+ DATA_FRU_MAX);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+ }
+ }
+ else if(l_cmd_ptr->version == DATA_THRM_THRES_VERSION_10)
+ {
+ // Store the base data
+ G_data_cnfg->thrm_thresh.version = l_cmd2_ptr->version;
+ G_data_cnfg->thrm_thresh.fan_control_loop_time = 0; //Indicates not to run fan control loop
+ G_data_cnfg->thrm_thresh.num_data_sets = l_cmd2_ptr->num_data_sets;
+
+ // Store the FRU related data
+ for(i=0; i<l_cmd2_ptr->num_data_sets; i++)
+ {
+ // Get the FRU type
+ l_frutype = l_cmd2_ptr->data[i].fru_type;
+
+ if((l_frutype >= 0) && (l_frutype < DATA_FRU_MAX))
+ {
+ // Copy FRU data
+ G_data_cnfg->thrm_thresh.data[l_frutype].fru_type = l_frutype;
+ G_data_cnfg->thrm_thresh.data[l_frutype].dvfs = l_cmd2_ptr->data[i].dvfs;
+ G_data_cnfg->thrm_thresh.data[l_frutype].error = l_cmd2_ptr->data[i].error;
+ G_data_cnfg->thrm_thresh.data[l_frutype].pm_dvfs = l_cmd2_ptr->data[i].dvfs;
+ G_data_cnfg->thrm_thresh.data[l_frutype].pm_error = l_cmd2_ptr->data[i].error;
+ G_data_cnfg->thrm_thresh.data[l_frutype].max_read_timeout = l_cmd2_ptr->data[i].max_read_timeout;
+
+ // Set a local flag if we get data for VRM FRU type
+ if(l_frutype == DATA_FRU_VRM)
+ {
+ l_vrm_frutype = TRUE;
+ }
+
+ // Useful trace for debugging
+ //TRAC_INFO("data_store_thrm_thresholds: FRU_type[0x%.2X] T_control[%u] DVFS[%u] Error[%u]",
+ // G_data_cnfg->thrm_thresh.data[l_frutype].fru_type,
+ // G_data_cnfg->thrm_thresh.data[l_frutype].t_control,
+ // G_data_cnfg->thrm_thresh.data[l_frutype].dvfs,
+ // G_data_cnfg->thrm_thresh.data[l_frutype].error);
+ }
+ else
+ {
+ // We got an invalid FRU type
+ TRAC_ERR("data_store_thrm_thresholds: Received an invalid FRU type[0x%.2X] max_FRU_number[0x%.2X]",
+ l_frutype,
+ DATA_FRU_MAX);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+ }
+
+ // Did we get data for VRM FRU type?
+ if(l_vrm_frutype)
+ {
+ // Then, set a global variable so that OCC attempts to talk to
+ // the VRMs
+ G_vrm_present = 1;
+ }
+ else
+ {
+ // No VRM data was received, so do not attempt to talk to the VRMs.
+ // Also, make the error count very high so that the health
+ // monitor doesn't complain about VRHOT being asserted.
+ G_vrm_present = 0;
+ G_data_cnfg->thrm_thresh.data[DATA_FRU_VRM].error_count = 0xFF;
+
+ TRAC_IMP("data_store_thrm_thresholds: No VRM data was received! OCC won't attempt to talk to VRMs.");
+ }
+ }
+
+ } while(0);
+
+ if(!l_err)
+ {
+ // If there were no errors, indicate that we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_THRM_THRESHOLDS;
+ TRAC_IMP("data_store_thrm_thresholds: Got valid Thermal Control Threshold data packet");
+
+ // Notify thermal thread to update its local copy of the thermal thresholds
+ THRM_thread_update_thresholds();
+ }
+
+ return l_err;
+}
+
+
+// Function Specification
+//
+// Name: data_store_mem_cfg
+//
+// Description: Store the HUID's for centaurs and dimms. This data is
+// sent to each OCC individually.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ cmdh_mem_cfg_t* l_cmd_ptr = (cmdh_mem_cfg_t*)i_cmd_ptr;
+ uint16_t l_data_length = 0;
+ uint16_t l_exp_data_length = 0;
+ uint8_t l_num_centaurs = 0;
+ uint8_t l_num_dimms = 0;
+ int i;
+ bool l_invalid_input = TRUE; //Assume bad input
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ l_data_length = CMDH_DATALEN_FIELD_UINT16((&l_cmd_ptr->header));
+
+ // Sanity checks on input data, break if:
+ // * the version doesn't match what we expect, OR
+ // * the actual data length does not match the expected data length.
+ if(l_cmd_ptr->header.version == DATA_MEM_CFG_VERSION_1)
+ {
+ l_exp_data_length = sizeof(cmdh_mem_cfg_header_t) - sizeof(cmdh_fsp_cmd_header_t) +
+ (l_cmd_ptr->header.num_data_sets * sizeof(cmdh_mem_cfg_data_set_t));
+
+ if(l_exp_data_length == l_data_length)
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+ else if(l_cmd_ptr->header.version == DATA_MEM_CFG_VERSION_10)
+ {
+ l_exp_data_length = sizeof(cmdh_mem_cfg_header_t) - sizeof(cmdh_fsp_cmd_header_t) +
+ (l_cmd_ptr->header.num_data_sets * sizeof(cmdh_mem_cfg_data_set_v10_t));
+
+ if(l_exp_data_length == l_data_length)
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+
+ if(l_invalid_input)
+ {
+ TRAC_ERR("data_store_mem_cfg: Invalid mem config data packet: data_length[%u] exp_length[%u] version[0x%02X] num_data_sets[%u]",
+ l_data_length,
+ l_exp_data_length,
+ l_cmd_ptr->header.version,
+ l_cmd_ptr->header.num_data_sets);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ if(l_cmd_ptr->header.num_data_sets == 0)
+ {
+ TRAC_IMP("Memory monitoring is not allowed (mem config data sets = 0)");
+ }
+ else
+ {
+ //This notifies other code that we need to request the mem throt packet
+ //and we need to enable memory monitoring when we enter observation state
+ G_mem_monitoring_allowed = TRUE;
+
+ //Require the mem throt packet for going to active and observation states
+ SMGR_VALIDATE_DATA_ACTIVE_MASK |= DATA_MASK_MEM_THROT;
+ SMGR_VALIDATE_DATA_OBSERVATION_MASK |= DATA_MASK_MEM_THROT;
+
+ TRAC_IMP("Memory monitoring is allowed (mem config data sets = %d)",
+ l_cmd_ptr->header.num_data_sets);
+ }
+
+ if(l_cmd_ptr->header.version == DATA_MEM_CFG_VERSION_1)
+ {
+ // Store the huid mapping
+ for(i=0; i<l_cmd_ptr->header.num_data_sets; i++)
+ {
+ cmdh_mem_cfg_data_set_t* l_data_set = &l_cmd_ptr->data_set[i];
+ //validate the centaur and dimm #'s for this data set
+ if(l_data_set->centaur_num >= MAX_NUM_CENTAURS ||
+ (l_data_set->dimm_num != 0xFF &&
+ l_data_set->dimm_num >= NUM_DIMMS_PER_CENTAUR))
+ {
+ TRAC_ERR("data_store_mem_cfg: Invalid dimm or centaur number. entry=%d, cent=%d, dimm=%d",
+ i,
+ l_data_set->centaur_num,
+ l_data_set->dimm_num);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ //Per the spec, if dimm_num = 0xFF then this is a centaur HUID
+ if(l_data_set->dimm_num == 0xFF)
+ {
+ G_sysConfigData.centaur_huids[l_data_set->centaur_num] = l_data_set->huid;
+ l_num_centaurs++;
+ }
+ else
+ {
+ G_sysConfigData.dimm_huids[l_data_set->centaur_num][l_data_set->dimm_num] =
+ l_data_set->huid;
+ l_num_dimms++;
+ }
+ }
+ }
+ else if(l_cmd_ptr->header.version == DATA_MEM_CFG_VERSION_10)
+ {
+ // Store the hardware sensor ID and the temperature sensor ID
+ for(i=0; i<l_cmd_ptr->header.num_data_sets; i++)
+ {
+ cmdh_mem_cfg_v10_t* l_cmd2_ptr = (cmdh_mem_cfg_v10_t*)i_cmd_ptr;
+ cmdh_mem_cfg_data_set_v10_t* l_data_set = &l_cmd2_ptr->data_set[i];
+
+ // Validate the centaur and dimm #'s for this data set
+ if(l_data_set->centaur_num >= MAX_NUM_CENTAURS ||
+ (l_data_set->dimm_num != 0xFF &&
+ l_data_set->dimm_num >= NUM_DIMMS_PER_CENTAUR))
+ {
+ TRAC_ERR("data_store_mem_cfg: Invalid dimm or centaur number. entry=%d, cent=%d, dimm=%d",
+ i,
+ l_data_set->centaur_num,
+ l_data_set->dimm_num);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ //Per the spec, if dimm_num = 0xFF then this is a centaur ID
+ if(l_data_set->dimm_num == 0xFF)
+ {
+ // Store the hardware sensor ID
+ G_sysConfigData.centaur_huids[l_data_set->centaur_num] = l_data_set->hw_sensor_id;
+
+ // Store the temperature sensor ID
+ g_amec->proc[0].memctl[l_data_set->centaur_num].centaur.temp_sid =
+ l_data_set->temp_sensor_id;
+
+ l_num_centaurs++;
+ }
+ else
+ {
+ // Store the hardware sensor ID
+ G_sysConfigData.dimm_huids[l_data_set->centaur_num][l_data_set->dimm_num] =
+ l_data_set->hw_sensor_id;
+
+ // Store the temperature sensor ID
+ g_amec->proc[0].memctl[l_data_set->centaur_num].centaur.dimm_temps[l_data_set->dimm_num].temp_sid =
+ l_data_set->temp_sensor_id;
+
+ l_num_dimms++;
+ }
+ }
+ }
+
+ } while(0);
+
+ if(!l_err)
+ {
+ // If there were no errors, indicate that we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_MEM_CFG;
+ TRAC_IMP("data_store_mem_cfg: Got valid mem cfg packet. cent#=%d, dimm#=%d",
+ l_num_centaurs, l_num_dimms);
+ }
+
+ return l_err;
+}
+
+
+// Function Specification
+//
+// Name: data_store_mem_throt
+//
+// Description: Store min/max mem throttle settings. This data is
+// sent to each OCC individually.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t data_store_mem_throt(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ cmdh_mem_throt_t* l_cmd_ptr = (cmdh_mem_throt_t*)i_cmd_ptr;
+ uint16_t l_data_length = 0;
+ uint16_t l_exp_data_length = 0;
+ int i;
+ uint16_t l_configured_mbas = 0;
+ bool l_invalid_input = TRUE; //Assume bad input
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+ l_data_length = CMDH_DATALEN_FIELD_UINT16((&l_cmd_ptr->header));
+
+ // Sanity checks on input data, break if:
+ // * the version doesn't match what we expect, OR
+ // * the actual data length does not match the expected data length.
+ if(l_cmd_ptr->header.version == DATA_MEM_THROT_VERSION_1)
+ {
+ l_exp_data_length = sizeof(cmdh_mem_throt_header_t) - sizeof(cmdh_fsp_cmd_header_t) +
+ (l_cmd_ptr->header.num_data_sets * sizeof(cmdh_mem_throt_data_set_t));
+
+ if(l_exp_data_length == l_data_length)
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+ else if(l_cmd_ptr->header.version == DATA_MEM_THROT_VERSION_10)
+ {
+ l_exp_data_length = sizeof(cmdh_mem_throt_header_t) - sizeof(cmdh_fsp_cmd_header_t) +
+ (l_cmd_ptr->header.num_data_sets * sizeof(cmdh_mem_throt_data_set_v10_t));
+
+ if(l_exp_data_length == l_data_length)
+ {
+ l_invalid_input = FALSE;
+ }
+ }
+
+ if(l_invalid_input)
+ {
+ TRAC_ERR("data_store_mem_throt: Invalid mem throttle data packet: data_length[%u] exp_length[%u] version[0x%02X] num_data_sets[%u]",
+ l_data_length,
+ l_exp_data_length,
+ l_cmd_ptr->header.version,
+ l_cmd_ptr->header.num_data_sets);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ if(l_cmd_ptr->header.version == DATA_MEM_THROT_VERSION_1)
+ {
+ // Store the memory throttle settings
+ for(i=0; i<l_cmd_ptr->header.num_data_sets; i++)
+ {
+ cmdh_mem_throt_data_set_t* l_data_set = &l_cmd_ptr->data_set[i];
+ mem_throt_config_data_t l_temp_set;
+ uint16_t * l_n_ptr;
+
+ //validate the centaur and mba #'s for this data set
+ if(l_data_set->centaur_num >= MAX_NUM_CENTAURS ||
+ l_data_set->mba_num >= NUM_MBAS_PER_CENTAUR)
+ {
+ TRAC_ERR("data_store_mem_throt: Invalid mba or centaur number. entry=%d, cent=%d, mba=%d",
+ i,
+ l_data_set->centaur_num,
+ l_data_set->mba_num);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ //copy into a temporary buffer while we check for N values of 0
+ memcpy(&l_temp_set, &(l_data_set->min_ot_n_per_mba), sizeof(mem_throt_config_data_t));
+
+ //a 0 for any N value is an error
+ for(l_n_ptr = &l_temp_set.min_ot_n_per_mba; l_n_ptr <= &l_temp_set.ovs_n_per_chip; l_n_ptr++)
+ {
+ if(!(*l_n_ptr))
+ {
+ TRAC_ERR("data_store_mem_throt: Memory Throttle N value is 0! cent[%d] mba[%d]",
+ l_data_set->centaur_num, l_data_set->mba_num);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ }
+ if(l_err)
+ {
+ break;
+ }
+
+ memcpy(&G_sysConfigData.mem_throt_limits[l_data_set->centaur_num][l_data_set->mba_num],
+ &(l_data_set->min_ot_n_per_mba),
+ sizeof(mem_throt_config_data_t));
+
+ l_configured_mbas |= 1 << ((l_data_set->centaur_num * 2) + l_data_set->mba_num);
+ }
+ }
+ else if(l_cmd_ptr->header.version == DATA_MEM_THROT_VERSION_10)
+ {
+ // Store the memory throttle settings
+ for(i=0; i<l_cmd_ptr->header.num_data_sets; i++)
+ {
+ cmdh_mem_throt_v10_t* l_cmd2_ptr = (cmdh_mem_throt_v10_t*)i_cmd_ptr;
+ cmdh_mem_throt_data_set_v10_t* l_data_set = &l_cmd2_ptr->data_set[i];
+ mem_throt_config_data_t l_temp_set;
+ uint16_t * l_n_ptr;
+
+ //validate the centaur and mba #'s for this data set
+ if(l_data_set->centaur_num >= MAX_NUM_CENTAURS ||
+ l_data_set->mba_num >= NUM_MBAS_PER_CENTAUR)
+ {
+ TRAC_ERR("data_store_mem_throt: Invalid mba or centaur number. entry=%d, cent=%d, mba=%d",
+ i,
+ l_data_set->centaur_num,
+ l_data_set->mba_num);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ //copy into a temporary buffer while we check for N values of 0
+ //memcpy(&l_temp_set, &(l_data_set->min_ot_n_per_mba), sizeof(mem_throt_config_data_t));
+ l_temp_set.min_ot_n_per_mba = l_data_set->min_ot_n_per_mba;
+ l_temp_set.nom_n_per_mba = l_data_set->redupwr_n_per_mba;
+ l_temp_set.nom_n_per_chip = l_data_set->redupwr_n_per_chip;
+ l_temp_set.turbo_n_per_mba = l_data_set->redupwr_n_per_mba;
+ l_temp_set.turbo_n_per_chip = l_data_set->redupwr_n_per_chip;
+ l_temp_set.ovs_n_per_mba = l_data_set->ovs_n_per_mba;
+ l_temp_set.ovs_n_per_chip = l_data_set->ovs_n_per_chip;
+
+ //a 0 for any N value is an error
+ for(l_n_ptr = &l_temp_set.min_ot_n_per_mba; l_n_ptr <= &l_temp_set.ovs_n_per_chip; l_n_ptr++)
+ {
+ if(!(*l_n_ptr))
+ {
+ TRAC_ERR("data_store_mem_throt: Memory Throttle N value is 0! cent[%d] mba[%d]",
+ l_data_set->centaur_num, l_data_set->mba_num);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+ }
+ if(l_err)
+ {
+ break;
+ }
+
+ memcpy(&G_sysConfigData.mem_throt_limits[l_data_set->centaur_num][l_data_set->mba_num],
+ &l_temp_set,
+ sizeof(mem_throt_config_data_t));
+
+ l_configured_mbas |= 1 << ((l_data_set->centaur_num * 2) + l_data_set->mba_num);
+ }
+ }
+
+ } while(0);
+
+ if(!l_err)
+ {
+ // If there were no errors, indicate that we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_MEM_THROT;
+ TRAC_IMP("data_store_mem_throt: Got valid mem throt packet. configured_mba_bitmap=0x%04x",
+ l_configured_mbas);
+
+ //update the configured mba bitmap
+ G_configured_mbas = l_configured_mbas;
+ }
+
+ return l_err;
+}
+
+
+// @rt002a - start
+// Function Specification
+//
+// Name: data_store_ips_config
+//
+// Description:
+//
+//
+//
+//
+// Flow: None
+//
+// End Function Specification
+errlHndl_t data_store_ips_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ errlHndl_t l_err = NULL;
+ cmdh_ips_config_t *l_cmd_ptr = (cmdh_ips_config_t *)i_cmd_ptr;// Cast the command to the struct for this format
+ uint16_t l_data_length = CMDH_DATALEN_FIELD_UINT16(l_cmd_ptr);
+ uint32_t l_ips_data_sz = sizeof(cmdh_ips_config_t) - sizeof(cmdh_fsp_cmd_header_t);
+
+
+ // Check if this is the Master OCC. Check length and version
+ if((OCC_MASTER != G_occ_role) ||
+ (l_cmd_ptr->iv_version != DATA_IPS_VERSION) ||
+ ( l_ips_data_sz != l_data_length) )
+ {
+ TRAC_ERR("data_store_ips_config: Invalid IPS Data packet");
+
+ /* @
+ * @errortype
+ * @moduleid DATA_STORE_IPS_DATA
+ * @reasoncode INVALID_INPUT_DATA
+ * @userdata1 data size
+ * @userdata2 packet version
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC recieved an invalid data packet from the FSP
+ */
+ l_err = createErrl(DATA_STORE_IPS_DATA,
+ INVALID_INPUT_DATA,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_data_length,
+ (uint32_t)l_cmd_ptr->iv_version);
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ else
+ {
+ // Copy data somewhere
+ memcpy(&G_ips_config_data, &l_cmd_ptr->iv_ips_config, sizeof(cmdh_ips_config_data_t));
+
+ // Change Data Request Mask to indicate we got this data
+ G_data_cnfg->data_mask |= DATA_MASK_IPS_CNFG;
+
+ TRAC_IMP("Got valid Idle Power Save Config data via TMGT: ipsEnabled[%d] Delay Time to enter IPS[%d], exit IPS[%d]. Utilization to enter IPS[%d], exit IPS[%d]",
+ l_cmd_ptr->iv_ips_config.iv_ipsEnabled,
+ l_cmd_ptr->iv_ips_config.iv_delayTimeforEntry,
+ l_cmd_ptr->iv_ips_config.iv_delayTimeforExit,
+ l_cmd_ptr->iv_ips_config.iv_utilizationForEntry,
+ l_cmd_ptr->iv_ips_config.iv_utilizationForExit );
+ }
+
+ return l_err;
+}
+// @rt002a - end
+
+// Function Specification
+//
+// Name: DATA_store_cnfgdata
+//
+// Description:
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t DATA_store_cnfgdata (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_errlHndl = NULL;
+ UINT32 l_new_data = 0;
+ ERRL_RC l_rc = ERRL_RC_INTERNAL_FAIL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ memset(o_rsp_ptr,0,(size_t)(sizeof(cmdh_fsp_rsp_t)));
+
+ TRAC_IMP("Data Config Packet Received Type: 0x%02x",i_cmd_ptr->data[0]);
+
+ switch (i_cmd_ptr->data[0])
+ {
+ //case DATA_FORMAT_TABLE_OFFSET:
+ //case DATA_FORMAT_ACTIVE_CORES:
+ //case DATA_FORMAT_PROC_IIC_ADDR: // This is not needed
+
+ //case DATA_FORMAT_TEMP:
+ //case DATA_FORMAT_VRM_SETPOINT:
+ //case DATA_FORMAT_AMBIENT:
+ //case DATA_FORMAT_ALTITUDE:
+ //case DATA_FORMAT_DYN_POWER:
+ //case DATA_FORMAT_FAN_CONTROL:
+ //case DATA_FORMAT_POWR_SUP_CALI:
+ //case DATA_FORMAT_GX_HOST_BRIDGE_TEMP:
+ //case DATA_FORMAT_ENVIRONMENT_WINDOW:
+ //case DATA_FORMAT_P7IOC_TEMPERATURE:
+ //case DATA_FORMAT_ETHERNET_TEMPERATURE:
+ //case DATA_FORMAT_AME_CIR_CALIB:
+
+ case DATA_FORMAT_FREQ:
+ l_errlHndl = data_store_freq_data(i_cmd_ptr , o_rsp_ptr);
+ if(NULL == l_errlHndl)
+ {
+ l_new_data = DATA_MASK_FREQ_PRESENT; // @th015
+ }
+ break;
+
+ case DATA_FORMAT_PSTATE_SUPERSTRUCTURE: // @th010
+ // Initialize the Pstate Table, based on the passed in
+ // PstateSuperStructure.
+
+ l_errlHndl = data_store_pstate_super(i_cmd_ptr, o_rsp_ptr);
+ if(NULL == l_errlHndl)
+ {
+ // Set this in case AMEC needs to know about this
+ l_new_data = DATA_MASK_PSTATE_SUPERSTRUCTURE; // @th015
+ }
+ break;
+
+ case DATA_FORMAT_SET_ROLE:
+ // Initialze our role to either be a master of a slave
+ // We must be in Standby State for this command to be
+ // accepted.
+
+ l_errlHndl = data_store_role(i_cmd_ptr, o_rsp_ptr);
+ if(NULL == l_errlHndl)
+ {
+ // Set this in case AMEC needs to know about this
+ l_new_data = DATA_MASK_SET_ROLE;
+ }
+ break;
+
+ case DATA_FORMAT_APSS_CONFIG:
+ // Initialze APSS settings so that OCC can correctly interpret
+ // the data that it gets from the APSS
+ l_errlHndl = data_store_apss_config(i_cmd_ptr, o_rsp_ptr); // @at014a
+
+ if(NULL == l_errlHndl)
+ {
+ // Set this in case AMEC needs to know about this
+ l_new_data = DATA_MASK_APSS_CONFIG;
+ }
+ break;
+
+ case DATA_FORMAT_POWER_CAP: // @at013a
+ // Store the pcap data in G_master_pcap_data
+ l_errlHndl = data_store_power_cap(i_cmd_ptr, o_rsp_ptr);
+
+ if(NULL == l_errlHndl)
+ {
+ // Set this in case AMEC needs to know about this
+ l_new_data = DATA_MASK_PCAP_PRESENT;
+ }
+ break;
+
+ case DATA_FORMAT_SYS_CNFG: // @at014a
+ // Store the system config data in G_sysConfigData
+ l_errlHndl = data_store_sys_config(i_cmd_ptr, o_rsp_ptr);
+
+ if(NULL == l_errlHndl)
+ {
+ // Set this in case AMEC needs to know about this
+ l_new_data = DATA_MASK_SYS_CNFG;
+ }
+ break;
+
+ case DATA_FORMAT_IPS_CNFG: // @rt002a
+ // Store the system config data in G_sysConfigData
+ l_errlHndl = data_store_ips_config(i_cmd_ptr, o_rsp_ptr);
+
+ if(NULL == l_errlHndl)
+ {
+ // Set this in case AMEC needs to know about this
+ l_new_data = DATA_MASK_IPS_CNFG;
+ }
+ break;
+
+ case DATA_FORMAT_THRM_THRESHOLDS:
+ // Store the thermal control thresholds sent by TMGT
+ l_errlHndl = data_store_thrm_thresholds(i_cmd_ptr, o_rsp_ptr);
+
+ if(NULL == l_errlHndl)
+ {
+ // Set this in case AMEC needs to know about this
+ l_new_data = DATA_MASK_THRM_THRESHOLDS;
+ }
+ break;
+
+ case DATA_FORMAT_MEM_CFG:
+ // Store HUID mapping for centaurs and dimms
+ l_errlHndl = data_store_mem_cfg(i_cmd_ptr, o_rsp_ptr);
+ if(NULL == l_errlHndl)
+ {
+ l_new_data = DATA_MASK_MEM_CFG;
+ }
+ break;
+
+ case DATA_FORMAT_MEM_THROT:
+ // Store memory throttle limits
+ l_errlHndl = data_store_mem_throt(i_cmd_ptr, o_rsp_ptr);
+ if(NULL == l_errlHndl)
+ {
+ l_new_data = DATA_MASK_MEM_THROT;
+ }break;
+
+ case DATA_FORMAT_CLEAR_ALL: // @at015a
+ // Make sure not in ACTIVE
+ if(CURRENT_STATE() != OCC_STATE_ACTIVE)
+ {
+ // Clear all configuration data except for any data needed to support observation
+ TRAC_INFO("Clear all active configuration data");
+ G_data_cnfg->data_mask &= SMGR_VALIDATE_DATA_OBSERVATION_MASK;
+
+ // Clear the frequencies config data
+ memset(&G_sysConfigData.sys_mode_freq.table[0], 0, sizeof(G_sysConfigData.sys_mode_freq.table)); // @at017a
+
+ }
+ else
+ {
+ TRAC_ERR("Failed to clear all active configuration data because we are in ACTIVE state");
+ l_rc = ERRL_RC_INVALID_STATE;
+ }
+ break;
+
+ default:
+ // Build Error Response packet, we are calling this here
+ // to generate the error log, it will get called again, below but
+ // that's ok, as long as we set l_rc here.
+ l_rc = ERRL_RC_INVALID_DATA;
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errlHndl); // @th036
+ break;
+ }
+
+ if((!l_errlHndl) && (l_new_data))
+ {
+ // Don't send a poll if we just received one or our periodic data
+ // packets like supernova, dimm, or p5ioc temperatures. This causes
+ // TMGT to wrap there trace with our attentions
+ // For simplicity, don't poll if we don't have any new data to
+ // request
+ if(DATA_request_cnfgdata() != 0)
+ {
+ //poll after we get new data to either inform the FSP that we need more,
+ //or inform the FSP that we have everything needed for a new state.
+ cmdh_fsp_attention(OCC_ALERT_FSP_SERVICE_REQD);
+ }
+
+ // Notify AMEC component of new data
+ AMEC_data_change(l_new_data); // @th015
+ }
+
+ if(l_errlHndl)
+ {
+ // Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errlHndl); // @th036
+ }
+ else
+ {
+ /// Build Response Packet - all formats return success with no data
+ o_rsp_ptr->data_length[0] = 0;
+ o_rsp_ptr->data_length[1] = 0;
+ o_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ }
+
+ return(l_errlHndl);
+}
+
diff --git a/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h b/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h
new file mode 100755
index 0000000..698c3a8
--- /dev/null
+++ b/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h
@@ -0,0 +1,550 @@
+/******************************************************************************
+// @file cmdh_fsp_cmds_datacnfg.h
+// @brief Command Handling for FSP Communication.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_fsp_cmds_datacnfg_h cmdh_fsp_cmds_datacnfg_h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th022 thallet 10/05/2012 Created
+ * @at013 878755 alvinwan 04/17/2013 OCC power capping implementation
+ * @at014 882077 alvinwan 05/09/2013 Support APSS and System Config data from TMGT
+ * @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
+ * @jh004 889884 joshych 07/24/2013 Support CPM param and updated frequency packet
+ * @th046 894648 thallet 08/08/2013 Fix Coreq problem with TMGT
+ * @gs010 899888 gjsilva 09/24/2013 Process data format 0x13 from TMGT
+ * @rt001 902613 tapiar 10/14/2013 Process data format 0x11 from TMGT
+ * @gm012 905097 milesg 10/31/2013 support mem throttle & mem config packets
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @fk008 942864 fmkassem 09/15/2014 BMC - APSS config data
+ * @gs042 942940 gjsilva 10/24/2014 Support for data packets in BMC-based systems
+ * @gs043 943177 gjsilva 10/30/2014 Support for mem data packets in BMC-based systems
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _CMDH_FSP_CMDS_DATACNFG_H
+#define _CMDH_FSP_CMDS_DATACNFG_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "cmdh_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "occ_common.h"
+#include "state.h"
+#include "cmdh_fsp.h"
+#include "gpsm.h"
+#include "pstates.h"
+#include "cmdh_fsp_cmds.h"
+#include "apss.h" // @at014a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//---------------------------------------------------------
+// ConfigData Store Command
+//---------------------------------------------------------
+
+/**
+ * @enum eConfigDataFormatVersion
+ * @brief Enum of the various CnfgData command formats that
+ * are sent to OC over the TMGT<->OCC interface.
+ */
+typedef enum
+{
+ DATA_FORMAT_PSTATE_SUPERSTRUCTURE = 0x01,
+ DATA_FORMAT_FREQ = 0x02,
+ DATA_FORMAT_SET_ROLE = 0x03,
+ DATA_FORMAT_APSS_CONFIG = 0x04,
+ DATA_FORMAT_MEM_CFG = 0x05,
+ DATA_FORMAT_POWER_CAP = 0x07, // @at013a
+ DATA_FORMAT_SYS_CNFG = 0x0f, // @at014a
+ DATA_FORMAT_IPS_CNFG = 0x11, // @rt001a
+ DATA_FORMAT_MEM_THROT = 0x12,
+ DATA_FORMAT_THRM_THRESHOLDS = 0x13, // @gs010a
+ DATA_FORMAT_CLEAR_ALL = 0xff, // @at015a
+} eConfigDataFormatVersion;
+
+/**
+ * @enum eConfigDataPriorityMask
+ * @brief Enum of the various Cnfg Data Masks that are used
+ * to signal that OCC has received cnfg data
+ */
+typedef enum
+{
+ DATA_MASK_PSTATE_SUPERSTRUCTURE = 0x00000001,
+ DATA_MASK_FREQ_PRESENT = 0x00000002,
+ DATA_MASK_SET_ROLE = 0x00000004,
+ DATA_MASK_APSS_CONFIG = 0x00000008,
+ DATA_MASK_PCAP_PRESENT = 0x00000010, // @at013a
+ DATA_MASK_SYS_CNFG = 0x00000020, // @at014a
+ //0x00000040 not assigned.
+ DATA_MASK_THRM_THRESHOLDS = 0x00000080, // @gs010a
+ DATA_MASK_IPS_CNFG = 0x00000100, // @rt001a
+ DATA_MASK_MEM_CFG = 0x00000200,
+ DATA_MASK_MEM_THROT = 0x00000400,
+} eConfigDataPriorityMask;
+
+typedef enum
+{
+ DATA_FRU_PROC = 0x00,
+ DATA_FRU_CENTAUR = 0x01,
+ DATA_FRU_DIMM = 0x02,
+ DATA_FRU_VRM = 0x03,
+ DATA_FRU_MAX,
+} eConfigDataFruType;
+
+/**
+ * @struct cmdh_store_cnfgdata_pstatess_t
+ * @brief Used by TMGT to send OCC the PstateSuperStruct
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t reserved[3];
+ PstateSuperStructure pstatess;
+}cmdh_store_cnfgdata_pstatess_t; // @th010
+#define CMDH_CNFGDATA_PSTATESS_DATALEN (sizeof(PstateSuperStructure) + 4)
+
+/**
+ * @struct cmdh_store_mode_freqs_t
+ * @brief Used by TMGT to send OCC the frequencies for each mode.
+ */
+typedef struct __attribute__ ((packed)) // @jh004c
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+}cmdh_store_mode_freqs_t;
+
+
+/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+/// TODO: START of HACK for 889884
+///
+
+/**
+ * @struct cmdh_store_mode_freqs_old_t
+ * @brief Old way used by TMGT to send OCC the frequencies for each mode.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ uint8_t mode_count;
+}cmdh_store_mode_freqs_old_t;
+
+///
+/// TODO: END of HACK
+/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+/**
+ * @struct cmdh_set_role_t
+ * @brief Used by TMGT to tell OCC if it is a master or not
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t role;
+ uint8_t reserved[2];
+}cmdh_set_role_t;
+
+/**
+ * @struct apss_cfg_adc_t
+ * @brief Used by TMGT to send OCC the APSS ADC Config Data
+ */
+//@fk008c
+typedef struct __attribute__ ((packed))
+{
+ uint8_t assignment;
+ uint8_t gnd_select;
+ uint32_t gain;
+ uint32_t offset;
+} apss_cfg_adc_v00_t; //Used by FSP
+
+//@fk008a
+typedef struct __attribute__ ((packed))
+{
+ uint8_t assignment;
+ uint16_t ipmisensorId;
+ uint8_t gnd_select;
+ uint32_t gain;
+ uint32_t offset;
+} apss_cfg_adc_v10_t; //Used by Habanero
+
+/**
+ * @struct apss_cfg_gpio_t
+ * @brief Used by TMGT to send OCC the GPIO Config Data
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint8_t mode;
+ uint8_t __reserved;
+ uint8_t assignment[8];
+} apss_cfg_gpio_t;
+
+/**
+ * @struct cmdh_apss_config_t
+ * @brief Used by TMGT to send OCC the full APSS config data.
+ */
+//@fk008c
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version; // @at014c
+ uint8_t reserved[2]; // @at014c
+ apss_cfg_adc_v00_t adc[MAX_APSS_ADC_CHANNELS]; // @at014c
+ apss_cfg_gpio_t gpio[MAX_APSS_GPIO_PORTS]; // @at014c
+}cmdh_apss_config_v00_t; //Used by FSP
+
+//@fk008a
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ uint8_t reserved[2];
+ apss_cfg_adc_v10_t adc[MAX_APSS_ADC_CHANNELS];
+ apss_cfg_gpio_t gpio[MAX_APSS_GPIO_PORTS];
+}cmdh_apss_config_v10_t; //Used by Habanero
+
+// @at013a - start
+/**
+ * @struct cmdh_pcap_config_data_t
+ * @brief Used by TMGT to send OCC the PCAP config data.
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint16_t current_pcap; // Node power cap requested by customer (AEM) in 1W units
+ uint16_t soft_min_pcap; // Minimum node power cap allowed in 1W units
+ uint16_t hard_min_pcap; // Minimum guaranteed node power cap in 1W units
+ uint16_t max_pcap; // Maximum customer settable node power cap in 1W units
+ uint16_t oversub_pcap; // Node power cap to be used for oversubscripion in 1W units
+ uint16_t system_pcap; // Fixed node power cap required by the system in 1W units
+ uint8_t unthrottle; // Only used on ITEs -- is indicated from CMM
+} cmdh_pcap_config_data_t;
+
+/**
+ * @struct cmdh_pcap_config_t
+ * @brief Used by TMGT to send OCC the PCAP config data.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ cmdh_pcap_config_data_t pcap_config;
+}cmdh_pcap_config_t;
+// @at013a - end
+
+typedef struct __attribute__ ((packed))
+{
+ uint16_t min_pcap; // Minimum guaranteed node power cap in 1W units
+ uint16_t sys_max_pcap; // Fixed node power cap required by the system in 1W units
+ uint16_t oversub_pcap; // Node power cap to be used for oversubscripion in 1W units
+} cmdh_pcap_config_data_v10_t;
+
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ cmdh_pcap_config_data_v10_t pcap_config;
+}cmdh_pcap_config_v10_t;
+
+// @at014a - start
+/**
+ * @struct cmdh_sys_config_data_t
+ * @brief Used by TMGT to send OCC the System config data.
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint8_t system_type; // OCC usage of this byte is TBD
+ uint64_t proc_huid; // Processor HUID
+ uint64_t backplane_huid; // Backplane HUID
+ uint64_t apss_huid; // APSS HUID
+ uint64_t dpss_huid; // DPSS HUID
+} cmdh_sys_config_data_t;
+
+/**
+ * @struct cmdh_sys_config_t
+ * @brief Used by TMGT to send OCC the system config data.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ cmdh_sys_config_data_t sys_config;
+}cmdh_sys_config_t;
+// @at014a - end
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t system_type; // General system type
+ uint16_t sensor_id[25]; // FIXME: Probably we need to break down into individual fields
+ uint16_t backplane_sid; // Backplane Sensor ID
+ uint16_t apss_sid; // APSS Sensor ID
+} cmdh_sys_config_data_v10_t;
+
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ cmdh_sys_config_data_v10_t sys_config;
+}cmdh_sys_config_v10_t;
+
+// @rt001a - start
+/**
+ * @struct cmdh_ips_config_data_t
+ * @brief Used by TMGT to send OCC the IPS config data.
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint8_t iv_ipsEnabled; // Idle Power Save Enabled (0 or 1)
+ uint16_t iv_delayTimeforEntry; // Delay Time in seconds to enter Idle Power
+ uint8_t iv_utilizationForEntry; // Utilization threshold percentage to enter Idle Power
+ uint16_t iv_delayTimeforExit; // Delay Time in seconds to exit Idle Power
+ uint8_t iv_utilizationForExit; // Utilization threshold percentage to exit Idle Power
+
+} cmdh_ips_config_data_t;
+
+/**
+ * @struct cmdh_ips_config_t
+ * @brief Used by TMGT to send OCC the IPS config data.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t iv_format;
+ uint8_t iv_version;
+ cmdh_ips_config_data_t iv_ips_config;
+}cmdh_ips_config_t;
+
+extern cmdh_ips_config_data_t G_ips_config_data;
+
+// @rt001a - end
+
+
+/**
+ * @struct cmdh_thrm_thresholds_set_t
+ * @brief Used by TMGT to send OCC thermal control thresholds
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint8_t fru_type;
+ uint8_t t_control;
+ uint8_t dvfs;
+ uint8_t error;
+ uint8_t pm_t_control;
+ uint8_t pm_dvfs;
+ uint8_t pm_error;
+ uint8_t acoustic_t_control;
+ uint8_t acoustic_dvfs;
+ uint8_t acoustic_error;
+ uint8_t warning;
+ uint8_t warning_reset;
+ uint8_t error_count;
+ uint8_t sample_time;
+ uint8_t sample_error_count;
+ uint8_t max_read_timeout;
+ uint16_t t_inc_zone1;
+ uint16_t t_inc_zone2;
+ uint16_t t_inc_zone3;
+ uint16_t t_inc_zone4;
+ uint16_t t_inc_zone5;
+ uint16_t t_inc_zone6;
+ uint16_t t_inc_zone7;
+ uint16_t t_inc_zone8;
+}cmdh_thrm_thresholds_set_t;
+
+/**
+ * @struct cmdh_thrm_thresholds_t
+ * @brief Used by TMGT to send OCC thermal control thresholds
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ uint8_t fan_control_loop_time;
+ uint8_t num_data_sets;
+ cmdh_thrm_thresholds_set_t data[DATA_FRU_MAX];
+}cmdh_thrm_thresholds_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t fru_type;
+ uint8_t dvfs;
+ uint8_t error;
+ uint8_t max_read_timeout;
+}cmdh_thrm_thresholds_set_v10_t;
+
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ uint8_t num_data_sets;
+ cmdh_thrm_thresholds_set_v10_t data[DATA_FRU_MAX];
+}cmdh_thrm_thresholds_v10_t;
+
+
+/**
+ * @struct cmdh_mem_cfg_header_t
+ * @brief header data for mem cfg packet
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ uint8_t num_data_sets;
+}cmdh_mem_cfg_header_t;
+
+/**
+ * @struct cmdh_mem_cfg_data_set_t
+ * @brief Maps an HUID to a centaur or dimm
+ * 0xFF for dimm means this is for a centaur
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint64_t huid;
+ uint8_t centaur_num;
+ uint8_t dimm_num;
+ uint16_t reserved;
+}cmdh_mem_cfg_data_set_t;
+
+/**
+ * @struct cmdh_mem_cfg_t
+ * @brief config packet definition used by TMGT to
+ * send HUID mappings for centaurs and dimms
+ */
+typedef struct __attribute__ ((packed))
+{
+ cmdh_mem_cfg_header_t header;
+ cmdh_mem_cfg_data_set_t data_set[1];
+}cmdh_mem_cfg_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint32_t reserved;
+ uint16_t hw_sensor_id;
+ uint16_t temp_sensor_id;
+ uint8_t centaur_num;
+ uint8_t dimm_num;
+ uint16_t reserved2;
+}cmdh_mem_cfg_data_set_v10_t;
+
+typedef struct __attribute__ ((packed))
+{
+ cmdh_mem_cfg_header_t header;
+ cmdh_mem_cfg_data_set_v10_t data_set[1];
+}cmdh_mem_cfg_v10_t;
+
+
+/**
+ * @struct cmdh_mem_throt_header_t
+ * @brief header data for mem throttle packet
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t format;
+ uint8_t version;
+ uint8_t num_data_sets;
+}cmdh_mem_throt_header_t;
+
+/**
+ * @struct cmdh_mem_throt_data_set_t
+ * @brief provides memory throttle min and max values
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint8_t centaur_num;
+ uint8_t mba_num;
+ uint16_t min_ot_n_per_mba;
+ uint16_t nom_n_per_mba;
+ uint16_t nom_n_per_chip;
+ uint16_t turbo_n_per_mba;
+ uint16_t turbo_n_per_chip;
+ uint16_t ovs_n_per_mba;
+ uint16_t ovs_n_per_chip;
+}cmdh_mem_throt_data_set_t;
+
+/**
+ * @struct cmdh_mem_throt_t
+ * @brief config packet definition used by TMGT to
+ * send mem throttle min/max settings.
+ */
+typedef struct __attribute__ ((packed))
+{
+ cmdh_mem_throt_header_t header;
+ cmdh_mem_throt_data_set_t data_set[1];
+}cmdh_mem_throt_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t centaur_num;
+ uint8_t mba_num;
+ uint16_t min_ot_n_per_mba;
+ uint16_t redupwr_n_per_mba;
+ uint16_t redupwr_n_per_chip;
+ uint16_t ovs_n_per_mba;
+ uint16_t ovs_n_per_chip;
+}cmdh_mem_throt_data_set_v10_t;
+
+typedef struct __attribute__ ((packed))
+{
+ cmdh_mem_throt_header_t header;
+ cmdh_mem_throt_data_set_v10_t data_set[1];
+}cmdh_mem_throt_v10_t;
+
+
+/**
+ * @struct data_cnfg_t
+ * @brief Used to mark present the config data TMGT has sent us.
+ */
+typedef struct data_cnfg
+{
+ uint32_t data_mask;
+ cmdh_thrm_thresholds_t thrm_thresh;
+} data_cnfg_t;
+
+
+/*******************************************************************/
+/* Function Definitions */
+/*******************************************************************/
+
+errlHndl_t DATA_store_cnfgdata (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr);
+
+uint8_t DATA_request_cnfgdata ();
+
+uint32_t DATA_get_present_cnfgdata ();
+
+errlHndl_t DATA_get_thrm_thresholds(cmdh_thrm_thresholds_t **o_thrm_thresh);
+
+errlHndl_t DATA_get_ips_cnfg(cmdh_ips_config_data_t **o_ips_cnfg);
+
+#endif
+
diff --git a/src/occ/cmdh/cmdh_mnfg_intf.c b/src/occ/cmdh/cmdh_mnfg_intf.c
new file mode 100755
index 0000000..d475f4e
--- /dev/null
+++ b/src/occ/cmdh/cmdh_mnfg_intf.c
@@ -0,0 +1,814 @@
+/******************************************************************************
+// @file cmdh_mnfg_intf.c
+// @brief Command Handling for Manufacturing Interface.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_mnfg_intf_c cmdh_mnfg_intf.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @gs004 gjsilva 05/15/2013 Created
+ * @gs005 883829 gjsilva 05/22/2013 Fix compilation issues
+ * @gm002 885429 milesg 05/30/2013 support for list/get sensors
+ * @gs006 884384 gjsilva 05/30/2013 Support for mnfg auto-slewing function
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @th042 thallet 07/22/2013 Fix a bug where sensor name was corrupted
+ * @gm004 892961 milesg 07/25/2013 Support memory auto slewing
+ * @gm012 905097 milesg 10/31/2013 Fix centaur enablement
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @gm017 909636 milesg 12/17/2013 changes from mem throttle review
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "cmdh_mnfg_intf.h"
+#include "cmdh_service_codes.h"
+#include "cmdh_fsp_cmds.h"
+#include "dcom.h"
+#include "amec_oversub.h"
+#include "amec_sys.h"
+#include "sensorQueryList.h"
+#include "amec_smh.h"
+#include "amec_master_smh.h"
+#include "centaur_data.h" //gm004
+#include "centaur_control.h" //gm004
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern task_t G_task_table[TASK_END]; //gm004
+extern centaur_throttle_t G_centaurThrottleLimits[MAX_NUM_CENTAURS][NUM_MBAS_PER_CENTAUR];
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Declarations
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: cmdh_mnfg_run_stop_slew
+//
+// Description: This function handles the manufacturing command to start
+// or stop frequency autoslewing.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t cmdh_mnfg_run_stop_slew(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_fmin = 0;
+ uint16_t l_fmax = 0;
+ uint16_t l_step_size = 0;
+ uint16_t l_step_delay = 0;
+ uint32_t l_temp = 0;
+ mnfg_run_stop_slew_cmd_t *l_cmd_ptr = (mnfg_run_stop_slew_cmd_t*) i_cmd_ptr;
+ mnfg_run_stop_slew_rsp_t *l_rsp_ptr = (mnfg_run_stop_slew_rsp_t*) o_rsp_ptr;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // This command is only supported on Master OCC
+ if (G_occ_role == OCC_SLAVE)
+ {
+ TRAC_ERR("cmdh_mnfg_run_stop_slew: Mnfg command not supported on Slave OCCs!");
+ break;
+ }
+
+ // Do some basic input verification
+ if ((l_cmd_ptr->action > MNFG_INTF_SLEW_STOP) ||
+ (l_cmd_ptr->step_mode > MNFG_INTF_FULL_SLEW))
+ {
+ // Invalid values were passed by the user!
+ TRAC_ERR("cmdh_mnfg_run_stop_slew: Invalid values were detected! action[0x%02x] step_mode[0x%02x]",
+ l_cmd_ptr->action,
+ l_cmd_ptr->step_mode);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // Are we stopping the auto-slew function?
+ if (l_cmd_ptr->action == MNFG_INTF_SLEW_STOP)
+ {
+ // Collect the slew count
+ l_rsp_ptr->slew_count = AMEC_MST_CUR_SLEW_COUNT();
+
+ // Collect the frequency range used for the auto-slew
+ l_rsp_ptr->fstart = AMEC_MST_CUR_MNFG_FMIN();
+ l_rsp_ptr->fstop = AMEC_MST_CUR_MNFG_FMAX();
+
+ TRAC_INFO("cmdh_mnfg_run_stop_slew: Auto-slewing has been stopped. Count[%u] fstart[%u] fstop[%u]",
+ AMEC_MST_CUR_SLEW_COUNT(),
+ AMEC_MST_CUR_MNFG_FMIN(),
+ AMEC_MST_CUR_MNFG_FMAX());
+
+ // Send a signal to RTL to stop auto-slewing
+ AMEC_MST_STOP_AUTO_SLEW();
+
+ // We are done
+ break;
+ }
+
+ // If we made it here, that means we are starting up a slew run
+ // First, determine the Fmax and Fmin for the slew run
+ if (l_cmd_ptr->bottom_mode == OCC_MODE_PWRSAVE)
+ {
+ // If bottom mode is Static Power Save, use the min frequency
+ // available
+ l_fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+ }
+ else
+ {
+ l_fmin = G_sysConfigData.sys_mode_freq.table[l_cmd_ptr->bottom_mode];
+ }
+ l_fmax = G_sysConfigData.sys_mode_freq.table[l_cmd_ptr->high_mode];
+
+ // Add the percentages to compute the min/max frequencies
+ l_fmin = l_fmin + (l_fmin * l_cmd_ptr->bottom_percent)/100;
+ l_fmax = l_fmax + (l_fmax * l_cmd_ptr->high_percent)/100;
+
+ TRAC_INFO("cmdh_mnfg_run_stop_slew: We are about to start auto-slewing function");
+ TRAC_INFO("cmdh_mnfg_run_stop_slew: bottom_mode[0x%.2X] freq[%u] high_mode[0x%.2X] freq[%u]",
+ l_cmd_ptr->bottom_mode,
+ l_fmin,
+ l_cmd_ptr->high_mode,
+ l_fmax);
+
+ // Determine the frequency step size and the step delay
+ if (l_cmd_ptr->step_mode == MNFG_INTF_FULL_SLEW)
+ {
+ l_step_size = l_fmax - l_fmin;
+
+ // Disable step delays if full slew mode has been selected
+ l_step_delay = 0;
+
+ TRAC_INFO("cmdh_mnfg_run_stop_slew: Enabling full-slew mode with step_size[%u] step_delay[%u]",
+ l_step_size,
+ l_step_delay);
+ }
+ else
+ {
+ l_step_size = 20; //TODO: Need to find out the step size from Pstate table
+
+ // Translate the step delay to internal OCC ticks
+ l_temp = (l_cmd_ptr->step_delay * 1000) / AMEC_US_PER_TICK;
+ l_step_delay = (uint16_t) l_temp;
+
+ TRAC_INFO("cmdh_mnfg_run_stop_slew: Enabling single-step mode with step_size[%u] step_delay[%u]",
+ l_step_size,
+ l_step_delay);
+ }
+
+ // Now, load the values for RTL consumption
+ AMEC_MST_SET_MNFG_FMIN(l_fmin);
+ AMEC_MST_SET_MNFG_FMAX(l_fmax);
+ AMEC_MST_SET_MNFG_FSTEP(l_step_size);
+ AMEC_MST_SET_MNFG_DELAY(l_step_delay);
+
+ // Reset the slew-counter before we start auto-slewing
+ AMEC_MST_CUR_SLEW_COUNT() = 0;
+
+ // Wait a little bit for RTL to process above parameters
+ ssx_sleep(SSX_MILLISECONDS(5));
+
+ // Send a signal to RTL to start auto-slewing
+ AMEC_MST_START_AUTO_SLEW();
+
+ // We are auto-slewing now, populate the response packet
+ l_rsp_ptr->slew_count = 0;
+ l_rsp_ptr->fstart = l_fmin;
+ l_rsp_ptr->fstop = l_fmax;
+
+ }while(0);
+
+ // Populate the response data packet
+ l_rsp_ptr->rc = l_rc;
+ l_rsp_ptr->data_length[0] = 0;
+ l_rsp_ptr->data_length[1] = MNFG_INTF_RUN_STOP_SLEW_RSP_SIZE;
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_mnfg_mem_slew
+//
+// Description: This function handles the manufacturing command to start
+// or stop memory autoslewing.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t cmdh_mnfg_mem_slew(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ mnfg_mem_slew_cmd_t *l_cmd_ptr = (mnfg_mem_slew_cmd_t*) i_cmd_ptr;
+ mnfg_mem_slew_rsp_t *l_rsp_ptr = (mnfg_mem_slew_rsp_t*) o_rsp_ptr;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+
+ // Do some basic input verification
+ if (l_cmd_ptr->action > MNFG_INTF_SLEW_STOP)
+ {
+ // Invalid values were passed by the user!
+ TRAC_ERR("cmdh_mnfg_mem_slew: Invalid value was detected! action[0x%02x]",
+ l_cmd_ptr->action);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // Are we stopping the auto-slew function?
+ if (l_cmd_ptr->action == MNFG_INTF_SLEW_STOP)
+ {
+ // Send a signal to RTL to stop auto-slewing
+ g_amec->mnfg_parms.mem_autoslew = FALSE;
+
+ // Collect the slew count
+ if(g_amec->mnfg_parms.mem_slew_counter > 0x0000FFFF)
+ {
+ l_rsp_ptr->slew_count = 0xFFFF;
+ }
+ else
+ {
+ l_rsp_ptr->slew_count = g_amec->mnfg_parms.mem_slew_counter;
+ }
+
+ // zero out the slew count;
+ g_amec->mnfg_parms.mem_slew_counter = 0;
+
+ TRAC_INFO("cmdh_mnfg_mem_slew: Auto-slewing has been stopped. Count[%u]",
+ l_rsp_ptr->slew_count);
+
+ // We are done
+ break;
+ }
+
+ // If we made it here, that means we are starting up a slew run
+ TRAC_INFO("cmdh_mnfg_mem_slew: We are about to start auto-slewing function");
+
+ // force activation of memory monitoring and control
+ if(!rtl_task_is_runnable(TASK_ID_CENTAUR_CONTROL))
+ {
+ uint32_t l_cent, l_mba;
+
+ //only run initialization on an active OCC
+ if(!IS_OCC_STATE_ACTIVE())
+ {
+ TRAC_ERR("cmdh_mnfg_mem_slew: OCC must be active to start mem slewing");
+ l_rc = ERRL_RC_INVALID_STATE;
+ break;
+ }
+
+ //Force all MBA's to be present
+ G_configured_mbas = -1;
+
+ TRAC_INFO("cmdh_mnfg_mem_slew: calling centaur_init()");
+ centaur_init(); //no rc, handles errors internally
+
+ //check if centaur_init resulted in a reset
+ //since we don't have a return code from centaur_init.
+ if(isSafeStateRequested())
+ {
+ TRAC_ERR("cmdh_mnfg_mem_slew: OCC is being reset");
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+ if(!CENTAUR_PRESENT(l_cent))
+ {
+ continue;
+ }
+
+ for(l_mba = 0; l_mba < NUM_MBAS_PER_CENTAUR; l_mba++)
+ {
+ mem_throt_config_data_t * l_throt_ptr =
+ &G_sysConfigData.mem_throt_limits[l_cent][l_mba];
+
+ //Uses values seen on tuleta as defaults -- gm017
+ l_throt_ptr->min_ot_n_per_mba = 13;
+ l_throt_ptr->nom_n_per_mba = 72;
+ l_throt_ptr->nom_n_per_chip = 72;
+ l_throt_ptr->turbo_n_per_mba = 72;
+ l_throt_ptr->turbo_n_per_chip = 72;
+ l_throt_ptr->ovs_n_per_mba = 72;
+ l_throt_ptr->ovs_n_per_chip = 72;
+ }
+
+ }
+
+
+ //initialization was successful.
+ //Set task flags to allow centaur control task to run and
+ //also to prevent us from doing initialization again.
+ G_task_table[TASK_ID_CENTAUR_DATA].flags = CENTAUR_DATA_RTL_FLAGS;
+ G_task_table[TASK_ID_CENTAUR_CONTROL].flags = CENTAUR_CONTROL_RTL_FLAGS;
+ }
+
+ // zero out the slew count
+ g_amec->mnfg_parms.mem_slew_counter = 0;
+
+ // Send a signal to RTL to start memory auto-slewing
+ g_amec->mnfg_parms.mem_autoslew = TRUE;
+
+ // We are auto-slewing now, populate the response packet
+ l_rsp_ptr->slew_count = 0;
+
+ TRAC_INFO("cmdh_mnfg_mem_slew: memory slewing started.");
+
+ }while(0);
+
+ // Populate the response data packet
+ l_rsp_ptr->rc = l_rc;
+ l_rsp_ptr->data_length[0] = 0;
+ l_rsp_ptr->data_length[1] = MNFG_INTF_MEM_SLEW_RSP_SIZE;
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_mnfg_emulate_oversub
+//
+// Description: This function handles the manufacturing command to emulate
+// oversubscription.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t cmdh_mnfg_emulate_oversub(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = 0;
+ mnfg_emul_oversub_cmd_t *l_cmd_ptr = (mnfg_emul_oversub_cmd_t*) i_cmd_ptr;
+ mnfg_emul_oversub_rsp_t *l_rsp_ptr = (mnfg_emul_oversub_rsp_t*) o_rsp_ptr;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // This command is only supported on Master OCC
+ if (G_occ_role == OCC_SLAVE)
+ {
+ TRAC_ERR("cmdh_mnfg_emulate_oversub: Mnfg command not supported on Slave OCCs!");
+ break;
+ }
+
+ switch (l_cmd_ptr->action)
+ {
+ case 0x00:
+ TRAC_INFO("cmdh_mnfg_emulate_oversub: Disable oversubscription emulation");
+ AMEC_INTF_GET_OVERSUBSCRIPTION_EMULATION() = 0;
+ l_rsp_ptr->state = l_cmd_ptr->action;
+ break;
+
+ case 0x01:
+ TRAC_INFO("cmdh_mnfg_emulate_oversub: Enable oversubscription emulation");
+ AMEC_INTF_GET_OVERSUBSCRIPTION_EMULATION() = 1;
+ l_rsp_ptr->state = l_cmd_ptr->action;
+ break;
+
+ case 0xFF:
+ TRAC_INFO("cmdh_mnfg_emulate_oversub: Query oversubscription emulation");
+ l_rsp_ptr->state = AMEC_INTF_GET_OVERSUBSCRIPTION_EMULATION();
+ break;
+
+ default:
+ TRAC_INFO("cmdh_mnfg_emulate_oversub: Invalid oversubscription emulation action");
+ l_rsp_ptr->state = AMEC_INTF_GET_OVERSUBSCRIPTION_EMULATION();
+ break;
+ }
+
+ }while(0);
+
+ // Populate the response data packet
+ l_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ l_rsp_ptr->data_length[0] = 0;
+ l_rsp_ptr->data_length[1] = 1;
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_mnfg_list_sensors
+//
+// Description: Returns a list of selected sensors
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t cmdh_mnfg_list_sensors(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_type = 0;
+ uint16_t l_location = 0;
+ uint16_t l_start_gsid;
+ uint16_t i = 0;
+ uint16_t l_resp_data_length = 0;
+ uint16_t l_datalength;
+ uint16_t l_num_of_sensors = MFG_MAX_NUM_SENSORS + 1;
+ cmdh_mfg_list_sensors_query_t *l_cmd_ptr =
+ (cmdh_mfg_list_sensors_query_t*) i_cmd_ptr;
+ cmdh_mfg_list_sensors_resp_t *l_resp_ptr =
+ (cmdh_mfg_list_sensors_resp_t*) o_rsp_ptr;
+ sensorQueryList_t l_sensor_list[MFG_MAX_NUM_SENSORS + 1];
+ errlHndl_t l_err = NULL;
+ OCC_APLT_STATUS_CODES l_status = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // Do sanity check on the function inputs
+ if ((NULL == i_cmd_ptr) || (NULL == o_rsp_ptr))
+ {
+ TRAC_ERR("cmdh_mnfg_list_sensors: invalid pointers. cmd[0x%08x] rsp[0x%08x]",
+ i_cmd_ptr, o_rsp_ptr);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ // Check packet data length
+ l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
+ if(l_datalength < (sizeof(cmdh_mfg_list_sensors_query_t) -
+ sizeof(cmdh_fsp_cmd_header_t)))
+ {
+ TRAC_ERR("cmdh_mnfg_list_sensors: incorrect data length. exp[%d] act[%d]",
+ (sizeof(cmdh_mfg_list_sensors_query_t) -
+ sizeof(cmdh_fsp_cmd_header_t)),
+ l_datalength);
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ // Check version
+ if(l_cmd_ptr->version != MFG_LIST_SENSOR_VERSION)
+ {
+ TRAC_ERR("cmdh_mnfg_list_sensors: incorrect version. exp[%d] act[%d]",
+ MFG_LIST_SENSOR_VERSION,
+ l_cmd_ptr->version);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // Capture user inputs
+ l_type = l_cmd_ptr->type;
+ l_location = l_cmd_ptr->location;
+ l_start_gsid = l_cmd_ptr->start_gsid;
+
+ TRAC_INFO("cmdh_mnfg_list_sensors: Type[0x%04x] Location[0x%04x]",
+ l_type,
+ l_location);
+
+ // Initialize the Applet arguments
+ querySensorListAppletArg_t l_applet_arg =
+ {
+ l_start_gsid, // i_startGsid - passed by the caller
+ l_cmd_ptr->present, // i_present - passed by the caller
+ l_type, // i_type - passed by the caller
+ l_location, // i_loc - passed by the caller
+ &l_num_of_sensors, // io_numOfSensors
+ l_sensor_list, // o_sensors
+ NULL // o_sensorInfoPtr - not needed
+ };
+
+ // Call the sensor query list applet
+ runApplet(OCC_APLT_SNSR_QUERY,
+ &l_applet_arg,
+ TRUE,
+ NULL,
+ &l_err,
+ &l_status);
+
+ if (NULL != l_err)
+ {
+ // Query failure
+ TRAC_ERR("cmdh_mnfg_list_sensors: Failed to run OCC_APLT_SNSR_QUERY applet. Error status is: 0x%x",
+ l_status);
+
+ // Commit error log
+ commitErrl(&l_err);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ else
+ {
+ TRAC_INFO("cmdh_mnfg_list_sensors: Numbers of sensors found[%u]",
+ l_num_of_sensors);
+
+ if (l_num_of_sensors > MFG_MAX_NUM_SENSORS)
+ {
+ // Got too many sensors back, need to truncate the list
+ TRAC_INFO("cmdh_mnfg_list_sensors: Got too many sensors back[%u]. Truncating number of sensors to %u",
+ l_num_of_sensors,
+ MFG_MAX_NUM_SENSORS);
+
+ l_num_of_sensors = MFG_MAX_NUM_SENSORS;
+ l_resp_ptr->truncated = 1;
+ }
+ else
+ {
+ l_resp_ptr->truncated = 0;
+ }
+
+ // Clear out the sensor fields - @th042
+ memset((void*) &(l_resp_ptr->sensor[0]), 0, (sizeof(cmdh_dbug_sensor_list_t)*l_num_of_sensors) );
+
+ // Populate the response data packet
+ l_resp_ptr->num_sensors = l_num_of_sensors;
+ for (i=0; i<l_num_of_sensors; i++)
+ {
+ l_resp_ptr->sensor[i].gsid = l_sensor_list[i].gsid;
+ l_resp_ptr->sensor[i].sample = l_sensor_list[i].sample;
+ strcpy(l_resp_ptr->sensor[i].name, l_sensor_list[i].name);
+ }
+ }
+
+ }while(0);
+
+ // Populate the response data header
+ l_resp_data_length = 2 + l_num_of_sensors * sizeof(cmdh_mfg_sensor_rec_t);
+ o_rsp_ptr->rc = l_rc;
+ o_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0];
+ o_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1];
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_mnfg_get_sensor
+//
+// Description: Returns a list of selected sensors
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t cmdh_mnfg_get_sensor(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_gsid;
+ uint16_t l_resp_data_length = 0;
+ uint16_t l_datalength;
+ uint16_t l_num_of_sensors = 1;
+ cmdh_mfg_get_sensor_query_t *l_cmd_ptr =
+ (cmdh_mfg_get_sensor_query_t*) i_cmd_ptr;
+ cmdh_mfg_get_sensor_resp_t *l_resp_ptr =
+ (cmdh_mfg_get_sensor_resp_t*) o_rsp_ptr;
+ sensor_info_t l_sensor_info;
+ errlHndl_t l_err = NULL;
+ OCC_APLT_STATUS_CODES l_status = 0;
+ sensor_t* l_sensor_ptr;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // Do sanity check on the function inputs
+ if ((NULL == i_cmd_ptr) || (NULL == o_rsp_ptr))
+ {
+ TRAC_ERR("cmdh_mnfg_get_sensor: invalid pointers. cmd[0x%08x] rsp[0x%08x]",
+ i_cmd_ptr, o_rsp_ptr);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ // Check packet data length
+ l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
+ if(l_datalength < (sizeof(cmdh_mfg_get_sensor_query_t) -
+ sizeof(cmdh_fsp_cmd_header_t)))
+ {
+ TRAC_ERR("cmdh_mnfg_get_sensor: incorrect data length. exp[%d] act[%d]",
+ (sizeof(cmdh_mfg_get_sensor_query_t) -
+ sizeof(cmdh_fsp_cmd_header_t)),
+ l_datalength);
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ // Check version
+ if(l_cmd_ptr->version != MFG_LIST_SENSOR_VERSION)
+ {
+ TRAC_ERR("cmdh_mnfg_get_sensor: incorrect version. exp[%d] act[%d]",
+ MFG_GET_SENSOR_VERSION,
+ l_cmd_ptr->version);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // Capture user inputs
+ l_gsid = l_cmd_ptr->gsid;
+
+ TRAC_INFO("cmdh_mnfg_get_sensor: gsid[0x%04x]", l_gsid);
+
+ // Initialize the Applet arguments
+ querySensorListAppletArg_t l_applet_arg =
+ {
+ l_gsid, // i_startGsid - passed by the caller
+ 0, // i_present - passed by the caller
+ AMEC_SENSOR_TYPE_ALL, // i_type
+ AMEC_SENSOR_LOC_ALL, // i_loc
+ &l_num_of_sensors, // io_numOfSensors
+ NULL, // o_sensors - not needed
+ &l_sensor_info // o_sensorInfoPtr
+ };
+
+ // Call the sensor query list applet
+ runApplet(OCC_APLT_SNSR_QUERY,
+ &l_applet_arg,
+ TRUE,
+ NULL,
+ &l_err,
+ &l_status);
+
+ if (NULL != l_err)
+ {
+ // Query failure
+ TRAC_ERR("cmdh_mnfg_get_sensor: Failed to run OCC_APLT_SNSR_QUERY applet. Error status is: 0x%x",
+ l_status);
+
+ // Commit error log
+ commitErrl(&l_err);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ else
+ {
+ l_resp_ptr->gsid = l_gsid;
+
+ // some of the response comes from the sensor
+ l_sensor_ptr = getSensorByGsid(l_gsid);
+ if (l_sensor_ptr == NULL)
+ {
+ TRAC_INFO("cmdh_mnfg_get_sensor: Didn't find sensor with gsid[0x%.4X]. Min/Max values won't be accurate.",
+ l_gsid);
+ l_resp_ptr->sample = 0;
+ l_resp_ptr->min = 0xFFFF;
+ l_resp_ptr->max = 0;
+ l_resp_ptr->accumulator = 0;
+ l_resp_ptr->status = 0;
+ }
+ else
+ {
+ l_resp_ptr->sample = l_sensor_ptr->sample;
+ l_resp_ptr->min = l_sensor_ptr->sample_min;
+ l_resp_ptr->max = l_sensor_ptr->sample_max;
+ l_resp_ptr->accumulator = l_sensor_ptr->accumulator;
+ l_resp_ptr->status = *(uint8_t*)(&l_sensor_ptr->status);
+ }
+
+ //the rest of the response comes from the sensor info
+ memcpy(l_resp_ptr->name, l_sensor_info.name, sizeof(l_resp_ptr->name));
+ memcpy(l_resp_ptr->units, l_sensor_info.sensor.units, sizeof(l_resp_ptr->units));
+ l_resp_ptr->freq = l_sensor_info.sensor.freq;
+ l_resp_ptr->scalefactor = l_sensor_info.sensor.scalefactor;
+ l_resp_ptr->location = l_sensor_info.sensor.location;
+ l_resp_ptr->type = l_sensor_info.sensor.type;
+ }
+
+ }while(0);
+
+ // Populate the response data header
+ l_resp_data_length = sizeof(cmdh_mfg_get_sensor_resp_t) -
+ sizeof(cmdh_fsp_rsp_header_t);
+ o_rsp_ptr->rc = l_rc;
+ o_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0];
+ o_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1];
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_mnfg_test_parse
+//
+// Description: This function parses the manufacturing commands sent via TMGT.
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = 0;
+ uint8_t l_sub_cmd = 0;
+ errlHndl_t l_errl = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Sub-command is always first byte of data
+ l_sub_cmd = i_cmd_ptr->data[0];
+
+ TRAC_INFO("cmdh_mnfg_test_parse: Mnfg sub-command [0x%02x]", l_sub_cmd);
+
+ switch (l_sub_cmd)
+ {
+ case MNFG_RUN_STOP_SLEW:
+ l_rc = cmdh_mnfg_run_stop_slew(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case MNFG_OVERSUB_EMULATION:
+ l_rc = cmdh_mnfg_emulate_oversub(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case MNFG_LIST_SENSORS:
+ l_rc = cmdh_mnfg_list_sensors(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case MNFG_GET_SENSOR:
+ l_rc = cmdh_mnfg_get_sensor(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case MNFG_MEMORY_SLEW:
+ l_rc = cmdh_mnfg_mem_slew(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case MNFG_RETRIEVE_EAR:
+ case MNFG_SET_FMINMAX:
+ case MNFG_FAILSAFE_EMULATION:
+ case MNFG_CPM_STRESS_CALI:
+ case MNFG_UV_CONTROL:
+ case MNFG_FCHECK_CONTROL:
+ default:
+ // Should never get here...
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // All errors in MNFG logged internally
+ if (l_rc)
+ {
+ TRAC_ERR("Mfg command 0x%02x failed with rc = %d", l_sub_cmd, l_rc);
+ // Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errl);
+ }
+
+ return;
+}
+
diff --git a/src/occ/cmdh/cmdh_mnfg_intf.h b/src/occ/cmdh/cmdh_mnfg_intf.h
new file mode 100755
index 0000000..b5ac63c
--- /dev/null
+++ b/src/occ/cmdh/cmdh_mnfg_intf.h
@@ -0,0 +1,236 @@
+/**
+ * @file cmdh_mnfg_intf.h
+ * @brief Header file for Manufacturing interface.
+ *
+ *
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_mnfg_intf_h cmdh_mnfg_intf.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- --------- ----------------------------------
+ * @gs004 gjsilva 05/15/2013 Created
+ * @gm002 885429 milesg 05/30/2013 support for list/get sensors
+ * @gs006 884384 gjsilva 05/30/2013 Support for mnfg auto-slewing function
+ * @gm004 892961 milesg 07/25/2013 Support memory auto slewing
+ *
+ * @endverbatim
+ */
+#ifndef CMDH_MNFG_INTF_H
+#define CMDH_MNFG_INTF_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "cmdh_fsp.h"
+#include "sensor.h"
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+typedef enum {
+ MNFG_RUN_STOP_SLEW = 0x02,
+ MNFG_LIST_SENSORS = 0x05,
+ MNFG_GET_SENSOR = 0x06,
+ MNFG_OVERSUB_EMULATION = 0x07,
+ MNFG_RETRIEVE_EAR = 0x08,
+ MNFG_MEMORY_SLEW = 0x09,
+ MNFG_SET_FMINMAX = 0x0A,
+ MNFG_FAILSAFE_EMULATION = 0x0C,
+ MNFG_CPM_STRESS_CALI = 0x0D,
+ MNFG_UV_CONTROL = 0x0E,
+ MNFG_FCHECK_CONTROL = 0x0F,
+} MNFG_CMD;
+
+#define MNFG_INTF_SLEW_START 0x00
+#define MNFG_INTF_SLEW_STOP 0x01
+#define MNFG_INTF_SINGLE_STEP 0x00
+#define MNFG_INTF_FULL_SLEW 0x01
+
+#define MNFG_INTF_RUN_STOP_SLEW_RSP_SIZE 6
+
+/**
+ * @struct mnfg_run_stop_slew_cmd_t
+ * @brief Used by OCC to get mnfg run/stop slew
+ * command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t version;
+ uint8_t action;
+ uint8_t bottom_mode;
+ int8_t bottom_percent;
+ uint8_t high_mode;
+ int8_t high_percent;
+ uint8_t step_mode;
+ uint8_t step_delay;
+}mnfg_run_stop_slew_cmd_t;
+
+/**
+ * @struct mnfg_run_stop_slew_rsp_t
+ * @brief Used by OCC firmware to respond to mnfg run/stop
+ * slew command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint16_t slew_count;
+ uint16_t fstart;
+ uint16_t fstop;
+ uint16_t checksum;
+}mnfg_run_stop_slew_rsp_t;
+
+/**
+ * @struct mnfg_mem_slew_cmd_t
+ * @brief Used by OCC to get mnfg memory slew
+ * command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t version;
+ uint8_t action;
+}mnfg_mem_slew_cmd_t;
+
+#define MNFG_INTF_MEM_SLEW_RSP_SIZE 2
+
+/**
+ * @struct mnfg_mem_slew_rsp_t
+ * @brief Used by OCC firmware to respond to mnfg memory
+ * slew command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint16_t slew_count;
+ uint16_t checksum;
+}mnfg_mem_slew_rsp_t;
+
+/**
+ * @struct mnfg_emul_oversub_cmd_t
+ * @brief Used by OCC to get mnfg emulate oversubscription
+ * command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t version;
+ uint8_t action;
+ uint8_t reserved;
+}mnfg_emul_oversub_cmd_t;
+
+/**
+ * @struct mnfg_emul_oversub_rsp_t
+ * @brief Used by OCC firmware to respond to mnfg emulate
+ * oversubscription command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint8_t state;
+ uint16_t checksum;
+}mnfg_emul_oversub_rsp_t;
+
+#define MFG_LIST_SENSOR_VERSION 0
+#define MFG_MAX_NUM_SENSORS 50 //20 bytes per sensor, 4k response packet (4k stack is limiting factor here).
+/**
+ * @struct cmdh_mfg_list_sensor_query_t
+ * @brief Used by mfg to get sensor data
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t version;
+ uint16_t start_gsid;
+ uint8_t present;
+ uint16_t location;
+ uint16_t type;
+}cmdh_mfg_list_sensors_query_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint16_t gsid;
+ char name[MAX_SENSOR_NAME_SZ]; //16 bytes
+ uint16_t sample;
+}cmdh_mfg_sensor_rec_t;
+
+/**
+ * @struct cmdh_mfg_list_sensors_resp_t
+ * @brief Used by OCC firmware to respond to the
+ * "MFG_LIST_SENSORS" mfg command. Follows
+ * the TMGT/OCC specification.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint8_t truncated;
+ uint8_t num_sensors;
+ cmdh_mfg_sensor_rec_t sensor[MFG_MAX_NUM_SENSORS];
+ uint16_t checksum;
+}cmdh_mfg_list_sensors_resp_t;
+
+#define MFG_GET_SENSOR_VERSION 0
+/**
+ * @struct cmdh_mfg_get_sensor_query_t
+ * @brief Used by mfg to get sensor data
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t version;
+ uint16_t gsid;
+}cmdh_mfg_get_sensor_query_t;
+
+/**
+ * @struct cmdh_mfg_get_sensor_resp_t
+ * @brief Used by OCC firmware to respond to the
+ * "MFG_GET_SENSOR" mfg command. Follows
+ * the TMGT/OCC specification.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint16_t gsid;
+ uint16_t sample;
+ uint8_t status;
+ uint32_t accumulator;
+ uint16_t min;
+ uint16_t max;
+ char name[MAX_SENSOR_NAME_SZ];
+ char units[MAX_SENSOR_UNIT_SZ];
+ uint32_t freq;
+ uint32_t scalefactor;
+ uint16_t location;
+ uint16_t type;
+ uint16_t checksum;
+}cmdh_mfg_get_sensor_resp_t;
+
+/*******************************************************************/
+/* Function Definitions */
+/*******************************************************************/
+
+void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+uint8_t cmdh_mnfg_emulate_oversub(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+uint8_t cmdh_mnfg_list_sensors(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+uint8_t cmdh_mnfg_get_sensor(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+uint8_t cmdh_mnfg_run_stop_slew(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+#endif
diff --git a/src/occ/cmdh/cmdh_service_codes.h b/src/occ/cmdh/cmdh_service_codes.h
new file mode 100755
index 0000000..785fffb
--- /dev/null
+++ b/src/occ/cmdh/cmdh_service_codes.h
@@ -0,0 +1,55 @@
+
+/**
+ * @file cmdh_service_codes.h
+ * @brief Error codes for cmdh component.
+ *
+ *
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_service_codes_h cmdh_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- --------- ----------------------------------
+ * @th022 thallet 10/03/2012 Added Generic Module ID
+ * @at013 878755 alvinwan 04/17/2013 OCC power capping implementation
+ * @th033 878894 thallet 04/17/2013 Mnfg AVP Support
+ * @th032 thallet 04/26/2013 Tuleta Mnfg Stage 2.5 Support
+ * @at014 882077 alvinwan 05/09/2013 Support APSS and System Config data from TMGT
+ * @jh004 889884 joshych 07/24/2013 Support CPM param and updated frequency packet
+ * @gs010 899888 gjsilva 09/24/2013 Process data format 0x13 from TMGT
+ * @rt001 902613 tapiar 10/14/2013 Process data format 0x11 from TMGT
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @jh009 908383 joshych 12/04/2013 Generate error logs when required for Reset Prep command
+ * @gm020 912611 milesg 01/21/2014 Add special wakeup for scom'ing core chiplets
+ *
+ * @endverbatim
+ */
+#ifndef CMDH_SERVICE_CODES_H
+#define CMDH_SERVICE_CODES_H
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum occCmdhModuleId
+{
+ DATA_STORE_GENERIC_DATA = CMDH_COMP_ID | 0x00,
+ DATA_STORE_FREQ_DATA = CMDH_COMP_ID | 0x01,
+ DATA_STORE_PCAP_DATA = CMDH_COMP_ID | 0x02, // @at013a
+ CMDH_FSI2HOST_MBOX_UNAVAIL = CMDH_COMP_ID | 0x03, // @th033
+ CMDH_GENERIC_CMD_FAILURE = CMDH_COMP_ID | 0x04, // @th032
+ DATA_STORE_SYS_DATA = CMDH_COMP_ID | 0x05, // @at014a
+ DATA_STORE_APSS_DATA = CMDH_COMP_ID | 0x06, // @at014a
+ CMDH_FSP_FSI2HOST_MBOX_WAIT4FREE = CMDH_COMP_ID | 0x07, // @gm020
+ DATA_GET_THRM_THRESHOLDS = CMDH_COMP_ID | 0x08, // @gs010a
+ DATA_STORE_IPS_DATA = CMDH_COMP_ID | 0x09, // @rt001a
+ DATA_GET_IPS_DATA = CMDH_COMP_ID | 0x0A, // @gs015a
+ DATA_GET_RESET_PREP_ERRL = CMDH_COMP_ID | 0x0B, // @jh009a
+};
+#endif
diff --git a/src/occ/cmdh/cmdh_snapshot.c b/src/occ/cmdh/cmdh_snapshot.c
new file mode 100755
index 0000000..2f3b7dd
--- /dev/null
+++ b/src/occ/cmdh/cmdh_snapshot.c
@@ -0,0 +1,542 @@
+/******************************************************************************
+// @file cmdh_snapshot.c
+// @brief Command Handling for snapshot buffer Interface
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_snapshot_c cmdh_snapshot.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @fk004 907588 fmkassem 11/25/2013 Created
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "cmdh_snapshot.h"
+#include "cmdh_service_codes.h"
+#include "cmdh_fsp_cmds.h"
+#include "dcom.h"
+#include "threadSch.h"
+//*************************************************************************
+// Externs
+//*************************************************************************
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Array of snapshot buffers to return to TMGT
+cmdh_snapshot_buffer_t g_cmdh_snapshot_array[CMDH_SNAPSHOT_MAX];
+
+// Current snapshot id.
+uint8_t g_cmdh_snapshot_cur_id = 0;
+
+// Current index into array for newest entry
+uint8_t g_cmdh_snapshot_cur_index = CMDH_SNAPSHOT_DEFAULT_CUR_INDEX;
+
+// This global is set to TRUE by default to get a clean start, and is also
+// set to TRUE in case of a resync request.
+bool g_cmdh_snapshot_reset = TRUE;
+
+SsxTimer G_snapshotTimer;
+
+// Max, min power, and accumulated frequency average over 30seconds
+pwr250us_over30sec_t g_pwr250us_over30sec;
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: cmdh_snapshot_find_oldest_newest
+//
+// Description: Returns the index of the oldest and newest snapshot in the
+// g_cmdh_snapshot_array.
+//
+//
+//
+//
+// Flow: 11/25/2013 FN=
+//
+// End Function Specification
+
+VOID cmdh_snapshot_find_oldest_newest(uint8_t *o_oldest,
+ uint8_t *o_newest)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_index = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // We wont be called if no snapshots are available so we know at least
+ // one is available
+
+ // If our current index is 0, it's id is 0, and the last entry has
+ // an id of 0 then we know we haven't wrapped yet since 2 entries
+ // can not have the same current_id and 0 was what's written in
+ // as an initializer
+ if((g_cmdh_snapshot_cur_index == 0) &&
+ (g_cmdh_snapshot_array[0].current_id == 0) &&
+ (g_cmdh_snapshot_array[CMDH_SNAPSHOT_MAX_INDEX].current_id == 0))
+ {
+ TRAC_INFO("cmdh_snapshot_find_oldest_newest: Entry 0 is the oldest and newest");
+ *o_oldest = 0;
+ *o_newest = 0;
+ break;
+ }
+
+ // Newest will be g_cmdh_snapshot_cur_index
+ *o_newest = g_cmdh_snapshot_cur_index;
+
+ // n = newest, o=oldest, x=used, _=empty
+ //________________________________________
+ //|x|x|x|x|x|x|x|x|x|x|x|n|o|x|x|x|x|x|x|x|
+ // Start by assuming that the oldest snapshot is right after the newest.
+ l_index = g_cmdh_snapshot_cur_index+1;
+
+ //________________________________________
+ //|o|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|n|
+ //Check on whether the newest was at the end of the array. That would
+ //mean that the oldest entry is at index 0.
+ if(l_index > CMDH_SNAPSHOT_MAX_INDEX)
+ {
+ l_index = 0;
+ }
+ //________________________________________
+ //|o|x|x|x|x|x|x|x|x|x|x|n|_|_|_|_|_|_|_|_|
+ //Check on whether the last entry in the array is empty and so is the one
+ //right after the newest entry. If so, that means oldest is at index 0 since
+ //we haven't wrapped yet.
+ else if((g_cmdh_snapshot_array[l_index].current_id == 0) &&
+ (g_cmdh_snapshot_array[CMDH_SNAPSHOT_MAX_INDEX].current_id == 0))
+ {
+ l_index = 0;
+ }
+ // else oldest is just equal to l_index
+ *o_oldest = l_index;
+
+ }while(FALSE);
+
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_snapshot_buffer_nonite
+//
+// Description: Returns the requested snapshot buffer to tmgt.
+//
+//
+//
+//
+// Flow: 11/25/2013 FN=
+//
+// End Function Specification
+ERRL_RC cmdh_snapshot_buffer_nonite(const cmdh_fsp_cmd_t *i_cmd_ptr,
+ cmdh_fsp_rsp_t *o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ cmdh_get_snapshot_query_t *l_cmd_ptr = (cmdh_get_snapshot_query_t *) i_cmd_ptr;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+ cmdh_get_snapshot_resp_v0_t *l_rsp_ptr = (cmdh_get_snapshot_resp_v0_t*) o_rsp_ptr;
+ uint8_t l_newest = 0;
+ uint8_t l_oldest = 0;
+ uint8_t l_req_idx = 0;
+ uint8_t i = 0;
+
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+
+ //Check case where there are no snapshot buffers available.
+ if (g_cmdh_snapshot_cur_index == CMDH_SNAPSHOT_DEFAULT_CUR_INDEX)
+ {
+ TRAC_INFO("cmdh_snapshot_buffer_nonite: No snapshot buffer available.");
+ break;
+ }
+
+ //Determine newest and oldest buffer.
+ cmdh_snapshot_find_oldest_newest(&l_oldest, &l_newest);
+
+ l_rsp_ptr->oldest_id = g_cmdh_snapshot_array[l_oldest].current_id;
+ l_rsp_ptr->newest_id = g_cmdh_snapshot_array[l_newest].current_id;
+
+ //Determine which snapshot buffer is requested by TMGT
+ if (l_cmd_ptr->getnewest)
+ {
+ l_req_idx = l_newest;
+ }
+ else
+ {
+ //Find requested snapshot, or if not available grab latest.
+ for (i =0; i< CMDH_SNAPSHOT_MAX; i++)
+ {
+ if (g_cmdh_snapshot_array[i].current_id == l_cmd_ptr->requested_id)
+ {
+ l_req_idx = i;
+ break;
+ }
+ }
+
+ if (i == CMDH_SNAPSHOT_MAX)
+ {
+ TRAC_INFO("cmdh_snapshot_buffer_nonite: Requested buffer:%u not found so sending back %u",
+ l_cmd_ptr->requested_id, l_rsp_ptr->newest_id);
+ l_req_idx = l_newest;
+ }
+ }
+
+ //Copy the requested snapshot buffer into the response buffer.
+ memcpy(&(l_rsp_ptr->snapshot),
+ &(g_cmdh_snapshot_array[l_req_idx]),
+ sizeof(cmdh_snapshot_buffer_t));
+
+ //Calculate returned data size.
+ uint16_t l_size = 2 + sizeof(cmdh_snapshot_buffer_t); //2bytes for newest and oldest + size of snapshots.
+ o_rsp_ptr->data_length[0] = ((uint8_t *)&l_size)[0];
+ o_rsp_ptr->data_length[1] = ((uint8_t *)&l_size)[1];
+
+
+ } while (0);
+
+ return(l_rc);
+}
+
+// Function Specification
+//
+// Name: cmdh_get_snapshot_buffer
+//
+// Description: Returns requested snapshot buffer to tmgt when requested.
+//
+//
+//
+//
+// Flow: 11/21/2013 FN=
+//
+// End Function Specification
+errlHndl_t cmdh_get_snapshot_buffer(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ cmdh_get_snapshot_query_t *l_cmd_ptr = (cmdh_get_snapshot_query_t *) i_cmd_ptr;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_query_sz = 0;
+ errlHndl_t l_err = NULL;
+
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ do
+ {
+
+
+ // command is only supported on Master OCC
+ if (G_occ_role == OCC_SLAVE)
+ {
+ TRAC_ERR("cmdh_get_snapshot_buffer: Get snapshot buffer command not supported on Slave OCCs!");
+ l_rc = ERRL_RC_INVALID_CMD;
+ break;
+ }
+
+ // Function Inputs Sanity Check
+ if( (NULL == i_cmd_ptr) || (NULL == o_rsp_ptr) )
+ {
+ TRAC_ERR("cmdh_get_snapshot_buffer: Received invalid inputs.");
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ l_query_sz = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
+ // Command Length Check. Should have 4 bytes total
+ if(l_query_sz != CMDH_GET_SNAPSHOT_QUERY_DATALEN)
+ {
+ TRAC_ERR("cmdh_get_snapshot_buffer: Received an invalid packet size. Expecting 4 bytes, received:%i",
+ l_query_sz);
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ //Call appropriate function based on version.
+ switch (l_cmd_ptr->version)
+ {
+ case CMDH_GET_SNAPSHOT_NONITE_VERSION:
+ l_rc = cmdh_snapshot_buffer_nonite(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case CMDH_GET_SNAPSHOT_ITE_VERSION:
+ default:
+ TRAC_ERR("cmdh_get_snapshot_buffer: Version %i cmd is not supported.", l_cmd_ptr->version);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ } while(0);
+
+ if (l_rc)
+ {
+ /// Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_err);
+ }
+
+ return l_err;
+}
+
+
+#define CMDH_SNAPSHOT_SYNC_DATA_SIZE 1
+// Function Specification
+//
+// Name: cmdh_snapshot_sync
+//
+// Description: Resets the snapshot buffer array and starts a new snapshot buffer from time 0.
+//
+// Flow: 11/25/2013 FN=
+//
+// End Function Specification
+errlHndl_t cmdh_snapshot_sync(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ cmdh_snapshot_sync_query_t *l_cmd_ptr = (cmdh_snapshot_sync_query_t *) i_cmd_ptr;
+ cmdh_snapshot_sync_resp_t *l_resp_ptr = (cmdh_snapshot_sync_resp_t *) o_rsp_ptr;
+ errlHndl_t l_err = NULL;
+ uint8_t l_query_sz = 0;
+ ERRL_RC l_rc = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+
+
+ do
+ {
+ l_query_sz = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
+ // Verify query data size
+ if(l_query_sz != CMDH_SNAPSHOT_SYNC_DATA_SIZE)
+ {
+ TRAC_ERR("cmdh_snapshot_sync: Received an invalid packet size. Expecting 1 byte, received:%i",
+ l_query_sz);
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ l_cmd_ptr = (cmdh_snapshot_sync_query_t *)i_cmd_ptr;
+
+ // Check received packet version
+ if (CMDH_SNAPSHOT_SYNC_VERSION != l_cmd_ptr->version)
+ {
+ TRAC_ERR("cmdh_snapshot_sync: Version %i cmd is not supported.", l_cmd_ptr->version);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // Set the global reset flag, that will cause all saved data to be cleared in the
+ // next callback that is done every 30seconds via a timer.
+ g_cmdh_snapshot_reset = TRUE;
+
+ // Reset current index to stop any possible calls from tmgt to get snapshot buffers.
+ g_cmdh_snapshot_cur_index = CMDH_SNAPSHOT_DEFAULT_CUR_INDEX;
+
+ //Reset timer and start counting from now. This will cause a call to the snapshot_callback
+ //function below which will reset the other globals based on the fact that g_cmdh_snapshot_reset
+ //is set to true.
+ l_rc = ssx_timer_schedule(&G_snapshotTimer, 0, SSX_SECONDS(30));
+ if (l_rc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_snapshot_sync: reseting the snapshot timer failed.");
+ break;
+ }
+
+ TRAC_INFO("cmdh_snapshot_sync: Snapshot buffer has been reset!");
+
+ l_resp_ptr->data_length[0] = 0;
+ l_resp_ptr->data_length[1] = 0;
+ l_resp_ptr->rc = 0;
+ }while(FALSE);
+
+ if (l_rc)
+ {
+ /// Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_err);
+ }
+ return(l_err);
+}
+
+// Function Specification
+//
+// Name: cmdh_
+//
+// Description: Called from timer every 30seconds to store cimp data into
+// an array of 20 cimp snapshots. Then it triggers the generation
+// of a new snapshot in the g_cmdh_sna
+//
+// Flow: 11/25/2013 FN=
+//
+// End Function Specification
+void cmdh_snapshot_callback(void * arg)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ static cmdh_snapshot_cimp_entry_t L_cim_buf[CMDH_CIMP_MAX]; //Holds the earlier cim data snapshots.
+ static uint8_t L_cim_seq_number = 0; // Holds the next cim seq number to be used.
+ static uint32_t L_prev_pwr_accum = 0; // Holds the previous power sensor accumulator
+ static uint32_t L_prev_pwr_update_tag = 0; // Holds the previous power sensor update tag.
+
+ uint32_t l_pwr_accum = AMECSENSOR_PTR(PWR250US)->accumulator;
+ uint32_t l_pwr_update_tag = AMECSENSOR_PTR(PWR250US)->update_tag;
+ uint32_t l_avg_pwr = 0;
+ uint32_t l_min_pwr = g_pwr250us_over30sec.min;
+ uint32_t l_max_pwr = g_pwr250us_over30sec.max;
+ uint32_t l_freq_accum = g_pwr250us_over30sec.freqaAccum;
+ uint32_t l_freq_cnt = g_pwr250us_over30sec.count;
+ uint16_t l_avg_freq = 0;
+
+ cmdh_snapshot_cimp_entry_t l_cim_buf_temp[CMDH_CIMP_MAX - 1];
+ cmdh_snapshot_buffer_t l_30s_snapshot; //Used to temporarily hold new snapshot data.
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //Clear data that is calculated every 250us to prep for next callback in 30seconds.
+ //Reset max and min over 30 seconds.
+ memset(&g_pwr250us_over30sec,0,sizeof(g_pwr250us_over30sec));
+
+ if (g_cmdh_snapshot_reset)
+ {
+ TRAC_INFO("cmdh_snapshot_callback: Initializing snapshot buffer and data.");
+
+ memset(g_cmdh_snapshot_array, 0, sizeof(g_cmdh_snapshot_array));
+ g_cmdh_snapshot_cur_id = 0;
+ memset(L_cim_buf,0,sizeof(cmdh_snapshot_buffer_t));
+ L_cim_seq_number = 0;
+ L_prev_pwr_accum = l_pwr_accum;
+ L_prev_pwr_update_tag = l_pwr_update_tag;
+ //Clear reset flag. - This should be the only place that clears it.
+ g_cmdh_snapshot_reset = FALSE;
+ g_cmdh_snapshot_cur_index = CMDH_SNAPSHOT_DEFAULT_CUR_INDEX;
+ }
+ else
+ {
+
+ uint32_t l_pwr_accum_diff = 0;
+ uint32_t l_pwr_uptag_diff = 0;
+
+ //Calculate the accumulator difference.
+ if(l_pwr_accum >= L_prev_pwr_accum)
+ {
+ l_pwr_accum_diff = l_pwr_accum - L_prev_pwr_accum;
+ }
+ else
+ {
+ l_pwr_accum_diff = l_pwr_accum + (~L_prev_pwr_accum);
+ }
+
+ //Calculate the update tag difference.
+ if(l_pwr_update_tag >= L_prev_pwr_update_tag)
+ {
+ l_pwr_uptag_diff = l_pwr_update_tag - L_prev_pwr_update_tag;
+ }
+ else if(l_pwr_update_tag < L_prev_pwr_update_tag) //accum must have wrapped.
+ {
+ l_pwr_uptag_diff = l_pwr_update_tag + (~L_prev_pwr_update_tag);
+ }
+
+ //Make sure we don't divide by 0
+ if(l_pwr_uptag_diff == 0)
+ {
+ //This should never happen.
+ TRAC_INFO("cmdh_snapshot_callback: update tag difference should not be 0. current:%i, previous:%i.",
+ l_pwr_update_tag, L_prev_pwr_update_tag);
+ l_avg_pwr = 0;
+ }
+ else
+ {
+ //Calculate average power since previous callback.
+ l_avg_pwr = l_pwr_accum_diff / l_pwr_uptag_diff;
+ }
+
+ if(l_freq_cnt == 0)
+ {
+ //This should never happen.
+ TRAC_INFO("cmdh_snapshot_callback: No frequency data has been accumulated. Returning 0 for frequency. count:%i.",
+ l_freq_cnt);
+ l_avg_freq = 0;
+ }
+ else
+ {
+ //Calculate average frequency of all Cores for the whole Node (all OCCs)
+ l_avg_freq = (uint16_t)(l_freq_accum / l_freq_cnt);
+ }
+
+ // Save power sensor accumulator and update tag values for next callback.
+ L_prev_pwr_accum = l_pwr_accum;
+ L_prev_pwr_update_tag = l_pwr_update_tag;
+
+ //Append the new cim buffer entry to the front of the local static array of cim buffers.
+ memcpy(l_cim_buf_temp, L_cim_buf, sizeof(cmdh_snapshot_cimp_entry_t) * (CMDH_CIMP_MAX - 1));
+
+ L_cim_buf[0].seq_number = L_cim_seq_number;
+ memcpy(L_cim_buf[0].avg_dc, &l_avg_pwr,sizeof(L_cim_buf[0].avg_dc));
+ memcpy(L_cim_buf[0].min_dc, &l_min_pwr,sizeof(L_cim_buf[0].min_dc));
+ memcpy(L_cim_buf[0].max_dc, &l_max_pwr,sizeof(L_cim_buf[0].max_dc));
+ memcpy(L_cim_buf[0].avg_cpu_freq, &l_avg_freq,sizeof(L_cim_buf[0].avg_cpu_freq));
+
+ memcpy(&(L_cim_buf[1]), l_cim_buf_temp, sizeof(cmdh_snapshot_cimp_entry_t) * (CMDH_CIMP_MAX - 1));
+
+ //Populate the local 30s snapshot buffer before writing it out to the global array. Reason is
+ //we don't want the buffer data to be read by tmgt cmd while we are filling it.
+
+ //Copy cim data to snapshot buffer.
+ memcpy(l_30s_snapshot.cim, L_cim_buf, sizeof(cmdh_snapshot_cimp_entry_t) * CMDH_CIMP_MAX);
+ l_30s_snapshot.current_id = g_cmdh_snapshot_cur_id;
+
+ //Increment current index to signify that we are going to add a new snapshot.
+ g_cmdh_snapshot_cur_index++;
+ if (g_cmdh_snapshot_cur_index > CMDH_SNAPSHOT_MAX_INDEX)
+ {
+ // Wrap back to start
+ g_cmdh_snapshot_cur_index = 0;
+ }
+
+ //Write buffer to the current index in the global array g_cmdh_snapshot_array.
+ memcpy(&(g_cmdh_snapshot_array[g_cmdh_snapshot_cur_index]),&l_30s_snapshot, sizeof(cmdh_snapshot_buffer_t));
+
+ //Increment snapshot id.
+ g_cmdh_snapshot_cur_id++;
+
+ //Increment sequence count.
+ L_cim_seq_number ++;
+ }
+}
diff --git a/src/occ/cmdh/cmdh_snapshot.h b/src/occ/cmdh/cmdh_snapshot.h
new file mode 100755
index 0000000..4fd6d7d
--- /dev/null
+++ b/src/occ/cmdh/cmdh_snapshot.h
@@ -0,0 +1,143 @@
+/**
+ * @file cmdh_snapshot.h
+ * @brief Header file for snapshot buffer interface.
+ *
+ *
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_snapshot_h cmdh_snapshot.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- --------- ----------------------------------
+ * @fk004 907588 fmkassem 11/25/2013 Created
+ *
+ * @endverbatim
+ */
+#ifndef CMDH_SNAPSHOT_H
+#define CMDH_SNAPSHOT_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "cmdh_fsp_cmds.h"
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+/* snapshot buffer timer */
+extern SsxTimer G_snapshotTimer;
+
+
+//@fk004a
+/**************************************************************************
+ * @struct cmdh_get_ssbuffer_req_t
+ * @brief Struct used to parse get snapshot buffer request Command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header; // Standard TMGT
+ uint8_t version; // Get snapshot request Version
+ uint8_t reserved; // Reserved.
+ uint8_t requested_id; // ID of snapshot buffer to be returned.
+ uint8_t getnewest; // 0x01 => return newest snapshot, 0x00 => return snapshot of ID given.
+}cmdh_get_snapshot_query_t;
+
+
+#define CMDH_GET_SNAPSHOT_NONITE_VERSION 0
+#define CMDH_GET_SNAPSHOT_ITE_VERSION 1
+#define CMDH_GET_SNAPSHOT_QUERY_DATALEN sizeof(cmdh_get_snapshot_query_t) - sizeof(cmdh_fsp_cmd_header_t)
+#define CMDH_SNAPSHOT_MAX 6
+#define CMDH_CIMP_MAX 20
+#define CMDH_SNAPSHOT_DEFAULT_CUR_INDEX 0xFF //Default value of g_cmdh_snapshot_cur_index
+#define CMDH_SNAPSHOT_MAX_INDEX (CMDH_SNAPSHOT_MAX - 1)
+#define CMDH_SNAPSHOT_SYNC_VERSION 0
+
+/**************************************************************************
+ * @struct cmdh_snapshot_entry_t;
+ * @brief Used by OCC to store sequenced snapshot entries. 16
+ * bytes each
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint8_t seq_number; //Snapshot Sequence number; 30 second time slice.
+ uint8_t avg_dc[4]; //Average total node DC power in milliwatts.
+ uint8_t max_dc[4]; //Maximum total node DC power in milliwatts.
+ uint8_t min_dc[4]; //Minimum total node DC power in milliwatts.
+ uint8_t avg_cpu_freq[2]; //Average Node CPU Frequency in MHz.
+ uint8_t reserved; //reserved.
+}cmdh_snapshot_cimp_entry_t;
+
+/**************************************************************************
+ * @struct cmdh_snapshot_entry_t;
+ * @brief Contains all entries in a snapshot.
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint8_t current_id; // Snapshot buffer ID number of buffer data to follow, typically this should match id in request data, unless it's not available.
+ cmdh_snapshot_cimp_entry_t cim[CMDH_CIMP_MAX]; // Data collected for cimp
+}cmdh_snapshot_buffer_t;
+
+/**************************************************************************
+ * @struct cmdh_get_snapshot_resp_v0_t;
+ * @brief Used by OCC to respond to "GET_SNAPSHOT_BUFFER" nonite(version 0) cmd. 323 bytes
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint8_t oldest_id; // Oldest available snapshot buffer ID number
+ uint8_t newest_id; // Newest available snapshot buffer ID number
+ cmdh_snapshot_buffer_t snapshot; // Snapshot.
+ uint8_t checksum[2]; // Checksum
+}cmdh_get_snapshot_resp_v0_t;
+
+/**************************************************************************
+ * @struct cmdh_snapshot_sync_resp_t;
+ * @brief Used by OCC to respond to "SNAPSHOT_SYNC" cmd.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ UINT8 checksum[2];
+}cmdh_snapshot_sync_resp_t;
+
+/**************************************************************************
+ * @struct cmdh_snapshot_sync_query_t;
+ * @brief structure of cmd packet received from tmgt.
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header; // Standard TMGT
+ UINT8 version;
+} cmdh_snapshot_sync_query_t;
+
+/**************************************************************************
+ * @struct pwr250us_over30sec_t
+ * @brief structure of data that need to be maintained between snapshots.
+ */
+typedef struct __attribute__ ((packed))
+{
+ uint32_t count; //Count of number of samples taken.
+ uint16_t max; //Max value of pwr250us
+ uint16_t min; //Min value of pwr250us
+ uint32_t freqaAccum;//Accumulated AvgFreq over the past 30seconds.
+} pwr250us_over30sec_t;
+
+extern pwr250us_over30sec_t g_pwr250us_over30sec;
+//*************************************************************************
+// Function Declarations
+//*************************************************************************
+
+errlHndl_t cmdh_get_snapshot_buffer(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr);
+
+errlHndl_t cmdh_snapshot_sync(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr);
+
+//Called by a timer that is triggered every 30seconds.
+void cmdh_snapshot_callback(void * arg);
+
+
+#endif
diff --git a/src/occ/cmdh/cmdh_thread.c b/src/occ/cmdh/cmdh_thread.c
new file mode 100644
index 0000000..e78d98d
--- /dev/null
+++ b/src/occ/cmdh/cmdh_thread.c
@@ -0,0 +1,166 @@
+/******************************************************************************
+// @file cmdh_thread.c
+// @brief Command Handling for FSP Communication.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_fsp_c cmdh_fsp.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th023 thallet 10/08/2012 Moved cmdh thread commands to this file
+ * @th033 878894 thallet 04/26/2013 AVP Moded changes
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup
+ * @th039 887066 thallet 06/11/2013 FSP Comm Improvements - Attn
+ * @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+ * @gs041 942203 gjsilva 10/17/2014 Support for HTMGT/BMC interface
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include "errl.h"
+#include "trac.h"
+#include <thread.h>
+#include <threadSch.h>
+#include "state.h"
+#include <cmdh_fsp.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+eCmdhWakeupThreadMask G_cmdh_thread_wakeup_mask;
+
+extern uint8_t G_occ_interrupt_type;
+
+//*************************************************************************
+// Function Declarations
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: Cmd_Hndl_thread_routine
+//
+// Description: This needs to be moved to separate file after we add cmd handler
+// thread support
+//
+// Flow:
+//
+// End Function Specification
+void Cmd_Hndl_thread_routine(void *arg)
+{
+#define OCC_RESP_READY_ALERT_TIMEOUT_ATTEMPTS 5
+ int l_rc = 0;
+ errlHndl_t l_errlHndl = NULL;
+
+ CHECKPOINT(CMDH_THREAD_STARTED);
+ TRAC_INFO("Command Handler Thread Started ... " );
+
+ // ------------------------------------------------
+ // Initialize HW for FSP Comm
+ // ------------------------------------------------
+ l_errlHndl = cmdh_fsp_init();
+ if(l_errlHndl)
+ {
+ // Mark Errl as committed, so FSP knows right away we are having
+ // problems with Attention, if that is the cause of the error.
+ commitErrl(&l_errlHndl);
+ }
+
+ CHECKPOINT(FSP_COMM_INITIALIZED);
+
+ // Only send this first attention if FSP is present
+ if(G_occ_interrupt_type == 0x00)
+ {
+ // ------------------------------------------------
+ // Send 'Service' Attention to signal that we are
+ // ready to accept commands from FSP.
+ // ------------------------------------------------
+ cmdh_fsp_attention( OCC_ALERT_FSP_SERVICE_REQD );
+
+ CHECKPOINT(FIRST_FSP_ATTN_SENT);
+ }
+
+ // ------------------------------------------------
+ // Loop forever, handling FSP commands
+ // ------------------------------------------------
+ while(1)
+ {
+ // ------------------------------------------------
+ // Block, Waiting on sem for a doorbell from FSP
+ // ------------------------------------------------
+ l_rc = cmdh_thread_wait_for_wakeup(); // Blocking Call
+
+ // ------------------------------------------------
+ // Handle the command
+ // ------------------------------------------------
+ if(SSX_OK == l_rc)
+ {
+ if( CMDH_WAKEUP_FSP_COMMAND & G_cmdh_thread_wakeup_mask )
+ {
+ clearCmdhWakeupCondition(CMDH_WAKEUP_FSP_COMMAND);
+
+ // Handle the command that TMGT just sent to OCC
+ l_errlHndl = cmdh_fsp_cmd_hndler();
+
+ // Commit an error if we get one passed back, do it before
+ // we tell the FSP we have a response ready
+ if(NULL != l_errlHndl)
+ {
+ commitErrl(&l_errlHndl);
+ }
+
+ // Check is the sender is FSP
+ if(G_fsp_msg.doorbell[0] == ATTN_SENDER_ID_FSP)
+ {
+ // Tell the FSP we have a response ready for them.
+ // Try to send this for 500ms before giving up
+ cmdh_fsp_attention_withRetry(OCC_ALERT_FSP_RESP_READY, 500);
+ }
+ }
+
+ if (CMDH_WAKEUP_FSP_ATTENTION_ALERT & G_cmdh_thread_wakeup_mask)
+ {
+ clearCmdhWakeupCondition(CMDH_WAKEUP_FSP_ATTENTION_ALERT);
+
+ // Tell the FSP we have something they need to come check on.
+ // Try to send this for 500ms, before giving up
+ cmdh_fsp_attention_withRetry(OCC_ALERT_FSP_SERVICE_REQD, 500);
+ }
+
+ if (CMDH_WAKEUP_FSP_CHECKSTOP_ALERT & G_cmdh_thread_wakeup_mask)
+ {
+ clearCmdhWakeupCondition(CMDH_WAKEUP_FSP_CHECKSTOP_ALERT);
+
+ // Tell the FSP we have something they need to come check on.
+ // Try to send this for 500ms, before giving up
+ cmdh_fsp_attention_withRetry(OCC_ALERT_SYS_CHECKSTOP, 500);
+ }
+
+ }
+ }
+
+}
+
+
+
diff --git a/src/occ/cmdh/cmdh_tunable_parms.c b/src/occ/cmdh/cmdh_tunable_parms.c
new file mode 100755
index 0000000..fe7164e
--- /dev/null
+++ b/src/occ/cmdh/cmdh_tunable_parms.c
@@ -0,0 +1,293 @@
+/******************************************************************************
+// @file cmdh_tunable_parms.c
+// @brief Command Handling for Tunable Parms Interface
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_tunable_parms_c cmdh_tunable_parms.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @rt004 905638 tapiar 11/13/2013 Created
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "cmdh_tunable_parms.h"
+#include "cmdh_service_codes.h"
+#include "cmdh_fsp_cmds.h"
+#include "dcom.h"
+//*************************************************************************
+// Externs
+//*************************************************************************
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Declarations
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: cmdh_tunable_parms_query
+//
+// Description: This function returns all supported tuanble parameters from the
+// Tunable Parameters List that this system type supports.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t cmdh_tunable_parms_query( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_numParms = 0;
+ tunable_parms_query_cmd_t *l_cmd_ptr = (tunable_parms_query_cmd_t*) i_cmd_ptr;
+ tunable_parms_query_rsp_t *l_rsp_ptr = (tunable_parms_query_rsp_t*) o_rsp_ptr;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // check version
+ if ( l_cmd_ptr->version != TUNABLE_PARMS_QUERY_VERSION )
+ {
+ TRAC_ERR("cmdh_tunable_parms_query: Tunable Parms invalid version: %x", l_cmd_ptr->version );
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+
+ // start setting up response ::
+
+ // version
+ l_rsp_ptr->version = TUNABLE_PARMS_QUERY_VERSION;
+
+ // number of parameters
+ l_numParms = sizeof(G_mst_tunable_parameter_table) / sizeof (cmdh_tunable_param_table_t);
+ l_rsp_ptr->numParms = l_numParms;
+
+ TRAC_INFO("cmdh_tunable_parms_query: Found %d entries", l_numParms );
+
+ // copy complete global array data into response
+ memcpy( l_rsp_ptr->data, G_mst_tunable_parameter_table, sizeof(G_mst_tunable_parameter_table) );
+
+ }while(0);
+
+ // setup the response data packet info
+ uint16_t l_size = 2 + sizeof(G_mst_tunable_parameter_table);
+ o_rsp_ptr->rc = l_rc;
+ o_rsp_ptr->data_length[0] = ((uint8_t *)&l_size)[0];
+ o_rsp_ptr->data_length[1] = ((uint8_t *)&l_size)[1];
+
+ return l_rc;
+}
+
+
+
+// Function Specification
+//
+// Name: cmdh_tunable_parms_write
+//
+// Description: This function is used to set the values for tunable parameters
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t cmdh_tunable_parms_write( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ tunable_parms_write_cmd_t *l_cmd_ptr = (tunable_parms_write_cmd_t*) i_cmd_ptr;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // check version
+ if ( l_cmd_ptr->version != TUNABLE_PARMS_WRITE_VERSION )
+ {
+ TRAC_ERR("cmdh_tunable_parms_write: Tunable Parms invalid version: %x", l_cmd_ptr->version );
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // loop through each parameter entry sent
+ uint8_t i = 0;
+ for (i=0; i < l_cmd_ptr->numParms; i++)
+ {
+ // check if id is valid
+ uint8_t l_id = l_cmd_ptr->data[i].id;
+ if ( (l_id>0) && (l_id<=CMDH_DEFAULT_TUNABLE_PARAM_NUM) )
+ {
+ // save off value
+ G_mst_tunable_parameter_table[l_id-1].value = CONVERT_UINT8_ARRAY_UINT16(l_cmd_ptr->data[i].value[0], l_cmd_ptr->data[i].value[1]);
+ G_mst_tunable_parameter_table_ext[l_id-1].adj_value = G_mst_tunable_parameter_table[l_id-1].value*G_mst_tunable_parameter_table_ext[l_id-1].multiplier;
+ }
+ else
+ {
+ TRAC_INFO("cmdh_tunable_parms_write: Tunable Parms invalid data found id=%x, value=%x",
+ l_id, CONVERT_UINT8_ARRAY_UINT16(l_cmd_ptr->data[i].value[0], l_cmd_ptr->data[i].value[1]) );
+
+ l_rc = ERRL_RC_INVALID_DATA;
+ }
+ }
+
+ }while(0);
+
+ // Populate the response data packet
+ o_rsp_ptr->rc = l_rc;
+
+ // set global var
+ G_mst_tunable_parameter_overwrite = 1;
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_tunable_parms_restore
+//
+// Description: This is used to tell OCC to use default value for all supported
+// tunable parameters defined in the Tunable Parameters list.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t cmdh_tunable_parms_restore(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // loop through global array
+ uint8_t i = 0;
+ for (i=0; i<CMDH_DEFAULT_TUNABLE_PARAM_NUM; i++)
+ {
+ // update value using default value
+ G_mst_tunable_parameter_table[i].value = G_mst_tunable_parameter_table_ext[i].def_value;
+ G_mst_tunable_parameter_table_ext[i].adj_value = G_mst_tunable_parameter_table_ext[i].def_value*G_mst_tunable_parameter_table_ext[i].multiplier;
+ }
+
+ }while(0);
+
+ // Populate the response data header
+ o_rsp_ptr->rc = l_rc;
+
+ // set global var
+ G_mst_tunable_parameter_overwrite = 2;
+
+ return l_rc;
+}
+
+
+
+// Function Specification
+//
+// Name: cmdh_tunable_parms
+//
+// Description: This function parses the tunable parms commands sent via TMGT.
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t cmdh_tunable_parms ( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t l_rc = 0;
+ uint8_t l_sub_cmd = 0;
+ errlHndl_t l_errl = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // command is only supported on Master OCC
+ if (G_occ_role == OCC_SLAVE)
+ {
+ TRAC_ERR("cmdh_tunable_parms: Tunable Parameters command not supported on Slave OCCs!");
+ l_rc = ERRL_RC_INVALID_CMD;
+ break;
+ }
+
+ // Sub-command is always first byte of data
+ l_sub_cmd = i_cmd_ptr->data[0];
+
+ TRAC_INFO("cmdh_tunable_parms: Tunable Parms sub-command [%d]", l_sub_cmd );
+
+ switch (l_sub_cmd)
+ {
+ case TUNABLE_PARMS_QUERY:
+ l_rc = cmdh_tunable_parms_query(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case TUNABLE_PARMS_WRITE:
+ l_rc = cmdh_tunable_parms_write(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case TUNABLE_PARMS_RESTORE:
+ l_rc = cmdh_tunable_parms_restore(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ default:
+ // Should never get here...
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+ } while (0);
+
+ // All errors in TUNABLE PARMS logged internally
+ if (l_rc)
+ {
+ TRAC_ERR("Tunable Parms command 0x%02x failed with rc = %d", l_sub_cmd, l_rc);
+
+ // Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errl);
+ }
+
+ return l_errl;
+}
+
diff --git a/src/occ/cmdh/cmdh_tunable_parms.h b/src/occ/cmdh/cmdh_tunable_parms.h
new file mode 100755
index 0000000..8dfb9d5
--- /dev/null
+++ b/src/occ/cmdh/cmdh_tunable_parms.h
@@ -0,0 +1,107 @@
+/**
+ * @file cmdh_tunable_parms.h
+ * @brief Header file for Tunable Parms interface.
+ *
+ *
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _cmdh_tunable_parms_h cmdh_tunable_parms.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * -------- ---------- -------- --------- ----------------------------------
+ * @rt004 905638 tapiar 11/13/2013 Created
+ *
+ * @endverbatim
+ */
+#ifndef CMDH_TUNABLE_PARMS_H
+#define CMDH_TUNABLE_PARMS_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "cmdh_fsp_cmds.h"
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+typedef enum {
+ TUNABLE_PARMS_QUERY = 0x00,
+ TUNABLE_PARMS_WRITE = 0x01,
+ TUNABLE_PARMS_RESTORE = 0x02,
+} TUNABLE_PARMS_CMD;
+
+
+/**
+ * @struct tunable_parms_query_cmd_t
+ * @brief Used by OCC to get tunable parms query
+ * command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t version;
+}tunable_parms_query_cmd_t;
+
+#define TUNABLE_PARMS_MAX_PARMS 29
+
+#define TUNABLE_PARMS_QUERY_VERSION 0
+#define TUNABLE_PARMS_WRITE_VERSION 0
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t id;
+ uint8_t value[2];
+}tunable_parm_write_entry_t;
+
+/**
+ * @struct tunable_parms_write_cmd_t
+ * @brief Used by OCC to get tunable parms write
+ * command
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t version;
+ uint8_t numParms;
+ tunable_parm_write_entry_t data[TUNABLE_PARMS_MAX_PARMS];
+}tunable_parms_write_cmd_t;
+
+
+/**
+ * @struct tunable_parms_query_rsp_t
+ * @brief Used by OCC to get tunable parms query
+ * response
+ */
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint8_t version;
+ uint8_t numParms;
+ cmdh_tunable_param_table_t data[TUNABLE_PARMS_MAX_PARMS];
+}tunable_parms_query_rsp_t;
+
+
+
+/*******************************************************************/
+/* Function Definitions */
+/*******************************************************************/
+
+errlHndl_t cmdh_tunable_parms( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+uint8_t cmdh_tunable_parms_query( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+uint8_t cmdh_tunable_parms_write( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+uint8_t cmdh_tunable_parms_restore( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
+
+#endif
diff --git a/src/occ/cmdh/ffdc.c b/src/occ/cmdh/ffdc.c
new file mode 100755
index 0000000..7f83e12
--- /dev/null
+++ b/src/occ/cmdh/ffdc.c
@@ -0,0 +1,145 @@
+
+/******************************************************************************
+ * @file ffdc.c
+ * @brief FFDC support routines.
+ ******************************************************************************/
+
+/******************************************************************************
+ * @page ChangeLogs Change Logs
+ * @section _ffdc_c ffdc.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ------------------------------------
+ * 916980 sbroyles 03/10/2014 Created
+ * @endverbatim
+ ******************************************************************************/
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+#include "ffdc.h"
+
+//******************************************************************************
+// Externs
+//******************************************************************************
+
+//******************************************************************************
+// Defines/Enums
+//******************************************************************************
+
+//******************************************************************************
+// Functions
+//******************************************************************************
+
+// Function Specification //////////////////////////////////////////////////////
+//
+// Name: ffdc_thread_dumper
+//
+// Description: Dump the state of the thread provided
+//
+// Flow: FN=None
+//
+// End Function Specification //////////////////////////////////////////////////
+void
+ffdc_thread_dumper(SsxThread *i_thread, void *o_ffdc_buffer)
+{
+ // Format of data dumped into FFDC buffer. The buffer space allocated must
+ // match the size of the dump. The dumped structure must agree with the
+ // structure of the FFDC defined in ll_ffdc.S.
+ //
+ // Offset Length Contents
+ // 0x00 1 Length of thread dump
+ // 0x01 1 Priority
+ // 0x02 1 State
+ // 0x03 1 Flags
+ // 0x04 4 Thread timer
+ // 0x08 4 Semaphore
+ // 0x0c 4 SRR0
+ // 0x10 4 SRR1
+ // 0x14 4 SRR2
+ // 0x18 4 SRR3
+ // 0x1c 4 LR
+ // 0x20 32 Thread stack unwind
+ //
+ // Total length = 64 bytes
+
+ uint8_t *l_byte_ptr = (uint8_t *)o_ffdc_buffer;
+ // Store length, priority, state and flags to buffer
+ l_byte_ptr[0] = 64;
+ l_byte_ptr[1] = (uint8_t)(i_thread->priority);
+ l_byte_ptr[2] = (uint8_t)(i_thread->state);
+ l_byte_ptr[3] = (uint8_t)(i_thread->flags);
+
+ // Store Timer, Semaphore
+ uint32_t *l_word_ptr = (uint32_t *)(l_byte_ptr + 4);
+ l_word_ptr[0] = (uint32_t)&(i_thread->timer);
+ l_word_ptr[1] = (uint32_t)(i_thread->semaphore);
+
+ // Store SRR0-3 and LR from saved context
+ SsxThreadContext *l_threadCtx = (SsxThreadContext *)(i_thread->saved_stack_pointer);
+ l_word_ptr[2] = (uint32_t)(l_threadCtx->srr0);
+ l_word_ptr[3] = (uint32_t)(l_threadCtx->srr1);
+ l_word_ptr[4] = (uint32_t)(l_threadCtx->srr2);
+ l_word_ptr[5] = (uint32_t)(l_threadCtx->srr3);
+ l_word_ptr[6] = (uint32_t)(l_threadCtx->lr);
+
+ // Store up to 8 LRs from stack chain, set stack frame pointer to caller's
+ // frame.
+ uint32_t *l_sptr = (uint32_t *)(((uint32_t*)l_threadCtx->r1)[0]);
+ // Reset the ffdc pointer
+ l_word_ptr = &l_word_ptr[7];
+ ffdc_stack_unwind(l_sptr, l_word_ptr, 8);
+}
+// End of ffdc_thread_dumper
+
+
+// Function Specification //////////////////////////////////////////////////////
+//
+// Name: ffdc_stack_unwind
+//
+// Description: Unwind the link registers from the provided stack pointer.
+//
+// Flow: FN=None
+//
+// End Function Specification //////////////////////////////////////////////////
+void
+ffdc_stack_unwind(uint32_t *i_sptr, uint32_t *o_buffer, uint32_t i_frameCount)
+{
+ // Format of the data dumped to the output buffer.
+ // The caller must provide at least one 32 bit word per frame requested by
+ // frame count parameter.
+ //
+ // Offset Length Contents
+ // 0x00 4 Link register for frame n
+ // 0x04 4 Link register for frame n+1
+ // ... do as many as frames as requested
+
+ uint32_t *l_sptr = i_sptr;
+ int i = 0;
+ // Loop through the frames storing the LR words
+ for (i = 0; i < i_frameCount; i++)
+ {
+ // Stop storing if we get to the last frame
+ if (l_sptr == NULL)
+ {
+ // Zero out the remaining words in the buffer and break
+ for (; i < i_frameCount; i++)
+ {
+ o_buffer[i] = 0x00000000;
+ }
+ break;
+ }
+ else
+ {
+ o_buffer[i] = (uint32_t)(l_sptr[1]);
+ l_sptr = (uint32_t *)l_sptr[0];
+ }
+ }
+}
+// End of ffdc_stack_unwind
+
+
+//
+// End of ffdc.c
+//
diff --git a/src/occ/cmdh/ffdc.h b/src/occ/cmdh/ffdc.h
new file mode 100755
index 0000000..ef7ba7a
--- /dev/null
+++ b/src/occ/cmdh/ffdc.h
@@ -0,0 +1,50 @@
+
+/******************************************************************************
+ * @file ffdc.h
+ * @brief FFDC support routines.
+ ******************************************************************************/
+
+/******************************************************************************
+ * @page ChangeLogs Change Logs
+ * @section _ffdc_h ffdc.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ------------------------------------
+ * 916980 sbroyles 03/10/2014 Created
+ * @endverbatim
+ ******************************************************************************/
+
+#ifndef _FFDC_H
+#define _FFDC_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+/*******************************************************************/
+/* Globals */
+/*******************************************************************/
+
+/*******************************************************************/
+/* Function Prototypes */
+/*******************************************************************/
+void ffdc_thread_dumper(SsxThread *, void *);
+void ffdc_stack_unwind(uint32_t *, uint32_t *, uint32_t);
+
+
+#endif // _FFDC_H
+
diff --git a/src/occ/cmdh/ll_ffdc.S b/src/occ/cmdh/ll_ffdc.S
new file mode 100644
index 0000000..2f1afd8
--- /dev/null
+++ b/src/occ/cmdh/ll_ffdc.S
@@ -0,0 +1,959 @@
+
+#*******************************************************************************
+# @file ll_ffdc.S
+# @brief save off registers to fsp response buffer
+#*******************************************************************************
+
+#*******************************************************************************
+# @page ChangeLogs Change Logs
+# @section _ll_ffdc_S ll_ffdc.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+# @sb002 908891 sbroyles 12/09/2013 FFDC updates
+# @sb012 910394 sbroyles 01/10/2014 More FFDC updates
+# @sb023 913769 sbroyles 02/08/2014 Fix SPR capture
+# @sb040 916980 sbroyles 02/26/2014 Multiple fixes and additions
+# @endverbatim
+#*******************************************************************************
+
+// @sb002 Updated header and ffdc packet info text
+
+/*****************************************************************************/
+// Includes
+/*****************************************************************************/
+#include "ssx.h"
+
+/*****************************************************************************/
+// Literals and Structures
+/*****************************************************************************/
+
+#
+# Format of FFDC header (8 bytes)
+#
+# Header Start
+# Sequence
+# | Command
+# | | Exception code
+# | | | Length of data
+# | | | | unused
+# | | | | | Panic Checkpoint: Two possible sets, 0xF00 (ABOUT_TO_HALT), a 405
+# | | | | | | trap event, and everything else. Other values
+# | | | | | | occur at init events, see checkpoints in occ_common.h
+# | | | | | | Begin data buffer
+# | | | | | | |
+# SSCCRRLL/LLxxKKKK D...
+# |
+# Header End
+# Return status is always 'E*'h
+# See cmdh_fsp.h ERRL_RC for command buffer response codes. All E* RCs are
+# meant to indicate a trap/halt event on the OCC and they should be followed
+# by an FFDC data packet. If they didn't it means that the occ has either
+# hung or trapped without processing the FFDC save function.
+#
+# FFDC Data packet:
+#
+# Offset Len Register(s)
+# from start of
+# rsp buffer
+# -----------------------------------------------------------------------------
+# 0 (x00) 1 Sequence (0x00 for FFDC)
+# 1 (x01) 1 Command (0x00 for FFDC)
+# 2 (x02) 1 Exception code (Always 0xE* for OCC FFDC)
+# 3 (x03) 1 Length Hi byte
+# 4 (x04) 1 Length Lo byte
+# 5 (x05) 1 Unused (0x00 for FFDC)
+# 6 (x06) 2 Checkpoint (Typically 0x0F00)
+# 8 (x08) 4 SSX Panic Code
+# 12 (x0c) 4 Panic Address (inside function that called panic)
+# 16 (x10) 4 Link Register (caller of function that called panic))
+# 20 (x14) 4 Machine Status Register (interrupt context?)
+# 24 (x18) 4 Condition Register (CR)
+# 28 (x1c) 4 Count Register (CTR)
+# (128) GPR0 - GPR31 (GPR1 is the stack pointer)
+# 32 (x20) 4 GPR0
+# 36 (x24) 4 GPR1
+# 40 (x28) 4 GPR2
+# 44 (x2c) 4 GPR3
+# 48 (x30) 4 GPR4
+# 52 (x34) 4 GPR5
+# 56 (x38) 4 GPR6
+# 60 (x3c) 4 GPR7
+# 64 (x40) 4 GPR8
+# 68 (x44) 4 GPR9
+# 72 (x48) 4 GPR10
+# 76 (x4c) 4 GPR11
+# 80 (x50) 4 GPR12
+# 84 (x54) 4 GPR13
+# 88 (x58) 4 GPR14
+# 92 (x5c) 4 GPR15
+# 96 (x60) 4 GPR16
+# 100 (x64) 4 GPR17
+# 104 (x68) 4 GPR18
+# 108 (x6c) 4 GPR19
+# 112 (x70) 4 GPR20
+# 116 (x74) 4 GPR21
+# 120 (x78) 4 GPR22
+# 124 (x7c) 4 GPR23
+# 128 (x80) 4 GPR24
+# 132 (x84) 4 GPR25
+# 136 (x88) 4 GPR26
+# 140 (x8c) 4 GPR27
+# 144 (x90) 4 GPR28
+# 148 (x94) 4 GPR29
+# 152 (x98) 4 GPR30
+# 156 (x9c) 4 GPR31
+#
+# 160 (xa0) 4 evpr
+# 164 (xa4) 4 xer
+# 168 (xa8) 4 esr
+# 172 (xac) 4 dear (bad address)
+# 176 (xb0) 4 srr0 (return address for non critical interrupt)
+# 180 (xb4) 4 srr1 (MSR at interrupt)
+# 184 (xb8) 4 srr2 (return address for critical interrupt)
+# 188 (xbc) 4 srr3 (MSR at interrupt)
+# 192 (xc0) 4 mcsr
+# 196 (xc4) 4 pid
+# 200 (xc8) 4 zpr
+# 204 (xcc) 4 usprg0
+# (32) sprg0 - sprg7
+# 208 (xd0) 4 sprg0
+# 212 (xd4) 4 sprg1
+# 216 (xd8) 4 sprg2
+# 220 (xdc) 4 sprg3
+# 224 (xe0) 4 sprg4
+# 228 (xe4) 4 sprg5
+# 232 (xe8) 4 sprg6
+# 236 (xec) 4 sprg7
+#
+# 240 (xf0) 4 tcr
+# 244 (xf4) 4 tsr
+# 248 (xf8) 4 dbcr0
+# 252 (xfc) 4 dbcr1
+# 256 (x100) 4 dbsr
+# 260 (x104) 4 OCB_OISR0
+# 264 (x108) 4 OCB_OISR1
+# 268 (x10c) 4 OCB_OUDER0
+# 272 (x110) 4 OCB_OUDER1
+# 276 (x114) 4 OCB_OIMR0
+# 280 (x118) 4 OCB_OIMR1
+# 284 (x11c) 4 OCB_OITR0
+# 288 (x120) 4 OCB_OITR1
+# 292 (x124) 4 OCB_OIEPR0
+# 296 (x128) 4 OCB_OIEPR1
+# 300 (x12c) 4 OCB_OCIR0
+# 304 (x130) 4 OCB_OCIR1
+# 308 (x134) 4 OCB_ONISR0
+# 312 (x138) 4 OCB_ONISR1
+# 316 (x13c) 4 OCB_OCISR0
+# 320 (x140) 4 OCB_OCISR1
+# 324 (x144) 4 OCB_ODHER0
+# 328 (x148) 4 OCB_ODHER1
+# 332 (x14c) 4 SSX timebase
+# 336 (x150) 16 Build name
+# 352 (x160) 8 OCCLFIR
+# 360 (x168) 8 PBAFIR
+# 368 (x170) 4 CORES_DECON
+# (64) Main thread dump
+# 372 (x174) 1 Length of thread dump (64)
+# 373 (x175) 1 Priority
+# 374 (x176) 1 State
+# 375 (x177) 1 Flags
+# 376 (x178) 4 Timer
+# 380 (x17c) 4 Semaphore
+# 384 (x180) 4 SRR0
+# 388 (x184) 4 SRR1
+# 392 (x188) 4 SRR2
+# 396 (x18c) 4 SRR3
+# 400 (x190) 4 Link register
+# 404 (x194) 32 Thread stack trace
+#
+# 436 (x1b4) 64 Command thread dump
+# 500 (x1f4) 64 App thread dump
+# 564 (x234) 64 DCOM thread dump
+# 628 (x274) 32 Stack trace
+# 660 (x294) 4 xffdcffdc End of buffer marker
+# -----------------------------------------------------------------------------
+# Total size: 664 - 8 + 3 = 659
+#
+// @sb040 Lots of updates including a new struct for the FFDC buffer, diff to
+// previous version to see all changes, individual line change tags left out to
+// reduce clutter.
+
+# --------------
+# FFDC Constants
+# --------------
+
+ .set FFDC_BUFFER_ADDR, 0xFFFF7000
+ .set FFDC_DBCR0, (DBCR0_EDM | DBCR0_TDE | DBCR0_FT)
+ .set FFDC_END_MARKER, 0xFFDCFFDC
+ .set FFDC_OCC_CHECKPOINT, 0x0F00
+ .set FFDC_SSX_PANIC_EX_CODE, 0xE0
+
+# ---------------------
+# FFDC buffer structure
+# ---------------------
+
+ .struct FFDC_BUFFER_ADDR
+SEQUENCE: .byte
+ .struct SEQUENCE + 1
+COMMAND: .byte
+ .struct COMMAND + 1
+EXCEPTION: .byte
+ .struct EXCEPTION + 1
+LENGTH_HI: .byte
+ .struct LENGTH_HI + 1
+LENGTH_LO: .byte
+ .struct LENGTH_LO + 1
+UNUSED: .byte
+ .struct UNUSED + 1
+CHECKPOINT: .short
+ .struct CHECKPOINT + 2
+PANIC_CODE: .int
+ .struct PANIC_CODE + 4
+PANIC_ADDR: .int
+ .struct PANIC_ADDR + 4
+LINK_REG: .int
+ .struct LINK_REG + 4
+MSR: .int
+ .struct MSR + 4
+CR: .int
+ .struct CR + 4
+CTR: .int
+ .struct CTR + 4
+GPR0: .int
+ .struct GPR0 + 4
+GPR1: .int
+ .struct GPR1 + 4
+GPR2: .int
+ .struct GPR2 + 4
+GPR3: .int
+ .struct GPR3 + 4
+GPR4: .int
+ .struct GPR4 + 4
+GPR5: .int
+ .struct GPR5 + 4
+GPR6: .int
+ .struct GPR6 + 4
+GPR7: .int
+ .struct GPR7 + 4
+GPR8: .int
+ .struct GPR8 + 4
+GPR9: .int
+ .struct GPR9 + 4
+GPR10: .int
+ .struct GPR10 + 4
+GPR11: .int
+ .struct GPR11 + 4
+GPR12: .int
+ .struct GPR12 + 4
+GPR13: .int
+ .struct GPR13 + 4
+GPR14: .int
+ .struct GPR14 + 4
+GPR15: .int
+ .struct GPR15 + 4
+GPR16: .int
+ .struct GPR16 + 4
+GPR17: .int
+ .struct GPR17 + 4
+GPR18: .int
+ .struct GPR18 + 4
+GPR19: .int
+ .struct GPR19 + 4
+GPR20: .int
+ .struct GPR20 + 4
+GPR21: .int
+ .struct GPR21 + 4
+GPR22: .int
+ .struct GPR22 + 4
+GPR23: .int
+ .struct GPR23 + 4
+GPR24: .int
+ .struct GPR24 + 4
+GPR25: .int
+ .struct GPR25 + 4
+GPR26: .int
+ .struct GPR26 + 4
+GPR27: .int
+ .struct GPR27 + 4
+GPR28: .int
+ .struct GPR28 + 4
+GPR29: .int
+ .struct GPR29 + 4
+GPR30: .int
+ .struct GPR30 + 4
+GPR31: .int
+ .struct GPR31 + 4
+EVPR: .int
+ .struct EVPR + 4
+EXR: .int
+ .struct EXR + 4
+ESR: .int
+ .struct ESR + 4
+DEAR: .int
+ .struct DEAR + 4
+SRR0: .int
+ .struct SRR0 + 4
+SRR1: .int
+ .struct SRR1 + 4
+SRR2: .int
+ .struct SRR2 + 4
+SRR3: .int
+ .struct SRR3 + 4
+MCSR: .int
+ .struct MCSR + 4
+PID: .int
+ .struct PID + 4
+ZPR: .int
+ .struct ZPR + 4
+USPRG0: .int
+ .struct USPRG0 + 4
+SPRG0: .int
+ .struct SPRG0 + 4
+SPRG1: .int
+ .struct SPRG1 + 4
+SPRG2: .int
+ .struct SPRG2 + 4
+SPRG3: .int
+ .struct SPRG3 + 4
+SPRG4: .int
+ .struct SPRG4 + 4
+SPRG5: .int
+ .struct SPRG5 + 4
+SPRG6: .int
+ .struct SPRG6 + 4
+SPRG7: .int
+ .struct SPRG7 + 4
+TCR: .int
+ .struct TCR + 4
+TSR: .int
+ .struct TSR + 4
+DBCR0: .int
+ .struct DBCR0 + 4
+DBCR1: .int
+ .struct DBCR1 + 4
+DBSR: .int
+ .struct DBSR + 4
+OISR0: .int
+ .struct OISR0 + 4
+OISR1: .int
+ .struct OISR1 + 4
+OUDER0: .int
+ .struct OUDER0 + 4
+OUDER1: .int
+ .struct OUDER1 + 4
+OIMR0: .int
+ .struct OIMR0 + 4
+OIMR1: .int
+ .struct OIMR1 + 4
+OITR0: .int
+ .struct OITR0 + 4
+OITR1: .int
+ .struct OITR1 + 4
+OIEPR0: .int
+ .struct OIEPR0 + 4
+OIEPR1: .int
+ .struct OIEPR1 + 4
+OCIR0: .int
+ .struct OCIR0 + 4
+OCIR1: .int
+ .struct OCIR1 + 4
+ONISR0: .int
+ .struct ONISR0 + 4
+ONISR1: .int
+ .struct ONISR1 + 4
+OCISR0: .int
+ .struct OCISR0 + 4
+OCISR1: .int
+ .struct OCISR1 + 4
+ODHER0: .int
+ .struct ODHER0 + 4
+ODHER1: .int
+ .struct ODHER1 + 4
+FFDC_TIMEBASE: .int
+ .struct FFDC_TIMEBASE + 4
+OCC_BUILD_NAME: .byte
+ .struct OCC_BUILD_NAME + 16
+OCCLFIR: .long
+ .struct OCCLFIR + 8
+PBAFIR: .long
+ .struct PBAFIR + 8
+CORES_DECON: .int
+ .struct CORES_DECON + 4
+MAIN_THREAD_DUMP: .byte
+ .struct MAIN_THREAD_DUMP + 64
+CMD_THREAD_DUMP: .byte
+ .struct CMD_THREAD_DUMP + 64
+APP_THREAD_DUMP: .byte
+ .struct APP_THREAD_DUMP + 64
+DCOM_THREAD_DUMP: .byte
+ .struct DCOM_THREAD_DUMP + 64
+STACK_TRACE: .byte
+ .struct STACK_TRACE + 32
+FFDC_END: .int
+ .struct FFDC_END + 4
+END_OF_BUFFER: .byte
+
+# The FFDC buffer length is the byte count starting at the unused byte after
+# the data length and counting to the end of the FFDC buffer.
+ .set FFDC_BUFFER_LENGTH, (END_OF_BUFFER-UNUSED)
+ .set FFDC_BUFFER_LENGTH_HI, ((FFDC_BUFFER_LENGTH >> 8) & 0x00FF)
+ .set FFDC_BUFFER_LENGTH_LO, (FFDC_BUFFER_LENGTH & 0x00FF)
+
+/*****************************************************************************/
+// Functions
+/*****************************************************************************/
+# Switch back to text section, .struct switched us to the absolute section
+ .section ".text"
+
+# @sb012 __save_ffdc_regs rewritten, __ssx_checkpoint_panic_and_save_ffdc added
+# @sb012 __panic_checkpoint tweaked, __occ_checkpoint_panic_and_save_ffdc added
+
+# Function Specification ******************************************************
+#
+# Name: __occ_checkpoint_panic_and_save_ffdc
+#
+# Description: Entry point for OCC_HALT initiated FFDC collection.
+#
+# Parameters:
+# Inputs:
+# r3 - Contains the LR at the time the function the was called (panic address)
+# r4 - Contains the exception code to be stored with the FFDC
+#
+# Outputs:
+# None
+#
+# Notes:
+# GPR0-31 will be restored before the function returns.
+# This function assumes that r3 and r4 have been saved away in special
+# variables called __occ_panic_save_r3 and __occ_panic_save_r4.
+#
+# Registers r1, r2 and r13 are dedicated for use by the ABI so they cannot be
+# destroyed.
+# r1 - stack ptr
+# r2 - ro small data anchor
+# r13 - rw small data anchor
+#
+# Register USPRG0 is reserved for SSX and cannot be modified
+# Registers SPRG0-7 are reserved for interrupt handlers and cannot be modified
+#
+# Clear critical interrupts during this process so it can't be stopped once
+# it has begun. Be sure to save the MSR first.
+#
+# End Function Specification **************************************************
+
+.global_function __occ_checkpoint_panic_and_save_ffdc
+__occ_checkpoint_panic_and_save_ffdc:
+ # Save r5 for later so we can use the register now
+ _stwsd %r5, __occ_panic_save_r5
+
+ # Save the MSR for later so we can immediately disable all interrupts to
+ # prevent critical interrupts from interrupting the FFDC collection. This
+ # will also disable data MMU protection.
+ mfmsr %r5
+ _stwsd %r5, __occ_panic_save_msr
+ li %r5, 0
+ mtmsr %r5
+ isync
+ sync
+
+ # Some of the FFDC will now be saved to make r3 available for use and
+ # to prevent corruption of the link register before proceeding.
+ # Save the link register value that was present at the time the panic macro
+ # was used, this is passed in r3. Saving it now will also make r3 available
+ # for use.
+ _stwi %r3, %r5, LINK_REG
+
+ # We can use r3 now...
+ # Save dbcr0 @sb002
+ mfdbcr0 %r3
+ _stwi %r3, %r5, DBCR0
+
+ # Enable external debug mode and the trap debug event and freeze the timers,
+ # this will cause a debug event halting the 405 before execution of a trap
+ # instruction in the conditions are such that the trap occurs.
+ _liwa %r5, FFDC_DBCR0
+ mtdbcr0 %r5
+ isync
+
+ # Save the panic address (the address of the panic macro user), this is just
+ # the current link register. Save this now to the FFDC before continuing so
+ # we can call other functions if we need to.
+ mflr %r3
+ _stwi %r3, %r5, PANIC_ADDR
+
+ #
+ # r3 and r5 are now available for general use.
+ #
+
+ # Unlike the ssx version of this function, a panic code was not passed in.
+ # Instead, r4 contains the exception code. Set the panic code in the FFDC
+ # buffer to 0 to indicate this is an OCC HALT.
+ li %r3, 0
+ _stwi %r3, %r5, PANIC_CODE
+
+ # Put the exception code found in r4 in r3 and call __panic_checkpoint, this
+ # will also put the panic checkpoint into the FFDC.
+ mr %r3, %r4
+
+ # __panic_checkpoint needs r4 and r5 to be available and expects the
+ # exception code in r3, r3 will be destroyed.
+ bl __panic_checkpoint
+
+ # Call __save_ffdc_regs to save the remaining FFDC
+ bl __save_ffdc_regs
+
+ # Return to the caller
+ blr
+
+
+# Function Specification ******************************************************
+#
+# Name: __ssx_checkpoint_panic_and_save_ffdc
+#
+# Description: Entry point for SSX_PANIC initiated FFDC collection.
+#
+# Parameters:
+# Inputs:
+# r3 - Contains the LR at the time the panic macro was used
+# r4 - Contains the SSX panic code to be stored with the FFDC
+#
+# Outputs:
+# None
+#
+# Notes:
+# GPR0-31 will be restored before the function returns.
+# This function assumes that r3 and r4 have been saved away in special
+# variables called __occ_panic_save_r3 and __occ_panic_save_r4.
+#
+# Registers r1, r2 and r13 are dedicated for use by the ABI so they cannot be
+# destroyed.
+# r1 - stack ptr
+# r2 - ro small data anchor
+# r13 - rw small data anchor
+#
+# Register USPRG0 is reserved for SSX and cannot be modified
+# Registers SPRG0-7 are reserved for interrupt handlers and cannot be modified
+#
+# Clear critical interrupts during this process so it can't be stopped once
+# it has begun. Be sure to save the MSR first.
+#
+# End Function Specification **************************************************
+
+.global_function __ssx_checkpoint_panic_and_save_ffdc
+__ssx_checkpoint_panic_and_save_ffdc:
+ # Save r5 for later so we can use the register now
+ _stwsd %r5, __occ_panic_save_r5
+
+ # Save the MSR for later so we can immediately disable all interrupts to
+ # prevent critical interrupts from interrupting the FFDC collection. This
+ # will also disable data MMU protection.
+ mfmsr %r5
+ _stwsd %r5, __occ_panic_save_msr
+ li %r5, 0
+ mtmsr %r5
+ isync
+ sync
+
+ # Some of the FFDC will now be saved to make r3 and r4 available for use and
+ # to prevent corruption of the link register before proceeding.
+ # Save the panic code(r4) to make r4 available for use
+ _stwi %r4, %r5, PANIC_CODE
+
+ # Save the link register value that was present at the time the panic macro
+ # was used, this is passed in r3. Saving it now will also make r3 available
+ # for use.
+ _stwi %r3, %r5, LINK_REG
+
+ # We can use r3 now...
+ # Save dbcr0 @sb002
+ mfdbcr0 %r3
+ _stwi %r3, %r5, DBCR0
+
+ # Enable external debug mode and the trap debug event and freeze the timers,
+ # this will cause a debug event halting the 405 before execution of a trap
+ # instruction if the conditions are such that the trap occurs.
+ _liwa %r5, FFDC_DBCR0
+ mtdbcr0 %r5
+ isync
+
+ # Save the panic address (the address of the panic macro user), this is just
+ # the current link register. Save this now to the FFDC before continuing so
+ # we can call other functions if we need to.
+ mflr %r3
+ _stwi %r3, %r5, PANIC_ADDR
+
+ #
+ # r3, r4, and r5 are now available for general use.
+ #
+
+ # Put the exception code in r3 and call __panic_checkpoint, this
+ # will also put the panic checkpoint into the FFDC. __panic_checkpoint
+ # destroys r3.
+ _liwa %r3, FFDC_SSX_PANIC_EX_CODE
+
+ # __panic_checkpoint needs r4 and r5 to be available and expects the
+ # exception code in r3, r3 will be destroyed.
+ bl __panic_checkpoint
+
+ # Call __save_ffdc_regs to save the remaining FFDC
+ bl __save_ffdc_regs
+
+ # Return to the caller
+ blr
+
+
+// @sb002 New function to save a panic checkpoint and return code to the ffdc
+// header before writing the ffdc data packet and going to halt.
+# Function Specification ******************************************************
+#
+# Name: __panic_checkpoint
+#
+# Description: Write the 8 byte FFDC header specific to a panic.
+# __panic_checkpoint functions like __CHECKPOINT(0x00, 0x0F00, 0xE0).
+#
+# See ffdc header format in __save_ffdc_regs
+#
+# Parameters: r3 contains the exception code.
+#
+# Important: This function assumes that r3 contains the exception code and
+# r4 and r5 can be used and that their contents do not need to be restored upon
+# exit.
+#
+# Important: This function destroys r3.
+#
+# Important: Be sure to save the link register if needed before calling this
+# function!
+#
+# End Function Specification **************************************************
+
+.global_function __panic_checkpoint
+__panic_checkpoint:
+
+ # Header Start
+ # Sequence
+ # | Command
+ # | | Exception code
+ # | | | Length of data
+ # | | | | unused
+ # | | | | | Panic Checkpoint
+ # | | | | | |
+ # SSCCRRLL/LLxxKKKK
+ # |
+ # Header End
+ #
+ # Write the 8 byte FFDC header to 0000xx00/0000yyyy where xx is the
+ # exception passed in r3 and yyyy is the OCC specific panic checkpoint
+ # value.
+ #
+ # r3 contains the exception code and r4 and r5 are available for use
+ li %r4, 0x00
+ # Sequence, command, length, unused are all set to 0
+ # Exception was passed in r3
+ _stbi %r4, %r5, SEQUENCE
+ _stbi %r4, %r5, COMMAND
+ _stbi %r3, %r5, EXCEPTION
+ _stbi %r4, %r5, LENGTH_HI
+ _stbi %r4, %r5, LENGTH_LO
+ _stbi %r4, %r5, UNUSED
+ # Use the predefined OCC panic checkpoint
+ li %r4, FFDC_OCC_CHECKPOINT
+ _sthi %r4, %r5, CHECKPOINT
+
+ # Set r4 to point to beginning of response buffer, sync
+ # data access and request a data cache flush
+ _liw %r4, FFDC_BUFFER_ADDR
+ sync
+ dcbf 0, %r4
+
+ # Return to caller
+ blr
+
+
+# Function Specification ******************************************************
+#
+# Name: __save_ffdc_regs
+#
+# Description: saves registers to fsp response buffer in sram for debug. Only
+# the data area and length fields of the FSP response buffer are modified, the
+# FFDC header area (except for the length) is left unmodified.
+#
+# GPR0-31 will be restored before the function returns.
+#
+# Important: This function assumes that r3, r4, r5 and the MSR have been saved
+# in small data area special variables before being called. It also assumes
+# that r3, r4 and r5 are available for general use.
+#
+# Important: This function assumes that the panic return code, panic address,
+# panic checkpoint, panic code and the link register at the time the panic
+# macro was used have already been saved in the FFDC.
+#
+# Important: This function assumes that the MSR has been set to disable all
+# interrupts and that the DBCR0 register has been saved and then set to enable
+# external debug mode, the trap debug event and timer freeze.
+#
+# End Function Specification **************************************************
+
+# @sb002 updated to save new FFDC format
+.global_function __save_ffdc_regs
+__save_ffdc_regs:
+
+ # Start by writing out the predetermined length of the FFDC to the buffer.
+ _liwa %r3, FFDC_BUFFER_LENGTH_HI
+ _stbi %r3, %r4, LENGTH_HI
+ _liwa %r3, FFDC_BUFFER_LENGTH_LO
+ _stbi %r3, %r4, LENGTH_LO
+
+ # Start storing the remaining FFDC starting with the MSR, get the MSR value
+ # from the special variable in the small data area since we assume the MSR
+ # had been altered before this function was called.
+ _lwzsd %r3, __occ_panic_save_msr
+ _stwi %r3, %r4, MSR
+ # CR
+ mfcr %r3
+ _stwi %r3, %r4, CR
+ # CTR
+ mfctr %r3
+ _stwi %r3, %r4, CTR
+
+ # Save all the gprs
+ _stwi %r0, %r4, GPR0
+ _stwi %r1, %r4, GPR1
+ _stwi %r2, %r4, GPR2
+ # Restore r3 from the special variable in the small data area
+ _lwzsd %r3, __occ_panic_save_r3
+ _stwi %r3, %r4, GPR3
+ # Restore r4 from the special variable in the small data area
+ _lwzsd %r4, __occ_panic_save_r4
+ _stwi %r4, %r3, GPR4
+ # Restore r5 from the special variable in the small data area
+ _lwzsd %r5, __occ_panic_save_r5
+ _stwi %r5, %r3, GPR5
+ # Use r3 now as an auto incrementing pointer to multi store the remaining
+ # gprs
+ # GPR6-GPR31 uses a single instruction (does not update r3!)
+ stmw %r6, 4(%r3)
+
+ # Move SPRs into the FFDC buffer, not going to use a gpr multi store so we
+ # avoid altering r13, just brute force it for clarity
+ # @sb023 Change mfivpr to mfevpr
+ mfevpr %r5
+ _stwi %r5, %r3, EVPR
+ mfxer %r5
+ _stwi %r5, %r3, EXR
+ mfesr %r5
+ _stwi %r5, %r3, ESR
+ mfdear %r5
+ _stwi %r5, %r3, DEAR
+ mfsrr0 %r5
+ _stwi %r5, %r3, SRR0
+ mfsrr1 %r5
+ _stwi %r5, %r3, SRR1
+ # @sb023 Change mfcsrr0 to mfsrr2
+ mfsrr2 %r5
+ _stwi %r5, %r3, SRR2
+ # @sb023 Change mfcsrr1 to mfsrr3
+ mfsrr3 %r5
+ _stwi %r5, %r3, SRR3
+ mfmcsr %r5
+ _stwi %r5, %r3, MCSR
+ # @sb023 Change mfmcsrr0 to mfpid
+ mfpid %r5
+ _stwi %r5, %r3, PID
+ # @sb023 Change mfmcsrr0 to mfzpr
+ mfzpr %r5
+ _stwi %r5, %r3, ZPR
+ mfusprg0 %r5
+ _stwi %r5, %r3, USPRG0
+ mfsprg0 %r5
+ _stwi %r5, %r3, SPRG0
+ mfsprg1 %r5
+ _stwi %r5, %r3, SPRG1
+ mfsprg2 %r5
+ _stwi %r5, %r3, SPRG2
+ mfsprg3 %r5
+ _stwi %r5, %r3, SPRG3
+ mfsprg4 %r5
+ _stwi %r5, %r3, SPRG4
+ mfsprg5 %r5
+ _stwi %r5, %r3, SPRG5
+ mfsprg6 %r5
+ _stwi %r5, %r3, SPRG6
+ mfsprg7 %r5
+ _stwi %r5, %r3, SPRG7
+ mftcr %r5
+ _stwi %r5, %r3, TCR
+ mftsr %r5
+ _stwi %r5, %r3, TSR
+
+ # DBCR0 is saved by __ssx_checkpoint_panic_and_save_ffdc and
+ # __occ_checkpoint_panic_and_save_ffdc since those callers will overwrite
+ # DBCR0 before we get here.
+
+ # Save debug control reg 1, debug status reg, interrupt status regs and
+ # unconditional debug event registers
+ # Save dbcr1 @sb002
+ mfdbcr1 %r5
+ _stwi %r5, %r3, DBCR1
+ # Save dbsr @sb002
+ mfdbsr %r5
+ _stwi %r5, %r3, DBSR
+ # Save OISR0 @sb002
+ # >> @sb040 Use _lwzi instead of _liw
+ _lwzi %r5, %r5, OCB_OISR0
+ _stwi %r5, %r3, OISR0
+ # Save OISR1 @sb002
+ _lwzi %r5, %r5, OCB_OISR1
+ _stwi %r5, %r3, OISR1
+ # Save OUDER0 @sb002
+ _lwzi %r5, %r5, OCB_OUDER0
+ _stwi %r5, %r3, OUDER0
+ # Save OUDER1 @sb002
+ _lwzi %r5, %r5, OCB_OUDER1
+ _stwi %r5, %r3, OUDER1
+ # << @sb040
+ # Save OIMR0
+ _lwzi %r5, %r5, OCB_OIMR0
+ _stwi %r5, %r3, OIMR0
+ # Save OIMR1
+ _lwzi %r5, %r5, OCB_OIMR1
+ _stwi %r5, %r3, OIMR1
+ # Save OITR0
+ _lwzi %r5, %r5, OCB_OITR0
+ _stwi %r5, %r3, OITR0
+ # Save OITR1
+ _lwzi %r5, %r5, OCB_OITR1
+ _stwi %r5, %r3, OITR1
+ # Save OIEPR0
+ _lwzi %r5, %r5, OCB_OIEPR0
+ _stwi %r5, %r3, OIEPR0
+ # Save OIEPR1
+ _lwzi %r5, %r5, OCB_OIEPR1
+ _stwi %r5, %r3, OIEPR1
+ # Save OCIR0
+ _lwzi %r5, %r5, OCB_OCIR0
+ _stwi %r5, %r3, OCIR0
+ # Save OCIR1
+ _lwzi %r5, %r5, OCB_OCIR1
+ _stwi %r5, %r3, OCIR1
+ # Save ONISR0
+ _lwzi %r5, %r5, OCB_ONISR0
+ _stwi %r5, %r3, ONISR0
+ # Save ONISR1
+ _lwzi %r5, %r5, OCB_ONISR1
+ _stwi %r5, %r3, ONISR1
+ # Save OCISR0
+ _lwzi %r5, %r5, OCB_OCISR0
+ _stwi %r5, %r3, OCISR0
+ # Save OCISR1
+ _lwzi %r5, %r5, OCB_OCISR1
+ _stwi %r5, %r3, OCISR1
+ # Save ODHER0
+ _lwzi %r5, %r5, OCB_ODHER0
+ _stwi %r5, %r3, ODHER0
+ # Save ODHER1
+ _lwzi %r5, %r5, OCB_ODHER1
+ _stwi %r5, %r3, ODHER1
+ # Save ssx timebase
+ _lwzsd %r5, __ssx_timebase_frequency_mhz
+ _stwi %r5, %r3, FFDC_TIMEBASE
+
+ # Save the buildname
+ # memcpy(OCC_BUILD_NAME, G_occ_buildname, 16)
+ _liwa %r3, OCC_BUILD_NAME
+ _liw %r4, G_occ_buildname
+ li %r5, 16
+ bl memcpy
+
+ # SCOM the OCCLFIR, both words, into the buffer @sb002
+ # The _getsom call will destroy r0 and r3-r11, but we restore all gprs at
+ # the end before returning.
+ # Make the scom timeout = __ssx_timebase_frequency_mhz * 10 usecs
+ # Load timebase freq from small data area in r3
+ _lwzsd %r3, __ssx_timebase_frequency_mhz
+ # Load 10 to r4
+ li %r4, 10
+ # Load r5 and r6 with high/low order timeout (64 bits), set high to 0 since
+ # we know the timeout will be less than 32 bits in this case, approx. 10 *
+ # 600
+ li %r5, 0
+ # r6 gets the low 32 bits of the product of r3 and r4
+ mullw %r6, %r3, %r4
+ # Put scom address in r3
+ _liwa %r3, OCB_OCCLFIR
+ # Save the FFDC buffer ptr in r4, _getscom saves the scom output at r4
+ _liwa %r4, OCCLFIR
+ # Call _getscom (non-panic version with timeout), timeout is 10us
+ bl _getscom
+
+ # SCOM the PBAFIR into the buffer
+ _lwzsd %r3, __ssx_timebase_frequency_mhz
+ li %r4, 10
+ li %r5, 0
+ mullw %r6, %r3, %r4
+ _liwa %r3, PBA_FIR
+ _liwa %r4, PBAFIR
+ bl _getscom
+
+ # Save core (de)configuration
+ _liw %r5, PMC_CORE_DECONFIGURATION_REG
+ _stwi %r5, %r3, CORES_DECON
+
+ # Add the Main thread dump
+ _liw %r3, Main_thread
+ _liwa %r4, MAIN_THREAD_DUMP
+ bl ffdc_thread_dumper
+
+ # Add the Command handler thread dump
+ _liw %r3, Cmd_Hndl_thread
+ _liwa %r4, CMD_THREAD_DUMP
+ bl ffdc_thread_dumper
+
+ # Add the App thread dump
+ _liw %r3, App_thread
+ _liwa %r4, APP_THREAD_DUMP
+ bl ffdc_thread_dumper
+
+ # Add the DCOM thread dump
+ _liw %r3, Dcom_thread
+ _liwa %r4, DCOM_THREAD_DUMP
+ bl ffdc_thread_dumper
+
+ # Unwind the current stack
+ mr %r3, %r1
+ _liwa %r4, STACK_TRACE
+ li %r5, 8
+ bl ffdc_stack_unwind
+
+ # Mark the end of the buffer @sb002
+ _liwa %r5, FFDC_END_MARKER
+ _stwi %r5, %r3, FFDC_END
+
+ # Force a sync and flush the data cache
+ sync
+ _liwa %r5, FFDC_BUFFER_ADDR
+ li %r4, 0
+1: dcbf %r4, %r5
+ addi %r4, %r4, 32
+ cmpwi %r4, FFDC_BUFFER_LENGTH
+ blt 1b
+
+ # Restore GPR0-GPR31
+ _liwa %r0, GPR1
+ lmw %r1, 0(%r0)
+ _liwa %r0, GPR0
+ lwz %r0, 0(%r0)
+
+ # @sb002 Ensure preceding memory access synchronization
+ sync
+
+ # Return to caller
+ blr
+
+
+# ----------------
+# End of ll_ffdc.S
+# ----------------
diff --git a/src/occ/common.c b/src/occ/common.c
new file mode 100755
index 0000000..56501b9
--- /dev/null
+++ b/src/occ/common.c
@@ -0,0 +1,77 @@
+/******************************************************************************
+// @file common.c
+// @brief Standard Library Calls
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section common.c COMMON.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include <common.h>
+#include <trac_service_codes.h>
+#include <string.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: memcmp
+//
+// Description: Standard Library Calls
+// Need implemented, since we can't statically link in Open Source libs
+// These implementations aren't optimized, but allow the code to function
+// so we can test out the code port.
+//
+// Flow: FN=None
+//
+// End Function Specification
+//int memcmp ( const void * ptr1, const void * ptr2, size_t num )
+//{
+// return 0;
+//}
+
+
+
+
+
+
diff --git a/src/occ/dcom/dcom.c b/src/occ/dcom/dcom.c
new file mode 100755
index 0000000..40ae891
--- /dev/null
+++ b/src/occ/dcom/dcom.c
@@ -0,0 +1,902 @@
+/******************************************************************************
+// @file dcom.c
+// @brief OCC to OCC communication handler general functions
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dcom.c DCOM.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @00 tapiar 09/14/2011 Created
+ * @01 tapiar 10/14/2011 stage 2 updates
+ * @02 tapiar 11/14/2011 stage 3 updates
+ * @th009 thallet 01/31/2012 Changes to allow OCC Slave
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th022 thallet 10/08/2012 Dcom State/Mode passing
+ * @th025 857856 thallet 10/16/2012 Dcom State/Mode passing part 2
+ * @th034 879027 thallet 04/18/2013 Broadcast Critical Power Data over PBAX
+ * @th032 thallet 04/26/2013 Tuleta Bringup Fixes
+ * @th035 881654 thallet 05/06/2013 Tuleta Bringup Pstate Fixes
+ * @th036 881677 thallet 05/09/2013 New Poll command support
+ * @th037 thallet 05/28/2013 Murano DCM Numbering modification
+ * @th038 thallet 06/03/2013 Disable Centaur since it isn't ready on HW yet
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @th042 892056 thallet 07/19/2013 Send OCC to safe mode if first APSS GPE fails
+ * @th044 892742 thallet 07/24/2013 Added module ID
+ * @gs008 894661 gjsilva 08/08/2013 Initial support for DPS-FP mode
+ * @at018 896098 alvinwan 08/20/2013 Race condition between OCC Master and OCC Slaves in DATA_FORMAT_CLEAR_ALL
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm007 899876 milesg 09/23/2013 failure to go active on 8 OCC system.
+ * @rt001 901927 tapiar 10/02/2013 Fix src tags
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @at019 908390 alvinwan 12/05/2013 Disable DPS algorithms from running in Sapphire
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @gm018 910012 milesg 12/20/2013 autoslew not working on proc0
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @gm033 920448 milesg 03/26/2014 use getscom/putscom ffdc wrapper
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ * @gs034 929799 gjsilva 06/19/2014 Temporary fix for Brazos SMP wrap-mode
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOM_C
+#define _DCOM_C
+
+/** \defgroup OCC-OCC Communication
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <pgp_pmc.h>
+#include "pgp_pba.h"
+#include <rtls.h>
+#include <apss.h>
+#include <dcom.h>
+#include <dcom_service_codes.h>
+#include <occ_service_codes.h>
+#include <trac.h>
+#include <state.h>
+#include <proc_pstate.h>
+#include <amec_data.h>
+#include <amec_sys.h>
+#include "scom.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define PBAX_CONFIGURE_RCV_GROUP_MASK 0xff
+
+#define PBAX_BROADCAST_GROUP 0xFF
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+dcom_timing_t G_dcomTime; // @th032
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+DMA_BUFFER( dcom_slv_inbox_t G_dcom_slv_inbox_tx[MAX_OCCS]) = {{0}};
+DMA_BUFFER( dcom_slv_outbox_t G_dcom_slv_outbox_tx) = {0};
+
+DMA_BUFFER( dcom_slv_outbox_t G_dcom_slv_outbox_rx[MAX_OCCS]) = {{0}};
+DMA_BUFFER( dcom_slv_inbox_t G_dcom_slv_inbox_rx) = {0};
+
+// =========================================================
+// Master & Slave
+// =========================================================
+
+
+
+// PBAX Circ Queue buffers (where PBAX will put the data in OCC SRAM, so that OCC
+// can grab it.
+
+PBAX_CQ_READ_BUFFER(G_pbax_queue_rx1_buffer,NUM_ENTRIES_PBAX_QUEUE1);
+PBAX_CQ_READ_BUFFER(G_pbax_queue_rx0_buffer,NUM_ENTRIES_PBAX_QUEUE0);
+
+
+// Initialize Globals
+
+// Indicate that Slave OCC got an inbox from master
+bool G_slv_inbox_received = FALSE;
+
+// Counters to debug Master/Slave communication errors
+dcom_fail_count_t G_dcomSlvInboxCounter = {0};
+
+uint8_t G_occ_role = OCC_SLAVE;
+
+uint8_t G_dcm_occ_role = OCC_DCM_SLAVE;
+
+// PowerBus ID of this OCC. Contains ChipId & NodeId.
+pob_id_t G_pob_id = {0};
+
+// PBAX 'Target' Structure (Register Abstraction) that has the data needed for
+// a multicast operation.
+PbaxTarget G_pbax_multicast_target;
+
+// PBAX 'Target' Structure (Register Abstraction) that has the data needed for
+// a unicast operation from the OCC Slave to the OCC Master.
+PbaxTarget G_pbax_unicast_target;
+
+// Number of occ's that *should* be present
+uint8_t G_occ_num_present; // @th025
+
+// DCM Status from all Slaves
+proc_gpsm_dcm_sync_occfw_t G_dcm_sync_occfw_table[MAX_OCCS]; // @th010
+
+// master/slave event flags
+uint32_t G_master_event_flags = 0;
+uint32_t G_slave_event_flags = 0;
+uint32_t G_master_event_flags_ack = 0 ;
+uint32_t G_slave_event_flags_ack[MAX_OCCS] = {0};
+
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Helper function to determine if slave inboxes are valid
+bool isDcomSlvInboxValid(void){return (G_dcomSlvInboxCounter.currentFailCount ? FALSE : TRUE);}
+
+// Function Specification
+//
+// Name: dcom_initialize_roles
+//
+// Description: Initialize roles so we know if we are master or slave
+//
+// Flow: 09/13/11 FN=dcom_initialize_roles
+//
+// End Function Specification
+void dcom_initialize_roles(void)
+{
+ G_occ_role = OCC_SLAVE;
+
+ // Locals
+ int l_rc = 0;
+ tpc_gp0_t l_tp_gp0_read;
+
+ // Used as a debug tool to correlate time between OCCs & System Time
+ getscom_ffdc( TOD_VALUE_REG, &G_dcomTime.tod, NULL); //commits errors internally -- gm033
+ G_dcomTime.base = ssx_timebase_get(); // @th032
+
+ // Scom will timeout if it can't be read
+ l_rc = getscom_ffdc( TPC_GP0, (uint64_t *) &l_tp_gp0_read, NULL); //commits errors internally -- gm033
+
+ if( l_rc == 0 )
+ {
+ // @th037 - Added check for Murano ChipId swizzle
+ if(CFAM_CHIP_TYPE_MURANO == cfam_chip_type())
+ {
+ /// Murano has a different numbering scheme than you would
+ /// expect. It uses NodeId to denote DCM Id, and ChipId to
+ /// denote chip within the DCM. This is due to they way the
+ /// PowerBus works for routing.
+ ///
+ /// To fix this, we need to manipulate our internal copy of
+ /// ChipId/NodeId to match the way OCC FW uses them. We do this
+ /// multiplying the NodeId by 2 then adding chip Id to get a unique
+ /// new ChipId (Max Node = 3, Max Chip = 1 by design
+ ///
+ /// Note that Murano is not multi-drawer capable, so we can
+ /// fix our node id at 0
+
+#define MAX_MURANO_CHIP_IDS 2
+#define MAX_MURANO_NODE_IDS 4
+ if( (l_tp_gp0_read.fields.tc_chip_id_dc < MAX_MURANO_CHIP_IDS)
+ && (l_tp_gp0_read.fields.tc_node_id_dc < MAX_MURANO_NODE_IDS))
+ {
+ // Tuleta was mis-wired on the backplane, so we need to hack
+ // around this to figure out the module that we are on.
+ // The problem is that we don't really know
+ // at this point in code that we are running on a Tuleta vs
+ // an Orlena. Since Orlena is not yet a thing..we will
+ // assume tuleta.
+ // TODO: Revisit this once Orlena becomes a thing. In
+ // Orlena, it should be possible just to use the
+ // node_id that was read from the chip's GP0
+
+ // Translate between chip ID & Module Id for Tuleta
+ uint8_t tuleta_chip2module[] = {0,0,2,2,1,1,3,3};
+
+ G_pob_id.chip_id = (l_tp_gp0_read.fields.tc_chip_id_dc
+ + ( MAX_MURANO_CHIP_IDS * l_tp_gp0_read.fields.tc_node_id_dc));
+ G_pob_id.node_id = 0;
+
+ // The module id is only used by Power Measurements
+ G_pob_id.module_id = tuleta_chip2module[G_pob_id.chip_id];
+ //G_pob_id.module_id = (l_tp_gp0_read.fields.tc_node_id_dc & 0x03);
+ }
+ else
+ {
+ // Chip Ids don't make any sense
+ TRAC_ERR("Proc ChipId (%d) and/or NodeId (%d) don't make sense for Murano",
+ l_tp_gp0_read.fields.tc_chip_id_dc,
+ l_tp_gp0_read.fields.tc_node_id_dc);
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_INIT_ROLES
+ * @reasoncode INTERNAL_HW_FAILURE
+ * @userdata1 TP.GP0 SCOM (upper)
+ * @userdata2 TP.GP0 SCOM (lower)
+ * @userdata4 ERC_CHIP_IDS_INVALID
+ * @devdesc Failure determining OCC role
+ */
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_INIT_ROLES, //modId
+ INTERNAL_HW_FAILURE, //reasoncode // @nh001c
+ ERC_CHIP_IDS_INVALID, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_tp_gp0_read.words.high_order, //userdata1
+ l_tp_gp0_read.words.low_order //userdata2
+ );
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // commit log
+ commitErrl( &l_errl );
+ }
+ }
+ else
+ {
+ // Save off chip and node ids directly as read
+ G_pob_id.chip_id = l_tp_gp0_read.fields.tc_chip_id_dc;
+ G_pob_id.node_id = l_tp_gp0_read.fields.tc_node_id_dc;
+
+ // Check if special SMP wrap mode is turned on. In this mode, a
+ // single drawer is configured as two virtual nodes. However, OCC
+ // still needs to treat it as a single node.
+ // As a temporary solution, HWSV is going to set bit 17 of the GP0
+ // register to inform OCC that SMP wrap is on.
+
+#define SMP_WRAP_MASK 0x00004000
+ if(l_tp_gp0_read.words.high_order & SMP_WRAP_MASK)
+ {
+ TRAC_INFO("dcom_initialize_roles: Temporary fix - SMP wrap mode has been detected");
+
+ // This is a single drawer
+ G_pob_id.node_id = 0;
+
+ // Translate the NodeId and ChipId into the correct internal
+ // representation for OCC to work.
+ if(l_tp_gp0_read.fields.tc_node_id_dc == 0)
+ {
+ G_pob_id.chip_id = 2 * l_tp_gp0_read.fields.tc_chip_id_dc;
+ }
+ else if(l_tp_gp0_read.fields.tc_node_id_dc == 1)
+ {
+ G_pob_id.chip_id = (l_tp_gp0_read.fields.tc_chip_id_dc) ? 1 : 3;
+ }
+ }
+
+ // Save off low 2 bits of chip ID as module ID. Won't be
+ // more than 4 on venice since it is SCMs.
+ G_pob_id.module_id = (G_pob_id.chip_id & 0x03);
+ }
+
+ // Always start as OCC Slave
+ G_occ_role = OCC_SLAVE; // @th022a
+ rtl_set_run_mask(RTL_FLAG_NOTMSTR); // @th022a
+
+ // Save off OCC role inside DCM chip
+ if(gpsm_dcm_slave_p())
+ {
+ G_dcm_occ_role = OCC_DCM_SLAVE;
+ }
+ else
+ {
+ G_dcm_occ_role = OCC_DCM_MASTER;
+ }
+
+ TRAC_IMP("Proc ChipId=%d, NodeId=%d, isDcm=%d, isDcmMaster=%d, ChipEC=0x%08x",
+ G_pob_id.chip_id,
+ G_pob_id.node_id,
+ gpsm_dcm_mode_p(),
+ !gpsm_dcm_slave_p(),
+ cfam_id() ); // @th035
+ }
+ else
+ {
+ //get scom failure
+ TRAC_ERR("getscom failure rc[0x%08X]", -l_rc );
+
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_INIT_ROLES
+ * @reasoncode INTERNAL_HW_FAILURE
+ * @userdata1 getscom failure rc
+ * @userdata4 ERC_GETSCOM_FAILURE
+ * @devdesc Failure determining OCC role
+ */
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_INIT_ROLES, //modId
+ INTERNAL_HW_FAILURE, //reasoncode // @nh001c
+ ERC_GETSCOM_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ 0 //userdata2
+ );
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // commit log
+ commitErrl( &l_errl );
+
+ // TODO request a reset of OCC
+ // we are toast without this working correctly
+ }
+
+ // Set the initial presence mask, and count the number of occ's present
+ G_sysConfigData.is_occ_present |= (0x01 << G_pob_id.chip_id); // @th036
+ G_occ_num_present = __builtin_popcount(G_sysConfigData.is_occ_present); // @th025
+
+ // Initialize DCOM Thread Sem
+ ssx_semaphore_create( &G_dcomThreadWakeupSem, // Semaphore
+ 1, // Initial Count
+ 0); // No Max Count @th035
+
+}
+
+
+// Function Specification
+//
+// Name: dcom_initialize_pbax_queues
+//
+// Description: Initialize the PBAX Queues for sending doorbells
+//
+// Flow: 09/13/11 FN=dcom_initialize_pbax_queues
+//
+// End Function Specification
+void dcom_initialize_pbax_queues(void)
+{
+ pbax_id_t l_pbaxid = dcom_pbusid2pbaxid(G_pob_id);
+
+ //SSX return codes
+ int l_rc = 0;
+
+ do
+ {
+ pbax_send_disable();
+
+ // check if conversion has valid information
+ if (( l_pbaxid.chip_id > MAX_PBAX_CHIP_ID ) || //@gm007
+ ( l_pbaxid.node_id == INVALID_NODE_ID ))
+ {
+ TRAC_ERR("Error converting pbusids to pbaxids. chip_id[0x%08x], node_id[0x%08x]",
+ l_pbaxid.chip_id, l_pbaxid.node_id);
+ l_rc = -1; //force error to be logged below. //@gm007
+ break;
+ }
+
+ l_rc = pbax_configure(G_occ_role, // master
+ l_pbaxid.node_id, // node id
+ l_pbaxid.chip_id, // chipd id
+ PBAX_CONFIGURE_RCV_GROUP_MASK); // group_mask
+
+ if(l_rc != 0)
+ {
+ TRAC_ERR("Error configuring the pbax rc[%x]",l_rc);
+ break;
+ }
+
+ //enabled pbax send does not return errors
+ pbax_send_enable();
+
+ if(G_occ_role == OCC_SLAVE)
+ {
+ // create pbax rx queue 1
+ l_rc = pbax_queue_create( &G_pbax_read_queue[1], //queue
+ ASYNC_ENGINE_PBAX_PUSH1, //engine
+ G_pbax_queue_rx1_buffer, //cq base
+ NUM_ENTRIES_PBAX_QUEUE1, //cq entries
+ PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE //protocol
+ );
+
+ if(l_rc != 0)
+ {
+ TRAC_ERR("Error creating pbax queue 1 rc[%x]",l_rc);
+ break;
+ }
+
+ // create pbax rx queue o
+ l_rc = pbax_queue_create( &G_pbax_read_queue[0], //queue
+ ASYNC_ENGINE_PBAX_PUSH0, //engine
+ G_pbax_queue_rx0_buffer, //cq base
+ NUM_ENTRIES_PBAX_QUEUE0, //cq entries
+ PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE //protocol
+ );
+
+ if(l_rc != 0)
+ {
+ TRAC_ERR("Error creating pbax queue 0 rc[%x]",l_rc);
+ break;
+ }
+
+ // enable the read 1 queue
+ l_rc = pbax_queue_enable(&G_pbax_read_queue[1]);
+
+ if(l_rc != 0)
+ {
+ TRAC_ERR("Error enabling queue 1 rc[%x]",l_rc);
+ break;
+ }
+
+ /// Don't enable the read 0 queue until we are ready
+ /// to listen
+ //l_rc = pbax_queue_enable(&G_pbax_read_queue[0]); // @th034
+ //if(l_rc != 0)
+ //{
+ // TRAC_ERR("Error enabling queue 0 rc[%x]",l_rc);
+ // break;
+ //}
+
+ }
+
+ if(G_occ_role == OCC_MASTER)
+ {
+ // TODO: Change this to PBAX_GROUP for Venice
+ l_rc = pbax_target_create( &G_pbax_multicast_target, // target,
+ PBAX_BROADCAST, // type
+ PBAX_SYSTEM, // scope TODO @th038
+ 0, //&pbax_read0_queue // queue
+ l_pbaxid.node_id, // node
+ PBAX_BROADCAST_GROUP); // chip_or_group
+
+ if(l_rc != 0)
+ {
+ TRAC_ERR("Error creating pbax target for master TX operations SSXrc[%x]",l_rc);
+ break;
+ }
+
+ }
+
+ }while(0);
+
+ if(l_rc)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_INIT_PBAX_QUEUES
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 SSX RC
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure initializing the PBAX queues
+ */
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_INIT_PBAX_QUEUES, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit log and request reset -- @gm007
+ REQUEST_RESET(l_errl);
+ }
+}
+
+
+// Function Specification
+//
+// Name: dcom_pbusid2pbaxid
+//
+// Description: translate between powerbus ID and pbax ID
+//
+// Flow: 08/23/11 FN=dcom_pbusid2pbaxid
+//
+// End Function Specification
+pbax_id_t dcom_pbusid2pbaxid(pob_id_t i_pobid)
+{
+ pbax_id_t l_pbax_id_t = {0};
+
+ // check if chip id and nod id are valid
+ if((i_pobid.chip_id < MAX_NUM_OCC)
+ && (i_pobid.node_id < MAX_NUM_NODES))
+ {
+ l_pbax_id_t.chip_id = G_sysConfigData.pob2pbax_chip[i_pobid.chip_id];
+ l_pbax_id_t.node_id = G_sysConfigData.pob2pbax_node[i_pobid.node_id];
+ }
+ else
+ {
+ // invalid data found
+
+ l_pbax_id_t.chip_id = MAX_PBAX_CHIP_ID;
+ l_pbax_id_t.node_id = INVALID_NODE_ID;
+
+ TRAC_ERR("Invalid Powerbus ID, could NOT convert chip id[%x] and node id[%x] to PBAX id",
+ i_pobid.chip_id,i_pobid.node_id);
+ }
+
+ return l_pbax_id_t;
+}
+
+// Function Specification
+//
+// Name: dcom_error_check
+//
+// Description: keep track of failure counts
+//
+// Flow: 10/24/11 FN=dcom_error_check
+//
+// End Function Specification
+void dcom_error_check( const dcom_error_type_t i_error_type, const bool i_clear_error, const uint32_t i_orc, const uint32_t i_orc_ext) // @nh001c
+{
+ static uint16_t L_rx_slv_outbox_fail_count = 0;
+ uint16_t l_modId = 0; // @nh001a
+ uint16_t *l_count_ptr = NULL;
+
+ if ( i_error_type == SLAVE_INBOX )
+ {
+ l_count_ptr = &G_dcomSlvInboxCounter.currentFailCount;
+ l_modId = DCOM_MID_TASK_RX_SLV_INBOX; // @nh001a
+ }
+ // if the i_error_type == SLAVE_OUTBOX then set the outbox count
+ else
+ {
+ l_count_ptr = &L_rx_slv_outbox_fail_count;
+ l_modId = DCOM_MID_TASK_RX_SLV_OUTBOX; // @nh001a
+ }
+
+ if ( i_clear_error )
+ {
+ *l_count_ptr = 0;
+ }
+ else
+ {
+ (*l_count_ptr)++;
+
+ if ( *l_count_ptr == DCOM_250us_GAP )
+ {
+ // trace an imp trace log
+ TRAC_IMP("l_count_ptr[%d], L_outbox[%d], L_inbox[%d]",
+ *l_count_ptr,
+ L_rx_slv_outbox_fail_count,
+ G_dcomSlvInboxCounter.currentFailCount );
+ }
+ else if ( *l_count_ptr == DCOM_4MS_GAP )
+ {
+ // create and commit error log
+
+ // NOTE: SRC tags are NOT needed here, they are
+ // taken care of by the caller
+ errlHndl_t l_errl = createErrl(
+ l_modId, //modId // @nh001c
+ i_orc, //reasoncode
+ i_orc_ext, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ *l_count_ptr, //userdata1
+ 0 //userdata2
+ );
+
+ // commit log
+ commitErrl( &l_errl );
+
+ // call request nominal macro to change state
+ REQUEST_NOMINAL();
+ }
+ else if ( *l_count_ptr == DCOM_1S_GAP )
+ {
+ // create and commit error log
+
+ // NOTE: SRC tags are NOT needed here, they are
+ // taken care of by the caller
+ errlHndl_t l_errl = createErrl(
+ l_modId, //modId // @nh001c
+ i_orc, //reasoncode
+ i_orc_ext, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ *l_count_ptr, //userdata1
+ 0 //userdata2
+ );
+
+ // commit log
+ // call request reset macro
+ REQUEST_RESET(l_errl); //@gm006
+ }
+ }
+}
+
+
+// Function Specification
+//
+// Name: dcom_build_dcm_sync_msg
+//
+// Description: Copy messages from DCM Master (OCC Slave) to
+// DCM Slave (also OCC Slave) and vice versa
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+// @th010 - Added function dcom_build_dcm_sync_msg()
+void dcom_build_dcm_sync_msg(const dcom_error_type_t i_which_msg)
+{
+ // If the OCC Master isn't a DCM, no one else is a DCM either, so
+ // no need to bother sending these messages back & forth.
+ if(proc_is_dcm())
+ {
+ if ( i_which_msg == SLAVE_INBOX )
+ {
+ uint32_t l_slv_idx = 0;
+ for(l_slv_idx = 0; l_slv_idx < MAX_OCCS; l_slv_idx++) // @th035
+ {
+ // Populate G_dcm_sync_occfw_table with the data from all OCC Slaves
+ G_dcm_sync_occfw_table[l_slv_idx] = G_dcom_slv_outbox_rx[l_slv_idx].dcm_sync;
+ }
+
+ // DCM are always in even/odd numbered pairs sequentially as
+ // DCM master = even number[0,2,4,6] DCM Slave = odd number [1,3,5,7]
+ // with DCM pairs being [0,1], [2,3], [4,5], [6,7]
+ // so we can do this simple swizzle here and not need a table to
+ // do the conversion.
+ for(l_slv_idx = 0; l_slv_idx < MAX_OCCS; l_slv_idx+=2) // @th035
+ {
+ G_dcom_slv_inbox_tx[l_slv_idx].dcm_sync = G_dcm_sync_occfw_table[l_slv_idx+1];
+ G_dcom_slv_inbox_tx[l_slv_idx+1].dcm_sync = G_dcm_sync_occfw_table[l_slv_idx];
+ }
+ }
+ else if ( i_which_msg == SLAVE_OUTBOX )
+ {
+ G_dcom_slv_outbox_tx.dcm_sync = proc_gpsm_dcm_sync_get_state();
+ }
+ }
+}
+
+
+// Function Specification
+//
+// Name: dcom_build_occfw_msg
+//
+// Description: Copy data into occ fw msg portion
+//
+// Flow: 10/24/11 FN=dcom_build_occfw_msg
+//
+// End Function Specification
+void dcom_build_occfw_msg( const dcom_error_type_t i_which_msg )
+{
+ if ( i_which_msg == SLAVE_INBOX )
+ {
+ uint32_t l_slv_idx = 0;
+
+ // for each occ slave
+ for(; l_slv_idx < MAX_OCCS; l_slv_idx++)
+ {
+ G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox[0] = G_occ_external_req_state;
+ G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox[1] = G_occ_external_req_mode;
+
+ G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox[2] = G_master_event_flags;
+ G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox[3] = G_slave_event_flags_ack[l_slv_idx];
+
+ G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox[4] = 0;
+ }
+ }
+ else if ( i_which_msg == SLAVE_OUTBOX )
+ {
+ G_dcom_slv_outbox_tx.occ_fw_mailbox[0] = CURRENT_STATE();
+
+ // @at019a - start
+ if(G_sysConfigData.system_type.kvm )
+ {
+ G_dcom_slv_outbox_tx.occ_fw_mailbox[1] = G_occ_external_req_mode_kvm;
+ }
+ else
+ {
+ G_dcom_slv_outbox_tx.occ_fw_mailbox[1] = CURRENT_MODE();
+ }
+ // @at019a - end
+
+ G_dcom_slv_outbox_tx.occ_fw_mailbox[2] = G_master_event_flags_ack;
+ G_dcom_slv_outbox_tx.occ_fw_mailbox[3] = G_slave_event_flags;
+
+ G_dcom_slv_outbox_tx.occ_fw_mailbox[4] = SMGR_validate_get_valid_states();
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: task_dcom_parse_occfwmsg
+//
+// Description: Purpose of this task is to handle and acknowledge
+// fw messages passed from Master to Slave and vice versa.
+//
+// Flow: 10-24-11 FN=task_dcom_parse_occfwmsg
+//
+// End Function Specification
+void task_dcom_parse_occfwmsg(task_t *i_self)
+{
+ if(G_occ_role == OCC_MASTER)
+ {
+ //local slave index counter
+ uint32_t l_slv_idx = 0;
+
+ //loop and collect occ data for each slave occ
+ for(; l_slv_idx < MAX_OCCS; l_slv_idx++)
+ {
+ // verify all slave are in correct state and mode
+ G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[0] = CURRENT_STATE();
+ // @at019a - start
+ if(G_sysConfigData.system_type.kvm )
+ {
+ G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[1] = G_occ_external_req_mode_kvm;
+ }
+ else
+ {
+ G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[1] = CURRENT_MODE();
+ }
+ // @at019a - end
+
+
+ // acknowledge all slave event flags
+ G_slave_event_flags_ack[l_slv_idx] = G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[3];
+
+ //Clear master event flags if slave has acknowledged them and the event has cleared
+ G_master_event_flags &= ~G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[2];
+
+ }
+
+ }//end master role check
+
+ // check if master has changed state and mode and update if changed
+ // so that we can handle it in a thread.
+ if( (G_occ_master_state != G_dcom_slv_inbox_rx.occ_fw_mailbox[0])
+ || (G_occ_master_mode != G_dcom_slv_inbox_rx.occ_fw_mailbox[1]) ) // @th025
+ {
+ if( ! isSafeStateRequested() ) // @th042
+ {
+ G_occ_master_state = G_dcom_slv_inbox_rx.occ_fw_mailbox[0];
+ G_occ_master_mode = G_dcom_slv_inbox_rx.occ_fw_mailbox[1];
+ ssx_semaphore_post(&G_dcomThreadWakeupSem); // @th025
+ }
+ }
+
+ // If we are master, we don't want to update based on
+ // the data sent to us, because it corrupts the 'golden' data
+ // If we are in standby, we don't want to update because
+ // the data may not have been set up yet, and would be set to zero.
+ if(OCC_MASTER != G_occ_role ) //gm037
+ {
+ // Update the system mode frequencies if they have changed
+ int l_mode = 0;
+ bool l_change = FALSE;
+ bool l_all_zero = TRUE;
+
+ // @at018c - start
+ // Check if all values are zero
+ for(l_mode = 0; l_mode<OCC_MODE_COUNT; l_mode++)
+ {
+ if( (0 != G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode]) )
+ {
+ l_all_zero = FALSE;
+ break;
+ }
+ }
+
+ extern data_cnfg_t * G_data_cnfg;
+ if( l_all_zero == FALSE)
+ {
+ for(l_mode =0; l_mode<OCC_MODE_COUNT; l_mode++)
+ {
+ // Don't trust a frequency of 0x0000
+ if( (0 != G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode]) )
+ {
+ if(G_sysConfigData.sys_mode_freq.table[l_mode]
+ != G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode])
+ {
+ TRAC_INFO("New Frequency for Mode %d: Old: %d MHz -> New: %d MHz",l_mode,
+ G_sysConfigData.sys_mode_freq.table[l_mode],
+ G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode]);
+
+ // Update mode frequency
+ G_sysConfigData.sys_mode_freq.table[l_mode] =
+ G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode];
+
+ l_change = TRUE;
+ }
+ }
+ }
+
+ if(l_change)
+ {
+ // Update "update count" for debug purposes
+ G_sysConfigData.sys_mode_freq.update_count =
+ G_dcom_slv_inbox_rx.sys_mode_freq.update_count;
+
+ // Change Data Request Mask to indicate we got this data
+ extern data_cnfg_t * G_data_cnfg;
+ G_data_cnfg->data_mask |= DATA_MASK_FREQ_PRESENT;
+
+ // Notify AMEC that the frequencies have changed
+ AMEC_data_change(DATA_MASK_FREQ_PRESENT);
+ }
+ }
+ else
+ {
+ // Clear Data Request Mask and data
+ G_data_cnfg->data_mask &= (~DATA_MASK_FREQ_PRESENT);
+ memset(&G_sysConfigData.sys_mode_freq.table[0], 0, sizeof(G_sysConfigData.sys_mode_freq.table));
+ }
+ // @at018c - end
+ }
+
+ // Copy mnfg parameters into g_amec structure -- gm018
+ g_amec->foverride_enable = G_dcom_slv_inbox_rx.foverride_enable;
+ g_amec->foverride = G_dcom_slv_inbox_rx.foverride;
+
+ // Copy IPS parameters sent by Master OCC
+ g_amec->slv_ips_freq_request = G_dcom_slv_inbox_rx.ips_freq_request;
+
+ // Copy DPS tunable parameters sent by Master OCC if required
+ if(G_dcom_slv_inbox_rx.tunable_param_overwrite)
+ {
+ AMEC_part_overwrite_dps_parameters();
+
+ if(G_dcom_slv_inbox_rx.tunable_param_overwrite == 1)
+ {
+ g_amec->slv_dps_param_overwrite = TRUE;
+ }
+ else
+ {
+ g_amec->slv_dps_param_overwrite = FALSE;
+ }
+ }
+
+ // Copy soft frequency boundaries sent by Master OCC
+ g_amec->part_config.part_list[0].soft_fmin = G_dcom_slv_inbox_rx.soft_fmin;
+ g_amec->part_config.part_list[0].soft_fmax = G_dcom_slv_inbox_rx.soft_fmax;
+
+ // Update DCM Sync var that will be used in thread
+ proc_gpsm_dcm_sync_update_from_mbox(&G_dcom_slv_inbox_rx.dcm_sync); // @th032
+
+ // acknowledge all masters event flags
+ G_master_event_flags_ack = G_dcom_slv_inbox_rx.occ_fw_mailbox[2];
+
+ // clear slave event flags if master has acknowledged them and the event has cleared
+ G_slave_event_flags = (G_slave_event_flags & (~(G_dcom_slv_inbox_rx.occ_fw_mailbox[3])));
+}
+
+
+#endif //_DCOM_C
+
diff --git a/src/occ/dcom/dcom.h b/src/occ/dcom/dcom.h
new file mode 100755
index 0000000..d296c2c
--- /dev/null
+++ b/src/occ/dcom/dcom.h
@@ -0,0 +1,585 @@
+/******************************************************************************
+// @file dcom.h
+// @brief OCC to OCC communication handler
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dcom.h DCOM.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @00 tapiar 09/14/2011 Created
+ * @01 tapiar 10/04/2011 Stage 2 updates
+ * @th002 thallet 11/01/2011 Misc Changes for Nov 1st Milestone
+ * @th005 thallet 11/23/2011 Sensor Initialization Changes
+ * @02 tapiar 11/14/2011 stage 3 updates
+ * @rc001 rickylie 01/02/2012 Moved debug trace defines to trac.h
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th022 thallet 10/08/2012 Removed initSection attribute
+ * @th025 857856 thallet 10/16/2012 Dcom State/Mode passing part 2
+ * @th034 879027 thallet 04/18/2013 Broadcast Critical Power Data over PBAX
+ * @th032 thallet 04/16/2013 Tuleta HW Bringup
+ * @th036 881677 thallet 04/16/2013 New Poll Command Support
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @gs007 888247 gjsilva 06/19/2013 OCC mnfg support for frequency distribution
+ * @th044 892742 thallet 07/24/2013 Added module ID
+ * @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+ * @rt001 897459 tapiar 08/19/2013 add active node pcap field to doorbell structure
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @gs016 905781 gjsilva 11/12/2013 Fix for Master->Slave doorbell loss of synchronization
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @rt004 908817 tapiar 12/11/2013 Expland slave outbox doorbell to include pcap valid
+ * field to be used by master when checking for pcap mismatches
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @mw626 mware 01/28/2013 Changed freqa250us to be freqa2ms.
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOM_H
+#define _DCOM_H
+
+/** \defgroup OCC-OCC Communication
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <common_types.h>
+#include <occ_service_codes.h>
+#include <occ_sys_config.h>
+#include <rtls.h>
+#include <apss.h>
+#include <proc_pstate.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// Max Centaur Throttles
+#define MAX_CENTAUR_THROTTLES 8
+
+// Max Interleave Group Throttles
+#define MAX_MEM_INTERLEAVE_GROUP_THROTTLES 8
+
+// OCC roles
+#define OCC_SLAVE 0
+#define OCC_MASTER 1
+#define OCC_BACKUP_MASTER 2
+
+// OCC roles inside a DCM socket
+#define OCC_DCM_SLAVE 0
+#define OCC_DCM_MASTER 1
+
+// OCC Master to Slave Messages (inbox ping/pong) - Need to go over BAR3
+#define ADDR_SLAVE_INBOX_MAIN_MEM_PING 0x30000000 // @th032
+#define ADDR_SLAVE_INBOX_MAIN_MEM_PONG 0x30000800 // @th032
+#define NUM_BYTES_IN_SLAVE_INBOX 256
+
+// Magic Number used to denote the end of Master->Slave Broadcast packets
+#define PBAX_MAGIC_NUMBER_32B 0x00123181 // @th034
+// Magic Number used to denote the start of Master->Slave Broadcast packets
+#define PBAX_MAGIC_NUMBER2_32B 0x00474A53
+
+#define MAX_PBAX_CHIP_ID 7
+#define INVALID_NODE_ID 7
+
+// OCC Slave to Master Messages (inbox ping/pong) - Need to go over BAR3
+#define ADDR_SLAVE_OUTBOX_MAIN_MEM_PING 0x30001000 // @th032
+#define ADDR_SLAVE_OUTBOX_MAIN_MEM_PONG 0x30003000 // @th032
+#define NUM_BYTES_IN_SLAVE_OUTBOX 1024
+
+// GP REG0
+#define TP_BRIDGE_GP_REG0 0x01000000
+
+// GP0 Read Chip Id Mask & Offset
+#define GP0_READ_CHIP_ID_MASK 0x00000000001C0000
+#define CHIP_ID_MASK_OFFSET 18
+
+// GP0 Read Node Id Mask & Offset
+#define GP0_READ_NODE_ID_MASK 0x0000000000E00000
+#define NODE_ID_MASK_OFFSET 21
+
+// What should these sizes be?
+#define NUM_ENTRIES_PBAX_QUEUE0 32 // @th034
+#define NUM_ENTRIES_PBAX_QUEUE1 16 // @th034
+
+// Wait for defines number of retries for task
+#define MAX_WAIT_FOR_SLAVES 400
+#define MAX_WAIT_FOR_MASTER 400
+
+// general defines
+#define TOD_SIZE 6
+#define NUM_TOD_SENSORS 3
+#define SLV_INBOX_RSV_SIZE 88
+#define SLV_MAILBOX_SIZE 32
+#define SLV_OUTBOX_RSV_SIZE 758
+#define DOORBELL_RSV_SIZE 1 // @rt001c
+
+#define DCOM_250us_GAP 1
+#define DCOM_4MS_GAP 8
+#define DCOM_1S_GAP 4000
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+// POB Id structure
+typedef struct
+{
+ uint8_t module_id :2;
+ uint8_t node_id :3;
+ uint8_t chip_id :3;
+} pob_id_t;
+
+
+// TODO may change in the future
+// for now pbax structure is same as pob id structure
+typedef pob_id_t pbax_id_t;
+
+
+// SLAVE INBOX structure
+typedef struct
+{
+ // Packet Type & Sequence Information
+ uint8_t seq; // [0]
+ uint8_t version; // [1]
+
+ // From APSS Power Measurement
+ uint16_t adc[MAX_APSS_ADC_CHANNELS]; // [2] - 32 bytes
+ uint16_t gpio[MAX_APSS_GPIO_PORTS]; // [34] - 4 bytes
+ uint16_t ambient_temp; // [38] - 2 bytes
+ uint16_t altitude; // [40] - 2 bytes
+ uint8_t tod[ TOD_SIZE ]; // [42] - 6 bytes
+
+ // AMEC Actuators
+ uint16_t freq250usp0cy[MAX_CORES]; // [48] - 24 bytes
+ uint16_t memsp2msP0MxCyPz[MAX_CENTAUR_THROTTLES]; // [72] - 16 bytes
+ uint16_t memsp2msP0IGx[MAX_MEM_INTERLEAVE_GROUP_THROTTLES]; // [88] - 16 bytes
+
+ // Manufacturing parameters
+ uint16_t foverride; // [104] - 2 bytes
+ uint8_t foverride_enable; // [106] - 1 byte
+ uint8_t emulate_oversub; // [107] - 1 byte
+
+ // Idle Power Saver parameters
+ uint16_t ips_freq_request; // [108] - 2 bytes
+
+ // DPS Tunable Parameters
+ uint16_t alpha_up; // [110] - 2 bytes
+ uint16_t alpha_down; // [112] - 2 bytes
+ uint16_t sample_count_util; // [114] - 2 bytes
+ uint16_t step_up; // [116] - 2 bytes
+ uint16_t step_down; // [118] - 2 bytes
+ uint16_t epsilon_perc; // [120] - 2 bytes
+ uint16_t tlutil; // [122] - 2 bytes
+ uint8_t tunable_param_overwrite; // [124] - 1 byte
+
+ // Soft frequency boundaries
+ uint16_t soft_fmin; // [125] - 2 bytes
+ uint8_t pad; // [127] - 1 bytes
+ uint16_t soft_fmax; // [128] - 2 bytes
+
+
+ // Reserved Bytes
+ union
+ {
+ struct
+ {
+ uint32_t counter; // @th002
+ freqConfig_t sys_mode_freq; // @th040
+ uint8_t tb_record;
+ };
+ uint8_t reserved[ SLV_INBOX_RSV_SIZE ]; // [130] - 88 bytes
+ };
+
+ // GPSM DCM Synchronization
+ proc_gpsm_dcm_sync_occfw_t dcm_sync; // @th010 // [220] - 4 bytes
+
+ // General Firmware Message Passing
+ uint8_t occ_fw_mailbox[ SLV_MAILBOX_SIZE ]; // [224] - 32 bytes
+
+} dcom_slv_inbox_t __attribute ((aligned (128)));
+
+
+
+// SLAVE OUTBOX structure
+typedef struct __attribute__ ((packed))
+{
+ // Packet Type & Sequence Information
+ uint8_t seq; // [0]
+ uint8_t version; // [1]
+
+ // Mini-sensors
+ uint16_t freqa2msp0; // [2] // @mw626
+ uint16_t ips2msp0cy[MAX_CORES]; // [4]
+ uint16_t mcpifd2msp0cy[MAX_CORES]; // [28]
+ uint16_t mcpifi2msp0cy[MAX_CORES]; // [52]
+ uint16_t memsp2msp0mx[MAX_NUM_MEM_CONTROLLERS]; // [76]
+ uint16_t pwr250usp0; // [92]
+ uint16_t pwr250usmemp0; // [94]
+ uint16_t sleepcnt2msp0; // [96]
+ uint16_t winkcnt2msp0; // [98]
+ uint16_t temp2msp0; // [100]
+ uint16_t temp2msp0peak; // [102]
+ uint16_t util2msp0cy[MAX_CORES]; // [104]
+ uint16_t vrfan250usmem; // [128]
+ uint16_t vrfan250usproc; // [130]
+ uint16_t mrd2msp0mx[MAX_NUM_MEM_CONTROLLERS]; // [132]
+ uint16_t mwr2msp0mx[MAX_NUM_MEM_CONTROLLERS]; // [148]
+ uint16_t pwrpx250usp0cy[MAX_CORES]; // [164]
+ uint16_t todclock[NUM_TOD_SENSORS]; // [188]
+ uint16_t temp2mscent; // [194] // @jh005a
+ uint16_t temp2msdimm; // [196] // @jh005a
+ uint16_t util2msp0; // [198] // @jh005a
+ uint16_t ips2msp0; // [200] // @jh005a
+ uint16_t nutil3sp0cy[MAX_CORES]; // [202] - 24 bytes
+
+ // Fwish (i.e., desired frequency that this OCC slave wants based on DPS
+ // algorithms)
+ uint16_t fwish; // [226] - 2 bytes
+ // Factual (i.e., actual frequency requested by this OCC slave)
+ uint16_t factual; // [228] - 2 bytes
+
+ // Reserved Bytes
+ union
+ {
+ uint8_t reserved[SLV_OUTBOX_RSV_SIZE]; // [230] - 758 bytes
+ struct __attribute__ ((packed))
+ {
+ uint8_t _reserved_1;
+ uint8_t _reserved_2;
+ uint32_t counter;
+ };
+ }; // @th002
+
+ // GPSM DCM Synchronization
+ proc_gpsm_dcm_sync_occfw_t dcm_sync; // [988] - 4 bytes
+
+ // General Firmware Message Passing
+ uint8_t occ_fw_mailbox[SLV_MAILBOX_SIZE]; // [992] - 32 bytes
+} dcom_slv_outbox_t __attribute__ ((aligned (128)));
+
+
+// Slave Inbox Doorbell
+// This must be aligned to 8 bytes since that is the unit
+// that the PBAX unit uses to send
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ /// PowerBus ID so that the slave knows who the master is
+ pob_id_t pob_id; // 1 byte
+ /// Magic Number denoting the start of the packet
+ uint32_t magic1 :24; // 3 bytes
+ /// OCI Address where the Slave Inbox Buffer was placed
+ uint32_t addr_slv_inbox_buffer0; // 4 bytes
+ /// PowerCap data sent from master to slaves
+ pcap_config_data_t pcap; // 14 bytes
+ /// PowerPreservingBoundry Fmax to throttle all OCCs the same
+ uint16_t ppb_fmax; // 2 bytes
+ /// GPIO pins from APSS
+ uint16_t gpio[2]; // 4 bytes
+ /// Raw ADC Channels from APSS
+ uint16_t adc[MAX_APSS_ADC_CHANNELS]; // 32 bytes
+ /// Reserved
+ uint8_t _reserved_0[4]; // 4 bytes
+ /// Time of Day Clock from the last APSS reading
+ uint64_t tod; // 8 bytes
+ /// Reserved
+ uint8_t _reserved_1[52]; // 52 bytes
+ /// Counter in case we want to determine sequence errors
+ uint8_t magic_counter; // 1 byte
+ /// Magic Number for denoting the end of the packet
+ uint32_t magic2 :24; // 3 bytes
+ }; // --------
+ uint64_t words[16]; // Total = 128 bytes
+ };
+} __attribute__ ((packed)) dcom_slv_inbox_doorbell_t; // @th034
+
+
+// Slave Outbox Doorbell
+typedef struct
+{
+ pob_id_t pob_id;
+ uint8_t pcap_valid; //@rt004a
+ uint16_t active_node_pcap; //@rt001a
+ uint32_t addr_slv_outbox_buffer;
+} __attribute__ ((packed)) dcom_slv_outbox_doorbell_t;
+
+typedef enum
+{
+ SLAVE_INBOX = 0,
+ SLAVE_OUTBOX
+
+} dcom_error_type_t;
+
+typedef struct
+{
+ uint32_t totalTicks;
+ uint32_t totalSuccessful;
+ uint16_t currentFailCount;
+} dcom_fail_count_t;
+
+typedef struct
+{
+ /// Mask denoting if OCC is currently responding
+ uint8_t alive;
+ /// Mask denoting if OCC has responded in the past, but stopped
+ uint8_t zombie;
+ /// Mask denoting if OCC has never responded
+ uint8_t dead;
+} dcom_present_mask_t; // @th025
+
+// DCOM Timing / Statistics
+// This is a DEBUG ONLY structure that is only used to measure certain
+// characteristics of the distributed communication mechanism.
+// It may be removed at any time without warning.
+//
+// For Reference:
+// Phase(degrees) = (((SsxTimebase % 250us) / 250us) * 360 degrees)
+typedef struct
+{
+ /// Master Only Statistics
+ struct
+ {
+ /// Start Time of the Most Recent Master Doorbell Broadcast
+ SsxTimebase doorbellStartTx;
+ /// Stop Time of the Most Recent Master Doorbell Broadcast
+ SsxTimebase doorbellStopTx;
+ /// The longest it has even taken to send the Master Doorbell Broadcast
+ SsxTimebase doorbellMaxDeltaTx;
+ /// How many Master Doorbell Broadcasts have been sent
+ uint32_t doorbellNumSent;
+ /// What is our "send" phase in relation to our SsxTimebase
+ uint16_t doorbellPhase;
+ /// The Most Recent Master Doorbell Broadcast sequence number
+ uint8_t doorbellSeq;
+ /// Masks of the current status of the slaves
+ dcom_present_mask_t allOccStatusMask; // @th036
+ } master;
+
+ /// Slave Statistics
+ struct
+ {
+ /// Start Time of the Most Recent Wait for Master Doorbell
+ SsxTimebase doorbellStartWaitRx;
+ /// Successful Stop Time of the Most Recent Wait for Master Doorbell
+ SsxTimebase doorbellStopWaitRx;
+ /// Timeout Stop Time of the Most Recent Wait for Master Doorbell
+ SsxTimebase doorbellTimeoutWaitRx;
+ /// The longest it has ever taken us to receive Master Doorbell
+ SsxTimebase doorbellMaxDeltaWaitRx;
+ /// Start Time of the Most Recent Slave Doorbell sent to Master
+ SsxTimebase doorbellStartRx;
+ /// Stop Time of the Most Recent Slave Doorbell sent to Master
+ SsxTimebase doorbellStopRx;
+ /// The longest it has ever taken us to send Slave Doorbell
+ SsxTimebase doorbellMaxDeltaRx;
+ /// How many Master Doorbell Broadcasts have we received
+ uint32_t doorbellNumRx;
+ /// How many Master Doorbell Broadcasts have we received via wait4master
+ uint32_t doorbellNumWaitRx;
+ /// "Receive Phase" of Master Doorbell in relation to our SsxTimebase
+ uint16_t doorbellPhase;
+ /// Most Recent Sequence number received from Master Doorbell
+ uint8_t doorbellSeq;
+ /// Error Flags for receiving Master Doorbell (never cleared)
+ struct
+ {
+ uint8_t timeout :1;
+ uint8_t incomplete :1;
+ uint8_t badSequence :1;
+ uint8_t badMagicNumEnd :1;
+ uint8_t dropPacket :1;
+ uint8_t hwError :1;
+ uint8_t timeoutRx :1;
+ } doorbellErrorFlags;
+ } slave;
+
+ /// General Timing
+ /// Used to calculate the difference between the SsxTimebase and the TOD,
+ /// to correlate between multiple OCCs.
+ SsxTimebase base;
+ uint64_t tod;
+
+} dcom_timing_t; // @th032
+extern dcom_timing_t G_dcomTime; // @th032
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// Used to tell AMEC code that the slave inbox has been received.
+// This could just be a flag, doesn't have to be semaphore, since
+// the RTL Loop task can't block on Semaphore, it would just have
+// to loop until it got a good return code.
+//SsxSemaphore G_sem_slv_inbox;
+extern bool G_slv_inbox_received;
+
+// Used to tell AMEC code that the slave outbox has been received.
+// This could just be a flag, doesn't have to be semaphore, since
+// the RTL Loop task can't block on Semaphore, it would just have
+// to loop until it got a good return code.
+extern uint8_t G_slv_outbox_complete;
+
+// Specifies if the OCC is a MASTER or SLAVE
+extern uint8_t G_occ_role;
+
+// Specifies if the OCC is configured to be a Master or Slave inside the DCM
+// chip. In the case of SCMs, it will always return the Master role.
+extern uint8_t G_dcm_occ_role;
+
+// Holds PowerBus ID of this OCC (Chip & node). From this we can determine OCC ID
+// and PBAX ID.
+extern pob_id_t G_pob_id;
+
+// PBAX 'Target' Structure (Register Abstraction) that has the data needed for
+// a multicast operation.
+extern PbaxTarget G_pbax_multicast_target;
+
+// PBAX 'Target' Structure (Register Abstraction) that has the data needed for
+// a unicast operation from the OCC Slave to the OCC Master.
+extern PbaxTarget G_pbax_unicast_target;
+
+//Number of occ's that *should* be present
+extern uint8_t G_occ_num_present; // @th025
+
+// master/slave event flags
+extern uint32_t G_master_event_flags;
+extern uint32_t G_slave_event_flags;
+extern uint32_t G_master_event_flags_ack;
+extern uint32_t G_slave_event_flags_ack[MAX_OCCS];
+
+extern dcom_fail_count_t G_dcomSlvInboxCounter;
+
+extern SsxSemaphore G_dcomThreadWakeupSem;
+
+// =========================================================
+// Master Only
+// =========================================================
+
+// Used to house the actuation & power measurement data from the master
+// before it is DMA'd to Main Memory from SRAM.
+//DMA_BUFFER(extern dcom_slv_inbox_t G_dcom_slv_inbox_tx[MAX_OCCS]);
+extern dcom_slv_inbox_t G_dcom_slv_inbox_tx[MAX_OCCS];
+
+// Used to house the Slave Outboxes with the mini-sensor data in in the master
+// after it is DMA'd from main memory.
+extern dcom_slv_outbox_t G_dcom_slv_outbox_rx[MAX_OCCS];
+
+
+// =========================================================
+// Master & Slave
+// =========================================================
+
+// Used to house the actuation & power measurement data coming from the master
+// after it is DMA'd from Main Memory to SRAM.
+extern dcom_slv_inbox_t G_dcom_slv_inbox_rx;
+
+// Used to house the Slave Outboxes with the mini-sensor data in the slave
+// before it is DMA'd to main memory.
+//DMA_BUFFER(extern dcom_slv_outbox_t G_dcom_slv_outbox_tx); // Slave
+extern dcom_slv_outbox_t G_dcom_slv_outbox_tx; // Slave
+
+// Used to house the pcap & power measurement data coming from the master
+// in a more reliable way than Main Memory
+extern dcom_slv_inbox_doorbell_t G_dcom_slv_inbox_doorbell_rx;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//check if slave inbox is valid, or if we are having errors
+bool isDcomSlvInboxValid(void);
+
+// copy data into slave inbox for use by master
+uint32_t dcom_build_slv_inbox(void);
+
+// fill out sensor data from slave to master
+uint32_t dcom_build_slv_outbox(void);
+
+// switch between ping pong buffers
+uint32_t dcom_which_buffer(void);
+
+// switch between ping pong buffers
+uint32_t dcom_which_buffer_slv_outbox(void);
+
+// get address of slave inbox in main memory
+uint32_t dcom_calc_slv_inbox_addr(void);
+
+// get address of slave outbox in main memory
+uint32_t dcom_calc_slv_outbox_addr( const dcom_slv_outbox_doorbell_t * i_doorbell, uint8_t * o_occ_id);
+
+// determine if we are master or slave
+void dcom_initialize_roles(void) INIT_SECTION;
+
+// copy slave inbox from main memory to sram
+void task_dcom_rx_slv_inbox(task_t *i_self);
+
+// copy slave outboxes from main memory to sram
+void task_dcom_rx_slv_outboxes(task_t *i_self);
+
+// copy slave inboxes from sram to main memory
+void task_dcom_tx_slv_inbox(task_t *i_self);
+
+// copy slave outboxes from sram to main memory
+void task_dcom_tx_slv_outbox(task_t *i_self);
+
+// initialize the pbax queues
+void dcom_initialize_pbax_queues(void);
+
+// translate pids to pbax ids
+pbax_id_t dcom_pbusid2pbaxid(pob_id_t i_pobid);
+
+// receive multicast doorbell
+uint32_t dcom_rx_slv_inbox_doorbell( void );
+
+// receive unicast doorbell
+uint32_t dcom_rx_slv_outbox_doorbell( void );
+
+// send multicast doorbells to slaves
+void dcom_tx_slv_inbox_doorbell( void );
+
+// send unicast doorbells to master
+void dcom_tx_slv_outbox_doorbell( void );
+
+//task to wait for the master multicast doorbell
+void task_dcom_wait_for_master( task_t *i_self);
+
+// keep track of failure counts
+#define dcom_error_check_reset(_e_) dcom_error_check( _e_, TRUE, OCC_SUCCESS_REASON_CODE, OCC_NO_EXTENDED_RC) // @nh001c
+void dcom_error_check( dcom_error_type_t i_error_type, bool i_clear_error, uint32_t i_orc , const uint32_t i_orc_ext); // @nh001c
+
+//task to parse occ firmware messages
+void task_dcom_parse_occfwmsg(task_t *i_self);
+
+// copy occ fw msg
+void dcom_build_occfw_msg( dcom_error_type_t i_which_msg );
+
+// Copy OCC DCM Sync Messages
+void dcom_build_dcm_sync_msg(const dcom_error_type_t i_which_msg); // @th010
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_DCOM_H
diff --git a/src/occ/dcom/dcomMasterRx.c b/src/occ/dcom/dcomMasterRx.c
new file mode 100644
index 0000000..8ff632a
--- /dev/null
+++ b/src/occ/dcom/dcomMasterRx.c
@@ -0,0 +1,430 @@
+/******************************************************************************
+// @file dcomMasterRx.c
+// @brief Slave OCC to Master OCC communication handler
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dcomMasterRx.c DCOMMASTERRX.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th023 thallet 10/08/2012 Moved Master RX function here
+ * @th025 857856 thallet 10/16/2012 Dcom Master Slave SMS part 2
+ * @th036 881677 thallet 05/09/2013 New Poll Command Support
+ * @rt001 897459 tapiar 08/19/2013 Upd: read active node pcaps from doorbell
+ * @rt004 908817 tapiar 12/11/2013 Save off slave pcap information, pcap & pcap valid field
+ * @sb003 908290 sbroyles 12/18/2013 Test BCE request states
+ * @sb013 911625 sbroyles 01/15/2014 Fix to 908290 changes
+ * @wb003 920760 wilbryan 03/25/2014 Update SRCs to match TPMD SRCs
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOMMASTERRX_C
+#define _DCOMMASTERRX_C
+
+/** \defgroup Slave to Master Communication
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <pgp_pmc.h>
+#include "pgp_pba.h"
+#include <rtls.h>
+#include <apss.h>
+#include <dcom.h>
+#include <dcom_service_codes.h>
+#include <occ_service_codes.h>
+#include <trac.h>
+#include <proc_pstate.h>
+#include <amec_master_smh.h> // @rt001a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//
+uint8_t G_slv_outbox_complete = 0;
+
+// SSX Block Copy Request for the Slave Outbox Receive Queue
+BceRequest G_slv_outbox_rx_pba_request[MAX_OCCS];
+
+// Used by the master to house the doorbell data that is received from
+// the slave unicast doorbells from each slave, stating that it put its slave
+// outbox in main memory.
+dcom_slv_outbox_doorbell_t G_dcom_slv_outbox_doorbell_rx[MAX_OCCS];
+
+// Make sure that the Slave Outbox RX Buffer is 1kB / OCC, otherwise cause
+// error on the compile.
+STATIC_ASSERT( (NUM_BYTES_IN_SLAVE_OUTBOX != (sizeof(G_dcom_slv_outbox_rx)/MAX_OCCS)) );
+
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: setbit_slvoutbox_complete
+//
+// Description: Helper function to set bit when outbox is complete
+//
+// Flow: 09/21/11 FN=setbit_slvoutbox_complete
+//
+// End Function Specification
+void setbit_slvoutbox_complete(uint8_t i_bit)
+{
+ if(i_bit < MAX_NUM_OCC)
+ {
+ G_slv_outbox_complete |= (1 << i_bit);
+ }
+}
+
+
+// Function Specification
+//
+// Name: task_dcom_rx_slv_outboxes
+//
+// Description: Copy Slave outboxes from Main Memory to SRAM
+// on master
+//
+// Flow: 09/21/11 FN=task_dcom_rx_slv_outboxes
+//
+// Task Flags: RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_MSTR,
+// RTL_FLAG_NOAPSS, RTL_FLAG_RUN
+//
+// End Function Specification
+void task_dcom_rx_slv_outboxes( task_t *i_self)
+{
+ static uint32_t L_wait4slaves = 0;
+ uint32_t l_orc = OCC_SUCCESS_REASON_CODE;
+ uint32_t l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ uint8_t l_slv_response_mask = 0; // @th025
+ // @sb003 Use a static local bool to track whether the BCE request used
+ // here has ever been successfully created at least once
+ static bool L_bce_slv_outbox_rx_request_created_once[MAX_OCCS] = {FALSE,};
+
+ DCOM_DBG("2. RX Slave Outboxes\n");
+
+ do
+ {
+ // doorbell from the slave
+ uint32_t l_num_doorbells_rxd = dcom_rx_slv_outbox_doorbell();
+
+ // how many doorbells were received?
+ if( l_num_doorbells_rxd < G_occ_num_present ) // @th025
+ {
+ if ( L_wait4slaves > MAX_WAIT_FOR_SLAVES )
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_RX_SLV_OUTBOX
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_GENERIC_TIMEOUT
+ * @devdesc Generic timeout failure
+ */
+ TRAC_ERR("Time out waiting for slaves" );
+ l_orc = INTERNAL_FAILURE; // @nh001c
+ l_orc_ext = ERC_GENERIC_TIMEOUT; // @nh001a
+ break;
+ }
+
+ L_wait4slaves++;
+ }
+
+ uint32_t l_slv_idx = 0;
+
+ //loop through all doorbells received
+ for(; l_slv_idx < l_num_doorbells_rxd; l_slv_idx++)
+ {
+ // index/occ id
+ uint8_t l_slv = 0;
+
+ // main memory address
+ uint32_t l_addr = dcom_calc_slv_outbox_addr( &G_dcom_slv_outbox_doorbell_rx[l_slv_idx], &l_slv);
+
+ G_slave_active_pcaps[l_slv].active_pcap = G_dcom_slv_outbox_doorbell_rx[l_slv_idx].active_node_pcap; //@rt001a rt004c
+ G_slave_active_pcaps[l_slv].pcap_valid = G_dcom_slv_outbox_doorbell_rx[l_slv_idx].pcap_valid; //@rt004a
+
+ // Add slave to mask of responding slaves
+ l_slv_response_mask |= (0x01 << l_slv); // @th025
+
+ //check valid address (should be inside inbox addresses range)
+ if ( (ADDR_SLAVE_OUTBOX_MAIN_MEM_PING <= l_addr) &&
+ ((ADDR_SLAVE_OUTBOX_MAIN_MEM_PONG+(sizeof(dcom_slv_outbox_t)*MAX_OCCS)) > l_addr) )
+ {
+ DCOM_DBG("2.X. Copy down Slave Outboxes from %x\n",l_addr);
+ uint32_t l_ssxrc = 0;
+
+ // @sb003
+ // Using a global bce request requires some special consideration
+ // of the possible request states. Note that since this task
+ // runs in the critical section of the RTL tick that external
+ // non-critical interrupts are disabled. This includes the PIT
+ // interrupt from the OCB timer used to generate the interrupt
+ // that runs the RTL tick code which led us here. The point is
+ // that this code cannot be re-entrant which implies that if a
+ // request is created without error then it will also be
+ // scheduled before this task runs again. In the good path we
+ // can never get here and have a BCE request that was not yet
+ // scheduled.
+ // There are four possible request states:
+ // 1. request is idle and complete: The request was created
+ // and scheduled and has completed without error.
+ // 2. request is idle and not complete: The request was created
+ // and scheduled but was either canceled, killed or has errored
+ // out, or there was an error scheduling the request.
+ // 3. request is not idle and not complete: The request was
+ // created and scheduled but is still in progress or still
+ // enqueued. Note that there is a special case here where this
+ // could also mean that this is the first time we are running
+ // this task so the global request is uninitialized. It could
+ // also mean there was an error creating the request (unlikely)
+ // so it was never scheduled.
+ // 4. request is not idle and complete: This can't happen.
+ //
+ bool l_proceed_with_request_and_schedule = FALSE;
+ int l_req_idle = async_request_is_idle(&(G_slv_outbox_rx_pba_request[l_slv].request));
+ int l_req_complete = async_request_completed(&(G_slv_outbox_rx_pba_request[l_slv].request));
+
+ if (!L_bce_slv_outbox_rx_request_created_once[l_slv])
+ {
+ // Do this case first, all other cases assume that this is
+ // true!
+ // This is the first time we have created a request so
+ // always proceed with request create and schedule
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && l_req_complete)
+ {
+ // Most likely case first. The request was created
+ // and scheduled and has completed without error. Proceed.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && !l_req_complete)
+ {
+ // There was an error on the schedule request or the request
+ // was scheduled but was canceled, killed or errored out.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv outbox rx request idle but not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_outbox_rx_pba_request[l_slv].request.callback_rc,
+ G_slv_outbox_rx_pba_request[l_slv].request.options,
+ G_slv_outbox_rx_pba_request[l_slv].request.state,
+ G_slv_outbox_rx_pba_request[l_slv].request.abort_state,
+ G_slv_outbox_rx_pba_request[l_slv].request.completion_state);
+ TRAC_INFO("Proceeding with BCE slv outbox rx request and schedule");
+ }
+ else if (!l_req_idle && !l_req_complete)
+ {
+ // The request was created and scheduled but is still in
+ // progress or still enqueued OR there was some error
+ // creating the request so it was never scheduled. The latter
+ // case is unlikely and will generate an error message when
+ // it occurs. It will also have to happen after the request
+ // was created at least once or we'll never get here. If the
+ // request does fail though before the state parms in the
+ // request are reset (like a bad parameter error), then this
+ // represents a hang condition that we can't recover from.
+ // DO NOT proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = FALSE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv outbox rx request not idle and not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_outbox_rx_pba_request[l_slv].request.callback_rc,
+ G_slv_outbox_rx_pba_request[l_slv].request.options,
+ G_slv_outbox_rx_pba_request[l_slv].request.state,
+ G_slv_outbox_rx_pba_request[l_slv].request.abort_state,
+ G_slv_outbox_rx_pba_request[l_slv].request.completion_state);
+ TRAC_INFO("NOT proceeding with BCE slv outbox rx request and schedule");
+ }
+ // else {// This case can't happen, ignore it.}
+
+ // @sb003 Only proceed if the BCE request state checked out
+ if (l_proceed_with_request_and_schedule)
+ {
+ // copy request from main memory to SRAM
+ l_ssxrc = bce_request_create(
+ &G_slv_outbox_rx_pba_request[l_slv], // block copy object
+ &G_pba_bcde_queue, // mainstore to sram copy engine
+ l_addr, // mainstore address
+ (uint32_t)&G_dcom_slv_outbox_rx[l_slv], // sram starting address
+ sizeof(dcom_slv_outbox_t), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ (AsyncRequestCallback)setbit_slvoutbox_complete, // call back
+ &l_slv, // call back arguments
+ ASYNC_CALLBACK_IMMEDIATE // blocking request
+ );
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_RX_SLV_OUTBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request create failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_CREATE_FAILURE; // @nh001a
+ break;
+ }
+
+ // @sb003 Request created at least once
+ L_bce_slv_outbox_rx_request_created_once[l_slv] = TRUE; // @sb013
+ l_ssxrc = bce_request_schedule(&G_slv_outbox_rx_pba_request[l_slv]); // actual copying
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_RX_SLV_OUTBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request schedule failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_SCHEDULE_FAILURE; // @nh001a
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_RX_SLV_OUTBOX
+ * @reasoncode INTERNAL_INVALID_INPUT_DATA
+ * @userdata1 N/A
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Memory related failure
+ */
+ TRAC_ERR("Invalid address from calculate slave inbox address function [%08X]", l_addr );
+ l_orc = INTERNAL_INVALID_INPUT_DATA; // @wb003
+ l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ break;
+ }
+ }
+
+ L_wait4slaves = 0;
+ }
+ while( 0 );
+
+ // Update the number of OCCs only if there is a new one that showed up
+ if((G_sysConfigData.is_occ_present | l_slv_response_mask) != G_sysConfigData.is_occ_present)
+ {
+ uint8_t l_temp = G_sysConfigData.is_occ_present;
+
+ // Update the mask that stores which OCCs we know are present because they
+ // are responding to master OCC (via doorbell). Only set, never clear.
+ // i.e. Don't remove the old ones. This is what is reported to TMGT
+ G_sysConfigData.is_occ_present |= l_slv_response_mask; // @th036
+
+ // Since we changed the mask, also update which ones are present.
+ G_occ_num_present = __builtin_popcount(G_sysConfigData.is_occ_present);
+ TRAC_IMP("Updated OCCs Present -- OldMask: 0x%02x, NewMask: 0x%02x",
+ l_temp,
+ G_sysConfigData.is_occ_present);
+ }
+
+
+
+ //<DEBUG>
+ // Activly responding to master
+ G_dcomTime.master.allOccStatusMask.alive = l_slv_response_mask; // @th036
+ // Was here, but stopped responding to master
+ G_dcomTime.master.allOccStatusMask.zombie =
+ ( G_sysConfigData.is_occ_present & ~l_slv_response_mask ); // @th036
+ // Has never been here or has never responded
+ G_dcomTime.master.allOccStatusMask.dead = ~G_sysConfigData.is_occ_present; // @th036
+ //</DEBUG>
+
+ if ( l_orc != OCC_SUCCESS_REASON_CODE )
+ {
+ // create and commit error
+ dcom_error_check( SLAVE_OUTBOX, FALSE, l_orc, l_orc_ext);
+ }
+ else
+ {
+ // done, lets clear our counter
+ dcom_error_check_reset( SLAVE_OUTBOX );
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: dcom_rx_slv_outbox_doorbell
+//
+// Description: receive unicast doorbell and save data
+// from slave (slave to master)
+//
+// Flow: 09/22/11 FN=dcom_rx_slv_outbox_doorbell
+//
+// End Function Specification
+uint32_t dcom_rx_slv_outbox_doorbell( void )
+{
+ static bool l_error = FALSE;
+ int l_pbarc = 0;
+ uint32_t l_read = 0;
+
+ // grab doorbells from slave
+ l_pbarc = pbax_read(
+ &G_pbax_read_queue[1],
+ &G_dcom_slv_outbox_doorbell_rx[0],
+ sizeof(dcom_slv_outbox_doorbell_t)*MAX_OCCS,
+ &l_read
+ );
+
+ if ( l_pbarc != 0 && l_error == FALSE )
+ {
+ // failure occurred but only trace it once
+ TRAC_ERR("PBAX Read Failure in receiving unicast doorbell - RC[%08X]", l_pbarc);
+
+ l_error = TRUE;
+ }
+ else
+ {
+ l_error = FALSE;
+ }
+ // return the number of doorbells read by dividing the bytes read by the number of occs slaves
+ return (l_read/sizeof(dcom_slv_outbox_doorbell_t));
+}
+
+
+#endif // DCOMMASTERRX_C
+
diff --git a/src/occ/dcom/dcomMasterTx.c b/src/occ/dcom/dcomMasterTx.c
new file mode 100755
index 0000000..d0efa5a
--- /dev/null
+++ b/src/occ/dcom/dcomMasterTx.c
@@ -0,0 +1,628 @@
+/******************************************************************************
+// @file dcomMasterToSlave.c
+// @brief Master OCC to Slave OCC communication handler
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dcomMasterToSlave.c DCOMMASTERTOSLAVE.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @00 abagepa 10/10/2011 Created
+ * @th002 thallet 11/01/2011 Misc Changes for Nov 1st Milestone
+ * @pb00A pbavari 11/15/2011 Set G_ApssPwrMeasCompleted to TRUE
+ * for SVN SIMICS
+ * @th005 thallet 11/01/2011 Added STATIC_ASSERT checks
+ * @01 tapiar 11/12/2011 Stage 3 updates
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th022 thallet 10/08/2012 Moved CNFG Data commands to diff file
+ * @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+ * @th034 879027 thallet 04/18/2013 Broadcast Power Data over PBAX
+ * @at013 878755 alvinwan 04/17/2013 OCC power capping implementation
+ * @th032 thallet 04/16/2013 Tuleta HW Bringup
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @fk001 879727 fmkassem 04/16/2013 OCC powercap support.
+ * @gs007 888247 gjsilva 06/19/2013 OCC mnfg support for frequency distribution
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @gs016 905781 gjsilva 11/12/2013 Fix for Master->Slave doorbell loss of synchronization
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @rt004 905638 tapiar 11/13/2013 Tunable parameters
+ * @gm014 907707 milesg 12/05/2013 don't panic on pbax_send timeout failures
+ * @jh00a 909791 joshych 12/16/2013 Enhance APSS pwr meas trace
+ * @sb003 908290 sbroyles 12/18/2013 Test BCE request states
+ * @jh00b 910184 joshych 01/10/2014 Add check for checkstop
+ * @sb013 911625 sbroyles 01/15/2014 Fix to 908290 changes
+ * @fk005 911760 fmkassem 01/14/2014 APSS data collection retry support.
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @sb023 913769 sbroyles 02/08/2014 Fix task_dcom_tx_slv_inbox !idle &&
+ * !complete hang.
+ * @gm028 911670 milesg 02/27/2014 Fixed compiler fails from stradale
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOMMASTERTX_C
+#define _DCOMMASTERTX_C
+
+/** \defgroup Master-Slave Communication
+ *
+ */
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <pgp_pmc.h>
+#include "pgp_pba.h"
+#include <rtls.h>
+#include <apss.h>
+#include <dcom.h>
+#include <dcom_service_codes.h>
+#include <occ_service_codes.h>
+#include <trac.h>
+#include <proc_pstate.h>
+#include <amec_sys.h>
+#include <amec_master_smh.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+extern UINT8 g_amec_tb_record; // from amec_amester.c for syncronized traces
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+
+// SSX Block Copy Request for the Slave Inbox Transmit Queue
+BceRequest G_slv_inbox_tx_pba_request;
+
+// Used by the master to house the doorbell data that is sent in
+// the master multicast doorbell, stating that it put slave inbox in main memory.
+dcom_slv_inbox_doorbell_t G_dcom_slv_inbox_doorbell_tx;
+
+// Make sure that the Slave Inbox TX Buffer is 256B, otherwise cause
+// error on the compile.
+STATIC_ASSERT( (NUM_BYTES_IN_SLAVE_INBOX != (sizeof(G_dcom_slv_inbox_tx)/MAX_OCCS)) );
+
+// Store return code and failed packet # from pbax_send so we can trace it
+uint32_t G_pbax_rc = 0;
+uint32_t G_pbax_packet = 0xffffffff;
+
+//Used to keep count of number of APSS data collection fails.
+uint8_t G_apss_fail_updown_count = 0x00;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: dcom_build_slv_inbox
+//
+// Description: The purpose of this function is to copy the Control Data into
+// the Slave inbox structures so that the Master can send it out.
+// Build the slave inboxes so master can send them to slaves
+//
+// Flow: 06/19/13 FN=dcom_build_slv_inbox
+//
+// changedby: @at013c, @fk001c
+//
+// End Function Specification
+
+uint32_t dcom_build_slv_inbox(void)
+{
+ // Locals
+ uint32_t l_addr_of_slv_inbox_in_main_mem = 0;
+ uint32_t l_slv_idx = 0;
+ uint32_t l_core_idx = 0;
+ uint32_t l_cntr_idx = 0;
+ uint32_t l_mem_intr_idx = 0;
+
+ static uint8_t L_seq = 0xFF;
+
+ L_seq++;
+
+ //If there was a pbax_send failure, trace it here since we can't do it in the critical
+ //interrupt context.
+ if(G_pbax_rc)
+ {
+ TRAC_INFO("PBAX Send Failure in transimitting multicast doorbell - RC[%08X], packet[%d]", G_pbax_rc, G_pbax_packet);
+ }
+
+
+ //INBOX...............
+ //For each occ slave collect its occ data.
+ for(; l_slv_idx < MAX_OCCS; l_slv_idx++)
+ {
+ G_dcom_slv_inbox_tx[l_slv_idx].seq = L_seq;
+ G_dcom_slv_inbox_tx[l_slv_idx].version = 0;
+ //G_dcom_slv_inbox_tx[l_slv_idx].ambient_temp = //Activate when ambient temperature is available.
+ //G_dcom_slv_inbox_tx[l_slv_idx].altitude = //Acitivate when altitude is available.
+
+ //TODO: adc,gpio,and tod are only sent here for sanity check and for bringup only.
+ //If the values are needed by the slaves, they should use the values sent in the doorbell.
+ //Probably remove them after bringup is complete.
+ memcpy( G_dcom_slv_inbox_tx[l_slv_idx].adc, G_apss_pwr_meas.adc, sizeof(G_dcom_slv_inbox_tx[l_slv_idx].adc));
+ memcpy( G_dcom_slv_inbox_tx[l_slv_idx].gpio, G_apss_pwr_meas.gpio, sizeof(G_dcom_slv_inbox_tx[l_slv_idx].gpio));
+ memcpy( G_dcom_slv_inbox_tx[l_slv_idx].tod, &G_apss_pwr_meas.tod, sizeof( G_dcom_slv_inbox_tx[l_slv_idx].tod )); //TODO - this doesn't work
+
+ memset( G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox, 0, sizeof( G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox ));
+
+ //Collect frequency data for each core
+ for( l_core_idx = 0; l_core_idx < MAX_CORES; l_core_idx++)
+ {
+ // TODO - uncomment once macro exists
+ //G_dcom_slv_inbox_tx[l_slv_idx].freq250usp0cy = FREQ250USPC[l_core_idx];
+ G_dcom_slv_inbox_tx[l_slv_idx].freq250usp0cy[l_core_idx] = l_core_idx;
+ }
+
+ //collect data for each centaur throttle
+ for( l_cntr_idx = 0; l_cntr_idx < MAX_CENTAUR_THROTTLES; l_cntr_idx++)
+ {
+ // TODO - uncomment once macro exists
+ //G_dcom_slv_inbox_tx[l_slv_idx].memsp2msP0MxCyPz = MEMSP2MSP0MxCyPz[l_cntr_idx];
+ G_dcom_slv_inbox_tx[l_slv_idx].memsp2msP0MxCyPz[l_cntr_idx] = l_cntr_idx;
+ }
+
+ //collect data for each mem interleave group throttle
+ for( l_mem_intr_idx = 0; l_mem_intr_idx < MAX_MEM_INTERLEAVE_GROUP_THROTTLES; l_mem_intr_idx++)
+ {
+ // TODO - uncomment once macro exists
+ //G_dcom_slv_inbox_tx[l_slv_idx].memsp2msP0IGx = MEMSP2MSP0IG[l_mem_intr_idx];
+ G_dcom_slv_inbox_tx[l_slv_idx].memsp2msP0IGx[l_mem_intr_idx] = l_mem_intr_idx;
+ }
+
+ //collect mnfg parameters that need to be sent to slaves
+ G_dcom_slv_inbox_tx[l_slv_idx].foverride_enable = g_amec->mnfg_parms.auto_slew;
+ G_dcom_slv_inbox_tx[l_slv_idx].foverride = g_amec->mnfg_parms.foverride;
+ G_dcom_slv_inbox_tx[l_slv_idx].emulate_oversub = AMEC_INTF_GET_OVERSUBSCRIPTION_EMULATION();
+
+ //collect Idle Power Saver parameters to be sent to slaves
+ G_dcom_slv_inbox_tx[l_slv_idx].ips_freq_request = g_amec->mst_ips_parms.freq_request;
+
+ //collect Tunable Paramaters to be sent to slaves
+ G_dcom_slv_inbox_tx[l_slv_idx].alpha_up = G_mst_tunable_parameter_table_ext[0].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].alpha_down = G_mst_tunable_parameter_table_ext[1].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].sample_count_util = G_mst_tunable_parameter_table_ext[2].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].step_up = G_mst_tunable_parameter_table_ext[3].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].step_down = G_mst_tunable_parameter_table_ext[4].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].epsilon_perc = G_mst_tunable_parameter_table_ext[5].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].tlutil = G_mst_tunable_parameter_table_ext[6].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].tunable_param_overwrite = G_mst_tunable_parameter_overwrite;
+
+ //collect soft frequency bondaries to be sent to slaves
+ G_dcom_slv_inbox_tx[l_slv_idx].soft_fmin = G_mst_soft_fmin;
+ G_dcom_slv_inbox_tx[l_slv_idx].soft_fmax = G_mst_soft_fmax;
+
+ //send trace recording bit to slaves for synchronized tracing. //Lefurgy
+ G_dcom_slv_inbox_tx[l_slv_idx].tb_record = g_amec_tb_record;
+
+ G_dcom_slv_inbox_tx[l_slv_idx].counter++; // @th002
+
+ memcpy( &G_dcom_slv_inbox_tx[l_slv_idx].sys_mode_freq,
+ &G_sysConfigData.sys_mode_freq,
+ sizeof( freqConfig_t )); // @th040
+ }
+
+ //Clear the tunable parameter overwrite once we collect the new values
+ G_mst_tunable_parameter_overwrite = 0;
+
+ //@01a
+ dcom_build_occfw_msg( SLAVE_INBOX );
+
+ // Copy Data from one DCM pair's Outbox to other DCM pair's inbox
+ dcom_build_dcm_sync_msg( SLAVE_INBOX ); // @th010
+
+ l_addr_of_slv_inbox_in_main_mem = dcom_which_buffer();
+
+ //DOORBELL.................
+ //Prepare data for doorbell. This is sent to all OCCs
+
+ G_dcom_slv_inbox_doorbell_tx.pob_id = G_pob_id;
+ G_dcom_slv_inbox_doorbell_tx.magic1 = PBAX_MAGIC_NUMBER2_32B;
+ G_dcom_slv_inbox_doorbell_tx.addr_slv_inbox_buffer0 = l_addr_of_slv_inbox_in_main_mem;
+
+ memcpy( (void *) &G_dcom_slv_inbox_doorbell_tx.pcap,
+ (void *) &G_master_pcap_data, // @at013c @fk001c
+ sizeof(pcap_config_data_t));
+
+ G_dcom_slv_inbox_doorbell_tx.ppb_fmax = G_sysConfigData.master_ppb_fmax; //master ppb fmax is calculated in amec_ppb_fmax_calc
+
+ memcpy( (void *) &G_dcom_slv_inbox_doorbell_tx.adc[0],
+ (void *) &G_apss_pwr_meas.adc[0],
+ sizeof( G_dcom_slv_inbox_doorbell_tx.adc ));
+
+ G_dcom_slv_inbox_doorbell_tx.gpio[0] = G_apss_pwr_meas.gpio[0];
+ G_dcom_slv_inbox_doorbell_tx.gpio[1] = G_apss_pwr_meas.gpio[1];
+ G_dcom_slv_inbox_doorbell_tx.tod = G_apss_pwr_meas.tod;
+
+ G_dcom_slv_inbox_doorbell_tx.magic_counter++;
+ G_dcom_slv_inbox_doorbell_tx.magic2 = PBAX_MAGIC_NUMBER_32B;
+
+ return l_addr_of_slv_inbox_in_main_mem;
+}
+
+
+// Function Specification
+//
+// Name: dcom_which_buffer
+//
+// Description: Determines which buffer in the 'double buffer'
+// or ping/pong to use. Basically alternates between
+// returning the ping or the pong address
+//
+// Flow: 08/23/11 FN=dcom_which_buffer
+//
+// End Function Specification
+
+uint32_t dcom_which_buffer(void)
+{
+ //Locals
+ uint32_t l_mem_address = ADDR_SLAVE_INBOX_MAIN_MEM_PONG;
+
+ // switch back and forth based on tick
+ if( CURRENT_TICK & 1 )
+ {
+ l_mem_address = ADDR_SLAVE_INBOX_MAIN_MEM_PING;
+ }
+
+ return l_mem_address;
+}
+
+
+// Function Specification
+//
+// Name: task_dcom_tx_slv_inbox
+//
+// Description: Copy slave inboxes from SRAM to main memory
+// so master can send data to slave
+//
+// Flow: 08/23/11 FN=task_dcom_tx_slv_inbox
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE
+//
+// Changes: @fk005c
+//
+// End Function Specification
+void task_dcom_tx_slv_inbox( task_t *i_self)
+{
+ static bool l_error = FALSE;
+ uint32_t l_orc = OCC_SUCCESS_REASON_CODE;
+ uint32_t l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ uint64_t l_start = ssx_timebase_get();
+ bool l_pwr_meas = FALSE; // @th002
+ bool l_request_reset = FALSE; // @fk005a
+ bool l_ssx_failure = FALSE;
+ // @sb003 Use a static local bool to track whether the BCE request used
+ // here has ever been successfully created at least once
+ static bool L_bce_slv_inbox_tx_request_created_once = FALSE;
+
+ DCOM_DBG("4. TX Slave Inbox\n");
+
+ do
+ {
+ // If we are in standby, we need to fake out
+ // the APSS data since we aren't talking to APSS.
+ if( OCC_STATE_STANDBY == CURRENT_STATE() ) // @th022
+ {
+ G_ApssPwrMeasCompleted = TRUE; // @th022
+ }
+
+ l_pwr_meas = G_ApssPwrMeasCompleted; // @th002
+
+ //did apss pwr complete?
+ if( l_pwr_meas == TRUE ) // @th002
+ {
+#ifdef DCOM_DEBUG
+ uint64_t l_end = ssx_timebase_get();
+ DCOM_DBG("Got APSS after waiting %d us\n",(int)( (l_end-l_start) / ( SSX_TIMEBASE_FREQUENCY_HZ / 1000000 ) ));
+#endif
+
+ //@fk005a
+ APSS_SUCCESS();
+
+ // build/setup inboxes
+ uint32_t l_addr_in_mem = dcom_build_slv_inbox();
+ uint32_t l_ssxrc = 0;
+
+ // @sb003
+ // See dcomMasterRx.c/task_dcom_rx_slv_outboxes for details on the
+ // checking done here before creating and scheduling the request.
+ bool l_proceed_with_request_and_schedule = FALSE;
+ int l_req_idle = async_request_is_idle(&(G_slv_inbox_tx_pba_request.request));
+ int l_req_complete = async_request_completed(&(G_slv_inbox_tx_pba_request.request));
+
+ if (!L_bce_slv_inbox_tx_request_created_once)
+ {
+ // Do this case first, all other cases assume that this is
+ // true!
+ // This is the first time we have created a request so
+ // always proceed with request create and schedule
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && l_req_complete)
+ {
+ // Most likely case first. The request was created
+ // and scheduled and has completed without error. Proceed.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && !l_req_complete)
+ {
+ // There was an error on the schedule request or the request
+ // was scheduled but was canceled, killed or errored out.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv inbox tx request idle but not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_inbox_tx_pba_request.request.callback_rc,
+ G_slv_inbox_tx_pba_request.request.options,
+ G_slv_inbox_tx_pba_request.request.state,
+ G_slv_inbox_tx_pba_request.request.abort_state,
+ G_slv_inbox_tx_pba_request.request.completion_state);
+ TRAC_INFO("Proceeding with BCE slv inbox tx request and schedule");
+ }
+ else if (!l_req_idle && !l_req_complete)
+ {
+ // The request was created and scheduled but is still in
+ // progress or still enqueued OR there was some error
+ // creating the request so it was never scheduled. The latter
+ // case is unlikely and will generate an error message when
+ // it occurs. It will also have to happen after the request
+ // was created at least once or we'll never get here. If the
+ // request does fail though before the state parms in the
+ // request are reset (like a bad parameter error), then this
+ // represents a hang condition that we can't recover from.
+ // DO NOT proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = FALSE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv inbox tx request not idle and not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_inbox_tx_pba_request.request.callback_rc,
+ G_slv_inbox_tx_pba_request.request.options,
+ G_slv_inbox_tx_pba_request.request.state,
+ G_slv_inbox_tx_pba_request.request.abort_state,
+ G_slv_inbox_tx_pba_request.request.completion_state);
+ TRAC_INFO("NOT proceeding with BCE slv inbox tx request and schedule");
+ }
+ // else {// This case can't happen, ignore it.}
+
+ // @sb003 Only proceed if the BCE request state checked out
+ if (l_proceed_with_request_and_schedule)
+ {
+ // set up inboxes copy request
+ l_ssxrc = bce_request_create(
+ &G_slv_inbox_tx_pba_request, // block copy object
+ &G_pba_bcue_queue, // mainstore to sram copy engine
+ l_addr_in_mem, // mainstore address
+ (uint32_t) &G_dcom_slv_inbox_tx[0], // sram starting address
+ sizeof(G_dcom_slv_inbox_tx), // size of copy // @th002
+ SSX_WAIT_FOREVER, // no timeout
+ (AsyncRequestCallback)dcom_tx_slv_inbox_doorbell, // call back
+ NULL, // call back arguments
+ ASYNC_CALLBACK_IMMEDIATE // callback mask
+ );
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_TX_SLV_INBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request create failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_CREATE_FAILURE; // @nh001a
+ l_ssx_failure = TRUE; // @wb001
+ break;
+ }
+
+ // @sb003 Request created at least once
+ L_bce_slv_inbox_tx_request_created_once = TRUE; // @sb013
+ l_ssxrc = bce_request_schedule(&G_slv_inbox_tx_pba_request); // actual copying
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_TX_SLV_INBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request schedule failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_SCHEDULE_FAILURE; // @nh001a
+ l_ssx_failure = TRUE; // @wb001
+ break;
+ }
+ }
+ // @sb023 Moved the break statement here in case we decide not to
+ // schedule the BCE request.
+ break;
+ }
+ else
+ {
+ // check time and break out if we reached limit
+ // @th032 -- TODO: shrink this later depending on how much
+ // work we are doing in RTL
+ if ((ssx_timebase_get() - l_start) < SSX_MICROSECONDS(150))
+ {
+ continue;
+ }
+ else
+ {
+ //Failure occurred, step up the FAIL_COUNT
+ APSS_FAIL();
+
+
+ if (G_apss_fail_updown_count >= APSS_DATA_FAIL_MAX)
+ {
+ TRAC_ERR("task_dcom_tx_slv_inbox: APSS data collection failure exceeded threshold. fail_count=%i, threshold:%i",
+ G_apss_fail_updown_count, APSS_DATA_FAIL_MAX);
+
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_TX_SLV_INBOX
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 N/A
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Time out waiting on power measurement completion
+ */
+ TRAC_ERR("Timed out waiting apss meas completion (dcom_start:%d us, apss_start:%d us, apss_end:%d us)",
+ (int) ((l_start)/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)),
+ (int) ((G_gpe_apss_time_start)/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)),
+ (int) ((G_gpe_apss_time_end)/(SSX_TIMEBASE_FREQUENCY_HZ/1000000))); // @jh00ac
+ l_orc = INTERNAL_FAILURE; // @nh001c
+ l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ l_request_reset = TRUE; // @fk005a
+
+ }
+ break;
+ }
+ }
+
+ } while (1); // @th002
+
+ //If an error exists and we have not logged one before or there's a new request to reset, then log error.
+ if ( (l_orc != OCC_SUCCESS_REASON_CODE) && ((l_error == FALSE) || (l_request_reset == TRUE)))
+ {
+ // create and commit error only once.
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_TASK_TX_SLV_INBOX, //modId
+ l_orc, //reasoncode // @nh001c
+ l_orc_ext, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0 //userdata2
+ );
+
+ // @wb001 -- Callout to firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ if ( FALSE == l_ssx_failure ) // @wb001
+ {
+ // Callout to processor
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+
+ // Callout to APSS
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.apss_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ }
+
+ if (l_request_reset)
+ {
+ REQUEST_RESET(l_errl);
+ }
+ else
+ {
+ commitErrl(&l_errl);
+ }
+
+ l_error = TRUE;
+ l_request_reset = FALSE;
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: dcom_tx_slv_inbox_doorbell
+//
+// Description: transmit doorbells to slaves
+// from master
+//
+// Flow: 08/23/11 FN=dcom_tx_slv_inbox_doorbell
+//
+// End Function Specification
+void dcom_tx_slv_inbox_doorbell( void )
+{
+ int l_pbarc = 0;
+ int l_tmp = 0;
+ int l_jj = 0;
+ uint64_t l_start = ssx_timebase_get();
+
+ /// Caclulate how many 8 byte packets are in the doorbell
+ l_tmp = sizeof( G_dcom_slv_inbox_doorbell_tx ) / sizeof(uint64_t);
+
+ /// Loop through all packets, sending one at a time. It should send
+ /// the previous packet almost immediately, but it is worth noting that
+ /// it is *possible* that the PowerBus is backed up, in which case it may
+ /// take a short amount of time (~1us <TBD>) to send each packet.
+ /// Estimated transfer time, under normal circumstances is 1kB/1us.
+ for(l_jj=0; l_jj<l_tmp; l_jj++)
+ {
+ // Send 8 bytes of multicast doorbell
+ l_pbarc = _pbax_send( &G_pbax_multicast_target, //gm014
+ G_dcom_slv_inbox_doorbell_tx.words[l_jj],
+ SSX_MICROSECONDS(15));
+
+ //Set this global so we know to trace this in the non-critical interrupt context
+ G_pbax_rc = l_pbarc;
+ if ( (l_pbarc != 0 ) )
+ {
+ G_pbax_packet = l_jj;
+ //Trace causes a panic in a critical interrupt! Don't trace here!(tries to pend a semaphore)
+
+ /// Break out of for loop and stop sending the rest of the doorbell
+ /// packets, since this likely occured b/c of a timeout.
+ break;
+ }
+ }
+
+ // <TULETA HW BRINGUP TIMING> @th032
+ uint64_t l_delta = (ssx_timebase_get() - l_start);
+ G_dcomTime.master.doorbellStartTx = l_start;
+ G_dcomTime.master.doorbellStopTx = ssx_timebase_get();
+ G_dcomTime.master.doorbellMaxDeltaTx = (l_delta > G_dcomTime.master.doorbellMaxDeltaTx) ?
+ l_delta : G_dcomTime.master.doorbellMaxDeltaTx;
+ G_dcomTime.master.doorbellSeq = G_dcom_slv_inbox_doorbell_tx.magic_counter;
+ G_dcomTime.master.doorbellNumSent++;
+ // </TULETA HW BRINGUP TIMING> @th032
+
+ DCOM_DBG("Sent multicast doorbell\n");
+} // @th034 - rewrote most of functino
+
+#endif //_DCOMMASTERTOSLAVE_C
+
diff --git a/src/occ/dcom/dcomSlaveRx.c b/src/occ/dcom/dcomSlaveRx.c
new file mode 100644
index 0000000..d7406d8
--- /dev/null
+++ b/src/occ/dcom/dcomSlaveRx.c
@@ -0,0 +1,671 @@
+/******************************************************************************
+// @file dcomSlaveRx.c
+// @brief Slave OCC to Master OCC communication handler
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dcomSlaveRx.c DCOMSLAVERX.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th022 thallet 10/08/2012 Changes for OCC Comm
+ * @th024 thallet 10/16/2012 Cleanup to use modifier function
+ * @th034 879027 thallet 04/18/2013 Broadcast Critical Power over PBAX
+ * @th032 thallet 04/26/2013 Added a bunch of timings for PBAX characterization
+ * @gs016 905781 gjsilva 11/12/2013 Fix for Master->Slave doorbell loss of synchronization
+ * @rt004 908817 tapiar 12/11/2013 Update pcap infromation via write_data_pcap
+ * once doorbell data is verfied
+ * @sb003 908290 sbroyles 12/18/2013 Test BCE request states
+ * @sb013 911625 sbroyles 01/15/2014 Fix to 908290 changes
+ * @wb003 920760 wilbryan 03/25/2014 Update SRCs to match TPMD SRCs
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOMSLAVERX_C
+#define _DCOMSLAVERX_C
+
+/** \defgroup Slave to Master Communication
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <pgp_pmc.h>
+#include "pgp_pba.h"
+#include <rtls.h>
+#include <apss.h>
+#include <dcom.h>
+#include <dcom_service_codes.h>
+#include <occ_service_codes.h>
+#include <trac.h>
+#include <proc_pstate.h>
+#include <amec_data.h> // @rt004a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// SSX Block Copy Request for the Slave Inbox Receive Queue
+BceRequest G_slv_inbox_rx_pba_request;
+
+// SSX PBAX Request for Multicast PBAX Queue (Master Doorbell to Slaves)
+PbaxRequest G_pbax_multicast_request; //does not get used should it??
+
+// SSX PBAX Request for Receiving PBAX Messages
+PbaxRequest G_pbax_rx_request;
+
+// Used by the slave to house the doorbell data that is received from
+// the master multicast doorbell, stating that it put slave inbox in main memory.
+dcom_slv_inbox_doorbell_t G_dcom_slv_inbox_doorbell_rx;
+
+// Make sure that the Slave Inbox RX Buffer is 256B, otherwise cause
+// error on the compile.
+STATIC_ASSERT( (NUM_BYTES_IN_SLAVE_INBOX != (sizeof(G_dcom_slv_inbox_rx))) );
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: dcom_calc_slv_inbox_addr
+//
+// Description: get slave inbox main memory address
+//
+// Flow: 08/23/11 FN=dcom_calc_slv_inbox_addr
+//
+// End Function Specification
+uint32_t dcom_calc_slv_inbox_addr(void)
+{
+ return (G_dcom_slv_inbox_doorbell_rx.addr_slv_inbox_buffer0 + ( G_pob_id.chip_id * sizeof(dcom_slv_inbox_t) ));
+}
+
+
+// Function Specification
+//
+// Name: dcom_rx_slv_inbox_callback
+//
+// Description: Callback to set inbox received to true
+//
+// Flow: FN=None
+//
+// End Function Specification
+void dcom_rx_slv_inbox_callback( void )
+{
+ // AMEC will use this, and reset it when done
+ G_slv_inbox_received = TRUE;
+}
+
+
+// Function Specification
+//
+// Name: task_dcom_rx_slv_inbox
+//
+// Description: Copy Slave inbox from Main Memory to SRAM
+// on slave
+//
+// Flow: 10/24/11 FN=task_dcom_rx_slv_inbox
+//
+// Task Flags: RTL_FLAG_OBS, RTL_FLAG_ACTIVE
+//
+// End Function Specification
+void task_dcom_rx_slv_inbox( task_t *i_self)
+{
+ uint32_t l_orc = OCC_SUCCESS_REASON_CODE;
+ uint32_t l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ uint64_t l_start = ssx_timebase_get();
+ uint32_t l_bytes = 0;
+ // @sb003 Use a static local bool to track whether the BCE request used
+ // here has ever been successfully created at least once
+ static bool L_bce_slv_inbox_rx_request_created_once = FALSE;
+
+ DCOM_DBG("1. RX Slave Inbox\n");
+
+ // Increment debug counter
+ G_dcomSlvInboxCounter.totalTicks++;
+ G_dcomTime.slave.doorbellStartWaitRx = l_start;
+
+ do
+ {
+ l_bytes = dcom_rx_slv_inbox_doorbell();
+ // doorbell from the master
+ if(l_bytes >= sizeof(G_dcom_slv_inbox_doorbell_rx))
+ {
+
+ // looks like we got a valid doorbell so notify slave
+ // code of pcap info @rt004a
+ amec_data_write_pcap();
+
+#ifdef DCOM_DEBUG
+ uint64_t l_end = ssx_timebase_get();
+ DCOM_DBG("Got Doorbell from Master after waiting %d us\n",(int)( (l_end-l_start) / ( SSX_TIMEBASE_FREQUENCY_HZ / 1000000 ) ));
+#endif
+ // <TULETA HW BRINGUP TIMING>
+ G_dcomTime.slave.doorbellStopWaitRx = ssx_timebase_get();
+ uint64_t l_delta = G_dcomTime.slave.doorbellStopWaitRx - G_dcomTime.slave.doorbellStartWaitRx;
+ G_dcomTime.slave.doorbellMaxDeltaWaitRx = (l_delta > G_dcomTime.slave.doorbellMaxDeltaWaitRx) ?
+ l_delta : G_dcomTime.slave.doorbellMaxDeltaWaitRx;
+ G_dcomTime.slave.doorbellNumRx++;
+ // </TULETA HW BRINGUP TIMING>
+
+ // Increment debug counter
+ G_dcomSlvInboxCounter.totalSuccessful++;
+
+ // main memory address
+ uint32_t l_addr_in_mem = dcom_calc_slv_inbox_addr();
+
+ //check valid address (should be inside inbox addresses range)
+ if ( (ADDR_SLAVE_INBOX_MAIN_MEM_PING <= l_addr_in_mem) &&
+ ((ADDR_SLAVE_INBOX_MAIN_MEM_PONG+(sizeof(dcom_slv_inbox_t)*MAX_OCCS)) > l_addr_in_mem) )
+ {
+ uint32_t l_ssxrc = 0;
+ // @sb003
+ // See dcomMasterRx.c/task_dcom_rx_slv_outboxes for details on the
+ // checking done here before creating and scheduling the request.
+ bool l_proceed_with_request_and_schedule = FALSE;
+ int l_req_idle = async_request_is_idle(&(G_slv_inbox_rx_pba_request.request));
+ int l_req_complete = async_request_completed(&(G_slv_inbox_rx_pba_request.request));
+
+ if (!L_bce_slv_inbox_rx_request_created_once)
+ {
+ // Do this case first, all other cases assume that this is
+ // true!
+ // This is the first time we have created a request so
+ // always proceed with request create and schedule
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && l_req_complete)
+ {
+ // Most likely case first. The request was created
+ // and scheduled and has completed without error. Proceed.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && !l_req_complete)
+ {
+ // There was an error on the schedule request or the request
+ // was scheduled but was canceled, killed or errored out.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv inbox rx request idle but not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_inbox_rx_pba_request.request.callback_rc,
+ G_slv_inbox_rx_pba_request.request.options,
+ G_slv_inbox_rx_pba_request.request.state,
+ G_slv_inbox_rx_pba_request.request.abort_state,
+ G_slv_inbox_rx_pba_request.request.completion_state);
+ TRAC_INFO("Proceeding with BCE slv inbox rx request and schedule");
+ }
+ else if (!l_req_idle && !l_req_complete)
+ {
+ // The request was created and scheduled but is still in
+ // progress or still enqueued OR there was some error
+ // creating the request so it was never scheduled. The latter
+ // case is unlikely and will generate an error message when
+ // it occurs. It will also have to happen after the request
+ // was created at least once or we'll never get here. If the
+ // request does fail though before the state parms in the
+ // request are reset (like a bad parameter error), then this
+ // represents a hang condition that we can't recover from.
+ // DO NOT proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = FALSE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv inbox rx request not idle and not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_inbox_rx_pba_request.request.callback_rc,
+ G_slv_inbox_rx_pba_request.request.options,
+ G_slv_inbox_rx_pba_request.request.state,
+ G_slv_inbox_rx_pba_request.request.abort_state,
+ G_slv_inbox_rx_pba_request.request.completion_state);
+ TRAC_INFO("NOT proceeding with BCE slv inbox rx request and schedule");
+ }
+ // else {// This case can't happen, ignore it.}
+
+ // @sb003 Only proceed if the BCE request state checked out
+ if (l_proceed_with_request_and_schedule)
+ {
+ // copy request from main memory to SRAM
+ l_ssxrc = bce_request_create(
+ &G_slv_inbox_rx_pba_request, // block copy object
+ &G_pba_bcde_queue, // mainstore to sram copy engine
+ l_addr_in_mem, // mainstore address
+ (uint32_t)&G_dcom_slv_inbox_rx, // sram starting address
+ sizeof(G_dcom_slv_inbox_rx), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ (AsyncRequestCallback)dcom_rx_slv_inbox_callback, // call back
+ NULL, // call back arguments
+ ASYNC_CALLBACK_IMMEDIATE // blocking request
+ );
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_RX_SLV_INBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request create failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_CREATE_FAILURE; // @nh001a
+ break;
+ }
+
+ // @sb003 Request created at least once
+ L_bce_slv_inbox_rx_request_created_once = TRUE; // @sb013
+ l_ssxrc = bce_request_schedule(&G_slv_inbox_rx_pba_request); // actual copying
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_RX_SLV_INBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request schedule failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_SCHEDULE_FAILURE; // @nh001a
+ break;
+ }
+ break; // @th002
+ }
+ }
+ else
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_RX_SLV_INBOX
+ * @reasoncode INTERNAL_INVALID_INPUT_DATA
+ * @userdata1 N/A
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware related internal error
+ */
+ TRAC_ERR("Invalid address from calculate slave inbox address function [%08X]", l_addr_in_mem );
+ l_orc = INTERNAL_INVALID_INPUT_DATA; // @wb003
+ l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ break;
+ }
+ break; // @th002
+ }
+ else
+ {
+ if(l_bytes)
+ {
+ TRAC_INFO("Only got %d bytes from master",l_bytes);
+ }
+ // check time and break out if we reached limit
+ if ((ssx_timebase_get() - l_start) < SSX_MICROSECONDS(100)) // @th002 -- TODO: shrink this down later
+ {
+ continue;
+ }
+ else
+ {
+#if 0
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_RX_SLV_INBOX
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_GENERIC_TIMEOUT
+ * @devdesc Generic timeout failure
+ */
+ TRAC_ERR("Time out waiting for receive doorbell" );
+ l_orc = INTERNAL_FAILURE; // @nh001c
+ l_orc_ext = ERC_GENERIC_TIMEOUT; // @nh001a
+#endif
+ // TODO: We need to signal this
+
+ // <TULETA HW BRINGUP TIMING>
+ G_dcomTime.slave.doorbellErrorFlags.timeoutRx = 1;
+ G_dcomTime.slave.doorbellTimeoutWaitRx = ssx_timebase_get();
+ // <TULETA HW BRINGUP TIMING>
+
+ // Let's signal that master is not ready, and then
+ // start task waiting for master to talk again.
+ rtl_start_task(TASK_ID_DCOM_WAIT_4_MSTR); // @th024
+ rtl_set_run_mask_deferred(RTL_FLAG_MSTR_READY);
+ TRAC_INFO("[%d]: Lost connection to master",(int) G_pob_id.chip_id);
+ break;
+ }
+ }
+ }
+ while( 1 ); // @th002
+
+
+ if ( l_orc != OCC_SUCCESS_REASON_CODE )
+ {
+ // create and commit error
+ dcom_error_check( SLAVE_INBOX, FALSE, l_orc, l_orc_ext); // @nh001c
+ }
+ else
+ {
+ // done, lets clear our counter
+ dcom_error_check_reset( SLAVE_INBOX );
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: dcom_rx_slv_inbox_doorbell
+//
+// Description: receive multicast doorbell and save data
+// from master (master to slave)
+//
+// Flow: 09/02/11 FN=dcom_rx_slv_inbox_doorbell
+//
+// End Function Specification
+uint32_t dcom_rx_slv_inbox_doorbell( void )
+{
+ static bool l_trace_once = FALSE;
+ int l_pbarc = 0;
+ uint32_t l_read = 0;
+ uint32_t l_bytes_so_far = 0;
+ uint64_t l_start = ssx_timebase_get();
+
+ G_dcomTime.slave.doorbellStartRx = l_start;
+
+ while(l_bytes_so_far < sizeof(G_dcom_slv_inbox_doorbell_rx))
+ {
+ /// Read 8 bytes of the doorbell from master
+ l_pbarc = pbax_read(
+ &G_pbax_read_queue[0],
+ &G_dcom_slv_inbox_doorbell_rx.words[(l_bytes_so_far / sizeof(uint64_t))],
+ sizeof(uint64_t), // Must read 8 bytes at a time
+ &l_read
+ );
+
+ DCOM_DBG("Doorbell (Multicast) Read: %d bytes\n",l_read);
+
+ /// We got an error reading from the PBAX, return to caller
+ if ( l_pbarc != 0 )
+ {
+ G_dcomTime.slave.doorbellErrorFlags.hwError = 1;
+ if ( FALSE == l_trace_once )
+ {
+ // failure occurred but only trace it once
+ TRAC_ERR("PBAX Read Failure in receiving multicast doorbell - RC[%08X]", l_pbarc);
+ l_trace_once = TRUE;
+ }
+ break;
+ }
+
+ /// Didn't read any bytes from pbax. We are either done, or we
+ /// simply don't have any data to read
+ if(0 == l_read){
+ if ((ssx_timebase_get() - l_start) > SSX_MICROSECONDS(3))
+ {
+ // <TULETA HW BRINGUP TIMING>
+ if(l_bytes_so_far){
+ G_dcomTime.slave.doorbellErrorFlags.incomplete = 1;
+ }
+ else{
+ G_dcomTime.slave.doorbellErrorFlags.timeout = 1;
+ }
+ // </TULETA HW BRINGUP TIMING>
+ break;
+ }
+ }
+ else{
+ /// If we just read some data, reset this EndOfMessage counter
+ l_start = ssx_timebase_get();
+ }
+
+ /// Increment the number of bytes we have in the buffer
+ l_bytes_so_far += l_read;
+
+ /// If it doesnt match the magic number, and it's the first
+ /// packet we read, just drop it on the floor and start over
+ if( 8 == l_bytes_so_far)
+ {
+ if(PBAX_MAGIC_NUMBER2_32B != G_dcom_slv_inbox_doorbell_rx.magic1)
+ {
+ l_read = 0;
+ l_bytes_so_far = 0;
+ G_dcomTime.slave.doorbellErrorFlags.dropPacket = 1;
+
+ TRAC_INFO("Slave Inbox - Start Magic Number Mismatch [0x%08X]",
+ G_dcom_slv_inbox_doorbell_rx.magic1);
+ }
+ }
+ /// If this is the last packet, make sure the magic number matches
+ else if (sizeof(G_dcom_slv_inbox_doorbell_rx) == l_bytes_so_far)
+ {
+ if(PBAX_MAGIC_NUMBER_32B != G_dcom_slv_inbox_doorbell_rx.magic2)
+ {
+ TRAC_INFO("Slave Inbox - End Magic Number Mismatch [0x%08X]",
+ G_dcom_slv_inbox_doorbell_rx.magic2);
+ G_dcomTime.slave.doorbellErrorFlags.badMagicNumEnd = 1;
+
+ /// Decrement the number of bytes we return so it fails
+ /// any valid length checks, but still indicates to us that
+ /// we 'got' data, just not good data if it is included in
+ /// an error log.
+ l_bytes_so_far = (sizeof(G_dcom_slv_inbox_doorbell_rx) - 1);
+ }
+ else
+ {
+ // <TULETA HW BRINGUP TIMING>
+ if(G_dcom_slv_inbox_doorbell_rx.magic_counter != (G_dcomTime.slave.doorbellSeq + 1))
+ {
+ G_dcomTime.slave.doorbellErrorFlags.badSequence = 1;
+ }
+ G_dcomTime.slave.doorbellSeq = G_dcom_slv_inbox_doorbell_rx.magic_counter;
+ // </TULETA HW BRINGUP TIMING>
+ }
+ break;
+ }
+ }
+
+ // <TULETA HW BRINGUP TIMING>
+ G_dcomTime.slave.doorbellStopRx = ssx_timebase_get();
+ uint64_t l_delta = G_dcomTime.slave.doorbellStopRx - G_dcomTime.slave.doorbellStartRx;
+ G_dcomTime.slave.doorbellMaxDeltaRx = (l_delta > G_dcomTime.slave.doorbellMaxDeltaRx) ?
+ l_delta : G_dcomTime.slave.doorbellMaxDeltaRx;
+ // </TULETA HW BRINGUP TIMING>
+
+ return l_bytes_so_far;
+} // @th034 -- rewrote most of function
+
+
+// Function Specification
+//
+// Name: task_dcom_wait_for_master
+//
+// Description: The purpose of this task is to wait for the reception of the
+// first master multicast doorbell. After it is received, it sets
+// a RTL flag indicating as such.
+//
+// Flow: 09/27/11 FN=task_dcom_wait_for_master
+//
+// End Function Specification
+#define POBID_RETRIES 2
+void task_dcom_wait_for_master( task_t *i_self)
+{
+ // Don't try and read the doorbell on the first tick of the RTL.
+ // If we do, then we will clear the RTL flags too early, and the actual
+ // task will miss the doorbell.
+ // This task will skip executing once every 12.41 days b/c of a rollover of
+ // CURRENT_TICK. This is not a concern, so we won't bother to check that case.
+ int l_rc = 0;
+ pbax_id_t l_pbaxid;
+ uint32_t l_num_read = 0; // @th034
+ static bool L_first_doorbell_rcvd = FALSE;
+ static bool L_queue_enabled = FALSE;
+ static uint32_t L_pobid_retries_left = POBID_RETRIES;
+
+ DCOM_DBG("0. Wait for Master\n");
+
+
+ do
+ {
+ /// If this is the first time we are in this task, enable
+ /// the queue, since now until forever we are able to read from it.
+ if(!L_queue_enabled)
+ {
+ pbax_queue_enable(&G_pbax_read_queue[0]);
+ L_queue_enabled = TRUE;
+ }
+
+ l_num_read = (CURRENT_TICK) ? dcom_rx_slv_inbox_doorbell() : 0; // @th034
+
+ G_dcomSlvInboxCounter.totalTicks++;
+
+ if(l_num_read < sizeof(G_dcom_slv_inbox_doorbell_rx))
+ {
+ // Don't log an error if we don't get doorbell within any certain timeout
+ // period. This will be taken care of by another function
+ break;
+ }
+
+ // Special handling for recieving the 1st master doorbell since we need to also
+ // set up a unicast PBAX target to the master -- gm037
+ if(!L_first_doorbell_rcvd)
+ {
+ //convert powerbus id to pbax id (sets node_id to INVALID_NODE_ID on failure)
+ l_pbaxid = dcom_pbusid2pbaxid(G_dcom_slv_inbox_doorbell_rx.pob_id); //traces failure internally
+ if(l_pbaxid.node_id == INVALID_NODE_ID)
+ {
+ //we received an invalid power bus id from the master.
+ //This may be a communication failure, so allow some retries
+ if(L_pobid_retries_left)
+ {
+ L_pobid_retries_left--;
+ break;
+ }
+
+ //retries exceeded. Log error and request reset.
+
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_WAIT_FOR_MASTER
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc An invalid power bus ID was sent from the master OCC
+ */
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_WAIT_FOR_MASTER, //modId
+ INTERNAL_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0 //userdata2
+ );
+
+ // commit log and request reset
+ REQUEST_RESET(l_errl);
+
+ break;
+ }
+
+ //Set up the master pbax unicast target for sending doorbells to the master
+ l_rc = pbax_target_create(&G_pbax_unicast_target, //target
+ PBAX_UNICAST, //type
+ PBAX_GROUP, //scope
+ 1, //queue
+ l_pbaxid.node_id, //node
+ l_pbaxid.chip_id); //chip (or group) id
+ if(l_rc)
+ {
+ //log an error and request reset when pbax_target_create fails
+
+ TRAC_ERR("pbax_target_create failed creating pbax target to master OCC. rc=%d, node=%d, chip=%d",
+ l_rc,
+ l_pbaxid.node_id,
+ l_pbaxid.chip_id);
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_WAIT_FOR_MASTER
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 SSX RC
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure initializing a PBAX queue
+ */
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_WAIT_FOR_MASTER, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit log and request reset -- @gm007
+ REQUEST_RESET(l_errl);
+
+ break;
+ }
+
+ TRAC_IMP("Slave OCC[%d] Received first doorbell from Master OCC[%d]",
+ (int) G_pob_id.chip_id,
+ G_dcom_slv_inbox_doorbell_rx.pob_id.chip_id);
+
+ // First message is dropped, so mark it as counted.
+ G_dcomSlvInboxCounter.totalTicks = 0;
+ G_dcomSlvInboxCounter.totalSuccessful = 0;
+ G_dcomSlvInboxCounter.currentFailCount = 0;
+
+ // initialization was successful
+ L_first_doorbell_rcvd = TRUE;
+
+ }
+ else
+ {
+ TRAC_INFO("[%d] Restablished contact via doorbell from Master",(int) G_pob_id.chip_id); // @th002
+ }
+
+ //got a multicast doorbell
+ G_dcomTime.slave.doorbellNumWaitRx++; // @th032
+
+ //set MASTER READY on global RTL FLAG
+ rtl_clr_run_mask_deferred(RTL_FLAG_MSTR_READY); // @th032
+
+ //CLEAR the RTL run FLAG for current task
+ rtl_stop_task(TASK_ID_DCOM_WAIT_4_MSTR); // @th024
+
+ }while(0);
+
+}
+
+
+#endif //_DCOMSLAVERX_C
+
diff --git a/src/occ/dcom/dcomSlaveTx.c b/src/occ/dcom/dcomSlaveTx.c
new file mode 100755
index 0000000..b259607
--- /dev/null
+++ b/src/occ/dcom/dcomSlaveTx.c
@@ -0,0 +1,431 @@
+/******************************************************************************
+// @file dcomSlaveTx.c
+// @brief Slave OCC to Master OCC communication handler
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dcomSlaveTx.c DCOMSLAVETX.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @00 abagepa 10/10/2011 Created
+ * @th002 thallet 11/01/2011 Misc Changes for Nov 1st Milestone
+ * @th005 thallet 11/23/2011 Added STATIC_ASSERT checks
+ * @01 tapiar 11/12/2011 Stage 3 updates
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th010 thallet 07/11/2012 Pstate Enablement`
+ * @th022 thallet 10/08/2012 Changes for OCC Comm
+ * @rt001 897459 tapiar 08/19/2013 Upd: save active node pcap from doorbell
+ * @gm014 907707 milesg 12/05/2013 don't panic on pbax_send timeout failures
+ * @rt004 908817 tapiar 12/11/2013 Save of valid pcap field so master can use it
+ * @sb003 908290 sbroyles 12/18/2013 Test BCE request states
+ * @sb013 911625 sbroyles 01/15/2014 Fix to 908290 changes
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOMSLAVETX_C
+#define _DCOMSLAVETX_C
+
+/** \defgroup Slave to Master Communication
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <pgp_pmc.h>
+#include "pgp_pba.h"
+#include <rtls.h>
+#include <apss.h>
+#include <dcom.h>
+#include <dcom_service_codes.h>
+#include <occ_service_codes.h>
+#include <trac.h>
+#include <proc_pstate.h>
+#include <amec_sys.h> // @rt001a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// SSX Block Copy Request for the Slave Outbox Transmit Queue
+BceRequest G_slv_outbox_tx_pba_request;
+
+// SSX PBAX Request for Unicast PBAX Queue (Slave Doorbell to Master)
+PbaxRequest G_pbax_unicast_request;
+
+// Used by the slave to house the doorbell data that is sent in
+// the slave unicast doorbell, stating that it put slave outbox in main memory.
+// *
+dcom_slv_outbox_doorbell_t G_dcom_slv_outbox_doorbell_tx;
+
+// Make sure that the Slave Outbox TX Buffer is 1kB, otherwise cause
+// error on the compile.
+STATIC_ASSERT( (NUM_BYTES_IN_SLAVE_OUTBOX != (sizeof(G_dcom_slv_outbox_tx))) );
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: dcom_build_slv_outbox
+//
+// Description: The purpose of this function is to fill out the Sensor Data into the
+// Slave Outbox Structures for transfer to the Master.
+// Build the slave outboxes so slave can send to master
+//
+// Flow: 09/21/11 FN=dcom_build_slv_outbox
+//
+// End Function Specification
+
+uint32_t dcom_build_slv_outbox(void)
+{
+ // Locals
+ uint32_t l_addr_of_slv_outbox_in_main_mem = 0;
+
+ static uint8_t L_seq = 0xFF;
+
+ L_seq++;
+
+ G_dcom_slv_outbox_tx.seq = L_seq;
+ G_dcom_slv_outbox_tx.version = 0;
+
+ memset( G_dcom_slv_outbox_tx.occ_fw_mailbox, 0, sizeof( G_dcom_slv_outbox_tx.occ_fw_mailbox ));
+
+ G_dcom_slv_outbox_tx.counter++; // @th002
+
+ // @01
+ // call dcom_build_occfw_msg
+ dcom_build_occfw_msg( SLAVE_OUTBOX );
+
+ // Create message that will be sent to DCM peer
+ dcom_build_dcm_sync_msg( SLAVE_OUTBOX ); // @th010
+
+ l_addr_of_slv_outbox_in_main_mem = dcom_which_buffer_slv_outbox();
+
+ l_addr_of_slv_outbox_in_main_mem += G_pob_id.chip_id*sizeof(dcom_slv_outbox_t);
+
+ G_dcom_slv_outbox_doorbell_tx.pob_id = G_pob_id;
+ G_dcom_slv_outbox_doorbell_tx.pcap_valid = g_amec->pcap_valid; //@rt004a
+ G_dcom_slv_outbox_doorbell_tx.active_node_pcap = g_amec->pcap.active_node_pcap; //@rt001a
+ G_dcom_slv_outbox_doorbell_tx.addr_slv_outbox_buffer = l_addr_of_slv_outbox_in_main_mem;
+
+
+ return l_addr_of_slv_outbox_in_main_mem;
+}
+
+
+// Function Specification
+//
+// Name: dcom_which_buffer_slv_outbox
+//
+// Description: Determines which buffer in the 'double buffer'
+// or ping/pong to use. Basically alternates between
+// returning the ping or the pong address
+//
+// Flow: 09/21/11 FN=dcom_which_buffer_slv_outbox
+//
+// End Function Specification
+
+uint32_t dcom_which_buffer_slv_outbox(void)
+{
+ //Locals
+ uint32_t l_mem_address = ADDR_SLAVE_OUTBOX_MAIN_MEM_PONG;
+
+ // switch back and forth based on tick
+ if( CURRENT_TICK & 1 )
+ {
+ l_mem_address = ADDR_SLAVE_OUTBOX_MAIN_MEM_PING;
+ }
+
+ return l_mem_address;
+}
+
+
+// Function Specification
+//
+// Name: dcom_calc_slv_outbox_addr
+//
+// Description: get slave outbox main memory address
+//
+// Flow: 09/20/11 FN=dcom_calc_slv_outbox_addr
+//
+// End Function Specification
+uint32_t dcom_calc_slv_outbox_addr( const dcom_slv_outbox_doorbell_t * i_doorbell, uint8_t * o_occ_id )
+{
+ *o_occ_id = i_doorbell->pob_id.chip_id;
+ return i_doorbell->addr_slv_outbox_buffer;
+}
+
+
+// Function Specification
+//
+// Name: task_dcom_tx_slv_outbox
+//
+// Description: Copy slave outboxes from SRAM to main memory
+// so slave can send data to master
+//
+// Flow: 09/21/11 FN=task_dcom_tx_slv_outbox
+//
+// Task Flags: RTL_FLAG_NONMSTR, RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE,
+// RTL_FLAG_NOAPSS, RTL_FLAG_RUN, RTL_FLAG_MSTR_READY
+//
+// End Function Specification
+void task_dcom_tx_slv_outbox( task_t *i_self)
+{
+ static bool l_error = FALSE;
+ uint32_t l_orc = OCC_SUCCESS_REASON_CODE;
+ uint32_t l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ // @sb003 Use a static local bool to track whether the BCE request used
+ // here has ever been successfully created at least once
+ static bool L_bce_slv_outbox_tx_request_created_once = FALSE;
+
+ DCOM_DBG("3. TX Slave Outboxes\n");
+
+ do
+ {
+ // build/setup outbox
+ uint32_t l_addr_in_mem = dcom_build_slv_outbox();
+ uint32_t l_ssxrc = 0;
+
+ // @sb003
+ // See dcomMasterRx.c/task_dcom_rx_slv_outboxes for details on the
+ // checking done here before creating and scheduling the request.
+ bool l_proceed_with_request_and_schedule = FALSE;
+ int l_req_idle = async_request_is_idle(&(G_slv_outbox_tx_pba_request.request));
+ int l_req_complete = async_request_completed(&(G_slv_outbox_tx_pba_request.request));
+
+ if (!L_bce_slv_outbox_tx_request_created_once)
+ {
+ // Do this case first, all other cases assume that this is
+ // true!
+ // This is the first time we have created a request so
+ // always proceed with request create and schedule
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && l_req_complete)
+ {
+ // Most likely case first. The request was created
+ // and scheduled and has completed without error. Proceed.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && !l_req_complete)
+ {
+ // There was an error on the schedule request or the request
+ // was scheduled but was canceled, killed or errored out.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv outbox tx request idle but not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_outbox_tx_pba_request.request.callback_rc,
+ G_slv_outbox_tx_pba_request.request.options,
+ G_slv_outbox_tx_pba_request.request.state,
+ G_slv_outbox_tx_pba_request.request.abort_state,
+ G_slv_outbox_tx_pba_request.request.completion_state);
+ TRAC_INFO("Proceeding with BCE slv outbox tx request and schedule");
+ }
+ else if (!l_req_idle && !l_req_complete)
+ {
+ // The request was created and scheduled but is still in
+ // progress or still enqueued OR there was some error
+ // creating the request so it was never scheduled. The latter
+ // case is unlikely and will generate an error message when
+ // it occurs. It will also have to happen after the request
+ // was created at least once or we'll never get here. If the
+ // request does fail though before the state parms in the
+ // request are reset (like a bad parameter error), then this
+ // represents a hang condition that we can't recover from.
+ // DO NOT proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = FALSE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv outbox tx request not idle and not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_outbox_tx_pba_request.request.callback_rc,
+ G_slv_outbox_tx_pba_request.request.options,
+ G_slv_outbox_tx_pba_request.request.state,
+ G_slv_outbox_tx_pba_request.request.abort_state,
+ G_slv_outbox_tx_pba_request.request.completion_state);
+ TRAC_INFO("NOT proceeding with BCE slv outbox tx request and schedule");
+ }
+ // else {// This case can't happen, ignore it.}
+
+ // @sb003 Only proceed if the BCE request state checked out
+ if (l_proceed_with_request_and_schedule)
+ {
+ // set up outbox copy request
+ l_ssxrc = bce_request_create(
+ &G_slv_outbox_tx_pba_request, // block copy object
+ &G_pba_bcue_queue, // mainstore to sram copy engine
+ l_addr_in_mem, // mainstore address
+ (uint32_t) &G_dcom_slv_outbox_tx, // sram starting address
+ sizeof(G_dcom_slv_outbox_tx), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ (AsyncRequestCallback)dcom_tx_slv_outbox_doorbell, // call back
+ NULL, // call back arguments
+ ASYNC_CALLBACK_IMMEDIATE // callback mask
+ );
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_TX_SLV_OUTBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request create failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_CREATE_FAILURE; // @nh001a
+ break;
+ }
+
+ // @sb003 Request created at least once
+ L_bce_slv_outbox_tx_request_created_once = TRUE; // @sb013
+ l_ssxrc = bce_request_schedule(&G_slv_outbox_tx_pba_request); // actual copying
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_TX_SLV_OUTBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request schedule failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_SCHEDULE_FAILURE; // @nh001a
+ break;
+ }
+ }
+
+ } while (0);
+
+
+ if ( l_orc != OCC_SUCCESS_REASON_CODE && l_error == FALSE)
+ {
+ // create and commit error
+ // see return code doxygen tags for error description
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_TASK_TX_SLV_OUTBOX, //modId
+ l_orc, //reasoncode // @nh001c
+ l_orc_ext, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0 //userdata2
+ );
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ commitErrl( &l_errl );
+
+ // TODO request a reset
+ l_error = TRUE;
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: dcom_tx_slv_outbox_doorbell
+//
+// Description: transmit unicast doorbell to master
+// from slaves
+//
+// Flow: 09/21/11 FN=dcom_tx_slv_outbox_doorbell
+//
+// End Function Specification
+void dcom_tx_slv_outbox_doorbell( void )
+{
+ static bool l_error = FALSE;
+ int l_pbarc = 0;
+ uint64_t l_tmp =0;
+
+ // save into temp
+ memcpy( &l_tmp, &G_dcom_slv_outbox_doorbell_tx, sizeof(dcom_slv_outbox_doorbell_t));
+
+ // send unicast doorbell
+ l_pbarc = _pbax_send( //gm014
+ &G_pbax_unicast_target,
+ l_tmp,
+ SSX_MICROSECONDS(15));
+
+ if ( l_pbarc != 0 && l_error == FALSE )
+ {
+ //failure occurred
+ //This is running in a critical interrupt context. Tracing not allowed!
+ //TRAC_ERR("PBAX Send Failure in transimitting unicast doorbell - RC[%08X]", l_pbarc);
+
+ l_error = TRUE;
+
+ // create and commit error
+#if 0 //try again on the next tick
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_SLV_OUTBOX_TX_DOORBELL
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX PBAX related failure
+ */
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_SLV_OUTBOX_TX_DOORBELL, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0 //userdata2
+ );
+
+ commitErrl( &l_errl );
+
+ //TODO request a reset
+#endif
+ }
+}
+
+
+#endif //_DCOMSLAVETOMASTER_C
+
diff --git a/src/occ/dcom/dcom_service_codes.h b/src/occ/dcom/dcom_service_codes.h
new file mode 100755
index 0000000..761e95e
--- /dev/null
+++ b/src/occ/dcom/dcom_service_codes.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+// @file dcom_service_codes.h
+// @brief Error codes for dcom component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _dcom_service_codes_h dcom_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * abagepa 09/19/2011 Created new file
+ * @01 tapiar 10/09/2011 State 2 updates
+ * @02 tapiar 11/09/2011 State 3 updates
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOM_SERVICE_CODES_H_
+#define _DCOM_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum dcomModuleId
+{
+ DCOM_MID_INIT_ROLES = DCOM_COMP_ID | 0x00,
+ DCOM_MID_TASK_RX_SLV_INBOX = DCOM_COMP_ID | 0x01,
+ DCOM_MID_TASK_TX_SLV_INBOX = DCOM_COMP_ID | 0x02,
+ DCOM_MID_INIT_PBAX_QUEUES = DCOM_COMP_ID | 0x03,
+ DCOM_MID_TASK_RX_SLV_OUTBOX = DCOM_COMP_ID | 0x04, //@01a
+ DCOM_MID_TASK_TX_SLV_OUTBOX = DCOM_COMP_ID | 0x05, //@01a
+ DCOM_MID_SLV_OUTBOX_TX_DOORBELL = DCOM_COMP_ID | 0x06, //@01a
+ DCOM_MID_TASK_WAIT_FOR_MASTER = DCOM_COMP_ID | 0x07, //@01a
+ DCOM_MID_ERROR_CHECK = DCOM_COMP_ID | 0x08, //@02a
+ DCOM_MID_WAIT_FOR_MASTER = DCOM_COMP_ID | 0x09, //@gm037
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _DCOM_SERVICE_CODES_H_ */
diff --git a/src/occ/dcom/dcom_thread.c b/src/occ/dcom/dcom_thread.c
new file mode 100755
index 0000000..fe62a1f
--- /dev/null
+++ b/src/occ/dcom/dcom_thread.c
@@ -0,0 +1,223 @@
+/******************************************************************************
+// @file dcom_thread.c
+// @brief OCC to OCC communication handler thread
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dcom_thread.c DCOM_THREAD.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th022 thallet 07/11/2012 Pstate Enablement
+ * @th025 857856 thallet 10/16/2012 Dcom Master/Slave SMS part 2
+ * @th032 thallet 04/16/2013 Tuleta HW Bringup
+ * @th035 881654 thallet 05/06/2013 Tuleta Bringup Pstate Fixes
+ * @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
+ * @th042 892056 thallet 07/19/2013 Send OCC to safe mode if first APSS GPE fails
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOM_THREAD_C
+#define _DCOM_THREAD_C
+
+/** \defgroup OCC-OCC Communication
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <pgp_pmc.h>
+#include "pgp_pba.h"
+#include <rtls.h>
+#include <apss.h>
+#include <dcom.h>
+#include <dcom_service_codes.h>
+#include <occ_service_codes.h>
+#include <trac.h>
+#include <state.h>
+#include <proc_pstate.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Debug Counter to make sure dcom thread is running
+uint16_t G_dcom_thread_counter = 0;
+
+SsxSemaphore G_dcomThreadWakeupSem; // @th025
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
+// Function Specification
+//
+// Name: Dcom_thread_routine
+//
+// Description: Purpose of this task is to handle messages passed from
+// Master to Slave and vice versa.
+//
+// Nothing in this thread should be time-critical, but should
+// happen more often than the 1-second that other threads run
+// at.
+//
+// This thread currently runs ~1ms, based on the RTL loop of
+// 250us.
+//
+// FWIW -- It is pointless to set this thread to run any more
+// often than the length of the RTL loop, since it is acting
+// on data passed back and forth via that loop.
+//
+// Flow: XX-XX-XX FN=
+//
+// End Function Specification
+void Dcom_thread_routine(void *arg)
+{
+ OCC_STATE l_newOccState = 0;
+ OCC_MODE l_newOccMode = 0;
+ SsxTimer l_timeout_timer;
+ errlHndl_t l_errlHndl = NULL; // @at015a
+ // --------------------------------------------------
+ // Create a timer that pops every 10 seconds to wake up
+ // this thread, in case a semaphore never gets posted.
+ // TODO: Is this really needed? @th035
+ // --------------------------------------------------
+ ssx_timer_create(&l_timeout_timer,
+ (SsxTimerCallback) ssx_semaphore_post,
+ (void *) &G_dcomThreadWakeupSem);
+ ssx_timer_schedule(&l_timeout_timer,
+ SSX_SECONDS(10),
+ SSX_SECONDS(10));
+
+ for(;;)
+ {
+ // --------------------------------------------------
+ // Wait on Semaphore until we get new data over DCOM
+ // (signalled by sem_post() or timeout occurs.
+ // Sem timeout is designed to be the slowest
+ // interval we will attempt to run this thread at.
+ // --------------------------------------------------
+
+ // Wait for sem_post before we run through this thread.
+ ssx_semaphore_pend(&G_dcomThreadWakeupSem, SSX_WAIT_FOREVER); // @th035
+
+ // --------------------------------------------------
+ // Counter to ensure thread is running (can wrap)
+ // --------------------------------------------------
+ G_dcom_thread_counter++;
+
+ // --------------------------------------------------
+ // Check if we need to update the sapphire table
+ // --------------------------------------------------
+ if(G_sysConfigData.system_type.kvm) //gm025
+ {
+ proc_check_for_sapphire_updates();
+ }
+
+ // --------------------------------------------------
+ // Set Mode and State Based on Master
+ // --------------------------------------------------
+ l_newOccState = (G_occ_master_state == CURRENT_STATE()) ? OCC_STATE_NOCHANGE : G_occ_master_state;
+ // @at019a
+ if(G_sysConfigData.system_type.kvm)
+ {
+ l_newOccMode = (G_occ_master_mode == G_occ_external_req_mode_kvm ) ? OCC_MODE_NOCHANGE : G_occ_master_mode;
+ }
+ else
+ {
+ l_newOccMode = (G_occ_master_mode == CURRENT_MODE() ) ? OCC_MODE_NOCHANGE : G_occ_master_mode;
+ }
+
+ // Override State if SAFE state is requested -- @th042
+ l_newOccState = ( isSafeStateRequested() ) ? OCC_STATE_SAFE : l_newOccState;
+
+ // Override State if we are in SAFE state already -- @th042
+ l_newOccState = ( OCC_STATE_SAFE == CURRENT_STATE() ) ? OCC_STATE_NOCHANGE : l_newOccState;
+
+ if( (OCC_STATE_NOCHANGE != l_newOccState)
+ || (OCC_MODE_NOCHANGE != l_newOccMode) )
+ {
+ // If we're active, then we should always process the mode change first
+ // If we're not active, then we should always process the state change first
+ // @at015c - start
+ if(OCC_STATE_ACTIVE == CURRENT_STATE())
+ {
+ // Set the new mode
+ l_errlHndl = SMGR_set_mode(l_newOccMode, 0 /* TODO V/F */ );
+ if(l_errlHndl)
+ {
+ commitErrl(&l_errlHndl);
+ }
+ // Set the new state
+ l_errlHndl = SMGR_set_state(l_newOccState);
+ if(l_errlHndl)
+ {
+ commitErrl(&l_errlHndl);
+ }
+ }
+ else
+ {
+ // Set the new state
+ l_errlHndl = SMGR_set_state(l_newOccState);
+ if(l_errlHndl)
+ {
+ commitErrl(&l_errlHndl);
+ }
+ // Set the new mode
+ l_errlHndl = SMGR_set_mode(l_newOccMode, 0 /* TODO V/F */ );
+ if(l_errlHndl)
+ {
+ commitErrl(&l_errlHndl);
+ }
+ }
+ // @at015c - end
+ }
+
+ // --------------------------------------------------
+ // DCM PStates
+ // \_ can do sem_post to increment through state machine
+ // --------------------------------------------------
+ if(OCC_STATE_SAFE != CURRENT_STATE()) // @th042
+ {
+ proc_gpsm_dcm_sync_enable_pstates_smh();
+ }
+
+ // --------------------------------------------------
+ // SSX Sleep
+ // --------------------------------------------------
+ // Even if semaphores are continually posted, there is no reason
+ // for us to run this thread any more often than once every 250us
+ // so we don't starve any other thread
+ ssx_sleep(SSX_MICROSECONDS(250)); // @th025
+ }
+}
+
+#endif //_DCOM_THREAD_C
+
diff --git a/src/occ/debug_trace.mk b/src/occ/debug_trace.mk
new file mode 100755
index 0000000..4e3367e
--- /dev/null
+++ b/src/occ/debug_trace.mk
@@ -0,0 +1,76 @@
+# $Id$
+
+# @file debug_trace.mk
+#
+# @brief mk occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section debug_trace.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc001 rickylie 01/09/2012 Created
+#
+# @endverbatim
+#
+
+#*******************************************************************************
+# Defines
+#*******************************************************************************
+#//>@rc001a
+
+ifdef MAIN_DEBUG
+D += -DMAIN_DEBUG=1
+endif
+
+ifdef RTLS_DEBUG
+D += -DRTLS_DEBUG=1
+endif
+
+ifdef THRD_DEBUG
+D += -DTHRD_DEBUG=1
+endif
+
+ifdef PROC_DEBUG
+D += -DPROC_DEBUG=1
+endif
+
+ifdef AMEC_DEBUG
+D += -DAMEC_DEBUG=1
+endif
+
+ifdef APLT_DEBUG
+D += -DAPLT_DEBUG=1
+endif
+
+ifdef DCOM_DEBUG
+D += -DDCOM_DEBUG=1
+endif
+
+ifdef ERRL_DEBUG
+D += -DERRL_DEBUG=1
+endif
+
+ifdef APSS_DEBUG
+D += -DAPSS_DEBUG=1
+endif
+
+ifdef DPSS_DEBUG
+D += -DDPSS_DEBUG=1
+endif
+
+ifdef SNSR_DEBUG
+D += -DSNSR_DEBUG=1
+endif
+
+ifdef TMER_DEBUG
+D += -DTMER_DEBUG=1
+endif
+
+#//@<rc001a
+
+#*******************************************************************************
diff --git a/src/occ/debug_trace_ode.mk b/src/occ/debug_trace_ode.mk
new file mode 100755
index 0000000..3503eae
--- /dev/null
+++ b/src/occ/debug_trace_ode.mk
@@ -0,0 +1,76 @@
+# $Id$
+
+# @file debug_trace.mk
+#
+# @brief mk occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section debug_trace.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc001 rickylie 01/09/2012 Created
+# #pb00E pbavari 03/11/2012 ODE Makefile support
+# @endverbatim
+#
+
+#*******************************************************************************
+# Defines
+#*******************************************************************************
+#//>@rc001a
+
+.ifdef MAIN_DEBUG
+DEFS += -DMAIN_DEBUG=1
+.endif
+
+.ifdef RTLS_DEBUG
+DEFS += -DRTLS_DEBUG=1
+.endif
+
+.ifdef THRD_DEBUG
+DEFS += -DTHRD_DEBUG=1
+.endif
+
+.ifdef PROC_DEBUG
+DEFS += -DPROC_DEBUG=1
+.endif
+
+.ifdef AMEC_DEBUG
+DEFS += -DAMEC_DEBUG=1
+.endif
+
+.ifdef APLT_DEBUG
+DEFS += -DAPLT_DEBUG=1
+.endif
+
+.ifdef DCOM_DEBUG
+DEFS += -DDCOM_DEBUG=1
+.endif
+
+.if defined( ERRL_DEBUG )
+DEFS += -DERRL_DEBUG=1
+.endif
+
+.ifdef APSS_DEBUG
+DEFS += -DAPSS_DEBUG=1
+.endif
+
+.ifdef DPSS_DEBUG
+DEFS += -DDPSS_DEBUG=1
+.endif
+
+.ifdef SNSR_DEBUG
+DEFS += -DSNSR_DEBUG=1
+.endif
+
+.ifdef TMER_DEBUG
+DEFS += -DTMER_DEBUG=1
+.endif
+
+#//@<rc001a
+
+#*******************************************************************************
diff --git a/src/occ/doc/Doxyfile b/src/occ/doc/Doxyfile
new file mode 100755
index 0000000..9fa0a2f
--- /dev/null
+++ b/src/occ/doc/Doxyfile
@@ -0,0 +1,1252 @@
+# Doxyfile 1.4.7
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = OCC
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 1.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.c *.h *.S *.C *.H
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = doc tools
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/src/occ/errl/errl.c b/src/occ/errl/errl.c
new file mode 100755
index 0000000..3f997b9
--- /dev/null
+++ b/src/occ/errl/errl.c
@@ -0,0 +1,984 @@
+/******************************************************************************
+// @file errl.h
+// @brief OCC Errl Component
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _errl_c errl.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * tapiar 06/15/2011 Created errl methods
+ * abagepa 08/15/2011 Add: a couple of trace statements
+ * @01 tapiar 10/05/2011 Add: a couple of trace statements
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th022 thallet 10/04/2012 Add helper function to return slotId
+ * @nh004 864941 neilhsu 12/20/2012 Support get/delete errl & added trace info
+ * @at012 868019 alvinwan 01/25/2013 TRAC_get_buffer_partial() can result in TLB Miss Exception
+ * @th032 thallet 04/19/2013 Dcache_Flush so FSP can read from SRAM
+ * @th036 881677 thallet 05/06/2013 Support for new Poll Command
+ * @jh001 881996 joshych 05/07/2013 Support SRAM error log format
+ * @jh002 883921 joshych 06/17/2013 Read OCC error log from SRAM
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm016 909061 milesg 12/10/2013 Allow traces to use all available space
+ * @gm028 911670 milesg 02/27/2014 Immediate safe mode on checkstop
+ * @gm041 928150 milesg 06/02/2014 allow callouts to be added to info errors if mfg action flag is set
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+
+#include <errl.h>
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <trac.h>
+#include <state.h>
+#include <dcom.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+uint32_t G_occErrSlotBits = 0x000000000;
+uint8_t G_occErrIdCounter= 0x00;
+
+uint8_t G_errslot1[MAX_ERRL_ENTRY_SZ] = {0};
+uint8_t G_errslot2[MAX_ERRL_ENTRY_SZ] = {0};
+uint8_t G_errslot3[MAX_ERRL_ENTRY_SZ] = {0};
+uint8_t G_errslot4[MAX_ERRL_ENTRY_SZ] = {0};
+uint8_t G_errslot5[MAX_ERRL_ENTRY_SZ] = {0};
+uint8_t G_errslot6[MAX_ERRL_ENTRY_SZ] = {0};
+uint8_t G_errslot7[MAX_ERRL_ENTRY_SZ] = {0};
+
+uint8_t G_infoslot[MAX_ERRL_ENTRY_SZ] = {0};
+
+uint8_t G_callslot[MAX_ERRL_CALL_HOME_SZ] = {0};
+
+errlHndl_t G_occErrSlots[ERRL_MAX_SLOTS] = {
+ (errlHndl_t) G_errslot1,
+ (errlHndl_t) G_errslot2,
+ (errlHndl_t) G_errslot3,
+ (errlHndl_t) G_errslot4,
+ (errlHndl_t) G_errslot5,
+ (errlHndl_t) G_errslot6,
+ (errlHndl_t) G_errslot7,
+ (errlHndl_t) G_infoslot,
+ (errlHndl_t) G_callslot
+ };
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void hexDumpLog( errlHndl_t i_log );
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: getErrSlotNumAndErrId
+//
+// Description: Get Error Slot Number and Error Id
+//
+// Flow: 06/06/11 FN=getErrSlotNumAndErrId
+//
+// End Function Specification
+uint8_t getErrSlotNumAndErrId(
+ ERRL_SEVERITY i_severity,
+ uint8_t *o_errlId,
+ uint64_t *o_timeStamp
+ )
+{
+ // Locals
+ uint8_t l_rc = ERRL_INVALID_SLOT;
+ uint32_t l_mask = ERRL_SLOT_MASK_DEFAULT;
+
+ switch ( i_severity )
+ {
+ case ERRL_SEV_INFORMATIONAL:
+ l_mask = ERRL_SLOT_MASK_INFORMATIONAL;
+ break;
+ case ERRL_SEV_PREDICTIVE:
+ l_mask = ERRL_SLOT_MASK_PREDICTIVE;
+ break;
+ case ERRL_SEV_UNRECOVERABLE:
+ l_mask = ERRL_SLOT_MASK_UNRECOVERABLE;
+ break;
+ case ERRL_SEV_CALLHOME_DATA:
+ l_mask = ERRL_SLOT_MASK_CALL_HOME_DATA;
+ break;
+ };
+
+
+ // we have a valid mask
+ if ( l_mask != ERRL_SLOT_MASK_DEFAULT )
+ {
+ // 1. Find an available slot
+ uint8_t l_slot = ERRL_INVALID_SLOT;
+ uint32_t l_slotBitWord = ~(G_occErrSlotBits | l_mask);
+ SsxMachineContext l_ctx;
+
+ // 2. use assembly cntlzw to get slot & (disable/enable interrupts)
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ __asm__ __volatile__ ( "cntlzw %0, %1;" : "=r" (l_slot) : "r" (l_slotBitWord));
+ ssx_critical_section_exit(&l_ctx);
+
+ // slot is valid
+ if ( l_slot < ERRL_MAX_SLOTS )
+ {
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ // 3. Get time stamp & save off timestamp
+ // Internal caller so assuming valid pointer
+ *o_timeStamp = ssx_timebase_get();
+ // save of counter and then increment it
+ // Note: Internal caller so assuming valid pointer
+ *o_errlId = ((++G_occErrIdCounter) == 0) ? ++G_occErrIdCounter : G_occErrIdCounter;
+
+ G_occErrSlotBits |= (ERRL_SLOT_SHIFT >> l_slot); // @nh004c
+ ssx_critical_section_exit(&l_ctx);
+
+ l_rc = l_slot;
+
+ }
+ }
+
+ // return slot
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: getErrSlotNumByErrId
+//
+// Description: Get Error Slot Num By Error Id
+//
+// End Function Specification
+uint8_t getErrSlotNumByErrId(const uint8_t i_errlId) // @nh004a
+{
+ uint8_t l_SlotNum = ERRL_INVALID_SLOT;
+ uint8_t i = 0;
+
+ // the errID should starting from 1 to 0xff
+ if (i_errlId != 0)
+ {
+ // search for all slot and try to get slot num
+ for (i = 0; i < ERRL_MAX_SLOTS; i ++)
+ {
+ if (i_errlId == G_occErrSlots[i]->iv_entryId)
+ {
+ // Found, return the array index as slot num
+ l_SlotNum = i;
+ break;
+ }
+ }
+ }
+
+ // return ERRL_INVALID_SLOT(0xff) if not found
+ return l_SlotNum;
+}
+
+
+// Function Specification
+//
+// Name: getErrSlotOCIAddr
+//
+// Description: Get Error Slot OCI address
+//
+// End Function Specification
+uint32_t getErrSlotOCIAddr(const uint8_t i_SlotNum) // @nh004a
+{
+ void *l_addr = 0;
+
+ if (i_SlotNum < ERRL_MAX_SLOTS)
+ {
+ l_addr = G_occErrSlots[i_SlotNum];
+ }
+
+ return (uint32_t)l_addr;
+}
+
+
+// Function Specification
+//
+// Name: getErrlOCIAddrByID
+//
+// Description: Get Error Slot OCI address
+//
+// End Function Specification
+uint32_t getErrlOCIAddrByID(const uint8_t i_id)
+{
+ // This function verifies the id is valid
+ uint8_t l_slot = getErrSlotNumByErrId(i_id);
+
+ // This function verifies that slot is valid
+ return getErrSlotOCIAddr(l_slot);
+}
+
+
+// Function Specification
+//
+// Name: getErrlLengthByID
+//
+// Description: Get Error Log Length
+//
+// End Function Specification
+uint16_t getErrlLengthByID(const uint8_t i_id)
+{
+ uint16_t l_length = 0;
+ uint8_t l_slot = getErrSlotNumByErrId(i_id);
+
+ /// check if error log is committed before returning length
+ /// because after it is committed, length shouldn't change.
+ if(l_slot < ERRL_MAX_SLOTS)
+ {
+ if (G_occErrSlots[l_slot]->iv_userDetails.iv_committed)
+ {
+ l_length = G_occErrSlots[l_slot]->iv_userDetails.iv_entrySize;
+ }
+ }
+
+ return l_length;
+}
+
+
+// Function Specification
+//
+// Name: getLastGetErrID
+//
+// Description: Get the oldest Error ID
+//
+// End Function Specification
+uint8_t getOldestErrlID() // @nh004a
+{
+ uint8_t l_entryId = 0;
+ uint8_t i = 0;
+ uint64_t l_timestamp = 0;
+
+ for (i = 0; i < ERRL_MAX_SLOTS; i++)
+ {
+ if (G_occErrSlots[i]->iv_userDetails.iv_committed)
+ {
+ // Get the oldest entry by searching the Mininum Err entry ID
+ if ((l_timestamp == 0) ||
+ (G_occErrSlots[i]->iv_userDetails.iv_timeStamp <= l_timestamp) )
+ {
+ l_timestamp = G_occErrSlots[i]->iv_userDetails.iv_timeStamp;
+ l_entryId = G_occErrSlots[i]->iv_entryId;
+ }
+ }
+ }
+
+ return l_entryId;
+}
+
+
+// Function Specification
+//
+// Name: createErrl
+//
+// Description: Create an Error Log
+//
+// Flow: 03/29/12 FN=createErrl
+//
+// End Function Specification
+errlHndl_t createErrl(
+ const uint16_t i_modId,
+ const uint8_t i_reasonCode,
+ const uint32_t i_extReasonCode, // @nh001a
+ const ERRL_SEVERITY i_sev,
+ const tracDesc_t i_trace,
+ const uint16_t i_traceSz,
+ const uint32_t i_userData1,
+ const uint32_t i_userData2
+ )
+{
+ // Locals
+ errlHndl_t l_rc = INVALID_ERR_HNDL;
+ uint64_t l_time = 0;
+ uint8_t l_id = 0;
+ uint8_t l_errSlot = getErrSlotNumAndErrId( i_sev, &l_id, &l_time);
+
+
+ if ( l_errSlot != ERRL_INVALID_SLOT )
+ {
+ TRAC_INFO("Creating error log in slot [%d]", l_errSlot);
+
+ // get slot pointer
+ l_rc = G_occErrSlots[ l_errSlot ];
+
+ // save off default size
+ l_rc->iv_userDetails.iv_entrySize = sizeof( ErrlEntry_t );
+
+ // add trace
+ addTraceToErrl( i_trace, i_traceSz, l_rc );
+
+ // save off entry Id
+ l_rc->iv_entryId = l_id;
+
+ //Save off version info
+ l_rc->iv_version = ERRL_STRUCT_VERSION_1;
+
+ // save off time
+ l_rc->iv_userDetails.iv_timeStamp = l_time;
+
+ // if its a call home error then set the sev to informational
+ l_rc->iv_severity = (i_sev == ERRL_SEV_CALLHOME_DATA ? (uint8_t)ERRL_SEV_INFORMATIONAL : i_sev);
+
+ l_rc->iv_userData4 = i_extReasonCode; // @nh001a
+
+ // save off user detail section version
+ l_rc->iv_userDetails.iv_version = ERRL_USR_DTL_STRUCT_VERSION_1;
+
+ // save off rest of input parameters
+ l_rc->iv_userDetails.iv_modId = i_modId;
+ l_rc->iv_reasonCode = i_reasonCode;
+ l_rc->iv_userDetails.iv_userData1 = i_userData1;
+ l_rc->iv_userDetails.iv_userData2 = i_userData2;
+
+ // set callout count to 0
+ l_rc->iv_numCallouts = 0;
+
+ // save off occ fields
+ //NOTE: Design does not exist for these fields
+ // TODO fix this when design is done!
+ l_rc->iv_userDetails.iv_fwLevel = 0;
+ l_rc->iv_userDetails.iv_occId = G_pob_id.chip_id;
+ l_rc->iv_userDetails.iv_occRole = G_occ_role;
+ l_rc->iv_userDetails.iv_operatingState = CURRENT_STATE();
+ }
+ else
+ {
+ // TODO: put a threshold on this trace
+ TRAC_INFO("Error Logs are FULL - Slot [%d]", l_errSlot); //@01a @nh004c
+ }
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: addTraceToErrl
+//
+// Description: Add trace to an error log
+//
+// Flow: 06/06/11 FN=addTraceToErrl
+//
+// End Function Specification
+void addTraceToErrl(
+ const tracDesc_t i_trace,
+ const uint16_t i_traceSz,
+ errlHndl_t io_err)
+{
+ UINT l_expectLen = 0, l_rtLen = 0, l_bytes_left; //gm016
+ void * l_traceAddr = io_err;
+ uint16_t l_actualSizeOfUsrDtls = 0;
+ pore_status_t l_gpe0_status;
+ static bool L_gpe_halt_traced = FALSE;
+
+
+ // check if GPE was frozen due to a checkstop
+ l_gpe0_status.value = in64(PORE_GPE0_STATUS);
+ if(l_gpe0_status.fields.freeze_action && !L_gpe_halt_traced)
+ {
+ L_gpe_halt_traced = TRUE;
+ TRAC_ERR("addTraceToErrl: OCC GPE halted due to checkstop. GPE0 status[0x%08x%08x]",
+ l_gpe0_status.words.high_order, l_gpe0_status.words.low_order);
+ }
+
+ // 1. Check if error log is not null
+ // 2. error log is not invalid
+ // 3. error log has not been commited
+ // 4. input trace is not zero
+ // 5. free space is enough
+ // 6. input trace descriptor is valid
+ if( (io_err != NULL) &&
+ (io_err != INVALID_ERR_HNDL) &&
+ (io_err->iv_userDetails.iv_committed == 0) &&
+ // @nh004d
+ (i_traceSz != 0) &&
+ ((io_err->iv_userDetails.iv_entrySize + sizeof(ErrlUserDetailsEntry_t)) < MAX_ERRL_ENTRY_SZ ) &&
+ ((i_trace==g_trac_inf)||(i_trace==g_trac_err)||(i_trace==g_trac_imp)||(i_trace==NULL)) ) // @at012a
+ {
+ //local copy of the usr details entry
+ ErrlUserDetailsEntry_t l_usrDtlsEntry;
+ uint16_t l_headerSz = sizeof( l_usrDtlsEntry );
+
+ //adjust user details entry size to available size (word align )
+ uint16_t l_availableSize = MAX_ERRL_ENTRY_SZ - (io_err->iv_userDetails.iv_entrySize + l_headerSz );
+ l_usrDtlsEntry.iv_size = ( i_traceSz < l_availableSize ) ? i_traceSz : l_availableSize; // @jh001c
+
+ //set type
+ l_usrDtlsEntry.iv_type = (uint8_t) ERRL_USR_DTL_TRACE_DATA;
+
+ //set version
+ l_usrDtlsEntry.iv_version = ERRL_TRACE_VERSION_1;
+
+ //copy the data into error the offset is the size of the current errorlog
+ void * l_p = io_err;
+
+ // @nh004a -- Start
+ // Caculate trace data address. Starting from errl address + sizeof(ErrlEntry_t + ErrlUserDetailsEntry_t).
+ l_traceAddr = l_p + io_err->iv_userDetails.iv_entrySize + l_headerSz;
+
+ // check if user request to add trace from a specific trace buffer
+ if (i_trace != NULL)
+ {
+ // Ensure requested length are larger than one trace info size.
+ if (l_usrDtlsEntry.iv_size >= sizeof (trace_buf_head_t))
+ {
+ l_rtLen = l_usrDtlsEntry.iv_size;
+ TRAC_get_buffer_partial(i_trace, l_traceAddr, &l_rtLen);
+
+ // Update data size
+ l_usrDtlsEntry.iv_size = l_rtLen;
+ }
+ else
+ {
+ TRAC_IMP("addTraceToErrl: Not enough buffer size for trace, Avail[%d], Req[%d]\n", l_availableSize, l_usrDtlsEntry.iv_size);
+
+ //Requested size is not able to fill in any trace info. Clear data length and give up.
+ l_usrDtlsEntry.iv_size = 0;
+ }
+ }
+ else
+ {
+ // User not specify which trace buffer to add.
+ // We have three kinds of trace buffer.(INF/IMP/ERR).Get partial of them to fill in user detail section of this ERR Log.
+ l_bytes_left = l_usrDtlsEntry.iv_size; //gm016
+ l_expectLen = l_bytes_left / NUM_OF_TRACE_TYPE;
+
+ // Ensure the size are able to fill in at least one trace info.
+ if (l_expectLen >= sizeof (trace_buf_head_t))
+ {
+ l_rtLen = l_expectLen;
+ TRAC_get_buffer_partial(TRAC_get_td("ERR"), l_traceAddr, &l_rtLen);
+ l_actualSizeOfUsrDtls += l_rtLen;
+ l_bytes_left -= l_rtLen; //gm016
+
+ l_rtLen = l_bytes_left / 2; //gm016
+ TRAC_get_buffer_partial(TRAC_get_td("IMP"), (l_traceAddr + l_actualSizeOfUsrDtls), &l_rtLen);
+ l_actualSizeOfUsrDtls += l_rtLen;
+ l_bytes_left -= l_rtLen; //gm016
+
+ l_rtLen = l_bytes_left; //gm016
+ TRAC_get_buffer_partial(TRAC_get_td("INF"), (l_traceAddr + l_actualSizeOfUsrDtls), &l_rtLen);
+ l_actualSizeOfUsrDtls += l_rtLen;
+
+ // Update data size
+ l_usrDtlsEntry.iv_size = l_actualSizeOfUsrDtls;
+ }
+ else
+ {
+ // Check to see if we are still able to fill in 1 or 2 traces into this Err log.
+ if (l_usrDtlsEntry.iv_size > sizeof (trace_buf_head_t))
+ {
+ l_rtLen = l_usrDtlsEntry.iv_size;
+
+ // Added only ERR trace info
+ TRAC_get_buffer_partial(TRAC_get_td("ERR"), l_traceAddr, &l_rtLen);
+
+ // Update data size
+ l_usrDtlsEntry.iv_size = l_rtLen;
+ }
+ else
+ {
+ TRAC_IMP("addTraceToErrl: Not enough buffer size for trace, Avail[%d], Req[%d]\n", l_availableSize, l_usrDtlsEntry.iv_size);
+
+ //We do not have enough size to fill in any trace info. Clear data length.
+ l_usrDtlsEntry.iv_size = 0;
+ }
+ }
+ }
+
+ if (l_usrDtlsEntry.iv_size)
+ {
+ // Finally, cacluate entire data length including usrDtl header.
+ l_actualSizeOfUsrDtls = l_usrDtlsEntry.iv_size + l_headerSz;
+
+ // save of user detail header for trace buf section we just added.
+ // Address is starting from "errl address + sizeof(ErrlEntry_t)."
+ //
+ // io_err |----------------------------------------|
+ // | ErrlEntry_t |
+ // | {iv_userDetails.iv_userDetailEntrySize,| <== we may have more usrdtl sections, need to add length
+ // | ... other elements ... }| of new usrdtl section(ErrlUserDetailsEntry_t + trace lens)
+ // |----------------------------------------|
+ // | ErrlUserDetailsEntry_t | <== copy usrdtl header to here (l_usrDtlsEntry)
+ // |----------------------------------------|
+ //trace buf | trace1(ex.INF) | <== trace already filled in at this moment.
+ // | trace2(ex.INF&IMP&ERR) |
+ // | ... |
+ //
+ l_p = memcpy( l_p+((io_err->iv_userDetails.iv_entrySize)),&l_usrDtlsEntry, l_headerSz );
+ }
+ // @nh004a -- End
+
+ //update usr data entry size
+ io_err->iv_userDetails.iv_userDetailEntrySize += l_actualSizeOfUsrDtls;
+
+ //update error log size
+ io_err->iv_userDetails.iv_entrySize += l_actualSizeOfUsrDtls;
+
+ }//end validation check
+}
+
+
+// Function Specification
+//
+// Name: reportErrorLog
+//
+// Description: report the log to tmgt
+//
+// Flow: FN=None
+//
+// End Function Specification
+void reportErrorLog( errlHndl_t i_err, uint16_t i_entrySize )
+{
+ // report the log to tmgt
+ // will need to give them the address and size to read
+
+ // TODO: Guts still not defined yet
+ TRAC_INFO("Reporting error @ %p with size %d",i_err, i_entrySize );
+ TRAC_INFO("ModID: 0x%08X, RC: 0x%08X, UserData1: 0x%08X, UserData2: 0x%08X",
+ i_err->iv_userDetails.iv_modId, i_err->iv_reasonCode,
+ i_err->iv_userDetails.iv_userData1, i_err->iv_userDetails.iv_userData2);
+
+ // TODO: remove this when tracing is enabled
+ hexDumpLog( i_err );
+}
+
+
+// Function Specification
+//
+// Name: commitErrl
+//
+// Description: Commit an Error Log
+//
+// Flow: 06/06/11 FN=commitErrl
+//
+// End Function Specification
+void commitErrl( errlHndl_t *io_err )
+{
+ pore_status_t l_gpe0_status;
+
+ if ( io_err != NULL )
+ {
+ // check if handle is valid and is NOT empty
+ if ((*io_err != NULL ) && ( *io_err != INVALID_ERR_HNDL ))
+ {
+ // check if GPE was frozen due to a checkstop
+ l_gpe0_status.value = in64(PORE_GPE0_STATUS);
+ if(l_gpe0_status.fields.freeze_action)
+ {
+ //Go to the reset state to minimize errors
+ reset_state_request(RESET_REQUESTED_DUE_TO_ERROR);
+
+ //clear out all other actions and set the safe mode req'd action
+ (*io_err)->iv_actions.word = ERRL_ACTIONS_SAFE_MODE_REQUIRED;
+
+ //set severity to informational
+ (*io_err)->iv_severity = ERRL_SEV_INFORMATIONAL;
+
+ //set callouts to 0
+ (*io_err)->iv_numCallouts = 0;
+ }
+
+ // if reset action bit is set force severity to unrecoverable and
+ // make sure there is at least one callout
+ if((*io_err)->iv_actions.reset_required) //@gm006
+ {
+ (*io_err)->iv_severity = ERRL_SEV_UNRECOVERABLE;
+ if(!(*io_err)->iv_numCallouts)
+ {
+ addCalloutToErrl(*io_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ }
+
+ // mark the last callout by zeroing out the next one
+ if((*io_err)->iv_numCallouts < ERRL_MAX_CALLOUTS)
+ {
+ memset(&(*io_err)->iv_callouts[(*io_err)->iv_numCallouts], 0,
+ sizeof(ErrlCallout_t));
+ }
+
+ // number of callouts must be the max value as defined by the TMGT-OCC spec.
+ (*io_err)->iv_numCallouts = ERRL_MAX_CALLOUTS; // @jh002a
+
+ // save off committed
+ (*io_err)->iv_userDetails.iv_committed = 1;
+
+ // calculate checksum & save it off
+ uint32_t l_cnt = 2; // starting point is after checksum field
+ uint32_t l_sum = 0;
+ uint32_t l_size = (*io_err)->iv_userDetails.iv_entrySize;
+ uint8_t * l_p = (uint8_t *)*io_err;
+
+ for( ; l_cnt < l_size ; l_cnt++ )
+ {
+ l_sum += *(l_p+l_cnt);
+ }
+
+ (*io_err)->iv_checkSum = l_sum;
+
+ // Flush error log out to SRAM since the FSP will directly read it
+ dcache_flush( *io_err, MAX_ERRL_ENTRY_SZ ); // @th032
+
+ // report error to FSP
+ reportErrorLog( *io_err, l_size );
+ }
+
+ *io_err = (errlHndl_t) NULL;
+ }
+}
+
+
+// Function Specification
+//
+// Name: getErrlLogId
+//
+// Description: Get Log Id from an Error Log
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+uint8_t getErrlLogId( errlHndl_t io_err )
+{
+ uint8_t l_logId = ERRL_INVALID_SLOT;
+
+ // check if handle is valid and is NOT empty
+ if ((io_err != NULL ) && ( io_err != INVALID_ERR_HNDL ))
+ {
+ l_logId = (io_err)->iv_entryId;
+ }
+
+ return l_logId;
+}
+
+
+// Function Specification
+//
+// Name: deleteErrl
+//
+// Description: Delete an Error Log
+//
+// Flow: 06/06/11 FN=deleteErrl
+//
+// End Function Specification
+errlHndl_t deleteErrl( errlHndl_t *io_err) // @nh004c
+{
+ errlHndl_t l_err = INVALID_ERR_HNDL;
+
+ if (io_err != NULL)
+ {
+ // check if handle is valid and is NOT empty
+ if ((*io_err != NULL ) &&
+ (*io_err != INVALID_ERR_HNDL ))
+ {
+
+ // find the slot number by traversing the global array
+ uint32_t l_slot = 0;
+
+ for( ; l_slot < ERRL_MAX_SLOTS; l_slot++ )
+ {
+ if ( *io_err == G_occErrSlots[ l_slot ] )
+ {
+ TRAC_INFO("deleting error @%p at slot [%d]", *io_err, l_slot );
+
+ // clear out space in that slot
+ memset(*io_err, 0, (*io_err)->iv_userDetails.iv_entrySize );
+
+ // Disable interrupts
+ SsxMachineContext l_ctx;
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+
+ //clear the error log slot bit for reuse
+ G_occErrSlotBits &= ~(ERRL_SLOT_SHIFT >> l_slot);
+
+ // Enable interrupts
+ ssx_critical_section_exit(&l_ctx);
+
+ l_err = NULL;
+
+ // done doing the work
+ break;
+ }
+ }
+ } // end if valid error log handl
+
+ //set the handle to null
+ *io_err = (errlHndl_t) NULL;
+ }
+
+ return l_err;
+}
+
+
+// Function Specification
+//
+// Name: addCalloutToErrl
+//
+// Description: Add a callout to an Error Log
+//
+// Flow: 06/06/11 FN=addCalloutToErrl
+//
+// End Function Specification
+// @jh001c
+void addCalloutToErrl(
+ errlHndl_t io_err,
+ const ERRL_CALLOUT_TYPE i_type,
+ const uint64_t i_calloutValue,
+ const ERRL_CALLOUT_PRIORITY i_priority)
+{
+ // 1. check if handle is valid (not null or invalid)
+ // 2. not committed
+ // 3. severity is not informational (unless mfg action flag is set)
+ // 4. callouts still not full
+ if ( (io_err != NULL ) &&
+ (io_err != INVALID_ERR_HNDL) &&
+ (io_err->iv_userDetails.iv_committed == 0) &&
+ (io_err->iv_actions.mfg_error || io_err->iv_severity != ERRL_SEV_INFORMATIONAL) && //gm041
+ (io_err->iv_numCallouts < ERRL_MAX_CALLOUTS) )
+ {
+ //set callout type
+ io_err->iv_callouts[ io_err->iv_numCallouts ].iv_type = (uint8_t)i_type;
+
+ //set callout value
+ io_err->iv_callouts[ io_err->iv_numCallouts ].iv_calloutValue = i_calloutValue;
+
+ //set priority
+ io_err->iv_callouts[ io_err->iv_numCallouts].iv_priority = (uint8_t)i_priority;
+
+ //increment actual number of callout
+ io_err->iv_numCallouts++;
+ }
+}
+
+
+// Function Specification
+//
+// Name: addUsrDtlsToErrl
+//
+// Description: Add User Details to an Error Log
+//
+// Flow: 06/06/11 FN=addUsrDtlsToErrl
+//
+// End Function Specification
+void addUsrDtlsToErrl(
+ errlHndl_t io_err,
+ uint8_t *i_dataPtr,
+ const uint16_t i_size,
+ const uint8_t i_version,
+ const ERRL_USR_DETAIL_TYPE i_type)
+{
+ // Locals
+ uint16_t l_maxSize = (i_type == ERRL_USR_DTL_CALLHOME_DATA) ? MAX_ERRL_CALL_HOME_SZ : MAX_ERRL_ENTRY_SZ;
+
+ // 1. check if handle is valid
+ // 2. NOT empty
+ // 3. not committed
+ // 4. size being passed in is valid
+ // 5. data pointer is valid
+ // 6. and we have enough size
+ if ((io_err != NULL ) &&
+ (io_err != INVALID_ERR_HNDL ) &&
+ (io_err->iv_userDetails.iv_committed == 0) &&
+ (i_size != 0) &&
+ (i_dataPtr != NULL) &&
+ ((io_err->iv_userDetails.iv_entrySize) < l_maxSize))
+ {
+ //local copy of the usr details entry
+ ErrlUserDetailsEntry_t l_usrDtlsEntry;
+ uint16_t l_headerSz = sizeof( l_usrDtlsEntry );
+
+ //adjust user details entry size to available size (word align )
+ uint16_t l_availableSize = l_maxSize - (io_err->iv_userDetails.iv_entrySize + l_headerSz );
+ l_usrDtlsEntry.iv_size = ( i_size < l_availableSize ) ? i_size : l_availableSize; // @jh001c
+
+ //set type
+ l_usrDtlsEntry.iv_type = (uint8_t)i_type;
+
+ //set version
+ l_usrDtlsEntry.iv_version = i_version;
+
+ //set the data
+ uint16_t l_actualSizeOfUsrDtls = l_headerSz + l_usrDtlsEntry.iv_size;
+
+ //copy the data into error the offset is the size of the current errorlog
+ void * l_p = io_err;
+ l_p = memcpy( l_p+((io_err->iv_userDetails.iv_entrySize)),&l_usrDtlsEntry, l_headerSz );
+ memcpy( l_p+l_headerSz, i_dataPtr, l_usrDtlsEntry.iv_size);
+
+ //update usr data entry size
+ io_err->iv_userDetails.iv_userDetailEntrySize += l_actualSizeOfUsrDtls;
+
+ //update error log size
+ io_err->iv_userDetails.iv_entrySize += l_actualSizeOfUsrDtls;
+ }
+}
+
+
+// Function Specification
+//
+// Name: setErrlSevToInfo
+//
+// Description: Set Error Log Severity to Informational
+// NOTE: Any callouts in the current error log will be DROPPED!
+//
+// Flow: 06/06/11 FN=setErrlSevToInfo
+//
+// End Function Specification
+void setErrlSevToInfo( errlHndl_t io_err )
+{
+ // check if handle is valid
+ // NOT empty
+ // not committed
+ if ( (io_err != NULL )
+ && ( io_err != INVALID_ERR_HNDL )
+ && (io_err->iv_userDetails.iv_committed == 0) )
+ {
+ //set sev to informational
+ io_err->iv_severity = ERRL_SEV_INFORMATIONAL;
+
+ //clear any callouts
+ uint32_t l_sizeOfcallouts = sizeof(ErrlCallout_t)*(io_err->iv_numCallouts);
+ memset(io_err->iv_callouts, 0,l_sizeOfcallouts );
+
+ //clear number of callouts
+ io_err->iv_numCallouts = 0;
+ }
+}
+
+
+// Function Specification
+//
+// Name: setErrlActions
+//
+// Description: Set Actions to an Error Log
+//
+// Flow: 05/14/13 FN=setErrlActions
+//
+// End Function Specification
+// @jh001a
+void setErrlActions(errlHndl_t io_err, const uint8_t i_mask)
+{
+ // check if handle is valid
+ // NOT empty
+ // not committed
+ if ( (io_err != NULL )
+ && ( io_err != INVALID_ERR_HNDL )
+ && (io_err->iv_userDetails.iv_committed == 0) )
+ {
+ // set the appropriate action bits$
+ io_err->iv_actions.word |= i_mask;
+ }
+}
+
+
+// Function Specification
+//
+// Name: hexDumpLog
+//
+// Description: Hex Dump Log
+//
+// Flow: FN=None
+//
+// End Function Specification
+void hexDumpLog( errlHndl_t i_log )
+{
+#if 0
+ // Locals
+ uint32_t l_written = 0;
+ uint32_t l_counter = 0;
+ uint8_t * l_data = (uint8_t*) i_log;
+ uint32_t l_len = i_log->iv_userDetails.iv_entrySize;
+
+ while ( l_counter < l_len)
+ {
+ if (( i_log == NULL ) ||
+ ( i_log == INVALID_ERR_HNDL ))
+ {
+ // break out if log is invalid
+ // do nothing
+ break;
+ }
+
+ printf("| %08X ", (uint32_t) l_data + l_counter);
+
+ // Display 16 bytes in Hex with 2 spaces in between
+ l_written = 0;
+ uint8_t i = 0;
+ for ( i = 0; i < 16 && l_counter < l_len; i++ )
+ {
+ l_written += printf("%02X",l_data[l_counter++]);
+
+ if ( ! ( l_counter % 4 ) )
+ {
+ l_written += printf(" ");
+ }
+ }
+
+ // Pad with spaces
+ uint8_t l_space[64] = {0};
+ memset( l_space, 0x00, sizeof( l_space ));
+ memset( l_space, ' ', 43-l_written);
+ printf("%s", l_space );
+
+ // Display ASCII
+ l_written = 0;
+ uint8_t l_char;
+ for ( ; i > 0 ; i-- )
+ {
+ l_char = l_data[ l_counter-i ];
+
+ if ( isprint( l_char ) &&
+ ( l_char != '&' ) &&
+ ( l_char != '<' ) &&
+ ( l_char != '>' )
+ )
+ {
+ l_written += printf("%c",l_char );
+ }
+ else
+ {
+ l_written += printf("." );
+ }
+ }
+
+ // Pad with spaces
+ uint8_t l_space2[64] = {0};
+ memset( l_space2, 0x00, sizeof( l_space2 ));
+ memset( l_space2, ' ', 19-l_written);
+ printf("%s|\n", l_space2 );
+ }
+#endif
+}
diff --git a/src/occ/errl/errl.h b/src/occ/errl/errl.h
new file mode 100755
index 0000000..830b614
--- /dev/null
+++ b/src/occ/errl/errl.h
@@ -0,0 +1,404 @@
+/******************************************************************************
+// @file errl.h
+// @brief OCC Errl Component header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _errl_h errl.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * tapiar 06/15/2011 Created errl methods
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th022 thallet 10/08/2012 Add method to get errl logId
+ * @nh004 864941 neilhsu 12/20/2012 Support get/delete errl & added trace info
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup
+ * @th036 881677 thallet 05/06/2013 Support for new poll command
+ * @jh001 881996 joshych 05/07/2013 Support SRAM error log format
+ * @jh002 883921 joshych 06/17/2013 Read OCC error log from SRAM
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gm028 911670 milesg 02/27/2014 Immediate safe mode on checkstop
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _ERRL_H
+#define _ERRL_H
+
+/** \defgroup OCC Errl Component
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <trac_interface.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// Used as default for invalid slot number
+static const uint8_t ERRL_INVALID_SLOT = 0xFF;
+
+// Used for shifting slot bits
+static const uint32_t ERRL_SLOT_SHIFT = 0x80000000;
+
+// Used for defaulting handle to invalid
+static const uint32_t INVALID_ERR = 0xFFFFFFFF;
+
+/* Sizes constants */
+// Max size of non call home data logs (2048 bytes)
+#define MAX_ERRL_ENTRY_SZ 0x800
+
+// Max size of call home data log (3072 bytes)
+#define MAX_ERRL_CALL_HOME_SZ 0xC00
+
+// Max size of callouts
+#define ERRL_MAX_CALLOUTS 6
+
+// Max number of error logs
+#define ERRL_MAX_SLOTS 9
+
+// Used to default a old/bad error handle
+#define INVALID_ERR_HNDL (errlHndl_t)INVALID_ERR
+
+// USED to determine the number of all trace buffer types. Now have (INF/IMP/ERR)
+#define NUM_OF_TRACE_TYPE 3
+
+// These bits are used to acquire a slot number. When used with the global
+// slot bit mask, we are able to get 7 slots for predictive/unrecoverable errors,
+// 1 slot for informational logs, and 1 slot for call home data log
+/* Slot Masks */
+typedef enum
+{
+ ERRL_SLOT_MASK_DEFAULT = 0xFFFFFFFF,
+ ERRL_SLOT_MASK_INFORMATIONAL = 0xFEFFFFFF,
+ ERRL_SLOT_MASK_PREDICTIVE = 0x01FFFFFF,
+ ERRL_SLOT_MASK_UNRECOVERABLE = 0x01FFFFFF,
+ ERRL_SLOT_MASK_CALL_HOME_DATA = 0xFF7FFFFF,
+} ERRL_SLOT_MASK;
+
+// These are the possible severities that an error log can have.
+// Users must ONLY use these enum values for severity.
+/* Error Severity */
+typedef enum
+{
+ ERRL_SEV_INFORMATIONAL = 0x00,
+ ERRL_SEV_PREDICTIVE = 0x01,
+ ERRL_SEV_UNRECOVERABLE = 0x02,
+ ERRL_SEV_CALLHOME_DATA = 0x03,
+} ERRL_SEVERITY;
+
+// These are the possible actions that an error log can have.
+// Users must ONLY use these enum values for actions.
+/* Error Actions */
+// @jh001a
+typedef enum
+{
+ ERRL_ACTIONS_CONSOLIDATE_ERRORS = 0x01, //ignored by tmgt at this time
+ ERRL_ACTIONS_MANUFACTURING_ERROR = 0x08, //tmgt will set severity to predictive while in mfg mode
+ ERRL_ACTIONS_SAFE_MODE_REQUIRED = 0x40, //immediate permanent safe mode without any recovery (checkstop)
+ ERRL_ACTIONS_RESET_REQUIRED = 0x80, //permanent safe mode after 3 recovery attempts
+} ERRL_ACTIONS_MASK;
+
+// These are the possible callout priorities that a callout can have.
+// Users must ONLY use these enum values for callout priority
+/* Callout Priority */
+typedef enum
+{
+ ERRL_CALLOUT_PRIORITY_INVALID = 0x00,
+ ERRL_CALLOUT_PRIORITY_LOW = 0x01,
+ ERRL_CALLOUT_PRIORITY_MED = 0x02,
+ ERRL_CALLOUT_PRIORITY_HIGH = 0x03,
+} ERRL_CALLOUT_PRIORITY;
+
+// These are the user detail types that a user details can have.
+// Users must ONLY use these enum values for user detail type
+/* User Detail Type */
+typedef enum
+{
+ ERRL_USR_DTL_TRACE_DATA = 0x01,
+ ERRL_USR_DTL_CALLHOME_DATA = 0x02,
+ ERRL_USR_DTL_BINARY_DATA = 0x03,
+} ERRL_USR_DETAIL_TYPE;
+
+// These are the possible OCC States.
+/* OCC States */
+typedef enum
+{
+ ERRL_OCC_STATE_INVALID = 0xFF,
+} ERRL_OCC_STATE;
+
+//Versions
+/* Errl Structure Version */
+typedef enum
+{
+ ERRL_STRUCT_VERSION_1 = 0x01,
+} ERRL_STRUCT_VERSION;
+
+/* Errl User Details Version */
+typedef enum
+{
+ ERRL_USR_DTL_STRUCT_VERSION_1 = 0x01,
+} ERRL_USR_DTL_STRUCT_VERSION;
+
+
+/* Errl Trace Version */
+typedef enum
+{
+ ERRL_TRACE_VERSION_1 = 0x00,
+} ERRL_TRACE_VERSION;
+
+/* Type of Callout */
+// @jh001a
+typedef enum
+{
+ ERRL_CALLOUT_TYPE_HUID = 0x01,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID = 0x02,
+} ERRL_CALLOUT_TYPE;
+
+/* TMGT-OCC Component Ids */
+// @jh001a
+typedef enum
+{
+ ERRL_COMPONENT_ID_FIRMWARE = 0x01,
+ ERRL_COMPONENT_ID_OVER_TEMPERATURE = 0x04,
+ ERRL_COMPONENT_ID_OVERSUBSCRIPTION = 0x05,
+ ERRL_COMPONENT_ID_NONE = 0xFF,
+} ERRL_COMPONENT_ID;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+/* Callout Structure */
+// @jh001c $
+// TMGT_OCC_INTERFACE_v1_2_1
+struct ErrlCallout
+{
+ // Type of callout. NOTE: Users must use ERRL_CALLOUT_TYPE enum
+ uint8_t iv_type;
+ // Callout Value
+ uint64_t iv_calloutValue;
+ // Callout Priority. NOTE: Users must use ERRL_CALLOUT_PRIORITY enum
+ uint8_t iv_priority;
+ // Reserved 1
+ uint16_t iv_reserved1;
+} __attribute__ ((__packed__));
+
+typedef struct ErrlCallout ErrlCallout_t;
+
+// The User Detail Entry Structure consists of the fields below followed
+// by the actual data the user is trying to collect.
+// NOTE: A data pointer field is NOT defined but rather inferred here. In the
+// error log contents, the user will see all the subsequent fields followed
+// by the actual data
+/* User Detail Entry Structure */
+struct ErrlUserDetailsEntry
+{
+ uint8_t iv_version; // User Details Entry Version
+ uint8_t iv_type; // User Details Entry Type
+ // Note: Users must use ERRL_USR_DETAIL_TYPE enum
+ uint16_t iv_size; // User Details Entry Size
+} __attribute__ ((__packed__));
+
+typedef struct ErrlUserDetailsEntry ErrlUserDetailsEntry_t;
+
+// The User Detail Structure consists of the fields below followed
+// by each individual User Details Entry structure & data
+// NOTE: A data pointer field is NOT defined but rather inferred here. In the
+// error log contents, the user will see all the subsequent fields followed
+// by each User Details Entry structure and its data
+/* User Detail Structure */
+struct ErrlUserDetails
+{
+ uint8_t iv_version; // User Details Version
+ uint8_t iv_reserved; // Reserved
+ uint16_t iv_modId; // Module Id
+ uint32_t iv_fwLevel; // Firmware Level
+ uint64_t iv_timeStamp; // Time Stamp
+ uint8_t iv_occId; // OCC ID
+ uint8_t iv_occRole; // OCC Role
+ uint8_t iv_operatingState; // OCC State
+ uint8_t iv_committed:1; // Log Committed?
+ uint8_t iv_reserved1:7;
+ uint32_t iv_userData1; // User Data Word 1
+ uint32_t iv_userData2; // User Data Word 2
+ uint32_t iv_userData3; // User Data Word 3
+ uint16_t iv_entrySize; // Log Size
+ uint16_t iv_userDetailEntrySize; // User Details Size
+} __attribute__ ((__packed__));
+
+typedef struct ErrlUserDetails ErrlUserDetails_t;
+
+/* Error Log Structure */
+// @jh001c
+// TMGT_OCC_INTERFACE_v1_2_1
+struct ErrlEntry
+{
+ // Log CheckSum
+ uint16_t iv_checkSum;
+ // Log Version
+ uint8_t iv_version;
+ // Log Entry ID
+ uint8_t iv_entryId;
+ // Log Reason Code
+ uint8_t iv_reasonCode;
+ // Log Severity - NOTE: Users must use ERRL_SEVERITY enum
+ uint8_t iv_severity;
+ // Actions to process the errors
+ union
+ {
+ struct
+ {
+ uint8_t reset_required : 1; // Error is critical and requires OCC reset
+ uint8_t safe_mode_required : 1; // immediate permanent safe mode (used for checkstops)
+ uint8_t reserved5 : 1;
+ uint8_t reserved4 : 1;
+ uint8_t mfg_error : 1; // Fan go to max,oversubscription,core above warning,Throttled.
+ uint8_t reserved2 : 1;
+ uint8_t reserved1 : 1;
+ uint8_t consolidate_error : 1; // Look for same SRC from all OCCs
+ };
+ uint8_t word;
+ } iv_actions;
+ // Reserved for extended reason code for uniquely identifying error if needed // @nh001c
+ uint32_t iv_userData4;
+ // Log Callout Number
+ uint8_t iv_numCallouts;
+ // Callouts
+ ErrlCallout_t iv_callouts[ERRL_MAX_CALLOUTS];
+ // User Details section for Log
+ ErrlUserDetails_t iv_userDetails;
+
+} __attribute__ ((__packed__));
+
+typedef struct ErrlEntry ErrlEntry_t;
+
+/* Error Log Handle */
+typedef ErrlEntry_t* errlHndl_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+extern uint32_t G_occErrSlotBits;
+extern uint8_t G_occErrIdCounter;
+
+extern errlHndl_t G_occErrSlots[ERRL_MAX_SLOTS];
+
+// Globals used by testcases
+extern uint8_t G_errslot1[MAX_ERRL_ENTRY_SZ];
+extern uint8_t G_errslot2[MAX_ERRL_ENTRY_SZ];
+extern uint8_t G_errslot3[MAX_ERRL_ENTRY_SZ];
+extern uint8_t G_errslot4[MAX_ERRL_ENTRY_SZ];
+extern uint8_t G_errslot5[MAX_ERRL_ENTRY_SZ];
+extern uint8_t G_errslot6[MAX_ERRL_ENTRY_SZ];
+extern uint8_t G_errslot7[MAX_ERRL_ENTRY_SZ];
+extern uint8_t G_infoslot[MAX_ERRL_ENTRY_SZ];
+extern uint8_t G_callslot[MAX_ERRL_CALL_HOME_SZ];
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+/* Create an Error Log */
+errlHndl_t createErrl(
+ const uint16_t i_modId,
+ const uint8_t i_reasonCode,
+ const uint32_t i_extReasonCode, // @nh001a
+ const ERRL_SEVERITY i_sev,
+ const tracDesc_t i_trace,
+ const uint16_t i_traceSz,
+ const uint32_t i_userData1,
+ const uint32_t i_userData2
+ );
+
+
+/* Add Trace Data to Error Log */
+void addTraceToErrl(
+ const tracDesc_t i_trace,
+ const uint16_t i_traceSz,
+ errlHndl_t io_errl
+ );
+
+/* Commit the Error Log */
+void commitErrl( errlHndl_t * io_err );
+
+/* Delete the Error Log */
+errlHndl_t deleteErrl( errlHndl_t * io_err);
+
+/* Add Callout to Error Log */
+// @jh001c
+void addCalloutToErrl(
+ errlHndl_t io_err,
+ const ERRL_CALLOUT_TYPE i_type,
+ const uint64_t i_calloutValue,
+ const ERRL_CALLOUT_PRIORITY i_priority);
+
+/* Add User Details Data to the Error Log */
+void addUsrDtlsToErrl(
+ errlHndl_t io_err,
+ uint8_t *i_dataPtr,
+ const uint16_t i_size,
+ const uint8_t i_version,
+ const ERRL_USR_DETAIL_TYPE i_type);
+
+/* Change Severity of Error Log to Informational */
+void setErrlSevToInfo( errlHndl_t io_err );
+
+/* Set Actions to an Errl */
+void setErrlActions(errlHndl_t io_err, const uint8_t i_mask);
+
+/* Return Error Log ID to report to TMGT */
+uint8_t getErrlLogId( errlHndl_t io_err );
+
+// @nh004a - start
+/* Get Error Slot Num By Error Id */
+uint8_t getErrSlotNumByErrId( uint8_t i_errlId);
+
+/* Get Error Slot OCI address */
+uint32_t getErrSlotOCIAddr(const uint8_t i_SlotNum);
+
+/* Get the oldest error log ID so that we can pass it to TMGT */
+uint8_t getOldestErrlID();
+
+/* Return Length of an Error Log based on ID, to send to TMGT */
+uint16_t getErrlLengthByID(const uint8_t i_id);
+
+/* Return Address of an Error Log based on ID, to send to TMGT */
+uint32_t getErrlOCIAddrByID(const uint8_t i_id);
+
+// @nh004a - end
+
+
+// NOTE: Not defining these in the .h since they are INTERNAL
+// methods!
+
+/* Report the Error Log */
+//void reportErrorLog( errlHndl_t i_err, uint16_t i_entrySize );
+
+/* Get Error Log Slot Number and Error Id */
+//uint8_t getErrSlotNumAndErrId(
+// ERRL_SEVERITY i_severity,
+// uint8_t *o_errlId,
+// uint64_t *o_timeStamp
+// );
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_ERRL_H
diff --git a/src/occ/errl/test/Makefile b/src/occ/errl/test/Makefile
new file mode 100755
index 0000000..b450fc5
--- /dev/null
+++ b/src/occ/errl/test/Makefile
@@ -0,0 +1,55 @@
+# $Id$
+
+# @file Makefile
+#
+# @brief Makefile occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+include test.mk
+
+APP = errltest
+APP_INCLUDES += -I../../../ssx
+APP_INCLUDES += -I../../../lib
+APP_INCLUDES += -I../../incl
+APP_INCLUDES += -I../../trac
+APP_INCLUDES += -I../../async
+APP_INCLUDES += -I../../errl
+APP_INCLUDES += -I../../gpe
+APP_INCLUDES += -I../../thread
+APP_INCLUDES += -I.
+
+
+
+
+#D = -DVERIFICATION=1 \
+ -DSSX_STACK_CHECK=0 \
+ -DINITIALIZE_PMC=0 \
+ -DINITIALIZE_SIMICS_IO=0 \
+ -DINITIALIZE_RTX_IO=1 \
+ -DINITIALIZE_PBA=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DSSX_KERNEL_TRACE_ENABLE=1
+
+
+SOURCES = ${all_cfiles}
+MODE = validation
+
+PGP_ASYNC_SUPPORT = 1
+
+include ./app.mk
+
+pgas:
+ $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10'
diff --git a/src/occ/errl/test/app.mk b/src/occ/errl/test/app.mk
new file mode 100755
index 0000000..3f674bf
--- /dev/null
+++ b/src/occ/errl/test/app.mk
@@ -0,0 +1,99 @@
+# $Id$
+
+# @file app.mk
+#
+# @brief mk occ application
+#
+# This Makefile is included-ed into application Makefiles and
+# encapsulates the steps necessary to create application images.
+#
+# The application Makefile (user) must define the following variables:
+#
+# APP - The name of the application
+# SOURCES - The list of local source files that implement the
+# application.
+#
+# The application Makefile (user) may optionally define the following
+# variables:
+#
+# D - The value of $(D) is appended to DEFS defined by ssx.mk
+#
+# MODE - The following modes are recognized:
+#
+# validation - (Default) An application that requires all SSX
+# services.
+#
+# firmware - An interrupt only configuration.
+#
+# The make process creates the following files:
+#
+# $(APP).out - The PowerPC-ELF version of the application
+# $(APP).bin - A binary SRAM image of the application
+# $(APP).map - The linker map of the application
+
+# @page ChangeLogs Change Logs
+# @section app.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+#
+# @endverbatim
+#
+
+OCC = ../../
+SSX = ../../../ssx
+LIB = ../../../lib
+PGP = $(SSX)/pgp
+
+ifeq "$(MODE)" "firmware"
+SSX_TIMER_SUPPORT = 0
+SSX_THREAD_SUPPORT = 0
+endif
+
+export SSX_TIMER_SUPPORT
+export SSX_THREAD_SUPPORT
+export PPC405_MMU_SUPPORT
+export PGP_ASYNC_SUPPORT
+
+INCLUDES = -I $(OCC) -I$(LIB)
+
+include $(PGP)/ssx.mk
+
+C-OBJECTS = $(SOURCES:.c=.o)
+OBJECTS = $(C-OBJECTS:.S=.o)
+
+LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \
+ -L $(OCC) -L $(LIB) -lssx -lppc32
+
+DEFS += $(D)
+
+all: $(OBJECTS) libssx.a
+ $(MAKE) -C $(PGP) DEFS="$(DEFS)" -e
+ $(CPP) -P $(DEFS) < $(OCC)/linkocc.cmd > linkscript
+ $(LD) $(OBJECTS) \
+ -Tlinkscript $(LDFLAGS) -Map $(APP).map -Bstatic -o $(APP).out
+ $(OBJCOPY) -O binary $(APP).out $(APP).bin
+ $(OBJDUMP) -d $(APP).out > $(APP).dis
+
+libssx.a:
+ $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e
+
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map linkscript
+ rm -f ./*/*.o ./*/*.d ./*/*.d.*
+
+.PHONY : clean_all
+clean_all:
+ $(MAKE) clean
+ $(MAKE) -C $(PGP) clean
+
+.PHONY : doc
+doc:
+ doxygen doc/Doxyfile
+
+include $(OBJECTS:.o=.d)
diff --git a/src/occ/errl/test/errltest.c b/src/occ/errl/test/errltest.c
new file mode 100755
index 0000000..b820fb7
--- /dev/null
+++ b/src/occ/errl/test/errltest.c
@@ -0,0 +1,786 @@
+/******************************************************************************
+// @file errltest.c
+// @brief OCC ERRL TEST
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section errltest.c ERRLTEST.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include <thread.h>
+#include <threadSch.h>
+#include <errl.h>
+#include <rand.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+uint8_t noncritical_stack[NONCRITICAL_STACK_SIZE];
+uint8_t critical_stack[CRITICAL_STACK_SIZE];
+/*@}*/ // Ending tag for stack module in doxygen
+
+/// Period in which to run #timer_routine
+#define TIMER_INTERVAL (SsxInterval) SSX_MICROSECONDS(100)
+
+#define SevAsciiValue( _v_ ) \
+ ( ( _v_ == ERRL_SEV_INFORMATIONAL ) ? "Informational" : \
+ ( _v_ == ERRL_SEV_PREDICTIVE ) ? "Predictive" : \
+ ( _v_ == ERRL_SEV_UNRECOVERABLE ) ? "Unrecovrable" : \
+ ( _v_ == ERRL_SEV_CALLHOME_DATA ) ? "Call Home" : \
+ "Unknown" )
+
+/*----------------------------------------------------------------------------*/
+/* SsxTimer and SsxThread Declarations and Priorities */
+/*----------------------------------------------------------------------------*/
+/** \defgroup TimersAndThreads Timer and Thread Information */ /*@{*/
+
+/// Our timer based on TIMER_INTERVAL that kicks off most of the work. See #timer_routine
+SsxTimer timer;
+
+/// Our idle thread. See #main_thread_routine
+SsxThread main_thread;
+
+/// \todo Goes away due to Bishop's device driver layer
+SsxThread prcd_thread;
+
+/*@}*/ // Ending tag for TimersAndThreads module in doxygen
+
+
+
+
+/*----------------------------------------------------------------------------*/
+/* SsxSemaphore Declarations */
+/*----------------------------------------------------------------------------*/
+SsxSemaphore prcd_sem;
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+int g_j = 0;
+int g_k = 0;
+
+SimicsStdio simics_stdout;
+SimicsStdio simics_stderr;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+extern void timer_routine(void *private);
+extern void rtloop_ocb_init(void);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: pgp_validation_ssx_main_hook
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void pgp_validation_ssx_main_hook(void)
+{
+
+}
+
+// Function Specification
+//
+// Name: Cmd_Hndl_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+//TODO placeholder
+void Cmd_Hndl_thread_routine(void *arg)
+{
+}
+
+// Function Specification
+//
+// Name: App_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void App_thread_routine(void *arg)
+{
+}
+
+// Function Specification
+//
+// Name: Thermal_Monitor_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Thermal_Monitor_thread_routine(void *arg)
+{
+}
+
+// Function Specification
+//
+// Name: Hlth_Monitor_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Hlth_Monitor_thread_routine(void *arg)
+{
+}
+
+// Function Specification
+//
+// Name: FFDC_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void FFDC_thread_routine(void *arg)
+{
+}
+
+
+// Function Specification
+//
+// Name: prcd_thread_routine
+//
+// Description: This thread loops as the highest priority thread, where it currently just
+//
+// Flow: FN=None
+//
+// End Function Specification
+void prcd_thread_routine(void *private)
+{
+ while(1)
+ {
+ // Just sit here until this semaphore is posted, which will never happen.
+ ssx_semaphore_pend(&prcd_sem, SSX_WAIT_FOREVER);
+
+ // Only trace the first XX times that this function loops
+ if(g_j < 20)
+ {
+ g_k = 0;
+ g_j++;
+
+ }
+ }
+}
+
+// Function Specification
+//
+// Name: dumpLog
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void dumpLog( errlHndl_t i_log, uint32_t i_len )
+{
+ uint32_t l_written = 0;
+ uint32_t l_counter = 0;
+ uint8_t * l_data = (uint8_t*) i_log;
+
+ printf("----------%p---------- \n", i_log );
+
+ if ( i_log == NULL )
+ return;
+
+ while ( l_counter < i_len)
+ {
+ printf("| %08X ", (uint32_t) l_data + l_counter);
+
+ // Display 16 bytes in Hex with 2 spaces in between
+ l_written = 0;
+ uint8_t i = 0;
+ for ( i = 0; i < 16 && l_counter < i_len; i++ )
+ {
+ l_written += printf("%02X",l_data[l_counter++]);
+
+ if ( ! ( l_counter % 4 ) )
+ {
+ l_written += printf(" ");
+ }
+ }
+
+ // Pad with spaces
+ uint8_t l_space[64] = {0};
+ memset( l_space, 0x00, sizeof( l_space ));
+ memset( l_space, ' ', 43-l_written);
+ printf("%s", l_space );
+
+ // Display ASCII
+ l_written = 0;
+ uint8_t l_char;
+ for ( ; i > 0 ; i-- )
+ {
+ l_char = l_data[ l_counter-i ];
+
+ if ( isprint( l_char ) &&
+ ( l_char != '&' ) &&
+ ( l_char != '<' ) &&
+ ( l_char != '>' )
+ )
+ {
+ l_written += printf("%c",l_char );
+ }
+ else
+ {
+ l_written += printf("." );
+ }
+ }
+
+ // Pad with spaces
+ uint8_t l_space2[64] = {0};
+ memset( l_space2, 0x00, sizeof( l_space2 ));
+ memset( l_space2, ' ', 19-l_written);
+ printf("%s\n", l_space2 );
+ }
+ printf("----------%p---------- \n", i_log );
+
+}
+
+// Function Specification
+//
+// Name: ppdumpslot
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void ppdumpslot(void)
+{
+ errlHndl_t l_array[ERRL_MAX_SLOTS] = {
+ (errlHndl_t)G_errslot1,
+ (errlHndl_t)G_errslot2,
+ (errlHndl_t)G_errslot3,
+ (errlHndl_t)G_errslot4,
+ (errlHndl_t)G_errslot5,
+ (errlHndl_t)G_errslot6,
+ (errlHndl_t)G_errslot7,
+ (errlHndl_t)G_infoslot,
+ (errlHndl_t)G_callslot,
+ };
+
+
+ printf("-------- \n");
+
+ uint8_t l_index = 0;
+ for(l_index =0; l_index < ERRL_MAX_SLOTS; l_index++)
+ {
+ if(l_array[l_index]->iv_version !=0)
+ {
+ printf("slot[%01d] sz[%04d] id[%03d] @[%p] \n",l_index,l_array[l_index]->iv_userDetails.iv_entrySize, l_array[l_index]->iv_entryId, l_array[l_index]);
+ }
+ else
+ {
+ printf("slot[%01d] [0] \n",l_index);
+ }
+ }
+ printf("-------- \n");
+}
+
+
+// Function Specification
+//
+// Name: testsizelimit
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void testsizelimit(const tracDesc_t i_trace)
+{
+ printf("%s: START \n", __FUNCTION__ );
+ errlHndl_t l_handle = NULL;
+ errlHndl_t l_handle2 = NULL;
+ errlHndl_t l_handle3 = NULL;
+
+ l_handle = createErrl( 0x1616, 0x08, ERRL_SEV_PREDICTIVE, i_trace, 512, 0x1, 0x2);
+ l_handle2 = createErrl( 0x1616, 0x08, ERRL_SEV_CALLHOME_DATA, i_trace, 512, 0x1, 0x2);
+ l_handle3 = createErrl( 0x1616, 0x08, ERRL_SEV_INFORMATIONAL, i_trace, 512, 0x1, 0x2);
+ errlHndl_t l_handleX = l_handle;
+ errlHndl_t l_handle2X = l_handle2;
+ errlHndl_t l_handle3X = l_handle3;
+ printf("%s: Slots after Create - 3 slots should be used (one of each)\n", __FUNCTION__ );
+ ppdumpslot();
+
+ uint8_t l_data[ MAX_ERRL_CALL_HOME_SZ * 2 ];
+
+ memset( l_data, 0xCC, sizeof( l_data ) );
+
+ addUsrDtlsToErrl( l_handle, l_data, sizeof( l_data ), ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+
+ memset( l_data, 0xEE, sizeof( l_data ) );
+
+ addUsrDtlsToErrl( l_handle2, l_data, sizeof( l_data ), ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_CALLHOME_DATA );
+
+ memset( l_data, 0xDD, sizeof( l_data ) );
+
+ addUsrDtlsToErrl( l_handle3, l_data, 76, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ dumpLog( l_handle2, l_handle2->iv_userDetails.iv_entrySize );
+ dumpLog( l_handle3, l_handle3->iv_userDetails.iv_entrySize );
+
+ commitErrl( &l_handle );
+ commitErrl( &l_handle2 );
+ commitErrl( &l_handle3 );
+ printf("%s: Slots after Commit - 3 slots should be used/committed \n", __FUNCTION__ );
+ ppdumpslot();
+
+ deleteErrl(&l_handleX);
+ deleteErrl(&l_handle2X);
+ deleteErrl(&l_handle3X);
+ printf("%s: Slots after delete Log - All slots should be empty\n", __FUNCTION__ );
+ ppdumpslot();
+ printf("%s: END \n", __FUNCTION__ );
+}
+
+// Function Specification
+//
+// Name: testdtlsizelimit
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void testdtlsizelimit(const tracDesc_t i_trace)
+{
+ printf("%s: START \n", __FUNCTION__ );
+ errlHndl_t l_handle = NULL;
+
+ l_handle = createErrl( 0x1616, 0x08, ERRL_SEV_PREDICTIVE, i_trace, 512, 0x1, 0x2);
+ errlHndl_t l_handleX = l_handle;
+ ppdumpslot();
+
+ uint8_t l_data[ MAX_ERRL_CALL_HOME_SZ * 2 ];
+
+ memset( l_data, 0xAA, sizeof( l_data ) );
+ addUsrDtlsToErrl( l_handle, l_data, 256, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ //dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ printf("%s: Slots after create + 256 bytes \n", __FUNCTION__ );
+ ppdumpslot();
+
+ memset( l_data, 0xBB, sizeof( l_data ) );
+ addUsrDtlsToErrl( l_handle, l_data, 512, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ //dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ printf("%s: Slots after create + 256 + 512 bytes \n", __FUNCTION__ );
+ ppdumpslot();
+
+ memset( l_data, 0xCC, sizeof( l_data ) );
+ addUsrDtlsToErrl( l_handle, l_data, 1024, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ //dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ printf("%s: Slots after create + 256 + 512 +1024 bytes \n", __FUNCTION__ );
+ ppdumpslot();
+
+ memset( l_data, 0xDD, sizeof( l_data ) );
+ addUsrDtlsToErrl( l_handle, l_data, 2048, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ printf("%s: Slots after create 2k should be full with DD having only 72 bytes \n", __FUNCTION__ );
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ ppdumpslot();
+
+
+ commitErrl( &l_handle );
+ deleteErrl(&l_handleX);
+ printf("%s: Slots should now be empty \n", __FUNCTION__ );
+ ppdumpslot();
+ printf("%s: END \n", __FUNCTION__ );
+}
+
+// Function Specification
+//
+// Name: timetest
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void timetest(const tracDesc_t i_trace)
+{
+ printf("%s: START \n", __FUNCTION__ );
+ errlHndl_t l_handle = NULL;
+ uint64_t l_start = 0;
+ uint64_t l_end = 0;
+
+ l_start = ssx_timebase_get();
+ l_handle = createErrl( 0x1716, 0x08, ERRL_SEV_CALLHOME_DATA, i_trace, 128, 0x1, 0x2);
+ errlHndl_t l_handle2 = l_handle;
+ commitErrl( &l_handle );
+ l_end = ssx_timebase_get();
+ printf("%s: Time to create/delete secs[%d] \n",__FUNCTION__, (int)SSX_MICROSECONDS(l_end-l_start));
+
+ deleteErrl(&l_handle2);
+ printf("%s: END \n", __FUNCTION__ );
+}
+
+// Function Specification
+//
+// Name: createcommitdeletelog
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void createcommitdeletelog(const tracDesc_t i_trace)
+{
+ printf("%s: START \n", __FUNCTION__ );
+ errlHndl_t l_handle = NULL;
+ l_handle = createErrl( 0x1616, 0x08, ERRL_SEV_CALLHOME_DATA, i_trace, 512, 0x1, 0x2);
+ printf("%s: Slots after Creating call home log \n", __FUNCTION__ );
+ ppdumpslot();
+
+
+ errlHndl_t l_handle2 = l_handle;
+ commitErrl( &l_handle );
+ printf("%s: Slots after Commiting call home log \n ", __FUNCTION__ );
+ dumpLog( l_handle2, l_handle2->iv_userDetails.iv_entrySize );
+ ppdumpslot();
+
+ deleteErrl(&l_handle2);
+ printf("%s: Slots after delete Log \n", __FUNCTION__ );
+ ppdumpslot();
+
+ printf("%s: END \n", __FUNCTION__ );
+}
+
+
+// Function Specification
+//
+// Name: create2infologtest
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void create2infologtest(const tracDesc_t i_trace)
+{
+ printf("%s: START \n", __FUNCTION__ );
+ printf("--------------------------------\n");
+ errlHndl_t l_handle = NULL;
+ errlHndl_t l_handle2= NULL;
+ l_handle = createErrl( 0x1616, 0x08, ERRL_SEV_INFORMATIONAL,i_trace, 5, 0x1, 0x2);
+
+ l_handle2 = createErrl( 0x2727, 0x19, ERRL_SEV_INFORMATIONAL, i_trace, 6, 0x2, 0x3);
+
+ if( l_handle2 == INVALID_ERR_HNDL )
+ {
+ printf("%s: Creating 2 info logs PASSED, only 1 was created @ %p \n", __FUNCTION__, l_handle );
+ ppdumpslot();
+ }
+ else
+ {
+ printf("%s: Creating 2 info logs FAILED, only 1 info log should be created! %p \n", __FUNCTION__, l_handle2 );
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ dumpLog( l_handle2, l_handle2->iv_userDetails.iv_entrySize );
+ ppdumpslot();
+ }
+
+ deleteErrl(&l_handle);
+
+ printf("%s: END \n", __FUNCTION__ );
+}
+
+// Function Specification
+//
+// Name: createMaxLogs
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void createMaxLogs(const tracDesc_t i_trace)
+{
+ ERRL_SEVERITY l_sevs[4] =
+ {
+ ERRL_SEV_UNRECOVERABLE,
+ ERRL_SEV_PREDICTIVE,
+ ERRL_SEV_CALLHOME_DATA,
+ ERRL_SEV_INFORMATIONAL
+ };
+
+ uint8_t l_chars[6] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
+
+
+ printf("%s: START \n", __FUNCTION__ );
+ errlHndl_t l_handle = NULL;
+ printf("--------------------------------\n");
+
+
+ uint32_t l_index = 0;
+ for(l_index =0; l_index < ERRL_MAX_SLOTS; l_index++)
+ {
+ uint32_t l_sev = (uint32_t)rand32(4);
+ uint32_t l_trace = (uint32_t)rand32( 512 );
+ l_handle = createErrl( 0x1616, 0x08, l_sevs[ l_sev ], i_trace, l_trace, 0x1, 0x2);
+
+ if( ( l_handle != INVALID_ERR_HNDL) &&
+ ( l_handle != NULL ) )
+ {
+ printf("Log Created @ %p with Sev[%s]\n",l_handle, SevAsciiValue( l_sevs[ l_sev ]) );
+
+ uint8_t l_ud = (uint8_t) rand32(2);
+ if ( l_ud )
+ {
+ uint8_t l_data[ (uint32_t) rand32( 512 ) ];
+
+ memset( l_data, l_chars[(uint8_t) rand32(6)], sizeof( l_data ) );
+ addUsrDtlsToErrl( l_handle, l_data, sizeof(l_data), ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ }
+
+ commitErrl( &l_handle );
+ }
+ else
+ {
+ printf("Could not create error log with Sev[%s]\n",SevAsciiValue( l_sevs[ l_sev ]) );
+
+ uint8_t l_purge = (uint8_t) rand32(2);
+
+ if ( l_purge )
+ {
+ uint32_t l_slots = (uint32_t)rand32(ERRL_MAX_SLOTS);
+
+ if ((G_occErrSlots[l_slots] != INVALID_ERR_HNDL) &&
+ (G_occErrSlots[l_slots] != NULL ))
+ {
+ printf("Deleting log with id[%d] @ %p (slot %d)\n", G_occErrSlots[l_slots]->iv_entryId, G_occErrSlots[l_slots], l_slots );
+ errlHndl_t l_handle = G_occErrSlots[l_slots];
+ deleteErrl( &l_handle );
+ }
+ }
+
+ }
+
+ uint8_t l_dumpfile = (uint8_t) rand32(2);
+
+ if ( l_dumpfile )
+ {
+ uint32_t l_slots = (uint32_t)rand32(ERRL_MAX_SLOTS);
+
+ if ((G_occErrSlots[l_slots] != INVALID_ERR_HNDL) &&
+ (G_occErrSlots[l_slots] != NULL ))
+ {
+ errlHndl_t l_handle = G_occErrSlots[l_slots];
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ }
+ }
+
+ ppdumpslot();
+ }
+
+ printf("%s: END \n", __FUNCTION__ );
+}
+
+
+// Function Specification
+//
+// Name: testcallouts
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void testcallouts(const tracDesc_t i_trace)
+{
+ printf("%s: START \n", __FUNCTION__ );
+ errlHndl_t l_handle = NULL;
+ printf("--------------------------------\n");
+
+ l_handle = createErrl( 0x1616, 0x08,ERRL_SEV_PREDICTIVE,i_trace, 5, 0x1, 0x2);
+ errlHndl_t l_log = l_handle;
+
+ if(l_handle != INVALID_ERR_HNDL)
+ {
+// printf("Commiting log @p %p\n",l_handle);
+ ERRL_CALLOUT_PRIORITY l_array[8] = {
+ ERRL_CALLOUT_PRIORITY_HIGH,
+ ERRL_CALLOUT_PRIORITY_MED,
+ ERRL_CALLOUT_PRIORITY_LOW,
+ ERRL_CALLOUT_PRIORITY_HIGH,
+ ERRL_CALLOUT_PRIORITY_MED,
+ ERRL_CALLOUT_PRIORITY_MED,
+ ERRL_CALLOUT_PRIORITY_LOW,
+ ERRL_CALLOUT_PRIORITY_LOW,
+ };
+ uint8_t l_index = 0;
+ for(l_index =0; l_index < 8; l_index++)
+ {
+ printf("%s: current callouts %d attempting to add callout # %d with priority %d\n", __FUNCTION__, l_handle->iv_numCallouts, l_index, l_array[l_index] );
+ addCalloutToErrl(l_handle,l_index,l_array[l_index]);
+ }
+
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+
+ commitErrl( &l_handle );
+ }
+ else
+ {
+ printf("could not create error log with [%s]\n",SevAsciiValue(ERRL_SEV_CALLHOME_DATA));
+ }
+
+ ppdumpslot();
+
+ deleteErrl( &l_log );
+
+ printf("%s: END \n", __FUNCTION__ );
+}
+
+// Function Specification
+//
+// Name: main_thread_routine
+//
+// Description: This thread currently just loops as the lowest priority thread, handling
+// the lowest priority tasks.
+//
+// Flow: FN=None
+//
+// End Function Specification
+void main_thread_routine(void *private)
+{
+ // Start the critical 250uS timer
+ ssx_timer_schedule(&timer, 1, TIMER_INTERVAL);
+
+ while(1)
+ {
+ // Only trace the first XX times that this function loops
+ if(g_k < 3)
+ {
+ g_k++;
+
+ }
+
+ // Sleep for 1000 before we run the loop again
+ ssx_sleep_absolute(1000);
+ }
+}
+
+
+// Function Specification
+//
+// Name: main
+//
+// Description: main() currently initalizes our trace buffer along with creating threads
+// and timers for execution. Note that once main runs ssx_start_threads, we
+// never return as the SSX kernel takes over.
+//
+// Flow: FN=None
+//
+// End Function Specification
+int main(int argc, char **argv)
+{
+
+ // Initialize stdout so we can do printf from within simics env
+ simics_stdout_create(&simics_stdout);
+ simics_stderr_create(&simics_stderr);
+ stdout = (FILE *)(&simics_stdout);
+ stderr = (FILE *)(&simics_stderr);
+
+ // Initialize SSX Stacks (note that this also reinitializes the time base to 0)
+ ssx_initialize((SsxAddress)noncritical_stack, NONCRITICAL_STACK_SIZE,
+ (SsxAddress)critical_stack, CRITICAL_STACK_SIZE,
+ 0);
+
+ // TRACE: Trace buffers initialized
+ tracDesc_t g_trac_main = NULL;
+
+ timetest(g_trac_main);
+
+ //createcommitdeletelog(g_trac_main);
+
+ //testsizelimit( g_trac_main );
+
+ //testdtlsizelimit( g_trac_main );
+
+ //create2infologtest(g_trac_main);
+
+ //createMaxLogs(g_trac_main);
+
+ //testcallouts(g_trac_main);
+
+
+ // Create Timers
+ //ssx_timer_create(&timer, timer_routine, 0);
+
+ // Create Global Semaphores
+ ssx_semaphore_create(&prcd_sem, 0, 13);
+
+ // Create Threads
+ ssx_thread_create(&main_thread,
+ main_thread_routine,
+ (void *)0,
+ (SsxAddress)main_thread_stack,
+ THREAD_STACK_SIZE,
+ 1);
+
+ // Create Threads
+ ssx_thread_create(&prcd_thread,
+ prcd_thread_routine,
+ (void *)0,
+ (SsxAddress)prcd_thread_stack,
+ THREAD_STACK_SIZE,
+ 0);
+
+ // Make Threads runnable
+ ssx_thread_resume(&main_thread);
+ ssx_thread_resume(&prcd_thread);
+
+ // Initialize Realtime Loop Timer Interrupt
+ //rtloop_ocb_init();
+
+ // Enter SSX Kernel
+ ssx_start_threads();
+
+ return 0;
+}
+
diff --git a/src/occ/errl/test/gpefiles.mk b/src/occ/errl/test/gpefiles.mk
new file mode 100755
index 0000000..ee9dbec
--- /dev/null
+++ b/src/occ/errl/test/gpefiles.mk
@@ -0,0 +1,24 @@
+# $Id$
+
+# @file gpefiles.mk
+#
+# @brief mk occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section gpefiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+occ_GPEFILES = ../../gpe/pore_test.S
+
+all_gpefiles = ${occ_GPEFILES}
+
diff --git a/src/occ/errl/test/parser.c b/src/occ/errl/test/parser.c
new file mode 100755
index 0000000..ee5c805
--- /dev/null
+++ b/src/occ/errl/test/parser.c
@@ -0,0 +1,292 @@
+/******************************************************************************
+// @file parser.c
+// @brief OCC ERRL TEST
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section parser.c PARSER.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+typedef uint32_t UINT32;
+typedef int32_t INT32;
+typedef uint8_t UCHAR;
+typedef uint8_t UINT8;
+typedef int8_t INT8;
+typedef uint16_t UINT16;
+typedef int16_t INT16;
+typedef char CHAR;
+typedef unsigned int UINT;
+typedef unsigned long ULONG;
+typedef int INT;
+typedef void VOID;
+typedef uint32_t size_t ;
+
+
+// Max size of non call home data logs (2048 bytes)
+#define MAX_ERRL_ENTRY_SZ 0x800
+
+// Max size of call home data log (3072 bytes)
+#define MAX_ERRL_CALL_HOME_SZ 0xC00
+
+// Max size of callouts
+#define ERRL_MAX_CALLOUTS 6
+
+// Max number of error logs
+#define ERRL_MAX_SLOTS 9
+
+// Used to default a old/bad error handle
+#define INVALID_ERR_HNDL (errlHndl_t)INVALID_ERR
+
+// These bits are used to acquire a slot number. When used with the global
+// slot bit mask, we are able to get 7 slots for predictive/unrecoverable errors,
+// 1 slot for informational logs, and 1 slot for call home data log
+/* Slot Masks */
+typedef enum
+{
+ ERRL_SLOT_MASK_DEFAULT = 0xFFFFFFFF,
+ ERRL_SLOT_MASK_INFORMATIONAL = 0xFEFFFFFF,
+ ERRL_SLOT_MASK_PREDICTIVE = 0x01FFFFFF,
+ ERRL_SLOT_MASK_UNRECOVERABLE = 0x01FFFFFF,
+ ERRL_SLOT_MASK_CALL_HOME_DATA = 0xFF7FFFFF,
+} ERRL_SLOT_MASK;
+
+// These are the possible severities that an error log can have.
+// Users must ONLY use these enum values for severity.
+/* Error Severity */
+typedef enum
+{
+ ERRL_SEV_INFORMATIONAL = 0x00,
+ ERRL_SEV_PREDICTIVE = 0x01,
+ ERRL_SEV_UNRECOVERABLE = 0x02,
+ ERRL_SEV_CALLHOME_DATA = 0x03,
+} ERRL_SEVERITY;
+
+// These are the possible callout priorities that a callout can have.
+// Users must ONLY use these enum values for callout priority
+/* Callout Priority */
+typedef enum
+{
+ ERRL_CALLOUT_PRIORITY_INVALID = 0x00,
+ ERRL_CALLOUT_PRIORITY_LOW = 0x01,
+ ERRL_CALLOUT_PRIORITY_MED = 0x02,
+ ERRL_CALLOUT_PRIORITY_HIGH = 0x03,
+} ERRL_CALLOUT_PRIORITY;
+
+// These are the user detail types that a user details can have.
+// Users must ONLY use these enum values for user detail type
+/* User Detail Type */
+typedef enum
+{
+ ERRL_USR_DTL_TRACE_DATA = 0x01,
+ ERRL_USR_DTL_CALLHOME_DATA = 0x02,
+} ERRL_USR_DETAIL_TYPE;
+
+// These are the possible OCC States.
+/* OCC States */
+typedef enum
+{
+ ERRL_OCC_STATE_INVALID = 0xFF,
+} ERRL_OCC_STATE;
+
+//Versions
+/* Errl Structure Version */
+typedef enum
+{
+ ERRL_STRUCT_VERSION_1 = 0x01,
+} ERRL_STRUCT_VERSION;
+
+/* Errl User Details Version */
+typedef enum
+{
+ ERRL_USR_DTL_STRUCT_VERSION_1 = 0x01,
+} ERRL_USR_DTL_STRUCT_VERSION;
+
+
+/* Errl Trace Version */
+typedef enum
+{
+ ERRL_TRACE_VERSION_1 = 0x00,
+} ERRL_TRACE_VERSION;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+/* Callout Structure */
+struct ErrlCallout
+{
+ uint64_t iv_homUnitId; // HOM Unit ID
+ uint8_t iv_priority; // Callout Priority
+ // NOTE: Users must use ERRL_CALLOUT_PRIORITY enum
+ uint8_t iv_reserved1; // Reserved 1
+ uint16_t iv_reserved2; // Reserved 2
+
+} __attribute__ ((__packed__));
+
+typedef struct ErrlCallout ErrlCallout_t;
+
+// The User Detail Entry Structure consists of the fields below followed
+// by the actual data the user is trying to collect.
+// NOTE: A data pointer field is NOT defined but rather inferred here. In the
+// error log contents, the user will see all the subsequent fields followed
+// by the actual data
+/* User Detail Entry Structure */
+struct ErrlUserDetailsEntry
+{
+ uint8_t iv_version; // User Details Entry Version
+ uint8_t iv_type; // User Details Entry Type
+ // Note: Users must use ERRL_USR_DETAIL_TYPE enum
+ uint16_t iv_size; // User Details Entry Size
+} __attribute__ ((__packed__));
+
+typedef struct ErrlUserDetailsEntry ErrlUserDetailsEntry_t;
+
+// The User Detail Structure consists of the fields below followed
+// by each individual User Details Entry structure & data
+// NOTE: A data pointer field is NOT defined but rather inferred here. In the
+// error log contents, the user will see all the subsequent fields followed
+// by each User Details Entry structure and its data
+/* User Detail Structure */
+struct ErrlUserDetails
+{
+ uint8_t iv_version; // User Details Version
+ uint8_t iv_reserved; // Reserved
+ uint16_t iv_modId; // Module Id
+ uint32_t iv_fwLevel; // Firmware Level
+ uint64_t iv_timeStamp; // Time Stamp
+ uint8_t iv_occId; // OCC ID
+ uint8_t iv_occRole; // OCC Role
+ uint8_t iv_operatingState; // OCC State
+ uint8_t iv_committed:1; // Log Committed?
+ uint8_t iv_reserved1:7;
+ uint32_t iv_userData1; // User Data Word 1
+ uint32_t iv_userData2; // User Data Word 2
+ uint32_t iv_userData3; // User Data Word 3
+ uint32_t iv_userData4; // User Data Word 4
+ uint16_t iv_entrySize; // Log Size
+ uint16_t iv_userDetailEntrySize; // User Details Size
+} __attribute__ ((__packed__));
+
+typedef struct ErrlUserDetails ErrlUserDetails_t;
+
+/* Error Log Structure */
+struct ErrlEntry
+{
+ uint16_t iv_checkSum; // Log CheckSum
+ uint8_t iv_version; // Log Version
+ uint8_t iv_entryId; // Log Entry ID
+ uint8_t iv_reasonCode; // Log Reason Code
+ uint8_t iv_severity; // Log Severity
+ // NOTE: Users must use ERRL_SEVERITY enum
+ uint8_t iv_reserved1; // Reserved
+
+ uint8_t iv_numCallouts; // Log Callout Number
+ ErrlCallout_t iv_callouts[ERRL_MAX_CALLOUTS];
+ ErrlUserDetails_t iv_userDetails; // User Details section for Log
+
+} __attribute__ ((__packed__));
+
+typedef struct ErrlEntry ErrlEntry_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: main
+//
+// Description: main function
+//
+// Flow: FN=None
+//
+// End Function Specification
+main()
+{
+ FILE * l_fptr = fopen( "occ.log.bin", "r");
+ uint32_t l_sizeRead = 0;
+ uint32_t l_readBuf[3072] = {0};
+
+ if ( l_fptr )
+ {
+ fseek( l_fptr, 0, SEEK_END);
+ uint32_t l_len = ftell( l_fptr );
+ fseek( l_fptr, 0, SEEK_SET);
+
+ l_sizeRead = fread( l_readBuf, 1, l_len, l_fptr );
+
+ printf("File read contains %d bytes read %d \n", l_len, l_sizeRead );
+ }
+
+ fclose( l_fptr );
+
+ ErrlEntry_t l_log;
+
+ memcpy( &l_log, l_readBuf, l_sizeRead );
+
+ printf(" CheckSum : 0x%04X \n", ntohs(l_log.iv_checkSum) );
+ printf(" Version : 0x%02X \n", l_log.iv_version);
+ printf(" Entry Id : 0x%02X \n", l_log.iv_entryId);
+ printf(" Reason Code: 0x%02X \n", l_log.iv_reasonCode);
+ printf(" Severity : 0x%02X \n", l_log.iv_severity);
+ printf(" Callouts : 0x%02X \n", l_log.iv_numCallouts);
+ uint8_t l_index=0;
+ for( l_index=0; l_index < ERRL_MAX_CALLOUTS; l_index++)
+ {
+ printf(" Callout%d : \n", l_index+1);
+ printf(" HOM UID : 0x%08X \n", ntohl(l_log.iv_callouts[l_index].iv_homUnitId));
+ printf(" Priority : 0x%02X \n", l_log.iv_callouts[l_index].iv_priority );
+ }
+ printf(" UserDetails : \n" );
+ printf(" Version : 0x%02X \n", l_log.iv_userDetails.iv_version );
+ printf(" Module Id : 0x%04X \n", ntohs(l_log.iv_userDetails.iv_modId) );
+ printf(" Firmware Level : 0x%08X \n", l_log.iv_userDetails.iv_fwLevel );
+ printf(" Time : 0x%08X \n", l_log.iv_userDetails.iv_timeStamp );
+ printf(" OCC ID : 0x%02X \n", l_log.iv_userDetails.iv_occId );
+ printf(" OCC Role : 0x%02X \n", l_log.iv_userDetails.iv_occRole );
+ printf(" OCC State : 0x%02X \n", l_log.iv_userDetails.iv_operatingState );
+ printf(" Committed : %s \n", (l_log.iv_userDetails.iv_committed != 0) ? "true":"false" );
+ printf(" Word 1 : 0x%08X \n", ntohl(l_log.iv_userDetails.iv_userData1) );
+ printf(" Word 2 : 0x%08X \n", ntohl(l_log.iv_userDetails.iv_userData2) );
+ printf(" Word 3 : 0x%08X \n", ntohl(l_log.iv_userDetails.iv_userData3) );
+ printf(" Word 4 : 0x%08X \n", ntohl(l_log.iv_userDetails.iv_userData4) );
+ printf(" Entry Size : 0x%04X \n", ntohs(l_log.iv_userDetails.iv_entrySize) );
+
+
+ return 0;
+}
diff --git a/src/occ/errl/test/test.mk b/src/occ/errl/test/test.mk
new file mode 100755
index 0000000..a4b5b4b
--- /dev/null
+++ b/src/occ/errl/test/test.mk
@@ -0,0 +1,28 @@
+# $Id$
+
+# @file test.mk
+#
+# @brief mk occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section test.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+errltest_CFILES = \
+ ../../common.c \
+ ../errl.c \
+ ../../thread/threadSch.c \
+ errltest.c
+
+all_cfiles = ${errltest_CFILES}
+
diff --git a/src/occ/gcov.h b/src/occ/gcov.h
new file mode 100644
index 0000000..0bc30ad
--- /dev/null
+++ b/src/occ/gcov.h
@@ -0,0 +1,110 @@
+#ifndef __GCOV_H
+#define __GCOV_H
+
+/** @file gcov.h
+ * @brief Header file to generate gcov_info chain for each module.
+ *
+ * Each gcov-instrumented module needs to have its own gcov_info chain
+ * and associated linking function. Each .o file will have its own
+ * gcov_info object which is added to the chain when the module is loaded
+ * (static initializers) by calling the __gcov_init function.
+ *
+ * We make the gcov_info chain unique per-module, instead of a single
+ * global chain, so that we don't have bad pointers if a module was
+ * loaded and then unloaded.
+ */
+#ifdef GCOV_CODE_COVERAGE
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+/** @struct gcov_info
+ * @brief Structure generated by gcc. Do not use.
+ *
+ * This structure is automatically generated and instances of it created by
+ * gcc when the --coverage compile option is used. We don't need to
+ * manipulate this structure from code except:
+ * 1) To fix up the chains as objects are added to the chain.
+ * 2) To copy the gcov_info and counters into the base-chain when we
+ * unload a module.
+ *
+ * The rest of this structure is parsed by the Gcov.pm debug tool.
+ *
+ * Most of the items in here are used as uint32_t's by gcov but are still
+ * aligned on a 64-bit boundary. The unusedN fields are to ensure proper
+ * alignment.
+ */
+struct gcov_info
+{
+ uint32_t version;
+ struct gcov_info* next;
+ uint32_t timestamp;
+ char* filename;
+ uint32_t n_functions;
+ void* functions;
+ uint32_t counter_mask;
+ uint32_t n_counters;
+ uint64_t* counters;
+} PACKED;
+
+// Preprocessor magic to create a variable name based off the module name.
+// GCOV_INFO_OBJ() will create a post-processed name like
+// 'foobar_gcov_info_head' or 'core_gcov_info_head'.
+#define __GCOV_PREFIX core
+#define __GCOV_PREFIX_NAME "core"
+
+#define __GCOV_INFO_OBJ(X,Y) X ## Y
+#define _GCOV_INFO_OBJ(X,Y) __GCOV_INFO_OBJ(X,Y)
+#define GCOV_INFO_OBJ() _GCOV_INFO_OBJ(__GCOV_PREFIX, _gcov_info_head)
+
+/** Pointer to the beginning of the gcov_info chain for this module. */
+struct gcov_info* GCOV_INFO_OBJ() = NULL;
+
+/** Function called by module loading to add the object gcov_info instance
+ * to the chain.
+ */
+void __gcov_init(struct gcov_info* i_info)
+{
+ // Atomically push i_info onto the gcov_info_head stack.
+ do
+ {
+ i_info->next = GCOV_INFO_OBJ();
+ } while (!__sync_bool_compare_and_swap(&GCOV_INFO_OBJ(),
+ i_info->next, i_info));
+}
+
+
+/** Unneeded function but must be defined to compile.
+ *
+ * This function appears to be typically used by libgcov.so when instrumented
+ * on a real linux-based system. It can be used to merge counters across
+ * multiple runs or when a 'fork' occurs. It doesn't appear that this
+ * function ever gets called for us but the unresolved symbol is added to
+ * the module (by gcc) so we've created a stub here to pass compile.
+ */
+void __gcov_merge_add()
+{
+ while(1);
+}
+
+
+typedef void (*ctor)(void);
+extern void __CTOR_LIST__;
+extern void __CTOR_END__;
+#define __CTOR_LIST ((const ctor *) &__CTOR_LIST__)
+#define __CTOR_END ((const ctor *) &__CTOR_END__)
+void gcov_entry() {
+ ctor const *ptr = __CTOR_LIST;
+ ctor const *end = __CTOR_END;
+ while(ptr != end) {
+ if(*ptr)
+ (*ptr)();
+ ptr++;
+ }
+}
+
+#endif
+
+#endif
+
diff --git a/src/occ/gpe/apss_altitude.pS b/src/occ/gpe/apss_altitude.pS
new file mode 100755
index 0000000..6deac1d
--- /dev/null
+++ b/src/occ/gpe/apss_altitude.pS
@@ -0,0 +1,163 @@
+# *****************************************************************************
+# @file apss_altitude.S
+# @brief Read the altitude from the APSS
+#
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section apss_altitude.S APSS_ALTITUDE.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Includes
+ //////////////////////////////////////////////////////////////////////
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Address Space
+ //////////////////////////////////////////////////////////////////////
+ .oci
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Symbols
+ //////////////////////////////////////////////////////////////////////
+
+#include <pss_constants.h>
+
+#define GPE_PROG_ID 0x0002
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Structures
+ //////////////////////////////////////////////////////////////////////
+
+ // Declare the offsets of the struct that will be passed to the
+ // GPE program via the ETR register
+ //
+ // struct G_gpe_apss_read_altitude_args =
+ // {
+ .struct 0
+ERROR_RC:
+ .struct ERROR_RC + 8
+ERROR_FFDC:
+ .struct ERROR_FFDC + 8
+ALTITUDE:
+ // };
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Begin Program
+ //////////////////////////////////////////////////////////////////////
+
+ .text
+
+#include <gpe_macros.h>
+#include <pss_macros.h>
+
+
+ //--------------------------------------------------------------------
+ // PORE-GPE Routine Specification:
+ //
+ // Name: GPE_apss_read_altitude
+ //
+ // Description: Initialize APSS GPIO pins for Input/Output, Interrupt
+ // Drive H/L
+ //
+ // Inputs: G_gpe_apss_read_altitude_args
+ // struct {
+ // PoreGpeErrorStruct error;
+ // uint16_t altitude; // This is where the altitude will be stored (output)
+ // uint8_t reserved[6]; // Requried since GPE only does 8 byte writes.
+ // } G_gpe_apss_read_altitude_args
+ // struct {
+ // uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+ // uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+ // } PoreGpeErrorStruct;
+ //
+ // Outputs: Altitude (and FFDC on failure)
+ //
+ // Flow: 7/20/11 FN=GPE_apss_set_composite_mode
+ //
+ // References: APSS FUnctional Specification v0.7.18
+ // GPE_apss_access_scoms.odt (summary of regisers/data)
+ //
+ // End PORE-GPE Routine Specification
+ //--------------------------------------------------------------------
+ .global GPE_apss_read_altitude
+GPE_apss_read_altitude:
+
+ // Copy passed Structure Pointer into A1
+ mr A1, ETR
+
+ // Wait for SPI operations to be complete (10usec timeout)
+ _wait_for_spi_ops_complete 10, error_timeout
+
+ // Setup control regs
+ // frame_size=16, out_count=16, in_delay1=never, in_count2=16
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x410FC00004000000
+ // bridge_enable, clock_divider=7, 2 frames
+ _putscom SPIPSS_P2S_CTRL_REG1, 0x801C400000000000
+ // inter_frame_delay=25 (2.5usec)
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x000C800000000000
+
+ // APSS command to get the altitude (APSS cmd 0x9000)
+ li D0, 0x9000000000000000
+ _putscom_d0 SPIPSS_P2S_WDATA_REG
+
+ // Start SPI transaction
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+
+ // wait 10usec for command to complete
+ waits (10 * MICROSECONDS)
+
+ // Wait for SPI operations to be complete (10usec timeout)
+ _wait_for_spi_ops_complete 10, error_altitude_timeout
+
+ // Read altitude and store in structure
+ _getscom SPIPSS_P2S_RDATA_REG
+ // The scom data for that cmd is in 2nd two bytes of the register (shift left 2 bytes)
+ rols D0, D0, 16
+ std D0, ALTITUDE, A1
+
+ halt // End of GPE_apss_initialize_gpio
+
+
+error_statusreg:
+ // An error/reserved bit was set when reading p2s status register...
+ // D0: P2S_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0002
+ halt
+
+
+error_timeout:
+ // p2s_ongoing bit was never cleared after several retries...
+ // D0: P2S_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0001
+ halt
+
+
+error_altitude_timeout:
+ // After sending the read altitude command, the p2s_ongoing bit was
+ // never cleared after several retries...
+ // D0: P2S_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0003
+ halt
+
+
+ //////////////////////////////////////////////////////////////////////
+ // End of Program
+ //////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/occ/gpe/apss_composite.pS b/src/occ/gpe/apss_composite.pS
new file mode 100755
index 0000000..7325eb0
--- /dev/null
+++ b/src/occ/gpe/apss_composite.pS
@@ -0,0 +1,169 @@
+# *****************************************************************************
+# @file apss_composite.S
+# @brief Set APSS into composite mode so OCC can read ADC, Temp & GPIO data
+#
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section apss_composite.S APSS_COMPOSITE.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @th032 thallet 04/16/2013 Tuleta HW Bringup
+# @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+# @gm026 916029 milesg 02/17/2014 revert back to auto2 mode without reading GPIO's
+# @gm038 926761 milesg 05/16/2014 slowed SPI bus down from 12MHz to 10MHz on venice (8MHz on murano)
+# @gs039 936836 gjsilva 08/28/2014 slowed SPI bus down from 10MHz to 8MHz on venice (~6MHz on murano)
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Includes
+ //////////////////////////////////////////////////////////////////////
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Address Space
+ //////////////////////////////////////////////////////////////////////
+ .oci
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Symbols
+ //////////////////////////////////////////////////////////////////////
+
+#include <pss_constants.h>
+
+#define GPE_PROG_ID 0x0003
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Structures
+ //////////////////////////////////////////////////////////////////////
+
+ // Declare the offsets of the struct that will be passed to the
+ // GPE program via the ETR register
+ //
+ // struct G_gpe_apss_read_altitude_args =
+ // {
+ .struct 0
+ERROR_RC:
+ .struct ERROR_RC + 8
+ERROR_FFDC:
+ .struct ERROR_FFDC + 8
+CONFIG:
+ // };
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Begin Program
+ //////////////////////////////////////////////////////////////////////
+
+ .text
+
+#include <gpe_macros.h>
+#include <pss_macros.h>
+
+
+ //--------------------------------------------------------------------
+ // PORE-GPE Routine Specification:
+ //
+ // Name: GPE_apss_set_composite_mode
+ //
+ // Description: Set APSS into composite mode so OCC can read ADC, Temp & GPIO data
+ //
+ // Inputs: G_gpe_apss_set_composite_mode_args
+ // struct {
+ // PoreGpeErrorStruct error;
+ // apssCompositeConfigStruct_t config; // G_apss_composite_config (input to APSS)
+ // } G_gpe_apss_set_composite_mode_args;
+ // struct {
+ // uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+ // uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+ // } PoreGpeErrorStruct;
+ // struct {
+ // uint8_t numAdcChannelsToRead;
+ // uint8_t numGpioPortsToRead;
+ // } apssCompositeConfigStruct
+ //
+ // Outputs: None (except FFDC on failure)
+ //
+ // Flow: 7/20/11 FN=GPE_apss_set_composite_mode
+ //
+ // References: APSS FUnctional Specification v0.7.18
+ // GPE_apss_access_scoms.odt (summary of regisers/data)
+ //
+ // End PORE-GPE Routine Specification
+ //--------------------------------------------------------------------
+ .global GPE_apss_set_composite_mode
+GPE_apss_set_composite_mode:
+
+ // Copy passed Structure Pointer into A1
+ mr A1, ETR
+
+ // Wait for SPI operations to be complete (10usec timeout)
+ _wait_for_spi_ops_complete 10, error_timeout
+
+ // Initialize SPIPSS -- Don't do this. Value is platform dependent and set by HWP outside of OCC (gm026)
+ //_putscom SPIPSS_100NS_REG, 0x0000003200000000
+
+ // Setup control regs
+ // frame size=16, out_count1=16, in_delay1=never, in_count2=16
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x4100000000000000
+ // bridge_enable, clock_divider=7, 1 frame
+ //_putscom SPIPSS_P2S_CTRL_REG1, 0x8060000000000000
+ //_putscom SPIPSS_P2S_CTRL_REG1, 0x8074000000000000 //gm038
+ _putscom SPIPSS_P2S_CTRL_REG1, 0x8090000000000000 //@gs039
+ // inter_frame_delay=25 (2.5usec)
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x0019000000000000
+
+ // APSS command to set composite data streaming mode (APSS cmd 0x8xxx, reserved bits are 1)
+ li D0, 0x8C00000000000000
+ // last ADC channel address (0 = 1 ADC, etc)
+ ldandi D1, CONFIG, A1, 0x1F00000000000000
+ srdi D1, D1, 56
+ subs D1, D1, 1
+ sldi D1, D1, 54
+ or D0, D0, D1
+ // number of GPIO ports to return (0 = 0 GPIOs, etc...)
+ ldandi D1, CONFIG, A1, 0x0003000000000000 // @at023c
+ or D0, D0, D1
+ ////_putscom_d0 SPIPSS_P2S_WDATA_REG
+ _putscom SPIPSS_P2S_WDATA_REG, 0x3FC0000000000000 // gm026 -- use auto2 mode (more reliable than composite mode)
+
+ // Start SPI transaction
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+
+ // Wait 20usec for apss becoming ready to send out the frame of composite mode
+ // 10usec is not enough and 20use is ok from test result.
+ waits (20 * MICROSECONDS) // @at023c
+
+ halt // End of GPE_apss_initialize_gpio
+
+
+error_statusreg:
+ // An error/reserved bit was set when reading p2s status register...
+ // D0: P2S_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0002
+ halt
+
+
+error_timeout:
+ // p2s_ongoing bit was never cleared after several retries...
+ // D0: P2S_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0001
+ halt
+
+
+ //////////////////////////////////////////////////////////////////////
+ // End of Program
+ //////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/occ/gpe/apss_constants.h b/src/occ/gpe/apss_constants.h
new file mode 100755
index 0000000..ddda1b4
--- /dev/null
+++ b/src/occ/gpe/apss_constants.h
@@ -0,0 +1,68 @@
+/******************************************************************************
+// @file apss_constants.h
+// @brief Constants used by APSS communications GPE programs
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section apss_constants.h APSS_CONSTANTS.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ *
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define SPIPSS_REGISTER_BASE 0x00020000
+#define SPIPSS_ADC_CTRL_REG0 (SPIPSS_REGISTER_BASE + 0x00)
+#define SPIPSS_ADC_CTRL_REG1 (SPIPSS_REGISTER_BASE + 0x01)
+#define SPIPSS_ADC_CTRL_REG2 (SPIPSS_REGISTER_BASE + 0x02)
+#define SPIPSS_ADC_STATUS_REG (SPIPSS_REGISTER_BASE + 0x03)
+#define SPIPSS_ADC_COMMAND_REG (SPIPSS_REGISTER_BASE + 0x04)
+#define SPIPSS_ADC_WDATA_REG (SPIPSS_REGISTER_BASE + 0x10)
+#define SPIPSS_ADC_RDATA_REG0 (SPIPSS_REGISTER_BASE + 0x20)
+#define SPIPSS_ADC_RDATA_REG1 (SPIPSS_REGISTER_BASE + 0x21)
+#define SPIPSS_ADC_RDATA_REG2 (SPIPSS_REGISTER_BASE + 0x22)
+#define SPIPSS_ADC_RDATA_REG3 (SPIPSS_REGISTER_BASE + 0x23)
+#define SPIPSS_P2S_CTRL_REG0 (SPIPSS_REGISTER_BASE + 0x40)
+#define SPIPSS_P2S_CTRL_REG1 (SPIPSS_REGISTER_BASE + 0x41)
+#define SPIPSS_P2S_CTRL_REG2 (SPIPSS_REGISTER_BASE + 0x42)
+#define SPIPSS_P2S_STATUS_REG (SPIPSS_REGISTER_BASE + 0x43)
+#define SPIPSS_P2S_COMMAND_REG (SPIPSS_REGISTER_BASE + 0x44)
+#define SPIPSS_P2S_WDATA_REG (SPIPSS_REGISTER_BASE + 0x50)
+#define SPIPSS_P2S_RDATA_REG (SPIPSS_REGISTER_BASE + 0x60)
+
+//*************************************************************************
+// Strustures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
diff --git a/src/occ/gpe/apss_init.pS b/src/occ/gpe/apss_init.pS
new file mode 100755
index 0000000..fd66147
--- /dev/null
+++ b/src/occ/gpe/apss_init.pS
@@ -0,0 +1,230 @@
+# *****************************************************************************
+# @file apss_init.S
+# @brief Initialize the APSS GPIOs
+#
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section apss_init.S APSS_INIT.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @gm038 926761 milesg 05/16/2014 slowed SPI bus down from 12MHz to 10MHz on venice (8MHz on murano)
+# @gs039 936836 gjsilva 08/28/2014 slowed SPI bus down from 10MHz to 8MHz on venice (~6MHz on murano)
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Includes
+ //////////////////////////////////////////////////////////////////////
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Address Space
+ //////////////////////////////////////////////////////////////////////
+ .oci
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Symbols
+ //////////////////////////////////////////////////////////////////////
+
+#include <pss_constants.h>
+
+#define GPE_PROG_ID 0x0001
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Structures
+ //////////////////////////////////////////////////////////////////////
+
+ // Declare the offsets of the struct that will be passed to the
+ // GPE program via the ETR register
+ //
+ // struct G_gpe_apss_initialize_gpio_args =
+ // {
+ .struct 0
+ERROR_RC:
+ .struct ERROR_RC + 8
+ERROR_FFDC:
+ .struct ERROR_FFDC + 8
+CONFIG:
+ // };
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Begin Program
+ //////////////////////////////////////////////////////////////////////
+
+ .text
+
+#include <gpe_macros.h>
+#include <pss_macros.h>
+
+
+ //--------------------------------------------------------------------
+ // Name: _perform_spi_transaction (MACRO)
+ //
+ // Description: Start SPI transaction, wait for 5usec, and then
+ // wait for operation to complete.
+ //
+ // Inputs: None
+ //
+ // Outputs: None (on error, D0 will contain status register)
+ //
+ // Modifies: CTR, D0, D1
+ //--------------------------------------------------------------------
+ .macro _perform_spi_transaction
+
+ // Start SPI transaction
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+
+ // wait 5usec
+ waits (5 * MICROSECONDS)
+
+ _wait_for_spi_ops_complete 10, error_timeout
+
+ .endm
+
+
+ //--------------------------------------------------------------------
+ // PORE-GPE Routine Specification:
+ //
+ // Name: GPE_apss_initialize_gpio
+ //
+ // Description: Initialize APSS GPIO pins for Input/Output, Interrupt
+ // Drive H/L
+ //
+ // Inputs: G_gpe_apss_initialize_gpio_args - Error and G_gpio_config
+ // struct {
+ // PoreGpeErrorStruct error;
+ // apssGpioConfigStruct gpio_config0 // G_gpio_config[0] (input to APSS)
+ // apssGpioConfigStruct gpio_config1 // G_gpio_config[1] (input to APSS)
+ // } G_gpe_apss_initialize_gpio_args
+ // struct {
+ // uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+ // uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+ // } PoreGpeErrorStruct;
+ // struct apssGpioConfigStruct
+ // {
+ // uint8_t direction;
+ // uint8_t drive;
+ // uint8_t interrupt;
+ // }
+ //
+ // Outputs: None (except FFDC on failure)
+ //
+ // Flow: 7/20/11 FN=GPE_apss_initialize_gpio
+ //
+ // References: APSS FUnctional Specification v0.7.18
+ // GPE_apss_access_scoms.odt (summary of regisers/data)
+ //
+ // End PORE-GPE Routine Specification
+ //--------------------------------------------------------------------
+ .global GPE_apss_initialize_gpio
+GPE_apss_initialize_gpio:
+
+ // Copy passed Structure Pointer into A1
+ mr A1, ETR
+ halt // TULETA_HW_BRINGUP
+
+ // Wait for SPI operations to be complete (up to 10usec timeout)
+ _wait_for_spi_ops_complete 10, error_timeout
+
+ // Setup control regs
+ // frame_size=16, out_count=16, in_delay1=never, in_count2=16
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x410FC00004000000
+ // bridge_enable, clock_divider=7, 2 frames
+ //_putscom SPIPSS_P2S_CTRL_REG1, 0x801C400000000000
+ //_putscom SPIPSS_P2S_CTRL_REG1, 0x8074400000000000 //gm038
+ _putscom SPIPSS_P2S_CTRL_REG1, 0x8090400000000000 //@gs039
+ // inter_frame_delay=50 (5usec)
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x0019000000000000
+
+ // Build apss commands based on gpio_config arguments
+ // Arguments are each 1 byte long and contain default
+ // value to be used to init each item (Direction/Drive/Interrupt)
+
+ //// Port 0
+
+ // Port 0 - Direction (APSS cmd 0x40xx)
+ ldandi D0, CONFIG, A1, 0xFF00000000000000
+ srdi D0, D0, 8
+ ori D0, D0, 0x4000000000000000
+ _putscom_d0 SPIPSS_P2S_WDATA_REG
+
+ _perform_spi_transaction
+
+ // Port 0 - Drive (APSS cmd 0x50xx)
+ ldandi D0, CONFIG, A1, 0x00FF000000000000
+ ori D0, D0, 0x5000000000000000
+ _putscom_d0 SPIPSS_P2S_WDATA_REG
+
+ _perform_spi_transaction
+
+ // Port 0 - Interrupt (APSS cmd 0x60xx)
+ ldandi D0, CONFIG, A1, 0x0000FF0000000000
+ ori D0, D0, 0x0060000000000000
+ sldi D0, D0, 8
+ _putscom_d0 SPIPSS_P2S_WDATA_REG
+
+ _perform_spi_transaction
+
+ //// Port 1
+
+ // Port 1 - Direction (APSS cmd 0x41xx)
+ ldandi D0, CONFIG, A1, 0x000000FF00000000
+ ori D0, D0, 0x0000410000000000
+ sldi D0, D0, 16
+ _putscom_d0 SPIPSS_P2S_WDATA_REG
+
+ _perform_spi_transaction
+
+ // Port 1 - Drive (APSS cmd 0x51xx)
+ ldandi D0, CONFIG, A1, 0x00000000FF000000
+ ori D0, D0, 0x0000005100000000
+ sldi D0, D0, 24
+ _putscom_d0 SPIPSS_P2S_WDATA_REG
+
+ _perform_spi_transaction
+
+ // Port 1 - Interrups (APSS cmd 0x61xx)
+ ldandi D0, CONFIG, A1, 0x0000000000FF0000
+ ori D0, D0, 0x0000000061000000
+ sldi D0, D0, 32
+ _putscom_d0 SPIPSS_P2S_WDATA_REG
+
+ // Start SPI transaction (dont need to wait for p2s_ongoing bit since last cmd)
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+
+ // wait 5usec
+ waits (5 * MICROSECONDS)
+
+ halt // End of GPE_apss_initialize_gpio
+
+
+error_statusreg:
+ // An error/reserved bit was set when reading p2s status register...
+ // D0: P2S_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0002
+ halt
+
+
+error_timeout:
+ // p2s_ongoing bit was never cleared after several retries...
+ // D0: P2S_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0001
+ halt
+
+
+ //////////////////////////////////////////////////////////////////////
+ // End of Program
+ //////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/occ/gpe/apss_meas_read_complete.pS b/src/occ/gpe/apss_meas_read_complete.pS
new file mode 100755
index 0000000..f16afb6
--- /dev/null
+++ b/src/occ/gpe/apss_meas_read_complete.pS
@@ -0,0 +1,143 @@
+# *****************************************************************************
+# @file apss_meas_read_complete.S
+# @brief Finish reading power measurements from APSS
+#
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section apss_meas_read_complete.S APSS_MEAS_READ_COMPLETE.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+# @gm026 916029 milesg 02/17/2014 revert back to auto2 mode without reading GPIO's
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Includes
+ //////////////////////////////////////////////////////////////////////
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Address Space
+ //////////////////////////////////////////////////////////////////////
+ .oci
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Symbols
+ //////////////////////////////////////////////////////////////////////
+
+#include <pss_constants.h>
+
+#define GPE_PROG_ID 0x0006
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Structures
+ //////////////////////////////////////////////////////////////////////
+
+ // Declare the offsets of the struct that will be passed to the
+ // GPE program via the ETR register
+ //
+ // struct G_gpe_apss_continue_pwr_meas_read_args =
+ // {
+ .struct 0
+ERROR_RC:
+ .struct ERROR_RC + 8
+ERROR_FFDC:
+ .struct ERROR_FFDC + 8
+MEASUREMENTS:
+ .struct MEASUREMENTS + 24
+MEASUREMENTS_TOD:
+ // };
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Begin Program
+ //////////////////////////////////////////////////////////////////////
+
+ .text
+
+#include <gpe_macros.h>
+#include <pss_macros.h>
+
+ //--------------------------------------------------------------------
+ // PORE-GPE Routine Specification:
+ //
+ // Name: GPE_apss_complete_pwr_meas_read
+ //
+ // Description: Kick of the power measurement from APSS
+ //
+ // Inputs: G_gpe_complete_pwr_meas_read_args
+ // struct {
+ // PoreGpeErrorStruct error;
+ // ApssPwrMeas_t meas;
+ // uint64_t meas_data[4]; // G_apss_pwr_meas (2nd block of data) (output from APSS)
+ // } G_gpe_complete_pwr_meas_read_args
+ // struct {
+ // uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+ // uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+ // } PoreGpeErrorStruct;
+ //
+ // Outputs: ApssPwrMeas (measurement data)
+ // GPE_complete_pwr_meas_read (error on failure)
+ //
+ // Flow: 7/20/11 FN=GPE_apss_complete_pwr_meas_read
+ //
+ // References: APSS FUnctional Specification v0.7.18
+ // GPE_apss_access_scoms.odt (summary of regisers/data)
+ //
+ // End PORE-GPE Routine Specification
+ //--------------------------------------------------------------------
+ .global GPE_apss_complete_pwr_meas_read
+GPE_apss_complete_pwr_meas_read:
+
+ // Copy passed Structure Pointer into A1
+ mr A1, ETR
+
+ // Wait for up to 5us for spi op complete, else branch to error_timeout
+ _wait_for_adc_ops_complete 100, error_timeout
+
+ // Read/save last 32 bytes of data and Time of Day
+ //_getscom SPIPSS_ADC_RDATA_REG0
+ //std D0, MEASUREMENTS, A1 //gm026
+
+ //_getscom SPIPSS_ADC_RDATA_REG1
+ //std D0, (MEASUREMENTS + 8), A1 //gm026
+
+ // REG2,3 not needed (all measurements fit in above data)
+
+ _getscom TOD_VALUE_REG
+ std D0, MEASUREMENTS_TOD, A1
+
+ halt // End of GPE_apss_complete_pwr_meas_read
+
+
+error_statusreg:
+ // An error/reserved bit was set when reading adc status register...
+ // D0: ADC_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0002
+ halt
+
+
+error_timeout:
+ // adc_ongoing bit was never cleared after several retries...
+ // D0: ADC_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0001
+ halt
+
+
+ //////////////////////////////////////////////////////////////////////
+ // End of Program
+ //////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/occ/gpe/apss_meas_read_cont.pS b/src/occ/gpe/apss_meas_read_cont.pS
new file mode 100755
index 0000000..1b71c9b
--- /dev/null
+++ b/src/occ/gpe/apss_meas_read_cont.pS
@@ -0,0 +1,161 @@
+# *****************************************************************************
+# @file apss_meas_read_cont.S
+# @brief Continue reading power measurements from APSS
+#
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section apss_meas_read_cont.S APSS_MEAS_READ_CONT.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+# @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+# @gm026 916029 milesg 02/17/2014 revert back to auto2 mode without reading GPIO's
+# @gm038 926761 milesg 05/16/2014 slowed SPI bus down from 12MHz to 10MHz on venice (8MHz on murano)
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Includes
+ //////////////////////////////////////////////////////////////////////
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Address Space
+ //////////////////////////////////////////////////////////////////////
+ .oci
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Symbols
+ //////////////////////////////////////////////////////////////////////
+
+#include <pss_constants.h>
+
+#define GPE_PROG_ID 0x0005
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Structures
+ //////////////////////////////////////////////////////////////////////
+
+ // Declare the offsets of the struct that will be passed to the
+ // GPE program via the ETR register
+ //
+ // struct G_gpe_apss_continue_pwr_meas_read_args =
+ // {
+ .struct 0
+ERROR_RC:
+ .struct ERROR_RC + 8
+ERROR_FFDC:
+ .struct ERROR_FFDC + 8
+MEASUREMENTS:
+ // };
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Begin Program
+ //////////////////////////////////////////////////////////////////////
+
+ .text
+
+#include <gpe_macros.h>
+#include <pss_macros.h>
+
+ //--------------------------------------------------------------------
+ // PORE-GPE Routine Specification:
+ //
+ // Name: GPE_apss_continue_pwr_meas_read
+ //
+ // Description: Kick of the power measurement from APSS
+ //
+ // Inputs: G_gpe_continue_pwr_meas_read_args
+ // struct {
+ // PoreGpeErrorStruct error;
+ // uint64_t meas_data[4]; // G_apss_pwr_meas (1st block of data) (output from APSS)
+ // } G_gpe_continue_pwr_meas_read_args
+ // struct {
+ // uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+ // uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+ // } PoreGpeErrorStruct;
+ //
+ // Outputs: GPE_continue_pwr_meas_read (error on failure)
+ //
+ // Flow: 7/20/11 FN=GPE_apss_continue_pwr_meas_read
+ //
+ // References: APSS FUnctional Specification v0.7.18
+ // GPE_apss_access_scoms.odt (summary of regisers/data)
+ //
+ // End PORE-GPE Routine Specification
+ //--------------------------------------------------------------------
+ .global GPE_apss_continue_pwr_meas_read
+GPE_apss_continue_pwr_meas_read:
+
+ // Copy passed Structure Pointer into A1
+ mr A1, ETR
+
+ // Wait for up to 5us for spi op complete, else branch to error_timeout
+ _wait_for_adc_ops_complete 100, error_timeout
+
+ // Read/save first 32 bytes of data
+ _getscom SPIPSS_ADC_RDATA_REG0 // Verified
+ std D0, MEASUREMENTS, A1
+
+ _getscom SPIPSS_ADC_RDATA_REG1 // Verified
+ std D0, (MEASUREMENTS + 8), A1
+
+ _getscom SPIPSS_ADC_RDATA_REG2 // Verified
+ std D0, (MEASUREMENTS + 16), A1
+
+ _getscom SPIPSS_ADC_RDATA_REG3 // Verified
+ std D0, (MEASUREMENTS + 24), A1
+
+ // Commented out reading of GPIO data -- gm026
+ // Delay between frames. Interframe delay are all 5usec
+ // Without this delay, can't get correct gpio data
+ //waits (5 * MICROSECONDS) // @at023a
+ // Setup control regs
+ // frame_size=16, out_count=16, in_count=16
+ //_putscom SPIPSS_ADC_CTRL_REG0, 0x4000100000000000 // @at023c
+ // ADC FSM, clock_divider=7, frames=2 // @ly003c ignore temperature
+ //_putscom SPIPSS_ADC_CTRL_REG1, 0x8060400000000000
+ //_putscom SPIPSS_ADC_CTRL_REG1, 0x8074400000000000 //gm038
+ // ADC interframe delay (5usec)
+ //_putscom SPIPSS_ADC_CTRL_REG2, 0x0019000000000000
+
+ // APSS command to continue previous command
+ //_putscom SPIPSS_ADC_WDATA_REG, 0x0000000000000000
+
+ // Start SPI transaction
+ //_putscom SPIPSS_ADC_COMMAND_REG, 0x8000000000000000
+
+ halt // End of GPE_apss_initialize_gpio
+
+
+error_statusreg:
+ // An error/reserved bit was set when reading adc status register...
+ // D0: ADC_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0002
+ halt
+
+
+error_timeout:
+ // adc_ongoing bit was never cleared after several retries...
+ // D0: ADC_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0001
+ halt
+
+
+ //////////////////////////////////////////////////////////////////////
+ // End of Program
+ //////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/occ/gpe/apss_meas_read_start.pS b/src/occ/gpe/apss_meas_read_start.pS
new file mode 100755
index 0000000..b8cae79
--- /dev/null
+++ b/src/occ/gpe/apss_meas_read_start.pS
@@ -0,0 +1,144 @@
+# *****************************************************************************
+# @file apss_meas_read_start.S
+# @brief Kick of the reading of power measurement from APSS
+#
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section apss_meas_read_start.S APSS_MEAS_READ_START.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @gm038 926761 milesg 05/16/2014 slowed SPI bus down from 12MHz to 10MHz on venice (8MHz on murano)
+# @gs039 936836 gjsilva 08/28/2014 slowed SPI bus down from 10MHz to 8MHz on venice (~6MHz on murano)
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Includes
+ //////////////////////////////////////////////////////////////////////
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Address Space
+ //////////////////////////////////////////////////////////////////////
+ .oci
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Symbols
+ //////////////////////////////////////////////////////////////////////
+
+#include <pss_constants.h>
+
+#define GPE_PROG_ID 0x0004
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Structures
+ //////////////////////////////////////////////////////////////////////
+
+ // Declare the offsets of the struct that will be passed to the
+ // GPE program via the ETR register
+ //
+ // struct G_gpe_apss_start_pwr_meas_read_args =
+ // {
+ .struct 0
+ERROR_RC:
+ .struct ERROR_RC + 8
+ERROR_FFDC:
+ .struct ERROR_FFDC + 8
+ // };
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Begin Program
+ //////////////////////////////////////////////////////////////////////
+
+ .text
+
+#include <gpe_macros.h>
+#include <pss_macros.h>
+
+ //--------------------------------------------------------------------
+ // PORE-GPE Routine Specification:
+ //
+ // Name: GPE_apss_start_pwr_meas_read
+ //
+ // Description: Kick of the power measurement from APSS
+ //
+ // Inputs: G_gpe_apss_start_pwr_meas_read_args
+ // struct {
+ // PoreGpeErrorStruct error;
+ // } G_gpe_apss_start_pwr_meas_read_args
+ // struct {
+ // uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+ // uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+ // } PoreGpeErrorStruct;
+ //
+ // Outputs: GPE_start_pwr_meas_read (error on failure)
+ //
+ // Flow: 7/20/11 FN=GPE_apss_start_pwr_meas_read
+ //
+ // References: APSS FUnctional Specification v0.7.18
+ // GPE_apss_access_scoms.odt (summary of regisers/data)
+ //
+ // End PORE-GPE Routine Specification
+ //--------------------------------------------------------------------
+ .global GPE_apss_start_pwr_meas_read
+GPE_apss_start_pwr_meas_read:
+
+ // Copy passed Structure Pointer into A1
+ mr A1, ETR
+
+ // Wait for up to 5us for spi op complete, else branch to error_timeout
+ _wait_for_adc_ops_complete 5, error_timeout
+
+ // Setup control regs
+ // frame_size=16, out_count=16, in_count=16
+ ////_putscom SPIPSS_ADC_CTRL_REG0, 0x4100100000000000
+ _putscom SPIPSS_ADC_CTRL_REG0, 0x4000100000000000 // Verified
+ // ADC FSM, clock_divider=7, frames=16
+ ////_putscom SPIPSS_ADC_CTRL_REG1, 0x801FC00000000000
+ ////_putscom SPIPSS_ADC_CTRL_REG1, 0x8063c00000000000 // Verified
+ //_putscom SPIPSS_ADC_CTRL_REG1, 0x8077c00000000000 //gm038
+ _putscom SPIPSS_ADC_CTRL_REG1, 0x8093c00000000000 //@gs039
+ // ADC interframe delay (5usec)
+ ////_putscom SPIPSS_ADC_CTRL_REG2, 0x0019000000000000
+ _putscom SPIPSS_ADC_CTRL_REG2, 0x0019000000000000 // Verified
+
+ // APSS command to continue previous command
+ _putscom SPIPSS_ADC_WDATA_REG, 0x0000000000000000 // Verified
+
+ // Start SPI transaction
+ _putscom SPIPSS_ADC_COMMAND_REG, 0x8000000000000000 // Verified
+
+ halt // End of GPE_apss_initialize_gpio
+
+
+error_statusreg:
+ // An error/reserved bit was set when reading adc status register...
+ // D0: ADC_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0002
+ halt
+
+
+error_timeout:
+ // adc_ongoing bit was never cleared after several retries...
+ // D0: ADC_STATUS_REG
+ _saveffdc GPE_PROG_ID, 0x0001
+ halt
+
+
+ //////////////////////////////////////////////////////////////////////
+ // End of Program
+ //////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/occ/gpe/gpe_export.h b/src/occ/gpe/gpe_export.h
new file mode 100755
index 0000000..3301a2d
--- /dev/null
+++ b/src/occ/gpe/gpe_export.h
@@ -0,0 +1,67 @@
+/******************************************************************************
+// @file gpe_export.h
+// @brief This file contains structures, etc, that are needed
+// by applications external to the GPE
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section gpe_export.h GPE_EXPORT.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @cc000 cjcain 08/04/2011 Created
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _GPE_EXPORT_H
+#define _GPE_EXPORT_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+typedef struct {
+ union
+ {
+ struct {
+ uint32_t rc;
+ uint32_t addr;
+ };
+ uint64_t error;
+ };
+ uint64_t ffdc;
+} PoreGpeErrorStruct; // Same for every GPE program
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_GPE_EXPORT_H
diff --git a/src/occ/gpe/gpe_macros.h b/src/occ/gpe/gpe_macros.h
new file mode 100755
index 0000000..4a54eeb
--- /dev/null
+++ b/src/occ/gpe/gpe_macros.h
@@ -0,0 +1,178 @@
+/******************************************************************************
+// @file gpe_macros.h
+// @brief Common macros for the APSS/DPSS code
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section gpe_macros.h GPE_MACROS.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ *
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _saveffdc
+ //
+ // Description: Save FFDC into error structure
+ //
+ // struct {
+ // uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+ // uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+ // } PoreGpeErrorStruct;
+ //
+ // - Copy D0 into PoreGpeErrorStruct->ffdc
+ // - Copy \gpe_id into PoreGpeErrorStruct->rc[63:32]
+ // - Copy \rc into PoreGpeErrorStruct->rc[31:0]
+ //
+ // Inputs: \gpe_id - Unique GPE program number to identify what prog failed
+ // \rc - Unique GPE error code that will indicate failure
+ // ETR - Assumed to be set to base address of
+ // passed argument structure
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _saveffdc, gpe_id, rc
+
+ // Make sure passed Structure Pointer is loaded into A1
+ mr A1, ETR
+
+ // Save address to send back (upper word of D1)
+ srdi D1, D1, 32
+ // TODO: Simcs does not support SPRG0 yet, so use 24 bit CTR for now
+ //mr SPRG0, D1
+ mr CTR, D1
+
+ // Check if rc was already saved...
+ ld D1, 0, A1
+ andi D1, D1, 0xFFFFFFFF00000000
+ branz D1, 1f
+
+ // Save D0 into FFDC of error structure
+ std D0, 8, A1
+ ld D0, 8, A1
+
+ // Save address to send back... (truncated to 24 bits)
+ mr D0, CTR
+ // Save GPE progam ID
+ li D1, \gpe_id
+ sldi D1, D1, 16
+ // and return code
+ ori D1, D1, \rc
+ sldi D1, D1, 32
+ // combine GPE program/RC with address
+ or D0, D0, D1
+
+ // Save data into error structure
+ std D0, 0, A1
+ ld D0, 8, A1
+ ld D0, 0, A1
+
+1:
+ .endm
+
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _getscom
+ //
+ // Description: Get a SCOM based on passed in Address, put it in D0
+ //
+ // Inputs: SCOM Address
+ //
+ // Outputs: D0 - Result of SCOM
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _getscom, address
+
+ lpcs P0, \address
+ ld D0, \address, P0
+
+ .endm
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _putscom
+ //
+ // Description: Store data into SCOM based on passed in Address
+ //
+ // Inputs: SCOM Address, Data
+ //
+ // Outputs: None
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _putscom, address, data
+
+ lpcs P0, \address
+ li D0, \data
+ std D0, \address, P0
+
+ .endm
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _putscom_d0
+ //
+ // Description: Store D0 into SCOM based on passed in Address
+ //
+ // Inputs: SCOM Address
+ //
+ // Outputs: None
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _putscom_d0, address
+
+ lpcs P0, \address
+ std D0, \address, P0
+
+ .endm
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+ #define TOD_VALUE_REG 0x00040020
+
+ // Constant for use in wait statments: waits (5 * MICROSECONDS)
+ #define MICROSECONDS 600
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
diff --git a/src/occ/gpe/pore_nop.pS b/src/occ/gpe/pore_nop.pS
new file mode 100755
index 0000000..923b00f
--- /dev/null
+++ b/src/occ/gpe/pore_nop.pS
@@ -0,0 +1,41 @@
+// $Id$
+
+/// \file pore_nop.S
+/// \brief A Quick NOP Program for PORE Model Timing
+///
+/// Used to generate the worst case timings for the AMEC
+/// sensors.
+
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ .oci
+
+ .data
+
+ .text
+
+ .global GPE_pore_nop
+
+ /// Run a nop instruction and then halt GPE
+GPE_pore_nop:
+ nop
+
+ /// -----------------------------------------------------
+ /// Only compile this in to test delaying PORE-GPE engine
+ .ifdef DELAY_PORE_NOP
+ li CTR, 120
+delay_loop:
+ waits 600
+ nop
+ loop delay_loop
+done:
+ .endif
+ /// -----------------------------------------------------
+
+ halt
+
+ .epilogue GPE_pore_nop
+
diff --git a/src/occ/gpe/pore_test.pS b/src/occ/gpe/pore_test.pS
new file mode 100755
index 0000000..f02c985
--- /dev/null
+++ b/src/occ/gpe/pore_test.pS
@@ -0,0 +1,74 @@
+# *****************************************************************************
+# @file pore_test.S
+# @brief A Quick Test Program for PORE Model
+# Delays for X (passed in) uS before halting PORE-GPE
+# program.
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section pore_test.S PORE_TEST.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ .oci
+
+// Parameter offsets
+
+ .data
+
+ .global jmptable
+ .align 3
+jmptable: // Error Handlers are replaced with Halts
+ .quad 0x0200000000000000 // Halt on Error 0
+ .quad 0x0000000002000000 // Halt on Error 1
+ .quad 0x0000000000000000
+ .quad 0x0200000000000000 // Halt on error 2
+ .quad 0x0000000002000000 // Halt on error 3
+ .quad 0x0000000000000000
+ .quad 0x0200000000000000 // Halt on Error 4
+ .quad 0x0000000002000000 // Halt on error 5
+ .quad 0x0000000000000000
+ .quad 0x0200000000000000 // Halt on Error 6
+ .quad 0x0000000002000000 // Halt on error 7
+ .quad 0x0000000000000000
+ .quad 0xA200000000003fff // BRAI pore_test
+ .quad 0xc146000000000000 // second word is not used
+
+ .global scratchspace
+ .align 3
+scratchspace:
+ .quad 0x0000000000000010 // Data scratch space
+ .quad 0x0000000000000020
+ .quad 0x0000000000000030
+ .quad 0x0000000000000040
+
+ .text
+
+ .global pore_test
+pore_test:
+
+ // Read parameter into CTR
+ mr CTR, ETR
+delay_loop:
+ waits 600
+ nop
+ loop delay_loop
+done:
+ halt // End of main
+
+// .epilogue pore_test
+
diff --git a/src/occ/gpe/pore_test_error.pS b/src/occ/gpe/pore_test_error.pS
new file mode 100755
index 0000000..344bdcb
--- /dev/null
+++ b/src/occ/gpe/pore_test_error.pS
@@ -0,0 +1,246 @@
+# *****************************************************************************
+# @file pore_test_error.S
+# @brief A Quick Test Program for PORE Model
+# Delays for X (passed in) uS before halting PORE-GPE
+# program. Always sets an error
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section pore_test_error.S PORE_TEST_ERROR.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+// Input:
+// struct {
+// uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+// uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+// } PoreGpeErrorStruct;
+//
+// struct {
+// PoreGpeErrorStruct error;
+// uint32_t pore_delay;
+// } PoreSimpleArgs;
+//
+//
+//
+
+ //////////////////////////////////////////////////////////////////////
+ // Includes
+ //////////////////////////////////////////////////////////////////////
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Address Space
+ //////////////////////////////////////////////////////////////////////
+ .oci
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Symbols
+ //////////////////////////////////////////////////////////////////////
+#define TOD_VALUE_REG 0x00040020
+#define SPIPSS_REGISTER_BASE 0x00020000
+#define SPIPSS_ADC_CTRL_REG0 (SPIPSS_REGISTER_BASE + 0x00)
+#define SPIPSS_ADC_CTRL_REG1 (SPIPSS_REGISTER_BASE + 0x01)
+#define SPIPSS_ADC_CTRL_REG2 (SPIPSS_REGISTER_BASE + 0x02)
+#define SPIPSS_ADC_STATUS_REG (SPIPSS_REGISTER_BASE + 0x03)
+#define SPIPSS_ADC_COMMAND_REG (SPIPSS_REGISTER_BASE + 0x04)
+#define SPIPSS_ADC_WDATA_REG (SPIPSS_REGISTER_BASE + 0x10)
+#define SPIPSS_ADC_RDATA_REG0 (SPIPSS_REGISTER_BASE + 0x20)
+#define SPIPSS_ADC_RDATA_REG1 (SPIPSS_REGISTER_BASE + 0x21)
+#define SPIPSS_ADC_RDATA_REG2 (SPIPSS_REGISTER_BASE + 0x22)
+#define SPIPSS_ADC_RDATA_REG3 (SPIPSS_REGISTER_BASE + 0x23)
+#define SPIPSS_P2S_CTRL_REG0 (SPIPSS_REGISTER_BASE + 0x40)
+#define SPIPSS_P2S_CTRL_REG1 (SPIPSS_REGISTER_BASE + 0x41)
+#define SPIPSS_P2S_CTRL_REG2 (SPIPSS_REGISTER_BASE + 0x42)
+#define SPIPSS_P2S_STATUS_REG (SPIPSS_REGISTER_BASE + 0x43)
+#define SPIPSS_P2S_COMMAND_REG (SPIPSS_REGISTER_BASE + 0x44)
+#define SPIPSS_P2S_WDATA_REG (SPIPSS_REGISTER_BASE + 0x50)
+#define SPIPSS_P2S_RDATA_REG (SPIPSS_REGISTER_BASE + 0x60)
+
+
+ .set GPE_PROG_ID, 100
+ .set GPE_ERROR_CODE, 0xAA55AA55
+ .set GPE_ERROR_RC, 0xBEEFCAFE
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Structures
+ //////////////////////////////////////////////////////////////////////
+
+ // Declare the offsets of the struct that will be passed to the
+ // GPE program via the ETR register
+ //
+ // struct PoreSimpleArgs =
+ // {
+ .struct 0
+RETURN_CODE:
+ .struct RETURN_CODE + 8
+FFDC:
+ .struct FFDC + 8
+PORE_DELAY:
+ // };
+
+ //////////////////////////////////////////////////////////////////////
+ // Begin Program
+ //////////////////////////////////////////////////////////////////////
+
+ .text
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _saveffdc
+ //
+ // Description: Save off RC, FFDC & Address when there is an error
+ // in a GPE program.
+ //
+ // - Copy D0 into PoreGpeErrorStruct->ffdc
+ // - Copy D1[63:32] into PoreGpeErrorStruct->rc[63:32]
+ // - Copy \error_code into PoreGpeErrorStruct->rc[31:0]
+ //
+ // Inputs: \error_code - Unique GPE error code that will
+ // indicate the failure mode of the GPE
+ // program.
+ // D0 - Set to FFDC data that will be copied to
+ // PoreGpeErrorStruct->ffdc
+ // D1 - Bits[63:32] set to address that will be
+ // copied to PoreGpeErrorStruct->rc[63:32]
+ // ETR - Assumed to be set to base address of
+ // passed argument structure
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _saveffdc, error_code
+
+ // Make sure passed Structure Pointer is loaded into A1
+ mr A1, ETR
+
+ // First save off D0 into FFDC
+ std D0, FFDC, A1
+
+ // Then save off SPRG0 into the lower 32 bits of D0
+ // TODO: SPRG0 doesn't work in Simics....switching to D1 for now
+ mr D0, D1
+
+ // Save off the address of the start of the GPE program into the
+ // upper 32 bits of D0
+ li D1, \error_code
+ sldi D1, D1, 32
+ or D0, D0, D1
+
+ // Save register off into code_addr
+ std D0, RETURN_CODE, A1
+
+ .endm
+
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _getscom
+ //
+ // Description: Get a SCOM based on passed in Address, put it in D0
+ //
+ // Inputs: SCOM Address
+ //
+ // Outputs: D0 - Result of SCOM
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _getscom, address
+
+ lpcs P0, \address
+ ld D0, \address, P0
+
+ .endm
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _putscom
+ //
+ // Description: Get a SCOM based on passed in Address, put it in D0
+ //
+ // Inputs: SCOM Address, Data
+ //
+ // Outputs: None
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _putscom, address, data
+
+ lpcs P0, \address
+ li D0, \data
+ std D0, \address, P0
+
+ .endm
+
+
+ //--------------------------------------------------------------------
+ // PORE-GPE Routine Specification:
+ //
+ // Name: pore_test_error
+ //
+ // Description: Delays for X (passed in) uS before halting PORE-GPE
+ // routine. Always sets the ffdc to indicate an error
+ // with a RC of 0xDEADBEEF
+ //
+ // Inputs: PoreSimpleArgs - FFDC & uS to delay.
+ //
+ // Outputs: None (except FFDC on failure)
+ //
+ // End PORE-GPE Routine Specification
+ //--------------------------------------------------------------------
+ .global pore_test_error
+pore_test_error:
+ // Copy passed Structure Pointer into A1
+ mr A1, ETR
+
+ // Read pore_delay parameter into D0
+ ld D0, PORE_DELAY, A1
+
+ // Shift Right so that we only use the upper 32 bits
+ // (not passed in as 64 bit value)
+ srdi D0, D0, 32
+
+ // Copy pore_delay into CTR so that we can loop
+ mr CTR, D0
+
+ // Set D0 to a value for some fake operation we are testing out
+ li D0, GPE_ERROR_CODE
+ li D1, GPE_ERROR_CODE
+
+ trap
+delay_loop:
+ waits 600
+ nop
+ loop delay_loop
+ trap
+
+ //bra done
+error:
+ _getscom TOD_VALUE_REG
+
+ _saveffdc 0xDEADBEEF
+
+done:
+
+
+
+ halt // End of pore_test
+
+ //////////////////////////////////////////////////////////////////////
+ // End of Program
+ //////////////////////////////////////////////////////////////////////
+
diff --git a/src/occ/gpe/pore_test_pss.pS b/src/occ/gpe/pore_test_pss.pS
new file mode 100755
index 0000000..a65c935
--- /dev/null
+++ b/src/occ/gpe/pore_test_pss.pS
@@ -0,0 +1,444 @@
+# *****************************************************************************
+# @file pore_test_pss.S
+# @brief A Quick Test Program for PORE Model
+# Delays for X (passed in) uS before halting PORE-GPE
+# program. Always sets an error
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section pore_test_pss.S PORE_TEST_PSS.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+
+// Input:
+// struct {
+// uint64_t rc; // This should be read as 63:32=addr, 31:0=rc
+// uint64_t ffdc; // Whatever GPE program puts in for FFDC data
+// } PoreGpeErrorStruct;
+//
+// struct {
+// PoreGpeErrorStruct error;
+// uint64_t adc[4];
+// uint64_t tod;
+// } PoreSimpleArgs;
+//
+//
+//
+
+ //////////////////////////////////////////////////////////////////////
+ // Includes
+ //////////////////////////////////////////////////////////////////////
+ .nolist
+#include "pgp.h"
+#include "pgas.h"
+ .list
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Address Space
+ //////////////////////////////////////////////////////////////////////
+ .oci
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Symbols
+ //////////////////////////////////////////////////////////////////////
+#define TOD_VALUE_REG 0x00040020
+#define SPIPSS_REGISTER_BASE 0x00020000
+#define SPIPSS_ADC_CTRL_REG0 (SPIPSS_REGISTER_BASE + 0x00)
+#define SPIPSS_ADC_CTRL_REG1 (SPIPSS_REGISTER_BASE + 0x01)
+#define SPIPSS_ADC_CTRL_REG2 (SPIPSS_REGISTER_BASE + 0x02)
+#define SPIPSS_ADC_STATUS_REG (SPIPSS_REGISTER_BASE + 0x03)
+#define SPIPSS_ADC_COMMAND_REG (SPIPSS_REGISTER_BASE + 0x04)
+#define SPIPSS_ADC_WDATA_REG (SPIPSS_REGISTER_BASE + 0x10)
+#define SPIPSS_ADC_RDATA_REG0 (SPIPSS_REGISTER_BASE + 0x20)
+#define SPIPSS_ADC_RDATA_REG1 (SPIPSS_REGISTER_BASE + 0x21)
+#define SPIPSS_ADC_RDATA_REG2 (SPIPSS_REGISTER_BASE + 0x22)
+#define SPIPSS_ADC_RDATA_REG3 (SPIPSS_REGISTER_BASE + 0x23)
+#define SPIPSS_P2S_CTRL_REG0 (SPIPSS_REGISTER_BASE + 0x40)
+#define SPIPSS_P2S_CTRL_REG1 (SPIPSS_REGISTER_BASE + 0x41)
+#define SPIPSS_P2S_CTRL_REG2 (SPIPSS_REGISTER_BASE + 0x42)
+#define SPIPSS_P2S_STATUS_REG (SPIPSS_REGISTER_BASE + 0x43)
+#define SPIPSS_P2S_COMMAND_REG (SPIPSS_REGISTER_BASE + 0x44)
+#define SPIPSS_P2S_WDATA_REG (SPIPSS_REGISTER_BASE + 0x50)
+#define SPIPSS_P2S_RDATA_REG (SPIPSS_REGISTER_BASE + 0x60)
+
+
+#define GPE_PROG_ID 0xDEAD
+
+#define GPE_ERROR_P2S_ONGOING_TIMEOUT 0x0001
+#define GPE_ERROR_PIB_TIMEOUT 0xFF00
+
+ .set GPE_ERROR_CODE, 0xAA55AA55
+ .set GPE_ERROR_RC, 0xBEEFCAFE
+
+ //////////////////////////////////////////////////////////////////////
+ // Define Structures
+ //////////////////////////////////////////////////////////////////////
+
+ // Declare the offsets of the struct that will be passed to the
+ // GPE program via the ETR register
+ //
+ // struct PoreSimpleArgs =
+ // {
+ .struct 0
+RETURN_CODE:
+ .struct RETURN_CODE + 8
+FFDC:
+ .struct FFDC + 8
+ADC0:
+ .struct ADC0 + 8
+ADC1:
+ .struct ADC1 + 8
+ADC2:
+ .struct ADC2 + 8
+ADC3:
+ .struct ADC3 + 8
+TOD:
+
+ // };
+
+ //////////////////////////////////////////////////////////////////////
+ // Begin Program
+ //////////////////////////////////////////////////////////////////////
+
+ .text
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _saveffdc
+ //
+ // Description: Save off RC, FFDC & Address when there is an error
+ // in a GPE program.
+ //
+ // - Copy D0 into PoreGpeErrorStruct->ffdc
+ // - Copy D1[63:32] into PoreGpeErrorStruct->rc[63:32]
+ // - Copy \error_code into PoreGpeErrorStruct->rc[31:0]
+ //
+ // Inputs: \error_code - Unique GPE error code that will
+ // indicate the failure mode of the GPE
+ // program.
+ // D0 - Set to FFDC data that will be copied to
+ // PoreGpeErrorStruct->ffdc
+ // D1 - Bits[63:32] set to address that will be
+ // copied to PoreGpeErrorStruct->rc[63:32]
+ // ETR - Assumed to be set to base address of
+ // passed argument structure
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _saveffdc, error_code
+
+ // Make sure passed Structure Pointer is loaded into A1
+ mr A1, ETR
+
+//.ifdef SIMICS_SPRG0_WORKING
+ // Copy D1[32:63] into SPRG0
+ mr D1, SPRG0
+
+ // Now Read RETURN_CODE into D1, check to see if it is 0
+ ld D1, RETURN_CODE, A1
+
+ // If it is not 0, then don't save off any FFDC
+ branz D1, 1f
+//.endif
+
+ // Copy SPRG0 into D1[32:63]
+ mr SPRG0, D1
+
+ // First save off D0 into FFDC
+ std D0, FFDC, A1
+
+ // Then save off D1[32:63] into the lower 32 bits [32:63] of D0
+ mr D0, D1
+
+ // Save off the passed \error_code into the upper 32 bits of D0
+ li D1, \error_code
+ sldi D1, D1, 32
+ or D0, D0, D1
+
+ // Save register off into code_addr
+ std D0, RETURN_CODE, A1
+1:
+ .endm
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _saveffdc3
+ //
+ // Description: Get a SCOM based on passed in Address, put it in D0
+ //
+ // Inputs: SCOM Address
+ //
+ // Outputs: D0 - Result of SCOM
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _saveffdc3, gpe_id, error_code
+
+ // This will cause an "Invalid Instruction Code" Error in the PORE-GPE
+ // which will cause an "error event 2" interrupt to the PPC405
+ .long 0xAABBCCDD
+
+ // The PPC405 will then be able to read the "Invalid Instruction Code"
+ // out of the IBUF_01 Register, which will contain the AABBCCDD opcode
+ // as well as the \gpe_id and \error_code.
+ .short \gpe_id
+ .short \error_code
+
+ // The PPC405 ISR will then grab & place into PoreRequestStruct:
+ // IBUF_01[32:63] (32b)
+ // DBG0 (64b)
+ // DBG1 (64b)
+ // D0 (64b)
+ // D1[32:63] (32b)
+ // A0 & A1 (64b)
+ // -------- -----
+ // Total 40 Bytes
+
+ .endm
+
+
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _getscom
+ //
+ // Description: Get a SCOM based on passed in Address, put it in D0
+ //
+ // Inputs: SCOM Address
+ //
+ // Outputs: D0 - Result of SCOM
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _getscom, address
+
+ lpcs P0, \address
+ ld D0, \address, P0
+
+ .endm
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _putscom
+ //
+ // Description: Put Data in a SCOM address
+ //
+ // Inputs: SCOM Address, Data
+ //
+ // Outputs: None
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _putscom, address, data
+
+ lpcs P0, \address
+ li D0, \data
+ std D0, \address, P0
+
+ .endm
+
+ //--------------------------------------------------------------------
+ // Macro Specification:
+ //
+ // Name: _spin_on_bitclear_scom
+ //
+ // Description: Wait for Bit to get cleared in scom register
+ //
+ // Inputs: SCOM Address, Mask
+ //
+ // Outputs: None
+ //
+ // End Macro Specification
+ //--------------------------------------------------------------------
+ .macro _spin_on_bitclear_scom, address, mask
+1:
+ _getscom \address
+ andi D0, D0, \mask
+ branz D0, 1b
+
+ .endm
+
+ //--------------------------------------------------------------------
+ // PORE-GPE Routine Specification:
+ //
+ // Name: pore_test_pss
+ //
+ // Description: Delays for X (passed in) uS before halting PORE-GPE
+ // routine. Always sets the ffdc to indicate an error
+ // with a RC of 0xDEADBEEF
+ //
+ // Inputs: PoreSimpleArgs - FFDC & uS to delay.
+ //
+ // Outputs: None (except FFDC on failure)
+ //
+ // End PORE-GPE Routine Specification
+ //--------------------------------------------------------------------
+ .global pore_test_pss
+pore_test_pss:
+ // Copy passed Structure Pointer into A1
+ mr A1, ETR
+
+ trap
+
+.ifdef APSS_MODEL_INCLUDED
+ _spin_on_bitclear_scom SPIPSS_P2S_STATUS_REG 0x8000000000000000
+ _spin_on_bitclear_scom SPIPSS_P2S_STATUS_REG 0x8000000000000000
+.endif
+
+ trap
+ _getscom 0x01000000
+
+.ifdef APSS_MODEL_INCLUDED
+ //////////////////////////////////////////////////
+ // Test out a Auto-2 Mode Setup
+ //////////////////////////////////////////////////
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x410FC00004000000
+ _putscom SPIPSS_P2S_CTRL_REG1, 0x001C000000000000
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x000C800000000000
+ _putscom SPIPSS_P2S_WDATA_REG, 0x3FC0000000000000
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+ waits 4000
+ _getscom SPIPSS_P2S_RDATA_REG
+ trap
+.endif
+
+.ifdef APSS_MODEL_INCLUDED
+ //////////////////////////////////////////////////
+ // Test out a GPIO Mode Setup - all High-Z
+ //////////////////////////////////////////////////
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x410FC00004000000
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x000C800000000000
+ _putscom SPIPSS_P2S_WDATA_REG, 0x50FF000000000000
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+ waits 4000
+ _getscom SPIPSS_P2S_RDATA_REG
+ trap
+.endif
+
+.ifdef APSS_MODEL_INCLUDED
+ //////////////////////////////////////////////////
+ // Test out ADC FSM
+ //////////////////////////////////////////////////
+ _putscom SPIPSS_ADC_CTRL_REG0, 0x4100100000000000
+ _putscom SPIPSS_ADC_CTRL_REG1, 0x801FC00000000000
+ _putscom SPIPSS_ADC_CTRL_REG2, 0x0019000000000000
+ _putscom SPIPSS_ADC_WDATA_REG, 0x0000000000000000
+ _putscom SPIPSS_ADC_COMMAND_REG, 0x8000000000000000
+ waits 30000
+ _getscom SPIPSS_ADC_RDATA_REG0
+ std D0, ADC0, A1
+ _getscom SPIPSS_ADC_RDATA_REG1
+ std D0, ADC1, A1
+ _getscom SPIPSS_ADC_RDATA_REG2
+ std D0, ADC2, A1
+ _getscom SPIPSS_ADC_RDATA_REG3
+ std D0, ADC3, A1
+ _getscom TOD_VALUE_REG
+ std D0, TOD, A1
+ trap
+
+.endif
+
+.ifdef APSS_MODEL_INCLUDED
+ //////////////////////////////////////////////////
+ // Test out a GPIO Port 0 Read from APSS
+ //////////////////////////////////////////////////
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x410FC00004000000
+ _putscom SPIPSS_P2S_CTRL_REG1, 0x001C400000000000
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x000C800000000000
+ _putscom SPIPSS_P2S_WDATA_REG, 0x7000000000000000
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+ waits 4000
+ _getscom SPIPSS_P2S_RDATA_REG
+ trap
+.endif
+
+.ifdef DPSS_MODEL_INCLUDED
+ //////////////////////////////////////////////////
+ // Test out a Fan RPM 7 Read from DPSS
+ //////////////////////////////////////////////////
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x410FC00004000000
+ _putscom SPIPSS_P2S_CTRL_REG1, 0x401C400000000000
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x000C800000000000
+ _putscom SPIPSS_P2S_WDATA_REG, 0x3200000000000000
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+ waits 4000
+ _getscom SPIPSS_P2S_RDATA_REG
+ trap
+.endif
+
+.ifdef DPSS_MODEL_INCLUDED
+.print "Building in DPSS Support"
+ //////////////////////////////////////////////////
+ // Test out a Stream of commands to the DPSS
+ //////////////////////////////////////////////////
+
+ // Send First(32) & Second(33) command
+ // Get Response to First command
+ //tgh_putscom SPIPSS_P2S_CTRL_REG0, 0x410FC04004000000
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x4104004004000000
+ //_putscom SPIPSS_P2S_CTRL_REG1, 0x401C400000000000
+ _putscom SPIPSS_P2S_CTRL_REG1, 0xC01C400000000000
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x000C800000000000
+ _putscom SPIPSS_P2S_WDATA_REG, 0x2B002C0000000000
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+ waits 4000
+ _spin_on_bitclear_scom SPIPSS_P2S_STATUS_REG 0x8000000000000000
+ _getscom SPIPSS_P2S_RDATA_REG
+ trap
+
+ // Send Third (34)& Forth (35) Command
+ // Get Response to Second & third
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x4100104004000000
+ //_putscom SPIPSS_P2S_CTRL_REG1, 0x401C400000000000
+ _putscom SPIPSS_P2S_CTRL_REG1, 0xC01C400000000000
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x000C800000000000
+ _putscom SPIPSS_P2S_WDATA_REG, 0x2D002E0000000000
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+ waits 4000
+ _getscom SPIPSS_P2S_RDATA_REG
+ trap
+ _spin_on_bitclear_scom SPIPSS_P2S_STATUS_REG 0x8000000000000000
+
+ // Send Fifth (36)& Last (00) Command
+ // Get Response to Forth & Fifth
+ _putscom SPIPSS_P2S_CTRL_REG0, 0x4100104004000000
+ //_putscom SPIPSS_P2S_CTRL_REG1, 0x401C400000000000
+ _putscom SPIPSS_P2S_CTRL_REG1, 0xC01C400000000000
+ _putscom SPIPSS_P2S_CTRL_REG2, 0x000C800000000000
+ _putscom SPIPSS_P2S_WDATA_REG, 0x2F00000000000000
+ _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000
+ waits 4000
+ _getscom SPIPSS_P2S_RDATA_REG
+ trap
+ _spin_on_bitclear_scom SPIPSS_P2S_STATUS_REG 0x8000000000000000
+ trap
+
+ _saveffdc3 GPE_PROG_ID GPE_ERROR_P2S_ONGOING_TIMEOUT
+.endif
+ bra done
+
+error:
+ _saveffdc 0xDEADBEEF
+
+done:
+
+ halt // End of pore_test
+
+ //////////////////////////////////////////////////////////////////////
+ // End of Program
+ //////////////////////////////////////////////////////////////////////
+
diff --git a/src/occ/gpe/pss_constants.h b/src/occ/gpe/pss_constants.h
new file mode 100755
index 0000000..79f1cbc
--- /dev/null
+++ b/src/occ/gpe/pss_constants.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+// @file pss_constants.h
+// @brief Constants used by PSS communications GPE programs
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section pss_constants.h PSS_CONSTANTS.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00e thallet 06/19/2012 SW133222: Change SPIPSS to 70000 to match HW
+ * @gm032 918715 milesg 03/19/2014 Improved APSS recovery
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define SPIPSS_REGISTER_BASE 0x00070000 // @th00e
+#define SPIPSS_ADC_CTRL_REG0 (SPIPSS_REGISTER_BASE + 0x00)
+#define SPIPSS_ADC_CTRL_REG1 (SPIPSS_REGISTER_BASE + 0x01)
+#define SPIPSS_ADC_CTRL_REG2 (SPIPSS_REGISTER_BASE + 0x02)
+#define SPIPSS_ADC_STATUS_REG (SPIPSS_REGISTER_BASE + 0x03)
+#define SPIPSS_ADC_COMMAND_REG (SPIPSS_REGISTER_BASE + 0x04)
+#define SPIPSS_ADC_RESET_REG (SPIPSS_REGISTER_BASE + 0x05) //gm032
+#define SPIPSS_ADC_WDATA_REG (SPIPSS_REGISTER_BASE + 0x10)
+#define SPIPSS_ADC_RDATA_REG0 (SPIPSS_REGISTER_BASE + 0x20)
+#define SPIPSS_ADC_RDATA_REG1 (SPIPSS_REGISTER_BASE + 0x21)
+#define SPIPSS_ADC_RDATA_REG2 (SPIPSS_REGISTER_BASE + 0x22)
+#define SPIPSS_ADC_RDATA_REG3 (SPIPSS_REGISTER_BASE + 0x23)
+#define SPIPSS_100NS_REG (SPIPSS_REGISTER_BASE + 0x28)
+#define SPIPSS_P2S_CTRL_REG0 (SPIPSS_REGISTER_BASE + 0x40)
+#define SPIPSS_P2S_CTRL_REG1 (SPIPSS_REGISTER_BASE + 0x41)
+#define SPIPSS_P2S_CTRL_REG2 (SPIPSS_REGISTER_BASE + 0x42)
+#define SPIPSS_P2S_STATUS_REG (SPIPSS_REGISTER_BASE + 0x43)
+#define SPIPSS_P2S_COMMAND_REG (SPIPSS_REGISTER_BASE + 0x44)
+#define SPIPSS_P2S_WDATA_REG (SPIPSS_REGISTER_BASE + 0x50)
+#define SPIPSS_P2S_RDATA_REG (SPIPSS_REGISTER_BASE + 0x60)
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
diff --git a/src/occ/gpe/pss_macros.h b/src/occ/gpe/pss_macros.h
new file mode 100755
index 0000000..0306d20
--- /dev/null
+++ b/src/occ/gpe/pss_macros.h
@@ -0,0 +1,192 @@
+/******************************************************************************
+// @file pss_macros.h
+// @brief Common macros for the APSS/DPSS code
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section pss_macros.h PSS_MACROS.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ *
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @gm032 918715 milesg 03/19/2014 Improved APSS recovery
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+ //--------------------------------------------------------------------
+ // Name: _wait_for_spi_ops_complete (MACRO)
+ //
+ // Description: Read SPIPSS_P2S_STATUS_REG and check if p2s_ongoing
+ // bit is 0 (operations done). If not, wait
+ // up to timeout usec (~1usec per retry).
+ // If still not clear, branch to timeout_label
+ // If error/reserved bits are set, a branch will be
+ // done to label: "error_status_reg"
+ //
+ // Inputs: timeout - # usec to wait for ongoing bit to clear
+ // timeout_label - label to branch to after timeout
+ //
+ // Outputs: None (on error, D0 will contain status register)
+ //
+ // Modifies: CTR, D0, D1
+ //--------------------------------------------------------------------
+ .macro _wait_for_spi_ops_complete, timeout, timeout_label
+
+ _wait_for_ops_complete SPIPSS_P2S_STATUS_REG, \timeout, \timeout_label
+
+ .endm
+
+
+ //--------------------------------------------------------------------
+ // Name: _wait_for_adc_ops_complete (MACRO)
+ //
+ // Description: Read SPIPSS_ADC_STATUS_REG and check if adc_ongoing
+ // bit is 0 (operations done). If not, wait
+ // up to timeout usec (~1usec per retry).
+ // If still not clear, branch to timeout_label
+ // If error/reserved bits are set, a branch will be
+ // done to label: "error_status_reg"
+ //
+ // Inputs: timeout - # usec to wait for ongoing bit to clear
+ // timeout_label - label to branch to after timeout
+ //
+ // Outputs: None (on error, D0 will contain status register)
+ //
+ // Modifies: CTR, D0, D1
+ //--------------------------------------------------------------------
+ .macro _wait_for_adc_ops_complete, timeout, timeout_label
+
+ _wait_for_ops_complete SPIPSS_ADC_STATUS_REG, \timeout, \timeout_label
+
+ .endm
+
+
+ //--------------------------------------------------------------------
+ // Name: _wait_for_ops_complete (MACRO)
+ //
+ // Description: Read specified register and check if ongoing bit (MSB)
+ // is 0 (operations done). If not, wait
+ // up to timeout usec (~1usec per retry).
+ // If still not clear, branch to timeout_label
+ // If error/reserved bits are set, a branch will be
+ // done to label: "error_status_reg"
+ //
+ // Inputs: register - SCOM register to read for ongong bit
+ // timeout - # usec to wait for ongoing bit to clear
+ // timeout_label - label to branch to after timeout
+ //
+ // Outputs: None (on error, D0 will contain status register)
+ //
+ // Modifies: CTR, D0, D1
+ //--------------------------------------------------------------------
+ .macro _wait_for_ops_complete, register, timeout, timeout_label
+
+ // Load CTR with approximate timeout value (1usec delay per retry)
+ li CTR, (\timeout - 1)
+1:
+ // Read spiadc_p2s_ongoing bit into D0
+ _getscom \register
+
+ // Don't fail on these status bits being set. Only fail if we get back invalid power data -- gm032
+ // Verify other error bits are not set
+ // andi D1, D0, 0x7FFFFFFFFFFFFFFF
+ // branz D1, error_statusreg
+
+ // Operation finished? (spiadc_p2s_ongoing = 0)
+ andi D1, D0, 0x8000000000000000
+ braz D1, 2f
+
+ // no, wait 1usec and retry
+ waits (1 * MICROSECONDS)
+ loop 1b
+
+ // Timeout waiting for spiadc_p2s_ongoing
+ bra \timeout_label
+2:
+ .endm
+
+
+
+ // TODO - Subroutine would be more efficient than macro, however:
+ // Subroutines do not currently clear the stack after a halt
+ // so we can NOT use subroutine (SCOM error, branch on fail, etc..)
+#if 0
+ //--------------------------------------------------------------------
+ // Name: sub_wait_for_spi_ops_complete (SUBROUTINE)
+ //
+ // Description: Read SPIPSS_P2S_STATUS_REG and check if p2s_ongoing
+ // bit is 0 (operations done). If not it will wait
+ // for 9 additional retries (~10usec). If still not
+ // done, a branch will be done to timeout code.
+ // If error/reserved bits are set, a branch will be
+ // done to error_status_reg.
+ //
+ // Inputs: None
+ //
+ // Outputs: None (on error, D0 will contain status register)
+ //
+ // Modifies: CTR, D0, D1
+ //--------------------------------------------------------------------
+sub_wait_for_spi_ops_complete:
+ // Wait up to 10usec
+ li CTR, 10
+
+read_status:
+ // Read spiadc_p2s_ongoing bit into D0
+ _getscom SPIPSS_P2S_STATUS_REG
+
+ // Verify other error bits are not set
+ andi D1, D0, 0x7FFFFFFFFFFFFFFF
+ branz D1, error_statusreg
+
+ // Ready to send command? (spiadc_p2s_ongoing = 0)
+ andi D1, D0, 0x8000000000000000
+ braz D1, ops_are_complete
+
+ // no, wait 1usec and retry
+ waits (1 * MICROSECONDS)
+ loop read_status
+
+ // Timeout waiting for spiadc_p2s_ongoing
+ bra error_timeout
+ops_are_complete:
+ ret
+#endif
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
diff --git a/src/occ/gpefiles.mk b/src/occ/gpefiles.mk
new file mode 100755
index 0000000..01b2e29
--- /dev/null
+++ b/src/occ/gpefiles.mk
@@ -0,0 +1,33 @@
+# @file gpefiles.mk
+#
+# @brief mk occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section gpefiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @pb00D pbavari 02/21/2012 Changed extension from .S to .pS
+# @pb00E pbavari 03/11/2012 ODE Makefile support
+# @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+#
+# @endverbatim
+#
+# @pb00Dc - Changed extension to .pS as we are now using gnu assembler for
+# compiling below files. This was done to distinguish it in the
+# makefile from other .S file which is compiled using PGAS PPC
+# assembler.
+occ_GPEFILES = gpe/apss_init.pS \
+ gpe/apss_composite.pS \
+ gpe/apss_meas_read_start.pS \
+ gpe/apss_meas_read_cont.pS \
+ gpe/pore_nop.pS \
+ gpe/apss_meas_read_complete.pS
+
+all_gpefiles = ${occ_GPEFILES:.pS=.o}
+
diff --git a/src/occ/homer.c b/src/occ/homer.c
new file mode 100755
index 0000000..ba60f5b
--- /dev/null
+++ b/src/occ/homer.c
@@ -0,0 +1,158 @@
+/******************************************************************************
+ * @file homer.c
+ * @brief HOMER specific functions
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section common.c COMMON.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * 905504 sbroyles 11/06/2013 Created
+ * @gs041 942203 gjsilva 10/17/2014 Support for HTMGT/BMC interface
+ *
+ * @endverbatim
+ *
+ ******************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include <homer.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+/*
+ * Function Specification
+ *
+ * Name: homer_hd_map_read_unmap
+ *
+ * Description: Wrapper function for reading the host data area of the homer.
+ * The caller passes in an ID indication what they want to read,
+ * this function checks the version of the host data area and
+ * returns the data to the location pointed to by the pointer
+ * argument, it is the callers responsibility to guarantee that
+ * there is enough space to receive the returned data.
+ * Note that this function will map the HOMER host data section to
+ * the normally reserved address 0 and unmap the data before
+ * returning to the caller.
+ * If an ssx error is returned from the map or unmap request the
+ * ssx return code will be returned in the ssx rc output word.
+ *
+ * Flow: FN=None
+ *
+ * End Function Specification
+ */
+
+homer_rc_t
+homer_hd_map_read_unmap
+(
+ const homer_read_var_t i_id,
+ uint32_t *o_host_data,
+ int *o_ssx_rc
+)
+{
+ // Locals
+ Ppc405MmuMap l_mmuMapHomer = 0;
+ homer_rc_t l_rc = HOMER_SUCCESS;
+ occHostConfigDataArea_t *l_hdcfg_data = 0x00000000;
+ *o_ssx_rc = SSX_OK;
+
+ // Validate the parms and id
+ if (!o_host_data)
+ {
+ l_rc = HOMER_BAD_PARM;
+ }
+ else if (HOMER_LAST_VAR <= i_id)
+ {
+ l_rc = HOMER_UNKNOWN_ID;
+ }
+ else
+ {
+ /*
+ * Map to mainstore at HOMER host data offset. The first parameter is
+ * the effective address where the data can be accessed once mapped, the
+ * second parameter is the real address in main memory (PBA adjusted)
+ * where the data is located.
+ */
+ *o_ssx_rc = ppc405_mmu_map((SsxAddress)l_hdcfg_data,
+ HOMER_HD_OFFSET,
+ sizeof(occHostConfigDataArea_t),
+ 0,
+ 0,
+ &l_mmuMapHomer);
+
+ if (SSX_OK != *o_ssx_rc)
+ {
+ l_rc = HOMER_SSX_MAP_ERR;
+ }
+ else
+ {
+ // Check version, if ok return data requested. We need to support
+ // current version as well as older ones
+ if (HOMER_HD_VERSION_SUPPORT < l_hdcfg_data->version)
+ {
+ l_rc = HOMER_UNSUPPORTED_HD_VERSION;
+ }
+ else
+ {
+ switch (i_id)
+ {
+ case HOMER_VERSION:
+ *o_host_data = l_hdcfg_data->version;
+ break;
+ case HOMER_NEST_FREQ:
+ *o_host_data = l_hdcfg_data->nestFrequency;
+ break;
+ case HOMER_INT_TYPE:
+ *o_host_data = l_hdcfg_data->occInterruptType;
+ break;
+ default:
+ // Nothing to do, range checked above
+ break;
+ }
+ }
+
+ *o_ssx_rc = ppc405_mmu_unmap(&l_mmuMapHomer);
+ if ((SSX_OK != *o_ssx_rc) && (HOMER_SUCCESS == l_rc))
+ {
+ l_rc = HOMER_SSX_UNMAP_ERR;
+ }
+ }
+ }
+
+ return l_rc;
+}
+// End of homer_hd_map_read_unmap
+
+// End of homer.c
diff --git a/src/occ/homer.h b/src/occ/homer.h
new file mode 100755
index 0000000..7e20f7a
--- /dev/null
+++ b/src/occ/homer.h
@@ -0,0 +1,105 @@
+/******************************************************************************
+ * @file homer.h
+ * @brief homer header file
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section homer.h HOMER.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * 905504 sbroyles 11/06/13 Created
+ * @gs041 942203 gjsilva 10/17/2014 Support for HTMGT/BMC interface
+ *
+ * @endverbatim
+ *
+ *****************************************************************************/
+
+#ifndef _homer_h
+#define _homer_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+/*
+ * Offset into the HOMER of the host data section and the size
+ */
+#define HOMER_HD_OFFSET 0x00100000
+#define HOMER_HD_SZ (128 * 1024)
+/*
+ * Version of HOMER host data currently supported
+ */
+#define HOMER_HD_VERSION_SUPPORT 2
+
+/*
+ * ID of host data variables
+ */
+typedef enum homer_read_var
+{
+ HOMER_VERSION, // 1
+ HOMER_NEST_FREQ, // 2
+ HOMER_INT_TYPE, // 3
+ HOMER_LAST_VAR
+} homer_read_var_t;
+
+/*
+ * HOMER methods return codes
+ */
+typedef enum homer_rc
+{
+ HOMER_SUCCESS, // 1
+ HOMER_UNSUPPORTED_HD_VERSION, // 2
+ HOMER_BAD_PARM, // 3
+ HOMER_UNKNOWN_ID, // 4
+ HOMER_SSX_MAP_ERR, // 5
+ HOMER_SSX_UNMAP_ERR, // 6
+ HOMER_LAST_RC
+} homer_rc_t;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+/*
+ * Current version of the layout for the Host Config Data section of the HOMER
+ */
+struct occHostConfigDataArea
+{
+ uint32_t version;
+ uint32_t nestFrequency;
+ uint32_t occInterruptType;
+ uint8_t __reserved[(1024*128)-12];
+}__attribute__ ((__packed__));
+typedef struct occHostConfigDataArea occHostConfigDataArea_t;
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+homer_rc_t homer_hd_map_read_unmap(const homer_read_var_t, uint32_t *, int *);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif // _homer_h
diff --git a/src/occ/incl/common_types.h b/src/occ/incl/common_types.h
new file mode 100755
index 0000000..6e1b791
--- /dev/null
+++ b/src/occ/incl/common_types.h
@@ -0,0 +1,225 @@
+/******************************************************************************
+// @file common_types.h
+// @brief File containing OCC common defines
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _common_types_h common_types.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 06/16/2010 Port
+ * @pb000 pbavari 07/07/2011 Added image_header structure and
+ * image macro
+ * @pb004 pbavari 09/14/2011 Added ssx_app_cfg.h for init sec
+ * defines
+ * @03 tapiar 10/03/2011 removed typedef from BOOLEAN type
+ * @04 dwoodham 12/12/2011 added aplt_id field to image_header
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @ai007 ailutsar 12/10/2012 Change OCC Image Header to reserve 64 bytes
+ * for SRAM Repair instead of 16
+ * @th027 865085 thallet 12/21/2012 SRAM 'hack' to allow previous "16" HW scripts to work.
+ * @ai009 865968 ailutsar 01/09/2013 OCC Error log and trace parser web tool enhancement
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _COMMON_TYPES_H
+#define _COMMON_TYPES_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <stdint.h>
+
+#ifdef USE_SSX_APP_CFG_H
+#include <ssx_app_cfg.h>
+#endif
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+typedef uint32_t UINT32;
+typedef int32_t INT32;
+typedef uint8_t UCHAR;
+typedef uint8_t UINT8;
+typedef int8_t INT8;
+typedef uint16_t UINT16;
+typedef int16_t INT16;
+typedef char CHAR;
+typedef unsigned int UINT;
+typedef unsigned long ULONG;
+typedef int INT;
+typedef void VOID;
+// @ai009c
+// Skip this typedef in x86 environment
+#ifndef OCC_X86_PARSER
+typedef uint8_t bool;
+#endif
+//@pb000d - moved typedef uint32_t size_t to common.h due to type conflict
+
+
+
+/* Definition of FALSE and TRUE */
+#if !defined(FALSE) && !defined(TRUE)
+typedef enum
+{
+ FALSE = 0,
+ TRUE
+} BOOLEAN;
+#endif
+
+#ifndef NULL
+#define NULL (VOID *) 0
+#endif
+
+//@pb000a - start
+#define MAIN_APP_ID "Main App Image\0"
+
+#define SRAM_REPAIR_RESERVE_SZ 64 // @ai007c
+#define IMAGE_ID_STR_SZ 16
+#define RESERVED_SZ 14 // @04c
+#define TRAP_INST 0x7FE00004
+#define ID_NUM_INVALID 0xFFFF // @04a sim. to OCC_APLT_INVALID
+
+// @04a Magic number set for applet headers // @ai007c Change data length
+#define APLT_MAGIC_NUMBER {0x1A,0x2B,0x3C,0x4D, 0x5E,0x6F,0x7A,0x8B, 0x9C,0xAD,0xAE,0x9F, 0x8A,0x7B,0x6C,0x5D, 0x4E,0x3F,0x2A,0x1B,\
+ 0x1A,0x2B,0x3C,0x4D, 0x5E,0x6F,0x7A,0x8B, 0x9C,0xAD,0xAE,0x9F, 0x8A,0x7B,0x6C,0x5D, 0x4E,0x3F,0x2A,0x1B,\
+ 0x1A,0x2B,0x3C,0x4D, 0x5E,0x6F,0x7A,0x8B, 0x9C,0xAD,0xAE,0x9F, 0x8A,0x7B,0x6C,0x5D, 0x4E,0x3F,0x2A,0x1B, 0x12,0x34,0xAB,0xCD}
+#define SRAM_HEADER_HACK 0x48000042 // @th027
+#ifndef __ASSEMBLER__
+
+// Structure for the common image header
+struct image_header
+{
+ // >@04c Overload sram_repair_reserved for magic applet number (thanks, Tim H.!)
+ // Note: unit64_t's don't compile when used w/IMAGE_HEADER macro.
+ union
+ {
+ struct
+ {
+ // @ai007c
+ uint32_t magic_1; // 0x1A2B3C4D
+ uint32_t magic_2; // 0x5E6F7A8B
+ uint32_t magic_3; // 0x9CADAE9F
+ uint32_t magic_4; // 0x8A7B6C5D
+ uint32_t magic_5; // 0x4E3F2A1B
+ uint32_t magic_6; // 0x1A2B3C4D
+ uint32_t magic_7; // 0x5E6F7A8B
+ uint32_t magic_8; // 0x9CADAE9F
+ uint32_t magic_9; // 0x8A7B6C5D
+ uint32_t magic_a; // 0x4E3F2A1B
+ uint32_t magic_b; // 0x1A2B3C4D
+ uint32_t magic_c; // 0x5E6F7A8B
+ uint32_t magic_d; // 0x9CADAE9F
+ uint32_t magic_e; // 0x8A7B6C5D
+ uint32_t magic_f; // 0x4E3F2A1B
+ uint32_t magic_10; // 0x1234ABCD
+ };
+ uint8_t sram_repair_reserved[SRAM_REPAIR_RESERVE_SZ]; //reserved for HW use
+ };
+ // <@04c
+ uint32_t ep_branch_inst; // entry point branch instruction for bootloader
+ uint32_t halt_inst; // halt instruction
+ uint32_t image_size; // image size including header
+ uint32_t start_addr; // image start address including header
+ uint32_t readonly_size; // readonly image size
+ uint32_t boot_writeable_addr; // boot writeable address
+ uint32_t boot_writeable_size; // boot writeable size
+ uint32_t zero_data_addr; // zero data address
+ uint32_t zero_data_size; // zero data size
+ uint32_t ep_addr; // entry point to the image
+ uint32_t checksum; // checksum of the image including header
+ uint32_t version; // image version
+ char image_id_str[IMAGE_ID_STR_SZ]; // image id string
+ uint16_t aplt_id; // @04a type: enum OCC_APLT
+ uint8_t reserved[RESERVED_SZ]; // reserved for future use
+} __attribute__ ((__packed__));
+
+typedef struct image_header imageHdr_t;
+
+extern uint32_t __READ_ONLY_DATA_LEN__;
+extern uint32_t __WRITEABLE_DATA_ADDR__;
+extern uint32_t __WRITEABLE_DATA_LEN__;
+extern uint32_t __START_ADDR__;
+
+
+// Macro for creating common image header
+// NOTE: ep_branch_inst is defaulted to trap instruction. Script to fix
+// header will change it to branch to address in ep_addr field.
+// >@04c Init field sram_repair_reserved. Add field IdNum == aplt_id.
+// >@ai007 Update magic number
+#define IMAGE_HEADER(nameStr, epAddr, IdStr, IdNum) \
+const volatile imageHdr_t nameStr __attribute__((section("imageHeader")))= \
+{ \
+ /* sram_repair_reserved values should match APLT_MAGIC_NUMBER for an applet; 0 otherwise */ \
+ { \
+ { \
+ .magic_1 = (IdNum == ID_NUM_INVALID)?0:0x1A2B3C4D, \
+ .magic_2 = (IdNum == ID_NUM_INVALID)?0:0x5E6F7A8B, \
+ .magic_3 = (IdNum == ID_NUM_INVALID)?0:0x9CADAE9F, \
+ .magic_4 = (IdNum == ID_NUM_INVALID)?0:0x8A7B6C5D, \
+ .magic_5 = (IdNum == ID_NUM_INVALID)? SRAM_HEADER_HACK:0x4E3F2A1B, \
+ .magic_6 = (IdNum == ID_NUM_INVALID)?0:0x1A2B3C4D, \
+ .magic_7 = (IdNum == ID_NUM_INVALID)?0:0x5E6F7A8B, \
+ .magic_8 = (IdNum == ID_NUM_INVALID)?0:0x9CADAE9F, \
+ .magic_9 = (IdNum == ID_NUM_INVALID)?0:0x8A7B6C5D, \
+ .magic_a = (IdNum == ID_NUM_INVALID)?0:0x4E3F2A1B, \
+ .magic_b = (IdNum == ID_NUM_INVALID)?0:0x1A2B3C4D, \
+ .magic_c = (IdNum == ID_NUM_INVALID)?0:0x5E6F7A8B, \
+ .magic_d = (IdNum == ID_NUM_INVALID)?0:0x9CADAE9F, \
+ .magic_e = (IdNum == ID_NUM_INVALID)?0:0x8A7B6C5D, \
+ .magic_f = (IdNum == ID_NUM_INVALID)?0:0x4E3F2A1B, \
+ .magic_10 = (IdNum == ID_NUM_INVALID)?0:0x1234ABCD, \
+ } \
+ }, \
+ TRAP_INST, /* ep_branch_Inst */ \
+ TRAP_INST, /* halt_inst */ \
+ 0, /* image_size (filled in later by imageHdrScript) */ \
+ (uint32_t)&__START_ADDR__, /* start_addr */ \
+ (uint32_t)&__READ_ONLY_DATA_LEN__, /* readonly_size */ \
+ (uint32_t)&__WRITEABLE_DATA_ADDR__, /* boot_writeable_addr */ \
+ (uint32_t)&__WRITEABLE_DATA_LEN__, /* boot_writeable_size */ \
+ 0, /* zero_data_addr (currently unused) */ \
+ 0, /* zero data_size (currently unused) */ \
+ (uint32_t)&epAddr, /* ep_addr */ \
+ 0, /* checksum (calculated later by imsageHdrScript) */ \
+ 0, /* version (filled in later by imageHdrScript) */ \
+ IdStr, /* image_id_str */ \
+ (uint16_t)IdNum, /* @04a aplt_id */ \
+ {0} /* reserved */ \
+};
+// <@ai007
+// <@04c
+
+#endif /* __ASSEMBLER__ */
+//@pb000a - end
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_COMMON_TYPES_H
diff --git a/src/occ/incl/comp_ids.h b/src/occ/incl/comp_ids.h
new file mode 100755
index 0000000..c08c2a5
--- /dev/null
+++ b/src/occ/incl/comp_ids.h
@@ -0,0 +1,126 @@
+/******************************************************************************
+// @file comp_ids.h
+// @brief File containing OCC component IDs
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section comp_ids.h COMP_IDS.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 06/16/2010 Port
+ * @01 dwoodham 08/10/2011 Add ID & Name for rtls and make all
+ * comp ID's increments of 0x0100
+ * pbavari 08/16/2011 Added SNSR(sensor) component id
+ * @cc000 cjcain 08/30/2011 Added APSS component id
+ * @02 tapiar 08/16/2011 Applet Manager component id
+ * @pb007 pbavari 09/26/2011 Added TMER component Id
+ * @03 abagepa 09/16/2010 Communication component id
+ * @04 nguyenp 10/03/2011 Added Proc data component id
+ * @th00a thallet 02/03/2012 Added AMEC component id
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00c thallet 04/23/2012 Added CENT component id
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+ //Note: Be sure to mirror changes in this file to occ/plugins/tmgtTpmdCompIds.H!!!
+ // If you don't, the ERRL plugin will eventually break, and you might break the
+ // fips build for TMGT. - Mike
+
+#ifndef _COMP_IDS_H
+#define _COMP_IDS_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+#define COMP_NAME_SIZE 4
+
+// >@01c
+#define MAIN_COMP_ID 0x0100
+#define MAIN_COMP_NAME "MAIN"
+
+
+#define ERRL_COMP_ID 0x0200
+#define ERRL_COMP_NAME "ERRL"
+
+#define TRAC_COMP_ID 0x0300
+#define TRAC_COMP_NAME "TRAC"
+// <@01c
+
+// >@01a
+#define RTLS_COMP_ID 0x0400
+#define RTLS_COMP_NAME "RTLS"
+// <@01a
+
+#define THRD_COMP_ID 0x0500
+#define THRD_COMP_NAME "THRD"
+
+#define SNSR_COMP_ID 0x0600
+#define SNSR_COMP_NAME "SNSR"
+
+// Applet Manager @02a
+#define APLT_COMP_ID 0x0700
+#define APLT_COMP_NAME "APLT"
+
+// @cc000
+#define PSS_COMP_ID 0x0800
+#define PSS_COMP_NAME "PSS"
+
+//@pb007a
+#define TMER_COMP_ID 0x0900
+#define TMER_COMP_NAME "TMER"
+
+// @03a
+#define DCOM_COMP_ID 0x0A00
+#define DCOM_COMP_NAME "DCOM"
+
+// Proc data @04a
+#define PROC_COMP_ID 0x0B00
+#define PROC_COMP_NAME "PROC"
+
+// Amec data @th00a
+#define AMEC_COMP_ID 0x0C00
+#define AMEC_COMP_NAME "AMEC"
+
+// Centaur data @th00c
+#define CENT_COMP_ID 0x0D00
+#define CENT_COMP_NAME "CENT"
+
+// Command Handler
+#define CMDH_COMP_ID 0x0E00
+#define CMDH_COMP_NAME "CMDH"
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif
+
diff --git a/src/occ/incl/occ_common.h b/src/occ/incl/occ_common.h
new file mode 100755
index 0000000..b23b290
--- /dev/null
+++ b/src/occ/incl/occ_common.h
@@ -0,0 +1,354 @@
+/******************************************************************************
+// @file occ_common.h
+// @brief OCC common functions
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section occ_common_h occ_common.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 06/16/2010 Port
+ * @pb000 pbavari 07/07/2011 Added typedef for uint32_t and
+ * removed TPMD_code_header
+ * @01 tapiar 08/07/2011 Moved default trace size to this file
+ * @pb003 pbavari 09/08/2011 Added MAX_OCCS and MAX_CORES define
+ * @pb007 pbavari 09/30/2011 Added HALT_WITH_FIR_SET
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/03/2012 Added some convert macros
+ * @pb00E pbavari 03/11/2012 File name changes
+ * @th00d thallet 04/23/2012 Added linear window macros
+ * @ai009 865968 ailutsar 01/09/2013 OCC Error log and trace parser web tool enhancement
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+ * @gm016 909061 milesg 12/10/2013 increased default trace size
+ * @sb002 908891 sbroyles 12/09/2013 FFDC updates
+ * @sb012 910394 sbroyles 01/10/2014 More FFDC updates
+ * @gm022 908890 milesg 01/23/2014 Halt OCC on OCCLFIR[38]
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _OCC_COMMON_H
+#define _OCC_COMMON_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h>
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+// From Linker Script
+extern void _LINEAR_WR_WINDOW_SECTION_BASE;
+// From Linker Script
+extern void _LINEAR_WR_WINDOW_SECTION_SIZE;
+// From Linker Script
+extern void _LINEAR_RD_WINDOW_SECTION_BASE;
+// From Linker Script
+extern void _LINEAR_RD_WINDOW_SECTION_SIZE;
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+/// Declare aligned data structures for Async access in a noncacheable section
+///
+/// These macros declare aligned data structures in a noncacheable section, with
+/// the alignment that is needed by the specified device driver (or more
+/// accurately, as specified by the hardware device itself.)
+///
+/// All buffers should be initialized - an initialization declaration using
+/// these macros would look as follows:
+/// Example: DMA_BUFFER(uint8_t g_bcue_test[1024]) = {0};
+///
+#define PBAX_BUFFER(declaration) \
+ declaration __attribute__ ((__aligned__ (8))) __attribute__ ((section (".noncacheable")))
+
+#define OCB_BUFFER(declaration) \
+ declaration __attribute__ ((__aligned__ (8))) __attribute__ ((section (".noncacheable")))
+
+#define DMA_BUFFER(declaration) \
+ declaration __attribute__ ((__aligned__ (128))) __attribute__ ((section (".noncacheable")))
+
+#define GPE_BUFFER(declaration) \
+ declaration __attribute__ ((__aligned__ (8))) __attribute__ ((section (".noncacheable")))
+
+#define LINEAR_WINDOW_WR_BUFFER(declaration) \
+ declaration __attribute__ ((section (".linear_wr")))
+
+#define LINEAR_WINDOW_RD_BUFFER(declaration) \
+ declaration __attribute__ ((section (".linear_rd")))
+
+#define PSTATE_TABLE(declaration) \
+ declaration __attribute__ ((__aligned__ (1024)))
+
+// Pinned in linker file as address for TMGT cmds to be sent/received
+#define CMDH_LINEAR_WINDOW_BASE_ADDRESS ((uint32_t) &_LINEAR_WR_WINDOW_SECTION_BASE)
+#define LINEAR_WR_WINDOW_SECTION_SIZE ((uint32_t) &_LINEAR_WR_WINDOW_SECTION_SIZE)
+#define CMDH_OCC_RESPONSE_BASE_ADDRESS ((uint32_t) &_LINEAR_RD_WINDOW_SECTION_BASE)
+#define LINEAR_RD_WINDOW_SECTION_SIZE ((uint32_t) &_LINEAR_RD_WINDOW_SECTION_SIZE)
+
+// Conversion Macro's
+
+// Get byte 0-1 of uint64
+#define CONVERT_UINT64_UINT16_UPPER(a) \
+ ((UINT16)((a>>48) & 0xFFFF))
+// Get byte 2-3 of uint64
+#define CONVERT_UINT64_UINT16_MIDUPPER(a) \
+ ((UINT16)((a>>32) & 0xFFFF))
+// Get byte 4-5 of uint64
+#define CONVERT_UINT64_UINT16_MIDLOWER(a) \
+ ((UINT16)((a>>16) & 0xFFFF))
+// Get byte 6-7 of uint64
+#define CONVERT_UINT64_UINT16_LOWER(a) \
+ ((UINT16)((a>>0) & 0xFFFF))
+
+
+// Get byte 0 of uint32
+#define CONVERT_UINT32_UINT8_UPPER_HIGH(a) \
+ ((UINT8)((a>>24) & 0xFF))
+// Get byte 1 of uint32
+#define CONVERT_UINT32_UINT8_UPPER_LOW(a) \
+ ((UINT8)((a>>16) & 0xFF))
+// Get byte 2 of uint32
+#define CONVERT_UINT32_UINT8_LOWER_HIGH(a) \
+ ((UINT8)((a>>8) & 0xFF))
+// Get byte 3 of uint32
+#define CONVERT_UINT32_UINT8_LOWER_LOW(a) \
+ ((UINT8)((a>>0) & 0xFF))
+
+
+// Get byte 0-1 of uint32
+#define CONVERT_UINT32_UINT16_UPPER(a) \
+ ((UINT16)((a>>16) & 0xFFFF))
+// Get byte 1-2 of uint32
+#define CONVERT_UINT32_UINT16_MIDDLE(a) \
+ ((UINT16)((a>>8) & 0xFFFF))
+// Get byte 2-3 of uint32
+#define CONVERT_UINT32_UINT16_LOWER(a) \
+ ((UINT16)((a>>0) & 0xFFFF))
+
+// Get high byte of uint16
+#define CONVERT_UINT16_UINT8_HIGH(a) \
+ ((UINT8)((a>>8) & 0xFF))
+// Get low byte of uint16
+#define CONVERT_UINT16_UINT8_LOW(a) \
+ ((UINT8)(a & 0x00FF))
+
+
+// Get high nybble of uint8
+#define CONVERT_UINT8_UINT4_HIGH(a) \
+ ((UINT8)((a>>4) & 0x0F))
+// Get low nybble of uint8
+#define CONVERT_UINT8_UINT4_LOW(a) \
+ ((UINT8)(a & 0x0F))
+
+// Convert a two byte uint8 to a uint16
+// Always cast LSB to UINT8 to assure this also works with INT's
+#define CONVERT_UINT8_ARRAY_UINT16(a,b) \
+ ((a<<8) | ((UINT8)b))
+
+// Convert a 4 byte uint8 to a uint32
+#define CONVERT_UINT8_ARRAY_UINT32(a,b,c,d) \
+ ((((UINT32)a)<<24) | (((UINT32)b)<<16) | (((UINT32)c)<<8) | (((UINT32)d)))
+
+
+// Bit Operation Macros
+#define SETBIT(var,bit) ((var) |= (1<<(bit)))
+#define CLEARBIT(var,bit) ((var) &= ~(1<<(bit)))
+
+#define WORDALIGN(n) \
+ ((n + 3) & ~3)
+
+
+
+//#define UTIL_MUTEX_GET(I_MUTEX, I_TIMEOUT) ssx_semaphore_pend(I_MUTEX,I_TIMEOUT)
+//#define UTIL_MUTEX_PUT(I_MUTEX) ssx_semaphore_post(I_MUTEX)
+
+// @sb002 CHECKPOINT macros revamped a little to allow a little more reuse with
+// new return codes ('Ex'h). Note that there is a special case version of this
+// code in ll_ffdc.S designed solely for writing an FFDC header in the SSX_PANIC
+// path.
+#define __CHECKPOINT(_flg, _ckp, _rc) \
+{ \
+ G_fsp_msg.rsp->fields.seq = 0; \
+ G_fsp_msg.rsp->fields.cmd_type = 0; \
+ G_fsp_msg.rsp->fields.rc = _rc; \
+ G_fsp_msg.rsp->fields.data_length[0] = 0; \
+ G_fsp_msg.rsp->fields.data_length[1] = 3; \
+ G_fsp_msg.rsp->fields.data[0] = _flg; \
+ G_fsp_msg.rsp->fields.data[1] = (uint8_t)(_ckp >> 8); \
+ G_fsp_msg.rsp->fields.data[2] = (uint8_t)_ckp; \
+ dcache_flush_line((void *)CMDH_OCC_RESPONSE_BASE_ADDRESS); \
+}
+
+// This macro should only be used in the initialization path leading
+// up to being able to communicate with the FSP. After that, the
+// response buffer is used for responses and must not be used for
+// checkpointing unless the OCC is about to halt.
+#define CHECKPOINT_INIT() \
+{ \
+ __CHECKPOINT(0x00, 0x0000, ERRL_RC_INIT_CHCKPNT); \
+}
+
+// In case we are not able to reach a state where OCC can receive
+// commands from the FSP. Place a checkpoint value in the response
+// buffer with the return code of the response set to ERRL_RC_INIT_CHCKPNT.
+// Then, if OCC doesn't respond to an FSP command, the FSP will see
+// ERRL_RC_INIT_CHCKPNT and log the checkpoint in a special error log.
+#define CHECKPOINT(_ckp) \
+{ \
+ __CHECKPOINT(G_fsp_msg.rsp->fields.data[0], _ckp, ERRL_RC_INIT_CHCKPNT); \
+}
+
+// Special purpose flags to be used at programmer's discretion
+#define CHECKPOINT_FLAG(_flg) \
+{ \
+ G_fsp_msg.rsp->fields.data[0] |= _flg; \
+ __CHECKPOINT(_flg, (G_fsp_msg.rsp->fields.data[1] << 8 | G_fsp_msg.rsp->fields.data[2]), G_fsp_msg.rsp->fields.rc);\
+}
+
+// @sb012 Minor rewrite and addition of assembler version
+// @sb002 A new OCC_HALT macro much like SSX_PANIC but for OCC code use. The
+// ex_code parm is placed in the exception code of the FFDC header as opposed to
+// SSX_PANIC which sets the panic code. OCC_HALT sets the panic code to 0 to
+// differentiate this halt from SSX initiated halts. This macro mirrors what
+// SSX_PANIC does except it calls a different function for saving the FFDC.
+// This macro will not return to the caller. There is also an assembly version
+// if needed.
+#ifndef __ASSEMBLER__
+#define OCC_HALT(ex_code) \
+do { \
+ barrier(); \
+ asm volatile ("stw %r3, __occ_panic_save_r3@sda21(0)"); \
+ asm volatile ("mflr %r3"); \
+ asm volatile ("stw %r4, __occ_panic_save_r4@sda21(0)"); \
+ asm volatile ("lis %%r4, %0"::"i" (ex_code >> 16)); \
+ asm volatile ("ori %%r4, %%r4, %0"::"i" (ex_code & 0xffff)); \
+ asm volatile ("bl __occ_checkpoint_panic_and_save_ffdc"); \
+ asm volatile ("trap"); \
+ asm volatile (".long %0" : : "i" (ex_code)); \
+} while (0)
+#else /* __ASSEMBLER__ */
+#define OCC_HALT(ex_code) _occ_halt ex_code
+ .macro _occ_halt, ex_code
+ stw %r3, __occ_panic_save_r3@sda21(0)
+ mflr %r3
+ stw %r4, __occ_panic_save_r4@sda21(0)
+ lis %r4, \ex_code@h
+ ori %r4, %r4, \ex_code@l
+ bl __occ_checkpoint_panic_and_save_ffdc
+ trap
+ .long \ex_code
+ .endm
+#endif /* __ASSEMBLER__ */
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//Unique checkpoints
+enum
+{
+ MAIN_STARTED = 0x01ff,
+ SSX_STARTING = 0x0210,
+ SSX_INITIALIZED = 0x02ff,
+ TRACE_INITIALIZED = 0x0310,
+ INITIALIZING_IRQS = 0x0320,
+ IRQS_INITIALIZED = 0x032f,
+ MAIN_THREAD_STARTED = 0x03ff,
+ ROLES_INITIALIZED = 0x04ff,
+ SENSORS_INITIALIZED = 0x05ff,
+ PROC_CORE_INITIALIZED = 0x06ff,
+ CENTAUR_INITIALIZED = 0x07ff,
+ SLAVE_OCC_INITIALIZED = 0x08ff,
+ WATCHDOG_INITIALIZED = 0x09ff,
+ RTL_TIMER_INITIALIZED = 0x0aff,
+ SEMS_AND_TIMERS_INITIALIZED = 0x0bff,
+ APP_SEMS_CREATED = 0x0c10,
+ APP_MEM_MAPPED = 0x0c20,
+ APP_ADDR_INITIALIZED = 0x0c30,
+ APP_MEM_UNMAP = 0x0c40,
+ APPLETS_INITIALIZED = 0x0cff,
+ CMDH_THREAD_STARTED = 0x0dff,
+ INIT_OCB = 0x0e05,
+ OCB_INITIALIZED = 0x0e07,
+ INIT_FSI_HOST_MBOX = 0x0e10,
+ FSI_HOST_MBOX_INITIALIZED = 0x0e20,
+ FSP_COMM_INITIALIZED = 0x0eff,
+ ABOUT_TO_HALT = 0x0f00, // @sb002
+ FIRST_FSP_ATTN_SENT = 0xffff,
+};
+
+//Checkpoint flags (one byte bitmap)
+enum
+{
+ CF_FSI_MB_TIMEOUT = 0x01,
+};
+
+// @01a
+#define DEFAULT_TRACE_SIZE 1536 //@gm006
+//@pb003a - added defines
+#define MAX_OCCS 8
+#define MAX_CORES 12
+
+//@pb007a - HALT with FIR bits set
+// TRAP instruction should also set FIR bits along with halting PPC405
+// Set DBCR0 to initial value (setting external debug event) so that
+// trap call also sets FIR bits and also does not invoke program interrupt.
+#define HALT_WITH_FIR_SET mtspr(SPRN_DBCR0,PPC405_DBCR0_INITIAL); \
+ asm volatile("trap")
+
+// Static Assert Macro for Compile time assertions.
+// - This macro can be used both inside and outside of a function.
+// - A value of true will cause the ASSERT to produce this error
+// - This will show up on a compile fail as:
+// <file>:<line> error: size of array '_static_assert' is negative
+// - It would be trivial to use the macro to paste a more descriptive
+// array name for each assert, but we will leave it like this for now.
+#define STATIC_ASSERT(cond) extern uint8_t _static_assert[cond ? -1 : 1] __attribute__ ((unused));
+
+// Convert duration based in SsxTimestamps to microseconds.
+#define DURATION_IN_US_UNTIL_NOW_FROM(start_time) \
+ (uint32_t) ((ssx_timebase_get() - (SsxTimebase) start_time) / ( SSX_TIMEBASE_FREQUENCY_HZ / 1000000 ))
+
+// Convert duration based in SsxTimestamps to milliseconds.
+#define DURATION_IN_MS_UNTIL_NOW_FROM(start_time) \
+ (uint32_t) ((ssx_timebase_get() - (SsxTimebase) start_time) / ( SSX_TIMEBASE_FREQUENCY_HZ / 1000 ))
+
+// @ai009c
+// Skip this typedef in x86 environment
+#ifndef OCC_X86_PARSER
+//@pb000a - moved from common_types.h to here
+typedef uint32_t size_t ;
+#endif
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+//@pb000d - removed TPMD_code_header
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+extern const char G_occ_buildname[16];
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+int memcmp ( const void * ptr1, const void * ptr2, size_t num );
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_OCC_COMMON_H
+
diff --git a/src/occ/linkocc.cmd b/src/occ/linkocc.cmd
new file mode 100755
index 0000000..7b93c89
--- /dev/null
+++ b/src/occ/linkocc.cmd
@@ -0,0 +1,570 @@
+// $Id$
+
+// This linker script creates SRAM images of SSX applications for PgP. This
+// script is processed through the C proprocessor to create
+// configuration-dependent images.
+//
+// All sections with different MMU protection properties are 1KB-aligned, even
+// when linked in real-addressing mode.
+//
+// NB: According to *info* manual for ld, it should not be necessary to specify
+// the '.' in the section commands, e.g.,
+//
+// .data.startup . : { *(.data.startup) } > sram
+//
+// However without these the sections are not aligned properly, as the linker
+// seems to ignore the LC and move the section 'backwards' until it abuts
+// (aligned) with the previous one.
+//
+// Info on PPC binaries:
+// http://devpit.org/wiki/Debugging_PowerPC_ELF_Binaries
+
+// Need to do this so that elf32-powerpc is not modified!
+#undef powerpc
+
+#ifndef INITIAL_STACK_SIZE
+#define INITIAL_STACK_SIZE 2000
+#endif
+
+// >> gitprep
+// Always include occLinkInputFile for GNU builds
+//#ifdef OCCMK
+INCLUDE occLinkInputFile
+//#endif
+// << gitprep
+
+OUTPUT_FORMAT(elf32-powerpc);
+
+// Define the beginning of SRAM, the location of the PowerPC exception
+// vectors (must be 64K-aligned) and the location of the boot branch.
+
+// 512 KB SRAM at the top of the 32-bit address space
+
+// Last 1kB must be reserved for PORE-SLW, so stack can't be in that space
+
+#define origin 0xfff80000
+#define vectors 0xfff80000
+#define reset 0xffffffec
+#define sram_available (reset - origin)
+#define sram_size 0x00080000
+#define reserved_for_slw 0x400
+
+// The SRAM controller aliases the SRAM at 8 x 128MB boundaries to support
+// real-mode memory attributes using DCCR, ICCR etc. Noncacheable access is
+// the next-to-last 128MB PPC405 region. Write-though access is the
+// next-to-next-to-last 128MB PPC405 region
+
+#define noncacheable_offset 0x08000000
+#define noncacheable_origin (origin - 0x08000000)
+
+#define writethrough_offset 0x10000000
+#define writethrough_origin (origin - 0x10000000)
+
+// main()'s stack starts just below the boot branch. The bootloader will
+// align this address as needed.
+
+_SSX_INITIAL_STACK = (reset - reserved_for_slw - 1);
+_SSX_INITIAL_STACK_LIMIT = _SSX_INITIAL_STACK - INITIAL_STACK_SIZE;
+
+// Define SSX kernel text sections to be packed into nooks and crannies of
+// the exception vector area. An option is provided _not_ to pack, to help
+// better judge the best way to pack. Note that any code eligible for packing
+// is considered 'core' code that will be needed by the application at
+// runtime. Any header data is _always_ packed into .vectors_0000 however.
+//
+// Note that in order to support MMU protection, we can't pack data along
+// with the text. All of the packed data sections are thus left empty.
+
+
+// .vectors_0000
+
+#define text_0000
+
+#define data_0000 main.o(imageHeader)
+
+
+// .vectors_0100
+
+#define text_0100 \
+ppc405_core.o(.text) \
+ppc405_irq_core.o(.text)
+
+#define data_0100
+
+
+// .vectors_0c00
+
+#if SSX_TIMER_SUPPORT
+#define text_0c00_conditional
+#else
+#define text_0c00_conditional
+#endif
+
+
+#define text_0c00 \
+text_0c00_conditional \
+ppc405_cache_core.o(.text)
+
+#define data_0c00
+
+
+// .vectors_0f00
+
+#if SSX_TIMER_SUPPORT
+
+#if SSX_THREAD_SUPPORT
+#define text_0f00_conditional \
+ssx_timer_init.o(.text) \
+ssx_timer_core.o(.text) \
+ssx_semaphore_core.o(.text)
+#endif /* SSX_THREAD_SUPPORT */
+
+#if !SSX_THREAD_SUPPORT
+#define text_0f00_conditional \
+ssx_timer_init.o(.text) \
+ssx_timer_core.o(.text)
+#endif /* !SSX_THREAD_SUPPORT */
+
+#else /* SSX_TIMER_SUPPORT */
+
+#define text_0f00_conditional
+#endif /* SSX_TIMER_SUPPORT */
+
+#define text_0f00 \
+text_0f00_conditional
+
+#define data_0f00
+
+// .vectors_2000
+
+#if SSX_THREAD_SUPPORT
+#define thread_text \
+ssx_thread_init.o(.text) \
+ssx_thread_core.o(.text) \
+ppc405_irq_init.o(.text) \
+ppc405_thread_init.o(.text) \
+ssx_semaphore_init.o(.text)
+#else
+#define thread_text
+#endif
+
+#if PPC405_MMU_SUPPORT
+#define mmu_text \
+ppc405_mmu.o(.text)\
+ppc405_mmu_asm.o(.text)
+#else
+#define mmu_text
+#endif
+
+#define text_2000 \
+pgp_irq_init.o(.text) \
+ppc405_cache_init.o(.text) \
+ppc405_breakpoint.o(.text) \
+pgp_cache.o(.text) \
+ssx_stack_init.o(.text) \
+thread_text \
+mmu_text \
+pgp_async.o(.text) \
+pgp_async_pore.o(.text) \
+pgp_async_ocb.o(.text) \
+pgp_async_pba.o(.text) \
+pgp_pmc.o(.text) \
+pgp_ocb.o(.text) \
+pgp_pba.o(.text) \
+pgp_id.o(.text) \
+pgp_centaur.o(.text) \
+ppc405_lib_core.o(.text) \
+ssx_core.o(.text)
+
+
+#define data_2000
+
+// .vectors_0000 is always packed with header information
+
+#define pack_0000 text_0000 data_0000
+#define nopack_0000
+
+#ifndef NO_PACK_SSX
+
+#define pack_0100 text_0100 data_0100
+#define nopack_0100
+
+#define pack_0c00 text_0c00 data_0c00
+#define nopack_0c00
+
+#define pack_0f00 text_0f00 data_0f00
+#define nopack_0f00
+
+#define pack_2000 text_2000 data_2000
+#define nopack_2000
+
+#else
+
+#define pack_0100
+#define nopack_0100 text_0100 data_0100
+
+#define pack_0c00
+#define nopack_0c00 text_0c00 data_0c00
+
+#define pack_0f00
+#define nopack_0f00 text_0f00 data_0f00
+
+#define pack_2000
+#define nopack_2000 text_2000 data_2000
+
+#endif
+
+#define init_text \
+ssx_init.o(.text) \
+ppc405_boot.o(.text) \
+ppc405_init.o(.text) \
+pgp_init.o(.text)
+
+#ifndef PPC405_MMU_SUPPORT
+ASSERT((0), "OCC Application Firmware can not be compiled without \
+PPC405_MMU_SUPPORT compile flag")
+#endif
+
+// Define memory areas.
+
+MEMORY
+{
+ sram : ORIGIN = origin, LENGTH = sram_available
+ noncacheable : ORIGIN = noncacheable_origin, LENGTH = sram_available
+ writethrough : ORIGIN = writethrough_origin, LENGTH = sram_available
+ boot : ORIGIN = reset, LENGTH = 20
+}
+
+// NB: The code that sets up the MMU assumes that the linker script provides a
+// standard set of symbols that define the base address and size of each
+// expected section. Any section with a non-0 size will be mapped in the MMU
+// using protection attributes appropriate for the section. All sections
+// requiring different MMU attributes must be 1KB-aligned.
+
+// NOTE: __START_ADDR__, __READ_ONLY_DATA_LEN__, __WRITEABLE_DATA_ADDR__,
+// __WRITEABLE_DATA_LEN__ are used for the common image header macro
+
+SECTIONS
+{
+ . = origin;
+ . = vectors;
+
+ _MEMORY_ORIGIN = .;
+ _MEMORY_SIZE = sram_size;
+
+ __START_ADDR__ = .;
+
+ ////////////////////////////////
+ // Text0
+ ////////////////////////////////
+
+ // Low-memory kernel code and any other code that would benefit from being
+ // resident in lower-latency SRAM
+
+ _TEXT0_SECTION_BASE = .;
+ _PPC405_VECTORS_BASE = .;
+
+ .exceptions . : {
+ ___vectors = .;
+ ppc405_exceptions.o(.vectors_0000)
+ pack_0000
+ . = ___vectors + 0x0100;
+ ppc405_exceptions.o(.vectors_0100)
+ pack_0100
+ . = ___vectors + 0x0c00;
+ ppc405_exceptions.o(.vectors_0c00)
+ pack_0c00
+ . = ___vectors + 0x0f00;
+ ppc405_exceptions.o(.vectors_0f00)
+ pack_0f00
+ . = ___vectors + 0x2000;
+ ppc405_exceptions.o(.vectors_2000)
+ pack_2000
+ } > sram
+
+ // If we're not packing, then place 'core' code immediately after the
+ // exception vectors.
+
+ .nopack . : { nopack_0000 nopack_0100 nopack_0c00 nopack_0f00 nopack_2000 } > sram
+
+ . = ALIGN(1024);
+ _TEXT0_SECTION_SIZE = . - _TEXT0_SECTION_BASE;
+
+ ////////////////////////////////
+ // Noncacheable and Write-through Data
+ ////////////////////////////////
+
+ // Non-cacheable and write-through data is placed in low memory to
+ // improve latency. PORE-private text and data is also placed here. PORE
+ // text and data are segregated to enable relocated PORE disassembly of
+ //.text.pore.
+
+ // When running without the MMU we need to carefully arrange things such
+ // that the noncacheable and writethrough data is linked at the correct
+ // aliased VMA while remaining loaded in contiguous LMA addresses.
+
+#if PPC405_MMU_SUPPORT
+
+#define ALIASED_SECTION(s) s . : {*(s)} > sram
+
+#else
+
+#define ALIASED_SECTION(s) \
+ _LMA = . + _lma_offset; \
+ s . : AT (_LMA) {*(s)}
+
+#endif
+
+#if !PPC405_MMU_SUPPORT
+ . = . - noncacheable_offset;
+ _lma_offset = noncacheable_offset;
+#endif
+
+ _NONCACHEABLE_RO_SECTION_BASE = .;
+
+ ALIASED_SECTION(.noncacheable_ro)
+ ALIASED_SECTION(.text.pore)
+ ALIASED_SECTION(.data.pore)
+
+ . = ALIGN(1024);
+ _NONCACHEABLE_RO_SECTION_SIZE = . - _NONCACHEABLE_RO_SECTION_BASE;
+
+
+ _NONCACHEABLE_SECTION_BASE = .;
+
+ ALIASED_SECTION(.noncacheable)
+
+ . = ALIGN(1024);
+ _NONCACHEABLE_SECTION_SIZE = . - _NONCACHEABLE_SECTION_BASE;
+
+
+#if !PPC405_MMU_SUPPORT
+ . = . + noncacheable_offset - writethrough_offset;
+ _lma_offset = writethrough_offset;
+#endif
+
+
+ _WRITETHROUGH_SECTION_BASE = .;
+
+ ALIASED_SECTION(.writethrough)
+
+ . = ALIGN(1024);
+ _WRITETHROUGH_SECTION_SIZE = . - _WRITETHROUGH_SECTION_BASE;
+
+#if !PPC405_MMU_SUPPORT
+ . = . + writethrough_offset;
+#endif
+
+ // To enable non-cacheable sections w/o the MMU will require setting up
+ // the linker script to use aliased addresses of the SRAM.
+
+#if PPC405_MMU_SUPPORT == 0
+ ASSERT(((_NONCACHEABLE_RO_SECTION_SIZE == 0) &&
+ (_NONCACHEABLE_SECTION_SIZE == 0) &&
+ (_WRITETHROUGH_SECTION_SIZE == 0)),
+ " Non-cacheable and writethrough sections are currently only supported for MMU-enabled configurations. Enabling these capabilities for untranslated addresses will require some modifications of the linker script. ")
+#endif
+
+
+ ////////////////////////////////
+ // Read-only Data
+ ////////////////////////////////
+
+ // Accesses of read-only data may or may not benefit from being in fast
+ // SRAM - we'll give it the benefit of the doubt.
+
+ _RODATA_SECTION_BASE = .;
+
+ // SDA2 constant sections .sdata2 and .sbss2 must be adjacent to each
+ // other. Our SDATA sections are small so we'll use strictly positive
+ // offsets.
+
+ _SDA2_BASE_ = .;
+ .sdata2 . : { *(.sdata2) } > sram
+ .sbss2 . : { *(.sbss2) } > sram
+
+ // The .rodata.vclcommand section contains read-only VclCommandRecord for
+ // the benefit of the vcl_console() command interpreter.
+
+ _VCL_COMMAND_SECTION_BASE = .;
+ .rodata.vclcommand . : { *(.rodata.vclcommand) } > sram
+ _VCL_COMMAND_SECTION_SIZE = . - _VCL_COMMAND_SECTION_BASE;
+
+ // The .rodata.vclthread section contains read-only VclThreadRecord for the
+ // benefit of the thread command.
+
+ _VCL_THREAD_SECTION_BASE = .;
+ .rodata.vclthread . : { *(.rodata.vclthread) } > sram
+ _VCL_THREAD_SECTION_SIZE = . - _VCL_THREAD_SECTION_BASE;
+
+ // The .rodata.vclpackage section contains read-only char* pointers for the
+ // benefit of the package command.
+
+ _VCL_PACKAGE_SECTION_BASE = .;
+ .rodata.vclpackage . : { *(.rodata.vclpackage) } > sram
+ _VCL_PACKAGE_SECTION_SIZE = . - _VCL_PACKAGE_SECTION_BASE;
+
+ // Other read-only data.
+
+ .buildname . : { *(.buildname) } > sram
+ .rodata . : { *(.rodata*) *(.got2) } > sram
+
+ . = ALIGN(1024);
+ _RODATA_SECTION_SIZE = . - _RODATA_SECTION_BASE;
+ __READ_ONLY_DATA_LEN__ = . - __START_ADDR__;
+
+
+ ////////////////////////////////
+ // Text1
+ ////////////////////////////////
+
+ // The default text section
+
+ _TEXT1_SECTION_BASE = .;
+
+ // Initialization text. If we ever do a scheme to get rid of
+ // initialization text then this will have to be moved if we're also doing
+ // MMU protection.
+
+ .itext . : { init_text } > sram
+
+ // Other text
+ // It's not clear why boot.S is generating empty .glink,.iplt
+
+ .otext . : { *(.text) *(.text.startup) gpe.bin*(*) gpe_1.bin*(*)} > sram
+ .glink . : { *(.glink) } > sram
+
+ __CTOR_LIST__ = .;
+ .ctors . : { *(.ctors) } > sram
+ __CTOR_END__ = .;
+
+ . = ALIGN(1024);
+ _TEXT1_SECTION_SIZE = . - _TEXT1_SECTION_BASE;
+
+ ////////////////////////////////
+ // Read-write Data
+ ////////////////////////////////
+
+ _DATA_SECTION_BASE = .;
+ __WRITEABLE_DATA_ADDR__ = .;
+
+ // SDA sections .sdata and .sbss must be adjacent to each
+ // other. Our SDATA sections are small so we'll use strictly positive
+ // offsets.
+
+ _SDA_BASE_ = .;
+ .sdata . : { *(.sdata) } > sram
+ // Make sbss section 128 bytes aligned as linker is complaining while
+ // compiling product applets that use global variables from the occ
+ // application. OCC application is compiled with SDA data enabled and
+ // applets are compiled with SDA sections not enabled.
+ .sbss . : { *(.sbss) . = ALIGN(128); } > sram
+
+ // Other read-write data
+ // It's not clear why boot.S is generating empty .glink,.iplt
+
+ .rela . : { *(.rela*) *(.glink*) *(.iplt*) } > sram
+ .rwdata . : { *(.data) *(.bss) *(COMMON) . = ALIGN(128); } > sram
+
+ // Initialization-only data. This includes the stack of main, the data
+ // structures declared by INITCALL, and any other data areas that can be
+ // reclaimed to the heap after initialization.
+ //
+ // NB: If we ever do reclaim this space, we need to modify the concept of
+ // executable free space.
+
+ _INIT_ONLY_DATA_BASE = .;
+
+ // _SSX_INITIAL_STACK_LIMIT = .;
+ // . = . + INITIAL_STACK_SIZE;
+ // _SSX_INITIAL_STACK = . - 1;
+
+ _INITCALL_SECTION_BASE = .;
+ .data.initcall . : { *(.data.initcall) } > sram
+ _INITCALL_SECTION_SIZE = . - _INITCALL_SECTION_BASE;
+
+ .data.startup . : { *(.data.startup) } > sram
+
+ _INIT_ONLY_DATA_SIZE = . - _INIT_ONLY_DATA_BASE;
+
+ ////////////////////////////////
+ // Free Space
+ ////////////////////////////////
+
+ // If the configuration allows executing from free space - i.e.,
+ // malloc()-ing a buffer and loading and executing code from it - then the
+ // free space is separated and aligned so that it can be marked executable.
+ // Otherwise it is simply read/write like the normal data sections.
+
+#ifndef EXECUTABLE_FREE_SPACE
+#define EXECUTABLE_FREE_SPACE 0
+#endif
+
+#if PPC405_MMU_SUPPORT && EXECUTABLE_FREE_SPACE
+ . = ALIGN(1024);
+#endif
+
+ // The free space available to the program starts here. This space does
+ // not include the initial stack used by the boot loader and main(). The
+ // initial stack space is considered part of the free 'section' for MMU
+ // purposes. Free space is always 8-byte aligned.
+ //
+ // Note that there is no data after _SSX_FREE_START. When binary images
+ // are created they can be padded to _SSX_FREE_START to guarantee
+ // that .bss and COMMON data are zeroed, and that the images contain an
+ // even multiple of 8 bytes (required for HW loaders).
+
+ . = ALIGN(8);
+ _EX_FREE_SECTION_BASE = .;
+ _SSX_FREE_START = .;
+
+#if EXECUTABLE_FREE_SPACE
+ _DATA_SECTION_SIZE = . - _DATA_SECTION_BASE;
+ __WRITEABLE_DATA_LEN__ = . - __WRITEABLE_DATA_ADDR__ ;
+ _EX_FREE_SECTION_SIZE = 0 - _EX_FREE_SECTION_BASE;
+#else
+ _DATA_SECTION_SIZE = _LINEAR_WR_WINDOW_SECTION_BASE - _DATA_SECTION_BASE;
+ __WRITEABLE_DATA_LEN__ = _LINEAR_WR_WINDOW_SECTION_BASE - __WRITEABLE_DATA_ADDR__ ;
+ _EX_FREE_SECTION_SIZE = 0;
+#endif
+
+ _SSX_FREE_END = _LINEAR_WR_WINDOW_SECTION_BASE - 1;
+
+ ////////////////////////////////
+ // FSP Command Buffer
+ ////////////////////////////////
+ __CUR_COUNTER__ = .;
+
+ _LINEAR_WR_WINDOW_SECTION_BASE = 0xffff6000;
+ _LINEAR_WR_WINDOW_SECTION_SIZE = 0x1000;
+ _LINEAR_RD_WINDOW_SECTION_BASE = 0xffff7000;
+ _LINEAR_RD_WINDOW_SECTION_SIZE = 0x1000;
+ . = _LINEAR_WR_WINDOW_SECTION_BASE;
+ .linear_wr . : {*(linear_wr) . = ALIGN(_LINEAR_WR_WINDOW_SECTION_SIZE);} > sram
+ .linear_rd . : {*(linear_rd) . = ALIGN(_LINEAR_RD_WINDOW_SECTION_SIZE);} > sram
+
+ . = __CUR_COUNTER__;
+
+ ////////////////////////////////
+ // Applet areas
+ ////////////////////////////////
+ __CUR_COUNTER__ = .;
+ _APPLET0_SECTION_BASE = 0xffff8000;
+ . = _APPLET0_SECTION_BASE;
+ // Section aligned to 128 to make occ main application image 128 bytes
+ // aligned which is requirement for applet manager when traversing through
+ // all the image headers
+ initSection . : { *(initSection) init_text . = ALIGN(128);} > sram
+
+ . = __CUR_COUNTER__;
+ _APPLET0_SECTION_SIZE = 0x00004000;
+ _APPLET1_SECTION_BASE = 0xffffc000;
+ _APPLET1_SECTION_SIZE = 0x00003c00;
+
+ //////////////////////////////
+ // End Of Memory
+ //////////////////////////////
+
+ _PPC405_END_OF_MEMORY = 0;
+}
+
diff --git a/src/occ/main.c b/src/occ/main.c
new file mode 100755
index 0000000..0d51fb6
--- /dev/null
+++ b/src/occ/main.c
@@ -0,0 +1,1180 @@
+/******************************************************************************
+// @file main.c
+// @brief OCC main
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section main.c MAIN.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb000 pbavari 07/08/2011 Added image header support
+ * @01 nguyenp 08/16/2011 Replaced rtloop_ocb_init with the
+ * new rtl_ocb_init in rtls directory
+ * @cc000 cjcain 08/18/2011 Added APSS communication code
+ * @02 tapiar 08/08/2011 Add Applet Manager code
+ * @th000 thallet 09/14/2011 Added SysConfig include
+ * @pb005 pbavari 09/15/2011 ifdef out apss_initialize call
+ * @th001 thallet 09/15/2011 Delete unused timer
+ * @pb004 pbavari 09/20/2011 Init section support
+ * @pb007 pbavari 09/27/2011 Watchdog timer support
+ * @03 tapiar 09/22/2011 add dcom support
+ * @04 nguyenp 09/28/2011 Added Proc core init call
+ * @dw000 dwoodham 10/21/2011 Add DPSS communication code
+ * @pb009 pbavari 10/20/2011 Main thread support
+ * @pb00A pbavari 11/15/2011 Changed name of APSS_SUPPORT Flag
+ * to OCC_ALONE_SIMICS
+ * @th005 thallet 11/23/2011 Added sensor_init_all
+ * @th006 thallet 11/21/2011 RESET_REQUEST substituted
+ * @pb00B pbavari 12/15/2011 Removed appletComplete semaphore
+ * from APSS_INIT Applet call
+ * @dw001 dwoodham 12/12/2011 Update call to IMAGE_HEADER macro
+ * @rc001 rickylie 01/10/2012 Changed TRAC_DBG to MAIN_DBG
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/2012 Moved slave_occ_init()
+ * @th00c thallet 04/04/2012 Centaur Support
+ * @th00d thallet 04/08/2012 OCC TMGT Communication Thread
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th013 thallet 07/24/2012 Minor changes for VPO/HW compile
+ * @th010 thallet 07/11/2012 Pstate Enablemen
+ * @th022 thallet 10/05/2012 Master Init after TMGT command
+ * @at009 859308 alvinwan 10/15/2012 Added tracepp support
+ * @th029 thallet 01/23/2013 Added GCOV capability
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @th032 thallet 04/26/2013 Tuleta HW bup
+ * @th035 881654 thallet 05/06/2013 Tuleta bup Pstate Fixes
+ * @th038 thallet 06/03/2013 Disable Centaur since it isn't ready on HW yet
+ * @th045 893135 thallet 07/26/2013 Updated for new Centaur Procedures
+ * @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+ * @sb000 905048 sbroyles 10/28/2013 Add tags for code cleanup,
+ * see RTC task 73327. Change tags are
+ * removed once resolved.
+ * @sb001 905504 sbroyles 11/06/2013 Resolve all fix tags.
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs019 908218 gjsilva 12/04/2013 Support cooling request architecture
+ * @sb002 908891 sbroyles 12/09/2013 Enable watchdog timers
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @sb022 910404 sbroyles 01/06/2014 Extend watchdog timeout
+ * @gs023 912003 gjsilva 01/16/2014 Generate VRHOT signal and control loop
+ * @gm022 908890 milesg 01/23/2014 Halt OCC on OCCLFIR[38]
+ * @gm031 916489 milesg 03/07/2014 Additional handling for OISR0[2] and OISR0[9]
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @wb001 919178 wilbryan 03/19/2014 Change nest frequency default when HOMER access fails
+ * @gm033 920448 milesg 03/26/2014 use getscom/putscom ffdc wrapper
+ * @gm036 917550 milesg 04/09/2014 Ignore phantom interrupts (log info error)
+ * @wb004 922138 wilbryan 04/07/2014 Ensure timely pstate completion
+ * @gs041 942203 gjsilva 10/17/2014 Support for HTMGT/BMC interface
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include "heartbeat.h" // @sb002 for heartbeat
+#include <thread.h>
+#include <sensor.h>
+#include <threadSch.h>
+#include <errl.h>
+#include <apss.h>
+#include <appletManager.h> // @02a Applet Manager
+#include <trac.h> // @02a trace
+#include <occ_service_codes.h> // @02a module ids
+#include <occ_sys_config.h> // @th000 Added for sys config access
+#include <timer.h> // @pb007a - watchdog timer init
+#include <dcom.h> // @th000 Added for sys config access
+#include <rtls.h> // @01a
+#include <proc_data.h> // @04a proc core data
+#include <centaur_data.h> //
+#include <dpss.h> // @dw000a DPSS comm
+#include <state.h>
+#include <amec_sys.h>
+#include <cmdh_fsp.h>
+#include <proc_pstate.h>
+#include <vrm.h>
+#include <chom.h> // @jh005a Call Home data
+#include <homer.h> // @sb001
+#include <amec_health.h>
+#include <amec_freq.h> // @wb004
+#include <thrm_thread.h>
+#include "scom.h"
+
+#ifdef GCOV_CODE_COVERAGE
+#include "gcov.h" // @th029a
+#endif
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+//@pb000a - added
+extern void __ssx_boot;
+extern uint32_t G_occ_phantom_critical_count; //gm036
+extern uint32_t G_occ_phantom_noncritical_count; //gm036
+extern uint8_t G_occ_interrupt_type; //@gs041
+
+//*************************************************************************
+// Image Header
+//*************************************************************************
+//@pb000a - added
+//@dw001c - added arg: idNum = ID_NUM_INVALID
+IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,ID_NUM_INVALID);
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+//Set main thread timer for one second
+#define MAIN_THRD_TIMER_SLICE ((SsxInterval) SSX_SECONDS(1))
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// SIMICS printf/printk
+SimicsStdio G_simics_stdout;
+SimicsStdio G_simics_stderr;
+
+
+// Critical /non Critical Stacks
+uint8_t G_noncritical_stack[NONCRITICAL_STACK_SIZE];
+uint8_t G_critical_stack[CRITICAL_STACK_SIZE];
+
+//NOTE: Three semaphores are used so that if in future it is decided
+// to move thermal, health monitor and FFDC into it's own threads, then
+// it can be done easily without more changes.
+// Semaphores for the thermal functions
+SsxSemaphore G_thrmSem;
+// Semaphores for the health monitor functions
+SsxSemaphore G_hmonSem;
+// Semaphores for the FFDC functions
+SsxSemaphore G_ffdcSem;
+// Timer for posting thermal, health monitor and FFDC semaphore
+SsxTimer G_mainThrdTimer;
+
+// @sb022 Variable holding main thread loop count
+uint32_t G_mainThreadLoopCounter = 0x0;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void pmc_hw_error_isr(void *private, SsxIrqId irq, int priority); //gm031
+
+//Macro creates a 'bridge' handler that converts the initial fast-mode to full
+//mode interrupt handler
+SSX_IRQ_FAST2FULL(pmc_hw_error_fast, pmc_hw_error_isr); //gm031
+
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+//gm016
+//Sets up the PBA so that there is no overlap in use of buffers between
+//GPE engines and other engines. This came from Bishop Brock.
+//It should be pulled out after the procedure that sets up the PBA
+//has been fixed. Without this workaround we see an invalid instruction
+//failure on the GPE.
+void workaround_HW258436()
+{
+ uint64_t l_scom_data = 0;
+ int l_rc = 0;
+
+ do
+ {
+ //scom errors will be committed internally -- gm033
+ l_rc = getscom_ffdc(0x64004, &l_scom_data, NULL);
+ if(l_rc) break;
+ l_scom_data &= 0xfffff1ffffffffffull;
+ l_scom_data |= 0x0000080000000000ull;
+ l_rc = putscom_ffdc(0x64004, l_scom_data, NULL);
+ if(l_rc) break;
+
+ l_rc = getscom_ffdc(0x64005, &l_scom_data, NULL);
+ if(l_rc) break;
+ l_scom_data &= 0xfffff1ffffffffffull;
+ l_scom_data |= 0x0000040000000000ull;
+ l_rc = putscom_ffdc(0x64005, l_scom_data, NULL);
+ if(l_rc) break;
+
+ l_rc = getscom_ffdc(0x64006, &l_scom_data, NULL);
+ if(l_rc) break;
+ l_scom_data &= 0xfffff1ffffffffffull;
+ l_scom_data |= 0x0000040000000000ull;
+ l_rc = putscom_ffdc(0x64006, l_scom_data, NULL);
+ if(l_rc) break;
+
+ l_rc = getscom_ffdc(0x64007, &l_scom_data, NULL);
+ if(l_rc) break;
+ l_scom_data &= 0xfffff1ffffffffffull;
+ l_scom_data |= 0x0000040000000000ull;
+ l_rc = putscom_ffdc(0x64007, l_scom_data, NULL);
+ if(l_rc) break;
+ }while(0);
+ if(l_rc)
+ {
+ TRAC_ERR("workaround_HW258436: scom failure. rc=0x%08x", l_rc);
+ }
+}
+
+
+//gm031
+//Handles IRQ for PMCLFIR bit being set. Only bits that are unmasked (0x1010843) and
+//have action0 (0x1010846) set to 1 and action1 (0x1010847) set to 0 will cause this
+//interupt (OISR0[9]) to fire. This runs in a non critical context (tracing allowed).
+void pmc_hw_error_isr(void *private, SsxIrqId irq, int priority)
+{
+ errlHndl_t l_err;
+ pmc_ffdc_data_t l_pmc_ffdc;
+ SsxMachineContext ctx;
+
+ // Mask this interrupt
+ ssx_irq_disable(irq);
+
+ // disable critical interrupts
+ ssx_critical_section_enter( SSX_NONCRITICAL, &ctx );
+
+ // clear this irq status in OISR0
+ ssx_irq_status_clear(irq);
+
+ // dump a bunch of FFDC registers
+ fill_pmc_ffdc_buffer(&l_pmc_ffdc);
+
+ TRAC_ERR("PMC Failure detected through OISR0[9]!!!");
+ /* @
+ * @moduleid PMC_HW_ERROR_ISR
+ * @reasonCode PMC_FAILURE
+ * @severity ERRL_SEV_PREDICTIVE
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure detected in processor
+ * power management controller (PMC)
+ */
+ l_err = createErrl( PMC_HW_ERROR_ISR, // i_modId,
+ PMC_FAILURE, // i_reasonCode,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE,
+ NULL, // tracDesc_t i_trace,
+ DEFAULT_TRACE_SIZE, // i_traceSz,
+ 0, // i_userData1,
+ 0); // i_userData2
+
+ //Add our register dump to the error log
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*) &l_pmc_ffdc,
+ sizeof(l_pmc_ffdc),
+ ERRL_USR_DTL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ //Add firmware callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ //Add processor callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ //Add planar callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.backplane_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+
+ REQUEST_RESET(l_err);
+
+ // Unmask this interrupt
+ ssx_irq_enable(irq);
+
+ // re-enable non-critical interrupts
+ ssx_critical_section_exit( &ctx );
+}
+
+//gm022
+//Handles IRQ for OCCLFIR bit being set. Only bits that are unmasked (0x1010803) and
+//have action0 (0x1010806) set to 1 and action1 (0x1010807) set to 0 will cause this
+//interupt (OISR0[2]) to fire. This runs in a critical context (no tracing!).
+//
+//NOTE: use "putscom pu 6B111 0 3 101 -ib -p1" to inject the error.
+#define OCC_LFIR_SPARE_BIT50 0x0000000000002000ull //gm031
+void occ_hw_error_isr(void *private, SsxIrqId irq, int priority)
+{
+ //gm031
+ //set bit 50 of the OCC LFIR so that the PRDF component will log an error and callout the processor
+ //TMGT will also see a problem and log an error but it will be informational.
+ _putscom(OCB_OCCLFIR_OR, OCC_LFIR_SPARE_BIT50, SCOM_TIMEOUT);
+
+ //Halt occ so that hardware will enter safe mode
+ OCC_HALT(ERRL_RC_OCC_HW_ERROR);
+}
+
+//gm022
+// Enable and register any ISR's that need to be set up as early as possible.
+void occ_irq_setup()
+{
+ int l_rc;
+ errlHndl_t l_err;
+
+ do
+ {
+
+ // ------------- OCC Error IRQ Setup ------------------
+
+ // Disable the IRQ while we work on it
+ ssx_irq_disable(PGP_IRQ_OCC_ERROR);
+
+ // Set up the IRQ
+ l_rc = ssx_irq_setup(PGP_IRQ_OCC_ERROR,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH,
+ SSX_IRQ_TRIGGER_EDGE_SENSITIVE);
+ if(l_rc)
+ {
+ TRAC_ERR("occ_irq_setup: ssx_irq_setup(PGP_IRQ_OCC_ERROR) failed with rc=0x%08x", l_rc);
+ break;
+ }
+
+ // Register the IRQ handler with SSX
+ l_rc = ssx_irq_handler_set(PGP_IRQ_OCC_ERROR,
+ occ_hw_error_isr,
+ NULL,
+ SSX_CRITICAL);
+ if(l_rc)
+ {
+ TRAC_ERR("occ_irq_setup: ssx_irq_handler_set(PGP_IRQ_OCC_ERROR) failed with rc=0x%08x", l_rc);
+ break;
+ }
+
+ //enable the IRQ
+ ssx_irq_status_clear(PGP_IRQ_OCC_ERROR);
+ ssx_irq_enable(PGP_IRQ_OCC_ERROR);
+
+
+ // ------------- PMC Error IRQ Setup ------------------ gm031
+
+ // Disable the IRQ while we work on it
+ ssx_irq_disable(PGP_IRQ_PMC_ERROR);
+
+ // Set up the IRQ
+ l_rc = ssx_irq_setup(PGP_IRQ_PMC_ERROR,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH,
+ SSX_IRQ_TRIGGER_EDGE_SENSITIVE);
+ if(l_rc)
+ {
+ TRAC_ERR("occ_irq_setup: ssx_irq_setup(PGP_IRQ_PMC_ERROR) failed with rc=0x%08x", l_rc);
+ break;
+ }
+
+ // Register the IRQ handler with SSX
+ l_rc = ssx_irq_handler_set(PGP_IRQ_PMC_ERROR,
+ pmc_hw_error_fast,
+ NULL,
+ SSX_NONCRITICAL);
+ if(l_rc)
+ {
+ TRAC_ERR("occ_irq_setup: ssx_irq_handler_set(PGP_IRQ_PMC_ERROR) failed with rc=0x%08x", l_rc);
+ break;
+ }
+
+ //enable the IRQ
+ ssx_irq_status_clear(PGP_IRQ_PMC_ERROR);
+ ssx_irq_enable(PGP_IRQ_PMC_ERROR);
+ }while(0);
+
+
+ if(l_rc)
+ {
+ //single error for all error cases, just look at trace to see where it failed.
+ /*@
+ * @moduleid OCC_IRQ_SETUP
+ * @reasonCode SSX_GENERIC_FAILURE
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @userdata1 SSX return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware failure initializing IRQ
+ */
+ l_err = createErrl( OCC_IRQ_SETUP, // i_modId,
+ SSX_GENERIC_FAILURE, // i_reasonCode,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_UNRECOVERABLE,
+ NULL, // tracDesc_t i_trace,
+ 0, // i_traceSz,
+ l_rc, // i_userData1,
+ 0); // i_userData2
+
+ //Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ commitErrl(&l_err);
+ }
+}
+
+// Function Specification
+//
+// Name: hmon_routine
+//
+// Description: Runs various routines that check the health of the OCC
+//
+// Flow:
+//
+// End Function Specification
+void hmon_routine()
+{
+ static uint32_t L_critical_phantom_count = 0;
+ static uint32_t L_noncritical_phantom_count = 0;
+ static bool L_c_phantom_logged = FALSE;
+ static bool L_nc_phantom_logged = FALSE;
+ bool l_log_phantom_error = FALSE;
+
+ //@rc001m - Modified to use MAIN debug traces
+ MAIN_DBG("HMON routine processing...");
+
+ //Check if we've had any phantom interrupts -- gm036
+ if(L_critical_phantom_count != G_occ_phantom_critical_count)
+ {
+ L_critical_phantom_count = G_occ_phantom_critical_count;
+ TRAC_INFO("hmon_routine: critical phantom irq occurred! count[%d]", L_critical_phantom_count);
+
+ //log a critical phantom error once
+ if(!L_c_phantom_logged)
+ {
+ L_c_phantom_logged = TRUE;
+ l_log_phantom_error = TRUE;
+ }
+ }
+ if(L_noncritical_phantom_count != G_occ_phantom_noncritical_count)
+ {
+ L_noncritical_phantom_count = G_occ_phantom_noncritical_count;
+ TRAC_INFO("hmon_routine: non-critical phantom irq occurred! count[%d]", L_noncritical_phantom_count);
+
+ //log a non-critical phantom error once
+ if(!L_nc_phantom_logged)
+ {
+ L_nc_phantom_logged = TRUE;
+ l_log_phantom_error = TRUE;
+ }
+ }
+
+ if(l_log_phantom_error)
+ {
+ /* @
+ * @errortype
+ * @moduleid HMON_ROUTINE_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 critical count
+ * @userdata2 non-critical count
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc interrupt with unknown source was detected
+ */
+ errlHndl_t l_err = createErrl(HMON_ROUTINE_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ L_critical_phantom_count, //userdata1
+ L_noncritical_phantom_count); //userdata2
+ // Commit Error
+ commitErrl(&l_err);
+ }
+
+ //if we are in activate state, then monitor the processor temperature for
+ //timeout conditions and the processor VRHOT signal.
+ if (IS_OCC_STATE_ACTIVE())
+ {
+ amec_health_check_proc_timeout();
+ amec_health_check_proc_vrhot();
+ }
+
+ //if we are in active state with memory temperature data being collected
+ //then monitor the temperature collections for overtemp and timeout conditions
+ if(IS_OCC_STATE_ACTIVE() &&
+ rtl_task_is_runnable(TASK_ID_CENTAUR_DATA))
+ {
+ amec_health_check_cent_timeout();
+ amec_health_check_cent_temp();
+ amec_health_check_dimm_timeout();
+ amec_health_check_dimm_temp();
+ }
+}
+
+
+// Function Specification
+//
+// Name: master_occ_init
+//
+// Description: Master OCC specific initialization.
+//
+// Flow: 09/21/2011 FN= master_occ_init
+//
+// End Function Specification
+void master_occ_init()
+{
+ // >@dw000a
+ // Init DPSS chip & start associated tasks.
+ // At present, this is uses function which is part of the INIT_SEC so
+ // it needs to be run before any applet runs. In future, we can make
+ // this an applet
+ // @pb00B - Commented out below call since we are not going to have DPSS
+ // support in OCC. In future if we decide to support it, this call needs
+ // to be changed to applet call as we have applet for initializing DPSS.
+ // start_dpss();
+ // <@dw000a
+
+ OCC_APLT_STATUS_CODES l_status = OCC_APLT_SUCCESS;
+ errlHndl_t l_errl = NULL;
+
+ // Initialize APSS // @cc000a
+ // @pb005a - ifdef apss_initialize call temporary
+ // until Bishop's simics model and Steve's simics model
+ // are synced. Bishop's model does not have apss support
+ // Steve's model does not have latest changes Bishop
+ // made for ssx. To make latest svn code usable for testing
+ // ifdef apss_initialize call
+ runApplet(OCC_APLT_APSS_INIT, // Applet enum Name
+ NULL, // Applet arguments
+ TRUE, // Blocking call?
+ NULL, // Applet finished semaphore
+ &l_errl, // Error log handle
+ &l_status); // Error status
+
+ if( (NULL != l_errl) || (l_status != OCC_APLT_SUCCESS))
+ {
+ TRAC_ERR("APSS init applet returned error: l_status: 0x%x", l_status);
+ // commit & delete. CommitErrl handles NULL error log handle
+ REQUEST_RESET(l_errl); //@gm006
+ }
+
+ // Reinitialize the PBAX Queues
+ dcom_initialize_pbax_queues(); // @th022
+}
+
+// Function Specification
+//
+// Name: slave_occ_init
+//
+// Description: Slave OCC specific initialization.
+//
+// Flow: 09/21/2011 FN= slave_occ_init
+//
+// End Function Specification
+void slave_occ_init()
+{
+ // >@dw000a
+ // Init the DPSS oversubscription IRQ handler
+ //@rc001m - Modified to use MAIN debug traces
+ MAIN_DBG("Initializing Oversubscription IRQ...");
+ errlHndl_t l_errl = dpss_oversubscription_irq_initialize();
+
+ if( l_errl )
+ {
+ // Trace and commit error
+ TRAC_ERR("Initialization of Oversubscription IRQ handler failed");
+
+ // commit log ... log should be deleted by reader mechanism
+ commitErrl( &l_errl );
+ }
+ else
+ {
+ TRAC_INFO("Oversubscription IRQ initialized");
+ }
+ // <@dw000a
+
+ // @03a set up our doorbell queues
+ dcom_initialize_pbax_queues();
+
+ // Run AMEC Slave Init Code
+ amec_slave_init(); // @th00a
+
+ // Initialize SMGR State Semaphores
+ extern SsxSemaphore G_smgrModeChangeSem;
+ ssx_semaphore_create(&G_smgrModeChangeSem, 1, 1); // @th022
+
+ // Initialize SMGR Mode Semaphores
+ extern SsxSemaphore G_smgrStateChangeSem;
+ ssx_semaphore_create(&G_smgrStateChangeSem, 1, 1); // @th022
+}
+
+// Function Specification
+//
+// Name: mainThrdTimerCallback
+//
+// Description: Main thread timer to post semaphores handled by main thread
+//
+// Flow: 09/21/2011 FN= mainThrdTimerCallback
+//
+// End Function Specification
+void mainThrdTimerCallback(void * i_argPtr)
+{
+ int l_rc = SSX_OK;
+ do
+ {
+ // Post Thermal semaphore
+ l_rc = ssx_semaphore_post( &G_thrmSem );
+
+ if ( l_rc != SSX_OK )
+ {
+ TRAC_ERR("Failure posting thermal semaphore: rc: 0x%x", l_rc);
+ break;
+ }
+ //@rc001m - Modified to use MAIN debug traces
+ MAIN_DBG("posted thrmSem");
+
+ // Post health monitor semaphore
+ l_rc = ssx_semaphore_post( &G_hmonSem );
+
+ if ( l_rc != SSX_OK )
+ {
+ TRAC_ERR("Failure posting HlTH monitor semaphore: rc: 0x%x", l_rc);
+ break;
+ }
+ //@rc001m - Modified to use MAIN debug traces
+ MAIN_DBG("posted hmonSem");
+
+ // Post FFDC semaphore
+ l_rc = ssx_semaphore_post( &G_ffdcSem );
+
+ if ( l_rc != SSX_OK )
+ {
+ TRAC_ERR("Failure posting FFDC semaphore: rc: 0x%x", l_rc);
+ break;
+ }
+ //@rc001m - Modified to use MAIN debug traces
+ MAIN_DBG("posted ffdcSem");
+
+ }while(FALSE);
+
+ // create error on failure posting semaphore
+ if( l_rc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid MAIN_THRD_TIMER_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Create thermal semaphore rc
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX semaphore related failure
+ */
+ errlHndl_t l_err = createErrl(MAIN_THRD_TIMER_MID, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ 0); //userdata2
+ // Commit Error
+ REQUEST_RESET(l_err); // @gm006
+ }
+}
+
+// Function Specification
+//
+// Name: initMainThrdSemAndTimer
+//
+// Description: Helper function to create semaphores handled by main thread. It also
+// creates and schedules timer used for posting main thread semaphores
+//
+// Flow: FN=None
+//
+// End Function Specification
+void initMainThrdSemAndTimer()
+{
+ // create the thermal Semaphore, starting at 0 with a max count of 0
+ // NOTE: Max count of 0 is used becuase there is possibility that
+ // semaphore can be posted more than once without any semaphore activity
+ int l_thrmSemRc = ssx_semaphore_create(&G_thrmSem, 0, 0);
+ // create the health monitor Semaphore, starting at 0 with a max count of 0
+ // NOTE: Max count of 0 is used becuase there is possibility that
+ // semaphore can be posted more than once without any semaphore activity
+ int l_hmonSemRc = ssx_semaphore_create(&G_hmonSem, 0, 0);
+ // create FFDC Semaphore, starting at 0 with a max count of 0
+ // NOTE: Max count of 0 is used becuase there is possibility that
+ // semaphore can be posted more than once without any semaphore activity
+ int l_ffdcSemRc = ssx_semaphore_create(&G_ffdcSem, 0, 0);
+ //create main thread timer
+ int l_timerRc = ssx_timer_create(&G_mainThrdTimer,mainThrdTimerCallback,0);
+
+ //check for errors creating the timer
+ if(l_timerRc == SSX_OK)
+ {
+ //schedule the timer so that it runs every MAIN_THRD_TIMER_SLICE
+ l_timerRc = ssx_timer_schedule(&G_mainThrdTimer, // Timer
+ 1, // time base
+ MAIN_THRD_TIMER_SLICE);// Timer period
+ }
+ else
+ {
+ TRAC_ERR("Error creating main thread timer: RC: %d", l_timerRc);
+ }
+
+ // Failure creating semaphore or creating/scheduling timer, create
+ // and log error.
+ if (( l_thrmSemRc != SSX_OK ) ||
+ ( l_hmonSemRc != SSX_OK ) ||
+ ( l_ffdcSemRc != SSX_OK ) ||
+ ( l_timerRc != SSX_OK))
+ {
+ TRAC_ERR("Semaphore/timer create failure: thrmSemRc: 0x%08x, "
+ "hmonSemRc: 0x08%x, ffdcSemRc: 0x%08x, l_timerRc: 0x%08x",
+ -l_thrmSemRc,-l_hmonSemRc,-l_ffdcSemRc, l_timerRc );
+
+ /* @
+ * @errortype
+ * @moduleid MAIN_THRD_SEM_INIT_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Create thermal semaphore rc
+ * @userdata2 Timer create/schedule rc
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX semaphore related failure
+ */
+ errlHndl_t l_err = createErrl(MAIN_THRD_SEM_INIT_MID, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_thrmSemRc, //userdata1
+ l_timerRc); //userdata2
+
+ REQUEST_RESET(l_err); // @gm006
+ }
+}
+
+// Function Specification
+//
+// Name: Main_thread_routine
+//
+// Description: Main thread handling OCC initialization and thernal, health
+// monitor and FFDC function semaphores
+//
+// Flow: 11/23/2011 FN= Main_thread_routine
+//
+// End Function Specification
+void Main_thread_routine(void *private)
+{
+ CHECKPOINT(MAIN_THREAD_STARTED);
+
+ TRAC_INFO("Main Thread Started ... " );
+
+ workaround_HW258436(); //gm016
+
+ // NOTE: At present, we are not planning to use any config data from
+ // mainstore. OCC Role will be provided by FSP after FSP communication
+ // So instead of doing config_data_init, we will directly use
+ // dcom_initialize_roles. If in future design changes, we will make
+ // change to use config_data_init at that time.
+ // Default role initialization and determine OCC/Chip Id
+ // @03a get our role
+ dcom_initialize_roles();
+ CHECKPOINT(ROLES_INITIALIZED);
+
+ // Sensor Initialization
+ // All Master & Slave Sensor are initialized here, it is up to the
+ // rest of the firmware if it uses them or not.
+ sensor_init_all();
+ CHECKPOINT(SENSORS_INITIALIZED);
+
+ // SPIVID Initialization
+ // Must be done before Pstates
+ // @sb001 Removed SPIVID inits
+ // All SPIVID inits are done by Hostboot, remove this section.
+ //#if 0
+ // o2s_initialize();
+ // spivid_initialize(7);
+ //#endif
+
+ //@04a
+ //Initialize structures for collecting core data.
+ //It needs to run before RTLoop start as pore initialization needs to be
+ // done before task to collect core data starts.
+ proc_core_init();
+ CHECKPOINT(PROC_CORE_INITIALIZED);
+
+ // Run slave OCC init on all OCCs. Master-only initialization will be
+ // done after determining actual role. By default all OCCs are slave.
+ slave_occ_init(); // @th00b - Moved after proc core init
+ CHECKPOINT(SLAVE_OCC_INITIALIZED);
+
+#ifndef OCC_SIMICS_RESPONDER
+ // $pb007a - Initialize watchdog timers. This needs to be right before
+ // start rtl to make sure timer doesn't timeout. This timer is being
+ // reset from the rtl task.
+ // @sb002 Enable watchdog timers
+ TRAC_INFO("Initializing watchdog timers.");
+ initWatchdogTimers();
+ CHECKPOINT(WATCHDOG_INITIALIZED);
+
+ //@01a
+ // Initialize Real time Loop Timer Interrupt
+ rtl_ocb_init();
+ CHECKPOINT(RTL_TIMER_INITIALIZED);
+#else
+ TRAC_ERR("---------------------------------");
+ TRAC_ERR(" OCC Responder for Simics");
+ TRAC_ERR("---------------------------------");
+#endif
+
+ // Initialize semaphores and timer for handling thermal, health monitor and
+ // FFDC functions.
+ initMainThrdSemAndTimer();
+ CHECKPOINT(SEMS_AND_TIMERS_INITIALIZED);
+
+ //Initialize the Applet Manager @02a
+ // This needs to be done before initThreadScheduler because command line
+ // handler thread might start using applet as soon as it starts. Command
+ // line handler thread is started as part of the initThreadScheduler along
+ // with product and test applet thread.
+ initAppletManager();
+ CHECKPOINT(APPLETS_INITIALIZED);
+
+ //Initialize the thread scheduler.
+ //Other thread initialization is done here so that don't have to handle
+ // blocking commnad handler thread as FSP might start communicating
+ // through cmd handler thread in middle of the initialization.
+ initThreadScheduler();
+
+#ifdef FSPLESS_SIMICS
+ // In order to avoid having to run a ton of separate commands to each
+ // occ when we want to test in Simics w/o FSP, we can run with a FSPLESS
+ // config, using hardcoded default data from occ_sys_config.c
+ sysConfigFspLess();
+#endif
+
+ int l_ssxrc = SSX_OK;
+ // @sb022 initWatchdogTimers called before will start running the timer but
+ // the interrupt handler will just restart the timer until we use this
+ // enable switch to actually start the watchdog function.
+ ENABLE_WDOG;
+
+ while (TRUE)
+ {
+ // @sb022 Count each loop so the watchdog can tell the main thread is
+ // running.
+ G_mainThreadLoopCounter++;
+
+ // Wait for thermal semaphore
+ l_ssxrc = ssx_semaphore_pend(&G_thrmSem,SSX_WAIT_FOREVER);
+
+ if ( l_ssxrc != SSX_OK )
+ {
+ TRAC_ERR("thermal Semaphore pending failure RC[0x%08X]", -l_ssxrc );
+ }
+ else
+ {
+ // Call thermal routine that executes fan control
+ thrm_thread_main();
+ }
+
+ if( l_ssxrc == SSX_OK)
+ {
+ // Wait for health monitor semaphore
+ l_ssxrc = ssx_semaphore_pend(&G_hmonSem,SSX_WAIT_FOREVER);
+
+ if( l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("health monitor Semaphore pending failure RC[0x%08X]",
+ -l_ssxrc );
+ }
+ else
+ {
+ // call health monitor routine
+ hmon_routine();
+ }
+ }
+
+ if( l_ssxrc == SSX_OK)
+ {
+ // Wait for FFDC semaphore
+ l_ssxrc = ssx_semaphore_pend(&G_ffdcSem,SSX_WAIT_FOREVER);
+
+ if( l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("FFDC Semaphore pending failure RC[0x%08X]",-l_ssxrc );
+ }
+ else
+ {
+ // Only Master OCC will log call home data
+ if (OCC_MASTER == G_occ_role) // jh005c
+ {
+ chom_main();
+ }
+ }
+ }
+
+ if( l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid MAIN_THRD_ROUTINE_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 semaphore pending return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX semaphore related failure
+ */
+
+ errlHndl_t l_err = createErrl(MAIN_THRD_ROUTINE_MID, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ -l_ssxrc, //userdata1
+ 0); //userdata2
+
+ REQUEST_RESET(l_err); // @gm006
+ }
+ } // while loop
+}
+
+// Function Specification
+//
+// Name: main
+//
+// Description: Entry point of the OCC application
+//
+// Flow: 10/25/2011 FN= main
+//
+// End Function Specification
+int main(int argc, char **argv)
+{
+ int l_ssxrc;
+
+ // ----------------------------------------------------
+ // Initialize TLB for Linear Window access here so we
+ // can write checkpoints into the fsp response buffer.
+ // ----------------------------------------------------
+ l_ssxrc = ppc405_mmu_map(
+ CMDH_OCC_RESPONSE_BASE_ADDRESS, //
+ CMDH_OCC_RESPONSE_BASE_ADDRESS, //
+ CMDH_FSP_RSP_SIZE, //
+ 0, //
+ TLBLO_WR | TLBLO_I, //
+ NULL //
+ );
+ if(l_ssxrc != SSX_OK)
+ {
+ //failure means we can't talk to FSP.
+ SSX_PANIC(0x01000001);
+ }
+
+ l_ssxrc = ppc405_mmu_map(
+ CMDH_LINEAR_WINDOW_BASE_ADDRESS, //
+ CMDH_LINEAR_WINDOW_BASE_ADDRESS, //
+ CMDH_FSP_CMD_SIZE, //
+ 0, //
+ TLBLO_I, //
+ NULL //
+ );
+ if(l_ssxrc != SSX_OK)
+ {
+ //failure means we can't talk to FSP.
+ SSX_PANIC(0x01000002);
+ }
+
+ CHECKPOINT_INIT();
+ CHECKPOINT(MAIN_STARTED);
+
+ // Initialize stdout so we can do printf from within simics env
+#ifdef OCC_SIMICS_RESPONDER
+ simics_stdout_create(&G_simics_stdout);
+ simics_stderr_create(&G_simics_stderr);
+ stdout = (FILE *)(&G_simics_stdout);
+ stderr = (FILE *)(&G_simics_stderr);
+ ssxout = (FILE *)(&G_simics_stdout); // @tgh001 - Adding to enable printk
+#endif
+
+#ifdef GCOV_CODE_COVERAGE
+ extern void gcov_entry(); // @th029a
+ gcov_entry(); // @th029a
+#endif
+
+ // Initialize SSX Stacks
+ // NOTE: This also reinitializes the time base to 0
+
+ // >> @sb001
+ // Get proc_pb_frequency from HOMER host data and calculate the timebase
+ // frequency for the OCC. Pass the timebase frequency to ssx_initialize.
+ // The passed value must be in Hz. The occ 405 runs at 1/4 the proc
+ // frequency so the passed value is 1/4 of the proc_pb_frequency from the
+ // HOMER, ie. if the MRW says that proc_pb_frequency is 2400 MHz, then
+ // pass 600000000 (600MHz)
+ // The offset from the start of the HOMER is 0x00100000, we will need to
+ // create a temporary mapping to this section of the HOMER with ppc405_mmu_map
+ // (at address 0x00000000) read the value, convert it, and then unmap.
+ homer_rc_t l_homerrc = HOMER_SUCCESS;
+ uint32_t l_tb_freq_hz = 0;
+ l_homerrc = homer_hd_map_read_unmap(HOMER_NEST_FREQ,
+ &l_tb_freq_hz,
+ &l_ssxrc);
+
+ if ((HOMER_SUCCESS == l_homerrc) || (HOMER_SSX_UNMAP_ERR == l_homerrc))
+ {
+ // Data is in Mhz upon return and needs to be converted to Hz and then
+ // quartered.
+ l_tb_freq_hz = (l_tb_freq_hz * 1000000)/4;
+ }
+ else
+ {
+ // Default to 400MHz
+ l_tb_freq_hz = 400000000; // @wb002
+ }
+ // << @sb001
+
+ // Get OCC interrupt type from HOMER host data area. This will tell OCC
+ // which interrupt to Host it should be using.
+ uint32_t l_occ_int_type = 0;
+ l_homerrc = homer_hd_map_read_unmap(HOMER_INT_TYPE,
+ &l_occ_int_type,
+ &l_ssxrc);
+
+ if ((HOMER_SUCCESS == l_homerrc) || (HOMER_SSX_UNMAP_ERR == l_homerrc))
+ {
+ G_occ_interrupt_type = (uint8_t) l_occ_int_type;
+ }
+ else
+ {
+ G_occ_interrupt_type = 0x00;
+ }
+
+ CHECKPOINT(SSX_STARTING);
+
+ ssx_initialize((SsxAddress)G_noncritical_stack,
+ NONCRITICAL_STACK_SIZE,
+ (SsxAddress)G_critical_stack,
+ CRITICAL_STACK_SIZE,
+ 0,
+ l_tb_freq_hz); // @sb001
+
+ CHECKPOINT(SSX_INITIALIZED);
+
+ // TRAC_XXX needs ssx service, so they can only be called after ssx_initialize
+ TRAC_init_buffers(); // @at009a6
+
+ CHECKPOINT(TRACE_INITIALIZED);
+
+ TRAC_INFO("Inside OCC Main"); //@pb000a - added
+ // Trace what happened before ssx initialization
+ TRAC_INFO("HOMER accessed, rc=%d, nest_freq=%d, int_type=%d, ssx_rc=%d",
+ l_homerrc, l_tb_freq_hz, l_occ_int_type, l_ssxrc);
+
+ // >> @sb001
+ // Catch and log the homer error after inits are done
+ if (HOMER_SUCCESS != l_homerrc)
+ {
+ // We could potentially have both an internal error dealing with the
+ // homer and an SSX error, for example we could find an unsupported
+ // version number in the homer and then have an ssx error trying to
+ // unmap the homer address space. This in catches all those cases
+ if (SSX_OK != l_ssxrc)
+ {
+ /* @
+ * @errortype
+ * @moduleid MAIN_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 HOMER and SSX return codes
+ * @userdata2 Timebase frequency applied
+ * @userdata4 ERC_HOMER_MAIN_SSX_ERROR
+ * @devdesc An SSX error ocurred mapping the HOMER host data
+ * into the OCC address space. User word 1 contains
+ * both the internal and SSX return codes returned
+ * by the method used to access the HOMER data.
+ */
+ errlHndl_t l_err = createErrl(MAIN_MID, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ ERC_HOMER_MAIN_SSX_ERROR, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ (l_homerrc << 16) | (0xFFFF & (uint32_t)l_ssxrc), //userdata1
+ l_tb_freq_hz); //userdata2
+ commitErrl(&l_err);
+ }
+ else
+ {
+ /* @
+ * @errortype
+ * @moduleid MAIN_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 HOMER return code
+ * @userdata2 Default timebase frequency applied
+ * @userdata4 ERC_HOMER_MAIN_ACCESS_ERROR
+ * @devdesc Error accessing initialization data
+ */
+ errlHndl_t l_err = createErrl(MAIN_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_HOMER_MAIN_ACCESS_ERROR,//Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity // @wb001
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_homerrc, //userdata1
+ l_tb_freq_hz); //userdata2
+ commitErrl(&l_err);
+ }
+ }
+ // >> @sb001
+
+ // enable and register additional interrupt handlers
+ CHECKPOINT(INITIALIZING_IRQS);
+
+ occ_irq_setup(); //gm022
+
+ CHECKPOINT(IRQS_INITIALIZED);
+
+ // Create and resume main thread
+ int l_rc = createAndResumeThreadHelper(&Main_thread,
+ Main_thread_routine,
+ (void *)0,
+ (SsxAddress)main_thread_stack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_2);
+
+ if( SSX_OK != l_rc)
+ {
+ TRAC_ERR("Failure creating/resuming main thread: rc: 0x%x", -l_rc);
+
+ /* @
+ * @errortype
+ * @moduleid MAIN_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware internal error creating thread
+ */
+ errlHndl_t l_err = createErrl(MAIN_MID, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ -l_rc, //userdata1
+ 0); //userdata2
+ // Commit Error log
+ REQUEST_RESET(l_err); // @gm006
+ }
+
+ // Enter SSX Kernel
+ ssx_start_threads();
+
+ return 0;
+}
+
diff --git a/src/occ/mode.c b/src/occ/mode.c
new file mode 100755
index 0000000..19f8905
--- /dev/null
+++ b/src/occ/mode.c
@@ -0,0 +1,489 @@
+/******************************************************************************
+// @file mode.c
+// @brief OCC Modes
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section state.c STATE.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th011 thallet 07/12/2012 Created
+ * @th015 thallet 08/03/2012 Amec freq range set on mode change
+ * @th022 thallet 10/03/2012 State/mode set by master occ
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @gs008 894661 gjsilva 08/08/2013 Initial support for DPS-FP mode
+ * @gs010 899888 gjsilva 09/24/2013 Process data format 0x13 from TMGT
+ * @gs011 900661 gjsilva 09/30/2013 Make data format 0x13 required to go active
+ * @at019 908390 alvinwan 12/05/2013 Disable DPS algorithms from running in Sapphire
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <common_types.h>
+#include "ssx_io.h"
+#include "trac.h"
+#include "rtls.h"
+#include "state.h"
+#include "occ_service_codes.h"
+#include "amec_freq.h"
+#include "amec_part.h"
+#include "amec_data.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Forward Declarations
+//*************************************************************************
+errlHndl_t SMGR_mode_transition_to_nominal();
+errlHndl_t SMGR_mode_transition_to_powersave();
+errlHndl_t SMGR_mode_transition_to_dynpowersave();
+errlHndl_t SMGR_mode_transition_to_dynpowersave_fp();
+errlHndl_t SMGR_mode_transition_to_turbo();
+errlHndl_t SMGR_mode_transition_to_superturbo();
+errlHndl_t SMGR_mode_transition_to_ffo();
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Mode that OCC is currently in
+OCC_MODE G_occ_internal_mode = OCC_MODE_NOCHANGE; // @th040
+
+// Mode that OCC is requesting that TMGT put OCC into
+OCC_MODE G_occ_internal_req_mode = OCC_MODE_NOCHANGE;
+
+// Mode that TMGT is requesting OCC go to
+OCC_MODE G_occ_external_req_mode = OCC_MODE_NOCHANGE;
+
+// Mode that TMGT is requesting OCC go to in KVM
+OCC_MODE G_occ_external_req_mode_kvm = OCC_MODE_NOCHANGE; // @at019a
+
+// Indicates if OCC must actually change the voltage / frequency during
+// a mode change.
+SMGR_SMS_CMD_TYPE G_occ_internal_sms = SMGR_SMS_VF_INFO_ONLY;
+
+// Indicates if we are currently in a mode transition
+bool G_mode_transition_occuring = FALSE;
+
+// Mode that OCC Master is in
+OCC_MODE G_occ_master_mode = OCC_MODE_NOCHANGE;
+
+// Semaphore to allow mode change to be called from multiple threads
+SsxSemaphore G_smgrModeChangeSem;
+
+
+// Table that indicates which functions should be run for a given mode
+// transition.
+const smgr_state_trans_t G_smgr_mode_trans[] =
+{
+ /* ----- SPECIFIC CASE MODE TRANSITIONS ----- */
+ /* These are specific mode transitions for when it matters what
+ * mode we were in before the transition. These must come before
+ * the agnostic mode transitions below, and will be run instead of
+ * those catch-all transition functions. */
+
+ /* Current Mode New Mode Transition Function */
+ {OCC_MODE_STURBO, OCC_MODE_NOMINAL, NULL},
+
+ /* ----- DEFAULT MODE TRANSITIONS ----- */
+ /* These are default mode transitions for when it doesn't matter what
+ * mode we were in before the transition. */
+
+ /* Current Mode New Mode Transition Function */
+ {OCC_MODE_ALL, OCC_MODE_NOMINAL, &SMGR_mode_transition_to_nominal},
+ {OCC_MODE_ALL, OCC_MODE_PWRSAVE, &SMGR_mode_transition_to_powersave},
+ {OCC_MODE_ALL, OCC_MODE_DYN_POWER_SAVE, &SMGR_mode_transition_to_dynpowersave},
+ {OCC_MODE_ALL, OCC_MODE_DYN_POWER_SAVE_FP, &SMGR_mode_transition_to_dynpowersave_fp},
+ {OCC_MODE_ALL, OCC_MODE_TURBO, &SMGR_mode_transition_to_turbo},
+ {OCC_MODE_ALL, OCC_MODE_STURBO, &SMGR_mode_transition_to_superturbo},
+ {OCC_MODE_ALL, OCC_MODE_FFO, &SMGR_mode_transition_to_ffo},
+};
+const uint8_t G_smgr_mode_trans_count = sizeof(G_smgr_mode_trans)/sizeof(smgr_state_trans_t);
+
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: SMGR_is_mode_transitioning
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+inline bool SMGR_is_mode_transitioning(void)
+{
+ return G_mode_transition_occuring;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_get_mode
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+inline OCC_MODE SMGR_get_mode(void)
+{
+ return G_occ_internal_mode;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_set_mode
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_set_mode(const OCC_MODE i_mode,
+ const uint8_t i_sms_type)
+{
+ errlHndl_t l_errlHndl = NULL;
+ int jj=0;
+ OCC_MODE l_mode = i_mode;
+
+ do
+ {
+ // Get lock for critical section
+ if(ssx_semaphore_pend(&G_smgrModeChangeSem,SSX_WAIT_FOREVER))
+ {
+ /* @
+ * @errortype
+ * @moduleid MAIN_MODE_TRANSITION_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 none
+ * @userdata4 ERC_RUNNING_SEM_PENDING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ l_errlHndl = createErrl(MAIN_MODE_TRANSITION_MID, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ ERC_RUNNING_SEM_PENDING_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ break;
+ } // @th022
+
+ //Check to see if we need to make a change
+ if(l_mode == OCC_MODE_NOCHANGE)
+ {
+ break;
+ }
+
+ // @at019 - start
+ // SAPPHIRE only accepts DPS-FE mode. In case OCC gets other modes, it should accept the request
+ // and keep reporting back that it is in that mode. However, internally we should not
+ // initiate any mode transition, i.e., OCC should remain internally in DPS-FE mode.
+ if(G_sysConfigData.system_type.kvm)
+ {
+ G_occ_external_req_mode_kvm = l_mode;
+ if (l_mode != OCC_MODE_DYN_POWER_SAVE)
+ {
+ TRAC_ERR("SAPPHIRE only accepts DPS-FE mode(6) but requested mode is : %d", l_mode);
+ l_mode = OCC_MODE_DYN_POWER_SAVE;
+ }
+ }
+ // @at019 - start
+
+ switch (l_mode)
+ {
+ case OCC_MODE_NOMINAL: // FALL THROUGH
+ case OCC_MODE_PWRSAVE: // FALL THROUGH
+ case OCC_MODE_DYN_POWER_SAVE: // FALL THROUGH
+ case OCC_MODE_DYN_POWER_SAVE_FP: // FALL THROUGH
+ case OCC_MODE_TURBO: // FALL THROUGH
+ case OCC_MODE_STURBO: // FALL THROUGH
+ case OCC_MODE_FFO: // FALL THROUGH
+ // Notify AMEC of mode change
+
+ // Change Mode via Transition Function
+ do
+ {
+ // Loop through mode transition table, and find the state
+ // transition function that matches the transition we need to do.
+ for(jj=0; jj<G_smgr_mode_trans_count; jj++)
+ {
+ if( ((G_smgr_mode_trans[jj].old_state == G_occ_internal_mode)
+ || (G_smgr_mode_trans[jj].old_state == OCC_MODE_ALL) )
+ && (G_smgr_mode_trans[jj].new_state == l_mode) )
+ {
+ // We found the transtion that matches, now run the function
+ // that is associated with that state transition.
+ if(NULL != G_smgr_mode_trans[jj].trans_func_ptr)
+ {
+ // Signal that we are now in a mode transition
+ G_mode_transition_occuring = TRUE;
+ // Run transition function
+ l_errlHndl = (G_smgr_mode_trans[jj].trans_func_ptr)();
+ // Signal that we are done with the transition
+ G_mode_transition_occuring = FALSE;
+ break;
+ }
+ }
+ }
+
+ // Check if we hit the end of the table without finding a valid
+ // mode transition. If we did, log an internal error.
+ if(G_smgr_mode_trans_count == jj)
+ {
+ TRAC_ERR("No transition (or NULL) found for the mode change\n");
+ l_errlHndl = NULL; //TODO: Create Error
+ break;
+ }
+
+ // Update the power mode for all core groups that are following system mode
+ AMEC_part_update_sysmode_policy(CURRENT_MODE());
+ }
+ while(0);
+
+ break;
+ default:
+ //unsupported mode
+ break;
+ }
+
+ if(l_errlHndl)
+ {
+ // Punt !!! :-)
+ break;
+ }
+
+ // Load correct thermal thresholds based on the current mode
+ l_errlHndl = AMEC_data_write_thrm_thresholds(CURRENT_MODE());
+
+ // Update the CPU speed in AME?
+ // Register the New Mode?
+ // Update Power Policy Requirements?
+ // Update CPM Calibration
+
+ }while(0);
+
+ // If we have a mode change failure, Mode change flag needs to be set,
+ // otherwise, it needs be be cleared/unset.
+ if(l_errlHndl)
+ {
+
+ }
+
+ // Unlock critical section
+ ssx_semaphore_post(&G_smgrModeChangeSem); // @th022
+
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_mode_transition_to_nominal()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Mode to Nominal Transition Started");
+
+ // Set Freq Mode for AMEC to use
+ l_errlHndl = amec_set_freq_range(OCC_MODE_NOMINAL); // @th015
+
+ CURRENT_MODE() = OCC_MODE_NOMINAL;
+ TRAC_IMP("SMGR: Mode to Nominal Transition Completed");
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_mode_transition_to_powersave()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Mode to PowerSave Transition Started");
+
+ // Set Freq Mode for AMEC to use
+ l_errlHndl = amec_set_freq_range(OCC_MODE_PWRSAVE); // @th015
+
+ CURRENT_MODE() = OCC_MODE_PWRSAVE;
+ TRAC_IMP("SMGR: Mode to PowerSave Transition Completed");
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_mode_transition_to_dynpowersave()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Mode to Dynamic PowerSave-Favor Energy Transition Started");
+
+ // Set Freq Mode for AMEC to use
+ l_errlHndl = amec_set_freq_range(OCC_MODE_DYN_POWER_SAVE); // @th015
+
+ CURRENT_MODE() = OCC_MODE_DYN_POWER_SAVE;
+ TRAC_IMP("SMGR: Mode to Dynamic PowerSave-Favor Energy Transition Completed");
+
+ return l_errlHndl;
+}
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_mode_transition_to_dynpowersave_fp()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Mode to Dynamic PowerSave-Favor Performance Transition Started");
+
+ // Set Freq Mode for AMEC to use
+ l_errlHndl = amec_set_freq_range(OCC_MODE_DYN_POWER_SAVE_FP);
+
+ CURRENT_MODE() = OCC_MODE_DYN_POWER_SAVE_FP;
+ TRAC_IMP("SMGR: Mode to Dynamic PowerSave-Favor Performance Transition Completed");
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_mode_transition_to_turbo()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Mode to Turbo Transition Started");
+
+ // Set Freq Mode for AMEC to use
+ l_errlHndl = amec_set_freq_range(OCC_MODE_TURBO); // @th015
+
+ CURRENT_MODE() = OCC_MODE_TURBO;
+ TRAC_IMP("SMGR: Mode to Turbo Transition Completed");
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_mode_transition_to_superturbo()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Mode to SuperTurbo Transition Started");
+
+ // Set Freq Mode for AMEC to use
+ l_errlHndl = amec_set_freq_range(OCC_MODE_STURBO); // @th015
+
+ CURRENT_MODE() = OCC_MODE_STURBO;
+ TRAC_IMP("SMGR: Mode to SuperTurbo Transition Completed");
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_mode_transition_to_ffo()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Mode to FFO Transition Started");
+
+ // Set Freq Mode for AMEC to use
+ l_errlHndl = amec_set_freq_range(OCC_MODE_FFO); // @th015
+
+ CURRENT_MODE() = OCC_MODE_FFO;
+ TRAC_IMP("SMGR: Mode to FFO Transition Completed");
+
+ return l_errlHndl;
+}
+
diff --git a/src/occ/mode.h b/src/occ/mode.h
new file mode 100755
index 0000000..d85c8ed
--- /dev/null
+++ b/src/occ/mode.h
@@ -0,0 +1,133 @@
+/******************************************************************************
+// @file mode.h
+// @brief OCC Modes
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section state.h STATE.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th011 thallet 07/13/2011 New file
+ * @th015 thallet 08/03/2012 Added 2 macros
+ * @th022 thallet 10/03/2012 Dcom State/Mode changes
+ * @th036 881677 thallet 05/06/2013 Support for new Poll Command
+ * @jh004 889884 joshych 07/24/2013 Support CPM param and updated frequency packet
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @at019 908390 alvinwan 12/05/2013 Disable DPS algorithms from running in Sapphire
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef _mode_h
+#define _mode_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <common_types.h>
+#include "rtls.h"
+#include "errl.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+// Returns the current OCC Mode
+#define CURRENT_MODE() G_occ_internal_mode
+
+// Returns the 'OCC Requested' OCC Mode
+#define REQUESTED_MODE() G_occ_internal_req_mode
+
+// Returns the 'Requested' SMS Mode
+#define CURRENT_SMS() G_occ_internal_sms
+
+// Returns the 'Requested' SMS Mode
+#define VALID_MODE(mode) ((mode < OCC_MODE_COUNT) ? 1 : 0)
+
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+/**
+ * @enum OCC_MODE
+ * @brief Typedef of the various modes that TMGT can put OCC into.
+ */
+typedef enum
+{
+ OCC_MODE_NOCHANGE = 0x00,
+ OCC_MODE_NOMINAL = 0x01,
+ // OCC_MODE_BENCHMARK = 0x02,
+ OCC_MODE_TURBO = 0x03,
+ OCC_MODE_SAFE = 0x04,
+ OCC_MODE_PWRSAVE = 0x05,
+ OCC_MODE_DYN_POWER_SAVE = 0x06,
+ OCC_MODE_MIN_FREQUENCY = 0x07,
+
+ // Mode 0x08-0x0A reserved by TMGT
+ // OCC_MODE_SAFE_LOW_POWER = 0x09,
+ OCC_MODE_DYN_POWER_SAVE_FP = 0x0A,
+ OCC_MODE_FFO = 0x0B,
+ OCC_MODE_STURBO = 0x0C,
+
+ // Make sure this is after the last valid mode
+ OCC_MODE_COUNT,
+
+ // These are used for mode transition table, and are not
+ // a valid mode in and of itself.
+ OCC_MODE_ALL = 0xFE,
+ OCC_MODE_INVALID = 0xFF,
+} OCC_MODE;
+
+/**
+ * @enum OCC_INTERNAL_MODE
+ * @brief Typedef of the various internal modes that OCC can be in.
+ */
+typedef enum
+{
+ OCC_INTERNAL_MODE_NOM = 0x00,
+ OCC_INTERNAL_MODE_SPS = 0x01,
+ OCC_INTERNAL_MODE_DPS = 0x02,
+ OCC_INTERNAL_MODE_DPS_MP = 0x03,
+ OCC_INTERNAL_MODE_FFO = 0x04,
+ OCC_INTERNAL_MODE_MAX_NUM,
+ OCC_INTERNAL_MODE_UNDEFINED = 0xFF
+} OCC_INTERNAL_MODE;
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+extern OCC_MODE G_occ_internal_mode;
+extern OCC_MODE G_occ_internal_req_mode;
+extern OCC_MODE G_occ_external_req_mode; // @th022
+extern OCC_MODE G_occ_external_req_mode_kvm; // @at019a
+extern OCC_MODE G_occ_master_mode; // @th022
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Returns true if we are in the middle of a mode transition
+inline bool SMGR_is_mode_transitioning(void);
+
+// Used to get the OCC Mode
+inline OCC_MODE SMGR_get_mode(void);
+
+// Used to set OCC Mode
+errlHndl_t SMGR_set_mode(const OCC_MODE i_mode,
+ const uint8_t i_sms_type);
+
+
+
+
+
+#endif
diff --git a/src/occ/occLinkInputFile b/src/occ/occLinkInputFile
new file mode 100644
index 0000000..45e23ef
--- /dev/null
+++ b/src/occ/occLinkInputFile
@@ -0,0 +1 @@
+INPUT ( amec_init.o amec_tasks.o amec_slave_smh.o amec_master_smh.o amec_sensors_core.o amec_sensors_centaur.o amec_sensors_power.o amec_sensors_fw.o amec_data.o amec_freq.o amec_amester.o amec_dps.o amec_part.o amec_perfcount.o amec_controller.o amec_oversub.o amec_pcap.o amec_health.o amec_parm.o amec_parm_table.o amec_analytics.o appletManager.o centaur_data.o centaur_control.o cmdh_fsp.o cmdh_thread.o cmdh_fsp_cmds.o cmdh_fsp_cmds_datacnfg.o cmdh_mnfg_intf.o cmdh_tunable_parms.o cmdh_snapshot.o ffdc.o dcom.o dcom_thread.o dcomSlaveTx.o dcomSlaveRx.o dcomMasterTx.o dcomMasterRx.o errl.o proc_data.o proc_data_control.o proc_pstate.o apss.o dpss.o rtls_tables.o rtls.o sensor.o sensor_table.o threadSch.o chom.o thrm_thread.o timer.o trac_interface.o occ_sys_config.o arl_test.o state.o reset.o mode.o main.o scom.o homer.o occbuildname.o ll_ffdc.o ssx_core.o ssx_init.o ssx_stack_init.o ssx_timer_core.o ssx_timer_init.o ssx_thread_init.o ssx_thread_core.o ssx_semaphore_init.o ssx_semaphore_core.o pgp_init.o pgp_irq_init.o pgp_pmc.o pgp_ocb.o pgp_pba.o pgp_id.o pgp_centaur.o pgp_cache.o pgp_async.o pgp_async_pore.o pgp_async_ocb.o pgp_async_pba.o ppc405_core.o ppc405_lib_core.o ppc405_cache_core.o ppc405_init.o ppc405_irq_core.o ppc405_irq_init.o ppc405_boot.o ppc405_exceptions.o ppc405_cache_init.o ppc405_mmu_asm.o ppc405_breakpoint.o ppc405_thread_init.o ppc405_mmu.o )
diff --git a/src/occ/occ_service_codes.h b/src/occ/occ_service_codes.h
new file mode 100755
index 0000000..e386e03
--- /dev/null
+++ b/src/occ/occ_service_codes.h
@@ -0,0 +1,303 @@
+/******************************************************************************
+// @file occ_service_codes.h
+// @brief Error codes for OCC.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _occ_service_codes_h occ_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 06/16/2010 Port
+ * @01 nguyenp 08/18/2011 Added new OCC reason code
+ * pbavari 08/16/2011 Added new reason code
+ * @02 tapiar 08/06/2011 New failure reason code
+ * @pb007 pbavari 09/27/2011 Added timer reasonCode and moduleid
+ * @03 abagepa 09/06/2011 new dcom failure reason codes
+ * @04 nguyenp 10/10/2011 New proc failure reason code
+ * @05 tapiar 11/17/2011 new dcom failure reason codes
+ * @pb009 pbavari 10/20/2011 Main thread support
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th010 thallet 07/14/2012 Added ERCs
+ * @ai002 ailutsar 07/24/2012 Fix data tlb miss in startApplet
+ * @th022 thallet 10/10/2012 Added Module IDs for State & Mode changes
+ * @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @th033 thallet 04/17/2013 Mnfg AVP Support
+ * @fk001 879727 fmkassem 04/16/2013 PCAP support.
+ * @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
+ * @db001 897459 deepthib 08/03/2013 AMEC pcap failure, mismatch changes
+ * @rt001 897459 tapiar 08/20/2013 AMEC Slave Performance Check
+ * @rt002 901927 tapiar 10/02/2013 Fix Extended Refcodes
+ * @gs012 903325 gjsilva 10/18/2013 Log Processor OT errors
+ * @gm011 903410 milesg 10/22/2013 Fail on murano dd10 or dd11 chips
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @rt003 905677 tapiar 11/07/2013 Match over pcap reason code to P7 value
+ * @sb000 905504 sbroyles 11/06/2013 New extrefs for HOMER error.
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @jh009 908383 joshych 12/04/2013 Generate error logs when required for Reset Prep command
+ * @gm015 907601 milesg 12/06/2013 L4 Bank Delete circumvention and centaur i2c recovery
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @at020 908666 alvinwan 12/16/2013 Oversubscription Error Handling
+ * @at021 910861 alvinwan 01/08/2014 Change SRCs back to original values
+ * @jh00b 910184 joshych 01/10/2014 Add check for checkstop
+ * @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+ * @gm022 908890 milesg 01/23/2014 Halt OCC on OCCLFIR[38]
+ * @fk005 911760 fmkassem 01/20/2014 APSS retry support.
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @fk006 914801 fmkassem 02/05/2014 Modify reasoncode list
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ * @sb055 911966 sbroyles 02/27/2014 Enable PBCS heartbeat
+ * @gm031 916489 milesg 03/07/2014 Additional handling for OISR0[2] and OISR0[9]
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @wb003 920760 wilbryan 03/24/2014 Update SRCs to match TPMD SRCs
+ * @gm033 920448 milesg 03/26/2014 use getscom/putscom ffdc wrapper
+ * @sbpde 922027 sbroyles 04/04/2014 Add error check to GPE proc data
+ * collection.
+ * @gm036 917550 milesg 04/09/2014 Ignore phantom interrupts (log info error)
+ * @wb004 922138 wilbryan 04/07/2014 Ensure timely pstate completion
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ * @gm041 928150 milesg 06/02/2014 log error in mfg if centaur lfir[6] bit is set
+ * @gs041 942203 gjsilva 10/17/2014 Support for HTMGT/BMC interface
+ * @gs042 942940 gjsilva 10/24/2014 Support for data packets in BMC-based systems
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _OCC_SERVICE_CODES_H_
+#define _OCC_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum occReasonCode // @nh001c @fk006c
+{
+ /// Generic OCC firmware error log with extended srcs.
+ INTERNAL_FAILURE = 0x00,
+ /// Informational periodic call home log
+ GEN_CALLHOME_LOG = 0x01,
+ /// Failure within the OCC Complex of the processor
+ PREP_FOR_RESET = 0x02, // @jh009a
+ /// Invalid Input Data received from FSP
+ INVALID_INPUT_DATA = 0x03, // @wb003
+ /// Oversubscription was asserted
+ OVERSUB_ALERT = 0x05, // @at020a
+ /// Failure to maintain a hard power cap
+ POWER_CAP_FAILURE = 0x06, // @wb003
+ /// Failsafe State
+ FAILSAFE_ALERT = 0x07, // @wb001
+ /// Fans are in full speed
+ FAN_FULL_SPEED = 0x08, // @at023a
+ /// Timed out reading a FRU temperature
+ FRU_TEMP_TIMEOUT = 0x09,
+ /// Processor reached error threshold
+ PROC_ERROR_TEMP = 0x10,
+ /// Timed out reading processor temperature
+ PROC_TEMP_TIMEOUT = 0x11,
+ /// @wb003 -- Removed PROCESSOR_NOT_SUPPORTED and changed error to INTERNAL_FAILURE
+ /// Processor SCOM failure -- gm025
+ PROC_SCOM_ERROR = 0x16,
+ /// Any failure coming from the SSX RTOS code
+ SSX_GENERIC_FAILURE = 0x17, // @wb003
+ /// Failure to handshake with an external fw entity (HB, FSP, PHYP, etc)
+ EXTERNAL_INTERFACE_FAILURE = 0x18, // @wb003
+ /// VRM reached error threshold (VR_HOT asserted)
+ VRM_ERROR_TEMP = 0x20,
+ /// Timed out reading VR_FAN signal from VRM
+ VRM_VRFAN_TIMEOUT = 0x21,
+ /// VR_FAN signal from VRM has been asserted
+ VRM_VRFAN_ASSERTED = 0x22,
+ /// DIMM reached error threshold
+ DIMM_ERROR_TEMP = 0x30,
+ /// Frequency limited due to oversubscription condition
+ OVERSUB_LIMIT_ALERT = 0x33, // SRC the same with TPMD // @at020a
+ /// Centaur reached error threshold
+ CENT_ERROR_TEMP = 0x40,
+ /// Centaur in-band scom failure
+ CENT_SCOM_ERROR = 0x41,
+ /// Centaur FIR bit set
+ CENT_LFIR_ERROR = 0x42, //gm041
+ /// Throttle in nominal or turbo mode due to the bulk power limit being reached with both power supplies good @rt003a
+ PCAP_THROTTLE_POWER_LIMIT = 0x61,
+ /// Failure within the OCC Complex of the processor
+ INTERNAL_HW_FAILURE = 0xB0, //@01a @jh009c
+ /// OCC GPE halted due to checkstop
+ OCC_GPE_HALTED = 0xB1, // @jh00ba
+ /// PMC Failure
+ PMC_FAILURE = 0xB2, // gm031
+ /// Data passed as an argument or returned from a function is invalid
+ INTERNAL_INVALID_INPUT_DATA = 0xB3, // @wb003
+ /// A core was not at the expected frequency
+ TARGET_FREQ_FAILURE = 0xB4, // @wb004
+ /// Request to read APSS data failed.
+ APSS_GPE_FAILURE = 0xC0, // @fk005a
+ /// Connector overcurrent pin still asserted.
+ CONNECTOR_OC_PINS_WARNING = 0xC1, // @wb001
+ CONNECTOR_OC_PINS_FAILURE = 0xC2, // @wb001
+ /// Request to read redundant APSS data failed -- gm037
+ REDUNDANT_APSS_GPE_FAILURE = 0xCB,
+ /// Success!
+ OCC_SUCCESS_REASON_CODE = 0xFF,
+};
+
+
+enum occExtReasonCode // @nh001a
+{
+ OCC_NO_EXTENDED_RC = 0x00000000,
+
+ ERC_GENERIC_TIMEOUT = 0x00000001,
+ ERC_INVALID_INPUT_DATA = 0x00000002,
+ ERC_MMU_MAP_FAILURE = 0x00000003,
+ ERC_MMU_UNMAP_FAILURE = 0x00000004,
+ ERC_BCE_REQUEST_CREATE_FAILURE = 0x00000005,
+ ERC_BCE_REQUEST_SCHEDULE_FAILURE = 0x00000006,
+
+ ERC_RUNNING_SEM_PENDING_FAILURE = 0x00000007,
+ ERC_RUNNING_SEM_POSTING_FAILURE = 0x00000008,
+ ERC_WAKEUP_SEM_PENDING_FAILURE = 0x00000009,
+ ERC_WAKEUP_SEM_POSTING_FAILURE = 0x0000000a,
+ ERC_FINISHED_SEM_PENDING_FAILURE = 0x0000000b,
+ ERC_FINISHED_SEM_POSTING_FAILURE = 0x0000000c,
+ ERC_CALLER_SEM_POSTING_FAILURE = 0x0000000d,
+ ERC_CREATE_SEM_FAILURE = 0x0000000e,
+
+ ERC_LOW_CORE_PORE_FLEX_CREATE_FAILURE = 0x0000000f,
+ ERC_HIGH_CORE_PORE_FLEX_CREATE_FAILURE = 0x00000010,
+ ERC_FAST_CORE_PORE_FLEX_CREATE_FAILURE = 0x00000011,
+
+ ERC_SSX_IRQ_SETUP_FAILURE = 0x00000012,
+ ERC_SSX_IRQ_HANDLER_SET_FAILURE = 0x00000013,
+ ERC_PPC405_WD_SETUP_FAILURE = 0x00000014,
+ ERC_OCB_WD_SETUP_FAILURE = 0x00000015,
+ ERC_ARG_POINTER_FAILURE = 0x00000016,
+
+ ERC_PSS_GPIO_INIT_FAIL = 0x00000017,
+ ERC_PSS_COMPOSITE_MODE_FAIL = 0x00000019,
+
+ ERC_PROC_CONTROL_TASK_FAILURE = 0x0000001a, // @th010
+
+ ERC_MMU_MAP_APPLET_READ_FAILURE = 0x0000001b, // @ai002
+ ERC_MMU_MAP_APPLET_WRITE_FAILURE = 0x0000001c, // @ai002
+ ERC_MMU_MAP_APPLET_OVERWRITE_FAILURE = 0x0000001d, // @ai002
+ ERC_MMU_UNMAP_APPLET_READ_FAILURE = 0x0000001e, // @ai002
+ ERC_MMU_UNMAP_APPLET_WRITE_FAILURE = 0x0000001f, // @ai002
+ ERC_MMU_UNMAP_APPLET_OVERWRITE_FAILURE = 0x00000020, // @ai002
+
+ ERC_CENTAUR_PORE_FLEX_CREATE_FAILURE = 0x00000021, // @th031
+ ERC_CENTAUR_PORE_FLEX_SCHEDULE_FAILURE = 0x00000022, // @
+ ERC_CENTAUR_INTERNAL_FAILURE = 0x00000023, // @
+
+ ERC_APSS_GPIO_OUT_OF_RANGE_FAILURE = 0x00000024, // @at014
+ ERC_APSS_GPIO_DUPLICATED_FAILURE = 0x00000025, // @at014
+ ERC_APSS_ADC_OUT_OF_RANGE_FAILURE = 0x00000026, // @at014
+ ERC_APSS_ADC_DUPLICATED_FAILURE = 0x00000027, // @at014
+
+ ERC_STATE_FROM_OBS_TO_STB_FAILURE = 0x00000028, // @at015
+ ERC_STATE_FROM_STB_TO_OBS_FAILURE = 0x00000029, // @at015
+ ERC_STATE_HEARTBEAT_CFG_FAILURE = 0x00000080, // @sb055
+
+ ERC_AMEC_PCAPS_MISMATCH_FAILURE = 0x0000002A, // @db001a
+ ERC_AMEC_UNDER_PCAP_FAILURE = 0x0000002B, // @db001a
+
+ ERC_AMEC_SLAVE_FAILSAFE_STATE = 0x0000002C, // @rt001a
+ ERC_AMEC_SLAVE_OVS_STATE = 0x0000002D, // @rt001a
+ ERC_AMEC_SLAVE_POWERCAP = 0x0000002E, // @rt001a
+
+ ERC_AMEC_PROC_ERROR_OVER_TEMPERATURE = 0x0000002F, // @gs012a
+
+ ERC_APLT_INIT_FAILURE = 0x00000030, //
+ ERC_APLT_START_VERSION_MISMATCH = 0x00000031, //
+ ERC_APLT_START_CHECKSUM_MISMATCH = 0x00000032, //
+
+ ERC_CMDH_MBOX_REQST_FAILURE = 0x00000040, //
+ ERC_CMDH_INTERNAL_FAILURE = 0x00000041, //
+ ERC_CMDH_THRM_DATA_MISSING = 0x00000042, //
+ ERC_CMDH_IPS_DATA_MISSING = 0x00000043,
+ ERC_CMDH_INVALID_ATTN_DATA = 0x00000044, // @gs041
+
+ ERC_CHIP_IDS_INVALID = 0x00000050,
+ ERC_GETSCOM_FAILURE = 0x00000051,
+
+ ERC_HOMER_MAIN_ACCESS_ERROR = 0x00000060, // @sb000
+ ERC_HOMER_MAIN_SSX_ERROR = 0x00000061, // @sb000
+
+ ERC_APSS_SCHEDULE_FAILURE = 0x00000062, // @fk005a
+ ERC_APSS_COMPLETE_FAILURE = 0x00000063, // @fk005a
+
+ ERC_PROC_CONTROL_INIT_FAILURE = 0x00000064, // @wb003 - Changed because it was previously a duplicate
+ ERC_PROC_PSTATE_INSTALL_FAILURE = 0x00000065, // @wb003
+ ERC_PROC_CORE_DATA_EMPATH_ERROR = 0x00000066, // @sbpde
+
+ ERC_BCE_REQ_CREATE_READ_FAILURE = 0x00000070,
+ ERC_BCE_REQ_SCHED_READ_FAILURE = 0x00000071,
+ ERC_BCE_REQ_CREATE_INPROG_FAILURE = 0x00000072,
+ ERC_BCE_REQ_SCHED_INPROG_FAILURE = 0x00000073,
+ ERC_BCE_REQ_CREATE_WRITE_FAILURE = 0x00000074,
+ ERC_BCE_REQ_SCHED_WRITE_FAILURE = 0x00000075,
+};
+
+
+enum occModuleId
+{
+ MAIN_MID = MAIN_COMP_ID | 0x01,
+ MAIN_THRD_ROUTINE_MID = MAIN_COMP_ID | 0x02,
+ MAIN_THRD_TIMER_MID = MAIN_COMP_ID | 0x03,
+ MAIN_THRD_SEM_INIT_MID = MAIN_COMP_ID | 0x04,
+ MAIN_STATE_TRANSITION_MID = MAIN_COMP_ID | 0x05, // @th022
+ MAIN_MODE_TRANSITION_MID = MAIN_COMP_ID | 0x06, // @th022
+ MAIN_GPE_HALTED_MID = MAIN_COMP_ID | 0x07, // @jh00ba
+ OCC_IRQ_SETUP = MAIN_COMP_ID | 0x08, // @gm022
+ PMC_HW_ERROR_ISR = MAIN_COMP_ID | 0x09, // @gm031
+ GETSCOM_FFDC_MID = MAIN_COMP_ID | 0x0a,
+ PUTSCOM_FFDC_MID = MAIN_COMP_ID | 0x0b,
+ HMON_ROUTINE_MID = MAIN_COMP_ID | 0x0c, // @gm036
+ AMEC_VERIFY_FREQ_MID = MAIN_COMP_ID | 0x0d, // @wb004
+};
+
+enum occUserDataType
+{
+ OCC_FULL_ELOG_TYPE = 0x0000, // complete error log data
+
+};
+
+enum occUserDataVersion
+{
+ OCC_FULL_ELOG_TYPE_VER1 = 0x0001, // complete error log data ver 1
+};
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _OCC_SERVICE_CODES_H_ */
diff --git a/src/occ/occ_sys_config.c b/src/occ/occ_sys_config.c
new file mode 100755
index 0000000..091ebad
--- /dev/null
+++ b/src/occ/occ_sys_config.c
@@ -0,0 +1,516 @@
+/******************************************************************************
+// @file occ_sys_config.c
+// @brief OCC System Configuration Variable Declaration & Initialization
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section occ_sys_config.c OCC_SYS_CONFIG.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th000 thallet 09/14/2011 Added SysConfig Initialization
+ * @rc002 rickylie 02/02/2012 Remove unused DPSS function
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/29/2012 Changed APSS ADC config to match spec
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th014 thallet 08/02/2012 Moved default PstateSS occ_sys_config
+ * @th019 853007 thallet 09/12/2012 Power Sensors
+ * @th022 thallet 10/03/2012 Dcom State/Mode changes
+ * @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+ * @th034 879027 thallet 04/18/2013 Broadcast critical power over PBAX
+ * @at013 878755 alvinwan 04/17/2013 OCC power capping implementation
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup
+ * @th035 881654 thallet 05/06/2013 Tuleta Bringup Pstate Fixes
+ * @at014 882077 alvinwan 05/09/2013 Support APSS and System Config data from TMGT
+ * @ly007 882183 lychen 05/21/2013 Send APSS and System Configuration commands to OCC
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @fk001 879727 fmkassem 04/16/2013 OCC powercap support.
+ * @th041 887658 thallet 06/17/2013 OCC default FFO Freq should be 0
+ * @jh004 889884 joshych 07/24/2013 Support CPM param and updated frequency packet
+ * @ly008 894646 lychen 08/08/2013 Fix bugs in OCC handling of APSS tables for Brazos/Orlena
+ * @gm012 905097 milesg 10/31/2013 support mem throttle & mem config packets
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <common_types.h>
+#include <occ_sys_config.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// -----------------------------------------------------------
+// SysConfig Section Defines
+// -----------------------------------------------------------
+#define SYSCFG_DEFAULT_VERSION 0xff
+
+// -----------------------------------------------------------
+// APSS Section Defines
+// -----------------------------------------------------------
+#define SYSCFG_ADC_1x_MULT 1000
+
+// @rc002 - Remove unused DPSS Section Defines
+
+// -----------------------------------------------------------
+// Master/Slave Section Defines
+// -----------------------------------------------------------
+#define SYSCFG_MASTER_CAPABLE_000 0x01
+#define SYSCFG_DEFAULT_MASTER_000 0x00
+#define SYSCFG_ALL_OCCS_PRESENT 0xff
+#define SYSCFG_ZERO_OCCS_PRESENT 0x00
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// OCC System Configuration Data
+//
+// We will initialize everything to default values, so in that case that we
+// can't read the data from mainstore, we will still be able to *do something*
+// instead of crash.
+occSysConfigData_t G_sysConfigData =
+{
+ .version = SYSCFG_DEFAULT_VERSION,
+ .debug_reserved = {0},
+
+ // -----------------------------------------------------------
+ // System Configuration Section Initializations
+ // -----------------------------------------------------------
+ .sys_num_proc_present = 4, //TODO: placeholder //fk001a
+
+ // -----------------------------------------------------------
+ // System maximum frequencies (in MHz) for each mode
+ // -----------------------------------------------------------
+ .sys_mode_freq.table = {
+ [OCC_MODE_NOMINAL] 3500,
+ [OCC_MODE_TURBO] 3700,
+ [OCC_MODE_PWRSAVE] 3000,
+ [OCC_MODE_MIN_FREQUENCY] 2575,
+ [OCC_MODE_FFO] 0,
+ },
+
+ // -----------------------------------------------------------
+ // APSS Section Initializations
+ // -----------------------------------------------------------
+ .apss_cal = {
+ [0] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [1] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [2] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [3] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [4] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [5] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [6] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [7] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [8] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [9] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [10] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [11] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [12] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [13] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [14] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ [15] {.gain = SYSCFG_ADC_1x_MULT, .offset = 0 , .gnd_select = 0},
+ },
+
+ .apss_gpio_map = {
+ .fans_watchdog_error = SYSCFG_INVALID_PIN,
+ .fans_full_speed = SYSCFG_INVALID_PIN,
+ .fans_error = SYSCFG_INVALID_PIN,
+ .fans_reserved = SYSCFG_INVALID_PIN,
+ .vr_fan[0] = SYSCFG_INVALID_PIN,
+ .vr_fan[1] = SYSCFG_INVALID_PIN,
+ .vr_fan[2] = SYSCFG_INVALID_PIN,
+ .vr_fan[3] = SYSCFG_INVALID_PIN,
+ // @ly007a - start
+ .cent_en_vcache[0] = SYSCFG_INVALID_PIN,
+ .cent_en_vcache[1] = SYSCFG_INVALID_PIN,
+ .cent_en_vcache[2] = SYSCFG_INVALID_PIN,
+ .cent_en_vcache[3] = SYSCFG_INVALID_PIN,
+ .cme_throttle_n = SYSCFG_INVALID_PIN,
+ .gnd_oc_n = SYSCFG_INVALID_PIN,
+ .dom_oc_latch[0] = SYSCFG_INVALID_PIN,
+ .dom_oc_latch[1] = SYSCFG_INVALID_PIN,
+ .dom_oc_latch[2] = SYSCFG_INVALID_PIN,
+ .dom_oc_latch[3] = SYSCFG_INVALID_PIN,
+ // @ly007a - end
+ },
+
+ .apss_adc_map = {
+ .memory[0] = SYSCFG_INVALID_ADC_CHAN,
+ .memory[1] = SYSCFG_INVALID_ADC_CHAN,
+ .memory[2] = SYSCFG_INVALID_ADC_CHAN,
+ .memory[3] = SYSCFG_INVALID_ADC_CHAN,
+ .vdd[0] = SYSCFG_INVALID_ADC_CHAN,
+ .vdd[1] = SYSCFG_INVALID_ADC_CHAN,
+ .vdd[2] = SYSCFG_INVALID_ADC_CHAN,
+ .vdd[3] = SYSCFG_INVALID_ADC_CHAN,
+ .io[0] = SYSCFG_INVALID_ADC_CHAN,
+ .io[1] = SYSCFG_INVALID_ADC_CHAN,
+ .io[2] = SYSCFG_INVALID_ADC_CHAN,
+ .fans[0] = SYSCFG_INVALID_ADC_CHAN,
+ .fans[1] = SYSCFG_INVALID_ADC_CHAN,
+ .storage_media[0] = SYSCFG_INVALID_ADC_CHAN,
+ .storage_media[1] = SYSCFG_INVALID_ADC_CHAN,
+ .vcs_vio_vpcie[0] = SYSCFG_INVALID_ADC_CHAN,
+ .vcs_vio_vpcie[1] = SYSCFG_INVALID_ADC_CHAN,
+ .vcs_vio_vpcie[2] = SYSCFG_INVALID_ADC_CHAN,
+ .vcs_vio_vpcie[3] = SYSCFG_INVALID_ADC_CHAN,
+ .total_current_12v = SYSCFG_INVALID_ADC_CHAN,
+ .sense_12v = SYSCFG_INVALID_ADC_CHAN,
+ .remote_gnd = SYSCFG_INVALID_ADC_CHAN,
+ .mem_cache = SYSCFG_INVALID_ADC_CHAN, // @ly008a
+ .gpu = SYSCFG_INVALID_ADC_CHAN,
+ },
+
+ .apssGpioPortsMode = {0, 0},
+
+ // -----------------------------------------------------------
+ // Power Cap Initializations
+ // -----------------------------------------------------------
+ .pcap = {
+ .current_pcap = 0,
+ .soft_min_pcap = 0,
+ .hard_min_pcap = 0,
+ .max_pcap = 0,
+ .oversub_pcap = 0,
+ .system_pcap = 0,
+ .unthrottle = 0,
+ }, // @th034
+
+ // -----------------------------------------------------------
+ // Master/Slave Section Initializations
+ // -----------------------------------------------------------
+ .pob2pbax_chip = {0,1,2,3,4,5,6,7},
+ .pob2pbax_node = {0,1,2,3},
+
+ .is_occ_present = SYSCFG_ZERO_OCCS_PRESENT,
+
+ .master_config = {
+ .is_master_capable = SYSCFG_MASTER_CAPABLE_000,
+ .default_master = SYSCFG_DEFAULT_MASTER_000,
+ },
+
+ // -----------------------------------------------------------
+ // Oversubscription Initializations
+ // -----------------------------------------------------------
+ .failsafe_enabled = FALSE, // @at010a
+
+ //Master ppb_fmax calculated by Master OCC's slave.
+ .master_ppb_fmax = 0xFFFF, // @fk001a
+
+ // -----------------------------------------------------------
+ // Centaur/Dimm HUID initializations
+ // -----------------------------------------------------------
+ .centaur_huids = {0},
+ .dimm_huids = {{0},{0},{0},{0},{0},{0},{0},{0}},
+
+ // -----------------------------------------------------------
+ // Memory Throttle Limits
+ // -----------------------------------------------------------
+ .mem_throt_limits = {{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}}},
+};
+
+
+// OCC Module Configuration Data
+//
+// We will initialize everything to default values, so in that case that we
+// can't read the data from mainstore, we will still be able to *do something*
+// instead of crash.
+occModuleConfigData_t G_occModuleConfigData = {
+ 0 // @th010 - Removed un-needed Pstate Table from this structure
+};
+
+
+// OCC Default PstateSuperStructure
+//
+// Default Pstate table, so that for testing we don't have to have TMGT
+// send one to us. Placing this in this file because it is necessary
+// configuration data for OCC to go to active state.
+//
+// This array was created with xxd -i pss.bin
+//
+// This can be removed or ifdef'd out to save space in the future.
+const unsigned char G_defaultOccPstateSuperStructure[] = {
+ 0x50, 0x53, 0x54, 0x41, 0x54, 0x45, 0x30, 0x31, 0x6e, 0x5e, 0x34, 0x44,
+ 0x24, 0x34, 0x00, 0xf3, 0x6d, 0x5d, 0x34, 0x44, 0x24, 0x34, 0x00, 0x9f,
+ 0x6c, 0x5c, 0x35, 0x45, 0x25, 0x35, 0x00, 0x22, 0x6b, 0x5b, 0x36, 0x46,
+ 0x26, 0x36, 0x00, 0x7b, 0x6a, 0x5a, 0x37, 0x47, 0x27, 0x37, 0x00, 0xc6,
+ 0x6a, 0x5a, 0x38, 0x48, 0x28, 0x38, 0x00, 0xe4, 0x69, 0x59, 0x38, 0x48,
+ 0x28, 0x38, 0x00, 0x88, 0x68, 0x58, 0x39, 0x49, 0x29, 0x39, 0x00, 0x35,
+ 0x67, 0x57, 0x3a, 0x4a, 0x2a, 0x3a, 0x00, 0xe2, 0x66, 0x56, 0x3b, 0x4b,
+ 0x2b, 0x3b, 0x00, 0x5f, 0x65, 0x56, 0x3c, 0x4c, 0x2c, 0x3c, 0x00, 0x7e,
+ 0x64, 0x55, 0x3d, 0x4c, 0x2d, 0x3c, 0x00, 0x8c, 0x63, 0x54, 0x3e, 0x4d,
+ 0x2e, 0x3d, 0x00, 0x89, 0x62, 0x53, 0x3f, 0x4e, 0x2f, 0x3e, 0x00, 0x68,
+ 0x61, 0x52, 0x40, 0x4f, 0x30, 0x3f, 0x00, 0xb7, 0x60, 0x51, 0x41, 0x50,
+ 0x31, 0x40, 0x00, 0xf8, 0x5f, 0x4f, 0x42, 0x52, 0x32, 0x42, 0x00, 0x68,
+ 0x5e, 0x4e, 0x43, 0x53, 0x33, 0x43, 0x00, 0xd5, 0x5d, 0x4d, 0x44, 0x54,
+ 0x34, 0x44, 0x00, 0xd0, 0x5c, 0x4c, 0x45, 0x55, 0x35, 0x45, 0x00, 0x6d,
+ 0x5b, 0x4b, 0x46, 0x56, 0x36, 0x46, 0x00, 0x34, 0x5a, 0x4a, 0x47, 0x57,
+ 0x37, 0x47, 0x00, 0x89, 0x5a, 0x4a, 0x48, 0x58, 0x38, 0x48, 0x00, 0xab,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xbe, 0xc8,
+ 0x00, 0x00, 0x82, 0x35, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77,
+ 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77,
+ 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x17, 0xea, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+
+// @at013a @fk001c
+// Power Configuration Data
+//
+pcap_config_data_t G_master_pcap_data =
+{
+ .current_pcap = 0,
+ .soft_min_pcap = 0,
+ .hard_min_pcap = 0,
+ .max_pcap = 0,
+ .oversub_pcap = 0,
+ .system_pcap = 0,
+ .unthrottle = 0,
+ .pcap_data_count = 0,
+};
+// TODO: Move this to a different file
+uint16_t G_conn_oc_pins_bitmap = 0x0000;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: sysConfigFspLess
+//
+// Description: Since we can have a OCC Simulation in Simics without
+// having a FSP, we need to have a way for OCC to automatically
+// set itself up the way FSP would. This is done via default
+// config data, and this function.
+//
+// Flow: --/--/-- FN=sysConfigFspLess
+//
+// End Function Specification
+#ifdef FSPLESS_SIMICS
+
+#include "cmdh_fsp_cmds_datacnfg.h"
+#include "dcom.h"
+#include "state.h"
+#include "mode.h"
+
+void sysConfigFspLess(void)
+{
+ // ----------------------------------------------------
+ // Set OCC Role based on Config Data
+ // ----------------------------------------------------
+ if( G_pob_id.chip_id == G_sysConfigData.master_config.default_master )
+ {
+ G_occ_role = OCC_MASTER;
+
+ // Run master initializations if we just became master
+ extern void master_occ_init(void);
+ master_occ_init();
+
+ // Turn off anything slave related since we are a master
+ rtl_clr_run_mask_deferred(RTL_FLAG_NOTMSTR);
+ rtl_set_run_mask_deferred(RTL_FLAG_MSTR);
+
+ // Set Final Mode & State. OCC will transition through as
+ // all requirements for state/mode become available.
+ G_occ_external_req_state = OCC_STATE_ACTIVE;
+ G_occ_external_req_mode = OCC_MODE_NOMINAL;
+ }
+ else
+ {
+ G_occ_role = OCC_SLAVE;
+
+ // Turn off anything master related since we are a slave
+ rtl_clr_run_mask_deferred(RTL_FLAG_MSTR);
+ rtl_set_run_mask_deferred(RTL_FLAG_NOTMSTR);
+ }
+
+ // Trace our current fspless role
+ if(OCC_MASTER == G_occ_role){
+ TRAC_IMP("Our current FspLess role: Master");
+ }
+ else{
+ TRAC_IMP("Our current FspLess role: Slave");
+ }
+
+ // ----------------------------------------------------
+ // Mark available all data we have hardcoded and
+ // correctly initialized.
+ // ----------------------------------------------------
+ extern data_cnfg_t * G_data_cnfg;
+ G_data_cnfg->data_mask = ( DATA_MASK_PSTATE_SUPERSTRUCTURE
+ | DATA_MASK_FREQ_PRESENT
+ | DATA_MASK_SET_ROLE
+ | DATA_MASK_APSS_CONFIG
+ | DATA_MASK_PCAP_PRESENT ); // @at013a
+
+ // Install the Pstate Table
+ proc_gpsm_pstate_initialize((PstateSuperStructure*) G_defaultOccPstateSuperStructure);
+
+}
+
+#endif
+
diff --git a/src/occ/occ_sys_config.h b/src/occ/occ_sys_config.h
new file mode 100755
index 0000000..17efdeb
--- /dev/null
+++ b/src/occ/occ_sys_config.h
@@ -0,0 +1,458 @@
+/******************************************************************************
+// @file occ_sys_config.h
+// @brief OCC System Configuration Structures sent down from HostBoot
+//
+// *** All config Structures *** must be defined in a completely self-contained
+// file (i.e no #includes) so that it can be used by both OCC & Host Boot.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section occ_sys_config.h OCC_SYS_CONFIG.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th001 thallet 09/15/2011 Created
+ * @01 abagepa 09/17/2011 extern a global
+ * @pb008 pbavari 10/17/2011 Use Pstate define from SSX for
+ * OCC FW Compilation.
+ * @th005 thallet 11/23/2011 Sensor Initialization changes
+ * @rc002 rickylie 02/02/2012 Remove unused DPSS function
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/2011 APSS Spec Changes
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th014 thallet 08/02/2012 Moved default PstateSS occ_sys_config
+ * @th018 852950 thallet 09/12/2012 Added Centaur thermal readings
+ * @th019 853007 thallet 09/12/2012 Power Sensors
+ * @th022 thallet 10/08/2012 Added way to init OCC w/o FSP for Simics
+ * @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+ * @th030 thallet 02/04/2013 Fixed a enum problem before external use
+ * @th034 thallet 04/18/2013 Broadcast Critical Power over PBAX
+ * @at013 878755 alvinwan 04/17/2013 OCC power capping implementation
+ * @at014 882077 alvinwan 05/09/2013 Support APSS and System Config data from TMGT
+ * @ly007 882183 lychen 05/21/2013 Send APSS and System Configuration commands to OCC
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @fk001 879727 fmkassem 04/16/2013 OCC powercap support.
+ * @ly008 894646 lychen 08/08/2013 Fix bugs in OCC handling of APSS tables for Brazos/Orlena
+ * @at016 891144 alvinwan 06/10/2013 OCC Power Cap Testing
+ * @gm008 SW226989 milesg 09/30/2013 Sapphire initial support
+ * @gm012 905097 milesg 10/31/2013 support mem throttle & mem config packets
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _occ_sys_config_h
+#define _occ_sys_config_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb008a - SSX defined Pstate in pgp_common.h file. Without below ifdef
+//compiler complains about redefinition for OCC.
+#ifdef OCC_FIRMWARE
+#include "pgp_common.h"
+#else
+#endif
+#include <state.h>
+#include <apss.h> // @at014a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define MAX_NUM_OCC 8
+#define MAX_NUM_NODES 4
+#define MAX_NUM_CORES 12
+#define MAX_THREADS_PER_CORE 8
+#define MAX_NUM_CHIP_MODULES 4
+#define MAX_NUM_POWER_SUPPLIES 4
+#define MAX_NUM_MEM_CONTROLLERS 8
+#define MAX_NUM_CENTAURS 8
+#define NUM_PROC_VRMS 2
+
+#define NUM_PROC_CHIPS_PER_OCC 1
+#define NUM_CENTAURS_PER_MEM_CONTROLLER 1
+#define NUM_PORT_PAIRS_PER_CENTAUR 2
+#define NUM_DIMMS_PER_CENTAUR 8 /* @th018 */
+#define NUM_MBAS_PER_CENTAUR 2
+
+#define UPPER_LIMIT_PROC_FREQ_MHZ 6000
+
+//Number of samples per second for performance-related algorithms (e.g. UTIL2MSP0Cy)
+#define AMEC_DPS_SAMPLING_RATE 500
+//Time interval for averaging utilization and frequency (IPS algorithm)
+#define AMEC_IPS_AVRG_INTERVAL 3
+
+/*****************************************************************************/
+// System Structures
+/*****************************************************************************/
+typedef union // @gm008
+{
+ struct
+ {
+ uint8_t kvm: 1;
+ uint8_t reserved: 5;
+ uint8_t ite: 1;
+ uint8_t single: 1;
+ };
+ uint8_t byte;
+} eSystemType;
+
+/*****************************************************************************/
+// APSS Structures & Defines
+/*****************************************************************************/
+#define SYSCFG_INVALID_ADC_CHAN 0xff
+#define SYSCFG_INVALID_PIN 0xff
+
+#define MAX_VRFAN_SIGNALS 4
+#define MAX_APSS_MEM_TEMPS 8
+#define MAX_ADC_IO_DOMAINS 3
+#define MAX_ADC_FAN_DOMAINS 2
+#define MAX_ADC_STORAGE_DOMAINS 2
+#define MAX_CENT_EN_VCACHE 4 // @ly007a
+#define MAX_DOM_OC_LATCH 4 // @ly007a
+#define MAX_CONN_OC_SIGNALS 5 // @fk001a
+
+typedef enum
+{
+ ADC_RESERVED = 0x00,
+ ADC_MEMORY_PROC_0 = 0x01,
+ ADC_MEMORY_PROC_1 = 0x02,
+ ADC_MEMORY_PROC_2 = 0x03,
+ ADC_MEMORY_PROC_3 = 0x04,
+ ADC_VDD_PROC_0 = 0x05,
+ ADC_VDD_PROC_1 = 0x06,
+ ADC_VDD_PROC_2 = 0x07,
+ ADC_VDD_PROC_3 = 0x08,
+ ADC_VCS_VIO_VPCIE_PROC_0 = 0x09,
+ ADC_VCS_VIO_VPCIE_PROC_1 = 0x0A,
+ ADC_VCS_VIO_VPCIE_PROC_2 = 0x0B,
+ ADC_VCS_VIO_VPCIE_PROC_3 = 0x0C,
+ ADC_IO_A = 0x0D,
+ ADC_IO_B = 0x0E,
+ ADC_IO_C = 0x0F,
+ ADC_FANS_A = 0x10,
+ ADC_FANS_B = 0x11,
+ ADC_STORAGE_A = 0x12,
+ ADC_STORAGE_B = 0x13,
+ ADC_12V_SENSE = 0x14,
+ ADC_GND_REMOTE_SENSE = 0x15,
+ ADC_TOTAL_SYS_CURRENT = 0x16,
+ ADC_MEM_CACHE = 0x17, // @ly008a
+ ADC_GPU_SENSE = 0x18,
+ NUM_ADC_ASSIGNMENT_TYPES // This should always be the last member
+} eApssAdcChannelAssignments;
+
+typedef enum
+{
+ GPIO_RESERVED = 0x0000,
+ GPIO_FAN_WATCHDOG_ERROR = 0x0001,
+ GPIO_FAN_FULL_SPEED = 0x0002,
+ GPIO_FAN_ERROR = 0x0003,
+ GPIO_FAN_RESERVED = 0x0004,
+ GPIO_VR_HOT_MEM_PROC_0 = 0x0005,
+ GPIO_VR_HOT_MEM_PROC_1 = 0x0006,
+ GPIO_VR_HOT_MEM_PROC_2 = 0x0007,
+ GPIO_VR_HOT_MEM_PROC_3 = 0x0008,
+ // @ly007a - start
+ GPIO_CENT_EN_VCACHE0 = 0x0009,
+ GPIO_CENT_EN_VCACHE1 = 0x000A,
+ GPIO_CENT_EN_VCACHE2 = 0x000B,
+ GPIO_CENT_EN_VCACHE3 = 0x000C,
+ CME_THROTTLE_N = 0x000D,
+ GND_OC_N = 0x000E,
+ DOM_A_OC_LATCH = 0x000F,
+ DOM_B_OC_LATCH = 0x0010,
+ DOM_C_OC_LATCH = 0x0011,
+ DOM_D_OC_LATCH = 0x0012,
+ // @ly007a - end
+ NUM_GPIO_ASSIGNMENT_TYPES // This should always be the last member
+} eApssGpioAssignments;
+
+typedef struct
+{
+ // Gain and Offset, Stored in a exponent/mantissa format (like P7 PS Gain/Offset)
+ uint32_t gain; // Think "multiplier"
+ uint32_t offset; // Will probably always be 0, since APSS is so accurate
+ uint8_t gnd_select; // @at014a
+} apssCalibrationData_t;
+
+typedef struct
+{
+ // Value stored will be APSS GPIO Number, if not present, set to INVALID = xFF.
+ // Example: vr_fan[0] = 4; (VR_FAN is APSS GPIO #4)
+ // @ly007a - start
+ uint8_t dom_oc_latch[MAX_DOM_OC_LATCH];
+ uint8_t gnd_oc_n;
+ uint8_t cme_throttle_n;
+ uint8_t cent_en_vcache[MAX_CENT_EN_VCACHE];
+ // @ly007a - end
+ uint8_t vr_fan[MAX_VRFAN_SIGNALS];
+ uint8_t fans_watchdog_error;
+ uint8_t fans_full_speed;
+ uint8_t fans_error;
+ uint8_t fans_reserved;
+} apssGpioPinData_t;
+
+typedef struct
+{
+ // Value stored will be APSS ADC Channel Number, if rail is not present, set
+ // to INVALID = xFF
+ uint8_t memory[MAX_NUM_CHIP_MODULES];
+ uint8_t vdd[MAX_NUM_CHIP_MODULES];
+ uint8_t io[MAX_ADC_IO_DOMAINS];
+ uint8_t fans[MAX_ADC_FAN_DOMAINS];
+ uint8_t storage_media[MAX_ADC_STORAGE_DOMAINS];
+ uint8_t total_current_12v;
+ uint8_t vcs_vio_vpcie[MAX_NUM_CHIP_MODULES];
+ uint8_t sense_12v;
+ uint8_t remote_gnd;
+ uint8_t mem_cache; // @ly008a
+ uint8_t gpu;
+} apssAdcChannelData_t;
+
+// @rc002 - Remove unused DPSS Structures & Defines
+
+/*****************************************************************************/
+// Master/Slave Configuration
+/*****************************************************************************/
+typedef struct
+{
+ // Bitmask that states if OCC is master capable
+ // (i.e. 0x11 = Chip_Id 000 & Chip_Id 100 can both be masters)
+ uint8_t is_master_capable;
+
+ // Which Chip_Id should be initial master
+ // (i.e. default_master = 0x00 for almost all cases)
+ uint8_t default_master;
+
+} masterCapability_t;
+
+
+//*************************************************************************
+// System Frequency
+//*************************************************************************
+typedef struct
+{
+ uint16_t table[OCC_MODE_COUNT]; // Table w/ freq for each mode
+ uint8_t update_count; //
+ uint8_t _reserved; // Align to 2 b/c we may use it in PBAX broadcast
+} freqConfig_t; // @th040
+
+//*************************************************************************
+// Power Cap Structures
+//*************************************************************************
+// @th034 @fk001c
+typedef struct
+{
+ uint16_t current_pcap; // Node power cap requested by customer (AEM) in 1W units
+ uint16_t soft_min_pcap; // Minimum node power cap allowed in 1W units
+ uint16_t hard_min_pcap; // Minimum guaranteed node power cap in 1W units
+ uint16_t max_pcap; // Maximum customer settable node power cap in 1W units
+ uint16_t oversub_pcap; // Node power cap to be used for oversubscripion in 1W units
+ uint16_t system_pcap; // Fixed node power cap required by the system in 1W units
+ uint8_t unthrottle; // Only used on ITEs -- is indicated from CMM
+ uint8_t pcap_data_count; // Used by OCC only. Initialized to 0 and incremented by 1 with every new packet.
+} pcap_config_data_t;
+
+//*************************************************************************
+// Memory Throttle settings
+//*************************************************************************
+typedef struct
+{
+ uint16_t min_ot_n_per_mba; //minimum value
+ uint16_t nom_n_per_mba; //max mba value for nominal mode
+ uint16_t nom_n_per_chip; //chip setting for nominal mode
+ uint16_t turbo_n_per_mba; //max mba value for turbo mode
+ uint16_t turbo_n_per_chip; //chip setting for nominal mode
+ uint16_t ovs_n_per_mba; //max mba value for oversubscription
+ uint16_t ovs_n_per_chip; //chip setting for oversubscription
+} mem_throt_config_data_t;
+
+//*************************************************************************
+// Sys Config Structure
+//*************************************************************************
+
+// Needs to be 128 bytes aligned so we can do a DMA to transfer this to SRAM from
+// Main Memory.
+
+// One global structure which is the same in all OCCs
+
+// TODO: If we cannot dynamically change this structure and have it
+// picked up by host boot & occ, then we will want to add reserved
+// fields for each 'section' of the structure for future-proofing
+
+typedef struct
+{
+ // ------------------------------------
+ // Identification & Debug Flags
+ // ------------------------------------
+
+ // Gives us a version number of this structure for ease of debug
+ uint8_t version;
+
+ // Gives us a lot of debug flags that we can use to change OCC behavior
+ // at startup.
+ uint8_t debug_reserved[7];
+
+
+
+ // ------------------------------------
+ // System Configuration
+ // ------------------------------------
+
+ // Instead of system-type, lets try to send all system attributes
+ // that matter instead of having tables in OCC code.
+ // @at014a - start
+ eSystemType system_type; // OCC usage of this byte is TBD
+
+ // Processor HUID - HUID for this OCC processor, used by OCC for processor error call out
+ uint64_t proc_huid;
+
+ // Backplane HUID - Used by OCC for system backplane error call out (i.e. VRM errors will call out backplane)
+ uint64_t backplane_huid;
+
+ // APSS HUID - Used by OCC for APSS error call out
+ uint64_t apss_huid;
+
+ // DPSS HUID - Used by OCC for DPSS error call out
+ uint64_t dpss_huid;
+ // @at014a - end
+
+ // Contains how many OCCs & how many proc modules are present.
+ uint8_t sys_num_proc_present;
+
+ // ------------------------------------
+ // Max Frequency for each mode
+ // ------------------------------------
+ freqConfig_t sys_mode_freq; // @th040
+
+ // ------------------------------------
+ // APSS Configuration Data
+ // ------------------------------------
+
+ // Holds the gain/offset needed to translate from raw ADC to actual power
+ // measurements
+ apssCalibrationData_t apss_cal[MAX_APSS_ADC_CHANNELS];
+
+ // Holds the mapping of GPIO signals to APSS pins
+ apssGpioPinData_t apss_gpio_map;
+
+ // Holds the mapping of ADC signals to APSS adc channels
+ apssAdcChannelData_t apss_adc_map;
+
+ // GPIO Port Mode
+ uint8_t apssGpioPortsMode[MAX_APSS_GPIO_PORTS]; // @at014a
+
+ // ------------------------------------
+ // Power Cap Configuration Data updated by Slaves
+ // ------------------------------------
+ pcap_config_data_t pcap; // @th034
+
+ // ------------------------------------
+ // Master/Slave OCC Configuration Data
+ // ------------------------------------
+
+ // Information Needed to translate from PowerBus ID to PBAX Id (OCC Id)
+ // - Index = Powerbus Id will get you PBAX Id as value at that index
+ // - Example pob2pbax_chip[1] = 4; (PowerBus ID 001 = PBAX ID 100
+ uint8_t pob2pbax_chip[MAX_NUM_OCC];
+ uint8_t pob2pbax_node[MAX_NUM_NODES];
+
+ // Bitmask that states if OCC is present
+ // (i.e. 0x11 = Chip_Id 000 & Chip_Id 100 are only OCCs present)
+ uint8_t is_occ_present;
+
+ // Tells us which OCCs can be master & which OCC should start out as master
+ masterCapability_t master_config;
+
+ // ------------------------------------
+ // Oversubscription Configuration Data
+ // ------------------------------------
+ // If it's ITE or non-ITE (enabled:ITE, non-enalbe: non-ITE)
+ uint8_t failsafe_enabled; // @at010a
+
+ // ppb_fmax as set by Master OCC. Initialized to 0xFFFF
+ uint32_t master_ppb_fmax; // @fk001a @at016c
+
+ // --------------------------------------
+ // HUID's for centaurs and dimms
+ // --------------------------------------
+ uint64_t centaur_huids[MAX_NUM_CENTAURS];
+ uint64_t dimm_huids[MAX_NUM_CENTAURS][NUM_DIMMS_PER_CENTAUR];
+
+ // --------------------------------------
+ // Memory Throttle limits
+ // --------------------------------------
+ mem_throt_config_data_t mem_throt_limits[MAX_NUM_CENTAURS][NUM_MBAS_PER_CENTAUR];
+
+} occSysConfigData_t; __attribute__ ((__aligned__ (128)))
+
+// @01a
+extern occSysConfigData_t G_sysConfigData;
+
+
+//*************************************************************************
+// End of Sys Config Structure
+//*************************************************************************
+
+//*************************************************************************
+// Individual OCC Config Structure
+//*************************************************************************
+
+// Needs to be 128 bytes aligned so we can do a DMA to transfer this to SRAM from
+// Main Memory.
+
+// One global structure per OCC (so there will be 8 up in main memory)
+
+// TODO: If we cannot dynamically change this structure and have it
+// picked up by host boot & occ, then we will want to add reserved
+// fields for each 'section' of the structure for future-proofing
+
+typedef struct
+{
+ int dummy; // @th010 - Removed un-needed Pstate Structure
+
+} occModuleConfigData_t; __attribute__ ((__aligned__ (128)))
+
+//*************************************************************************
+// End of Individual OCC Config Structure
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Default PstateSuperStructure that can be used instead of TMGT provided one.
+extern const unsigned char G_defaultOccPstateSuperStructure[];
+
+// MASTER PCAP values. @at013a, @fk001c
+extern pcap_config_data_t G_master_pcap_data;
+
+//
+extern uint16_t G_conn_oc_pins_bitmap;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+#ifdef FSPLESS_SIMICS
+void sysConfigFspLess(void);
+#endif
+
+/*****************************************************************************/
+#endif // _occ_sys_config_h
diff --git a/src/occ/occbuildname.c b/src/occ/occbuildname.c
new file mode 100755
index 0000000..9f46847
--- /dev/null
+++ b/src/occ/occbuildname.c
@@ -0,0 +1 @@
+volatile const char G_occ_buildname[16] __attribute__((section(".buildname"))) = /*<BuildName>*/ "occSandboxBuild\0" /*</BuildName>*/ ;
diff --git a/src/occ/proc/proc_data.c b/src/occ/proc/proc_data.c
new file mode 100755
index 0000000..af0e402
--- /dev/null
+++ b/src/occ/proc/proc_data.c
@@ -0,0 +1,925 @@
+/******************************************************************************
+// @file proc_data.c
+// @brief Data codes for proc component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _proc_data_c proc_data.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * nguyenp 09/27/2011 Created
+ * nguyenp 09/27/2011 Added bulk core data and proc core
+ * initialization code.
+ * @01 nguyenp 10/19/2011 Added fast core data colect code.
+ * Added new interfaces to gain access to
+ * bulk core and fast core data.
+ * Change OCC core id numbering scheme.
+ * @th006 thallet 11/21/2011 RESET_REQUEST substituted for todo's
+ * @rc001 rickylie 12/30/2011 Moved debug trace defines to trac.h
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/2012 Minor changes to make proc collection work.
+ * @th00f thallet 06/27/2012 Changed to use CoreData as provided by HW team
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup
+ * @th043 892554 thallet 07/23/2013 Automatic Nominal/Active state change
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm022 908890 milesg 01/23/2014 update global core presence mask from pmc deconfig register
+ * @sb055 911966 sbroyles 02/27/2014 Enable PBCS heartbeat
+ * @sbpde 922027 sbroyles 04/04/2014 Add error check to GPE proc data
+ * collection.
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "proc_data.h"
+#include "pgp_async.h"
+#include "threadSch.h"
+#include "pmc_register_addresses.h"
+#include "proc_data_service_codes.h"
+#include "occ_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "apss.h"
+#include "state.h"
+#include "proc_data_control.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+//Global array of core data buffers
+GPE_BUFFER(gpe_bulk_core_data_t G_core_data[MAX_NUM_FW_CORES+NUM_CORE_DATA_DOUBLE_BUF+NUM_CORE_DATA_EMPTY_BUF]) = {{{0}}}; // @th00b @th00f
+
+//@01c Changed OCC core id numbering scheme
+//Global array of core data pointers
+gpe_bulk_core_data_t * G_core_data_ptrs[MAX_NUM_FW_CORES] = { &G_core_data[0], &G_core_data[1],
+ &G_core_data[2], &G_core_data[3], &G_core_data[4], &G_core_data[5], &G_core_data[6],
+ &G_core_data[7], &G_core_data[8], &G_core_data[9], &G_core_data[10], &G_core_data[11] };
+
+//Global structures for gpe get core data parms
+GPE_BUFFER(GpeGetCoreDataParms G_low_cores_data_parms);
+GPE_BUFFER(GpeGetCoreDataParms G_high_cores_data_parms);
+
+//@01c Changed core data structure to fit the new core id numbering scheme
+//We will have separate bulk core data structure for low and high cores.
+//Global low and high cores structures used for task data pointers.
+bulk_core_data_task_t G_low_cores = { 0, 0, 5, &G_core_data[12] };
+bulk_core_data_task_t G_high_cores = { 6, 6, 11, &G_core_data[13] };
+
+//AMEC needs to know when data for a core has been collected.
+uint32_t G_updated_core_mask = 0;
+
+// >> @sbpde
+// Mask to indicate when an empath error has been detected and empath data
+// should be ignored. Core bits are cleared when empath data is collected
+// without error.
+uint32_t G_empath_error_core_mask = 0;
+// << @sbpde
+
+//Global G_present_cores is bitmask of all cores
+//(1 = present, 0 = not present. Core 0 has the most significant bit)
+uint32_t G_present_cores = 0;
+
+//>@01a
+//Global double buffering for fast core data collection.
+GPE_BUFFER(gpe_fast_core_data_t G_fast_core_data[NUM_FAST_CORE_DATA_BUFF]) = {{0}};
+
+//Pointer to the latest fast core data that will be used by AMEC code.
+GPE_BUFFER(gpe_fast_core_data_t * G_read_fast_core_data_ptr) = { &G_fast_core_data[0] };
+
+//Pointer used by GPE code to write fast core data.
+GPE_BUFFER(gpe_fast_core_data_t * G_write_fast_core_data_ptr) = { &G_fast_core_data[1] };
+
+//Globals structure for gpe get chip data fast parms.
+//The Gpe parameter fields are set up each time before collect data start.
+GPE_BUFFER(GpeGetChipDataFastParms G_chip_data_fast_parms); // @th008c
+
+//Pore flex request for GPE job. The initialization
+//will be done one time during pore flex create.
+PoreFlex G_fast_cores_req;
+
+//Global G_present_hw_cores is bitmask of all hardware cores
+//(1 = present, 0 = not present. Core 0 has the most significant bit)
+uint32_t G_present_hw_cores = 0;
+
+//OCC to HW core id mapping array
+uint8_t G_occ2hw_core_id[MAX_NUM_HW_CORES] = { 1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 0, 7, 8, 15 };
+
+//HW to OCC core id mapping array
+uint8_t G_hw2occ_core_id[MAX_NUM_HW_CORES] = { 12, 0, 1, 2, 3, 4, 5, 13, 14, 6, 7, 8, 9, 10, 11, 15 };
+
+//Flag to keep tract of one time trace for GPE running case
+//for task core data.
+bool G_queue_not_idle_traced = FALSE;
+
+//Flag to keep tract of one time trace for GPE running case
+//for Fast core data.
+bool G_fast_core_queue_not_idle_traced = FALSE;
+//<@01a
+
+// >> @sb055
+// Global to track the maximum time elapsed between pore flex schedules of
+// per core get_per_core_data tasks. The array is indexed by core number.
+uint32_t G_get_per_core_data_max_schedule_intervals[MAX_NUM_HW_CORES] = {0,};
+// << @sb055
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+//@rc001a - debug function declaration
+#ifdef PROC_DEBUG
+void print_core_data_sensors(uint8_t core);
+void print_core_status(uint8_t core);
+void print_fast_core_data(void);
+#endif
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: task_core_data
+//
+// Description: Collect bulk core data for all cores in specified range.
+// The task used for core data collection will be split into two
+// individual task instances. The task function is the same but it needs
+// to gather data for different sets of cores.
+//
+// Flow: 10/18/11 FN=task_core_data
+//
+// End Function Specification
+
+void task_core_data( task_t * i_task )
+{
+
+ errlHndl_t l_err = NULL; //Error handler
+ tracDesc_t l_trace = NULL; //Temporary trace descriptor
+ int rc = 0; //return code
+ bulk_core_data_task_t * l_bulk_core_data_ptr = (bulk_core_data_task_t *)i_task->data_ptr;
+ GpeGetCoreDataParms * l_parms = (GpeGetCoreDataParms *)(l_bulk_core_data_ptr->gpe_req.parameter);
+ gpe_bulk_core_data_t * l_temp = NULL;
+
+ do
+ {
+ //First, check to see if the previous GPE request still running
+ //A request is considered idle if it is not attached to any of the
+ //asynchronous request queues
+ if( !(async_request_is_idle(&l_bulk_core_data_ptr->gpe_req.request)) )
+ {
+ //This should not happen unless there's a problem
+ //Trace 1 time
+ if( !G_queue_not_idle_traced )
+ {
+ TRAC_ERR("Core data GPE is still running \n");
+ G_queue_not_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ //Need to complete collecting data for all assigned cores from previous interval
+ //and tick 0 is the current tick before collect data again.
+ if( (l_bulk_core_data_ptr->current_core == l_bulk_core_data_ptr->end_core)
+ &&
+ ((CURRENT_TICK & (MAX_NUM_TICKS - 1)) != 0) )
+ {
+ //@rc001m
+ PROC_DBG("Not collect data. Need to wait for tick.\n");
+ break;
+ }
+
+ //Check to see if the previously GPE request has successfully completed
+ //A request is not considered complete until both the engine job
+ //has finished without error and any callback has run to completion.
+
+ if( async_request_completed(&l_bulk_core_data_ptr->gpe_req.request)
+ &&
+ CORE_PRESENT(l_bulk_core_data_ptr->current_core) )
+ {
+ //If the previous GPE request succeeded then swap core_data_ptr
+ //with the global one. The gpe routine will write new data into
+ //a buffer that is not being accessed by the RTLoop code.
+
+ //@rc001m
+ PROC_DBG( "Swap core_data_ptr [%x] with the global one\n",
+ l_bulk_core_data_ptr->current_core );
+
+ //debug only
+#ifdef PROC_DEBUG
+ print_core_status(l_bulk_core_data_ptr->current_core);
+ print_core_data_sensors(l_bulk_core_data_ptr->current_core);
+#endif
+
+ l_temp = l_bulk_core_data_ptr->core_data_ptr;
+ l_bulk_core_data_ptr->core_data_ptr =
+ G_core_data_ptrs[l_bulk_core_data_ptr->current_core];
+ G_core_data_ptrs[l_bulk_core_data_ptr->current_core] = l_temp;
+
+ //Core data has been collected so set the bit in global mask.
+ //AMEC code will know which cores to update sensors for. AMEC is
+ //responsible for clearing the bit later on.
+ G_updated_core_mask |= CORE0_PRESENT_MASK >> (l_bulk_core_data_ptr->current_core); // @th00b
+
+ // >> @sbpde
+ // Presumptively clear the empath error mask
+ G_empath_error_core_mask &=
+ ~(CORE0_PRESENT_MASK >> (l_bulk_core_data_ptr->current_core));
+
+ // The gpe_data collection code has to handle the workaround for
+ // HW280375. Two new flags have been added to the OHA_RO_STATUS_REG
+ // image to indicate whether the EMPATH collection failed, and
+ // whether it was due to an "expected" error that we can ignore
+ // (we can ignore the data as well), or an "unexpected" error that
+ // we will create an informational log one time.
+ //
+ // The "expected" errors are very rare in practice, in fact we may
+ // never even see them unless running a specific type of workload.
+ // If you want to test the handling of expected errors compile the
+ // GPE code with -DINJECT_HW280375_ERRORS which will inject an error
+ // approximately every 1024 samples
+ //
+ // To determine if the expected error has occurred inspect the
+ // CoreDataOha element of the CoreData structure written by the GPE
+ // core data job. The OHA element contains the oha_ro_status_reg.
+ // Inside the OHA status register is a 16 bit reserved field.
+ // gpe_data.h defines two masks that can be applied against the
+ // reserved field to check for these errors:
+ // CORE_DATA_EXPECTED_EMPATH_ERROR
+ // CORE_DATA_UNEXPECTED_EMPATH_ERROR
+ // Also, a 4-bit PCB parity + error code is saved at bit position:
+ // CORE_DATA_EMPATH_ERROR_LOCATION, formally the length is
+ // specified by: CORE_DATA_EMPATH_ERROR_BITS
+ gpe_bulk_core_data_t *l_core_data =
+ G_core_data_ptrs[l_bulk_core_data_ptr->current_core];
+
+ // We will trace the errors, but only a certain number of
+ // times, we will only log the unexpected error once.
+#define OCC_EMPATH_ERROR_THRESH 10
+ static uint32_t L_expected_emp_err_cnt = 0;
+ static uint32_t L_unexpected_emp_err_cnt = 0;
+
+ // Check the reserved field for the expected or the unexpected error flag
+ if ((l_core_data->oha.oha_ro_status_reg.fields._reserved0 & CORE_DATA_EXPECTED_EMPATH_ERROR)
+ ||
+ (l_core_data->oha.oha_ro_status_reg.fields._reserved0 & CORE_DATA_UNEXPECTED_EMPATH_ERROR))
+ {
+ // Indicate empath error on current core
+ G_empath_error_core_mask |=
+ CORE0_PRESENT_MASK >> (l_bulk_core_data_ptr->current_core);
+
+ // Save the high and low order words of the OHA status reg
+ uint32_t l_oha_reg_high = l_core_data->oha.oha_ro_status_reg.words.high_order;
+ uint32_t l_oha_reg_low = l_core_data->oha.oha_ro_status_reg.words.low_order;
+
+ // Handle each error case
+ if ((l_core_data->oha.oha_ro_status_reg.fields._reserved0 & CORE_DATA_EXPECTED_EMPATH_ERROR)
+ &&
+ (L_expected_emp_err_cnt < OCC_EMPATH_ERROR_THRESH))
+ {
+ L_expected_emp_err_cnt++;
+ TRAC_IMP("Expected empath collection error occurred %d time(s)! Core = %d",
+ L_expected_emp_err_cnt,
+ l_bulk_core_data_ptr->current_core);
+ TRAC_IMP("OHA status register: 0x%4.4x%4.4x",
+ l_oha_reg_high, l_oha_reg_low);
+ }
+
+ if ((l_core_data->oha.oha_ro_status_reg.fields._reserved0 & CORE_DATA_UNEXPECTED_EMPATH_ERROR)
+ &&
+ (L_unexpected_emp_err_cnt < OCC_EMPATH_ERROR_THRESH))
+ {
+ L_unexpected_emp_err_cnt++;
+ TRAC_ERR("Unexpected empath collection error occurred %d time(s)! Core = %d",
+ L_unexpected_emp_err_cnt,
+ l_bulk_core_data_ptr->current_core);
+ TRAC_ERR("OHA status register: 0x%4.4x%4.4x",
+ l_oha_reg_high, l_oha_reg_low);
+
+ // Create and commit an informational error the first
+ // time this occurs.
+ if (L_unexpected_emp_err_cnt == 1)
+ {
+ TRAC_IMP("Logging unexpected empath collection error 1 time only.");
+ /*
+ * @errortype
+ * @moduleid PROC_TASK_CORE_DATA_MOD
+ * @reasoncode INTERNAL_HW_FAILURE
+ * @userdata1 OHA status reg high
+ * @userdata2 OHA status reg low
+ * @userdata4 ERC_PROC_CORE_DATA_EMPATH_ERROR
+ * @devdesc An unexpected error occurred while
+ * collecting core empath data.
+ */
+ l_err = createErrl(
+ PROC_TASK_CORE_DATA_MOD, //modId
+ INTERNAL_HW_FAILURE, //reason code
+ ERC_PROC_CORE_DATA_EMPATH_ERROR, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_oha_reg_high, //userdata1
+ l_oha_reg_low); //userdata2
+
+ commitErrl(&l_err);
+ }
+ }
+ }
+ }
+ // << @sbpde
+
+ // If the core is not present, then we need to point to the empty G_core_data
+ // so that we don't use old/stale data from a leftover G_core_data
+ if( !CORE_PRESENT(l_bulk_core_data_ptr->current_core)) // @th00b
+ {
+ G_core_data_ptrs[l_bulk_core_data_ptr->current_core] = &G_core_data[14]; // @th00b
+ }
+
+ //Update current core
+ if ( l_bulk_core_data_ptr->current_core >= l_bulk_core_data_ptr->end_core )
+ {
+ l_bulk_core_data_ptr->current_core = l_bulk_core_data_ptr->start_core;
+ }
+ else
+ {
+ l_bulk_core_data_ptr->current_core++;
+ }
+
+ //If core is not present then skip it. This task assigned to this core will
+ //be idle during this time it would have collected the data.
+ if( CORE_PRESENT(l_bulk_core_data_ptr->current_core) )
+ {
+ //@rc001m
+ PROC_DBG("Schedule PoreFlex OCC core [%x] or HW core [%x]\n",
+ l_bulk_core_data_ptr->current_core, CORE_OCC2HW(l_bulk_core_data_ptr->current_core));
+
+ //1. Setup the get core data parms
+ l_parms->config =
+ ((uint64_t) CORE0_PRESENT_MASK_GPE) >> (CORE_OCC2HW(l_bulk_core_data_ptr->current_core)); // @th008c
+
+ if( (cfam_id() == CFAM_CHIP_ID_MURANO_10)
+ || (cfam_id() == CFAM_CHIP_ID_MURANO_11)
+ || (cfam_id() == CFAM_CHIP_ID_MURANO_12) )
+ {
+ // Due to HW243646 & HW243942 fallout, we will not be collecting EX core
+ // activity counter scoms until Murano DD1.3 @th032
+ l_parms->select = GPE_GET_CORE_DATA_DTS_CPM | GPE_GET_CORE_DATA_PCB_SLAVE;
+ }
+ else
+ {
+ l_parms->select = GPE_GET_CORE_DATA_ALL;
+ }
+
+ l_parms->data = (uint32_t) l_bulk_core_data_ptr->core_data_ptr;
+
+ // >> @sb055
+ // Static array to record the last timestamp a get_per_core_data task was
+ // scheduled for a core.
+ static SsxTimebase L_last_get_per_core_data_scheduled_time[MAX_NUM_HW_CORES] = {0,};
+ uint8_t l_current_core = l_bulk_core_data_ptr->current_core;
+ SsxTimebase l_now = ssx_timebase_get();
+ // If the last scheduled timestamp is 0, record time and continue to schedule
+ if (L_last_get_per_core_data_scheduled_time[l_current_core] == 0)
+ {
+ L_last_get_per_core_data_scheduled_time[l_current_core] = l_now;
+ }
+ else
+ {
+ // Calculate elapsed time in usecs since last get_per_core_data
+ // task for the current core was scheduled.
+ uint32_t l_elapsed_us =
+ (uint32_t)((l_now - L_last_get_per_core_data_scheduled_time[l_current_core])/
+ (SSX_TIMEBASE_FREQUENCY_HZ/1000000));
+ // Save the last scheduled timestamp
+ L_last_get_per_core_data_scheduled_time[l_current_core] = l_now;
+ // If the new elapsed time is greater than what is currently saved,
+ // save the larger time.
+ if (G_get_per_core_data_max_schedule_intervals[l_current_core] < l_elapsed_us)
+ {
+ G_get_per_core_data_max_schedule_intervals[l_current_core] = l_elapsed_us;
+ TRAC_INFO("New max get_per_core_data interval: core=%d, interval(us)=%d",
+ l_current_core, l_elapsed_us);
+ }
+ // Also sniff if the request has actually completed, it is checked above but
+ // the schedule proceeds regardless which could be dangerous...
+ if (!async_request_completed(&l_bulk_core_data_ptr->gpe_req.request))
+ {
+ TRAC_ERR("Async get_per_core_data task for core=%d not complete!",
+ l_current_core);
+ }
+ }
+
+ // The PCBS heartbeat timer may time out even though we are scheduling
+ // the get_per_core_data task for each core every 2ms. Reason at time
+ // of this code change is still unknown but reproducible. We are going
+ // to getscom the PMSTATEHISTOCC register (PCBS_PMSTATEHISTOCC_REG) for
+ // each configured core before scheduling the PORE job to try and make
+ // sure the heartbeat doesn't expire.
+ // Recent tests show the heartbeat is holding steady so the getscom is
+ // commented out and incomplete, the core number needs to be converted
+ // to a hardware core number if this code is activated.
+ //uint64_t l_dont_care = 0;
+ //uint32_t core = CORE_CHIPLET_ADDRESS(PCBS_PMSTATEHISTOCC_REG, ???);
+ //getscom(address???, &l_dont_care);
+ // << @sb055
+
+ //2. Port flex schedule gpe_get_per_core_data
+ // Check pore_flex_schedule return code if error
+ // then request OCC reset.
+
+ rc = pore_flex_schedule( &l_bulk_core_data_ptr->gpe_req );
+ if( rc != 0 )
+ {
+ //Error in schedule gpe get core data
+ TRAC_ERR("Failed PoreFlex schedule core [%x] \n", rc);
+
+ /*
+ * @errortype
+ * @moduleid PROC_TASK_CORE_DATA_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 pore_flex_schedule return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX PORE related failure
+ */
+ l_err = createErrl(
+ PROC_TASK_CORE_DATA_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //TODO: create l_trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ REQUEST_RESET(l_err); // @gm006
+ break;
+ }
+ }
+ }
+ while(0);
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: proc_core_init
+//
+// Description: Initialize structure for collecting core data. It
+// needs to be run in occ main and before RTLoop started.
+//
+// Flow: 09-27-11 FN=proc_core_init
+//
+// End Function Specification
+
+void proc_core_init( void )
+{
+ errlHndl_t l_err = NULL; //Error handler
+ tracDesc_t l_trace = NULL; //Temporary trace descriptor
+ int rc = 0; //Return code
+
+ do
+ {
+ //Before RTLoop starts to collect data. We need to determine what cores
+ //are present and configured. We have a register that has information
+ //of all cores that have been deconfigured in the chip so we need to read that.
+
+ //>@01a
+ G_present_hw_cores = in32(PMC_CORE_DECONFIGURATION_REG);
+
+ //Inverse the bitmask of the deconfigured register to get present
+ //cores and save it in the global present hardware cores.
+ G_present_hw_cores = ~G_present_hw_cores & HW_CORES_MASK;
+
+ //Convert hardware core numering to OCC core numering.
+ G_present_cores = ((G_present_hw_cores & LO_CORES_MASK) << 1) |
+ ((G_present_hw_cores & HI_CORES_MASK) << 3);
+ //@rc001m
+ PROC_DBG("G_present_hw_cores =[%x] and G_present_cores =[%x] \n",
+ G_present_hw_cores, G_present_cores);
+ //<@01a
+
+ //Initializes low cores data PoreFlex object
+ rc = pore_flex_create( &G_low_cores.gpe_req, //gpe_req for the task
+ &G_pore_gpe0_queue, //queue
+ gpe_get_per_core_data, //entry point // @th00b
+ //parm for the task
+ (uint32_t) &G_low_cores_data_parms,
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, //callback
+ NULL, //callback argument
+ 0 ); //options
+ if( rc )
+ {
+ //If fail to create pore flex object then there is a problem.
+ TRAC_ERR("Fail to create low cores poreFlex object[0x%x]", rc );
+
+ /*
+ * @errortype
+ * @moduleid PROC_CORE_INIT_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 pore_flex_create return code
+ * @userdata4 ERC_LOW_CORE_PORE_FLEX_CREATE_FAILURE
+ * @devdesc Failure to create low cores poreflex object
+ */
+ l_err = createErrl(
+ PROC_CORE_INIT_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ ERC_LOW_CORE_PORE_FLEX_CREATE_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //TODO: create l_trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ REQUEST_RESET(l_err); // @gm006
+ break;
+ }
+
+ //Initializes existing PoreFlex object for high cores data
+ rc = pore_flex_create( &G_high_cores.gpe_req, //gpe_req for the task
+ &G_pore_gpe0_queue, //queue
+ gpe_get_per_core_data, //entry point // @th00b
+ //parm for the task
+ (uint32_t) &G_high_cores_data_parms,
+ SSX_WAIT_FOREVER, //no timeout
+ NULL, //callback
+ NULL, //callback argument
+ 0 ); //options
+ if( rc )
+ {
+ //If fail to create pore flex object then there is a problem.
+ TRAC_ERR("Fail to create high cores poreFlex object[0x%x]", rc );
+
+ /*
+ * @errortype
+ * @moduleid PROC_CORE_INIT_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 pore_flex_create return code
+ * @userdata4 ERC_HIGH_CORE_PORE_FLEX_CREATE_FAILURE
+ * @devdesc Failure to create high core poreFlex object
+ */
+ l_err = createErrl(
+ PROC_CORE_INIT_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ ERC_HIGH_CORE_PORE_FLEX_CREATE_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //TODO: create l_trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ REQUEST_RESET(l_err); // @gm006
+ break;
+ }
+
+ //>@01a
+ //Initializes PoreFlex object for fast core data
+ rc = pore_flex_create( &G_fast_cores_req, //gpe_req for the task
+ &G_pore_gpe0_queue, //queue
+ gpe_get_core_data_fast, //entry point
+ //parm for the task
+ (uint32_t) &G_chip_data_fast_parms,
+ SSX_WAIT_FOREVER, //no timeout
+ NULL, //callback
+ NULL, //callback argument
+ 0 ); //options
+ if( rc )
+ {
+ //If fail to create pore flex object then there is a problem.
+ TRAC_ERR("Fail to create fast cores poreFlex object[0x%x]", rc );
+
+ /*
+ * @errortype
+ * @moduleid PROC_CORE_INIT_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 pore_flex_create return code
+ * @userdata4 ERC_FAST_CORE_PORE_FLEX_CREATE_FAILURE
+ * @devdesc Failure to create fast core data poreFlex object
+ */
+ l_err = createErrl(
+ PROC_CORE_INIT_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ ERC_FAST_CORE_PORE_FLEX_CREATE_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //TODO: create l_trace point //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ REQUEST_RESET(l_err); // @gm006
+ break;
+ }
+ //<@01a
+
+ } while(0);
+
+ // Initialize the core data control structures at the same time
+ proc_core_data_control_init(); // @th010
+
+ return;
+}
+
+//>@01a
+// Function Specification
+//
+// Name: task_fast_core_data
+//
+// Description: Collect fast core data for all configured cores on every tick.
+//
+// Flow: 10/18/11 FN=task_fast_core_data
+//
+// End Function Specification
+
+void task_fast_core_data( task_t * i_task )
+{
+
+ errlHndl_t l_err = NULL; //Error handler
+ tracDesc_t l_trace = NULL; //Temporary trace descriptor
+ int rc = 0; //Return code
+ gpe_fast_core_data_t * l_temp = NULL;
+ uint32_t l_pres_hw_cores;
+
+ //poll the pmc deconfig register for newly deconfigured cores -- gm022
+ l_pres_hw_cores = (~in32(PMC_CORE_DECONFIGURATION_REG)) & HW_CORES_MASK;
+ if(l_pres_hw_cores != G_present_hw_cores)
+ {
+ TRAC_IMP("Present cores changed. old_hw_mask[0x%04x] new_hw_mask[0x%04x]",
+ G_present_hw_cores, l_pres_hw_cores);
+
+ //update our global core presence masks -- gm022
+ G_present_hw_cores = l_pres_hw_cores;
+ G_present_cores = ((l_pres_hw_cores & LO_CORES_MASK) << 1) |
+ ((l_pres_hw_cores & HI_CORES_MASK) << 3);
+ }
+
+ do
+ {
+ //Check to see if the previous GPE request still running
+ if( !(async_request_is_idle(&G_fast_cores_req.request)) )
+ {
+ //This should not happen unless there's a problem
+ //Trace 1 time
+ if( !G_fast_core_queue_not_idle_traced )
+ {
+ TRAC_ERR("GPE is still running \n");
+ G_fast_core_queue_not_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ //Check to see if the previosuly GPE request has been succeeded
+ if( async_request_completed(&G_fast_cores_req.request) )
+ {
+ //If the previous GPE request succeeded then swap the
+ //G_read_fast_core_data_ptr with the G_write_fast_core_data_ptr.
+
+ //@rc001m
+ PROC_DBG("Fast core data GPE request has been succeeded.\n");
+
+ #ifdef PROC_DEBUG
+ print_fast_core_data();
+ #endif
+
+ l_temp = G_write_fast_core_data_ptr;
+ G_write_fast_core_data_ptr = G_read_fast_core_data_ptr;
+ G_read_fast_core_data_ptr = l_temp;
+ }
+
+ //Setup the get fast core data parms
+ G_chip_data_fast_parms.config = (uint64_t) (((uint64_t) G_present_hw_cores) << 32); // @th008c
+ G_chip_data_fast_parms.select = GPE_GET_CORE_DATA_FAST_FREQ_TARGET; // @th008c
+ G_chip_data_fast_parms.data = (uint32_t) G_write_fast_core_data_ptr;
+
+ //Port flex schedule gpe_get_core_data_fast
+ //Check pore_flex_schedule return code if error
+ //then request OCC reset.
+
+ rc = pore_flex_schedule( &G_fast_cores_req );
+ if( rc != 0 )
+ {
+ //Error in schedule gpe get fast core data
+ TRAC_ERR("Failed PoreFlex schedule fast core data [%x] \n", rc);
+
+ /*
+ * @errortype
+ * @moduleid PROC_TASK_FAST_CORE_DATA_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 pore_flex_schedule return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX PORE related failure
+ */
+ l_err = createErrl(
+ PROC_TASK_FAST_CORE_DATA_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //TODO: create l_trace point //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0 ); //userdata2
+
+ // commit error log
+ REQUEST_RESET(l_err); // @gm006
+ break;
+ }
+ } while(0);
+
+ return;
+}
+
+// Function Specification
+//
+// Name: proc_get_bulk_core_data_ptr
+//
+// Description: Returns a pointer to the most up-to-date bulk core data for
+// the core associated with the specified OCC core id. Returns
+// NULL for core ID outside the range of 0 to 11.
+//
+// Flow: FN=None
+//
+// End Function Specification
+gpe_bulk_core_data_t * proc_get_bulk_core_data_ptr( const uint8_t i_occ_core_id )
+{
+ //The caller needs to send in a valid OCC core id. Since type is uchar
+ //so there is no need to check for case less than 0.
+ //If core id is invalid then returns NULL.
+
+ if( i_occ_core_id <= 11 )
+ {
+ //Returns a pointer to the most up-to-date bulk core data.
+ return G_core_data_ptrs[i_occ_core_id];
+ }
+ else
+ {
+ //Core id outside the range
+ TRAC_ERR("Invalid OCC core id [0x%x]", i_occ_core_id);
+ return( NULL );
+ }
+}
+
+// Function Specification
+//
+// Name: proc_get_fast_core_data_ptr
+//
+// Description: Returns a pointer to the most up-to-date fast core data
+//
+// Flow: FN=None
+//
+// End Function Specification
+gpe_fast_core_data_t * proc_get_fast_core_data_ptr( void )
+{
+ //Returns a pointer to the most up-to-date fast core data.
+ //Core data is organized is organized in hardware scheme.
+
+ return G_read_fast_core_data_ptr;
+}
+//<@01a
+
+
+
+#ifdef PROC_DEBUG
+// Function Specification
+//
+// Name: print_core_data_sensors
+//
+// Description: Print out sensors data of a specified core in the chip
+//
+// Flow: FN=None
+//
+// End Function Specification
+
+void print_core_data_sensors(uint8_t core)
+{
+ gpe_bulk_core_data_t * l_core_data = proc_get_bulk_core_data_ptr(core);
+
+ if( l_core_data != NULL )
+ {
+ //@rc001m
+ PROC_DBG("\n-------------------------------\n");
+ PROC_DBG("Core [%x] Sensors Data \n", core);
+ // @th008 -- commented these out b/c they take too long to run in task.
+ // -- maybe with some creative coding they could be moved to an applet
+ //dumpHexString(&l_core_data->sensors_tod, sizeof(l_core_data->sensors_tod), "Sensor TOD");
+ //dumpHexString(&l_core_data->sensors_v0, sizeof(l_core_data->sensors_v0), "Sensor VO");
+ //dumpHexString(&l_core_data->sensors_v1, sizeof(l_core_data->sensors_v1), "Sensor V1");
+ //dumpHexString(&l_core_data->sensors_v8, sizeof(l_core_data->sensors_v8), "Sensor V8");
+ //dumpHexString(&l_core_data->sensors_v9, sizeof(l_core_data->sensors_v9), "Sensor V9");
+ PROC_DBG("\n");
+ }
+ else
+ {
+ //@rc001m
+ PROC_DBG("\n G_core_data_ptrs[%x] is NULL. This should not happen.\n", core);
+ }
+ return;
+}
+
+// Function Specification
+//
+// Name: print_core_status
+//
+// Description: Print out information of a specified core in the chip
+//
+// Flow: FN=None
+//
+// End Function Specification
+
+void print_core_status(uint8_t core)
+{
+ gpe_bulk_core_data_t * l_core_data = proc_get_bulk_core_data_ptr(core);
+
+ if( l_core_data != NULL )
+ {
+ //@rc001m
+ PROC_DBG("\n-------------------------\n");
+ PROC_DBG("Core [%x] status \n", core);
+ // @th008 -- commented these out b/c they take too long to run in task.
+ // -- maybe with some creative coding they could be moved to an applet
+ //dumpHexString(&l_core_data->core_tod, sizeof(l_core_data->core_tod), "Core TOD");
+ //dumpHexString(&l_core_data->core_raw_cycles, sizeof(l_core_data->core_raw_cycles), "Core Raw Cycles");
+ //dumpHexString(&l_core_data->core_run_cycles, sizeof(l_core_data->core_run_cycles), "Run Cycles");
+ //dumpHexString(&l_core_data->core_dispatch, sizeof(l_core_data->core_dispatch), "Core Dispatch");
+ //dumpHexString(&l_core_data->core_completion, sizeof(l_core_data->core_completion), "Core Completion");
+ //dumpHexString(&l_core_data->core_workrate, sizeof(l_core_data->core_workrate), "Core Workrate");
+ //dumpHexString(&l_core_data->core_spurr, sizeof(l_core_data->core_spurr), "Core Spurr");
+ //dumpHexString(&l_core_data->core_mem_hler_a, sizeof(l_core_data->core_mem_hler_a), "Mem A");
+ //dumpHexString(&l_core_data->core_mem_hler_b, sizeof(l_core_data->core_mem_hler_b), "Mem B");
+ //dumpHexString(&l_core_data->mem_tod, sizeof(l_core_data->mem_tod), "Mem TOD");
+ //dumpHexString(&l_core_data->mem_raw_cycles, sizeof(l_core_data->mem_raw_cycles), "Mem Raw Cycles");
+ PROC_DBG("\n");
+ }
+ else
+ {
+ //@rc001m
+ PROC_DBG("\n G_core_data_ptrs[%x] is NULL. This should not happen.\n", core);
+ }
+ return;
+}
+
+//>@01a
+// Function Specification
+//
+// Name: print_fast_core_data
+//
+// Description: Print out fast core data of the chip
+//
+// Flow: FN=None
+//
+// End Function Specification
+
+void print_fast_core_data(void)
+{
+ gpe_fast_core_data_t * l_fast_core_data = proc_get_fast_core_data_ptr();
+
+ if( l_fast_core_data != NULL )
+ {
+ //@rc001m
+ PROC_DBG("\n---------------------------\n");
+ // @th008 -- commented these out b/c they take too long to run in task.
+ // -- maybe with some creative coding they could be moved to an applet
+ //dumpHexString(&l_fast_core_data->tod, sizeof(l_fast_core_data->tod), "Fast Core Data TOD");
+ //dumpHexString(&l_fast_core_data->core_data, sizeof(fast_core_data_t) * MAX_NUM_HW_CORES, "Fast Core Data");
+ PROC_DBG("\n");
+ }
+ else
+ {
+ //@rc001m
+ PROC_DBG("\n G_read_fast_core_data_ptr is NULL. This should not happen.\n");
+ }
+ return;
+}
+//<@01a
+#endif
+
diff --git a/src/occ/proc/proc_data.h b/src/occ/proc/proc_data.h
new file mode 100755
index 0000000..05f6913
--- /dev/null
+++ b/src/occ/proc/proc_data.h
@@ -0,0 +1,255 @@
+/******************************************************************************
+// @file proc_data.h
+// @brief Data codes for proc component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _proc_data_h proc_data.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * nguyenp 09/27/2011 Created
+ * nguyenp 09/27/2011 Added bulk core data and proc core
+ * initilization code.
+ * @01 nguyenp 10/19/2011 Added fast core data code.
+ * Added new interfaces to gain access to
+ * bulk core and fast core data.
+ * Added macro to translate occ core id
+ * to hardware core id and vice versa.
+ * @rc001 rickylie 12/30/2011 Moved debug trace defines to trac.h
+ * remove print_core_data_sensors
+ * remove print_core_status
+ * remove print_fast_core_data
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/12 Added a couple enums,defines,macros
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th00f thallet 06/27/2012 Change to use Core Data struct as provided by HW team
+ * @sbpde 922027 sbroyles 04/04/2014 Add empath error core mask
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _PROC_DATA_H
+#define _PROC_DATA_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include "rtls.h"
+#include "gpe_data.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+//>@01a
+//Returns 0 if the specified core is not present. Otherwise, returns none-zero.
+#define CORE_PRESENT(occ_core_id) \
+ ((CORE0_PRESENT_MASK >> occ_core_id) & G_present_cores)
+
+//Takes an OCC core id and converts it to a core id that
+//can be used by the hardware. The caller needs to send in
+//a valid core id. Since type is uchar so there is no need to check for
+//case less than 0. If core id is invalid then returns unconfigured core 16.
+#define CORE_OCC2HW(occ_core_id) \
+ ((occ_core_id <= 15) ? G_occ2hw_core_id[occ_core_id] : 16)
+
+//Takes a hardware core id and returns a OCC core id.
+//The caller needs to send in a valid core id. Since type is uchar so
+//there is no need to check for case less than 0. If core id
+//is invalid then returns unconfigured core 16.
+#define CORE_HW2OCC(hw_core_id) \
+ ((hw_core_id <= 15) ? G_hw2occ_core_id[hw_core_id] : 16)
+//<@01a
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define ALL_CORES_MASK 0xffff0000
+#define CORE0_PRESENT_MASK 0x80000000ul
+#define CORE0_PRESENT_MASK_GPE 0x8000000000000000ull // @th008a
+
+#define MAX_NUM_HW_CORES 16
+#define MAX_NUM_FW_CORES 12
+
+#define THREADS_PER_CORE 8
+#define MAX_MEM_PARTS 4
+
+//>@01a
+#define NUM_FAST_CORE_DATA_BUFF 2
+#define NUM_CORE_DATA_BUFF 7 // @th00b
+#define NUM_CORE_DATA_DOUBLE_BUF 2 // @th00b
+#define NUM_CORE_DATA_EMPTY_BUF 1 // @th00b
+
+#define LO_CORES_MASK 0x7e000000
+#define HI_CORES_MASK 0x007e0000
+#define HW_CORES_MASK 0xffff0000
+//<@01a
+
+enum eOccProcCores
+{
+ CORE_0 = 0,
+ CORE_1 = 1,
+ CORE_2 = 2,
+ CORE_3 = 3,
+ CORE_4 = 4,
+ CORE_5 = 5,
+ CORE_6 = 6,
+ CORE_7 = 7,
+ CORE_8 = 8,
+ CORE_9 = 9,
+ CORE_10 = 10,
+ CORE_11 = 11,
+}; // @th00b
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+typedef CoreData gpe_bulk_core_data_t; // @th00f
+
+//Processor data collect structures used for task data pointers
+//gpe_req.request.parameter points to GpeGetCoreDataParms
+struct bulk_core_data_task {
+ uint8_t start_core;
+ uint8_t current_core;
+ uint8_t end_core;
+ gpe_bulk_core_data_t * core_data_ptr;
+ PoreFlex gpe_req;
+} __attribute__ ((__packed__));
+typedef struct bulk_core_data_task bulk_core_data_task_t;
+
+//>@01a
+//Only PCBS_LOCAL_PSTATE_FREQ_TARGET_STATUS_REG register is being
+//collected at this time. Other register will be added when needed.
+struct fast_core_data {
+ uint64_t pcbs_lpstate_freq_target_sr;
+} __attribute__ ((__packed__));
+typedef struct fast_core_data fast_core_data_t;
+
+//gpe fast core data structure
+struct gpe_fast_core_data {
+ uint32_t tod;
+ uint32_t reserved;
+ fast_core_data_t core_data[MAX_NUM_HW_CORES];
+} __attribute__ ((__packed__));
+typedef struct gpe_fast_core_data gpe_fast_core_data_t;
+//<@01a
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//Global low and high cores structures used for task data pointers
+extern bulk_core_data_task_t G_low_cores;
+extern bulk_core_data_task_t G_high_cores;
+
+//Global G_present_cores is bitmask of all OCC core numbering
+extern uint32_t G_present_cores;
+
+//>@01a
+//Global G_present_hw_cores is bitmask of all hardware cores
+extern uint32_t G_present_hw_cores;
+extern uint8_t G_occ2hw_core_id[MAX_NUM_HW_CORES];
+extern uint8_t G_hw2occ_core_id[MAX_NUM_HW_CORES];
+//<@01a
+
+//AMEC needs to know when data for a core has been collected.
+extern uint32_t G_updated_core_mask;
+
+// >> @sbpde
+// External reference to empath error mask
+extern uint32_t G_empath_error_core_mask;
+// << @sbpde
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+/*----------------------------------------------------------------------------*/
+/* Macros */
+/*----------------------------------------------------------------------------*/
+//Returns 0 if the specified core is not present. Otherwise, returns none-zero.
+#define CORE_PRESENT(occ_core_id) \
+ ((CORE0_PRESENT_MASK >> occ_core_id) & G_present_cores)
+
+//Returns 0 if the specified core is not updated. Otherwise, returns none-zero.
+#define CORE_UPDATED(occ_core_id) \
+ ((CORE0_PRESENT_MASK >> occ_core_id) & G_updated_core_mask)
+
+//Returns 0 if the specified core is not updated. Otherwise, returns none-zero.
+#define CLEAR_CORE_UPDATED(occ_core_id) \
+ G_updated_core_mask &= ~(CORE0_PRESENT_MASK >> occ_core_id)
+
+// >> @sbpde
+// Evaluates to true if an empath collection error has occurred on a core
+#define CORE_EMPATH_ERROR(occ_core_id) \
+ ((CORE0_PRESENT_MASK >> occ_core_id) & G_empath_error_core_mask)
+// << @sbpde
+
+//Takes an OCC core id and converts it to a core id that
+//can be used by the hardware. The caller needs to send in
+//a valid core id. Since type is uchar so there is no need to check for
+//case less than 0. If core id is invalid then returns unconfigured core 16.
+#define CORE_OCC2HW(occ_core_id) \
+ ((occ_core_id <= 15) ? G_occ2hw_core_id[occ_core_id] : 16)
+
+//Takes a hardware core id and returns a OCC core id.
+//The caller needs to send in a valid core id. Since type is uchar so
+//there is no need to check for case less than 0. If core id
+//is invalid then returns unconfigured core 16.
+#define CORE_HW2OCC(hw_core_id) \
+ ((hw_core_id <= 15) ? G_hw2occ_core_id[hw_core_id] : 16)
+//<@01a
+
+/*----------------------------------------------------------------------------*/
+/* Collect bulk core data function */
+/*----------------------------------------------------------------------------*/
+//Collect bulk core data for all cores in specified range
+void task_core_data( task_t * i_task );
+
+/*----------------------------------------------------------------------------*/
+/* proc core initialization function */
+/*----------------------------------------------------------------------------*/
+//Initialize structures for collecting core data.
+void proc_core_init( void ) INIT_SECTION;
+
+//>@01a
+/*----------------------------------------------------------------------------*/
+/* Collect fast core data function */
+/*----------------------------------------------------------------------------*/
+//Collect fast core data for all configured cores on every tick
+void task_fast_core_data( task_t * i_task );
+
+/*----------------------------------------------------------------------------*/
+/* Get bulk core data pointer */
+/*----------------------------------------------------------------------------*/
+//Returns a pointer to the most up-to-date bulk core data for the core
+//associated with the specified OCC core id.
+gpe_bulk_core_data_t * proc_get_bulk_core_data_ptr( const uint8_t i_occ_core_id );
+
+/*----------------------------------------------------------------------------*/
+/* Get fast core data pointer */
+/*----------------------------------------------------------------------------*/
+//Returns a pointer to the most up-to-date fast core data
+gpe_fast_core_data_t * proc_get_fast_core_data_ptr( void );
+//<@01a
+
+/*----------------------------------------------------------------------------*/
+/* Debug */
+/*----------------------------------------------------------------------------*/
+//@rc001
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_PROC_DATA_H
diff --git a/src/occ/proc/proc_data_control.c b/src/occ/proc/proc_data_control.c
new file mode 100755
index 0000000..f87625f
--- /dev/null
+++ b/src/occ/proc/proc_data_control.c
@@ -0,0 +1,312 @@
+/******************************************************************************
+// @file proc_data_control.c
+// @brief Data codes for proc component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _proc_data_control_c proc_data_control.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th010 thallet 06/27/2012 Created
+ * @th014 thallet 08/02/2012 Temporary Control Data Fix & TODO flags added
+ * @th015 thallet 08/03/2012 Set core Pstates function
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm008 SW226989 milesg 09/30/2013 Sapphire initial support
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "proc_data.h"
+#include "pgp_async.h"
+#include "threadSch.h"
+#include "pmc_register_addresses.h"
+#include "proc_data_service_codes.h"
+#include "occ_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "apss.h"
+#include "state.h"
+#include "gpe_control.h"
+#include "occ_sys_config.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Pore flex request for GPE job. The initialization will be done one time
+// during pore flex create.
+PoreFlex G_core_data_control_req;
+
+// Global double buffering for core data control
+GPE_BUFFER(PcbsPstateRegs G_core_data_control_a[MAX_NUM_HW_CORES]) = {{{0}}};
+GPE_BUFFER(PcbsPstateRegs G_core_data_control_b[MAX_NUM_HW_CORES]) = {{{0}}};
+
+// Pointer to the core data control that will be used by GPE engine.
+GPE_BUFFER(PcbsPstateRegs * G_core_data_control_gpewrite_ptr) = { &G_core_data_control_a[0] };
+
+// Pointer to the core data control that will be written to by the OCC FW.
+GPE_BUFFER(PcbsPstateRegs * G_core_data_control_occwrite_ptr) = { &G_core_data_control_b[0] };
+
+// The Gpe parameter fields are set up each time before the GPE starts.
+GPE_BUFFER(GpeSetPstatesParms G_core_data_control_parms);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: proc_set_pstate
+//
+// Description: Function to demonstrate setting Pstates to all cores
+// Should only be run from RTL
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+void proc_set_pstate_all(Pstate i_pstate)
+{
+ uint8_t l_chiplet = 0;
+
+ for(; l_chiplet<MAX_NUM_HW_CORES; l_chiplet++)
+ {
+ set_chiplet_pstate(G_core_data_control_occwrite_ptr,
+ l_chiplet,
+ i_pstate,
+ i_pstate);
+ }
+
+ PROC_DBG("Setting Pstates to %d\n",i_pstate);
+}
+
+
+// Function Specification
+//
+// Name: proc_set_core_pstate
+//
+// Description: Function to demonstrate setting Pstates to all cores
+// Should only be run from RTL
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+void proc_set_core_pstate(Pstate i_pstate, uint8_t i_core)
+{
+ set_chiplet_pstate(G_core_data_control_occwrite_ptr,
+ CORE_OCC2HW(i_core),
+ i_pstate,
+ i_pstate);
+}
+
+// gm025
+// Function Specification
+//
+// Name: proc_set_core_bounds
+//
+// Description: Function to set core pmin/pmax
+// Should only be run from RTL
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+void proc_set_core_bounds(Pstate i_pmin, Pstate i_pmax, uint8_t i_core)
+{
+ Pstate l_pmax;
+ uint8_t l_hw_core = CORE_OCC2HW(i_core);
+
+ //don't allow pmax to be set lower than pmin
+ if(i_pmax < i_pmin)
+ {
+ l_pmax = i_pmin;
+ }
+ else
+ {
+ l_pmax = i_pmax;
+ }
+
+ set_chiplet_pmax(G_core_data_control_occwrite_ptr,
+ l_hw_core,
+ l_pmax);
+ set_chiplet_pmin(G_core_data_control_occwrite_ptr,
+ l_hw_core,
+ i_pmin);
+}
+
+
+// Function Specification
+//
+// Name: proc_core_data_control_init
+//
+// Description: Initializations needed for core data control task
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+void proc_core_data_control_init( void )
+{
+ errlHndl_t l_err = NULL; //Error handler
+ tracDesc_t l_trace = NULL; //Temporary trace descriptor
+ int rc = 0; //Return code
+
+ do
+ {
+ //Initializes PoreFlex object for fast core data
+ rc = pore_flex_create( &G_core_data_control_req, //gpe_req for the task
+ &G_pore_gpe0_queue, //queue
+ gpe_set_pstates, //entry point
+ (uint32_t) &G_core_data_control_parms, //parm for the task
+ SSX_WAIT_FOREVER, //no timeout
+ NULL, //callback
+ NULL, //callback argument
+ 0 ); //options
+ if( rc )
+ {
+ //If fail to create pore flex object then there is a problem.
+ TRAC_ERR("Fail to create core control poreFlex object[0x%x]", rc );
+
+ /*
+ * @errortype
+ * @moduleid PROC_CORE_INIT_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 pore_flex_create return code
+ * @userdata4 ERC_PROC_CONTROL_INIT_FAILURE
+ * @devdesc Failure to create poreflex object
+ */
+ l_err = createErrl(
+ PROC_CORE_INIT_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ ERC_PROC_CONTROL_INIT_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //TODO: create l_trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ REQUEST_RESET(l_err); //$gm006
+ break;
+ }
+
+ } while(0);
+}
+
+// Function Specification
+//
+// Name: task_core_data_control
+//
+// Description: Control core actuation for all configured cores on every tick.
+//
+// Flow: 07/02/12 FN=task_core_data_control
+//
+// End Function Specification
+void task_core_data_control( task_t * i_task )
+{
+ errlHndl_t l_err = NULL; //Error handler
+ tracDesc_t l_trace = NULL; //Temporary trace descriptor
+ int rc = 0; //Return code
+ PcbsPstateRegs * l_temp = NULL;
+
+ do
+ {
+
+ //Check to see if the previous GPE request still running
+ if( !(async_request_is_idle(&G_core_data_control_req.request)) )
+ {
+ // Trace 1 time - This should not happen
+
+ //if( !G_fast_core_queue_not_idle_traced )
+ //{
+ // TRAC_ERR("GPE is still running \n");
+ // G_fast_core_queue_not_idle_traced = TRUE;
+ //}
+ break;
+ }
+
+ //Check to see if the previosuly GPE request has been succeeded
+ if( async_request_completed(&G_core_data_control_req.request) )
+ {
+ //If the previous GPE request succeeded then swap the
+ //gpewrite ptr with the occwrite ptr.
+ l_temp = G_core_data_control_occwrite_ptr;
+ // TODO: For now, set these ptrs equal to each other
+ // This data is not thread-safe/interrupt safe
+ // but will need to fix this later.
+ //G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr; // TODO: @th014
+ G_core_data_control_gpewrite_ptr = l_temp;
+ }
+
+ //Setup the core data control parms
+ G_core_data_control_parms.config = (uint64_t) (((uint64_t) G_present_hw_cores) << 32);
+ if(G_sysConfigData.system_type.kvm) //gm025
+ {
+ //Set the chiplet bounds (pmax/pmin) only on sapphire
+ G_core_data_control_parms.select = GPE_SET_PSTATES_PMBR;
+ }
+ else
+ {
+ //Set the chiplet pstate request on non-sapphire systems
+ G_core_data_control_parms.select = GPE_SET_PSTATES_PMCR;
+ }
+
+ G_core_data_control_parms.regs = (uint32_t) G_core_data_control_gpewrite_ptr;
+
+ rc = pore_flex_schedule( &G_core_data_control_req );
+ if( rc != 0 )
+ {
+ TRAC_ERR("Failed PoreFlex schedule core data control [%x] \n", rc);
+
+ /*
+ * @errortype
+ * @moduleid PROC_TASK_CORE_DATA_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 pore_flex_schedule return code
+ * @userdata4 ERC_PROC_CONTROL_TASK_FAILURE
+ * @devdesc Failure to schedule poreflex object
+ */
+ l_err = createErrl(
+ PROC_TASK_CORE_DATA_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ ERC_PROC_CONTROL_TASK_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //TODO: create l_trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ REQUEST_RESET(l_err); //@gm006
+ break;
+ }
+ } while(0);
+
+ return;
+}
+
+
diff --git a/src/occ/proc/proc_data_control.h b/src/occ/proc/proc_data_control.h
new file mode 100755
index 0000000..cb4d0d1
--- /dev/null
+++ b/src/occ/proc/proc_data_control.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+// @file proc_data_control.h
+// @brief Data codes for proc component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _proc_data_h proc_data.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th010 thallet 07/11/2012 Created
+ * @th015 thallet 08/03/2012 Function to set core Pstates
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _PROC_DATA_CONTROL_H
+#define _PROC_DATA_CONTROL_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <ssx.h>
+#include "rtls.h"
+#include "gpe_control.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+// Initialze the structures used by the GPE
+void proc_core_data_control_init( void );
+
+// Task that sets the PMCR, PMBR, PMICR
+void task_core_data_control( task_t * i_task );
+
+// Function to demonstrate setting Pstates to all cores
+void proc_set_pstate_all(Pstate i_pstate);
+
+// Function to demonstrate setting Pstates one core
+void proc_set_core_pstate(Pstate i_pstate, uint8_t i_core);
+
+// Sets the Pmin/Pmax clip values for one core
+void proc_set_core_bounds(Pstate i_pmin, Pstate i_pmax, uint8_t i_core);
+#endif
diff --git a/src/occ/proc/proc_data_service_codes.h b/src/occ/proc/proc_data_service_codes.h
new file mode 100755
index 0000000..3cf8eb4
--- /dev/null
+++ b/src/occ/proc/proc_data_service_codes.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+// @file proc_data_service_codes.h
+// @brief Error codes for proc component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _proc_data_service_codes_h proc_data_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * nguyenp 09/23/2011 Created
+ * @01 nguyenp 10/19/2011 Added task fast core data module id.
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _PROC_DATA_SERVICE_CODES_H_
+#define _PROC_DATA_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum procModuleId
+{
+ PROC_TASK_CORE_DATA_MOD = PROC_COMP_ID | 0x00,
+ PROC_CORE_INIT_MOD = PROC_COMP_ID | 0x01,
+ PROC_TASK_FAST_CORE_DATA_MOD = PROC_COMP_ID | 0x02, //@01a
+ PROC_GPST_INIT_FAILURE_MOD = PROC_COMP_ID | 0x03,
+ PROC_ENABLE_PSTATES_SMH_MOD = PROC_COMP_ID | 0x04, //@gm006
+ PROC_PSTATE_KVM_SETUP_MOD = PROC_COMP_ID | 0x05, //@gm025
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _PROC_DATA_SERVICE_CODES_H_ */
diff --git a/src/occ/proc/proc_pstate.c b/src/occ/proc/proc_pstate.c
new file mode 100755
index 0000000..b5c4376
--- /dev/null
+++ b/src/occ/proc/proc_pstate.c
@@ -0,0 +1,1171 @@
+/******************************************************************************
+// @file proc_pstate.c
+// @brief OCC Handling of Pstates
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _proc_pstate_c proc_pstate.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th010 thallet 07/10/2012 Created
+ * @th014 thallet 08/02/2012 Updated PstateSS & TODO flags added
+ * @th015 thallet 08/03/2012 Bounds checking on freq2pstate
+ * @th025 857856 thallet 10/16/2012 Dcom Master Slave SMS part 2
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup Changes
+ * @th035 881654 thallet 05/06/2013 Tuleta Bringup Pstate Fixes
+ * @th036 881677 thallet 05/07/2013 Cleanup
+ * @th040 887069 thalllet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @fk001 879727 fmkassem 04/16/2013 PCAP support.
+ * @ly009 895318 lychen 08/13/2013 OCC-Sapphire shared memory interface
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm011 903410 milesg 10/22/2013 Fail on murano dd10 or dd11 chips
+ * @ly010 908832 lychen 12/09/2013 Sapphire update status for reset
+ * @gm022 908890 milesg 01/23/2014 Fixed pstate table traces
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @wb003 920760 wilbryan 03/25/2014 Update SRCs to match TPMD SRCs
+ * @gm033 920448 milesg 03/26/2014 use getscom/putscom ffdc wrapper
+ * @gs032 925755 gjsilva 05/07/2014 Optimize freq2pstate function
+ * @gs033 929049 gjsilva 06/13/2014 Fix computation of pstate
+ * @gs044 943766 gjsilva 11/03/2014 Clear bit 11 of PCBS_PMGP1_REG during KVM setup
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "proc_data_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "dcom.h"
+#include "occ_common.h"
+#include "state.h"
+#include "cmdh_fsp_cmds.h"
+#include "cmdhDbugCmd.h"
+#include "appletManager.h"
+#include "gpsm.h"
+#include "pstates.h"
+#include "proc_data.h"
+#include "proc_pstate.h"
+#include "scom.h"
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// GPSM DCM Synchronization States
+typedef enum
+{
+ PROC_GPSM_SYNC_NO_PSTATE_TABLE = 0,
+ PROC_GPSM_SYNC_PSTATE_TABLE_INSTALLED = 1,
+ PROC_GPSM_SYNC_READY_TO_ENABLE_MASTER = 2,
+ PROC_GPSM_SYNC_PSTATE_MASTER_ENABLED = 3,
+ PROC_GPSM_SYNC_READY_TO_ENABLE_SLAVE = 4,
+ PROC_GPSM_SYNC_PSTATE_SLAVE_ENABLED = 5,
+ PROC_GPSM_SYNC_PSTATE_HW_MODE = 6,
+ PROC_GPSM_SYNC_PSTATE_HW_MODE_ENABLED = 7,
+ PROC_GPSM_SYNC_PSTATE_ERROR,
+} eProcGpsmDcmSyncStates;
+
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Instance of the PState Table in OCC SRAM. Should be placed in RO section
+// so that OCC FW can't corrupt it
+GLOBAL_PSTATE_TABLE(G_global_pstate_table);
+
+// Used for passing DCM Master & Slave States to each other over MBOX
+proc_gpsm_dcm_sync_occfw_t G_proc_dcm_sync_state = {0, PROC_GPSM_SYNC_NO_PSTATE_TABLE, PROC_GPSM_SYNC_NO_PSTATE_TABLE,0,0};
+
+// Holds Fmax from GPST for ease of proc_freq2pstate calculation
+uint32_t G_proc_gpst_fmax = 0;
+
+// Holds Fmin from GPST for ease of proc_freq2pstate calculation
+uint32_t G_proc_gpst_fmin = 0;
+
+// Holds Pmax from GPST for ease of proc_freq2pstate calculation
+int8_t G_proc_gpst_pmax = 0;
+
+// Remembers if we are a DCM, for DCOM's sake
+bool G_isDcm = FALSE;
+
+// Used for Sapphire
+DMA_BUFFER( sapphire_table_t G_sapphire_table ) = {{0}}; // @ly009a
+
+//KVM throttle reason coming from the frequency voting box.
+extern uint8_t G_amec_kvm_throt_reason;
+
+//*************************************************************************
+// Forward Declarations
+//*************************************************************************
+
+// Set DCM Sync State
+void proc_gpsm_dcm_sync_set_state(eProcGpsmDcmSyncStates i_dcm_sync_state);
+
+// Tracing out pstate table when it gets installed
+void proc_trace_pstate_table_quick(void);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
+// Function Specification
+//
+// Name: proc_is_hwpstate_enabled
+//
+// Description: Checks DCM Master (or SCM) state to see if Pstate HW Mode
+// is enabled. We can check the DCM master state, since DCM
+// slave also knows the master and DCM master can't be in this
+// state if DCM slave isn't in HW mode
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+bool proc_is_hwpstate_enabled(void)
+{
+ return ((PROC_GPSM_SYNC_PSTATE_HW_MODE_ENABLED == G_proc_dcm_sync_state.sync_state_master) ? TRUE : FALSE);
+}
+
+
+// Function Specification
+//
+// Name: proc_gpsm_dcm_sync_update_from_mbox
+//
+// Description: Updates the global variable used for DCM sync based on the
+// data that was received via the master/slave mailbox.
+//
+// Thread: Interrupt; Callback when Slave Inbox is received
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void proc_gpsm_dcm_sync_update_from_mbox(proc_gpsm_dcm_sync_occfw_t * i_dcm_sync_state)
+{
+ if(!gpsm_dcm_slave_p())
+ {
+ G_proc_dcm_sync_state.sync_state_slave = i_dcm_sync_state->sync_state_slave;
+ }
+ else
+ {
+ G_proc_dcm_sync_state.sync_state_master = i_dcm_sync_state->sync_state_master;
+ G_proc_dcm_sync_state.pstate_v = i_dcm_sync_state->pstate_v;
+ G_proc_dcm_sync_state.pstate_f = i_dcm_sync_state->pstate_f;
+ }
+}
+
+
+// Function Specification
+//
+// Name: proc_gpsm_dcm_sync_get_state
+//
+// Description: Return the global variable used for DCM sync
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+inline proc_gpsm_dcm_sync_occfw_t proc_gpsm_dcm_sync_get_state(void)
+{
+ return G_proc_dcm_sync_state;
+}
+
+
+// Function Specification
+//
+// Name: proc_is_dcm
+//
+// Description: Return if we are a DCM or not
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+inline bool proc_is_dcm(void)
+{
+ return G_isDcm;
+}
+
+
+// Function Specification
+//
+// Name: proc_gpsm_dcm_sync_set_state
+//
+// Description: Set the state of global variable used for DCM sync
+// Differnt nybble will get set depending on if we are
+// DCM Master or DCM Slave
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+inline void proc_gpsm_dcm_sync_set_state(eProcGpsmDcmSyncStates i_dcm_sync_state)
+{
+ if(!gpsm_dcm_slave_p())
+ {
+ G_proc_dcm_sync_state.sync_state_master = i_dcm_sync_state;
+ }
+ else
+ {
+ G_proc_dcm_sync_state.sync_state_slave = i_dcm_sync_state;
+ }
+}
+
+
+// Function Specification
+//
+// Name: proc_gpsm_dcm_sync_get_state
+//
+// Description: Return the state of global variable used for DCM sync
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+eProcGpsmDcmSyncStates proc_gpsm_dcm_sync_get_my_state(void)
+{
+ if(!gpsm_dcm_slave_p())
+ {
+ return G_proc_dcm_sync_state.sync_state_master;
+ }
+ else
+ {
+ return G_proc_dcm_sync_state.sync_state_slave;
+ }
+} // Added @th025
+
+
+// Function Specification
+//
+// Name: proc_trace_pstate_table_quick
+//
+// Description: Debug Function to Print portion of Pstate Table
+// Eventually, this should trace key elements of Pstate
+// table to Trace Buffer.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void proc_trace_pstate_table_quick(void)
+{
+ GlobalPstateTable * l_gpst_ptr = NULL;
+
+ l_gpst_ptr = gpsm_gpst();
+ // Check the pointer since it may not have been installed on chips with 0 configured cores -- gm011
+ if(l_gpst_ptr == &G_global_pstate_table)
+ {
+ TRAC_IMP("GPST Installed: Pstate[0]: %d kHz, Step: %d kHz, Entries: %d, Pvsafe[%d], Psafe[%d]",
+ l_gpst_ptr->pstate0_frequency_khz,
+ l_gpst_ptr->frequency_step_khz,
+ (int8_t) l_gpst_ptr->entries,
+ (int8_t) l_gpst_ptr->pvsafe,
+ (int8_t) l_gpst_ptr->psafe
+ );
+
+ TRAC_IMP("Pmin[%d]: %d kHz, Pmax[%d]: %d kHz",
+ (int8_t) l_gpst_ptr->pmin,
+ (l_gpst_ptr->pstate0_frequency_khz + ((int8_t) l_gpst_ptr->pmin) * l_gpst_ptr->frequency_step_khz),
+ ((int8_t) l_gpst_ptr->pmin + l_gpst_ptr->entries - 1),
+ (l_gpst_ptr->pstate0_frequency_khz + ((int8_t) l_gpst_ptr->pmin + l_gpst_ptr->entries - 1) * l_gpst_ptr->frequency_step_khz)
+ );
+ }
+ else //gm011
+ {
+ //This likely means that the processor has no configured cores (may not be an error scenario)
+ TRAC_IMP("GPST not installed. hw pointer= 0x%08x, present cores= 0x%08x", (uint32_t)l_gpst_ptr, G_present_cores);
+ }
+}
+
+
+// Function Specification
+//
+// Name: proc_pstate2freq
+//
+// Description: Convert Pstate to Frequency
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint32_t proc_pstate2freq(Pstate i_pstate)
+{
+ uint32_t l_freq = 0;
+ int8_t l_pmax = 0;
+ GlobalPstateTable * l_gpst_ptr = NULL;
+
+ do
+ {
+ // Get pointer to Pstate table
+ l_gpst_ptr = gpsm_gpst();
+
+ // Return the zero frequency if we don't have a PstateTable installed
+ if(&G_global_pstate_table != l_gpst_ptr)
+ {
+ l_freq = 0;
+ break;
+ }
+
+ // Calculate Pmax, since it is derived instead of being a explicit member
+ l_pmax = ((int8_t) l_gpst_ptr->pmin + l_gpst_ptr->entries - 1);
+
+ if(i_pstate < l_gpst_ptr->pmin)
+ {
+ // If passed in Pstate is lower than Pmin, just use Pmin
+ i_pstate = l_gpst_ptr->pmin;
+ }
+ else if (i_pstate > l_pmax)
+ {
+ // If passed in Pstate is greater than Pmax, just use Pmax
+ i_pstate = l_pmax;
+ }
+
+ // Calculate Frequency based on Pstate
+ l_freq = (l_gpst_ptr->pstate0_frequency_khz + ((int8_t) i_pstate) * l_gpst_ptr->frequency_step_khz);
+ l_freq /= 1000; // Convert to MHz
+ }
+ while(0);
+
+ return l_freq; // MHz
+}
+
+
+// Function Specification
+//
+// Name: proc_freq2pstate
+//
+// Description: Convert Frequency to Nearest Pstate
+//
+//
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+Pstate proc_freq2pstate(uint32_t i_freq_mhz)
+{
+ GlobalPstateTable * l_gpst_ptr = NULL;
+ int8_t l_pstate = PSTATE_MIN;
+ int8_t l_temp_pstate = 0;
+ int32_t l_temp_freq = 0;
+ uint32_t l_freq_khz = 0;
+
+ do
+ {
+ // Get pointer to Pstate table
+ l_gpst_ptr = gpsm_gpst();
+
+ // Return the minimum PState if we don't have a PstateTable installed
+ if(&G_global_pstate_table != l_gpst_ptr)
+ {
+ break;
+ }
+
+ // Freq Units need to be in kHz, not Mhz for the following calculations
+ l_freq_khz = i_freq_mhz * 1000;
+
+ // Make sure that we don't ever get a frequency below the min Freq from
+ // def file
+ if(i_freq_mhz < G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY])
+ {
+ l_freq_khz = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY] * 1000;
+ }
+
+ if(l_freq_khz < G_proc_gpst_fmax)
+ {
+ // First, calculate the delta between passed in freq, and Pmin
+ l_temp_freq = l_freq_khz - G_proc_gpst_fmin;
+
+ // Check if the passed in frequency is smaller than anything in the
+ // table
+ if(l_freq_khz <= G_proc_gpst_fmin)
+ {
+ // We need to substract a full step (minus 1) to make sure we
+ // are keeping things safe
+ l_temp_freq -= (l_gpst_ptr->frequency_step_khz - 1);
+ }
+
+ // Next, calculate how many Pstate steps there are in that delta
+ l_temp_pstate = l_temp_freq / (int32_t)l_gpst_ptr->frequency_step_khz;
+
+ // Lastly, calculate Pstate, by adding delta Pstate steps to Pmin
+ l_pstate = l_gpst_ptr->pmin + l_temp_pstate;
+ }
+ else
+ {
+ // Freq is bigger than anything in table -- return Pmax
+ l_pstate = G_proc_gpst_pmax;
+ }
+ }
+ while(0);
+
+ return (Pstate) l_pstate;
+}
+
+
+// Function Specification
+//
+// Name: proc_gpsm_pstate_initialize
+//
+// Description: Initialize Pstate Table (and the rest of the Pstate
+// SuperStructure). Also, initialize Global variables
+// that will speed up the proc_freq2pstate function.
+//
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t proc_gpsm_pstate_initialize(const PstateSuperStructure* i_pss)
+{
+ errlHndl_t l_errlHndl = NULL;
+ GlobalPstateTable * l_gpst_ptr = NULL;
+ int l_rc = 0;
+
+ do
+ {
+ /// Because early EC's of the Murano chip did not have valid #V data,
+ /// we need to exclude them from loading a pstate table created by a
+ /// hardware procedure. If we run a table created from a #V on these
+ /// chips, we could crash the box (or worse, burn something up!)
+ if ( (cfam_id() == CFAM_CHIP_ID_MURANO_10)
+ || (cfam_id() == CFAM_CHIP_ID_MURANO_11) )
+ {
+ TRAC_ERR("OCC not supported on murano dd10 or dd11 due to bad #V data. chip id = 0x%08x"); //gm011
+ // Create Error Log and return to caller
+ /* @
+ * @errortype
+ * @moduleid PROC_GPST_INIT_FAILURE_MOD
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 chip id
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC not supported on Murano DD10 or DD11
+ */
+ l_errlHndl = createErrl(
+ PROC_GPST_INIT_FAILURE_MOD, //modId
+ INTERNAL_FAILURE, //reasoncode // @wb003
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ cfam_id(), //userdata1
+ 0 //userdata2
+ );
+
+ //callout the processor
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ break;
+ }
+
+ l_rc = gpsm_initialize(i_pss, &G_global_pstate_table);
+
+ // Print key elements of table for debug
+ proc_trace_pstate_table_quick();
+
+ // Get Pstate Table Ptr
+ l_gpst_ptr = gpsm_gpst();
+
+ if(l_rc || (l_gpst_ptr != &G_global_pstate_table)) //gm011
+ {
+ TRAC_ERR("gpsm_initialize failed with rc=0x%08x or l_gpstr_ptr=0x%08x", l_rc, l_gpst_ptr);
+
+ // Create Error Log and return to caller
+ /* @
+ * @errortype
+ * @moduleid PROC_GPST_INIT_FAILURE_MOD
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 SRAM Address of the Pstate Table
+ * @userdata2 Return Code of call that failed
+ * @userdata4 ERC_PROC_PSTATE_INSTALL_FAILURE
+ * @devdesc Failed to install Pstate Table
+ */
+ l_errlHndl = createErrl(
+ PROC_GPST_INIT_FAILURE_MOD, //modId
+ INTERNAL_FAILURE, //reasoncode // @wb003
+ ERC_PROC_PSTATE_INSTALL_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ (uint32_t) &G_global_pstate_table, //userdata1
+ l_rc //userdata2
+ );
+
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_MED);
+ break;
+ }
+
+
+ // set up key globals based on the pstate table.
+
+ // Set the pstate state (state machine will start enabling pstates
+ // when it sees this)
+ proc_gpsm_dcm_sync_set_state(PROC_GPSM_SYNC_PSTATE_TABLE_INSTALLED);
+
+ // Set up Key Globals for use by proc_freq2pstate functions
+ G_proc_gpst_fmax = l_gpst_ptr->pstate0_frequency_khz
+ + (((int8_t) l_gpst_ptr->pmin + l_gpst_ptr->entries - 1)
+ * l_gpst_ptr->frequency_step_khz);
+ G_proc_gpst_fmin = l_gpst_ptr->pstate0_frequency_khz
+ + (((int8_t) l_gpst_ptr->pmin)
+ * l_gpst_ptr->frequency_step_khz);
+ G_proc_gpst_pmax = l_gpst_ptr->pmin + l_gpst_ptr->entries - 1;
+
+ // Dcom uses this to know whether to pass DCM msgs or not.
+ G_isDcm = gpsm_dcm_mode_p();
+
+ // Set globals used by amec for pcap calculation
+ G_mhz_per_pstate = (l_gpst_ptr->frequency_step_khz)/1000;
+
+ }while(0);
+
+ return l_errlHndl;
+}
+
+
+// gm025
+// Function Specification
+//
+// Name: proc_pstate_kvm_setup
+//
+// Description: Get everything set up for KVM mode
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void proc_pstate_kvm_setup()
+{
+ int l_core;
+ int l_rc = 0;
+ uint32_t l_configured_cores;
+ pcbs_pcbspm_mode_reg_t l_ppmr;
+ pcbs_pmgp1_reg_t l_pmgp1;
+ pcbs_power_management_bounds_reg_t l_pmbr;
+ errlHndl_t l_errlHndl;
+
+ do
+ {
+ //only run this in KVM mode
+ if(!G_sysConfigData.system_type.kvm)
+ {
+ break;
+ }
+
+ l_configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG);
+
+ // Do per-core configuration
+ for(l_core = 0; l_core < PGP_NCORES; l_core++, l_configured_cores <<= 1)
+ {
+ if(!(l_configured_cores & 0x80000000)) continue;
+
+ //do read-modify-write to allow pmax clip to also clip voltage (not just frequency)
+ l_rc = getscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_PCBSPM_MODE_REG, l_core),
+ &(l_ppmr.value), NULL); //commit errors internally -- gm033
+ if(l_rc)
+ {
+ TRAC_ERR("proc_pstate_kvm_setup: getscom(PCBS_PCBSPM_MODE_REG) failed. rc=%d, hw_core=%d",
+ l_rc, l_core);
+ break;
+ }
+ l_ppmr.fields.enable_clipping_of_global_pstate_req = 1;
+ l_rc = putscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_PCBSPM_MODE_REG, l_core),
+ l_ppmr.value, NULL); //commit errors internally -- gm033
+ if(l_rc)
+ {
+ TRAC_ERR("proc_pstate_kvm_setup: putscom(PCBS_PCBSPM_MODE_REG) failed. rc=%d, hw_core=%d",
+ l_rc, l_core);
+ break;
+ }
+
+ //per Vaidy Srinivasan, clear bit 11 in the Power Management GP1 register
+ l_pmgp1.value = 0;
+ l_pmgp1.fields.pm_spr_override_en = 1;
+ l_rc = putscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG_AND, l_core),
+ ~l_pmgp1.value, NULL); //commit errors internally
+ if(l_rc)
+ {
+ TRAC_ERR("proc_pstate_kvm_setup: putscom(PCBS_PMGB1_REG_OR) failed. rc=0x%08x, hw_core=%d",
+ l_rc, l_core);
+ break;
+ }
+
+ //set pmax/pmin clip initial settings
+ l_pmbr.value = 0;
+ l_pmbr.fields.pmin_clip = gpst_pmin(&G_global_pstate_table)+1; //Per David Du, we must use pmin+1 to avoid gpsa hang
+ l_pmbr.fields.pmax_clip = gpst_pmax(&G_global_pstate_table);
+ l_rc = putscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_POWER_MANAGEMENT_BOUNDS_REG, l_core),
+ l_pmbr.value, NULL); //commit errors internally -- gm033
+ if(l_rc)
+ {
+ TRAC_ERR("proc_pstate_kvm_setup: putscom(PCBS_POWER_MANAGEMENT_BOUNDS_REG) failed. rc=0x%08x, hw_core=%d",
+ l_rc, l_core);
+ break;
+ }
+
+ }// end of per-core config
+
+ if(l_rc)
+ {
+ break;
+ }
+
+ // Set the voltage clipping register to match the pmax/pmin clip values set above.
+ pmc_rail_bounds_register_t prbr;
+ prbr.value = in32(PMC_RAIL_BOUNDS_REGISTER);
+ prbr.fields.pmin_rail = gpst_pmin(&G_global_pstate_table);
+ prbr.fields.pmax_rail = gpst_pmax(&G_global_pstate_table);
+ TRAC_IMP("pmin clip pstate = %d, pmax clip pstate = %d", prbr.fields.pmin_rail, prbr.fields.pmax_rail);
+ out32(PMC_RAIL_BOUNDS_REGISTER, prbr.value);
+
+ // Initialize the sapphire table in SRAM (sets valid bit)
+ populate_pstate_to_sapphire_tbl();
+
+ // copy sram image into mainstore HOMER
+ populate_sapphire_tbl_to_mem();
+ TRAC_IMP("proc_pstate_kvm_setup: RUNNING IN KVM MODE");
+ }while(0);
+
+ if(l_rc)
+ {
+ // Create Error Log and request reset
+ /* @
+ * @errortype
+ * @moduleid PROC_PSTATE_KVM_SETUP_MOD
+ * @reasoncode PROC_SCOM_ERROR
+ * @userdata1 l_configured_cores
+ * @userdata2 Return Code of call that failed
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC failed to scom a core register
+ */
+ l_errlHndl = createErrl(
+ PROC_PSTATE_KVM_SETUP_MOD, //modId
+ PROC_SCOM_ERROR, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_configured_cores, //userdata1
+ l_rc //userdata2
+ );
+
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ REQUEST_RESET(l_errlHndl);
+ }
+}
+
+// Function Specification
+//
+// Name: proc_gpsm_dcm_sync_enable_pstates_smh
+//
+// Description: Step through all the states & synch needed to enable
+// Pstates on both master & slave on a DCM. This also
+// works for a SCM, which will act as DCM master (as far
+// as this function is concerned.)
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void proc_gpsm_dcm_sync_enable_pstates_smh(void)
+{
+ // Static Locals
+ static GpsmEnablePstatesMasterInfo l_master_info;
+ static Pstate l_voltage_pstate, l_freq_pstate;
+
+ // Local Variables
+ int l_rc = 0;
+ errlHndl_t l_errlHndl = NULL;
+
+ if(!gpsm_dcm_slave_p())
+ {
+ // ---------------------------------------
+ // SCM or DCM Master
+ // ---------------------------------------
+ switch( G_proc_dcm_sync_state.sync_state_master )
+ {
+ case PROC_GPSM_SYNC_NO_PSTATE_TABLE:
+ // Waiting for Pstate Table from TMGT
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_TABLE_INSTALLED:
+ PROC_DBG("GPST DCM Master State %d\n",G_proc_dcm_sync_state.sync_state_master);
+ // DCM SYNC (MasterWaitForSlave): Wait for slave to install Pstate table
+ if(gpsm_dcm_mode_p()){
+ if( G_proc_dcm_sync_state.sync_state_slave == PROC_GPSM_SYNC_PSTATE_TABLE_INSTALLED)
+ {
+ // Move to next state in state machine
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_READY_TO_ENABLE_MASTER;
+ }
+ }
+ else
+ {
+ // Move to next state in state machine
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_READY_TO_ENABLE_MASTER;
+ }
+ break;
+
+ case PROC_GPSM_SYNC_READY_TO_ENABLE_MASTER:
+ PROC_DBG("GPST DCM Master State %d\n",G_proc_dcm_sync_state.sync_state_master);
+
+ // Pstate tables has been installed, so now Master can start to enable Pstates
+ l_rc = gpsm_enable_pstates_master(&l_master_info, &l_voltage_pstate, &l_freq_pstate);
+ if(l_rc)
+ {
+ // Error
+ TRAC_ERR("MSTR: gpsm_enable_pstates_master failed with rc=0x%08x", l_rc);
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_PSTATE_ERROR;
+ break;
+ }
+ TRAC_IMP("MSTR: Initial Pstates: V: %d, F: %d\n",l_voltage_pstate, l_freq_pstate);
+
+ // DCM SYNC (Master2Slave): Send V & F Pstate to slave
+ G_proc_dcm_sync_state.dcm_pair_id = G_pob_id.chip_id;
+ G_proc_dcm_sync_state.pstate_v = l_voltage_pstate;
+ G_proc_dcm_sync_state.pstate_f = l_freq_pstate;
+
+ // Move to next state in state machine
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_PSTATE_MASTER_ENABLED;
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_MASTER_ENABLED:
+ PROC_DBG("GPST DCM Master State %d\n",G_proc_dcm_sync_state.sync_state_master);
+ // DCM SYNC (MasterWaitForSlave): Wait for slave to complete gpsm_enable_pstates_slave()
+ if(gpsm_dcm_mode_p()){
+ if( G_proc_dcm_sync_state.sync_state_slave == PROC_GPSM_SYNC_PSTATE_SLAVE_ENABLED)
+ {
+ // Move to next state in state machine
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_READY_TO_ENABLE_SLAVE;
+ }
+ }
+ else
+ {
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_READY_TO_ENABLE_SLAVE;
+ }
+ break;
+
+
+ case PROC_GPSM_SYNC_READY_TO_ENABLE_SLAVE:
+ PROC_DBG("GPST DCM Master State %d\n",G_proc_dcm_sync_state.sync_state_master);
+
+ // Master does next step of enabling Pstates, now that slave has done it's enable
+ l_rc = gpsm_enable_pstates_slave(&l_master_info, l_voltage_pstate, l_freq_pstate);
+ if(l_rc)
+ {
+ // Error
+ TRAC_ERR("MSTR: gpsm_enable_pstates_slave failed with rc=0x%08x", l_rc);
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_PSTATE_ERROR;
+ break;
+ }
+ TRAC_INFO("MSTR: Completed DCM Pstate Slave Init\n");
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_PSTATE_SLAVE_ENABLED;
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_SLAVE_ENABLED:
+ PROC_DBG("GPST DCM Master State %d\n",G_proc_dcm_sync_state.sync_state_master);
+ // Master puts this chip in Pstate HW mode
+ l_rc = gpsm_hw_mode();
+ if(l_rc)
+ {
+ // Error
+ TRAC_ERR("MSTR: gpsm_hw_mode failed with rc=0x%08x", l_rc);
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_PSTATE_ERROR;
+ break;
+ }
+ // DCM SYNC (Master2Slave): Tell Slave Master has entered HW mmode
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_PSTATE_HW_MODE;
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_HW_MODE:
+ PROC_DBG("GPST DCM Master State %d\n",G_proc_dcm_sync_state.sync_state_master);
+ // DCM SYNC (Master2Slave): Wait for Slave to Enter HW Mode
+ if(gpsm_dcm_mode_p()){
+ if( G_proc_dcm_sync_state.sync_state_slave == PROC_GPSM_SYNC_PSTATE_HW_MODE)
+ {
+ TRAC_INFO("MSTR: Completed DCM Pstate Enable");
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_PSTATE_HW_MODE_ENABLED;
+
+ //do additional setup if in kvm mode -- gm025
+ proc_pstate_kvm_setup();
+ }
+ }
+ else
+ {
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_PSTATE_HW_MODE_ENABLED;
+ TRAC_INFO("MSTR: Completed SCM Pstate Enable");
+
+ //do additional setup if in kvm mode -- gm025
+ proc_pstate_kvm_setup();
+ }
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_HW_MODE_ENABLED:
+ // Final State
+ // Pstates Enabled on both modules in DCM
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_ERROR:
+ // Do nothing, something will have to come and kick us out of this state
+ break;
+
+ default:
+ G_proc_dcm_sync_state.sync_state_master = PROC_GPSM_SYNC_NO_PSTATE_TABLE;
+ break;
+ }
+ }
+ else if (gpsm_dcm_slave_p())
+ {
+ // ---------------------------------------
+ // DCM Slave
+ // - Don't need to check if DCM, since we can't come in here unless DCM
+ // ---------------------------------------
+
+ switch( G_proc_dcm_sync_state.sync_state_slave)
+ {
+ case PROC_GPSM_SYNC_NO_PSTATE_TABLE:
+ // Waiting for Pstate Table from TMGT
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_TABLE_INSTALLED:
+ // Pstate table has been installed, but slave needs to wait
+ // for master before it can do anything else.
+
+ // DCM SYNC (SlaveWaitForMaster): Send V & F Pstate to slave
+ // Wait for Master to complete gpsm_enable_pstates_master()
+ // before running gpsm_enable_pstates_slave()
+ if( G_proc_dcm_sync_state.sync_state_master == PROC_GPSM_SYNC_PSTATE_MASTER_ENABLED)
+ {
+ // Go to next state
+ G_proc_dcm_sync_state.sync_state_slave = PROC_GPSM_SYNC_PSTATE_MASTER_ENABLED;
+ }
+ break;
+
+
+ case PROC_GPSM_SYNC_PSTATE_MASTER_ENABLED:
+ PROC_DBG("GPST DCM Slave State %d\n",G_proc_dcm_sync_state.sync_state_slave);
+ // Read the initial Pstates from the data DCM master sent
+ l_voltage_pstate = G_proc_dcm_sync_state.pstate_v;
+ l_freq_pstate = G_proc_dcm_sync_state.pstate_f;
+
+ // NULL is passed to this function when run on dcm slave
+ l_rc = gpsm_enable_pstates_slave(NULL, l_voltage_pstate, l_freq_pstate);
+ if(l_rc)
+ {
+ // Error
+ TRAC_ERR("SLV: gpsm_enable_pstates_slave failed with rc=0x%08x", l_rc);
+ G_proc_dcm_sync_state.sync_state_slave = PROC_GPSM_SYNC_PSTATE_ERROR;
+ break;
+ }
+ TRAC_INFO("SLV: Completed DCM Pstate Slave Init\n");
+
+ // DCM SYNC (Slave2Master):
+ // Tell Master that slave has run gpsm_enable_pstates_slave()
+
+ // Go to next state
+ G_proc_dcm_sync_state.sync_state_slave = PROC_GPSM_SYNC_PSTATE_SLAVE_ENABLED;
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_SLAVE_ENABLED:
+ // DCM SYNC (SlaveWaitForMaster): Wait for Master to run gpsm_hw_mode
+ if( G_proc_dcm_sync_state.sync_state_master == PROC_GPSM_SYNC_PSTATE_HW_MODE)
+ {
+ // Enter Pstate HW mode
+ l_rc = gpsm_hw_mode();
+ if(l_rc)
+ {
+ // Error
+ TRAC_ERR("SLV: gpsm_hw_mode failed with rc=0x%08x", l_rc);
+ G_proc_dcm_sync_state.sync_state_slave = PROC_GPSM_SYNC_PSTATE_ERROR;
+ break;
+ }
+
+ // DCM SYNC (Slave2Master): Tell master that DCM slave made it to HW mode
+
+ // Go to next state
+ G_proc_dcm_sync_state.sync_state_slave = PROC_GPSM_SYNC_PSTATE_HW_MODE;
+ }
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_HW_MODE:
+ // Slave & Master now both know each other has HW mode enabled
+ if( G_proc_dcm_sync_state.sync_state_master == PROC_GPSM_SYNC_PSTATE_HW_MODE_ENABLED)
+ {
+ G_proc_dcm_sync_state.sync_state_slave = PROC_GPSM_SYNC_PSTATE_HW_MODE_ENABLED;
+ TRAC_INFO("SLV: Completed DCM Pstate Enable");
+
+ //do additional setup if in kvm mode -- gm025
+ proc_pstate_kvm_setup();
+ }
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_HW_MODE_ENABLED:
+ // Final State
+ // Pstates Enabled on both modules in DCM
+ break;
+
+ case PROC_GPSM_SYNC_PSTATE_ERROR:
+ // Do nothing, something will have to come and kick us out of this state
+ break;
+
+ default:
+ G_proc_dcm_sync_state.sync_state_slave = PROC_GPSM_SYNC_NO_PSTATE_TABLE;
+ break;
+
+ }
+ }
+
+ // If we are in the process of running through the state machine,
+ // we will do a sem_post to speed up the DCOM Thread and step us
+ // through faster.
+ if( PROC_GPSM_SYNC_NO_PSTATE_TABLE != proc_gpsm_dcm_sync_get_my_state()
+ && !proc_is_hwpstate_enabled() )
+ {
+ ssx_semaphore_post(&G_dcomThreadWakeupSem); // @th025
+ }
+
+ // If we broke out of loops above because of an error, create an
+ // error log and return it to caller.
+ if(l_rc)
+ {
+ /* @
+ * @errortype
+ * @moduleid PROC_ENABLE_PSTATES_SMH_MOD
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 SRAM Address of the Pstate Table
+ * @userdata2 Return Code of call that failed
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to install Pstate Table
+ */
+ l_errlHndl = createErrl( //@gm006
+ PROC_ENABLE_PSTATES_SMH_MOD, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //TODO: create trace //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ (uint32_t) &G_global_pstate_table, //userdata1
+ l_rc); //userdata2
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ REQUEST_RESET(l_errlHndl);
+ }
+
+ return;
+}
+
+
+// @ly010a
+// Function Specification
+//
+// Name: populate_pstate_to_sapphire_tbl
+//
+// Description:
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void populate_pstate_to_sapphire_tbl()
+{
+ uint8_t i = 0;
+ GlobalPstateTable * l_gpst_ptr = NULL;
+
+ memset(&G_sapphire_table, 0, sizeof(sapphire_table_t));
+
+ l_gpst_ptr = gpsm_gpst();
+ const int8_t l_pmax = (int8_t) l_gpst_ptr->pmin + l_gpst_ptr->entries - 1;
+ G_sapphire_table.config.valid = 1; // default 0x01
+ G_sapphire_table.config.version = 1; // default 0x01
+ G_sapphire_table.config.throttle = NO_THROTTLE; // defult 0x00
+ G_sapphire_table.config.pmin = gpst_pmin(&G_global_pstate_table)+1; //Per David Du, we must use pmin+1 to avoid gpsa hang -- gm025
+ G_sapphire_table.config.pnominal = (int8_t)proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]);
+ G_sapphire_table.config.pmax = gpst_pmax(&G_global_pstate_table);
+ const uint16_t l_entries = G_sapphire_table.config.pmax - G_sapphire_table.config.pmin + 1;
+ const uint8_t l_idx = l_gpst_ptr->entries-1;
+
+ for (i = 0; i < l_entries; i++)
+ {
+ G_sapphire_table.data[i].pstate = (int8_t) l_pmax - i;
+ G_sapphire_table.data[i].flag = 0; // defult 0x00
+ if (i < l_gpst_ptr->entries)
+ {
+ G_sapphire_table.data[i].evid_vdd = l_gpst_ptr->pstate[i].fields.evid_vdd;
+ G_sapphire_table.data[i].evid_vcs = l_gpst_ptr->pstate[i].fields.evid_vcs;
+ }
+ else
+ {
+ // leave the VDD & VCS Vids the same as the "Pstate Table Pmin"
+ G_sapphire_table.data[i].evid_vdd = l_gpst_ptr->pstate[l_idx].fields.evid_vdd;
+ G_sapphire_table.data[i].evid_vcs = l_gpst_ptr->pstate[l_idx].fields.evid_vcs;
+ }
+ // extrapolate the frequency
+ G_sapphire_table.data[i].freq_khz = l_gpst_ptr->pstate0_frequency_khz + (G_sapphire_table.data[i].pstate * l_gpst_ptr->frequency_step_khz);
+ }
+}
+
+
+// @ly009a @ly010c
+// Function Specification
+//
+// Name: populate_sapphire_tbl_to_mem
+//
+// Description:
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void populate_sapphire_tbl_to_mem()
+{
+ int l_ssxrc = SSX_OK;
+ uint32_t l_reasonCode = 0;
+ uint32_t l_extReasonCode = 0;
+
+ do
+ {
+#define SAPPHIRE_OFFSET_IN_HOMER 0x001F8000
+ BceRequest pba_copy;
+ // Set up copy request
+ l_ssxrc = bce_request_create(&pba_copy, // block copy object
+ &G_pba_bcue_queue, // sram to mainstore copy engine
+ SAPPHIRE_OFFSET_IN_HOMER, // mainstore address
+ (uint32_t) &G_sapphire_table, // sram starting address
+ (size_t) sizeof(G_sapphire_table), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // call back
+ NULL, // call back arguments
+ ASYNC_REQUEST_BLOCKING // callback mask
+ );
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("populate_sapphire_tbl_to_mem: PBA request create failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for PBA block-copy engine
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE;
+ break;
+ }
+
+ // Do actual copying
+ l_ssxrc = bce_request_schedule(&pba_copy);
+
+ if(l_ssxrc != SSX_OK)
+ {
+ TRAC_ERR("populate_sapphire_tbl_to_mem: PBA request schedule failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for PBA block-copy engine
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc Failed to copy data by using DMA
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE;
+ break;
+ }
+ } while(0);
+
+ if ( l_ssxrc != SSX_OK )
+ {
+ errlHndl_t l_errl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ l_reasonCode, //reasoncode
+ l_extReasonCode, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ 0, //Trace Size
+ -l_ssxrc, //userdata1
+ 0); //userdata2
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ commitErrl(&l_errl);
+ }
+}
+
+// gm025
+// Function Specification
+//
+// Name: proc_check_for_sapphire_updates
+//
+// Description: Checks if the sapphire table needs an update
+// and updates if necessary.
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void proc_check_for_sapphire_updates()
+{
+ uint8_t l_latest_throttle_reason;
+
+ //If safe state is requested then that overrides anything from amec
+ if(isSafeStateRequested())
+ {
+ l_latest_throttle_reason = OCC_RESET;
+ }
+ else
+ {
+ l_latest_throttle_reason = G_amec_kvm_throt_reason;
+ }
+
+ //If the throttle reason changed, update it in the HOMER
+ if(G_sapphire_table.config.throttle != l_latest_throttle_reason)
+ {
+ TRAC_INFO("proc_check_for_sapphire_updates: throttle reason changed to %d", l_latest_throttle_reason);
+ G_sapphire_table.config.throttle = l_latest_throttle_reason;
+ G_sapphire_table.config.version = 1; // default 0x01
+ G_sapphire_table.config.valid = 1; //default 0x01
+ populate_sapphire_tbl_to_mem();
+ }
+}
diff --git a/src/occ/proc/proc_pstate.h b/src/occ/proc/proc_pstate.h
new file mode 100755
index 0000000..b274bc7
--- /dev/null
+++ b/src/occ/proc/proc_pstate.h
@@ -0,0 +1,159 @@
+/******************************************************************************
+// @file proc_pstate.h
+// @brief OCC Firmware Handline of Pstates
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _proc_pstate_h proc_pstate.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th010 thallet 04/05/2012 Created
+ * @th015 thallet 08/03/2012 Removed inline from functions
+ * @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+ * @fk001 879727 fmkassem 04/16/2013 PCAP support.
+ * @ly009 895318 lychen 08/13/2013 OCC-Sapphire shared memory interface
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @ly010 908832 lychen 12/09/2013 Sapphire update status for reset
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef PROC_PSTATE_H
+#define PROC_PSTATE_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "cmdh_service_codes.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "occ_common.h"
+#include "state.h"
+#include "cmdh_fsp_cmds.h"
+#include "cmdhDbugCmd.h"
+#include "appletManager.h"
+#include "gpsm.h"
+#include "pstates.h"
+
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// GPSM DCM Synchronization - used by MBOX to transfer between DCM M & S
+typedef struct
+{
+ uint8_t dcm_pair_id;
+ uint8_t sync_state_master :4;
+ uint8_t sync_state_slave :4;
+ uint8_t pstate_v;
+ uint8_t pstate_f;
+} proc_gpsm_dcm_sync_occfw_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t valid;
+ uint8_t version;
+ // Sapphire_OCC_interface_v3.odp // @ly010c
+ // throttle status 0x00 No throttle, 0x01 Powercap, 0x02 CPU overtemp, 0x03 power supply failure, 0x04 overcurrent, 0x05 OCC reset
+ uint8_t throttle;
+ int8_t pmin;
+ int8_t pnominal;
+ int8_t pmax;
+ uint16_t spare;
+} sapphire_config_t; // @ly009a
+
+typedef struct __attribute__ ((packed))
+{
+ int8_t pstate;
+ uint8_t flag;
+ uint8_t evid_vdd;
+ uint8_t evid_vcs;
+ uint32_t freq_khz;
+} sapphire_data_t; // @ly009a
+
+#define PSTATE_ENTRY_NUMBER 256
+// This size must be a multiple of 128
+typedef struct __attribute__ ((packed))
+{
+ sapphire_config_t config;
+ uint64_t reserved;
+ sapphire_data_t data[PSTATE_ENTRY_NUMBER];
+ uint8_t pad[112];
+} sapphire_table_t __attribute__ ((aligned (128))); // @ly009a
+
+enum {
+ NO_THROTTLE = 0x00,
+ POWERCAP = 0x01,
+ CPU_OVERTEMP = 0x02,
+ POWER_SUPPLY_FAILURE = 0x03,
+ OVERCURRENT = 0x04,
+ OCC_RESET = 0x05,
+}; // @ly010a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern GlobalPstateTable G_global_pstate_table; // @at010a
+
+extern uint32_t G_mhz_per_pstate; // @fk001a
+
+extern sapphire_table_t G_sapphire_table; // @ly009a
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// ---------------------------------
+// Pstate Init Functions
+// ---------------------------------
+
+// Initialize PState Table
+errlHndl_t proc_gpsm_pstate_initialize(const PstateSuperStructure* i_pss);
+
+// Entry function for enabling Pstates once table is installed
+void proc_gpsm_dcm_sync_enable_pstates_smh(void);
+
+
+// ---------------------------------
+// Pstate Init DCM Sync Functions
+// ---------------------------------
+
+// Get DCM Sync State
+proc_gpsm_dcm_sync_occfw_t proc_gpsm_dcm_sync_get_state(void);
+
+// Pull down DCM pair's Sync State & Info via Mbox
+void proc_gpsm_dcm_sync_update_from_mbox(proc_gpsm_dcm_sync_occfw_t * i_dcm_sync_state);
+
+// ---------------------------------
+// Pstate Related Helper Functions
+// ---------------------------------
+
+// Helper function to translate from Frequency to nearest Pstate
+Pstate proc_freq2pstate(uint32_t i_freq_mhz);
+
+// Helper function to translate from Pstate to nearest Frequency
+uint32_t proc_pstate2freq(Pstate i_pstate);
+
+// Helper function to determine if we are a DCM
+inline bool proc_is_dcm();
+
+// Helper function to determine if we are in HW Pstate mode
+inline bool proc_is_hwpstate_enabled(void);
+
+// Copy pstate data to sapphire table
+void populate_pstate_to_sapphire_tbl(); // @ly010a
+
+// Copy sapphire table to mainstore memory at SAPPHIRE_OFFSET_IN_HOMER
+void populate_sapphire_tbl_to_mem(); // @ly009a
+
+// Check if sapphire table needs update
+void proc_check_for_sapphire_updates();
+#endif
diff --git a/src/occ/proc/test/Makefile b/src/occ/proc/test/Makefile
new file mode 100755
index 0000000..1914163
--- /dev/null
+++ b/src/occ/proc/test/Makefile
@@ -0,0 +1,85 @@
+# $Id$
+
+# @file Makefile
+#
+# @brief Makefile occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+#
+# @endverbatim
+#
+
+
+proctest_CFILES = \
+ ../../common.c \
+ ../../errl/errl.c \
+ ../../pss/apss.c \
+ ../../rtls/rtls.c \
+ ../../thread/threadSch.c \
+ ../../aplt/appletManager.c \
+ ../proc_data.c \
+ ../../rtls/rtls_tables.c \
+ ../../timer/timer.c \
+ ../../dcom/dcom.c \
+ ../../occ_sys_config.c \
+ main.c
+all_cfiles = ${proctest_CFILES}
+
+occ_GPEFILES = ../../gpe/apss_init.S \
+ ../../gpe/apss_composite.S \
+ ../../gpe/apss_meas_read_start.S \
+ ../../gpe/apss_meas_read_cont.S \
+ ../../gpe/apss_meas_read_complete.S \
+ ../../gpe/pore_test.S
+all_gpefiles = ${occ_GPEFILES}
+
+APP = proctest
+APP_INCLUDES += -I../../../ssx
+APP_INCLUDES += -I../../../lib
+APP_INCLUDES += -I../../incl
+APP_INCLUDES += -I../../trac
+APP_INCLUDES += -I../../errl
+APP_INCLUDES += -I../../thread
+APP_INCLUDES += -I../../gpe
+APP_INCLUDES += -I../../aplt
+APP_INCLUDES += -I../../aplt/incl
+APP_INCLUDES += -I../../sensor
+APP_INCLUDES += -I../../pss
+APP_INCLUDES += -I../../rtls
+APP_INCLUDES += -I../../async
+APP_INCLUDES += -I../../proc
+APP_INCLUDES += -I../../timer
+APP_INCLUDES += -I../../dcom
+APP_INCLUDES += -I.
+
+D = -DOCC_FIRMWARE=1
+
+#D = -DVERIFICATION=1 \
+ -DSSX_STACK_CHECK=0 \
+ -DINITIALIZE_PMC=0 \
+ -DINITIALIZE_SIMICS_IO=0 \
+ -DINITIALIZE_RTX_IO=1 \
+ -DINITIALIZE_PBA=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DSSX_KERNEL_TRACE_ENABLE=1
+
+
+SOURCES = ${all_cfiles} ${all_gpefiles}
+MODE = validation
+
+PGP_ASYNC_SUPPORT = 1
+
+include ./app.mk
+
+pgas:
+ $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10' ${all_gpefiles}
diff --git a/src/occ/proc/test/app.mk b/src/occ/proc/test/app.mk
new file mode 100755
index 0000000..a0c3072
--- /dev/null
+++ b/src/occ/proc/test/app.mk
@@ -0,0 +1,103 @@
+# $Id$
+
+# @file app.mk
+#
+# @brief mk occ application
+#
+# This Makefile is included-ed into application Makefiles and
+# encapsulates the steps necessary to create application images.
+#
+# The application Makefile (user) must define the following variables:
+#
+# APP - The name of the application
+# SOURCES - The list of local source files that implement the
+# application.
+#
+# The application Makefile (user) may optionally define the following
+# variables:
+#
+# D - The value of $(D) is appended to DEFS defined by ssx.mk
+#
+# MODE - The following modes are recognized:
+#
+# validation - (Default) An application that requires all SSX
+# services.
+#
+# firmware - An interrupt only configuration.
+#
+# The make process creates the following files:
+#
+# $(APP).out - The PowerPC-ELF version of the application
+# $(APP).bin - A binary SRAM image of the application
+# $(APP).map - The linker map of the application
+
+# @page ChangeLogs Change Logs
+# @section app.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# nguyenp 09/27/2011 created
+# borrowed from occ/rtls/test/app.mk
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+
+OCC = ../../
+SSX = ../../../ssx
+LIB = ../../../lib
+PGP = $(SSX)/pgp
+
+ifeq "$(MODE)" "firmware"
+SSX_TIMER_SUPPORT = 0
+SSX_THREAD_SUPPORT = 0
+endif
+
+export SSX_TIMER_SUPPORT
+export SSX_THREAD_SUPPORT
+export PPC405_MMU_SUPPORT
+export PGP_ASYNC_SUPPORT
+
+INCLUDES = -I $(OCC) -I$(LIB)
+
+include $(PGP)/ssx.mk
+
+C-OBJECTS = $(SOURCES:.c=.o)
+OBJECTS = $(C-OBJECTS:.S=.o)
+
+LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \
+ -L $(OCC) -L $(LIB) -lssx -lppc32
+
+DEFS += $(D)
+
+all: $(OBJECTS) libssx.a
+ $(MAKE) -C $(PGP) DEFS="$(DEFS)" -e
+ $(CPP) -P $(DEFS) < $(OCC)/linkocc.cmd > linkscript
+ $(LD) $(OBJECTS) \
+ -Tlinkscript $(LDFLAGS) -Map $(APP).map -Bstatic -o $(APP).out
+ $(OBJCOPY) -O binary $(APP).out $(APP).bin
+ $(OBJDUMP) -d $(APP).out > $(APP).dis
+
+libssx.a:
+ $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e
+
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map linkscript
+ rm -f ./*/*.o ./*/*.d ./*/*.d.*
+
+.PHONY : clean_all
+clean_all:
+ $(MAKE) clean
+ $(MAKE) -C $(PGP) clean
+
+.PHONY : doc
+doc:
+ doxygen doc/Doxyfile
+
+include $(OBJECTS:.o=.d)
diff --git a/src/occ/proc/test/main.c b/src/occ/proc/test/main.c
new file mode 100755
index 0000000..1a18808
--- /dev/null
+++ b/src/occ/proc/test/main.c
@@ -0,0 +1,451 @@
+/******************************************************************************
+// @file main.c
+// @brief OCC PROC TEST MAIN
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _main_c main.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * nguyenp 10/03/2011 Created
+ * To run the test, first need to enable
+ * the PROC_DBG define in proc_data.h and
+ * replace this main.c in occ
+ * directory with this main.c
+ * @pb00A pbavari 11/15/2011 changed name from APSS_SUPPORT to
+ * OCC_ALONE_SIMICS
+ * @dw000 dwoodham 12/12/2011 Update call to IMAGE_HEADER
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @fk003 907687 fmkassem 11/25/2013 Fix name of extended reason code
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+ //*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include <thread.h>
+#include <threadSch.h>
+#include <errl.h>
+#include <apss.h>
+#include <appletManager.h>
+#include <trac.h>
+#include <occ_service_codes.h>
+#include <occ_sys_config.h>
+#include <proc_data.h>
+#include <timer.h>
+#include <dcom.h>
+#include <rtls.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern void __ssx_boot;
+
+//*************************************************************************
+// Image Header
+//*************************************************************************
+// @dw000c
+IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,OCC_APLT_TEST);
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+/// Period in which to run #timer_routine
+#define TIMER_INTERVAL (SsxInterval) SSX_MICROSECONDS(5000)
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+int g_j = 0;
+int g_k = 0;
+
+SimicsStdio simics_stdout;
+SimicsStdio simics_stderr;
+
+/*----------------------------------------------------------------------------*/
+/* Critical/Non-Critical stack */
+/*----------------------------------------------------------------------------*/
+
+uint8_t noncritical_stack[NONCRITICAL_STACK_SIZE];
+uint8_t critical_stack[CRITICAL_STACK_SIZE];
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: pgp_validation_ssx_main_hook
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void pgp_validation_ssx_main_hook(void)
+{
+
+}
+
+// Function Specification
+//
+// Name: Cmd_Hndl_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Cmd_Hndl_thread_routine(void *arg)
+{
+ TRAC_INFO("Command Handler Thread Started ... " );
+}
+
+// Function Specification
+//
+// Name: Thermal_Monitor_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Thermal_Monitor_thread_routine(void *arg)
+{
+ TRAC_INFO("Thermal Monitor Thread Started ... " );
+}
+
+// Function Specification
+//
+// Name: Hlth_Monitor_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Hlth_Monitor_thread_routine(void *arg)
+{
+ TRAC_INFO("Health Monitor Thread Started ... " );
+}
+
+// Function Specification
+//
+// Name: FFDC_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void FFDC_thread_routine(void *arg)
+{
+ TRAC_INFO("FFDC Thread Started ... " );
+}
+
+// Function Specification
+//
+// Name: get_core_info
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void get_core_info()
+{
+ //uintt64_t l_deconfigured_cores;
+ uint32_t l_deconfigured_cores;
+ uint32_t l_configured_cores;
+
+ //rc = _getscom( PMC_CORE_DECONFIGURATION_REG, &l_deconfigured_cores, SCOM_TIMEOUT );
+
+ l_deconfigured_cores = in32(PMC_CORE_DECONFIGURATION_REG);
+ PROC_DEBUG( "Deconfigured cores in the chip [0x%x]\n", l_deconfigured_cores);
+
+
+ l_configured_cores = ~l_deconfigured_cores & ALL_CORES_MASK;
+ PROC_DEBUG( "Configured cores in the chip [0x%x]\n", l_configured_cores);
+
+ return;
+}
+
+/** Main Thread
+ *
+ * This thread currently just loops as the lowest priority thread, handling
+ * the lowest priority tasks.
+ *
+ */
+// Function Specification
+//
+// Name: main_thread_routine
+//
+// Description: This thread currently just loops as the lowest priority thread, handling
+// the lowest priority tasks.
+//
+// Flow: FN=None
+//
+// End Function Specification
+void main_thread_routine(void *private)
+{
+
+ TRAC_INFO("Main Thread Started ... " );
+ errlHndl_t l_errl = NULL;
+ SsxSemaphore l_appletComplete;
+ uint8_t l_status = 0;
+ uint32_t l_rc = 0 ;
+ int l_ssxrc = 0;
+
+ // Start the critical 250uS timer
+ //ssx_timer_schedule(&timer, 1, TIMER_INTERVAL);
+
+ // Initialize applet semaphore
+ l_ssxrc = ssx_semaphore_create(&l_appletComplete, 0, 1);
+
+ // Initialize APSS // @cc000a
+ //$pb005a - ifdef apss_initialize call temporary
+ // until Bishop's simics model and Steve's simics model
+ // are synced. Bishop's model does not have apss support
+ // Steve's model does not have latest changes Bishop
+ // made for ssx. To make latest svn code usable for testing
+ // ifdef apss_initialize call
+#ifdef OCC_ALONE_SIMICS
+ l_rc = runApplet(OCC_APLT_APSS_INIT, // Applet enum Name
+ NULL, // Applet arguments
+ TRUE, // Blocking call?
+ &l_appletComplete, // Applet finished semaphore
+ &l_errl, // error log handle
+ &l_status); // status from applet manager
+#endif
+ if( NULL != l_errl )
+ {
+ TRAC_ERR("APSS Init failed! (retrying) ErrLog[%p]", l_errl );
+ setErrlSevToInfo(l_errl);
+ // commit & delete
+ commitErrl( &l_errl );
+
+ l_rc = runApplet(OCC_APLT_APSS_INIT, // Applet enum Name
+ NULL, // Applet arguments
+ TRUE, // Blocking call?
+ &l_appletComplete, // Applet finished semaphore
+ &l_errl, // error log handle
+ &l_status); // status from applet manager
+ if( NULL != l_errl )
+ {
+ TRAC_ERR("APSS Init failed again! (OCC will be reset)ErrLog[%p]",
+ l_errl );
+
+ // commit & delete
+ commitErrl( &l_errl );
+
+ //$TODO: Request OCC Reset
+ }
+ }
+
+ while(1)
+ {
+ // Only trace the first XX times that this function loops
+ if(g_k < 3)
+ {
+ g_k++;
+
+ }
+
+ // Sleep for 1000 before we run the loop again
+ ssx_sleep(SSX_SECONDS(5));
+ }
+}
+
+
+/** Entry point for OCC execution
+ *
+ * main() currently initalizes our trace buffer along with creating threads
+ * and timers for execution. Note that once main runs ssx_start_threads, we
+ * never return as the SSX kernel takes over.
+ *
+ */
+// Function Specification
+//
+// Name: main
+//
+// Description: Entry point for OCC execution
+//
+// Flow: FN=None
+//
+// End Function Specification
+int main(int argc, char **argv)
+{
+ // Initialize stdout so we can do printf from within simics env
+ simics_stdout_create(&simics_stdout);
+ simics_stderr_create(&simics_stderr);
+ stdout = (FILE *)(&simics_stdout);
+ stderr = (FILE *)(&simics_stderr);
+ ssxout = (FILE *)(&simics_stdout);
+
+ TRAC_INFO("Inside OCC Main");
+
+ // Initialize SSX Stacks (note that this also reinitializes the time base to 0)
+ ssx_initialize((SsxAddress)noncritical_stack, NONCRITICAL_STACK_SIZE,
+ (SsxAddress)critical_stack, CRITICAL_STACK_SIZE,
+ 0);
+
+ // Create Threads
+ ssx_thread_create(&main_thread,
+ main_thread_routine,
+ (void *)0,
+ (SsxAddress)main_thread_stack,
+ THREAD_STACK_SIZE,
+ 1);
+
+
+ // Make Threads runnable
+ ssx_thread_resume(&main_thread);
+
+ errlHndl_t l_errl = NULL;
+ //Initialize the thread scheduler
+ l_errl = initThreadScheduler();
+
+ if( l_errl )
+ {
+ // Trace and commit error
+ TRAC_ERR("init thread Scheduler failure");
+
+ // commit log
+ // NOTE: log should be deleted by reader mechanism
+ commitErrl( &l_errl );
+ }
+
+ // lets map mainstore to oci space only once
+ // NOTE: This will stay mapped for remainder of occ life
+ // TODO: This sounds like a temporary solution and may
+ // end up moving to simics environment setup
+ // TODO: This map needs to be unmapped after done accessing
+ // main memory for the OCC initialization.
+ Ppc405MmuMap pba_mmu_map;
+ int l_ssxrc1 = ppc405_mmu_map(
+ 0, //Mainstore address 0x0
+ 0, //OCI address 0x0
+ 1048576, //Max size = 1 Mb
+ 0, //
+ 0, //no TLBIE permissions only need to read
+ &pba_mmu_map
+ );
+
+ if ( l_ssxrc1 != SSX_OK )
+ {
+ tracDesc_t l_trace = NULL;
+
+ TRAC_ERR("mmu map failure SsxRc[0x%08X]", -l_ssxrc1 );
+
+ /*
+ * @errortype
+ * @moduleid MAIN_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 pore_flex_schedule return code
+ * @userdata4 ERC_MMU_MAP_FAILURE
+ * @devdesc Failure mapping OCI space
+ */
+ l_errl = createErrl(
+ MAIN_MID, //modId
+ SSX_GENERIC_FAILURE, //reasoncode // @nh001c
+ ERC_MMU_MAP_FAILURE, //Extended reason code //@fk003c
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_ssxrc1, //userdata1
+ 0 //userdata2
+ );
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // commit log
+ commitErrl( &l_errl );
+
+ // TODO request a reset of OCC since applet manager will
+ // be toast without this working correctly
+ }
+
+ //Initialize the Applet Manager @02a
+ l_errl = initAppletManager();
+
+ if( l_errl )
+ {
+ // Trace and commit error
+ TRAC_ERR("init Applet Manager failure");
+
+ // commit log
+ commitErrl( &l_errl );
+
+ // TODO request a reset of OCC since applet manager will
+ // be toast without this working correctly
+ }
+
+
+ //Initialize structures for collecting core data.
+ //It needs to run before RTLoop start.
+ proc_core_init();
+
+ get_core_info();
+
+ // Initialize Realtime Loop Timer Interrupt
+ rtl_ocb_init();
+
+//>@paulng
+/////////////////////////////////////////////////////////////////////////////////////////
+//Proc core data testing notes:
+//
+//proc data gathering data testing are imbeded in the proc_data.c file
+//Only need to enable proc debug flag in the header file then test will be run.
+//
+//Tests cover the following:
+//Test case 1: I tested the G_core_presents and verified the deconfigured registry value.
+//
+//Test case 2: I verified the porflex get created successfully during initilization.
+//
+//Test case 3: I tested the "GPE request still running" case by modified the Ticks table
+// to let same set cores task run back to back.
+//
+//Test case 4: I tested GPE request has been succeeded for each core
+// and verified the data pointers get swapped properly.
+//
+//Test case 5: I tested and verified the poreflex scheduled correctly.
+//
+//Test case 6: I tested and verified the RTL Tick table that has the both task core data
+// for low/high set core ran properly.
+//
+/////////////////////////////////////////////////////////////////////////////////////////
+//<@paulng
+
+ // Enter SSX Kernel
+ ssx_start_threads();
+
+ return 0;
+}
+
diff --git a/src/occ/pss/apss.c b/src/occ/pss/apss.c
new file mode 100755
index 0000000..5ce452d
--- /dev/null
+++ b/src/occ/pss/apss.c
@@ -0,0 +1,911 @@
+/******************************************************************************
+// @file apss.c
+// @brief OCC APSS component
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _apss_c apss.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @cc000 cjcain 08/04/2011 Created
+ * @pb004 pbavari 09/02/2011 Initialize section support
+ * @01 abagepa 09/14/2011 add global for dcom component
+ * @th002 thallet 11/01/2011 Misc Changes for Nov 1st Milestone
+ * @th006 thallet 11/21/2011 RESET_REQUEST substituted for todo's
+ * @rc001 rickylie 01/10/2012 Change DEBUG_PRINTF to APSS_DBG
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @at009 859308 alvinwan 10/15/2012 Added tracepp support
+ * @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup Changes
+ * @th042 892056 thallet 07/19/2013 Make GPE arg structs non-cacheable
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @jh00a 909791 joshych 12/16/2013 Enhance APSS pwr meas trace
+ * @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+ * @fk005 911760 fmkassem 01/14/2014 APSS data collection retry support.
+ * @gm024 914291 milesg 02/10/2014 APSS data getting out of sync
+ * @gm025 915973 milesg 02/14/2014 Detect power data going to 0
+ * @gm032 918715 milesg 03/19/2014 Improved APSS recovery
+ * @gm035 921471 milesg 03/31/2014 Support retries after GPE times out
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ * @gm039 922963 milesg 05/28/2014 Change redundant apss error to predictive
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+
+#include <trac_interface.h>
+#include <apss.h>
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <pss_service_codes.h>
+#include <occ_service_codes.h> // @nh001a
+#include <trac.h>
+#include <state.h>
+#include <occ_sys_config.h> // @at023a
+#include <dcom.h> // @at023a
+#include "pss_constants.h" //gm024
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// threshold for calling out the redundant APSS -- gm037
+#define MAX_BACKUP_FAILURES 8
+
+// Configure both GPIOs (directoin/drive/interrupts): All Input, All 1's, No Interrupts
+const apssGpioConfigStruct_t G_gpio_config[2] = { {0x00, 0xFF, 0x00}, {0x00, 0xFF, 0x00} };
+
+// Configure streaming of: 16 ADCs, 2 GPIOs // @ly003c @at023c
+const apssCompositeConfigStruct_t G_apss_composite_config = { 16, 2 };
+
+// Power Measurements (read from APSS every RealTime loop)
+apssPwrMeasStruct_t G_apss_pwr_meas = { {0} };
+
+GPE_BUFFER(initGpioArgs_t G_gpe_apss_initialize_gpio_args);
+GPE_BUFFER(setCompositeModeArgs_t G_gpe_apss_set_composite_mode_args);
+
+uint64_t G_gpe_apss_time_start; // @jh00aa
+uint64_t G_gpe_apss_time_end; // @jh00aa
+
+// Flag for requesting APSS recovery when OCC detects all zeroes or data out of sync
+bool G_apss_recovery_requested = FALSE; //gm024
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+
+
+GPE_BUFFER(apss_start_args_t G_gpe_start_pwr_meas_read_args);
+GPE_BUFFER(apss_continue_args_t G_gpe_continue_pwr_meas_read_args);
+GPE_BUFFER(apss_complete_args_t G_gpe_complete_pwr_meas_read_args);
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+PoreEntryPoint GPE_apss_start_pwr_meas_read;
+PoreEntryPoint GPE_apss_continue_pwr_meas_read;
+PoreEntryPoint GPE_apss_complete_pwr_meas_read;
+
+// up/down counter for redundant apss failures -- gm037
+uint32_t G_backup_fail_count = 0;
+
+// @01a
+// used to tell slave inbox that pwr meas is complete
+volatile bool G_ApssPwrMeasCompleted = FALSE; // @th002
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: dumpHexString
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+#if ( (!defined(NO_TRAC_STRINGS)) && defined(TRAC_TO_SIMICS) )
+// utility function to dump hex data to screen
+void dumpHexString(const void *i_data, const unsigned int len, const char *string)
+{
+ unsigned int i, j;
+ char text[17];
+ uint8_t *data = (uint8_t*)i_data;
+ unsigned int l_len = len;
+
+ text[16] = '\0';
+ if (string != NULL)
+ {
+ printf("%s\n", string);
+ }
+
+ if (len > 0x0800) l_len = 0x800;
+ for(i = 0; i < l_len; i++)
+ {
+ if (i % 16 == 0)
+ {
+ if (i > 0) printf(" \"%s\"\n", text);
+ printf(" %04x:",i);
+ }
+ if (i % 4 == 0) printf(" ");
+
+ printf("%02x",(int)data[i]);
+ if (isprint(data[i])) text[i%16] = data[i];
+ else text[i%16] = '.';
+ }
+ if ((i%16) != 0) {
+ text[i%16] = '\0';
+ for(j = (i % 16); j < 16; ++j) {
+ printf(" ");
+ if (j % 4 == 0) printf(" ");
+ }
+ }
+ printf(" \"%s\"\n", text);
+ return;
+}
+#endif
+
+// Function Specification
+//
+// Name: do_apss_recovery
+//
+// Description: Collect FFDC and attempt recovery for APSS failures
+//
+// Flow: ??? FN= ???
+//
+// End Function Specification
+void do_apss_recovery(void) //gm037
+{
+#define PSS_START_COMMAND 0x8000000000000000ull
+#define PSS_RESET_COMMAND 0x4000000000000000ull
+ int l_scom_rc = 0;
+ uint32_t l_scom_addr;
+ uint64_t l_spi_adc_ctrl0;
+ uint64_t l_spi_adc_ctrl1;
+ uint64_t l_spi_adc_ctrl2;
+ uint64_t l_spi_adc_status;
+ uint64_t l_spi_adc_reset;
+ uint64_t l_spi_adc_wdata;
+
+
+ TRAC_ERR("detected invalid power data[%08x%08x]",
+ (uint32_t)(G_gpe_continue_pwr_meas_read_args.meas_data[0] >> 32),
+ (uint32_t)(G_gpe_continue_pwr_meas_read_args.meas_data[0] & 0x00000000ffffffffull));
+
+ do
+ {
+ //collect SPI ADC FFDC data -- gm032
+ l_scom_addr = SPIPSS_ADC_RESET_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_reset, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG0;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl0, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG1;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl1, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG2;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl2, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_STATUS_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_status, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_WDATA_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_wdata, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ TRAC_ERR("70000[%08x] 70001[%08x] 70002[%08x] 70003|70005[%08x] 70010[%08x]",
+ (uint32_t)(l_spi_adc_ctrl0 >> 32),
+ (uint32_t)(l_spi_adc_ctrl1 >> 32),
+ (uint32_t)(l_spi_adc_ctrl2 >> 32),
+ (uint32_t)((l_spi_adc_status >> 32) | (l_spi_adc_reset >> 48)), //stuff reset register in lower 16 bits
+ (uint32_t)(l_spi_adc_wdata >> 32));
+
+ //special error handling on OCC backup. Keep an up/down counter of
+ //fail/success and log predictive error when we reach the limit.
+ if(G_occ_role == OCC_SLAVE)
+ {
+ if(G_backup_fail_count < MAX_BACKUP_FAILURES)
+ {
+ //increment the up/down counter
+ G_backup_fail_count++;
+ }
+ else
+ {
+ //We're logging the error so stop running apss tasks
+ rtl_stop_task(TASK_ID_APSS_START);
+ rtl_stop_task(TASK_ID_APSS_CONT);
+ rtl_stop_task(TASK_ID_APSS_DONE);
+
+ TRAC_INFO("Redundant APSS has exceeded failure threshold. Logging Error");
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_DO_APSS_RECOVERY
+ * @reasoncode REDUNDANT_APSS_GPE_FAILURE
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Redundant APSS failure. Power Management Redundancy Lost.
+ */
+ errlHndl_t l_err = createErrl(PSS_MID_DO_APSS_RECOVERY,
+ REDUNDANT_APSS_GPE_FAILURE,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE, //gm039
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ 0,
+ 0);
+
+ //apss callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.apss_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ //processor callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ //backplane callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.backplane_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ //firmware callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ commitErrl(&l_err);
+
+ break;
+ }
+ }
+
+ TRAC_INFO("Starting APSS recovery. fail_count=%d", G_backup_fail_count);
+
+ //reset the ADC engine -- gm032
+ l_scom_addr = SPIPSS_ADC_RESET_REG;
+ l_scom_rc = _putscom(l_scom_addr, PSS_RESET_COMMAND, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ //zero out the reset register -- gm032
+ l_scom_rc = _putscom(l_scom_addr, 0, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ //attempt recovery by sending the apss
+ //command that was set up earlier by initialization GPE
+ l_scom_addr = SPIPSS_P2S_COMMAND_REG;
+ l_scom_rc = _putscom(l_scom_addr, PSS_START_COMMAND, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ }while(0);
+
+ //Just trace it if we get a scom failure trying to collect FFDC -- gm032
+ if(l_scom_rc)
+ {
+ TRAC_ERR("apss recovery scom failure. addr=0x%08x, rc=0x%08x", l_scom_addr, l_scom_rc);
+ }
+}
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_start_request;
+// Function Specification
+//
+// Name: task_apss_start_pwr_meas
+//
+// Description: Start the GPE program to request power measurement data from APSS
+// If previous call had failed, commit the error and request reset
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// Flow: 07/20/11 FN=task_apss_start_pwr_meas
+//
+// End Function Specification
+void task_apss_start_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_start_pwr_meas_read (non-blocking)
+ APSS_DBG("GPE_start_pwr_meas_read started\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_start_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_start_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ //check if we need to try recovering the apss -- gm024
+ if(G_apss_recovery_requested)
+ {
+ //do recovery then wait until next tick to do anything more.
+ do_apss_recovery();
+ break;
+ }
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_start_request.request.completion_state) ||
+ (0 != G_gpe_start_pwr_meas_read_args.error.error))
+ {
+ //error should only be non-zero in the case where the GPE timed out waiting for
+ //the APSS master to complete the last operation. Just keep retrying until
+ //DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_start_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_start_pwr_meas_read_args.error.rc,
+ G_gpe_start_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_start_pwr_meas_read_args.error.ffdc,
+ G_meas_start_request.request.completion_state);
+
+ //collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_START_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_START_MEAS, // i_modId,
+ APSS_GPE_FAILURE, // i_reasonCode,
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_start_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_start_request.ffdc,
+ sizeof(G_meas_start_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ //Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ //clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_start_pwr_meas_read_args.error.error = 0;
+ G_gpe_start_pwr_meas_read_args.error.ffdc = 0;
+
+ //submit the next request
+ l_rc = pore_flex_schedule(&G_meas_start_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_start_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_START_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_start_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_START_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ //Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+
+ }while (0);
+
+
+ APSS_DBG("GPE_start_pwr_meas_read finished w/rc=0x%08X\n", G_gpe_start_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_start_pwr_meas_read_args, sizeof(G_gpe_start_pwr_meas_read_args), "G_gpe_start_pwr_meas_read_args"); // @at009c
+ G_ApssPwrMeasCompleted = FALSE; //Will complete when 3rd task is complete.
+ G_gpe_apss_time_start = ssx_timebase_get(); // @jh00aa
+
+
+} // end task_apss_start_pwr_meas()
+
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_cont_request;
+// Function Specification
+//
+// Name: task_apss_continue_pwr_meas
+//
+// Description: Start GPE to collect 1st block of power measurement data and request
+// the 2nd block
+// If previous call had failed, commit the error and request reset
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// Flow: 07/20/11 FN=task_apss_continue_pwr_meas
+//
+// End Function Specification
+void task_apss_continue_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_apss_continue_pwr_meas_read (non-blocking)
+ APSS_DBG("Calling task_apss_continue_pwr_meas.\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_cont_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_continue_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ //Don't run anything if apss recovery is in progress - gm024
+ if(G_apss_recovery_requested)
+ {
+ break;
+ }
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_cont_request.request.completion_state) ||
+ (0 != G_gpe_continue_pwr_meas_read_args.error.error))
+ {
+ //error should only be non-zero in the case where the GPE timed out waiting for
+ //the APSS master to complete the last operation. Just keep retrying until
+ //DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_continue_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_continue_pwr_meas_read_args.error.rc,
+ G_gpe_continue_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_continue_pwr_meas_read_args.error.ffdc,
+ G_meas_cont_request.request.completion_state);
+
+
+ //collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_CONT_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_CONT_MEAS, // i_modId,
+ APSS_GPE_FAILURE, // i_reasonCode,
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_continue_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_cont_request.ffdc,
+ sizeof(G_meas_cont_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ //Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ //clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_continue_pwr_meas_read_args.error.error = 0;
+ G_gpe_continue_pwr_meas_read_args.error.ffdc = 0;
+
+ //submit the next request
+ l_rc = pore_flex_schedule(&G_meas_cont_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_cont_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_CONT_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_continue_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_CONT_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ //Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+
+ }while (0);
+
+ APSS_DBG("task_apss_continue_pwr_meas: finished w/rc=0x%08X\n", G_gpe_continue_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_continue_pwr_meas_read_args, sizeof(G_gpe_continue_pwr_meas_read_args), "G_gpe_continue_pwr_meas_read_args");
+
+} // end task_apss_continue_pwr_meas
+
+
+// Function Specification
+//
+// Name: reformat_meas_data
+//
+// Description: Extract measurement from GPE programs into G_apss_pwr_meas structure
+// This function is called when the GPE completes the final measurement
+// collection for this loop.
+//
+// Flow: FN=None
+//
+// End Function Specification
+#define APSS_ADC_SEQ_MASK 0xf000f000f000f000ull
+#define APSS_ADC_SEQ_CHECK 0x0000100020003000ull
+void reformat_meas_data()
+{
+ APSS_DBG("GPE_complete_pwr_meas_read finished w/rc=0x%08X\n", G_gpe_complete_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_complete_pwr_meas_read_args, sizeof(G_gpe_complete_pwr_meas_read_args), "G_gpe_complete_pwr_meas_read_args"); // @at009c
+
+ do
+ {
+ // Make sure complete was successful
+ if (G_gpe_complete_pwr_meas_read_args.error.error)
+ {
+ break;
+ }
+
+ // Check that the first 4 sequence nibbles are 0, 1, 2, 3 in the ADC data
+ if (((G_gpe_continue_pwr_meas_read_args.meas_data[0] & APSS_ADC_SEQ_MASK) != APSS_ADC_SEQ_CHECK) ||
+ !(G_gpe_continue_pwr_meas_read_args.meas_data[0] & ~APSS_ADC_SEQ_MASK)) //gm025
+ {
+ //recovery will begin on the next tick
+ G_apss_recovery_requested = TRUE;
+ break;
+ }
+
+ //decrement up/down fail counter for backup on success.
+ if(G_backup_fail_count)
+ {
+ G_backup_fail_count--;
+ }
+
+ //Don't do the copy unless this is the master OCC -- gm037
+ if(G_occ_role == OCC_MASTER)
+ {
+
+ //fail every 16 seconds
+ //if(!(CURRENT_TICK & 0x0000ffff))
+ //{
+ // G_apss_recovery_requested = TRUE;
+ //}
+
+ APSS_DBG("Populate meas data:\n");
+#if 0
+ APSS_DBG_HEXDUMP(G_gpe_continue_pwr_meas_read_args.meas_data, sizeof(G_gpe_continue_pwr_meas_read_args.meas_data), "G_gpe_continue_pwr_meas_read_args.meas_data"); // @at009c
+ APSS_DBG_HEXDUMP(G_gpe_complete_pwr_meas_read_args.meas_data, sizeof(G_gpe_complete_pwr_meas_read_args.meas_data), "G_gpe_complete_pwr_meas_read_args.meas_data"); // @at009c
+#endif
+
+ // Merge continue/complete data into a single buffer
+ const uint16_t l_continue_meas_length = sizeof(G_gpe_continue_pwr_meas_read_args.meas_data);
+ const uint16_t l_complete_meas_length = sizeof(G_gpe_complete_pwr_meas_read_args.meas_data);
+ uint8_t l_buffer[l_continue_meas_length+l_complete_meas_length];
+ memcpy(&l_buffer[ 0], G_gpe_continue_pwr_meas_read_args.meas_data, l_continue_meas_length);
+ memcpy(&l_buffer[l_continue_meas_length], G_gpe_complete_pwr_meas_read_args.meas_data, l_complete_meas_length);
+ APSS_DBG_HEXDUMP(l_buffer, sizeof(l_buffer), "l_buffer"); // @at009c
+
+ // Copy measurements into correct struction locations (based on composite config)
+ uint16_t l_index = 0;
+ memcpy(G_apss_pwr_meas.adc, &l_buffer[l_index], (G_apss_composite_config.numAdcChannelsToRead * 2));
+ l_index += (G_apss_composite_config.numAdcChannelsToRead * 2);
+ memcpy(G_apss_pwr_meas.gpio, &l_buffer[l_index], (G_apss_composite_config.numGpioPortsToRead * 2));
+ // TOD is always located at same offset
+ memcpy(&G_apss_pwr_meas.tod, &l_buffer[l_continue_meas_length+l_complete_meas_length-8], 8);
+
+ APSS_DBG("...into structure: (%d ADC, %d GPIO)\n", G_apss_composite_config.numAdcChannelsToRead,
+ G_apss_composite_config.numGpioPortsToRead); // @ly003c
+ APSS_DBG_HEXDUMP(&G_apss_pwr_meas, sizeof(G_apss_pwr_meas), "G_apss_pwr_meas"); // @at009c
+ }
+
+ // mark apss pwr meas completed and valid
+ G_ApssPwrMeasCompleted = TRUE; // @th002
+ G_gpe_apss_time_end = ssx_timebase_get(); // @jh00aa
+ APSS_DBG("APSS Completed - %d\n",(int) ssx_timebase_get());
+ }while(0);
+}
+
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_complete_request;
+
+// Function Specification
+//
+// Name: task_apss_complete_pwr_meas
+//
+// Description: Start GPE to collect 2nd block of power measurement data and TOD.
+// If previous call had failed, commit the error and request reset
+//
+// Flow: 07/20/11 FN=task_apss_complete_pwr_meas
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// End Function Specification
+void task_apss_complete_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_apss_complete_pwr_meas_read (non-blocking)
+ APSS_DBG("Calling task_apss_complete_pwr_meas.\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_complete_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_complete_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ if(G_apss_recovery_requested) //gm024
+ {
+ //allow apss measurement to proceed on next tick
+ G_apss_recovery_requested = FALSE;
+ break;
+ }
+
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_complete_request.request.completion_state) ||
+ (0 != G_gpe_complete_pwr_meas_read_args.error.error))
+ {
+ //error should only be non-zero in the case where the GPE timed out waiting for
+ //the APSS master to complete the last operation. Just keep retrying until
+ //DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_complete_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_complete_pwr_meas_read_args.error.rc,
+ G_gpe_complete_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_complete_pwr_meas_read_args.error.ffdc,
+ G_meas_complete_request.request.completion_state);
+
+ //collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_COMPLETE_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_COMPLETE_MEAS, // i_modId,
+ APSS_GPE_FAILURE, // i_reasonCode,
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_complete_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_complete_request.ffdc,
+ sizeof(G_meas_complete_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ //Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ //clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_complete_pwr_meas_read_args.error.error = 0;
+ G_gpe_complete_pwr_meas_read_args.error.ffdc = 0;
+
+ //submit the next request
+ l_rc = pore_flex_schedule(&G_meas_complete_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_complete_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_COMPLETE_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_complete_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_COMPLETE_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ //Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+
+ }while (0);
+
+ APSS_DBG("task_apss_complete_pwr_meas: finished w/rc=0x%08X\n", G_gpe_complete_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_complete_pwr_meas_read_args, sizeof(G_gpe_complete_pwr_meas_read_args), "G_gpe_complete_pwr_meas_read_args");
+
+
+} // end task_apss_complete_pwr_meas
+
+// @at023a - start
+bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value)
+{
+ bool l_valid = FALSE;
+
+ if( (i_pin_number != SYSCFG_INVALID_PIN) && (o_pin_value != NULL) )
+ {
+ // Check if G_dcom_slv_inbox_rx is valid.
+ // The default value is all 0, so check if it's no-zero
+ bool l_dcom_data_valid = FALSE;
+ int i=0;
+ for(;i<sizeof(G_dcom_slv_inbox_rx);i++)
+ {
+ if( ((char*)&G_dcom_slv_inbox_rx)[i] != 0 )
+ {
+ l_dcom_data_valid = TRUE;
+ break;
+ }
+ }
+
+ if( l_dcom_data_valid == TRUE)
+ {
+ uint8_t l_gpio_port = i_pin_number/NUM_OF_APSS_PINS_PER_GPIO_PORT;
+ uint8_t l_gpio_mask = 0x1 << i_pin_number % NUM_OF_APSS_PINS_PER_GPIO_PORT;
+ l_valid = TRUE;
+ if( G_dcom_slv_inbox_rx.gpio[l_gpio_port] & l_gpio_mask )
+ {
+ *o_pin_value = 1;
+ }
+ else
+ {
+ *o_pin_value = 0;
+ }
+ }
+ }
+ return l_valid;
+}
+// @at023a - end
diff --git a/src/occ/pss/apss.h b/src/occ/pss/apss.h
new file mode 100755
index 0000000..78c5b86
--- /dev/null
+++ b/src/occ/pss/apss.h
@@ -0,0 +1,181 @@
+/******************************************************************************
+// @file apss.h
+// @brief OCC APSS component header file.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _apss_h apss.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * cjcain 08/04/2011 Created
+ * @pb004 pbavari 09/02/2011 Initialize section support
+ * @01 abagepa 09/14/2011 add global for dcom component
+ * @th002 thallet 11/01/2011 Misc Changes for Nov 1st Milestone
+ * @rc001 rickylie 01/02/2012 Modved debug trace defines to trac.h
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @at009 859308 alvinwan 10/15/2012 Added tracepp support
+ * @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+ * @at014 882077 alvinwan 05/09/2013 Support APSS and System Config data from TMGT
+ * @jh00a 909791 joshych 12/16/2013 Enhance APSS pwr meas trace
+ * @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+ * @fk005 911760 fmkassem 01/14/2014 APSS data collection retry support.
+ * @gm028 911670 milesg 02/27/2014 Fixed compiler fails from stradale
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _APSS_H
+#define _APSS_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <trac_interface.h>
+#include <errl.h>
+#include <gpe_export.h>
+#include <rtls.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define NUM_OF_APSS_GPIO_PORTS 2
+#define NUM_OF_APSS_PINS_PER_GPIO_PORT 8 // @at014a
+#define MAX_APSS_ADC_CHANNELS 16
+#define MAX_APSS_GPIO_PORTS NUM_OF_APSS_GPIO_PORTS
+#define MEAS_PADDING_REQUIRED (28-MAX_APSS_ADC_CHANNELS+MAX_APSS_GPIO_PORTS) // @ly003c
+#define APSS_12BIT_ADC_MASK 0x0fff
+
+#if ( (!defined(NO_TRAC_STRINGS)) && defined(TRAC_TO_SIMICS) )
+void dumpHexString(const void *i_data, const unsigned int len, const char *string);
+#endif
+
+//@fk005a
+#define APSS_DATA_FAIL_MAX 32 //Number of steps we reach before reseting OCC. This should allow for 4ms/16ticks with no APSS data.
+#define APSS_DATA_FAILURE_STEP 2 //Number of steps to increment FAIL_COUNT due to a failed APSS data collection.
+#define APSS_DATA_SUCCESS_STEP 1 //Number of steps to decrement the FAIL_COUNT due to successful APSS data collection.
+#define APSS_ERRORLOG_RESET_THRESHOLD 16 //When to allow apss tasks to log another error if count goes back to 0 again.
+
+//Count of number of
+extern uint8_t G_apss_fail_updown_count; //Used to keep count of number of APSS data collection fails.
+//bool G_apss_error_logged_flag = FALSE; //Used to tell apss tasks whether to log an error or not.
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//@fk005a
+//Decrement APSS_FAIL_COUNT by APSS_DATA_SUCCESS_STEP to a minimum of 0.
+#define APSS_SUCCESS() {(G_apss_fail_updown_count >= APSS_DATA_SUCCESS_STEP)? \
+ (G_apss_fail_updown_count -= APSS_DATA_SUCCESS_STEP): \
+ (G_apss_fail_updown_count = 0);}
+
+
+//Increment APSS_FAIL_COUNT by APSS_DATA_FAILURE_STEP to a maximum of APSS_DATA_FAIL_MAX.
+#define APSS_FAIL() {((APSS_DATA_FAIL_MAX - G_apss_fail_updown_count) >= APSS_DATA_FAILURE_STEP)? \
+ (G_apss_fail_updown_count += APSS_DATA_FAILURE_STEP): \
+ (G_apss_fail_updown_count = APSS_DATA_FAIL_MAX);}
+
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+struct apssGpioConfigStruct
+{
+ uint8_t direction;
+ uint8_t drive;
+ uint8_t interrupt;
+} __attribute__ ((__packed__));
+typedef struct apssGpioConfigStruct apssGpioConfigStruct_t;
+
+struct apssCompositeConfigStruct
+{
+ uint8_t numAdcChannelsToRead;
+ uint8_t numGpioPortsToRead;
+} __attribute__ ((__packed__));
+typedef struct apssCompositeConfigStruct apssCompositeConfigStruct_t;
+
+struct apssPwrMeasStruct
+{
+ uint16_t adc[MAX_APSS_ADC_CHANNELS];
+ uint16_t gpio[MAX_APSS_GPIO_PORTS];
+ uint16_t pad[MEAS_PADDING_REQUIRED]; // padding to allow TOD to be 8 byte aligned
+ uint64_t tod; // Time of Day that the ADC Collection Completed
+} __attribute__ ((__packed__));
+typedef struct apssPwrMeasStruct apssPwrMeasStruct_t;
+
+typedef struct {
+ PoreGpeErrorStruct error;
+ apssGpioConfigStruct_t config0; // G_gpio_config[0] (input to APSS)
+ apssGpioConfigStruct_t config1; // G_gpio_config[1] (input to APSS)
+} initGpioArgs_t;
+
+typedef struct {
+ PoreGpeErrorStruct error;
+ apssCompositeConfigStruct_t config; // G_apss_composite_config (input to APSS)
+} setCompositeModeArgs_t;
+
+typedef struct
+{
+ PoreGpeErrorStruct error;
+} apss_start_args_t;
+
+typedef struct {
+ PoreGpeErrorStruct error;
+ uint64_t meas_data[4]; // G_apss_pwr_meas (1st block of data) (output from APSS)
+} apss_continue_args_t;
+
+typedef struct {
+ PoreGpeErrorStruct error;
+ uint64_t meas_data[4]; // G_apss_pwr_meas (2nd block of data) (output from APSS)
+} apss_complete_args_t;
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// @TODO - does G_gpio_config and G_apss_composite_config need to be used outside of APSS? If not I will remove from .h
+// G_gpio_config: configuration for APSS GPIO pins (default all input, all 1's, not int)
+extern const apssGpioConfigStruct_t G_gpio_config[NUM_OF_APSS_GPIO_PORTS];
+// G_apss_composite_config: system parms needed to select correct composite command options
+extern const apssCompositeConfigStruct_t G_apss_composite_config;
+
+// G_apss_pwr_meas: power, temp and GPIO readings that OCC gathers from APSS every tick
+extern apssPwrMeasStruct_t G_apss_pwr_meas;
+
+// @01a
+// used to tell slave inbox that pwr meas is complete
+extern volatile bool G_ApssPwrMeasCompleted; // @th002
+
+extern initGpioArgs_t G_gpe_apss_initialize_gpio_args;
+extern setCompositeModeArgs_t G_gpe_apss_set_composite_mode_args;
+
+extern uint64_t G_gpe_apss_time_start; // @jh00aa
+extern uint64_t G_gpe_apss_time_end; // @jh00aa
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// apss_initialize is product applet
+void task_apss_start_pwr_meas(task_t *i_self);
+void task_apss_continue_pwr_meas(task_t *i_self);
+void task_apss_complete_pwr_meas(task_t *i_self);
+
+void apss_test_pwr_meas(); // @temp cc - used to test measurements
+void reformat_meas_data();
+bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value); // @at023a
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_APSS_H
diff --git a/src/occ/pss/dpss.c b/src/occ/pss/dpss.c
new file mode 100755
index 0000000..2479d80
--- /dev/null
+++ b/src/occ/pss/dpss.c
@@ -0,0 +1,233 @@
+/******************************************************************************
+// @file dpss.c
+// @brief OCC DPSS component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _dpss_c dpss.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * dwoodham 09/21/2011 Created
+ * @th006 thallet 11/21/2011 Added REQUEST_RESET in place of todo's
+ * @at000 atwang 12/07/2011 Moved start_dpss and dpss_initialize
+ * into a product applet
+ * @rc001 rickylie 01/10/2012 Change DPSS_DEBUG_PRINTF to DPSS_DBG
+ * @rc002 rickylie 02/01/2012 Remove unused DPSS function
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @at010 859992 alvinwan 11/07/2012 Added oversubscription feature
+ * @th032 thallet 04/19/2013 Changed oversubscription to non-critical
+ * @gm036 917550 milesg 04/09/2014 Ignore phantom interrupts (log info error)
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+
+#include <dpss.h>
+#include <trac.h>
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <occ_sys_config.h>
+#include <trac_interface.h>
+#include <occ_service_codes.h>
+#include <pss_service_codes.h>
+#include <state.h>
+#include <amec_oversub.h> // @at010a
+#include <ppc405_irq.h> //gm036
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+//Macro creates a 'bridge' handler that converts the initial fast-mode to full-
+//mode interrupt handler
+SSX_IRQ_FAST2FULL(isr_dpss_oversubscription_handler, isr_dpss_oversubscription_handler_full);
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// Increment a counter each time we see a phantom interrupt (used by health monitor thread) -- gm036
+uint32_t G_occ_phantom_critical_count = 0;
+uint32_t G_occ_phantom_noncritical_count = 0;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: isr_dpss_oversubscription_handler_full
+//
+// Description: From the flow diagram:
+// Will eventually be doing something to set the Pstates & Memory
+// Throttles when this interrupt occurs, but for now just put in this
+// comment and no code besides clearing the irq and tracing the fact that
+// we got an interrupt.
+//
+// Flow: 08/03/11 FN=isr_dpss_oversubscription
+//
+// End Function Specification
+void isr_dpss_oversubscription_handler_full(void *private, SsxIrqId irq, int priority)
+{
+ SsxMachineContext ctx;
+
+ // disable further interrupts at this level
+ ssx_irq_disable(irq);
+
+ // enter the protected context
+ ssx_critical_section_enter( SSX_CRITICAL, &ctx );
+
+ // clear this irq
+ ssx_irq_status_clear(irq);
+
+ // exit the protected context
+ ssx_critical_section_exit( &ctx );
+
+ // call oversub isr
+ amec_oversub_isr();
+
+ // re-enable interrupts at this level
+ ssx_irq_enable(irq);
+
+} // end isr_dpss_oversubscription_handler_full
+
+// Function Specification
+//
+// Name: occ_phantom_irq_handler
+//
+// Description:
+// handler for an interrupt that fired and then went away before
+// we could read what it was.
+//
+// Flow: ??? FN= ???
+//
+// End Function Specification
+void occ_phantom_irq_handler(void* i_arg, SsxIrqId i_irq, int i_critical) //gm036
+{
+ if(i_critical == SSX_CRITICAL)
+ {
+ G_occ_phantom_critical_count++;
+ }
+ else
+ {
+ G_occ_phantom_noncritical_count++;
+ }
+}
+
+// Function Specification
+//
+// Name: dpss_oversubscription_irq_initialize
+//
+// Description:
+// Installs the power oversubscription IRQ handler for the DPSS
+//
+// Flow: 08/03/11 FN=dpss_oversubscription_irq_initialize
+//
+// End Function Specification
+errlHndl_t dpss_oversubscription_irq_initialize()
+{
+ int rc = 0;
+ errlHndl_t l_err = NULL;
+
+ // override the default phantom interrupt handler -- gm036
+ // NOTE: It is believed that the oversubscription interrupt bounces
+ // on and off as power supplies are re-inserted. If it happens quickly enough
+ // it will clear the interrupt before the code has a chance to see the cause
+ // of the interrupt. The default phantom handler would then be invoked and
+ // cause occ to panic. Instead, we just increment a counter and log an info
+ // error.
+ __ppc405_phantom_irq.handler = occ_phantom_irq_handler;
+
+ // Disable the IRQ while we work on it
+ ssx_irq_disable(PGP_IRQ_EXTERNAL_TRAP);
+
+ // Setup the IRQ
+ rc = ssx_irq_setup(PGP_IRQ_EXTERNAL_TRAP,
+ SSX_IRQ_POLARITY_ACTIVE_LOW,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE); // @at010c
+
+ if( rc ) {
+ TRAC_ERR("%s: Failed IRQ setup.", __FUNCTION__);
+
+ /*@
+ * @moduleid PSS_MID_DPSS_OVS_IRQ_INIT
+ * @reasonCode SSX_GENERIC_FAILURE
+ * @severity ERRL_SEV_PREDICTIVE
+ * @userdata1 ssx_irq_setup return code
+ * @userdata4 ERC_SSX_IRQ_SETUP_FAILURE
+ * @devdesc Firmware failure initializing DPSS IRQ
+ */
+ l_err = createErrl( PSS_MID_DPSS_OVS_IRQ_INIT, // i_modId,
+ SSX_GENERIC_FAILURE, // i_reasonCode,
+ ERC_SSX_IRQ_SETUP_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL, // tracDesc_t i_trace,
+ 0, // i_traceSz,
+ rc, // i_userData1,
+ 0); // i_userData2
+ }
+ else {
+ // Set the IRQ handler
+ rc = ssx_irq_handler_set(PGP_IRQ_EXTERNAL_TRAP,
+ isr_dpss_oversubscription_handler,
+ NULL,
+ SSX_NONCRITICAL); // @th032
+
+ if( rc ) {
+ TRAC_ERR("%s: Failed to set the IRQ handler.", __FUNCTION__);
+
+ /*@
+ * @moduleid PSS_MID_DPSS_OVS_IRQ_INIT
+ * @reasonCode SSX_GENERIC_FAILURE
+ * @severity ERRL_SEV_PREDICTIVE
+ * @userdata1 ssx_irq_handler_set return code
+ * @userdata4 ERC_SSX_IRQ_HANDLER_SET_FAILURE
+ * @devdesc Firmware failure setting up DPSS routine
+ */
+ l_err = createErrl( PSS_MID_DPSS_OVS_IRQ_INIT, // i_modId,
+ SSX_GENERIC_FAILURE, // i_reasonCode,
+ ERC_SSX_IRQ_HANDLER_SET_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL, // tracDesc_t i_trace,
+ 0, // i_traceSz,
+ rc, // i_userData1,
+ 0); // i_userData2
+ }
+ else {
+ // Enable the IRQ
+ ssx_irq_status_clear(PGP_IRQ_EXTERNAL_TRAP);
+ ssx_irq_enable(PGP_IRQ_EXTERNAL_TRAP);
+ }
+ }
+
+ return l_err;
+} // end dpss_oversubscription_irq_initialize
+
+
+
+
+
diff --git a/src/occ/pss/dpss.h b/src/occ/pss/dpss.h
new file mode 100755
index 0000000..a6b0e7d
--- /dev/null
+++ b/src/occ/pss/dpss.h
@@ -0,0 +1,68 @@
+/******************************************************************************
+// @file dpss.h
+// @brief OCC DPSS component header file.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _dpss_h dpss.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * dwoodham 09/21/2011 Created
+ * @at000 atwang 12/07/2011 Moved start_dpss and dpss_initialize
+ * into a product applet
+ * @rc001 rickylie 01/02/2012 Moved debug trace defines to trac.h
+ * @rc002 rickylie 02/02/2012 Remove unused DPSS function
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DPSS_H
+#define _DPSS_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <errl.h>
+#include <rtls.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// dpss_initialize is part of the dpss init applet @at000D
+
+// DPSS oversubscription IRQ handler
+void isr_dpss_oversubscription_handler_full(void *private, SsxIrqId irq, int priority);
+
+// Installs the DPSS oversubscription IRQ handler
+errlHndl_t dpss_oversubscription_irq_initialize();
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_DPSS_H
diff --git a/src/occ/pss/pss_service_codes.h b/src/occ/pss/pss_service_codes.h
new file mode 100755
index 0000000..c26b538
--- /dev/null
+++ b/src/occ/pss/pss_service_codes.h
@@ -0,0 +1,74 @@
+/******************************************************************************
+// @file pss_service_codes.h
+// @brief Error codes for pss component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _pss_service_codes_h pss_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @cc000 cjcain 08/04/2011 Created
+ * @dw001 dwoodham 09/22/2011 Added code for dpss
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _PSS_SERVICE_CODES_H_
+#define _PSS_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum pssModuleId // @dw001c
+{
+ PSS_MID_APSS_INIT = PSS_COMP_ID | 0x00,
+ PSS_MID_APSS_START_MEAS = PSS_COMP_ID | 0x01,
+ PSS_MID_APSS_CONT_MEAS = PSS_COMP_ID | 0x02,
+ PSS_MID_APSS_COMPLETE_MEAS = PSS_COMP_ID | 0x03,
+ PSS_MID_DPSS_INIT = PSS_COMP_ID | 0x04, // @dw001a
+ PSS_MID_DPSS_OVS_IRQ_INIT = PSS_COMP_ID | 0x05, // @dw001a
+ PSS_MID_DPSS_RD_STATUS = PSS_COMP_ID | 0x06, // @dw001a
+ PSS_MID_DO_APSS_RECOVERY = PSS_COMP_ID | 0x07, // @gm037
+};
+
+// move return code to occ_service_code.h as ERC codes // @nh001d
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _PSS_SERVICE_CODES_H_ */
diff --git a/src/occ/pss/test/Makefile b/src/occ/pss/test/Makefile
new file mode 100755
index 0000000..c53785f
--- /dev/null
+++ b/src/occ/pss/test/Makefile
@@ -0,0 +1,76 @@
+# $Id$
+
+# @file Makefile
+#
+# @brief Makefile occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+#
+# @endverbatim
+#
+
+
+apsstest_CFILES = \
+ ../../common.c \
+ ../../errl/errl.c \
+ ../../thread/threadSch.c \
+ ../apss.c \
+ apsstest.c
+all_cfiles = ${apsstest_CFILES}
+
+
+occ_GPEFILES = ../../gpe/apss_init.S \
+ ../../gpe/apss_composite.S \
+ ../../gpe/apss_meas_read_start.S \
+ ../../gpe/apss_meas_read_cont.S \
+ ../../gpe/apss_meas_read_complete.S \
+ ../../gpe/pore_test.S
+all_gpefiles = ${occ_GPEFILES}
+
+
+APP = apsstest
+APP_INCLUDES += -I../../../ssx
+APP_INCLUDES += -I../../../lib
+APP_INCLUDES += -I../../incl
+APP_INCLUDES += -I../../trac
+APP_INCLUDES += -I../../async
+APP_INCLUDES += -I../../errl
+APP_INCLUDES += -I../../gpe
+APP_INCLUDES += -I../../thread
+#APP_INCLUDES += -I../../aplt
+#APP_INCLUDES += -I../../rtls
+#APP_INCLUDES += -I../../sensor
+APP_INCLUDES += -I../../pss
+APP_INCLUDES += -I.
+
+D = -DSIMICS_MAGIC_PANIC=1
+
+#D = -DVERIFICATION=1 \
+ -DSSX_STACK_CHECK=0 \
+ -DINITIALIZE_PMC=0 \
+ -DINITIALIZE_SIMICS_IO=0 \
+ -DINITIALIZE_RTX_IO=1 \
+ -DINITIALIZE_PBA=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DSSX_KERNEL_TRACE_ENABLE=1
+
+
+SOURCES = ${all_cfiles} ${all_gpefiles}
+MODE = validation
+
+PGP_ASYNC_SUPPORT = 1
+
+include ./app.mk
+
+pgas:
+ $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10' ${all_gpefiles}
diff --git a/src/occ/pss/test/app.mk b/src/occ/pss/test/app.mk
new file mode 100755
index 0000000..f0ecbfc
--- /dev/null
+++ b/src/occ/pss/test/app.mk
@@ -0,0 +1,128 @@
+# $Id$
+
+# @file app.mk
+#
+# @brief mk occ application
+#
+# This Makefile is included-ed into application Makefiles and
+# encapsulates the steps necessary to create application images.
+#
+# The application Makefile (user) must define the following variables:
+#
+# APP - The name of the application
+# SOURCES - The list of local source files that implement the
+# application.
+#
+# The application Makefile (user) may optionally define the following
+# variables:
+#
+# D - The value of $(D) is appended to DEFS defined by ssx.mk
+#
+# MODE - The following modes are recognized:
+#
+# validation - (Default) An application that requires all SSX
+# services.
+#
+# firmware - An interrupt only configuration.
+#
+# The make process creates the following files:
+#
+# $(APP).out - The PowerPC-ELF version of the application
+# $(APP).bin - A binary SRAM image of the application
+# $(APP).map - The linker map of the application
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# nguyenp 09/27/2011 created
+# borrowed from occ/rtls/test/app.mk
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+
+#*******************************************************************************
+# mk variable Declaration
+#*******************************************************************************
+
+OCC = ../../
+SSX = ../../../ssx
+LIB = ../../../lib
+PGP = $(SSX)/pgp
+
+ifeq "$(MODE)" "firmware"
+SSX_TIMER_SUPPORT = 0
+SSX_THREAD_SUPPORT = 0
+endif
+
+#*******************************************************************************
+# Export
+#*******************************************************************************
+export SSX_TIMER_SUPPORT
+export SSX_THREAD_SUPPORT
+export PPC405_MMU_SUPPORT
+export PGP_ASYNC_SUPPORT
+
+#*******************************************************************************
+# Flags
+#*******************************************************************************
+
+INCLUDES = -I $(OCC) -I$(LIB)
+
+include $(PGP)/ssx.mk
+
+C-OBJECTS = $(SOURCES:.c=.o)
+OBJECTS = $(C-OBJECTS:.S=.o)
+
+LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \
+ -L $(OCC) -L $(LIB) -lssx -lppc32
+
+
+DEFS += $(D)
+
+#*******************************************************************************
+# compilation
+#*******************************************************************************
+# @pb000a - Added $(BOOTLOADER)/imageHdrScript usage for building occ image
+all: $(OBJECTS) libssx.a
+ $(MAKE) -C $(PGP) DEFS="$(DEFS)" -e
+ $(CPP) -P $(DEFS) < $(PGP)/linkssx.cmd > linkscript
+ $(LD) $(OBJECTS) \
+ -Tlinkscript $(LDFLAGS) -Map $(APP).map -Bstatic -o $(APP).out
+ $(OBJCOPY) -O binary $(APP).out $(APP).bin
+ $(OBJDUMP) -d $(APP).out > $(APP).dis
+
+
+libssx.a:
+ $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e
+
+#*******************************************************************************
+# clean
+#*******************************************************************************
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map linkscript
+ rm -f ./*/*.o ./*/*.d ./*/*.d.*
+
+.PHONY : clean_all
+clean_all:
+ $(MAKE) clean
+ $(MAKE) -C $(PGP) clean
+
+#*******************************************************************************
+# Doxygen
+#*******************************************************************************
+
+.PHONY : doc
+doc:
+ doxygen doc/Doxyfile
+
+#*******************************************************************************
+# .d file creation
+#*******************************************************************************
+
+include $(OBJECTS:.o=.d)
diff --git a/src/occ/pss/test/apsstest.c b/src/occ/pss/test/apsstest.c
new file mode 100755
index 0000000..8a0ab99
--- /dev/null
+++ b/src/occ/pss/test/apsstest.c
@@ -0,0 +1,478 @@
+/******************************************************************************
+// @file apsstest.c
+// @brief OCC APSS TEST
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section apsstest.c APSSTEST.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ *
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+//#include <trac_interface.h>
+#include <thread.h>
+#include <threadSch.h>
+#include <errl.h>
+#include <apss.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+//@pb000a - added
+//extern void __ssx_boot;
+
+//*************************************************************************
+// Image Header
+//*************************************************************************
+//@pb000a - added
+//@dw000c - call with Applet ID arg (in case it gets uncommented & reused).
+//IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,OCC_APLT_TEST);
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+/// Period in which to run #timer_routine
+#define TIMER_INTERVAL (SsxInterval) SSX_MICROSECONDS(5000)
+//@pb000d - deleted TPMD_code_header as not used
+SsxSemaphore prcd_sem;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+int g_j = 0;
+int g_k = 0;
+
+SimicsStdio simics_stdout;
+SimicsStdio simics_stderr;
+
+uint8_t noncritical_stack[NONCRITICAL_STACK_SIZE];
+uint8_t critical_stack[CRITICAL_STACK_SIZE];
+
+SsxTimer G_test_timer;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+extern void timer_routine(void *private);
+extern void rtloop_ocb_init(void);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: pgp_validation_ssx_main_hook
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void pgp_validation_ssx_main_hook(void)
+{
+
+}
+
+// Function Specification
+//
+// Name: Cmd_Hndl_thread_routine
+//
+// Description:
+//
+// Flow: FN=Cmd_Hndl_thread_routine
+//
+// End Function Specification
+//TODO placeholder
+void Cmd_Hndl_thread_routine(void *arg)
+{
+ do
+ {
+ int x=0;
+ for(x=0; x < 1000; x++)
+ {
+
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: App_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void App_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: Thermal_Monitor_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Thermal_Monitor_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: Hlth_Monitor_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Hlth_Monitor_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: FFDC_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void FFDC_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+/** PRCD Thread
+ *
+ * This thread loops as the highest priority thread, where it currently
+ * just
+ *
+ */
+// Function Specification
+//
+// Name: prcd_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void prcd_thread_routine(void *private)
+{
+ while(1)
+ {
+ // Just sit here until this semaphore is posted, which will never happen.
+ ssx_semaphore_pend(&prcd_sem, SSX_WAIT_FOREVER);
+
+ // Only trace the first XX times that this function loops
+ if(g_j < 20)
+ {
+ g_k = 0;
+ g_j++;
+
+ }
+ }
+}
+
+
+// Function Specification
+//
+// Name: apss_test_pwr_meas
+//
+// Description: Request the full power measurement data in a single function call for TESTING ONLY
+//
+// Flow: FN=None
+//
+// End Function Specification
+extern PoreEntryPoint pore_test; // Sleep for specified amount of time...
+void apss_test_pwr_meas(void)
+{
+ task_apss_start_pwr_meas();
+
+ // Schedule GPE program to delay to ensure the data is available... (BLOCKING)
+ // bad: 48, good: 56
+ PoreFlex test_request;
+ DEBUG_PRINTF(("apss_test_pwr_meas: delay...\n"));
+ pore_flex_create(&test_request,
+ &pore_gpe0_queue,
+ (void*)pore_test, // entry_point
+ (uint32_t)56, // entry_point argument
+ NULL, // callback,
+ NULL, // callback arg
+ ASYNC_REQUEST_BLOCKING); // options
+ pore_flex_schedule(&test_request);
+ DEBUG_PRINTF(("apss_test_pwr_meas: delay complete\n"));
+
+ task_apss_continue_pwr_meas();
+
+ task_apss_complete_pwr_meas();
+
+} // end apss_test_pwr_meas()
+
+
+
+
+/** Main Thread
+ *
+ * This thread currently just loops as the lowest priority thread, handling
+ * the lowest priority tasks.
+ *
+ */
+// Function Specification
+//
+// Name: main_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void main_thread_routine(void *private)
+{
+ // Start the critical 250uS timer
+ ssx_timer_schedule(&timer, 1, TIMER_INTERVAL);
+
+ // Initialize APSS // @cc000a
+ errlHndl_t l_errl = apss_initialize();
+ if (l_errl)
+ {
+ // init failed, attempt one more time before giving up
+ printf("ERROR: apss_initialize failed! (retrying)\n");
+ setErrlSevToInfo(l_errl);
+ commitErrl(&l_errl);
+
+ l_errl = apss_initialize();
+ if (l_errl)
+ {
+ printf("ERROR: apss_initialize failed again! (OCC will be reset)");
+ commitErrl(&l_errl);
+
+ // $TODO - Request Reset
+ }
+ }
+
+ // Attempt to retrieve 3 sets of measurements
+ printf("Attempting to gather power measurements\n");
+ apss_test_pwr_meas();
+ apss_test_pwr_meas();
+ apss_test_pwr_meas();
+
+ while(1)
+ {
+ // Only trace the first XX times that this function loops
+ if(g_k < 3)
+ {
+ g_k++;
+
+ // TRACE: Main Thread
+ }
+
+
+ // Sleep for 1000 before we run the loop again
+ ssx_sleep_absolute(1000);
+ }
+}
+
+// Function Specification
+//
+// Name: dump_thread_info
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void dump_thread_info(void *arg)
+{
+
+ printf("dumping thread info--------------------------\n");
+ int l_rc = 0;
+ SsxThreadState l_state = 0;
+ SsxThreadPriority l_pri = 0;
+ int l_runnable=0;
+ int x=0;
+ for(x=0; x < THREADS_TO_SCHEDULE; x++)
+ {
+ l_rc = ssx_thread_info_get(G_scheduledThreads[x],
+ &l_state,
+ &l_pri,
+ &l_runnable);
+
+ printf("Thread %p: State %x priority %x runnable %x rc %x Global index %x\n",G_scheduledThreads[x],
+ l_state,
+ l_pri,
+ l_runnable,
+ l_rc,
+ G_threadSchedulerIndex);
+
+ }
+
+}
+
+/** Entry point for OCC execution
+ *
+ * main() currently initalizes our trace buffer along with creating threads
+ * and timers for execution. Note that once main runs ssx_start_threads, we
+ * never return as the SSX kernel takes over.
+ *
+ */
+// Function Specification
+//
+// Name: main
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+int main(int argc, char **argv)
+{
+ //locals
+ errlHndl_t l_errl = NULL;
+
+ // Initialize Trace Buffers immediately, so they can be used
+ // from this point on.
+ //TRAC_init_buffers();
+
+ // Initialize stdout so we can do printf from within simics env
+ simics_stdout_create(&simics_stdout);
+ simics_stderr_create(&simics_stderr);
+ stdout = (FILE *)(&simics_stdout);
+ stderr = (FILE *)(&simics_stderr);
+
+ //@pb000a - added
+ printf("Inside apsstest main\n");
+
+ // Initialize SSX Stacks (note that this also reinitializes the time base to 0)
+ ssx_initialize((SsxAddress)noncritical_stack, NONCRITICAL_STACK_SIZE,
+ (SsxAddress)critical_stack, CRITICAL_STACK_SIZE,
+ 0);
+
+ // Create Timers
+ //ssx_timer_create(&timer, timer_routine, 0);
+
+ // Create Global Semaphores
+ ssx_semaphore_create(&prcd_sem, 0, 13);
+
+ // Create Threads
+ ssx_thread_create(&main_thread,
+ main_thread_routine,
+ (void *)0,
+ (SsxAddress)main_thread_stack,
+ THREAD_STACK_SIZE,
+ 1);
+
+ // Create Threads
+ ssx_thread_create(&prcd_thread,
+ prcd_thread_routine,
+ (void *)0,
+ (SsxAddress)prcd_thread_stack,
+ THREAD_STACK_SIZE,
+ 0);
+
+ // Make Threads runnable
+ ssx_thread_resume(&main_thread);
+ ssx_thread_resume(&prcd_thread);
+
+ //Initialize the thread scheduler
+ l_errl = initThreadScheduler();
+
+ if( l_errl )
+ {
+ // Trace and commit error
+
+ // TODO add trace
+
+ // commit log
+ // NOTE: log should be deleted by reader mechanism
+ commitErrl( &l_errl );
+ }
+
+ // Initialize Realtime Loop Timer Interrupt
+ //rtloop_ocb_init();
+
+ //kick off timer
+ ssx_timer_create(&G_test_timer, dump_thread_info, 0);
+ ssx_timer_schedule(&G_test_timer, 1, 500000000);
+
+
+ // Enter SSX Kernel
+ ssx_start_threads();
+
+ return 0;
+}
+
diff --git a/src/occ/reset.c b/src/occ/reset.c
new file mode 100755
index 0000000..e771d00
--- /dev/null
+++ b/src/occ/reset.c
@@ -0,0 +1,234 @@
+/******************************************************************************
+// @file reset.c
+// @brief OCC Reset States
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section reset.c reset.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th011 thallet 07/16/2012 New file
+ * @th042 892056 thallet 07/19/2013 Send OCC to safe mode if first APSS GPE fails
+ * @th046 894648 thallet 08/08/2013 Piggyback a 1-liner on the coreq fix
+ * @jh00b 910184 joshych 01/10/2014 Add check for checkstop
+ * @gm028 911670 milesg 02/27/2014 Immediate safe mode on checkstop
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <common_types.h>
+#include "ssx_io.h"
+#include "trac.h"
+#include "rtls.h"
+#include "state.h"
+#include "dcom.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Forward Declarations
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// Holds the state of the reset state machine
+uint8_t G_reset_state = RESET_NOT_REQUESTED;
+
+// Flag indicating if we should halt on a reset request, or if we should
+// enter the reset state machine. Default this to false
+bool G_halt_on_reset_request = FALSE; // @th042
+
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: reset_disable_halt
+//
+// Description: Clear Flag that indicates if OCC should call halt
+//
+// Flow: 10/25/11 FN=task_reset_state_machine
+//
+// End Function Specification
+inline void reset_disable_halt(void)
+{
+ G_halt_on_reset_request = FALSE;
+}
+
+
+// Function Specification
+//
+// Name: isSafeStateRequested
+//
+// Description: Helper function for determining if we should go to safe state
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+bool isSafeStateRequested(void)
+{
+ return ((RESET_REQUESTED_DUE_TO_ERROR == G_reset_state) ? TRUE : FALSE);
+}
+
+
+// Function Specification
+//
+// Name: reset_state_request
+//
+// Description: Request Reset States
+//
+// Flow: 10/25/11 FN=task_reset_state_machine
+//
+// End Function Specification
+void reset_state_request(uint8_t i_request)
+{
+ //TODO: This needs to be changed so that G_reset_state operations are
+ // atomic.
+
+ switch(i_request)
+ {
+ case RESET_REQUESTED_DUE_TO_ERROR:
+ // In case we want to just halt() if fw requests a reset, this is
+ // the place to do it. It is disabled by default, and there is no
+ // code to eanble it.
+ if( G_halt_on_reset_request )
+ {
+ TRAC_ERR("Halt()");
+
+ // This isn't modeled very well in simics. OCC will go into an
+ // infinite loop, which eventually would crash Simics.
+ HALT_WITH_FIR_SET;
+ }
+
+ // If we have TMGT comm, and we aren't already in reset, set the reset
+ // state to reset to enter the reset state machine.
+ if(G_reset_state < RESET_REQUESTED_DUE_TO_ERROR)
+ {
+ TRAC_ERR("Resetting via Reset State Machine");
+
+ G_reset_state = RESET_REQUESTED_DUE_TO_ERROR;
+
+ // Post the semaphore to wakeup the thread that
+ // will put us into SAFE state.
+ ssx_semaphore_post(&G_dcomThreadWakeupSem); // @th042
+
+ // Set RTL Flags here too, depending how urgent it is that we stop
+ // running tasks.
+ rtl_set_run_mask(RTL_FLAG_RST_REQ);
+ }
+ break;
+
+ case NOMINAL_REQUESTED_DUE_TO_ERROR:
+ if(G_reset_state < NOMINAL_REQUESTED_DUE_TO_ERROR)
+ {
+ TRAC_ERR("Going to Nominal because of error");
+
+ // May need to add counter if multiple places request nominal
+ G_reset_state = NOMINAL_REQUESTED_DUE_TO_ERROR;
+
+ //TODO: Will need to set some flag or event here
+ }
+ break;
+
+ case RESET_NOT_REQUESTED:
+ if(G_reset_state == NOMINAL_REQUESTED_DUE_TO_ERROR)
+ {
+ TRAC_IMP("Clearing Nominal Reset State because of error");
+
+ // May need to add counter check if multiple places request nominal
+ G_reset_state = RESET_NOT_REQUESTED;
+
+ //TODO: Will need to clear some flag or event here
+ }
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+// Function Specification
+//
+// Name: task_check_for_checkstop
+//
+// Description: Check for checkstop
+//
+// Flow: FN=task_check_for_checkstop
+//
+// End Function Specification
+void task_check_for_checkstop(task_t *i_self) // @jh00bc
+{
+ pore_status_t l_gpe0_status;
+ static bool L_gpe_halt_traced = FALSE;
+
+ do
+ {
+ //only do this once
+ if(L_gpe_halt_traced)
+ {
+ break;
+ }
+
+ L_gpe_halt_traced = TRUE;
+
+ l_gpe0_status.value = in64(PORE_GPE0_STATUS);
+
+ if (l_gpe0_status.fields.freeze_action)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_check_for_checkstop: OCC GPE halted due to checkstop");
+
+ /*
+ * @errortype
+ * @moduleid MAIN_GPE_HALTED_MID
+ * @reasoncode OCC_GPE_HALTED
+ * @userdata1 0
+ * @userdata2 0
+ * @devdesc OCC GPE halted due to checkstop
+ */
+ l_err = createErrl(MAIN_GPE_HALTED_MID,
+ OCC_GPE_HALTED,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ 0,
+ 0);
+
+ //This will request safe mode under the covers due to the GPE being halted.
+ commitErrl(&l_err);
+ }
+
+ } while (0);
+}
+
+
+
+
diff --git a/src/occ/rtls/rtls.c b/src/occ/rtls/rtls.c
new file mode 100755
index 0000000..4802700
--- /dev/null
+++ b/src/occ/rtls/rtls.c
@@ -0,0 +1,574 @@
+/******************************************************************************
+// @file rtls.c
+// @brief OCC rtls component
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _rtls_c rtls.c
+ * @verbatim
+ * @th00a thallet 02/03/12 Worst case FW timings in AMEC Sensors
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * np, dw 08/10/2011 created by nguyenp & dwoodham
+ * @01 dwoodham 08/29/2011 only log 1 unrec err on invalid task ID
+ * @02 tapiar 10/03/2011 Changed BOOLEAN to bool
+ * @03 nguyenp 10/03/2011 Added bit observation state to the
+ * global rtls run mask
+ * @th002 thallet 11/01/2011 Misc Changes for Nov 1st Milestone
+ * @pb00A pbavari 11/15/2011 Deferred mask support
+ * @rc001 rickylie 12/30/2011 Added trac.h
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th022 thallet 10/01/2012 Added STANDBY FLAG
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @wb003 920760 wilbryan 03/25/2014 Update SRCs to match TPMD SRCs
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "rtls.h"
+#include "rtls_service_codes.h"
+#include "threadSch.h" // for DEFAULT_TRACE_SIZE
+#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
+#include <pgp_common.h> // OCB interrupt controller
+#include <pgp_ocb.h> // OCB timer
+#include <errl.h> // Error logging
+#include "amec_external.h"
+#include <trac.h> // Traces
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+//Macro creates a 'bridge' handler that converts the initial fast-mode to full
+//mode interrupt handler
+SSX_IRQ_FAST2FULL(rtl_intr_handler, rtl_do_tick);
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define RTLOOP_TIMEOUT_IN_NS (MICS_PER_TICK * 1000)
+
+#define GLOBAL_RUN_MASK RTL_FLAG_RUN | RTL_FLAG_STANDBY | RTL_FLAG_MSTR_READY | RTL_FLAG_APSS_NOT_INITD
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// Required flag bits for running
+// The run flag is always set
+uint32_t G_run_mask = GLOBAL_RUN_MASK; //@03a @th002
+// @pb00Aa - Added deferred mask global
+uint32_t G_run_mask_deferred = GLOBAL_RUN_MASK;
+
+// The value of the current tick
+uint32_t G_current_tick = 0xFFFFFFFF;
+
+// The durations measured within the current tick
+fw_timing_t G_fw_timing; // @th00a
+
+// The global TICK table
+// See notes regarding this table in rtls_tables.c.
+extern uint8_t *G_tick_table[MAX_NUM_TICKS];
+
+// The global TASK table
+// See notes regarding this table in rtls_tables.c.
+extern task_t G_task_table[TASK_END];
+
+// ARL Test Code Function from arl_test.c
+// Added for enablement of Research use of OCC Environment
+//TODO: Remove when no longer needed.
+extern void arl_test(void); // @th002
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: rtl_start_task
+//
+// Description: Request that a task runs.
+//
+// Flow: 08/09/11 FN=rtl_do_tick
+//
+// End Function Specification
+
+void rtl_start_task(const task_id_t i_task_id) {
+
+ errlHndl_t l_err = NULL; // Error handler
+ tracDesc_t l_trace = NULL; // Temporary trace descriptor
+
+ if ( i_task_id < TASK_END ) {
+ // Request the task be run
+ G_task_table[i_task_id].flags |= RTL_FLAG_RUN;
+ }
+ else {
+ // Invalid task ID for this operation
+ // TODO use correct trace
+
+ /*
+ * @errortype
+ * @moduleid RTLS_START_TASK_MOD
+ * @reasoncode INTERNAL_INVALID_INPUT_DATA
+ * @userdata1 Failing task ID
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware failure starting task
+ */
+ l_err = createErrl(
+ RTLS_START_TASK_MOD, //modId
+ INTERNAL_INVALID_INPUT_DATA, //reasoncode // @wb003
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_task_id, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ commitErrl( &l_err );
+ }
+}
+
+
+// Function Specification
+//
+// Name: rtl_stop_task
+//
+// Description: Request that a task NOT run
+//
+// Flow: 08/09/11 FN=rtl_do_tick
+//
+// End Function Specification
+
+void rtl_stop_task(const task_id_t i_task_id) {
+
+ errlHndl_t l_err = NULL; // Error handler
+ tracDesc_t l_trace = NULL; // Temporary trace descriptor
+
+ if ( i_task_id < TASK_END ) {
+ // Request the task NOT be run
+ G_task_table[i_task_id].flags &= ~RTL_FLAG_RUN;
+ }
+ else {
+ // Invalid task ID for this operation
+ // TODO use correct trace
+
+ /*
+ * @errortype
+ * @moduleid RTLS_STOP_TASK_MOD
+ * @reasoncode INTERNAL_INVALID_INPUT_DATA
+ * @userdata1 Failing task ID
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware failure stopping task
+ */
+ l_err = createErrl(
+ RTLS_STOP_TASK_MOD, //modId
+ INTERNAL_INVALID_INPUT_DATA, //reasoncode // @wb003
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_task_id, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ commitErrl( &l_err );
+ }
+}
+
+
+// Function Specification
+//
+// Name: rtl_task_is_runnable
+//
+// Description: Find out if a task can run or not.
+//
+// Flow: 08/09/11 FN=rtl_do_tick
+//
+// End Function Specification
+
+bool rtl_task_is_runnable(const task_id_t i_task_id) {
+
+ bool task_can_run = FALSE; // Default: task can NOT run
+ errlHndl_t l_err = NULL; // Error handler
+ tracDesc_t l_trace = NULL; // Temporary trace descriptor
+
+ if ( i_task_id < TASK_END ) {
+
+ if ( G_task_table[i_task_id].flags & RTL_FLAG_RUN ) {
+ // Yes, the task CAN run
+ task_can_run = TRUE;
+ }
+ }
+ else {
+ // Invalid task ID for this operation
+ // TODO use correct trace
+
+ /*
+ * @errortype
+ * @moduleid RTLS_TASK_RUNABLE_MOD
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 Failing task ID
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware failure on task operation
+ */
+ l_err = createErrl(
+ RTLS_TASK_RUNABLE_MOD, //modId
+ INTERNAL_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_task_id, //userdata1
+ 0 //userdata2
+ );
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // commit error log
+ commitErrl( &l_err );
+ }
+
+ return task_can_run;
+}
+
+
+// Function Specification
+//
+// Name: rtl_ocb_init
+//
+// Description: responsible for initializing the hardware timer in occ control
+// block. It is the timer that supplies the periodic RTL interrupt.
+//
+// Flow: 08/09/11 FN=rtl_do_tick
+//
+// End Function Specification
+
+void rtl_ocb_init(void)
+{
+ int rc = 0;
+ errlHndl_t l_err = NULL;
+ tracDesc_t l_trace = NULL; // Temporary trace descriptor
+
+ //setup an OCB timer and interrupt handler
+ //the ocb_timer_setup will do the following:
+ //a) setup the interrupt
+ //b) setup interrupt handler
+ //c) reset the timer
+ //d) enable the interrupt
+ rc = ocb_timer_setup(OCB_TIMER0,
+ OCB_TIMER_AUTO_RELOAD, //auto reload
+ RTLOOP_TIMEOUT_IN_NS, //250000ns or 250us for 1 tick
+ rtl_intr_handler, //intr handlers
+ 0,
+ SSX_NONCRITICAL);
+ if( rc )
+ {
+ //TODO: add trace
+
+ /*
+ * @errortype
+ * @moduleid RTLS_OCB_INIT_MOD
+ * @reasoncode INTERNAL_HW_FAILURE
+ * @userdata1 Return code for ocb_timer_setup
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure on hardware related function
+ */
+ l_err = createErrl(
+ RTLS_OCB_INIT_MOD, //modId
+ INTERNAL_HW_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ commitErrl( &l_err );
+ }
+}
+
+
+// Function Specification
+//
+// Name: rtl_do_tick
+//
+// Description: RTL intr handler, a full-mode handler that invokes through the
+// macro bridge. Runs all tasks in the current tick sequence.
+//
+// Flow: 11/15/11 FN=rtl_do_tick
+//
+// End Function Specification
+
+void rtl_do_tick( void *private, SsxIrqId irq, int priority )
+{
+ uint64_t l_start = ssx_timebase_get();
+
+ uint8_t *l_taskid_ptr = NULL; // Pointer to the current task ID in the current tick sequence
+ task_t *l_task_ptr = NULL; // Pointer to the currently executing task
+ errlHndl_t l_err = NULL; // Error handler
+ tracDesc_t l_trace = NULL; // Temporary trace descriptor (replace this when tracing is implemented)
+
+ bool l_bad_id_reported = FALSE; // @01a Has an invalid task ID already been reported?
+
+ //int rc;
+ SsxMachineContext ctx;
+
+ //enter the protected context
+ ssx_critical_section_enter( SSX_NONCRITICAL, &ctx );
+
+ //clear OCB timer0 status based on the interrupt
+ ocb_timer_status_clear( irq );
+
+ // Walk the tick sequence for the current tick,
+ // executing each runnable task listed.
+ CURRENT_TICK++;
+
+ // Save off start time of RTL tick
+ G_fw_timing.rtl_start = l_start; // @th00a
+
+ //@pb00Aa - Set global run mask point to deferred mask so that any
+ // modification to the deferred mask flag is taken into effect for this tick
+ G_run_mask = G_run_mask_deferred;
+
+ RTLS_DBG("#### Tick %d ####\n",CURRENT_TICK);
+
+ // Execute ARL Test Code before we run any tasks. TODO: Remove when no longer needed.
+ arl_test(); // @th002
+
+ // Index into the tick table to get a pointer to the tick sequence for the current tick.
+ l_taskid_ptr = G_tick_table[ (MAX_NUM_TICKS - 1) & CURRENT_TICK ];
+
+ do
+ {
+ if ( *l_taskid_ptr == TASK_END ) {
+ // We're done with this tick
+ break;
+ }
+
+ // >@01c
+ if ( *l_taskid_ptr > TASK_END ) {
+ // Invalid task ID.
+
+ if ( ! l_bad_id_reported ) {
+ // First bad task ID we've seen this tick. Log an unrecoverable error.
+
+ // TODO use correct trace
+
+ /*
+ * @errortype
+ * @moduleid RTLS_DO_TICK_MOD
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 Invalid task ID
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware failure on task operation
+ */
+ l_err = createErrl(
+ RTLS_DO_TICK_MOD, //modId
+ INTERNAL_FAILURE, //reasoncode // @nh001c
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ *l_taskid_ptr, //userdata1
+ 0 //userdata2
+ );
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // commit error log
+ commitErrl( &l_err );
+
+ // set our "bad ID reported" flag
+ l_bad_id_reported = TRUE;
+ }
+
+ // Under all conditions, move on to the next task ID.
+ l_taskid_ptr++;
+ continue;
+ }
+ // <@01c
+
+ l_task_ptr = &(G_task_table[ *l_taskid_ptr ]);
+
+ if ( ((l_task_ptr->flags & G_run_mask) == G_run_mask ) && (l_task_ptr->func_ptr != NULL) ) {
+
+ // The task's flags match the global run mask, and its function pointer is valid.
+ // This task is ready to run.
+ l_task_ptr->func_ptr(l_task_ptr);
+ }
+
+ // Increment to the next tick sequence before looping again.
+ l_taskid_ptr++;
+
+ } while(TRUE);
+
+ // Save timing of RTL tick
+ G_fw_timing.rtl_dur = DURATION_IN_US_UNTIL_NOW_FROM(l_start); // @th00a
+
+ RTLS_DBG("RTL Tick Duration: %d us\n",(int)G_fw_timing.rtl_dur);
+
+ //exit the protected context
+ ssx_critical_section_exit( &ctx );
+}
+
+
+// Function Specification
+//
+// Name: rtl_set_task_data
+//
+// Description: Changes the data pointer for the specified task
+//
+// Flow: 08/09/11 FN=rtl_do_tick
+//
+// End Function Specification
+
+void rtl_set_task_data( const task_id_t i_task_id, void * i_data_ptr )
+{
+ errlHndl_t l_err = NULL;
+ tracDesc_t l_trace = NULL; // Temporary trace descriptor
+
+ if ( i_task_id >= TASK_END )
+ {
+ //TODO: add trace
+ // Task ID is invalid so log an error internally
+
+ /*
+ * @errortype
+ * @moduleid RTLS_SET_TASK_DATA_MOD
+ * @reasoncode INTERNAL_INVALID_INPUT_DATA
+ * @userdata1 Failing task ID
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware internal failure setting task data
+ */
+ l_err = createErrl(
+ RTLS_SET_TASK_DATA_MOD, //modId
+ INTERNAL_INVALID_INPUT_DATA, //reasoncode // @wb003
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_task_id, //userdata1
+ 0 //userdata2
+ );
+
+ // commit error log
+ commitErrl( &l_err );
+ }
+ else
+ {
+ G_task_table[i_task_id].data_ptr = i_data_ptr;
+ }
+ return;
+}
+
+
+// Function Specification
+//
+// Name: rtl_set_run_mask
+//
+// Description: Stores the bitwise-or of i_flag and the global run mask into
+// the global run mask
+//
+// Flow: 11/15/11 FN=rtl_do_tick
+//
+// End Function Specification
+//@pb00A - Added setting of the flag in the global deferred run mask
+void rtl_set_run_mask( const uint32_t i_flags )
+{
+ G_run_mask |= i_flags;
+ G_run_mask_deferred |= i_flags;
+ return;
+}
+
+
+// Function Specification
+//
+// Name: rtl_clr_run_mask
+//
+// Description: Stores the bitwise-and of the inverse of i_flag and the global
+// run mask into the global run mask
+//
+// Flow: 11/15/11 FN=rtl_do_tick
+//
+// End Function Specification
+//@pb00A - Added clearing of the flag from the global deferred run mask
+void rtl_clr_run_mask( const uint32_t i_flags )
+{
+ // Don't let the caller clear the run flag from the global mask.
+ // We use an interim variable so we can keep i_flags const.
+ uint32_t l_mask = i_flags & ~RTL_FLAG_RUN;
+
+ G_run_mask &= ~l_mask;
+ G_run_mask_deferred &= ~l_mask;
+ return;
+}
+
+// Function Specification
+//
+// Name: rtl_set_run_mask_deferred
+//
+// Description: Stores the bitwise-or of i_flag and the global run mask
+// deferred into the global run mask deferred
+//
+// Flow: 11/15/11 FN=rtl_do_tick
+//
+// End Function Specification
+
+void rtl_set_run_mask_deferred( const uint32_t i_flags )
+{
+ G_run_mask_deferred |= i_flags;
+ return;
+}
+
+
+// Function Specification
+//
+// Name: rtl_clr_run_mask_deferred
+//
+// Description: Stores the bitwise-and of the inverse of i_flag and the global
+// run mask deferred into the global run mask deferred.
+//
+// Flow: 11/15/11 FN=rtl_do_tick
+//
+// End Function Specification
+
+void rtl_clr_run_mask_deferred( const uint32_t i_flags )
+{
+ // Don't let the caller clear the run flag from the global mask.
+ // We use an interim variable so we can keep i_flags const.
+ uint32_t l_mask = i_flags & ~RTL_FLAG_RUN;
+
+ G_run_mask_deferred &= ~l_mask;
+ return;
+}
diff --git a/src/occ/rtls/rtls.h b/src/occ/rtls/rtls.h
new file mode 100755
index 0000000..516ebd5
--- /dev/null
+++ b/src/occ/rtls/rtls.h
@@ -0,0 +1,214 @@
+/******************************************************************************
+// @file rtls.h
+// @brief OCC rtls component header file.
+*/
+/******************************************************************************
+ * @th00a thallet 02/06/12 Sensors with fw timings
+ *
+ * @page ChangeLogs Change Logs
+ * @section _rtls_h rtls.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * np, dw 08/10/2011 created by nguyenp & dwoodham
+ * @pb004 pbavari 09/12/2011 Initialization section support
+ * @pb007 pbavari 09/27/2011 Watchdog timer task support
+ * @02 tapiar 10/03/2011 Changed BOOLEAN to bool, added tasks
+ * @03 nguyenp 10/10/2011 Added task_core_data_low and
+ * add task_core_data_high tasks
+ * @pb008 pbavari 10/04/2011 Combined watchdog reset tasks
+ * @05 abagepa 10/16/2011 Added slave to master tasks &
+ * master ready flag
+ * @dw000 dwoodham 10/21/2011 Added DPSS read status task
+ * @06 nguyenp 10/24/2011 Added fast_core_data task
+ * @07 abagepa 11/16/2011 Added dcom parse occ task
+ * & reset state machine task
+ * @08 tapiar 11/30/2011 Added Amec slave and master tasks
+ * @rc001 rickylie 12/30/2011 Moved debug trace defines to trac.h
+ * @rc002 rickylie 02/02/2012 Remove unused DPSS function
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th00c thallet 04/04/2012 Centaur Support
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th015 thallet 08/03/2012 Added deferred task flag setting
+ * @th022 thallet 10/03/2012 Changes to allow DCOM State/Mode setting
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @gm004 892961 milesg 07/25/2013 Allow mem autslew to start centaur tasks
+ * @jh00b 910184 joshych 01/10/2014 Add check for checkstop
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ * @gm038 926761 milesg 05/16/2014 Centaur tasks were not running
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _RTLSCH_H
+#define _RTLSCH_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <ssx.h>
+#include <ssx_app_cfg.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+typedef struct task {
+ uint32_t flags;
+ void (*func_ptr)(struct task*);
+ void *data_ptr;
+}task_t;
+
+// Task ID values
+// These are used as indices into the task table defined below.
+// @pb007a - Added TASK_ID_RESET_405WDT and TASK_ID_RESET_OCBT
+// @pb008c - Combined ppc405 watchdog and OCB timer task into one
+// @rc002 - Remove unused TASK_ID_DPSS_RD_STATUS
+typedef enum {
+ TASK_ID_APSS_START = 0x00,
+ TASK_ID_CORE_DATA_LOW, //@03a
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH, //@03a
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA, //@06a
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_POKE_WDT, // reset ppc405 watchdog and OCB timer
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP, // @jh00bc
+ TASK_ID_AMEC_SLAVE, // @08a amec smh tasks
+ TASK_ID_AMEC_MASTER, // @08a amec smh task
+ TASK_ID_CENTAUR_DATA, // @tgh00c centaur task
+ TASK_ID_CORE_DATA_CONTROL, // @th010
+ TASK_ID_CENTAUR_CONTROL, // @th031 centaur task
+ TASK_END // This must always be the last enum in this list,
+ // so that TASK_END always equals the last task ID + 1.
+} task_id_t;
+
+// Structure containing the durations measured within a tick
+typedef struct
+{
+ uint32_t rtl_dur; // Duration of RTL tick interrupt
+ uint32_t ameint_dur; // Combined duration of mstr & slv AMEC tasks
+ uint32_t amess_dur; // Combined duration of last mstr & slv AMEC state
+ uint8_t amess_state; // Last AMEC state that was run
+ uint64_t rtl_start; // SsxTimebase of Start of current RTL Tick
+ uint64_t rtl_start_gpe; // SsxTimebase of Start of current RTL Tick (for GPE > 250us meas)
+ uint32_t gpe_dur[2]; // Duration of the GPE Engines / tick
+ PoreFlex * gpe0_timing_request; // GPE Request that facilitates GPE WC meas
+ PoreFlex * gpe1_timing_request; // GPE Request that facilitates GPE WC meas
+} fw_timing_t; // @th00a
+
+
+// Bit flags to define when a task can run
+// NOTE: whenever new flag is added, it must also be added to the
+// RTL_ALL_FLAGS define.
+#define RTL_FLAG_NONE 0x00000000 // Task has been turned off permanently
+#define RTL_FLAG_RUN 0x00000001 // Task has been requested to run
+#define RTL_FLAG_MSTR 0x00000002 // Task can run on the master
+#define RTL_FLAG_NOTMSTR 0x00000004 // Task can run on non-masters
+#define RTL_FLAG_OBS 0x00000008 // Task can run in observation state
+#define RTL_FLAG_ACTIVE 0x00000010 // Task can run in active state
+#define RTL_FLAG_RST_REQ 0x00000020 // Task can run after a reset request
+#define RTL_FLAG_NO_APSS 0x00000040 // Task can run with no APSS present
+#define RTL_FLAG_MSTR_READY 0x00000080 // Task can run Master is ready
+#define RTL_FLAG_STANDBY 0x00000100 // Task can run in Standby state // @th022
+#define RTL_FLAG_APSS_NOT_INITD 0x00000200 // Task can run while APSS is not initialized -- gm037
+
+//gm038
+#define RTL_ALL_FLAGS (RTL_FLAG_RUN | RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | \
+ RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_RST_REQ | \
+ RTL_FLAG_NO_APSS | RTL_FLAG_MSTR_READY | RTL_FLAG_STANDBY | \
+ RTL_FLAG_APSS_NOT_INITD)
+
+//gm038
+#define CENTAUR_CONTROL_RTL_FLAGS (RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_ACTIVE | \
+ RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | \
+ RTL_FLAG_APSS_NOT_INITD)
+//gm038
+#define CENTAUR_DATA_RTL_FLAGS (RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | \
+ RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | \
+ RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD)
+
+// Tick Timer definitions
+#define MICS_PER_TICK 250 // Number of micro-seconds per tick
+#define MAX_NUM_TICKS 8 // Number of entries in the global tick table (power of 2)
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// The value of the current tick
+extern uint32_t G_current_tick;
+
+// The durations measured within the current tick
+extern fw_timing_t G_fw_timing; // @th00a
+
+// Preferred macro for accessing the current tick value
+#define CURRENT_TICK G_current_tick
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// rtl_ocb_init
+// Responsible for initializing the hardware timer in occ control block.
+// It is the timer that supplies the periodic RTL interrupt.
+void rtl_ocb_init(void) INIT_SECTION;
+
+// rtl_do_tick
+// RTL intr handler, a full-mode handler that invokes through the macro brige
+// Runs all tasks in the current tick sequence.
+void rtl_do_tick(void *private, SsxIrqId irq, int priority);
+
+// rtl_start_task
+// Request that a task runs, starting the next time it comes up
+// in a tick sequence.
+void rtl_start_task(const task_id_t i_task_id);
+
+// rtl_stop_task
+// Request that a task NOT run any time it comes up in a tick sequence.
+void rtl_stop_task(const task_id_t i_task_id);
+
+// rtl_task_is_runnable
+// Find out if a task can run or not.
+bool rtl_task_is_runnable(const task_id_t i_task_id);
+
+// rtl_set_task_data
+// Changes the data pointer for the specified task.
+void rtl_set_task_data(const task_id_t i_task_id, void* i_data_ptr);
+
+// rtl_set_run_mask
+// Stores the bitwise-or of i_flag and the global run mask
+// into the global run mask.
+void rtl_set_run_mask(const uint32_t i_flags);
+void rtl_set_run_mask_deferred( const uint32_t i_flags );
+
+// rtl_clr_run_mask
+// Stores the bitwise-and of the inverse of i_flag and the global run mask
+// into the global run mask.
+void rtl_clr_run_mask(const uint32_t i_flags);
+void rtl_clr_run_mask_deferred( const uint32_t i_flags );
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_RTLSCH_H
diff --git a/src/occ/rtls/rtls_service_codes.h b/src/occ/rtls/rtls_service_codes.h
new file mode 100755
index 0000000..b54138d
--- /dev/null
+++ b/src/occ/rtls/rtls_service_codes.h
@@ -0,0 +1,66 @@
+/******************************************************************************
+// @file rtls_service_codes.h
+// @brief Error codes for rtls component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _rtls_service_codes_h rtls_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * np, dw 08/10/2011 created by nguyenp & dwoodham
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _RTLS_SERVICE_CODES_H_
+#define _RTLS_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum rtlsModuleId
+{
+ RTLS_OCB_INIT_MOD = RTLS_COMP_ID | 0x00,
+ RTLS_DO_TICK_MOD = RTLS_COMP_ID | 0x01,
+ RTLS_START_TASK_MOD = RTLS_COMP_ID | 0x02,
+ RTLS_STOP_TASK_MOD = RTLS_COMP_ID | 0x03,
+ RTLS_TASK_RUNABLE_MOD = RTLS_COMP_ID | 0x04,
+ RTLS_SET_TASK_DATA_MOD = RTLS_COMP_ID | 0x05,
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _RTLS_SERVICE_CODES_H_ */
diff --git a/src/occ/rtls/rtls_tables.c b/src/occ/rtls/rtls_tables.c
new file mode 100755
index 0000000..96c8f09
--- /dev/null
+++ b/src/occ/rtls/rtls_tables.c
@@ -0,0 +1,370 @@
+/******************************************************************************
+// @file rtls_tables.c
+// @brief OCC RTLS COMPONENT TABLES
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _rtls_tables_c rtls_tables.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * np, dw 08/10/2011 created by nguyenp & dwoodham
+ * @pb007 pbavari 09/27/2011 Watchdog timer support
+ * @01 abagepa 09/18/2011 updated task table with tasks
+ * @02 nguyenp 09/28/2011 Added task_core_data_low and
+ * add task_core_data_high tasks
+ * @pb008 pbavari 10/04/2011 Combined watchdog reset tasks
+ * @04 tapiar 10/16/2011 Added dcom slave to master tasks
+ * @dw000 dwoodham 10/21/2011 Add DPSS read status task
+ * @05 nguyenp 10/24/2011 Added fast_core_data task
+ * @pb00A pbavari 11/15/2011 APSS task enabled only on occ_alone
+ * simics model
+ * @06 abagepa 11/16/2011 Added dcom parse occ task
+ * & reset state machine task
+ * @07 tapiar 11/30/2011 Added amec slave and master state
+ * machine tasks
+ * @rc002 rickylie 02/02/2012 Remove unused DPSS function
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00c thallet 04/04/2012 Centaur Support
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th015 thallet 08/03/2012 Proc Data control in active only
+ * @th022 thallet 10/03/2012 Changes to allow DCOM State/Mode setting
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup Changes - moved wait4mstr
+ * @th038 thallet 06/03/2013 Disable Centaur since it isn't ready on HW yet
+ * @gm004 892961 milesg 07/25/2013 Allow mem autoslew to start centaur tasks
+ * @th046 894648 thallet 08/08/2013 Piggyback a RESET flag change on the coreq fix
+ * @jh00b 910184 joshych 01/10/2014 Add check for checkstop
+ * @sb023 913769 sbroyles 02/08/2014 Change poke watchdog flags
+ * @gm029 917998 milesg 03/06/2014 Send slave inbox while in standby state
+ * @gm035 921471 milesg 03/31/2014 removed unused code
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "rtls.h"
+#include <timer.h> // timer reset task
+#include "apss.h"
+#include "dcom.h"
+#include "state.h"
+#include "proc_data.h" // @02a
+#include "proc_data_control.h" // @th010
+#include <centaur_data.h>
+#include <centaur_control.h> // @th031
+#include "amec_master_smh.h" // @07a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+//flags for task table
+//@th022 - removed OCC_ALONE check
+#define APSS_TASK_FLAGS RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_RUN
+
+//>@th002
+#define FLAGS_DCOM_RX_SLV_INBX RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_RUN | RTL_FLAG_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_DCOM_TX_SLV_INBX RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_RUN | RTL_FLAG_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
+
+//>@04
+#define FLAGS_DCOM_WAIT_4_MSTR RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_DCOM_RX_SLV_OUTBOX RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_DCOM_TX_SLV_OUTBOX RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_STANDBY | RTL_FLAG_APSS_NOT_INITD
+//<@04
+
+//>@02a
+#define FLAGS_LOW_CORES_DATA RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_HIGH_CORES_DATA RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
+//<@02a
+
+//Start out with centaur tasks not running.
+#define FLAGS_CENTAUR_DATA RTL_FLAG_NONE
+#define FLAGS_CENTAUR_CONTROL RTL_FLAG_NONE
+
+//>@05a
+#define FLAGS_FAST_CORES_DATA RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
+//<@05a
+//<@th002
+
+//>@06a
+#define FLAGS_AMEC_SLAVE RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_AMEC_MASTER RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
+//<@06a
+
+#define FLAGS_APSS_START_MEAS APSS_TASK_FLAGS
+#define FLAGS_APSS_CONT_MEAS APSS_TASK_FLAGS
+#define FLAGS_APSS_DONE_MEAS APSS_TASK_FLAGS
+
+//>@06a
+#define FLAGS_DCOM_PARSE_OCC_FW_MSG RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_CHECK_FOR_CHECKSTOP RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
+//<@06a // @jh00bc
+
+//>@th010
+#define FLAGS_CORE_DATA_CONTROL RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
+//<@th010
+// @sb023 Don't run watchdog poke in all cases, expecially if a reset request
+// is pending
+#define FLAGS_POKE_WDT RTL_FLAG_RUN | RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_STANDBY | \
+ RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_APSS_NOT_INITD
+
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// Global tick sequences
+// The number and size of these will vary as the real tick sequences are developed over time.
+//@pb007a - added TASK_ID_RESET_405WDT and TASK_ID_RESET_OCBT to every tick
+//@02a - added TASK_ID_CORE_DATA_LOW and TASK_ID_CORE_DATA_HIGH
+//@pb008c - Combined ppc405 watchdog and OCB timer task into one
+//@05a - added TASK_ID_FAST_CORE_DATA
+//@rc002 - Remove unused TASK_ID_DPSS_RD_STATUS
+
+//NOTE: Currently this is the only way the complete apss works in simics TODO need to revisit in
+// the future.
+
+/* The Global Task Table
+ Use task_id_t values to index into this table and find a specific task.
+ Add rows to this table as TASK_END grows.
+
+ Example use:
+ #define TASK_0_FLAGS RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE
+ void task_0_func(struct task *i_self);
+ uint32_t task_0_data = 0x00000000; // Use whatever data type makes sense
+
+ // flags, func_ptr, data_ptr, // task_id_t
+ { TASK_0_FLAGS, task_0_func, (void *)&task_0_data }, // TASK_ID_0
+*/
+//@pb007a - added timer reset tasks
+//@pb008c - Combined ppc405 watchdog and OCB timer task into one
+//@rc002 - Remove unused flag task_dpss_read_status
+task_t G_task_table[TASK_END] = {
+ // flags, func_ptr, data_ptr,// task_id_t
+ { FLAGS_APSS_START_MEAS, task_apss_start_pwr_meas, NULL }, // TASK_ID_APSS_START
+ { FLAGS_LOW_CORES_DATA, task_core_data, (void *) &G_low_cores}, //@02a
+ { FLAGS_APSS_CONT_MEAS, task_apss_continue_pwr_meas, NULL }, // TASK_ID_APSS_CONT
+ { FLAGS_HIGH_CORES_DATA, task_core_data, (void *) &G_high_cores}, //@02a
+ { FLAGS_APSS_DONE_MEAS, task_apss_complete_pwr_meas, NULL }, // TASK_ID_APSS_DONE
+ { FLAGS_FAST_CORES_DATA, task_fast_core_data, NULL }, //@05a
+ { FLAGS_DCOM_RX_SLV_INBX, task_dcom_rx_slv_inbox, NULL }, // TASK_ID_DCOM_RX_INBX
+ { FLAGS_DCOM_TX_SLV_INBX, task_dcom_tx_slv_inbox, NULL }, // TASK_ID_DCOM_TX_INBX
+ { FLAGS_POKE_WDT, task_poke_watchdogs, NULL }, // TASK_ID_POKE_WDT
+ { FLAGS_DCOM_WAIT_4_MSTR, task_dcom_wait_for_master, NULL }, // TASK_ID_DCOM_WAIT_4_MSTR
+ { FLAGS_DCOM_RX_SLV_OUTBOX, task_dcom_rx_slv_outboxes, NULL }, // TASK_ID_DCOM_RX_OUTBX
+ { FLAGS_DCOM_TX_SLV_OUTBOX, task_dcom_tx_slv_outbox, NULL }, // TASK_ID_DCOM_TX_OUTBX
+ { FLAGS_DCOM_PARSE_OCC_FW_MSG, task_dcom_parse_occfwmsg, NULL }, // TASK_ID_DCOM_PARSE_FW_MSG
+ { FLAGS_CHECK_FOR_CHECKSTOP, task_check_for_checkstop, NULL }, // TASK_ID_CHECK_FOR_CHECKSTOP // @jh00bc
+ { FLAGS_AMEC_SLAVE, task_amec_slave, NULL }, // TASK_ID_AMEC_SLAVE @07a
+ { FLAGS_AMEC_MASTER, task_amec_master, NULL }, // TASK_ID_AMEC_MASTER @07a
+ { FLAGS_CENTAUR_DATA, task_centaur_data, (void *) &G_centaur_data_task}, // TASK_ID_CENTAUR_DATA @th00c
+ { FLAGS_CORE_DATA_CONTROL, task_core_data_control, NULL }, // TASK_ID_CORE_DATA_CONTROL
+ { FLAGS_CENTAUR_CONTROL, task_centaur_control, (void *) &G_centaur_control_task }, // TASK_ID_CENTAUR_CONTROL @th038
+};
+
+const uint8_t G_tick0_seq[] = {
+ TASK_ID_APSS_START,
+ TASK_ID_CORE_DATA_LOW,
+ TASK_ID_CENTAUR_DATA,
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH,
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA,
+ TASK_ID_CENTAUR_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_POKE_WDT,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_AMEC_SLAVE,
+ TASK_ID_AMEC_MASTER,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_END };
+
+const uint8_t G_tick1_seq[] = {
+ TASK_ID_APSS_START,
+ TASK_ID_CORE_DATA_LOW,
+ TASK_ID_CENTAUR_DATA,
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH,
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA,
+ TASK_ID_CENTAUR_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_AMEC_SLAVE,
+ TASK_ID_AMEC_MASTER,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_END };
+
+const uint8_t G_tick2_seq[] = {
+ TASK_ID_APSS_START,
+ TASK_ID_CORE_DATA_LOW,
+ TASK_ID_CENTAUR_DATA,
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH,
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA,
+ TASK_ID_CENTAUR_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_AMEC_SLAVE,
+ TASK_ID_AMEC_MASTER,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_END };
+
+const uint8_t G_tick3_seq[] = {
+ TASK_ID_APSS_START,
+ TASK_ID_CORE_DATA_LOW,
+ TASK_ID_CENTAUR_DATA,
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH,
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA,
+ TASK_ID_CENTAUR_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_AMEC_SLAVE,
+ TASK_ID_AMEC_MASTER,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_END };
+
+const uint8_t G_tick4_seq[] = {
+ TASK_ID_APSS_START,
+ TASK_ID_CORE_DATA_LOW,
+ TASK_ID_CENTAUR_DATA,
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH,
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA,
+ TASK_ID_CENTAUR_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_POKE_WDT,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_AMEC_SLAVE,
+ TASK_ID_AMEC_MASTER,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_END };
+
+const uint8_t G_tick5_seq[] = {
+ TASK_ID_APSS_START,
+ TASK_ID_CORE_DATA_LOW,
+ TASK_ID_CENTAUR_DATA,
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH,
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA,
+ TASK_ID_CENTAUR_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_AMEC_SLAVE,
+ TASK_ID_AMEC_MASTER,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_END };
+
+const uint8_t G_tick6_seq[] = {
+ TASK_ID_APSS_START,
+ TASK_ID_CORE_DATA_LOW,
+ TASK_ID_CENTAUR_DATA,
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH,
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA,
+ TASK_ID_CENTAUR_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_AMEC_SLAVE,
+ TASK_ID_AMEC_MASTER,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_END };
+
+const uint8_t G_tick7_seq[] = {
+ TASK_ID_APSS_START,
+ TASK_ID_CORE_DATA_LOW,
+ TASK_ID_CENTAUR_DATA,
+ TASK_ID_APSS_CONT,
+ TASK_ID_CORE_DATA_HIGH,
+ TASK_ID_APSS_DONE,
+ TASK_ID_FAST_CORE_DATA,
+ TASK_ID_CENTAUR_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_DCOM_WAIT_4_MSTR,
+ TASK_ID_DCOM_RX_INBX,
+ TASK_ID_DCOM_RX_OUTBX,
+ TASK_ID_DCOM_TX_OUTBX,
+ TASK_ID_DCOM_TX_INBX,
+ TASK_ID_AMEC_SLAVE,
+ TASK_ID_AMEC_MASTER,
+ TASK_ID_DCOM_PARSE_FW_MSG,
+ TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_END };
+
+// The Global Tick Table
+// This will change as the real tick sequences are developed.
+const uint8_t *G_tick_table[MAX_NUM_TICKS] = {
+ G_tick0_seq,
+ G_tick1_seq,
+ G_tick2_seq,
+ G_tick3_seq,
+ G_tick4_seq,
+ G_tick5_seq,
+ G_tick6_seq,
+ G_tick7_seq
+};
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
diff --git a/src/occ/rtls/test/Makefile b/src/occ/rtls/test/Makefile
new file mode 100755
index 0000000..4bd495f
--- /dev/null
+++ b/src/occ/rtls/test/Makefile
@@ -0,0 +1,65 @@
+# $Id$
+
+# @file Makefile
+#
+# @brief Makefile occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# np, dw 08/10/2011 created by nguyenp & dwoodham
+# borrowed from occ/thread/test/app.mk
+# @dw000 dwoodham 12/13/2011 compile with applet header & ID
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+# Note: This compiles the _local_ test copy of rtls_tables.c, _NOT_ the production copy.
+
+rtlstest_CFILES = \
+ ../../common.c \
+ ../../errl/errl.c \
+ ../rtls.c \
+ rtls_tables.c \
+ main.c
+
+all_cfiles = ${rtlstest_CFILES}
+
+APP = rtlstest
+APP_INCLUDES += -I../../../ssx
+APP_INCLUDES += -I../../../lib
+APP_INCLUDES += -I../../incl
+APP_INCLUDES += -I../../trac
+APP_INCLUDES += -I../../errl
+APP_INCLUDES += -I../../thread
+APP_INCLUDES += -I../../rtls
+APP_INCLUDES += -I../../aplt/incl
+APP_INCLUDES += -I.
+
+D = -DOCC_FIRMWARE=1
+
+#D = -DVERIFICATION=1 \
+ -DSSX_STACK_CHECK=0 \
+ -DINITIALIZE_PMC=0 \
+ -DINITIALIZE_SIMICS_IO=0 \
+ -DINITIALIZE_RTX_IO=1 \
+ -DINITIALIZE_PBA=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DSSX_KERNEL_TRACE_ENABLE=1
+
+
+SOURCES = ${all_cfiles}
+MODE = validation
+
+PGP_ASYNC_SUPPORT = 1
+
+include ./app.mk
+
+pgas:
+ $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10'
diff --git a/src/occ/rtls/test/app.mk b/src/occ/rtls/test/app.mk
new file mode 100755
index 0000000..e576716
--- /dev/null
+++ b/src/occ/rtls/test/app.mk
@@ -0,0 +1,101 @@
+# $Id$
+
+# @file app.mk
+#
+# @brief mk occ application
+#
+# This Makefile is included-ed into application Makefiles and
+# encapsulates the steps necessary to create application images.
+#
+# The application Makefile (user) must define the following variables:
+#
+# APP - The name of the application
+# SOURCES - The list of local source files that implement the
+# application.
+#
+# The application Makefile (user) may optionally define the following
+# variables:
+#
+# D - The value of $(D) is appended to DEFS defined by ssx.mk
+#
+# MODE - The following modes are recognized:
+#
+# validation - (Default) An application that requires all SSX
+# services.
+#
+# firmware - An interrupt only configuration.
+#
+# The make process creates the following files:
+#
+# $(APP).out - The PowerPC-ELF version of the application
+# $(APP).bin - A binary SRAM image of the application
+# $(APP).map - The linker map of the application
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# np, dw 08/10/2011 created by nguyenp & dwoodham
+# borrowed from occ/thread/test/app.mk
+# @01 dwoodham 08/30/2011 Use link script from OCC vs. from SSX
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+
+OCC = ../../
+SSX = ../../../ssx
+LIB = ../../../lib
+PGP = $(SSX)/pgp
+
+ifeq "$(MODE)" "firmware"
+SSX_TIMER_SUPPORT = 0
+SSX_THREAD_SUPPORT = 0
+endif
+
+export SSX_TIMER_SUPPORT
+export SSX_THREAD_SUPPORT
+export PPC405_MMU_SUPPORT
+export PGP_ASYNC_SUPPORT
+
+INCLUDES = -I $(OCC) -I$(LIB)
+
+include $(PGP)/ssx.mk
+
+C-OBJECTS = $(SOURCES:.c=.o)
+OBJECTS = $(C-OBJECTS:.S=.o)
+
+LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \
+ -L $(OCC) -L $(LIB) -lssx -lppc32
+
+DEFS += $(D)
+
+all: $(OBJECTS) libssx.a
+ $(MAKE) -C $(PGP) DEFS="$(DEFS)" -e
+ $(CPP) -P $(DEFS) < $(OCC)/linkocc.cmd > linkscript
+ $(LD) $(OBJECTS) \
+ -Tlinkscript $(LDFLAGS) -Map $(APP).map -Bstatic -o $(APP).out
+ $(OBJCOPY) -O binary $(APP).out $(APP).bin
+ $(OBJDUMP) -d $(APP).out > $(APP).dis
+
+libssx.a:
+ $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e
+
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map linkscript
+ rm -f ./*/*.o ./*/*.d ./*/*.d.*
+
+.PHONY : clean_all
+clean_all:
+ $(MAKE) clean
+ $(MAKE) -C $(PGP) clean
+
+.PHONY : doc
+doc:
+ doxygen doc/Doxyfile
+
+include $(OBJECTS:.o=.d)
diff --git a/src/occ/rtls/test/main.c b/src/occ/rtls/test/main.c
new file mode 100755
index 0000000..08d3e2f
--- /dev/null
+++ b/src/occ/rtls/test/main.c
@@ -0,0 +1,730 @@
+/******************************************************************************
+// @file main.c
+// @brief OCC RTLS COMPONENT TEST MAIN FUNCTION
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _main_c main.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * np, dw 08/10/2011 created by nguyenp & dwoodham
+ * @dw000 dwoodham 12/12/2011 Update call to IMAGE_HEADER
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include <thread.h>
+#include <errl.h>
+#include <rand.h>
+#include <rtls.h>
+#include <appletId.h> // For applet ID @dw000a
+
+
+/** \mainpage OCC Overview
+ *
+ * Some general info.
+ *
+ * This manual is divided in the following sections:
+ * - \subpage Timer
+ */
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern void __ssx_boot;
+
+//*************************************************************************
+// Image Header
+//*************************************************************************
+// @dw000c
+IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,OCC_APLT_TEST);
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+/// Period in which to run #timer_routine
+#define TIMER_INTERVAL (SsxInterval) SSX_MICROSECONDS(5000)
+
+/*----------------------------------------------------------------------------*/
+/* SsxSemaphore Declarations */
+/*----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------*/
+/* Globals */
+/*----------------------------------------------------------------------------*/
+int g_j = 0;
+int g_k = 0;
+
+extern uint32_t G_run_mask;
+
+// Globals from local copy of rtls_tables.c:
+extern task_t G_task_table[TASK_END]; // Global task table
+
+extern uint32_t task_0_data; // Default task data buffers
+extern uint32_t task_1_data;
+extern uint32_t task_2_data;
+extern uint32_t task_3_data;
+
+extern uint32_t task_0_alt_data; // Alternate task data buffers
+extern uint32_t task_1_alt_data;
+extern uint32_t task_2_alt_data;
+extern uint32_t task_3_alt_data;
+
+SimicsStdio simics_stdout;
+SimicsStdio simics_stderr;
+
+
+/*----------------------------------------------------------------------------*/
+/* Critical/Non-Critical stack */
+/*----------------------------------------------------------------------------*/
+uint8_t noncritical_stack[NONCRITICAL_STACK_SIZE];
+uint8_t critical_stack[CRITICAL_STACK_SIZE];
+uint8_t test_thread_stack[THREAD_STACK_SIZE];
+
+
+/*----------------------------------------------------------------------------*/
+/* Threads */
+/*----------------------------------------------------------------------------*/
+SsxThread test_thread;
+
+
+/*----------------------------------------------------------------------------*/
+/* Timers */
+/*----------------------------------------------------------------------------*/
+SsxTimer G_test_timer;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// Inits the IRQ handler.
+extern void rtl_ocb_init( void );
+
+// Run the IRQ handler for at least MAX_NUM_TICKS, then disable it again.
+int rtl_run_max_ticks(void);
+
+// Utility clears the data buffers in all tasks in the global task table.
+void clear_task_data_bufs(void);
+
+// Utility clears the flags in all tasks in the global task table.
+void clear_task_flags(void);
+
+// Utility writes the flags in the specified task to the specified value.
+void write_task_flags(task_id_t i_task_id, uint32_t new_flags);
+
+// Utility to dump flags & data for all tasks in G_task_table, along with
+// the current values of G_run_mask and CURRENT_TICK.
+void dump_global_state(void);
+
+// Tests the API that reads & writes the global & task run flags.
+void test_flags_api(void);
+
+// Tests the function ('rtl_stop_task') that indicates a task is NOT ready to run.
+void test_task_stop_api(void);
+
+// Tests the function ('rtl_set_task_data') that assigns a new data buffer to a
+// task in the global task list.
+void test_set_data_api(void);
+
+// Thread routine that runs all our tests.
+void test_thread_routine(void *private);
+
+// The main routine.
+int main(int argc, char **argv);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: rtl_run_max_ticks
+//
+// Description:
+// Run the RTLS IRQ handler for at least MAX_NUM_TICKS, then stop.
+// Note: This function does not guarantee that the IRQ handler will run for
+// exactly MAX_NUM_TICKS ticks. It does guarantee that the IRQ handler will
+// run for _at_least_ MAX_NUM_TICKS ticks (but could run for more).
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+int rtl_run_max_ticks(void)
+{
+// If we can loop this many cycles without seeing our IRQ stop condition,
+// then something is broken.
+#define MAX_WAIT_CYCLES 10000
+
+ int i = 0; // Counter
+ int rc = 0; // Return Code
+
+ // Start the RTLS IRQ timer.
+ ssx_irq_enable( PGP_IRQ_OCC_TIMER0 );
+
+ // Wait for the timer to hit MAX_NUM_TICKS ticks.
+ // Note: When we enter this loop, CURRENT_TICK may still equal 0xFFFFFFFF,
+ // so handle that condition appropriately.
+ for( i = 0; i < MAX_WAIT_CYCLES; i++) {
+
+ // Warning: ssx_sleep only works if called from a thread OTHER than the one that
+ // calls ocb_timer_setup (function called by rtl_ocb_init). If this rule is not
+ // followed, the OCB IRQ handler will run a trap instruction and hang.
+ ssx_sleep(1);
+
+ if( (CURRENT_TICK >= MAX_NUM_TICKS) && (CURRENT_TICK < 0xFFFFFFFF) ) {
+ ssx_irq_disable(PGP_IRQ_OCC_TIMER0);
+ CURRENT_TICK = 0xFFFFFFFF;
+ break;
+ }
+ }
+
+ if( i >= MAX_WAIT_CYCLES ) {
+ // We timed-out waiting for CURRENT_TICK to equal MAX_NUM_TICKS. Make noise & exit.
+ printf(" ERROR: %s: %d: Timed-out waiting for CURRENT_TICK to reach %d.\n\n", __FILE__, __LINE__, MAX_NUM_TICKS);
+ rc = -1;
+ }
+ return rc;
+}
+
+
+// Function Specification
+//
+// Name: clear_task_data_bufs
+//
+// Description:
+// Utility clears the data buffers in all tasks in the global task table.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void clear_task_data_bufs(void)
+{
+ int i;
+
+ for( i = 0; i < TASK_END; i++ ) {
+ *((uint32_t *)(G_task_table[i].data_ptr)) = 0x00000000;
+ }
+}
+
+
+// Function Specification
+//
+// Name: clear_task_flags
+//
+// Description:
+// Utility clears the flags in all tasks in the global task table.
+// Note: This sets all task flags to 0.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void clear_task_flags(void)
+{
+ int i;
+
+ for( i = 0; i < TASK_END; i++ ) {
+ G_task_table[i].flags = 0x00000000;
+ }
+}
+
+
+// Function Specification
+//
+// Name: write_task_flags
+//
+// Description:
+// Utility writes the flags in the specified task to the specified value.
+// Note: This overwrites the prior flags value for the given task.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void write_task_flags(task_id_t i_task_id, uint32_t new_flags)
+{
+ if( i_task_id >= TASK_END ) {
+ printf("Warning: %s: write_task_flags: Invalid task ID: %02x. Not overwriting flags.\n", __FILE__, i_task_id);
+ }
+ else {
+ G_task_table[i_task_id].flags = new_flags;
+ }
+}
+
+
+// Function Specification
+//
+// Name: dump_global_state
+//
+// Description:
+// Utility to dump flags & data for all tasks in G_task_table, along with
+// the current values of G_run_mask and CURRENT_TICK.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void dump_global_state(void)
+{
+ int i;
+ printf("\n G_run_mask = [0x%04x] ; CURRENT_TICK = [0x%04x]\n", G_run_mask, CURRENT_TICK);
+
+ for( i = 0; i < TASK_END; i++ ) {
+ printf(" TASK_ID_%02d : flags [0x%08x] ; data_p [0x%p] ; data [0x%08x]\n", \
+ i, G_task_table[i].flags, G_task_table[i].data_ptr, *((uint32_t *)(G_task_table[i].data_ptr)) );
+ }
+
+ printf("\n");
+}
+
+
+// Function Specification
+//
+// Name: test_1
+//
+// Description:
+// This test is to stop ocb timer after complete 1 loop
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void test_1()
+{
+ // Announce which test is running.
+ printf("\ntest_1:\n");
+
+ // re-enable interrupt so RTL will continue again (CURRENT_TICK = 0xFFFFFFFF)
+ printf(" Test_1_1: starting ocb timer\n");
+
+ rtl_run_max_ticks();
+
+ printf(" Test_1_1: exiting subroutine.\n");
+ return;
+}
+
+
+// Function Specification
+//
+// Name: test_2
+//
+// Description:
+// This test to set and clear the global run mask interfaces
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void test_2()
+{
+ // Announce which test is running.
+ printf("\ntest_2:\n");
+
+ //test rtl_set_run_mask() interface
+ G_run_mask = 0x00000000;
+ printf(" Test_2_1: G_run_mask = 0x%08x before setting\n", G_run_mask);
+
+ rtl_set_run_mask( RTL_FLAG_ACTIVE | RTL_FLAG_OBS );
+ printf(" Test_2_2: G_run_mask = 0x%08x after setting\n", G_run_mask);
+
+
+ //test rtl_clr_run_mask() interface
+ G_run_mask = RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_ACTIVE |
+ RTL_FLAG_OBS | RTL_FLAG_RST_REQ |RTL_FLAG_NO_APSS ;
+ printf(" Test_2_3: G_run_mask = 0x%08x before clearing\n", G_run_mask);
+
+ rtl_clr_run_mask( RTL_FLAG_ACTIVE | RTL_FLAG_OBS );
+ printf(" Test_2_4: G_run_mask = 0x%08x after clearing\n", G_run_mask);
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: test_flags_api
+//
+// Description: Tests the global & task run flags, including the API that
+// reads & writes these flags.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void test_flags_api(void)
+{
+ int i = 0; // Counter
+ BOOLEAN l_result = FALSE;
+
+ // Local copy of new run mask (odd-numbered bits set).
+ uint32_t l_odd_run_mask = RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_RST_REQ;
+
+ // Partial inverse of l_odd_run_mask (even-numbered bits set, except for the 'run' flag: bit 0).
+ uint32_t l_even_run_mask = RTL_FLAG_NOTMSTR | RTL_FLAG_ACTIVE | RTL_FLAG_NO_APSS;
+
+ // Announce which test is running.
+ printf("\ntest_flags_api:\n");
+
+ // Clear all task data & flags.
+ clear_task_data_bufs();
+ clear_task_flags();
+
+ // Use API to set 'run' flag + odd-numbered bits in global flags mask.
+ rtl_clr_run_mask(0xFFFFFFFF);
+ rtl_set_run_mask(RTL_FLAG_RUN | l_odd_run_mask);
+
+ // Set 1/2 the tasks to run w/same mask as global, and the other 1/2 of the
+ // tasks to run w/opposite mask from the global.
+ for (i = 0; i < TASK_END; i++) {
+ // Use i as i_task_id
+
+ if (i % 2) {
+ // Task ID is odd
+ write_task_flags((task_id_t) i, l_odd_run_mask);
+ }
+ else {
+ // Task ID is even
+ write_task_flags((task_id_t) i, l_even_run_mask);
+ }
+ }
+
+ // Use API to set all tasks as runnable.
+ for (i = 0; i < TASK_END; i++) {
+
+ rtl_start_task((task_id_t) i);
+ }
+
+ // Use API to check which tasks are runnable.
+ // Expect all tasks to report as runnable.
+ printf(" Before IRQ enable. Using \'odd\' global mask.\n");
+ printf(" Expect: All tasks report as runnable.\n");
+ printf(" Actual: Tasks reporting as runnable: ");
+
+ for (i = 0; i < TASK_END; i++) {
+
+ l_result = rtl_task_is_runnable((task_id_t) i);
+
+ if (l_result) { printf("%d ", i); }
+ }
+ printf("\n");
+ dump_global_state();
+
+ // Run the rtls for MAX_NUM_TICKS, then stop.
+ rtl_run_max_ticks();
+
+ // Dump task data, task flags, global flags and CURRENT_TICK.
+ printf(" After IRQ ran.\n");
+ printf(" Expect: Only tasks using the \'odd\' flags mask actually ran.\n");
+ printf(" Actual: Task state:\n");
+ dump_global_state();
+
+ // Clear all task data, but not the task flags.
+ clear_task_data_bufs();
+
+ // Use the API to reverse the sense of the global flags only.
+ rtl_clr_run_mask(0xFFFFFFFF);
+ rtl_set_run_mask(RTL_FLAG_RUN | l_even_run_mask);
+
+ // Use API to check which tasks are runnable.
+ // Expect all tasks to report as runnable.
+ printf(" Before IRQ enable. Using \'even\' global mask.\n");
+ printf(" Expect: All tasks report as runnable.\n");
+ printf(" Actual: Tasks reporting as runnable: ");
+
+ for (i = 0; i < TASK_END; i++) {
+
+ l_result = rtl_task_is_runnable((task_id_t) i);
+ printf("%d ", i);
+ }
+ printf("\n");
+ dump_global_state();
+
+ // Run the rtls for MAX_NUM_TICKS, then stop.
+ rtl_run_max_ticks();
+
+ // Dump task data, task flags, global flags and CURRENT_TICK.
+ printf(" After IRQ ran.\n");
+ printf(" Expect: Only tasks using the \'even\' flags mask actually ran.\n");
+ printf(" Actual: Task state:\n");
+ dump_global_state();
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: test_task_stop_api
+//
+// Description: Tests the API function that indicates a task is NOT ready
+// to run: 'rtl_stop_task'.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void test_task_stop_api(void)
+{
+ int i = 0; // Counter
+ BOOLEAN l_result = FALSE;
+
+ // Local copy of new run mask (odd-numbered bits set).
+ uint32_t l_odd_run_mask = RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_RST_REQ;
+
+ // Announce which test is running.
+ printf("\ntest_task_stop_api:\n");
+
+ // Clear all task data & flags.
+ clear_task_data_bufs();
+ clear_task_flags();
+
+ // Use API to set 'run' flag + odd-numbered bits in global flags mask.
+ rtl_clr_run_mask(0xFFFFFFFF);
+ rtl_set_run_mask(RTL_FLAG_RUN | l_odd_run_mask);
+
+ // Set other task flags so all task flags == global flag mask.
+ // Use the API to set the RTL_FLAG_RUN flags in all tasks.
+ for (i = 0; i < TASK_END; i++) {
+ // Use i as i_task_id
+ write_task_flags((task_id_t) i, l_odd_run_mask);
+ rtl_start_task((task_id_t) i);
+ }
+
+ // Now use the API to "stop" ~1/2 the tasks (clear RTL_FLAG_RUN).
+ for (i = 0; i < TASK_END; i++) {
+ // Use i as i_task_id
+
+ if ( (i % 2) == 0 ) {
+ // Task ID is even
+ rtl_stop_task((task_id_t) i);
+ }
+ }
+
+ // Use API to check which tasks are runnable. Expect 1/2 the tasks are runnable.
+ printf(" Before IRQ runs.\n");
+ printf(" Expect: Half of the tasks report as runnable.\n");
+ printf(" Actual: Tasks reporting as runnable: ");
+
+ for (i = 0; i < TASK_END; i++) {
+
+ l_result = rtl_task_is_runnable((task_id_t) i);
+
+ if (l_result) { printf("%d ", i); }
+ }
+ printf("\n");
+ dump_global_state();
+
+ // Run the rtls for MAX_NUM_TICKS, then stop.
+ rtl_run_max_ticks();
+
+ // Dump task data, task flags, global flags and CURRENT_TICK.
+ printf(" After IRQ ran.\n");
+ printf(" Expect: \'Runnable\' tasks ran; \'non-runnable\' tasks did not run.\n");
+ printf(" Actual: Task state:\n");
+ dump_global_state();
+ return;
+}
+
+
+// Function Specification
+//
+// Name: test_set_data_apii
+//
+// Description: Tests the API function that assigns a new data buffer to a
+// task in the global task list: 'rtl_set_task_data'.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void test_set_data_api(void)
+{
+ int i = 0; // Counter
+ BOOLEAN l_result = FALSE;
+
+ uint32_t *l_task_1_old_data_p = NULL; // Copy of original task 1 data ptr
+ uint32_t *l_task_3_old_data_p = NULL; // Copy of original task 3 data ptr
+
+ // Local copy of new run mask (odd-numbered bits set).
+ uint32_t l_odd_run_mask = RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_RST_REQ;
+
+ // Announce which test is running.
+ printf("\ntest_set_data_api:\n");
+
+ // Clear all task data & flags.
+ clear_task_data_bufs();
+ clear_task_flags();
+
+ // Use API to set global flags.
+ rtl_clr_run_mask(0xFFFFFFFF);
+ rtl_set_run_mask(RTL_FLAG_RUN | l_odd_run_mask);
+
+ printf(" Before task data pointers re-assigned.\n");
+ dump_global_state();
+
+ // Save-off old data ptrs for tasks 1 & 3.
+ // Use API to re-assign data ptrs for ~1/2 of the tasks.
+ // Remember: The task data pointer won't get changed if
+ // RTL_FLAG_RUN is set in the task's flags mask.
+ l_task_1_old_data_p = G_task_table[1].data_ptr;
+ l_task_3_old_data_p = G_task_table[3].data_ptr;
+
+ rtl_set_task_data(TASK_ID_1, &task_1_alt_data);
+ rtl_set_task_data(TASK_ID_3, &task_3_alt_data);
+
+ // To be sure we start clean, clear the task data buffers again.
+ clear_task_data_bufs();
+
+ // Use API to set task flags so all tasks will run.
+ for (i = 0; i < TASK_END; i++) {
+ // Use i as i_task_id
+ write_task_flags((task_id_t) i, l_odd_run_mask);
+ rtl_start_task((task_id_t) i);
+ }
+
+ // Use API to check which tasks are runnable. Expect all tasks are runnable.
+ printf(" After task data pointers re-assigned; before IRQ runs.\n");
+ printf(" Expect: All tasks will report as runnable.\n");
+ printf(" Actual: Tasks reporting as runnable: ");
+
+ for (i = 0; i < TASK_END; i++) {
+
+ l_result = rtl_task_is_runnable((task_id_t) i);
+
+ if (l_result) { printf("%d ", i); }
+ }
+ printf("\n");
+ dump_global_state();
+
+ // Run the rtls for MAX_NUM_TICKS, then stop.
+ rtl_run_max_ticks();
+
+ // Dump task data, task flags, global flags and CURRENT_TICK.
+ // Dump the old task data (the ones that were de-assigned).
+ // Expect: New task data buffers indicate the tasks ran. Old task data buffers are still cleared.
+ printf(" After IRQ ran.\n");
+ printf(" Expect: All tasks will have run. Old task data buffers will still be clear.\n");
+ printf(" Actual: Task state:\n");
+ dump_global_state();
+ printf(" TASK_ID_1 : old data_p: [0x%p] ; old data [0x%08x]\n", l_task_1_old_data_p, *l_task_1_old_data_p);
+ printf(" TASK_ID_3 : old data_p: [0x%p] ; old data [0x%08x]\n", l_task_3_old_data_p, *l_task_3_old_data_p);
+ printf("\n");
+
+ // Unless you want to report a "task busy" error when you un-do the data ptr assignments,
+ // clear your task flags here (mainly just need to clear the run flag).
+ clear_task_flags();
+
+ // Now un-do data ptr re-assignments.
+ rtl_set_task_data(TASK_ID_1, &task_1_data);
+ rtl_set_task_data(TASK_ID_3, &task_3_data);
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: test_thread_routine
+//
+// Description:
+// We run our tests in a thread so that, when a test re-enables the OCB timer for the RTLS,
+// the timer will actually interrupt the test, and run until it hits MAX_NUM_TICKS and
+// is re-disabled. At that point, the test resumes its activity and dumps the results
+// of the RTLS IRQ's operation.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+void test_thread_routine(void *private)
+{
+ test_1();
+ test_2();
+ test_flags_api();
+ test_task_stop_api();
+ test_set_data_api();
+
+ // Uncomment if you want to re-enable the OCB timer for further testing
+ // after this test suite exits.
+ // ssx_irq_enable( PGP_IRQ_OCC_TIMER0 );
+}
+
+
+// Function Specification
+//
+// Name: main
+//
+// Description: Entry point for running our tests.
+// Sets up our OCB timer and our test thread, then kicks them both off.
+//
+// Flow: 08/09/11 FN=rtl_scheduler.odt
+//
+// End Function Specification
+
+int main(int argc, char **argv)
+{
+ // Initialize Trace Buffers immediately, so they can be used
+ // from this point on.
+
+ // Initialize stdout so we can do printf from within simics env
+ simics_stdout_create(&simics_stdout);
+ simics_stderr_create(&simics_stderr);
+ stdout = (FILE *)(&simics_stdout);
+ stderr = (FILE *)(&simics_stderr);
+
+ // Initialize SSX Stacks (note that this also reinitializes the time base to 0)
+ ssx_initialize((SsxAddress)noncritical_stack, NONCRITICAL_STACK_SIZE,
+ (SsxAddress)critical_stack, CRITICAL_STACK_SIZE,
+ 0);
+
+ // Create our test thread
+ ssx_thread_create(&test_thread, // thread control block (struct)
+ test_thread_routine, // thread function
+ (void *)0, // thread function arg
+ (SsxAddress)test_thread_stack, // stack to use for this thread
+ THREAD_STACK_SIZE, // size of this thread's stack
+ THREAD_PRIORITY_0); // this thread's priority (0 is highest)
+
+ // Make the test thread runnable
+ ssx_thread_resume(&test_thread);
+
+ // start rtl code
+ rtl_ocb_init();
+
+ // Stop the interrupt handler and initialize CURRENT_TICK (just in case).
+ // Also set the 'testing' flag.
+ ssx_irq_disable(PGP_IRQ_OCC_TIMER0);
+ CURRENT_TICK = 0xFFFFFFFF;
+ printf("\n\nmain: ocb timer stopped; waiting for first test\n");
+
+ // Enter SSX Kernel
+ ssx_start_threads();
+
+ return 0;
+}
+
diff --git a/src/occ/rtls/test/rtls_tables.c b/src/occ/rtls/test/rtls_tables.c
new file mode 100755
index 0000000..5a8088c
--- /dev/null
+++ b/src/occ/rtls/test/rtls_tables.c
@@ -0,0 +1,199 @@
+/******************************************************************************
+// @file rtls_tables.c
+// @brief OCC RTLS COMPONENT TEST
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _rtls_tables_c rtls_tables.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * np, dw 08/10/2011 created by nguyenp & dwoodham
+ * @dw001 dwoodham 01/06/2012 added substitute task defines that have
+ * been over-written in product code
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "rtls.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// Default task data buffers
+uint32_t task_0_data = 0x00000000;
+uint32_t task_1_data = 0x00000000;
+uint32_t task_2_data = 0x00000000;
+uint32_t task_3_data = 0x00000000;
+
+// Alternate task data buffers
+uint32_t task_0_alt_data = 0x00000000;
+uint32_t task_1_alt_data = 0x00000000;
+uint32_t task_2_alt_data = 0x00000000;
+uint32_t task_3_alt_data = 0x00000000;
+
+// >@dw001a
+// Added this so our 'substitute' rtls_table will still compile.
+#define TASK_ID_0 0
+#define TASK_ID_1 1
+#define TASK_ID_2 2
+#define TASK_ID_3 3
+#define TASK_ID_END 4
+// <@dw001a
+
+// Test tick sequences
+// For testing, run every task on every tick, but vary the order.
+uint8_t G_tick0_seq[TASK_END + 1] = { TASK_ID_0, TASK_ID_1, TASK_ID_2, TASK_ID_3, TASK_END };
+uint8_t G_tick1_seq[TASK_END + 1] = { TASK_ID_1, TASK_ID_2, TASK_ID_3, TASK_ID_0, TASK_END };
+uint8_t G_tick2_seq[TASK_END + 1] = { TASK_ID_2, TASK_ID_3, TASK_ID_0, TASK_ID_1, TASK_END };
+uint8_t G_tick3_seq[TASK_END + 1] = { TASK_ID_3, TASK_ID_0, TASK_ID_1, TASK_ID_2, TASK_END };
+uint8_t G_tick4_seq[TASK_END + 1] = { TASK_ID_3, TASK_ID_2, TASK_ID_1, TASK_ID_0, TASK_END };
+uint8_t G_tick5_seq[TASK_END + 1] = { TASK_ID_2, TASK_ID_1, TASK_ID_0, TASK_ID_3, TASK_END };
+uint8_t G_tick6_seq[TASK_END + 1] = { TASK_ID_1, TASK_ID_0, TASK_ID_3, TASK_ID_2, TASK_END };
+uint8_t G_tick7_seq[TASK_END + 1] = { TASK_ID_0, TASK_ID_3, TASK_ID_2, TASK_ID_1, TASK_END };
+
+
+/* Tick Table */
+uint8_t *G_tick_table[MAX_NUM_TICKS] = {
+ G_tick0_seq,
+ G_tick1_seq,
+ G_tick2_seq,
+ G_tick3_seq,
+ G_tick4_seq,
+ G_tick5_seq,
+ G_tick6_seq,
+ G_tick7_seq
+};
+
+// Example Task Table
+// Use task_id_t values to index into this table and find a specific task.
+task_t G_task_table[TASK_END] = {
+ // flags, func_ptr, data_ptr, task_id_t
+ { 0x00000000, task_0_func, (void *)&task_0_data }, // TASK_ID_0
+ { 0x00000000, task_1_func, (void *)&task_1_data }, // TASK_ID_1
+ { 0x00000000, task_2_func, (void *)&task_2_data }, // TASK_ID_2
+ { 0x00000000, task_3_func, (void *)&task_3_data } // TASK_ID_3
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// Task function declarations
+void task_0_func(struct task *);
+void task_1_func(struct task *);
+void task_2_func(struct task *);
+void task_3_func(struct task *);
+
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+// Task function definitions
+
+// Function Specification
+//
+// Name: task_0_func
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void task_0_func(struct task *i_self) {
+ uint8_t curr_tick = (uint8_t)((MAX_NUM_TICKS - 1) & CURRENT_TICK);
+
+ // If our task pointer & it's data pointer are valid, set a bit
+ // in the data area indicating which tick this function ran during.
+
+ if ( i_self && i_self -> data_ptr ) {
+ *((uint32_t *)(i_self -> data_ptr)) |= (0x00000001 << curr_tick);
+ }
+ return;
+}
+
+// Function Specification
+//
+// Name: task_1_func
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void task_1_func(struct task *i_self) {
+ uint8_t curr_tick = (uint8_t)((MAX_NUM_TICKS - 1) & CURRENT_TICK);
+
+ // If our task pointer & it's data pointer are valid, set a bit
+ // in the data area indicating which tick this function ran during.
+
+ if ( i_self && i_self -> data_ptr ) {
+ *((uint32_t *)(i_self -> data_ptr)) |= (0x00000001 << curr_tick);
+ }
+ return;
+}
+
+// Function Specification
+//
+// Name: task_2_func
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void task_2_func(struct task *i_self) {
+ uint8_t curr_tick = (uint8_t)((MAX_NUM_TICKS - 1) & CURRENT_TICK);
+
+ // If our task pointer & it's data pointer are valid, set a bit
+ // in the data area indicating which tick this function ran during.
+
+ if ( i_self && i_self -> data_ptr ) {
+ *((uint32_t *)(i_self -> data_ptr)) |= (0x00000001 << curr_tick);
+ }
+ return;
+}
+
+// Function Specification
+//
+// Name: task_3_func
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void task_3_func(struct task *i_self) {
+ uint8_t curr_tick = (uint8_t)((MAX_NUM_TICKS - 1) & CURRENT_TICK);
+
+ // If our task pointer & it's data pointer are valid, set a bit
+ // in the data area indicating which tick this function ran during.
+
+ if ( i_self && i_self -> data_ptr ) {
+ *((uint32_t *)(i_self -> data_ptr)) |= (0x00000001 << curr_tick);
+ }
+ return;
+}
+
diff --git a/src/occ/scom.c b/src/occ/scom.c
new file mode 100644
index 0000000..dcc63c0
--- /dev/null
+++ b/src/occ/scom.c
@@ -0,0 +1,239 @@
+/******************************************************************************
+// @file scom.c
+// @brief Wrapper functions for getscom/putscom
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section scom.c scom.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @gm033 920448 milesg 03/26/2014 New file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include "ssx.h"
+#include "scom.h"
+#include "trac.h"
+#include "occ_service_codes.h"
+#include "occ_sys_config.h"
+#include "polling.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+//*************************************************************************
+// Macros
+//*************************************************************************
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define MAX_SCOM_FFDC_RETRIES 1
+//*************************************************************************
+// Structures
+//*************************************************************************
+//*************************************************************************
+// Forward Declarations
+//*************************************************************************
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// End Function Specification
+// Function Specification
+//
+// Name: getscom_ffdc
+//
+// Description: peforms a getscom that does not panic on error and will add
+// trace data and create a predictive error log with callouts.
+// If caller passes in NULL for o_errp, the error will be
+// committed internally. Otherwise, o_errp will point to the
+// uncomitted error log.
+//
+// Flow: FN=
+//
+// End Function Specification
+int getscom_ffdc(uint32_t i_addr, uint64_t* o_data, errlHndl_t* o_errp)
+{
+ pmc_o2p_addr_reg_t l_addr;
+ pmc_o2p_ctrl_status_reg_t l_status;
+ int l_rc;
+ int l_retries = 0;
+ errlHndl_t l_err = NULL;
+
+ while(l_retries <= MAX_SCOM_FFDC_RETRIES)
+ {
+ l_rc = _getscom(i_addr, o_data, SCOM_TIMEOUT);
+ if(!l_rc)
+ {
+ break;
+ }
+
+ //_getscom returns immediately if the o2p interface was busy
+ //wait to see if busy condition clears up
+ if(l_rc == -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY)
+ {
+ busy_wait(SCOM_TIMEOUT);
+ }
+
+ l_retries++;
+ }
+
+ if(l_rc)
+ {
+ //grab additional ffdc
+ l_status.value = in32(PMC_O2P_CTRL_STATUS_REG);
+ l_addr.value = in32(PMC_O2P_ADDR_REG);
+ TRAC_ERR("getscom_ffdc: scom failed. addr[%08x] rc[%08x] o2p_stat[%08x] o2p_addr[%08x]",
+ i_addr,
+ -l_rc,
+ l_status.value,
+ l_addr.value);
+
+ /* @
+ * @errortype
+ * @moduleid GETSCOM_FFDC_MID
+ * @reasoncode PROC_SCOM_ERROR
+ * @userdata1 scom address
+ * @userdata2 failure code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Processor register read failure
+ */
+ l_err = createErrl(GETSCOM_FFDC_MID, //modId
+ PROC_SCOM_ERROR, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_addr, //userdata1
+ -l_rc); //userdata2
+
+ //adding a processor callout should also cause data to be collected by PRDF component on FSP
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ if(o_errp)
+ {
+ //caller will commit the error
+ *o_errp = l_err;
+ }
+ else
+ {
+ //error committed internally
+ commitErrl(&l_err);
+ }
+ }
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: putscom_ffdc
+//
+// Description: peforms a putscom that does not panic on error and will add
+// trace data and create a predictive error log with callouts.
+// If caller passes in NULL for o_errp, the error will be
+// committed internally. Otherwise, o_errp will point to the
+// uncomitted error log.
+//
+// Flow: FN=
+//
+// End Function Specification
+int putscom_ffdc(uint32_t i_addr, uint64_t i_data, errlHndl_t* o_errp)
+{
+ pmc_o2p_addr_reg_t l_addr;
+ pmc_o2p_ctrl_status_reg_t l_status;
+ int l_rc;
+ int l_retries = 0;
+ errlHndl_t l_err = NULL;
+
+ while(l_retries <= MAX_SCOM_FFDC_RETRIES)
+ {
+ l_rc = _putscom(i_addr, i_data, SCOM_TIMEOUT);
+ if(!l_rc)
+ {
+ break;
+ }
+
+ //_putscom returns immediately if the o2p interface was busy. Instead, see if
+ //it cleared after SCOM_TIMEOUT period.
+ if(l_rc == -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY)
+ {
+ busy_wait(SCOM_TIMEOUT);
+ }
+
+ l_retries++;
+ }
+
+ if(l_rc)
+ {
+ //grab addtional ffdc
+ l_status.value = in32(PMC_O2P_CTRL_STATUS_REG);
+ l_addr.value = in32(PMC_O2P_ADDR_REG);
+ TRAC_ERR("putscom_ffdc: scom failed. addr[%08x] rc[%08x] o2p_stat[%08x] o2p_addr[%08x]",
+ i_addr,
+ -l_rc,
+ l_status.value,
+ l_addr.value);
+
+ /* @
+ * @errortype
+ * @moduleid PUTSCOM_FFDC_MID
+ * @reasoncode PROC_SCOM_ERROR
+ * @userdata1 scom address
+ * @userdata2 failure code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Processor register write failure
+ */
+ l_err = createErrl(PUTSCOM_FFDC_MID, //modId
+ PROC_SCOM_ERROR, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_addr, //userdata1
+ -l_rc); //userdata2
+
+ //adding a processor callout should also cause data to be collected by PRDF component on FSP
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ if(o_errp)
+ {
+ //caller will commit the error
+ *o_errp = l_err;
+ }
+ else
+ {
+ //commit error internally
+ commitErrl(&l_err);
+ }
+ }
+
+ return l_rc;
+}
+
diff --git a/src/occ/scom.h b/src/occ/scom.h
new file mode 100644
index 0000000..3a7e504
--- /dev/null
+++ b/src/occ/scom.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+// @file scom.h
+// @brief scom wrapper functions
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section scom.h SCOM.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @gm033 920448 milesg 03/26/2014 New file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef _scom_h
+#define _scom_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <common_types.h>
+#include "errl.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//uses non-panic version of getscom/putscom and creates predictive error log
+//with trace and processor callout on failure. If o_err is NULL, error is
+//committed internally. Otherwise, it is assumed the caller will handle
+//committing the error log. These errors should not be discarded!
+int putscom_ffdc(uint32_t i_addr, uint64_t i_data, errlHndl_t* o_err);
+int getscom_ffdc(uint32_t i_addr, uint64_t* o_data, errlHndl_t* o_err);
+
+#endif
+
diff --git a/src/occ/sensor/sensor.c b/src/occ/sensor/sensor.c
new file mode 100755
index 0000000..9b6a137
--- /dev/null
+++ b/src/occ/sensor/sensor.c
@@ -0,0 +1,626 @@
+/******************************************************************************
+// @file sensor.c
+// @brief OCC sensor infrastructure interfaces
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensor.c SENSOR.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb002 pbavari 08/15/2011 Created
+ * @pb003 pbavari 08/31/2011 mini-sensor support
+ * @pb004 pbavari 09/02/2011 Initialize section support
+ * @pb00A pbavari 11/14/2011 Moved sensor_init from applet and
+ * updated with latest design change
+ * @th005 thallet 11/23/2011 Sensor initialization changes
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @wb003 920760 wilbryan 03/25/2014 Update SRCs to match TPMD SRCs
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <sensor.h> // sensor structure and other defines
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h> // For size_t needed by memset
+#include <string.h> // For memset
+#include "ssx_io.h" // For sprintf
+#include <occ_service_codes.h> // OCC reason codes
+#include <sensor_service_codes.h> // sensor module ids
+#include <trac.h> // Trace macros
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+#define UINT16_MIN 0
+
+// Global sensor counter
+uint32_t G_amec_sensor_count = 0;
+
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void sensor_init(sensor_t * io_sensor_ptr,
+ const uint16_t i_gsid,
+ const uint16_t * i_miniSnsrPtr
+ ) INIT_SECTION;
+
+void sensor_init_all(void) INIT_SECTION;
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: sensor_init
+//
+// Description: Initialize global sensor list.
+//
+// Flow: 11/15/2011 FN= sensor_init
+//
+// End Function Specification
+void sensor_init(sensor_t * io_sensor_ptr,
+ const uint16_t i_gsid,
+ const uint16_t * i_miniSnsrPtr
+ )
+{
+ // check if input pointers are valid and global sensor count is
+ // within range.
+ // Note: Don't need to check i_miniSnsrPtr here as it can be NULL
+ if(( io_sensor_ptr != NULL) &&
+ (G_amec_sensor_count < MAX_AMEC_SENSORS))
+ {
+ // zero out sensor pointer
+ memset(io_sensor_ptr,0x0,sizeof(sensor_t));
+
+ io_sensor_ptr->gsid = i_gsid;
+
+ io_sensor_ptr->status.reset = 1;
+
+ // set mini sensor pointer to point to i_miniSnsrPtr. i_miniSnsrPtr can
+ // be NULL
+ io_sensor_ptr->mini_sensor = (uint16_t*)i_miniSnsrPtr;
+
+ G_amec_sensor_count++;
+
+ } // end valid input and max sensor count check
+ else
+ {
+ TRAC_ERR("Invalid input parameters OR Number of "
+ "sensor is out of range. Current sensor count: 0x%x, "
+ "max allowed: 0x%x",G_amec_sensor_count,MAX_AMEC_SENSORS);
+ }
+}
+
+// Function Specification
+//
+// Name: sensor_clear_minmax
+//
+// Description: Clears minimum and maximum fields in the sensor structure.
+//
+// Flow: 06/22/2011 FN= sensor_clear_minmax
+//
+// End Function Specification
+void sensor_clear_minmax( sensor_t * io_sensor_ptr)
+{
+ if( io_sensor_ptr != NULL)
+ {
+ io_sensor_ptr->sample_min = UINT16_MAX;
+ io_sensor_ptr->sample_max = UINT16_MIN;
+
+ // If it has vector sensor, clear max and min position
+ if( io_sensor_ptr->vector != NULL)
+ {
+ io_sensor_ptr->vector->max_pos = VECTOR_SENSOR_DEFAULT_VAL;
+ io_sensor_ptr->vector->min_pos = VECTOR_SENSOR_DEFAULT_VAL;
+ }
+ }
+ else
+ {
+ TRAC_ERR("Invalid input parameters ");
+ }
+}
+
+
+// Function Specification
+//
+// Name: sensor_reset
+//
+// Description: Reset sensor fields
+//
+// Flow: 08/31/2011 FN= sensor_reset
+//
+// End Function Specification
+void sensor_reset( sensor_t * io_sensor_ptr)
+{
+ if( io_sensor_ptr != NULL)
+ {
+ io_sensor_ptr->accumulator = 0x0;
+ io_sensor_ptr->sample = 0x0;
+
+ // clear mini sensor value
+ if( io_sensor_ptr->mini_sensor != NULL)
+ {
+ *(io_sensor_ptr->mini_sensor) = 0x0;
+ }
+
+ sensor_clear_minmax(io_sensor_ptr);
+
+ io_sensor_ptr->status.reset = 0;
+ }
+ else
+ {
+ TRAC_ERR("Invalid input parameters ");
+ }
+}
+
+
+// Function Specification
+//
+// Name: sensor_vectorize
+//
+// Description: vectorize sensor
+//
+// Flow: 08/22/2011 FN= sensor_vectorize
+//
+// End Function Specification
+void sensor_vectorize( sensor_t * io_sensor_ptr,
+ vectorSensor_t * io_vec_sensor_ptr,
+ const VECTOR_SENSOR_OP i_op)
+{
+ if( (io_vec_sensor_ptr != NULL) && (io_sensor_ptr != NULL))
+ {
+ // assign to sensor vector pointer
+ io_sensor_ptr->vector = io_vec_sensor_ptr;
+ // zero out vector sensor and set operation
+ memset(io_vec_sensor_ptr,0x0,sizeof(vectorSensor_t));
+ io_vec_sensor_ptr->operation = i_op;
+ }
+ else
+ {
+ TRAC_ERR("Invalid input sensor pointer");
+ }
+}
+
+
+// Function Specification
+//
+// Name: sensor_update
+//
+// Description: Update sensor
+//
+// Flow: 08/31/2011 FN= sensor_update
+//
+// End Function Specification
+void sensor_update( sensor_t * io_sensor_ptr, const uint16_t i_sensor_value)
+{
+ if( io_sensor_ptr != NULL)
+ {
+ // reset sensors if requested
+ if( io_sensor_ptr->status.reset == 1)
+ {
+ sensor_reset(io_sensor_ptr);
+ }
+
+ // update sample value
+ io_sensor_ptr->sample = i_sensor_value;
+
+ // update sample min value if input sample value is lower than
+ // sample_min
+ if( i_sensor_value < io_sensor_ptr->sample_min)
+ {
+ io_sensor_ptr->sample_min = i_sensor_value;
+ }
+
+ // update sample max value if input sample value is greater than
+ // sample_max
+ if( i_sensor_value > io_sensor_ptr->sample_max)
+ {
+ io_sensor_ptr->sample_max = i_sensor_value;
+ }
+
+ // If this sensor has mini sensor, update it's value
+ if( io_sensor_ptr->mini_sensor != NULL)
+ {
+ *(io_sensor_ptr->mini_sensor) = i_sensor_value;
+ }
+
+ // add sample value to accumulator
+ io_sensor_ptr->accumulator += i_sensor_value;
+ // increment update tag
+ io_sensor_ptr->update_tag += 1;
+ }
+ else
+ {
+ TRAC_ERR("Invalid sensor pointer");
+ }
+}
+
+
+// Function Specification
+//
+// Name: sensor_op_min
+//
+// Description: Perform min operation on vector sensor
+//
+// Flow: FN= None
+//
+// End Function Specification
+uint16_t sensor_op_min(const vectorSensor_t * i_vecSensorPtr,
+ uint8_t * o_position)
+{
+ uint16_t l_value = UINT16_MAX;
+ uint16_t i = 0;
+
+ // Internal function so not checking for input NULL pointers
+
+ // traverse through enabled vector sensors to find the minimum value
+ for(; i < i_vecSensorPtr->size; i++)
+ {
+ // check if sensor is enabled
+ if( i_vecSensorPtr->elem_enabled[i] == 1)
+ {
+ if( i_vecSensorPtr->source_ptr[i]->sample < l_value)
+ {
+ l_value = i_vecSensorPtr->source_ptr[i]->sample;
+ *o_position = i;
+ }
+ } // end element enabled check
+
+ } // end for loop
+
+ return l_value;
+
+}
+
+
+// Function Specification
+//
+// Name: sensor_op_max
+//
+// Description: Perform max operation for vector sensor
+//
+// Flow: FN= None
+//
+// End Function Specification
+uint16_t sensor_op_max(const vectorSensor_t * i_vecSensorPtr,
+ uint8_t * o_position)
+{
+ uint16_t l_value = UINT16_MIN;
+ uint16_t i = 0;
+
+ // Internal function so not checking for input NULL pointers
+
+ // traverse through enabled vector sensors to find the maximum value
+ for(; i < i_vecSensorPtr->size; i++)
+ {
+ // Check if element is enabled
+ if( i_vecSensorPtr->elem_enabled[i] == 1)
+ {
+ if( i_vecSensorPtr->source_ptr[i]->sample > l_value)
+ {
+ l_value = i_vecSensorPtr->source_ptr[i]->sample;
+ *o_position = i;
+ }
+ }// end element enabled check
+
+ } // end for loop
+
+ return l_value;
+
+}
+
+
+// Function Specification
+//
+// Name: sensor_op_avg
+//
+// Description: Perform average operation for vector sensor
+//
+// Flow: FN= None
+//
+// End Function Specification
+uint16_t sensor_op_avg(const vectorSensor_t * i_vecSensorPtr,
+ const uint16_t i_threshold)
+{
+ uint32_t l_sum = 0;
+ uint16_t i = 0;
+ uint16_t l_number = 0;
+
+ // Internal function so not checking for input NULL pointers
+
+ // traverse through enabled vector sensors to get sum of sensor sample
+ for(; i < i_vecSensorPtr->size; i++)
+ {
+ // check if element is enabled
+ if( i_vecSensorPtr->elem_enabled[i] == 1)
+ {
+ // Include sample only if it is higher than threshold
+ if( i_vecSensorPtr->source_ptr[i]->sample > i_threshold)
+ {
+ l_number++;
+ l_sum += i_vecSensorPtr->source_ptr[i]->sample;
+ }
+ } // end element enabled check
+
+ } // end for loop
+
+ // Calculate average
+ if( l_number != 0)
+ {
+ l_sum = l_sum / l_number;
+ }
+
+ return l_sum;
+}
+
+
+// Function Specification
+//
+// Name: sensor_vector_update
+//
+// Description: Update Vector Sensor
+//
+// Flow: 08/31/2011 FN= sensor_vector_update
+//
+// End Function Specification
+void sensor_vector_update( sensor_t * io_sensor_ptr,const uint32_t i_threshold)
+{
+ if( io_sensor_ptr != NULL)
+ {
+ // Reset sensor if requested
+ if( io_sensor_ptr->status.reset == 1)
+ {
+ sensor_reset(io_sensor_ptr);
+ }
+
+ // Perform vector sensor operation and update sensor
+ if( io_sensor_ptr->vector != NULL)
+ {
+ uint16_t l_value = 0;
+ uint8_t l_position = 0;
+
+ // Min operation
+ if( VECTOR_OP_MIN == io_sensor_ptr->vector->operation)
+ {
+ // calculate min value and get sensor position holding min value
+ l_value = sensor_op_min(io_sensor_ptr->vector, &l_position);
+ // set min position in vector sensor
+ io_sensor_ptr->vector->min_pos = l_position;
+ // Update only if needed
+ if( l_value != UINT16_MAX)
+ {
+ // update sensor with new min value
+ sensor_update(io_sensor_ptr,l_value);
+ }
+ }
+ // Max operation
+ else if( VECTOR_OP_MAX == io_sensor_ptr->vector->operation)
+ {
+ // calculate max value and get sensor position holding max value
+ l_value = sensor_op_max(io_sensor_ptr->vector, &l_position);
+ // set max position in vector sensor
+ io_sensor_ptr->vector->max_pos = l_position;
+ // Update only if needed
+ if( l_value != UINT16_MIN)
+ {
+ // update sensor with new max value
+ sensor_update(io_sensor_ptr,l_value);
+ }
+ }
+ // Average operation
+ else if( VECTOR_OP_AVG == io_sensor_ptr->vector->operation)
+ {
+ // Calculate average of the sensor sample
+ l_value = sensor_op_avg(io_sensor_ptr->vector,i_threshold);
+ // Update only if needed
+ if( l_value != 0)
+ {
+ // update sensor with new average value
+ sensor_update(io_sensor_ptr,l_value);
+ }
+ }
+ // Unsupported operation
+ else
+ {
+ TRAC_ERR("Unsupported vector sensor operation: 0x%x",
+ io_sensor_ptr->vector->operation);
+ }
+
+ } // end valid vector sensor check
+ else
+ {
+ TRAC_ERR("This sensor does not have vector sensor");
+ }
+ }
+ else
+ {
+ TRAC_ERR("Invalid input sensor pointer");
+ }
+}
+
+
+// Function Specification
+//
+// Name: getSensorByGsid
+//
+// Description: Get sensor data using GSID (Global Sensor ID)
+//
+// Flow: 07/15/2011 FN= getSensorByGsid
+//
+// End Function Specification
+sensor_t * getSensorByGsid( const uint16_t i_gsid)
+{
+ sensor_t * l_sensorPtr = NULL;
+
+ // check if input gsid is within range. Return sensor pointer if within
+ // range. Else return NULL
+ if( i_gsid < G_amec_sensor_count)
+ {
+ l_sensorPtr = G_amec_sensor_list[i_gsid];
+ }
+
+ return l_sensorPtr;
+}
+
+
+// Function Specification
+//
+// Name: sensor_vector_elem_enable
+//
+// Description: Enable/disable vector sensor element. This interface can be
+// used at runtime
+//
+// Flow: 07/18/2011 FN= sensor_vector_elem_enable
+//
+// End Function Specification
+void sensor_vector_elem_enable( vectorSensor_t* io_sensor_vector_ptr,
+ const uint8_t i_loc,
+ const uint8_t i_enable)
+{
+ if( io_sensor_vector_ptr != NULL)
+ {
+ // check if location of the vector sensor is within range
+ if( i_loc < io_sensor_vector_ptr->size)
+ {
+ // set element enabled
+ io_sensor_vector_ptr->elem_enabled[i_loc] = i_enable;
+ }
+ else
+ {
+ TRAC_ERR("Invalid input location: 0x%x, max size: 0x%x",
+ i_loc,io_sensor_vector_ptr->size);
+ }
+ }
+ else
+ {
+ TRAC_ERR("NULL input vector sensor pointer");
+ }
+}
+
+
+// Function Specification
+//
+// Name: sensor_vector_elem_add
+//
+// Description: Add element to the vector sensor. If element at the given
+// location is already present, it will be overwritten.
+//
+// Flow: 08/17/2011 FN= sensor_vector_elem_add
+//
+// End Function Specification
+void sensor_vector_elem_add( vectorSensor_t* io_sensor_vector_ptr,
+ const uint8_t i_loc,
+ const sensor_t * i_elemPtr)
+{
+ if( (io_sensor_vector_ptr == NULL) ||
+ (i_elemPtr == NULL ) ||
+ (i_loc >= MAX_VECTOR_SENSORS))
+ {
+ TRAC_ERR("Invalid input parameters. Either pointers are NULL or "
+ "location is out of range i_loc: 0x%x,max allowed: 0x%x",
+ i_loc,MAX_VECTOR_SENSORS);
+ }
+ else if( (i_loc > io_sensor_vector_ptr->size))
+ {
+ TRAC_ERR("Invalid location. Location does not make element contiguous "
+ "i_loc: 0x%x,current vector size: 0x%x",i_loc,
+ io_sensor_vector_ptr->size);
+ }
+ else
+ {
+ // Increase size if spot is empty. Else we are overwriting existing
+ // slot so no need to increment vector size
+ if(io_sensor_vector_ptr->source_ptr[i_loc] == NULL)
+ {
+ io_sensor_vector_ptr->size++;
+ }
+ // set element and enable it.
+ io_sensor_vector_ptr->source_ptr[i_loc] = (sensor_t*)i_elemPtr;
+ io_sensor_vector_ptr->elem_enabled[i_loc] = 1;
+ }
+}
+
+
+
+// Function Specification
+//
+// Name: sensor_init_all
+//
+// Description: Initialize all sensors in the global sensor list.
+//
+// Flow: --/--/2011 FN=None
+//
+// End Function Specification
+void sensor_init_all(void)
+{
+ int i;
+ int l_num_entries = NUMBER_OF_SENSORS_IN_LIST;
+ const sensor_ptr_t * l_argPtrSensor = &G_amec_sensor_list[0];
+ const minisensor_ptr_t * l_argPtrMiniSensor = &G_amec_mini_sensor_list[0];
+
+ for(i=0; i < l_num_entries; i++)
+ {
+ sensor_init(l_argPtrSensor[i], i, l_argPtrMiniSensor[i]);
+ }
+
+ // If G_amec_sensor_count doesn't match the number of sensors, we must have
+ // failed to initialize one or more sensors.
+ if(NUMBER_OF_SENSORS_IN_LIST != G_amec_sensor_count)
+ {
+ TRAC_ERR("Sensor Initialization Failed to initialize all sensors");
+
+ /* @
+ * @errortype
+ * @moduleid SENSOR_INITIALIZE
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 G_amec_sensor_count - number of sensors initialized
+ * @userdata2 NUMBER_OF_SENSORS_IN_LIST - total number of OCC sensors
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware internal failure initializing sensors
+ */
+ errlHndl_t l_err = createErrl(
+ SENSOR_INITIALIZE, // Module ID
+ INTERNAL_FAILURE, // Reason Code // @wb003
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_PREDICTIVE, // Severity
+ NULL, // Trace
+ 0, // Trace Size
+ G_amec_sensor_count, // UserData 1
+ NUMBER_OF_SENSORS_IN_LIST // UserData 2
+ );
+
+ commitErrl(&l_err);
+ }
+
+ TRAC_IMP("Sensor Initialization Complete");
+}
+
diff --git a/src/occ/sensor/sensor.h b/src/occ/sensor/sensor.h
new file mode 100755
index 0000000..8aeac74
--- /dev/null
+++ b/src/occ/sensor/sensor.h
@@ -0,0 +1,282 @@
+/******************************************************************************
+// @file sensor.h
+// @brief OCC Sensor structure and other common defines.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensor.h SENSOR.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb002 pbavari 08/15/2011 Created
+ * @pb003 pbavari 08/31/2011 mini-sensor support
+ * @pb004 pbavari 09/02/2011 Initialize section support
+ * @pb00A pbavari 11/14/2011 Moved sensor_init from applet and
+ * updated with latest design change
+ * @th005 thallet 11/23/2011 Sensor Initialization Changes
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/12 Added 2D macro
+ * @at003 alvinwan 03/19/2012 Move sensor_info_t from sensor_info.c
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @gm002 885429 milesg 05/30/2013 change type/location to 16 bit bitmask
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @fk009 942864 fmkassem 09/30/2014 BMC/HTMGT Poll command version 0x10 support.
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _sensor_h
+#define _sensor_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // defines for uint8_t,uint3_t..etc
+#include <errl.h> // For errlHndl_t
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h> // Common OCC defines
+#include <sensor_enum.h> // For Sensor Enum
+
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+// Macro to get mini sensor value. It gives the mini sensor value for
+// the given occId at given the given field. If occId is out of range, it will
+// return 0.
+#define MINI_SENSOR_VALUE(occId,fieldNm) \
+ ( (occId < MAX_OCCS) ? G_dcom_slv_outbox[occId].fieldNm : 0x0)
+
+// Make a AMEC Number out of mantissa & exponent.
+#define AMEFP(mantissa,exp) (((UINT32)mantissa << 8) | (UINT32)((UINT8) 256 + (UINT8)exp))
+
+// Get pointer to sensor based on GSID
+#define AMECSENSOR_PTR(sensor) G_amec_sensor_list[sensor]
+#define AMECSENSOR_ARRAY_PTR(sensor_base,idx) G_amec_sensor_list[sensor_base+idx]
+#define AMECSENSOR_2D_ARRAY_PTR(sensor_base,idx,idx2) G_amec_sensor_list[sensor_base+idx+idx2]
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+#define AMEC_SENSOR_NONUM 0xFF
+#define SENSOR_TYPE_ALL 0xFFFF
+#define SENSOR_LOC_ALL 0xFFFF
+#define MAX_VECTOR_SENSORS 32
+#define MAX_SENSOR_NAME_SZ 16 // including NULL
+#define MAX_SENSOR_UNIT_SZ 4 // including NULL
+#define MAX_AMEC_SENSORS 500
+#define VECTOR_SENSOR_DEFAULT_VAL 0xFF
+
+typedef enum
+{
+ AMEC_SENSOR_TYPE_UNKNOWN = 0x0000,
+ AMEC_SENSOR_TYPE_GENERIC = 0x0001,
+ AMEC_SENSOR_TYPE_CURRENT = 0x0002,
+ AMEC_SENSOR_TYPE_VOLTAGE = 0x0004,
+ AMEC_SENSOR_TYPE_TEMP = 0x0008,
+ AMEC_SENSOR_TYPE_UTIL = 0x0010,
+ AMEC_SENSOR_TYPE_TIME = 0x0020,
+ AMEC_SENSOR_TYPE_FREQ = 0x0040,
+ AMEC_SENSOR_TYPE_POWER = 0x0080,
+// AMEC_SENSOR_TYPE_CPM = 0x0100, //CPM - Commented out as requested by Malcolm
+ AMEC_SENSOR_TYPE_PERF = 0x0200,
+ AMEC_SENSOR_TYPE_ALL = 0xffff,
+}AMEC_SENSOR_TYPE;
+
+typedef enum
+{
+ AMEC_SENSOR_LOC_UNKNOWN = 0x0000,
+ AMEC_SENSOR_LOC_SYS = 0x0001,
+ AMEC_SENSOR_LOC_PROC = 0x0002,
+ AMEC_SENSOR_LOC_LPAR = 0x0004,
+ AMEC_SENSOR_LOC_MEM = 0x0008,
+ AMEC_SENSOR_LOC_VRM = 0x0010,
+ AMEC_SENSOR_LOC_OCC = 0x0020,
+ AMEC_SENSOR_LOC_CORE = 0x0040,
+ AMEC_SENSOR_LOC_ALL = 0xffff,
+}AMEC_SENSOR_LOC;
+
+// Vector Sensor operation enumeration
+typedef enum
+{
+ VECTOR_OP_NONE = 0x00,
+ VECTOR_OP_MAX = 0x01,
+ VECTOR_OP_MIN = 0x02,
+ VECTOR_OP_AVG = 0x03,
+
+} VECTOR_SENSOR_OP;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+/*****************************************************************************/
+// Forward declaration as used in vectorSensor
+struct sensor;
+typedef struct sensor sensor_t;
+
+// Vector Sensor structure
+struct vectorSensor
+{
+ VECTOR_SENSOR_OP operation; //Operation that this vector should execute
+ uint8_t size; // Number of elements in this vector
+ uint8_t elem_enabled[MAX_VECTOR_SENSORS]; // indicates if a given element
+ // is enabled or disabled
+ sensor_t* source_ptr[MAX_VECTOR_SENSORS]; // Pointer to an array of source
+ //pointers (source elements of this vector)
+ uint8_t min_pos; // Minimum val vector position for the latest snapshot
+ uint8_t max_pos; // Maximum val vector position for the latest snapshot
+
+} __attribute__ ((__packed__));
+
+typedef struct vectorSensor vectorSensor_t;
+
+//@at003A
+typedef struct
+{
+ char name[MAX_SENSOR_NAME_SZ];
+ struct
+ {
+ char units[MAX_SENSOR_UNIT_SZ];
+ uint16_t type;
+ uint16_t location;
+ uint8_t number;
+ uint32_t freq;
+ uint32_t scalefactor;
+ } __attribute__ ((__packed__)) sensor;
+} __attribute__ ((__packed__)) sensor_info_t;
+
+/*****************************************************************************/
+//Sensor status structure
+struct sensorStatus
+{
+ uint8_t buffer_area_type:1,
+ update_histogram:1,
+ reset:1,
+ reserved:5;
+};
+typedef struct sensorStatus sensorStatus_t;
+
+/*****************************************************************************/
+//@fk009c - added the ipmi_sid.
+//@pb003d - removed histogram pointer as it will be statically allocated
+// outside of sensor structure
+//@pb003c - changed type of mini_sensor pointer to uint16 from uint8
+// Sensor structure
+struct sensor
+{
+ uint16_t gsid; // Global Sensor ID
+ uint16_t sample; // Latest sample of this sensor
+ uint16_t sample_min; // Minimum value since last reset
+ uint16_t sample_max; // Maximum Value since last reset
+ uint32_t accumulator; // Accumulator register for this sensor
+ uint32_t src_accum_snapshot; // Copy of the source sensor's accumulator
+ // used for time-derived sensors
+ uint32_t update_tag; // Count of the number of 'ticks' that have passed
+ // between updates to this sensor (used for time-
+ // derived sensor)
+ uint16_t ipmi_sid; // Ipmi sensor id obtained from mrw //@fk009
+ vectorSensor_t * vector; // Pointer to vector control structure. NULL if
+ // this is not a vector sensor.
+ uint16_t * mini_sensor; // Pointer to entry in mini-sensor table. NULL if
+ // this sensor does not have a mini-sensor
+ sensorStatus_t status; // Status and control register
+
+} __attribute__ ((__packed__));
+
+// Typedef for this structure is part of the forward declaration for the
+// vector sensor structure section in this file
+
+/*****************************************************************************/
+// Sensor Query list structure used for querying sensor data
+struct sensorQueryList
+{
+ uint16_t gsid; // Global Sensor ID
+ uint16_t sample; // Latest sample of the sensor
+ char name[MAX_SENSOR_NAME_SZ]; // Sensor Name
+};
+
+typedef struct sensorQueryList sensorQueryList_t;
+
+/*****************************************************************************/
+// Sensor List Structures used to build tables of sensor pointers.
+// Global sensor list type
+typedef sensor_t * sensor_ptr_t;
+// Global mini-sensor list type
+typedef uint16_t * minisensor_ptr_t;
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+/*****************************************************************************/
+// These are used by the sensor init
+// Global sensor counter
+extern uint32_t G_amec_sensor_count;
+
+// Contains array of pointers to sensors, indexed by GSID
+extern const sensor_ptr_t G_amec_sensor_list[];
+
+extern const sensor_info_t G_sensor_info[]; //@fk009a
+
+// Contains array of pointers to mini-sensors, indexed by GSID
+extern const minisensor_ptr_t G_amec_mini_sensor_list[];
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// sensor_init
+void sensor_init(sensor_t * io_sensor_ptr,
+ const uint16_t i_gsid,
+ const uint16_t * i_miniSnsrPtr
+ );
+
+// Clear minmax value
+void sensor_clear_minmax( sensor_t * io_sensor_ptr);
+
+// Sensor reset
+void sensor_reset( sensor_t * io_sensor_ptr);
+
+//Vectorize sensor
+void sensor_vectorize( sensor_t * io_sensor_ptr,
+ vectorSensor_t * io_vec_sensor_ptr,
+ const VECTOR_SENSOR_OP i_op);
+
+//Update sensor
+void sensor_update( sensor_t * io_sensor_ptr, const uint16_t i_sensor_value);
+
+//Perform operation on vector sensor and update sensor
+void sensor_vector_update( sensor_t * io_sensor_ptr,const uint32_t i_threshold);
+
+// Get sensor by GSID
+sensor_t * getSensorByGsid( const uint16_t i_gsid);
+
+// enable/disable vector sensor element
+void sensor_vector_elem_enable( vectorSensor_t* io_sensor_vector_ptr,
+ const uint8_t i_loc,
+ const uint8_t i_enable);
+
+// Add element to the vector sensor
+void sensor_vector_elem_add( vectorSensor_t* io_sensor_vector_ptr,
+ const uint8_t i_loc,
+ const sensor_t * i_elemPtr);
+
+// Initialize all sensors
+void sensor_init_all(void);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif // _sensor_h
+
+
diff --git a/src/occ/sensor/sensor_enum.h b/src/occ/sensor/sensor_enum.h
new file mode 100755
index 0000000..071246f
--- /dev/null
+++ b/src/occ/sensor/sensor_enum.h
@@ -0,0 +1,631 @@
+/******************************************************************************
+// @file sensor_enum.h
+// @brief OCC SENSOR COMPONENT ENUM
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensor_enum.h SENSOR_ENUM.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th005 thallet 11/21/2011 Created
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @ly001 853751 lychen 09/17/2012 Support DPS algorithm
+ * @th026 865074 thallet 12/21/2012 Updated Centaur sensors
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ * @mw682 933716 mware 07/28/2014 Renamed MCIFD to be NOTBZE and MCIFI to be NOTFIN.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _sensor_enum_h
+#define _sensor_enum_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+/*****************************************************************************
+ * This enum is the list of all the sensors that are used in the system. The
+ * value of the enum is the GSID of the sensor, and all tables are initialized
+ * based on this.
+ * If you add a sensor to this enum:
+ * - All GSIDs after it will automatically change
+ * - The number of sensors & size of arrays will automatially change
+ * - The name of the enum will be turned into a string, and that is the
+ * string that will be stored as that sensor's name.
+ * - This means the enum name must match the Sensor Name string
+ * and will need to follow the rules for that string (max 15 chars)
+ * - You will need to modify the following files:
+ * - sensor_table.c - add sensor pointer to G_amec_sensor_list and
+ * if needed to G_amec_mini_sensor_list
+ * - sensor_info.c - add sensor information to G_sensor_info
+ * - amec/amec_sys.h - add sensor_t to system structure so you can
+ */
+
+enum e_gsid
+{
+ // ------------------------------------------------------
+ // Code/Firmware Sensors
+ // ------------------------------------------------------
+ AMEintdur = 0, // Combined duration of the AMEC Master & Slave Tasks
+
+ AMESSdur0, // Combined duration of the AMEC Master & Slave 0
+ AMESSdur1, // Combined duration of the AMEC Master & Slave 1
+ AMESSdur2, // Combined duration of the AMEC Master & Slave 2
+ AMESSdur3, // Combined duration of the AMEC Master & Slave 3
+ AMESSdur4, // Combined duration of the AMEC Master & Slave 4
+ AMESSdur5, // Combined duration of the AMEC Master & Slave 5
+ AMESSdur6, // Combined duration of the AMEC Master & Slave 6
+ AMESSdur7, // Combined duration of the AMEC Master & Slave 7
+
+ PROBE250US0, // Internal Sensor for debug via AMESTER
+ PROBE250US1, // Internal Sensor for debug via AMESTER
+ PROBE250US2, // Internal Sensor for debug via AMESTER
+ PROBE250US3, // Internal Sensor for debug via AMESTER
+ PROBE250US4, // Internal Sensor for debug via AMESTER
+ PROBE250US5, // Internal Sensor for debug via AMESTER
+ PROBE250US6, // Internal Sensor for debug via AMESTER
+ PROBE250US7, // Internal Sensor for debug via AMESTER
+
+ GPEtickdur0, // Duration on the GPE0 Engine
+ GPEtickdur1, // Duration on the GPE1 Engine
+ RTLtickdur, // Duration on the RTL tick interrupt
+
+ // ------------------------------------------------------
+ // System Sensors
+ // ------------------------------------------------------
+ TEMPAMBIENT, // Ambient Temp of System (from APSS)
+ ALTITUDE, // Altitude of System (from APSS)
+ PWR250US, // System DC Power (from APSS)
+ PWR250USFAN, // Fan Power (from APSS)
+ PWR250USIO, // IO Subsystem Power (from APSS)
+ PWR250USSTORE, // Storage Subsys Power (from APSS)
+ PWR250USGPU, // GPU Subsystem Power (from APSS) e.g. Nvidia GPU
+ FANSPEEDAVG, // Average Fan Speed (from DPSS)
+
+ // ------------------------------------------------------
+ // Chip Sensors
+ // ------------------------------------------------------
+ TODclock0, // \ .
+ TODclock1, // => 32 MHz TimeOfDay Clock split into 3 sensors
+ TODclock2, // / (from Chip SCOM)
+
+ // ------------------------------------------------------
+ // Processor Sensors
+ // ------------------------------------------------------
+ FREQA2MSP0,
+ IPS2MSP0,
+ MEMSP2MSP0,
+ PWR250USP0,
+ PWR250USVDD0,
+ CUR250USVDD0,
+ PWR250USVCS0,
+ PWR250USMEM0, //TODO: should this be P0 or just 0
+ SLEEPCNT2MSP0,
+ WINKCNT2MSP0,
+ SP250USP0,
+ TEMP2MSP0,
+ TEMP2MSP0PEAK,
+ UTIL2MSP0,
+ VRFAN250USPROC,
+ VRHOT250USPROC,
+
+ // ------------------------------------------------------
+ // Core Sensors (12 of each)
+ // ------------------------------------------------------
+
+/* CPM2MSP0C0, //CPM - Commented out as requested by Malcolm
+ CPM2MSP0C1,
+ CPM2MSP0C2,
+ CPM2MSP0C3,
+ CPM2MSP0C4,
+ CPM2MSP0C5,
+ CPM2MSP0C6,
+ CPM2MSP0C7,
+ CPM2MSP0C8,
+ CPM2MSP0C9,
+ CPM2MSP0C10,
+ CPM2MSP0C11,
+*/
+ FREQ250USP0C0,
+ FREQ250USP0C1,
+ FREQ250USP0C2,
+ FREQ250USP0C3,
+ FREQ250USP0C4,
+ FREQ250USP0C5,
+ FREQ250USP0C6,
+ FREQ250USP0C7,
+ FREQ250USP0C8,
+ FREQ250USP0C9,
+ FREQ250USP0C10,
+ FREQ250USP0C11,
+
+ FREQA2MSP0C0,
+ FREQA2MSP0C1,
+ FREQA2MSP0C2,
+ FREQA2MSP0C3,
+ FREQA2MSP0C4,
+ FREQA2MSP0C5,
+ FREQA2MSP0C6,
+ FREQA2MSP0C7,
+ FREQA2MSP0C8,
+ FREQA2MSP0C9,
+ FREQA2MSP0C10,
+ FREQA2MSP0C11,
+
+ IPS2MSP0C0,
+ IPS2MSP0C1,
+ IPS2MSP0C2,
+ IPS2MSP0C3,
+ IPS2MSP0C4,
+ IPS2MSP0C5,
+ IPS2MSP0C6,
+ IPS2MSP0C7,
+ IPS2MSP0C8,
+ IPS2MSP0C9,
+ IPS2MSP0C10,
+ IPS2MSP0C11,
+
+ NOTBZE2MSP0C0,
+ NOTBZE2MSP0C1,
+ NOTBZE2MSP0C2,
+ NOTBZE2MSP0C3,
+ NOTBZE2MSP0C4,
+ NOTBZE2MSP0C5,
+ NOTBZE2MSP0C6,
+ NOTBZE2MSP0C7,
+ NOTBZE2MSP0C8,
+ NOTBZE2MSP0C9,
+ NOTBZE2MSP0C10,
+ NOTBZE2MSP0C11,
+
+ NOTFIN2MSP0C0,
+ NOTFIN2MSP0C1,
+ NOTFIN2MSP0C2,
+ NOTFIN2MSP0C3,
+ NOTFIN2MSP0C4,
+ NOTFIN2MSP0C5,
+ NOTFIN2MSP0C6,
+ NOTFIN2MSP0C7,
+ NOTFIN2MSP0C8,
+ NOTFIN2MSP0C9,
+ NOTFIN2MSP0C10,
+ NOTFIN2MSP0C11,
+
+ SPURR2MSP0C0,
+ SPURR2MSP0C1,
+ SPURR2MSP0C2,
+ SPURR2MSP0C3,
+ SPURR2MSP0C4,
+ SPURR2MSP0C5,
+ SPURR2MSP0C6,
+ SPURR2MSP0C7,
+ SPURR2MSP0C8,
+ SPURR2MSP0C9,
+ SPURR2MSP0C10,
+ SPURR2MSP0C11,
+
+ TEMP2MSP0C0,
+ TEMP2MSP0C1,
+ TEMP2MSP0C2,
+ TEMP2MSP0C3,
+ TEMP2MSP0C4,
+ TEMP2MSP0C5,
+ TEMP2MSP0C6,
+ TEMP2MSP0C7,
+ TEMP2MSP0C8,
+ TEMP2MSP0C9,
+ TEMP2MSP0C10,
+ TEMP2MSP0C11,
+
+ UTIL2MSP0C0,
+ UTIL2MSP0C1,
+ UTIL2MSP0C2,
+ UTIL2MSP0C3,
+ UTIL2MSP0C4,
+ UTIL2MSP0C5,
+ UTIL2MSP0C6,
+ UTIL2MSP0C7,
+ UTIL2MSP0C8,
+ UTIL2MSP0C9,
+ UTIL2MSP0C10,
+ UTIL2MSP0C11,
+
+ NUTIL3SP0C0,
+ NUTIL3SP0C1,
+ NUTIL3SP0C2,
+ NUTIL3SP0C3,
+ NUTIL3SP0C4,
+ NUTIL3SP0C5,
+ NUTIL3SP0C6,
+ NUTIL3SP0C7,
+ NUTIL3SP0C8,
+ NUTIL3SP0C9,
+ NUTIL3SP0C10,
+ NUTIL3SP0C11,
+
+ MSTL2MSP0C0,
+ MSTL2MSP0C1,
+ MSTL2MSP0C2,
+ MSTL2MSP0C3,
+ MSTL2MSP0C4,
+ MSTL2MSP0C5,
+ MSTL2MSP0C6,
+ MSTL2MSP0C7,
+ MSTL2MSP0C8,
+ MSTL2MSP0C9,
+ MSTL2MSP0C10,
+ MSTL2MSP0C11,
+
+ CMT2MSP0C0,
+ CMT2MSP0C1,
+ CMT2MSP0C2,
+ CMT2MSP0C3,
+ CMT2MSP0C4,
+ CMT2MSP0C5,
+ CMT2MSP0C6,
+ CMT2MSP0C7,
+ CMT2MSP0C8,
+ CMT2MSP0C9,
+ CMT2MSP0C10,
+ CMT2MSP0C11,
+
+
+ CMBW2MSP0C0,
+ CMBW2MSP0C1,
+ CMBW2MSP0C2,
+ CMBW2MSP0C3,
+ CMBW2MSP0C4,
+ CMBW2MSP0C5,
+ CMBW2MSP0C6,
+ CMBW2MSP0C7,
+ CMBW2MSP0C8,
+ CMBW2MSP0C9,
+ CMBW2MSP0C10,
+ CMBW2MSP0C11,
+
+ PPICP0C0,
+ PPICP0C1,
+ PPICP0C2,
+ PPICP0C3,
+ PPICP0C4,
+ PPICP0C5,
+ PPICP0C6,
+ PPICP0C7,
+ PPICP0C8,
+ PPICP0C9,
+ PPICP0C10,
+ PPICP0C11,
+
+ PWRPX250USP0C0,
+ PWRPX250USP0C1,
+ PWRPX250USP0C2,
+ PWRPX250USP0C3,
+ PWRPX250USP0C4,
+ PWRPX250USP0C5,
+ PWRPX250USP0C6,
+ PWRPX250USP0C7,
+ PWRPX250USP0C8,
+ PWRPX250USP0C9,
+ PWRPX250USP0C10,
+ PWRPX250USP0C11,
+
+ // ------------------------------------------------------
+ // Regulator Sensors
+ // ------------------------------------------------------
+ UVOLT250USP0V0,
+ UVOLT250USP0V1,
+ VOLT250USP0V0,
+ VOLT250USP0V1,
+
+#if 0
+ // ------------------------------------------------------
+ // Channel-pair Sensors
+ // ------------------------------------------------------
+ MEMSP2MSP0MyCz, //TODO: There should be 8 of these
+#endif
+
+ // ------------------------------------------------------
+ // Memory Sensors
+ // ------------------------------------------------------
+ VRFAN250USMEM,
+ VRHOT250USMEM,
+
+ MRD2MSP0M0,
+ MRD2MSP0M1,
+ MRD2MSP0M2,
+ MRD2MSP0M3,
+ MRD2MSP0M4,
+ MRD2MSP0M5,
+ MRD2MSP0M6,
+ MRD2MSP0M7,
+
+ MWR2MSP0M0,
+ MWR2MSP0M1,
+ MWR2MSP0M2,
+ MWR2MSP0M3,
+ MWR2MSP0M4,
+ MWR2MSP0M5,
+ MWR2MSP0M6,
+ MWR2MSP0M7,
+
+ TEMPDIMMAXP0M0,
+ TEMPDIMMAXP0M1,
+ TEMPDIMMAXP0M2,
+ TEMPDIMMAXP0M3,
+ TEMPDIMMAXP0M4,
+ TEMPDIMMAXP0M5,
+ TEMPDIMMAXP0M6,
+ TEMPDIMMAXP0M7,
+
+ LOCDIMMAXP0M0,
+ LOCDIMMAXP0M1,
+ LOCDIMMAXP0M2,
+ LOCDIMMAXP0M3,
+ LOCDIMMAXP0M4,
+ LOCDIMMAXP0M5,
+ LOCDIMMAXP0M6,
+ LOCDIMMAXP0M7,
+
+ // ------------------------------------------------------
+ // Centaur Sensors - 8 MemC/Proc - 1 Cent/MemC - 2 PP/Cent
+ // ------------------------------------------------------
+ MAC2MSP0M0C0P0,
+ MAC2MSP0M0C0P1,
+ MAC2MSP0M1C0P0,
+ MAC2MSP0M1C0P1,
+ MAC2MSP0M2C0P0,
+ MAC2MSP0M2C0P1,
+ MAC2MSP0M3C0P0,
+ MAC2MSP0M3C0P1,
+ MAC2MSP0M4C0P0,
+ MAC2MSP0M4C0P1,
+ MAC2MSP0M5C0P0,
+ MAC2MSP0M5C0P1,
+ MAC2MSP0M6C0P0,
+ MAC2MSP0M6C0P1,
+ MAC2MSP0M7C0P0,
+ MAC2MSP0M7C0P1,
+
+ MPU2MSP0M0C0P0,
+ MPU2MSP0M0C0P1,
+ MPU2MSP0M1C0P0,
+ MPU2MSP0M1C0P1,
+ MPU2MSP0M2C0P0,
+ MPU2MSP0M2C0P1,
+ MPU2MSP0M3C0P0,
+ MPU2MSP0M3C0P1,
+ MPU2MSP0M4C0P0,
+ MPU2MSP0M4C0P1,
+ MPU2MSP0M5C0P0,
+ MPU2MSP0M5C0P1,
+ MPU2MSP0M6C0P0,
+ MPU2MSP0M6C0P1,
+ MPU2MSP0M7C0P0,
+ MPU2MSP0M7C0P1,
+
+ MIRB2MSP0M0C0P0,
+ MIRB2MSP0M0C0P1,
+ MIRB2MSP0M1C0P0,
+ MIRB2MSP0M1C0P1,
+ MIRB2MSP0M2C0P0,
+ MIRB2MSP0M2C0P1,
+ MIRB2MSP0M3C0P0,
+ MIRB2MSP0M3C0P1,
+ MIRB2MSP0M4C0P0,
+ MIRB2MSP0M4C0P1,
+ MIRB2MSP0M5C0P0,
+ MIRB2MSP0M5C0P1,
+ MIRB2MSP0M6C0P0,
+ MIRB2MSP0M6C0P1,
+ MIRB2MSP0M7C0P0,
+ MIRB2MSP0M7C0P1,
+
+ MIRL2MSP0M0C0P0,
+ MIRL2MSP0M0C0P1,
+ MIRL2MSP0M1C0P0,
+ MIRL2MSP0M1C0P1,
+ MIRL2MSP0M2C0P0,
+ MIRL2MSP0M2C0P1,
+ MIRL2MSP0M3C0P0,
+ MIRL2MSP0M3C0P1,
+ MIRL2MSP0M4C0P0,
+ MIRL2MSP0M4C0P1,
+ MIRL2MSP0M5C0P0,
+ MIRL2MSP0M5C0P1,
+ MIRL2MSP0M6C0P0,
+ MIRL2MSP0M6C0P1,
+ MIRL2MSP0M7C0P0,
+ MIRL2MSP0M7C0P1,
+
+ MIRM2MSP0M0C0P0,
+ MIRM2MSP0M0C0P1,
+ MIRM2MSP0M1C0P0,
+ MIRM2MSP0M1C0P1,
+ MIRM2MSP0M2C0P0,
+ MIRM2MSP0M2C0P1,
+ MIRM2MSP0M3C0P0,
+ MIRM2MSP0M3C0P1,
+ MIRM2MSP0M4C0P0,
+ MIRM2MSP0M4C0P1,
+ MIRM2MSP0M5C0P0,
+ MIRM2MSP0M5C0P1,
+ MIRM2MSP0M6C0P0,
+ MIRM2MSP0M6C0P1,
+ MIRM2MSP0M7C0P0,
+ MIRM2MSP0M7C0P1,
+
+ MIRH2MSP0M0C0P0,
+ MIRH2MSP0M0C0P1,
+ MIRH2MSP0M1C0P0,
+ MIRH2MSP0M1C0P1,
+ MIRH2MSP0M2C0P0,
+ MIRH2MSP0M2C0P1,
+ MIRH2MSP0M3C0P0,
+ MIRH2MSP0M3C0P1,
+ MIRH2MSP0M4C0P0,
+ MIRH2MSP0M4C0P1,
+ MIRH2MSP0M5C0P0,
+ MIRH2MSP0M5C0P1,
+ MIRH2MSP0M6C0P0,
+ MIRH2MSP0M6C0P1,
+ MIRH2MSP0M7C0P0,
+ MIRH2MSP0M7C0P1,
+
+ MTS2MSP0M0C0P0,
+ MTS2MSP0M0C0P1,
+ MTS2MSP0M1C0P0,
+ MTS2MSP0M1C0P1,
+ MTS2MSP0M2C0P0,
+ MTS2MSP0M2C0P1,
+ MTS2MSP0M3C0P0,
+ MTS2MSP0M3C0P1,
+ MTS2MSP0M4C0P0,
+ MTS2MSP0M4C0P1,
+ MTS2MSP0M5C0P0,
+ MTS2MSP0M5C0P1,
+ MTS2MSP0M6C0P0,
+ MTS2MSP0M6C0P1,
+ MTS2MSP0M7C0P0,
+ MTS2MSP0M7C0P1,
+
+ MEMSP2MSPM0C0P0,
+ MEMSP2MSPM0C0P1,
+ MEMSP2MSPM1C0P0,
+ MEMSP2MSPM1C0P1,
+ MEMSP2MSPM2C0P0,
+ MEMSP2MSPM2C0P1,
+ MEMSP2MSPM3C0P0,
+ MEMSP2MSPM3C0P1,
+ MEMSP2MSPM4C0P0,
+ MEMSP2MSPM4C0P1,
+ MEMSP2MSPM5C0P0,
+ MEMSP2MSPM5C0P1,
+ MEMSP2MSPM6C0P0,
+ MEMSP2MSPM6C0P1,
+ MEMSP2MSPM7C0P0,
+ MEMSP2MSPM7C0P1,
+
+ M4RD2MSP0M0C0P0,
+ M4RD2MSP0M0C0P1,
+ M4RD2MSP0M1C0P0,
+ M4RD2MSP0M1C0P1,
+ M4RD2MSP0M2C0P0,
+ M4RD2MSP0M2C0P1,
+ M4RD2MSP0M3C0P0,
+ M4RD2MSP0M3C0P1,
+ M4RD2MSP0M4C0P0,
+ M4RD2MSP0M4C0P1,
+ M4RD2MSP0M5C0P0,
+ M4RD2MSP0M5C0P1,
+ M4RD2MSP0M6C0P0,
+ M4RD2MSP0M6C0P1,
+ M4RD2MSP0M7C0P0,
+ M4RD2MSP0M7C0P1,
+
+ M4WR2MSP0M0C0P0,
+ M4WR2MSP0M0C0P1,
+ M4WR2MSP0M1C0P0,
+ M4WR2MSP0M1C0P1,
+ M4WR2MSP0M2C0P0,
+ M4WR2MSP0M2C0P1,
+ M4WR2MSP0M3C0P0,
+ M4WR2MSP0M3C0P1,
+ M4WR2MSP0M4C0P0,
+ M4WR2MSP0M4C0P1,
+ M4WR2MSP0M5C0P0,
+ M4WR2MSP0M5C0P1,
+ M4WR2MSP0M6C0P0,
+ M4WR2MSP0M6C0P1,
+ M4WR2MSP0M7C0P0,
+ M4WR2MSP0M7C0P1,
+
+ MIRC2MSP0M0,
+ MIRC2MSP0M1,
+ MIRC2MSP0M2,
+ MIRC2MSP0M3,
+ MIRC2MSP0M4,
+ MIRC2MSP0M5,
+ MIRC2MSP0M6,
+ MIRC2MSP0M7,
+
+ MLP2P0M0,
+ MLP2P0M1,
+ MLP2P0M2,
+ MLP2P0M3,
+ MLP2P0M4,
+ MLP2P0M5,
+ MLP2P0M6,
+ MLP2P0M7,
+
+ TEMP2MSCENT,
+ TEMP2MSDIMM,
+ MEMSP2MS,
+
+ // @ly001a - start
+ // ------------------------------------------------------
+ // Partition Sensors
+ // ------------------------------------------------------
+ UTIL2MSSLCG000,
+ UTIL2MSSLCG001,
+ UTIL2MSSLCG002,
+ UTIL2MSSLCG003,
+ UTIL2MSSLCG004,
+ UTIL2MSSLCG005,
+ UTIL2MSSLCG006,
+ UTIL2MSSLCG007,
+ UTIL2MSSLCG008,
+ UTIL2MSSLCG009,
+ UTIL2MSSLCG010,
+ UTIL2MSSLCG011,
+ // @ly001a - end
+
+ //TODO: These sensors from "Sensor List v17.xls" haven't been implemented
+#if 0
+ MEMSP2MSP0IGx, //TODO: 16
+#endif
+
+ // ------------------------------------------------------
+ // END of Sensor List (this must be last entry)
+ // ------------------------------------------------------
+ NUMBER_OF_SENSORS_IN_LIST,
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif
+
diff --git a/src/occ/sensor/sensor_info.c b/src/occ/sensor/sensor_info.c
new file mode 100755
index 0000000..ed037ca
--- /dev/null
+++ b/src/occ/sensor/sensor_info.c
@@ -0,0 +1,336 @@
+/******************************************************************************
+// @file sensor_info.c
+// @brief Common sensor List for product applets
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensor_info.c SENSOR_INFO.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th005 thallet 11/15/2011 created
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00b thallet 02/28/12 Fix frequency on 3 sensors
+ * @at003 alvinwan 03/19/2012 Move sensor_info_t to sensor.h
+ * @ly001 853751 lychen 09/17/2012 Support DPS algorithm
+ * @th026 865074 thallet 12/21/2012 Updated Centaur sensors
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup Changes
+ * @gm002 885429 milesg 05/30/2013 Updated type and location values
+ * @at016 891144 alvinwan 06/10/2013 OCC Power Cap Testing
+ * @gs010 899888 gjsilva 09/24/2013 Fix scale factor for UTIL sensors
+ * @gm012 905097 milesg 10/31/2013 Change core sensor strings to use hw numbering
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @mw633 mware 02/08/2014 Correct scaling on per core memory read and write bandwidth sensors.
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ * @mw655 918066 mware 03/11/2014 2x higher scaling on per chip memory read/write bandwidth and core memory bandwidth sensors.
+ * @mw671 mware 05/06/2014 Removed 2x higher scaling on per chip memory read/write bandwidth and per core.
+ * @mw682 933716 mware 07/28/2014 Renamed MCPIFD to be NOTBZE and MCPIFI to be NOTFIN.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef APPLET_BUILD
+#warning "This file is only in OCC App Source Tree for convenience of updating sensors in one place."
+#error "This file can only be included and built into an applet due to large table size"
+#endif
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h> // STATIC_ASSERT macro
+#include <sensor.h> // For Sensor defines
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define AMEEFP_2MS_IN_HZ AMEFP(5,2) // 500 Hz
+#define AMEEFP_250US_IN_HZ AMEFP(4,3) // 4000 Hz
+#define AMEEFP_3S_IN_HZ AMEFP(333,-3) // 0.333 Hz
+#define AMEFP_SCALE_0_16384 AMEFP(610352,-8) // scalar so that digital 16384=100% // @ly001a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+// This will get the string when given the GSID
+#define SENSOR_GSID_TO_STRING(gsid) G_sensor_list[gsid].name;
+
+// This will define the fields of the "sensor" member of the sensor_info_t
+#define SENSOR_VALUES(units, type, location, number, frequency, scaleFactor) \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}
+
+// This will put a single sensor entry into the sensor list table
+#define SENSOR_INFO_T_ENTRY(sensor_name, units, type, location, number, frequency, scaleFactor) \
+ [sensor_name] = {.name = #sensor_name, \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}
+
+// This will paste a number onto a sensor name base to create the full enum
+// representation of the sensor name
+#define SENSOR_W_NUM(sensor_name, num) sensor_name##num
+
+// This will paste a number onto a sensor name base to create the full enum
+// representation of the sensor name
+#define SENSOR_W_CENTAUR_NUM_HELPER(sensor_name, memc,centL,cent,ppL,pp) sensor_name##memc##centL##cent##ppL##pp
+#define SENSOR_W_CENTAUR_NUM(sensor_name, memc,cent,pp) SENSOR_W_CENTAUR_NUM_HELPER(sensor_name,memc,C,cent,P,pp)
+
+// This will stringify the enum so to create the sensor name. This will help
+// save keystrokes, as well as reduce typos & copy paste errors.
+#define SENSOR_STRING(sensor_name) #sensor_name
+
+// This will stringify the enum so to create the sensor name. This will help
+// save keystrokes, as well as reduce typos & copy paste errors.
+#define CENTAUR_SENSOR_STRING_HELPER(sensor_name, memc,centL,cent,ppL,pp) SENSOR_STRING(sensor_name##memc##centL##cent##ppL##pp)
+#define CENTAUR_SENSOR_STRING(sensor_name,memc,cent,pp) CENTAUR_SENSOR_STRING_HELPER(sensor_name, memc,C,cent,P,pp)
+
+// This will create a set of 12 sensor entries into the sensor list table.
+// (one for each core...) The base name of the sensor enum must be passed
+// and this macro will take care of the paste & stringify operations.
+#define SENS_CORE_ENTRY_SET(sensor_name, units, type, location, number, frequency, scaleFactor) \
+ [SENSOR_W_NUM(sensor_name,0)] = {.name = SENSOR_STRING(sensor_name ## 1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,1)] = {.name = SENSOR_STRING(sensor_name ## 2), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,2)] = {.name = SENSOR_STRING(sensor_name ## 3), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,3)] = {.name = SENSOR_STRING(sensor_name ## 4), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,4)] = {.name = SENSOR_STRING(sensor_name ## 5), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,5)] = {.name = SENSOR_STRING(sensor_name ## 6), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,6)] = {.name = SENSOR_STRING(sensor_name ## 9), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,7)] = {.name = SENSOR_STRING(sensor_name ## 10), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,8)] = {.name = SENSOR_STRING(sensor_name ## 11), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,9)] = {.name = SENSOR_STRING(sensor_name ## 12), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,10)] = {.name = SENSOR_STRING(sensor_name ## 13), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,11)] = {.name = SENSOR_STRING(sensor_name ## 14), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}
+
+// This will create a set of 8 sensor entries into the sensor list table.
+// (one for each memc...) The base name of the sensor enum must be passed
+// and this macro will take care of the paste & stringify operations.
+#define SENS_MEMC_ENTRY_SET(sensor_name, units, type, location, number, frequency, scaleFactor) \
+ [SENSOR_W_NUM(sensor_name,0)] = {.name = SENSOR_STRING(sensor_name ## 0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,1)] = {.name = SENSOR_STRING(sensor_name ## 1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,2)] = {.name = SENSOR_STRING(sensor_name ## 2), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,3)] = {.name = SENSOR_STRING(sensor_name ## 3), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,4)] = {.name = SENSOR_STRING(sensor_name ## 4), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,5)] = {.name = SENSOR_STRING(sensor_name ## 5), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,6)] = {.name = SENSOR_STRING(sensor_name ## 6), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_NUM(sensor_name,7)] = {.name = SENSOR_STRING(sensor_name ## 7), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}
+
+
+// This will create a set of 16 sensor entries into the sensor list table.
+// (one for each centaur...) The base name of the sensor enum must be passed
+// and this macro will take care of the paste & stringify operations.
+#define SEN_CENTR_ENTRY_SET(sensor_name, units, type, location, number, frequency, scaleFactor) \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,0,0,0)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,0,0,0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,0,0,1)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,0,0,1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,1,0,0)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,1,0,0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,1,0,1)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,1,0,1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,2,0,0)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,2,0,0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,2,0,1)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,2,0,1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,3,0,0)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,3,0,0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,3,0,1)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,3,0,1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,4,0,0)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,4,0,0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,4,0,1)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,4,0,1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,5,0,0)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,5,0,0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,5,0,1)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,5,0,1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,6,0,0)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,6,0,0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,6,0,1)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,6,0,1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,7,0,0)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,7,0,0), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}, \
+ [SENSOR_W_CENTAUR_NUM(sensor_name,7,0,1)] = {.name = CENTAUR_SENSOR_STRING(sensor_name,7,0,1), \
+ .sensor = { units, type, location, number, frequency, scaleFactor },}
+
+
+// This table takes care of the ordering of the sensors (by GSID) and all parameters needed for AMEC or AMESTER. The order
+// that is in the table below doesn't matter because we use designated initializers.
+// If anything more than the barebones sensor_t is need, an applet will need to be called in order to gather that data.
+// For refernce:
+// AMEFP(1, 3); // 1000:1 scale factor
+// AMEFP(1, 0); // 1:1 scale factor
+// AMEFP(1,-1); // 1:0.1 scale factor
+// AMEFP(1,-3); // 1:0.001 scale factor
+//
+const sensor_info_t G_sensor_info[] =
+{
+ /* ==FirmwareSensors== NameString Units Type Location Number Freq ScaleFactor */
+ SENSOR_INFO_T_ENTRY( AMEintdur, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( AMESSdur0, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( AMESSdur1, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( AMESSdur2, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( AMESSdur3, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( AMESSdur4, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( AMESSdur5, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( AMESSdur6, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( AMESSdur7, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PROBE250US0, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PROBE250US1, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PROBE250US2, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PROBE250US3, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PROBE250US4, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PROBE250US5, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PROBE250US6, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PROBE250US7, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( GPEtickdur0, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( GPEtickdur1, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( RTLtickdur, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+
+ /* ==SystemSensors== NameString Units Type Location Number Freq ScaleFactor */
+ SENSOR_INFO_T_ENTRY( TEMPAMBIENT, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_SYS, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( ALTITUDE, "m\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_SYS, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PWR250US, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_SYS, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @at016c
+ SENSOR_INFO_T_ENTRY( PWR250USFAN, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_SYS, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @at016c
+ SENSOR_INFO_T_ENTRY( PWR250USIO, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_SYS, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @at016c
+ SENSOR_INFO_T_ENTRY( PWR250USSTORE, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_SYS, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @at016c
+ SENSOR_INFO_T_ENTRY( PWR250USGPU, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_SYS, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( FANSPEEDAVG, "RPM\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_SYS, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+
+ /* ==ChipSensors== NameString Units Type Location Number Freq ScaleFactor */
+ SENSOR_INFO_T_ENTRY( TODclock0, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_ALL, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 16, 0) ), // @mw586
+ SENSOR_INFO_T_ENTRY( TODclock1, "sec\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_ALL, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1048576,-6) ), // @mw586
+ SENSOR_INFO_T_ENTRY( TODclock2, "day\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_ALL, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 795364,-6) ), // @mw586
+
+ /* ==ProcSensors== NameString Units Type Location Number Freq ScaleFactor */
+ SENSOR_INFO_T_ENTRY( FREQA2MSP0, "MHz\0", AMEC_SENSOR_TYPE_FREQ, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( IPS2MSP0, "MIP\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @mw584
+ SENSOR_INFO_T_ENTRY( MEMSP2MSP0, "%\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( PWR250USP0, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ), // @at016c
+ SENSOR_INFO_T_ENTRY( PWR250USVDD0, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ), // @at016c
+ SENSOR_INFO_T_ENTRY( CUR250USVDD0, "A\0", AMEC_SENSOR_TYPE_CURRENT, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1,-2) ), // @mw586
+ SENSOR_INFO_T_ENTRY( PWR250USVCS0, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ), // @at016c
+ SENSOR_INFO_T_ENTRY( PWR250USMEM0, "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ), // @at016c
+ SENSOR_INFO_T_ENTRY( SLEEPCNT2MSP0, "#\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( WINKCNT2MSP0, "#\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( SP250USP0, "%\0", AMEC_SENSOR_TYPE_FREQ, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( TEMP2MSP0, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( TEMP2MSP0PEAK, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( UTIL2MSP0, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1,-2) ),
+ SENSOR_INFO_T_ENTRY( VRFAN250USPROC, "pin\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_VRM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( VRHOT250USPROC, "pin\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_VRM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+
+ /* ==ReguSensors== NameString Units Type Location Number Freq ScaleFactor */
+ SENSOR_INFO_T_ENTRY( UVOLT250USP0V0, "mV\0", AMEC_SENSOR_TYPE_VOLTAGE, AMEC_SENSOR_LOC_VRM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, -1) ), //@cl003
+ SENSOR_INFO_T_ENTRY( UVOLT250USP0V1, "mV\0", AMEC_SENSOR_TYPE_VOLTAGE, AMEC_SENSOR_LOC_VRM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, -1) ), //@cl003
+ SENSOR_INFO_T_ENTRY( VOLT250USP0V0, "mV\0", AMEC_SENSOR_TYPE_VOLTAGE, AMEC_SENSOR_LOC_VRM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, -1) ), //@cl003
+ SENSOR_INFO_T_ENTRY( VOLT250USP0V1, "mV\0", AMEC_SENSOR_TYPE_VOLTAGE, AMEC_SENSOR_LOC_VRM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, -1) ), //@cl003
+
+ /* ==CoreSensors== NameString Units Type Location Number Freq ScaleFactor */
+// SENS_CORE_ENTRY_SET( CPM2MSP0C , "bit\0", AMEC_SENSOR_TYPE_CPM, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), //CPM - Commented out as requested by Malcolm
+ SENS_CORE_ENTRY_SET( FREQ250USP0C , "MHz\0", AMEC_SENSOR_TYPE_FREQ, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENS_CORE_ENTRY_SET( FREQA2MSP0C , "MHz\0", AMEC_SENSOR_TYPE_FREQ, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @mw584
+ SENS_CORE_ENTRY_SET( IPS2MSP0C , "MIP\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @mw584
+ SENS_CORE_ENTRY_SET( NOTBZE2MSP0C , "cyc\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @mw682
+ SENS_CORE_ENTRY_SET( NOTFIN2MSP0C , "cyc\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ), // @mw682
+ SENS_CORE_ENTRY_SET( SPURR2MSP0C , "%\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENS_CORE_ENTRY_SET( TEMP2MSP0C , "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENS_CORE_ENTRY_SET( UTIL2MSP0C , "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1,-2) ),
+ SENS_CORE_ENTRY_SET( NUTIL3SP0C , "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_3S_IN_HZ, AMEFP( 1,-2) ),
+ SENS_CORE_ENTRY_SET( MSTL2MSP0C , "cpi\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENS_CORE_ENTRY_SET( CMT2MSP0C , "%\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENS_CORE_ENTRY_SET( CMBW2MSP0C , "GBs\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 128, -5) ), // @mw671
+ SENS_CORE_ENTRY_SET( PPICP0C , "%\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENS_CORE_ENTRY_SET( PWRPX250USP0C , "W\0", AMEC_SENSOR_TYPE_POWER, AMEC_SENSOR_LOC_CORE, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+
+ /* ==MemSensors== NameString Units Type Location Number Freq ScaleFactor */
+ SENSOR_INFO_T_ENTRY( VRFAN250USMEM, "pin\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_VRM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( VRHOT250USMEM, "pin\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_VRM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENS_MEMC_ENTRY_SET( MRD2MSP0M, "GBs\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 128, -5) ), // @mw671
+ SENS_MEMC_ENTRY_SET( MWR2MSP0M, "GBs\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 128, -5) ), // @mw671
+ SENS_MEMC_ENTRY_SET( MIRC2MSP0M, "eps\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENS_MEMC_ENTRY_SET( MLP2P0M, "eps\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENS_MEMC_ENTRY_SET( TEMPDIMMAXP0M, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+ SENS_MEMC_ENTRY_SET( LOCDIMMAXP0M, "loc\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 1, 0) ),
+
+ /* ==CentaurSensors== NameString Units Type Location Number Freq ScaleFactor */
+ SEN_CENTR_ENTRY_SET( MAC2MSP0M, "rps\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SEN_CENTR_ENTRY_SET( MPU2MSP0M, "rps\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SEN_CENTR_ENTRY_SET( MIRB2MSP0M, "eps\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SEN_CENTR_ENTRY_SET( MIRL2MSP0M, "eps\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SEN_CENTR_ENTRY_SET( MIRM2MSP0M, "eps\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SEN_CENTR_ENTRY_SET( MIRH2MSP0M, "eps\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SEN_CENTR_ENTRY_SET( MTS2MSP0M, "cnt\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SEN_CENTR_ENTRY_SET( MEMSP2MSPM, "%\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SEN_CENTR_ENTRY_SET( M4RD2MSP0M, "GBs\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 128, -5) ), // @mw671
+ SEN_CENTR_ENTRY_SET( M4WR2MSP0M, "GBs\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP( 128, -5) ), // @mw671
+
+
+ /* ==MemSummarySensors== NameString Units Type Location Number Freq ScaleFactor */
+ SENSOR_INFO_T_ENTRY( TEMP2MSCENT, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( TEMP2MSDIMM, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( MEMSP2MS, "%\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+
+ // @ly001a - start
+ /* ==PartSummarySensors== NameString Units Type Location Number Freq ScaleFactor */
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG000, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG001, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG002, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG003, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG004, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG005, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG006, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG007, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG008, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG009, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG010, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG011, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384),
+ // @ly001a - end
+};
+
+// Cause a compile error if we don't have all the sensors in the enum in the initialization list.
+STATIC_ASSERT( (NUMBER_OF_SENSORS_IN_LIST != (sizeof(G_sensor_info)/sizeof(sensor_info_t))) );
+STATIC_ASSERT( (MAX_AMEC_SENSORS < (sizeof(G_sensor_info)/sizeof(sensor_info_t))) );
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
diff --git a/src/occ/sensor/sensor_service_codes.h b/src/occ/sensor/sensor_service_codes.h
new file mode 100755
index 0000000..baed523
--- /dev/null
+++ b/src/occ/sensor/sensor_service_codes.h
@@ -0,0 +1,63 @@
+/******************************************************************************
+// @file sensor_service_codes.h
+// @brief Error codes for sensor component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _sensor_service_codes_h sensor_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * pbavari 08/16/2011 Created
+ * @th005 thallet 11/23/2011 Sensor Initialization Changes
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _SENSOR_SERVICE_CODES_H_
+#define _SENSOR_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum occSensorModuleId
+{
+ SENSOR_QUERY_LIST = SNSR_COMP_ID | 0x00,
+ SENSOR_INITIALIZE = SNSR_COMP_ID | 0x01,
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _SENSOR_SERVICE_CODES_H_ */
diff --git a/src/occ/sensor/sensor_table.c b/src/occ/sensor/sensor_table.c
new file mode 100755
index 0000000..84b6536
--- /dev/null
+++ b/src/occ/sensor/sensor_table.c
@@ -0,0 +1,530 @@
+/******************************************************************************
+// @file sensor_table.c
+// @brief OCC sensor pointer tables
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensor_table.c SENSOR_TABLE.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th005 thallet 11/23/2011 Created
+ * @th00a thallet 02/03/2012 Worst case FW timings in AMEC Sensors
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @ly001 853751 lychen 09/17/2012 Support DPS algorithm
+ * @th026 865074 thallet 12/21/2012 Updated Centaur sensors
+ * @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @gs026 915840 gjsilva 02/13/2014 Support for Nvidia GPU power measurement
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ * @mw682 933716 mware 07/28/2014 Renamed MCPIFD to be NOTBZE and MCPIFI to be NOTFIN.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <sensor.h> // sensor structure and other defines
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h> // For size_t needed by memset
+#include <amec_sys.h> // For pointers to amec_sys_t structures
+#include <dcom.h> // For mini-sensor pointers
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern amec_sys_t g_amec_sys;
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+// Will create an entry in the G_amec_sensor_list with a pointer at the sensor
+// index (gsid) passed in by "sensor"
+#define SENSOR_PTR(sensor,ptr) [sensor] = ptr
+
+// Will paste number onto enum 'sensor base name'
+#define SENSOR_W_NUM(sensor,num) sensor##num
+
+// This will paste a number onto a sensor name base to create the full enum
+// representation of the sensor name
+#define SENSOR_W_CENTAUR_NUM_HELPER(sensor_name, memc,centL,cent,ppL,pp) sensor_name##memc##centL##cent##ppL##pp
+#define SENSOR_W_CENTAUR_NUM(sensor_name, memc,cent,pp) SENSOR_W_CENTAUR_NUM_HELPER(sensor_name,memc,C,cent,P,pp)
+
+// Will define a set of "core sensor pointers" by passing in base sensor name
+// and ptr to [0] entry of array of 12 core sensors
+#define CORE_SENSOR_PTRS(sensor,ptrbase,ptrmember) \
+ [SENSOR_W_NUM(sensor, 0)] = ptrbase[ 0].ptrmember, \
+ [SENSOR_W_NUM(sensor, 1)] = ptrbase[ 1].ptrmember, \
+ [SENSOR_W_NUM(sensor, 2)] = ptrbase[ 2].ptrmember, \
+ [SENSOR_W_NUM(sensor, 3)] = ptrbase[ 3].ptrmember, \
+ [SENSOR_W_NUM(sensor, 4)] = ptrbase[ 4].ptrmember, \
+ [SENSOR_W_NUM(sensor, 5)] = ptrbase[ 5].ptrmember, \
+ [SENSOR_W_NUM(sensor, 6)] = ptrbase[ 6].ptrmember, \
+ [SENSOR_W_NUM(sensor, 7)] = ptrbase[ 7].ptrmember, \
+ [SENSOR_W_NUM(sensor, 8)] = ptrbase[ 8].ptrmember, \
+ [SENSOR_W_NUM(sensor, 9)] = ptrbase[ 9].ptrmember, \
+ [SENSOR_W_NUM(sensor,10)] = ptrbase[10].ptrmember, \
+ [SENSOR_W_NUM(sensor,11)] = ptrbase[11].ptrmember
+
+// Will define a set of "memory controller sensor pointers" by passing in
+// base sensor nameand ptr to [0] entry of array of 8 memcontroller sensors
+#define MEMCONTROL_SENSOR_PTRS(sensor,ptrbase,ptrmember) \
+ [SENSOR_W_NUM(sensor, 0)] = ptrbase[0].ptrmember, \
+ [SENSOR_W_NUM(sensor, 1)] = ptrbase[1].ptrmember, \
+ [SENSOR_W_NUM(sensor, 2)] = ptrbase[2].ptrmember, \
+ [SENSOR_W_NUM(sensor, 3)] = ptrbase[3].ptrmember, \
+ [SENSOR_W_NUM(sensor, 4)] = ptrbase[4].ptrmember, \
+ [SENSOR_W_NUM(sensor, 5)] = ptrbase[5].ptrmember, \
+ [SENSOR_W_NUM(sensor, 6)] = ptrbase[6].ptrmember, \
+ [SENSOR_W_NUM(sensor, 7)] = ptrbase[7].ptrmember
+
+// Will define a set of "centaur_port_pair sensor pointers" by passing in
+// base sensor nameand ptr to [0] entry of array of 16 memcontroller sensors
+#define PORTPAIR_SENSOR_PTRS(sensor,ptrbase,ptrmember,ptrsnsr) \
+ [SENSOR_W_CENTAUR_NUM(sensor, 0, 0, 0)] = ptrbase[0].ptrmember[0].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 0, 0, 1)] = ptrbase[0].ptrmember[1].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 1, 0, 0)] = ptrbase[1].ptrmember[0].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 1, 0, 1)] = ptrbase[1].ptrmember[1].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 2, 0, 0)] = ptrbase[2].ptrmember[0].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 2, 0, 1)] = ptrbase[2].ptrmember[1].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 3, 0, 0)] = ptrbase[3].ptrmember[0].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 3, 0, 1)] = ptrbase[3].ptrmember[1].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 4, 0, 0)] = ptrbase[4].ptrmember[0].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 4, 0, 1)] = ptrbase[4].ptrmember[1].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 5, 0, 0)] = ptrbase[5].ptrmember[0].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 5, 0, 1)] = ptrbase[5].ptrmember[1].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 6, 0, 0)] = ptrbase[6].ptrmember[0].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 6, 0, 1)] = ptrbase[6].ptrmember[1].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 7, 0, 0)] = ptrbase[7].ptrmember[0].ptrsnsr, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 7, 0, 1)] = ptrbase[7].ptrmember[1].ptrsnsr
+
+
+// Will create an entry in the G_amec_mini_sensor_list with a pointer at
+// the sensor index (gsid) passed in by "sensor"
+#define MINI_SENSOR_PTR(sensor,ptr) [sensor] = ptr
+
+// Will define a set of "core mini-sensor pointers" by passing in base
+// sensor name and ptr to [0] entry of array of core sensors
+#define CORE_MINI_SENSOR_PTRS(sensor,ptr) \
+ [SENSOR_W_NUM(sensor, 0)] = ptr[ 0], \
+ [SENSOR_W_NUM(sensor, 1)] = ptr[ 1], \
+ [SENSOR_W_NUM(sensor, 2)] = ptr[ 2], \
+ [SENSOR_W_NUM(sensor, 3)] = ptr[ 3], \
+ [SENSOR_W_NUM(sensor, 4)] = ptr[ 4], \
+ [SENSOR_W_NUM(sensor, 5)] = ptr[ 5], \
+ [SENSOR_W_NUM(sensor, 6)] = ptr[ 6], \
+ [SENSOR_W_NUM(sensor, 7)] = ptr[ 7], \
+ [SENSOR_W_NUM(sensor, 8)] = ptr[ 8], \
+ [SENSOR_W_NUM(sensor, 9)] = ptr[ 9], \
+ [SENSOR_W_NUM(sensor,10)] = ptr[10], \
+ [SENSOR_W_NUM(sensor,11)] = ptr[11]
+
+// Will define a set of "core mini-sensor pointers" as NULL, since not
+// every sensor must have a mini-sensor.
+#define CORE_MINI_SENSOR_PTRS_NULL(sensor) \
+ [SENSOR_W_NUM(sensor, 0)] = NULL, \
+ [SENSOR_W_NUM(sensor, 1)] = NULL, \
+ [SENSOR_W_NUM(sensor, 2)] = NULL, \
+ [SENSOR_W_NUM(sensor, 3)] = NULL, \
+ [SENSOR_W_NUM(sensor, 4)] = NULL, \
+ [SENSOR_W_NUM(sensor, 5)] = NULL, \
+ [SENSOR_W_NUM(sensor, 6)] = NULL, \
+ [SENSOR_W_NUM(sensor, 7)] = NULL, \
+ [SENSOR_W_NUM(sensor, 8)] = NULL, \
+ [SENSOR_W_NUM(sensor, 9)] = NULL, \
+ [SENSOR_W_NUM(sensor,10)] = NULL, \
+ [SENSOR_W_NUM(sensor,11)] = NULL
+
+// Will define a set of "memory controller mini sensor ptrs" by passing in
+// base sensor nameand ptr to [0] entry of array of 8 memcontroller sensors
+#define MEMCONTROL_MINI_SENSOR_PTRS(sensor,ptr) \
+ [SENSOR_W_NUM(sensor, 0)] = ptr[ 0], \
+ [SENSOR_W_NUM(sensor, 1)] = ptr[ 1], \
+ [SENSOR_W_NUM(sensor, 2)] = ptr[ 2], \
+ [SENSOR_W_NUM(sensor, 3)] = ptr[ 3], \
+ [SENSOR_W_NUM(sensor, 4)] = ptr[ 4], \
+ [SENSOR_W_NUM(sensor, 5)] = ptr[ 5], \
+ [SENSOR_W_NUM(sensor, 6)] = ptr[ 6], \
+ [SENSOR_W_NUM(sensor, 7)] = ptr[ 7]
+
+// Will define a set of "memc mini-sensor pointers" as NULL, since not
+// every sensor must have a mini-sensor.
+#define MEMCONTROL_MINI_SENSOR_PTRS_NULL(sensor) \
+ [SENSOR_W_NUM(sensor, 0)] = NULL, \
+ [SENSOR_W_NUM(sensor, 1)] = NULL, \
+ [SENSOR_W_NUM(sensor, 2)] = NULL, \
+ [SENSOR_W_NUM(sensor, 3)] = NULL, \
+ [SENSOR_W_NUM(sensor, 4)] = NULL, \
+ [SENSOR_W_NUM(sensor, 5)] = NULL, \
+ [SENSOR_W_NUM(sensor, 6)] = NULL, \
+ [SENSOR_W_NUM(sensor, 7)] = NULL
+
+// Will define a set of "memory controller mini sensor ptrs" by passing in
+// base sensor nameand ptr to [0] entry of array of 8 memcontroller sensors
+#define PORTPAIR_MINI_SENSOR_PTRS(sensor,ptr) \
+ [SENSOR_W_CENTAUR_NUM(sensor, 0, 0, 0)] = ptr[ 0], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 0, 0, 1)] = ptr[ 1], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 1, 0, 0)] = ptr[ 2], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 1, 0, 1)] = ptr[ 3], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 2, 0, 0)] = ptr[ 4], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 2, 0, 1)] = ptr[ 5], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 3, 0, 0)] = ptr[ 6], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 3, 0, 1)] = ptr[ 7], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 4, 0, 0)] = ptr[ 8], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 4, 0, 1)] = ptr[ 9], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 5, 0, 0)] = ptr[10], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 5, 0, 1)] = ptr[11], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 6, 0, 0)] = ptr[12], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 6, 0, 1)] = ptr[13], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 7, 0, 0)] = ptr[14], \
+ [SENSOR_W_CENTAUR_NUM(sensor, 7, 0, 1)] = ptr[15]
+
+// Will define a set of "memc mini-sensor pointers" as NULL, since not
+// every sensor must have a mini-sensor.
+#define PORTPAIR_MINI_SENSOR_PTRS_NULL(sensor) \
+ [SENSOR_W_CENTAUR_NUM(sensor, 0, 0, 0)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 0, 0, 1)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 1, 0, 0)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 1, 0, 1)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 2, 0, 0)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 2, 0, 1)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 3, 0, 0)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 3, 0, 1)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 4, 0, 0)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 4, 0, 1)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 5, 0, 0)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 5, 0, 1)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 6, 0, 0)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 6, 0, 1)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 7, 0, 0)] = NULL, \
+ [SENSOR_W_CENTAUR_NUM(sensor, 7, 0, 1)] = NULL
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//****************************************************************************
+// Sensor Pointer Table
+// ----------------------
+// - Indexed by GSID
+// - Resident in SRAM
+// - Must contain every sensor in enum, or STATIC_ASSERT will give compile
+// failure.
+//****************************************************************************
+const sensor_ptr_t G_amec_sensor_list[] =
+{
+ // ------------------------------------------------------
+ // Code/Firmware Sensors
+ // ------------------------------------------------------
+ SENSOR_PTR( AMEintdur, &g_amec_sys.fw.ameintdur),
+ SENSOR_PTR( AMESSdur0, &g_amec_sys.fw.amessdur[0]),
+ SENSOR_PTR( AMESSdur1, &g_amec_sys.fw.amessdur[1]),
+ SENSOR_PTR( AMESSdur2, &g_amec_sys.fw.amessdur[2]),
+ SENSOR_PTR( AMESSdur3, &g_amec_sys.fw.amessdur[3]),
+ SENSOR_PTR( AMESSdur4, &g_amec_sys.fw.amessdur[4]),
+ SENSOR_PTR( AMESSdur5, &g_amec_sys.fw.amessdur[5]),
+ SENSOR_PTR( AMESSdur6, &g_amec_sys.fw.amessdur[6]),
+ SENSOR_PTR( AMESSdur7, &g_amec_sys.fw.amessdur[7]),
+ SENSOR_PTR( PROBE250US0, &g_amec_sys.fw.probe250us[0]),
+ SENSOR_PTR( PROBE250US1, &g_amec_sys.fw.probe250us[1]),
+ SENSOR_PTR( PROBE250US2, &g_amec_sys.fw.probe250us[2]),
+ SENSOR_PTR( PROBE250US3, &g_amec_sys.fw.probe250us[3]),
+ SENSOR_PTR( PROBE250US4, &g_amec_sys.fw.probe250us[4]),
+ SENSOR_PTR( PROBE250US5, &g_amec_sys.fw.probe250us[5]),
+ SENSOR_PTR( PROBE250US6, &g_amec_sys.fw.probe250us[6]),
+ SENSOR_PTR( PROBE250US7, &g_amec_sys.fw.probe250us[7]),
+
+ SENSOR_PTR( GPEtickdur0, &g_amec_sys.fw.gpetickdur[0]),
+ SENSOR_PTR( GPEtickdur1, &g_amec_sys.fw.gpetickdur[1]),
+ SENSOR_PTR( RTLtickdur, &g_amec_sys.fw.prcdupdatedur),
+
+ // ------------------------------------------------------
+ // System Sensors
+ // ------------------------------------------------------
+ SENSOR_PTR( TEMPAMBIENT, &g_amec_sys.sys.tempambient),
+ SENSOR_PTR( ALTITUDE, &g_amec_sys.sys.altitude),
+ SENSOR_PTR( PWR250US, &g_amec_sys.sys.pwr250us),
+ SENSOR_PTR( PWR250USFAN, &g_amec_sys.fan.pwr250usfan),
+ SENSOR_PTR( PWR250USIO, &g_amec_sys.io.pwr250usio),
+ SENSOR_PTR( PWR250USSTORE, &g_amec_sys.storage.pwr250usstore),
+ SENSOR_PTR( PWR250USGPU, &g_amec_sys.sys.pwr250usgpu),
+ SENSOR_PTR( FANSPEEDAVG, &g_amec_sys.fan.fanspeedavg),
+
+ // ------------------------------------------------------
+ // Chip Sensors
+ // ------------------------------------------------------
+ SENSOR_PTR( TODclock0, &g_amec_sys.sys.todclock0 ),
+ SENSOR_PTR( TODclock1, &g_amec_sys.sys.todclock1 ),
+ SENSOR_PTR( TODclock2, &g_amec_sys.sys.todclock2 ),
+
+ // ------------------------------------------------------
+ // Processor Sensors
+ // ------------------------------------------------------
+ SENSOR_PTR( FREQA2MSP0, &g_amec_sys.proc[0].freqa2ms), // @mw624
+ SENSOR_PTR( IPS2MSP0, &g_amec_sys.proc[0].ips2ms),
+ SENSOR_PTR( MEMSP2MSP0, &g_amec_sys.proc[0].memsp2ms),
+ SENSOR_PTR( PWR250USP0, &g_amec_sys.proc[0].pwr250us),
+ SENSOR_PTR( PWR250USVDD0, &g_amec_sys.proc[0].pwr250usvdd),
+ SENSOR_PTR( CUR250USVDD0, &g_amec_sys.proc[0].cur250usvdd),
+ SENSOR_PTR( PWR250USVCS0, &g_amec_sys.proc[0].pwr250usvcs),
+ SENSOR_PTR( PWR250USMEM0, &g_amec_sys.proc[0].pwr250usmem), //TODO: should this be P0 or just 0
+ SENSOR_PTR( SLEEPCNT2MSP0, &g_amec_sys.proc[0].sleepcnt2ms),
+ SENSOR_PTR( WINKCNT2MSP0, &g_amec_sys.proc[0].winkcnt2ms),
+ SENSOR_PTR( SP250USP0, &g_amec_sys.proc[0].sp250us),
+ SENSOR_PTR( TEMP2MSP0, &g_amec_sys.proc[0].temp2ms),
+ SENSOR_PTR( TEMP2MSP0PEAK, &g_amec_sys.proc[0].temp2mspeak),
+ SENSOR_PTR( UTIL2MSP0, &g_amec_sys.proc[0].util2ms),
+ SENSOR_PTR( VRFAN250USPROC, &g_amec_sys.sys.vrfan250usproc),
+ SENSOR_PTR( VRHOT250USPROC, &g_amec_sys.sys.vrhot250usproc),
+
+ // ------------------------------------------------------
+ // Core Sensors (12 of each)
+ // ------------------------------------------------------
+// CORE_SENSOR_PTRS( CPM2MSP0C , &g_amec_sys.proc[0].core, cpm2ms), //CPM - Commented out as requested by Malcolm
+ CORE_SENSOR_PTRS( FREQ250USP0C , &g_amec_sys.proc[0].core, freq250us),
+ CORE_SENSOR_PTRS( FREQA2MSP0C , &g_amec_sys.proc[0].core, freqa2ms), // @mw624
+ CORE_SENSOR_PTRS( IPS2MSP0C , &g_amec_sys.proc[0].core, ips2ms),
+ CORE_SENSOR_PTRS( NOTBZE2MSP0C , &g_amec_sys.proc[0].core, mcpifd2ms),
+ CORE_SENSOR_PTRS( NOTFIN2MSP0C , &g_amec_sys.proc[0].core, mcpifi2ms),
+ CORE_SENSOR_PTRS( SPURR2MSP0C , &g_amec_sys.proc[0].core, spurr2ms),
+ CORE_SENSOR_PTRS( TEMP2MSP0C , &g_amec_sys.proc[0].core, temp2ms),
+ CORE_SENSOR_PTRS( UTIL2MSP0C , &g_amec_sys.proc[0].core, util2ms),
+ CORE_SENSOR_PTRS( NUTIL3SP0C , &g_amec_sys.proc[0].core, nutil3s),
+ CORE_SENSOR_PTRS( MSTL2MSP0C , &g_amec_sys.proc[0].core, mstl2ms),
+ CORE_SENSOR_PTRS( CMT2MSP0C , &g_amec_sys.proc[0].core, cmt2ms),
+ CORE_SENSOR_PTRS( CMBW2MSP0C , &g_amec_sys.proc[0].core, cmbw2ms),
+ CORE_SENSOR_PTRS( PPICP0C , &g_amec_sys.proc[0].core, ppic),
+ CORE_SENSOR_PTRS( PWRPX250USP0C , &g_amec_sys.proc[0].core, pwrpx250us),
+
+ // ------------------------------------------------------
+ // Memory Sensors
+ // ------------------------------------------------------
+ SENSOR_PTR( VRFAN250USMEM, &g_amec_sys.sys.vrfan250usmem),
+ SENSOR_PTR( VRHOT250USMEM, &g_amec_sys.sys.vrhot250usmem),
+
+ MEMCONTROL_SENSOR_PTRS(MRD2MSP0M, &g_amec_sys.proc[0].memctl, mrd2ms),
+ MEMCONTROL_SENSOR_PTRS(MWR2MSP0M, &g_amec_sys.proc[0].memctl, mwr2ms),
+ MEMCONTROL_SENSOR_PTRS(MIRC2MSP0M, &g_amec_sys.proc[0].memctl, centaur.mirc2ms),
+ MEMCONTROL_SENSOR_PTRS(MLP2P0M, &g_amec_sys.proc[0].memctl, centaur.mlp2ms),
+ MEMCONTROL_SENSOR_PTRS(TEMPDIMMAXP0M, &g_amec_sys.proc[0].memctl, centaur.tempdimmax),
+ MEMCONTROL_SENSOR_PTRS(LOCDIMMAXP0M, &g_amec_sys.proc[0].memctl, centaur.locdimmax),
+
+ PORTPAIR_SENSOR_PTRS(MAC2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, mac2ms),
+ PORTPAIR_SENSOR_PTRS(MPU2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, mpu2ms),
+ PORTPAIR_SENSOR_PTRS(MIRB2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, mirb2ms),
+ PORTPAIR_SENSOR_PTRS(MIRL2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, mirl2ms),
+ PORTPAIR_SENSOR_PTRS(MIRM2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, mirm2ms),
+ PORTPAIR_SENSOR_PTRS(MIRH2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, mirh2ms),
+ PORTPAIR_SENSOR_PTRS(MTS2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, mts2ms),
+ PORTPAIR_SENSOR_PTRS(MEMSP2MSPM, &g_amec_sys.proc[0].memctl, centaur.portpair, memsp2ms),
+ PORTPAIR_SENSOR_PTRS(M4RD2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, m4rd2ms),
+ PORTPAIR_SENSOR_PTRS(M4WR2MSP0M, &g_amec_sys.proc[0].memctl, centaur.portpair, m4wr2ms),
+
+
+ SENSOR_PTR( TEMP2MSCENT, &g_amec_sys.proc[0].temp2mscent),
+ SENSOR_PTR( TEMP2MSDIMM, &g_amec_sys.proc[0].temp2msdimm),
+ SENSOR_PTR( MEMSP2MS, &g_amec_sys.proc[0].memsp2ms_tls),
+
+ // ------------------------------------------------------
+ // Regulator Sensors
+ // ------------------------------------------------------
+ SENSOR_PTR( UVOLT250USP0V0, &g_amec_sys.proc[0].vrm[0].uvolt250us),
+ SENSOR_PTR( UVOLT250USP0V1, &g_amec_sys.proc[0].vrm[1].uvolt250us),
+ SENSOR_PTR( VOLT250USP0V0, &g_amec_sys.proc[0].vrm[0].volt250us),
+ SENSOR_PTR( VOLT250USP0V1, &g_amec_sys.proc[0].vrm[1].volt250us),
+
+ // @ly001a - start
+ // ------------------------------------------------------
+ // Partition Sensors
+ // ------------------------------------------------------
+ SENSOR_PTR( UTIL2MSSLCG000, &g_amec_sys.part_config.part_list[0].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG001, &g_amec_sys.part_config.part_list[1].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG002, &g_amec_sys.part_config.part_list[2].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG003, &g_amec_sys.part_config.part_list[3].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG004, &g_amec_sys.part_config.part_list[4].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG005, &g_amec_sys.part_config.part_list[5].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG006, &g_amec_sys.part_config.part_list[6].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG007, &g_amec_sys.part_config.part_list[7].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG008, &g_amec_sys.part_config.part_list[8].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG009, &g_amec_sys.part_config.part_list[9].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG010, &g_amec_sys.part_config.part_list[10].util2msslack),
+ SENSOR_PTR( UTIL2MSSLCG011, &g_amec_sys.part_config.part_list[11].util2msslack),
+ // @ly001a - end
+
+};
+STATIC_ASSERT( (NUMBER_OF_SENSORS_IN_LIST != (sizeof(G_amec_sensor_list)/sizeof(sensor_ptr_t))) );
+STATIC_ASSERT( (MAX_AMEC_SENSORS < (sizeof(G_amec_sensor_list)/sizeof(sensor_ptr_t))) );
+
+
+//****************************************************************************
+// Mini-Sensor Pointer Table
+// ----------------------
+// - Indexed by GSID
+// - Resident in initSection of SRAM, and will be deleted after sensor init
+// - Must contain every sensor in enum, or STATIC_ASSERT will give compile
+// failure.
+// - Pointers to mini-sensors can be NULL, but they must still be in array.
+// - The reason why this is a separate table is so that we can put this
+// in the init section and reclaim ~1.5kB of space (# sensors * 4bytes)
+//****************************************************************************
+const minisensor_ptr_t G_amec_mini_sensor_list[] INIT_SECTION =
+{
+ // ------------------------------------------------------
+ // Code/Firmware Sensors
+ // ------------------------------------------------------
+ MINI_SENSOR_PTR( AMEintdur, NULL),
+ MINI_SENSOR_PTR( AMESSdur0, NULL),
+ MINI_SENSOR_PTR( AMESSdur1, NULL),
+ MINI_SENSOR_PTR( AMESSdur2, NULL),
+ MINI_SENSOR_PTR( AMESSdur3, NULL),
+ MINI_SENSOR_PTR( AMESSdur4, NULL),
+ MINI_SENSOR_PTR( AMESSdur5, NULL),
+ MINI_SENSOR_PTR( AMESSdur6, NULL),
+ MINI_SENSOR_PTR( AMESSdur7, NULL),
+ MINI_SENSOR_PTR( PROBE250US0, NULL),
+ MINI_SENSOR_PTR( PROBE250US1, NULL),
+ MINI_SENSOR_PTR( PROBE250US2, NULL),
+ MINI_SENSOR_PTR( PROBE250US3, NULL),
+ MINI_SENSOR_PTR( PROBE250US4, NULL),
+ MINI_SENSOR_PTR( PROBE250US5, NULL),
+ MINI_SENSOR_PTR( PROBE250US6, NULL),
+ MINI_SENSOR_PTR( PROBE250US7, NULL),
+ MINI_SENSOR_PTR( GPEtickdur0, NULL),
+ MINI_SENSOR_PTR( GPEtickdur1, NULL),
+ MINI_SENSOR_PTR( RTLtickdur, NULL),
+
+ // ------------------------------------------------------
+ // System Sensors
+ // ------------------------------------------------------
+ MINI_SENSOR_PTR( TEMPAMBIENT, NULL),
+ MINI_SENSOR_PTR( ALTITUDE, NULL),
+ MINI_SENSOR_PTR( PWR250US, NULL),
+ MINI_SENSOR_PTR( PWR250USFAN, NULL),
+ MINI_SENSOR_PTR( PWR250USIO, NULL),
+ MINI_SENSOR_PTR( PWR250USSTORE, NULL),
+ MINI_SENSOR_PTR( PWR250USGPU, NULL),
+ MINI_SENSOR_PTR( FANSPEEDAVG, NULL),
+
+ // ------------------------------------------------------
+ // Chip Sensors
+ // ------------------------------------------------------
+ MINI_SENSOR_PTR( TODclock0, &G_dcom_slv_outbox_tx.todclock[0]),
+ MINI_SENSOR_PTR( TODclock1, &G_dcom_slv_outbox_tx.todclock[1]),
+ MINI_SENSOR_PTR( TODclock2, &G_dcom_slv_outbox_tx.todclock[2]),
+
+ // ------------------------------------------------------
+ // Processor Sensors
+ // ------------------------------------------------------
+ MINI_SENSOR_PTR( FREQA2MSP0, &G_dcom_slv_outbox_tx.freqa2msp0), // @mw624
+ MINI_SENSOR_PTR( IPS2MSP0, &G_dcom_slv_outbox_tx.ips2msp0), // @jh005c
+ MINI_SENSOR_PTR( MEMSP2MSP0, NULL),
+ MINI_SENSOR_PTR( PWR250USP0, &G_dcom_slv_outbox_tx.pwr250usp0),
+ MINI_SENSOR_PTR( PWR250USVDD0, NULL),
+ MINI_SENSOR_PTR( CUR250USVDD0, NULL),
+ MINI_SENSOR_PTR( PWR250USVCS0, NULL),
+ MINI_SENSOR_PTR( PWR250USMEM0, &G_dcom_slv_outbox_tx.pwr250usmemp0), //TODO: should this be P0 or just 0
+ MINI_SENSOR_PTR( SLEEPCNT2MSP0, &G_dcom_slv_outbox_tx.sleepcnt2msp0),
+ MINI_SENSOR_PTR( WINKCNT2MSP0, &G_dcom_slv_outbox_tx.winkcnt2msp0),
+ MINI_SENSOR_PTR( SP250USP0, NULL),
+ MINI_SENSOR_PTR( TEMP2MSP0, &G_dcom_slv_outbox_tx.temp2msp0),
+ MINI_SENSOR_PTR( TEMP2MSP0PEAK, &G_dcom_slv_outbox_tx.temp2msp0peak),
+ MINI_SENSOR_PTR( UTIL2MSP0, &G_dcom_slv_outbox_tx.util2msp0), // @jh005c
+ MINI_SENSOR_PTR( VRFAN250USPROC, &G_dcom_slv_outbox_tx.vrfan250usproc),
+ MINI_SENSOR_PTR( VRHOT250USPROC, NULL),
+
+ // ------------------------------------------------------
+ // Core Sensors (12 of each)
+ // ------------------------------------------------------
+// CORE_MINI_SENSOR_PTRS_NULL( CPM2MSP0C ), //CPM - Commented out as requested by Malcolm
+ CORE_MINI_SENSOR_PTRS_NULL( FREQ250USP0C ),
+ CORE_MINI_SENSOR_PTRS_NULL( FREQA2MSP0C ), // @mw624
+ CORE_MINI_SENSOR_PTRS( IPS2MSP0C, &G_dcom_slv_outbox_tx.ips2msp0cy ),
+ CORE_MINI_SENSOR_PTRS( NOTBZE2MSP0C, &G_dcom_slv_outbox_tx.mcpifd2msp0cy ),
+ CORE_MINI_SENSOR_PTRS( NOTFIN2MSP0C, &G_dcom_slv_outbox_tx.mcpifi2msp0cy ),
+ CORE_MINI_SENSOR_PTRS_NULL( SPURR2MSP0C ),
+ CORE_MINI_SENSOR_PTRS_NULL( TEMP2MSP0C ),
+ CORE_MINI_SENSOR_PTRS( UTIL2MSP0C, &G_dcom_slv_outbox_tx.util2msp0cy ),
+ CORE_MINI_SENSOR_PTRS( NUTIL3SP0C, &G_dcom_slv_outbox_tx.nutil3sp0cy ),
+ CORE_MINI_SENSOR_PTRS_NULL( MSTL2MSP0C ),
+ CORE_MINI_SENSOR_PTRS_NULL( CMT2MSP0C ),
+ CORE_MINI_SENSOR_PTRS_NULL( CMBW2MSP0C ),
+ CORE_MINI_SENSOR_PTRS_NULL( PPICP0C ),
+ CORE_MINI_SENSOR_PTRS( PWRPX250USP0C, &G_dcom_slv_outbox_tx.pwrpx250usp0cy), //
+
+ // ------------------------------------------------------
+ // Memory Sensors
+ // ------------------------------------------------------
+ MINI_SENSOR_PTR( VRFAN250USMEM, &G_dcom_slv_outbox_tx.vrfan250usmem),
+ MINI_SENSOR_PTR( VRHOT250USMEM, NULL),
+
+ MEMCONTROL_MINI_SENSOR_PTRS(MRD2MSP0M, &G_dcom_slv_outbox_tx.mrd2msp0mx), //
+ MEMCONTROL_MINI_SENSOR_PTRS(MWR2MSP0M, &G_dcom_slv_outbox_tx.mwr2msp0mx), //
+ MEMCONTROL_MINI_SENSOR_PTRS_NULL(MIRC2MSP0M),
+ MEMCONTROL_MINI_SENSOR_PTRS_NULL(MLP2P0M),
+
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(MAC2MSP0M),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(MPU2MSP0M),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(MIRB2MSP0M),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(MIRL2MSP0M),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(MIRM2MSP0M),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(MIRH2MSP0M),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(MTS2MSP0M),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(MEMSP2MSPM),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(M4RD2MSP0M),
+ PORTPAIR_MINI_SENSOR_PTRS_NULL(M4WR2MSP0M),
+
+ MINI_SENSOR_PTR( TEMP2MSCENT, &G_dcom_slv_outbox_tx.temp2mscent), // @jh005c
+ MINI_SENSOR_PTR( TEMP2MSDIMM, &G_dcom_slv_outbox_tx.temp2msdimm), // @jh005c
+ MINI_SENSOR_PTR( MEMSP2MS, NULL),
+
+ // ------------------------------------------------------
+ // Regulator Sensors
+ // ------------------------------------------------------
+ MINI_SENSOR_PTR( UVOLT250USP0V0, NULL),
+ MINI_SENSOR_PTR( UVOLT250USP0V1, NULL),
+ MINI_SENSOR_PTR( VOLT250USP0V0, NULL),
+ MINI_SENSOR_PTR( VOLT250USP0V1, NULL),
+
+ // @ly001a - start
+ // ------------------------------------------------------
+ // Partition Sensors
+ // ------------------------------------------------------
+ MINI_SENSOR_PTR( UTIL2MSSLCG000, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG001, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG002, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG003, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG004, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG005, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG006, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG007, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG008, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG009, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG010, NULL),
+ MINI_SENSOR_PTR( UTIL2MSSLCG011, NULL),
+ // @ly001a - end
+};
+STATIC_ASSERT( (NUMBER_OF_SENSORS_IN_LIST != (sizeof(G_amec_mini_sensor_list)/sizeof(uint16_t *))) );
+STATIC_ASSERT( (MAX_AMEC_SENSORS < (sizeof(G_amec_mini_sensor_list)/sizeof(uint16_t *))) );
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
diff --git a/src/occ/ssx_app_cfg.h b/src/occ/ssx_app_cfg.h
new file mode 100755
index 0000000..60edc68
--- /dev/null
+++ b/src/occ/ssx_app_cfg.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+// @file ssx_app_cfg.h
+// @brief Common application configuration for OCC
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section ssx_app_cfg.h SSX_APP_CFG.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th043 892554 thallet 07/23/2013 Automatic Nominal/Active state change
+ * @gm010 901580 milesg 10/06/2013 Low Level FFDC support
+ * @sb002 908891 sbroyles 12/09/2013 FFDC updates
+ * @sb012 910394 sbroyles 01/10/2014 More FFDC updates
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef __SSX_APP_CFG_H__
+#define __SSX_APP_CFG_H__
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+// @sb012 These versions of SSX_PANIC are being changed so that they exactly
+// mirror each other and are exactly structured at 8 instructions only and
+// make only one branch to outside code.
+#ifndef __ASSEMBLER__
+#ifndef SSX_PANIC
+#define SSX_PANIC(code) \
+do { \
+ barrier(); \
+ asm volatile ("stw %r3, __occ_panic_save_r3@sda21(0)"); \
+ asm volatile ("mflr %r3"); \
+ asm volatile ("stw %r4, __occ_panic_save_r4@sda21(0)"); \
+ asm volatile ("lis %%r4, %0"::"i" (code >> 16)); \
+ asm volatile ("ori %%r4, %%r4, %0"::"i" (code & 0xffff)); \
+ asm volatile ("bl __ssx_checkpoint_panic_and_save_ffdc"); \
+ asm volatile ("trap"); \
+ asm volatile (".long %0" : : "i" (code)); \
+} while (0)
+#endif // SSX_PANIC
+#else /* __ASSEMBLER__ */
+#ifndef SSX_PANIC
+// This macro cannot be more than 8 instructions long, but it can be less than
+// 8.
+#define SSX_PANIC(code) _ssx_panic code
+ .macro _ssx_panic, code
+ stw %r3, __occ_panic_save_r3@sda21(0)
+ mflr %r3
+ stw %r4, __occ_panic_save_r4@sda21(0)
+ lis %r4, \code@h
+ ori %r4, %r4, \code@l
+ bl __ssx_checkpoint_panic_and_save_ffdc
+ trap
+ .long \code
+ .endm
+#endif // SSX_PANIC
+#endif /* __ASSEMBLER__ */
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define INIT_SEC_NM_STR "initSection"
+#define INIT_SECTION __attribute__ ((section (INIT_SEC_NM_STR)))
+
+#define SIMICS_ENVIRONMENT 0
+
+/// Since OCC Firmware desires time intervals longer than 7 seconds, we will
+/// change the interval to be a uint64_t instead of a uint32_t so we don't
+/// hit the overflow condition
+#define SSX_TIME_INTERVAL_TYPE uint64_t
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* __SSX_APP_CFG_H__ */
+
+
diff --git a/src/occ/state.c b/src/occ/state.c
new file mode 100755
index 0000000..0ecf339
--- /dev/null
+++ b/src/occ/state.c
@@ -0,0 +1,810 @@
+/******************************************************************************
+// @file state.c
+// @brief OCC States (including Reset)
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section state.c STATE.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th003 thallet 11/08/2011 New file
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th00d thallet 04/08/2012 Added SMGR function
+ * @th011 thallet 07/12/2012 Split Mode/State/Reset into sep files
+ * @th015 thallet 08/03/2012 Added RTL Flag setting
+ * @th022 thallet 10/03/2012 Changes to allow DCOM State/Mode setting
+ * @th036 881677 thallet 05/06/2013 Support for poll & reset_prep commands
+ * @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
+ * @th043 892554 thallet 07/23/2013 Automatic Nominal/Active state change
+ * @th046 894648 thallet 08/08/2013 Piggyback activeReady Fix on the coreq fix
+ * @ly009 895318 lychen 08/13/2013 OCC-Sapphire shared memory interface
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gm008 SW226989 milesg 09/30/2013 Sapphire initial support
+ * @rt001 903366 tapiar 10/23/2013 Require pcap config for master to go active
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @rt004 908817 tapiar 12/11/2013 remove workaround for pcap see @rt001
+ * @ly010 908832 lychen 12/09/2013 Sapphire update status for reset
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @sb002 908891 sbroyles 12/09/2013 Enable watchdog timers
+ * @gm025 915973 milesg 02/14/2014 Full support for sapphire (KVM) mode
+ * @sb055 911966 sbroyles 02/27/2014 Enable PBCS heartbeat
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @gm033 920448 milesg 03/26/2014 use getscom/putscom ffdc wrapper
+ * @gm034 920562 milesg 03/26/2014 more ffdc for pstate enablement failures
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <common_types.h>
+#include <centaur_data.h>
+#include "ssx_io.h"
+#include "trac.h"
+#include "rtls.h"
+#include "state.h"
+#include "dcom.h"
+#include "occ_service_codes.h"
+#include "proc_pstate.h"
+#include "cmdh_fsp_cmds_datacnfg.h"
+#include "cmdh_fsp.h"
+#include "proc_data.h" // @sb055
+#include "heartbeat.h" // @sb055
+#include "scom.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern proc_gpsm_dcm_sync_occfw_t G_proc_dcm_sync_state; //@gm006
+extern bool G_mem_monitoring_allowed;
+extern task_t G_task_table[TASK_END]; // Global task table
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// Maximum allowed value approx. 16.3 ms
+#define PCBS_HEARBEAT_TIME_US 16320 // @sb055
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Forward Declarations
+//*************************************************************************
+errlHndl_t SMGR_standby_to_observation();
+errlHndl_t SMGR_standby_to_active();
+errlHndl_t SMGR_observation_to_standby();
+errlHndl_t SMGR_observation_to_active();
+errlHndl_t SMGR_active_to_observation();
+errlHndl_t SMGR_active_to_standby();
+errlHndl_t SMGR_all_to_safe();
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// State that OCC is currently in
+OCC_STATE G_occ_internal_state = OCC_STATE_STANDBY;
+
+// State that OCC is requesting that TMGT put OCC into
+OCC_STATE G_occ_internal_req_state = OCC_STATE_NOCHANGE;
+
+// State that TMGT wants to put OCC into
+OCC_STATE G_occ_external_req_state = OCC_STATE_NOCHANGE;
+
+// Indicates if we are currently in a state transition
+bool G_state_transition_occuring = FALSE;
+
+// State that OCC Master is requesting
+OCC_STATE G_occ_master_state = OCC_STATE_NOCHANGE;
+
+// Semaphore to allow state change to be called from multiple threads
+SsxSemaphore G_smgrStateChangeSem;
+
+// Table that indicates which functions should be run for a given mode
+// transition.
+const smgr_state_trans_t G_smgr_state_trans[] =
+{
+ /* ----- SPECIFIC CASE STATE TRANSITIONS ----- */
+ /* These are specific state transitions for when it matters what
+ * state we were in before the transition. These must come before
+ * the agnostic state transitions below, and will be run instead of
+ * those catch-all transition functions. */
+
+ /* Current State New State Transition Function */
+ {OCC_STATE_STANDBY, OCC_STATE_OBSERVATION, &SMGR_standby_to_observation},
+ {OCC_STATE_STANDBY, OCC_STATE_ACTIVE, &SMGR_standby_to_active},
+ {OCC_STATE_OBSERVATION, OCC_STATE_STANDBY, &SMGR_observation_to_standby},
+ {OCC_STATE_OBSERVATION, OCC_STATE_ACTIVE, &SMGR_observation_to_active},
+ {OCC_STATE_ACTIVE, OCC_STATE_OBSERVATION, &SMGR_active_to_observation},
+ {OCC_STATE_ACTIVE, OCC_STATE_STANDBY, &SMGR_active_to_standby},
+
+ /* ----- DEFAULT STATE TRANSITIONS ----- */
+ /* These are default state transitions for when it doesn't matter what
+ * state we were in before the transition. */
+
+ /* Current State New State Transition Function */
+ {OCC_STATE_ALL, OCC_STATE_SAFE, &SMGR_all_to_safe},
+};
+const uint8_t G_smgr_state_trans_count = sizeof(G_smgr_state_trans)/sizeof(smgr_state_trans_t);
+
+uint32_t G_smgr_validate_data_active_mask = SMGR_VALIDATE_DATA_ACTIVE_MASK_HARDCODES;
+uint32_t G_smgr_validate_data_observation_mask = SMGR_VALIDATE_DATA_OBSERVATION_MASK_HARDCODES;
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: SMGR_is_mode_transitioning
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+inline bool SMGR_is_state_transitioning(void)
+{
+ return G_state_transition_occuring;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_standby_to_observation()
+{
+ errlHndl_t l_errlHndl = NULL;
+ static bool l_error_logged = FALSE; // To prevent trace and error log happened over and over // @at015a
+
+ if( SMGR_MASK_OBSERVATION_READY ==
+ (SMGR_validate_get_valid_states() & SMGR_MASK_OBSERVATION_READY))
+ {
+ l_error_logged = FALSE; // @at015a
+ TRAC_IMP("SMGR: Standby to Observation Transition Started");
+
+ //This flag is set if tmgt sends us at least one data set in the
+ //mem config data packet. No data sets will be sent for centaur ec less than 2.0
+ //due to an intermittent hw failure that can occur on those chips.
+ if(G_mem_monitoring_allowed)
+ {
+ if(!rtl_task_is_runnable(TASK_ID_CENTAUR_DATA))
+ {
+
+ TRAC_INFO("SMGR_standby_to_observation: calling centaur_init()");
+ centaur_init(); //no rc, handles errors internally
+
+ //check if centaur_init resulted in a reset
+ //since we don't have a return code from centaur_init.
+ if(isSafeStateRequested())
+ {
+ TRAC_ERR("SMGR_standby_to_observation: OCC is being reset, centaur_init failed");
+ }
+ else
+ {
+ //initialization was successful.
+ //Set task flags to allow centaur control task to run and
+ //also to prevent us from doing initialization again.
+ G_task_table[TASK_ID_CENTAUR_DATA].flags = CENTAUR_DATA_RTL_FLAGS;
+ G_task_table[TASK_ID_CENTAUR_CONTROL].flags = CENTAUR_CONTROL_RTL_FLAGS;
+ }
+ }
+ }
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Set OBSERVATION b/c we're in OBSERVATION State
+ rtl_clr_run_mask_deferred(RTL_FLAG_STANDBY);
+ rtl_set_run_mask_deferred(RTL_FLAG_OBS);
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_OBSERVATION;
+
+ TRAC_IMP("SMGR: Standby to Observation Transition Completed");
+ }
+ else if(FALSE == l_error_logged)// @at015a
+ {
+ l_error_logged = TRUE;
+ TRAC_ERR("SMGR: Standby to Observation Transition Failed");
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 none
+ * @userdata4 ERC_STATE_FROM_STB_TO_OBS_FAILURE
+ * @devdesc Failed changing from standby to observation
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_STATE_FROM_STB_TO_OBS_FAILURE,//Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_observation_to_standby()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Observation to Standby Transition Started");
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Clear ACTIVE b/c not in ACTIVE State
+ // - Clear OBSERVATION b/c not in OBSERVATION State
+ rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE | RTL_FLAG_OBS );
+ rtl_set_run_mask_deferred(RTL_FLAG_STANDBY);
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_STANDBY;
+
+ TRAC_IMP("SMGR: Observation to Standby Transition Completed");
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name:
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_observation_to_active()
+{
+ errlHndl_t l_errlHndl = NULL;
+ static bool l_error_logged = FALSE; // To prevent trace and error log happened over and over // @at015a
+ int l_extRc = OCC_NO_EXTENDED_RC;
+ int l_rc = 0;
+
+ // First check to make sure Pstates are enabled. If they aren't, then
+ // wait TBD seconds in case we are going directly from Standby to Active
+ // (pstate init only happens in observation state, so it might not be
+ // done yet...must call it in this while loop since it is done in this
+ // same thread...)
+ //
+ // NOTE that this is really unnecessary if you follow the TMGT OCC
+ // Interface Spec, which tells you that you need to check for the "Active
+ // Ready" bit in the poll response before you go to active state.
+ // But since we have scenerios where TMGT isn't the one putting us in
+ // active state (we are going there automatically) we needed to add this
+
+ // If we have all data we need to go to active state, but don't have pstates
+ // enabled yet...then we will do the aforementioned wait
+ if(((DATA_get_present_cnfgdata() & SMGR_VALIDATE_DATA_ACTIVE_MASK) ==
+ SMGR_VALIDATE_DATA_ACTIVE_MASK)
+ && !proc_is_hwpstate_enabled() )
+ {
+ SsxTimebase start = ssx_timebase_get();
+ while( ! proc_is_hwpstate_enabled() )
+ {
+ SsxInterval timeout = SSX_SECONDS(5);
+ if ((ssx_timebase_get() - start) > timeout)
+ {
+ if(FALSE == l_error_logged)
+ {
+ TRAC_ERR("SMGR: Timeout waiting for Pstates to be enabled, master state=%d, slave state=%d, pmc_mode[%08x], chips_present[%02x], pmc_deconfig[%08x]", //gm034
+ G_proc_dcm_sync_state.sync_state_master,
+ G_proc_dcm_sync_state.sync_state_slave,
+ in32(PMC_MODE_REG),
+ G_sysConfigData.is_occ_present,
+ in32(PMC_CORE_DECONFIGURATION_REG));
+ }
+ l_extRc = ERC_GENERIC_TIMEOUT;
+ break;
+ }
+ proc_gpsm_dcm_sync_enable_pstates_smh();
+ ssx_sleep(SSX_MICROSECONDS(500));
+ }
+ if(proc_is_hwpstate_enabled() && G_sysConfigData.system_type.kvm) // @ly010c
+ {
+ TRAC_IMP("SMGR: Pstates are enabled, continuing with state trans");
+ }
+ } // @th043 -- whole if statement
+
+ // Check if all conditions are met to transition to active state. If
+ // they aren't, then log an error and fail to change state.
+
+ if( (SMGR_MASK_ACTIVE_READY ==
+ (SMGR_validate_get_valid_states() & SMGR_MASK_ACTIVE_READY))
+ && proc_is_hwpstate_enabled() )
+ {
+ l_error_logged = FALSE; // @at015a
+ TRAC_IMP("SMGR: Observation to Active Transition Started");
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Clear OBSERVATION b/c not in OBSERVATION State
+ // - Set ACTIVE b/c we're in ACTIVE State
+ rtl_clr_run_mask_deferred(RTL_FLAG_OBS);
+ rtl_set_run_mask_deferred(RTL_FLAG_ACTIVE);
+
+ //@gm008
+ // Ensure that the dpll override (enabled when mfg biases freq) has been disabled.
+ int l_core;
+ uint32_t l_configured_cores;
+ pcbs_pmgp1_reg_t l_pmgp1;
+ l_configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG);
+ for(l_core = 0; l_core < PGP_NCORES; l_core++, l_configured_cores <<= 1)
+ {
+ if(!(l_configured_cores & 0x80000000)) continue;
+ l_pmgp1.value = 0;
+ l_pmgp1.fields.dpll_freq_override_enable = 1;
+ l_rc = putscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG_AND, l_core),
+ ~l_pmgp1.value, NULL); //commit errors internally -- gm033
+ if(l_rc)
+ {
+ TRAC_ERR("Failed disabling dpll frequency override. rc=0x%08x, core=%d", l_rc, l_core);
+ break;
+ }
+ }
+
+ if(!l_rc)
+ {
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_ACTIVE;
+ TRAC_IMP("SMGR: Observation to Active Transition Completed");
+
+ // >> @sb055
+ // Configure and enable the PCB slave heartbeat timer
+ //
+ // task_core_data is running in every RTL tick and scheduling a run
+ // of gpe_get_per_core_data which will do a getscom on
+ // PCBS_PMSTATEHISTOCC_REG. We will use PCBS_PMSTATEHISTOCC_REG as
+ // the PCBS heartbeat trigger register.
+ unsigned int l_actual_pcbs_hb_time = 0;
+ ChipConfigCores l_cfgd_cores =
+ (ChipConfigCores)((uint64_t)core_configuration() >> 16);
+ TRAC_IMP("Configuring PCBS heartbeat for configured cores=0x%8.8x", l_cfgd_cores);
+ TRAC_IMP("OCC configuration view: G_present_hw_cores=0x%8.8x, G_present_cores=0x%8.8x",
+ G_present_hw_cores, G_present_cores);
+ // Setup the pcbs heartbeat timer
+ l_rc = pcbs_hb_config(1, // enable = yes
+ l_cfgd_cores,
+ PCBS_PMSTATEHISTOCC_REG,
+ PCBS_HEARBEAT_TIME_US,
+ 0, // force = no
+ &l_actual_pcbs_hb_time);
+
+ if (l_rc)
+ {
+ TRAC_ERR("Failure configuring the PCBS heartbeat timer, rc=%d",
+ l_rc);
+ // FIXME #state_c_002 Add appropriate callouts for
+ // serviceability review
+ l_extRc = ERC_STATE_HEARTBEAT_CFG_FAILURE;
+ }
+ else
+ {
+ TRAC_IMP("PCBS heartbeat enabled, requested time(us)=%d, actual time(us)=%d",
+ PCBS_HEARBEAT_TIME_US,
+ l_actual_pcbs_hb_time);
+ }
+ // << @sb055
+
+ // >> @sb002 FIXME #state_c_001 Manually configuring the PMC
+ // heartbeat until pmc_hb_config is shown to be working
+ // Reference SW238882 for more information on updates needed in
+ // pmc_hb_config. Note that if PMC parameter hangpulse pre-divider
+ // is 0 then the PMC heartbeat counter uses nest_nclck/4 instead of
+ // the hangpulse to count the heartbeat timeout.
+ pmc_parameter_reg0_t ppr0;
+ pmc_occ_heartbeat_reg_t pohr;
+ pohr.value = in32(PMC_OCC_HEARTBEAT_REG);
+ ppr0.value = in32(PMC_PARAMETER_REG0);
+ pohr.fields.pmc_occ_heartbeat_en = 0;
+ // This combined with the hang pulse count and pre-divider yields
+ // about a 2 second timeout
+ pohr.fields.pmc_occ_heartbeat_time = 0xffff;
+ TRAC_IMP("Configure PMC heartbeat, heartbeat_time=0x%x",
+ pohr.fields.pmc_occ_heartbeat_time);
+ ppr0.fields.hangpulse_predivider = 1;
+ TRAC_IMP("Configure PMC parm reg predivider=%d",
+ ppr0.fields.hangpulse_predivider);
+ // Write registers twice, known issue with heartbeat reg
+ out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
+ out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
+ out32(PMC_PARAMETER_REG0, ppr0.value);
+ out32(PMC_PARAMETER_REG0, ppr0.value);
+ TRAC_IMP("Enable PMC heartbeat timer");
+ pohr.value = in32(PMC_OCC_HEARTBEAT_REG);
+ pohr.fields.pmc_occ_heartbeat_en = 1;
+ out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
+ out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
+ // << @sb002
+ }
+ }
+ else
+ {
+ //trace and log an error.
+ l_rc = -1;
+ }
+
+ if(l_rc)
+ {
+ TRAC_ERR("SMGR: Observation to Active Transition Failed, cnfgdata=0x%08x, reqd=0x%08x",
+ DATA_get_present_cnfgdata(),
+ SMGR_VALIDATE_DATA_ACTIVE_MASK); //@gm006
+ }
+
+
+ if(l_rc && FALSE == l_error_logged)// @at015a
+ {
+ l_error_logged = TRUE;
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 SMGR_MASK_ACTIVE_READY
+ * @userdata2 valid states
+ * @userdata4 ERC_STATE_FROM_OBS_TO_STB_FAILURE
+ * @devdesc Failed changing from observation to standby
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ l_extRc, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ SMGR_MASK_ACTIVE_READY, //userdata1 - @gm006
+ SMGR_validate_get_valid_states());//userdata2 - @gm006
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_active_to_observation
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_active_to_observation()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Active to Observation Transition Started");
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Set OBSERVATION b/c in OBSERVATION State
+ // - Clear ACTIVE b/c not in ACTIVE State
+ rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE);
+ rtl_set_run_mask_deferred(RTL_FLAG_OBS);
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_OBSERVATION;
+
+ TRAC_IMP("SMGR: Active to Observation Transition Completed");
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_active_to_standby
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_active_to_standby()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Active to Standby Transition Started");
+
+ // Transtion through both functions on this multi-state transtion
+ l_errlHndl = SMGR_active_to_observation();
+ if(NULL == l_errlHndl)
+ {
+ l_errlHndl = SMGR_observation_to_standby();
+ }
+
+ if(l_errlHndl) // @at015a
+ {
+ TRAC_ERR("SMGR: Active to Standby Transition Failed");
+ }
+ else
+ {
+ TRAC_IMP("SMGR: Active to Standby Transition Completed");
+ }
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_standby_to_active
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_standby_to_active()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: Standby to Active Transition Started");
+
+ // Transtion through both functions on this multi-state transtion
+ l_errlHndl = SMGR_standby_to_observation();
+ if(NULL == l_errlHndl)
+ {
+ l_errlHndl = SMGR_observation_to_active();
+ }
+
+ if(l_errlHndl) // @at015a
+ {
+ TRAC_ERR("SMGR: Standby to Active Transition Failed");
+ }
+ else
+ {
+ TRAC_IMP("SMGR: Standby to Active Transition Completed");
+ }
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_all_to_safe
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_all_to_safe()
+{
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_IMP("SMGR: All States to Safe Transition Started");
+
+ // If we are master, make sure we are broadcasting that the requested
+ // state is "safe state"
+ if (OCC_MASTER == G_occ_role)
+ {
+ G_occ_external_req_state = OCC_STATE_SAFE;
+ }
+
+ // If we are master, we will wait 15ms to go to full on safe mode
+ // This is to give the slaves time to see that we are broadcasting
+ // Safe State, and react to it. This must be > 10ms. It doesn't hurt
+ // to do this on the slaves also.
+ ssx_sleep(SSX_MILLISECONDS(15));
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Clear ACTIVE b/c not in ACTIVE State
+ // - Clear OBSERVATION b/c not in OBSERVATION State
+ // - Clear STANDBY b/c not in STANDBY State
+ rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE | RTL_FLAG_OBS | RTL_FLAG_STANDBY);
+
+ // Only reset task & wdt task will run from now on
+ // !!! There is no recovery to this except a reset !!!
+ rtl_set_run_mask_deferred(RTL_FLAG_RST_REQ);
+
+ // Notes:
+ // - We can still talk to FSP
+ // - We will still be able to go out on PIB
+ // - We will still attempt to load an applet if told to do so
+ // - The master will no longer broadcast to slaves, and vice versa
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_SAFE;
+
+ TRAC_IMP("SMGR: All States to Safe Transition Completed");
+
+ return l_errlHndl;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_set_state
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+errlHndl_t SMGR_set_state(OCC_STATE i_new_state)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_transResult = NULL; //Was the transition successful?
+ int jj=0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // Get lock for critical section
+ if(ssx_semaphore_pend(&G_smgrStateChangeSem,SSX_WAIT_FOREVER))
+ {
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 none
+ * @userdata4 ERC_RUNNING_SEM_PENDING_FAILURE
+ * @devdesc SSX semaphore related failure
+ */
+ l_transResult = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ ERC_RUNNING_SEM_PENDING_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_transResult,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ break;
+ } // @th022
+
+ //If there is no change to the state, just exit
+ if(i_new_state == OCC_STATE_NOCHANGE)
+ {
+ break;
+ }
+
+ // Loop through state transition table, and find the state
+ // transition function that matches the transition we need to do.
+ for(jj=0; jj<G_smgr_state_trans_count; jj++)
+ {
+ if( ((G_smgr_state_trans[jj].old_state == G_occ_internal_state)
+ || (G_smgr_state_trans[jj].old_state == OCC_STATE_ALL) )
+ && (G_smgr_state_trans[jj].new_state == i_new_state) )
+ {
+ // We found the transtion that matches, now run the function
+ // that is associated with that state transition.
+ if(NULL != G_smgr_state_trans[jj].trans_func_ptr)
+ {
+ // Signal that we are now in a state transition
+ G_state_transition_occuring = TRUE; // @th011
+ // Run transition function
+ l_transResult = (G_smgr_state_trans[jj].trans_func_ptr)();
+ // Signal that we are done with the transition
+ G_state_transition_occuring = FALSE; // @th011
+ break;
+ }
+ }
+ }
+
+ // Check if we hit the end of the table without finding a valid
+ // state transition. If we did, log an internal error.
+ if(G_smgr_state_trans_count == jj)
+ {
+ TRAC_ERR("No transition (or NULL) found for the state change\n");
+ l_transResult = NULL; //TODO: Create Error
+ break;
+ }
+
+ // If the state OCC requested from TMGT is the state we are now in,
+ // then change the requested state to NO CHANGE.
+ if(CURRENT_STATE() == REQUESTED_STATE())
+ {
+ REQUESTED_STATE() = OCC_STATE_NOCHANGE;
+ }
+ } while ( 0 );
+
+ // Get lock for critical section
+ ssx_semaphore_post(&G_smgrStateChangeSem);
+
+ return l_transResult;
+}
+
+
+// Function Specification
+//
+// Name: SMGR_validate_get_valid_states
+//
+// Description:
+//
+// Flow: FN=
+//
+// End Function Specification
+uint8_t SMGR_validate_get_valid_states(void)
+{
+ uint8_t l_valid_states = 0;
+ uint32_t l_datamask = DATA_get_present_cnfgdata();
+ static BOOLEAN l_throttle_traced = FALSE; //@rt004a
+
+ // If we have everything we need to go to observation state
+ if((l_datamask & SMGR_VALIDATE_DATA_OBSERVATION_MASK) ==
+ SMGR_VALIDATE_DATA_OBSERVATION_MASK)
+ {
+ l_valid_states |= SMGR_MASK_OBSERVATION_READY;
+ }
+
+ // If we have everything we need to go to active state
+ if(((l_datamask & SMGR_VALIDATE_DATA_ACTIVE_MASK) ==
+ SMGR_VALIDATE_DATA_ACTIVE_MASK) )
+ {
+ l_valid_states |= SMGR_MASK_ACTIVE_READY; //@rt004c
+
+ if(!l_throttle_traced)
+ {
+ TRAC_IMP("Setting Active Bit for this OCC");
+ l_throttle_traced = TRUE;
+ }
+ }
+
+ // If we hit an oversubscription, we need to set that bit
+ if(FSI2HOST_MBOX_INITIALIZED == G_fsi2host_mbox_ready)
+ {
+ l_valid_states |= SMGR_MASK_ATTN_ENABLED;
+ }
+
+ // If we are master OCC, set this bit
+ if(OCC_MASTER == G_occ_role)
+ {
+ l_valid_states |= SMGR_MASK_MASTER_OCC;
+ }
+
+ return l_valid_states;
+}
+
diff --git a/src/occ/state.h b/src/occ/state.h
new file mode 100755
index 0000000..61755c3
--- /dev/null
+++ b/src/occ/state.h
@@ -0,0 +1,234 @@
+/******************************************************************************
+// @file state.h
+// @brief OCC States (including Reset)
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section state.h STATE.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th003 thallet 11/08/2011 New file
+ * @01 tapiar 11/10/2011 New state/mode macro/enums
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th00d thallet 04/23/2012 SMGR States, Structs & Functions
+ * @th011 thallet 07/12/2012 Split State/Mode/Reset into sep files
+ * @th022 thallet 10/03/2012 Changes to allow DCOM State/Mode setting
+ * @th036 881677 thallet 05/06/2013 Support for new poll command
+ * @th042 892056 thallet 07/19/2013 Send OCC to safe mode if first APSS GPE fails
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @gs011 900661 gjsilva 09/30/2013 Make data format 0x13 required to go active
+ * @gm013 907548 milesg 11/22/2013 Memory therm monitoring support
+ * @rt004 908817 tapiar 12/11/2013 Add APSS & THRM Threshold config data as required for OBS
+ * Add PCAP config data as required for Active
+ * @gm016 909061 milesg 12/10/2013 Support memory throttling due to temperature
+ * @jh00b 910184 joshych 01/10/2014 Add check for checkstop
+ * @gm028 911670 milesg 02/27/2014 Immediate safe mode on checkstop
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef _state_h
+#define _state_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <common_types.h>
+#include "rtls.h"
+#include "errl.h"
+#include "mode.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern uint32_t G_smgr_validate_data_active_mask;
+extern uint32_t G_smgr_validate_data_observation_mask;
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum eResetStates
+{
+ RESET_NOT_REQUESTED = 0,
+ NOMINAL_REQUESTED_DUE_TO_ERROR,
+ RESET_REQUESTED_DUE_TO_ERROR,
+};
+
+/**
+ * @enum OCC_STATE
+ * @brief Typedef of the various states that TMGT can put OCC into.
+ */
+typedef enum
+{
+ OCC_STATE_NOCHANGE = 0x00,
+ OCC_STATE_STANDBY = 0x01,
+ OCC_STATE_OBSERVATION = 0x02,
+ OCC_STATE_ACTIVE = 0x03,
+ OCC_STATE_SAFE = 0x04,
+ OCC_STATE_RESET = 0x05, // Invalid State, TPMD Legacy
+ OCC_STATE_STANDBYOBSERVATION = 0x06, // Invalid State, TPMD Legacy
+
+ // These are used for state transition table, and are not
+ // a valid state in and of itself.
+ OCC_STATE_ALL = 0xFE,
+ OCC_STATE_INVALID = 0xFF,
+} OCC_STATE;
+
+
+/**
+ * @enum SMGR_SMS_CMD_TYPE
+ * @brief SMGR set-mode-state commands version 0 contains a byte that indicates if
+ * the TPMD must actually change the voltage / frequency during a mode change.
+ */
+typedef enum
+{
+ SMGR_SMS_VF_INFO_ONLY = 0x00,
+ SMGR_SMS_VF_CHANGE_REQ = 0x01,
+ SMGR_SMS_STATIC_VF_CHANGE_REQ = 0x02,
+} SMGR_SMS_CMD_TYPE;
+extern SMGR_SMS_CMD_TYPE G_occ_internal_sms; // TODO: Move to state.c
+
+/**
+ * @enum SMGR_SMS_STATUS_TYPE
+ * @brief TMGT Poll contains a byte that indicates status based on this
+ * bitmask
+ */
+#define SMGR_MASK_MASTER_OCC 0x80 ///This is the master OCC
+#define SMGR_MASK_RESERVED_6 0x40 ///Reserved
+#define SMGR_MASK_RESERVED_5 0x20 ///Reserved
+#define SMGR_MASK_STATUS_REG_CHANGE 0x10 ///Change in status register
+#define SMGR_MASK_ATTN_ENABLED 0x08 ///Attentions to FSP are enabled
+#define SMGR_MASK_RESERVED_2 0x04 ///Reserved
+#define SMGR_MASK_OBSERVATION_READY 0x02 ///Observation Ready
+#define SMGR_MASK_ACTIVE_READY 0x01 ///Active Ready
+
+/**
+ * @enum SMGR_VALIDATE_STATES
+ * @brief Config Data Formats needed from TMGT to trans. between states
+ *
+ */
+// <TULETA HW BRINGUP>
+#define SMGR_VALIDATE_DATA_OBSERVATION_MASK_HARDCODES \
+ (DATA_MASK_SYS_CNFG | \
+ DATA_MASK_APSS_CONFIG | \
+ DATA_MASK_SET_ROLE | \
+ DATA_MASK_MEM_CFG | \
+ DATA_MASK_THRM_THRESHOLDS )
+
+// </TULETA HW BRINGUP>
+
+#define SMGR_VALIDATE_DATA_ACTIVE_MASK G_smgr_validate_data_active_mask
+#define SMGR_VALIDATE_DATA_OBSERVATION_MASK G_smgr_validate_data_observation_mask
+
+#define SMGR_VALIDATE_DATA_ACTIVE_MASK_HARDCODES \
+ (SMGR_VALIDATE_DATA_OBSERVATION_MASK_HARDCODES | \
+ DATA_MASK_PSTATE_SUPERSTRUCTURE | \
+ DATA_MASK_FREQ_PRESENT | \
+ DATA_MASK_PCAP_PRESENT )
+
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+// Used by OCC FW to request an OCC Reset because of an error.
+// It's the action flag that actually requests the reset.
+// Severity will be set to UNRECOVERABLE if it is INFORMATIONAL.
+#define REQUEST_RESET(error_log) \
+{\
+ reset_state_request(RESET_REQUESTED_DUE_TO_ERROR);\
+ setErrlActions(error_log, ERRL_ACTIONS_RESET_REQUIRED);\
+ commitErrl(&error_log);\
+}
+
+#define REQUEST_SAFE_MODE(error_log) \
+{\
+ reset_state_request(RESET_REQUESTED_DUE_TO_ERROR);\
+ setErrlActions(error_log, ERRL_ACTIONS_SAFE_MODE_REQUIRED);\
+ commitErrl(&error_log);\
+}
+
+
+// Used by OCC FW to request that OCC go to Nominal because of an error
+#define REQUEST_NOMINAL() reset_state_request(NOMINAL_REQUESTED_DUE_TO_ERROR);
+
+// Used by OCC FW to signify that OCC can leave Nominal state because the
+// error that caused OCC to go to Nominal has cleared.
+#define CLEAR_NOMINAL() reset_state_request(RESET_NOT_REQUESTED);
+
+// Used to indicate that OCC has established TMGT Comm, and should no longer
+// halt() on a reset request.
+#define DISABLE_HALT_ON_RESET_REQUEST() reset_disable_halt();
+
+// Returns the current OCC State
+#define CURRENT_STATE() G_occ_internal_state
+
+// Returns the 'OCC Requested' OCC State
+#define REQUESTED_STATE() G_occ_internal_req_state
+
+// Returns true if OCC State is active
+#define IS_OCC_STATE_ACTIVE() ( (OCC_STATE_ACTIVE == G_occ_internal_state)? 1 : 0 )
+
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+/**
+ * @struct smgr_state_trans_t
+ * @brief Used by the "Set State" command to call the correct transition
+ * function, based on the current & new states.
+ */
+typedef struct
+{
+ uint8_t old_state;
+ uint8_t new_state;
+ errlHndl_t (*trans_func_ptr)(void);
+} smgr_state_trans_t;
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+extern OCC_STATE G_occ_internal_state;
+extern OCC_STATE G_occ_internal_req_state;
+extern SMGR_SMS_CMD_TYPE G_occ_internal_sms;
+extern OCC_STATE G_occ_master_state; // @th022
+extern OCC_STATE G_occ_external_req_state; // @th022
+
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// Used by macro above to clear flag indicating to not halt OCC when a reset
+// is requested.
+inline void reset_disable_halt(void);
+
+// Used to see if anyone has requested reset/safe state
+bool isSafeStateRequested(void); // @th042
+
+// Used by macros to request reset states extenally
+void reset_state_request(uint8_t i_request);
+
+// Task that will check for checkstop // @jh00bc
+void task_check_for_checkstop(task_t *i_self);
+
+// Used to set OCC State
+errlHndl_t SMGR_set_state(OCC_STATE i_state);
+
+// Used to indicate which OCC States are valid, given the config data/system
+// parms we currently know.
+uint8_t SMGR_validate_get_valid_states(void);
+
+#endif
+
diff --git a/src/occ/thread/chom.c b/src/occ/thread/chom.c
new file mode 100755
index 0000000..2e32c02
--- /dev/null
+++ b/src/occ/thread/chom.c
@@ -0,0 +1,511 @@
+/******************************************************************************
+// @file chom.c
+// @brief OCC thread Component
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _chom_c chom.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+ * @jh007 897706 joshych 09/17/2013 Updates to call-home data interface
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ * @gm016 909061 milesg 12/10/2013 Changed trace from error to info
+ * @fk006 914801 fmkassem 02/05/2014 Modify reasoncode list
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <sensor.h>
+#include <trac.h>
+#include <chom.h>
+#include <mode.h>
+#include <dcom.h>
+#include <amec_sys.h>
+#include <occ_service_codes.h>
+#include <thread_service_codes.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern amec_sys_t g_amec_sys;
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+#define CHOM_SENSOR_DATA(index,data) [index] = data
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+/* chom timer */
+uint32_t g_chom_gen_periodic_log_timer;
+/* track which power mode has been during the polling period */
+uint8_t g_chom_pwr_modes[OCC_INTERNAL_MODE_MAX_NUM]; // Nominal, SPS, DPS, DPS-MP, FFO
+/* force immediate chom log flag*/
+uint8_t g_chom_force;
+/* chom data log */
+ChomLogData_t g_chom_log;
+ChomLogData_t * g_chom = &g_chom_log;
+
+// Make sure that the size of chom log is less than 3kB
+// otherwise cause error on the compile.
+STATIC_ASSERT( sizeof(ChomLogData_t) > CHOM_LOG_DATA_MAX );
+
+/* chom sensors table
+ * some of the chom sensors need multiple mini-sensor to calculate
+ * the max, summstion of temperature or bandwidth
+ * mark those mini-sensor "NULL" and will be updated
+ * from "chom_update_sensors()"
+ */
+const uint16_t * g_chom_sensor_table[CHOM_NUM_OF_SENSORS] =
+{ /* Node total power (DC) */
+ &g_amec_sys.sys.pwr250us.sample,
+ /* Socket power */ // This is only for tuleta 2S @jh007c
+ &g_amec_sys.proc[0].pwr250us.sample,
+ &G_dcom_slv_outbox_rx[2].pwr250usp0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ /* Memory power */
+ &G_dcom_slv_outbox_rx[0].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[1].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[2].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[3].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[4].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[5].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[6].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[7].pwr250usmemp0,
+ /* Fan power */
+ &g_amec_sys.fan.pwr250usfan.sample, // @jh007a
+ /* Processor frequency */ // @mw624
+ &G_dcom_slv_outbox_rx[0].freqa2msp0,
+ &G_dcom_slv_outbox_rx[1].freqa2msp0,
+ &G_dcom_slv_outbox_rx[2].freqa2msp0,
+ &G_dcom_slv_outbox_rx[3].freqa2msp0,
+ &G_dcom_slv_outbox_rx[4].freqa2msp0,
+ &G_dcom_slv_outbox_rx[5].freqa2msp0,
+ &G_dcom_slv_outbox_rx[6].freqa2msp0,
+ &G_dcom_slv_outbox_rx[7].freqa2msp0,
+ /* Processor utilization sensor */
+ &G_dcom_slv_outbox_rx[0].util2msp0,
+ &G_dcom_slv_outbox_rx[1].util2msp0,
+ &G_dcom_slv_outbox_rx[2].util2msp0,
+ &G_dcom_slv_outbox_rx[3].util2msp0,
+ &G_dcom_slv_outbox_rx[4].util2msp0,
+ &G_dcom_slv_outbox_rx[5].util2msp0,
+ &G_dcom_slv_outbox_rx[6].util2msp0,
+ &G_dcom_slv_outbox_rx[7].util2msp0,
+ /* Max Core temperature for all processors in the node */
+ NULL,
+ /* Max Centaur temperature for all Centaurs in the node */
+ NULL,
+ /* Max Dimm temperature for all Dimms in the node */
+ NULL,
+ /* Instructions per second sensor */
+ NULL,
+ /* Memory bandwidth for process memory controller */
+ /* P0M0 ~ P0M7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* P1M0 ~ P1M7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* P2M0 ~ P2M7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* P3M0 ~ P3M7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* P4M0 ~ P4M7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* P5M0 ~ P5M7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* P6M0 ~ P6M7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* P7M0 ~ P7M7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+// Function Specification
+//
+// Name: chom_data_init
+//
+// Description: Init chom data
+//
+// End Function Specification
+void chom_data_init()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // chom data reset
+ chom_data_reset();
+ // update eyecatcher
+ memcpy(&g_chom->nodeData.eyecatcher, "CHOM", 0x04);
+ // update chom version
+ g_chom->nodeData.version = CHOM_VERSION;
+ // update num of sensors
+ g_chom->nodeData.numSensors = CHOM_NUM_OF_SENSORS;
+}
+
+
+// Function Specification
+//
+// Name: chom_data_reset
+//
+// Description: Reset chom data
+//
+// End Function Specification
+void chom_data_reset()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // reset chom data log
+ memset(g_chom, 0x00, sizeof(*g_chom));
+ // reset chom modes in log
+ memset(g_chom_pwr_modes, 0x00, sizeof(g_chom_pwr_modes));
+ // reset chom timer
+ g_chom_gen_periodic_log_timer = 0;
+ // reset flag
+ g_chom_force = FALSE;
+
+}
+
+
+// Function Specification
+//
+// Name: chom_update_sensors
+//
+// Description: Update chom sensor data
+//
+// Flow: 8-12-13 FN:chom_update_sensors.odg
+//
+// End Function Specification
+void chom_update_sensors()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_max_core_temp = 0;
+ uint16_t l_max_cent_temp = 0;
+ uint16_t l_max_dimm_temp = 0;
+ uint16_t l_mips = 0;
+ uint16_t l_mem_rw = 0;
+ uint16_t l_sample = 0;
+ uint16_t i = 0;
+ uint16_t j = 0;
+ uint16_t k = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // Is the current mode different than previous poll
+ if (g_chom->nodeData.curPwrMode != CURRENT_MODE())
+ {
+ // update current power mode
+ g_chom->nodeData.curPwrMode = CURRENT_MODE();
+ // copy the current mode data to previous mode
+ memcpy(&g_chom->sensorData[1], &g_chom->sensorData[0], sizeof(ChomSensorData_t));
+ // reset all fields in the current chom sensors
+ memset(&g_chom->sensorData[0], 0x00, sizeof(ChomSensorData_t));
+ // update power saving mode of sensor data
+ g_chom->sensorData[0].pwrMode.mode = g_chom->nodeData.curPwrMode;
+
+ // initial min value of chom sensors
+ for (i=0 ; i<CHOM_NUM_OF_SENSORS ; i++)
+ {
+ g_chom->sensorData[0].sensor[i].sampleMin = 0xffff;
+ }
+
+ // update the number of power modes during the polling period
+ switch (g_chom->nodeData.curPwrMode)
+ {
+ case OCC_MODE_NOMINAL:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_NOM] = 1;
+ break;
+
+ case OCC_MODE_PWRSAVE:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_SPS] = 1;
+ break;
+
+ case OCC_MODE_DYN_POWER_SAVE:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_DPS] = 1;
+ break;
+
+ case OCC_MODE_DYN_POWER_SAVE_FP:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_DPS_MP] = 1;
+ break;
+
+ case OCC_MODE_FFO:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_FFO] = 1;
+ break;
+
+ default:
+ TRAC_INFO("chom_update_sensors: Cannot record chom data for mode 0x%02X",
+ g_chom->sensorData[0].pwrMode.mode);
+ break;
+ }
+ }
+
+ // update number of samples
+ g_chom->sensorData[0].pwrMode.numOfSamples++;
+
+ // update chom sensors which has multiple mini-sensor source
+ for (i = 0 ; i<MAX_OCCS ; i++)
+ {
+ if (G_dcom_slv_outbox_rx[i].temp2msp0peak > l_max_core_temp)
+ {
+ l_max_core_temp = G_dcom_slv_outbox_rx[i].temp2msp0peak;
+ }
+
+ if (G_dcom_slv_outbox_rx[i].temp2mscent > l_max_cent_temp)
+ {
+ l_max_cent_temp = G_dcom_slv_outbox_rx[i].temp2mscent;
+ }
+
+ if (G_dcom_slv_outbox_rx[i].temp2msdimm > l_max_dimm_temp)
+ {
+ l_max_dimm_temp = G_dcom_slv_outbox_rx[i].temp2msdimm;
+ }
+ }
+ g_chom->sensorData[0].sensor[CHOMTEMPPROC].sample = l_max_core_temp;
+ g_chom->sensorData[0].sensor[CHOMTEMPCENT].sample = l_max_cent_temp;
+ g_chom->sensorData[0].sensor[CHOMTEMPDIMM].sample = l_max_dimm_temp;
+
+ // update MIPS
+ k = 0;
+ for (i=0 ; i<MAX_OCCS ; i++)
+ {
+ if (0 != G_dcom_slv_outbox_rx[i].ips2msp0)
+ {
+ l_mips += G_dcom_slv_outbox_rx[i].ips2msp0;
+ k++;
+ }
+ }
+ if (k != 0)
+ {
+ g_chom->sensorData[0].sensor[CHOMIPS].sample = (l_mips/k);
+ }
+
+ // update memory bandwidth
+ k = CHOMBWP0M0;
+ for (i=0 ; i<MAX_OCCS ; i++)
+ {
+ for (j=0 ; j<MAX_NUM_MEM_CONTROLLERS ; j++)
+ {
+ // TODO: Need to take a snapshot of the "max" field for that sensor and
+ // redefine the mini-sensor information that we pass back to the Master
+ l_mem_rw = G_dcom_slv_outbox_rx[i].mrd2msp0mx[j]+G_dcom_slv_outbox_rx[i].mwr2msp0mx[j];
+ g_chom->sensorData[0].sensor[k].sample = l_mem_rw;
+ k++;
+ }
+ }
+
+ // loop through all sensors and update data from mini-sensors
+ for (i = 0 ; i<CHOM_NUM_OF_SENSORS ; i++)
+ { // update sample, min, max, average sensor data
+ if (NULL != g_chom_sensor_table[i])
+ { // directly mapping to mini-sensor
+ g_chom->sensorData[0].sensor[i].sample = *g_chom_sensor_table[i];
+ }
+
+ l_sample = g_chom->sensorData[0].sensor[i].sample;
+
+ if (g_chom->sensorData[0].sensor[i].sampleMin > l_sample)
+ {
+ g_chom->sensorData[0].sensor[i].sampleMin = l_sample;
+ }
+ if (g_chom->sensorData[0].sensor[i].sampleMax < l_sample)
+ {
+ g_chom->sensorData[0].sensor[i].sampleMax = l_sample;
+ }
+ g_chom->sensorData[0].sensor[i].accumulator += l_sample;
+ g_chom->sensorData[0].sensor[i].average = (g_chom->sensorData[0].sensor[i].accumulator/
+ g_chom->sensorData[0].pwrMode.numOfSamples);
+ }
+}
+
+
+// Function Specification
+//
+// Name: chom_collect_cpi_data
+//
+// Description: collect CPI data
+//
+// End Function Specification
+void chom_collect_cpi_data(void)
+{
+ // TODO
+}
+
+
+// Function Specification
+//
+// Name: chom_gen_periodic_log
+//
+// Description: Create call home data logs
+//
+// End Function Specification
+void chom_gen_periodic_log()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint8_t i = 0;
+ errlHndl_t l_errlHndl = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ TRAC_INFO("Enter chom_gen_periodic_log");
+
+ // update total time
+ g_chom->nodeData.totalTime = g_chom_gen_periodic_log_timer;
+
+ // update the number of different power modes
+ for (i=0 ; i<OCC_INTERNAL_MODE_MAX_NUM ; i++)
+ {
+ if (g_chom_pwr_modes[i] == 1)
+ {
+ g_chom->nodeData.modeInLog++;
+ }
+ }
+
+ // collect CPI data
+ chom_collect_cpi_data();
+
+ /* @
+ * @errortype
+ * @moduleid THRD_MID_GEN_CALLHOME_LOG
+ * @reasoncode GEN_CALLHOME_LOG
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Generating periodic call-home log, which contains critical power/thermal/performance data since the last log was generated (or the last OCC reset)
+ */
+ l_errlHndl = createErrl(
+ THRD_MID_GEN_CALLHOME_LOG, // modId
+ GEN_CALLHOME_LOG, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_INFORMATIONAL, // Severity
+ NULL, // Trace Buf
+ 0, // Trace Size
+ 0, // userdata1
+ 0 // userdata2
+ );
+
+ // add chom data
+ addUsrDtlsToErrl(l_errlHndl,
+ (uint8_t*)g_chom,
+ sizeof(*g_chom),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_CALLHOME_DATA);
+
+ // commit error log
+ if (l_errlHndl != NULL)
+ {
+ commitErrl(&l_errlHndl);
+ }
+}
+
+
+// Function Specification
+//
+// Name: chom_force_gen_log()
+//
+// Description: immediate chom log
+//
+// End Function Specification
+void chom_force_gen_log()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ g_chom_force = TRUE;
+}
+
+
+// Function Specification
+//
+// Name: chom_main
+//
+// Description: Call home data routine
+//
+// Flow: 8-12-13 FN=chom_main.odg
+//
+// End Function Specification
+void chom_main()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+ // @rc001m - Modified to use MAIN debug traces
+ MAIN_DBG("CHOM routine processing...");
+
+ // check if this is the first time we run
+ if (memcmp(&g_chom->nodeData.eyecatcher, "CHOM", 0x04) != 0)
+ {
+ chom_data_init();
+ }
+
+ // only update chom sensors on an active OCC
+ if (IS_OCC_STATE_ACTIVE())
+ {
+ chom_update_sensors();
+ }
+
+ // increase chom timer
+ g_chom_gen_periodic_log_timer++;
+
+ // check if the timer expired
+ if ((g_chom_gen_periodic_log_timer >= CHOM_GEN_LOG_PERIODIC_TIME) ||
+ (TRUE == g_chom_force))
+ {
+ chom_gen_periodic_log();
+ chom_data_reset();
+ }
+}
diff --git a/src/occ/thread/chom.h b/src/occ/thread/chom.h
new file mode 100755
index 0000000..e8da6da
--- /dev/null
+++ b/src/occ/thread/chom.h
@@ -0,0 +1,249 @@
+/******************************************************************************
+// @file chom.h
+// @brief OCC thread Component header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _chom_h chom.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+ * @jh007 897706 joshych 09/17/2013 Updates to call-home data interface
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _CHOM_H
+#define _CHOM_H
+
+/** \defgroup OCC thread Component
+ *
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <occ_common.h>
+#include <trac_interface.h>
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define CHOM_GEN_LOG_PERIODIC_TIME 86400 // of seconds in a day
+#define CHOM_VERSION 0x00
+/* max size of chom data log */
+#define CHOM_LOG_DATA_MAX 3072
+
+// List of call home sensors
+enum
+{
+ /* Node total power (DC) */
+ CHOMPWR = 0,
+ /* Socket power */ // @jh007c
+ CHOMPWRP0,
+ CHOMPWRP1,
+ CHOMPWRP2,
+ CHOMPWRP3,
+ CHOMPWRP4,
+ CHOMPWRP5,
+ CHOMPWRP6,
+ CHOMPWRP7,
+ /* Memory power */
+ CHOMPWRM0,
+ CHOMPWRM1,
+ CHOMPWRM2,
+ CHOMPWRM3,
+ CHOMPWRM4,
+ CHOMPWRM5,
+ CHOMPWRM6,
+ CHOMPWRM7,
+ /* Fan power */
+ CHOMPWRFAN, // @jh007a
+ /* Processor frequency */
+ CHOMFREQP0,
+ CHOMFREQP1,
+ CHOMFREQP2,
+ CHOMFREQP3,
+ CHOMFREQP4,
+ CHOMFREQP5,
+ CHOMFREQP6,
+ CHOMFREQP7,
+ /* Processor utilization sensor */
+ CHOMUTILP0,
+ CHOMUTILP1,
+ CHOMUTILP2,
+ CHOMUTILP3,
+ CHOMUTILP4,
+ CHOMUTILP5,
+ CHOMUTILP6,
+ CHOMUTILP7,
+ /* Max core temperature for all processors in the node */
+ CHOMTEMPPROC,
+ /* Max Centaur temperature for all Centaurs in the node */
+ CHOMTEMPCENT,
+ /* Max Dimm temperature for all Dimms in the node */
+ CHOMTEMPDIMM,
+ /* Instructions per second sensor */
+ CHOMIPS,
+ /* Memory bandwidth for process memory controller */
+ CHOMBWP0M0,
+ CHOMBWP0M1,
+ CHOMBWP0M2,
+ CHOMBWP0M3,
+ CHOMBWP0M4,
+ CHOMBWP0M5,
+ CHOMBWP0M6,
+ CHOMBWP0M7,
+ CHOMBWP1M0,
+ CHOMBWP1M1,
+ CHOMBWP1M2,
+ CHOMBWP1M3,
+ CHOMBWP1M4,
+ CHOMBWP1M5,
+ CHOMBWP1M6,
+ CHOMBWP1M7,
+ CHOMBWP2M0,
+ CHOMBWP2M1,
+ CHOMBWP2M2,
+ CHOMBWP2M3,
+ CHOMBWP2M4,
+ CHOMBWP2M5,
+ CHOMBWP2M6,
+ CHOMBWP2M7,
+ CHOMBWP3M0,
+ CHOMBWP3M1,
+ CHOMBWP3M2,
+ CHOMBWP3M3,
+ CHOMBWP3M4,
+ CHOMBWP3M5,
+ CHOMBWP3M6,
+ CHOMBWP3M7,
+ CHOMBWP4M0,
+ CHOMBWP4M1,
+ CHOMBWP4M2,
+ CHOMBWP4M3,
+ CHOMBWP4M4,
+ CHOMBWP4M5,
+ CHOMBWP4M6,
+ CHOMBWP4M7,
+ CHOMBWP5M0,
+ CHOMBWP5M1,
+ CHOMBWP5M2,
+ CHOMBWP5M3,
+ CHOMBWP5M4,
+ CHOMBWP5M5,
+ CHOMBWP5M6,
+ CHOMBWP5M7,
+ CHOMBWP6M0,
+ CHOMBWP6M1,
+ CHOMBWP6M2,
+ CHOMBWP6M3,
+ CHOMBWP6M4,
+ CHOMBWP6M5,
+ CHOMBWP6M6,
+ CHOMBWP6M7,
+ CHOMBWP7M0,
+ CHOMBWP7M1,
+ CHOMBWP7M2,
+ CHOMBWP7M3,
+ CHOMBWP7M4,
+ CHOMBWP7M5,
+ CHOMBWP7M6,
+ CHOMBWP7M7,
+
+ /* The number of chom sensors reported*/
+ CHOM_NUM_OF_SENSORS
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+/* Call home sensor Structure */
+struct ChomSensor
+{
+ uint16_t sample; // last sample value during the polling period
+ uint16_t sampleMin; // min sample value recorded during polling period
+ uint16_t sampleMax; // max sample value recorded during polling period
+ uint16_t average; // average sample value during polling period
+ uint32_t accumulator; // accumulator register to computer the average
+} __attribute__ ((__packed__));
+
+typedef struct ChomSensor ChomSensor_t;
+
+/* CPI data structure */
+struct ChomCpiData
+{
+ uint8_t proc;
+ uint32_t cpi;
+}__attribute__ ((__packed__));
+
+typedef struct ChomCpiData ChomCpiData_t;
+
+/* Power mode structure */
+struct ChomPwrMode
+{
+ uint8_t mode; // OCC power mode
+ uint32_t numOfSamples; // Number of times samples were polled while in this mode
+}__attribute__ ((__packed__));
+
+typedef struct ChomPwrMode ChomPwrMode_t;
+
+/* Call home data Structure */
+struct ChomNodeData
+{
+ uint32_t eyecatcher; // "CHOM" will mark the beginning of the data
+ uint8_t version; // version of call home data being reported
+ uint8_t curPwrMode; // the current power mode at the time of the polling event
+ uint32_t totalTime; // duration of the polling period
+ uint8_t modeInLog; // the number of different power mode in the polling period
+ ChomCpiData_t cpiData[MAX_OCCS]; // Chip Packing Interface data, 5 bytes per processor
+ uint16_t numSensors; // the number of sensors for which call home data was collected
+} __attribute__ ((__packed__));
+
+typedef struct ChomNodeData ChomNodeData_t;
+
+/* Call home sensor data */
+struct ChomSensorData
+{
+ ChomPwrMode_t pwrMode;
+ ChomSensor_t sensor[CHOM_NUM_OF_SENSORS];
+}__attribute__ ((__packed__));
+
+typedef struct ChomSensorData ChomSensorData_t;
+
+/* Call home log data */
+struct ChomLogData
+{
+ ChomNodeData_t nodeData; // general node data
+ ChomSensorData_t sensorData[2]; // sensors data (current and previous power mode)
+}__attribute__ ((__packed__));
+
+typedef struct ChomLogData ChomLogData_t;
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern uint32_t g_chom_gen_periodic_log_timer;
+extern ChomLogData_t * g_chom;
+extern uint8_t g_chom_force;
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+void chom_data_init();
+void chom_update_sensors();
+void chom_gen_periodic_log();
+void chom_data_reset();
+void chom_force_gen_log();
+void chom_main();
+
+#endif //_CHOM_H
diff --git a/src/occ/thread/test/Makefile b/src/occ/thread/test/Makefile
new file mode 100755
index 0000000..2a4133b
--- /dev/null
+++ b/src/occ/thread/test/Makefile
@@ -0,0 +1,60 @@
+# $Id$
+
+# @file Makefile
+#
+# @brief Makefile occ application
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+
+threadtest_CFILES = \
+ ../../common.c \
+ ../../errl/errl.c \
+ ../threadSch.c \
+ threadtest.c
+
+all_cfiles = ${threadtest_CFILES}
+
+APP = threadtest
+APP_INCLUDES += -I../../../ssx
+APP_INCLUDES += -I../../../lib
+APP_INCLUDES += -I../../incl
+APP_INCLUDES += -I../../trac
+APP_INCLUDES += -I../../errl
+APP_INCLUDES += -I../../thread
+APP_INCLUDES += -I../../aplt/incl
+APP_INCLUDES += -I.
+
+
+
+#D = -DVERIFICATION=1 \
+ -DSSX_STACK_CHECK=0 \
+ -DINITIALIZE_PMC=0 \
+ -DINITIALIZE_SIMICS_IO=0 \
+ -DINITIALIZE_RTX_IO=1 \
+ -DINITIALIZE_PBA=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DSSX_KERNEL_TRACE_ENABLE=1
+
+
+SOURCES = ${all_cfiles}
+MODE = validation
+
+PGP_ASYNC_SUPPORT = 1
+
+include ./app.mk
+
+pgas:
+ $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10'
diff --git a/src/occ/thread/test/app.mk b/src/occ/thread/test/app.mk
new file mode 100755
index 0000000..c50c029
--- /dev/null
+++ b/src/occ/thread/test/app.mk
@@ -0,0 +1,101 @@
+# $Id$
+
+# @file app.mk
+#
+# @brief mk occ application
+#
+# This Makefile is included-ed into application Makefiles and
+# encapsulates the steps necessary to create application images.
+#
+# The application Makefile (user) must define the following variables:
+#
+# APP - The name of the application
+# SOURCES - The list of local source files that implement the
+# application.
+#
+# The application Makefile (user) may optionally define the following
+# variables:
+#
+# D - The value of $(D) is appended to DEFS defined by ssx.mk
+#
+# MODE - The following modes are recognized:
+#
+# validation - (Default) An application that requires all SSX
+# services.
+#
+# firmware - An interrupt only configuration.
+#
+# The make process creates the following files:
+#
+# $(APP).out - The PowerPC-ELF version of the application
+# $(APP).bin - A binary SRAM image of the application
+# $(APP).map - The linker map of the application
+#
+# @page ChangeLogs Change Logs
+# @section app.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+
+OCC = ../../
+SSX = ../../../ssx
+LIB = ../../../lib
+PGP = $(SSX)/pgp
+
+ifeq "$(MODE)" "firmware"
+SSX_TIMER_SUPPORT = 0
+SSX_THREAD_SUPPORT = 0
+endif
+
+export SSX_TIMER_SUPPORT
+export SSX_THREAD_SUPPORT
+export PPC405_MMU_SUPPORT
+export PGP_ASYNC_SUPPORT
+
+INCLUDES = -I $(OCC) -I$(LIB)
+
+include $(PGP)/ssx.mk
+
+C-OBJECTS = $(SOURCES:.c=.o)
+OBJECTS = $(C-OBJECTS:.S=.o)
+
+LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \
+ -L $(OCC) -L $(LIB) -lssx -lppc32
+
+DEFS += $(D)
+
+all: $(OBJECTS) libssx.a
+ $(MAKE) -C $(PGP) DEFS="$(DEFS)" -e
+ $(CPP) -P $(DEFS) < $(OCC)/linkocc.cmd > linkscript
+ $(LD) $(OBJECTS) \
+ -Tlinkscript $(LDFLAGS) -Map $(APP).map -Bstatic -o $(APP).out
+ $(OBJCOPY) -O binary $(APP).out $(APP).bin
+ $(OBJDUMP) -d $(APP).out > $(APP).dis
+
+libssx.a:
+ $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e
+
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map linkscript
+ rm -f ./*/*.o ./*/*.d ./*/*.d.*
+
+.PHONY : clean_all
+clean_all:
+ $(MAKE) clean
+ $(MAKE) -C $(PGP) clean
+
+.PHONY : doc
+doc:
+ doxygen doc/Doxyfile
+
+include $(OBJECTS:.o=.d)
diff --git a/src/occ/thread/test/threadtest.c b/src/occ/thread/test/threadtest.c
new file mode 100755
index 0000000..abf09b5
--- /dev/null
+++ b/src/occ/thread/test/threadtest.c
@@ -0,0 +1,398 @@
+/******************************************************************************
+// @file threadtest.c
+// @brief OCC THREAD TEST MAIN FUNCTION
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section threadtest.c THREADTEST.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @dw000 dwoodham 12/12/2011 Update call to IMAGE_HEADER; Added change log
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include <errl.h>
+#include <rand.h>
+#include <thread.h>
+#include <threadSch.h>
+#include <appletId.h> // @dw000a
+
+
+/** \mainpage OCC Overview
+ *
+ * Some general info.
+ *
+ * This manual is divided in the following sections:
+ * - \subpage Timer
+ */
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern void __ssx_boot;
+
+//*************************************************************************
+// Image Header
+//*************************************************************************
+// @dw000c
+IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,OCC_APLT_TEST);
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+/// Period in which to run #timer_routine
+#define TIMER_INTERVAL (SsxInterval) SSX_MICROSECONDS(5000)
+
+
+/*----------------------------------------------------------------------------*/
+/* SsxSemaphore Declarations */
+/*----------------------------------------------------------------------------*/
+SsxSemaphore prcd_sem;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+int g_j = 0;
+int g_k = 0;
+/*----------------------------------------------------------------------------*/
+/* noncrtical/critical stack */
+/*----------------------------------------------------------------------------*/
+uint8_t noncritical_stack[NONCRITICAL_STACK_SIZE];
+uint8_t critical_stack[CRITICAL_STACK_SIZE];
+SimicsStdio simics_stdout;
+SimicsStdio simics_stderr;
+
+SsxTimer G_test_timer;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+extern void timer_routine(void *private);
+extern void rtloop_ocb_init(void);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: pgp_validation_ssx_main_hook
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void pgp_validation_ssx_main_hook(void)
+{
+
+}
+
+// Function Specification
+//
+// Name: Cmd_Hndl_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+//TODO placeholder
+void Cmd_Hndl_thread_routine(void *arg)
+{
+ do
+ {
+ int x=0;
+ for(x=0; x < 1000; x++)
+ {
+
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: App_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void App_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: Thermal_Monitor_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Thermal_Monitor_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: Hlth_Monitor_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void Hlth_Monitor_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: FFDC_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void FFDC_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+
+/** Main Thread
+ *
+ * This thread currently just loops as the lowest priority thread, handling
+ * the lowest priority tasks.
+ *
+ */
+// Function Specification
+//
+// Name: main_thread_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void main_thread_routine(void *private)
+{
+ // Start the critical 250uS timer
+ ssx_timer_schedule(&timer, 1, TIMER_INTERVAL);
+
+ while(1)
+ {
+ // Only trace the first XX times that this function loops
+ if(g_k < 3)
+ {
+ g_k++;
+
+ // TRACE: Main Thread
+ }
+
+ // Sleep for 1000 before we run the loop again
+ ssx_sleep_absolute(1000);
+ }
+}
+
+// Function Specification
+//
+// Name: timer_routine
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void timer_routine (void *arg)
+{
+
+}
+
+// Function Specification
+//
+// Name: dump_thread_info
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void dump_thread_info(void *arg)
+{
+
+ printf("dumping thread info--------------------------\n");
+ int l_rc = 0;
+ SsxThreadState l_state = 0;
+ SsxThreadPriority l_pri = 0;
+ int l_runnable=0;
+ int x=0;
+ for(x=0; x < THREADS_TO_SCHEDULE; x++)
+ {
+ l_rc = ssx_thread_info_get(G_scheduledThreads[x],
+ &l_state,
+ &l_pri,
+ &l_runnable);
+
+ printf("Thread %p: State %x priority %x runnable %x rc %x Global index %x\n",G_scheduledThreads[x],
+ l_state,
+ l_pri,
+ l_runnable,
+ l_rc,
+ G_threadSchedulerIndex);
+
+ }
+
+}
+
+/** Entry point for OCC execution
+ *
+ * main() currently initalizes our trace buffer along with creating threads
+ * and timers for execution. Note that once main runs ssx_start_threads, we
+ * never return as the SSX kernel takes over.
+ *
+ */
+// Function Specification
+//
+// Name: main
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+int main(int argc, char **argv)
+{
+ //locals
+ errlHndl_t l_errl = INVALID_ERR_HNDL;
+
+ // Initialize Trace Buffers immediately, so they can be used
+ // from this point on.
+
+ // Initialize stdout so we can do printf from within simics env
+ simics_stdout_create(&simics_stdout);
+ simics_stderr_create(&simics_stderr);
+ stdout = (FILE *)(&simics_stdout);
+ stderr = (FILE *)(&simics_stderr);
+
+ // Initialize SSX Stacks (note that this also reinitializes the time base to 0)
+ ssx_initialize((SsxAddress)noncritical_stack, NONCRITICAL_STACK_SIZE,
+ (SsxAddress)critical_stack, CRITICAL_STACK_SIZE,
+ 0);
+
+
+
+ // Create Global Semaphores
+ ssx_semaphore_create(&prcd_sem, 0, 13);
+
+ ssx_timer_create(&timer, timer_routine, 0);
+
+// //create thread with already mapped priority
+// // Create Threads
+ ssx_thread_create(&main_thread,
+ main_thread_routine,
+ (void *)0,
+ (SsxAddress)main_thread_stack,
+ THREAD_STACK_SIZE,
+ 0);
+
+
+ // Make Threads runnable
+ ssx_thread_resume(&main_thread);
+
+
+ //Initialize the thread scheduler
+ l_errl = initThreadScheduler();
+
+ if(l_errl)
+ {
+ // Trace and commit error
+
+ // TODO add trace
+
+ // commit log
+ // NOTE: log should be deleted by reader mechanism
+ commitErrl( &l_errl );
+ }
+
+
+ //kick off timer
+ ssx_timer_create(&G_test_timer, dump_thread_info, 0);
+ ssx_timer_schedule(&G_test_timer, 1, 500000000);
+
+
+ // Enter SSX Kernel
+ ssx_start_threads();
+
+ return 0;
+}
+
diff --git a/src/occ/thread/thread.h b/src/occ/thread/thread.h
new file mode 100755
index 0000000..2a28107
--- /dev/null
+++ b/src/occ/thread/thread.h
@@ -0,0 +1,133 @@
+/******************************************************************************
+// @file thread.h
+// @brief OCC THREAD COMPONENT header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _thread_h thread.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * abagepa 07/15/2011 Created Threads definition header
+ * @pb004 pbavari 09/12/2011 Test applet thread support
+ * @pb009 pbavari 10/20/2011 Removed unused thread related data
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @th022 thallet 10/03/2012 Changes to allow DCOM State/Mode setting
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _THREAD_H
+#define _THREAD_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include "ssx.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// Thread priorities for Thread creation.
+typedef enum
+{
+ THREAD_PRIORITY_0, //reserved for high priority
+ THREAD_PRIORITY_1, //reserved for high priority
+ THREAD_PRIORITY_2,
+ THREAD_PRIORITY_3,
+ THREAD_PRIORITY_4,
+ THREAD_PRIORITY_5,
+ THREAD_PRIORITY_6,
+ THREAD_PRIORITY_7,
+ THREAD_PRIORITY_8,
+}THREAD_PRIORITY;
+
+/*----------------------------------------------------------------------------*/
+/* Stack Size and Declaration */
+/*----------------------------------------------------------------------------*/
+
+/** \defgroup Stack Stack Information
+ * Stack sizes are defined by entity
+ * - Non-Critical Stack used by non-critical interrupt handlers, including timer callbacks
+ * - Critical Stack used for critical interrupts
+ * - Stacks for each thread
+ */
+
+#define NONCRITICAL_STACK_SIZE 8192 // 8kB
+#define CRITICAL_STACK_SIZE 4096 // 4kB
+#define THREAD_STACK_SIZE 4096 // 4kB
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+/*@{*/
+extern uint8_t main_thread_stack[THREAD_STACK_SIZE];
+extern uint8_t Cmd_hndl_thread_stack[THREAD_STACK_SIZE];
+extern uint8_t App_thread_stack[THREAD_STACK_SIZE];
+//@pb004a - added
+extern uint8_t testAppletThreadStack[THREAD_STACK_SIZE];
+
+/*@}*/ // Ending tag for stack module in doxygen
+
+/*----------------------------------------------------------------------------*/
+/*SsxTimer and SsxThread Declarations */
+/*----------------------------------------------------------------------------*/
+/** \defgroup TimersAndThreads Timer and Thread Information */ /*@{*/
+
+/// Our timer based on TIMER_INTERVAL that kicks off most of the work. See #timer_routine
+//SsxTimer timer; // @tgh001 -- unused
+
+/// Our idle thread. See #main_thread_routine
+extern SsxThread Main_thread;
+
+//Command handler thread
+extern SsxThread Cmd_Hndl_thread;
+
+//Application manager thread
+extern SsxThread App_thread;
+
+//@pb004a - Test applet thread
+extern SsxThread TestAppletThread;
+
+//Application manager thread
+extern SsxThread Dcom_thread;
+
+/*@}*/ // Ending tag for TimersAndThreads module in doxygen
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+void Main_thread_routine(void *private);
+
+void Cmd_Hndl_thread_routine(void *arg);
+
+void App_thread_routine(void *arg);
+
+void Dcom_thread_routine(void *arg);
+
+//@pb004a -added
+void testAppletThreadRoutine(void *arg);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_THREAD_H
diff --git a/src/occ/thread/threadSch.c b/src/occ/thread/threadSch.c
new file mode 100755
index 0000000..e593747
--- /dev/null
+++ b/src/occ/thread/threadSch.c
@@ -0,0 +1,370 @@
+/******************************************************************************
+// @file threadSch.c
+// @brief OCC THREAD COMPONENT Thread Scheduler methods
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _threadSch_c threadSch.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * abagepa 07/15/2011 Created Thread Scheduler methods
+ * @pb004 pbavari 09/02/2011 Test applet thread support
+ * @pb009 pbavari 10/20/2011 Main thread support
+ * @th006 thallet 11/21/2011 RESET_REQUEST substituted for todo's
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th022 thallet 10/03/2012 Added DCOM Thread for State/Mode setting
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @fk004 907588 fmkassem 11/25/2013 Snapshot buffer support.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <threadSch.h>
+#include "ssx.h"
+#include "thread_service_codes.h"
+#include "occ_service_codes.h"
+#include <appletManager.h>
+#include <trac.h>
+#include <state.h>
+#include "cmdh_snapshot.h" // @fk004a
+
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+//Numbers of threads to schedule
+//@pb009c - Changed to use dynamic calculation
+#define THREADS_TO_SCHEDULE (sizeof(G_scheduledThreads)/sizeof(SsxThread*))
+
+//10 ms
+#define THREAD_TIME_SLICE (SsxInterval) SSX_MILLISECONDS(10)
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+/* Thread Timer to reprioritize the threads */
+SsxTimer G_threadSchTimer;
+
+//Index of highest priority thread in G_scheduledThreads
+uint16_t G_threadSchedulerIndex = 0;
+
+/* Array that holds the threads that need scheduling */
+//@pb009c - Removed not needed threads
+SsxThread* G_scheduledThreads[] =
+{
+ &Main_thread,
+ &Cmd_Hndl_thread,
+ &App_thread,
+ &TestAppletThread,
+ &Dcom_thread,
+};
+
+//Error log counter for the callback
+// so that only 1 error log is created
+uint8_t G_threadSwapErrlCounter = 0;
+
+// Global for the parameter to the applet thread routine
+OCC_APLT_TYPE G_apltPdtType = APLT_TYPE_PRODUCT;
+OCC_APLT_TYPE G_apltTestType = APLT_TYPE_TEST;
+
+//Thread Stacks
+uint8_t main_thread_stack[THREAD_STACK_SIZE];
+uint8_t Cmd_hndl_thread_stack[THREAD_STACK_SIZE];
+uint8_t App_thread_stack[THREAD_STACK_SIZE];
+uint8_t testAppletThreadStack[THREAD_STACK_SIZE];
+uint8_t dcomThreadStack[THREAD_STACK_SIZE];
+
+/// Our idle thread. See #main_thread_routine
+SsxThread Main_thread;
+
+//Command handler thread
+SsxThread Cmd_Hndl_thread;
+
+//Application manager thread
+SsxThread App_thread;
+
+//@pb004a - Test applet thread
+SsxThread TestAppletThread;
+
+//@thXXXa - Dcom thread
+SsxThread Dcom_thread;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: createAndResumeThreadHelper
+//
+// Description: create and resume thread helper
+//
+// Flow: FN=None
+//
+// End Function Specification
+int createAndResumeThreadHelper(SsxThread *io_thread,
+ SsxThreadRoutine i_thread_routine,
+ void *io_arg,
+ SsxAddress i_stack,
+ size_t i_stack_size,
+ THREAD_PRIORITY i_priority)
+{
+
+ //locals
+ int l_rc = SSX_OK;
+
+ //Thread creation
+ l_rc = ssx_thread_create(io_thread,
+ i_thread_routine,
+ io_arg,
+ i_stack,
+ i_stack_size,
+ (SsxThreadPriority)i_priority);
+
+ //check for errors creating a thread
+ if(l_rc != SSX_OK)
+ {
+ TRAC_ERR("Failure creating thread. rc: 0x%x", -l_rc);
+ }
+ else
+ {
+ //resume thread once created
+ l_rc = ssx_thread_resume(io_thread);
+ }
+
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: initThreadScheduler
+//
+// Description: Init the threads in the scheduler and start the
+// timer.
+//
+// Flow: 10/31/11 FN=initThreadScheduler
+//
+// End Function Specification
+// @pb009c - Removed not needed threads from the initialization
+void initThreadScheduler(void)
+{
+ //locals
+ int l_appThreadRc = SSX_OK;
+ int l_cmdThreadRc = SSX_OK;
+ int l_timerRc = SSX_OK;
+ int l_testAppletThreadRc = SSX_OK;
+ int l_dcomThreadRc = SSX_OK;
+ int l_snapshotTimerRc = SSX_OK;
+
+ //Creating threads that need to be scheduled
+ //Thread priority range should match scheduled
+ // threads in G_scheduledThreads ie highest priority thread should be
+ // index 0 of G_scheduledThreads
+
+ l_cmdThreadRc = createAndResumeThreadHelper(&Cmd_Hndl_thread,
+ Cmd_Hndl_thread_routine,
+ (void *)0,
+ (SsxAddress)Cmd_hndl_thread_stack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_3);
+
+ l_appThreadRc = createAndResumeThreadHelper(&App_thread,
+ App_thread_routine,
+ (void *)&G_apltPdtType,
+ (SsxAddress)App_thread_stack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_4);
+
+ l_testAppletThreadRc = createAndResumeThreadHelper(&TestAppletThread,
+ App_thread_routine,
+ (void *)&G_apltTestType,
+ (SsxAddress)testAppletThreadStack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_5);
+
+ l_dcomThreadRc = createAndResumeThreadHelper(&Dcom_thread,
+ Dcom_thread_routine,
+ (void *)0,
+ (SsxAddress)dcomThreadStack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_6);
+
+ //create the thread scheduler timer
+ l_timerRc = ssx_timer_create(&G_threadSchTimer, threadSwapcallback, 0);
+
+ //check for errors creating the timer
+ if(l_timerRc == SSX_OK)
+ {
+ TRAC_INFO("timer created and scheduled");
+ //schedule the timer so that it runs every THREAD_TIME_SLICE
+ l_timerRc = ssx_timer_schedule(&G_threadSchTimer, 1, THREAD_TIME_SLICE);
+ }
+ else
+ {
+ TRAC_INFO("Error creating timer: RC: %d", l_timerRc);
+ }
+
+ //Create snapshot timer
+ l_snapshotTimerRc = ssx_timer_create(&G_snapshotTimer, cmdh_snapshot_callback, 0);
+
+ //check for errors creating the timer
+ if(l_snapshotTimerRc == SSX_OK)
+ {
+ //TRAC_INFO("snapshot buffer timer created and scheduled every 30 seconds");
+ //schedule the timer so that it runs every 30 seconds.
+ l_snapshotTimerRc = ssx_timer_schedule(&G_snapshotTimer, 0, SSX_SECONDS(30));
+ if (l_snapshotTimerRc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_snapshot_sync: reseting the snapshot timer failed.");
+
+ }
+ }
+ else
+ {
+ TRAC_INFO("Error creating timer: RC: %d", l_snapshotTimerRc);
+ }
+
+
+ //If there are any errors creating the threads or starting the
+ //timer create an error log to pass back.
+ if( l_appThreadRc
+ || l_testAppletThreadRc
+ || l_cmdThreadRc
+ || l_dcomThreadRc
+ || l_timerRc
+ || l_snapshotTimerRc )
+ {
+ TRAC_ERR("Error creating thread: l_appThreadRc: %d, "
+ "l_testAppletThreadRc: %d, l_cmdThreadRc: %d, "
+ "l_dcomThreadRc: %d", l_appThreadRc,l_testAppletThreadRc,
+ l_timerRc,l_cmdThreadRc,l_dcomThreadRc);
+ TRAC_ERR("Error starting timers: timerRc: %d, snapshotTimerRc: %d.",
+ l_timerRc, l_snapshotTimerRc);
+ // Create error log and log it
+ // TODO use correct trace
+ tracDesc_t l_trace = NULL;
+
+ /* @
+ * @errortype
+ * @moduleid THRD_MID_INIT_THREAD_SCHDLR
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Schedule timer return code
+ * @userdata2 Snapshot timer return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX thread related failure
+ */
+ errlHndl_t l_rc = createErrl(THRD_MID_INIT_THREAD_SCHDLR, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_timerRc, //userdata1
+ l_snapshotTimerRc); //userdata2
+
+ REQUEST_RESET(l_rc); // @gm006
+ }
+}
+
+
+// Function Specification
+//
+// Name: threadSwapcallback
+//
+// Description: a periodic timer callback to swap prorities of scheduled threads
+//
+// Flow: 07/16/11 FN=threadSwapcallback
+//
+// End Function Specification
+void threadSwapcallback(void * arg)
+{
+ //locals
+ int l_rc = SSX_OK;
+
+ //current location of index in scheduled thread array
+ int l_threadAIndex = G_threadSchedulerIndex;
+
+ //if global index == last item swap priorities with 1st
+ int l_threadBIndex = (G_threadSchedulerIndex == (THREADS_TO_SCHEDULE-1)) ? 0 : ++G_threadSchedulerIndex;
+
+ //swap priorities with global index +1
+ l_rc = ssx_thread_priority_swap(G_scheduledThreads[l_threadAIndex],G_scheduledThreads[l_threadBIndex]);
+
+ if(l_rc != SSX_OK)
+ {
+ //TODO trace error
+
+ //create and commit error log
+ if(G_threadSwapErrlCounter == 0)
+ {
+ // TODO use correct trace
+ tracDesc_t l_trace = NULL;
+
+ /*
+ * @errortype
+ * @moduleid THRD_MID_THREAD_SWAP_CALLBACK
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Return code of thread priority swap
+ * @userdata2 Current location of index in scheduled thread array
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX thread related failure
+ */
+ errlHndl_t l_err = createErrl(
+ THRD_MID_THREAD_SWAP_CALLBACK, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ l_trace, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_rc, //userdata1
+ l_threadAIndex //userdata2
+ );
+
+ // commit log
+ // NOTE: log should be deleted by reader mechanism
+ commitErrl( &l_err );
+
+ //Increment errl counter
+ G_threadSwapErrlCounter++;
+
+ }//end thread swap counter if
+ }
+ else
+ {
+ //reset counter since it started working again
+ G_threadSwapErrlCounter = 0;
+
+ //set the global to the new location of the highest priority thread
+ G_threadSchedulerIndex = l_threadBIndex;
+ }
+}
+
diff --git a/src/occ/thread/threadSch.h b/src/occ/thread/threadSch.h
new file mode 100755
index 0000000..c457646
--- /dev/null
+++ b/src/occ/thread/threadSch.h
@@ -0,0 +1,83 @@
+/******************************************************************************
+// @file threadSch.h
+// @brief OCC THREAD COMPONENT Thread Scheduler header file
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _threadSch_h threadSch.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * abagepa 07/15/2011 Created Thread scheduler methods
+ * @01 tapiar 08/05/2011 Moved define to common.h
+ * @pb004 pbavari 09/02/2011 Initialize section support
+ * @pb009 pbavari 10/20/2011 Main thread support
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _THREADSCH_H
+#define _THREADSCH_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <thread.h>
+#include "ssx.h"
+#include <errl.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+/* Function to reprioritize the threads in the array */
+void threadSwapcallback(void * arg);
+
+/* Function to initilize the threads and the thread schedule timer */
+//@pb009c - Changed to return void and handle error internally similar to other
+// calls from main thread
+void initThreadScheduler(void) INIT_SECTION;
+
+//@pb009a - Made function available to used by other components (used by main)
+/* Function to create and resume thread. Externalizing as it is used to
+ * create main thread
+ */
+int createAndResumeThreadHelper(SsxThread *io_thread,
+ SsxThreadRoutine i_thread_routine,
+ void *io_arg,
+ SsxAddress i_stack,
+ size_t i_stack_size,
+ THREAD_PRIORITY i_priority);
+
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_THREADSCH_H
diff --git a/src/occ/thread/thread_service_codes.h b/src/occ/thread/thread_service_codes.h
new file mode 100755
index 0000000..1569fb7
--- /dev/null
+++ b/src/occ/thread/thread_service_codes.h
@@ -0,0 +1,79 @@
+/******************************************************************************
+// @file thread_service_codes.h
+// @brief Error codes for thread component.
+*
+* Note that the thread component will not actually generate errors
+* using the thread component. This is due to the fact that will
+* use trace so therefore we can induce non-ending recursion if trace
+* were to use ERRL.
+*
+* A trace failure is not a system critical failure which is why we
+* can get away with it not reporting errors.
+*
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _thread_service_codes_h thread_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 06/16/2010 Port
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @jh005 894560 joshych 08/14/2013 Create call home data logs every 24 hours
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+ * @fk006 914801 fmkassem 02/05/2014 Remove reason code list and merge with occ_service_codes list
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _THREAD_SERVICE_CODES_H_
+#define _THREAD_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum thrdModuleId
+{
+ THRD_MID_INIT_THREAD_SCHDLR = THRD_COMP_ID | 0x00,
+ THRD_MID_THREAD_SWAP_CALLBACK = THRD_COMP_ID | 0x01,
+ THRD_MID_GEN_CALLHOME_LOG = THRD_COMP_ID | 0x02,
+ THRD_THERMAL_VRM_FAN_CONTROL = THRD_COMP_ID | 0x03,
+ THRD_THERMAL_MAIN = THRD_COMP_ID | 0x04, // @at023a
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _THREAD_SERVICE_CODES_H_ */
diff --git a/src/occ/thread/thrm_thread.c b/src/occ/thread/thrm_thread.c
new file mode 100755
index 0000000..5db89f9
--- /dev/null
+++ b/src/occ/thread/thrm_thread.c
@@ -0,0 +1,538 @@
+/******************************************************************************
+// @file thrm_thread.c
+// @brief OCC thermal thread firmware.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _thrm_thread_c thrm_thread.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @gs019 gjsilva 11/21/2013 Created
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ * @gm017 909636 milesg 12/17/2013 Memory fan control
+ * @gs021 909855 gjsilva 12/18/2013 Support for processor OT condition
+ * @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @gm026 916029 milesg 02/17/2014 revert back to auto2 mode without reading GPIO's
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <cmdh_fsp_cmds_datacnfg.h>
+#include <thrm_thread.h>
+#include <trac.h>
+#include <state.h>
+#include <occ_service_codes.h>
+#include <thread_service_codes.h>
+#include <occ_sys_config.h> // @at023a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+// Global for notifying the thermal thread if it needs to update its copy
+// of the thermal threshold data packet (format 0x13)
+BOOLEAN G_thrm_parms_need_update = FALSE;
+
+// Fan control loop time in seconds sent by TMGT (format 0x13)
+uint8_t G_thrm_loop_time = 0;
+
+// Cooling request status (0=no request; 1=send request)
+uint8_t G_thrm_cooling_request = 0;
+
+// Local copy of thermal thresholds sent by TMGT (format 0x13)
+thrm_fru_control_t G_thrm_fru_control[DATA_FRU_MAX];
+
+// Global array to store dynamic information for each FRU
+thrm_fru_data_t G_thrm_fru_data[DATA_FRU_MAX];
+
+//*************************************************************************
+// Function Declarations
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: THRM_thread_update_thresholds
+//
+// Description: Notify thermal thread to update its local copy of the
+// thermal threshold data packet.
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+void THRM_thread_update_thresholds()
+{
+ G_thrm_parms_need_update = TRUE;
+}
+
+// Function Specification
+//
+// Name: THRM_thread_get_cooling_request
+//
+// Description: Get the status of the cooling request from the thermal
+// thread.
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+uint8_t THRM_thread_get_cooling_request()
+{
+ return G_thrm_cooling_request;
+}
+
+// Function Specification
+//
+// Name: thrm_thread_load_thresholds
+//
+// Description: Read thermal thresholds sent by TMGT (data format 0x13)
+// and store them for thermal thread consumption.
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+errlHndl_t thrm_thread_load_thresholds()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ cmdh_thrm_thresholds_t *l_data = NULL;
+ uint8_t i = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ // Get thermal threshold data sent by TMGT
+ l_err = DATA_get_thrm_thresholds(&l_data);
+ if(l_err)
+ {
+ TRAC_ERR("thrm_thread_load_thresholds: Thermal control thresholds not available!");
+
+ // This is a critical failure since we can't run the fan control
+ // without the thermal thresholds. Make the fan control loop time
+ // zero so that we don't execute any fan control
+ G_thrm_loop_time = 0;
+ break;
+ }
+
+ // Load fan control loop time
+ G_thrm_loop_time = l_data->fan_control_loop_time;
+
+ TRAC_INFO("thrm_thread_load_thresholds: Fan Control loop time[%u]",
+ G_thrm_loop_time);
+
+ // Load FRU data
+ for (i=0; i<DATA_FRU_MAX; i++)
+ {
+ // Load data that is not dependant on the system mode
+ G_thrm_fru_control[i].warning = l_data->data[i].warning;
+ G_thrm_fru_control[i].warning_reset = l_data->data[i].warning_reset;
+ G_thrm_fru_control[i].t_inc_zone[0] = l_data->data[i].t_inc_zone1;
+ G_thrm_fru_control[i].t_inc_zone[1] = l_data->data[i].t_inc_zone2;
+ G_thrm_fru_control[i].t_inc_zone[2] = l_data->data[i].t_inc_zone3;
+ G_thrm_fru_control[i].t_inc_zone[3] = l_data->data[i].t_inc_zone4;
+ G_thrm_fru_control[i].t_inc_zone[4] = l_data->data[i].t_inc_zone5;
+ G_thrm_fru_control[i].t_inc_zone[5] = l_data->data[i].t_inc_zone6;
+ G_thrm_fru_control[i].t_inc_zone[6] = l_data->data[i].t_inc_zone7;
+ G_thrm_fru_control[i].t_inc_zone[7] = l_data->data[i].t_inc_zone8;
+
+ // Load data that depends on the system mode
+ // Acoustic mode takes priority
+ if (0) // FIXME: Need to implement acoustic mode
+ {
+ G_thrm_fru_control[i].t_control = l_data->data[i].acoustic_t_control;
+ G_thrm_fru_control[i].error = l_data->data[i].acoustic_error;
+ }
+ // ...then nominal mode
+ else if (CURRENT_MODE() == OCC_MODE_NOMINAL)
+ {
+ G_thrm_fru_control[i].t_control = l_data->data[i].t_control;
+ G_thrm_fru_control[i].error = l_data->data[i].error;
+ }
+ // ...then any other power management mode
+ else
+ {
+ G_thrm_fru_control[i].t_control = l_data->data[i].pm_t_control;
+ G_thrm_fru_control[i].error = l_data->data[i].pm_error;
+ }
+
+ TRAC_INFO("thrm_thread_load_thresholds: Using t_control[%u] error[%u] for FRU[0x%02X]",
+ G_thrm_fru_control[i].t_control,
+ G_thrm_fru_control[i].error,
+ i);
+
+ // For debug only...
+ //TRAC_INFO("DBUG: Zone1[%u] Zone2[%u] Zone3[%u] Zone4[%u] Zone5[%u]",
+ // G_thrm_fru_control[i].t_inc_zone[0],
+ // G_thrm_fru_control[i].t_inc_zone[1],
+ // G_thrm_fru_control[i].t_inc_zone[2],
+ // G_thrm_fru_control[i].t_inc_zone[3],
+ // G_thrm_fru_control[i].t_inc_zone[4]);
+ }
+ }while(0);
+
+ return(l_err);
+
+}
+
+
+// Function Specification
+//
+// Name: thrm_thread_fan_control
+//
+// Description: Execute the fan control algorithm for the specified FRU.
+// Returns TRUE or FALSE depending whether we need to increase fan speeds
+// or not.
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+BOOLEAN thrm_thread_fan_control(const uint8_t i_fru_type,
+ const uint16_t i_fru_temperature)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ eConfigDataFruType k = i_fru_type;
+ BOOLEAN l_IncreaseFans = FALSE;
+ uint8_t i = 0;
+ uint16_t l_delta_temp = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ //If there's a read error, assume temperature is t_control + 1 -- gm017
+ if(G_thrm_fru_data[k].read_failure)
+ {
+ G_thrm_fru_data[k].Tcurrent = G_thrm_fru_control[k].t_control + 1;
+ }
+ else
+ {
+ // Collect the current FRU temperature
+ G_thrm_fru_data[k].Tcurrent = i_fru_temperature;
+ }
+
+ // Is the current FRU temperature bigger than the FRU T_control?
+ if (G_thrm_fru_data[k].Tcurrent > G_thrm_fru_control[k].t_control)
+ {
+ // Is the current temperature below the previous temperature?
+ if (G_thrm_fru_data[k].Tcurrent < G_thrm_fru_data[k].Tprevious)
+ {
+ // Temperature is decreasing so we don't need to request any
+ // additional cooling
+ G_thrm_fru_data[k].temp_increasing = FALSE;
+ }
+ else if (G_thrm_fru_data[k].Tcurrent > G_thrm_fru_data[k].Tprevious)
+ {
+ // Temperature is increasing and we need to request more cooling
+ G_thrm_fru_data[k].temp_increasing = TRUE;
+ l_IncreaseFans = TRUE;
+ }
+ else
+ {
+ // Temperature is the same as previous iteration. Check the trend
+ // to see whether is increasing or decreasing
+ if (G_thrm_fru_data[k].temp_increasing == TRUE)
+ {
+ // Need to request additional cooling
+ l_IncreaseFans = TRUE;
+ }
+ else
+ {
+ // No need to request additional cooling
+ }
+ }
+ }
+
+ // Prepare the cooling requests for all Zones
+ l_delta_temp = G_thrm_fru_data[k].Tcurrent - G_thrm_fru_control[k].t_control;
+
+ if (l_IncreaseFans == TRUE)
+ {
+ for (i = 0; i < THRM_MAX_NUM_ZONES; i++)
+ {
+ G_thrm_fru_data[k].FanIncZone[i] = l_delta_temp *
+ G_thrm_fru_control[k].t_inc_zone[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < THRM_MAX_NUM_ZONES; i++)
+ {
+ G_thrm_fru_data[k].FanIncZone[i] = 0;
+ }
+ }
+
+ // Store the current temperature for next iteration
+ G_thrm_fru_data[k].Tprevious = G_thrm_fru_data[k].Tcurrent;
+
+ return(l_IncreaseFans);
+}
+
+
+// Function Specification
+//
+// Name: thrm_thread_vrm_fan_control
+//
+// Description: Execute the fan control algorithm for VRM based on the
+// VR_FAN signal. Returns TRUE or FALSE depending whether we need to increase
+// fan speeds or not.
+//
+// Flow: xx/xx/xx FN=
+//
+// End Function Specification
+BOOLEAN thrm_thread_vrm_fan_control(const uint16_t i_vrfan)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ BOOLEAN l_IncreaseFans = FALSE;
+ static BOOLEAN L_error_logged = FALSE;
+ uint8_t i = 0;
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ if ((i_vrfan == 1) || (G_thrm_fru_data[DATA_FRU_VRM].read_failure == 1))
+ {
+ // If VR_FAN has been asserted or we cannot read it, request one T_INC
+ // for each zone to be controlled
+ l_IncreaseFans = TRUE;
+
+ for (i = 0; i < THRM_MAX_NUM_ZONES; i++)
+ {
+ G_thrm_fru_data[DATA_FRU_VRM].FanIncZone[i] =
+ G_thrm_fru_control[DATA_FRU_VRM].t_inc_zone[i];
+ }
+
+ // Log an informational error the first time VR_FAN was asserted (this
+ // is for manufacturing mode IPLs)
+ if (i_vrfan == 1)
+ {
+ if (!L_error_logged)
+ {
+ L_error_logged = TRUE;
+
+ TRAC_ERR("thrm_thread_vrm_fan_control: VR_FAN for this regulator has been asserted!");
+
+ /* @
+ * @errortype
+ * @moduleid THRD_THERMAL_VRM_FAN_CONTROL
+ * @reasoncode VRM_VRFAN_ASSERTED
+ * @userdata1 state of VR_FAN signal
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc VR_FAN signal from regulator has been asserted.
+ *
+ */
+ l_err = createErrl(THRD_THERMAL_VRM_FAN_CONTROL, //modId
+ VRM_VRFAN_ASSERTED, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_vrfan, //userdata1
+ 0); //userdata2
+
+ // Set the manufacturing error flag in the log
+ setErrlActions(l_err, ERRL_ACTIONS_MANUFACTURING_ERROR);
+
+ // Commit the error
+ commitErrl(&l_err);
+ }
+ }
+ }
+ else
+ {
+ // If VR_FAN is de-asserted, don't send any cooling requests
+ l_IncreaseFans = FALSE;
+
+ for (i = 0; i < THRM_MAX_NUM_ZONES; i++)
+ {
+ G_thrm_fru_data[DATA_FRU_VRM].FanIncZone[i] = 0;
+ }
+ }
+
+ return(l_IncreaseFans);
+}
+
+// Function Specification
+//
+// Name: thrm_thread_main
+//
+// Description: Main thermal thread routine
+//
+//
+// Flow: OCC Fan Control Loop (TMGT to OCC Interface Architecture, Version 2.0,
+// Section 4.2)
+//
+// End Function Specification
+void thrm_thread_main()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ errlHndl_t l_err = NULL;
+ BOOLEAN l_IncreaseFans = FALSE;
+ sensor_t *l_sensor = NULL;
+ static uint8_t L_counter = 0;
+ static BOOLEAN L_full_speed_log = FALSE; // @at023a
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Execute fan control loop if OCC is in observation state or active state
+ // AND if we have received the thermal threshold data packet
+ if (((CURRENT_STATE() == OCC_STATE_OBSERVATION) ||
+ (CURRENT_STATE() == OCC_STATE_ACTIVE)) &&
+ (DATA_get_present_cnfgdata() & DATA_MASK_THRM_THRESHOLDS))
+ {
+ // Check if we need to update our local copy of the thermal threshold
+ // data packet
+ if (G_thrm_parms_need_update)
+ {
+ // Clear this flag now that we are going to update our local copy
+ G_thrm_parms_need_update = FALSE;
+
+ // Update our local copy of the thermal thresholds
+ l_err = thrm_thread_load_thresholds();
+
+ if (l_err)
+ {
+ // Commit error log for failing to load thermal thresholds
+ commitErrl(&l_err);
+ }
+ else
+ {
+ // Clear our counter that determines when to run the fan
+ // control loop
+ L_counter = 0;
+ }
+ }
+
+ // Increment our counter and make sure it doesn't wrap
+ L_counter++;
+ // The fan control loop time is only 1-byte long. A loop time of 0
+ // indicates that we shouldn't run the fan control loop.
+ if (L_counter == 0)
+ {
+ L_counter = 0xFF;
+ }
+
+ // Is it time to execute the fan control loop?
+ if (L_counter == G_thrm_loop_time)
+ {
+ // Reset our counter
+ L_counter = 0;
+
+ // Determine if additional cooling is required for VRMs
+ l_sensor = getSensorByGsid(VRFAN250USPROC);
+ l_IncreaseFans |= thrm_thread_vrm_fan_control(l_sensor->sample);
+
+ // Determine if additional cooling is required for processors
+ // For processors, use the hottest of the core averages
+ l_sensor = getSensorByGsid(TEMP2MSP0PEAK);
+ l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_PROC,
+ l_sensor->sample);
+
+ // Determine if additional cooling is required for centaurs -- gm017
+ l_sensor = getSensorByGsid(TEMP2MSCENT);
+ l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_CENTAUR,
+ l_sensor->sample);
+
+ // Determine if additional cooling is required for dimms -- gm017
+ l_sensor = getSensorByGsid(TEMP2MSDIMM);
+ l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_DIMM,
+ l_sensor->sample);
+
+ //For debug only...
+ //TRAC_INFO("DBUG: Cooling requests Zone1[%u] Zone2[%u] Zone3[%u]",
+ // G_thrm_fru_data[0].FanIncZone[0],
+ // G_thrm_fru_data[0].FanIncZone[1],
+ // G_thrm_fru_data[0].FanIncZone[2]);
+
+ // Do we need to request a fan increase?
+ if (l_IncreaseFans == TRUE)
+ {
+ // Set 'Cooling Request' for the poll response
+ G_thrm_cooling_request = 1;
+
+ // Send 'Service' attention to FSP to force TMGT to send poll
+ // command
+ cmdh_fsp_attention(OCC_ALERT_FSP_SERVICE_REQD);
+
+ // @at023a - start
+ // Check if fans are currently already at max (known from APSS)
+ // log informational B1812A08 and have the "Manufacturing error"
+ // bit in the actions field set so that TMGT will flag this in manufacturing.
+ // ** No longer reading gpio from APSS in GA1 due to instability in APSS composite mode -- gm026
+ uint8_t l_full_speed = 1; //low active
+ //uint8_t l_full_speed_pin = G_sysConfigData.apss_gpio_map.fans_full_speed; //gm026
+ if( (L_full_speed_log == FALSE) &&
+ FALSE) //apss_gpio_get(l_full_speed_pin,&l_full_speed) ) //gm026
+ {
+ if(l_full_speed == 0) //low active
+ {
+ L_full_speed_log = TRUE; // log this error ONLY ONCE per IPLL
+ TRAC_ERR("thrm_thread_main: Request a fan increase and fan is already in full speed");
+
+ /* @
+ * @errortype
+ * @moduleid THRD_THERMAL_MAIN
+ * @reasoncode FAN_FULL_SPEED
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Request a fan increase and fan is already in full speed
+ *
+ */
+ l_err = createErrl(THRD_THERMAL_MAIN, //modId
+ FAN_FULL_SPEED, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ // Set the manufacturing error flag in the log
+ setErrlActions(l_err, ERRL_ACTIONS_MANUFACTURING_ERROR);
+ commitErrl(&l_err);
+ }
+ }
+ // @at023a - end
+ }
+ else
+ {
+ // Reset the 'Cooling Request' since we don't need a fan increase
+ G_thrm_cooling_request = 0;
+ }
+ }
+ }
+}
diff --git a/src/occ/thread/thrm_thread.h b/src/occ/thread/thrm_thread.h
new file mode 100755
index 0000000..55eff7f
--- /dev/null
+++ b/src/occ/thread/thrm_thread.h
@@ -0,0 +1,70 @@
+/**
+ * @file thrm_thread.h
+ * @brief Header file for thermal thread.
+ *
+ *
+*/
+/**
+ * @page ChangeLogs Change Logs
+ * @section _thrm_thread_h thrm_thread.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- --------- ----------------------------------
+ * @gs019 gjsilva 11/21/2013 Created
+ * @gs020 909320 gjsilva 12/12/2013 Support for VR_FAN thermal control
+ *
+ * @endverbatim
+ */
+#ifndef THRM_THREAD_H
+#define THRM_THREAD_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define THRM_MAX_NUM_ZONES 8
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+typedef struct thrm_fru_control
+{
+ uint8_t t_control;
+ uint8_t error;
+ uint8_t warning;
+ uint8_t warning_reset;
+ uint16_t t_inc_zone[THRM_MAX_NUM_ZONES];
+}thrm_fru_control_t;
+
+typedef struct thrm_fru_data
+{
+ // Flag to indicate that we have timed out trying to read this thermal sensor
+ uint8_t read_failure;
+ // Current temperature of this FRU
+ uint16_t Tcurrent;
+ // Previous temperature of this FRU
+ uint16_t Tprevious;
+ // Coooling requests to be sent back to TMGT
+ uint16_t FanIncZone[THRM_MAX_NUM_ZONES];
+ // Flag to indicate if the temperature for this FRU is increasing or not
+ BOOLEAN temp_increasing;
+}thrm_fru_data_t;
+
+/*******************************************************************/
+/* Function Definitions */
+/*******************************************************************/
+
+errlHndl_t thrm_thread_load_thresholds();
+void THRM_thread_update_thresholds();
+uint8_t THRM_thread_get_cooling_request();
+BOOLEAN thrm_thread_fan_control(const uint8_t i_frutype,
+ const uint16_t i_fru_temperature);
+BOOLEAN thrm_thread_vrm_fan_control(const uint16_t i_vrfan);
+void thrm_thread_main();
+
+#endif
diff --git a/src/occ/timer/timer.c b/src/occ/timer/timer.c
new file mode 100755
index 0000000..0959af5
--- /dev/null
+++ b/src/occ/timer/timer.c
@@ -0,0 +1,318 @@
+/******************************************************************************
+// @file timer.c
+// @brief OCC timer interfaces
+*/
+
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section timer.c TIMER.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb007 pbavari 09/27/2011 Created
+ * @pb008 pbavari 10/04/2011 Combined watchdog reset tasks
+ * @pb009 pbavari 10/20/2011 Main thread support
+ * @rc001 rickylie 01/02/2012 Change TRAC_DBG to TMER_DBG
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @sb002 908891 sbroyles 12/09/2013 FFDC updates
+ * @sb022 910404 sbroyles 01/06/2014 Extend watchdog timeout
+ * @sb012 910394 sbroyles 01/10/2014 More FFDC updates
+ * @sb023 913769 sbroyles 02/08/2014 Clear WIS on each interrupt
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <timer.h> // timer defines
+#include "ssx.h"
+#include <trac.h> // Trace macros
+#include <pgp_common.h> // PGP common defines
+#include <pgp_ocb.h> // OCB timer interfaces
+#include <occ_service_codes.h> // Reason codes
+#include <timer_service_codes.h> // Module Id
+#include <cmdh_fsp.h> // @sb002 for RCs in the checkpoint macros
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+// @sb022 Variable holding main thread loop count
+extern uint32_t G_mainThreadLoopCounter;
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+// PPC405 watchdog timer handler
+SSX_IRQ_FAST2FULL(ppc405WDTHndler, ppc405WDTHndlerFull);
+// OCB timer handler
+SSX_IRQ_FAST2FULL(ocbTHndler, ocbTHndlerFull);
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+// @sb023 Change watchdog reset control to take no action on state TSR[WIS]=1
+// and TSR[ENW]=1
+// Watchdog reset control set to "No reset"
+#define OCC_TCR_WRC 0
+// @sb002 Bump up wdog period to ~1s
+#define OCC_TCR_WP 3
+// 4ms represented in nanoseconds
+#define OCB_TIMER_TIMOUT 4000000
+// @sb022 Removed old watchdog code
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// @sb022
+bool G_wdog_enabled = FALSE;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: initWatchdogTimers
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+void initWatchdogTimers()
+{
+ int l_rc = SSX_OK;
+ errlHndl_t l_err = NULL;
+
+ TRAC_IMP("Initializing ppc405 watchdog. period=%d, reset_ctrl=%d",
+ OCC_TCR_WP,
+ OCC_TCR_WRC);
+
+ // set up PPC405 watchdog timer
+ l_rc = ppc405_watchdog_setup(OCC_TCR_WP, // watchdog period
+ OCC_TCR_WRC, // watchdog reset control
+ ppc405WDTHndler, // interrupt handler
+ NULL); // argument to handler
+
+ if (SSX_OK != l_rc)
+ {
+ TRAC_ERR("Error setting up ppc405 watchdog timer: l_rc: %d",l_rc);
+ /*
+ * @errortype
+ * @moduleid INIT_WD_TIMERS
+ * @reasoncode INTERNAL_HW_FAILURE
+ * @userdata1 Return code of PPC405 watchdog timer setup
+ * @userdata4 ERC_PPC405_WD_SETUP_FAILURE
+ * @devdesc Failure on hardware related function
+ */
+ l_err = createErrl(INIT_WD_TIMERS, // mod id
+ INTERNAL_HW_FAILURE, // reason code // @nh001c
+ ERC_PPC405_WD_SETUP_FAILURE, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // severity
+ NULL, // trace buffer
+ 0, // trace size
+ l_rc, // userdata1
+ 0); // userdata2
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // Commit error log
+ commitErrl(&l_err);
+ }
+
+ // @sb002 Defer setting up OCB timer 1, all it does is time the real time
+ // loop at this point
+ // FIXME #timer_c_001 Review RTL timer requirements
+ //// Set up OCB timer
+ //TRAC_IMP("Initializing OCB timer. timer=%d, auto_reload=%d, timeout_us=%d",
+ // OCB_TIMER1,
+ // OCB_TIMER_ONE_SHOT,
+ // OCB_TIMER_TIMOUT/1000);
+ //l_rc = ocb_timer_setup(OCB_TIMER1, // ocb timer
+ // OCB_TIMER_ONE_SHOT, // no auto reload
+ // OCB_TIMER_TIMOUT, // timeout in ns
+ // ocbTHndler, // interrupt handler
+ // NULL, // argument to handler
+ // SSX_CRITICAL); // interrupt priority
+
+ if( SSX_OK != l_rc)
+ {
+ TRAC_ERR("Error setting up OCB timer: l_rc: %d",l_rc);
+ /*
+ * @errortype
+ * @moduleid INIT_WD_TIMERS
+ * @reasoncode INTERNAL_HW_FAILURE
+ * @userdata1 Return code of OCB timer setup
+ * @userdata4 ERC_OCB_WD_SETUP_FAILURE
+ * @devdesc Failure on hardware related function
+ */
+ l_err = createErrl(INIT_WD_TIMERS, // mod id
+ INTERNAL_HW_FAILURE, // reason code // @nh001c
+ ERC_OCB_WD_SETUP_FAILURE, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // severity
+ NULL, // trace buffer
+ 0, // trace size
+ l_rc, // userdata1
+ 0); // userdata2
+
+ // @wb001 -- Callout firmware
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ // Commit error log
+ commitErrl(&l_err);
+ }
+ // @sb002 Removed UDER set to halt on OCB timer expiration. Let timer
+ // interrupt handler take over.
+ // @sb002 Simplified error handling
+}
+
+
+// Function Specification
+//
+// Name: task_poke_watchdogs
+//
+// Description: Reset PPC405 watchdog timer by clearing TSR[ENW] bit and reset OCB timer
+//
+// Flow: FN=None
+//
+// End Function Specification
+void task_poke_watchdogs( struct task * i_self )
+{
+ // @sb002 Read the PMC status register on every RTL, this is how the OCC
+ // generates a PMC hearbeat.
+ pmc_status_reg_t psr;
+ psr.value = in32(PMC_STATUS_REG);
+
+ // @sb002 FIXME #timer_c_002 Review RTL timer requirements
+ // Monitor the real time loop and make sure the poke task runs at
+ // least once every 4ms.
+ //static bool L_loggedOnce = FALSE;
+ //int l_rc = SSX_OK;
+ //// Reset OCB timer
+ //l_rc = ocb_timer_reset(OCB_TIMER1, // OCB Timer
+ // OCB_TIMER_ONE_SHOT, // no auto reload
+ // OCB_TIMER_TIMOUT); // timeout in ns
+ // @sb002 Removed all the 405 wdog thread counter code, 405 wdog control
+ // now in main thread loop
+ //if (SSX_OK != l_rc)
+ //{
+ // if (L_loggedOnce == FALSE)
+ // {
+ // TRAC_ERR("Error resetting OCB timer: l_rc: %d",l_rc);
+ // /*
+ // * @errortype
+ // * @moduleid RESET_OCB_TIMER
+ // * @reasoncode INTERNAL_HW_FAILURE
+ // * @userdata1 Return code of OCB timer reset
+ // * @userdata4 OCC_NO_EXTENDED_RC
+ // * @devdesc Faiure on hardware related function
+ // */
+ // errlHndl_t l_err = createErrl(RESET_OCB_TIMER, // mod id
+ // INTERNAL_HW_FAILURE, // reason code // @nh001c
+ // OCC_NO_EXTENDED_RC, // Extended reason code
+ // ERRL_SEV_UNRECOVERABLE, // severity
+ // NULL, // trace buf
+ // 0, // trace size
+ // l_rc, // userdata1
+ // 0); // userdata2
+ // // Commit error log
+ // commitErrl(&l_err);
+ // // Set flag to indicate already logged once
+ // L_loggedOnce = TRUE;
+ // }
+ //}
+}
+
+
+// Function Specification
+//
+// Name: ppc405WDTHndlerFull
+//
+// Description: PPC405 watchdog interrupt handler
+//
+// Flow: FN=None
+//
+// End Function Specification
+void ppc405WDTHndlerFull(void * i_arg,SsxIrqId i_irq,int i_priority)
+{
+ // @sb002 Removed trace, causes data storage exception in interrupt context
+ // @sb022 Small rewrite, added enable/disable switch, extend total time to
+ // around 6 seconds
+ static uint8_t l_wdog_intrpt_cntr = 0;
+
+ // @sb023 Always reset the watchdog interrupt status in the TSR. If we halt
+ // and leave TSR[WIS]=1 then the watchdog counter will eventually set
+ // TSR[ENW]=1 and upon expiration of the next watchdog period the 405 will
+ // take whatever action is in TCR[WRC] potentially resetting the OCC while
+ // we have it in a halted state, an undesirable outcome.
+ // Always clear TSR[ENW,WIS] to reset the watchdog state machine.
+ mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
+
+ if (WDOG_ENABLED)
+ {
+ // When enabled, always increment this local static counter
+ l_wdog_intrpt_cntr++;
+ // The hardware timer should be set to around a second, on the third
+ // interrupt we go to halt if the main thread counter hasn't incremented
+ // since the last time it was reset.
+ if (l_wdog_intrpt_cntr == 3)
+ {
+ l_wdog_intrpt_cntr = 0;
+ // The watchdog interrupt has fired three times, time to check the
+ // state of the main thread by looking at the main thread loop
+ // counter, it must be non-zero else we will halt the occ
+ if (G_mainThreadLoopCounter > 0)
+ {
+ // The main thread has run at least once in the last ~6 seconds
+ G_mainThreadLoopCounter = 0;
+ }
+ else
+ {
+ // @sb002 Added checkpoint and and halt macros
+ // @sb012 Removed SPR set and __CHECKPOINT macros, use new
+ // OCC_HALT with exception code passed in.
+ OCC_HALT(ERRL_RC_WDOG_TIMER);
+ }
+ }
+ }
+}
+
+
+// Function Specification
+//
+// Name: ocbTHndlerFull
+//
+// Description: OCB timer interrupt handler
+//
+// Flow: FN=None
+//
+// End Function Specification
+void ocbTHndlerFull(void * i_arg,SsxIrqId i_irq,int i_priority)
+{
+ // @sb002 Removed trace, causes data storage exception in interrupt context
+ // @sb002 Added checkpoint and and halt macros
+ // Enable external debug mode, checkpoint and halt
+ // @sb012 Removed SPR set and __CHECKPOINT macros, use new
+ // OCC_HALT with exception code passed in.
+ OCC_HALT(ERRL_RC_OCB_TIMER);
+}
diff --git a/src/occ/timer/timer.h b/src/occ/timer/timer.h
new file mode 100755
index 0000000..b1bcd14
--- /dev/null
+++ b/src/occ/timer/timer.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+// @file timer.h
+// @brief OCC watchdog timer functions and defines.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section timer.h TIMER.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb007 pbavari 09/27/2011 Created
+ * @pb008 pbavari 10/04/2011 Combined watchdog reset tasks
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th022 thallet 10/03/2012 Moved task flags to RTLS files
+ * @sb002 908891 sbroyles 12/09/2013 FFDC updates
+ * @sb022 910404 sbroyles 01/06/2014 Extend watchdog timeout
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _timer_h
+#define _timer_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // defines for uint8_t,uint3_t..etc
+#include <rtls.h> // For RTL task
+#include <errl.h> // For errlHndl_t
+#include <ssx_app_cfg.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+// @sb022 Macro to switch watchdog on and off
+#define ENABLE_WDOG G_wdog_enabled = TRUE
+#define DISABLE_WDOG G_wdog_enabled = FALSE
+#define WDOG_ENABLED (G_wdog_enabled)
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// @sb022 Variable to switch watchdog on and off
+extern bool G_wdog_enabled;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+// Initialize watchdog timers
+void initWatchdogTimers() INIT_SECTION;
+
+// Task to reset PPC405 watchdog timer and reset OCB timer
+void task_poke_watchdogs( struct task * i_self );
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif // _timer_h
+
+
diff --git a/src/occ/timer/timer_service_codes.h b/src/occ/timer/timer_service_codes.h
new file mode 100755
index 0000000..ac67a0e
--- /dev/null
+++ b/src/occ/timer/timer_service_codes.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+// @file timer_service_codes.h
+// @brief Error codes for timer component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _timer_service_codes_h timer_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * pbavari 09/26/2011 Created
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _TIMER_SERVICE_CODES_H_
+#define _TIMER_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum occTimerModuleId
+{
+ INIT_WD_TIMERS = TMER_COMP_ID | 0x00,
+ RESET_OCB_TIMER = TMER_COMP_ID | 0x01,
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _TIMER_SERVICE_CODES_H_ */
diff --git a/src/occ/tools/EXAMPLE_.occ_simics_config b/src/occ/tools/EXAMPLE_.occ_simics_config
new file mode 100755
index 0000000..1414e24
--- /dev/null
+++ b/src/occ/tools/EXAMPLE_.occ_simics_config
@@ -0,0 +1,22 @@
+# This is the configuration file for the 'start_occ_simics' script. The script will start
+# a simics session and attempt to automatically load the OCC binaries based off the
+# inputs and values below
+
+# Location of simics-workspace that contains simics executable and target directory
+SIMICS_WORKSPACE = /afs/rchland.ibm.com/usr8/arink/sandboxes/occ/simics-workspace
+
+# Target to use. Can be overridden via "-t" option to start_occ_simics
+DEFAULT_TARGET = /afs/rchland.ibm.com/usr8/arink/sandboxes/occ/simics-workspace/targets/occ/occ-simple-common.simics
+
+# Binary file to use. Can be overridden by passing in a .out file to start_occ_simics
+DEFAULT_BINARY = /afs/rchland.ibm.com/usr8/arink/sandboxes/occ/src/occ/occ.out
+
+# Directories to check when looking for target/binary files
+PATH = /afs/rchland.ibm.com/usr8/arink/sandboxes/occ/src/occ
+PATH = /afs/rchland.ibm.com/usr8/arink/sandboxes/occ/src/validation
+PATH = /afs/rchland.ibm.com/usr8/arink/sandboxes/occ/src/occ
+
+# Default commands to run
+COMMAND = pushd tools
+COMMAND = output-radix 16
+COMMAND = enable-magic-breakpoint
diff --git a/src/occ/tools/Gcov.pm b/src/occ/tools/Gcov.pm
new file mode 100644
index 0000000..d79339e
--- /dev/null
+++ b/src/occ/tools/Gcov.pm
@@ -0,0 +1,811 @@
+#!/usr/bin/perl
+use strict;
+use File::Path;
+use File::Basename;
+
+package Gcov;
+#use Hostboot::_DebugFrameworkVMM qw(NotFound NotPresent getPhysicalAddr);
+
+use Exporter;
+our @EXPORT_OK = ('main');
+
+# NOTE:
+#
+# Neither the in-memory structures or the resulting file format is well
+# documented for GCOV. I was able to piece together enough of this to
+# make it work for our purposes by looking at gcov-io.h and libgcov.c
+# from the gcc source and gcov/gcc_3_4.c from the linux source.
+#
+# Since this is a Perl script only used internally for debug, I do not see
+# any risk for contamination. If we decided to give Hostboot to external
+# vendors than this Perl script would be distributed as source which should
+# not lead us into any issues.
+#
+# If you are personally concerned about contamination by reading this
+# code you are hereby warned of the potential. Proceed at your own choice.
+
+use constant GCOV_EXTENDED_IMAGE_ADDRESS => (0xfff80000);
+use constant GCOV_INFO_HEAD_SYMBOLNAME => "_gcov_info_head";
+
+use constant GCOV_INFO_VERSION_OFFSET => 0;
+use constant GCOV_INFO_NEXT_OFFSET => GCOV_INFO_VERSION_OFFSET + 4;
+use constant GCOV_INFO_TIMESTAMP_OFFSET => GCOV_INFO_NEXT_OFFSET + 4;
+use constant GCOV_INFO_FILENAME_OFFSET => GCOV_INFO_TIMESTAMP_OFFSET + 4;
+use constant GCOV_INFO_NFUNCTIONS_OFFSET => GCOV_INFO_FILENAME_OFFSET + 4;
+use constant GCOV_INFO_FUNCTIONS_OFFSET => GCOV_INFO_NFUNCTIONS_OFFSET + 4;
+use constant GCOV_INFO_CTRMASK_OFFSET => GCOV_INFO_FUNCTIONS_OFFSET + 4;
+use constant GCOV_INFO_COUNTS_OFFSET => GCOV_INFO_CTRMASK_OFFSET + 4;
+
+use constant GCOV_FNINFO_IDENT_OFFSET => 0;
+use constant GCOV_FNINFO_CHECKSUM_OFFSET => GCOV_FNINFO_IDENT_OFFSET + 4;
+use constant GCOV_FNINFO_NCTRS_OFFSET => GCOV_FNINFO_CHECKSUM_OFFSET + 4;
+
+use constant GCOV_CTRINFO_COUNT_OFFSET => 0;
+use constant GCOV_CTRINFO_VALUEPTR_OFFSET => GCOV_CTRINFO_COUNT_OFFSET + 4;
+
+use constant GCOV_GCDA_MAGIC_VALUE => 0x67636461;
+use constant GCOV_FUNCTION_TAG => 0x01000000;
+use constant GCOV_COUNTERS_TAG => 0x01a10000;
+
+# In memory format:
+# GCC creates a 'gcov_info' structure for each .o file. The info
+# structure has a next pointer to form a chain. In Hostboot we have
+# organized the chains so that the pointer to the first entry is
+# stored at [modulename]_gcov_info_head (where modulename = "core" for
+# kernel and basic system libraries).
+#
+# The gcov_info has a version id (for the gcc compiled with), a
+# compile timestamp, c-string with the name of the .gcda file to be
+# generated, a count of the number of functions in the object, a
+# pointer to a set of function descriptors, a "counter mask" and a
+# set of counter descriptors.
+#
+# GCOV supports multiple types of counters. The only one we are
+# interested in is the "ARCS" counter, which describes the number of
+# times a particular branch is executed. The other counters are for,
+# for instance, profiling the value of a particular variable. The
+# "counter mask" specifies which counters are instrumented, which
+# determines the size of some of the array structures, but we only
+# parse the ARCS-counter type (we do properly calculate sizes if
+# needed).
+#
+# Each function descriptor contains an identity number and checksum
+# pair so the processing tools can match data to code information.
+# Also the function descriptor has an "n_counters" array which
+# determines for each counter type how many counters are instrumented.
+# Again, we are only concerned with the ARCS counter type.
+#
+# The counter descriptor is a size and pointer to array of counter
+# values. If there were 3 functions in the object each with n_counter
+# values of [3, 5, 2], then the size of the counter descriptor would be
+# 3+5+2 = 10. The values are arranged such that the first function has
+# the first 3 values, second one has the next 5, etc. The relationship
+# between function descriptor / "n_counters" and counter descriptor
+# values was not obvious from reading the gcov-io.h.
+#
+# For more details on these structures search the internet for gcov-io.h
+# or ask the building block team for the source code to the compiler we
+# are currently using. The offsets of all of these structures are all
+# documented in Perl constants above so you should only need this if
+# something breaks.
+#
+# .gcda file format:
+# The gcov tools expect a .gcda (gcov data) file as input, containing the
+# instrumented counter values, to go along with the .gcno (gcov note)
+# file created by the compiler. The format is documented in gcov-io.h
+# as well but was again not obvious to decipher.
+#
+# Here is a distilled file format description. Each entity is an u32.
+#
+# file : magic version stamp {function counts}*
+# function: f_header ident checksum
+# counts: c_header count*
+# count: lo hi
+# f_header: F_TAG(=0x01000000) F_LENGTH(=2)
+# c_header: C_TAG(=0x01a10000) C_LENGTH(=count_length*2)
+#
+# The file has three u32 of header followed by any number of function
+# descriptor and count set pairs. The function descriptor is the
+# identity and checksum of the function. The count set is an array of
+# uint64_ts, containing instrumented counts, for the preceeding function.
+
+# Global of where we want the output to go.
+our $output_dir;
+our $debug_mode;
+BEGIN
+{
+ $debug_mode = 1;
+ $output_dir = "";
+}
+return 1;
+
+#-----------------------------------------------------------------------------
+# Added for OCC usage
+#
+use IO::Seekable;
+our ($parsedSymbolFile, %symbolAddress, %symbolTOC,
+ %addressSymbol, %symbolSize);
+our ($parsedModuleFile, %moduleAddress);
+our $imgPath;
+use constant NotFound => 'not found';
+use constant NotPresent => 'not present';
+
+# @sub getPhysicalAddr
+#
+# Find the physical address in the VMM from a VA passed in.
+#
+# @param address we are looking for
+# @param debug var to indicate debug mode (1 = debug on)
+# @return physical address
+#
+sub getPhysicalAddr
+{
+ my $vaddr = shift;
+ my $debug = shift;
+ my $displaySPTE = shift;
+
+ my $phyAddr = NotFound;
+
+ #if( ($vaddr - 0xfff80000) > 0 ){
+ # $phyAddr = ($vaddr - 0xfff80000);
+ #}
+ $phyAddr = $vaddr;
+
+ return $phyAddr;
+}
+
+# @sub readData
+#
+# Reads a data blob from the dump file.
+#
+# @param integer - Address to read at.
+# @param size - Size (in bytes) to read.
+#
+# @return The blob of data requested.
+#
+sub _readData
+{
+ my $addr = shift;
+ my $size = shift;
+
+ if( ($addr >= 0xfff80000) ){
+ $addr = ($addr - 0xfff80000);
+ } else {
+ $addr = 0;
+ }
+
+ seek DUMPFILE, $addr, SEEK_SET;
+
+ my $result = "";
+ read DUMPFILE, $result, $size;
+
+ return $result;
+}
+
+# @sub userDisplay
+#
+# Display parameters to the user.
+#
+# @param varargs - Items to display to the user.
+#
+sub userDisplay
+{
+ foreach my $value (@_)
+ {
+ print $value;
+ }
+}
+
+sub getImgPath
+{
+ #my $path = "/home/thallet/ProjectWorkspace/temp/occ.syms";
+ my $path = $imgPath;
+ return $path;
+}
+
+# @sub parseSymbolFile <INTERNAL ONLY>
+#
+# Parses through a .syms file and populates a hash.
+#
+sub parseSymbolFile
+{
+ if ($parsedSymbolFile) { return; }
+
+ my $symsFile = getImgPath();
+
+ open(FILE, "< $symsFile") or die "Cannot open symbol file $symsFile";
+ while (my $line = <FILE>)
+ {
+ $line =~ m/(.*?) (.*?) (.*)/;
+ my $name = $3;
+ my $addr = hex $1;
+ my $tocAddr = 0;
+ my $size = 0;
+ my $type = $2;
+
+ $addressSymbol{$addr} = $name;
+ $addressSymbol{$tocAddr} = $name;
+
+ # Use only the first definition of a symbol.
+ # This is useful for constructors where we only want to call the
+ # 'in-charge' version of the constructor.
+ if (defined $symbolAddress{$name})
+ {
+ next;
+ }
+
+ $symbolAddress{$name} = $addr;
+ if ($type eq "F")
+ {
+ $symbolTOC{$name} = $tocAddr;
+ }
+ $symbolSize{$name} = $size;
+
+ }
+ close(FILE);
+
+ $parsedSymbolFile = 1;
+}
+
+# @sub findSymbolAddress
+#
+# Searchs a syms file for the address of a particular symbol name.
+#
+# @param string - Symbol to search for.
+# @return array of (address, size) or (not-defined, not-defined).
+#
+sub findSymbolAddress
+{
+ my $name = shift;
+
+ parseSymbolFile();
+
+ return ($symbolAddress{$name}, $symbolSize{$name} );
+}
+
+
+# @sub littleendian
+#
+# Utility function to determine if the current machine is little or big
+# endian.
+#
+# @return true if machine is little-endian.
+#
+sub _littleendian
+{
+ return (unpack("L", pack("N", 0xabcd1234)) != 0xabcd1234);
+}
+
+# @sub read64
+#
+# Reads a 64-bit unsigned integer from an address.
+#
+# @param Address to read from.
+# @return Value.
+#
+sub _read64
+{
+ my $addr = shift;
+
+ my $result = _readData($addr, 8);
+ if (_littleendian()) { $result = reverse($result); }
+
+ return unpack("Q", $result);
+}
+
+# @sub read32
+#
+# Reads a 32-bit unsigned integer from an address.
+#
+# @param Address to read from.
+# @return Value.
+#
+sub _read32
+{
+ my $addr = shift;
+
+ my $result = _readData($addr, 4);
+ if (_littleendian()) { $result = reverse($result); }
+
+ return unpack("L", $result);
+}
+
+# @sub read16
+#
+# Reads a 16-bit unsigned integer from an address.
+#
+# @param Address to read from.
+# @return Value.
+#
+sub _read16
+{
+ my $addr = shift;
+
+ my $result = _readData($addr, 2);
+ if (littleendian()) { $result = reverse($result); }
+
+ return unpack("S", $result);
+}
+
+# @sub read8
+#
+# Reads a 8-bit unsigned integer from an address.
+#
+# @param Address to read from.
+# @return Value.
+#
+sub _read8
+{
+ my $addr = shift;
+
+ my $result = _readData($addr, 1);
+
+ return unpack("C", $result);
+}
+
+# @sub readStr
+#
+# Reads a string from an address.
+#
+# @param Address to read from.
+# @return Value.
+#
+sub _readStr
+{
+ my $addr = shift;
+
+ my $result = "";
+ my $byte = 0;
+
+ do
+ {
+ $byte = read8($addr);
+ $addr += 1;
+
+ if ($byte != 0)
+ {
+ $result = $result.pack("C",$byte);
+ }
+ } while ($byte != 0);
+
+ return $result;
+}
+
+# @sub readExtImage
+#
+# Reads from the extended image file.
+#
+# @param addr - Address to read.
+# @param size - Size to read.
+sub _readExtImage
+{
+ my $addr = shift;
+ my $size = shift;
+
+ my $extImage = extImageFile();
+
+ seek $extImage, $addr, SEEK_SET;
+
+ my $result = "";
+ read $extImage, $result, $size;
+
+ return $result;
+}
+
+# @sub extImageFile
+#
+# Returns a file descriptor to the extended image file.
+#
+my $extImage = 0;
+sub extImageFile
+{
+ if ($extImage == 0)
+ {
+ my $path = getImgPath();
+
+ userDebug("".$path."\n");
+
+ open($extImage, "< $path") or die "Cannot find extended image";
+ binmode($extImage);
+ }
+
+ return $extImage;
+}
+
+#
+#
+#-----------------------------------------------------------------------------
+sub main
+{
+ # Pick a new output directory based on the time.
+ $output_dir = sprintf "gcov.output.%d/", time;
+ File::Path::mkpath($output_dir);
+
+ #my $dumpfile = "/home/thallet/ProjectWorkspace/temp/occ_gcov.bin";
+ my $dumpfile = shift;
+ $imgPath = shift;
+
+ # Open dump file.
+ open(DUMPFILE, "< $dumpfile") or die "Can't open dump file.\n";
+ binmode(DUMPFILE);
+
+ # Find all the hostboot modules.
+ my @modules = getModules();
+
+ # Search for the gcov_info object for each module and parse.
+ foreach my $module (@modules)
+ {
+ parseModuleGcov($module);
+ }
+
+ my $pwd = `pwd`;
+ chomp $pwd;
+ userDisplay "GCOV output written to: $pwd/$output_dir\n";
+}
+
+sub parseModuleGcov
+{
+ my $module = shift;
+ userDisplay "Extracting GCOV info for ".$module."\n";
+
+ # Search for gcov_info chain symbol.
+ my ($gcov_info, $unused) =
+ findSymbolAddress($module.GCOV_INFO_HEAD_SYMBOLNAME);
+
+ userDebug("\tFound info at 0x" . (sprintf "%x", $gcov_info) . "\n");
+
+ # Translate gcov_info chain to a physical address if in a module.
+ if (isVirtualAddress($gcov_info))
+ {
+ $gcov_info = getPhysicalAddr($gcov_info);
+
+ if (($gcov_info eq NotFound) || ($gcov_info eq NotPresent))
+ {
+ userDisplay "\tModule data is not present.\n";
+ return;
+ }
+ }
+
+ # Check that we found the gcov_info chain.
+ if ($gcov_info == 0)
+ {
+ userDisplay "\tUnable to find gcov_info chain. Skipped.\n";
+ return;
+ }
+
+ userDebug("\tFound info at 0x" . (sprintf "%x", $gcov_info) . "\n");
+
+ # Parse info chain.
+ parseGcovInfo(read32($gcov_info));
+}
+
+sub parseGcovInfo
+{
+ my $info_ptr = shift;
+ return if (0 eq $info_ptr);
+
+ userDebug("\tAddr = ".(sprintf "%x", $info_ptr)."\n");
+ my $filename = readStr(read32($info_ptr + GCOV_INFO_FILENAME_OFFSET));
+ userDebug("\tFile = ".$filename."\n");
+
+ my $version = read32($info_ptr + GCOV_INFO_VERSION_OFFSET);
+ my $stamp = read32($info_ptr + GCOV_INFO_TIMESTAMP_OFFSET);
+
+ my $func_count = read32($info_ptr + GCOV_INFO_NFUNCTIONS_OFFSET);
+ userDebug("\tFunction Count = ".$func_count."\n");
+
+ my $funcs = read32($info_ptr + GCOV_INFO_FUNCTIONS_OFFSET);
+ userDebug("\tFunc Address = ".(sprintf "%x", $funcs)."\n");
+
+ my $ctrmask = read32($info_ptr + GCOV_INFO_CTRMASK_OFFSET);
+ if ($ctrmask % 2) # Check that COUNTER_ARCS is turned on.
+ {
+ # COUNTER_ARCS is on. Create file, find arc-values array,
+ # parse functions.
+
+ my $fd = createGcovFile($filename, $version, $stamp);
+
+ my $arcs_ptr = read32($info_ptr + GCOV_INFO_COUNTS_OFFSET +
+ GCOV_CTRINFO_VALUEPTR_OFFSET);
+ parseGcovFuncs($fd, $funcs, $func_count, $ctrmask, $arcs_ptr);
+
+ close $fd;
+ }
+ else
+ {
+ userDebug("COUNTER_ARCS is missing!\n");
+ }
+
+ # Look for next .o in gcov_info chain, parse.
+ my $next = read32($info_ptr + GCOV_INFO_NEXT_OFFSET);
+ sleep(4);
+ parseGcovInfo($next);
+}
+
+sub parseGcovFuncs
+{
+ my $fd = shift;
+ my $func_ptr = shift;
+ my $func_count = shift;
+ my $mask = shift;
+ my $val_ptr = shift;
+
+ my $fn_offset = 0;
+
+ # Need to calculate the number of counters based on the bits on in
+ # the 'mask'. This is used to determine the size of the function
+ # descriptor object.
+ my $counters = 0;
+ {
+ my $_mask = $mask;
+
+ while (0 != $_mask)
+ {
+ $counters++;
+ $_mask = ($_mask >> 1);
+ }
+ }
+
+ userDebug("\tCounters = ".$counters."\n");
+
+ # Round up the counter count to the nearest two for alignment of the
+ # function descriptor object.
+ if ($counters % 2)
+ {
+ $counters++;
+ }
+ my $func_size = GCOV_FNINFO_CHECKSUM_OFFSET + 4 * $counters;
+
+ userDebug("\tFunction size = ".$func_size."\n");
+
+ # Iterate through the functions and parse.
+ for(my $function = 0; $function < $func_count; $function++)
+ {
+ my $func_off = ($func_ptr + $func_size * $function);
+ my $ident = read32($func_off + GCOV_FNINFO_IDENT_OFFSET);
+ my $chksum = read32($func_off + GCOV_FNINFO_CHECKSUM_OFFSET);
+
+ userDebug("Ident = ".(sprintf "%x", $ident)."\n");
+ userDebug("Chksum = ".(sprintf "%x", $chksum)."\n");
+
+ print $fd pack('l', GCOV_FUNCTION_TAG); # Write function tag.
+ print $fd pack('l', 2); # Write size = 2.
+ print $fd pack('l', $ident); # Write ident.
+ print $fd pack('l', $chksum); # Write checksum.
+
+ my $nctr_val = read32($func_off + GCOV_FNINFO_NCTRS_OFFSET);
+ userDebug("N-Counters = ".$nctr_val."\n");
+
+ print $fd pack('l', GCOV_COUNTERS_TAG); # Write counter tag.
+ print $fd pack('l', $nctr_val * 2); # Write counter length.
+
+ # Read each counter value, output.
+ # Read as one big block for performance reasons.
+ my $counters = readData($val_ptr + 8*($fn_offset), 8 * $nctr_val);
+ #my $counters = readData($val_ptr + 4*($fn_offset), 8 * $nctr_val);
+ for(my $v_idx = 0; $v_idx < $nctr_val; $v_idx++)
+ {
+ my $val = substr $counters, 0, 8;
+ $counters = substr $counters, 8;
+ if (_littleendian()) { $val = reverse($val); }
+ $val = unpack("Q", $val);
+ userDebug("\tValue[$v_idx] = ".$val."\n");
+
+ print $fd pack('l', $val & 0xFFFFFFFF); # Write lower word.
+ print $fd pack('l', $val >> 32) ; # Write upper word.
+ }
+
+ # We used up a number of counters, so move the offset forward for
+ # the next function.
+ $fn_offset += $nctr_val;
+ }
+
+}
+
+# The *.gcda filename found in the gcov_info struct is an absolute path to
+# the corresponding .o file (not the .C file). This is of the form:
+# ${HOSTBOOTROOT}/src/usr/module/${ROOTPATH}/obj/${MODULE}/foo.gcda .
+# Since we might not even be running this on the same machine, we need to put
+# the output into the "output_dir" but we need to strip off a lot of stuff.
+# The path is going to have an obj in it somewhere so we key off that
+# as the location for where the output file will go.
+sub createGcovFile
+{
+ my $name = shift;
+ my $version = shift;
+ my $stamp = shift;
+
+ # Change *./../obj/ into obj/, prepend output_dir.
+ $name =~ s/.*\/obj\//obj\//;
+ $name = $output_dir.$name;
+
+ # Make sure everything after 'obj/' exists (create subdirs).
+ my $dir = File::Basename::dirname($name);
+ File::Path::mkpath($dir);
+
+ # Create file.
+ open(my $GCOVFILE, "> $name");
+ binmode($GCOVFILE);
+
+ # Write out header.
+ print $GCOVFILE pack('l', GCOV_GCDA_MAGIC_VALUE);
+ print $GCOVFILE pack('l', $version);
+ print $GCOVFILE pack('l', $stamp);
+
+ return $GCOVFILE;
+}
+
+# Search the module list for each code module (lib*.so). Also add "core"
+# for the kernel instrumentation.
+sub getModules
+{
+ my @result = ( "core" );
+ return @result;
+}
+
+# Determine if an address is virtual.
+sub isVirtualAddress
+{
+ my $addr = shift;
+
+ return (0);
+}
+
+# Utility to read a block of data from eithr memory or using the extended
+# image file as a fallback if not present in memory.
+use constant PAGESIZE => 4096;
+sub readData
+{
+ my $addr = shift;
+ my $size = shift;
+
+ if (isVirtualAddress($addr))
+ {
+ my $result = "";
+
+ while($size)
+ {
+ my $amount = $size;
+
+ if ((($addr % PAGESIZE) + $size) >= PAGESIZE)
+ {
+ $amount = PAGESIZE - ($addr % PAGESIZE);
+ }
+
+ my $paddr = getPhysicalAddr($addr);
+ if ((NotFound eq $paddr) || (NotPresent eq $paddr))
+ {
+ $paddr = $addr - GCOV_EXTENDED_IMAGE_ADDRESS;
+ $result = $result._readExtImage($paddr, $amount);
+ }
+ else
+ {
+ $result = $result._readData($paddr, $amount);
+ }
+
+ $size = $size - $amount;
+ }
+
+ return $result;
+ }
+
+ return _readData($addr, $size);
+}
+
+# Utility to read 64 bits from either memory or using the extended image file
+# as a fallback if not present in memory.
+sub read64
+{
+ my $addr = shift;
+ my $old_addr = $addr;
+ if (isVirtualAddress($addr))
+ {
+ $addr = getPhysicalAddr($addr);
+ if ((NotFound eq $addr) || (NotPresent eq $addr))
+ {
+ $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS;
+ my $result = _readExtImage($addr, 8);
+ if (_littleendian()) { $result = reverse($result); }
+ return unpack("Q", $result);
+ }
+ }
+
+ return _read64($addr);
+}
+
+# Utility to read 32 bits from either memory or using the extended image file
+# as a fallback if not present in memory.
+sub read32
+{
+ my $addr = shift;
+ my $old_addr = $addr;
+ if (isVirtualAddress($addr))
+ {
+ $addr = getPhysicalAddr($addr);
+ if ((NotFound eq $addr) || (NotPresent eq $addr))
+ {
+ $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS;
+ my $result = _readExtImage($addr, 4);
+ if (_littleendian()) { $result = reverse($result); }
+ return unpack("L", $result);
+ }
+ }
+
+ return _read32($addr);
+}
+
+# Utility to read 8 bits from either memory or using the extended image file
+# as a fallback if not present in memory.
+sub read8
+{
+ my $addr = shift;
+ my $old_addr = $addr;
+ if (isVirtualAddress($addr))
+ {
+ $addr = getPhysicalAddr($addr);
+ if ((NotFound eq $addr) || (NotPresent eq $addr))
+ {
+ $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS;
+ my $result = _readExtImage($addr, 1);
+ return unpack("C", $result);
+ }
+ }
+
+ return _read8($addr);
+}
+
+# Utility to read a string from either memory or using the extended image file
+# as a fallback if not present in memory.
+sub readStr
+{
+ my $addr = shift;
+ my $old_addr = $addr;
+ if (isVirtualAddress($addr))
+ {
+ $addr = $addr - GCOV_EXTENDED_IMAGE_ADDRESS;
+
+ # Virtual address, so need to read 1 byte at a time from the file.
+ my $string = "";
+ my $byte = 0;
+
+ do
+ {
+ $byte = _readExtImage($addr,1);
+ $addr = $addr + 1;
+
+ if (unpack("C",$byte) eq 0)
+ {
+ return $string;
+ }
+
+ $string = $string.$byte;
+
+ } while (1)
+ }
+ else
+ {
+ _readStr($addr);
+ }
+}
+
+sub userDebug
+{
+ return if (!$debug_mode);
+
+ my $string = shift;
+ userDisplay $string;
+}
+
+# Debug tool help info.
+sub helpInfo
+{
+ my %info = (
+ name => "Gcov",
+ intro => [ "Extracts the GCOV information."],
+ );
+}
+
+#-----------------------------------------------------------------------------
+
+
+
diff --git a/src/occ/tools/OccSimicsAutomate.pm b/src/occ/tools/OccSimicsAutomate.pm
new file mode 100755
index 0000000..f385243
--- /dev/null
+++ b/src/occ/tools/OccSimicsAutomate.pm
@@ -0,0 +1,1010 @@
+##############################################################################
+#
+# @file OccSimicsAutomate.pm
+#
+# @author Timothy Hallett
+#
+# @package OccSimicsAutomate
+#
+# @brief Perl class for automating simics for OCC.
+#
+# @verbatim
+#
+# Updates: 11/28/2011 -- thallet -- File/Class created
+# 11/29/2011 -- thallet -- Methods for automating tracing and simics
+# added and tested. Integration into Code
+# Coverage Tool (HOCCT) works as well.
+# v0.2 01/17/2012 -- thallet -- Made change to handle post_model_hook.simics
+# v0.2.1 01/19/2012 -- thallet -- Clear accum on Expect calls. Changed simics
+# prompt string.
+#
+# @endverbatim
+#
+#
+##############################################################################
+
+package OccSimicsAutomate;
+
+use strict;
+use Expect;
+
+
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# Package Config/Default Parms
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
+# @brief VERSION - contains VERSION of this class
+my $VERSION = "0.2.1";
+
+# @brief DEBUG_LEVEL - sets debug level of this class's print output
+my $DEBUG_LEVEL = 1;
+
+# @brief CMD_PROMPT - sets what Expect should see for Linux bash prompt
+my $CMD_PROMPT = '^.*[$%>#]\s';
+
+# @brief CMD_PROMPT - sets what Expect should see for Simics prompt
+my $SIMICS_PROMPT = "simics> \x1b.*m";
+
+# @brief EXPECT_COMMAND - sets what Expect should run to get a bash prompt
+my $EXPECT_COMMAND = "bash -i";
+
+# @brief DEFAULT_TRACE_FILE - sets default filename for simics execution trace
+my $DEFAULT_TRACE_FILE = "occ_exe_trace";
+
+# @brief DEFAULT_INSTRUCTION_FILE - sets default filename for parsed out instruction trace
+my $DEFAULT_INSTRUCTION_FILE = "/tmp/occ_instructions.txt";
+
+# @brief SIMICS_CYCLES_PER_MS - sets timing for how many simics cycles are in 1ms.
+my $SIMICS_CYCLES_PER_MS = (150016 * 4);
+
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# Package Global Variables
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
+# @var G_occ_start_cmds
+#
+# @brief Holds commands that need to run to initialize simics for OCC execution
+#
+my @G_occ_start_cmds =
+(
+ "enable-magic-breakpoint",
+ "new-symtable st_auto ../src/occ/occ.out",
+ "\@conf.OccComplex.OccSimpleSlot.cpu.current_context.symtable = conf.st_auto",
+);
+
+# @var G_trace_start_cmds
+#
+# @brief Holds commands that need to run to initialize simics for tracing instructions
+#
+my @G_trace_start_cmds =
+(
+ "load-module trace",
+ "new-tracer",
+ "trace0->trace_data = 0",
+ "trace0->trace_exceptions = 0",
+ "trace0->print_virtual_address = 0",
+ "trace0->print_memory_type = 0",
+ "trace0->print_linear_address = 0",
+ "trace0->print_data = 0",
+);
+
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# Constructor
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
+#------------------------------------------------
+# @fn new
+#
+# @brief Constructor, spawns bash shell with expect.
+#
+# @param None
+#
+# @return self - Pointer to $self as class pointer
+#------------------------------------------------
+sub new
+{
+ my $class = shift;
+ my $self =
+ {
+ debug_lvl => $DEBUG_LEVEL,
+ prompt => $CMD_PROMPT,
+ shell_cmd => $EXPECT_COMMAND,
+ cyc_per_ms => $SIMICS_CYCLES_PER_MS,
+ trace_file => $DEFAULT_TRACE_FILE,
+ instr_file => $DEFAULT_INSTRUCTION_FILE,
+ expect_obj => undef,
+ last_rc => undef,
+ temp_file1 => undef,
+ temp_file2 => undef,
+ };
+
+ # Spawn a bash shell to run in
+ my @params;
+ $self->{expect_obj} = Expect->spawn($self->{shell_cmd}, @params) or die "Cannot spawn $self->{shell_cmd}: $!\n";
+ #$self->{expect_obj}->log_file("filename", "w"); #Later, add option to log all expect activity?
+ #$self->{expect_obj}->log_file("filename"); #Later, add option to log all expect activity?
+ $self->{last_rc} = $self->{expect_obj}->expect(10,'-re',$self->{prompt});
+
+ #If call fails, print out error
+ if(0 == $self->{last_rc})
+ {
+ print "Could not get bash prompt!"; die;
+ }
+
+ # For now, lets die if we aren't in a sandbox
+ if( !defined($ENV{"sb"}) ){die "This script needs to run in an ODE sandbox!\n";}
+
+
+ bless ($self, $class);
+ return $self;
+}
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# Destructor
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
+#------------------------------------------------
+# @fn DESTROY
+#
+# @brief Cleans up class, closes simics & expect.
+#
+# @param None
+#
+# @return None
+#------------------------------------------------
+sub DESTROY
+{
+ my ( $self ) = @_;
+
+ simics_cmd($self,"exit");
+
+ $self->{expect_obj}->soft_close();
+}
+
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# Base Methods
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
+#------------------------------------------------
+# @fn prereq_simics
+#
+# @brief Makes sure that prereqs are in place to starts the simics session
+#
+# @param None
+#
+# @return rc - Return code of expect operation
+#------------------------------------------------
+sub prereq_simics
+{
+ my ( $self ) = @_;
+
+ # Make sure we have the simics command script setup to run
+ #if( !(-e $ENV{"sb"}."/../post_model_hook.simics") )
+ {
+ if( -e $ENV{"sb"}."/occ/tools/occ_post_model_hook.simics" )
+ {
+ print "Setting up Symlinks...\n";
+ system("rm ".$ENV{"sb"}."/../simics/post_model_hook.simics");
+ system("ln -s ".$ENV{"sb"}."/occ/tools/occ_post_model_hook.simics ".$ENV{"sb"}."/../simics/post_model_hook.simics");
+ }
+ }
+}
+
+#------------------------------------------------
+# @fn start_simics
+#
+# @brief Starts the simics session via expect
+#
+# @param None
+#
+# @return rc - Return code of expect operation
+#------------------------------------------------
+sub start_simics
+{
+ my ( $self ) = @_;
+
+ prereq_simics($self);
+
+ $self->{expect_obj}->clear_accum();
+ $self->{expect_obj}->send("start_simics -m occ_alone -st -batch_mode\n");
+ $self->{last_rc} = $self->{expect_obj}->expect(300,'-re',$SIMICS_PROMPT);
+
+ #If call fails, print out error
+ if(0 == $self->{last_rc})
+ {
+ print "Couldn't get simics prompt ".$self->{last_rc}." \n"; die;
+ }
+
+ return $self->{last_rc};
+}
+
+#------------------------------------------------
+# @fn close
+#
+# @brief Exits & Closes the simics session via expect
+#
+# @param None
+#
+# @return None
+#------------------------------------------------
+sub close
+{
+ my ( $self ) = @_;
+
+ simics_cmd_w_timeout($self,1,"exit");
+
+ $self->{expect_obj}->soft_close();
+}
+
+#------------------------------------------------
+# @fn simics_cmd
+#
+# @brief Runs a simics command, watis for "simics>"
+#
+# @param cmd - String with command that will be sent
+#
+# @return rc - Return code of expect operation
+#------------------------------------------------
+sub simics_cmd
+{
+ my ( $self, $cmd ) = @_;
+
+ $self->{expect_obj}->clear_accum();
+ $self->{expect_obj}->send("$cmd\n");
+ $self->{last_rc} = $self->{expect_obj}->expect(10,'-re',$SIMICS_PROMPT) or return;
+
+ #If a person wanted to parse out the command, you would use this
+ #expect call here:
+ # @lines = $self->{expect_obj}->before();
+ # foreach(@lines){do something to $_};
+
+ return $self->{last_rc};
+}
+
+
+#------------------------------------------------
+# @fn simics_cmd_w_response
+#
+# @brief Runs a simics command, watis for "simics>"
+#
+# @param cmd - String with command that will be sent
+#
+# @return rc - Return code of expect operation
+#------------------------------------------------
+sub simics_cmd_w_response
+{
+ my ( $self, $cmd ) = @_;
+
+ $self->{expect_obj}->clear_accum();
+ $self->{expect_obj}->send("$cmd\n");
+ $self->{last_rc} = $self->{expect_obj}->expect(10,'-re',$SIMICS_PROMPT) or return;
+
+ #If a person wanted to parse out the command, you would use this
+ #expect call here:
+ my @lines = $self->{expect_obj}->before();
+ # foreach(@lines){do something to $_};
+ return @lines;
+}
+
+#------------------------------------------------
+# @fn get_last_simics_cmd_response
+#
+# @brief Returns what expect read before last prompt
+#
+# @return All response from last command before prompt
+#------------------------------------------------
+sub get_last_simics_cmd_response
+{
+ my ( $self ) = @_;
+
+ return $self->{expect_obj}->before();
+}
+
+#------------------------------------------------
+# @fn simics_cmd_w_timeout
+#
+# @brief Runs a simics command, watis for "simics>"
+#
+# @param t - Timeout in seconds of expect operation
+# @param cmd - String with command that will be sent
+#
+# @return rc - Return code of expect operation
+#------------------------------------------------
+sub simics_cmd_w_timeout
+{
+ my ($self, $t, $cmd) = @_;
+
+ $self->{expect_obj}->clear_accum();
+ $self->{expect_obj}->send("$cmd\n");
+ $self->{last_rc} = $self->{expect_obj}->expect($t,'-re',$SIMICS_PROMPT) or return;
+
+ return $self->{last_rc};
+}
+
+#------------------------------------------------
+# @fn simics_cmd_w_timeout_w_running
+#
+# @brief Runs a simics command, watis for "running>"
+#
+# @param t - Timeout in seconds of expect operation
+# @param cmd - String with command that will be sent
+#
+# @return rc - Return code of expect operation
+#------------------------------------------------
+sub simics_cmd_w_timeout_w_running
+{
+ my ($self, $t, $cmd) = @_;
+
+ $self->{expect_obj}->clear_accum();
+ $self->{expect_obj}->send("$cmd\n");
+ $self->{last_rc} = $self->{expect_obj}->expect($t,'-re','running> ') or return;
+
+ return $self->{last_rc};
+}
+
+#------------------------------------------------
+# @fn simics_cmd_w_running
+#
+# @brief Runs a simics command, watis for "running>"
+#
+# @param cmd - String with command that will be sent
+#
+# @return rc - Return code of expect operation
+#------------------------------------------------
+sub simics_cmd_w_running
+{
+ my ( $self, $cmd ) = @_;
+
+ $self->{expect_obj}->clear_accum();
+ $self->{expect_obj}->send("$cmd\n");
+ $self->{last_rc} = $self->{expect_obj}->expect(10,'-re','running> ') or return;
+
+ return $self->{last_rc};
+}
+
+#------------------------------------------------
+# @fn DEBUG
+#
+# @brief Prints out debug data, based on debug_lvl
+#
+# @param lvl - Min Level of debug at which string will print
+# @param str - String that will be printed
+#
+# @return None
+#------------------------------------------------
+sub DEBUG
+{
+ my ($self,$lvl,$str) = @_;
+ if($lvl <= $self->{debug_lvl})
+ {
+ print $str;
+ }
+}
+
+#------------------------------------------------
+# @fn DEBUG
+#
+# @brief Prints out debug data, based on debug_lvl
+#
+# @param lvl - Min Level of debug at which string will print
+# @param str - String that will be printed
+#
+# @return None
+#------------------------------------------------
+sub SET_DEBUG_LVL
+{
+ my ($self,$lvl) = @_;
+
+ $self->{debug_lvl} = $lvl;
+
+ if($lvl <= 5)
+ {
+ print "Turning on Expect debugging\n\n";
+ $self->{expect_obj}->debug(3);
+ $self->{expect_obj}->exp_internal(1);
+ }
+}
+
+
+
+#-----------------------------------------------------------------------------
+# Base Utilities (generic, based off base methods)
+#-----------------------------------------------------------------------------
+
+#------------------------------------------------
+# @fn waitForSimicsPrompt
+#
+# @brief Helper function, returns when "simics>" is seen
+#
+# @return None
+#------------------------------------------------
+sub waitForSimicsPrompt
+{
+ my ( $self ) = @_;
+
+ simics_cmd($self,"echo");
+}
+
+#------------------------------------------------
+# @fn waitForRunningPrompt
+#
+# @brief Helper function, returns when "running>" is seen
+#
+# @return None
+#------------------------------------------------
+sub waitForRunningPrompt
+{
+ my ( $self ) = @_;
+
+ simics_cmd_w_timeout_w_running($self,10,"echo");
+}
+
+#------------------------------------------------
+# @fn getSimicsTime
+#
+# @brief Helper function
+#
+# @return None
+#------------------------------------------------
+sub getSimicsTime
+{
+ my ( $self ) = @_;
+
+ simics_cmd($self,"print-time");
+ simics_cmd($self,"print-time -t");
+}
+
+#------------------------------------------------
+# @fn dumpOccStackTrace
+#
+# @brief Helper function
+#
+# @return None
+#------------------------------------------------
+sub dumpOccStackTrace
+{
+ my ( $self ) = @_;
+
+ simics_cmd($self,"stack-trace");
+}
+
+#------------------------------------------------
+# @fn interact
+#
+# @brief Swithes to interactive mode so that user can
+# interact directly with simics, when script wants
+# that to happen
+#
+# @return rc - Return code of expect operation
+#------------------------------------------------
+sub interact
+{
+ my ( $self ) = @_;
+
+ waitForSimicsPrompt($self);
+ waitForSimicsPrompt($self);
+ waitForSimicsPrompt($self);
+ waitForSimicsPrompt($self);
+ waitForSimicsPrompt($self);
+ waitForSimicsPrompt($self);
+ waitForSimicsPrompt($self);
+ waitForSimicsPrompt($self);
+ waitForSimicsPrompt($self);
+
+ print "Switching to Interactive Mode: Type \"END\" and hit \"<Return>\" twice to return to script\n\n";
+
+ $self->{expect_obj}->interact(\*STDIN, "END");
+
+ return $self->{last_rc};
+}
+
+#------------------------------------------------
+# @fn setOccVariable
+#
+# @brief Sets variable abstracting weird simics syntax
+#
+# @param var - String with variable name
+# @param value - Value to write to variable
+#
+# @return None
+#------------------------------------------------
+sub setOccVariable
+{
+ my ( $self, $var, $value ) = @_;
+
+ simics_cmd($self,"set (sym \"&$var\") $value (sym \"sizeof($var)\")");
+}
+
+#------------------------------------------------
+# @fn getOccVariable
+#
+# @brief Gets variable abstracting weird simics syntax
+#
+# @param var - String with variable name
+#
+# @return None
+#------------------------------------------------
+sub getOccVariable
+{
+ my ( $self, $var) = @_;
+
+ simics_cmd($self,"psym \"$var\"");
+}
+
+
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# OCC Simics Execution
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
+#------------------------------------------------
+# @fn startAndRunOccUntilMain
+#
+# @brief Automates all steps needed to reach OCC
+# application code main(), then stops on
+# breakpoint there.
+#
+# @return None
+#------------------------------------------------
+sub startAndRunOccUntilMain
+{
+ my ( $self ) = @_;
+
+ start_simics($self);
+ runOccSimicsInitCmds($self);
+ runOccSimicsTraceInitCmds($self);
+ setOccBreakpointOnFunction($self,"main");
+ runOccToBreakpoint($self);
+ deleteOccBreakpoints($self);
+ getSimicsTime($self);
+}
+
+#------------------------------------------------
+# @fn startAndRunOccUntilSsxBoot
+#
+# @brief Automates all steps needed to reach SSX
+# entry point __ssx_boot(), then stops on
+# breakpoint there.
+#
+# @return None
+#------------------------------------------------
+sub startAndRunOccUntilSsxBoot
+{
+ my ( $self ) = @_;
+
+ start_simics($self);
+ runOccSimicsInitCmds($self);
+ runOccSimicsTraceInitCmds($self);
+ setOccBreakpointOnFunction($self,"__ssx_boot");
+ runOccToBreakpoint($self);
+ deleteOccBreakpoints($self);
+ getSimicsTime($self);
+}
+
+
+#------------------------------------------------
+# @fn runOccSimicsInitCmds
+#
+# @brief Runs batch of simics commands to init OCC
+# Simics Environment
+#
+# @return None
+#------------------------------------------------
+sub runOccSimicsInitCmds
+{
+ my ( $self ) = @_;
+
+ foreach(@G_occ_start_cmds)
+ {
+ simics_cmd($self,$_);
+ }
+}
+
+#------------------------------------------------
+# @fn setOccBreakpointOnFunction
+#
+# @brief Sets breakpoint
+#
+# @param func - String with name of function to break on
+#
+# @return None
+#------------------------------------------------
+sub setOccBreakpointOnFunction
+{
+ my ( $self, $func ) = @_;
+
+ simics_cmd($self,"break (sym $func)");
+}
+
+#------------------------------------------------
+# @fn setOccBreakpointOnWriteToVariable
+#
+# @brief Sets breakpoint
+#
+# @param var - String with name of variable to break on
+# when it is written to
+#
+# @return None
+#------------------------------------------------
+sub setOccBreakpointOnWriteToVariable
+{
+ my ( $self, $var ) = @_;
+
+ setOccBreakpointOnAddressWrite($self,"(sym \"&$var\")");
+}
+
+#------------------------------------------------
+# @fn setOccBreakpointOnCycles
+#
+# @brief Sets breakpoint
+#
+# @param num_cycles - Number of cycles until now that
+# simics will run until it breaks.
+#
+# @return None
+#------------------------------------------------
+sub setOccBreakpointOnCycles
+{
+ my ( $self, $num_cycles ) = @_;
+
+ simics_cmd($self,"OccComplex.OccSimpleSlot.cpu.cycle-break $num_cycles");
+}
+
+#------------------------------------------------
+# @fn setOccBreakpointOnSource
+#
+# @brief Sets breakpoint
+#
+# @param file - Filename that breakpoint is in
+# @param line - Line in filename that breakpoint is on
+#
+# @return None
+#------------------------------------------------
+sub setOccBreakpointOnSource
+{
+ my ( $self, $file, $line ) = @_;
+
+ simics_cmd($self,"break -x (pos $file:$line)");
+}
+
+#------------------------------------------------
+# @fn setOccBreakpointOnAddress
+#
+# @brief Sets breakpoint
+#
+# @param hex_addr - "0x"-prefixed string with address
+# to break on when accessed as read,
+# write, or executed (see $flags)
+# @param flags - String; can be -r, -w, -x. -x is default
+#
+# @return None
+#------------------------------------------------
+sub setOccBreakpointOnAddress
+{
+ # flags can be -r, -w, -x. -x is default
+ my ( $self, $hex_addr, $flags ) = @_;
+
+ simics_cmd($self,"break $hex_addr $flags");
+}
+
+#------------------------------------------------
+# @fn setOccBreakpointOnAddressExecute
+#
+# @brief Sets breakpoint
+#
+# @param hex_addr - "0x"-prefixed string with address
+# to break on when accessed as execute,
+#
+# @return None
+#------------------------------------------------
+sub setOccBreakpointOnAddressExecute
+{
+ my ( $self, $hex_addr) = @_;
+
+ setOccBreakpointOnAddress($self, $hex_addr, "-x");
+}
+
+#------------------------------------------------
+# @fn setOccBreakpointOnAddressWrite
+#
+# @brief Sets breakpoint
+#
+# @param hex_addr - "0x"-prefixed string with address
+# to break on when accessed as write,
+#
+# @return None
+#------------------------------------------------
+sub setOccBreakpointOnAddressWrite
+{
+ my ( $self, $hex_addr) = @_;
+
+ setOccBreakpointOnAddress($self, $hex_addr, "-w");
+}
+
+#------------------------------------------------
+# @fn runOccToBreakpoint
+#
+# @brief Runs simics until breakpoint is set, or
+# timeout (60 seconds) is reached.
+#
+# @return None
+#------------------------------------------------
+sub runOccToBreakpoint
+{
+ my ( $self ) = @_;
+
+ simics_cmd_w_timeout_w_running($self,60,"r");
+ waitForSimicsPrompt($self);
+}
+
+#------------------------------------------------
+# @fn deleteOccBreakpoints
+#
+# @brief Deletes all breakpoints
+#
+# @return None
+#------------------------------------------------
+sub deleteOccBreakpoints
+{
+ my ( $self ) = @_;
+
+ simics_cmd($self,"delete -all");
+}
+
+
+#------------------------------------------------
+# @fn runOccForTimeInterval
+#
+# @brief Runs OCC for time interval of x ms
+#
+# @param time_in_ms - Time in ms that simics should run
+# before stopping.
+#
+# @return None
+#------------------------------------------------
+sub runOccForTimeInterval
+{
+ my ( $self, $time_in_ms ) = @_;
+
+ # x = 150016 cycles ~= 250us;
+ # x * 40 = 10ms
+
+ my $ms_per_loop = 10;
+ my $cyc_per_ms = $self->{cyc_per_ms};
+ my $cyc_per_loop = $cyc_per_ms * 10;
+
+ my $loops = int($time_in_ms / $ms_per_loop);
+ my $cyc_in_last_loop = ($time_in_ms % $ms_per_loop) * $cyc_per_ms;
+
+ for (my $f=0; $f<$loops; $f++)
+ {
+ setOccBreakpointOnCycles($self,$cyc_per_loop);
+ runOccToBreakpoint($self);
+ }
+
+ setOccBreakpointOnCycles($self,$cyc_in_last_loop);
+ runOccToBreakpoint($self);
+}
+
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# OCC Simics Instruction Trace
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
+#------------------------------------------------
+# @fn runOccSimicsTraceInitCmds
+#
+# @brief Initializes Simics and filesyste to grab
+# OCC instruction trace
+#
+# @return None
+#------------------------------------------------
+sub runOccSimicsTraceInitCmds
+{
+ my ( $self ) = @_;
+
+ $self->{temp_file1} = "/tmp/temp_a".time().".txt";
+ $self->{temp_file2} = "/tmp/temp_b".time().".txt";
+
+ if ( -e $self->{instr_file} )
+ {
+ system("rm ".$self->{instr_file}."");
+ }
+ system("touch ".$self->{instr_file}."");
+
+ system("touch ".$self->{trace_file}."");
+ system("cat /dev/null >| ".$self->{trace_file}."");
+
+
+ foreach(@G_trace_start_cmds)
+ {
+ simics_cmd($self,$_);
+ }
+}
+
+#------------------------------------------------
+# @fn startOccSimicsTrace
+#
+# @brief Starts the simics instruction trace
+#
+# @return None
+#------------------------------------------------
+sub startOccSimicsTrace
+{
+ my ( $self ) = @_;
+
+ simics_cmd($self,"trace0.start ".$self->{trace_file}."");
+ simics_cmd($self,"!touch ".$self->{trace_file}."");
+}
+
+#------------------------------------------------
+# @fn stopOccSimicsTrace
+#
+# @brief Stops the simics instruction trace and
+# verifies file exists before returning.
+#
+# @return None
+#------------------------------------------------
+sub stopOccSimicsTrace
+{
+ my ( $self ) = @_;
+
+ # Stop the trace
+ simics_cmd_w_timeout($self,200,"trace0.stop");
+
+ # Flush the filesystem (not sure this actually does anything useful)
+ simics_cmd($self,"!sync");
+
+ # Used to see an issue where the file wouldn't get updated in GSA between
+ # the simics pool system and the sandbox pool system, so this is a check
+ # making sure the file update occurs
+ if( (-z $ENV{"sb"}."/../simics/".$self->{trace_file}."") ){print "..";sleep(5);}
+ if( (-z $ENV{"sb"}."/../simics/".$self->{trace_file}."") ){print "..";sleep(5);}
+ if( (-z $ENV{"sb"}."/../simics/".$self->{trace_file}."") ){print "..";sleep(5);}
+ if( (-z $ENV{"sb"}."/../simics/".$self->{trace_file}."") ){print "..";sleep(5);}
+ if( (-z $ENV{"sb"}."/../simics/".$self->{trace_file}."") ){print "..";sleep(5);}
+ if( (-z $ENV{"sb"}."/../simics/".$self->{trace_file}."") ){print "..";sleep(5);}
+ if( (-z $ENV{"sb"}."/../simics/".$self->{trace_file}."") ){system("sync"); DEBUG($self,1,"ERROR: Don't see trace file ".$ENV{"sb"}."/../simics/".$self->{trace_file}."");}
+}
+
+
+#------------------------------------------------
+# @fn parseOccSimicsTraceFile
+#
+# @brief Parses the simics instruction trace and
+# prepares files for another pass.
+#
+# @return None
+#------------------------------------------------
+sub parseOccSimicsTraceFile
+{
+ my ( $self ) = @_;
+
+ my $trace_file = $self->{trace_file};
+ DEBUG($self,1,"Lines in Trace file: ");
+ system("wc -l \$sb/../simics/$trace_file");
+
+ DEBUG($self,1,"Get instructions\n");
+ system("strings \$sb/../simics/$trace_file | head -n 2");
+
+ # Simics sometimes dumps some garbage into the trace file, so need to pass it through
+ # strings first.
+ system("\\strings \$sb/../simics/$trace_file | \\grep inst | \\grep -ho \"p:0x........\" | \\grep -ho \"........\$\" | sort | uniq > ".$self->{temp_file1}."");
+
+ system("cat ".$self->{instr_file}." ".$self->{temp_file1}." | sort | uniq > ".$self->{temp_file2}."");
+ system("mv ".$self->{temp_file2}." ".$self->{instr_file}."");
+
+ DEBUG($self,1,"Emptying Trace files to save space\n");
+ DEBUG($self,1,"Lines in Inst file: ");
+ system("wc -l ".$self->{instr_file}."");
+ system("LINES=`wc -l \$sb/../simics/$trace_file | cut -d\" \" -f1`; if [ \"\$LINES\" -lt 3 ]; then mv \$sb/../simics/$trace_file /tmp/failure__t_ccov_".int(rand(1000)).".txt; fi");
+ system("LINES=`wc -l ".$self->{instr_file}." | cut -d\" \" -f1`; if [ \"\$LINES\" -eq 0 ]; then mv \$sb/../simics/$trace_file /tmp/failure_ccov_".int(rand(1000)).".txt; fi");
+ #if( (-z $ENV{"sb"}."/../simics/".$self->{instr_file}."") ){system("mv $self->{instr_file} /tmp/failure_ccov.txt"); die "Instruction File Empty!!!\n";}
+
+ system("echo \"\" > \$sb/../simics/$trace_file");
+ system("echo \"\" > ".$self->{temp_file1}."");
+}
+
+
+#------------------------------------------------
+# @fn runOccWithInstructionTrace
+#
+# @brief Runs simics w/ instruction trace, parses instructions
+# out of trace file, and appends to overall instruction
+# trace.
+#
+# @param time_in_ms - Time in ms that simics should
+# execute OCC and grab the instruction
+# trace.
+#
+# @return None
+#------------------------------------------------
+sub runOccWithInstructionTrace
+{
+ my ( $self, $time_in_ms ) = @_;
+
+ # x = 150016 cycles ~= 250us;
+ # x * 40 = 10ms
+
+ my $ms_per_loop = 10;
+ my $cyc_per_ms = $self->{cyc_per_ms};
+ my $cyc_per_loop = $cyc_per_ms * 10;
+
+ my $loops = int($time_in_ms / $ms_per_loop);
+ my $cyc_in_last_loop = ($time_in_ms % $ms_per_loop) * $cyc_per_ms;
+
+ #WORKAROUND: First Loop (10 cycles for workaround)
+ startOccSimicsTrace($self);
+ setOccBreakpointOnCycles($self,10);
+ runOccToBreakpoint($self);
+ stopOccSimicsTrace($self);
+ parseOccSimicsTraceFile($self);
+
+ for (my $f=0; $f<$loops; $f++)
+ {
+ startOccSimicsTrace($self);
+ setOccBreakpointOnCycles($self,$cyc_per_loop);
+ runOccToBreakpoint($self);
+ stopOccSimicsTrace($self);
+ parseOccSimicsTraceFile($self);
+ }
+
+ #Last Loop
+ startOccSimicsTrace($self);
+ setOccBreakpointOnCycles($self,$cyc_in_last_loop);
+ runOccToBreakpoint($self);
+ stopOccSimicsTrace($self);
+ parseOccSimicsTraceFile($self);
+}
+
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# End of Package
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
+1;
+
+##############################################################################
+#-----------------------------------------------------------------------------
+#
+# End of File
+#
+#-----------------------------------------------------------------------------
+##############################################################################
+
diff --git a/src/occ/tools/cpPluginFiles.pl b/src/occ/tools/cpPluginFiles.pl
new file mode 100755
index 0000000..2f24c28
--- /dev/null
+++ b/src/occ/tools/cpPluginFiles.pl
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+
+# This is a utility to generate tmgtSrcParse.C automatically.
+# It will searching backing build if file is not present in the sandbox.
+
+use strict;
+use File::Find ();
+use Time::localtime;
+
+
+#use re 'debug';
+my $VERSION = 1.0;
+
+
+sub usage() {
+ print "Usage: $0 -o output directory \n";
+ print "\n";
+ print "-o: Used as the output directory where plugins files are dropped\n";
+ print "\n\n";
+ exit 1;
+}
+
+
+# Locals
+my $base = $ENV{PWD};
+my $baseBB = $ENV{PWD};
+my $output;
+my $arg;
+my %Comps;
+my $ignore = 1;
+my $fips_comp_id = "$ENV{bs}/fstp/fsp/fips_comp_id.H";
+#occ/incl/comp_ids.h
+my $wordn = "userdata";
+my $wordnd = 0;
+my $Errno = 0;
+my $NA = 1;
+
+while ($ARGV = shift)
+{
+ if ( $ARGV =~ m/-o/i )
+ {
+ $output = shift;
+ }
+}
+
+if ( $output eq "" )
+{
+ print "Please specify an output directory\n\n";
+ usage();
+}
+# Hardcode just the values that occc needs
+$base="$ENV{SANDBOXBASE}/src/occc/405/";
+#$baseBB="$ENV{bb}/src/occc/405/";
+#$baseBB="/afs/austin.ibm.com/projects/esw/occ810/Builds/occ810_130926a/src/occc/405/";
+$baseBB="$ENV{BACKED_SANDBOXDIR}";
+my @values = split(':', $baseBB);
+foreach my $val (@values)
+{
+ if ( $val =~ m/occ810/)
+ {
+ $baseBB=$val;
+ }
+ }
+#we should not input -d option, let $ignore = 1; #so compile won't fail if there are dups
+$wordnd = 4; #look at userdata4
+$wordn .= $wordnd;
+#$NA = 0;
+my $IgnoreDir = "ssx";
+
+# grab all the files we want to copy
+# *_service_codes.h, occSrcParse.C, comp_ids.h
+my $IncludeFiles=`find $base -type f -name \"comp_ids.h\" -or -name \"*_service_codes.h\" -or -name \"*SrcParse.C"`;
+my @IncludeFilesArray= split("\n", $IncludeFiles);
+foreach my $val (@IncludeFilesArray)
+{
+ print "cp $val $output\n";
+ system "cp $val $output\n";
+}
diff --git a/src/occ/tools/fsp_trace_parse.pl b/src/occ/tools/fsp_trace_parse.pl
new file mode 100755
index 0000000..72c2f82
--- /dev/null
+++ b/src/occ/tools/fsp_trace_parse.pl
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+#
+# This file is used by the trace.simics script to format an OCC trace. It pulls
+# data out of the memory of the simics session, packs it into hex, outputs as a
+# file and then runs fsp-trace.
+#
+# FUTURE IMPROVEMENTS
+# 1.
+#
+#
+
+my $filename = "/tmp/occ_output_trace_data.txt";
+my $fsp_trace_loc = "fsp-trace";
+my $data;
+
+while (defined($line = <STDIN>))
+{
+ chomp $line;
+
+ # Initial format is p:0xfffc30b0 0000 0000 0000 0000 0000 0000 0000 0000 ................
+ # and we just want to keep the hex digits
+ $line =~ /^p:\S+\s\s+(\S+.*)\s\s/;
+ my $hex_string = $1;
+
+ #print "$line ---> $hex_string\n";
+ # Split it up into 2 byte segments
+ my @array = split(/\s+/, $hex_string);
+
+ # And pack as hex
+ foreach $entry (@array)
+ {
+ $data .= pack('H4', $entry);
+ }
+}
+
+# Output toa file
+open(FILEHANDLE, ">$filename");
+print FILEHANDLE $data;
+close(FILEHANDLE);
+
+
+# Format the trace
+open(TRAC, "fsp-trace -s trexStringFile $filename |") || die "Failed: $!\n";
+while( <TRAC> )
+{
+ my $line = $_;
+ chomp $line;
+
+ # Find the timestamp. Example: 0015543.977001
+ if($line =~ /^(\d+\.\d+)\|/)
+ {
+ $num = $1;
+
+ $text = sprintf("%014f", $num / 3.6);
+ #print $text . " ";
+
+ $line =~ s/^(\d+\.\d+)\|/$text\|/;
+ }
+
+
+ if($line =~ /Can't open device 2/)
+ {
+ # get rid of stupid warning message
+ }
+ else
+ {
+ print $line . "\n";
+ }
+}
+close(TRAC);
+
+# And delete the file
+#unlink($filename);
diff --git a/src/occ/tools/hocct.pl b/src/occ/tools/hocct.pl
new file mode 100755
index 0000000..ff30a43
--- /dev/null
+++ b/src/occ/tools/hocct.pl
@@ -0,0 +1,739 @@
+#!/usr/bin/perl
+#
+# Homemade OCC Code Coverage Tool (HOCCT)
+#
+# Written by: Timothy Hallett (tghallett@us.ibm.com)
+# Date: 11/17/2011
+# Purpose: To determine code coverage by parsing OCC Simics Execution Trace
+# and comparing it to OCC objdump source code output.
+#
+# Updates: 11/28/2011 - Automatic dump of source/assembler within sandbox
+# - Handle CLI args better (flags instead of static)
+# - Added ability to interleave source code into ccov
+# output files, with variable parameters for number
+# of lines of source context.
+# 11/29/2011 - Added ability to use simics (via OccSimincsAutomate
+# package) to generate the execution/instruction trace
+# 11/30/2011 - Modified Help to give useful information.
+# Added timing of simics & viewer for source-interleave dump
+# Added autobuild of occ.out & image.bin if they are not
+# present in the sandbox.
+# 01/17/2012 - Check for zero instructions run (and helpful error)
+# 01/20/2012 - Updated tool for multi-user/system use (unique instructions.txt filename)
+# Updated tool to start code coverage from __ssx_boot() instead of main()
+#
+# Usage: hocct.pl [args]
+#
+# Output File will be dumped to: /tmp/occ_source_dump.ccov.txt
+#
+# It will contain ":::::" at the start of lines that have been
+# executed in the simics trace that was grabbed.
+#
+# It is receommeded that if a user wants a graphical view of the
+# code coverage, they use the following command:
+# gvimdiff /tmp/occ_source_dump.txt /tmp/occ_source_dump.ccov.txt
+#
+# Ideas: - When opening in Gvim, could eaily convert to HTML (:TOhtml), save
+# and then have a visual representation of the changes.
+# - If it is in HTML, might as well make the hyperlinks actually
+# link to the file...somehow...
+# - Of course, 1 & 1a are moot if you are well versed at GVIM and use
+# that as the diff tool. If that is the case, then you can just use
+# the gF command to go directly to the source & line number you have
+# under the cursor.
+#
+# Todo: 11/30/2011 - Have arg that allows folders to be skipped for counting
+# code coverage, or for source-interleave tool.
+# 11/30/2011 - Create a sandbox and enter it, check out files, compile,
+# start simics, etc. Easy to do, hard to do correctly...
+# ...i.e. ask user for backing build/svn revs? etc...
+# 12/01/2011 - Could probably easily allow user to pass in command file to
+# run while getting trace...
+# 01/20/2012 - Code coverage on applet space? Complex, Would need to break on applet
+# start & end, and keep track of which applet ran.
+
+use strict;
+use File::Basename;
+
+# First email in the list is the primary contact
+my @G_contact_emails = ("tghallett\@us.ibm.com","someone_else\@us.ibm.com");
+my $G_primary_contact = @G_contact_emails[0];
+my $VERSION = "0.1.0";
+
+# Will be using following env vars
+# $ENV{"sb"}
+# $ENV{"MCP_PATH"}
+# $ENV{"MCP_VER"}
+# $ENV{"SANDBOX"}
+# $ENV{"USER"}
+#
+
+# Global variables modified by CLI args
+my $G_instructions_file = "";
+my $G_source_dump_file = "";
+my $G_diff_prog = "";
+my $G_viewer = "";
+my $G_objdump_args = "-d -l";
+my $G_debug_lvl = 0;
+my $G_interleave_source = 0;
+my $G_num_src_lines_context = 5;
+my $G_num_src_lines_before = 0;
+my $G_date = "occ";
+my $G_ccov_time_in_ms = 25;
+
+#Global variables that are internal only
+my $G_inst_counter = 0;
+my $G_source_counter = 0;
+my @G_func_list_from_source;
+my @G_func_executed;
+
+# For debug statistics
+my $G_time_started = 0;
+my $G_time_compare_started = 0;
+my $G_time_compare_ended = 0;
+my $G_time_simics_started = 0;
+my $G_time_simics_ended = 0;
+my $G_time_interleave_started = 0;
+my $G_time_interleave_ended = 0;
+
+#------------------------------------------------
+# Parse Arguments
+#------------------------------------------------
+@ARGV = ('-') unless @ARGV;
+#Available -: __c__fg____lmnopqr__u_wxyz1234567890
+#Available +: abcdefghijklmnopqrstuvwxyz1234567890
+
+while ($ARGV = shift)
+{
+ if ($ARGV =~ m%^-i%i)
+ {
+ $G_instructions_file = shift;
+ }
+ elsif ($ARGV =~ m%^-s%i)
+ {
+ $G_source_dump_file = shift;
+ }
+ elsif ($ARGV =~ m%^-d%i)
+ {
+ # External Diff program
+ $G_diff_prog = shift;
+ }
+ elsif ($ARGV =~ m%^-w%i)
+ {
+ # External EDITOR program
+ $G_viewer = shift;
+ }
+ elsif ($ARGV =~ m%^-v%i)
+ {
+ # Makes use of DEBUG subroutine to spit out debug into
+ $G_debug_lvl = shift;
+ }
+ elsif ($ARGV =~ m%^-j%i)
+ {
+ # Don't play with this unless you know what you are doing
+ $G_objdump_args = shift;
+ }
+ elsif ($ARGV =~ m%^-t%i)
+ {
+ # Don't play with this unless you know what you are doing
+ $G_ccov_time_in_ms = shift;
+ }
+ elsif ($ARGV =~ m%^-e%i)
+ {
+ # Create ccov src interleaved output file
+ if($G_interleave_source == 0){$G_interleave_source = 1;}
+ }
+ elsif ($ARGV =~ m%^-k%i)
+ {
+ # Hide executed assembly from ccov src interleaved output file
+ $G_interleave_source = 2;
+ }
+ elsif ($ARGV =~ m%^-a%i)
+ {
+ # Number of src lines after current in ccov src interleaved output file
+ $G_num_src_lines_context = shift;
+ }
+ elsif ($ARGV =~ m%^-b%i)
+ {
+ # Number of src lines before current in ccov src interleaved output file
+ $G_num_src_lines_before = shift;
+ }
+ elsif ($ARGV =~ m%^-u%i)
+ {
+ # Create unique filenames each run (appends date/time)
+ $G_date = "";
+ }
+ elsif ($ARGV =~ m%^-h%i)
+ {
+ dump_help();
+ exit 0;
+ }
+ else
+ {
+ dump_help();
+ exit 0;
+ }
+}
+
+#------------------------------------------------
+# Check for all required arguments
+#------------------------------------------------
+if(0)
+{
+ # No arguments required at this time.
+}
+
+
+#------------------------------------------------
+# For now, lets die if we aren't in a sandbox
+#------------------------------------------------
+if( !defined($ENV{"sb"}) ){die "This script needs to run in an ODE sandbox!\n";}
+
+#------------------------------------------------
+# Get all Date/Time info for use later in script
+#------------------------------------------------
+my ($second, $minute, $hour, $dayOfMonth, $monthOffset, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
+my $year = 1900 + $yearOffset;
+my $month = 1 + $monthOffset;
+my $day = $dayOfMonth;
+my $yyyymmdd = sprintf("%04d%02d%02d",$year,$month,$day);
+my $hhmmss = sprintf("%02d%02d%02d",$hour,$minute,$second);
+
+if(!($G_date))
+{
+ $G_date = "".$yyyymmdd."_".$hhmmss."";
+}
+$G_time_started = time();
+
+#------------------------------------------------
+# Run commands to generate binaries if needed
+#------------------------------------------------
+if( !(-e "".$ENV{"sb"}."/occ/occ.out") )
+{
+ system("pushd \$sb; make clean && make; popd");
+
+ if( !(-e "".$ENV{"sb"}."/occ/occ.out") ){die "No \$sb/occ/occ.out to run objdump against!";}
+}
+
+if( !(-e "".$ENV{"sb"}."/image.bin") )
+{
+ system("pushd \$sb; make combineImage; popd");
+
+ if( !(-e "".$ENV{"sb"}."/image.bin") ){die "No \$sb/image.bin to run simics with!";}
+}
+
+#------------------------------------------------
+# Run commands to generate objdump file if needed
+#------------------------------------------------
+if(!($G_source_dump_file))
+{
+ my $objdump_args = $G_objdump_args;
+ my $elf_file = "".$ENV{"sb"}."/occ/occ.out";
+ my $output_file = "/tmp/occ_source_".$ENV{"USER"}."_".$ENV{"SANDBOX"}."_".$G_date."";
+ $G_source_dump_file = $output_file;
+
+ my $temp_elf = "/tmp/occ.out.".$ENV{"USER"}."";
+
+ system("cp $elf_file $temp_elf");
+
+ print "Generating Source/Assembler Dump File: $G_source_dump_file\n";
+ system("".$ENV{"MCP_PATH"}."/opt/mcp/bin/ppcnf-".$ENV{"MCP_VER"}."-objdump ".$objdump_args." ".$temp_elf." > ".$output_file."");
+
+ system("ls -lrth $output_file");
+
+ system("rm $temp_elf");
+}
+
+
+#------------------------------------------------
+# Run simics to generate instruction trace file if needed
+#------------------------------------------------
+$G_time_simics_started = time();
+if(!($G_instructions_file))
+{
+ print "Generating OCC Instruction Trace via Simics:\n";
+ sleep(1);
+
+ use lib "/afs/rch/usr4/thallet/public/bin/";
+ use OccSimicsAutomate;
+
+ $G_instructions_file = "/tmp/instructions_".$ENV{"USER"}."_".$ENV{"SANDBOX"}."_".$G_date.".txt";
+
+ my $simics = new OccSimicsAutomate;
+ $OccSimicsAutomate::DEBUG_LEVEL = 1;
+
+ $simics->{instr_file} = $G_instructions_file;
+ $simics->startAndRunOccUntilSsxBoot();
+
+ $simics->runOccWithInstructionTrace($G_ccov_time_in_ms);
+
+ $simics->close();
+}
+$G_time_simics_ended = time();
+
+
+#------------------------------------------------
+# Open Files
+#------------------------------------------------
+open(INST,"<$G_instructions_file");
+open(SOURCE,"<$G_source_dump_file");
+open(CCOV,">$G_source_dump_file.ccov.txt");
+
+
+#-------------------------------------------------------------------
+# Compare Instructions to Source; Create new file with Coverage Info
+#-------------------------------------------------------------------
+$G_time_compare_started = time();
+
+while (<INST>)
+{
+ my $str = $_;
+ chomp($str);
+
+ DEBUG(2,"Searching for $str\n");
+ if( !($_ =~ /^fff/)){DEBUG(1,"Invalid instruction address: $str\n"); next;} #should check to make sure address makes sense
+
+ while(<SOURCE>)
+ {
+ # Only increment source line count if address starts the line.
+ if($_ =~ /^fff/){$G_source_counter++}
+
+ # If this line contains a function call, add it to list.
+ if($_ =~ /(^fff..... <)(.*)(>:)/){push(@G_func_list_from_source,$2);}
+
+ # See if this source line matches the instruction
+ if($_ =~ /^$str/)
+ {
+ # Print to the screen when we see we covered a function call
+ # but don't leave while look, because there will be another
+ # instruction with this same address
+ if($_ =~ /(^fff..... <)(.*)(>:)/){push(@G_func_executed,$2); DEBUG(0,"Executed Function: $2\n");print CCOV ":::::$_";}
+ else
+ {
+ $G_inst_counter++; # Found instruction that matches
+ print CCOV ":::::$_";
+
+ last;
+ }
+ }
+ else
+ {
+ print CCOV $_;
+ }
+ if(eof(SOURCE)){print "Couldn't find instruction @ $str!!!\n";}
+ }
+}
+
+#------------------------------------------------
+# Finish dumping rest of source file
+#------------------------------------------------
+while(<SOURCE>)
+{
+ print CCOV $_;
+}
+
+
+#------------------------------------------------
+# Compare list of functions (executed v. source)
+#------------------------------------------------
+foreach (@G_func_executed)
+{
+ my $func = $_;
+
+ # This must be set to zero before the following foreach
+ # loop runs. It is used as the index to the array.
+ my $idx = 0;
+
+ # Loops through function list in source, looking for
+ # match to an executed function.
+ foreach(@G_func_list_from_source)
+ {
+ $idx++;
+
+ # If funtion matches...
+ if($_ =~ /$func/)
+ {
+ #print "Removing $func Idx: ".($idx-1)."\n";
+
+ # Remove element from this array
+ splice(@G_func_list_from_source,$idx-1,1);
+
+ # Leave for loop
+ last;
+ }
+ }
+}
+
+foreach(@G_func_list_from_source)
+{
+ DEBUG(0,"Didn't Execute Function: $_\n");
+}
+
+
+#------------------------------------------------
+# Print Results to screen
+#------------------------------------------------
+if($G_source_counter)
+{
+ printf("Code Coverage: %2.1f % (%d of %d instructions executed)\n",($G_inst_counter/$G_source_counter)*100,$G_inst_counter,$G_source_counter);
+ print "\nDumped executed code coverage file into ccov output file: $G_source_dump_file.ccov.txt\n\n";
+}
+else
+{
+ die "No instructions were executed, exiting script without continuing processing\n";
+}
+
+
+#------------------------------------------------
+# Cleanup
+#------------------------------------------------
+close(SOURCE);
+close(CCOV);
+close(INST);
+
+$G_time_compare_ended = time();
+
+
+#------------------------------------------------
+# Do a diff if requested
+#------------------------------------------------
+if($G_diff_prog)
+{
+ system("$G_diff_prog $G_source_dump_file $G_source_dump_file.ccov.txt");
+}
+
+
+#------------------------------------------------
+# Do a source dump info ccov file if requested
+#------------------------------------------------
+$G_time_interleave_started = time();
+if($G_interleave_source)
+{
+ print "Dumping source code into ccov output file: $G_source_dump_file.ccov_src.txt\n";
+
+ open(CCOV,"<$G_source_dump_file.ccov.txt");
+ open(SRCCOV,">$G_source_dump_file.ccov_src.txt");
+
+ my $last_file = "";
+ my $last_dir = "";
+ my $last_line_num = 0;
+ my $l_new_file = 0;
+
+ while(<CCOV>)
+ {
+ # Grab file/line num every time
+ if($_ =~ /(^\/gsa\/.*)(:)([0-9]*$)/)
+ {
+ if($l_new_file == 0){print SRCCOV "\n\n"};
+ $last_file = $1;
+ $last_line_num = $3;
+ $l_new_file = 1;
+ DEBUG(1,"Source File: $last_file, Line: $last_line_num\n");
+ my ($f, $d) = fileparse($last_file);
+ $last_dir = $d;
+ DEBUG(4,"Basename: $last_dir\n");
+ if(2 == $G_interleave_source){next;}
+ }
+ elsif ($_ =~ /(^\..*\/.*\.[chS])(:)([0-9]*$)/)
+ {
+ if($l_new_file == 0){print SRCCOV "\n\n"};
+ $last_file = $last_dir.$1;
+ if ( !(-e $last_file)){$last_file = $ENV{"sb"}."/occ/".$1;}
+ if ( !(-e $last_file)){$last_file = $ENV{"sb"}."/ssx/".$1;}
+ if ( !(-e $last_file)){$last_file = $ENV{"sb"}."/ssx/ppc405/".$1;}
+ $last_line_num = $3;
+ $l_new_file = 1;
+ DEBUG(1,"Source File: $last_file, Line: $last_line_num\n");
+ if(2 == $G_interleave_source){next;}
+ }
+ elsif ($_ =~ /(^[a-zA-Z]*\/.*\.[chS])(:)([0-9]*$)/)
+ {
+ if($l_new_file == 0){print SRCCOV "\n\n"};
+ $last_file = $ENV{"sb"}."/occ/".$1;
+ $last_line_num = $3;
+ $l_new_file = 1;
+ DEBUG(1,"Source File: $last_file, Line: $last_line_num\n");
+ if(2 == $G_interleave_source){next;}
+ }
+
+ # If line starts with fff, it is instruction that didn't get executed
+ if($_ =~ /^fff/)
+ {
+ if($l_new_file)
+ {
+ $l_new_file = 0;
+ open(READ,"<$last_file");
+ my @src_lines = <READ>;
+
+ print SRCCOV "-----------------------------------------------------------------------------\n";
+ print SRCCOV "$last_file:$last_line_num\n";
+ print SRCCOV "-----------------------------------------------------------------------------\n";
+
+ print SRCCOV "\n";
+ print SRCCOV "Source:\n";
+ print SRCCOV "------------------------------\n";
+ for(my $f=($G_num_src_lines_before*-1); $f<$G_num_src_lines_context; $f++)
+ {
+ if($last_line_num+$f > 0)
+ {
+ print SRCCOV "".($last_line_num+$f).":\t".@src_lines[($last_line_num+$f-1)];
+ }
+ }
+ print SRCCOV "\n";
+ print SRCCOV "Assembly:\n";
+ print SRCCOV "------------------------------\n";
+
+ close(READ);
+ }
+ print SRCCOV $_;
+ }
+ else
+ {
+ if(2 == $G_interleave_source)
+ {
+ if( !($_ =~ /^:::::/) )
+ {
+ print SRCCOV $_;
+ }
+ }
+ else
+ {
+ print SRCCOV $_;
+ }
+ }
+
+
+ }
+
+ close(CCOV);
+ close(SRCCOV);
+
+ #------------------------------------------------
+ # Open file for viewing if requested
+ #------------------------------------------------
+ if($G_viewer)
+ {
+ system("$G_viewer $G_source_dump_file.ccov_src.txt");
+ }
+}
+$G_time_interleave_ended = time();
+
+
+
+
+
+#------------------------------------------------
+# Dump some Stats if in Debug
+#------------------------------------------------
+if($G_debug_lvl > 0)
+{
+ my $fs1 = -s "$G_instructions_file";
+ my $fs2 = -s "$G_source_dump_file";
+ my $fs3 = -s "$G_source_dump_file.ccov.txt";
+ my $fs4 = -s "$G_source_dump_file.ccov_src.txt";
+
+ my $script_time = time() - $G_time_started;
+ my $mDiff = int($script_time / 60);
+ my $sDiff = sprintf("%02d", $script_time - 60 * $mDiff);
+
+ $script_time = $G_time_compare_ended - $G_time_compare_started;
+ my $cmDiff = int($script_time / 60);
+ my $csDiff = sprintf("%02d", $script_time - 60 * $cmDiff);
+
+ $script_time = $G_time_simics_ended - $G_time_simics_started;
+ my $smDiff = int($script_time / 60);
+ my $ssDiff = sprintf("%02d", $script_time - 60 * $smDiff);
+
+ $script_time = $G_time_interleave_ended - $G_time_interleave_started;
+ my $imDiff = int($script_time / 60);
+ my $isDiff = sprintf("%02d", $script_time - 60 * $imDiff);
+
+ printf("Total Time (mm:ss) = %02d\:%02d\n",$mDiff,$sDiff);
+ printf(" - Simics (mm:ss) = %02d\:%02d\n",$smDiff,$ssDiff);
+ printf(" - Compare (mm:ss) = %02d\:%02d\n",$cmDiff,$csDiff);
+ printf(" - Interleave (mm:ss) = %02d\:%02d\n",$imDiff,$isDiff);
+ print "\n";
+ print "File Sizes:\n";
+ printf(" - $G_instructions_file: %.2f kB\n",($fs1/1024));
+ printf(" - $G_source_dump_file: %.2f kB\n",($fs2/1024));
+ printf(" - $G_source_dump_file.ccov.txt: %.2f kB\n",($fs3/1024));
+ printf(" - $G_source_dump_file.ccov_src.txt: %.2f kB\n",($fs4/1024));
+ print "\n";
+}
+
+
+
+
+
+exit 0;
+#------------------------------------------------
+# End of Program
+#------------------------------------------------
+
+
+
+
+
+
+
+
+
+##############################################################################
+##############################################################################
+#
+# Subroutines
+#
+##############################################################################
+##############################################################################
+
+#Simics command reference
+#
+
+#
+sub DEBUG
+{
+ my ($lvl,$str) = @_;
+ if($lvl <= $G_debug_lvl)
+ {
+ print $str;
+ }
+}
+
+
+##############################################################################
+##############################################################################
+#
+# Help Dump
+#
+##############################################################################
+##############################################################################
+sub dump_help()
+{
+ my $name = "hocct.pl";
+
+ print "\n";
+ print "Usage: $name [options]\n";
+ print "\n";
+ print "Version: $VERSION\n\n";
+
+ print "Usage Notes:\n";
+ print " - Must be run from sandbox unless both [-s] and [-i] args are passed in\n";
+ print " - Output File(s) will be dumped to *.ccov.txt and or *.ccov_src.txt\n";
+ print " - Ccov file will contain \":::::\" at the start of lines that have been\n";
+ print " executed in the simics instruction trace that was used.\n";
+
+ print "\n";
+
+ print "Options:\n";
+ print "\t[-i <file>] Use <file> as instruction trace instead of generating one.\n";
+ print "\t[-s <file>] Use <file> as source dump file instead of generating one.\n";
+ print "\t[-d <program>] Use <program> as diff viewer, and view diff of source dump\n";
+ print "\t and Code Coverage modified source dump.\n";
+ print "\t[-w <program>] Use <program as viewer, and view source-interleaved-code-coverage\n";
+ print "\t output file.\n";
+ print "\t[-v <lvl>] Set verbose to debug level <lvl>\n";
+ print "\t[-t <time(ms)>] Run simics for <time(ms)> of OCC execution time to gather\n";
+ print "\t instruction trace (can't be used with [-i]\n";
+ print "\t[-e] Create source-interleaved-code-coverage file *.ccov_src.txt\n";
+ print "\t leaving all executed instructions from file\n";
+ print "\t[-k] Create source-interleaved-code-coverage file *.ccov_src.txt\n";
+ print "\t but remove all executed instructions from file\n";
+ print "\t[-a <num>] Used with [-e] or [-k]. When doing source-interleave, print\n";
+ print "\t <num> lines after 'unexecuted' source line as context.\n";
+ print "\t[-b <num>] Used with [-e] or [-k]. When doing source-interleave, print\n";
+ print "\t <num> lines after 'unexecuted' source line as context.\n";
+ print "\t[-u] Create unique filenames for each run (appends date/time to filename\n";
+ print "\t[-h] Dump Help\n";
+ print "\n";
+
+ DEBUG(1,"Secret Options:\n");
+ DEBUG(1,"\t[-j <string>] Modifiy objdump arguments\n");
+ DEBUG(1,"\n");
+
+ print "Examples:\n";
+ print "\t- Get code coverage automatically for 35ms of OCC time\n";
+ print "\t $name -t 35\n";
+ print "\n";
+ print "\t- Get code coverage w/ source-interleave automatically for 35ms of OCC time\n";
+ print "\t and print 3 lines of source before un-executed instruction and 5 lines after\n";
+ print "\t then view source-interleaved file in gvim when complete\n";
+ print "\t $name -t 35 -k -a 5 -b 3 -w /usr/bin/gvim\n";
+ print "\n";
+ print "\t- Get code coverage based on an already dumped instruction trace\n";
+ print "\t $name -i /tmp/instructions.txt\n";
+ print "\n";
+ print "\t- Get code coverage based on an already dumped instruction trace, and stop most\n";
+ print "\t STDOUT printing\n";
+ print "\t $name -i /tmp/instructions.txt -v \"-1\"\n";
+ print "\n";
+ print "\t- Get code coverage based on an already dumped instruction trace and source dump\n";
+ print "\t $name -i /tmp/instructions.txt -s /tmp/source_dump.txt\n";
+ print "\n";
+
+ print "Contact:\n";
+ print "\tFor bugs, feature requests, etc., please contact:\n";
+ print "\tPrimary Contact: $G_primary_contact\n";
+ print "\tAll Contacts: ";
+ foreach(@G_contact_emails){print "$_, ";}print "\n";
+ print "\n";
+
+
+ #----------------------------------------
+ # Only print this if we are in debug mode
+ #----------------------------------------
+ if(1 <= $G_debug_lvl)
+ {
+print <<END;
+------------------------------------------------------------------------------
+Instructions for Use
+------------------------------------------------------------------------------
+To get the instruction trace needed for <instruction trace file>:
+ - Start Simics
+ - Load OCC
+ - Set a breakpoint (if you don't do this, the file will be way too huge
+ before you can Ctrl+C)
+ - Run in Simics:
+ simics> load-module trace
+ simics> new-tracer
+ simics> trace0->trace_data = 0
+ simics> trace0->trace_exceptions = 0
+ simics> trace0.start occ_exe_trace
+ simics> r
+ running>...breakpoint hits
+ simics> trace0.stop
+
+ - Run in Sandbox (Bash Prompt):
+ \\grep inst \$sb/../simics/occ_exe_trace | \\grep -ho "p:0x........" | \\grep -ho "........\$" | sort | uniq > /tmp/occ_instructions.txt
+
+ - This grabs all instructions run & physical mem addresses, sorts them,
+ and removes duplicate addresses)
+ - This takes ~1.3seconds/250us worth of OCC data
+
+
+To get the source file needed for <source dump file>:
+ - After compiling:
+ ppcnf-mcp5-objdump -d -l \$sb/occ/occ.out > /tmp/occ_source_dump.txt
+ -- or --
+ The script will just take care of this for you.
+
+Output File will be dumped to: /tmp/occ_source_dump.ccov.txt
+ - It will contain ":::::" at the start of lines that have been
+ executed in the simics trace that was grabbed.
+
+ - It is recommeded that if a user wants a graphical view of the
+ code coverage, they use the following command:
+ gvimdiff /tmp/occ_source_dump.txt /tmp/occ_source_dump.ccov.txt
+
+Notes:
+ - To trace 8 real-world seconds of OCC Simics Execution, simics
+ creates a 250MB file.
+ - This takes ~45 seconds to parse w/ grep/sort/uniq
+ - To trace 250us in OCC time, Simics creates a 10MB file.
+ - This takes ~1.5 seconds to parse w/ grep/sort/uniq
+ - It is very important that both the instruction trace and source file
+ have all their addresses in numerical order.
+
+END
+}
+}
+
diff --git a/src/occ/tools/mkvpozip.sh b/src/occ/tools/mkvpozip.sh
new file mode 100755
index 0000000..dca6e56
--- /dev/null
+++ b/src/occ/tools/mkvpozip.sh
@@ -0,0 +1,66 @@
+DESC=$1
+
+DATE=`date +'%m%d%y84S'`
+VPODIR="/tmp/vpo_zip_$DESC"
+USERNAME=$USER
+
+mkdir -p $VPODIR
+mkdir $VPODIR/gpe
+cd $sb/occc/405
+# Added 3-15-2012, Commented out 3-30-2012
+#make clean && make NO_TRAC_STRINGS=1 OCC_SVN_SIMICS=1 && make combineImage #No APSS
+# Added 3-30-2012, Commented out x-xx-xxxx
+#make clean && make NO_TRAC_STRINGS=1 && make combineImage #w/ APSS
+mk clobber_all && mk -a -DFSPLESS_SIMICS=1 && mk combineImage #w/ APSS
+cp $sb/../obj/ppc/occc/405/image.bin $VPODIR/occ_l3_image_$DESC.bin
+
+# Copy OCC SRAM Image & Symbol/Disassembly
+cp $sb/../obj/ppc/occc/405/occ/occ.bin $VPODIR/occ_sram_image_$DESC.bin
+cp $sb/../obj/ppc/occc/405/occ/occ.out $VPODIR/occ_sram_image_$DESC.out
+cp $sb/../obj/ppc/occc/405/occ/occ.map $VPODIR/occ_sram_image_$DESC.map
+cp $sb/../obj/ppc/occc/405/occ/occ.dis $VPODIR/occ_sram_image_$DESC.dis
+
+# Copy OCC Bootloader & Symbol/Disassembly
+cp $sb/../obj/ppc/occc/405/occBootLoader/bootloader.map $VPODIR/occ_bootloader_$DESC.map
+cp $sb/../obj/ppc/occc/405/occBootLoader/bootloader.out $VPODIR/occ_bootloader_$DESC.out
+cp $sb/../obj/ppc/occc/405/occBootLoader/bootloader.dis $VPODIR/occ_bootloader_$DESC.dis
+
+# Disassemble GPEs & Copy Disassembly of GPE into Zip
+for gpeobj in $(for f in $(find ./ -iname '*\.ps'); do echo $f | sed 's/\.pS/\.o/'; done);
+do
+ BASE=`basename $gpeobj`;
+ /afs/awd/projects/cte/tools/porebinutils/prod/bin/pore-elf64-objdump -d $gpeobj > $VPODIR/gpe/$BASE.$DESC.dis;
+done
+
+zip -r occ_vpo_$DESC.$DATE.zip $VPODIR
+chmod 775 occ_vpo_$DESC.$DATE.zip
+
+echo "Created occ_vpo_$DESC.$DATE.zip @ full path:"
+echo "$sb/occ_vpo_$DESC.$DATE.zip"
+
+rm -rf $VPODIR
+#tar cvf - ./occ_vpo_$DESC.$DATE.zip | ssh $USERNAME@hdmdbld.boeblingen.de.ibm.com 'umask 0022; cd /afs/apd/u/thallet/public/occ_vpo/; tar xvf -'
+
+echo "Do you want to copy occ_vpo_$DESC.$DATE.zip to...?"
+echo "1. hdmdbld.boeblingen.de.ibm.com:/modbld/mur/tim/"
+echo "2. /afs/bb/u/rembold/occ/"
+echo "3. /afs/apd/u/thallet/public/occ_vpo/"
+echo "4. None"
+read choice
+
+
+case $choice in
+ [1]* ) #scp $sb/occ_vpo_$DESC.$DATE.zip $USERNAME@hdmdbld.boeblingen.de.ibm.com:/modbld/mur/tim/;
+ #ssh $USERNAME@hdmdbld.boeblingen.de.ibm.com chmod 755 /modbld/mur/tim/occ_vpo_$DESC.$DATE.zip
+ tar cvf - ./occ_vpo_$DESC.$DATE.zip | ssh $USERNAME@hdmdbld.boeblingen.de.ibm.com 'umask 0022; cd /modbld/mur/tim/; tar xvf -'
+ exit;;
+ [2]* ) #scp $sb/occ_vpo_$DESC.$DATE.zip $USERNAME@hdmdbld.boeblingen.de.ibm.com:/afs/bb/u/rembold/occ/;
+ #ssh $USERNAME@hdmdbld.boeblingen.de.ibm.com chmod 755 /afs/bb/u/rembold/occ/occ_vpo_$DESC.$DATE.zip
+ tar cvf - ./occ_vpo_$DESC.$DATE.zip | ssh $USERNAME@hdmdbld.boeblingen.de.ibm.com 'umask 0022; cd /afs/bb/u/rembold/occ/; tar xvf -'
+ exit;;
+ [3]* ) cp $sb/occ_vpo_$DESC.$DATE.zip /afs/apd/u/thallet/public/occ_vpo/;
+ chmod 755 /afs/apd/u/thallet/public/occ_vpo/occ_vpo_$DESC.$DATE.zip
+ exit;;
+ * ) exit;;
+esac
+
diff --git a/src/occ/tools/occGcov.pl b/src/occ/tools/occGcov.pl
new file mode 100755
index 0000000..2c22ca0
--- /dev/null
+++ b/src/occ/tools/occGcov.pl
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+
+
+use strict;
+use Getopt::Long;
+
+use lib "$ENV{sb}/occc/405/occ/tools";
+use Gcov;
+
+my $dumpfile = "$ENV{sb}/../simics/occ_gcov.bin";
+my $symfile = "$ENV{sb}/../obj/ppc/occc/405/occ/occ.syms";
+
+GetOptions( "file:s" => \$dumpfile,
+ "symfile:s" => \$symfile);
+
+Gcov::main($dumpfile, $symfile);
+
+
+
diff --git a/src/occ/tools/occWebTool/Makefile b/src/occ/tools/occWebTool/Makefile
new file mode 100755
index 0000000..35033e5
--- /dev/null
+++ b/src/occ/tools/occWebTool/Makefile
@@ -0,0 +1,36 @@
+# $Id$
+
+# @file Makefile
+#
+# @brief Makefile OCC Error Log Parser application
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @rc004 rickylie 03/12/2012 Created
+# @ai009 865968 ailutsar 01/09/2013 OCC Error log and trace parser web tool enhancement
+#
+# @endverbatim
+#
+CC = g++
+
+INCDIR += -I../../incl
+INCDIR += -I../../errl
+INCDIR += -I../../trac
+INCDIR += -I../../../ssx/
+
+errllog_CFILES = parser.c
+
+
+all_cfiles = ${errllog_CFILES}
+SOURCES = ${all_cfiles}
+MODE = validation
+
+pgas:
+ $(CC) ${all_cfiles} $(INCDIR) -DOCC_X86_PARSER -Wl,--hash-style=sysv -g -o OCCFileParser
diff --git a/src/occ/tools/occWebTool/parser.c b/src/occ/tools/occWebTool/parser.c
new file mode 100755
index 0000000..2c4b263
--- /dev/null
+++ b/src/occ/tools/occWebTool/parser.c
@@ -0,0 +1,451 @@
+/******************************************************************************
+// @file parser.c
+// @brief OCC ERRL TEST
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section parser.c PARSER.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @rc004 rickylie 02/15/2012 Created
+ * @ai009 865968 ailutsar 01/07/2012 Initial version
+ * OCC Error log and trace parser web tool enhancement
+ * @jh001 881996 joshych 05/07/2013 Support SRAM error log format
+ * @jh006 897972 joshych 09/17/2013 Problems with OCC elog web parser
+ * @jh008 899096 joshych 09/23/2013 OCC Event Log Parser UserDetail Failure
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <memory>
+#include <time.h>
+#include <errl.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define HEX(value,digit_width) std::uppercase << std::setfill('0') << \
+ std::setw(digit_width) << std::hex << (uint32_t)value
+#define DEC(value) std::dec << (uint32_t)value
+#define tracr_buffer_size 1024
+
+// This definition would be changing this to a dynamic variable to be passed
+// into this function
+#define SSX_TIMEBASE_FREQUENCY_HZ 600000000
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+std::string hex_dump(uint8_t* i_binary_buffer, uint32_t i_buffer_size);
+
+//*************************************************************************
+// Global variables
+//*************************************************************************
+std::string g_severityTbl[3] = { "INFORMATIONAL", "PREDICTIVE", "UNRECOVERABLE"}; // @jh006a
+std::string g_calloutTypeTbl[2] = { "HUID", "CompID"}; // @jh006a
+std::string g_UsrDtlTypeTbl[3] = { "TRACE", "CallHome", "BINARY"}; // @jh008a
+
+//*************************************************************************
+// Structures/Classes
+//*************************************************************************
+class ErrlUserDetailsEntryContent
+{
+ public:
+ uint8_t* iv_Content;
+ uint32_t iv_length;
+
+ ErrlUserDetailsEntryContent() {
+ iv_length = 0;
+ iv_Content = NULL;
+ }
+
+ ErrlUserDetailsEntryContent(uint8_t* i_binary_buffer, uint32_t i_buffer_size) {
+ iv_length = i_buffer_size;
+ iv_Content = new uint8_t[iv_length];
+ memcpy(iv_Content, i_binary_buffer, iv_length);
+ }
+
+ ErrlUserDetailsEntryContent & operator=(const ErrlUserDetailsEntryContent & i_ErrlUserDetailsEntryContent){
+ iv_length = i_ErrlUserDetailsEntryContent.iv_length;
+ iv_Content = new uint8_t[iv_length];
+ memcpy(iv_Content, i_ErrlUserDetailsEntryContent.iv_Content, iv_length);
+ }
+
+ ErrlUserDetailsEntryContent(const ErrlUserDetailsEntryContent& i_ErrlUserDetailsEntryContent) {
+ iv_length = i_ErrlUserDetailsEntryContent.iv_length;
+ iv_Content = new uint8_t[iv_length];
+ memcpy(iv_Content, i_ErrlUserDetailsEntryContent.iv_Content, iv_length);
+ }
+
+ ~ErrlUserDetailsEntryContent() {
+ if(iv_Content)
+ {
+ delete [] iv_Content;
+ }
+ }
+
+ std::string hexdump() {
+ return hex_dump(iv_Content, iv_length);
+ }
+};
+
+class OCC_ERRL
+{
+ public:
+ OCC_ERRL();
+ OCC_ERRL(uint8_t*, uint32_t);
+
+ std::string dump_header();
+ std::string dump_userDetails();
+
+ private:
+ /// Error Log Header
+ ErrlEntry_t iv_header;
+
+ /// User Details Entry
+ std::vector<ErrlUserDetailsEntry_t> iv_UserDetailsHeader;
+
+ /// User Details Entry Content
+ std::vector<ErrlUserDetailsEntryContent> iv_UserDetailsContent;
+};
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+std::string OCC_ERRL::dump_header() // jh001c
+{
+ std::stringstream l_stream;
+ std::string l_string;
+
+ l_stream << "\n OCC Error Log Dump";
+ l_stream << "\n-------------------------------------------------------------------------------";
+ l_stream << "\n Error Log Header";
+ l_stream << "\n-------------------------------------------------------------------------------";
+ l_stream << "\n Version : 0x" << HEX(iv_header.iv_version, 2);
+ l_stream << "\n Entry Id : 0x" << HEX(iv_header.iv_entryId, 2);
+ l_stream << "\n Reason Code : 0x" << HEX(iv_header.iv_reasonCode,2);
+ l_stream << "\n Severity : " << g_severityTbl[iv_header.iv_severity]; // @jh006c
+ l_stream << "\n Actions : 0x" << HEX(iv_header.iv_actions.word,2);
+ l_stream << "\n Word 4 : 0x" << HEX(ntohl(iv_header.iv_userData4), 8);
+
+ // loop for print out Callouts
+ // @jh006c - start
+ uint8_t l_index = 0;
+ uint32_t l_callout = 0;
+ for (uint8_t i=0 ; i<iv_header.iv_numCallouts ; i++)
+ {
+ l_callout = iv_header.iv_callouts[i].iv_calloutValue >> 32;
+ if (0 == l_callout)
+ {
+ break;
+ }
+ l_index++;
+ }
+ l_stream << "\n-------------------------------------------------------------------------------";
+ l_stream << "\n Number Of Callouts : 0x" << HEX(l_index, 2)
+ << " (Dec " << DEC(l_index) << ")";
+ l_stream << "\n-------------------------------------------------------------------------------";
+ for (uint8_t i=0 ; i<l_index ; i++)
+ {
+ l_callout = iv_header.iv_callouts[i].iv_calloutValue >> 32;
+ l_stream << "\n Type : " << g_calloutTypeTbl[iv_header.iv_callouts[i].iv_type-1];
+ l_stream << "\n Callout Value : 0x" << HEX(ntohl(l_callout), 8);
+ l_stream << "\n Priority : 0x" << HEX(iv_header.iv_callouts[i].iv_priority, 2);
+ l_stream << "\n-------------------------------------------------------------------------------";
+ }
+ // @jh006c - end
+
+ // print out User Details Header
+ l_stream << "\n UserDetails Header ";
+ l_stream << "\n-------------------------------------------------------------------------------";
+ l_stream << "\n Version : 0x" << HEX(iv_header.iv_userDetails.iv_version, 2);
+ l_stream << "\n Module Id : 0x" << HEX(ntohs(iv_header.iv_userDetails.iv_modId), 4);
+ l_stream << "\n Firmware Level : 0x" << HEX(ntohl(iv_header.iv_userDetails.iv_fwLevel), 8);
+
+ // parsing timestamp to format( seconds: microseconds)
+ l_stream << "\n Time : " << DEC((iv_header.iv_userDetails.iv_timeStamp/SSX_TIMEBASE_FREQUENCY_HZ)/CLOCKS_PER_SEC) << " seconds:"
+ << DEC((iv_header.iv_userDetails.iv_timeStamp/SSX_TIMEBASE_FREQUENCY_HZ)%CLOCKS_PER_SEC ) << " microseconds";
+
+ l_stream << "\n OCC ID : 0x" << HEX(iv_header.iv_userDetails.iv_occId, 2);
+ l_stream << "\n OCC Role : " << ((iv_header.iv_userDetails.iv_occRole != 0) ? "OCC_MASTER":"OCC_SLAVE");
+ l_stream << "\n OCC State : 0x" << HEX(iv_header.iv_userDetails.iv_operatingState, 2);
+
+ // the commited bit is actually stored at reserved1 due to reverse bit order
+ uint8_t l_commited = iv_header.iv_userDetails.iv_reserved1 >> 6;
+ l_stream << "\n Committed : " << (l_commited == 1 ? "true":"false"); // @jh006c
+ l_stream << "\n Word 1 : 0x" << HEX(ntohl(iv_header.iv_userDetails.iv_userData1), 8);
+ l_stream << "\n Word 2 : 0x" << HEX(ntohl(iv_header.iv_userDetails.iv_userData2), 8);
+ l_stream << "\n Word 3 : 0x" << HEX(ntohl(iv_header.iv_userDetails.iv_userData3), 8);
+
+ l_stream << "\n-------------------------------------------------------------------------------";
+ l_stream << "\n Error log Entry Size : " << HEX(ntohs(iv_header.iv_userDetails.iv_entrySize), 4)
+ << " (Dec " << DEC(ntohs(iv_header.iv_userDetails.iv_entrySize)) << ")";
+ l_stream << "\n-------------------------------------------------------------------------------";
+ l_stream << "\n User Details Size : " << HEX(ntohs(iv_header.iv_userDetails.iv_userDetailEntrySize), 4)
+ << " (Dec " << DEC(ntohs(iv_header.iv_userDetails.iv_userDetailEntrySize)) << ")";
+ l_stream << "\n-------------------------------------------------------------------------------";
+
+ l_string = l_stream.str();
+
+ return l_string;
+}
+
+std::string OCC_ERRL::dump_userDetails()
+{
+ std::stringstream l_stream;
+ std::string l_string;
+ FILE *fd = NULL;
+ uint8_t * l_readBufEntry = NULL;
+
+ for(uint32_t l_index = 0; l_index < iv_UserDetailsHeader.size(); l_index++)
+ {
+ // print out header of User Detail Section
+ l_stream << "\n Section : " << l_index+1; // @jh008c
+ l_stream << "\n Version : 0x" << HEX(iv_UserDetailsHeader[l_index].iv_version, 2);
+ l_stream << "\n Type : " << g_UsrDtlTypeTbl[iv_UserDetailsHeader[l_index].iv_type-1]; // jh008c
+ l_stream << "\n Section Size : 0x" << HEX(ntohs(iv_UserDetailsHeader[l_index].iv_size), 4)
+ << " (Dec " << DEC(ntohs(iv_UserDetailsHeader[l_index].iv_size)) << ")";
+ l_stream << "\n Section Data : ";
+ l_stream << iv_UserDetailsContent[l_index].hexdump();
+
+ // parsing User Detail
+ switch(iv_UserDetailsHeader[l_index].iv_type)
+ {
+ case ERRL_USR_DTL_TRACE_DATA: // Traces
+ l_stream << "\n-------------------------------------------------------------------------------";
+ l_stream << "\n Trace Data\n";
+
+ do{
+ // open file to store traces data
+ std::ofstream l_fstr_out("/tmp/tmp_occ_trace", std::ios::binary);
+ if(!l_fstr_out.is_open())
+ {
+ //open fstream failed
+ l_stream << "\nFailed to open trace file";
+ break;
+ }
+
+ // dump trace data to file, then close it
+ l_fstr_out.write((const char*)iv_UserDetailsContent[l_index].iv_Content,
+ iv_UserDetailsContent[l_index].iv_length);
+ l_fstr_out.close();
+
+ // call fsp-trace to get traces content
+ l_readBufEntry = new uint8_t[tracr_buffer_size];
+
+ // use popen to execute fsp-trace
+ fd = popen("./fsp-trace -s ./trexStringFile /tmp/tmp_occ_trace|sed \"/Can't open device 2/d\";rm /tmp/tmp_occ_trace", "r");
+ if(NULL == fd)
+ {
+ //popen failed
+ l_stream << "\nFailed to execute fsp-trace command";
+ break;
+ }
+
+ //read all data into buffer
+ while(fgets((char*)l_readBufEntry, tracr_buffer_size, fd))
+ {
+ l_stream << l_readBufEntry;
+ }
+
+ // close popen fd
+ pclose(fd);
+
+
+ }while(FALSE);
+ break;
+ default:
+ break;
+ }
+ l_stream << "\n-------------------------------------------------------------------------------";
+ }
+
+ l_string = l_stream.str();
+
+ if(l_readBufEntry)
+ {
+ delete [] l_readBufEntry;
+ }
+
+ return l_string;
+}
+
+OCC_ERRL::OCC_ERRL()
+{
+ memset(&iv_header, 0, sizeof(iv_header));
+}
+
+// @jh008c
+OCC_ERRL::OCC_ERRL(uint8_t* i_binary_buffer, uint32_t i_buffer_size)
+{
+ uint32_t l_sizeRead = 0;
+ ErrlUserDetailsEntry_t l_UserDetailsEntry;
+ //copy Error Log Header into ErrlEntry_t
+ if (i_buffer_size >= sizeof(ErrlEntry_t))
+ {
+ memcpy(&iv_header, i_binary_buffer, sizeof(ErrlEntry_t));
+ l_sizeRead = sizeof(ErrlEntry_t);
+ }
+
+ while(l_sizeRead < i_buffer_size){
+ // make sure we have the enough buffer size
+ if (l_sizeRead+sizeof(ErrlUserDetailsEntry_t) <= i_buffer_size)
+ {
+ // copy User Details Entry structure
+ memset(&l_UserDetailsEntry, 0x00, sizeof(l_UserDetailsEntry));
+ memcpy(&l_UserDetailsEntry, i_binary_buffer + l_sizeRead, sizeof(ErrlUserDetailsEntry_t));
+ l_sizeRead += sizeof(ErrlUserDetailsEntry_t);
+ if (l_sizeRead+ntohs(l_UserDetailsEntry.iv_size) <= i_buffer_size)
+ {
+ //get User Details Entry content
+ ErrlUserDetailsEntryContent l_UserDetailsEntryContent(i_binary_buffer + l_sizeRead,
+ ntohs(l_UserDetailsEntry.iv_size));
+ l_sizeRead += ntohs(l_UserDetailsEntry.iv_size);
+ // push user detail structure and content into containers
+ iv_UserDetailsHeader.push_back(l_UserDetailsEntry);
+ iv_UserDetailsContent.push_back(l_UserDetailsEntryContent);
+ }
+ else
+ {
+ break;
+ } // check l_UserDetailsEntry.iv_size
+ }
+ else
+ {
+ break;
+ } // check ErrlUserDetailsEntry_t
+ }
+
+}
+
+std::string hex_dump(uint8_t* i_binary_buffer, uint32_t i_buffer_size)
+{
+ std::stringstream l_stream;
+ std::string l_string;
+
+ for(uint32_t i = 0; i < i_buffer_size; i++)
+ {
+ l_stream << HEX((uint32_t)i_binary_buffer[i], 2);
+ if(3 == i%4) // 4 bytes as a group
+ {
+ l_stream << " ";
+ }
+ if(15 == i%16) // insert new line and space
+ {
+ l_stream << "\n ";
+ }
+ }
+
+ l_string = l_stream.str();
+
+ return l_string;
+}
+
+// Function Specification
+//
+// Name: main
+//
+// Description: main function
+//
+// Flow: FN=None
+//
+// End Function Specification
+
+int main(int argc, char* argv[])
+{
+ OCC_ERRL * l_occ_errl = NULL; // Error Log Object
+ std::vector<uint8_t> l_readBufEntry; // Buffer for storing source data
+ uint32_t l_len = 0; // length of source data
+
+ if (argc > 2)
+ {
+ do {
+ std::ifstream l_fstr_in;
+ std::ofstream l_fstr_out;
+
+ //open file for reading source of Error Log
+ l_fstr_in.open(argv[1], std::ios::binary);
+
+ // open file for writing parsing result
+ l_fstr_out.open(argv[2], std::ios::binary);
+
+ if (!l_fstr_in.is_open() || !l_fstr_out.is_open())
+ {
+ //open fstream failed
+ std::cout << "Failed to open file\n";
+ break;
+ }
+
+ // get length of file:
+ l_fstr_in.seekg (0, std::ios::end);
+ l_len = l_fstr_in.tellg();
+ l_fstr_in.seekg (0, std::ios::beg);
+
+ l_readBufEntry.resize((l_len));
+ l_fstr_in.read ((char*)&l_readBufEntry[0],l_len);
+ l_fstr_in.close();
+
+ try{
+ // create OCC ERRL object
+ l_occ_errl = new OCC_ERRL(&l_readBufEntry[0], l_readBufEntry.size());
+
+ if(l_occ_errl)
+ {
+ // get ERRL header and dump to file
+ std::string l_string = l_occ_errl->dump_header();
+ l_fstr_out << l_string;
+
+ // get user details and dump to file
+ l_string = l_occ_errl->dump_userDetails();
+ l_fstr_out << l_string;
+ }
+ }
+ catch(...)
+ {
+ l_fstr_out << "Parsing error!\n";
+ }
+
+ l_fstr_out.close();
+
+ }while(FALSE);
+ }
+ else
+ {
+ std::cout << "Usage: OCCFileParser <input_file> <output_file>\n";
+ }
+
+ if(l_occ_errl)
+ {
+ delete l_occ_errl;
+ }
+
+ return 0;
+}
diff --git a/src/occ/tools/occ_amec_sensors.py b/src/occ/tools/occ_amec_sensors.py
new file mode 100755
index 0000000..0994790
--- /dev/null
+++ b/src/occ/tools/occ_amec_sensors.py
@@ -0,0 +1,367 @@
+# @file - occ_amec_sensors.py
+# @brief Create Simics Commands for Reading AMEC Sensors
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# thallet 02/28/2012 Created
+# $fk002 905632 fmkassem 11/18/2013 Removed cpm support.
+
+
+from time import sleep
+from random import randint
+import sys
+import re
+
+##############################################################################
+###########################################################
+# Globals
+###########################################################
+##############################################################################
+
+# To create this listing, run the following command:
+#\grep g_amec_sys sensor_table.c | \grep " SENSOR_PTR" | sed 's/),.*$/",/g' | sed 's/^.*&/"/g'
+amec_sensors = [
+"g_amec_sys.fw.ameintdur",
+"g_amec_sys.fw.amessdur[0]",
+"g_amec_sys.fw.amessdur[1]",
+"g_amec_sys.fw.amessdur[2]",
+"g_amec_sys.fw.amessdur[3]",
+"g_amec_sys.fw.amessdur[4]",
+"g_amec_sys.fw.amessdur[5]",
+"g_amec_sys.fw.amessdur[6]",
+"g_amec_sys.fw.amessdur[7]",
+"g_amec_sys.fw.probe250us[0]",
+"g_amec_sys.fw.probe250us[1]",
+"g_amec_sys.fw.probe250us[2]",
+"g_amec_sys.fw.probe250us[3]",
+"g_amec_sys.fw.probe250us[4]",
+"g_amec_sys.fw.probe250us[5]",
+"g_amec_sys.fw.probe250us[6]",
+"g_amec_sys.fw.probe250us[7]",
+"g_amec_sys.fw.gpetickdur[0]",
+"g_amec_sys.fw.gpetickdur[1]",
+"g_amec_sys.fw.prcdupdatedur",
+"g_amec_sys.sys.tempambient",
+"g_amec_sys.sys.altitude",
+"g_amec_sys.sys.pwr250us",
+"g_amec_sys.fan.pwr250usfan",
+"g_amec_sys.io.pwr250usio",
+"g_amec_sys.storage.pwr250usstore",
+"g_amec_sys.fan.fanspeedavg",
+"g_amec_sys.sys.todclock0 ",
+"g_amec_sys.sys.todclock1 ",
+"g_amec_sys.sys.todclock2 ",
+"g_amec_sys.proc[0].freqa250us",
+"g_amec_sys.proc[0].ips2ms",
+"g_amec_sys.proc[0].memsp2ms",
+"g_amec_sys.proc[0].pwr250us",
+"g_amec_sys.proc[0].pwr250usvdd",
+"g_amec_sys.proc[0].cur250usvdd",
+"g_amec_sys.proc[0].pwr250usvcs",
+"g_amec_sys.proc[0].pwr250usmem",
+"g_amec_sys.proc[0].sleepcnt2ms",
+"g_amec_sys.proc[0].winkcnt2ms",
+"g_amec_sys.proc[0].sp250us",
+"g_amec_sys.proc[0].temp2ms",
+"g_amec_sys.proc[0].temp2mspeak",
+"g_amec_sys.proc[0].util2ms",
+"g_amec_sys.sys.vrfan250usproc",
+"g_amec_sys.sys.vrhot250usproc",
+"g_amec_sys.sys.vrfan250usmem",
+"g_amec_sys.sys.vrhot250usmem",
+"g_amec_sys.proc[0].temp2mscent",
+"g_amec_sys.proc[0].temp2msdimm",
+"g_amec_sys.proc[0].memsp2ms_tls",
+"g_amec_sys.proc[0].vrm[0].uvolt250us",
+"g_amec_sys.proc[0].vrm[1].uvolt250us",
+"g_amec_sys.proc[0].vrm[0].volt250us",
+"g_amec_sys.proc[0].vrm[1].volt250us",
+]
+
+#\grep g_amec_sys sensor_table.c | \grep " CORE_SENSOR_PTR" | sed 's/),.*$/",/g' | sed 's/^.*&/"/g' | sed 's/core, /core[0]./g'
+amec_core_sensors = [
+"g_amec_sys.proc[0].core[0].freq250us",
+"g_amec_sys.proc[0].core[0].freqa250us",
+"g_amec_sys.proc[0].core[0].ips2ms",
+"g_amec_sys.proc[0].core[0].mcpifd2ms",
+"g_amec_sys.proc[0].core[0].mcpifi2ms",
+"g_amec_sys.proc[0].core[0].spurr2ms",
+"g_amec_sys.proc[0].core[0].temp2ms",
+"g_amec_sys.proc[0].core[0].util2ms",
+"g_amec_sys.proc[0].core[0].mstl2ms",
+"g_amec_sys.proc[0].core[0].cmt2ms",
+"g_amec_sys.proc[0].core[0].cmrd2ms",
+"g_amec_sys.proc[0].core[0].cmwr2ms",
+"g_amec_sys.proc[0].core[0].ppic",
+"g_amec_sys.proc[0].core[0].pwrpx250us",
+]
+
+#\grep g_amec_sys sensor_table.c | \grep " PORTPAIR_SENSOR_PTR" | sed 's/),.*$/",/g' | sed 's/^.*&/"/g' | sed 's/memctl, /memctl[0]./g' | sed 's/portpair, /portpair[0]./g'
+amec_portpair_sensors = [
+"g_amec_sys.proc[0].memctl[0].centaur.portpair[0].mac2ms",
+"g_amec_sys.proc[0].memctl[0].centaur.portpair[0].mpu2ms",
+"g_amec_sys.proc[0].memctl[0].centaur.portpair[0].mirb2ms",
+"g_amec_sys.proc[0].memctl[0].centaur.portpair[0].mirl2ms",
+"g_amec_sys.proc[0].memctl[0].centaur.portpair[0].mirm2ms",
+"g_amec_sys.proc[0].memctl[0].centaur.portpair[0].mirh2ms",
+"g_amec_sys.proc[0].memctl[0].centaur.portpair[0].mts2ms",
+"g_amec_sys.proc[0].memctl[0].centaur.portpair[0].memsp2ms",
+]
+
+##############################################################################
+###########################################################
+# Functions
+###########################################################
+##############################################################################
+def print_symbol( str ):
+ tick = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + '\"')
+ print str + ": ", tick[1].rstrip('\n')
+ return
+
+def print_all_as_hex( str ):
+ tick = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + '\"')
+ splitter = re.compile(r'(\d+)')
+ p_sym = tick[1].rstrip('\n')
+ r_sym = splitter.split(p_sym)
+ out_str = ''
+ for item in r_sym:
+ if item.isdigit():
+ if (int(item) > 0xffffffff):
+ out_str += "0x%016x" % int(item)
+ else:
+ out_str += "0x%08x" % int(item)
+ else:
+ out_str += `item`
+
+ print out_str
+ return
+
+def print_symbol_value_hex( str ):
+ tick = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + '\"')
+ print str + ": \t", "0x%04x" % int(tick[1].rstrip('\n'))
+ return
+
+def print_symbol_value_hex_apss( str ):
+ tick = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + '\"')
+ value = int(tick[1].rstrip('\n'))
+ print str + ": \t", "0x%04x (raw=0x%04x), %d" % ((value&0x0fff), (value),(value&0x0fff))
+ return
+
+def print_sensor_quick( str ):
+ sample = ".sample"
+ max = ".sample_max"
+ min = ".sample_min"
+ mnsnsr = ".mini_sensor"
+ update = ".update_tag"
+
+ s_sample = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + sample + '\"')
+ s_max = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + max + '\"')
+ s_min = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + min + '\"')
+ s_upd = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + update + '\"')
+ s_mns = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"*' + str + mnsnsr + '\"')
+
+ p_str = str.replace("g_amec_sys.","")
+ p_sample = s_sample[1].rstrip('\n')
+ p_max = s_max[1].rstrip('\n')
+ p_min = s_min[1].rstrip('\n')
+ p_upd = s_upd[1].rstrip('\n')
+ p_mns = s_mns[1].rstrip('\n')
+
+ print p_str.ljust(45) + ":\t", p_sample.rjust(6) + ", " \
+ + p_max.rjust(6) + ", " \
+ + p_min.rjust(6) + ", " \
+ + p_mns.rjust(6) + ", " \
+ + p_upd.rjust(10)
+ return
+
+def print_core_sensor_quick( ):
+ for sensor in amec_core_sensors:
+ print ""
+ for x in range(0,12):
+ name = sensor.replace("core[0]","core["+str(x)+"]")
+ print_sensor_quick(name)
+
+def print_sensor_quick_string( strin ):
+ print "Name".ljust(45) + " \t", "Sample".rjust(6) + ", " \
+ + "Max".rjust(6) + ", " \
+ + "Min".rjust(6) + ", " \
+ + "MnSnsr".rjust(6) + ", " \
+ + "UpdateTag".rjust(10)
+
+ for sensor in amec_core_sensors:
+ for x in range(0,12):
+ name = sensor.replace("core[0]","core["+str(x)+"]")
+ if re.search( strin, name ):
+ print_sensor_quick(name)
+ for sensor in amec_sensors:
+ if re.search( strin, sensor ):
+ print_sensor_quick(sensor)
+ for sensor in amec_portpair_sensors:
+ for x in range(0,8):
+ t_name = sensor.replace("memctl[0]","memctl["+str(x)+"]")
+ for x in range(0,2):
+ name = t_name.replace("portpair[0]","portpair["+str(x)+"]")
+ if re.search( strin, name ):
+ print_sensor_quick(name)
+
+
+def print_array_quick( strin, idx ):
+ for x in range(0,idx):
+ name = strin.replace("[0]","["+str(x)+"]")
+ s_sample = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + name + '\"')
+ p_sample = s_sample[1].rstrip('\n')
+ print name + ":\t" + p_sample
+
+def set_value( strin, value ):
+ s_sample = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + strin + '\"')
+ p_sample = s_sample[1].rstrip('\n')
+ print "Old: " + strin + ":\t" + p_sample
+
+ s_sample = cli.quiet_run_command( G_occ_list[0] + ".oci_space.set (" + G_occ_list[0] + ".cpu.sym " + '\"&' + strin + '\") ' + str(value) + " (sym \"sizeof(" + strin + ")\")")
+
+ s_sample = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + strin + '\"')
+ p_sample = s_sample[1].rstrip('\n')
+ print "New: " + strin + ":\t" + p_sample
+
+
+def print_sensors_all( ):
+ print "Name".ljust(45) + " \t", "Sample".rjust(6) + ", " \
+ + "Max".rjust(6) + ", " \
+ + "Min".rjust(6) + ", " \
+ + "MnSnsr".rjust(6) + ", " \
+ + "UpdateTag".rjust(10)
+ for sensor in amec_sensors:
+ print_sensor_quick(sensor)
+
+ print_core_sensor_quick()
+
+ for sensor in amec_portpair_sensors:
+ for x in range(0,8):
+ t_name = sensor.replace("memctl[0]","memctl["+str(x)+"]")
+ for x in range(0,2):
+ name = t_name.replace("portpair[0]","portpair["+str(x)+"]")
+ print_sensor_quick(name)
+ print ""
+
+ print __file__
+
+
+
+def print_apss_pwr( ):
+ strin = "G_apss_pwr_meas->adc[0]"
+ for x in range(0,16):
+ name = strin.replace("[0]","["+str(x)+"]")
+ print_symbol_value_hex_apss(name)
+ print ""
+ print_symbol_value_hex("G_apss_pwr_meas->gpio[0]")
+ print_symbol_value_hex("G_apss_pwr_meas->gpio[1]")
+ print ""
+ print_symbol_value_hex("G_apss_pwr_meas->tod")
+
+
+##############################################################################
+###########################################################
+# Register some New Simics Commands
+###########################################################
+##############################################################################
+
+#----------------------------------------------------------
+#
+#
+new_command("occ-print-sensor", print_sensor_quick_string,
+ args = [arg(str_t, "name")],
+ alias = "ps",
+ type = "occ-fw-module-commands",
+ short = "Print a sensor",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["my_other_command"],
+ doc = """
+ <b>my-command</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+#----------------------------------------------------------
+#
+#
+new_command("occ-print-sensors-all", print_sensors_all,
+ args = [],
+ alias = "psa",
+ type = "occ-fw-module-commands",
+ short = "Print all sensors",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["my_other_command"],
+ doc = """
+ <b>my-command</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+#----------------------------------------------------------
+#
+#
+new_command("occ-print-array", print_array_quick,
+ args = [arg(str_t, "name"),arg(int_t, "arg", "?", 10),],
+ alias = "pa",
+ type = "occ-fw-module-commands",
+ short = "Print an array",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["my_other_command"],
+ doc = """
+ <b>my-command</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+#----------------------------------------------------------
+#
+#
+new_command("occ-set-value", set_value,
+ args = [arg(str_t, "name"),arg(int_t, "arg", "?", 10),],
+ alias = "sv",
+ type = "occ-fw-module-commands",
+ short = "Set a variable to a value",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["my_other_command"],
+ doc = """
+ <b>my-command</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+#----------------------------------------------------------
+#
+#
+new_command("occ-dump-raw-power", print_apss_pwr,
+ args = [],
+ alias = "drp",
+ type = "occ-fw-module-commands",
+ short = "OCC Dump Raw Power from APSS",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["my_other_command"],
+ doc = """
+ <b>my-command</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+# this is my Python function that will be called when the
+# command is invoked from the Simics prompt.
+#def my_command_fun(int_arg, str_arg, flag_arg):
+# print "My integer: %d" % int_arg
+# print "My string: %s" % str_arg
+# print "Flag is",
+# if flag_arg:
+# print "given"
+# else:
+# print "not given"
+# return int_arg
+## register our new command
+#new_command("my-command", my_command_fun,
+# args = [arg(int_t, "arg", "?", 10), arg(str_t, "name"),
+# arg(flag_t, "-f")],
+# alias = "mc",
+# type = "my-module-commands",
+# short = "my command does it",
+# doc_items = [("NOTE", "This command is best")],
+# see_also = ["my_other_command"],
+# doc = """
+# <b>my-command</b> is best.
+# This is its documentation. <i>arg</i>
+# is the first argument...""")
+
diff --git a/src/occ/tools/occ_autotest b/src/occ/tools/occ_autotest
new file mode 100755
index 0000000..0743b82
--- /dev/null
+++ b/src/occ/tools/occ_autotest
@@ -0,0 +1,609 @@
+#!/bin/bash
+################################################################################
+## Simics automation using autosim
+## 2011-10-15 tgh modified to run occ in simics
+##
+## Usage:
+## autocitest [--quiet] <backing_build> <sandbox_name> <hbi_image>
+################################################################################
+function waitkb()
+{
+
+ ## wait for kbhit to continue
+ ## echo "Hit any key to continue"
+ ## read kb
+ echo "."
+}
+
+function usage()
+{
+
+ echo "usage:"
+ echo "$0 [--quiet] backing_tree_dir sandbox_name path_to_hbicore_test_img "
+}
+
+
+function stopsim()
+{
+ # Stop simics
+ echo "Stopping simics"
+ autosim $NOWIN $VERBOSE --stopsim
+ if [ $? -ne 0 ] ; then
+ echo "WARNING: Unable to stop simics cleanly"
+ fi
+}
+
+
+function stopserver()
+{
+ # Stop simics server
+ echo "Stopping simics server"
+ autosim $NOWIN $VERBOSE --stopserver
+ if [ $? -ne 0 ] ; then
+ echo "WARNING: Unable to stop simics server cleanly"
+ fi
+}
+
+
+function runsimics()
+{
+ # Stop simics server
+ echo "Starting simics server"
+ autosim $NOWIN $VERBOSE --simcmd "r"
+ if [ $? -ne 0 ] ; then
+ echo "WARNING: Unable to start simics server cleanly"
+ fi
+}
+
+function loadocc()
+{
+ # Stop simics server
+ echo "Loading OCC"
+ autosim $NOWIN $VERBOSE --simcmd "run-command-file $sb/occc/405/occ/tools/occ_post_model_hook.simics" 1>> /tmp/totaltests3.log 2> /dev/null
+ if [ $? -ne 0 ] ; then
+ echo "WARNING: Unable to load OCC cleanly"
+ fi
+}
+
+function simicsCmd()
+{
+ # Run a Simics command
+ echo "Running Simics Command -- $1"
+ autosim $NOWIN $VERBOSE --simcmd "$1" 1>> /tmp/totaltests2.log 2> /dev/null
+ if [ $? -ne 0 ] ; then
+ echo "WARNING: Unable to run Simics Command $1"
+ fi
+}
+
+function fspCmd()
+{
+ # Run a FSP command
+ echo "Running Simics FSP Command -- $1"
+ autosim $NOWIN $VERBOSE --fspcmd "$1" 1>> /tmp/totaltests2.log 2> /dev/null
+ if [ $? -ne 0 ] ; then
+ echo "WARNING: Unable to run Simics FSP Command $1"
+ fi
+}
+
+function simicsFspToOccCmd()
+{
+ # Stop simics server
+ echo "Running FSP->OCC Command -- $*"
+ # There must be a more eloquent way than this
+ case "$#" in
+ 1) autosim $NOWIN $VERBOSE --simcmd "@occ_fsp_command('$1')" 1>> /tmp/totaltests2.log 2> /dev/null
+ ;;
+ 2) autosim $NOWIN $VERBOSE --simcmd "@occ_fsp_command('$1', '$2')" 1>> /tmp/totaltests2.log 2> /dev/null
+ ;;
+ 3) autosim $NOWIN $VERBOSE --simcmd "@occ_fsp_command('$1', '$2', '$3')" 1>> /tmp/totaltests2.log 2> /dev/null
+ ;;
+ *) echo "Num args not supported"
+ ;;
+ esac
+ if [ $? -ne 0 ] ; then
+ echo "WARNING: Unable to run Simics Command $1"
+ fi
+ sleep 10;
+ autosim $NOWIN $VERBOSE --simcmd "@occ_fsp_response(128)" 1>> /tmp/totaltests2.log 2> /dev/null
+}
+
+function occTrace()
+{
+ TRAC_ADDR_TMP=`nm $sb/../obj/ppc/occc/405/occ/occ.out | \grep "g_trac_inf_buffer" | awk '{print $1}' | sed 's/^00000000/0x/g'`
+ TRAC_ADDR=`perl -e "printf(\"0x%08x\",$TRAC_ADDR_TMP - 0xfff80000)"`
+ TRAC_LEN="0x6000"
+
+ # Save off full OCC binary to generate code coverage from
+ echo "Collecting Trace"
+ rm $sb/../simics/occ_trace.bin
+ simicsCmd "p8Proc0.OccComplexSlot.OccSimpleSlot.sram_image.save occ_trace.bin $TRAC_ADDR $TRAC_LEN"
+
+ #Wait in case of filesystem sync issues
+ sleep 60
+ echo "Attempting a filesystem sync"
+ sync
+ sleep 10
+
+ # Parse
+ echo "Parsing Trace"
+ fsp-trace -s $sb/../obj/trexStringFile $sb/../simics/occ_trace.bin | strings | tee $sb/../simics/occ_trace.txt
+}
+
+function runTestApplet()
+{
+ applet=$1
+
+ if [ ! -d $sb/../unit_test ]; then
+ mkdir -p $sb/../unit_test
+ fi
+
+ pushd $sb/../unit_test > /dev/null
+
+ rm $sb/../unit_test/*
+
+ echo "------------------------------------------"
+ echo "Running OCC Testcase Applet -- $applet"
+ echo "------------------------------------------"
+ testAppletFilename=$applet
+ split -b2k $testAppletFilename `basename $testAppletFilename`.
+ NN=0
+ for f in $(find . -xtype f -name "`basename $testAppletFilename`.*" -print | sed 's=.*/==')
+ do
+ SS=`printf "%02x" $NN`
+
+ simicsFspToOccCmd "40" "E0"$SS"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "$sb/../unit_test/$f"
+
+ NN=$((NN+1))
+ done
+
+ simicsFspToOccCmd "40" "E0FF"
+
+ sleep 20
+
+ popd > /dev/null
+}
+
+
+##############################################################################
+##
+## parse args
+##
+##############################################################################
+## verbose is the default.
+VERBOSE=" --verbose"
+NOWIN="--nowin" ## remote execution does not have a display
+COMPILE_GCOV=0
+GCOV=0
+FSPLESS_SIM=0
+UNIT_TEST=0
+WATCH_SIM=0
+ENABLE_VPM=""
+RUN_STANDARD_CMDS=1
+EXTEND_SCRIPT_ARRAY=()
+
+while [ "$1" ]
+do
+ case "$1" in
+ -m|--machine)
+ shift
+ MACHINE=$1
+ ;;
+ -g|--gcov)
+ GCOV=1
+ ;;
+ -u|--unit-test)
+ UNIT_TEST=1
+ ;;
+ -e|--extend-test)
+ # This can be passed multiple times
+ shift
+ EXTEND_SCRIPT_ARRAY=("${EXTEND_SCRIPT_ARRAY[@]}" "$1") # Push
+ ;;
+ -c|--compile-gcov)
+ COMPILE_GCOV=1
+ ;;
+ -f|--fspless)
+ FSPLESS_SIM=1
+ ;;
+ -n|--skip-std-cmds)
+ RUN_STANDARD_CMDS=0
+ ;;
+ -q|--quiet)
+ VERBOSE=""
+ ;;
+ -w|--show-window)
+ NOWIN=""
+ ;;
+ -t|--watch-sim)
+ WATCH_SIM=1
+ ;;
+ --enable-vpm)
+ ENABLE_VPM=""
+ ;;
+ *)
+ echo "Usage:"
+ echo " [-m | --machine] <machine> Specify machine type to run test on"
+ echo " [-g | --gcov] Grab GCOV data"
+ echo " [-u | --unit-test] Run UnitTests"
+ echo " [-e | --extend-test] <path/to/fileOrDir> Run tests from specified file"
+ echo " [-c | --compile-gcov] Grab GCOV data"
+ echo " [-f | --fspless] FSPLESS Sim Compile of OCC; no TMGT cmds"
+ echo " [-n | --skip-std-cmds] Don't run standard FSP commands test"
+ echo " [-q | --quiet] Don't dump so much output"
+ echo " [-w | --show-window] Show a Simics Output xterm window"
+ echo " [-t | --watch-sim] Watch Simics commands and output via tail -f"
+ echo " [--enable-vpm] Tell VPM to run"
+ echo ""
+ echo "Example:"
+ echo " # Run a test doign pretty much everything"
+ echo " $0 -m tuleta -c -g -u -w -t -e \$sb/first_test.sh -e \$sb/test_dir/"
+ echo ""
+ echo ""
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+echo "Variables Passed:"
+echo "---------------------------"
+echo "MACHINE: $MACHINE"
+echo "GCOV: $GCOV"
+echo "FSPLESS_SIM: $FSPLESS_SIM"
+echo "VERBOSE: $VERBOSE"
+echo "COMPILE_GCOV: $COMPILE_GCOV"
+echo "UNIT_TEST: $UNIT_TEST"
+echo "NOWIN: $NOWIN"
+echo "ENABLE_VPM: $ENABLE_VPM"
+echo "EXT_SCRIPT: ${EXTEND_SCRIPT_ARRAY[@]}"
+echo ""
+
+# Quit if we aren't in a sandbox
+if [ -z $sb ]; then
+ exit 1
+fi
+
+waitkb
+
+##############################################################################
+##
+## Compile for code coverage
+##
+##############################################################################
+if [ $COMPILE_GCOV -eq 1 ]
+then
+ pushd $sb/occc/405/
+
+ make clean && make FSPLESS_SIMICS=1 GCOV_CODE_COVERAGE=1 && make combineImage
+
+ if [ $? -ne 0 ]; then
+ echo "Compile failed, exiting"
+ exit 1;
+ fi
+
+ # Compile Pstate Table
+ pushd $sb/occc/405/lib/test > /dev/null
+ make pss.bin
+ popd > /dev/null
+
+ if [ $? -ne 0 ]; then
+ echo "Pstate Compile failed, exiting"
+ exit 1;
+ else
+ if [ ! -d $sb/../obj/ppc/occc/405/occ ]; then
+ mkdir -p $sb/../obj/ppc/occc/405/occ
+ fi
+
+ echo "Copying output files to obj/ppc..."
+ cp -f $sb/occc/405/image.bin $sb/../obj/ppc/occc/405/
+ cp -f $sb/occc/405/occ/occ.out $sb/../obj/ppc/occc/405/occ/
+ cp -f $sb/occc/405/occApplet/testApplet/*.bin $sb/../obj/ppc/occc/405/occApplet/testApplet/
+ fi
+fi
+
+
+##############################################################################
+##
+## set up
+##
+##############################################################################
+DEFAULT_OCC_MACHINE="occ_alone"
+
+MACHINE=${MACHINE:-$DEFAULT_OCC_MACHINE}
+export MACHINE
+
+timestamp=`date +'%H:%M:%S'`
+echo "$timestamp Starting autosample test..."
+
+waitkb
+
+# Run set up in current shell
+echo "run autosimsetup.."
+. autosimsetup
+
+waitkb
+
+###### Start the simics server
+echo "Starting simics server in sandbox $SANDBOX on machine $MACHINE"
+autosim $NOWIN $VERBOSE --startserver --wp --sandbox $SANDBOX --machine $MACHINE
+if [ $? -ne 0 ] ; then
+ echo "ERROR: Unable to start simics server $?"
+ exit 1
+fi
+
+waitkb
+
+
+##############################################################################
+##
+## Start simics and wait for it to reach standby
+##
+##############################################################################
+echo "Starting simics"
+#autosim $VERBOSE --startsim --chkpt standby <<< chkpt not working yet
+autosim $NOWIN $VERBOSE --startsim --norun
+if [ $? -ne 0 ] ; then
+ echo "ERROR: Unable to start simics $?"
+ stopserver ## kill the server again.
+ exit 1
+fi
+
+
+waitkb
+
+if [ $WATCH_SIM -eq 1 ]; then
+ xterm -hold -e tail -f ~/autosim.log &
+fi
+
+##############################################################################
+##
+## Load OCC and run it until steady state
+##
+##############################################################################
+
+loadocc
+runsimics
+
+## Need to wait here for OCC to get up to a steady state
+sleep 30
+
+# Print out Simulation Time
+simicsCmd 'ptime'
+
+waitkb
+
+##############################################################################
+##
+## Run FSP commands needed to get OCC into working Active State
+##
+##############################################################################
+
+#if [ -z $FSPLESS_SIM ]
+#then
+# simicsFspToOccCmd "21" "03000000" # Set Slave
+# sleep 5
+# simicsFspToOccCmd "21" "03010000" # Set Master
+# sleep 5
+# simicsFspToOccCmd "20" "01030000" # Set Active
+#fi
+
+##############################################################################
+##
+## Start running OCC testcases
+##
+##############################################################################
+
+if [ $RUN_STANDARD_CMDS -eq 1 ];
+then
+ # Poll
+ simicsFspToOccCmd "00" "01"
+
+ # QFL
+ simicsFspToOccCmd "01"
+
+ # ClearElog
+ simicsFspToOccCmd "12" "FF"
+
+ # CNFG -- Invalid
+ simicsFspToOccCmd "21" "05"
+ simicsFspToOccCmd "20" "00010000" # Set Standby
+ simicsFspToOccCmd "21" "03000000" # Set Slave
+ simicsFspToOccCmd "21" "03010000" # Set Master
+ simicsFspToOccCmd "20" "00030000" # Set Active
+ simicsFspToOccCmd "21" "04010000" # APSS Config Data
+ simicsFspToOccCmd "21" "020003020C22030C33050C00" # Freq Operation Points
+ if [ -f "$sb/occc/405/lib/test/pss.bin" ]; then
+ simicsFspToOccCmd "21" "01000000" "$sb/occc/405/lib/test/pss.bin" # PstateSuperStructure
+ fi
+
+ # Debug
+ simicsFspToOccCmd "40" "00"
+
+ # SMS
+ simicsFspToOccCmd "20" "01000000" # SMS BadVersion
+ simicsFspToOccCmd "20" "00010000" # NoChange, Standby
+ sleep 10
+ simicsFspToOccCmd "20" "00030100" # Nominal, Active
+ sleep 10
+ simicsFspToOccCmd "20" "00000200" # Benchmark
+ sleep 10
+ simicsFspToOccCmd "20" "00000300" # Turbo
+ sleep 10
+ simicsFspToOccCmd "20" "00000400" # Safe
+ sleep 10
+ simicsFspToOccCmd "20" "00000500" # PowerSave
+ sleep 10
+ simicsFspToOccCmd "20" "00000600" # Dynamic PowerSave
+ sleep 10
+ simicsFspToOccCmd "20" "00000700" # Min Freq
+ sleep 10
+ simicsFspToOccCmd "20" "00000800" # Invalid
+ sleep 10
+ simicsFspToOccCmd "20" "00000900" # Invalid
+ sleep 10
+ simicsFspToOccCmd "20" "00000A00" # Invalid
+ sleep 10
+ simicsFspToOccCmd "20" "00000B00" # FFO
+ sleep 10
+ simicsFspToOccCmd "20" "00000C00" # SuperTurbo
+ sleep 10
+ simicsFspToOccCmd "20" "00000100" # Nominal
+
+ # AME Passthrough
+ simicsFspToOccCmd "41" "3C001C" # AME component level constants
+ simicsFspToOccCmd "41" "3C001D" # Just return 2 bytes of zero data
+ simicsFspToOccCmd "41" "3C0021" # Clear Min/Max of all sensors
+ simicsFspToOccCmd "41" "3C0025" # Get sensors info
+ simicsFspToOccCmd "41" "3C00FEAABBCCDD" # Echo
+ simicsFspToOccCmd "41" "3C00FF0010" # Return sequential bytes string
+ simicsFspToOccCmd "41" "3B0003" # CPU Present bitmask
+
+fi
+
+
+##############################################################################
+##
+## Extend this script
+## * Extensions run in the order they are sent on the command line
+## * Within a directory, they are run in "sort" order, and only files that
+## have the executable bit set will be run
+##
+##############################################################################
+for index in "${EXTEND_SCRIPT_ARRAY[@]}"
+do
+ EXTEND_SCRIPT_FILENAME=$index
+ if [ ! -z $EXTEND_SCRIPT_FILENAME ]; then
+ if [ -d $EXTEND_SCRIPT_FILENAME ]; then
+ for extend in $(find $EXTEND_SCRIPT_FILENAME -xtype f -perm -001 | sort)
+ do
+ echo "---------------------------------------------"
+ echo "Running OCC Script Extension via Dir -- $extend"
+ echo " * Only runs files with executable bit set *"
+ echo "---------------------------------------------"
+ source $extend
+ done
+ elif [ -e $EXTEND_SCRIPT_FILENAME ]; then
+ echo "------------------------------------------"
+ echo "Running OCC Script Extension -- $EXTEND_SCRIPT_FILENAME"
+ echo "------------------------------------------"
+ source $EXTEND_SCRIPT_FILENAME
+ fi
+ fi
+done
+
+
+##############################################################################
+##
+## Automatic Unit Tests based on test Applets
+##
+##############################################################################
+if [ $UNIT_TEST -eq 1 ]
+then
+ for applet in $(find $sb/../obj/ppc/occc/405/occApplet/testApplet/ -xtype f \( -name "errl*.bin" -o -name "trace*.bin" -o -name "apss*.bin" \) )
+ do
+ runTestApplet $applet
+ done
+
+fi
+
+##############################################################################
+##
+## Dump an OCC Trace
+##
+##############################################################################
+occTrace
+
+##############################################################################
+##
+## Code Coverage Processing
+##
+##############################################################################
+if [ $GCOV -eq 1 ]
+then
+ timestamp_gcov=`date +"%s"`
+
+ # Save off full OCC binary to generate code coverage from
+ simicsCmd 'p8Proc0.OccComplexSlot.OccSimpleSlot.sram_image.save occ_gcov.bin'
+ #Wait in case of filesystem sync issues
+ sleep 10
+ # Build the syms file out of the occ.out file
+ pushd $sb/../obj/ppc/occc/405/occ > /dev/null
+ nm -n occ.out > occ.syms
+ popd > /dev/null
+
+ # Move old gcov output direcories if they exist
+ for f in `find . -xtype d -name "gcov.output*" | xargs -n 1 basename`; do mv -v $f _$f; done
+
+ #Delete any old gcda data files
+ pushd $sb/occc/405 > /dev/null
+ find . -xtype f -name "*.gcda" -exec rm {} +
+ popd > /dev/null
+
+ # Build GCDA files out of occ_gcov.bin
+ $sb/occc/405/occ/tools/occGcov.pl
+
+ # Copy GCDA files into directory structure
+ for f in `find . -xtype d -name "gcov.output*" | xargs -n 1 basename`;
+ do
+ echo "GCOV data in $f"
+ pushd $f > /dev/null
+ echo "rsync -r -a -v .`readlink -f $sb`/occc/405/occ/ $sb/occc/405/occ/"
+ rsync -r -a -v .`readlink -f $sb`/occc/405/occ/ $sb/occc/405/occ/
+ popd > /dev/null
+ done
+
+ # Build up LCOV HTML output
+ pushd $sb/occc/405/occ > /dev/null
+ lcov -b . --capture --directory . --output-file coverage.info
+ genhtml coverage.info --output-directory /tmp/gcov_$SANDBOX_$timestamp_gcov
+ popd > /dev/null
+
+ # Open output in firefox
+ firefox /tmp/gcov_$SANDBOX_$timestamp_gcov/index.html &
+fi
+
+waitkb
+
+
+##############################################################################
+##
+## Calculate test results if applicable
+##
+##############################################################################
+
+echo "====> dump totaltests..."
+autosim $NOWIN --simcmd "(ptime -t)" 1> /tmp/totaltests.log 2> /dev/null
+if [ $? -ne 0 ] ; then
+ echo "ERROR: Unable to run $?"
+ stopsim
+ stopserver
+ exit 1
+fi
+totaltests=`cat /tmp/totaltests.log | xargs echo -n`
+
+
+##############################################################################
+##
+## done. Stop the simulation
+##
+##############################################################################
+stopsim
+
+
+## now stop the server.
+stopserver
+
+
+##############################################################################
+##
+## Print out results in footer
+##
+##############################################################################
+timestamp_end=`date +'%H:%M:%S'`
+
+echo "Started: $timestamp"
+echo "Ended: $timestamp_end"
+
+exit 0
+
+
diff --git a/src/occ/tools/occ_autotest_extend.example b/src/occ/tools/occ_autotest_extend.example
new file mode 100644
index 0000000..0da932c
--- /dev/null
+++ b/src/occ/tools/occ_autotest_extend.example
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Example OCC Autotest Extension File
+#
+# Purpose of these scripts are to extend the OCC Autotest without making
+# one gigantic script.
+#
+# RULES
+# -------------------------------------
+# These scripts will only execute if they are specified on the cli, and if they
+# are marked execuable (chmod a+x)
+#
+# If a directory is specified on the cli, the scripts in that directory will be
+# run in the order that occurs during `find . -xtype f -perm -001 | sort`
+#
+# This file is run as a bash script, so you can do anything that bash can do.
+# That includes calling external programs, file operations, sleep, echo, etc.
+#
+# Anything that you can do in the autotest you *could* do here, but to keep it
+# simple, here are some thing that are most useful, and probably what you should
+# stick to.
+#
+# Variables Available:
+# $sb: All Sandbox / Environment variable are available
+# $MACHINE: Machine Type Simics is simulating
+# $ENABLE_VPM: Did caller request VPM to start
+#
+# Functions Available:
+# Send a simics command
+# simicsCmd "command"
+#
+# Send a fsp command (once FSP is up...)
+# fspCmd "command" :
+#
+# Run a test applet
+# runTestApplet "path/to/applet"
+#
+# Send OCC a command from the FSP (fake out FSP if it's not there)
+# simicsFspToOccCmd "command" [data] [datafile]
+# Example: simicsFspToOccCmd "00" "01" # Send a Poll Command
+#
+# Happy Scripting!
+#
+##############################################################################
+
+
diff --git a/src/occ/tools/occ_fsp_fakeout.py b/src/occ/tools/occ_fsp_fakeout.py
new file mode 100755
index 0000000..c681d47
--- /dev/null
+++ b/src/occ/tools/occ_fsp_fakeout.py
@@ -0,0 +1,302 @@
+# @file - occ_fsp_fakeout.py
+# @brief Create Simics Commands for Reading AMEC Sensors
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# thallet 07/01/2012 Created
+
+
+from time import sleep
+from random import randint
+import sys
+import re
+
+import struct
+import array
+import os
+
+G_occ_command = []
+G_occ_response = []
+G_occ_resp_rc = {0x00:'ERRL_RC_SUCCESS',
+ 0x01:'ERRL_RC_CONDITIONAL_SUCCESS',
+ 0x11:'ERRL_RC_INVALID_CMD',
+ 0x12:'ERRL_RC_INVALID_CMD_LEN',
+ 0x13:'ERRL_RC_INVALID_DATA',
+ 0x14:'ERRL_RC_CHECKSUM_FAIL',
+ 0x15:'ERRL_RC_INTERNAL_FAIL',
+ 0x16:'ERRL_RC_INVALID_STATE'}
+
+def occ_calc_cksm( ):
+ global G_occ_command
+ cksm = sum( G_occ_command )
+ cksm_16 = cksm & 0xFFFF
+ cksm_hi = cksm_16/256
+ cksm_lo = cksm_16%256
+ cksm_data = [cksm_hi,cksm_lo]
+ return cksm_data
+
+
+def occ_send_command( occ_idx ):
+ simics_occ_send_commands = []
+
+ # SCOM to set up OCBAR
+ simics_occ_send_commands.append("p8Proc" + occ_idx + ".proc_chip.invoke parallel_store SCOM 0x6b010 \"0xffff6000_00000000\" 64")
+
+ # SCOMs to send data to OCC sram (8bytes per scom, so must pad)
+ full = (len(G_occ_command)/8)
+ partial = (len(G_occ_command)%8)
+
+ # Pad out to 8byte boundry
+ for byte in range((8-partial)):
+ G_occ_command.append(0);
+
+ # Build up simics commands
+ for byte in range(full+1):
+ simics_occ_send_commands.append( "p8Proc" + occ_idx + ".proc_chip.invoke parallel_store SCOM 0x6b015 \"0x" + \
+ '%02x' % (G_occ_command[((byte*8) + 0)]) + \
+ '%02x' % (G_occ_command[((byte*8) + 1)]) + \
+ '%02x' % (G_occ_command[((byte*8) + 2)]) + \
+ '%02x' % (G_occ_command[((byte*8) + 3)]) + \
+ "_" + \
+ '%02x' % (G_occ_command[((byte*8) + 4)]) + \
+ '%02x' % (G_occ_command[((byte*8) + 5)]) + \
+ '%02x' % (G_occ_command[((byte*8) + 6)]) + \
+ '%02x' % (G_occ_command[((byte*8) + 7)]) + \
+ "\" 64")
+
+ # SCOM to send doorbell to OCC
+ simics_occ_send_commands.append("p8Proc" + occ_idx + ".proc_chip.invoke parallel_store SCOM 0x6b035 \"0x11111111_22222222\" 64")
+
+ # Send SCOMs
+ for line in simics_occ_send_commands:
+ cli.quiet_run_command(line)
+
+
+def occ_read_command( occ_idx, i_length=128 ):
+ simics_occ_read_commands = []
+
+ # SCOM to set up OCBAR
+ simics_occ_read_commands.append("p8Proc" + occ_idx + ".proc_chip.invoke parallel_store SCOM 0x6b010 \"0xffff7000_00000000\" 64")
+
+ # Build up simics commands to read the requested amount of data from SRAM
+ for doublewords in range((i_length/8)):
+ simics_occ_read_commands.append("p8Proc" + occ_idx + ".proc_chip.invoke parallel_load SCOM 0x6b015 64")
+
+ # Send SCOMs
+ for line in simics_occ_read_commands:
+ rsp = cli.run_command(line)
+
+
+def occ_read_command_sram_direct( occ_idx ):
+ global G_occ_response
+
+ # Clear out response buffer
+ G_occ_response = []
+
+ simics_occ_read_commands = []
+
+ # Build up simics command to read SRAM
+ simics_occ_read_commands.append("p8Proc" + occ_idx + ".OccComplexSlot.OccSimpleSlot.cpu.x 0xffff7000 128")
+
+ # Convert SRAM read into bytes, then fill in G_occ_response array
+ for line in simics_occ_read_commands:
+ data = []
+ rsp = cli.quiet_run_command(line)
+
+ # Loop through lines returned, and do patter matching to split into bytes
+ for byteline in rsp[1].split('\n'):
+ #Pattern Example: v:0xffff7000 aa00 0000 0b03 0101 ff00 0000 00f4 0506 ................
+ data = re.match(r'(v.0xffff7...) (..)(..) (..)(..) (..)(..) (..)(..) (..)(..) (..)(..) (..)(..) (..)(..) (.{16})',byteline,re.M)
+ # If match, add to G_occ_response
+ if data:
+ G_occ_response.append(int(data.group(2) ,16))
+ G_occ_response.append(int(data.group(3) ,16))
+ G_occ_response.append(int(data.group(4) ,16))
+ G_occ_response.append(int(data.group(5) ,16))
+ G_occ_response.append(int(data.group(6) ,16))
+ G_occ_response.append(int(data.group(7) ,16))
+ G_occ_response.append(int(data.group(8) ,16))
+ G_occ_response.append(int(data.group(9) ,16))
+ G_occ_response.append(int(data.group(10),16))
+ G_occ_response.append(int(data.group(11),16))
+ G_occ_response.append(int(data.group(12),16))
+ G_occ_response.append(int(data.group(13),16))
+ G_occ_response.append(int(data.group(14),16))
+ G_occ_response.append(int(data.group(15),16))
+ G_occ_response.append(int(data.group(16),16))
+ G_occ_response.append(int(data.group(17),16))
+
+
+
+def hexstr2bytearray( data_str ):
+ # Convert a ascii hex string of indeterminite length to byte array
+ byte_array = []
+ if data_str:
+ for x in xrange(0, len(data_str), 2):
+ byte_array.append(int(data_str[x:x+2], 16))
+ return byte_array
+
+
+def binfile2bytearray( file_name ):
+ # Convert a binary of indeterminite length to byte array
+ data_file = open(file_name,"rb")
+ byte_array = array.array('B')
+ fsize = os.path.getsize(file_name)
+ fsize %= 4096
+ byte_array.fromfile(data_file,fsize)
+ byte_list = byte_array.tolist()
+ return byte_list
+
+
+def occ_build_command(command, data, seq='AA'):
+ global G_occ_command
+
+ # Command is string 'XX' ascii hex representation
+ # Seq is string 'XX' ascii hex representation
+ # Data is array of data bytes
+
+ # Empty G_occ_command buffer
+ G_occ_command = []
+
+ #Add seq num into byte 0
+ G_occ_command.insert(0,int(seq,16))
+
+ #Add command into byte 1
+ G_occ_command.insert(1,int(command,16))
+
+ # Add data length
+ data_len_hi = (len(data)/256)
+ data_len_lo = (len(data)%256)
+ G_occ_command.insert(2,data_len_hi)
+ G_occ_command.insert(3,data_len_lo)
+
+ # Add data
+ G_occ_command = G_occ_command + data
+
+ # Add checksum
+ cksm = occ_calc_cksm()
+ G_occ_command = G_occ_command + cksm
+
+
+def occ_parse_command_generic():
+ print "----------------------"
+ print "Sent OCC Command"
+ print "----------------------"
+ print "SEQUENCE: %02x" % G_occ_command[0]
+ print "COMMAND : %02x" % G_occ_command[1]
+ print "DATA_LEN: %02x%02x" % (int(G_occ_command[2]),int(G_occ_command[3]))
+ print "DATA :",
+ data_len = int(int(G_occ_command[2])*256 + int(G_occ_command[3]))
+ for byte in range((data_len -1)):
+ print "%02x" % G_occ_command[byte+4],
+ print ""
+ print "CHECKSUM: %02x%02x" % (G_occ_command[ (data_len + 4) ], G_occ_command[ (data_len + 5 ) ])
+
+
+def occ_parse_response_generic():
+ print "----------------------"
+ print "Received OCC Response"
+ print "----------------------"
+ print "SEQUENCE: %02x" % G_occ_response[0]
+ print "COMMAND : %02x" % G_occ_response[1]
+ print "RC : %02x (%s)" % (G_occ_response[2],G_occ_resp_rc[ G_occ_response[2] ])
+ print "DATA_LEN: %02x%02x" % (int(G_occ_response[3]),int(G_occ_response[4]))
+ print "DATA :",
+ data_len = int(int(G_occ_response[3]) + int(G_occ_response[4]))
+ for byte in range((data_len )):
+ print "%02x" % G_occ_response[byte+5],
+ print ""
+ print "CHECKSUM: %02x%02x" % (G_occ_response[ (data_len + 5) ], G_occ_response[ (data_len + 6 ) ])
+ print ""
+
+
+def occ_trace_grabber(occid=0):
+ cli.quiet_run_command("pipe \"p8Proc" + occid + ".OccComplexSlot.OccSimpleSlot.oci_space.x (p8Proc" + occid + ".OccComplexSlot.OccSimpleSlot.cpu.sym g_trac_inf) 0x6000\" \"sed 's/^p:0x........ //g' | sed 's/ ................$//g' | sed 's/ //g' | xxd -r -p> test.bin\"")
+ cli.run_command("!fsp-trace -s " + os.getenv("sb") + "/../obj/trexStringFile test.bin | strings")
+
+
+#----------------------------------------------------------
+# Simics Helper functions
+#
+
+def occ_fsp_command(command,data="",datafile="",seq="",occid=0):
+ if datafile:
+ # If binary data file is passed in, append that to any other data bytes we have
+ occ_build_command(command=command, data=hexstr2bytearray(data) + binfile2bytearray(datafile))
+ else:
+ # Do this without data bytes
+ occ_build_command(command=command, data=hexstr2bytearray(data))
+
+ # Send Command
+ occ_send_command(str(int(occid or 0)))
+ # Parse out the command we just sent to the screen
+ occ_parse_command_generic()
+
+
+def occ_fsp_response(length,occid=0):
+ # Get response from SCOMs
+ occ_read_command(str(int(occid or 0)))
+ # Get response from SRAM -- same as above, but easier to parse
+ occ_read_command_sram_direct(str(int(occid or 0)))
+ # Parse out the response we just sent to the screen
+ occ_parse_response_generic()
+
+
+def occ_trace(occid=0):
+ occ_trace_grabber(str(int(occid or 0)))
+
+
+
+
+#----------------------------------------------------------
+# Simics Command: occ-fsp-cmd
+#
+new_command("occ-fsp-cmd", occ_fsp_command,
+ args = [arg(str_t, "command"),arg(str_t, "data","?"),arg(str_t, "datafile","?"),arg(str_t, "seq","?"),arg(int_t, "occid","?")],
+ alias = "",
+ type = "occ-fw-module-commands",
+ short = "Send FSP Command to OCC",
+ doc_items = [("NOTE", "")],
+ see_also = ["occ-fsp-rsp"],
+ doc = """
+ <b>occ-fsp-cmd</b> is used to send commands to OCC. Checksum is automatically calculated.\n
+ <i>command</i> is the hex value of the command to be sent. i.e. "21"\n
+ <i>data</i> is the hex data that should be sent. i.e "AA55BB66CC77"\n
+ <i>datafile</i> is filename of a binary data file that should be sent. It will be added after the data arg. i.e. "pss.bin"\n
+ <i>seq</i> is the sequence number, and it currently ignored, and defaults to AA\n
+ <i>occid</i> is the OCC ID Number you want to send the command to (defaults to 0)\n
+ <b>Example:</b> occ-fsp-cmd command="21" data="0B" datafile="0123.bin" \n
+ will build a command like "AA2100050B0001020300E1"
+""")
+
+#----------------------------------------------------------
+# Simics Command: occ-fsp-rsp
+#
+new_command("occ-fsp-rsp", occ_fsp_response,
+ args = [arg(int_t, "size","?"),arg(int_t, "occid","?")],
+ alias = "",
+ type = "occ-fw-module-commands",
+ short = "Get FSP Command Response from OCC",
+ doc_items = [("NOTE", "")],
+ see_also = ["occ-fsp-cmd"],
+ doc = """
+ <b>occ-fsp-rsp</b> is used to get/parse response from OCC.
+ <i>occid</i> is the OCC ID Number you want to send the command to\n
+ <i>size</i>
+ is the only other argument, and currently is ignored""")
+
+
+#----------------------------------------------------------
+# Simics Command: occ-trace
+#
+new_command("occ-trace", occ_trace,
+ args = [arg(int_t, "occid","?")],
+ alias = "",
+ type = "occ-fw-module-commands",
+ short = "Get Trace from OCC",
+ doc_items = [("NOTE", "")],
+ see_also = ["occ-fsp-cmd"],
+ doc = """
+ <b>occ-trace</b> is used to get trace from OCC.
+ <i>occid</i> is the OCC ID Number you want to send the command to\n""")
+
diff --git a/src/occ/tools/occ_gdb.pl b/src/occ/tools/occ_gdb.pl
new file mode 100755
index 0000000..c5b5de1
--- /dev/null
+++ b/src/occ/tools/occ_gdb.pl
@@ -0,0 +1,282 @@
+#!/usr/bin/perl
+##############################################################################
+#
+# @file occ_gdb.pl
+#
+# @author Timothy Hallett
+#
+# @brief Perl script for starting OCC Simics & GDB
+#
+# @verbatim
+#
+# Updates:
+# v0.1.0 01/10/2012 -- thallet -- created.
+# v0.1.1 01/27/2012 -- thallet -- Allow starting @ __ssx_boot or in OCC
+# bootloader.
+#
+# @endverbatim
+#
+#
+##############################################################################
+
+
+
+use strict;
+
+use lib "/afs/rch/usr4/thallet/public/bin/";
+use OccSimicsAutomate;
+
+my $VERSION = "0.1.1";
+
+#----------------------------------------------------------
+# GDB/DDD Related Globals
+#----------------------------------------------------------
+my $G_gdb_path = "/gsa/ausgsa/home/t/h/thallet/web/shared/gdb_ppc_eabi/usr/local/bin/powerpc-\*-eabi-gdb";
+my $G_ddd_path = "ddd --debugger $G_gdb_path";
+my $G_gdbscript_filename = "/tmp/occgdb.".$ENV{"USER"}.".txt";
+my $G_gdb_cmd_file = "";
+my $G_gdb = 1;
+my $G_ddd = 0;
+my $G_xterm = 1;
+my $G_custom_term = 0;
+my $G_nexus = 0;
+my $G_ssx_boot_start = 0;
+my $G_occ_bootloader_start = 0;
+
+
+#----------------------------------------------------------
+# Simics Related Globals
+#----------------------------------------------------------
+my $port = "0";
+my $name = "occgdb";
+my $hostname = "";
+
+
+
+#----------------------------------------------------------
+# Handle Args
+#----------------------------------------------------------
+while ($ARGV = shift)
+{
+ if ($ARGV =~ m%^-d%i)
+ {
+ # Use DDD instead of GDB
+ $G_gdb = 0;
+ $G_ddd = 1;
+ }
+ elsif ($ARGV =~ m%^-f%i)
+ {
+ # Allow user to specify file with gdb commands
+ # that will be run after OCC GDB setup commands
+ $G_gdb_cmd_file = shift;
+ }
+ elsif ($ARGV =~ m%^-n%i)
+ {
+ # Allow user to specify file with gdb commands
+ # that will be run after OCC GDB setup commands
+ $G_nexus = 1;
+ }
+ elsif ($ARGV =~ m%^-t%i)
+ {
+ $G_xterm = 0;
+ }
+ elsif ($ARGV =~ m%^-p%i)
+ {
+ # Allow user to specify path to gdb
+ $G_gdb_path = shift;
+ $G_ddd_path = "ddd --debugger $G_gdb_path"
+ }
+ elsif ($ARGV =~ m%^-s%i)
+ {
+ $G_ssx_boot_start = 1;
+ }
+ elsif ($ARGV =~ m%^-x%i)
+ {
+ $G_occ_bootloader_start = 1;
+ }
+ else
+ {
+ # Use defaults
+ dump_help();
+ exit;
+ }
+}
+
+my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+my @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
+my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
+my $year = 1900 + $yearOffset;
+my $hhmmss = sprintf("%02d:%02d:%02d",$hour,$minute,$second);
+my $G_time = @weekDays[$dayOfWeek]." ".$months[$month]." ".$dayOfMonth.", $year ".$hhmmss;
+
+#----------------------------------------------------------
+# Start Simics, start OCC, start GDB, then hand control to user
+#----------------------------------------------------------
+if(1)
+{
+ #----------------------------------------------------------
+ # Start Simics & run OCC in Simics until main(), __ssx_boot or
+ # first instruction.
+ #----------------------------------------------------------
+ my $simics = new OccSimicsAutomate;
+ if($G_ssx_boot_start)
+ {
+ $simics->startAndRunOccUntilSsxBoot();
+ }
+ elsif($G_occ_bootloader_start)
+ {
+ $simics->start_simics();
+ $simics->getSimicsTime();
+ }
+ else
+ {
+ $simics->startAndRunOccUntilMain();
+ }
+
+ #--------------------------------------------------------
+ # Start GDB Session
+ #--------------------------------------------------------
+ $simics->simics_cmd("new-gdb-remote port=$port name=$name");
+
+
+ #--------------------------------------------------------
+ # Get Hostname Simics is running on
+ #--------------------------------------------------------
+ $simics->simics_cmd("!hostname > occ_simics_hostname");
+ sleep(5);
+ open(HOSTNAME,"<".$ENV{"sb"}."/../simics/occ_simics_hostname");
+ while(<HOSTNAME>)
+ {
+ if ($_ =~ /ibm/){$hostname = $_; chomp($hostname);}
+ }
+ close(HOSTNAME);
+ $simics->simics_cmd("!echo \"\" > occ_simics_hostname");
+
+
+ #--------------------------------------------------------
+ # Get Port GDB is listening on
+ #--------------------------------------------------------
+ $simics->simics_cmd("pipe \"print -d $name->listen\" \"cat > occ_simics_port\"");
+ sleep(5);
+ open(PORT,"<".$ENV{"sb"}."/../simics/occ_simics_port");
+ while(<PORT>)
+ {
+ if ($_ =~ /[0-9]{4,}/){$port = $_; chomp($port);}
+ }
+ close(PORT);
+ $simics->simics_cmd("!echo \"\" > occ_simics_port");
+
+
+ #--------------------------------------------------------
+ # Create a file with GDB Initialization commands
+ #--------------------------------------------------------
+ my @gdb_start_commands =
+ (
+ "echo \"Automating GDB Connection to OCC in Simics: $hostname:$port\n",
+ "set architecture powerpc:common\n",
+ "symbol-file ".$ENV{"sb"}."/occ/occ.out\n",
+ "target remote $hostname:$port"
+ );
+ open(GDB_SCRIPT,">$G_gdbscript_filename");
+ foreach(@gdb_start_commands)
+ {
+ print GDB_SCRIPT $_;
+ }
+ close(GDB_SCRIPT);
+
+ #--------------------------------------------------------
+ # If user passed in a GDB command file, append it to GDBscript
+ # we just created
+ #--------------------------------------------------------
+ if($G_gdb_cmd_file)
+ {
+ system("cat $G_gdb_cmd_file >> $G_gdbscript_filename");
+ }
+
+ #--------------------------------------------------------
+ # Make simics command prompt interactive
+ # or tell user that it is not interactive
+ #--------------------------------------------------------
+ if($G_xterm == 0)
+ {
+ system("echo \"Simics Command Line is Unavailable while running GDB\"");
+ }
+
+ #--------------------------------------------------------
+ # Now start GDB or DDD, passing in the command file
+ #--------------------------------------------------------
+ if($G_ddd)
+ {
+ system("$G_ddd_path --command=$G_gdbscript_filename");
+ }
+ elsif($G_nexus)
+ {
+ # Don't start GDB
+ }
+ elsif($G_xterm)
+ {
+ system("xterm -bg darkolivegreen -fg wheat -sb -sl 10000 -geometry 120x40 -hold -title \"GDB -> OCC [".$ENV{"SANDBOX"}."] @ $hostname:$port, started $G_time\" -e $G_gdb_path --command=$G_gdbscript_filename &");
+ }
+ elsif($G_custom_term)
+ {
+ system("$G_custom_term \"$G_gdb_path --command=$G_gdbscript_filename\"");
+ }
+ else
+ {
+ system("$G_gdb_path --command=$G_gdbscript_filename");
+ }
+
+ #--------------------------------------------------------
+ # Make simics command prompt interactive
+ #--------------------------------------------------------
+ $simics->interact();
+
+ #--------------------------------------------------------
+ # When we are done, close simics & clean up files
+ #--------------------------------------------------------
+ $simics->close();
+ system("if [ -e $G_gdbscript_filename ]; then rm $G_gdbscript_filename; fi");
+}
+
+
+sub dump_help
+{
+ my $name = "occgdb.pl";
+
+ print "\n";
+ print "Usage: $name [options]\n";
+ print "\n";
+ print "Version: $VERSION\n\n";
+
+ print "Usage Notes:\n";
+ print " This script will start simics and make a gdb or ddd connection to it automatically.\n";
+ print " - Must be run from sandbox\n";
+ print " - DDD must be in PATH\n";
+
+ print "\n";
+
+ print "Options:\n";
+ print "\t[-d] Use DDD instead of GDB\n";
+ print "\t[-n] Use Nexus Debugger instead of GDB (must manually start & attach Nexus)\n";
+ print "\t[-t] Don't start a seperate xterm to do debugging (no simics interaction allowed) \n";
+ print "\t[-f <gdb cmd file>] Use <gdb command file> to run gdb commands after OCC has started\n";
+ print "\t[-p <path/to/gdb>] Use <path/to/gdb> as the gdb executable\n";
+ print "\t[-s] Don't start @ OCC main(), start @ __ssx_boot() instead.\n";
+ print "\t[-x] Don't start @ OCC main(), start @ first instruction (bootloader)) \n";
+
+ print "\n";
+}
+
+
+##############################################################################
+# Notes:
+# ----------------------------------------------------------------------------
+#
+# GDB Command File Example Commands:
+# graph display g_amec_sys.fw.ameintdur
+# break rtl_do_tick
+# c
+# print g_amec_sys.fw.ameintdur
+#
+
+
diff --git a/src/occ/tools/occ_gdb.py b/src/occ/tools/occ_gdb.py
new file mode 100755
index 0000000..0344187
--- /dev/null
+++ b/src/occ/tools/occ_gdb.py
@@ -0,0 +1,116 @@
+# @file - occ_gdb.py
+# @brief Start GDB on OCC
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# thallet 08/14/2012 Created
+
+
+from time import sleep
+from random import randint
+import sys
+import re
+
+G_gdb_path = "/gsa/ausgsa/home/t/h/thallet/web/shared/gdb_ppc_eabi/usr/local/bin/powerpc-\*-eabi-gdb";
+G_ddd_path = "ddd --debugger " + G_gdb_path;
+G_gdb_port = 0
+G_gdb_hostname = ""
+
+##############################################################################
+###########################################################
+# Functions
+###########################################################
+##############################################################################
+
+def start_gdb_server( occ_idx ):
+ global G_gdb_port
+ global G_gdb_hostname
+
+ # TODO: Add a check here for not restarting gdb if already started
+ tick = cli.quiet_run_command("object-exists occgdb" + str(occ_idx))
+ exists = tick[0]
+ if exists:
+ print "Object occgdb" + str(occ_idx) + "already exists"
+ else:
+ tick = cli.run_command("new-gdb-remote cpu = " + G_occ_list[int(occ_idx)] + ".cpu " + "port=0 name=occgdb" + str(occ_idx))
+
+ tick = cli.run_command("occgdb" + str(occ_idx) + "->listen")
+ port = tick
+ tick = cli.quiet_run_command("!hostname")
+ hostname = tick[0]
+
+ print "Port: %d" % port
+ print "Hostname: %s" % hostname
+
+ gdb_start_commands = [
+ "echo \"Automating GDB Connection to OCC in Simics: " + hostname +": " + str(port) + "\n",
+ "set architecture powerpc:common\n",
+ "symbol-file " + os.getenv("sb") + "/../obj/ppc/occc/405/occ/occ.out\n",
+ "target remote " + hostname + ":" + str(port) + "\n",
+ "handle SIGTRAP nostop noprint\n",
+ ]
+ fout = open("occgdb_" + str(occ_idx) + "_gdb_cmds.txt","w")
+ for cmd in gdb_start_commands:
+ fout.write(cmd)
+ fout.close()
+
+ G_gdb_port = port
+ G_gdb_hostname = hostname
+
+ return
+
+
+def ddd_connect( occ_idx ):
+ os.system(G_ddd_path + " --command=occgdb_" + str(occ_idx) + "_gdb_cmds.txt &")
+ return
+
+def gdb_connect( occ_idx ):
+ if occ_idx == 0:
+ os.system("xterm -bg darkolivegreen -fg wheat -sb -sl 10000 -geometry 120x40 -hold -title \"GDB -> OCC["+ str(occ_idx) +"] [" + os.getenv("SANDBOX") + "] @ " + G_gdb_hostname + ":" + str(G_gdb_port) + "\" -e " + G_gdb_path + " --command=occgdb_" + str(occ_idx) + "_gdb_cmds.txt &")
+ else:
+ os.system("xterm -bg honeydew4 -fg wheat -sb -sl 10000 -geometry 120x40 -hold -title \"GDB -> OCC["+ str(occ_idx) +"] [" + os.getenv("SANDBOX") + "] @ " + G_gdb_hostname + ":" + str(G_gdb_port) + "\" -e " + G_gdb_path + " --command=occgdb_" + str(occ_idx) + "_gdb_cmds.txt &")
+
+ return
+
+def occ_gdb_start ( occ_idx ):
+ start_gdb_server(int(occ_idx))
+ gdb_connect(int(occ_idx))
+ return
+
+def occ_ddd_start ( occ_idx ):
+ start_gdb_server(int(occ_idx))
+ ddd_connect(int(occ_idx))
+ return
+
+
+##############################################################################
+###########################################################
+# Register some New Simics Commands
+###########################################################
+##############################################################################
+
+#----------------------------------------------------------
+# Simics Command: occ-gdb-start
+#
+new_command("occ-gdb-start", occ_gdb_start,
+ args = [arg(int_t, "occidx")],
+ alias = "",
+ type = "occ-fw-module-commands",
+ short = "Connect GDB to OCC",
+ doc_items = [("NOTE", "")],
+ see_also = ["occ-ddd-start"],
+ doc = """
+""")
+
+#----------------------------------------------------------
+# Simics Command: occ-ddd-start
+#
+new_command("occ-ddd-start", occ_ddd_start,
+ args = [arg(int_t, "occidx","?")],
+ alias = "",
+ type = "occ-fw-module-commands",
+ short = "Connect DDD to OCC",
+ doc_items = [("NOTE", "")],
+ see_also = ["occ-ddd-start"],
+ doc = """
+""")
diff --git a/src/occ/tools/occ_hwp_id.pl b/src/occ/tools/occ_hwp_id.pl
new file mode 100644
index 0000000..ff7242c
--- /dev/null
+++ b/src/occ/tools/occ_hwp_id.pl
@@ -0,0 +1,458 @@
+#!/usr/bin/perl
+
+# @file occ_hwp_id.pl
+#
+# @brief occ_hwp_id script to generate the occ/tools/occ_hwp_id.html page that
+# will be displayed in the build page and lists the hardware procedures and
+# the version checked in into that build level.
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @fk007 918955 fmkassem 03/11/2013 create.
+#
+
+use strict;
+use File::Find ();
+use File::Path;
+use File::Basename;
+use Cwd;
+
+# Variables
+my $DEBUG = 0;
+my @outputFnVn;
+my @foundFn;
+my $baseDir = ".";
+my $basePath;
+my @searchFiles;
+my @searchDirs;
+my $baseName;
+
+my $SHOW_INFO = 0;
+# a bit for each:
+use constant SHOW_IMAGEID => 0x01;
+use constant SHOW_MISSING => 0x02;
+use constant SHOW_VERSION => 0x04;
+use constant SHOW_SHORT => 0x08;
+use constant SHOW_FULLPATH => 0x10;
+use constant SHOW_HTML => 0x20;
+use constant SHOW_ONLYMISS => 0x40;
+
+# directories that we'll check for files:
+my @dirList = (
+ "src/occc/",
+ ) ;
+
+# set defaults
+my $imageId = "";
+$SHOW_INFO = SHOW_VERSION;
+
+while( $ARGV = shift )
+{
+ if( $ARGV =~ m/-h/ )
+ {
+ usage();
+ }
+ elsif( $ARGV =~ m/-D/ )
+ {
+ if ( $baseDir = shift )
+ {
+ print("Using directory(s): $baseDir\n");
+ }
+ else
+ {
+ usage();
+ }
+ }
+ elsif( $ARGV =~ m/-d/ )
+ {
+ $DEBUG = 1;
+ }
+ elsif( $ARGV =~ m/-f/ )
+ {
+ $SHOW_INFO |= SHOW_FULLPATH;
+ }
+ elsif( $ARGV =~ m/-F/ )
+ {
+ # no directory, list of files
+ $baseDir = "";
+ @searchFiles = @ARGV;
+ last; # done with options
+ }
+ elsif( $ARGV =~ m/-I/ )
+ {
+ $SHOW_INFO |= SHOW_IMAGEID;
+ if ( $imageId = shift )
+ {
+ debugMsg("using supplied Hostboot version: $imageId\n");
+ }
+ else
+ {
+ usage();
+ }
+ }
+ elsif( $ARGV =~ m/-i/ )
+ {
+ $SHOW_INFO |= SHOW_IMAGEID;
+ }
+ elsif( $ARGV =~ m/-l/ )
+ {
+ $SHOW_INFO |= SHOW_HTML;
+ $SHOW_INFO &= ~SHOW_VERSION;
+ $SHOW_INFO &= ~SHOW_SHORT;
+ }
+ elsif( $ARGV =~ m/-M/ )
+ {
+ $SHOW_INFO |= SHOW_ONLYMISS;
+ }
+ elsif( $ARGV =~ m/-m/ )
+ {
+ $SHOW_INFO |= SHOW_MISSING;
+ }
+ elsif( $ARGV =~ m/-s/ )
+ {
+ $SHOW_INFO |= SHOW_SHORT;
+ $SHOW_INFO &= ~SHOW_VERSION;
+ $SHOW_INFO &= ~SHOW_HTML;
+ }
+ elsif( $ARGV =~ m/-v/ )
+ {
+ $SHOW_INFO |= SHOW_VERSION;
+ $SHOW_INFO &= ~SHOW_SHORT;
+ $SHOW_INFO &= ~SHOW_HTML;
+ }
+ else
+ {
+ usage();
+ }
+}
+
+if ($SHOW_INFO & SHOW_ONLYMISS)
+{
+ $SHOW_INFO &= ~SHOW_VERSION;
+ $SHOW_INFO &= ~SHOW_SHORT;
+ $SHOW_INFO &= ~SHOW_HTML;
+}
+
+# generate starting html if needed
+if ($SHOW_INFO & SHOW_HTML)
+{
+ print "<html>\n";
+ print " <head><title>OCC HWP names and version IDs</title></head>\n";
+ print <<STYLESHEET;
+ <style type="text/css">
+ table.occ_hwp_id {
+ border-width: 1px;
+ border-spacing: 2px;
+ border-style: outset;
+ border-color: gray;
+ border-collapse: separate;
+ background-color: white;
+ }
+ table.occ_hwp_id th {
+ border-width: 1px;
+ padding: 1px;
+ border-style: inset;
+ border-color: gray;
+ background-color: white;
+ }
+ table.occ_hwp_id td {
+ border-width: 1px;
+ padding: 1px;
+ border-style: inset;
+ border-color: gray;
+ background-color: white;
+ }
+ </style>
+STYLESHEET
+ print " <body>\n";
+}
+
+# determine what the hbi_ImageId would be, if we were asked to display that
+if ($SHOW_INFO & SHOW_IMAGEID)
+{
+ $baseName = basename($baseDir);
+ if ($SHOW_INFO & SHOW_HTML)
+ {
+ print "<h1>OCC version: $baseName</h1>\n";
+ }
+ else
+ {
+ print("OCC version: $baseName\n");
+ }
+}
+
+# if baseDir - recurse into directories
+if ($baseDir)
+{
+ # there may be multiple base directories
+ @searchDirs = split(/:/, $baseDir);
+
+ foreach( @searchDirs )
+ {
+ # make sure we're in the correct place
+ chdir "$_";
+ $basePath = $_;
+
+ # do the work - for each directory, check the files...
+ foreach( @dirList )
+ {
+ @outputFnVn = ();
+ checkDirs( $_ );
+
+ if (scalar(@outputFnVn) > 0)
+ {
+ outputFileInfo($_, @outputFnVn);
+ }
+ }
+ }
+}
+else # list of files
+{
+ @outputFnVn = ();
+
+ # do the work - for each file, check it
+ foreach( @searchFiles )
+ {
+ findIdVersion( $_ );
+ }
+
+ if (scalar(@outputFnVn) > 0)
+ {
+ my $pwd = getcwd();
+ outputFileInfo($pwd, @outputFnVn);
+ }
+}
+
+# generate closing html if needed
+if ($SHOW_INFO & SHOW_HTML)
+{
+ print " </body>\n";
+ print "</html>\n";
+}
+
+#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+# End of Main program
+#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+################################################################################
+#
+# Print debug messages if $DEBUG is enabled.
+#
+################################################################################
+
+sub debugMsg
+{
+ my ($msg) = @_;
+ if( $DEBUG )
+ {
+ print "DEBUG: $msg\n";
+ }
+}
+
+################################################################################
+#
+# outputFileInfo - Print output, as options dictate
+#
+################################################################################
+
+sub outputFileInfo
+{
+ my $dir = shift;
+
+ if ($SHOW_INFO & SHOW_HTML)
+ {
+ print("<h2>OCC HWP files in $basePath/$dir</h2>\n");
+ }
+ else
+ {
+ print("[OCC HWP files in $dir]\n");
+ }
+
+ if ($SHOW_INFO & SHOW_SHORT)
+ {
+ print("[Procedure,Revision]\n" );
+ }
+
+ if ($SHOW_INFO & SHOW_HTML)
+ {
+ print "<table class='occ_hwp_id'>\n";
+ print " <tr>\n";
+ print " <th>Filename</th>\n";
+ print " <th>Version</th>\n";
+ print " </tr>\n";
+ }
+
+ foreach( sort(@_) )
+ {
+ print( "$_\n" );
+ }
+
+ if ($SHOW_INFO & SHOW_HTML)
+ {
+ print "</table>\n";
+ }
+}
+
+################################################################################
+#
+# findIdVersion - prints out filename and version from the $Id: string.
+#
+################################################################################
+
+sub findIdVersion
+{
+ my ($l_file) = @_;
+ debugMsg( "finding Id & Version from file: $l_file" );
+
+ local *FH;
+ open(FH, "$l_file") or die("Cannot open: $l_file: $!");
+ my $data;
+ read(FH, $data, -s FH) or die("Error reading $l_file: $!");
+ close FH;
+
+ # look for special string to skip file
+ if ($data =~ /HWP_IGNORE_VERSION_CHECK/ )
+ {
+ debugMsg( "findIdVersion: found HWP_IGNORE_VERSION_CHECK in: $l_file" );
+ next;
+ }
+
+ # look for
+ # $Id: - means this IS an hwp - print version and continue
+ # else - missing!
+ if ($data =~ /\$Id: (.*),v ([0-9.]*) .* \$/mgo )
+ {
+ my $fn = $1; # filename
+ my $vn = $2; # version
+ my $display_name;
+ my $redundant = 0;
+ if ($SHOW_INFO & SHOW_FULLPATH)
+ {
+ $display_name = $l_file;
+ }
+ else
+ {
+ $display_name = $fn;
+ }
+ $redundant = grep { m/^$fn$/ } @foundFn;
+ if ( !$redundant )
+ {
+ push( @foundFn, $display_name );
+ debugMsg( "File: $display_name Version: $vn" );
+ if ($SHOW_INFO & SHOW_VERSION)
+ {
+ push( @outputFnVn, "File: $display_name Version: $vn" );
+ }
+ elsif ($SHOW_INFO & SHOW_SHORT)
+ {
+ push( @outputFnVn, "$display_name,$vn" );
+ }
+ elsif ($SHOW_INFO & SHOW_HTML)
+ {
+ push( @outputFnVn, "<tr><td>$display_name</td><td>$vn</td></tr>" );
+ }
+ }
+ }
+ else
+ {
+ debugMsg( "findIdVersion: MISSING \$Id tag: $l_file" );
+ if ($SHOW_INFO & SHOW_MISSING)
+ {
+ if ($SHOW_INFO & SHOW_VERSION)
+ {
+ print( "File: $l_file Version: \$Id is MISSING\n" );
+ }
+ elsif ($SHOW_INFO & SHOW_SHORT)
+ {
+ print( "$l_file,MISSING\n" );
+ }
+ elsif ($SHOW_INFO & SHOW_HTML)
+ {
+ print( "<tr><td>$l_file</td><td>\$Id is MISSING</td></tr>\n" );
+ }
+ }
+ elsif ($SHOW_INFO & SHOW_ONLYMISS)
+ {
+ print( "File: $l_file Version: \$Id is MISSING\n" );
+ }
+ }
+}
+
+################################################################################
+#
+# checkDirs - find *.[hHcC] and *.initfile files that are hwp files
+# and prints out their filename and version from the $Id: string.
+# This recursively searches the input directory passed in for all files.
+#
+################################################################################
+
+sub checkDirs
+{
+ my ($l_input_dir) = @_;
+
+ debugMsg( "Getting Files for dir: $l_input_dir" );
+
+ # Open the directory and read all entry names.
+
+ local *DH;
+ opendir(DH, $l_input_dir) ;#or die("Cannot open $l_input_dir: $!");
+ # skip the dots
+ my @dir_entry;
+ @dir_entry = grep { !/^\./ } readdir(DH);
+ closedir(DH);
+ while (@dir_entry)
+ {
+ my $l_entry = shift(@dir_entry);
+ my $full_path = "$l_input_dir/$l_entry";
+
+ debugMsg( "checkDirs: Full Path: $full_path" );
+
+ # if this is valid file:
+ if (($l_entry =~ /\.[H|h|C|c|S]$/) ||
+ ($l_entry =~ /\.pS$/) ||
+ ($l_entry =~ /\.mk$/) ||
+ ($l_entry =~ /\.ode$/) ||
+ ($l_entry =~ /Makefile$/))
+ {
+ findIdVersion($full_path);
+ }
+ # else if this is a directory
+ elsif (-d $full_path)
+ {
+ # recursive here
+ checkDirs($full_path);
+ }
+ # else we ignore the file.
+ }
+}
+
+################################################################################
+#
+# Print the Usage message
+#
+################################################################################
+
+sub usage
+{
+ print "Usage: $0 <option> [-F <files>]\n";
+ print "\n";
+ print "Default - show name and version for hwp files with \$Id string.\n";
+ print "-D dirs Use dir as top of build, may be ':' separated list.\n";
+ print "-d Enable Debug messages.\n";
+ print "-f Show full pathname of all files.\n";
+ print "-F files Search listed full-path files. Must be last parameter.\n";
+ print "-h Display usage message.\n";
+ print "-I lvl Show hostboot ImageId value as supplied lvl\n";
+ print "-i Show hostboot ImageId value.\n";
+ print "-m Include files that are missing Id strings.\n";
+ print "\n";
+ print " output is in one of 4 formats:\n";
+ print "-l Output in html table.\n";
+ print "-s Show short \"filename,version\" format.\n";
+ print "-v Show longer \"File: f Version: v\" format. (default)\n";
+ print "-M Only show files that are missing Id strings.\n";
+ print "\n";
+ exit 1;
+}
diff --git a/src/occ/tools/occ_post_model_hook.simics b/src/occ/tools/occ_post_model_hook.simics
new file mode 100755
index 0000000..a383af9
--- /dev/null
+++ b/src/occ/tools/occ_post_model_hook.simics
@@ -0,0 +1,344 @@
+################################################################################
+# post_model_hook.simics
+# This file is used to run a set of commands on the simics console after
+# modules have loaded.
+
+$occc = [0]
+$proc_chip = [0]
+
+if not (lookup-file ../src/occc/405/occ/tools/occ_simics_gen_lists.py ){
+ #run-python-file /gsa/ausgsa/projects/o/occfw/public/simics/scripts/cc_simics_gen_lists.py
+
+ #----------------------------------------------------------
+ # Figure out what OCCs are out there & create a list
+ #----------------------------------------------------------
+ $occc[0]=0; $b=0; foreach $c in (get-object-list -all occ_simple) {$occc[$b] = $c; $b = $b + 1}
+ #----------------------------------------------------------
+ # Figure out what CEC-chips are out there & create a list
+ #----------------------------------------------------------
+ $proc_chip[0]=0; $f=0; foreach $g in (get-object-list -all cec-chip) {$proc_chip[$f] = $g; $f = $f + 1}
+} else {
+ run-python-file ../src/occc/405/occ/tools/occ_simics_gen_lists.py
+}
+
+#----------------------------------------------------------
+# Figure out what OCCs are out there & create a list
+#----------------------------------------------------------
+#$occc[0]=0; $b=0; foreach $c in (get-object-list -all occ_simple) {$occc[$b] = $c; $b = $b + 1}
+
+#----------------------------------------------------------
+# Figure out what PSSs are out there & create a list
+#----------------------------------------------------------
+$apss = [0]
+$apss[0]=0; $d=0; foreach $e in (get-object-list -all apss_device) {$apss[$d] = $e; $d = $d + 1}
+#$dpss[0]=0; $f=0; foreach $g in (get-object-list -all dpss_device) {$dpss[$f] = $g; $f = $f + 1}
+
+#----------------------------------------------------------
+# Figure out what CEC-chips are out there & create a list
+#----------------------------------------------------------
+#$proc_chip[0]=0; $f=0; foreach $g in (get-object-list -all cec-chip) {$proc_chip[$f] = $g; $f = $f + 1}
+
+#----------------------------------------------------------
+# ChipId/NodeId Lists for OCC Alone Model
+#----------------------------------------------------------
+$occChipId_murano = []
+$occChipId_murano[0] = 0x0000000000000000; # NodeID=0, ChipID=0
+$occChipId_murano[1] = 0x0000000000040000; # NodeID=0, ChipID=1
+$occChipId_murano[2] = 0x0000000000200000; # NodeID=1, ChipID=0
+$occChipId_murano[3] = 0x0000000000240000; # NodeID=1, ChipID=1
+$occChipId_murano[4] = 0x0000000000400000; # NodeID=2, ChipID=0
+$occChipId_murano[5] = 0x0000000000440000; # NodeID=2, ChipID=1
+$occChipId_murano[6] = 0x0000000000600000; # NodeID=3, ChipID=0
+$occChipId_murano[7] = 0x0000000000640000; # NodeID=3, ChipID=1
+
+$occChipId_venice = []
+$occChipId_venice[0] = 0x0000000000000000; # NodeID=0, ChipID=0
+$occChipId_venice[1] = 0x0000000000040000; # NodeID=0, ChipID=1
+$occChipId_venice[2] = 0x0000000000080000; # NodeID=0, ChipID=2
+$occChipId_venice[3] = 0x00000000000C0000; # NodeID=0, ChipID=3
+$occChipId_venice[4] = 0x0000000000100000; # NodeID=0, ChipID=4
+$occChipId_venice[5] = 0x0000000000140000; # NodeID=0, ChipID=5
+$occChipId_venice[6] = 0x0000000000180000; # NodeID=0, ChipID=6
+$occChipId_venice[7] = 0x00000000001C0000; # NodeID=0, ChipID=7
+
+
+#----------------------------------------------------------
+# Set up path to OCC image
+#----------------------------------------------------------
+$occ_image = "../obj/ppc/occc/405/image.bin"
+if not (lookup-file $occ_image ){
+ echo "Using GNUmake image"
+ $occ_image = "../src/occc/405/image.bin"
+}else{
+ echo "Using ODEmake image"
+}
+
+
+#----------------------------------------------------------
+# Create symbol table for occ application using sandbox or backing build
+#----------------------------------------------------------
+@occoutfile = "/../obj/ppc/occc/405/occ/occ.out"
+@occsb = os.getenv("sb")
+@cli.run_command("$occsb = " + occsb + occoutfile)
+@occbb = os.getenv("bb")
+@cli.run_command("$occbb = " + occbb + "/src" + occoutfile)
+
+# Create symbol table - first look in $sb, then $bb, then gnumake location
+if not (lookup-file $occsb ){
+ echo "Cannot find OCC Symbols file in Sandbox"
+
+ if not (lookup-file $occbb) {
+ echo "Cannot find OCC Symbols file in Backing Build"
+
+ @cli.run_command("$occsb = " + occsb + "/occc/405/occ/occ.out")
+ if not (lookup-file $occsb) {
+ echo "Cannot find OCC Symbols file in src/ tree"
+ }else{
+ echo "Loaded symbol file from src/occ/occ.out"
+ new-symtable occst $occsb
+ }
+ }else{
+ echo "Loaded symbol table from $bb/obj/ppc/occc/405/occ/occ.out"
+ new-symtable occst $occbb
+ }
+}else{
+ echo "Loaded symbol table from $sb/obj/ppc/occc/405/occ/occ.out"
+ new-symtable occst $occsb
+}
+
+
+#----------------------------------------------------------
+# Create symbol table for occ Bootloader using sandbox or backing build
+#----------------------------------------------------------
+@btoutfile = "/../obj/ppc/occc/405/occBootLoader/bootloader.out"
+@cli.run_command("$occsb = " + occsb + btoutfile)
+@cli.run_command("$occbb = " + occbb + "/src" + btoutfile)
+
+# Create symbol table - first look in $sb, then $bb, then gnumake location
+if not (lookup-file $occsb ){
+ echo "Cannot find Bootloader Symbols file in Sandbox"
+ if not (lookup-file $occbb) {
+ echo "Cannot find Bootloader Symbols file in Backing Build"
+
+ @cli.run_command("$occsb = " + occsb + "/occc/405/occBootLoader/bootloader.out")
+ if not (lookup-file $occsb) {
+ echo "Cannot find Bootloader Symbols file src/ tree"
+ }else{
+ echo "Loaded symbol file from src/occBootLoader/bootloader.out"
+ occst.load-symbols $occsb
+ }
+ }else{
+ echo "Loaded symbol table from $bb/obj/ppc/occc/405/occBootLoader/bootloader.out"
+ occst.load-symbols $occbb
+ }
+}else{
+ echo "Loaded symbol table from $sb/obj/ppc/occc/405/occBootLoader/bootloader.out"
+ occst.load-symbols $occsb
+}
+
+
+#----------------------------------------------------------
+# Loop through all present OCCs, setting them all to the
+# same initial settings
+#----------------------------------------------------------
+while $b {
+ $b -= 1
+
+ echo " "
+ echo "-------------------------------------------------------- "
+ echo "Loading & configuring: "
+ echo $occc[$b]
+ echo "-------------------------------------------------------- "
+
+ # Set up symbol table for each OCC
+ @occ_path = cli.quiet_run_command("echo $occc[$b]")
+ @cli.run_command("@conf." + occ_path[1].rstrip('\n') + ".cpu.current_context.symtable = conf.occst")
+
+ # Load OCC image
+ # $occc[$b].pob_space.load-file ../src/image.bin
+
+ # Load OCC image
+ $alone = p8Proc0.OccComplexSlot->isStandalone
+ if $alone == 0 {
+ echo "Loading OCC image into phys_mem"
+ proc_venicechip_cmp0.phys_mem.load-file $occ_image 0x400000
+ $occc[$b].pba->pba_slvctl0 = 0x87001E0000000000 # OCC HOMER Image
+ $occc[$b].pba->pba_barmsk0 = 0x0000000000300000 # OCC HOMER Image
+ $occc[$b].pba->pba_bar0 = 0x0000000000400000 # OCC HOMER Image
+ } else {
+ echo "Alone: Loading into fake phys_mem"
+ backplane0.phys_mem.load-file $occ_image 0x400000
+ $occc[$b].pba->pba_slvctl0 = 0x87001E0000000000 # OCC HOMER Image
+ $occc[$b].pba->pba_barmsk0 = 0x0000000000300000 # OCC HOMER Image
+ $occc[$b].pba->pba_bar0 = 0x0000000000400000 # OCC HOMER Image
+ }
+
+ # Set PBA BAR register - simics 04/04/2012 and newer
+ $occc[$b].pba->pba_mode = 0x00E03A9000000000
+ $occc[$b].pba->pba_slvctl3 = 0xD7005E4000000000 # OCC Common
+ $occc[$b].pba->pba_slvctl2 = 0xC7005E4000000000 # PORE-SLW
+ $occc[$b].pba->pba_slvctl1 = 0xE6005E4000000000 # Centaur
+ $occc[$b].pba->pba_bar1 = 0x0003e00000000000 # Centaur
+ $occc[$b].pba->pba_barmsk1 = 0x1fffff00000 # Centaur
+ $occc[$b].pba->pba_bar3 = 0x0000000008000000 # OCC Common Image
+ $occc[$b].pba->pba_barmsk3 = 0x00000700000 # OCC Common Image
+
+ # Set OCB registers until we are always talking via TMGT/HWSV
+ $occc[$b].ocb->ocb_ocbar0 = 0xffff600000000000
+ $occc[$b].ocb->ocb_ocbcsr0 = 0x0800000000000000
+ $occc[$b].ocb->ocb_ocbcsr1 = 0x0c00000000000000
+ $occc[$b].ocb->ocb_ocbar1 = 0xffff600000000000
+
+ # Set CPI to be more accurate. Simics defaults to a CPI = 1, but it
+ # is more likely with our workload that we will have a CPI ~= 3. Simics
+ # only allows certain step rates, so we will end up with a CPI of 2.9767
+ # Step Rate = IPC = 1/CPI
+ $occc[$b].cpu.set-step-rate "43/128"
+
+ # Set branch to address 64(0x40) and place this branch at 0xFFFFFFFC.
+ $occc[$b].oci_space.set 0xfffffffc 0x48000042
+
+ # ---------------------------------------------------------
+ # Temporary Workarounds
+ # ---------------------------------------------------------
+ echo " "
+ echo "-------------------------------------------------------- "
+ echo "Applying Workarounds to Enable OCC"
+ echo "-------------------------------------------------------- "
+
+ # In the beginning Scott Prather created the simics model and the occ.
+ # Now the occ was formless and empty, [and didn't have all the inits
+ # that would happen on a real system.]
+ # And Scott said, "Let there be clocks": and there was clocks.
+ # Scott saw that clocks were good, and Scott divided clocks from [simics
+ # init into this seperate initialization.]
+ $proc_chip[$b].regwrite LOGIC 0xFF000001 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50000 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50001 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50002 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50003 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50004 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50005 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50006 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50007 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50008 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50009 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50010 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50011 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50012 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50013 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50014 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50015 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50016 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC50019 FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC5001A FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC5001B FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC5001C FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC5001D FFFFFFFF_FFFFFFFF 64
+ $proc_chip[$b].regwrite LOGIC 0xFFC5001E FFFFFFFF_FFFFFFFF 64
+
+ # FW588165 : PHYP scom to OCC targeting invalid address 0x40020
+ $occc[$b].pcb_space.add-map $occc[$b].ocb:pib 0x00040020 0x1
+
+ # Simics Crash when hitting PBAX operations
+ #@cli.run_command("@conf." + occ_path[1].rstrip('\n') + ".pba.pbax_connector=conf.p8Proc0.OccComplexSlot.pbax_router")
+
+ if $alone == 0 {
+ echo ""
+ } else {
+ echo "OCC Alone Workaround: Set ChipId & NodeId (Murano)"
+ $occc[$b].pib_master->address = 0x01000000
+ $occc[$b].pib_master->data = $occChipId_murano[$b]
+ }
+}
+
+# ---------------------------------------------------------
+# APSS settings
+# ---------------------------------------------------------
+$apss[0]->adc_channel_val = [ 0x2da, # [0]: Memory 1 -- 90.000 W
+ 0x302, # [1]: Memory 2 -- 95.000 W
+ 0x3cd, # [2]: Proc1 Vdd -- 120.000 W
+ 0x3bd, # [3]: Proc2 Vdd -- 118.000 W
+ 0x659, # [4]: Proc 1 Vcs/Vio/Vpcie -- 100.000 W
+ 0x6aa, # [5]: Proc 2 Vcs/Vio/Vpcie -- 105.000 W
+ 0x592, # [6]: Storage/Media 1 -- 80.000 W
+ 0x5eb, # [7]: Storage/Media 2 -- 85.000 W
+ 0x000, # [8]: Remote GND -- 0.000 V
+ 0xecb, # [9]: 12V Voltage Sense -- 12.300 V
+ 0x1bd, # [a]: IO 1 -- 25.000 W
+ 0x1cf, # [b]: IO 2 -- 26.000 W
+ 0x1e1, # [c]: IO 3 -- 27.000 W
+ 0x10b, # [d]: Fans 1 -- 15.000 W
+ 0x0d5, # [e]: Fans 2 -- 12.000 W
+ 0x001] # [f]: Unused -- 0.000
+# ----------
+# Total -- 898.000 W
+
+
+# ---------------------------------------------------------
+# Vpm - Uncomment lines below to run Vpm
+# ---------------------------------------------------------
+#@occoutfile = "/../simics/vpm/vpxP7"
+#@occsb = os.getenv("sb")
+#@cli.run_command("!" + occsb + occoutfile)
+
+@poolsys = os.getenv("DISPLAY")
+#@cli.run_command("Vpm.run-spec spec = square vpxServer = " + poolsys.split( ':',1)[0])
+#Vpm.enable-vpm
+
+
+# ---------------------------------------------------------
+# Misc Simics settings
+# ---------------------------------------------------------
+output-radix 16 # output in hex
+
+# ---------------------------------------------------------
+# Run python script(s) to enable some OCC Simics Commands
+# ---------------------------------------------------------
+echo " "
+echo "-------------------------------------------------------- "
+echo "Load OCC Developer Debug Scripts"
+echo "-------------------------------------------------------- "
+if not (lookup-file ../src/occc/405/occ/tools/occ_simics_debug.py ){
+ echo "Load Scripts from GSA"
+ run-python-file /gsa/ausgsa/projects/o/occfw/public/simics/scripts/occ_simics_debug.py # hsym, h64sym, h64attr
+ run-python-file /gsa/ausgsa/projects/o/occfw/public/simics/scripts/occ_amec_sensors.py # amec commands
+ run-python-file /gsa/ausgsa/projects/o/occfw/public/simics/scripts/occ_fsp_fakeout.py # tmgt commands
+ run-python-file /gsa/ausgsa/projects/o/occfw/public/simics/scripts/occ_gdb.py # gdb/ddd commands
+}else{
+ echo "Load Scripts from Sandbox"
+ run-python-file ../src/occc/405/occ/tools/occ_simics_debug.py # hsym, h64sym, h64attr
+ run-python-file ../src/occc/405/occ/tools/occ_amec_sensors.py # amec commands
+ run-python-file ../src/occc/405/occ/tools/occ_fsp_fakeout.py # tmgt commands
+ run-python-file ../src/occc/405/occ/tools/occ_gdb.py # gdb/ddd commands
+}
+
+# ---------------------------------------------------------
+# Set up Centaur/MCS so OCC can access Centaur
+# ---------------------------------------------------------
+echo " "
+echo "-------------------------------------------------------- "
+echo "Set up Centaur/MCS so OCC can access Centaur"
+echo "-------------------------------------------------------- "
+#putscom 0x2011802 0x83e0000000000000 # Centaur 0 -- Venice Only
+#putscom 0x2011882 0x83e0200000000000 # Centaur 1 -- Venice Only
+#putscom 0x2011902 0x83e0400000000000 # Centaur 2 -- Venice Only
+#putscom 0x2011982 0x83e0600000000000 # Centaur 3 -- Venice Only
+##putscom 0x2011c02 0x83e0800000000000 # Centaur 4
+##putscom 0x2011c82 0x83e0a00000000000 # Centaur 5
+##putscom 0x2011d02 0x83e0c00000000000 # Centaur 6
+##putscom 0x2011d82 0x83e0e00000000000 # Centaur 7
+
+
+# ---------------------------------------------------------
+# Enabling Magic Breakpoint to help with development debug
+# ---------------------------------------------------------
+echo " "
+echo "-------------------------------------------------------- "
+echo "Enabling Simics Magic Breakpoint for OCC developer debug "
+echo " To Disable: disable-magic-breakpoint"
+echo " To Start GDB: occ-gdb-start <occnum>"
+echo "-------------------------------------------------------- "
+echo " "
+enable-magic-breakpoint
+
diff --git a/src/occ/tools/occ_simics_debug.py b/src/occ/tools/occ_simics_debug.py
new file mode 100755
index 0000000..63cee85
--- /dev/null
+++ b/src/occ/tools/occ_simics_debug.py
@@ -0,0 +1,174 @@
+# @file - occ_simics_debug.py
+# @brief Create Simics Generic Commands
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# thallet 03/28/2012 Created
+
+
+from time import sleep
+from random import randint
+import sys
+import re
+
+G_occ_list = []
+
+##############################################################################
+###########################################################
+# Functions
+###########################################################
+##############################################################################
+def print_sym_as_hex( str ):
+ tick = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + '\"')
+ splitter = re.compile(r' (\d+)')
+ p_sym = tick[1].rstrip('\n')
+ r_sym = splitter.split(p_sym)
+ out_str = ''
+ for item in r_sym:
+ if item.isdigit():
+ if (int(item) > 0xffffffff):
+ out_str += "0x%016x" % int(item)
+ else:
+ out_str += "0x%08x" % int(item)
+ else:
+ out_str += `item`
+
+ print out_str
+ return
+
+def print_sym_as_hex64( str ):
+ tick = cli.quiet_run_command(G_occ_list[0] + ".cpu.psym " + '\"' + str + '\"')
+ splitter = re.compile(r' (\d+)')
+ p_sym = tick[1].rstrip('\n')
+ r_sym = splitter.split(p_sym)
+ out_str = ''
+ for item in r_sym:
+ if item.isdigit():
+ out_str += "0x%016x" % int(item)
+ else:
+ out_str += `item`
+
+ print out_str
+ return
+
+
+def print_simics_attr_as_hex64( str ):
+ tick = cli.quiet_run_command(str)
+ splitter = re.compile(r'(\d+)')
+ p_sym = tick[0]
+ print "0x%016x" % p_sym
+ return
+
+
+def getscom( int ):
+ tick = cli.quiet_run_command(G_occ_list[0] + ".pib_master->address = " + str(int))
+ tick = cli.quiet_run_command(G_occ_list[0] + ".pib_master->data")
+ p_sym = tick[0]
+ print "0x%016x" % p_sym
+ return
+
+def putscom( addr, data ):
+ tick = cli.quiet_run_command(G_occ_list[0] + ".pib_master->address = " + str(addr))
+ tick = cli.quiet_run_command(G_occ_list[0] + ".pib_master->data = " + str(data))
+ getscom(addr)
+ return
+
+def generate_occlist():
+ tick = cli.quiet_run_command("$occc[0]=0; $b=0; foreach $c in (get-object-list -all occ_simple) {$occc[$b] = $c; $b = $b + 1}")
+ num = cli.quiet_run_command("print -d $b")
+ for idx in range(int(num[1].rstrip('\n'))):
+ tick = cli.quiet_run_command("echo $occc[" + str(idx) + "]")
+ G_occ_list.insert(idx,tick[1].rstrip('\n'))
+ G_occ_list.sort()
+ for idx in range(int(num[1].rstrip('\n'))):
+ print str(idx) + ": " + G_occ_list[idx]
+
+ return
+
+
+generate_occlist()
+
+##############################################################################
+###########################################################
+# Register some New Simics Commands
+###########################################################
+##############################################################################
+
+
+#----------------------------------------------------------
+#
+#
+new_command("hsym", print_sym_as_hex,
+ args = [arg(str_t, "symbol-name")],
+ alias = "hsym",
+ type = "occ-fw-module-commands",
+ short = "Print a symbol as hex (uint64 or uint32) for all structure members",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["h64sym"],
+ doc = """
+ <b>hsym</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+#----------------------------------------------------------
+#
+#
+new_command("h64sym", print_sym_as_hex64,
+ args = [arg(str_t, "symbol-name")],
+ alias = "hsym64",
+ type = "occ-fw-module-commands",
+ short = "Print a symbol as hex (uint64) for all structure members",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["hsym"],
+ doc = """
+ <b>h64sym</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+
+#----------------------------------------------------------
+#
+#
+new_command("h64attr", print_simics_attr_as_hex64,
+ args = [arg(str_t, "simics-attribute")],
+ alias = "hattr",
+ type = "occ-fw-module-commands",
+ short = "Print a simics attribute as hex (uint64) for all structure members",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["hsym","h64sym"],
+ doc = """
+ <b>h64attr</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+#----------------------------------------------------------
+#
+#
+new_command("getscom", getscom,
+ args = [arg(int_t, "scomAddress")],
+ alias = "gs",
+ type = "occ-fw-module-commands",
+ short = "Do a getscom",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["hsym","h64sym"],
+ doc = """
+ <b>h64attr</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
+
+#----------------------------------------------------------
+#
+#
+new_command("putscom", putscom,
+ args = [arg(int_t, "scomAddress"),arg(int_t, "data")],
+ alias = "ps",
+ type = "occ-fw-module-commands",
+ short = "Do a getscom",
+ doc_items = [("NOTE", "This command is best")],
+ see_also = ["hsym","h64sym"],
+ doc = """
+ <b>h64attr</b> is best.
+ This is its documentation. <i>arg</i>
+ is the first argument...""")
+
diff --git a/src/occ/tools/occ_simics_gen_lists.py b/src/occ/tools/occ_simics_gen_lists.py
new file mode 100644
index 0000000..92768e7
--- /dev/null
+++ b/src/occ/tools/occ_simics_gen_lists.py
@@ -0,0 +1,53 @@
+# @file - occ_simics_debug.py
+# @brief Create Simics Generic Commands
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# thallet 03/28/2012 Created
+
+
+from time import sleep
+from random import randint
+import sys
+import re
+
+G_occ_list = []
+G_proc_list = []
+
+##############################################################################
+###########################################################
+# Functions
+###########################################################
+##############################################################################
+
+def generate_occlist():
+ occsimicslist = cli.quiet_run_command("$occc[0]=0; $b=0; foreach $c in (get-object-list -all occ_simple) {$occc[$b] = $c; $b = $b + 1}")
+ num = cli.quiet_run_command("print -d $b")
+ for idx in range(int(num[1].rstrip('\n'))):
+ occsimicslist = cli.quiet_run_command("echo $occc[" + str(idx) + "]")
+ G_occ_list.insert(idx,occsimicslist[1].rstrip('\n'))
+ G_occ_list.sort()
+ for idx in range(int(num[1].rstrip('\n'))):
+ cli.quiet_run_command("$occc[" + str(idx) + "]= " + G_occ_list[idx] + "")
+ print str(idx) + ": " + G_occ_list[idx]
+
+ return
+
+def generate_proclist():
+ procsimicslist = cli.quiet_run_command("$proc_chip[0]=0; $f=0; foreach $g in (get-object-list -all cec-chip) {$proc_chip[$f] = $g; $f = $f + 1}")
+ num = cli.quiet_run_command("print -d $f")
+ for idx in range(int(num[1].rstrip('\n'))):
+ procsimicslist = cli.quiet_run_command("echo $proc_chip[" + str(idx) + "]")
+ G_proc_list.insert(idx,procsimicslist[1].rstrip('\n'))
+ G_proc_list.sort()
+ for idx in range(int(num[1].rstrip('\n'))):
+ cli.quiet_run_command("$proc_chip[" + str(idx) + "]= " + G_proc_list[idx] + "")
+ print str(idx) + ": " + G_proc_list[idx]
+
+ return
+
+
+
+generate_occlist()
+generate_proclist()
+
diff --git a/src/occ/tools/occ_trace.simics b/src/occ/tools/occ_trace.simics
new file mode 100755
index 0000000..53175fb
--- /dev/null
+++ b/src/occ/tools/occ_trace.simics
@@ -0,0 +1,3 @@
+# Simics script to pull trace data. To run:
+# run-command-file trace.simics
+pipe "oci_space.x (sym g_trac_main) (sym \"sizeof(g_trac_main_buffer)\")" fsp_trace_parse.pl
diff --git a/src/occ/tools/occgenlid.pl b/src/occ/tools/occgenlid.pl
new file mode 100755
index 0000000..d373fed
--- /dev/null
+++ b/src/occ/tools/occgenlid.pl
@@ -0,0 +1,123 @@
+#!/usr/bin/perl
+
+################################################################################
+# change log:
+# n/a andrewg 09/07/06 Created
+# eggler 2009/04/06 added option file parm
+# thallet 2012/08/09 Modified to use with OCC
+################################################################################
+
+################################################################################
+#
+# The purpose of this script is to take as input a occ binary file and convert
+# it to a lid which can then be checked into cmvc.
+#
+################################################################################
+
+use strict;
+use warnings;
+
+# ---- MODULES ---- #
+use Getopt::Long;
+use File::Path;
+use File::Basename;
+
+# ---- CONSTANTS ---- #
+
+# ---- GLOBALS ---- #
+my $g_debug = 0;
+
+################################################################################
+#
+# Main program
+#
+################################################################################
+
+exit(main());
+
+################################################################################
+#
+# Main
+#
+################################################################################
+
+sub main
+{
+ my $l_help = '';
+ my $l_input_bin;
+ my $l_lid_name;
+ my $l_update_bin;
+ my $optionsfile;
+
+
+ if (!GetOptions('h|help' => \$l_help,
+ 'd|debug' => \$g_debug,
+ 'i|input_binary=s'=> \$l_input_bin,
+ 'l|lid_name=s' => \$l_lid_name,
+ 'o|optionsfile=s' => \$optionsfile))
+ {
+ return -1;
+ }
+
+ #-- Handle the usage statement immediately.
+ if ($l_help)
+ {
+ usageInfo();
+ return 0;
+ }
+
+ if((!defined($l_input_bin)) || (!defined($l_lid_name)))
+ {
+ print "Must provide both --input_binary and --lid_name!\n";
+ return -1;
+ }
+
+ if(! -e $l_input_bin)
+ {
+ print "Input binary file, $l_input_bin, does not exist!\n";
+ return -1;
+
+ }
+
+
+ # We should now have some file called update_bin_* - lets rename it
+ system ("cp $l_input_bin occ_update.bin");
+
+ # Make sure that the extucode dir exists
+ if( !(-d $ENV{'sb'}."/extucode") )
+ {
+ print "Directory ".$ENV{'sb'}."/extucode not found....Creating\n";
+ system("mkdir " .$ENV{'sb'}."/extucode");
+ }
+
+ # Now lets run the build scripts
+ system ("apyfipshdr -r ". $ENV{'bb'} . "/src/lidhdr/$l_lid_name.lidhdr -l ./occ_update.bin -o " . $ENV{'sb'} . "/extucode/$l_lid_name.fips");
+
+ system("apyruhhdr -r " . $ENV{'bb'} . "/src/lidhdr/$l_lid_name.lidhdr -l " . $ENV{'sb'} . "/extucode/$l_lid_name.fips");
+
+ return(0);
+}
+
+
+
+################################################################################
+#
+# usageInfo
+#
+################################################################################
+
+sub usageInfo
+{
+print<<EOF;
+Usage:
+ tpmdgenlid.pl -i <absolute bin file> -l <lid name>
+
+OPERATIONS:
+ -h, -H, --help : Print this summary of options and exit.
+ -d, --debug : Displays additional output
+ -i --input_binary : Input binary file
+ -l --lid_name : Lid name to output to w/o lid suffix (i.e. -l 81e00430)
+
+
+EOF
+}
diff --git a/src/occ/tools/scanforsrcs.pl b/src/occ/tools/scanforsrcs.pl
new file mode 100755
index 0000000..f3b0a8f
--- /dev/null
+++ b/src/occ/tools/scanforsrcs.pl
@@ -0,0 +1,1121 @@
+#!/usr/bin/perl
+
+# This is a utility to generate occSrcParse.C automatically.
+# It will searching backing build if file is not present in the sandbox.
+
+use strict;
+use File::Find ();
+use Time::localtime;
+
+#use re 'debug';
+my $VERSION = 1.5;
+
+
+sub usage() {
+ print "Usage: $0 < -b base > <-d> < -o output dir > < -w Word N > \"location of fips_comp_id.H\"\n";
+ print "\n";
+ print "-b: base directory ( default is pwd )\n";
+ print "-d: Allow duplicates - default is to ignore\n";
+ print "-o: Used as the output directory where plugins are dropped\n";
+ print " Default is PWD\n";
+ print "-w: Use word N in generating unique SRCs ( N is between 1 and 4 )\n";
+ print "-e: Word N is errno\n";
+ print "-n: Don't display tag lines equal to NA or N/A\n";
+ print "-V Display version.\n";
+ print "-h Display version.\n";
+ print "\n\n";
+ exit 1;
+}
+
+# Locals
+my $base = $ENV{PWD};
+my $baseBB = $ENV{PWD};
+my $output = $base;
+my $arg;
+my %Comps;
+my $ignore = 1;
+my $fips_comp_id = "$ENV{bs}/fstp/fsp/fips_comp_id.H";
+#occ/incl/comp_ids.h
+my $wordn = "userdata";
+my $wordnd = 0;
+my $Errno = 0;
+my $NA = 1;
+
+while ($ARGV = shift) {
+ if ( $ARGV =~ m/-b/ ) {
+ $base = shift;
+ }
+ elsif ( $ARGV =~ m/-d/i ) {
+ $ignore = 0;
+ }
+ elsif ( $ARGV =~ m/-o/i ) {
+ $output = shift;
+ }
+ elsif ( $ARGV =~ m/-w/i ) {
+ $wordnd = shift;
+ $wordn .= $wordnd;
+ }
+ elsif ( $ARGV =~ m/-e/i ) {
+ $Errno = shift;
+ }
+ elsif ( $ARGV =~ m/-n/i ) {
+ $NA = 0;
+ }
+ elsif ( $ARGV =~ m/-h/i ) {
+ usage();
+ }
+ elsif ( $ARGV =~ m/-V/ ) {
+ print "$0 version = $VERSION\n\n";
+ exit 0;
+ }
+ else {
+ $fips_comp_id = $ARGV . "/$fips_comp_id";
+ }
+}
+
+# Hardcode just the values that occ needs
+$base="$ENV{SANDBOXBASE}/src/occc/405/";
+#$baseBB="$ENV{bb}/src/occc/405/";
+#$baseBB="/afs/austin.ibm.com/projects/esw/occ810/Builds/occ810_130926a/src/occc/405/";
+$baseBB="$ENV{BACKED_SANDBOXDIR}";
+my @values = split(':', $baseBB);
+foreach my $val (@values)
+{
+ if ( $val =~ m/occ810/)
+ {
+ $baseBB=$val;
+ }
+ }
+
+#we should not input -d option, let $ignore = 1; #so compile won't fail if there are dups
+$output=$base; # put output file in base directory
+$wordnd = 4; #look at userdata4
+$wordn .= $wordnd;
+#$NA = 0;
+my $IgnoreDir = "ssx";
+
+
+FindFiles();
+
+my $cntr;
+
+foreach my $key ( sort keys %Comps )
+{
+ DumpPlugin( $key, \@{$Comps{$key}} );
+}
+
+
+#DumpMakefile();
+
+print " +++ $0 is DONE. \n";
+
+exit;
+
+sub FindFiles
+{
+ # Array which will have the final set of files to scan
+ my @FilteredArray;
+
+ # Array holding Base Sandbox files
+ my $BaseFiles=`find $base -name $IgnoreDir -prune -type f -name \'*.h\' -or -name \'*.c\'`;
+ my @BaseFileArray= split("\n", $BaseFiles);
+ #foreach my $val (@BaseFileArray)
+ #{
+ # print "SandboxFiles:: $val \n";
+ #}
+ # Array holding the Backing Build files
+ my $BBFiles=`find $baseBB -name $IgnoreDir -prune -type f -name \'*.h\' -or -name \'*.c\'`;
+ my @BBFileArray= split("\n", $BBFiles);
+ #foreach my $val (@BBFileArray)
+ #{
+ # print "BackingBuildFiles:: $val \n";
+ #}
+
+ # find all build files from makefile and remove unnecessary files from src scan list
+ my @BuildList = FindBuildList();
+ #foreach my $val (@BuildList)
+ #{
+ # print "BuildList:: $val \n";
+ #}
+
+
+ CheckBuildList(\@BBFileArray, @BuildList);
+ CheckBuildList(\@BaseFileArray, @BuildList);
+
+ # Start with Sandbox Files
+ @FilteredArray=@BaseFileArray;
+
+ # Cycle through all Backing Build Files
+ for my $BBFileArrayCntr(@BBFileArray)
+ {
+ # found flag
+ my $found = 0;
+
+ # Cycle through all Sandbox Files
+ for my $BaseFileArrayCntr(@BaseFileArray)
+ {
+
+ # strip off everything an get current Backing Build File
+ my $tmp1 = rindex($BBFileArrayCntr, "/") + 1;
+ my $BBFileName = substr($BBFileArrayCntr, $tmp1);
+
+ # strip off everyting and get current Sandbox File
+ my $tmp2 = rindex($BaseFileArrayCntr, "/") + 1;
+ my $FileName = substr($BaseFileArrayCntr, $tmp2);
+
+ # if Backing Build File name is same is SandBox file name
+ # then we are done checking this Backing Build file, exit!
+ if ( "$BBFileName" eq "$FileName" )
+ {
+ $found = 1;
+ last;
+ }
+ }
+
+ # if we didnt find any matches then it means that the
+ # backing build file name should be used
+ if ( $found eq 0 )
+ {
+ # add to final array
+ @FilteredArray=(@FilteredArray,$BBFileArrayCntr);
+ }
+ }
+
+ # sort final arry based on ascii of strings
+ @FilteredArray = sort( @FilteredArray );
+
+ # now called wanted to extract SRCs
+ foreach my $FilteredArrayCntr(@FilteredArray)
+ {
+ # extract srcs from this file
+ &wanted( $FilteredArrayCntr );
+ }
+}
+
+# Find build lists from makefile
+sub FindBuildList
+{
+ # Array holding all makefiles
+ my @MakefileArray;
+
+ # Array holding makefiles in Base Sandbox
+ my $BaseMakefile = `find $base -type f -name *.mk -or -name "Makefile*"`;
+ my @BaseMakefileArray = split("\n", $BaseMakefile);
+
+ # Array holding makefiles in Backing Build
+ my $BBMakefile = `find $baseBB -type f -name *.mk -or -name "Makefile*"`;
+ my @BBMakefileArray = split("\n", $BBMakefile);
+
+ # Use makefiles in sandbox as the base
+ @MakefileArray = @BaseMakefileArray;
+
+ # Cycle through all Backing Build Files
+ for my $BBMakefileArrayCntr(@BBMakefileArray)
+ {
+ # found flag
+ my $found = 0;
+
+ # Cycle through all Sandbox Files
+ for my $BaseMakefileArrayCntr(@BaseMakefileArray)
+ {
+ # strip off everything and get current Backing Build File
+ my $tmp1 = rindex($BBMakefileArrayCntr, "/src/occc/405") + 1;
+ my $BBMakefileName = substr($BBMakefileArrayCntr, $tmp1);
+
+ # strip off everyting and get current Sandbox File
+ my $tmp2 = rindex($BaseMakefileArrayCntr, "/src/occc/405") + 1;
+ my $FileName = substr($BaseMakefileArrayCntr, $tmp2);
+
+ # To check if the makefiles is only found in Backing Build
+ if ("$BBMakefileName" eq "$FileName")
+ {
+ $found = 1;
+ last;
+ }
+ }
+
+ # if we didnt find any matches, use makefile from backing build
+ if ($found == 0)
+ { # add to final array
+ @MakefileArray = (@MakefileArray,$BBMakefileArrayCntr);
+ }
+ }
+
+ # sort final array based on ascii of strings
+ @MakefileArray = sort( @MakefileArray );
+
+ # loop for all makefiles to collect build files
+ my @TempArray;
+ foreach my $makefileCnt (@MakefileArray)
+ {
+ #will display which makefile we cross reference against
+ #print "Using $makefileCnt\n";
+ my $var;
+ {
+ local $/;
+ open my $fh, '<', $makefileCnt or die "can't open $makefileCnt: $!";
+ $var = <$fh>;
+ close $fh;
+ }
+ $var =~ s/#.*//g; # remove comments
+# print "$var \n";
+ while ($var =~ m/(\w+)\.o/g)
+ { # Add to build list
+ @TempArray = (@TempArray,$1);
+ }
+
+ while ($var =~ m/(\w+)\.c/g)
+ { # Add to build list
+ @TempArray = (@TempArray,$1);
+ }
+ }
+
+ # remove duplicate elements
+ my %hash = map { $_, 1 } @TempArray;
+ my @BuildArray = keys %hash;
+ # sort final arry based on ascii of strings
+ @BuildArray = sort(@BuildArray);
+
+ # foreach my $val (@BuildArray)
+ # {
+ # print "$val \n";
+ # }
+
+ return @BuildArray
+}
+
+# Remove files which are not in the build list
+sub CheckBuildList
+{
+ my ($FileArray, @BuildList) = @_;
+
+ my @tempArray; # since we cannot delete elements in array in loop
+
+ foreach my $ArrayCnt(@$FileArray)
+ { # strip off everything and get filename
+ my $pos = rindex($ArrayCnt, "/") + 1;
+ my $File = substr($ArrayCnt, $pos, -2);
+
+ if ( $ArrayCnt =~ /\/lib\// )
+ {
+ #print "LIB file found! $ArrayCnt \n";
+ next;
+ }
+
+ if ( $ArrayCnt =~ /\/ssx\// )
+ {
+ #print "SSX file found! $ArrayCnt \n";
+ next;
+ }
+
+ #print "Found $File.c\n";
+
+ my $found = 0;
+ foreach my $Buildfile(@BuildList)
+ {
+ if ($Buildfile =~ /$File/)
+ {
+ # found filename in makefile, add to scan SRC
+
+ # will give you the full path of file we
+ # adding to our scan list
+ # print "Adding $ArrayCnt to src scan list. \n";
+
+ push @tempArray, $ArrayCnt;
+ $found = 1;
+ last;
+ }
+ }
+
+ if ($found == 0)
+ { # not found, ignore this file
+ print "Ignoring $ArrayCnt. \n";
+ }
+ }
+
+ @$FileArray = @tempArray;
+}
+
+sub FileFind
+{
+ # Set the variable $File::Find::dont_use_nlink if you're using AFS,
+ # since AFS cheats.
+
+ # for the convenience of &wanted calls, including -eval statements:
+ use vars qw/*name *dir *prune/;
+ *name = *File::Find::name;
+ *dir = *File::Find::dir;
+ *prune = *File::Find::prune;
+
+ # Traverse desired filesystems
+ File::Find::find({wanted => \&wanted}, $base);
+
+}
+
+
+sub wanted {
+ #my ($dev,$ino,$mode,$nlink,$uid,$gid);
+ my $data;
+ my $file = "@_";
+
+ print "Processing: $file\n";
+
+ open FH, $file or die "Cannot open: $file";
+ read FH, $data, -s FH or die "Error reading $file: $!";
+ close FH;
+
+ # extract filename from full path
+ my $pos = rindex($file, "/") + 1;
+ my $fileName = substr($file, $pos);
+
+ # extract component
+# $fileName =~ /^(\w{4})/;
+# my $comp = $1;
+ # No matter filename has prefix "hwsv"(applet) or "tmgt"(all other tmgt code), put all function in one file which is "occSrcParse.C",
+ my $comp = 'occc';
+
+ while ( $data =~ /\@errortype(?:.*?)\n((.+?\n)+?).+?\*\//mgo )
+ {
+ my $text = $1;
+ my $found = 0;
+ my %hash = $text =~ /\@(\w+)(?:\s+|\.+)\b(.+?)$/gm;
+ my $tmp;
+
+ foreach my $key (sort keys %hash)
+ {
+ # Extract multi-line string
+ $text =~ /\@$key(?:\s+|\.+)(.+?)(?:\@|$).*/s;
+ $tmp = $1;
+
+ # take off comment starting with "//"
+ $tmp =~ s/\s*\/\/.*//gm;
+
+ # replace "\*" with "\n"
+ $tmp =~ s/\s*\*\s*/ \n/gm;
+
+ chomp($tmp);
+ $hash{$key} = $tmp;
+ }
+
+ #add on file info
+ $hash{file} = $file;
+
+# print "------------------------>\n";
+# print "$text\n\n";
+# foreach my $key (sort keys %hash)
+# {
+# print "\t$key => $hash{$key}\n";
+# }
+# print "<------------------------\n";
+
+ # Remove trailing words
+ $hash{moduleid} =~ s/^(\w+).*$/$1/;
+ $hash{reasoncode} =~ s/^(\w+).*$/$1/;
+
+ if ( $ignore )
+ {
+ my $res;
+ my @RedundantComps;
+
+ # Find duplicates
+ foreach my $href ( @{ $Comps{$comp} } )
+ {
+ $res = hasheq( 3, $href, \%hash);
+ $found |= $res;
+
+ # showing up duplicated files
+ if ($res)
+ {
+ push @RedundantComps, $href;
+ }
+ }
+
+ if ($found) {
+ foreach my $href ( @RedundantComps )
+ {
+ print "!!!! Also found the same combination in file => $href->{file}\n";
+ }
+
+ die "ERROR: $hash{moduleid}/$hash{reasoncode}/$hash{$wordn} combination used more than once in file $fileName!\n";
+ }
+ }
+
+ if ( ! $found )
+ {
+ push @{ $Comps{$comp} }, \%hash;
+ }
+ }
+}
+
+
+sub hasheq
+{
+ my ($cmpnum, $ha1, $ha2) = @_;
+ my $h1w2 = "";
+ my $h2w2 = "";
+
+ $h1w2 = $1 if $ha1->{$wordn} =~ /^(\w+)/;
+ $h2w2 = $1 if $ha2->{$wordn} =~ /^(\w+)/;
+
+ if ( $ha1->{moduleid} eq $ha2->{moduleid} &&
+ $ha1->{reasoncode} eq $ha2->{reasoncode} )
+ {
+ if ($cmpnum eq 2)
+ {
+ return 1;
+ }
+ # compare one more parm (userdataX)
+ elsif ($cmpnum eq 3 &&
+ $h1w2 eq $h2w2 )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+sub TakeOffRedundantFunc
+{
+ my ( $aref ) = @_;
+
+ my @nonRedundantComps;
+ my $sameflag = 0;
+ my $i;
+ my $j;
+
+ #take off redundent componets
+ for($j = 0; $j < @$aref; $j++)
+ {
+ for($i = ($j + 1); $i < @$aref; $i++)
+ {
+ if ( hasheq( 2, @$aref[$j], @$aref[$i]) )
+ {
+ $sameflag = 1;
+ last;
+ }
+ }
+
+ if ($sameflag == 0)
+ {
+ push @nonRedundantComps, @$aref[$j];
+ }
+ $sameflag = 0;
+ }
+
+ return @nonRedundantComps;
+}
+
+
+sub DumpPlugin
+{
+ my ( $compName, $aref ) = @_;
+ my $filename = "$output/$compName" . "SrcParse.C";
+ my $filename2 = "$output/$compName" . "SrcParse.H";
+
+ my $fh;
+ my $fh2;
+
+ #if the plugins subdir doesn't exist, create it
+ if (!-e $output)
+ {
+ print "Creating directory $output\n";
+ `mkdir -p $output`;
+ }
+
+ `rm -f $filename`;
+ `rm -f $filename2`;
+
+ open $fh, ">$filename" or die "Cannot open $filename: $!\n";
+ open $fh2, ">$filename2" or die "Cannot open $filename2: $!\n";
+
+ DumpHeader( $compName, $fh, $fh2 );
+
+ DumpPrototypes( $fh, $aref );
+
+ DumpTable( $fh, $compName, $aref );
+
+ DumpBody( $fh );
+
+ DumpParsers( $fh, $aref );
+
+ close $fh or die "Cannot close $filename: $!\n";
+ close $fh2 or die "Cannot close $filename: $!\n";
+}
+
+
+
+
+sub DumpHeader
+{
+ my ( $compName, $fh, $fh2 ) = @_;
+ my $schdr = $compName . "SrcParse.H";
+ my $struct = $compName . "SrcParser";
+ my $timestamp = ctime();
+
+ #lets look for the header includes we will need!
+ my $compIdFiles=`find $base -type f -name \"comp_ids.h\"`;
+ my @compIdFilesArray= split("\n", $compIdFiles);
+
+
+ my $headerString = "// includes from occ code base \n// $base \n";
+ foreach my $val (@compIdFilesArray)
+ {
+ #print "IncludeFiles:: $val \n";
+
+ open ( my $l_fh, $val ) or die "Could not open $val";
+
+ my $filedata = "";
+ my $start=0;
+ while (my $row = <$l_fh>)
+ {
+ chomp $row;
+ if ( $row =~ /#ifndef/)
+ {
+ $start = 1;
+ }
+
+ if ($start == 1)
+ {
+ if ( $row =~ /#include/)
+ {
+ #ignore the line
+ }
+ else
+ {
+ $filedata .= "$row \n";
+ }
+ }
+
+ if ( $row =~ /#endif/)
+ {
+ $start = 0;
+ }
+
+ }
+
+ #print "$filedata \n";
+ close ($l_fh);
+
+ # strip off everyting and get current Sandbox File
+ #my $tmp2 = rindex($val, "/") + 1;
+ #my $FileName = substr($val, $tmp2);
+
+ #$headerString .= "#include <$FileName> \n";
+ $headerString .= "$filedata \n";
+ }
+
+
+ #lets look for the header includes we will need!
+ my $IncludeFiles=`find $base -type f -name \"*_service_codes.h\"`;
+ my @IncludeFilesArray= split("\n", $IncludeFiles);
+
+ foreach my $val (@IncludeFilesArray)
+ {
+ #print "IncludeFiles:: $val \n";
+
+ open ( my $l_fh, $val ) or die "Could not open $val";
+
+ my $filedata = "";
+ my $start=0;
+ while (my $row = <$l_fh>)
+ {
+ chomp $row;
+ if ( $row =~ /#ifndef/)
+ {
+ $start = 1;
+ }
+
+ if ($start == 1)
+ {
+ if ( $row =~ /#include/)
+ {
+ #ignore the line
+ }
+ else
+ {
+ $filedata .= "$row \n";
+ }
+ }
+
+ if ( $row =~ /#endif/)
+ {
+ $start = 0;
+ }
+
+ }
+
+ #print "$filedata \n";
+ close ($l_fh);
+
+ # strip off everyting and get current Sandbox File
+ #my $tmp2 = rindex($val, "/") + 1;
+ #my $FileName = substr($val, $tmp2);
+
+ #$headerString .= "#include <$FileName> \n";
+ $headerString .= "$filedata \n";
+ }
+
+
+ #print "$headerString ";
+
+ my $filehdr = "
+
+/*
+ * Automatically generated by $0
+ *
+ * TimeStamp: $timestamp
+ *
+*/
+
+/*****************************************************************************/
+// I n c l u d e s
+/*****************************************************************************/
+#include <cstring>
+#include <errno.h>
+
+#include <errlplugins.H>
+#include <errlusrparser.H>
+#include <srcisrc.H>
+
+#include <$schdr>
+
+typedef void (*parser_t) ( ErrlUsrParser & i_parser, const SrciSrc & i_src );
+
+
+// Returns specified userdata word (1-4) for supplied SRC
+uint32_t get_usrword(const SrciSrc & i_src, const uint8_t i_userdata_num)
+{
+ const uint32_t *l_wordarray = NULL;
+ uint32_t l_wordcount = 0;
+ uint32_t l_word = 0;
+ uint16_t l_index = i_userdata_num + 3; // userdata1 is at array index 4, ...
+
+ // Access user words 2-9 and get count
+ l_wordarray = i_src.getHexData(l_wordcount);
+ if ( l_index < l_wordcount)
+ {
+ l_word = l_wordarray[l_index];
+ }
+
+ return l_word;
+}
+
+
+/*****************************************************************************/
+// Forward
+/*****************************************************************************/
+static bool SrcDataParse(
+ ErrlUsrParser & i_parser,
+ const SrciSrc & i_src
+);
+
+
+/*****************************************************************************/
+// User types
+/*****************************************************************************/
+struct $struct
+{
+ uint32_t iv_uid;
+ parser_t iv_parser;
+};
+
+
+/*****************************************************************************/
+// Prototypes
+/*****************************************************************************/
+";
+
+ print $fh $filehdr;
+ print $fh2 $headerString;
+}
+
+
+sub DumpPrototypes
+{
+ my ( $fh, $aref ) = @_;
+ my $forward;
+
+ # get nonRedundant functions to avoid declare same prototype for miltiple times.
+ my @nonRedundant = TakeOffRedundantFunc($aref);
+
+ foreach my $href ( @nonRedundant )
+ {
+ $forward = "void Parse_$href->{moduleid}_$href->{reasoncode}( ErrlUsrParser & i_parser, const SrciSrc & i_src );\n";
+ print $fh $forward;
+ }
+
+ print $fh "\n\n";
+
+}
+
+
+sub DumpTable
+{
+ my ( $fh, $compName, $aref ) = @_;
+ my $structname = $compName . "SrcParser";
+ my $compId = ( uc $compName ) . "_COMP_ID";
+ my $header = "
+/*****************************************************************************/
+// Globals
+/*****************************************************************************/
+static errl::SrcPlugin g_SrcPlugin( $compId, SrcDataParse );
+
+static $structname g_ParserList[] =
+{
+";
+
+ my $footer =
+" { 0, 0 }
+};";
+
+ my $forward;
+
+ print $fh $header;
+
+ # get nonRedundant functions to avoid declare same function for miltiple times.
+ my @nonRedundant= TakeOffRedundantFunc($aref);
+
+ foreach my $href ( @nonRedundant )
+ {
+ $forward = " { ( ( $href->{moduleid} << 16 ) | ( OCCC_COMP_ID | $href->{reasoncode}) ), Parse_$href->{moduleid}_$href->{reasoncode} },\n";
+ print $fh $forward;
+ }
+
+ print $fh "$footer\n\n";
+
+}
+
+sub DumpBody
+{
+ my ( $fh ) = @_;
+ print $fh "
+/*****************************************************************************/
+// Main Parser
+/*****************************************************************************/
+bool SrcDataParse(
+ ErrlUsrParser & i_parser,
+ const SrciSrc & i_src
+)
+{
+ // Locals
+ int l_cntr = 0;
+ uint32_t l_uid = 0;
+ bool l_rc = false;";
+
+
+ if ( $Errno > 0 ) # || $wordnd > 0
+ {
+ print $fh "
+ const uint32_t *l_wa = 0;
+ uint32_t l_wc = 0;
+
+ // Access user words
+ l_wa = i_src.getHexData(l_wc);";
+
+ }
+
+ print $fh "
+
+ // Form Unique Id
+ uint8_t l_w4 = (uint8_t) ( ( get_usrword(i_src,4) & 0xFF000000) >> 24); //extract the component id from word 4
+ l_uid = (l_w4 << 24) | ( i_src.moduleId() << 16 ) | i_src.reasonCode();
+
+ //i_parser.PrintNumber( \"original l_uid: \", \"0x%08X\", l_uid );
+
+ //i_parser.PrintNumber( \"new gList value\", \"0x%08X\", ( (AMEC_MST_CHECK_UNDER_PCAP & 0x00FF) << 16 ) | (OCCC_COMP_ID|INTERNAL_FAILURE) );
+
+
+ ";
+
+
+ if ( $Errno > 0 )
+ {
+ print $fh "
+
+ // Set errno
+ errno = l_wa[$Errno+3];";
+
+ }
+
+ print $fh "
+
+ // Find unique parser and transfer control
+ while ( g_ParserList[l_cntr].iv_uid )
+ {
+ if ( g_ParserList[l_cntr].iv_uid == l_uid )
+ {
+ g_ParserList[l_cntr].iv_parser( i_parser, i_src );
+ l_rc = true;
+ break;
+ }
+ l_cntr++;
+ }
+
+ return l_rc;
+}
+
+
+";
+
+
+}
+
+
+sub DumpParsers
+{
+
+ my ( $fh, $aref ) = @_;
+ my $FuncName;
+
+ foreach my $href ( @$aref )
+ {
+ my $mid = $href->{moduleid};
+ my $erc = $href->{reasoncode};
+
+ $FuncName = "Parse_$mid\_$erc";
+
+ my $header = "
+/*****************************************************************************/
+// $mid, $erc
+/*****************************************************************************/
+void $FuncName( ErrlUsrParser & i_parser, const SrciSrc & i_src )
+{
+";
+ print $fh $header;
+
+ my @sameComps;
+ my @othersComps;
+ my $other;
+ #check if we have the same modid and reason code, but different data4.
+ while (@$aref != "")
+ {
+ $other = pop (@$aref);
+ if ( ($href != $other) &&
+ hasheq( 2, $href, $other) )
+ {
+ push @sameComps, $other;
+ }
+ else
+ {
+ push @othersComps, $other;
+ }
+ }
+ @sameComps = reverse(@sameComps);
+ @othersComps = reverse(@othersComps);
+ @$aref = @othersComps;
+
+# print "I am $href, othersComps = @othersComps\n";
+# print "Current Array: @$aref\n";
+# printf "--------------------\n";
+
+ #add itself into array
+ push @sameComps, $href;
+
+ my %hashtemp;
+ #if more than one errl has same moduleID/reason, sort errl by userdata4.
+ if (@sameComps > 1)
+ {
+ my @tempComps;
+ my @Result;
+ my $temp;
+ my $wdnString;
+
+ while (@sameComps)
+ {
+ $temp = pop (@sameComps);
+ %hashtemp = %{ $temp };
+
+ # if userdata4 filed is not null, put it to the front of result array.
+ if ($hashtemp{$wordn} ne "")
+ {
+ # check if userdata4 still has string
+ $wdnString = $hashtemp{$wordn} =~ /[:alpha:]/;
+ if ($wdnString)
+ {
+ print "WARNING: userdata4 can only be number!!! Current value =\"$hashtemp{$wordn}\", file : $hashtemp{file}\n";
+ }
+
+ push @Result, $temp;
+ }
+ else
+ {
+ push @tempComps, $temp;
+ }
+ }
+
+ # push remain elements(userdata4 == null) into end of result array
+ while (@tempComps)
+ {
+ $temp = pop (@tempComps);
+ push @Result, $temp;
+ }
+ # write Result back
+ @sameComps = @Result;
+ }
+
+ my $i;
+ my $errl;
+ # create code for Errl combination
+ for($i = 0; $i < scalar(@sameComps); $i++)
+ {
+ $errl = @sameComps[$i];
+ %hashtemp = %{ $errl };
+
+ #print if/esle case
+ if (scalar(@sameComps) > 1)
+ {
+ if ( $i eq 0 )
+ {
+ print $fh "
+ uint32_t l_word = (get_usrword(i_src,4) & 0x00FFFFFF)\;
+ if (l_word == $hashtemp{$wordn})
+ {\n";
+ }
+ elsif ($i eq (@sameComps - 1))
+ {
+ print $fh "
+ else
+ {\n";
+ }
+ else
+ {
+ print $fh "
+ else if (l_word == $hashtemp{$wordn})
+ {\n";
+ }
+ }
+
+ #print code line by line for errl detail.
+ foreach my $tag ( sort keys %$errl )
+ {
+ $errl->{$tag} =~ s/\"/\\\"/g;
+
+ # Do not print out file information which is not require by LOG
+ if ( $tag =~ /file/ )
+ {
+ next;
+ }
+
+ my @lines = split /^/, $errl->{$tag};
+
+ # if we have if/else cases, shift 4 space for coding standard.
+ if (scalar(@sameComps) > 1)
+ {
+ print $fh " ";
+ }
+
+ if ( scalar(@lines) > 1 )
+ {
+ print $fh " i_parser.PrintString(\"$tag\",\n";
+ foreach my $line ( @lines )
+ {
+ $line =~ s/\n//g;
+ print $fh " \"$line\"\n";
+ }
+ print $fh " );\n";
+ }
+ else
+ {
+ my $line = $errl->{$tag};
+ $line =~ s/\n//g;
+
+ if ( $tag =~ /$Errno/ )
+ {
+ print $fh " i_parser.PrintString(\"errno\", strerror(errno));\n";
+ }
+ elsif ( $NA == 1 || ! ( $line =~ /^N\/??A/ ) )
+ {
+ print $fh " i_parser.PrintString(\"$tag\", \"$line\");\n";
+ }
+ }
+
+ }
+
+ if ( scalar(@sameComps) > 1)
+ {
+ print $fh " }"
+ }
+ }
+ print $fh "\n}\n\n\n";
+ }
+
+}
+
+sub DumpMakefile
+{
+ my $filename = "$output/makefile";
+ my $fh;
+ my $fcid; # Fips Component Ids
+ my %comphash;
+
+ if ( ! open $fcid, "<$fips_comp_id" )
+ {
+ print "Cannot open $fips_comp_id: $! - makefile will NOT be created\n";
+ return;
+ }
+ else
+ {
+ my $data;
+ read $fcid, $data, -s $fcid or die "Error reading $fips_comp_id: $!";
+ close $fcid;
+ %comphash = $data =~ /(\w{4})_COMP_ID.*?=.*?0x(\w{4})/mg;
+ #foreach my $key ( sort keys %comphash )
+ #{
+ # print "MAP: $key->$comphash{$key}\n";
+ #}
+ }
+ if ( ! open $fh, ">$filename" )
+ {
+ print "Cannot open $filename: $! - makefile will NOT be created\n";
+ return;
+ }
+
+ my @keys = keys %Comps;
+ my %libnames;
+
+ print $fh "\n";
+ foreach my $key ( @keys )
+ {
+ my $uKey = $key;
+ $uKey =~ tr/a-z/A-Z/;
+ $libnames{$key} = "libE-" . $comphash{$uKey} . ".so";
+ my $srcfile = $key . "SrcParse.o\n";
+ print $fh "$libnames{$key}_OFILES = $srcfile";
+ #$libnames{$key} = $libnames{$key} . ".so";
+ }
+ print $fh "\n";
+
+ print $fh "INCFLAGS\t+= ";
+ foreach my $key ( @keys )
+ {
+ print $fh "-I../$key/fsp ";
+ }
+ print $fh "\n\n";
+
+ print $fh "SHARED_LIBRARIES\t=\t\t\\\n";
+ foreach my $key ( @keys )
+ {
+ print $fh "\t$libnames{$key} \t\\\n";
+ }
+ print $fh "\n\n";
+
+ print $fh ".if ( \$(CONTEXT) != \"x86\" )\n";
+ foreach my $key ( @keys )
+ {
+ print $fh "$libnames{$key}_IDIR = /fs/nfs.fips/lib/\n";
+ }
+ print $fh ".endif\n\n";
+
+ print $fh "SHIPLIST = \$\{ILIST\}\n\n";
+
+ print $fh ".include<\$\{RULES_MK\}>\n\n";
+
+ close $fh or die "Cannot close $filename: $!\n";
+}
diff --git a/src/occ/tools/start_occ_simics.pl b/src/occ/tools/start_occ_simics.pl
new file mode 100755
index 0000000..15c8890
--- /dev/null
+++ b/src/occ/tools/start_occ_simics.pl
@@ -0,0 +1,251 @@
+#!/usr/bin/perl -w
+
+#----------------------------------------------------------------------------
+use strict;
+use Cwd;
+
+#use Getopt::Long;
+#use File::Basename;
+#use Time::Local;
+#use POSIX qw(strftime);
+#use Carp;
+#use FindBin; # std
+#use Cwd 'abs_path';
+
+#use Time::Local;
+
+use lib "$ENV{'sb'}/simu/fsp/perl/CPAN";
+use lib "$ENV{'bb'}/src/simu/fsp/perl/CPAN";
+
+# Setup/declare some of our initial variables
+my $configuration_file = "$ENV{'HOME'}/.occ_simics_config";
+my $cur_dir = getcwd();
+my $use_gdb = 0; # Default to not allowing GDB in simics
+my $verbose = 0; # Default to non-verbose output
+my $commands = "";
+
+my $target = "occ-simple-common.simics";
+my $binary_file = "validation/apps/ocb_irq/ocb_irq.out";
+my $simics_workspace = "";
+my @search_paths;
+
+# Read in the configuration file
+read_configuration_file();
+
+#start by handling the command line arguments
+process_command_line();
+
+# Add $simics_workspace and $cur_dir to @search_paths
+push @search_paths, $simics_workspace;
+push @search_paths, $cur_dir;
+
+# Now put all our read in options together...
+$target = find_full_path($target);
+$binary_file = find_full_path($binary_file);
+
+
+# And setup our command line arguments
+my $binary_cmd = "oci_space.load-binary $binary_file";
+my $symtable_cmd = "new-symtable st $binary_file";
+my $gdb_cmd = "new-gdb-remote";
+
+my $full_command = "\"" . $binary_cmd . ";" . $symtable_cmd . ";" . $commands;
+if($use_gdb)
+{
+ $full_command .= $gdb_cmd . ";";
+}
+$full_command .= "\"";
+
+# Create the simics command
+if($verbose)
+{
+ print "Target: $target\n";
+ print "Binary: $binary_file\n";
+}
+my $simics_command = "ulimit -c unlimited; $simics_workspace/simics -verbose $target -e $full_command";
+
+
+# Run the simics command
+if($verbose)
+{
+ print "\nRunning $simics_command\n";
+}
+
+system("$simics_command");
+
+exit 0;
+
+
+
+
+###############################################################################
+# Helper Functions #
+###############################################################################
+
+
+################################################################################
+#
+# Processes any command line arguments.
+#
+################################################################################
+sub process_command_line
+{
+ my $n = 0;
+
+ while ( $n < @ARGV )
+ {
+ $_ = $ARGV[$n];
+ chomp($_);
+
+ if (/^-h$/i || /^--h$/i || /^-help$/i || /^--help$/i)
+ {
+ print "start_occ_simics.pl [options] [binary .out file]\n\n";
+ print "Based on your \$HOME/.occ_simics_config and passed in arguments, it will start\n";
+ print "a simics session. The parameters in the EXAMPLE_.occ_simics_config file:\n";
+ print "\tSIMICS_WORKSPACE: Path to simics workspace\n";
+ print "\tDEFAULT_TARGET: Target you wish you to use in the target directory under simics-workspace\n";
+ print "\tDEFAULT_BINARY: Binary value to use like occ.out\n";
+ print "\tPATH: Paths to check when looking for target/binary files. Checked recursively\n";
+ print "\tCOMMAND: Comands to run immediately when starting simics. Can add directories, set output-radix, etc\n";
+ print "\n";
+ print "Arguments to start_occ_simics.pl\n";
+ print "-t Modifies the target\n";
+ print "-g Automatically enables GDB\n";
+ print "-v Verbose option\n";
+ print "\n";
+ exit 0;
+ }
+ elsif(/^-t$/i || /^--target$/i)
+ {
+ $target = $ARGV[$n + 1] or die "Bad command line variable: expecting a target\n";
+ $n++;
+ }
+ elsif(/\.out/)
+ {
+ $binary_file = $ARGV[$n];
+ }
+ elsif(/^-g$/i)
+ {
+ $use_gdb = 1;
+ }
+ elsif(/^-v/)
+ {
+ $verbose = 1;
+ }
+ else
+ {
+ print ("Unrecognized command: $_ \n");
+ print ("To view all the options and help text run \'start_simics -h\' \n");
+ exit 1;
+ }
+
+ $n++;
+ }
+}
+
+################################################################################
+#
+# Parses the configuration file located at $configuration_file
+#
+################################################################################
+sub read_configuration_file
+{
+
+ open(CONFIG_FILE, "$configuration_file") || warn "Could not read $configuration_file\n";
+
+
+ while(<CONFIG_FILE>)
+ {
+ #print $_;
+ if(/^SIMICS_WORKSPACE\s*=\s*(\/.*)/)
+ {
+ $simics_workspace = $1;
+ chomp $simics_workspace;
+
+ my $last_char = substr $simics_workspace,-1,1;
+ if($last_char ne '/')
+ {
+ $simics_workspace .= "/";
+ }
+ }
+ elsif(/^PATH\s*=\s*(\/.*)/)
+ {
+ my $path = $1;
+ chomp $path;
+
+ my $last_char = substr $path,-1,1;
+ if($last_char ne '/')
+ {
+ $path .= "/";
+ }
+
+ push @search_paths, $path;
+ }
+ elsif(/^DEFAULT_TARGET\s*=\s*(\/.*)/)
+ {
+ $target = $1;
+ chomp $target;
+ }
+ elsif(/^DEFAULT_BINARY\s*=\s*(\/.*)/)
+ {
+ $binary_file = $1;
+ chomp $binary_file;
+ }
+ elsif(/^COMMAND\s*=\s*(.*)/)
+ {
+ my $tmp_cmd = $1;
+ chomp $tmp_cmd;
+ #print "Saw $tmp_cmd\n";
+ $commands .= $1 . ";";
+ }
+ }
+
+ close(CONFIG_FILE);
+}
+
+
+
+################################################################################
+#
+# Finds the full path for a passed in file using @search_paths
+#
+################################################################################
+sub find_full_path
+{
+ my $arg = shift;
+
+ # If $arg starts with "/" assume we were given the full path
+ if($arg =~ /^\//)
+ {
+ # Do nothing
+ }
+ else
+ {
+ my $entry_found = 0;
+
+ foreach my $path (@search_paths)
+ {
+ # Need to find the file based off either our $cur_dir or $simics_workspace
+ my @output = `find $path 2>&1 | grep $arg `;
+ foreach my $entry (@output)
+ {
+ chomp $entry;
+ if($entry =~ /$arg$/)
+ {
+ $arg = $entry; # $arg now has the full path
+ $entry_found = 1;
+ last;
+ }
+ }
+
+ if($entry_found)
+ {
+ last;
+ }
+ }
+
+ $entry_found or die "Could not find $arg";
+ }
+
+ return $arg;
+}
diff --git a/src/occ/tools/trexStringFile b/src/occ/tools/trexStringFile
new file mode 100755
index 0000000..9cbf2db
--- /dev/null
+++ b/src/occ/tools/trexStringFile
@@ -0,0 +1,12 @@
+#FSP_TRACE_v2|||6/17/2010|||BUILD:OCC 1
+761415651||Trace buffers initialized||
+959803951||timer_routine loop %d||
+2017357799||PRCD Thread||
+3219055108||Main Thread||
+1049182497||timer: New maximum time of %d ticks (10 ticks = 6 ns?)||
+459971656||Procedure Number: %d completed||
+4171193265||First Critical Timer Tick||
+2775191224||>>PRCD_update_procedures||
+26695188||Exit: PRCD_update_procedures||
+481443942||PRCD Submit %d||
+
diff --git a/src/occ/trac/trac.h b/src/occ/trac/trac.h
new file mode 100755
index 0000000..8c9081d
--- /dev/null
+++ b/src/occ/trac/trac.h
@@ -0,0 +1,298 @@
+/******************************************************************************
+// @file trac.h
+// @brief OCC trace defines
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section trac.h TRAC.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb002 pbavari 08/26/2011 Created
+ * @01 tapiar 08/29/2011 fix trac_inf and trac_imp
+ * @th002 thallet 09/19/2011 Added ifdef to strip strings from
+ * compile.
+ * @pb009 pbavari 10/20/2011 Added TRAC_DBG
+ * @rc001 rickylie 12/30/2011 Added <compNm>_DEBUG
+ * @pb00C pbavari 01/20/2012 Fixed SNR_DBG for the else part
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00c thallet 04/19/2012 Added cent debug
+ * @th013 thallet 07/24/2012 Minor changes for VPO/HW compile
+ * @at009 859308 alvinwan 10/15/2012 Added tracepp support
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#ifndef _trac_h
+#define _trac_h
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <trac_interface.h>
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#ifndef NO_TRAC_STRINGS
+
+#define ERR_MRK "ERR: "
+#define INFO_MRK "INF: "
+#define IMP_MRK "IMP: "
+#define DBG_MRK "DBG: "
+
+//NOTE: TRAC_ERR must be used for tracing error related information only
+// TRAC_IMP must be used for tracing important OCC state/status that
+// changes once or twice OCC lifetime. It must NOT be used
+// for tracing anything that seems important to particular
+// developer. This trace buffer must not wrap so use it with
+// caution.
+// TRAC_INFO must be used for anything that does not fall under
+// TRAC_ERR or TRAC_IMP. Any debug or informational traces.
+// TRAC_DBG must be used for debug purpose only. This traces will be
+// turned OFF with product code.
+#ifdef TRAC_TO_SIMICS
+#define TRAC_ERR(frmt,args...) \
+ printf(ERR_MRK "%s: "frmt "\n",__FUNCTION__,##args)
+#define TRAC_INFO(frmt,args...) \
+ printf(INFO_MRK "%s: "frmt "\n",__FUNCTION__,##args)
+#define TRAC_IMP(frmt,args...) \
+ printf(IMP_MRK "%s: "frmt "\n",__FUNCTION__,##args)
+
+#define DBG_PRINT(fmt,args...) \
+ printf(DBG_MRK "%s: "fmt "\n",__FUNCTION__,##args)
+
+extern void dumpHexString(const void *i_data, const unsigned int len, const char *string);
+#define DEBUG_HEXDUMP(data, len, string) \
+ dumpHexString(data, len, string)
+//TODO: Do we want to have one buffer for tracing binary
+
+#else //TRAC_TO_SIMICS
+
+// @at009a - start
+#define TRAC_ERR(frmt,args...) \
+ TRACE(g_trac_err,ERR_MRK frmt,##args)
+#define TRAC_INFO(frmt,args...) \
+ TRACE(g_trac_inf,INFO_MRK frmt,##args)
+#define TRAC_IMP(frmt,args...) \
+ TRACE(g_trac_imp,IMP_MRK frmt,##args)
+#define DBG_PRINT(fmt,args...) \
+ TRACE(g_trac_inf,DBG_MRK fmt,##args)
+#define DEBUG_HEXDUMP(data, len, string) \
+ TRACEBIN(g_trac_inf, string, data,len)
+
+// @at009a - end
+#endif //TRAC_TO_SIMICS
+
+
+//<@rc001a @at009c
+#ifdef MAIN_DEBUG
+ #define MAIN_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define MAIN_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define MAIN_DBG(frmt,args...)
+ #define MAIN_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef RTLS_DEBUG
+ #define RTLS_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define RTLS_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define RTLS_DBG(frmt,args...)
+ #define RTLS_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef PROC_DEBUG
+ #define PROC_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define PROC_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define PROC_DBG(frmt,args...)
+ #define PROC_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef CENT_DEBUG
+ #define CENT_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define CENT_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define CENT_DBG(frmt,args...)
+ #define CENT_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef THRD_DEBUG
+ #define THRD_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define THRD_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define THRD_DBG(frmt,args...)
+ #define THRD_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef AMEC_DEBUG
+ #define AMEC_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define AMEC_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define AMEC_DBG(frmt,args...)
+ #define AMEC_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef APLT_DEBUG
+ #define APLT_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define APLT_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define APLT_DBG(frmt,args...)
+ #define APLT_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef DCOM_DEBUG
+ #define DCOM_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define DCOM_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define DCOM_DBG(frmt,args...)
+ #define DCOM_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef ERRL_DEBUG
+ #define ERRL_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define ERRL_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define ERRL_DBG(frmt,args...)
+ #define ERRL_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef APSS_DEBUG
+ #define APSS_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define APSS_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define APSS_DBG(frmt,args...)
+ #define APSS_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef DPSS_DEBUG
+ #define DPSS_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define DPSS_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define DPSS_DBG(frmt,args...)
+ #define DPSS_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef CMDH_DEBUG
+ #define CMDH_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define CMDH_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define CMDH_DBG(frmt,args...)
+ #define CMDH_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef SNSR_DEBUG
+ #define SNSR_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define SNSR_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define SNSR_DBG(frmt,args...)
+ #define SNSR_DBG_HEXDUMP(data, len, string)
+#endif
+
+#ifdef TMER_DEBUG
+ #define TMER_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define TMER_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define TMER_DBG(frmt,args...)
+ #define TMER_DBG_HEXDUMP(data, len, string)
+#endif
+//>@rc001a @at009c
+
+#else // NO_TRAC_STRINGS
+
+#define TRAC_ERR(frmt,args...)
+#define TRAC_INFO(frmt,args...)
+#define TRAC_IMP(frmt,args...)
+
+//<@rc001a @at009c
+#define MAIN_DBG(frmt,args...)
+#define RTLS_DBG(frmt,args...)
+#define PROC_DBG(frmt,args...)
+#define THRD_DBG(frmt,args...)
+#define AMEC_DBG(frmt,args...)
+#define APLT_DBG(frmt,args...)
+#define DCOM_DBG(frmt,args...)
+#define ERRL_DBG(frmt,args...)
+#define CENT_DBG(frmt,args...)
+#define CMDH_DBG(frmt,args...)
+#define APSS_DBG(frmt,args...)
+#define DPSS_DBG(frmt,args...)
+#define SNSR_DBG(frmt,args...)
+#define TMER_DBG(frmt,args...)
+
+#define MAIN_DBG_HEXDUMP(frmt,args...)
+#define RTLS_DBG_HEXDUMP(frmt,args...)
+#define PROC_DBG_HEXDUMP(frmt,args...)
+#define THRD_DBG_HEXDUMP(frmt,args...)
+#define AMEC_DBG_HEXDUMP(frmt,args...)
+#define APLT_DBG_HEXDUMP(frmt,args...)
+#define DCOM_DBG_HEXDUMP(frmt,args...)
+#define ERRL_DBG_HEXDUMP(frmt,args...)
+#define CENT_DBG_HEXDUMP(frmt,args...)
+#define CMDH_DBG_HEXDUMP(frmt,args...)
+#define APSS_DBG_HEXDUMP(frmt,args...)
+#define DPSS_DBG_HEXDUMP(frmt,args...)
+#define SNSR_DBG_HEXDUMP(frmt,args...)
+#define TMER_DBG_HEXDUMP(frmt,args...)
+
+
+//>@rc001a @at009c
+
+#endif
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif // _trac_h
+
+
diff --git a/src/occ/trac/trac_interface.c b/src/occ/trac/trac_interface.c
new file mode 100755
index 0000000..112c17a
--- /dev/null
+++ b/src/occ/trac/trac_interface.c
@@ -0,0 +1,1207 @@
+/******************************************************************************
+// @file trac_interface.c
+// @brief Interface codes for TRAC component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _trac_interface_c trac_interface.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 06/16/2010 Port
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @at009 859308 alvinwan 10/15/2012 Added tracepp support
+ * @ai005 860268 ailutsar 11/20/2012 Create trace test applet
+ * @nh004 864941 neilhsu 12/20/2012 Support get/delete errl & added trace info
+ * @rc005 864101 rickylie 12/12/2012 add small circ buffer to handle ISR semaphore conflict
+ * @at011 866759 alvinwan 01/15/2013 Fix OCC trexStringFile and trace
+ * @at012 868019 alvinwan 01/25/2014 TRAC_get_buffer_partial() can result in TLB Miss Exception
+ * @sbte0 916280 sbroyles 02/27/2014 Trace buffer fencing
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+
+#include <trac_interface.h>
+#include <trac_service_codes.h>
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <comp_ids.h>
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define TRAC_END_BUFFER "&"
+
+#define TRAC_INTF_MUTEX_TIMEOUT SSX_SECONDS(5)
+
+#define TRACE_BUF_VERSION 0x01; /*!< Trace buffer version */
+#define TRACE_FIELDTRACE 0x4654; /*!< Field Trace - "FT" */
+#define TRACE_FIELDBIN 0x4644 /*!< Binary Field Trace - "FD" */
+
+#define TRAC_TIME_REAL 0 // upper 32 = seconds, lower 32 = microseconds
+#define TRAC_TIME_50MHZ 1
+#define TRAC_TIME_200MHZ 2
+#define TRAC_TIME_167MHZ 3 // 166666667Hz
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// @at009c - start
+
+/// Instantiate the buffers for the traces.
+///
+/// There are
+/// It may be beneficial to add the attribute:
+/// __attribute__ ((section (".noncacheable")))
+/// when debugging on real HW, in case the OCC hangs and we can't access
+/// the cache to get coherent data.
+uint8_t g_trac_inf_buffer[TRACE_BUFFER_SIZE];
+uint8_t g_trac_err_buffer[TRACE_BUFFER_SIZE];
+uint8_t g_trac_imp_buffer[TRACE_BUFFER_SIZE];
+
+// Need to modify the addTraceToErrl() function in errl.c when new trace buffer is added/removed
+tracDesc_t g_trac_inf = (tracDesc_t) &g_trac_inf_buffer;
+tracDesc_t g_trac_err = (tracDesc_t) &g_trac_err_buffer;
+tracDesc_t g_trac_imp = (tracDesc_t) &g_trac_imp_buffer;
+
+const trace_descriptor_array_t g_des_array[] =
+{
+ {&g_trac_inf,"INF"},
+ {&g_trac_err,"ERR"},
+ {&g_trac_imp,"IMP"}
+};
+// @at009c - end
+
+SsxSemaphore g_trac_mutex;
+
+// @rc005a - start
+static bool circular_full_flag = FALSE;
+circular_buf_header_t g_isr_circular_header;
+circular_entire_data_t g_isr_circular_buf[CIRCULAR_BUFFER_SIZE];
+// @rc005a - end
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+/**
+ * @brief Initialize all header values of a trace buffer
+ *
+ * This function will initialize all of the values in the trace buffer
+ * header so that it is ready for tracing.
+ *
+ * @param o_buf Pointer to trace buffer which will be initialized.
+ * @param i_comp Component who is getting buffer initialized.
+ *
+ * @return Non-zero return code on error.
+ */
+UINT trac_init_values_buffer(tracDesc_t *o_buf,const CHAR *i_comp);
+
+
+ /**
+ * @brief Raw buffer write function
+ *
+ * This function assumes i_td has been initialized and it also assume
+ * the critical region of the input trace descriptor has been locked.
+ *
+ * @param io_td Intialized trace descriptor point to buffer to trace to.
+ * @param i_ptr Pointer to data to write to trace buffer
+ * @param i_size Size of i_ptr
+ *
+ * @return Non-zero return code on error.
+ */
+UINT trac_write_data(tracDesc_t io_td,
+ const void *i_ptr,
+ const ULONG i_size);
+
+// @rc005a - start
+ /**
+ * @brief Raw buffer write function
+ *
+ *
+ * @param i_ptr
+ *
+ * @return Non-zero return code on error.
+ */
+uint16_t trac_write_data_to_circular(circular_entire_data_t *i_ptr);
+
+
+ /**
+ * @brief Raw buffer write function
+ *
+ *
+ * @param o_ptr
+ *
+ * @return Non-zero return code on error.
+ */
+uint16_t get_trac_entry_data_from_circular(circular_entire_data_t *o_ptr);
+// @rc005a - end
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: TRAC_init_buffers
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+UINT TRAC_init_buffers()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ INT l_rc = 0;
+ UINT l_num_des = 0;
+ UINT i=0;
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+
+ // Initialize trace mutex
+ l_rc = ssx_semaphore_create(&g_trac_mutex, 1, 1);
+
+ if(SSX_OK != l_rc)
+ {
+ // Badness, don't continue
+ FIELD("TRAC_init_buffers: Failed to create mutex");
+ }
+ else
+ {
+ // Initialize trace buffers
+ l_num_des = sizeof(g_des_array) / sizeof(trace_descriptor_array_t);
+
+ for(i=0;i<l_num_des;i++)
+ {
+ // Initialize the buffer
+ l_rc = trac_init_values_buffer(g_des_array[i].entry,
+ g_des_array[i].comp);
+ if(l_rc)
+ {
+ FIELD1("TRAC_init_buffers: Failed to initialize buffer: ",
+ (unsigned char)i);
+ break;
+ }
+ }
+ }
+
+ // @rc005a
+ // Initialize isr circular buffer it to all 0's
+ g_isr_circular_header.head = 0;
+ g_isr_circular_header.tail = 0;
+ g_isr_circular_header.entryCount = 0;
+
+ memset(g_isr_circular_buf, 0 , CIRCULAR_BUFFER_SIZE * sizeof(circular_entire_data_t));
+
+ return(l_rc);
+}
+
+// Function Specification
+//
+// Name: trac_init_values_buffer
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+UINT trac_init_values_buffer(tracDesc_t *o_buf,const CHAR *i_comp)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT16 l_rc = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Initialize it to all 0's
+ memset(*o_buf,0,(size_t)TRACE_BUFFER_SIZE);
+
+ (*o_buf)->ver = TRACE_BUF_VERSION;
+ (*o_buf)->hdr_len = sizeof(trace_buf_head_t);
+ (*o_buf)->time_flg = TRAC_TIME_REAL; // @at009c
+ (*o_buf)->endian_flg = 'B'; // Big Endian
+ memcpy((*o_buf)->comp,i_comp,(size_t)COMP_NAME_SIZE);
+ (*o_buf)->size = TRACE_BUFFER_SIZE;
+ (*o_buf)->times_wrap = 0;
+ (*o_buf)->next_free = sizeof(trace_buf_head_t);
+
+ return(l_rc);
+}
+
+// Function Specification
+//
+// Name: trace_adal_write_all
+//
+// Description: In order to leverage the tracepp, need to add this function. It will call
+// trac_write_int finally
+//
+// Flow: FN=None
+//
+// End Function Specification
+//@at009a
+UINT trace_adal_write_all(tracDesc_t io_td,const trace_hash_val i_hash,
+ const char *i_fmt,const ULONG i_line, const ULONG i_type,...)
+{
+ UINT rc = 0, i = 0;
+ UINT l_num_args = 0;
+ ULONG l_i_param[TRACE_MAX_ARGS] = {0}; // @ai005c
+
+ // Calculate the number of optional parameters by looking at the i_fmt.
+ // i_fmt will store something like "%d,%f,%u"
+ if(i_fmt != NULL)
+ {
+ l_num_args = 1;
+ for(i=0;i_fmt[i] != 0;i++)
+ {
+ if( i_fmt[i] == ',')
+ {
+ l_num_args++;
+ }
+ }
+ }
+
+
+ // Get the optional parameters
+ va_list l_argptr; //will hold optional parameters
+ va_start(l_argptr,i_type);
+
+ // @ai005a
+ // Check the number of optional parameters
+ if(TRACE_MAX_ARGS < l_num_args)
+ {
+ l_num_args = TRACE_MAX_ARGS;
+ }
+
+ for (i=0;i<l_num_args;i++)
+ {
+ l_i_param[i] = va_arg(l_argptr,ULONG);
+ }
+
+ va_end(l_argptr);
+
+
+
+ rc = trac_write_int(io_td,
+ i_hash, i_line,
+ l_num_args,
+ l_i_param[0],
+ l_i_param[1],
+ l_i_param[2],
+ l_i_param[3],
+ l_i_param[4] );
+ return rc;
+}
+
+
+// Function Specification
+//
+// Name: trac_write_int
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+UINT trac_write_int(tracDesc_t io_td,const trace_hash_val i_hash,
+ const ULONG i_line,
+ const UINT i_num_args,
+ const ULONG i_1,const ULONG i_2,const ULONG i_3,
+ const ULONG i_4,const ULONG i_5
+ )
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT l_rc = 0;
+ ULONG l_entry_size = 0;
+ trace_entire_entry_t l_entry;
+ SsxMachineContext l_ctx = 0; // @sbte0
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ if(io_td != NULL)
+ {
+
+ // Calculate total space needed
+ l_entry_size = sizeof(trace_entry_stamp_t);
+ l_entry_size += sizeof(trace_entry_head_t);
+
+ // We always add the size of the entry at the end of the trace entry
+ // so the parsing tool can easily walk the trace buffer stack so we
+ // need to add that on to total size
+ l_entry_size += sizeof(ULONG);
+
+ // Now add on size for acutal number of arguments we're tracing
+ l_entry_size += (i_num_args * sizeof(ULONG));
+
+ // Word align the entry
+ l_entry_size = (l_entry_size + 3) & ~3;
+
+ // Fill in the entry structure
+ //l_entry.stamp.tid = (ULONG)tx_thread_identify(); // What is response to this in AME code?
+ l_entry.stamp.tid = (__ssx_kernel_context_thread() ? 1 : 0); //context thread or ISR
+
+ // Capture the time. Note the time stamp is split into tbh (upper) and
+ // tbl (lower), both of which are 32 bits each. The ssx_timebase_get
+ // call returns a uint64_t
+
+ // @rc005c move
+ // @at009c - start
+ uint64_t l_time = ssx_timebase_get(); // @at011c
+ l_entry.stamp.tbh = l_time / SSX_TIMEBASE_FREQUENCY_HZ; // seconds @at011c
+ l_entry.stamp.tbl = ((l_time % SSX_TIMEBASE_FREQUENCY_HZ)*1000000000) // nanoseconds @at011c
+ /SSX_TIMEBASE_FREQUENCY_HZ;
+ // @at009c - end
+
+ // Length is equal to size of data
+ l_entry.head.length = (i_num_args * sizeof(ULONG));
+ l_entry.head.tag = TRACE_FIELDTRACE;
+ l_entry.head.hash = i_hash;
+ l_entry.head.line = i_line;
+
+ switch (i_num_args)
+ {
+ case 5: l_entry.args[4] = i_5; // Intentional Fall Through ignore BEAM warning
+ case 4: l_entry.args[3] = i_4; // Intentional Fall Through ignore BEAM warning
+ case 3: l_entry.args[2] = i_3; // Intentional Fall Through ignore BEAM warning
+ case 2: l_entry.args[1] = i_2; // Intentional Fall Through ignore BEAM warning
+ case 1: l_entry.args[0] = i_1; // Intentional Fall Through ignore BEAM warning
+ default: ;
+ }
+
+ // Now put total size at end of buffer
+ l_entry.args[i_num_args] = l_entry_size;
+
+ // >> @sbte0 Disable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ // << @sbte0
+
+ // @rc005c - start
+ // Check if context thread or ISR get semaphore or not
+ // If ISR did not get semaphore, will add trace log into circular buffer.
+ // Context thread will check circular buffer, and add log back into trac buffer.
+ // Prevent ISR did not get semaphore, and lost trace log.
+ l_rc = ssx_semaphore_pend(&g_trac_mutex,
+ __ssx_kernel_context_thread()? \
+ TRAC_INTF_MUTEX_TIMEOUT : SSX_NO_WAIT);
+
+ if(l_rc == SSX_OK)
+ {
+ // @sbte0 Either this is thread context and mutex was locked within
+ // timeout or this is interrupt context and mutex was immediately
+ // available, regardless, mutex is now locked.
+ l_rc = SUCCESS;
+
+ // Update the entry count
+ io_td->te_count++;
+
+ l_rc = trac_write_data(io_td, (void *)&l_entry, l_entry_size);
+
+ if(l_rc != SUCCESS)
+ {
+ // Badness - Not much we can do on trace failure. Can't log error
+ // because of recursion concerns. Luckily a trace error is not critical.
+ FIELD("trac_write_int: Failed in call to trac_write_data()");
+ }
+
+ // Always try to release even if error above
+ ssx_semaphore_post(&g_trac_mutex);
+ }
+ else if(!__ssx_kernel_context_thread())
+ {
+ // @sbte0 Tracing in interrupt context and mutex was locked, SSX
+ // returned -SSX_SEMAPHORE_PEND_NO_WAIT
+
+ // Failed to get semaphore in ISR
+ // Create trace in ISR circular buffer
+ circular_entire_data_t l_cir_data_in;
+ l_cir_data_in.len = l_entry_size;
+ memcpy(&l_cir_data_in.comp, io_td->comp, (size_t)COMP_NAME_SIZE);
+ l_cir_data_in.entry = l_entry;
+
+ if(g_isr_circular_header.entryCount >= CIRCULAR_BUFFER_SIZE)
+ {
+ FIELD("trac_write_int: Circular Buffer size insufficient!\n");
+ circular_full_flag = TRUE;
+ l_rc = TRAC_CIRCULAR_BUFF_FULL;
+ // Always try to release even if error above
+ ssx_semaphore_post(&g_trac_mutex);
+ return(l_rc);
+ }
+
+ // Save to Circular Buffer
+ l_rc = trac_write_data_to_circular(&l_cir_data_in);
+ g_isr_circular_header.head = (++g_isr_circular_header.head) % CIRCULAR_BUFFER_SIZE;
+ g_isr_circular_header.entryCount++;
+
+ if(l_rc != SUCCESS)
+ {
+ // Badness - Not much we can do on trace failure. Can't log error
+ // because of recursion concerns. Luckily a trace error is not critical.
+ FIELD("trac_write_int: Failed in call to trac_write_data_to_circular()");
+ }
+ }
+ else
+ {
+ // Failed to get mutex in thread
+ FIELD("trac_write_int: Failed to get mutex");
+ }
+ // @rc005c - end
+
+ // >> @sbte0 Re-enable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_exit(&l_ctx);
+ // << @sbte0
+
+
+ // @rc005a - start
+ //2nd. Check caller from thread?
+ if(__ssx_kernel_context_thread() && (g_isr_circular_header.entryCount > 0))
+ {
+ if(circular_full_flag)
+ {
+ // If ISR circular buffer is full, create a trace in IMP
+ // Use existed trace structure to create new trace
+
+ // re-calculate size of the new trace entry
+ l_entry_size = l_entry_size + ((1 - i_num_args)*4);
+
+ // fill trace field
+ l_entry.head.hash = trace_adal_hash("IMP: ISR Circular Buffer is full, %d entries losted", -1);
+ l_entry.head.line = __LINE__;
+
+ // one argment for this trace
+ l_entry.head.length = sizeof(ULONG);
+ l_entry.args[0] = circular_full_flag;
+ l_entry.args[1] = l_entry_size;
+
+ // >> @sbte0 Disable non-critical interrupts in thread context
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ // << @sbte0
+
+ //Write to IMP trace buffer
+ l_rc = ssx_semaphore_pend(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT);
+ if(l_rc == SSX_OK)
+ {
+ tracDesc_t imp_td = TRAC_get_td("IMP");
+ // Update the entry count
+ imp_td->te_count++;
+
+ l_rc = trac_write_data(imp_td, (void *)&l_entry, l_entry_size);
+ if(l_rc != SUCCESS)
+ {
+ // Badness - Not much we can do on trace failure. Can't log error
+ // because of recursion concerns. Luckily a trace error is not critical.
+ FIELD("trac_write_int: Failed in call to trac_write_data()");
+ }
+ ssx_semaphore_post(&g_trac_mutex);
+ }
+ else
+ {
+ // Failed to get mutex in thread
+ FIELD("trac_write_int: Failed to get mutex");
+ }
+
+ // >> @sbte0 Re-enable non-critical interrupts
+ ssx_critical_section_exit(&l_ctx);
+ // << @sbte0
+
+ // Reset full flag
+ circular_full_flag = FALSE;
+ l_rc = TRAC_CIRCULAR_BUFF_FULL;
+ }
+
+ circular_entire_data_t l_cir_data_out;
+
+ do
+ {
+ // >> @sbte0 Thread context here, disable non-critical
+ // interrupts while unloading circular buffer
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ // << @sbte0
+
+ // Get tail position
+ g_isr_circular_header.tail = g_isr_circular_header.tail % CIRCULAR_BUFFER_SIZE;
+ //Copy One trace entity from circular buffer
+ get_trac_entry_data_from_circular(&l_cir_data_out);
+
+ //Write to trace buffer
+ l_rc = ssx_semaphore_pend(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT);
+ if(l_rc == SSX_OK)
+ {
+ tracDesc_t i_td = TRAC_get_td((const char *)l_cir_data_out.comp);
+
+ // Update the entry count
+ i_td->te_count++;
+
+ l_rc = trac_write_data(i_td,
+ (const void *)&l_cir_data_out.entry,
+ (const ULONG)l_cir_data_out.len);
+
+ if(l_rc == SUCCESS)
+ {
+ if(g_isr_circular_header.tail == g_isr_circular_header.head )
+ g_isr_circular_header.entryCount = 0;
+ else
+ {
+ g_isr_circular_header.tail++;
+ g_isr_circular_header.entryCount--;
+ }
+ }
+ else
+ {
+ // Badness - Not much we can do on trace failure. Can't log error
+ // because of recursion concerns. Luckily a trace error is not critical.
+ FIELD("trac_write_int: Failed in call to trac_write_data()");
+ }
+
+ ssx_semaphore_post(&g_trac_mutex);
+ }
+ else
+ {
+ // Failed to get mutex in thread
+ FIELD("trac_write_int: Failed to get mutex");
+ }
+ // >> @sbte0 Re-enable non-critical interrupts
+ ssx_critical_section_exit(&l_ctx);
+ // << @sbte0
+ }
+ while(g_isr_circular_header.entryCount > 0);
+ }
+ // @rc005a - end
+ }
+ else
+ {
+ l_rc = TRAC_INVALID_PARM;
+ FIELD("trac_write_int: User passed invalid parameter");
+ }
+
+ return(l_rc);
+}
+
+
+// Function Specification
+//
+// Name: trac_write_bin
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+UINT trac_write_bin(tracDesc_t io_td,const trace_hash_val i_hash,
+ const ULONG i_line,
+ const void *i_ptr,
+ const ULONG i_size)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT l_rc = 0;
+ ULONG l_entry_size = 0;
+ trace_bin_entry_t l_entry;
+ SsxMachineContext l_ctx = 0; // @sbte0
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ if((io_td == NULL) || (i_ptr == NULL) || (i_size == 0))
+ {
+ l_rc = TRAC_INVALID_PARM;
+ }
+ else
+ {
+ // Calculate total space needed
+ l_entry_size = sizeof(trace_entry_stamp_t);
+ l_entry_size += sizeof(trace_entry_head_t);
+
+ // We always add the size of the entry at the end of the trace entry
+ // so the parsing tool can easily walk the trace buffer stack so we
+ // need to add that on to total size
+ l_entry_size += sizeof(ULONG);
+
+ // Now add on size for acutal size of the binary data
+ l_entry_size += i_size;
+
+ // Word align the entry
+ l_entry_size = (l_entry_size + 3) & ~3;
+
+ // Fill in the entry structure
+ //l_entry.stamp.tid = (ULONG)tx_thread_identify(); // What is response to this in AME code?
+ l_entry.stamp.tid = 0; // What is response to this in AME code?
+
+ // Length is equal to size of data
+ l_entry.head.length = i_size;
+ l_entry.head.tag = TRACE_FIELDBIN;
+ l_entry.head.hash = i_hash;
+ l_entry.head.line = i_line;
+
+ // We now have total size and need to reserve a part of the trace
+ // buffer for this
+
+ // CRITICAL REGION START
+ // >> @sbte0 Disable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ // << @sbte0
+
+ l_rc = ssx_semaphore_pend(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT);
+
+ if(l_rc != SSX_OK)
+ {
+ // Badness
+ FIELD("trac_write_bin: Failed to get mutex");
+ }
+ else
+ {
+ // Capture the time. Note the time stamp is split into tbh (upper) and
+ // tbl (lower), both of which are 32 bits each. The ssx_timebase_get
+ // call returns a uint64_t
+
+ // @at009c - start
+ uint64_t l_time = ssx_timebase_get(); // @at011c
+ l_entry.stamp.tbh = l_time / SSX_TIMEBASE_FREQUENCY_HZ; // seconds @at011c
+ l_entry.stamp.tbl = ((l_time % SSX_TIMEBASE_FREQUENCY_HZ)*1000000000) // nanoseconds @at011c
+ /SSX_TIMEBASE_FREQUENCY_HZ;
+ // @at009c - end
+
+ // Increment trace counter
+ io_td->te_count++;;
+
+ // First write the header
+ l_rc = trac_write_data(io_td,
+ (void *)&l_entry,
+ sizeof(l_entry));
+ do
+ {
+ if(l_rc != SUCCESS)
+ {
+ // Badness - Not much we can do on trace failure. Can't log error
+ // because of recursion concerns. Luckily a trace error is not critical.
+ FIELD("trac_write_bin: Failed in call to trac_write_data - 1()");
+ break;
+ }
+
+ // Now write the actual binary data
+ l_rc = trac_write_data(io_td,
+ i_ptr,
+ i_size);
+ if(l_rc != SUCCESS)
+ {
+ // Badness - Not much we can do on trace failure. Can't log error
+ // because of recursion concerns. Luckily a trace error is not critical.
+ FIELD("trac_write_bin: Failed in call to trac_write_data - 2()");
+ break;
+ }
+
+ // Now write the size at the end
+ l_rc = trac_write_data(io_td,
+ (void *)&l_entry_size,
+ sizeof(l_entry_size));
+ if(l_rc != SUCCESS)
+ {
+ // Badness - Not much we can do on trace failure. Can't log error
+ // because of recursion concerns. Luckily a trace error is not critical.
+ FIELD("trac_write_bin: Failed in call to trac_write_data - 3()");
+ break;
+ }
+ }
+ while(FALSE);
+
+ ssx_semaphore_post(&g_trac_mutex);
+ // >> @sbte0 Re-enable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_exit(&l_ctx);
+ // << @sbte0
+ }
+ // CRITICAL REGION END
+ }
+
+ return(l_rc);
+}
+
+// Function Specification
+//
+// Name: trac_write_data
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+UINT trac_write_data(tracDesc_t io_td,
+ const void *i_ptr,
+ const ULONG i_size)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT l_rc = 0;
+ ULONG l_total_size = i_size;
+ void *l_buf_ptr = NULL;
+ ULONG l_offset = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+
+ if(i_size > TRACE_BUFFER_SIZE)
+ {
+ FIELD("trac_write_data: Input size to large!");
+ l_rc = TRAC_DATA_SIZE_TO_LARGE;
+ break;
+ }
+
+ if((io_td->next_free + l_total_size) > TRACE_BUFFER_SIZE)
+ {
+ // copy what we can to end
+ l_buf_ptr = (char *)io_td + io_td->next_free;
+ l_buf_ptr = (void *) ( ((ULONG) l_buf_ptr + 3) & ~3);
+ l_offset = TRACE_BUFFER_SIZE-io_td->next_free;
+ memcpy(l_buf_ptr,i_ptr,(size_t)l_offset);
+
+ l_total_size -= l_offset;
+
+ // Now adjust the main header of buffer
+ io_td->times_wrap++;
+ io_td->next_free = io_td->hdr_len;
+ }
+
+ l_buf_ptr = (char *)io_td + io_td->next_free;
+
+ // Word align the write - total size includes this allignment
+ l_buf_ptr = (void *) ( ((ULONG) l_buf_ptr + 3) & ~3);
+
+ memcpy(l_buf_ptr,(char *)i_ptr + l_offset,l_total_size);
+
+ // Make sure size is correct for word allignment
+ // Note that this works with binary trace because only the binary data
+ // has the potential to be un-word aligned. If two parts of the binary
+ // trace had this problem then this code would not work.
+ l_total_size = (l_total_size + 3) & ~3;
+ io_td->next_free += l_total_size;
+
+ }while(FALSE);
+
+ return(l_rc);
+
+}
+
+// Function Specification
+//
+// Name: TRAC_get_td
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+tracDesc_t TRAC_get_td(const char *i_comp)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT l_num_des = 0;
+ UINT i=0;
+ tracDesc_t l_td = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ l_num_des = sizeof(g_des_array) / sizeof(trace_descriptor_array_t);
+
+ for(i=0;i<l_num_des;i++)
+ {
+ if(memcmp(i_comp,(*(g_des_array[i].entry))->comp,(size_t)COMP_NAME_SIZE) == 0)
+ {
+ // Found the component
+ l_td = *g_des_array[i].entry;
+ break;
+ }
+ }
+
+ return(l_td);
+}
+
+// Function Specification
+//
+// Name: TRAC_get_buffer
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+UINT TRAC_get_buffer(const tracDesc_t i_td_ptr,
+ void *o_data)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT l_rc = 0;
+ SsxMachineContext l_ctx = 0; // @sbte0
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ if((i_td_ptr) && (o_data != NULL))
+ {
+ // >> @sbte0 Disable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ // << @sbte0
+
+ // Get the lock
+ l_rc = ssx_semaphore_pend(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT);
+ if(l_rc != SSX_OK)
+ {
+ // Badness
+ FIELD("TRAC_get_buffer: Failed to get mutex");
+ }
+ else
+ {
+ l_rc = SUCCESS;
+
+ // @at009a -start
+ // Copy it's buffer into temp one
+ memcpy(o_data,i_td_ptr,(size_t)TRACE_BUFFER_SIZE);
+
+ // Always try to release even if error above
+ ssx_semaphore_post(&g_trac_mutex);
+ // @at009a -end
+
+ // >> @sbte0 Re-enable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_exit(&l_ctx);
+ // << @sbte0
+ }
+ }
+ else
+ {
+ FIELD("TRAC_get_buffer: Invalid parameter passed by caller");
+ l_rc = TRAC_INVALID_PARM;
+ }
+
+ return(l_rc);
+}
+
+// Function Specification
+//
+// Name: TRAC_get_buffer_partial
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+UINT TRAC_get_buffer_partial(const tracDesc_t i_td_ptr,
+ void *io_data,
+ UINT *io_size)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT l_rc = 0;
+ char *l_full_buf = NULL;
+ tracDesc_t l_head = NULL;
+ UINT l_part_size = 0;
+ bool l_lock_get = FALSE; // @at009a
+ SsxMachineContext l_ctx = 0; // @sbte0
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ if((i_td_ptr == NULL) || (io_data == NULL) || (io_size == NULL))
+ {
+ FIELD("TRAC_get_buffer_partial: Invalid parameter passed by caller");
+ l_rc = TRAC_INVALID_PARM;
+ if(io_size != NULL)
+ {
+ *io_size = 0;
+ }
+ break;
+ }
+
+ // We can't even fit in first part of buffer
+ // Make sure data size is larger than header length
+ // Otherwise, we will be accessing beyond memory
+ if(*io_size < sizeof(trace_buf_head_t))
+ {
+ // Need to at least have enough space for the header
+ FIELD("TRAC_get_buffer_partial: *io_size to small");
+ l_rc = TRAC_DATA_SIZE_LESS_THAN_HEADER_SIZE; // @ai005c
+ *io_size = 0;
+ break;
+ }
+
+ // CRITICAL REGION START
+ // >> @sbte0 Disable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ // << @sbte0
+
+ // Get the lock
+ l_rc = ssx_semaphore_pend(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT); // @at009a
+ if(l_rc != SSX_OK) // @at009a
+ {
+ // Badness
+ FIELD("TRAC_get_buffer_partial: Failed to get mutex");
+ }
+ else
+ {
+ // Now that we have full buffer, adjust it to be requested size
+ memset(io_data,0,(size_t)*io_size);
+
+ l_lock_get = TRUE; // @at009a
+ l_full_buf = (char*)i_td_ptr; // @at009a
+ if(*io_size >= TRACE_BUFFER_SIZE)
+ {
+ // It fits
+ *io_size = TRACE_BUFFER_SIZE;
+ memcpy(io_data,l_full_buf,(size_t)*io_size);
+ break;
+ }
+
+ // copy the header of the trace buffer to io_data
+ l_head = (tracDesc_t)l_full_buf;
+ memcpy(io_data,l_full_buf,(size_t)(l_head->hdr_len));
+
+ // Reuse the l_head to point to the io_data and fill in the data
+ l_head = (tracDesc_t)io_data;
+ // @nh004d
+
+ if((l_head->next_free == l_head->hdr_len) && (l_head->times_wrap == 0))
+ {
+ // No data in buffer so just return what we have
+ *io_size = 0; // @nh004a
+ break;
+ }
+
+ if(l_head->next_free > *io_size)
+ {
+ // @ai005d remove duplcate case
+
+ l_part_size = *io_size - l_head->hdr_len;
+
+ memcpy((UCHAR *)io_data+l_head->hdr_len,
+ l_full_buf+l_head->next_free-l_part_size,
+ (size_t)l_part_size);
+
+ // We don't need to update *io_size, all data copied.
+ l_head->size = *io_size; // @nh004a
+
+ // Set pointer at beginning because this will be a
+ // "just wrapped" buffer.
+ l_head->next_free = l_head->hdr_len;
+
+ // Buffer is now wrapped because we copied max data into it.
+ if(!l_head->times_wrap)
+ {
+ l_head->times_wrap = 1;
+ }
+ }
+ else
+ {
+ // First part of buffer fits fine
+ memcpy((UCHAR *)io_data+l_head->hdr_len,
+ l_full_buf+l_head->hdr_len,
+ (size_t)(l_head->next_free - l_head->hdr_len));
+
+
+ // If it's wrapped then pick up some more data
+ if(l_head->times_wrap)
+ {
+ // Figure out how much room we have left
+ l_part_size = *io_size - l_head->next_free;
+
+ memcpy((UCHAR *)io_data+l_head->next_free,
+ l_full_buf+TRACE_BUFFER_SIZE-l_part_size,
+ (size_t)l_part_size);
+
+ // We don't need to update *io_size, all data copied.
+ l_head->size = *io_size; // @nh004a
+ }
+ else
+ {
+ // Update copied lens which is what we have in trace buf
+ l_head->size = l_head->next_free; // @nh004c
+ *io_size = l_head->next_free; // @nh004c
+ }
+ }
+ }
+ // CRITICAL REGION END
+ }
+ while(FALSE);
+
+ // @at009a - start
+ // Always try to release even if error above
+ if(l_lock_get)
+ {
+ ssx_semaphore_post(&g_trac_mutex);
+ // >> @sbte0 Re-enable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_exit(&l_ctx);
+ // << @sbte0
+ }
+ // @at009a - end
+
+ return(l_rc);
+}
+
+// Function Specification
+//
+// Name: TRAC_reset_buf
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+UINT TRAC_reset_buf()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ UINT l_rc = 0;
+ UINT l_num_des = 0;
+ UINT i=0;
+ SsxMachineContext l_ctx = 0; // @sbte0
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // >> @sbte0 Disable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_enter(SSX_NONCRITICAL, &l_ctx);
+ // << @sbte0
+
+ // Get mutex so no one traces
+ l_rc = ssx_semaphore_pend(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT);
+ if(l_rc != SSX_OK)
+ {
+ FIELD("TRAC_reset_buf: Failure trying to get mutex");
+ // Badness
+ }
+ else
+ {
+ l_num_des = sizeof(g_des_array) / sizeof(trace_descriptor_array_t);
+
+ for(i=0;i<l_num_des;i++)
+ {
+ // Initialize the buffer
+ l_rc = trac_init_values_buffer(g_des_array[i].entry,
+ g_des_array[i].comp);
+ if(l_rc)
+ {
+ FIELD("TRAC_reset_buf: Failure in call to trac_init_values_buffer()");
+ break;
+ }
+ }
+ }
+
+ // Always try to release even if fail above
+ ssx_semaphore_post(&g_trac_mutex);
+
+ // >> @sbte0 Re-enable non-critical interrupts if thread context
+ if (__ssx_kernel_context_thread())
+ ssx_critical_section_exit(&l_ctx);
+ // << @sbte0
+
+ return(l_rc);
+}
+
+
+// @rc005a - start
+
+// Function Specification
+//
+// Name: trac_write_data_to_circular
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint16_t trac_write_data_to_circular(circular_entire_data_t *i_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_rc = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ memcpy((void *)&g_isr_circular_buf[g_isr_circular_header.head],
+ (void *)i_ptr,
+ sizeof(circular_entire_data_t));
+
+ return(l_rc);
+}
+
+// Function Specification
+//
+// Name: get_trac_entry_data_from_circular
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint16_t get_trac_entry_data_from_circular(circular_entire_data_t *o_ptr)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_rc = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ memcpy((void *)o_ptr,
+ (void *)&g_isr_circular_buf[g_isr_circular_header.tail],
+ sizeof(circular_entire_data_t));
+
+ return(l_rc);
+}
+
+// @rc005a -end
diff --git a/src/occ/trac/trac_interface.h b/src/occ/trac/trac_interface.h
new file mode 100755
index 0000000..15c5aca
--- /dev/null
+++ b/src/occ/trac/trac_interface.h
@@ -0,0 +1,335 @@
+/******************************************************************************
+// @file trac_interface.h
+// @brief Interface codes for TRAC component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _trac_interface_h trac_interface.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 06/16/2010 Port
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @at009 859308 alvinwan 10/15/2012 Added tracepp support
+ * @ai005 860268 ailutsar 11/20/2012 Create trace test applet
+ * @rc005 864101 rickylie 12/12/2012 add small circ buffer to handle ISR semaphore conflict
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _TRAC_INTERFACE_H
+#define _TRAC_INTERFACE_H
+
+/** \defgroup Trace Trace Component
+ * Port of the trace code used in the fsp and tpmd.
+ */
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+/**
+ * \defgroup TracMacros Trace Component Macro Interfaces
+ * \ingroup Trace
+ * Used to trace 0 - 5 arguments or a binary buffer when using a hash value.
+ */
+/*@{*/
+
+
+// @at009c - start
+#define TRACE(i_td,i_string,args...) \
+ trace_adal_write_all(i_td,trace_adal_hash(i_string,-1),__LINE__,0,##args)
+
+#define TRACEBIN(i_td,i_string,i_ptr,i_size) \
+ trac_write_bin(i_td,trace_adal_hash(i_string,0),__LINE__,i_ptr,i_size)
+
+#ifndef NO_TRAC_STRINGS
+
+#define FIELD(a) \
+ printf("%s",a)
+
+#define FIELD1(a,b) \
+ printf("%s%lx",a,(unsigned long)b)
+
+#else // NO_TRAC_STRINGS
+
+#define FIELD(a)
+
+#define FIELD1(a,b)
+
+#endif // NO_TRAC_STRINGS
+
+#define SUCCESS 0
+// @at009c - end
+
+
+
+/*@}*/
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define TRACE_MAX_ARGS 5 /*!< Maximum number of args to trace */
+
+typedef uint32_t trace_hash_val;
+
+// NOTE! Increment this when new components are added!
+#define TRAC_NUM_TRACE_COMPONENTS 1
+
+
+#define TRACE_BUFFER_SIZE 8192 // @ai005a
+
+#define CIRCULAR_BUFFER_SIZE 4 // @rc005a
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+/*
+ * @brief Structure is put at beginning of all trace buffers
+ */
+typedef struct trace_buf_head {
+ UCHAR ver; /*!< version of this struct (1) */
+ UCHAR hdr_len; /*!< size of this struct in bytes */
+ UCHAR time_flg; /*!< meaning of timestamp entry field */
+ UCHAR endian_flg; /*!< flag for big ('B') or little ('L') endian */
+ CHAR comp[16]; /*!< the buffer name as specified in init call */
+ UINT32 size; /*!< size of buffer, including this struct */
+ UINT32 times_wrap; /*!< how often the buffer wrapped */
+ UINT32 next_free; /*!< offset of the byte behind the latest entry */
+ UINT32 te_count; /*!< Updated each time a trace is done */
+ UINT32 extracted; /*!< Not currently used */
+}trace_buf_head_t;
+
+/*!
+ * @brief Timestamp and thread id for each trace entry.
+ */
+typedef struct trace_entry_stamp {
+ UINT32 tbh; /*!< timestamp upper part */
+ UINT32 tbl; /*!< timestamp lower part */
+ UINT32 tid; /*!< process/thread id */
+}trace_entry_stamp_t;
+
+/*
+ * @brief Structure is used by adal app. layer to fill in trace info.
+ */
+typedef struct trace_entry_head {
+ UINT16 length; /*!< size of trace entry */
+ UINT16 tag; /*!< type of entry: xTRACE xDUMP, (un)packed */
+ UINT32 hash; /*!< a value for the (format) string */
+ UINT32 line; /*!< source file line number of trace call */
+}trace_entry_head_t;
+
+/*
+ * @brief Parameter traces can be all contained in one write.
+ */
+typedef struct trace_entire_entry {
+ trace_entry_stamp_t stamp;
+ trace_entry_head_t head;
+ UINT32 args[TRACE_MAX_ARGS + 1];
+} trace_entire_entry_t;
+
+
+/*
+ * @brief Binary first writes header and time stamp.
+ */
+typedef struct trace_bin_entry {
+ trace_entry_stamp_t stamp;
+ trace_entry_head_t head;
+} trace_bin_entry_t;
+
+/**
+ * @brief Used as input to traces to get to correct buffer.
+ */
+typedef trace_buf_head_t * tracDesc_t;
+
+/*
+ * @brief Structure is used to hold array of all trace descriptors
+ */
+typedef struct trace_descriptor_array
+{
+ tracDesc_t *entry; /*!< Pointer to trace descriptor */
+ CHAR *comp; /*!< Pointer to component name */
+}trace_descriptor_array_t;
+
+// @rc005a - start
+typedef struct circular_buf_head
+{
+ UINT32 head; // pointer to head
+ UINT32 tail; // pointer to tail
+ UINT32 entryCount; // nums of entry
+} circular_buf_header_t;
+
+
+typedef struct circular_entire_data {
+ UINT32 len;
+ CHAR comp[4];
+ trace_entire_entry_t entry;
+} circular_entire_data_t;
+
+// @rc005a - end
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// All TPMF component trace descriptors.
+extern tracDesc_t g_trac_inf; // @at009a
+extern tracDesc_t g_trac_err; // @at009a
+extern tracDesc_t g_trac_imp; // @at009a
+
+extern const trace_descriptor_array_t g_des_array[];
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+/**
+ * \defgroup TracIntefaces Trace Component Interfaces for External Use
+ * \ingroup Trace
+ */
+/*@{*/
+
+
+/**
+ * @brief Allocate and initialize all trace buffers in memory.
+ *
+ * This function will allocate memory for each of the pre-defined trace
+ * buffers, initilize the buffers with starting data, and setup the
+ * trace descriptors which each component will use to trace.
+ *
+ * This function must be called first before any components try to trace!
+ *
+ * @return Non-zero return code on error.
+ */
+UINT TRAC_init_buffers(void);
+
+/**
+ * @brief Retrieve full trace buffer for component i_comp
+ *
+ * This function assumes memory has already been allocated for
+ * the full trace buffer in o_data.
+ *
+ * @param i_td_ptr Trace descriptor of buffer to retrieve.
+ * @param o_data Pre-allocated pointer to where data will be stored.
+ *
+ * @return Non-zero return code on error
+ */
+UINT TRAC_get_buffer(const tracDesc_t i_td_ptr,
+ void *o_data);
+
+/**
+ * @brief Retrieve partial trace buffer for component i_comp
+ *
+ * This function assumes memory has already been allocated for
+ * the trace buffer (size io_size). This function will copy
+ * in up to io_size in bytes to the buffer and set io_size
+ * to the exact size that is copied in.
+ *
+ * @param i_td_ptr Trace descriptor of buffer to retrieve.
+ * @param o_data Pre-allocated pointer to where data will be stored.
+ * @param io_size Size of trace data to retrieve (input)
+ * Actual size of trace data stored (output)
+ *
+ * @return Non-zero return code on error
+ */
+UINT TRAC_get_buffer_partial(const tracDesc_t i_td_ptr,
+ void *o_data,
+ UINT *io_size);
+
+/**
+ * @brief Retrieve trace descriptor for input component name
+ *
+ * @param i_comp Component name to retrieve trace descriptor for.
+ *
+ * @return Valid trace descriptor on success, NULL on failure.
+ */
+tracDesc_t TRAC_get_td(const char *i_comp);
+
+/**
+ * @brief Reset all trace buffers
+ *
+ * @return Non-zero return code on error
+ */
+UINT TRAC_reset_buf(void);
+
+/*@}*/ // Ending tag for external interface module in doxygen
+
+
+/**
+ * @brief Trace input integers to trace buffer.
+ *
+ * This function assumes i_td has been initialized.
+ *
+ * @param io_td Intialized trace descriptor point to buffer to trace to.
+ * @param i_hash Hash value to be recorded for this trace.
+ * @param i_fmt Output format
+ * @param i_line Line number trace is occurring on.
+ * @param i_type trace type. filed or debug.
+ * @param ... parames that are limited to a size of 4 bytes, i.e. int, uint32_t, nnn*
+ *
+ * @return Non-zero return code on error.
+ */
+UINT trace_adal_write_all(tracDesc_t io_td,const trace_hash_val i_hash,
+ const char *i_fmt,const ULONG i_line, const ULONG i_type,...);
+
+
+/**
+ * @brief Trace input integers to trace buffer.
+ *
+ * This function assumes i_td has been initialized.
+ *
+ * @param io_td Intialized trace descriptor point to buffer to trace to.
+ * @param i_hash Hash value to be recorded for this trace.
+ * @param i_line Line number trace is occurring on.
+ * @param i_num_args Number of arguments to trace.
+ * @param i_1 Input Parameter 1
+ * @param i_2 Input Parameter 2
+ * @param i_3 Input Parameter 3
+ * @param i_4 Input Parameter 4
+ * @param i_5 Input Parameter 5
+ *
+ * @return Non-zero return code on error.
+ */
+UINT trac_write_int(tracDesc_t io_td,const trace_hash_val i_hash,
+ const ULONG i_line,
+ const UINT i_num_args,
+ const ULONG i_1,const ULONG i_2,const ULONG i_3,
+ const ULONG i_4,const ULONG i_5
+ );
+
+
+ /**
+ * @brief Trace binary data to buffer.
+ *
+ * This function assumes i_td has been initialized.
+ *
+ * @param io_td Intialized trace descriptor point to buffer to trace to.
+ * @param i_hash Hash value to be recorded for this trace.
+ * @param i_line Line number trace is occurring on.
+ * @param i_ptr Pointer to binary data to trace.
+ * @param i_size Size of data to copy from i_ptr.
+ *
+ * @return Non-zero return code on error.
+ */
+UINT trac_write_bin(tracDesc_t io_td,const trace_hash_val i_hash,
+ const ULONG i_line,
+ const void *i_ptr,
+ const ULONG i_size);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif //_TRAC_INTERFACE_H
diff --git a/src/occ/trac/trac_service_codes.h b/src/occ/trac/trac_service_codes.h
new file mode 100755
index 0000000..2dec32f
--- /dev/null
+++ b/src/occ/trac/trac_service_codes.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+// @file trac_service_codes.h
+// @brief Error codes for TRAC component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _trac_service_codes_h trac_service_codes.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * TEAM 06/16/2010 Port
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @rc005 864101 rickylie 12/12/2012 add small circ buffer to handle ISR semaphore conflict
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _TRAC_SERVICE_CODES_H_
+#define _TRAC_SERVICE_CODES_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum tracReasonCodes
+{
+ TRAC_ERROR_BLOCK_ALLOCATE = TRAC_COMP_ID | 0x00,
+ TRAC_ERROR_COMP_NOT_FOUND = TRAC_COMP_ID | 0x01,
+ TRAC_MEM_ALLOC_FAIL = TRAC_COMP_ID | 0x02,
+ TRAC_MEM_BUFF_TO_SMALL = TRAC_COMP_ID | 0x03,
+ TRAC_INVALID_PARM = TRAC_COMP_ID | 0x04,
+ TRAC_DATA_SIZE_TO_LARGE = TRAC_COMP_ID | 0x05,
+ TRAC_DATA_SIZE_LESS_THAN_HEADER_SIZE = TRAC_COMP_ID | 0x06,
+ TRAC_CIRCULAR_BUFF_FULL = TRAC_COMP_ID | 0x07, //@rc005a
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _TRAC_SERVICE_CODES_H_ */
diff --git a/src/occApplet/Makefile b/src/occApplet/Makefile
new file mode 100755
index 0000000..1aa4200
--- /dev/null
+++ b/src/occApplet/Makefile
@@ -0,0 +1,53 @@
+# @file Makefile
+#
+# @brief OCC Applet Makefile
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb001 pbavari 07/21/2011 Created
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+# >> gitprep
+ifndef ROOTPATH
+ROOTPATH = $(shell pwd)/../
+export OCCROOT = $(ROOTPATH)
+endif
+# << gitprep
+
+#*******************************************************************************
+# mk variable Declaration
+#*******************************************************************************
+SUBDIRS = productApplet testApplet
+CLEANCMD = $(MAKE) clean -C $(dir);
+ALLCMD = $(MAKE) -j6 -C $(dir);
+COMBINEIMAGE = $(MAKE) combineImage -C $(dir);
+
+#*******************************************************************************
+# Compilation
+#*******************************************************************************
+all:
+ $(foreach dir,$(SUBDIRS),$(ALLCMD))
+
+#*******************************************************************************
+# combineImage
+#*******************************************************************************
+.PHONY : combineImage
+combineImage:
+ $(foreach dir,$(SUBDIRS),$(COMBINEIMAGE))
+
+#*******************************************************************************
+# Clean
+#*******************************************************************************
+clean:
+ $(foreach dir,$(SUBDIRS),$(CLEANCMD))
+
diff --git a/src/occApplet/createApplet b/src/occApplet/createApplet
new file mode 100755
index 0000000..784fcaa
--- /dev/null
+++ b/src/occApplet/createApplet
@@ -0,0 +1,135 @@
+#!/usr/bin/perl
+#
+# Create a new applet source file from a template
+#
+#
+my $template;
+my $newfile = 0;
+my $typeflag = 0;
+my $feature = "";
+my $username = $ENV{USER};
+# version 2: Added applet id name support.
+# version 1: Created this file
+my $VERSION = "2";
+
+#template file path
+$template = $ENV{SANDBOXBASE} . "/src/occc/405/occApplet/template";
+
+#usage
+sub usage()
+{
+
+ print "Usage: $0 -d <short_description_of_file> -f <functionNM> -i <unique applet Id String> <filename> \n";
+ print "\n";
+ print "-d: short description for the file\n";
+ print "-f: Entry point function name\n";
+ print "-i: Unique Applet Id string(15 char long and must be unique within applets)\n";
+ print "-n: Applet ID name from the OCC_APLT enumeration for this applet (eg: OCC_APLT_TEST)\n";
+ print "-V: Version\n";
+ print "\n\n";
+
+ exit 1;
+}
+
+sub createfile(@)
+{
+
+ ($newfile,$type,$shortDesc,$funcNm,$appIdStr,$appIdNm) = @_;
+
+ open TEMPL, "<$template.$type" || die "Unable to open: $template.$type\n";
+ open NEWFILE, ">$newfile.$type" || die "Can't open: $newfile.$type\n";
+
+ read TEMPL, $buf, ( -s TEMPL ) || die "Unable to read template $template.$type\n";
+ close TEMPL;
+
+ # change the filename,function name, short description, applet id string
+ # and applet id
+ $upperNewFile = uc($newfile);
+ $upperFuncNm = uc($funcNm);
+ $buf =~ s/<filename.$type>/$newfile.$type/g;
+ $buf =~ s/<FILENAME.$type>/$upperNewFile.$type/g;
+ $buf =~ s/<shortDesc>/$shortDesc/g;
+ $buf =~ s/<funcNm>/$funcNm/g;
+ $buf =~ s/<FUNCNM>/$upperFuncNm/g;
+ $buf =~ s/<APPLET_ID_STR>/$appIdStr/g;
+ $buf =~ s/<APLT_ID>/$appIdNm/g;
+
+ #change creation date
+ ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
+ $year = sprintf("%02s", $year % 100);
+ $mon = sprintf("%02s", $mon + 1);
+ $mday = sprintf("%02s", $mday);
+ $buf =~ s/MM\/DD\/YY/$mon\/$mday\/$year/;
+
+ #change the userid
+ $buf =~ s/USERID/$username/;
+
+ #write the file
+ print NEWFILE $buf;
+
+ close NEWFILE;
+
+}
+
+while ($ARGV = shift)
+{
+
+ if ($ARGV =~ m/-V/)
+ {
+ print "$0 version = $VERSION\n\n";
+ exit 0;
+ }
+ elsif ($ARGV =~ m/-d/i)
+ {
+ $desc = shift;
+ usage() if $desc =~ m/(-f|-i)/;
+ $shortDesc = $desc;
+ $descFound = 1;
+ }
+ elsif ($ARGV =~ m/-f/i)
+ {
+ $func = shift;
+ usage() if $func =~ m/(-i)/;
+ $funcNm = $func;
+ }
+ elsif ($ARGV =~ m/-i/i)
+ {
+ $appIdStr = shift;
+ usage() if ! $appIdStr =~ m/\w+/;
+ }
+ elsif ($ARGV =~ m/-n/i)
+ {
+ $appIdNm = shift;
+ usage() if ! $appIdNm =~ m/\w+/;
+ }
+ elsif ($ARGV =~ m/\w+/)
+ {
+ $newfile = $ARGV;
+ }
+}
+
+# check if all the expected inputs are received
+if ( ! $newfile || ! $desc || ! $func || ! $appIdStr || !$appIdNm)
+{
+ usage();
+}
+
+if ( -e "$newfile.c" )
+{
+ print "File $newfile exists, clobber file? (y/n) [n] ";
+ $clobber = <STDIN>;
+ if ( $clobber !~ m/^y/i )
+ {
+ die "\nFile exists, cannot continue....\n";
+ }
+ else
+ {
+ createfile($newfile,"c",$shortDesc,$funcNm,$appIdStr,$appIdNm);
+ }
+}
+else
+{
+ createfile($newfile,"c",$shortDesc,$funcNm,$appIdStr,$appIdNm);
+}
+
+
diff --git a/src/occApplet/productApplet/Makefile b/src/occApplet/productApplet/Makefile
new file mode 100755
index 0000000..e87e37d
--- /dev/null
+++ b/src/occApplet/productApplet/Makefile
@@ -0,0 +1,130 @@
+# $Id$
+# @file Makefile
+#
+# @brief OCC Product Applet Makefile
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb001 pbavari 07/18/2011 Created
+# @ani01 abagepa 08/08/2011 Creating to "test" applets
+# as placeholders for real applets
+# Update to include for easier compiling
+# @pb006 pbavari 09/16/2011 Display size support
+# @pb004 pbavari 09/20/2011 Initialization Section support
+# @pb00A pbavari 11/14/2011 Moved sensor_init from applet to init section
+# @th005 thallet 11/23/2011 Sensor querySensorList support
+# @pb00C pbavari 01/20/2012 Added debug_trace.mk
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @at009 859308 alvinwan 10/15/2012 Added tracepp support
+# @th029 thallet 01/23/2013 MD5sum in applet version & include aplt headers
+#
+# @endverbatim
+#
+
+# >> gitprep
+ifndef ROOTPATH
+ROOTPATH = $(shell pwd)/../../
+export OCCROOT = $(ROOTPATH)
+endif
+# << gitprep
+
+#*******************************************************************************
+# mk variable Declaration
+#*******************************************************************************
+OCC = ../../occ
+BOOTLOADER = ../../occBootLoader
+SSX = ../../ssx
+PRODUCTAPPLET = .
+LIB = ../../lib
+
+# New product applet source file must to listed as part of the SOURCES variable
+# to create product applet image. Prodcut applet images will be added to the
+# mainstore single image in the order source files are listed in SOURCES
+# variable.
+# @ani01c
+# Note: New applets must be updated in the applet enum list
+# see occ/aplt/appletManager.h
+
+# >> gitprep
+# Add missing flags for GNU build
+LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \
+ -L $(OCC) -L $(LIB) -lssx -lppc32 --oformat=elf32-powerpc -melf32ppc
+buildImage = $(LD) -R $(OCC)/occ.out $(obj) -Tlinkscript $(LDFLAGS) \
+ -Map $(basename $(obj)).map -Bstatic -o $(basename $(obj)).out;\
+ $(OBJCOPY) -I elf32-powerpc -O binary $(basename $(obj)).out $(basename $(obj)).bin; \
+ $(OBJDUMP) -d $(basename $(obj)).out > $(basename $(obj)).dis; \
+ $(BOOTLOADER)/imageHdrScript $(basename $(obj)).bin `md5sum $(OCC)/occ.out | cut -c 1-4`;
+# << gitprep
+
+image = $(BOOTLOADER)/imageHdrScript $(basename $(obj)).bin combineImage;\
+ $(BOOTLOADER)/imageHdrScript $(basename $(obj)).out displaySize;
+
+#*******************************************************************************
+# Includes
+#*******************************************************************************
+include $(SSX)/pgp/ssx.mk
+#$pb00Ca - Added for debug traces
+include $(OCC)/debug_trace.mk
+include productappletfiles.mk
+
+# >> gitprep
+# Add needed includes for GNU build
+INCLUDES = -I. -I$(OCC)/incl -I$(OCC)/errl -I$(OCC)/trac -I$(LIB) -I$(SSX)/ssx \
+ -I$(OCC)/sensor -I$(OCC) -I$(OCC)/rtls -I$(OCC)/cmdh -I$(OCC)/pss -I$(OCC)/gpe \
+ -I$(OCC)/aplt/incl -I$(OCC)/aplt -I$(OCC)/cent -I$(OCC)/proc -I$(OCC)/thread \
+ -I$(SSX)/ppc405 -I$(SSX)/pgp -I$(SSX)/ppc32 -I$(SSX)/pgp/registers
+# << gitprep
+
+#*******************************************************************************
+# Flags
+#*******************************************************************************
+#D = -DSIMICS_MAGIC_PANIC=1 \
+ -DINITIALIZE_SIMICS_IO=1
+
+DEFS += $(D)
+DEFS += -DAPPLET_BUILD=1
+# >> gitprep
+# Very important we build applets with custom cfg header
+DEFS += -DUSE_SSX_APP_CFG_H=1
+# << gitprep
+
+# If this makefile is called as "make NO_TRAC_STRINGS=1" then trace strings
+# won't be built into the image. This will be used for metrics regarded to the
+# realistic OCC Code Size. Note that "make clean" must be run before this define
+# will be picked up by the compiler, otherwise previously compiled objects will
+# be used. You can also see the space used by strings by running:
+# strings occ.bin | \grep "ERR\|INF\|IMP" | sed 's/^...: %s: //g' | wc -m
+ifdef NO_TRAC_STRINGS
+D += -DNO_TRAC_STRINGS=1
+endif
+
+# Do not use SDA sections for product applet
+GCC-CFLAGS = -c -g -Wall -fsigned-char -msoft-float -pipe \
+ -Wa,-m405 -m32 -mcpu=405 -mmultiple -mstring -meabi \
+ -ffreestanding -Os -mno-sdata
+#*******************************************************************************
+# Compilation
+#*******************************************************************************
+all: $(PRDTAPLT_OBJECTS)
+ $(CPP) -P $(DEFS) < linkProductApplet.cmd > linkscript
+ $(foreach obj,$(PRDTAPLT_OBJECTS),$(buildImage))
+
+#*******************************************************************************
+# combineImage
+#*******************************************************************************
+.PHONY : combineImage
+combineImage:
+ $(foreach obj,$(PRDTAPLT_OBJECTS),$(image))
+
+#*******************************************************************************
+# Clean
+#*******************************************************************************
+clean:
+ rm -f *.o *.out *.bin *.dis *.map *.hash linkscript
diff --git a/src/occApplet/productApplet/apssInitApplet.c b/src/occApplet/productApplet/apssInitApplet.c
new file mode 100755
index 0000000..4a7a84f
--- /dev/null
+++ b/src/occApplet/productApplet/apssInitApplet.c
@@ -0,0 +1,322 @@
+/******************************************************************************
+// @file apssInitApplet.c
+// @brief APSS initialization product applet
+*/
+
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section apssInitApplet.c APSSINITAPPLET.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb004 pbavari 09/13/2011 created
+ * @pb009 pbavari 10/31/2011 Moved apss_initialize retry
+ * inside applet
+ * @dw000 dwoodham 12/12/2011 Update call to IMAGE_HEADER
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @at009 859308 alvinwan 10/15/2012 Added tracepp support
+ * @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+ * @th042 892056 thallet 07/19/2013 Send OCC to safe mode if first APSS GPE fails
+ * @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+ * @fk005 911760 fmkassem 01/21/2014 APSS retry support.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <errl.h> // For error handle
+#include <trac.h> // For traces
+#include <occ_service_codes.h> // for SSX_GENERIC_FAILURE // @nh001a
+#include <pss_service_codes.h> // APSS module ids
+#include <apss.h> // APSS defines
+#include <appletId.h> // For applet ID num dw000a
+#include "ssx_io.h" // For printf
+#include <state.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern PoreEntryPoint GPE_apss_initialize_gpio;
+extern PoreEntryPoint GPE_apss_set_composite_mode;
+extern PoreFlex G_meas_start_request;
+extern PoreFlex G_meas_cont_request;
+extern PoreFlex G_meas_complete_request;
+extern apss_start_args_t G_gpe_start_pwr_meas_read_args;
+extern apss_continue_args_t G_gpe_continue_pwr_meas_read_args;
+extern apss_complete_args_t G_gpe_complete_pwr_meas_read_args;
+extern PoreEntryPoint GPE_apss_start_pwr_meas_read;
+extern PoreEntryPoint GPE_apss_continue_pwr_meas_read;
+extern PoreEntryPoint GPE_apss_complete_pwr_meas_read;
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define APSS_INITIALIZE_ID "APSS Init Aplt\0"
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
+// Function Specification
+//
+// Name: apss_initialize
+//
+// Description: Completes all APSS initialization including GPIOs, altitude and
+// mode
+//
+// Flow: 07/20/11 FN=apss_initialize
+//
+// changeTags: @fk005c,
+//
+// End Function Specification
+errlHndl_t apss_initialize()
+{
+ errlHndl_t l_err = NULL;
+ PoreFlex request;
+
+ // Setup the GPIO init structure to pass to the GPE program
+ G_gpe_apss_initialize_gpio_args.error.error = 0;
+ G_gpe_apss_initialize_gpio_args.error.ffdc = 0;
+ G_gpe_apss_initialize_gpio_args.config0.direction
+ = G_gpio_config[0].direction;
+ G_gpe_apss_initialize_gpio_args.config0.drive
+ = G_gpio_config[0].drive;
+ G_gpe_apss_initialize_gpio_args.config0.interrupt
+ = G_gpio_config[0].interrupt;
+ G_gpe_apss_initialize_gpio_args.config1.direction
+ = G_gpio_config[1].direction;
+ G_gpe_apss_initialize_gpio_args.config1.drive = G_gpio_config[1].drive;
+ G_gpe_apss_initialize_gpio_args.config1.interrupt
+ = G_gpio_config[1].interrupt;
+
+ // Create/schedule GPE_apss_initialize_gpio and wait for it to complete (BLOCKING)
+ TRAC_INFO("Creating request for GPE_apss_initialize_gpio");
+ pore_flex_create(&request, // request
+ &G_pore_gpe0_queue, // queue
+ (void*)GPE_apss_initialize_gpio, // GPE entry_point
+ (uint32_t)&G_gpe_apss_initialize_gpio_args,// GPE argument_ptr
+ SSX_SECONDS(5), // timeout
+ NULL, // callback
+ NULL, // callback arg
+ ASYNC_REQUEST_BLOCKING); // options
+ // Schedule the request to be executed
+ pore_flex_schedule(&request);
+
+ // Check for a timeout, will create the error log later
+ // NOTE: As of 2013/07/16, simics will still fail here on a OCC reset
+
+ if(ASYNC_REQUEST_STATE_TIMED_OUT == request.request.completion_state)
+ {
+ // For whatever reason, we hit a timeout. It could be either
+ // that the HW did not work, or the request didn't ever make
+ // it to the front of the queue.
+ // Let's log an error, and include the FFDC data if it was
+ // generated.
+ TRAC_ERR("Timeout communicating with PORE-GPE for APSS Init");
+ }
+
+ TRAC_INFO("GPE_apss_initialize_gpio completed w/rc=0x%08x\n",
+ request.request.completion_state);
+
+ // Only continue if completed without errors...
+ if (ASYNC_REQUEST_STATE_COMPLETE == request.request.completion_state)
+ {
+ // @ly003c - start
+ // Setup the composite mode structure to pass to the GPE program
+ G_gpe_apss_set_composite_mode_args.error.error = 0;
+ G_gpe_apss_set_composite_mode_args.error.ffdc = 0;
+ G_gpe_apss_set_composite_mode_args.config.numAdcChannelsToRead =
+ G_apss_composite_config.numAdcChannelsToRead;
+ G_gpe_apss_set_composite_mode_args.config.numGpioPortsToRead =
+ G_apss_composite_config.numGpioPortsToRead;
+
+ // Create/schedule GPE_apss_set_composite_mode and wait for it to complete (BLOCKING)
+ TRAC_INFO("Creating request for GPE_apss_set_composite_mode");
+ pore_flex_create(&request, // request
+ &G_pore_gpe0_queue, // queue
+ (void*)GPE_apss_set_composite_mode, // GPE entry_point
+ (uint32_t)&G_gpe_apss_set_composite_mode_args,// GPE argument_ptr
+ SSX_SECONDS(5), // timeout
+ NULL, // callback
+ NULL, // callback arg
+ ASYNC_REQUEST_BLOCKING); // options
+ pore_flex_schedule(&request);
+
+ // Check for a timeout, will create the error log later
+ // NOTE: As of 2013/07/16, simics will still fail here on a OCC reset
+
+ if(ASYNC_REQUEST_STATE_TIMED_OUT == request.request.completion_state)
+ {
+ // For whatever reason, we hit a timeout. It could be either
+ // that the HW did not work, or the request didn't ever make
+ // it to the front of the queue.
+ // Let's log an error, and include the FFDC data if it was
+ // generated.
+ TRAC_ERR("Timeout communicating with PORE-GPE for APSS Init");
+ }
+
+ TRAC_INFO("GPE_apss_set_composite_mode completed w/rc=0x%08x",
+ request.request.completion_state);
+
+ if (ASYNC_REQUEST_STATE_COMPLETE != request.request.completion_state)
+ {
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_INIT
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata2 GPE returned abort code
+ * @userdata4 ERC_PSS_COMPOSITE_MODE_FAIL
+ * @devdesc Failure from GPE for setting composite mode on
+ * APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_INIT, // i_modId,
+ INTERNAL_FAILURE, // i_reasonCode,
+ ERC_PSS_COMPOSITE_MODE_FAIL, // extended reason code
+ ERRL_SEV_UNRECOVERABLE, // i_severity
+ NULL, // TODO - tracDesc_t i_trace,
+ 0x0000, // i_traceSz,
+ request.request.completion_state, // i_userData1,
+ request.request.abort_state); // i_userData2
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_gpe_apss_set_composite_mode_args,
+ sizeof(G_gpe_apss_set_composite_mode_args),
+ ERRL_STRUCT_VERSION_1, // TODO
+ ERRL_USR_DTL_TRACE_DATA);
+
+ // Returning an error log will cause us to go to safe
+ // state so we can report error to FSP
+ }
+ // @ly003c - end
+
+
+ TRAC_INFO("apss_initialize: Creating request G_meas_start_request.");
+ //Create the request for measure start. Scheduling will happen in apss.c
+ pore_flex_create(&G_meas_start_request,
+ &G_pore_gpe0_queue, // queue
+ (void*)GPE_apss_start_pwr_meas_read, // entry_point
+ (uint32_t)&G_gpe_start_pwr_meas_read_args, // entry_point arg
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // callback
+ NULL, // callback arg
+ ASYNC_CALLBACK_IMMEDIATE); // options
+
+ TRAC_INFO("apss_initialize: Creating request G_meas_cont_request.");
+ //Create the request for measure continue. Scheduling will happen in apss.c
+ pore_flex_create(&G_meas_cont_request,
+ &G_pore_gpe0_queue, // request
+ (void*)GPE_apss_continue_pwr_meas_read, // entry_point
+ (uint32_t)&G_gpe_continue_pwr_meas_read_args, // entry_point arg
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // callback
+ NULL, // callback arg
+ ASYNC_CALLBACK_IMMEDIATE); // options
+
+ TRAC_INFO("apss_initialize: Creating request G_meas_complete_request.");
+ //Create the request for measure complete. Scheduling will happen in apss.c
+ pore_flex_create(&G_meas_complete_request,
+ &G_pore_gpe0_queue, // queue
+ (void*)GPE_apss_complete_pwr_meas_read, // entry_point
+ (uint32_t)&G_gpe_complete_pwr_meas_read_args,// entry_point arg
+ SSX_WAIT_FOREVER, // no timeout
+ (AsyncRequestCallback)reformat_meas_data, // callback,
+ (void*)NULL, // callback arg
+ ASYNC_CALLBACK_IMMEDIATE); // options
+
+ }
+ else
+ {
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_INIT
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata2 GPE returned abort code
+ * @userdata4 ERC_PSS_GPIO_INIT_FAIL
+ * @devdesc Failure from GPE for gpio initialization on APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_INIT, // i_modId,
+ INTERNAL_FAILURE, // i_reasonCode,
+ ERC_PSS_GPIO_INIT_FAIL, // extended reason code
+ ERRL_SEV_UNRECOVERABLE, // i_severity
+ NULL, // tracDesc_t i_trace,
+ 0x0000, // i_traceSz,
+ request.request.completion_state, // i_userData1,
+ request.request.abort_state); // i_userData2
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_gpe_apss_initialize_gpio_args,
+ sizeof(G_gpe_apss_initialize_gpio_args),
+ ERRL_STRUCT_VERSION_1, // TODO
+ ERRL_USR_DTL_TRACE_DATA);
+
+ // Returning an error log will cause us to go to safe
+ // state so we can report error to FSP
+ }
+
+ return l_err;
+}
+
+
+// Function Specification
+//
+// Name: apssInitApplet
+//
+// Description: Entry point function
+//
+// Flow: --/--/---- FN= None
+//
+// End Function Specification
+errlHndl_t apssInitApplet(void * i_arg)
+{
+ errlHndl_t l_err = NULL;
+
+ // Initialize APSS
+ l_err = apss_initialize();
+
+ if( NULL != l_err)
+ {
+ TRAC_ERR("APSS Init failed! (retrying) ErrLog[%p]", l_err );
+ setErrlSevToInfo(l_err);
+ // commit & delete
+ commitErrl( &l_err );
+
+ // Retry one more time
+ l_err = apss_initialize();
+
+ if( NULL != l_err)
+ {
+ TRAC_ERR("APSS Init failed again! ErrLog[%p]",l_err);
+ }
+ }
+
+ return l_err;
+}
+/*****************************************************************************/
+// Image Header
+/*****************************************************************************/
+// @dw000 - Add applet ID arg to IMAGE_HEADER macro call
+IMAGE_HEADER (G_apss_initialize,apssInitApplet,APSS_INITIALIZE_ID,OCC_APLT_APSS_INIT);
+
diff --git a/src/occApplet/productApplet/cmdhDbugCmd.c b/src/occApplet/productApplet/cmdhDbugCmd.c
new file mode 100755
index 0000000..2ef7788
--- /dev/null
+++ b/src/occApplet/productApplet/cmdhDbugCmd.c
@@ -0,0 +1,341 @@
+/******************************************************************************
+// @file cmdhDebugCmd.c
+// @brief CMDH Debug Command
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section cmdhDbugCmd.c CMDHDEBUGCMD.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th00d thallet 04/25/2012 created
+ * @nh004 864941 neilhsu 12/20/2012 Support get/delete errl & added trace info
+ * @th031 878471 thallet 04/15/2013 Centaur Throttles
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup
+ * @th036 881677 thallet 05/07/2013 Cleanup
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @rt001 897459 tapiar 10/02/2013 Update module ids with unique ids
+ * @fk002 905632 fmkassem 11/05/2013 Remove CriticalPathMonitor code
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <occ_service_codes.h> // For reason code
+#include <aplt_service_codes.h> // For test applet module ID
+#include <errl.h> // For error handle
+#include <trac.h> // For traces
+#include <state.h>
+#include <appletId.h>
+#include <cmdhDbugCmd.h>
+#include <cmdh_fsp.h>
+#include <cmdh_fsp_cmds.h>
+#include <centaur_data.h>
+#include <gpe_data.h>
+#include <proc_data.h>
+#include <apss.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define CMDH_DBUG_APPLET_ID "Cmdh_Dbug_Aplt\0"
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: dbug_err_inject
+//
+// Description: Injects an error
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+void dbug_err_inject(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr) // @nh004c
+{
+ errlHndl_t l_err;
+ cmdh_dbug_inject_errl_query_t *l_cmd_ptr = (cmdh_dbug_inject_errl_query_t*) i_cmd_ptr;
+
+ i_rsp_ptr->data_length[0] = 0;
+ i_rsp_ptr->data_length[1] = 0;
+ i_rsp_ptr->rc = ERRL_RC_SUCCESS;
+
+ if(!strncmp(l_cmd_ptr->comp, "RST", OCC_TRACE_NAME_SIZE)) //@gm006
+ {
+ l_err = createErrl(TEST_APLT_MODID_ERRLTEST, //modId
+ INTERNAL_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0xff, //userdata1
+ 0); //userdata2
+
+ if (INVALID_ERR_HNDL == l_err)
+ {
+ i_rsp_ptr->rc = ERRL_RC_INTERNAL_FAIL;
+ }
+
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID, //callout type (HUID/CompID)
+ G_sysConfigData.proc_huid, //callout data
+ ERRL_CALLOUT_PRIORITY_HIGH); //priority
+
+ REQUEST_RESET(l_err);
+ }
+ else
+ {
+ l_err = createErrl(TEST_APLT_MODID_ERRLTEST, //modId
+ INTERNAL_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ TRAC_get_td(l_cmd_ptr->comp), //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0xff, //userdata1
+ 0); //userdata2
+
+ if (INVALID_ERR_HNDL == l_err)
+ {
+ i_rsp_ptr->rc = ERRL_RC_INTERNAL_FAIL;
+ }
+
+ // Commit Error log
+ commitErrl(&l_err);
+ }
+
+ if (i_rsp_ptr->rc == ERRL_RC_INTERNAL_FAIL)
+ {
+ TRAC_ERR("cmdh_dbug_inject_errl: Fail creating ERR Log\n");
+ }
+ else
+ {
+ TRAC_INFO("cmdh_dbug_inject_errl: inject errl for COMP : %s\n", l_cmd_ptr->comp);
+ }
+
+ return;
+}
+
+// Function Specification
+//
+// Name: dbug_centaur_dump
+//
+// Description: Injects an error
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+void dbug_centaur_dump(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr) // @nh004c
+{
+ uint16_t l_datalen = 0;
+ uint8_t l_jj=0;
+
+ // Determine the size of the data we are returning
+ l_datalen = (sizeof(MemData) * MAX_NUM_CENTAURS);
+
+ // Fill out the response with the data we are returning
+ for(l_jj=0; l_jj < MAX_NUM_CENTAURS; l_jj++)
+ {
+ MemData * l_sensor_cache_ptr =
+ cent_get_centaur_data_ptr(l_jj);
+
+ memcpy((void *) &(i_rsp_ptr->data[l_jj*sizeof(MemData)]),
+ (void *) l_sensor_cache_ptr,
+ sizeof(MemData));
+ }
+
+ // Fill out the rest of the response data
+ i_rsp_ptr->data_length[0] = CONVERT_UINT16_UINT8_HIGH(l_datalen);
+ i_rsp_ptr->data_length[1] = CONVERT_UINT16_UINT8_LOW(l_datalen);
+ i_rsp_ptr->rc = ERRL_RC_SUCCESS;
+
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: dbug_apss_dump
+//
+// Description: Dumps the APSS power measurement raw ADC / GPIO data
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+void dbug_apss_dump(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr)
+{
+ uint16_t l_datalen = 0;
+
+ // Determine the size of the data we are returning
+ l_datalen = (sizeof(apssPwrMeasStruct_t));
+
+ memcpy((void *) &(i_rsp_ptr->data[0]),
+ (void *) &G_apss_pwr_meas,
+ sizeof(apssPwrMeasStruct_t));
+
+ // Fill out the rest of the response data
+ i_rsp_ptr->data_length[0] = CONVERT_UINT16_UINT8_HIGH(l_datalen);
+ i_rsp_ptr->data_length[1] = CONVERT_UINT16_UINT8_LOW(l_datalen);
+ i_rsp_ptr->rc = ERRL_RC_SUCCESS;
+
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: dbug_proc_data_dump
+//
+// Description: Dumps the processor core data
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+void dbug_proc_data_dump(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * i_rsp_ptr)
+{
+ uint16_t l_datalen = 0;
+ uint8_t l_jj=0;
+
+ // Determine the size of the data we are returning
+ l_datalen = (sizeof(CoreData) * MAX_NUM_CORES);
+
+ // Fill out the response with the data we are returning
+ for(l_jj=0; l_jj < MAX_NUM_CORES; l_jj++)
+ {
+ CoreData * l_core_data_ptr =
+ proc_get_bulk_core_data_ptr(l_jj);
+
+ memcpy((void *) &(i_rsp_ptr->data[l_jj*sizeof(CoreData)]),
+ (void *) l_core_data_ptr,
+ sizeof(CoreData));
+ }
+
+ // Fill out the rest of the response data
+ i_rsp_ptr->data_length[0] = CONVERT_UINT16_UINT8_HIGH(l_datalen);
+ i_rsp_ptr->data_length[1] = CONVERT_UINT16_UINT8_LOW(l_datalen);
+ i_rsp_ptr->rc = ERRL_RC_SUCCESS;
+
+
+ return;
+}
+
+// Function Specification
+//
+// Name: cmdhDbugCmd
+//
+// Description: Entry-point for CMDH Debug Commands
+//
+// Flow: --/--/-- FN=
+//
+// End Function Specification
+errlHndl_t cmdhDbugCmd(void * i_arg)
+{
+ errlHndl_t l_errl = NULL;
+ cmdhDbugCmdAppletArg_t * l_arg = (cmdhDbugCmdAppletArg_t *) i_arg;
+ cmdh_fsp_cmd_t * l_cmd_ptr = l_arg->i_cmd_ptr;
+ cmdh_fsp_rsp_t * l_rsp_ptr = l_arg->io_rsp_ptr;
+ uint8_t l_sub_cmd = 0;
+
+ // Sub Command for debug is always first byte of data
+ l_sub_cmd = l_cmd_ptr->data[0];
+
+ // Trace that a debug command was run
+ TRAC_INFO("Debug Command via Applet: Sub:0x%02x\n", l_sub_cmd);
+
+ // Build up a successful default response
+ l_rsp_ptr->rc = ERRL_RC_SUCCESS;
+ l_rsp_ptr->data_length[0] = 0;
+ l_rsp_ptr->data_length[1] = 0;
+
+ switch ( l_sub_cmd )
+ {
+ case DBUG_INJECT_ERRL:
+ dbug_err_inject(l_cmd_ptr, l_rsp_ptr);
+ break;
+
+ case DBUG_CENTAUR_SENSOR_CACHE:
+ dbug_centaur_dump(l_cmd_ptr, l_rsp_ptr);
+ break;
+
+ case DBUG_DUMP_RAW_AD:
+ dbug_apss_dump(l_cmd_ptr, l_rsp_ptr);
+ break;
+
+ case DBUG_DUMP_PROC_DATA:
+ dbug_proc_data_dump(l_cmd_ptr, l_rsp_ptr);
+ break;
+
+ case DBUG_READ_SCOM: // Obsolete
+ case DBUG_PUT_SCOM: // Obsolete
+ case DBUG_POKE: // Can't allow in trusted
+ case DBUG_GET_TRACE:
+ case DBUG_CLEAR_TRACE:
+ case DBUG_SET_PEXE_EVENT:
+ case DBUG_DUMP_THEMAL:
+ case DBUG_DUMP_POWER:
+ case DBUG_MEM_PWR_CTL:
+ case DBUG_PERFCOUNT:
+ case DBUG_TEST_INTF:
+ case DBUG_SET_BUS_SPEED: // Obsolete
+ case DBUG_FAN_CONTROL: // Obsolete
+ case DBUG_IIC_READ: // Obsolete
+ case DBUG_IIC_WRITE: // Obsolete
+ case DBUG_GPIO_READ:
+ case DBUG_CALCULATE_MAX_DIFF:
+ case DBUG_FORCE_ELOG:
+ case DBUG_SWITCH_PHASE:
+ case DBUG_INJECT_ERR:
+ case DBUG_VERIFY_V_F:
+ case DBUG_DUMP_PPM_DATA:
+ default:
+ l_rsp_ptr->rc = ERRL_RC_INVALID_DATA;
+ break;
+ } //end switch
+
+
+ return l_errl;
+}
+
+
+
+
+
+/*****************************************************************************/
+// Image Header
+/*****************************************************************************/
+IMAGE_HEADER (G_cmdhDbugCmd,cmdhDbugCmd,CMDH_DBUG_APPLET_ID,OCC_APLT_CMDH_DBUG);
+
diff --git a/src/occApplet/productApplet/dpssInitApplet.c b/src/occApplet/productApplet/dpssInitApplet.c
new file mode 100755
index 0000000..5015feb
--- /dev/null
+++ b/src/occApplet/productApplet/dpssInitApplet.c
@@ -0,0 +1,304 @@
+/******************************************************************************
+// @file dpssInitApplet.c
+// @brief DPSS initialization product applet
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dpssInitApplet.c DPSSINITAPPLET.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @at000 alvinwan 12/07/2011 created
+ * @dw000 dwoodham 12/16/2011 Update call to IMAGE_HEADER
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <errl.h> // For error handle
+#include <dpss.h>
+#include <trac.h> // For traces
+#include <occ_sys_config.h>
+#include <occ_service_codes.h> // for SSX_GENERIC_FAILURE // @nh001a
+#include <pss_service_codes.h>
+#include <state.h>
+#include <appletId.h> // For applet ID num dw000a
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern PoreEntryPoint GPE_dpss_send_command_stream;
+extern PoreFlex G_dpss_read_status_request;
+extern gpeDpssCommandStream_t G_gpe_dpss_read_status;
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define DPSSINITAPPLET_ID "DPSS_Init_Aplt\0"
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: dpss_initialize
+//
+// Description: Initializes DPSS fans and oversubscription interrupt
+// If errHndl is returned, caller should call this function again,
+// one time only, in the hopes that it will work on the retry.
+//
+// Flow: 08/03/11 FN=dpss_initialize
+//
+// End Function Specification
+errlHndl_t dpss_initialize(void)
+{
+ errlHndl_t l_err = NULL;
+ PoreFlex request;
+ uint8_t i, l_idx_limit; // index counter and limit value
+
+ // Build command data
+ // Structures from this array we will be passed into our GPE program one-by-one
+ gpeDpssCommandStream_t l_gpe_dpss_stream_dpss_config[] = {
+
+ { .dpss_msg_stream = {
+ .command[0] = DPSS_CMD_SET_MIN_FANS | G_sysConfigData.dpss_fan.min_fans,
+ .command[1] = DPSS_CMD_SET_PWM_DELAY | G_sysConfigData.dpss_fan.pwm_delay_reg,
+ .command[2] = DPSS_CMD_SET_PWM_STEP | G_sysConfigData.dpss_fan.pwm_step_reg,
+ .command[3] = 0x0000,
+ .response = {0}
+ },
+ },
+
+ { .dpss_msg_stream = {
+ .command[0] = DPSS_CMD_SET_FAN_PPR_0 | G_sysConfigData.dpss_fan.fan_ppr[0],
+ .command[1] = DPSS_CMD_SET_FAN_PPR_1 | G_sysConfigData.dpss_fan.fan_ppr[1],
+ .command[2] = 0x0000,
+ .command[3] = 0x0000,
+ .response = {0}
+ },
+ },
+
+ // Fan hysterisis: write low byte, then high byte
+ { .dpss_msg_stream = {
+ .command[0] = DPSS_CMD_SET_FAN_HYST_1_LO | G_sysConfigData.dpss_fan.fan_hysterisis[1],
+ .command[1] = DPSS_CMD_SET_FAN_HYST_0_HI | G_sysConfigData.dpss_fan.fan_hysterisis[0],
+ .command[2] = 0x0000,
+ .command[3] = 0x0000,
+ .response = {0}
+ },
+ },
+
+ // Fan hysterisis: write low byte, then high byte
+ { .dpss_msg_stream = {
+ .command[0] = DPSS_CMD_SET_FAN_HYST_3_LO | G_sysConfigData.dpss_fan.fan_hysterisis[3],
+ .command[1] = DPSS_CMD_SET_FAN_HYST_2_HI | G_sysConfigData.dpss_fan.fan_hysterisis[2],
+ .command[2] = DPSS_CMD_SET_FAN_MODE | G_sysConfigData.dpss_fan.fan_mode,
+ .command[3] = 0x0000,
+ .response = {0}
+ },
+ },
+
+ { .dpss_msg_stream = {
+ .command[0] = DPSS_CMD_SET_FAN_MASK | G_sysConfigData.dpss_fan.fan_mask,
+ .command[1] = DPSS_CMD_SET_FAN_HYST_MASK | G_sysConfigData.dpss_fan.fan_hyst_mask,
+ .command[2] = DPSS_CMD_SET_MAX_FAN_PWM | G_sysConfigData.dpss_fan.max_fan_pwm,
+ .command[3] = 0x0000,
+ .response = {0}
+ },
+ },
+
+ { .dpss_msg_stream = {
+ .command[0] = DPSS_CMD_SET_MIN_PWM | G_sysConfigData.dpss_fan.min_pwm,
+ .command[1] = DPSS_CMD_SET_SPI_FFS | G_sysConfigData.dpss_fan.spi_ffs,
+ .command[2] = DPSS_CMD_SET_SPIS_INT_MASK | G_sysConfigData.dpss_spis_int_mask,
+ .command[3] = 0x0000,
+ .response = {0}
+ },
+ },
+
+ { .dpss_msg_stream = {
+ .command[0] = DPSS_CMD_SET_END_COUNT | G_sysConfigData.dpss_fan.end_count_reg,
+ .command[1] = DPSS_CMD_SET_FAN_WARN_COUNT | G_sysConfigData.dpss_fan.fan_warning_cnt,
+ .command[2] = 0x0000,
+ .command[3] = 0x0000,
+ .response = {0}
+ },
+ },
+ };
+
+ // Calculate the array size dynamically so we don't have to update it if the array changes.
+ l_idx_limit = sizeof(l_gpe_dpss_stream_dpss_config) / sizeof(gpeDpssCommandStream_t);
+
+ for( i = 0; i < l_idx_limit; i++) {
+ // Clear the error reporting parts of the argument structure.
+ l_gpe_dpss_stream_dpss_config[i].gpe_error.error = 0;
+ l_gpe_dpss_stream_dpss_config[i].gpe_error.ffdc = 0;
+
+ // Create GPE program request
+ DPSS_DEBUG_PRINTF(("%s: Calling GPE_dpss_send_command_stream for index %d\n", __FUNCTION__, i));
+ pore_flex_create(&request, // request
+ &pore_gpe0_queue, // queue
+ (void*)GPE_dpss_send_command_stream, // GPE entry_point
+ (uint32_t)&l_gpe_dpss_stream_dpss_config[i], // GPE argument_ptr
+ NULL, // callback
+ NULL, // callback arg
+ ASYNC_REQUEST_BLOCKING); // options
+
+ // Schedule the request to be executed
+ // Because our GPE structures are not in non-cacheable RAM (they are in the .init section instead),
+ // we have to flush the dcache before making the pore flex request, then invalidate the dcache afterward.
+ dcache_flush(&l_gpe_dpss_stream_dpss_config[i], sizeof(l_gpe_dpss_stream_dpss_config[i]));
+ pore_flex_schedule(&request);
+ dcache_invalidate((void *)(&l_gpe_dpss_stream_dpss_config[i]), sizeof(l_gpe_dpss_stream_dpss_config[i]));
+
+ DPSS_DEBUG_PRINTF(("%s: GPE_dpss_send_command_stream for index %d returned: 0x%08X\n", __FUNCTION__, i, l_gpe_dpss_stream_dpss_config[i].gpe_error.rc));
+ DPSS_DEBUG_PRINTF(("\tcommand[0] = 0x%04x, response[0] = 0x%04x\n", l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.command[0], l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.response[0]));
+ DPSS_DEBUG_PRINTF(("\tcommand[1] = 0x%04x, response[1] = 0x%04x\n", l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.command[1], l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.response[1]));
+ DPSS_DEBUG_PRINTF(("\tcommand[2] = 0x%04x, response[2] = 0x%04x\n", l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.command[2], l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.response[2]));
+ DPSS_DEBUG_PRINTF(("\tcommand[3] = 0x%04x, response[3] = 0x%04x\n", l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.command[3], l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.response[3]));
+
+ // Check for errors and invalid DPSS responses.
+ // (Valid DPSS responses should be an echo of the cmd & data passed in).
+
+ if ( (l_gpe_dpss_stream_dpss_config[i].gpe_error.rc != 0) ||
+ (l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.response[0] != l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.command[0]) ||
+ (l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.response[1] != l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.command[1]) ||
+ (l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.response[2] != l_gpe_dpss_stream_dpss_config[i].dpss_msg_stream.command[2]) )
+ {
+ DPSS_DEBUG_PRINTF(("%s: ...Failed with error.\n", __FUNCTION__));
+
+ /*@
+ * @moduleid PSS_MID_DPSS_INIT
+ * @reasonCode INTERNAL_HW_FAILURE
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @userdata1 GPE error return code
+ * @userdata2 GPE error ffdc
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc GPE command failed to initialize the DPSS
+ */
+ l_err = createErrl(PSS_MID_DPSS_INIT, // i_modId,
+ INTERNAL_HW_FAILURE, // i_reasonCode,
+ OCC_NO_EXTENDED_RC, // extended reason code // @nh001a
+ ERRL_SEV_UNRECOVERABLE,
+ NULL, // tracDesc_t i_trace,
+ 0x0000, // i_traceSz,
+ l_gpe_dpss_stream_dpss_config[i].gpe_error.rc, // i_userData1,
+ l_gpe_dpss_stream_dpss_config[i].gpe_error.ffdc >> 32); // i_userData2
+
+ // Put extra debug info into local data struct
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&l_gpe_dpss_stream_dpss_config[i],
+ sizeof(l_gpe_dpss_stream_dpss_config[i]),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_TRACE_DATA);
+ break;
+ }
+ else {
+ DPSS_DEBUG_PRINTF(("%s: ...Success!\n", __FUNCTION__));
+ }
+ }
+
+ return l_err;
+} // end dpss_initialize()
+
+// Function Specification
+//
+// Name: dpssInitApplet (old name is start_dpss)
+//
+// Description:
+// Entry-point for enabling DPSS functionality.
+// Initializes the DPSS chip. Starts the "DPSS Read Status" RTLS task.
+//
+// Flow: 08/03/11 FN=dpss_initialize
+// Modified from original flow (approved, T. Hallett, 10/03/2011).
+// Further mods recommended in DPSS code review 10/19/2011.
+//
+// End Function Specification
+errlHndl_t dpssInitApplet(void * i_arg)
+{
+ // Init DPSS
+ TRAC_INFO("Initializing DPSS registers...");
+
+ errlHndl_t l_errl = dpss_initialize();
+
+ if (l_errl)
+ {
+ // init failed, attempt one more time before giving up
+ TRAC_ERR("dpss_initialize failed! (retrying)...");
+
+ // Convert the error severity to info and log it.
+ setErrlSevToInfo(l_errl);
+ commitErrl( &l_errl );
+
+ l_errl = dpss_initialize();
+
+ if (l_errl)
+ {
+ TRAC_ERR("dpss_initialize failed again! OCC will be reset.");
+
+ // Log the error with its original unrecoverable severity
+ commitErrl( &l_errl );
+
+ REQUEST_RESET(); // @th006
+ }
+ }
+
+ if( !l_errl )
+ {
+ TRAC_INFO("...DPSS initialized.");
+ TRAC_INFO("Enabling DPSS Read Status RTLS task.");
+
+ // Init the global DPSS read-status PORE flex request.
+ // None of these values is expected to change.
+ pore_flex_create(&G_dpss_read_status_request, // request
+ &pore_gpe0_queue, // queue
+ (void*)GPE_dpss_send_command_stream, // GPE entry_point
+ (uint32_t)&G_gpe_dpss_read_status, // GPE argument_ptr
+ NULL, // callback
+ NULL, // callback arg
+ 0); // options DO NOT set this to ASYNC_REQUEST_BLOCKING
+
+ // Make this task runnable.
+ rtl_start_task(TASK_ID_DPSS_RD_STATUS);
+ }
+
+ return l_errl;
+} // end dpssInitApplet
+
+
+
+
+
+/*****************************************************************************/
+// Image Header
+/*****************************************************************************/
+// @dw000 - Add applet ID arg to IMAGE_HEADER macro call
+// TODO: Change this if/when DPSS is enabled.
+IMAGE_HEADER (G_dpssInitApplet,dpssInitApplet,DPSSINITAPPLET_ID,OCC_APLT_INVALID);
+
diff --git a/src/occApplet/productApplet/linkProductApplet.cmd b/src/occApplet/productApplet/linkProductApplet.cmd
new file mode 100755
index 0000000..f806f92
--- /dev/null
+++ b/src/occApplet/productApplet/linkProductApplet.cmd
@@ -0,0 +1,55 @@
+
+// $Id$
+
+
+// This linker script for the product applet.
+
+#define APP_IMAGE_SRAM_START_ADDR 0xFFFF8000
+#define WORD_ALIGN 4
+#define BYTE_ALIGN 1024
+#ifdef OCCMK
+INCLUDE occLinkInputFile
+#endif
+
+MEMORY
+{
+ AppMem : ORIGIN = APP_IMAGE_SRAM_START_ADDR, LENGTH = 0x4000
+}
+
+SECTIONS
+{
+ . = APP_IMAGE_SRAM_START_ADDR;
+
+ __START_ADDR__ = .;
+
+ ////////////////////////////////
+ // start read-only section
+ ////////////////////////////////
+ imageHeader . : { *(imageHeader) } > AppMem
+
+ ////////////////////////////////
+ // text section 1024 byte aligned
+ ////////////////////////////////
+ .text . : { *(.text) . = ALIGN(1024);} > AppMem
+ // NOTE: rodata section needs to be 1k aligned as it is used for setting
+ // mmu permission druing applet execution
+ .rodata . : { *(.rodata) *(.got2) *(.rodata.str1.4) *(.rodata.str1.1). = ALIGN(BYTE_ALIGN); } > AppMem
+ __READ_ONLY_DATA_LEN__ = . - APP_IMAGE_SRAM_START_ADDR ;
+
+ ////////////////////////////////
+ // start writeable section
+ ////////////////////////////////
+ __WRITEABLE_DATA_ADDR__ = .;
+
+ ////////////////////////////////
+ // read-write section 1024 byte aligned
+ ////////////////////////////////
+ .rela . : { *(.rela*) . = ALIGN(WORD_ALIGN);} > AppMem
+ // NOTE: rwdata section needs to be 1024 bytes aligned for setting mmu
+ // permission, so that applet total size is 1024 bytes aligned.
+ // It is needed for doing DMA copy of the applet.
+ .rwdata . : { *(.data) *(.bss) *(COMMON) . = ALIGN(BYTE_ALIGN);} > AppMem
+
+ __WRITEABLE_DATA_LEN__ = . - __WRITEABLE_DATA_ADDR__;
+
+}
diff --git a/src/occApplet/productApplet/occLinkInputFile b/src/occApplet/productApplet/occLinkInputFile
new file mode 100644
index 0000000..24c17c3
--- /dev/null
+++ b/src/occApplet/productApplet/occLinkInputFile
@@ -0,0 +1 @@
+INPUT ( cmdhDbugCmd.o )
diff --git a/src/occApplet/productApplet/productappletfiles.mk b/src/occApplet/productApplet/productappletfiles.mk
new file mode 100755
index 0000000..d11968d
--- /dev/null
+++ b/src/occApplet/productApplet/productappletfiles.mk
@@ -0,0 +1,30 @@
+# @file libofiles.mk
+#
+# @brief mk for libssx.a object files
+#
+# @page ChangeLogs Change Logs
+# @section ofiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/28/2012 Makefile ODE support
+#
+# @endverbatim
+#
+##########################################################################
+# INCLUDES
+##########################################################################
+C-SOURCES = apssInitApplet.c sensorQueryList.c cmdhDbugCmd.c
+
+PRDTAPLT_OBJECTS = $(C-SOURCES:.c=.o)
+
+apssInitApplet_OFILES = apssInitApplet.o
+sensorQueryList_OFILES = sensorQueryList.o
+cmdhDbugCmd_OFILES = cmdhDbugCmd.o
+
+
+
+
diff --git a/src/occApplet/productApplet/sensorQueryList.c b/src/occApplet/productApplet/sensorQueryList.c
new file mode 100755
index 0000000..e78ec12
--- /dev/null
+++ b/src/occApplet/productApplet/sensorQueryList.c
@@ -0,0 +1,308 @@
+/******************************************************************************
+// @file sensorQueryList.c
+// @brief sensor sensorQueryList product applet
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensorQueryList.c SENSORQUERYLIST.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @th005 thallet 11/21/2011 Created
+ * @dw000 dwoodham 12/12/2011 Update call to IMAGE_HEADER
+ * @pb00C pbavari 01/20/2012 Changed printf to SNR_DBG
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @at003 alvinwan 03/19/2012 Add o_sensorInfoPtrs to querySensorListAppletArg_t
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @gm002 885429 milesg 05/30/2013 change loc/type to 16 bit bitmask
+ * @wb003 920760 wilbryan 03/25/2014 Update SRCs to match TPMD SRCs
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <occ_common.h> // imageHdr_t declaration and image header macro
+#include <errl.h> // For error handle
+#include "ssx_io.h" // For sprintf
+#include <trac.h> // For traces
+#include <sensor_service_codes.h> // sensor module ids
+#include <occ_service_codes.h> // sensor module ids
+#include <sensor.h> // For Sensor defines
+#include <sensorQueryList.h> // For args to applet
+#include <appletId.h> // For applet ID num dw000a
+
+/*****************************************************************************/
+// C Source File Includes for this Applet
+// --------------------------------------
+// \_ Must be done to give this applet access to the G_sensor_info
+// sensor list
+/*****************************************************************************/
+#include "sensor_info.c"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define SENSOR_QUERY_ID "SNSR QueryList\0"
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+
+// Function Specification
+//
+// Name: printSensorInfo
+//
+// Description: Dump a sensor's info via printf
+//
+// Flow: --/--/---- FN= None
+//
+// End Function Specification
+void printSensorInfo(uint16_t i_gsid)
+{
+ //@pb00Cc - Changed to initialize variable j and k with NULL and then
+ // point to sensor to avoid compilation error when SNSR_DEBUG is not
+ // defined. j and k are only used with SNSR_DBG which is no-op statement
+ // when SNSR_DEBUG is not defined.
+ sensor_t * k = NULL;
+ k = G_amec_sensor_list[i_gsid];
+ uint16_t * j = NULL;
+ j = G_amec_sensor_list[i_gsid]->mini_sensor;
+
+ // Print Sensors Information from Sensor_info_t Table
+ SNSR_DBG("Sensor [%d] = Name: %s, Units: %s, Type: 0x%04x, Loc: 0x%04x, Num: %d, Freq: 0x%08x, Scale: 0x%08x\n",
+ i_gsid,
+ G_sensor_info[i_gsid].name,
+ G_sensor_info[i_gsid].sensor.units,
+ G_sensor_info[i_gsid].sensor.type,
+ G_sensor_info[i_gsid].sensor.location,
+ G_sensor_info[i_gsid].sensor.number,
+ G_sensor_info[i_gsid].sensor.freq,
+ G_sensor_info[i_gsid].sensor.scalefactor
+ );
+
+ // Print Sensor Information from Sensor_t
+ SNSR_DBG("SensorPtr=0x%08x, Sample=%d, Max=%d, Min=%d, Tag=%d, MiniSensorPtr=0x%08x, MiniSensorVal=0x%04x\n",
+ (uint32_t) k,
+ k->sample,
+ k->sample_max,
+ k->sample_min,
+ k->update_tag,
+ (uint32_t)k->mini_sensor,
+ (NULL != j) ? *j : 0
+ );
+}
+
+
+// Function Specification
+//
+// Name: printAllSensors
+//
+// Description: Dump all sensors via printf.
+//
+// Flow: --/--/---- FN= none
+//
+// End Function Specification
+void printAllSensors(void)
+{
+ int i;
+
+ // Loop through sensor table and printf all sensors
+ for(i=0; i < NUMBER_OF_SENSORS_IN_LIST; i++)
+ {
+ printSensorInfo(i);
+ }
+}
+
+
+/*****************************************************************************/
+// Entry point function
+/*****************************************************************************/
+
+// Function Specification
+//
+// Name: querySensorList
+//
+// Description: Query sensor list
+//
+// Flow: 06/27/2011 FN= querySensorList
+//
+// End Function Specification
+
+// When this moved to applet, instead of getting the data
+// via sensor_t, it now has to get some of it via sensor_info_t. The sensor
+// info array is still be indexed by gsid, so this should be easy.
+errlHndl_t querySensorList(const querySensorListAppletArg_t * i_argPtr)
+{
+ errlHndl_t l_err = NULL;
+
+ if(i_argPtr != NULL)
+ {
+ uint16_t i_startGsid = i_argPtr->i_startGsid;
+ uint8_t i_present = i_argPtr->i_present;
+ uint16_t i_type = i_argPtr->i_type;
+ uint16_t i_loc = i_argPtr->i_loc;
+ uint16_t * io_numOfSensors = i_argPtr->io_numOfSensors;
+ sensorQueryList_t * o_sensors = i_argPtr->o_sensors;
+ sensor_info_t * o_sensorInfoPtrs= i_argPtr->o_sensorInfoPtrs; //@at003A
+
+ // Validate input parameters
+ if( (i_startGsid >= NUMBER_OF_SENSORS_IN_LIST) ||
+ ((o_sensors == NULL) && (o_sensorInfoPtrs ==NULL)) || //@at003M
+ (io_numOfSensors == NULL))
+ {
+ TRAC_ERR("Invalid input pointers OR start GSID is out of range: "
+ "i_startGsid: 0x%x, G_amec_sensor_count: 0x%x",
+ i_startGsid,G_amec_sensor_count);
+
+ /* @
+ * @errortype
+ * @moduleid SENSOR_QUERY_LIST
+ * @reasoncode INTERNAL_INVALID_INPUT_DATA
+ * @userdata1 i_startGsid -- passed in Global Sensor ID
+ * @userdata2 G_amec_sensor_count -- number of OCC sensors
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Firmware failure caused due to invalid GSID passed
+ */
+
+ /* @
+ * @errortype
+ * @moduleid SENSOR_QUERY_LIST
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 i_startGsid -- passed in Global Sensor ID
+ * @userdata2 G_amec_sensor_count -- number of OCC sensors
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc NULL pointer passed for querySensorList applet output args
+ */
+ l_err = createErrl(SENSOR_QUERY_LIST, //modId
+ ((i_startGsid >= NUMBER_OF_SENSORS_IN_LIST)?
+ INTERNAL_INVALID_INPUT_DATA : INTERNAL_FAILURE), //reasoncode // @wb003
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ 0, //Trace Size
+ i_startGsid, //userdata1
+ G_amec_sensor_count //userdata2
+ );
+ }
+ else
+ {
+ uint32_t l_cnt = i_startGsid;
+ uint32_t l_num = *io_numOfSensors;
+ *io_numOfSensors = 0;
+
+ // Traverse through sensor list starting at i_startGsid to find
+ // matching sensor. Return it in the output variable
+ for(;(l_cnt < NUMBER_OF_SENSORS_IN_LIST && ((*io_numOfSensors) < l_num));
+ l_cnt++)
+ {
+ // If sample value is not zero then it means sensor is present.
+ // This is currently only used by debug/mfg purpose
+ // If user is looking for present sensors and sample is zero,
+ // then don't include current sensor in the query list
+ if( (i_present) && (G_amec_sensor_list[l_cnt]->sample == 0))
+ {
+ continue;
+ }
+
+ // If user is NOT looking for any sensor type and input type,
+ // does not match the current sensor type, then don't include
+ // current sensor in the query list
+ if((i_type & G_sensor_info[l_cnt].sensor.type) == 0)
+ {
+ continue;
+ }
+
+ // If user is NOT looking for any sensor location and input loc,
+ // does not match the current sensor location, then don't include
+ // current sensor in the query list
+ if((i_loc & G_sensor_info[l_cnt].sensor.location) == 0)
+ {
+ continue;
+ }
+
+ //@at003M begin<
+ if( o_sensors != NULL)
+ {
+ // All conditions match. Include current sensor in the query list
+ // Copy gsid, name and sample
+ o_sensors->gsid = l_cnt;
+ strncpy(o_sensors->name,G_sensor_info[l_cnt].name,
+ MAX_SENSOR_NAME_SZ);
+ o_sensors->sample = G_amec_sensor_list[l_cnt]->sample;
+ o_sensors++;
+ }
+
+ if( o_sensorInfoPtrs != NULL)
+ {
+ memcpy( o_sensorInfoPtrs, &G_sensor_info[l_cnt], sizeof(sensor_info_t));
+ o_sensorInfoPtrs++;
+ }
+ // @at003M end>
+
+ (*io_numOfSensors)++;
+ } // end for loop
+ } // valid input parameter path
+ }
+ else
+ {
+ TRAC_ERR("Invalid applet argument pointer = NULL");
+
+ /* @
+ * @errortype
+ * @moduleid SENSOR_QUERY_LIST
+ * @reasoncode INTERNAL_INVALID_INPUT_DATA
+ * @userdata1 NULL
+ * @userdata2 NULL
+ * @userdata4 ERC_ARG_POINTER_FAILURE
+ * @devdesc NULL pointer passed to querySensorList applet
+ */
+ l_err = createErrl(
+ SENSOR_QUERY_LIST, // Module ID
+ INTERNAL_INVALID_INPUT_DATA, // Reason Code // @wb003
+ ERC_ARG_POINTER_FAILURE, // Extended reason code
+ ERRL_SEV_PREDICTIVE, // Severity
+ NULL, // Trace
+ 0, // Trace Size
+ 0, // UserData 1
+ 0 // UserData 2
+ );
+ }
+
+ return l_err;
+}
+
+
+
+/*****************************************************************************/
+// Image Header
+/*****************************************************************************/
+// @dw000 - Add applet ID arg to IMAGE_HEADER macro call
+IMAGE_HEADER (G_querySensorList,querySensorList,SENSOR_QUERY_ID,OCC_APLT_SNSR_QUERY);
+
diff --git a/src/occApplet/template.c b/src/occApplet/template.c
new file mode 100755
index 0000000..749f79d
--- /dev/null
+++ b/src/occApplet/template.c
@@ -0,0 +1,73 @@
+/******************************************************************************
+// @file <filename.c>
+// @brief <shortDesc>
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section <filename.c> <FILENAME.c>
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * USERID MM/DD/YY created
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <errl.h> // For error handle
+#include "ssx_io.h" // For printfs
+#include <trac.h> // For traces
+#include <appletId.h> // For applet ID
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define <FUNCNM>_ID "<APPLET_ID_STR>\0"
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+//*************************************************************************
+// Entry point function
+//*************************************************************************
+errlHndl_t <funcNm>(void * i_arg)
+{
+ TRAC_INFO("Enter");
+ errlHndl_t l_err = NULL;
+
+ TRAC_INFO("Exit");
+ return l_err;
+}
+
+//*************************************************************************
+// Image Header
+//*************************************************************************
+IMAGE_HEADER (G_<funcNm>,<funcNm>,<FUNCNM>_ID,<APLT_ID>);
diff --git a/src/occApplet/testApplet/Makefile b/src/occApplet/testApplet/Makefile
new file mode 100755
index 0000000..9a5ea0b
--- /dev/null
+++ b/src/occApplet/testApplet/Makefile
@@ -0,0 +1,107 @@
+# @file Makefile
+#
+# @brief OCC Test Applet Makefile
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb001 pbavari 07/18/2011 Created
+# @pb002 pbavari 08/17/2011 Added sensorTest.c
+# @cc000 cjcain 08/30/2011 Added apssTest.c
+# @pb004 pbavari 09/15/2011 Added support for calling
+# product aplt from test aplt
+# @02 tapiar 10/03/2011 Adding new dir includes
+# @dw000 dwodham 12/13/2011 Add include for appletId
+# @rc001 rickylie 01/16/2012 Include debug_trace.mk
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @at002 alvinwan 02/10/2012 Added errlTest.c
+# @at009 859308 alvinwan 10/15/2012 Added tracepp support
+# @th029 thallet 01/23/2013 Added md5sum in version
+#
+# @endverbatim
+#
+
+# >> gitprep
+ifndef ROOTPATH
+ROOTPATH = $(shell pwd)/../../
+export OCCROOT = $(ROOTPATH)
+endif
+# << gitprep
+
+#*******************************************************************************
+# mk variable Declaration
+#*******************************************************************************
+OCC = ../../occ
+BOOTLOADER = ../../occBootLoader
+SSX = ../../ssx
+TESTAPPLET = .
+LIB = ../../lib
+
+# >> gitprep
+# Add missing link flags fir GNU build
+LDFLAGS += --oformat=elf32-powerpc -melf32ppc
+
+buildImage = $(LD) -R $(OCC)/occ.out $(obj) -Tlinkscript $(LDFLAGS) \
+ -Map $(basename $(obj)).map -Bstatic -o $(basename $(obj)).out;\
+ $(OBJCOPY) -I elf32-powerpc -O binary $(basename $(obj)).out $(basename $(obj)).bin; \
+ $(OBJDUMP) -d $(basename $(obj)).out > $(basename $(obj)).dis; \
+ $(BOOTLOADER)/imageHdrScript $(basename $(obj)).bin `md5sum $(OCC)/occ.out | cut -c 1-4`; \
+# << gitprep
+
+#*******************************************************************************
+# Includes
+#*******************************************************************************
+include $(SSX)/pgp/ssx.mk
+#@rc001a
+include $(OCC)/debug_trace.mk
+include testappletfiles.mk
+
+INCLUDES = -I. -I$(OCC)/rtls -I$(OCC)/incl -I$(OCC)/errl -I$(OCC)/trac -I$(LIB) -I$(SSX)/ssx
+INCLUDES += -I$(SSX)/ppc405 -I$(SSX)/pgp -I$(SSX)/ppc32 -I$(SSX)/pgp/registers
+INCLUDES += -I$(OCC)/sensor -I$(OCC)/pss -I$(OCC)/gpe -I$(OCC) -I$(OCC)/aplt -I$(OCC)/dcom
+# >> gitprep
+# Add missing include paths
+INCLUDES += -I$(OCC)/aplt/incl -I$(OCC)/cmdh
+# << gitprep
+
+#*******************************************************************************
+# Flags
+#*******************************************************************************
+#D = -DSIMICS_MAGIC_PANIC=1 \
+ -DINITIALIZE_SIMICS_IO=1
+
+DEFS += $(D)
+DEFS += -DOCC=1 \
+ -DUSE_SSX_APP_CFG_H=1
+
+# Do not use SDA sections for product applet
+# >> gitprep
+# Add missing compile flags for GNU build
+GCC-CFLAGS = -c -g -Wall -fsigned-char -msoft-float -pipe \
+ -m32 -Wa,-m405 -mcpu=405 -mmultiple -mstring -meabi \
+ -ffreestanding -Os -mno-sdata
+# << gitprep
+
+#*******************************************************************************
+# Compilation
+#*******************************************************************************
+all: $(TESTAPLT_OBJECTS)
+ $(CPP) -P $(DEFS) < linkTestApplet.cmd > linkscript
+ $(foreach obj,$(TESTAPLT_OBJECTS),$(buildImage))
+
+#*******************************************************************************
+# combineImage
+#*******************************************************************************
+.PHONY : combineImage
+combineImage:
+#*******************************************************************************
+# Clean
+#*******************************************************************************
+clean:
+ rm -f *.o *.out *.bin *.dis *.map *.hash linkscript
diff --git a/src/occApplet/testApplet/apsstest.c b/src/occApplet/testApplet/apsstest.c
new file mode 100755
index 0000000..8ccd968
--- /dev/null
+++ b/src/occApplet/testApplet/apsstest.c
@@ -0,0 +1,107 @@
+/******************************************************************************
+// @file apsstest.c
+// @brief APSS test applet
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section apsstest.c APSSTEST.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * cjcain 08/30/2011 created
+ * @02 abagepa 10/03/2011 updated task signature
+ * @dw000 dwoodham 12/12/2011 Update call to IMAGE_HEADER macro
+ * @rc001 rickylie 01/10/2012 Change DEBUG_PRINTF to APSS_DBG
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <errl.h> // For error handle
+#include "ssx_io.h" // For printfs
+#include <apss.h> // APSS Interfaces
+#include <appletId.h> // For applet ID @dw000a
+#include <trac.h> // For traces
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern PoreEntryPoint GPE_pore_nop; // Sleep for specified amount of time...
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define APSSTESTMAIN_ID "apsstest1\0"
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: apssTestMain
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+errlHndl_t apssTestMain(void * i_arg)
+{
+ APSS_DBG("Running apssTestMain\n");
+ errlHndl_t l_err = NULL;
+ task_apss_start_pwr_meas(NULL);
+
+ // Schedule GPE program to delay to ensure the data is available... (BLOCKING)
+ // bad: 48, good: 56
+ PoreFlex test_request;
+ APSS_DBG("apss_test_pwr_meas: delay...\n");
+ pore_flex_create(&test_request,
+ &G_pore_gpe0_queue,
+ (void*)GPE_pore_nop, // entry_point
+ (uint32_t)56, // entry_point argument
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // callback,
+ NULL, // callback arg
+ ASYNC_REQUEST_BLOCKING); // options
+ pore_flex_schedule(&test_request);
+ APSS_DBG("apss_test_pwr_meas: delay complete\n");
+
+ task_apss_continue_pwr_meas(NULL);
+
+ task_apss_complete_pwr_meas(NULL);
+
+ APSS_DBG("Done apssTestMain\n");
+
+ return l_err;
+}
+
+/*****************************************************************************/
+// Image Header
+/*****************************************************************************/
+// @dw000 - call macro with Applet ID arg
+IMAGE_HEADER (G_apssTestMain,apssTestMain,APSSTESTMAIN_ID,OCC_APLT_TEST);
+
diff --git a/src/occApplet/testApplet/errlTest.c b/src/occApplet/testApplet/errlTest.c
new file mode 100755
index 0000000..c466c8f
--- /dev/null
+++ b/src/occApplet/testApplet/errlTest.c
@@ -0,0 +1,1210 @@
+/******************************************************************************
+// @file errlTest.c
+// @brief OCC errl component test applet
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section errlTest.c ERRLTEST.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @at002 alvinwan 02/10/2012 Created
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @at012 868019 alvinwan 01/25/2014 TRAC_get_buffer_partial() can result in TLB Miss Exception
+ * @jh001 881996 joshych 05/07/2013 Support SRAM error log format
+ * @jh003 890574 joshych 15/07/2013 Fix errlTest Applet
+ * @rt001 901927 tapiar 10/02/2013 Update error log to use unique module id
+ * @fk006 914801 fmkassem 01/05/2013 Remove wrong reference to a reasoncode
+ * @sb100 916174 sbroyles 02/18/2014 Remove rand.h include for ssx release release20140214
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#define ERRL_DEBUG
+/*****************************************************************************/
+// Includes
+/*****************************************************************************/
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include "ssx.h"
+#include "ssx_io.h" // For ERRL_DBGs
+#include <errl.h>
+#include <appletId.h> // For applet ID
+// #include <rand.h> @sb100
+#include <trac.h> // For traces
+#include <occ_service_codes.h> // Reason code
+#include <cmdh_fsp.h> // Needed for rc codes.
+#include <trac_interface.h>
+#include <aplt_service_codes.h> // For test applet module ID
+#include <testApltId.h> // For test applet ID
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+#define CHECK_CONDITION(cond, rv) \
+ if( !(cond) ) \
+ { \
+ rv = __LINE__; \
+ break; \
+ }
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define ERRLTESTMAIN_ID "errl Test\0"
+#define TRAC_PATTERN 0x55
+#define MAX_BUFFER_SIZE MAX_ERRL_CALL_HOME_SZ
+#define TEST_MODULE_ID 0x1616 // @nh001a
+
+// sensor test module ID enumeration
+typedef enum
+{
+ TEST_ERROR_HANDLING = 0x00,
+ TEST_CREATE_COMMIT_DELETE_LOG = 0x01,
+ TEST_ADD_USRDTLS_TO_ERRL = 0x02,
+ TEST_ADD_TRACE_TO_ERRL = 0x03,
+ TEST_TIME = 0x04,
+ TEST_CREATE2INFO_CALLHOMELOG = 0x05,
+ TEST_CREATE_MAX_LOGS = 0x06,
+ TEST_CALLOUTS = 0x07,
+ TEST_SET_ERRLSEV_TO_INFO = 0x08,
+ TEST_ERRL_TEST_WORD_ALIGN = 0x09
+} errlTestModId;
+
+// errl test return codes
+typedef enum
+{
+ SUCCESS_RC = 0x00000000,
+} errlTestRc;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// TRACE: Trace buffers initialized
+uint8_t G_data[ MAX_BUFFER_SIZE];
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+uint32_t errlTestErrorHandling();
+uint32_t errlTestAddUsrDtlsToErrl();
+uint32_t errlTestAddTraceToErrl();
+uint32_t errlTestDtlSizeLimit();
+uint32_t errlTestTime();
+uint32_t errlTestCreateCommitDeleteLog();
+uint32_t errlTestCreate2InfoCallhomeLog();
+uint32_t errlTestCreateMaxLogs();
+uint32_t errlTestCallouts();
+uint32_t errlTestSetErrlSevToInfo();
+uint32_t errlTestWordAlign();
+void dumpLog( errlHndl_t i_log, uint32_t i_len );
+void ppdumpslot(void);
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+// Function errlTestMain
+//
+// Name: sensorTestMain
+//
+// Description: Entry point function
+//
+// Flow: FN=None
+//
+// End Function Specification
+errlHndl_t errlTestMain(void * i_arg)
+{
+
+ errlHndl_t l_err = NULL;
+ uint16_t l_modId = 0;
+ uint32_t l_rc = ERRL_RC_SUCCESS;
+
+ ERRL_DBG("Enter errlTestMain\n");
+
+ do
+ {
+ l_rc = errlTestErrorHandling();
+ l_modId = TEST_ERROR_HANDLING;
+
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on error handling test");
+ break;
+ };
+
+ l_rc = errlTestCreateCommitDeleteLog();
+ l_modId = TEST_CREATE_COMMIT_DELETE_LOG ;
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on Log test");
+ break;
+ }
+
+ l_rc = errlTestAddUsrDtlsToErrl();
+ l_modId = TEST_ADD_USRDTLS_TO_ERRL ;
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on add user detail test");
+ break;
+ }
+
+ l_rc = errlTestAddTraceToErrl();
+ l_modId = TEST_ADD_TRACE_TO_ERRL ;
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on add trace test");
+ break;
+ }
+
+ l_rc = errlTestTime();
+ l_modId = TEST_TIME ;
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on time test");
+ break;
+ }
+
+ l_rc = errlTestCreate2InfoCallhomeLog();
+ l_modId = TEST_CREATE2INFO_CALLHOMELOG ;
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on create call home log test");
+ break;
+ }
+
+ l_rc = errlTestCreateMaxLogs();
+ l_modId = TEST_CREATE_MAX_LOGS ;
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on create max logs test");
+ break;
+ }
+
+ l_rc = errlTestCallouts();
+ l_modId = TEST_CALLOUTS ;
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on callouts test");
+ break;
+ }
+
+ l_rc = errlTestSetErrlSevToInfo();
+ l_modId = TEST_SET_ERRLSEV_TO_INFO ;
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ TRAC_INFO("Failure on SetErrlSevToInfo test");
+ break;
+ }
+
+ // @jh003c
+ // comment out the test case since we no longer add the alignment in addUsrDtlsToErrl
+ //l_rc = errlTestWordAlign();
+ //l_modId = TEST_ERRL_TEST_WORD_ALIGN ;
+ //if( l_rc != ERRL_RC_SUCCESS)
+ //{
+ // TRAC_INFO("Failure on word alignment test");
+ // break;
+ //}
+ } while (0);
+
+ if( l_rc != ERRL_RC_SUCCESS)
+ {
+ ERRL_DBG("**********************************************");
+ ERRL_DBG("* errl Test Failed (errlTest.c): line: %d",l_rc);
+ ERRL_DBG("**********************************************");
+ /* @
+ * @errortype
+ * @moduleid TEST_APLT_MODID_ERRLTEST
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 Test Applet ID
+ * @userdata2 Return Code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure executing test applet
+ */
+ l_err = createErrl(TEST_APLT_MODID_ERRLTEST,
+ INTERNAL_FAILURE, // @nh001c
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ 0,
+ ERRL_TEST_APLT,
+ l_rc);
+ }
+ else
+ {
+ ERRL_DBG("**********************************************");
+ ERRL_DBG("* errl Test Passed (errlTest.c)");
+ ERRL_DBG("**********************************************");
+ }
+
+ ERRL_DBG("Exit errlTestMain\n");
+
+ return l_err;
+}
+
+
+// Function Specification
+//
+// Name: errlTestErrorHandling
+//
+// Description: errlTestErrorHandling
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t errlTestErrorHandling()
+{
+ uint32_t l_rc = 0;
+ errlHndl_t l_errlHnd = NULL;
+ uint8_t l_dataPtr[10];
+ uint16_t l_entrySizeBefore = 0;
+ uint16_t l_entrySizeAfter = 0;
+
+ ERRL_DBG(" START");
+ do
+ {
+ /****************************************************/
+ // Test createErrl with incorrect parameter
+ // Set ERRL_SEVERITY to 0x04, out of range so log won't be created
+ l_errlHnd = createErrl(TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, 0x04, NULL, 0, 0x01, 0x02); // @nh001c
+ CHECK_CONDITION( l_errlHnd == INVALID_ERR_HNDL, l_rc);
+
+ /****************************************************/
+ // Test addTraceToErrl with incorrect parameter
+ // Create a log
+ l_errlHnd = createErrl(TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE, NULL, 0, 0x01, 0x02); // @nh001c
+ CHECK_CONDITION( l_errlHnd != INVALID_ERR_HNDL, l_rc);
+
+ // i_trace = NULL, so entry size doesn't change
+ l_entrySizeBefore = l_errlHnd->iv_userDetails.iv_entrySize;
+ addTraceToErrl(NULL, 5, l_errlHnd);
+ l_entrySizeAfter = l_errlHnd->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION(l_entrySizeBefore == l_entrySizeAfter, l_rc);
+
+ // i_traceSz = 0, entry size doesn't change
+ l_entrySizeBefore = l_errlHnd->iv_userDetails.iv_entrySize;
+ addTraceToErrl(g_trac_inf, 0, l_errlHnd); // @at012c
+ l_entrySizeAfter = l_errlHnd->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeBefore == l_entrySizeAfter, l_rc);
+
+ // io_err = NULL, entry size doesn't change
+ l_entrySizeBefore = l_errlHnd->iv_userDetails.iv_entrySize;
+ addTraceToErrl(g_trac_inf, 32, NULL); // @at012c
+ l_entrySizeAfter = l_errlHnd->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeBefore == l_entrySizeAfter, l_rc);
+
+ // test addTraceToErrl after log is comitted so entry size doesn't change
+ errlHndl_t l_errlHndx = l_errlHnd;
+ commitErrl(&l_errlHnd);
+ l_entrySizeBefore = l_errlHndx->iv_userDetails.iv_entrySize;
+ addTraceToErrl(g_trac_inf, 32, l_errlHndx); // @at012c
+ l_entrySizeAfter = l_errlHndx->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeBefore == l_entrySizeAfter, l_rc);
+
+ deleteErrl(&l_errlHndx);
+ CHECK_CONDITION( l_errlHndx == NULL, l_rc);
+
+ // io_err = INVALID_ERR_HNDL
+ // We are making sure that this function
+ // handles a INVALID_ERR_HNDL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ l_errlHnd = INVALID_ERR_HNDL;
+ addTraceToErrl(g_trac_inf, 32, l_errlHnd); // @at012c
+
+ /****************************************************/
+ // Test commitErrl with incorrect parameter
+ // io_err = NULL
+ // We are making sure that this function
+ // handles a NULL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ commitErrl( NULL);
+
+ // l_errlHnd should be set to NULL
+ l_errlHnd = INVALID_ERR_HNDL;
+ commitErrl(&l_errlHnd);
+ CHECK_CONDITION( l_errlHnd == NULL, l_rc);
+
+ /****************************************************/
+ // Test deleteErrl with incorrect parameter
+ // io_err = NULL
+ // We are making sure that this function
+ // handles a NULL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ deleteErrl( NULL);
+
+ // l_errlHnd should be set to NULL
+ l_errlHnd = INVALID_ERR_HNDL;
+ deleteErrl(&l_errlHnd);
+ CHECK_CONDITION( l_errlHnd == NULL, l_rc);
+
+ /****************************************************/
+ // Test addCalloutToErrl with incorrect parameter
+ // Set io_err to NULL
+ // We are making sure that this function
+ // handles a NULL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ addCalloutToErrl(NULL, ERRL_CALLOUT_TYPE_HUID, 0, ERRL_CALLOUT_PRIORITY_LOW); // @jh001c
+
+ // Set io_err to INVALID_ERR_HNDL
+ // We are making sure that this function
+ // handles a INVALID_ERR_HNDL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ addCalloutToErrl(INVALID_ERR_HNDL, ERRL_CALLOUT_TYPE_HUID, 0, ERRL_CALLOUT_PRIORITY_LOW); // @jh001c
+
+ /****************************************************/
+ // Test addUsrDtlsToErrl with incorrect parameter
+ // Create a log
+ l_errlHnd = createErrl(TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE, NULL, 0, 0x01, 0x02); // @nh001c
+ CHECK_CONDITION( l_errlHnd != INVALID_ERR_HNDL, l_rc);
+
+ // io_err = NULL
+ // We are making sure that this function
+ // handles a NULL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ addUsrDtlsToErrl(NULL, l_dataPtr, 10, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA);
+
+ // io_err = INVALID_ERR_HNDL
+ // We are making sure that this function
+ // handles a INVALID_ERR_HNDL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ addUsrDtlsToErrl(INVALID_ERR_HNDL, l_dataPtr, 10, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA);
+
+ // i_dataPtr = NULL so entry size doesn't change
+ l_entrySizeBefore = l_errlHnd->iv_userDetails.iv_entrySize;
+ addUsrDtlsToErrl(l_errlHnd, NULL, 10, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA);
+ l_entrySizeAfter = l_errlHnd->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeBefore == l_entrySizeAfter, l_rc);
+
+ // i_size = 0 so so entry size doesn't change
+ l_entrySizeBefore = l_errlHnd->iv_userDetails.iv_entrySize;
+ addUsrDtlsToErrl(l_errlHnd, l_dataPtr, 0, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA);
+ l_entrySizeAfter = l_errlHnd->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeBefore == l_entrySizeAfter, l_rc);
+
+ // test addUsrDtlsToErrl after log is committed so entry size doesn't change
+ l_errlHndx = l_errlHnd;
+ commitErrl(&l_errlHnd);
+ l_entrySizeBefore = l_errlHndx->iv_userDetails.iv_entrySize;
+ addUsrDtlsToErrl(l_errlHndx, l_dataPtr, 10, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA);
+ l_entrySizeAfter = l_errlHndx->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeBefore == l_entrySizeAfter, l_rc);
+
+ deleteErrl(&l_errlHndx);
+ CHECK_CONDITION( l_errlHndx == NULL, l_rc);
+
+ /****************************************************/
+ // Test setErrlSevToInfo with incorrect parameter
+ // Set io_err to NULL.
+ // We are making sure that this function
+ // handles a NULL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ setErrlSevToInfo(NULL);
+
+ // Set io_err to INVALID_ERR_HNDL
+ // We are making sure that this function
+ // handles a INVALID_ERR_HNDL being passed, and that we can't verify if
+ // an error occured by checking anything. (It will just cause
+ // a TLB exception)
+ setErrlSevToInfo(INVALID_ERR_HNDL);
+ }while(0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: errlTestCreateCommitDeleteLog
+//
+// Description: errlTestCreateCommitDeleteLog
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t errlTestCreateCommitDeleteLog()
+{
+ ERRL_DBG("START");
+ uint32_t l_rc = 0;
+
+ do
+ {
+ /****************************************************/
+ // Test create log
+ errlHndl_t l_handle = NULL;
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_CALLHOME_DATA, g_trac_inf, 512, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ ERRL_DBG("Slots after Creating call home log" );
+ ppdumpslot();
+
+ /****************************************************/
+ // Test commit log
+ errlHndl_t l_handle2 = l_handle;
+ commitErrl( &l_handle );
+ CHECK_CONDITION( (l_handle == NULL) &&
+ (l_handle2->iv_userDetails.iv_committed == 1), l_rc);
+
+ ERRL_DBG("Slots after Commiting call home log" );
+ dumpLog( l_handle2, l_handle2->iv_userDetails.iv_entrySize );
+ ppdumpslot();
+
+ /****************************************************/
+ // Test delete log
+ deleteErrl(&l_handle2);
+ CHECK_CONDITION( l_handle2 == NULL, l_rc);
+
+ ERRL_DBG("Slots after delete Log" );
+ ppdumpslot();
+
+ ERRL_DBG("END \n");
+
+ }while(0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: errlTestAddUsrDtlsToErrl
+//
+// Description: errlTestAddUsrDtlsToErrl
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t errlTestAddUsrDtlsToErrl()
+{
+ uint32_t l_rc = 0;
+ ERRL_DBG("START");
+ uint16_t l_entrySizeBefore = 0;
+ uint16_t l_entrySizeAfter = 0;
+
+ do
+ {
+ // Create three err logs
+ errlHndl_t l_handle = NULL;
+ errlHndl_t l_handle2 = NULL;
+ errlHndl_t l_handle3 = NULL;
+
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_UNRECOVERABLE, NULL, 512, 0x1, 0x2); // @nh001c
+ l_handle2 = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_CALLHOME_DATA, NULL, 512, 0x1, 0x2); // @nh001c
+ l_handle3 = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_INFORMATIONAL, NULL, 512, 0x1, 0x2); // @nh001c
+
+ // l_handle will set to NULL after calling the commitErrl, so we need to store it
+ errlHndl_t l_handleX = l_handle;
+ errlHndl_t l_handle2X = l_handle2;
+ errlHndl_t l_handle3X = l_handle3;
+ ERRL_DBG("Slots after Create - 3 slots should be used (one of each");
+ ppdumpslot();
+
+ CHECK_CONDITION( (l_handle != INVALID_ERR_HNDL) &&
+ (l_handle2 != INVALID_ERR_HNDL) &&
+ (l_handle3 != INVALID_ERR_HNDL), l_rc);
+
+ /****************************************************/
+ // Test sizelimit for addUsrDtlsToErrl
+ // Add "user details" data that exceeds the max size for l_handle
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ memset( G_data, 0xCC, sizeof( G_data ) );
+ addUsrDtlsToErrl( l_handle, G_data, sizeof( G_data ), ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeAfter == MAX_ERRL_ENTRY_SZ, l_rc);
+
+ // Add "user details" data that exceeds the max size for l_handle2
+ l_entrySizeBefore = l_handle2->iv_userDetails.iv_entrySize;
+ memset( G_data, 0xDD, sizeof( G_data ) );
+ addUsrDtlsToErrl( l_handle2, G_data, sizeof( G_data ), ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_CALLHOME_DATA );
+ l_entrySizeAfter = l_handle2->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeAfter == MAX_ERRL_CALL_HOME_SZ, l_rc);
+
+ // Add "user details" with size 76 for l_handle3
+ l_entrySizeBefore = l_handle3->iv_userDetails.iv_entrySize;
+ memset( G_data, 0xEE, sizeof( G_data ) );
+ addUsrDtlsToErrl( l_handle3, G_data, 76, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ l_entrySizeAfter = l_handle3->iv_userDetails.iv_entrySize;
+ // (header + 76) is the size that add to entry
+ CHECK_CONDITION( l_entrySizeAfter == (l_entrySizeBefore+sizeof(ErrlUserDetailsEntry_t)+76), l_rc);
+
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ dumpLog( l_handle2, l_handle2->iv_userDetails.iv_entrySize );
+ dumpLog( l_handle3, l_handle3->iv_userDetails.iv_entrySize );
+
+ commitErrl( &l_handle );
+ commitErrl( &l_handle2 );
+ commitErrl( &l_handle3 );
+ ERRL_DBG("Slots after Commit - 3 slots should be used/committed");
+ ppdumpslot();
+
+ deleteErrl(&l_handleX);
+ deleteErrl(&l_handle2X);
+ deleteErrl(&l_handle3X);
+ CHECK_CONDITION( (l_handleX == NULL) &&
+ (l_handle2X == NULL) &&
+ (l_handle3X == NULL), l_rc);
+
+ ERRL_DBG("Slots after delete Log - All slots should be empty");
+ ppdumpslot();
+
+ /****************************************************/
+ // Test sizelimit for addUsrDtlsToErrl with continuous calls
+ // Create log with 512 bytes trace
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE, g_trac_inf, 512, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ // l_handle will set to NULL after calling the commitErrl, so we need to store it
+ l_handleX = l_handle;
+ ppdumpslot();
+
+ // add 256 bytes of "user details" (512+256)
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ memset( G_data, 0xAA, sizeof( G_data ) );
+ addUsrDtlsToErrl( l_handle, G_data, 256, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ ERRL_DBG("Slots after create + 256 bytes" );
+ ppdumpslot();
+ // (header + 256) is the size that add to entry
+ CHECK_CONDITION( l_entrySizeAfter == (l_entrySizeBefore+sizeof(ErrlUserDetailsEntry_t)+256), l_rc);
+
+ // add 512 bytes of "user details" (512+256+512)
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ memset( G_data, 0xBB, sizeof( G_data ) );
+ addUsrDtlsToErrl( l_handle, G_data, 512, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ ERRL_DBG("Slots after create + 256 + 512 bytes");
+ ppdumpslot();
+ // (header + 512) is the size that add to entry
+ CHECK_CONDITION( l_entrySizeAfter == (l_entrySizeBefore+sizeof(ErrlUserDetailsEntry_t)+512), l_rc);
+
+ // add 1024 bytes of "user details" (512+256+512+1024), the entry size is more than 2048 now
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ memset( G_data, 0xCC, sizeof( G_data ) );
+ addUsrDtlsToErrl( l_handle, G_data, 1024, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ ERRL_DBG("Slots after create + 256 + 512 +1024 bytes");
+ ppdumpslot();
+ // (header + 1024) is the size that add to entry
+ CHECK_CONDITION( l_entrySizeAfter <= MAX_ERRL_ENTRY_SZ, l_rc); // @at012c
+
+ commitErrl( &l_handle );
+ deleteErrl(&l_handleX);
+ ERRL_DBG("Slots should now be empty");
+ ppdumpslot();
+ ERRL_DBG("END \n");
+ }while(0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: errlTestAddTraceToErrl
+//
+// Description: errlTestAddTraceToErrl
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t errlTestAddTraceToErrl()
+{
+ uint32_t l_rc = 0;
+ uint16_t l_entrySizeBefore = 0;
+ uint16_t l_entrySizeAfter = 0;
+ ERRL_DBG("START");
+
+ do
+ {
+ // Create one err log
+ errlHndl_t l_handle = NULL;
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE, NULL, 512, 0x1, 0x2); // @nh001c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ // l_handle will set to NULL after calling the commitErrl, so we need to store it
+ errlHndl_t l_handleX = l_handle;
+ ERRL_DBG("Slots after Create - 1 slots should be used (one of each");
+ ppdumpslot();
+
+ /****************************************************/
+ // Test sizelimit for addTraceToErrl
+ // Add "trace" data that exceeds the max size
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ addTraceToErrl(g_trac_inf, MAX_BUFFER_SIZE, l_handle); // @at012c
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ CHECK_CONDITION( l_entrySizeAfter <= MAX_ERRL_ENTRY_SZ, l_rc); // @at012c
+
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ commitErrl( &l_handle );
+ ERRL_DBG("Slots after Commit - 1 slots should be used/committed");
+ ppdumpslot();
+
+ deleteErrl(&l_handleX);
+ ERRL_DBG("Slots after delete Log - All slots should be empty");
+ ppdumpslot();
+
+ /****************************************************/
+ // Test sizelimit for addTraceToErrl with continuous calls
+ // Create log with 512 bytes trace
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE, g_trac_inf, 512, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ // l_handle will set to NULL after calling the commitErrl, so we need to store it
+ l_handleX = l_handle;
+ ppdumpslot();
+
+ // Add 256 bytes of trace (512+256)
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ addTraceToErrl(g_trac_inf, 256, l_handle); // @at012c
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ ERRL_DBG("Slots after create + 256 bytes" );
+ ppdumpslot();
+ // (header + 256) is the size that add to entry
+ CHECK_CONDITION( l_entrySizeAfter <= (l_entrySizeBefore+sizeof(ErrlUserDetailsEntry_t)+256), l_rc); // @at012c
+
+ // Add 512 bytes of trace (512+256+512)
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ addTraceToErrl(g_trac_inf, 512, l_handle); // @at012c
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ ERRL_DBG("Slots after create + 256 + 512 bytes");
+ ppdumpslot();
+ CHECK_CONDITION( l_entrySizeAfter <= (l_entrySizeBefore+sizeof(ErrlUserDetailsEntry_t)+512), l_rc); // @at012c
+
+ // Add 1024 bytes of trace (512+256+512+1024), the entry size is more than 2048 now
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ addTraceToErrl(g_trac_inf, 1024, l_handle); // @at012c
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ ERRL_DBG("Slots after create + 256 + 512 bytes");
+ ppdumpslot();
+ CHECK_CONDITION( l_entrySizeAfter <= MAX_ERRL_ENTRY_SZ, l_rc); // @at012c
+
+ commitErrl( &l_handle );
+ deleteErrl(&l_handleX);
+ ERRL_DBG("Slots should now be empty");
+ ppdumpslot();
+ ERRL_DBG("END \n");
+
+ }while(0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: errlTestTime
+//
+// Description: errlTestTime
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t errlTestTime()
+{
+ uint32_t l_rc = 0;
+
+ do
+ {
+ ERRL_DBG("START");
+ errlHndl_t l_handle = NULL;
+ uint64_t l_start = 0;
+ uint64_t l_end = 0;
+
+
+ /****************************************************/
+ // Check timeStamp
+ // Create one log
+ l_start = ssx_timebase_get();
+ l_handle = createErrl( 0x1716, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_CALLHOME_DATA, g_trac_inf, 128, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+
+ // check time stamp
+ errlHndl_t l_handle2 = l_handle;
+ commitErrl( &l_handle );
+ l_end = ssx_timebase_get();
+ CHECK_CONDITION( (l_handle2->iv_userDetails.iv_timeStamp >= l_start) &&
+ (l_handle2->iv_userDetails.iv_timeStamp <= l_end ), l_rc);
+
+ deleteErrl(&l_handle2);
+ ERRL_DBG("END \n");
+
+ }while(0);
+
+ return l_rc;
+}
+
+/*****************************************************************************/
+// errlTestCreate2InfoCallhomeLog
+/*****************************************************************************/
+uint32_t errlTestCreate2InfoCallhomeLog()
+{
+ ERRL_DBG("START" );
+ uint32_t l_rc = 0;
+
+ do
+ {
+ /****************************************************/
+ // Check creating Info logs twice
+ // Create first Info log
+ errlHndl_t l_handle = NULL;
+ errlHndl_t l_handle2= NULL;
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_INFORMATIONAL,g_trac_inf, 32, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ // Create second Info log and it should fail
+ l_handle2 = createErrl( 0x2727, 0x19, OCC_NO_EXTENDED_RC, ERRL_SEV_INFORMATIONAL, g_trac_inf, 32, 0x2, 0x3); // @nh001c @at012c
+ CHECK_CONDITION( l_handle2 == INVALID_ERR_HNDL, l_rc);
+
+ deleteErrl(&l_handle);
+
+ /****************************************************/
+ // Check creating Callhome logs twice
+ // Create first Callhome log
+ l_handle = NULL;
+ l_handle2= NULL;
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_CALLHOME_DATA,g_trac_inf, 32, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ // Create second Callhome log and it should fail
+ l_handle2 = createErrl( 0x2727, 0x19, OCC_NO_EXTENDED_RC, ERRL_SEV_CALLHOME_DATA, g_trac_inf, 32, 0x2, 0x3); // @nh001c @at012c
+ CHECK_CONDITION( l_handle2 == INVALID_ERR_HNDL, l_rc);
+
+ deleteErrl(&l_handle);
+
+ ERRL_DBG("END \n");
+ }while(0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: errlTestCreateMaxLogs
+//
+// Description: errlTestCreateMaxLogs
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t errlTestCreateMaxLogs()
+{
+ uint32_t l_rc = 0;
+
+ ERRL_DBG("START");
+ do
+ {
+
+ /****************************************************/
+ // Check max logs
+ ERRL_SEVERITY l_sev = 0;
+ errlHndl_t l_backupHandle[ERRL_MAX_SLOTS-2];
+ errlHndl_t l_handle = NULL;
+
+ uint32_t l_index = 0;
+ // Create 7 ERRL_SEV_PREDICTIVE or ERRL_SEV_UNRECOVERABLE slots randomly
+ for(l_index =0; l_index < ERRL_MAX_SLOTS-2; l_index++)
+ {
+
+ uint64_t l_time = ssx_timebase_get();
+ l_sev = l_time%2 ? ERRL_SEV_PREDICTIVE : ERRL_SEV_UNRECOVERABLE;
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, l_sev, g_trac_inf, 512, 0x1, l_index); // @nh001c @at012c
+ CHECK_CONDITION( (l_handle != INVALID_ERR_HNDL) &&
+ (l_handle != NULL), l_rc);
+
+ // backup handle
+ l_backupHandle[l_index] = l_handle;
+
+ ERRL_DBG("Log Created @ %p with Sev: %d\n",l_handle, l_sev );
+ // addUsrDtlsToErrl
+ memset( G_data, l_index, sizeof( G_data ) );
+ addUsrDtlsToErrl( l_handle, G_data, sizeof(G_data), ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+
+ // commitErrl( &l_handle );
+ }
+ // check if something wrong in for loop
+ if(l_rc != 0)
+ break;
+
+ // Create one more and it should fail
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, l_sev, g_trac_inf, 512, 0x1, l_index); // @nh001c @at012c
+ CHECK_CONDITION( l_handle == INVALID_ERR_HNDL, l_rc);
+
+ // delete errl
+ for(l_index = 0; l_index < ERRL_MAX_SLOTS-2; l_index++)
+ {
+ deleteErrl(&l_backupHandle[l_index]);
+ }
+ ppdumpslot();
+
+ /****************************************************/
+ // Check log id overflow
+ for(l_index = 0; l_index < 256; l_index++)
+ {
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, l_sev, g_trac_inf, 512, 0x1, l_index); // @nh001c @at012c
+ CHECK_CONDITION( (l_handle != INVALID_ERR_HNDL) &&
+ (l_handle != NULL), l_rc);
+
+ deleteErrl(&l_handle);
+ }
+
+ ERRL_DBG("END \n");
+ }while(0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: errlTestCallouts
+//
+// Description: errlTestCallouts
+//
+// Flow: FN=None
+//
+// End Function Specification
+// @jh001c
+uint32_t errlTestCallouts()
+{
+ uint32_t l_rc = 0;
+ ERRL_DBG("START");
+
+ do
+ {
+ errlHndl_t l_handle = NULL;
+ ERRL_DBG("--------------------------------\n");
+
+ /****************************************************/
+ // Check max callouts
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE,g_trac_inf, 128, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ ERRL_CALLOUT_PRIORITY l_array[8] = {
+ ERRL_CALLOUT_PRIORITY_HIGH,
+ ERRL_CALLOUT_PRIORITY_MED,
+ ERRL_CALLOUT_PRIORITY_LOW,
+ ERRL_CALLOUT_PRIORITY_HIGH,
+ ERRL_CALLOUT_PRIORITY_MED,
+ ERRL_CALLOUT_PRIORITY_MED,
+ ERRL_CALLOUT_PRIORITY_LOW,
+ ERRL_CALLOUT_PRIORITY_LOW,
+ };
+
+ ERRL_CALLOUT_TYPE l_type[8] = {
+ ERRL_CALLOUT_TYPE_HUID,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_CALLOUT_TYPE_HUID,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_CALLOUT_TYPE_HUID,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_CALLOUT_TYPE_HUID,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ };
+
+ // add 6 (ERRL_MAX_CALLOUTS) callouts
+ uint8_t l_index = 0;
+ for(l_index = 0; l_index < ERRL_MAX_CALLOUTS; l_index++)
+ {
+ ERRL_DBG("current callouts %d attempting to add callout # %d with type %d ,priority %d", l_handle->iv_numCallouts, l_index, l_type[l_index], l_array[l_index] );
+ addCalloutToErrl(l_handle,l_type[l_index],l_index,l_array[l_index]);
+ }
+ CHECK_CONDITION( l_handle->iv_numCallouts == ERRL_MAX_CALLOUTS, l_rc);
+
+ // add one more callout and it should fail
+ addCalloutToErrl(l_handle,l_type[0],l_index,l_array[0]);
+ CHECK_CONDITION( l_handle->iv_numCallouts == ERRL_MAX_CALLOUTS, l_rc);
+
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ deleteErrl( &l_handle );
+ ppdumpslot();
+
+ /****************************************************/
+ // Check callouts after errl is committed
+ // Create log
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE,g_trac_inf, 32, 0x1, 0x2); // @nh001c @at012c
+ errlHndl_t l_log = l_handle;
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ // Commit log and add callout. But adding callout should fail
+ commitErrl( &l_handle );
+ addCalloutToErrl(l_handle,l_type[0],0,l_array[0]);
+ CHECK_CONDITION( l_log->iv_numCallouts == ERRL_MAX_CALLOUTS, l_rc); // @jh003c
+
+ deleteErrl(&l_log);
+
+ /****************************************************/
+ // Check addCalloutToErrl for ERRL_SEV_INFORMATIONAL log
+ // Create ERRL_SEV_INFORMATIONAL log
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_INFORMATIONAL,g_trac_inf, 128, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+ if(l_handle == INVALID_ERR_HNDL)
+
+ // add one callout and it should fail
+ addCalloutToErrl(l_handle,l_type[0],l_index,l_array[0]);
+ CHECK_CONDITION( l_handle->iv_numCallouts == 0, l_rc);
+
+ dumpLog( l_handle, l_handle->iv_userDetails.iv_entrySize );
+ deleteErrl( &l_handle );
+ ppdumpslot();
+
+ ERRL_DBG("END \n");
+ }while(0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: errlTestSetErrlSevToInfo
+//
+// Description: errlTestSetErrlSevToInfo
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t errlTestSetErrlSevToInfo()
+{
+ uint32_t l_rc = 0;
+ ERRL_DBG("START");
+
+ do
+ {
+ errlHndl_t l_handle = NULL;
+
+ /****************************************************/
+ // Check setErrlSevToInfo
+ // Create ERRL_SEV_PREDICTIVE log
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE,g_trac_inf, 128, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ // Add callout
+ addCalloutToErrl(l_handle,ERRL_CALLOUT_TYPE_HUID,0x00,ERRL_CALLOUT_PRIORITY_LOW); // @jh001c
+ CHECK_CONDITION( l_handle->iv_numCallouts == 1, l_rc);
+
+ // Call setErrlSevToInfo. Callouts within log should be cleared and
+ // iv_severity should be set to ERRL_SEV_INFORMATIONAL
+ setErrlSevToInfo(l_handle);
+ CHECK_CONDITION( (l_handle->iv_numCallouts == 0) &&
+ (l_handle->iv_severity == ERRL_SEV_INFORMATIONAL), l_rc);
+
+ deleteErrl( &l_handle );
+ ppdumpslot();
+
+ /****************************************************/
+ // Check setErrlSevToInfo after errl is committed
+ // Create log
+ l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE,g_trac_inf, 128, 0x1, 0x2); // @nh001c @at012c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ errlHndl_t l_log = l_handle;
+
+ // Add callout
+ addCalloutToErrl(l_handle,ERRL_CALLOUT_TYPE_HUID,0x00,ERRL_CALLOUT_PRIORITY_LOW); // @jh001c
+ CHECK_CONDITION( l_handle->iv_numCallouts == 1, l_rc);
+
+ // Commit log and call setErrlSevToInfo. But setErrlSevToInfo will do nothing
+ commitErrl( &l_handle );
+ setErrlSevToInfo(l_handle);
+ CHECK_CONDITION( (l_log->iv_numCallouts == ERRL_MAX_CALLOUTS) && // @jh003c
+ (l_log->iv_severity == ERRL_SEV_PREDICTIVE), l_rc);
+
+ deleteErrl(&l_log);
+ ERRL_DBG("END \n");
+
+ }while(0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: errlTestWordAlign
+//
+// Description: errlTestWordAlign
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t errlTestWordAlign()
+{
+ uint32_t l_rc = 0;
+ uint16_t l_entrySizeBefore = 0;
+ uint16_t l_entrySizeAfter = 0;
+ ERRL_DBG("START");
+
+ do
+ {
+ /****************************************************/
+ // Test word align for addUsrDtlsToErrl
+ // Create log
+ errlHndl_t l_handle = createErrl( TEST_MODULE_ID, 0x08, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE, NULL, 0, 0x1, 0x2); // @nh001c
+ CHECK_CONDITION( l_handle != INVALID_ERR_HNDL, l_rc);
+
+ // l_handle will set to NULL after calling the commitErrl, so we need to store it
+ errlHndl_t l_handleX = l_handle;
+ ppdumpslot();
+
+ // add 13 bytes of "user details"
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ memset( G_data, 0xAA, sizeof( G_data ) );
+ addUsrDtlsToErrl( l_handle, G_data, 13, ERRL_USR_DTL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA );
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ ERRL_DBG("Slots after create + 13 bytes" );
+ ppdumpslot();
+ // (header + WORDALIGN(13)) is the size that add to entry
+ CHECK_CONDITION( l_entrySizeAfter == (l_entrySizeBefore+sizeof(ErrlUserDetailsEntry_t)+16), l_rc);
+
+ /****************************************************/
+ // Test word align for addTraceToErrl
+ // add 21 bytes of trace
+ l_entrySizeBefore = l_handle->iv_userDetails.iv_entrySize;
+ addTraceToErrl(g_trac_inf, 21, l_handle); // @at012c
+ l_entrySizeAfter = l_handle->iv_userDetails.iv_entrySize;
+ ERRL_DBG("Slots after create + 21 bytes" );
+ ppdumpslot();
+ // (header + WORDALIGN(21)) is the size that add to entry
+ CHECK_CONDITION( l_entrySizeAfter <= (l_entrySizeBefore+sizeof(ErrlUserDetailsEntry_t)+24), l_rc); // @at012c
+
+ commitErrl( &l_handle );
+ deleteErrl(&l_handleX);
+ ERRL_DBG("Slots should now be empty");
+ ppdumpslot();
+ ERRL_DBG("END \n");
+ }while(0);
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: dumpLog
+//
+// Description: dumpLog
+//
+// Flow: FN=None
+//
+// End Function Specification
+void dumpLog( errlHndl_t i_log, uint32_t i_len )
+{
+ uint32_t l_written = 0;
+ uint32_t l_counter = 0;
+ uint8_t * l_data = (uint8_t*) i_log;
+
+ printf("----------%p---------- \n", i_log );
+
+ if ( i_log == NULL )
+ return;
+
+ while ( l_counter < i_len)
+ {
+ printf("| %08X ", (uint32_t) l_data + l_counter);
+
+ // Display 16 bytes in Hex with 2 spaces in between
+ l_written = 0;
+ uint8_t i = 0;
+ for ( i = 0; i < 16 && l_counter < i_len; i++ )
+ {
+ l_written += printf("%02X",l_data[l_counter++]);
+
+ if ( ! ( l_counter % 4 ) )
+ {
+ l_written += printf(" ");
+ }
+ }
+
+ // Pad with spaces
+ uint8_t l_space[64] = {0};
+ memset( l_space, 0x00, sizeof( l_space ));
+ memset( l_space, ' ', 43-l_written);
+ printf("%s", l_space );
+
+ // Display ASCII
+ l_written = 0;
+ uint8_t l_char = 0;
+ for ( ; i > 0 ; i-- )
+ {
+ l_char = l_data[ l_counter-i ];
+
+ if ( isprint( l_char ) &&
+ ( l_char != '&' ) &&
+ ( l_char != '<' ) &&
+ ( l_char != '>' )
+ )
+ {
+ l_written += printf("%c",l_char );
+ }
+ else
+ {
+ l_written += printf("." );
+ }
+ }
+
+ // Pad with spaces
+ uint8_t l_space2[64] = {0};
+ memset( l_space2, 0x00, sizeof( l_space2 ));
+ memset( l_space2, ' ', 19-l_written);
+ printf("%s\n", l_space2 );
+ }
+ printf("----------%p---------- \n", i_log );
+
+}
+
+// Function Specification
+//
+// Name: ppdumpslot
+//
+// Description: ppdumpslot
+//
+// Flow: FN=None
+//
+// End Function Specification
+void ppdumpslot(void)
+{
+ errlHndl_t l_array[ERRL_MAX_SLOTS] = {
+ (errlHndl_t)G_errslot1,
+ (errlHndl_t)G_errslot2,
+ (errlHndl_t)G_errslot3,
+ (errlHndl_t)G_errslot4,
+ (errlHndl_t)G_errslot5,
+ (errlHndl_t)G_errslot6,
+ (errlHndl_t)G_errslot7,
+ (errlHndl_t)G_infoslot,
+ (errlHndl_t)G_callslot,
+ };
+
+
+ printf("-------- \n");
+
+ uint8_t l_index = 0;
+ for(l_index = 0; l_index < ERRL_MAX_SLOTS; l_index++)
+ {
+ if(l_array[l_index]->iv_version != 0)
+ {
+ printf("slot[%01d] sz[%04d] id[%03d] @[%p] \n",l_index,l_array[l_index]->iv_userDetails.iv_entrySize, l_array[l_index]->iv_entryId, l_array[l_index]);
+ }
+ else
+ {
+ printf("slot[%01d] [0] \n",l_index);
+ }
+ }
+ printf("-------- \n");
+}
+
+/*****************************************************************************/
+// Image Header
+/*****************************************************************************/
+IMAGE_HEADER (G_errlTestMain,errlTestMain,ERRLTESTMAIN_ID,OCC_APLT_TEST);
+
diff --git a/src/occApplet/testApplet/linkTestApplet.cmd b/src/occApplet/testApplet/linkTestApplet.cmd
new file mode 100755
index 0000000..d5635d0
--- /dev/null
+++ b/src/occApplet/testApplet/linkTestApplet.cmd
@@ -0,0 +1,60 @@
+
+// $Id$
+
+
+// This linker script for the test applet
+
+#define APP_IMAGE_SRAM_START_ADDR 0xFFFFC000
+#define WORD_ALIGN 4
+#define BYTE_ALIGN 1024
+#ifdef OCCMK
+INCLUDE occLinkInputFile
+#endif
+
+MEMORY
+{
+ AppMem : ORIGIN = APP_IMAGE_SRAM_START_ADDR, LENGTH = 0x3C00
+}
+
+SECTIONS
+{
+ . = APP_IMAGE_SRAM_START_ADDR;
+
+ __START_ADDR__ = .;
+
+ ////////////////////////////////
+ // start read-only section
+ ////////////////////////////////
+ imageHeader . : { *(imageHeader) } > AppMem
+
+ ////////////////////////////////
+ // text section 1024 byte aligned
+ ////////////////////////////////
+ .text . : { *(.text) . = ALIGN(BYTE_ALIGN);} > AppMem
+ // NOTE: rodata section needs to be 1k aligned as it is used for setting
+ // mmu permission during applet execution
+ .rodata . : { *(.rodata) *(.got2) *(.rodata.str1.1) *(.rodata.str1.4) . = ALIGN(BYTE_ALIGN);} > AppMem
+
+ __READ_ONLY_DATA_LEN__ = . - APP_IMAGE_SRAM_START_ADDR ;
+
+ ////////////////////////////////
+ // start writeable section
+ ////////////////////////////////
+ __WRITEABLE_DATA_ADDR__ = .;
+
+ ////////////////////////////////
+ // read-write section 1024 byte aligned
+ ////////////////////////////////
+ .rela . : { *(.rela*) . = ALIGN(WORD_ALIGN);} > AppMem
+ // NOTE: rwdata section needs to be 1024 bytes aligned for setting mmu
+ // permission, so that applet total size is 1024 bytes aligned.
+ // It is needed for doing DMA copy of the applet.
+ // NOTE: add one dummy bye "BYTE(1)" to prevent this section empty. If section
+ // is empty, "ALIGN(BYTE_ALIGN)" won't work.
+ .rwdata . : { *(.data) *(.bss) *(COMMON) BYTE(1); . = ALIGN(BYTE_ALIGN);} > AppMem
+
+ __WRITEABLE_DATA_LEN__ = . - __WRITEABLE_DATA_ADDR__ ;
+
+ // NOTE: make sure the whole image is 128-byte aligned
+
+}
diff --git a/src/occApplet/testApplet/occLinkInputFile b/src/occApplet/testApplet/occLinkInputFile
new file mode 100644
index 0000000..273836b
--- /dev/null
+++ b/src/occApplet/testApplet/occLinkInputFile
@@ -0,0 +1 @@
+INPUT ( pstApplet.o )
diff --git a/src/occApplet/testApplet/pstApplet.c b/src/occApplet/testApplet/pstApplet.c
new file mode 100755
index 0000000..a658d1a
--- /dev/null
+++ b/src/occApplet/testApplet/pstApplet.c
@@ -0,0 +1,124 @@
+/******************************************************************************
+// @file pstApplet.c
+// @brief pstate_applet
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section pstApplet.c PSTAPPLET.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * prpulusa 02/05/14 created
+ * @gm043 928988 milesg 06/19/14 checked in to cmvc after some bug fixes.
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <errl.h> // For error handle
+#include "ssx_io.h" // For printfs
+#include <trac.h> // For traces
+#include <appletId.h> // For applet ID
+#include "ssx.h"
+#include "pgp_common.h"
+#include "pstates.h"
+#include "gpsm.h"
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define MYENTRYPOINT_ID "pstApplet\0"
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+//*************************************************************************
+// Entry point function
+//*************************************************************************
+errlHndl_t myEntryPoint(void * i_arg)
+{
+
+ TRAC_INFO("Enter");
+ //initialize variables
+ errlHndl_t l_err = NULL;
+ int rc=0;
+ GlobalPstateTable * l_gpst_ptr = NULL;
+ l_gpst_ptr = gpsm_gpst();
+ unsigned int deconfigured_cores = in32(PMC_CORE_DECONFIGURATION_REG);
+ pcbs_power_management_control_reg_t pmcr;
+ pmcr.value=0;
+ unsigned char trace_count[PGP_NCORES] = {0};
+
+
+ //get minimum and maximum p states
+ Pstate min_ps = gpst_pmin(l_gpst_ptr);
+ Pstate max_ps = gpst_pmax(l_gpst_ptr);
+ int iterations;
+ for(iterations=0;iterations<1000;iterations++){
+ //loop through the functioning cores
+ int core;
+ for (core = 0; core < PGP_NCORES; core++) {
+ if (deconfigured_cores & (0x80000000 >> core)) continue;
+ //go through all the valid power states
+ int ps;
+ for (ps=min_ps;ps<=max_ps;ps++){
+
+ //Issue scoms l
+ pmcr.fields.local_pstate_req=ps;
+ pmcr.fields.global_pstate_req=ps;
+ rc = _putscom(CORE_CHIPLET_ADDRESS(PCBS_POWER_MANAGEMENT_CONTROL_REG,core),pmcr.value, SCOM_TIMEOUT * 20);
+ if (rc) {
+ if(trace_count[core] < 5)
+ {
+ trace_count[core]++;
+ TRAC_ERR("pstApplet: putscom failed on core %d with rc = 0x%08x, deconfig_cores = 0x%08x, iteration = %d",
+ core, rc, deconfigured_cores, iterations);
+ }
+ if(rc == 7)
+ {
+ continue;
+ }
+ break;
+ }
+ //Wait 500us before changing the pstate
+ ssx_sleep(SSX_MICROSECONDS(500));
+
+ }
+ }
+ }
+ TRAC_INFO("Exit");
+ return l_err;
+}
+
+//*************************************************************************
+// Image Header
+//*************************************************************************
+IMAGE_HEADER (G_myEntryPoint,myEntryPoint,MYENTRYPOINT_ID,OCC_APLT_TEST);
diff --git a/src/occApplet/testApplet/sensorTest.c b/src/occApplet/testApplet/sensorTest.c
new file mode 100755
index 0000000..74a51be
--- /dev/null
+++ b/src/occApplet/testApplet/sensorTest.c
@@ -0,0 +1,1175 @@
+/******************************************************************************
+// @file sensorTest.c
+// @brief OCC Sensor test applet
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section sensorTest.c SENSORTEST.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * pbavari 08/17/2011 created
+ * @pb003 pbavari 08/31/2011 mini-sensor support
+ * @pb004 pbavari 09/14/2011 Changed to call sensor_init
+ * product applet
+ * @pb00A pbavari 11/14/2011 Moved sensor_init from applet and
+ * updated with latest design change
+ * @th005 thallet 11/21/2011 #if'd out reset of sensor test so
+ * it would compile
+ * @dw000 dwoodham 12/12/2011 Update call to IMAGE_HEADER macro
+ * @at001 alvinwan 01/10/2012 Enable sensor test applet due to
+ * sensor interface design changes
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @at003 alvinwan 03/19/2012 Add test case for querySensorList.
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @ai003 ailutsar 11/06/2012 Fix OCC Test Applets so they don't crash OCC
+ * @th030 thallet 02/04/2013 Removed sensor list query b/c too big
+ * @gm002 885429 milesg 05/30/2013 change type/location to 16 bit bitmask
+ * @rt002 901927 tapiar 10/02/2013 update error log to use unique module id
+ * @fk009 942864 fmkassem 09/30/2014 BMC/HTMGT Poll command version 0x10 support.
+ * @endverbatim
+ *
+ *///*************************************************************************/
+#define SNSR_DEBUG
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <errl.h> // For error handle
+#include "ssx_io.h" // For printfs
+#include <sensor.h> // Sensor interfaces
+#include <occ_service_codes.h> // Reason code
+#include <errl.h> // For errlHndl_t
+#include <trac.h> // For traces
+#include <appletManager.h>
+#include <sensorQueryList.h>
+#include <appletId.h> // For applet ID @dw000a
+#include <aplt_service_codes.h> // For test applet module ID
+#include <testApltId.h> // For test applet ID
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define SENSORTESTMAIN_ID "Sensor Test\0"
+#define UINT16_MIN 0
+
+//sensor test module ID enumeration
+typedef enum
+{
+ TEST_NULL_POINTER = 0x00,
+ TEST_GET_SENSOR_BY_GSID = 0x01,
+ TEST_COMMON = 0x02,
+ TEST_QUERY_LIST = 0x03,
+
+} sensorTestModId;
+
+// sensor test return codes
+typedef enum
+{
+ SUCCESS_RC = 0x00000000,
+ GET_SNSR_FAILURE = 0x00000001,
+ SNSR_RESET_FAILURE = 0x00000002,
+ SNSR_UPDT_FAILURE = 0x00000003,
+ SNSR_UPDT_FAILURE2 = 0x00000004,
+ SNSR_UPDT_FAILURE3 = 0x00000005,
+ SNSR_UPDT_FAILURE4 = 0x00000006,
+ SNSR_UPDT_FAILURE5 = 0x00000007,
+ SNSR_RESET_FAILURE2 = 0x00000008,
+ RESET_WITH_VECTORIZE_FAILURE= 0x00000009,
+ VECTORIZE_FAILURE = 0x0000000A,
+ VECTORIZE_FAILURE2 = 0x0000000B,
+ VECTORIZE_FAILURE3 = 0x0000000C,
+ VECTOR_ADD_FAILURE = 0x0000000D,
+ VECTOR_ADD_FAILURE2 = 0x0000000E,
+ VECTOR_ADD_FAILURE3 = 0x0000000F,
+ VECTOR_UPDT_FAILURE = 0x00000010,
+ VECTOR_UPDT_FAILURE2 = 0x00000011,
+ VECTOR_UPDT_FAILURE3 = 0x00000012,
+ VECTOR_UPDT_FAILURE4 = 0x00000013,
+ VECTOR_UPDT_FAILURE5 = 0x00000014,
+ VECTOR_UPDT_FAILURE6 = 0x00000015,
+ VECTOR_UPDT_FAILURE7 = 0x00000016,
+ VECTOR_UPDT_FAILURE8 = 0x00000017,
+ VECTOR_UPDT_FAILURE9 = 0x00000018,
+ VECTOR_UPDT_FAILURE10 = 0x00000019,
+ VECTOR_ADD_FAILURE4 = 0x0000001A,
+ QUERY_LIST_FAILURE = 0x0000001B,
+ QUERY_LIST_FAILURE2 = 0x0000001C,
+ QUERY_LIST_FAILURE3 = 0x0000001D,
+ QUERY_LIST_FAILURE4 = 0x0000001E,
+ QUERY_LIST_FAILURE5 = 0x0000001F,
+ QUERY_LIST_FAILURE6 = 0x00000020,
+ QUERY_LIST_FAILURE7 = 0x00000021,
+ QUERY_LIST_FAILURE8 = 0x00000022,
+ QUERY_LIST_FAILURE9 = 0x00000023,
+ QUERY_LIST_FAILURE10 = 0x00000024,
+ QUERY_LIST_FAILURE11 = 0x00000025,
+ QUERY_LIST_FAILURE12 = 0x00000026,
+ QUERY_LIST_FAILURE13 = 0x00000027,
+ QUERY_LIST_FAILURE14 = 0x00000028,
+ GET_SNSR_FAILURE1 = 0x00000029,
+ GET_SNSR_FAILURE2 = 0x0000002A,
+} sensorTestRc;
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+// @ai003A
+// Stack size for test applet thread is only 4000 bytes,
+// put big structure here for prevent stack overflow
+
+// @th030 -- ifdef'd out b/c the sensor list is too big to test in applet
+#if 0
+sensorQueryList_t G_snsrList[NUMBER_OF_SENSORS_IN_LIST];
+#endif
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+uint32_t sensorTestNullPointer();
+uint32_t sensorTestGetSensorByGsid();
+uint32_t sensorTestCommon();
+void printSensor(sensor_t i_snsr);
+uint32_t sensorTestQueryList();
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: sensorTestMain
+//
+// Description: Entry point function
+//
+// Flow: FN=None
+//
+// End Function Specification
+errlHndl_t sensorTestMain(void * i_arg)
+{
+ SNSR_DBG("Enter sensorTestMain\n");
+ errlHndl_t l_err = NULL;
+
+ uint32_t l_rc = SUCCESS_RC;
+ uint8_t l_modId = 0;
+
+ do
+ {
+ l_rc = sensorTestNullPointer();
+ if( l_rc != SUCCESS_RC)
+ {
+ l_modId = TEST_NULL_POINTER;
+ TRAC_INFO("Failure on null pointer test");
+ break;
+ }
+
+ l_rc = sensorTestGetSensorByGsid();
+ if( l_rc != SUCCESS_RC)
+ {
+ l_modId = TEST_GET_SENSOR_BY_GSID;
+ TRAC_INFO("Failure on get sensor by Gsid test");
+ break;
+ }
+
+ l_rc = sensorTestCommon();
+ if( l_rc != SUCCESS_RC)
+ {
+ l_modId = TEST_COMMON;
+ TRAC_INFO("Failure on common test");
+ break;
+ }
+// @th030 - If'd out b/c the sensor list is too big for an applet
+#if 0
+ l_rc = sensorTestQueryList();
+ if( l_rc != SUCCESS_RC)
+ {
+ l_modId = TEST_QUERY_LIST;
+ TRAC_INFO("Failure on query list test");
+ break;
+ }
+#endif
+ } while (0);
+
+ if( l_rc != SUCCESS_RC)
+ {
+ SNSR_DBG("**********************************************\n");
+ SNSR_DBG("* Sensor Test Failed: ModId: 0x%x,l_rc: 0x%x\n",l_modId,l_rc);
+ SNSR_DBG("**********************************************\n");
+ /* @
+ * @errortype
+ * @moduleid TEST_APLT_MODID_SENSORTEST
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 Test Applet ID
+ * @userdata2 Return Code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure executing test applet
+ */
+ l_err = createErrl(TEST_APLT_MODID_SENSORTEST,
+ INTERNAL_FAILURE, // @nh001c
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ 0,
+ SNSR_TEST_APLT,
+ l_rc);
+ }
+ else
+ {
+ SNSR_DBG("**********************************************\n");
+ SNSR_DBG("* Sensor Test Passed\n");
+ SNSR_DBG("**********************************************\n");
+ }
+
+
+ SNSR_DBG("Exit sensorTestMain\n");
+
+ return l_err;
+}
+
+
+// Function Specification
+//
+// Name: sensorTestNullPointer
+//
+// Description: SensorTestNullPointers
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t sensorTestNullPointer()
+{
+ uint32_t l_rc = SUCCESS_RC;
+ /****************************************************/
+ // Try to clear minmax with NULL sensor pointer. Call will be no-op
+ sensor_clear_minmax(NULL);
+
+ /****************************************************/
+ // Try to reset sensor with NULL sensor pointer. Call will be no-op
+ sensor_reset(NULL);
+
+ /****************************************************/
+ // Try to vectorize with NULL sensor pointer and valid vector sensor.
+ // Call will be no-op
+ vectorSensor_t l_vecsnsr;
+ sensor_vectorize(NULL,&l_vecsnsr,0);
+
+ /****************************************************/
+ // Try to vectorize with NULL vector sensor pointer and valid sensor pointer
+ // Call will be no-op
+ sensor_t l_snsr;
+ sensor_vectorize(&l_snsr,NULL,0);
+
+ /****************************************************/
+ // Try to update sensor with NULL sensor pointer. Call will be no-op
+ sensor_update(NULL,1);
+
+ /****************************************************/
+ // Try to do vector update with NULL sensor pointer. Call will be no-op
+ sensor_vector_update(NULL,1);
+
+ /****************************************************/
+ // Try to enable vector sensor with NULL pointer. Call will be no-op
+ sensor_vector_elem_enable(NULL,1,1);
+
+ /****************************************************/
+ // Try to add vector element with NULL vector sensor pointer.
+ // Call will be no-op
+ sensor_t l_sensor;
+ sensor_vector_elem_add(NULL,1,&l_sensor);
+
+ /****************************************************/
+ // Try to add vector element with NULL element pointer.
+ // Call will be no-op
+ vectorSensor_t l_vecSensor;
+ sensor_vector_elem_add(&l_vecSensor,1,NULL);
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: sensorTestGetSensorByGsid
+//
+// Description: SensorTestGetSensorByGsid
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t sensorTestGetSensorByGsid()
+{
+ uint32_t l_rc = SUCCESS_RC;
+
+ do
+ {
+ /****************************************************/
+ // Try to get sensor with invalid GSID. It should return NULL
+ sensor_t * l_sensor = NULL;
+ l_sensor = getSensorByGsid(0xFFFF);
+
+ if( l_sensor != NULL)
+ {
+ l_rc = GET_SNSR_FAILURE;
+ break;
+ }
+
+ // Good path for this function is already tested with other test cases.
+
+ }while(0);
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: printSensor
+//
+// Description: printSensor
+//
+// Flow: FN=None
+//
+// End Function Specification
+void printSensor(sensor_t i_snsr)
+{
+ SNSR_DBG("Printing sensor information\n");
+ SNSR_DBG("*******************************\n");
+ SNSR_DBG("GSID: 0x%x\n",i_snsr.gsid);
+ SNSR_DBG("sample: 0x%x\n",i_snsr.sample);
+ SNSR_DBG("sample_min: 0x%x\n",i_snsr.sample_min);
+ SNSR_DBG("sample_max: 0x%x\n",i_snsr.sample_max);
+ SNSR_DBG("status.reset: 0x%x\n",i_snsr.status.reset);
+ SNSR_DBG("accumulator: 0x%x\n",i_snsr.accumulator);
+ SNSR_DBG("update_tag: 0x%x\n",i_snsr.update_tag);
+ SNSR_DBG("src_accum_snapshot: 0x%x\n",i_snsr.src_accum_snapshot);
+ SNSR_DBG("ipmi sensor id: 0x%x\n",i_snsr.ipmi_sid); //@fk009c
+ SNSR_DBG("vector sensor:\n");
+ if( i_snsr.vector != NULL)
+ {
+ SNSR_DBG("\toperation: 0x%x\n",i_snsr.vector->operation);
+ SNSR_DBG("\tsize: 0x%x\n",i_snsr.vector->size);
+ SNSR_DBG("\tmin_pos: 0x%x\n",i_snsr.vector->min_pos);
+ SNSR_DBG("\tmax_pos: 0x%x\n",i_snsr.vector->max_pos);
+ uint16_t i = 0;
+ for(; i < i_snsr.vector->size; i++)
+ {
+ SNSR_DBG("\t[%d].sample:0x%x\n",i,
+ i_snsr.vector->source_ptr[i]->sample);
+ } // end for loop
+ }
+ SNSR_DBG("mini sensor:\n");
+ if( i_snsr.mini_sensor != NULL)
+ {
+ SNSR_DBG("\tmini sensor sample: 0x%x\n",*(i_snsr.mini_sensor));
+ }
+ SNSR_DBG("*******************************\n");
+
+}
+
+
+// Function Specification
+//
+// Name: sensorTestCommon
+//
+// Description: sensorTestCommon
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t sensorTestCommon()
+{
+ uint32_t l_rc = SUCCESS_RC;
+ /****************************************************/
+ // Use test sensors to avoid the conflict with other components
+ // PROBE250US0, // Internal Sensor for debug via AMESTER
+ // PROBE250US1, // Internal Sensor for debug via AMESTER
+ // PROBE250US2, // Internal Sensor for debug via AMESTER
+ // PROBE250US3, // Internal Sensor for debug via AMESTER
+ // PROBE250US4, // Internal Sensor for debug via AMESTER
+ // PROBE250US5, // Internal Sensor for debug via AMESTER
+ // PROBE250US6, // Internal Sensor for debug via AMESTER
+ // PROBE250US7, // Internal Sensor for debug via AMESTER
+
+ sensor_t *l_sensor=getSensorByGsid(PROBE250US0);
+ sensor_t *l_sensor1=getSensorByGsid(PROBE250US1);
+ sensor_t *l_sensor2=getSensorByGsid(PROBE250US4);
+ sensor_t *l_sensor3=getSensorByGsid(PROBE250US7);
+ do
+ {
+ // make sure getSensorByGsid did not return NULL pointer.
+ if( (l_sensor == NULL) ||
+ (l_sensor1 == NULL) ||
+ (l_sensor2 == NULL) ||
+ (l_sensor3 == NULL))
+ {
+ l_rc = GET_SNSR_FAILURE2;
+ break;
+ }
+
+ //Check sensor gsid
+ if((l_sensor->gsid!=PROBE250US0) ||
+ (l_sensor1->gsid!=PROBE250US1) ||
+ (l_sensor2->gsid!=PROBE250US4) ||
+ (l_sensor3->gsid!=PROBE250US7) )
+ {
+ l_rc = GET_SNSR_FAILURE1;
+ break;
+ }
+
+ // Reset sensors before any other test so that we don't
+ // end up using old data if exists.
+ sensor_reset(l_sensor);
+ sensor_reset(l_sensor1);
+ sensor_reset(l_sensor2);
+ sensor_reset(l_sensor3);
+
+ /****************************************************/
+ uint16_t l_miniSnsr = 0;
+ // Set minisnsr to test minisnr reset and update
+ l_sensor2->mini_sensor = &l_miniSnsr;
+ // test update sensors.
+ sensor_update(l_sensor,10);
+ sensor_update(l_sensor1,11);
+ sensor_update(l_sensor2,12);
+
+ if( (l_sensor->sample != 10) ||
+ (l_sensor->mini_sensor != NULL) ||
+ (l_sensor->sample_max!=10) ||
+ (l_sensor->sample_min!=10) ||
+ (l_sensor1->sample != 11) ||
+ (l_sensor1->mini_sensor != NULL) ||
+ (l_sensor1->sample_max!=11) ||
+ (l_sensor1->sample_min!=11) ||
+ (l_sensor2->sample != 12) ||
+ (l_sensor2->mini_sensor == NULL) ||
+ (l_sensor2->sample_max!=12) ||
+ (l_sensor2->sample_min!=12) ||
+ (*(l_sensor2->mini_sensor) != 12) ||
+ (l_miniSnsr != 12)
+ )
+ {
+ l_rc = SNSR_UPDT_FAILURE;
+ break;
+ }
+
+ /****************************************************/
+ // test reset sensors without vectorize
+ sensor_reset(l_sensor2);
+ if( (l_sensor2->sample != 0) ||
+ (l_sensor2->status.reset != 0) ||
+ (l_sensor2->sample_min != UINT16_MAX) ||
+ (l_sensor2->sample_max != UINT16_MIN) ||
+ (*(l_sensor2->mini_sensor) != 0) ||
+ (l_miniSnsr != 0))
+ {
+ l_rc = SNSR_RESET_FAILURE;
+ break;
+ }
+ /****************************************************/
+ // test update of sensor with reset status bit set
+ l_sensor2->status.reset = 1;
+ sensor_update(l_sensor2,12);
+
+ if( (l_sensor2->sample != 12) ||
+ (l_sensor2->status.reset != 0) ||
+ (l_sensor2->sample_min != 12) ||
+ (l_sensor2->sample_max != 12) )
+ {
+ l_rc = SNSR_RESET_FAILURE2;
+ break;
+ }
+
+ /****************************************************/
+ // vectorize with reset status bit set
+ l_sensor->status.reset = 1;
+ vectorSensor_t l_vecSnsr;
+
+ sensor_vectorize(l_sensor,&l_vecSnsr, VECTOR_OP_MIN);
+
+ if(l_sensor->vector==NULL)
+ {
+ l_rc = VECTORIZE_FAILURE2;
+ break;
+ }
+ else
+ {
+ if(l_vecSnsr.operation!=VECTOR_OP_MIN)
+ {
+ l_rc = VECTORIZE_FAILURE3;
+ break;
+ }
+ }
+
+ /****************************************************/
+ // test getSensorByGsid with valid GSID
+ sensor_t * l_tempSensor = getSensorByGsid(PROBE250US0);
+
+ if((l_tempSensor == NULL) ||
+ (l_tempSensor->gsid!=PROBE250US0))
+ {
+ l_rc = GET_SNSR_FAILURE;
+ break;
+ }
+ else
+ {
+ if( l_tempSensor->vector->operation != VECTOR_OP_MIN)
+ {
+ l_rc = VECTORIZE_FAILURE;
+ break;
+ }
+ }
+ /****************************************************/
+ // test reset sensor with vectorize
+ sensor_reset(l_sensor);
+ if((l_sensor->vector->max_pos != VECTOR_SENSOR_DEFAULT_VAL) ||
+ (l_vecSnsr.max_pos != VECTOR_SENSOR_DEFAULT_VAL) ||
+ (l_sensor->vector->min_pos != VECTOR_SENSOR_DEFAULT_VAL) ||
+ (l_vecSnsr.min_pos != VECTOR_SENSOR_DEFAULT_VAL) ||
+ (l_sensor->sample_min != UINT16_MAX) ||
+ (l_sensor->sample_max != UINT16_MIN) )
+ {
+ l_rc = RESET_WITH_VECTORIZE_FAILURE;
+ break;
+ }
+
+ /****************************************************/
+ // test update of sensor with different min and max values
+ sensor_update(l_sensor,10);
+
+ sensor_update(l_sensor3,5);
+ if( (l_sensor3->sample != 5) ||
+ (l_sensor3->mini_sensor != NULL) ||
+ (l_sensor3->sample_max!=5) ||
+ (l_sensor3->sample_min!=5)
+ )
+ {
+ l_rc = SNSR_UPDT_FAILURE2;
+ break;
+ }
+ sensor_update(l_sensor3,2);
+ if( (l_sensor3->sample != 2) ||
+ (l_sensor3->mini_sensor != NULL) ||
+ (l_sensor3->sample_max!=5) ||
+ (l_sensor3->sample_min!=2)
+ )
+ {
+ l_rc = SNSR_UPDT_FAILURE3;
+ break;
+ }
+ sensor_update(l_sensor3,8);
+ if( (l_sensor3->sample != 8) ||
+ (l_sensor3->mini_sensor != NULL) ||
+ (l_sensor3->sample_max!=8) ||
+ (l_sensor3->sample_min!=2)
+ )
+ {
+ l_rc = SNSR_UPDT_FAILURE4;
+ break;
+ }
+ sensor_update(l_sensor3,5);
+ if( (l_sensor3->sample != 5) ||
+ (l_sensor3->mini_sensor != NULL) ||
+ (l_sensor3->sample_max!=8) ||
+ (l_sensor3->sample_min!=2)
+ )
+ {
+ l_rc = SNSR_UPDT_FAILURE5;
+ break;
+ }
+
+ /****************************************************/
+ // test adding vector element with invalid location
+ sensor_vector_elem_add(l_sensor->vector,0xFF,l_sensor3);
+
+ if( (l_sensor->vector->size != 0) ||
+ (l_vecSnsr.size != 0))
+ {
+ l_rc = VECTOR_ADD_FAILURE;
+ break;
+ }
+
+ /****************************************************/
+ // test adding vector element with valid location
+ sensor_vector_elem_add(l_sensor->vector,0,l_sensor2);
+
+ if( (l_sensor->vector->size != 1) ||
+ (l_vecSnsr.size != 1))
+ {
+ l_rc = VECTOR_ADD_FAILURE4;
+ break;
+ }
+
+ /****************************************************/
+ // test adding vector element with non-contiguous location.
+ // It should not add element to the vector
+ sensor_vector_elem_add(l_sensor->vector,2,l_sensor1);
+
+ if((l_sensor->vector->size != 1) ||
+ (l_vecSnsr.size != 1))
+ {
+ l_rc = VECTOR_ADD_FAILURE2;
+ break;
+ }
+
+ /****************************************************/
+ // test adding vector element with contiguous location
+ sensor_vector_elem_add(l_sensor->vector,1,l_sensor1);
+ sensor_vector_elem_add(l_sensor->vector,0,l_sensor3);
+
+ if((l_sensor->vector->size != 2) ||
+ (l_vecSnsr.size != 2))
+ {
+ l_rc = VECTOR_ADD_FAILURE3;
+ break;
+ }
+ sensor_vector_elem_add(l_sensor->vector,2,l_sensor2);
+
+ //so far the source sensors of vector sensor are:
+ // l_sensor3=5
+ // l_sensor1=11
+ // l_sensor2=12
+
+ /****************************************************/
+ // test disabling vector element with valid location
+ sensor_vector_elem_enable(l_sensor->vector,0,0);
+
+ /****************************************************/
+ // test updating vector element with min operation and
+ // element disabled
+
+ uint32_t l_tempacc=l_sensor->accumulator;
+ sensor_vector_update(l_sensor,0);
+ if( (l_sensor->sample != 11) || (l_sensor->sample_min != 10 ) ||
+ (l_sensor->sample_max != 11 ) ||
+ (l_sensor->accumulator != l_tempacc+11)||
+ (l_sensor->vector->min_pos != 1 ))
+ {
+ l_rc = VECTOR_UPDT_FAILURE;
+ break;
+ }
+
+ /****************************************************/
+ // test enabling vector element with min
+
+ l_tempacc=l_sensor->accumulator;
+ sensor_vector_elem_enable(l_sensor->vector,0,1);
+ sensor_vector_update(l_sensor,0);
+
+ if( (l_sensor->sample != 5) || (l_sensor->sample_min != 5 ) ||
+ (l_sensor->sample_max != 11 ) ||
+ (l_sensor->accumulator != l_tempacc+5)||
+ (l_sensor->vector->min_pos != 0 ))
+ {
+ l_rc = VECTOR_UPDT_FAILURE9;
+ break;
+ }
+
+ /****************************************************/
+ // test updating vector element with max operation
+ vectorSensor_t l_vecSnsr3;
+ sensor_vectorize(l_sensor3,&l_vecSnsr3,VECTOR_OP_MAX);
+
+ sensor_vector_elem_add(l_sensor3->vector,0,l_sensor1);
+ sensor_vector_elem_add(l_sensor3->vector,1,l_sensor2);
+ sensor_vector_elem_add(l_sensor3->vector,2,l_sensor);
+
+
+ //so far the source sensors of vector sensor are:
+ // l_sensor1=11
+ // l_sensor2=12
+ // l_sensor=5
+ /****************************************************/
+ // test enabling vector element with invalid location
+ sensor_vector_elem_enable(l_sensor3->vector,0xFF,0);
+ sensor_vector_elem_enable(l_sensor3->vector,2,0);
+
+ /****************************************************/
+ // test updating vector element with max operation and
+ // disabled element
+ l_tempacc=l_sensor3->accumulator;
+ sensor_vector_update(l_sensor3,0);
+
+ if( (l_sensor3->sample != 12) || (l_sensor3->sample_min != 2 ) ||
+ (l_sensor3->sample_max != 12 ) ||
+ (l_sensor3->accumulator != l_tempacc+12)||
+ (l_sensor3->vector->max_pos != 1))
+ {
+ l_rc = VECTOR_UPDT_FAILURE2;
+ break;
+ }
+
+ l_tempacc=l_sensor3->accumulator;
+ sensor_vector_elem_enable(l_sensor3->vector,2,1);
+ sensor_vector_update(l_sensor3,0);
+
+ if( (l_sensor3->sample != 12) || (l_sensor3->sample_min != 2 ) ||
+ (l_sensor3->sample_max != 12 ) ||
+ (l_sensor3->accumulator != l_tempacc+12)||
+ (l_sensor3->vector->max_pos != 1))
+ {
+ l_rc = VECTOR_UPDT_FAILURE10;
+ break;
+ }
+
+ vectorSensor_t l_vecSnsr1;
+ /****************************************************/
+ // test updating vector element with average operation
+ sensor_vectorize(l_sensor1,&l_vecSnsr1,VECTOR_OP_AVG);
+ sensor_vector_elem_add(l_sensor1->vector,0,l_sensor2);
+ sensor_vector_elem_add(l_sensor1->vector,1,l_sensor);
+ /****************************************************/
+
+ //so far the source sensors of vector sensor are:
+ // l_sensor2=12
+ // l_sensor=5
+
+ // test updating vector element with status reset bit set and
+ // average op
+ l_sensor1->status.reset = 1;
+ sensor_vector_update(l_sensor1,11);
+ if( (l_sensor1->sample != 12) || (l_sensor1->sample_min != 12 ) ||
+ (l_sensor1->sample_max != 12 ) || (l_sensor1->accumulator != 12)||
+ (l_sensor1->vector->max_pos != VECTOR_SENSOR_DEFAULT_VAL) ||
+ (l_sensor1->vector->min_pos != VECTOR_SENSOR_DEFAULT_VAL))
+ {
+ l_rc = VECTOR_UPDT_FAILURE3;
+ break;
+ }
+
+ /****************************************************/
+ // test updating vector element with average operation and
+ // disabled element
+ l_tempacc=l_sensor1->accumulator;
+ sensor_vector_elem_enable(l_sensor1->vector,0,0);
+ sensor_vector_update(l_sensor1,2);
+
+ if( (l_sensor1->sample != 5) || (l_sensor1->sample_min != 5 ) ||
+ (l_sensor1->sample_max != 12 ) ||
+ (l_sensor1->accumulator != l_tempacc+5))
+ {
+ l_rc = VECTOR_UPDT_FAILURE7;
+ break;
+ }
+
+ sensor_vector_elem_enable(l_sensor1->vector,0,1);
+ /****************************************************/
+ // test updating vector element with average operation and
+ // threshold greater than samples
+ l_tempacc=l_sensor1->accumulator;
+ sensor_vector_update(l_sensor1,25);
+
+ if( (l_sensor1->sample != 5) || (l_sensor1->sample_min != 5 ) ||
+ (l_sensor1->sample_max != 12 ) ||
+ (l_sensor1->accumulator != l_tempacc) )
+ {
+ l_rc = VECTOR_UPDT_FAILURE4;
+ break;
+ }
+
+ /****************************************************/
+ // test updating vector element with average operation and
+ // threshold lower than samples
+ l_tempacc=l_sensor1->accumulator;
+ sensor_vector_update(l_sensor1,2);
+ if( (l_sensor1->sample != 8) || (l_sensor1->sample_min != 5 ) ||
+ (l_sensor1->sample_max != 12 ) ||
+ (l_sensor1->accumulator != l_tempacc+8))
+ {
+ l_rc = VECTOR_UPDT_FAILURE8;
+ break;
+ }
+
+ l_sensor2->status.reset = 0;
+ /****************************************************/
+ // test update without vectorize should not do anything. Call should be
+ // noop
+ sensor_vector_update(l_sensor2,0);
+
+ if( (l_sensor2->sample != 12))
+ {
+ l_rc = VECTOR_UPDT_FAILURE5;
+ break;
+ }
+
+ vectorSensor_t l_vecSnsr2;
+ /****************************************************/
+ // test updating vector and vectorize with invalid operation
+ // should not update anything
+ sensor_vectorize(l_sensor2,&l_vecSnsr2,0xFF);
+
+ sensor_vector_elem_add(l_sensor2->vector,0,l_sensor);
+ sensor_vector_elem_add(l_sensor2->vector,1,l_sensor3);
+ //so far the source sensors of vector sensor are:
+ // l_sensor=5
+ // l_sensor3=12
+ sensor_vector_update(l_sensor2,0);
+
+ if( (l_sensor2->sample != 12))
+ {
+ l_rc = VECTOR_UPDT_FAILURE6;
+ break;
+ }
+
+ }while(0);
+
+ if( (l_sensor != NULL) &&
+ (l_sensor1 != NULL) &&
+ (l_sensor2 != NULL) &&
+ (l_sensor3 != NULL))
+ {
+ l_sensor->vector = NULL;
+ l_sensor1->vector = NULL;
+ l_sensor2->vector = NULL;
+ l_sensor3->vector = NULL;
+ l_sensor->mini_sensor = NULL;
+ l_sensor1->mini_sensor = NULL;
+ l_sensor2->mini_sensor = NULL;
+ l_sensor3->mini_sensor = NULL;
+ }
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: callQuerySensorList
+//
+// Description: querySensorList: Will call the SenosrQeryList product applet
+//
+// Flow: FN=None
+//
+// End Function Specification
+errlHndl_t callQuerySensorList(const uint16_t i_startGsid,
+ const uint8_t i_present,
+ const uint16_t i_type,
+ const uint16_t i_loc,
+ uint16_t * io_numOfSensors,
+ sensorQueryList_t * o_sensors,
+ sensor_info_t * o_sensorInfoPtrs // @at003A
+ )
+{
+ OCC_APLT_STATUS_CODES l_status = OCC_APLT_SUCCESS;
+ errlHndl_t l_errl = NULL;
+
+ querySensorListAppletArg_t l_querySensorListAppletArg={
+ i_startGsid,
+ i_present,
+ i_type,
+ i_loc,
+ io_numOfSensors,
+ o_sensors,
+ o_sensorInfoPtrs // @at003A
+ };
+
+
+ //Call sensor query list applet
+ runApplet(OCC_APLT_SNSR_QUERY, // Applet enum Name
+ &l_querySensorListAppletArg, // Applet arguments
+ TRUE, // Blocking call?
+ NULL, // Applet finished semaphore
+ &l_errl, // Error log handle
+ &l_status); // Error status
+
+ return l_errl;
+
+}
+
+
+// Function Specification
+//
+// Name: printQuerySensor
+//
+// Description: printQuerySensor
+//
+// Flow: FN=None
+//
+// End Function Specification
+void printQuerySensor( const uint16_t i_count,
+ sensorQueryList_t * i_sensors,
+ sensor_info_t * i_sensorInfos)
+{
+ int i;
+ if(i_count!=0 && // @at003M
+ ( (i_sensors!=NULL) || // @at003M
+ (i_sensorInfos!=NULL) ) ) // @at003M
+ {
+ // Print sensorQueryList_t
+ if( i_sensors != NULL )
+ {
+ SNSR_DBG("Printing sensorQueryList_t information");
+ SNSR_DBG("*******************************");
+
+ for(i=0;i<i_count;i++)
+ {
+ SNSR_DBG("ID:0x%4x Value:%4d Name:%s",i_sensors[i].gsid,
+ i_sensors[i].sample, i_sensors[i].name);
+ }
+ SNSR_DBG("*******************************\n");
+ }
+
+ // @at003A begin
+ // Print sensor_info_t
+ if ( i_sensorInfos != NULL )
+ {
+ SNSR_DBG("Printing sensor_info_t information");
+ SNSR_DBG("*******************************");
+
+ for(i=0;i<i_count;i++)
+ {
+ SNSR_DBG("Name:%s", i_sensorInfos[i].name);
+ SNSR_DBG("Frq:0x%4x", i_sensorInfos[i].sensor.freq);
+ SNSR_DBG("Location:0x%4x", i_sensorInfos[i].sensor.location);
+ SNSR_DBG("Number:0x%4x", i_sensorInfos[i].sensor.number);
+ SNSR_DBG("Scalefactor:0x%4x", i_sensorInfos[i].sensor.scalefactor);
+ SNSR_DBG("Type:0x%4x", i_sensorInfos[i].sensor.type);
+ SNSR_DBG("Unit:%s", i_sensorInfos[i].sensor.units);
+ }
+ SNSR_DBG("*******************************\n");
+ }
+ }
+ // @at003A end
+}
+
+
+// @th030 -- ifdef'd out b/c the sensor list is too big to test this in an applet
+#if 0
+
+// Function Specification
+//
+// Name: sensorTestQueryList
+//
+// Description: sensorTestQueryList
+//
+// Flow: FN=None
+//
+// End Function Specification
+uint32_t sensorTestQueryList()
+{
+ uint32_t l_rc = SUCCESS_RC;
+ uint16_t l_count = NUMBER_OF_SENSORS_IN_LIST;
+ errlHndl_t l_err = NULL;
+
+ do
+ {
+ uint16_t l_numOfSensors = 0;
+ sensor_info_t l_sensorInfo; // @at003M
+ /****************************************************/
+ // Test with invalid GSID. Must return error
+ l_err = callQuerySensorList(0xFFFF,1,SENSOR_TYPE_ALL,SENSOR_LOC_ALL,
+ &l_numOfSensors,G_snsrList, NULL); // @at003M // @ai003M
+
+ if( NULL == l_err)
+ {
+ l_rc = QUERY_LIST_FAILURE;
+ break;
+ }
+ else if( (l_err != INVALID_ERR_HNDL) &&
+ (l_err->iv_reasonCode != INTERNAL_FAILURE)) // @nh001c
+ {
+ l_rc = QUERY_LIST_FAILURE12;
+ break;
+
+ }
+
+ deleteErrl(&l_err);
+
+ /****************************************************/
+ // Test with NULL number of sensor pointer. Must return error
+ l_err = callQuerySensorList(0,1,SENSOR_TYPE_ALL,SENSOR_LOC_ALL,
+ NULL,G_snsrList, NULL); // @at003M // @ai003M
+
+ if( NULL == l_err)
+ {
+ l_rc = QUERY_LIST_FAILURE2;
+ break;
+ }
+ else if( (l_err != INVALID_ERR_HNDL) &&
+ (l_err->iv_reasonCode != INTERNAL_FAILURE)) // @nh001c
+ {
+ l_rc = QUERY_LIST_FAILURE13;
+ break;
+
+ }
+
+ deleteErrl(&l_err);
+
+ /****************************************************/
+ // Test with NULL sensor list pointer. Must return error
+ l_err = callQuerySensorList(0,1,SENSOR_TYPE_ALL,SENSOR_LOC_ALL,
+ &l_numOfSensors,NULL, NULL); // @at003M
+
+ if( NULL == l_err)
+ {
+ l_rc = QUERY_LIST_FAILURE3;
+ break;
+ }
+ else if( (l_err != INVALID_ERR_HNDL) &&
+ (l_err->iv_reasonCode != INTERNAL_FAILURE)) // @nh001c
+ {
+ l_rc = QUERY_LIST_FAILURE14;
+ break;
+
+ }
+
+ deleteErrl(&l_err);
+
+ /****************************************************/
+ // Query 0 # of sensors. Must return 0 sensors and no error
+ l_err = callQuerySensorList(0,1,SENSOR_TYPE_ALL,SENSOR_LOC_ALL,
+ &l_numOfSensors,G_snsrList,NULL); // @at003M // @ai003M
+
+ if( (l_err != NULL) || (l_numOfSensors != 0))
+ {
+ l_rc = QUERY_LIST_FAILURE4;
+ break;
+ }
+
+ /****************************************************/
+ // Query All sensors except last one. Must return no error
+ l_numOfSensors = l_count -1; //(-1) to leave out last sensor
+ l_err = callQuerySensorList(0,1,SENSOR_TYPE_ALL,SENSOR_LOC_ALL,
+ &l_numOfSensors,G_snsrList, NULL); // @at003M // @ai003M
+
+
+ if( (l_err != NULL) || (l_numOfSensors > (l_count-1)))
+ {
+ l_rc = QUERY_LIST_FAILURE5;
+ break;
+ }
+
+ /****************************************************/
+ // Query last sensors. Must return no error. Trying to get
+ // more sensors but should return only once since start GSID
+ // is of last sensor
+ l_numOfSensors = 5;
+ sensor_t *l_sensor=getSensorByGsid(l_count-1);
+ sensor_update(l_sensor, 10);
+
+ l_err = callQuerySensorList(l_count-1,1,SENSOR_TYPE_ALL,
+ SENSOR_LOC_ALL,&l_numOfSensors,G_snsrList, NULL); // @at003M // @ai003M
+
+ if( (l_err != NULL) || (l_numOfSensors != 1) ||
+ (l_sensor->gsid!=l_count-1))
+ {
+ l_rc = QUERY_LIST_FAILURE6;
+
+ break;
+ }
+
+ /****************************************************/
+ // Query sensors that are not present Must return no error.
+ l_numOfSensors = 10;
+ l_err = callQuerySensorList(PROBE250US0,0,SENSOR_TYPE_ALL,
+ SENSOR_LOC_ALL,&l_numOfSensors,G_snsrList, NULL); // @at003M // @ai003M
+ //printQuerySensor(l_numOfSensors,G_snsrList, NULL ); // @ai003M
+ if( (l_err != NULL) || (l_numOfSensors == 0))
+ {
+ l_rc = QUERY_LIST_FAILURE7;
+ break;
+ }
+
+ /****************************************************/
+ // Query sensors that are present, type and location
+ // does not match any. Must return no error and no sensors
+ l_numOfSensors = 10;
+ l_err = callQuerySensorList(PROBE250US0,1,0x0,0x0,
+ &l_numOfSensors,G_snsrList, NULL); // @at003M // @ai003M
+ printQuerySensor(l_numOfSensors,G_snsrList, NULL ); // @ai003M
+
+ if( (l_err != NULL) || (l_numOfSensors != 0))
+ {
+ l_rc = QUERY_LIST_FAILURE8;
+ break;
+ }
+
+ /****************************************************/
+ // Query sensors that are present,type=AMEC_SENSOR_TYPE_GENERIC,
+ // loc=AMEC_SENSOR_LOC_OCC. Must return no error.
+ l_numOfSensors = 10;
+ l_err = callQuerySensorList(PROBE250US0,1,AMEC_SENSOR_TYPE_GENERIC,
+ AMEC_SENSOR_LOC_OCC,
+ &l_numOfSensors,G_snsrList, NULL); // @at003M // @ai003M
+
+ if( (l_err != NULL) || (l_numOfSensors == 0))
+ {
+ l_rc = QUERY_LIST_FAILURE9;
+ break;
+ }
+
+ /****************************************************/
+ // Query sensors that are present,type=AMEC_SENSOR_TYPE_GENERIC and
+ // any location. Must return no error.
+ l_numOfSensors = 10;
+ l_err = callQuerySensorList(PROBE250US0,1,AMEC_SENSOR_TYPE_GENERIC,
+ SENSOR_LOC_ALL,
+ &l_numOfSensors,G_snsrList, NULL); // @at003M // @ai003M
+
+ if( (l_err != NULL) || (l_numOfSensors == 0))
+ {
+ l_rc = QUERY_LIST_FAILURE10;
+ break;
+ }
+
+ /****************************************************/
+ // Query sensors that are present,any type and
+ // location=AMEC_SENSOR_LOC_OCC. Must return no error.
+ l_numOfSensors = 10;
+ l_err = callQuerySensorList(PROBE250US0,1,SENSOR_TYPE_ALL,
+ AMEC_SENSOR_LOC_OCC,&l_numOfSensors,
+ G_snsrList, NULL); // @at003M // @ai003M
+
+ if( (l_err != NULL) || (l_numOfSensors == 0))
+ {
+ l_rc = QUERY_LIST_FAILURE11;
+ break;
+ }
+
+ // @at003A begin
+ /****************************************************/
+ // Query sensors to get sensor info,any type and
+ // location=AMEC_SENSOR_LOC_OCC. Must return no error.
+ l_numOfSensors = 1;
+ l_err = callQuerySensorList(PROBE250US0,1,SENSOR_TYPE_ALL,
+ SENSOR_LOC_ALL,&l_numOfSensors,
+ NULL, &l_sensorInfo); // @at003M
+ if( (l_err != NULL) || (l_numOfSensors == 0))
+ {
+ l_rc = QUERY_LIST_FAILURE11;
+ break;
+ }
+ printQuerySensor(l_numOfSensors,NULL, &l_sensorInfo );
+ // @at003A end
+
+ }while(0);
+
+ if( l_err != NULL)
+ {
+ deleteErrl(&l_err);
+ }
+
+ return l_rc;
+}
+#endif
+
+
+/*****************************************************************************/
+// Image Header
+/*****************************************************************************/
+// @dw000 - call macro with Applet ID arg
+IMAGE_HEADER (G_sensorTestMain,sensorTestMain,SENSORTESTMAIN_ID,OCC_APLT_TEST);
+
diff --git a/src/occApplet/testApplet/testApltId.h b/src/occApplet/testApplet/testApltId.h
new file mode 100755
index 0000000..cda2e64
--- /dev/null
+++ b/src/occApplet/testApplet/testApltId.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+// @file testApltId.h
+// @brief Error codes for aplt component.
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section testApltId.h
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _TESTAPLTID_H_
+#define _TESTAPLTID_H_
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+enum testApltIds
+{
+ TEST_APLT_ID_UNKNOWN = 0x00,
+ SNSR_TEST_APLT = 0x01,
+ ERRL_TEST_APLT = 0x02,
+};
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif /* #ifndef _TESTAPLTID_H_ */
diff --git a/src/occApplet/testApplet/testappletfiles.mk b/src/occApplet/testApplet/testappletfiles.mk
new file mode 100755
index 0000000..7a0962d
--- /dev/null
+++ b/src/occApplet/testApplet/testappletfiles.mk
@@ -0,0 +1,37 @@
+# @file libofiles.mk
+#
+# @brief mk for libssx.a object files
+#
+# @page ChangeLogs Change Logs
+# @section ofiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/28/2012 Makefile ODE support
+# @gm043 928988 milesg 06/19/2014 Added pstApplet
+#
+# @endverbatim
+#
+##########################################################################
+# INCLUDES
+##########################################################################
+# New test applet source file must to listed as part of the SOURCES variable
+# to create test applet image. This will only create the image. It will not
+# add these images as part of the mainstore single image. To make it part of
+# of the mainstore single image, please see comments for IMAGE_TO_COMBINE
+# variable
+C-SOURCES = sensorTest.c apsstest.c errlTest.c traceTest.c pstApplet.c
+
+TESTAPLT_OBJECTS = $(C-SOURCES:.c=.o)
+
+sensorTest_OFILES = sensorTest.o
+apsstest_OFILES = apsstest.o
+errlTest_OFILES = errlTest.o
+traceTest_OFILES = traceTest.o
+pstApplet_OFILES = pstApplet.o
+
+
+
diff --git a/src/occApplet/testApplet/traceTest.c b/src/occApplet/testApplet/traceTest.c
new file mode 100755
index 0000000..975ea72
--- /dev/null
+++ b/src/occApplet/testApplet/traceTest.c
@@ -0,0 +1,340 @@
+/******************************************************************************
+// @file traceTest.c
+// @brief Test applet for trace functions
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section traceTest.c TRACETEST.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * ailutsar 11/13/12 created
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <common_types.h> // imageHdr_t declaration and image header macro
+#include <errl.h> // For error handle
+#include "ssx_io.h" // For printfs
+#include <trac.h> // For traces
+#include <appletId.h> // For applet ID @dw000a
+#include <trac_service_codes.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern SsxSemaphore g_trac_mutex;
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+#define TRAC_INTF_MUTEX_TIMEOUT SSX_SECONDS(5)
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define TRACETEST_ID "traceTest\0"
+#define para_int_0 "0 para"
+#define para_int_1 "1 para (%d)"
+//#define para_int_2 "2 para (%d) (%d)"
+//#define para_int_3 "3 para (%d) (%d) (%d)"
+//#define para_int_4 "4 para (%d) (%d) (%d) (%d)"
+#define para_int_5 "5 para (%d) (%d) (%d) (%d) (%d)"
+#define para_int_6 "6 para (%d) (%d) (%d) (%d) (%d) (%d)"
+#define para_hex_0 "0 para"
+#define para_hex_1 "1 para (%X)"
+//#define para_hex_2 "2 para (%X) (%X)"
+//#define para_hex_3 "3 para (%X) (%X) (%X)"
+//#define para_hex_4 "4 para (%X) (%X) (%X) (%X)"
+#define para_hex_5 "5 para (%X) (%X) (%X) (%X) (%X)"
+#define para_hex_6 "6 para (%X) (%X) (%X) (%X) (%X) (%X)"
+#define para_chr_0 "0 para"
+#define para_chr_1 "1 para (%s)"
+//#define para_chr_2 "2 para (%s) (%s)"
+//#define para_chr_3 "3 para (%s) (%s) (%s)"
+//#define para_chr_4 "4 para (%s) (%s) (%s) (%s)"
+#define para_chr_5 "5 para (%s) (%s) (%s) (%s) (%s)"
+#define para_chr_6 "6 para (%s) (%s) (%s) (%s) (%s) (%s)"
+#define MIN_TRACE_ENTRY_SIZE 32
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+char G_trac_buffer[TRACE_BUFFER_SIZE + 100];
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+int traceSemTest(void)
+{
+ UINT l_rc = 0;
+
+ // lock trace semaphore first
+ l_rc = ssx_semaphore_pend(&g_trac_mutex, TRAC_INTF_MUTEX_TIMEOUT);
+ if(SSX_OK == l_rc)
+ {
+ // create one trace
+ TRAC_INFO("traceTest Applet: test trace semaphore");
+
+ // Unlock trace semaphore
+ ssx_semaphore_post(&g_trac_mutex);
+
+ }
+ else
+ {
+ l_rc = 1;
+ }
+
+ return l_rc;
+}
+
+int traceFuncTest()
+{
+ UINT l_rc = 0;
+ UINT l_max_trace_entries = TRACE_BUFFER_SIZE / MIN_TRACE_ENTRY_SIZE;
+ UINT l_entry_count = 0;
+ UINT l_buffer_size = 0;
+ tracDesc_t l_head = NULL;
+
+ do
+ {
+ // Test target - trac_write_XXX(), TRAC_get_buffer() and TRAC_get_td()
+ // This testcase would create l_max_trace_entries +1 trace entries
+ // to fill trace buffer, times_wrap should be larger than zero
+ do{
+ l_entry_count++;
+ TRAC_INFO("traceTest applet INFO record: count %d", (int)l_entry_count);
+ TRAC_ERR("traceTest applet ERR record: count %d", (int)l_entry_count);
+ TRAC_IMP("traceTest applet IMP record: count %d", (int)l_entry_count);
+ }while(l_max_trace_entries >= l_entry_count);
+
+ // Check times_wrap in TRAC_INFO.
+ // Because structures are all the same, skip TRAC_ERR and TRAC_IMP
+ l_rc = TRAC_get_buffer(TRAC_get_td("INF"), G_trac_buffer);
+ l_head = (tracDesc_t)&G_trac_buffer;
+ if((l_rc != 0 ) || (l_head->times_wrap == 0))
+ {
+ printf("Fail: times_wrap error in trace buffer: %d, %d\n", l_rc, l_head->times_wrap);
+ break;
+ }
+
+ // Test target - TRAC_get_buffer() and TRAC_get_td()
+ // case: invalid paramenters
+ l_rc = TRAC_get_buffer(TRAC_get_td("INF"), NULL);
+ l_head = (tracDesc_t)&G_trac_buffer;
+ if(l_rc == 0)
+ {
+ printf("TRAC_get_buffer(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer() invalid 1th parameter\n");
+ break;
+ }
+
+ l_rc = TRAC_get_buffer(NULL, G_trac_buffer);
+ l_head = (tracDesc_t)&G_trac_buffer;
+ if(l_rc == 0)
+ {
+ printf("TRAC_get_buffer(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer() invalid 2nd parameter\n");
+ break;
+ }
+
+ // Test target - TRAC_get_buffer_partial() and TRAC_get_td()
+ // case: invalid paramenters
+ l_buffer_size = TRACE_BUFFER_SIZE;
+ l_rc = TRAC_get_buffer_partial(NULL, G_trac_buffer, &l_buffer_size);
+ if((l_rc != TRAC_INVALID_PARM) && (l_buffer_size !=0))
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer_partial() invalid 1st parameter\n");
+ break;
+ }
+
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("UNKNOWN"), NULL, &l_buffer_size);
+ if((l_rc != TRAC_INVALID_PARM) && (l_buffer_size !=0))
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer_partial() invalid 1st parameter\n");
+ break;
+ }
+
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("INF"), NULL, &l_buffer_size);
+ if((l_rc != TRAC_INVALID_PARM) && (l_buffer_size !=0))
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer_partial() invalid 2nd parameter\n");
+ break;
+ }
+
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("ERR"), G_trac_buffer, NULL);
+ if(l_rc != TRAC_INVALID_PARM)
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer_partial() invalid 3rd parameter\n");
+ break;
+ }
+
+ // Test target - TRAC_get_buffer_partial()
+ // case: input buffer less then the size of trace buffer header
+ l_buffer_size = sizeof(trace_buf_head_t) - 1;
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("IMP"), G_trac_buffer, &l_buffer_size);
+ if(l_rc != TRAC_DATA_SIZE_LESS_THAN_HEADER_SIZE)
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer_partial() with illegal small input buffer\n");
+ break;
+ }
+
+ // Test target - TRAC_get_buffer_partial()
+ // case: input buffer is small then then trace buffer
+ l_buffer_size = sizeof(trace_buf_head_t) + (TRACE_BUFFER_SIZE/4);
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("INF"), G_trac_buffer, &l_buffer_size);
+ if(l_rc)
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer_partial() with small input buffer\n");
+ break;
+ }
+
+ // Test target - TRAC_get_buffer_partial()
+ // case: input buffer is larger then trace buffer
+ l_buffer_size = sizeof(G_trac_buffer);
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("INF"), G_trac_buffer, &l_buffer_size);
+ if(l_rc || (l_buffer_size != TRACE_BUFFER_SIZE))
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d size %d/%d\n", l_rc, l_buffer_size, TRACE_BUFFER_SIZE);
+ printf("Fail: test TRAC_get_buffer_partial() with too large input buffer\n");
+ break;
+ }
+
+ // Test target - TRAC_reset_buf() and TRAC_get_buffer_partial()
+ // case: clear trace buffer and check with buffer larger than trace buffer
+ TRAC_reset_buf();
+ l_buffer_size = sizeof(G_trac_buffer);
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("ERR"), G_trac_buffer, &l_buffer_size);
+ if(l_rc)
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_reset_buf()/TRAC_get_buffer_partial() with empty trace\n");
+ break;
+ }
+
+ // Test target - TRAC_reset_buf() and TRAC_get_buffer_partial()
+ // case: clear trace buffer and check it with buffer smaller than trace buffer
+ TRAC_reset_buf();
+ l_buffer_size = TRACE_BUFFER_SIZE/2;
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("ERR"), G_trac_buffer, &l_buffer_size);
+ if(l_rc)
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_reset_buf()/TRAC_get_buffer_partial() with empty trace\n");
+ break;
+ }
+
+ // Test target - TRAC_get_buffer_partial()
+ // case: create some traces and test with large input buffer
+ l_entry_count = 0;
+ do{
+ l_entry_count++;
+ TRAC_INFO("traceTest applet INFO record: count %d", (int)l_entry_count);
+ TRAC_ERR("traceTest applet ERR record: count %d", (int)l_entry_count);
+ TRAC_IMP("traceTest applet IMP record: count %d", (int)l_entry_count);
+ }while((l_max_trace_entries/4) >= l_entry_count);
+ l_buffer_size = TRACE_BUFFER_SIZE;
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("IMP"), G_trac_buffer, &l_buffer_size);
+ l_head = (tracDesc_t)&G_trac_buffer;
+ if(l_rc || (l_head->times_wrap != 0))
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer_partial() with large input buffer\n");
+ break;
+ }
+
+ // Test target - TRAC_get_buffer_partial()
+ // case: create some traces and test with small input buffer
+ l_buffer_size = sizeof(trace_buf_head_t) + (TRACE_BUFFER_SIZE/4);
+ l_rc = TRAC_get_buffer_partial(TRAC_get_td("INF"), G_trac_buffer, &l_buffer_size);
+ if(l_rc)
+ {
+ printf("TRAC_get_buffer_partial(), reason code: %d\n", l_rc);
+ printf("Fail: test TRAC_get_buffer_partial() with small input buffer\n");
+ break;
+ }
+
+ }while(0);
+
+ return l_rc;
+}
+
+//*************************************************************************
+// Entry point function
+//*************************************************************************
+errlHndl_t traceTest(void * i_arg)
+{
+ errlHndl_t l_err = NULL;
+ UINT l_rc = 0;
+
+ do
+ {
+ // function unit test
+ l_rc = traceFuncTest();
+ if(l_rc)
+ {
+ printf("traceTest Applet: Function test failed\n");
+ break;
+ }
+
+ // Macro test: test basic trace macros with/without parameters
+ // Please check occ memory dump with fsp-trace
+
+ // int: supported
+ TRAC_INFO(para_int_0);
+ TRAC_INFO(para_int_1, 1);
+ TRAC_INFO(para_int_5, 1, 2, 3, 4, 5);
+ TRAC_INFO(para_int_6, 1, 2, 3, 4, 5, 6);
+
+ // hex: supported
+ TRAC_ERR(para_hex_0);
+ TRAC_ERR(para_hex_1, 0xA);
+ TRAC_ERR(para_hex_5, 0xA, 0xB, 0xC, 0xD, 0xE);
+ TRAC_ERR(para_hex_6, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF);
+
+ // char: not supported
+ TRAC_IMP(para_int_0);
+ TRAC_IMP(para_chr_1, "1");
+ TRAC_IMP(para_chr_5, "1", "2", "3", "4", "5");
+ TRAC_IMP(para_chr_6, "1", "2", "3", "4", "5", "6");
+
+#ifdef TEST_SEMAPHORE
+ // semaphore test
+ l_rc = traceSemTest();
+ if(l_rc)
+ {
+ printf("traceTest Applet: Semaphore test failed\n");
+ break;
+ }
+#endif
+ }while(0);
+
+ printf("traceTest Applet: test finish\n");
+ return l_err;
+}
+
+
+//*************************************************************************
+// Image Header
+//*************************************************************************
+IMAGE_HEADER (G_traceTest,traceTest,TRACETEST_ID,OCC_APLT_TEST);
diff --git a/src/occBootLoader/Makefile b/src/occBootLoader/Makefile
new file mode 100755
index 0000000..a9446b3
--- /dev/null
+++ b/src/occBootLoader/Makefile
@@ -0,0 +1,90 @@
+# @file Makefile
+#
+# @brief bootloader Makefile
+#
+
+# @page ChangeLogs Change Logs
+# @section Makefile
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb000 pbavari 07/01/2011 Created
+# @pb001 pbavari 07/16/2011 Changed to combine image
+# as separate command
+# @pb006 pbavari 09/16/2011 Display size support
+# @pb004 pbavari 09/20/2011 Added occ/ in include path
+# @pb007 pbavari 09/29/2011 Added ppc405 in include path
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+#
+# @endverbatim
+#
+
+# >> gitprep
+ifndef ROOTPATH
+ROOTPATH = $(shell pwd)/../
+export OCCROOT = $(ROOTPATH)
+endif
+# << gitprep
+
+#*******************************************************************************
+# mk variable Declaration
+#*******************************************************************************
+OCC = ../occ
+BOOTLOADER = .
+SSX = ../ssx
+#*******************************************************************************
+# Includes
+#*******************************************************************************
+include bootfiles.mk
+include ../ssx/pgp/ssx.mk
+
+INCLUDES = -I. -I$(SSX)/ppc32 -I$(SSX)/pgp -I$(OCC)/incl -I$(OCC)/ \
+ -I$(SSX)/ppc405
+
+#*******************************************************************************
+# Flags
+#*******************************************************************************
+OBJECTS = ${BOOTLOADER_OBJECTS}
+EXECUTABLE = bootloader
+imageHdrScript = imageHdrScript
+imageHdrScript_CC = gcc
+
+#D = -DSIMICS_MAGIC_PANIC=1 \
+ -DINITIALIZE_SIMICS_IO=1
+
+DEFS += $(D)
+
+#*******************************************************************************
+# Compilation
+#*******************************************************************************
+
+all: ${BOOTLOADER_OBJECTS} imageHdrScript
+ $(CPP) -P $(DEFS) < linkboot.cmd > linkscript
+ # >> gitprep
+ # Add missing link and objcopy flags
+ $(LD) ${BOOTLOADER_OBJECTS} \
+ -Tlinkscript $(LDFLAGS) -zmuldefs -Map $(EXECUTABLE).map -melf32ppc --oformat=elf32-powerpc -Bstatic -o \
+ $(EXECUTABLE).out
+ $(OBJCOPY) -I elf32-powerpc -O binary $(EXECUTABLE).out $(EXECUTABLE).bin
+ # << gitprep
+ $(OBJDUMP) -d $(EXECUTABLE).out > $(EXECUTABLE).dis
+ $(BOOTLOADER)/$(imageHdrScript) $(EXECUTABLE).bin t1
+
+.PHONY : combineImage
+combineImage:
+ $(BOOTLOADER)/imageHdrScript $(EXECUTABLE).bin combineImage
+ $(BOOTLOADER)/imageHdrScript $(EXECUTABLE).out displaySize
+
+imageHdrScript: imageHdrScript.c
+ $(imageHdrScript_CC) $(LDFLAGS) -I$(BOOTLOADER) -I$(OCC)/incl -I$(OCC)/ \
+ imageHdrScript.c -o $@
+
+#*******************************************************************************
+# Clean
+#*******************************************************************************
+clean:
+ rm -f *.o *.d *.out *.bin *.srec *.dis *.map linkscript imageHdrScript
+ rm -rf $(EXECUTABLE) $(IMAGE_FILE)
diff --git a/src/occBootLoader/bootInit.S b/src/occBootLoader/bootInit.S
new file mode 100755
index 0000000..9f4c104
--- /dev/null
+++ b/src/occBootLoader/bootInit.S
@@ -0,0 +1,234 @@
+# *****************************************************************************
+# @file bootInit.S
+# @brief OCC boot loader initialization
+#
+
+# *****************************************************************************
+#
+# @page ChangeLogs Change Logs
+# @section bootInit.S BOOTINIT.S
+# @verbatim
+#
+# Flag Def/Fea Userid Date Description
+# ------- ---------- -------- ---------- ----------------------------------
+# @pb000 pbavari 06/21/2011 Created
+# @pb007 pbavari 09/29/2011 Added trap if reset was due to
+# watchdog timer
+# @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+# @th00c thallet 03/02/2012 DCCR was getting loaded with incorret imm
+#
+# @endverbatim
+#
+# *****************************************************************************
+
+/*****************************************************************************/
+// Includes
+/*****************************************************************************/
+#include "bootMain.h"
+#include "ppc32_asm.h"
+#include "ppc405_spr.h"
+/*****************************************************************************/
+
+/*****************************************************************************/
+// Functions
+/*****************************************************************************/
+# Function Specification ******************************************************
+#
+# Name: boot_low_level_init
+#
+# Description: Low level boot initialization
+#
+# Flow: 06/22/2011 FN= ??
+#
+# End Function Specification **************************************************
+
+.global_function __boot_low_level_init
+
+__boot_low_level_init:
+
+
+#enable machine check exception
+# initialize exception vector prefix to zero
+# enable machine check (19th bit)
+
+li %r3, 0
+mtevpr %r3
+_liwa %r4, MACHINE_CHECK_ENABLE
+mtmsr %r4
+
+// Check if TSR[WSR] indicates that reset was due to watchdog,
+// then initialize external debug event and trap(halt). Otherwise
+// continue normally. Setting up external debug event will set FIR bits on halt
+mftsr %r3
+_liwa %r4, ( TSR_WRS_CHIP | TSR_WRS_CORE | TSR_WRS_SYSTEM )
+AND %r5, %r3, %r4
+li %r4, 0
+cmp 0, 0, %r4, %r5
+beq skip_wd_reset_trap
+
+// Initialize external debug event before doing trap
+_liwa %r3, (DBCR0_EDM | DBCR0_TDE | DBCR0_FT )
+mtdbcr0 %r3
+tw 31,0,0
+
+skip_wd_reset_trap:
+
+# enable write back data cache and instruction cache
+# enable write back data for 0x80000000. Note:write-back=0,write-through=1
+# Data cache enabled for 0x80000000. Bit 16 going left-right. 1=enable,0=disable
+# enable instruction cache for 0x80000000. Bit 16 going left-right.
+# 1= enable, 0 = disable
+
+li %r3, 0
+mtdcwr %r3
+_liw %r3, DATA_CACHE_BLOCK_ENABLE
+mtdccr %r3
+mticcr %r3
+
+dcache_invalidate:
+ ## We loop through addresses 0 ... (DCACHE_SIZE / DCACHE_WAYS) - 1
+ ## invalidating the D-Cache. The dccci instruction on the 405
+ ## invalidates both ways. Added: @th00c
+
+ li %r3, 0
+ _liwa %r4, (DATA_CACHE_LINES / 2)
+ mtctr %r4
+
+1:
+ dccci %r0, %r3
+ addi %r3, %r3, CACHE_LINE_SIZE
+ bdnz 1b
+
+ sync
+
+# fill in 16K with zero for the data cache
+# set counter to loop for number of data cache lines
+
+_liw %r3, 0
+_liwa %r5, DATA_CACHE_BLOCK_ADDR
+_liwa %r4, DATA_CACHE_LINES
+mtctr %r4
+
+dcbz_loop:
+
+ dcbz %r5, %r3
+ addi %r3, %r3, CACHE_LINE_SIZE
+ bdnz dcbz_loop
+
+
+# calculate writable data section start address
+# start_addr + readonly_size = writable data section address
+# load start address into r5
+# load readonly size address into r4
+# add contents of r5 and r4 and put into r3
+# r3 now has source address
+# load address of size of the data to be copied into r4
+# load destination address into r5
+# store number of word trasfers in r4
+# set counter to r4 content
+# NOTE: (-4) for the source and destination address is done because
+# in the loop 4 is added to get to the correct address.
+
+_liw %r5, (__START_ADDR__ - 4)
+_liw %r4, __READ_ONLY_DATA_LEN__
+add %r3, %r5, %r4
+_liw %r4, __WRITEABLE_DATA_LEN__
+_liw %r5, (__WRITEABLE_DATA_ADDR__ - 4)
+_liw %r6, 2
+srw %r4, %r4, %r6
+
+# Compare r4 and r6. If equal then skip_loop. Else execute copy_loop
+_liw %r6, 0
+cmp 0, 0, %r4, %r6
+beq skip_loop
+mtctr %r4
+copy_loop:
+
+ lwzu %r4, 4(%r3)
+ stwu %r4, 4(%r5)
+ bdnz copy_loop
+
+skip_loop:
+
+# set up EABI constant registers r2,r13
+
+_liw %r2, _SDA2_BASE_
+_liw %r13, _SDA_BASE_
+
+# set up stack pointer - register r1
+
+_liwa %r1, STACK_POINTER_ADDR
+
+# jump to main
+
+b main
+
+# function clean up and return
+
+.epilogue __boot_low_level_init
+
+# vector section
+
+.section .vectors_0000, "a", @progbits
+ .global __vectors_0000
+
+__vectors_0000:
+
+
+ .section .vectors_0100, "ax", @progbits
+ .global __vectors_0100
+
+__vectors_0100:
+
+# Trap instruction
+tw 31,0,0
+
+ .section .vectors_0200, "ax", @progbits
+ .global __vectors_0200
+
+__vectors_0200:
+
+# Trap instruction
+tw 31,0,0
+
+ .section .vectors_0300, "ax", @progbits
+ .global __vectors_0300
+
+__vectors_0300:
+
+# Trap instruction
+tw 31,0,0
+
+ .section .vectors_0400, "ax", @progbits
+ .global __vectors_0400
+
+__vectors_0400:
+
+# Trap instruction
+tw 31,0,0
+
+ .section .vectors_0500, "ax", @progbits
+ .global __vectors_0500
+
+__vectors_0500:
+
+# Trap instruction
+tw 31,0,0
+
+ .section .vectors_0600, "ax", @progbits
+ .global __vectors_0600
+
+__vectors_0600:
+
+# Trap instruction
+tw 31,0,0
+
+
+ .section .vectors_0700, "ax", @progbits
+ .global __vectors_0700
+
+__vectors_0700:
+
+# Trap instruction
+tw 31,0,0
+
diff --git a/src/occBootLoader/bootMain.c b/src/occBootLoader/bootMain.c
new file mode 100755
index 0000000..10df75f
--- /dev/null
+++ b/src/occBootLoader/bootMain.c
@@ -0,0 +1,308 @@
+/******************************************************************************
+// @file bootMain.c
+// @brief OCC boot loader main
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section bootMain.c BOOTMAIN.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb000 pbavari 06/22/2011 Created
+ * @dw000 dwoodham 12/12/2011 Update call to IMAGE_HEADER macro
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @th00c thallet 03/02/2012 VPO Changes to 405 Caching
+ * @sb000 905048 sbroyles 10/28/2013 Add tags for code cleanup,
+ * see RTC task 73327.
+* @sb001 906184 sbroyles 11/11/2013 Resolve fix tags
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <bootMain.h> // boot loader defines
+#include <pgp_common.h> // Nest frequency constant
+#include <stddef.h> // offsetof
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+extern void __boot_low_level_init;
+
+//*************************************************************************
+// Image header
+//*************************************************************************
+//@dw001c - added arg: idNum = ID_NUM_INVALID
+IMAGE_HEADER (G_bootImageHdr,__boot_low_level_init,BOOT_LOADER_ID,
+ ID_NUM_INVALID);
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+//Forward declaration
+uint32_t boot_test_sram();
+uint32_t boot_load_image(const imageHdr_t * i_hdrAddr);
+uint32_t calChecksum(const uint32_t i_startAddr,const uint32_t i_sz );
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: boot_main
+//
+// Description: boot main will test SRAM, copy main application image from
+// main memory to SRAM, validate checksum and calls ssx_boot.
+//
+// Flow: 06/22/2011 FN= boot_main
+//
+// End Function Specification
+void main()
+{
+ uint32_t l_rc = 0;
+ // set checkpoint to boot test SRAM
+ WRITE_TO_SPRG0(BOOT_TEST_SRAM_CHKPOINT);
+
+#ifndef VPO
+ // @th00c - This is ifdef'd out b/c it takes too long to run in VPO
+ // Test SRAM
+ l_rc = boot_test_sram();
+#endif
+
+ // If failed to test SRAM, write failed return code to SPRG1 and halt
+ if( 0 != l_rc )
+ {
+ WRITE_TO_SPRG1_AND_HALT(l_rc);
+ }
+
+ // set imageHdr_t pointer to point to boot image header to get to boot
+ // image size. This way we can get to main application image header.
+ imageHdr_t *l_hdrPtr = (imageHdr_t*)(G_bootImageHdr.start_addr +
+ G_bootImageHdr.image_size );
+
+ // set checkpoint to boot load main application image to SRAM
+ WRITE_TO_SPRG0(BOOT_LOAD_IMAGE_CHKPOINT );
+
+ // Load main application image to SRAM including main application header
+ l_rc = boot_load_image(l_hdrPtr);
+
+ // If failed to load image, write failed return code to SPRG1 and halt
+ if( 0 != l_rc )
+ {
+ WRITE_TO_SPRG1_AND_HALT(l_rc);
+ }
+
+ // set checkpoint to calculate checksum
+ WRITE_TO_SPRG0(BOOT_CALCULTE_CHKSUM_CHKPOINT);
+
+ // calculate checksum for the SRAM main application image
+ uint32_t l_checksum = calChecksum(l_hdrPtr->start_addr,
+ l_hdrPtr->image_size);
+
+ // If checksum does not match, store bad checksum into SPRG1 and halt
+ if( l_checksum != l_hdrPtr->checksum)
+ {
+ WRITE_TO_SPRG1_AND_HALT(l_checksum);
+ }
+
+ // set checkpoint to get nest frequency
+ WRITE_TO_SPRG0(BOOT_GET_NEST_FREQ_CHKPOINT);
+
+ // @sb001 Remove this local.
+ //uint32_t l_nestFreq = 2400000;
+
+ // set checkpoint to call to SSX_BOOT
+ WRITE_TO_SPRG0(BOOT_SSX_BOOT_CALL_CHKPOINT);
+
+ // Invalidate Data Cache before calling __ssx_boot()
+ //dcache_invalidate_all(); // @th00c
+
+ // create function pointer pointing to main application header entry point
+ // address. This is similar to jump/branch to address in assembly
+
+ // @sb001 Don't pass l_nestFreq anymore, ssx boot code isn't reading it.
+ //void (*execute_ssx_boot)(uint32_t) = (void (*)(uint32_t)) l_hdrPtr->ep_addr;
+ //(*execute_ssx_boot)(l_nestFreq);
+ void (*execute_ssx_boot)(void) = (void (*)(void)) l_hdrPtr->ep_addr;
+ (*execute_ssx_boot)();
+
+ // set checkpoint to return from ssx_boot. This should never happen so
+ // halt at this point.
+ WRITE_TO_SPRG0(BOOT_SSX_RETURNED_CHKPOINT);
+ WRITE_TO_SPRG1_AND_HALT(l_hdrPtr->ep_addr);
+
+}
+
+// Function Specification
+//
+// Name: calChecksum
+//
+// Description: Calculate checksum starting at given address and given size
+// bytes. Skip checksum field in the imageHdr_t while calculating
+// checksum
+//
+// Flow: None FN= None
+//
+// End Function Specification
+
+uint32_t calChecksum(const uint32_t i_startAddr,const uint32_t i_sz )
+{
+ uint32_t l_checksum = 0;
+ uint32_t l_counter = 0;
+ uint8_t * l_srcPtr = (uint8_t *) (i_startAddr);
+
+ while (l_counter < i_sz )
+ {
+ l_checksum += (*(l_srcPtr + l_counter));
+ l_counter = l_counter + 1;
+ if( l_counter == (uint32_t)(offsetof(imageHdr_t,checksum)))
+ {
+ l_counter = ((uint32_t)(offsetof(imageHdr_t,checksum)) +
+ sizeof(G_bootImageHdr.checksum));
+ }
+ }
+
+ return l_checksum;
+}
+
+// Function Specification
+//
+// Name: boot_load_image
+//
+// Description: This function copies main application image from main memory
+// to SRAM
+//
+//
+// Flow: 06/22/2011 FN= boot_load_image
+//
+// End Function Specification
+
+uint32_t boot_load_image(const imageHdr_t * i_hdrAddr )
+{
+ uint32_t l_rc = 0x0;
+ uint32_t l_mainAppDestRang = (i_hdrAddr->start_addr) +
+ (i_hdrAddr->image_size-1);
+
+ // Make sure main application destination rang address falls within SRAM
+ // range.
+ if( ( l_mainAppDestRang < SRAM_START_ADDRESS) ||
+ (l_mainAppDestRang > SRAM_END_ADDRESS ))
+ {
+ // Return destination rang address if address is out of range and
+ // address is not zero. If address is zero, then return eye-catcher
+ // address.
+ if( l_mainAppDestRang != 0 )
+ {
+ l_rc = l_mainAppDestRang;
+ }
+ else
+ {
+ l_rc = EYE_CATCHER_ADDRESS;
+ }
+ }
+ //Make sure main application start address falls within SRAM range
+ else if ((i_hdrAddr->start_addr < SRAM_START_ADDRESS) ||
+ (i_hdrAddr->start_addr > SRAM_END_ADDRESS))
+ {
+ // Return start address if address is out of range and
+ // address is not zero. If address is zero, then return eye-catcher
+ // address.
+ if( i_hdrAddr->start_addr != 0 )
+ {
+ l_rc = i_hdrAddr->start_addr;
+ }
+ else
+ {
+ l_rc = EYE_CATCHER_ADDRESS;
+ }
+ }
+ else
+ {
+ // At this point we know that main application destination address
+ // is within SRAM range.
+ // Now copy main application header specified
+ // size of data from main memory to main application header specified
+ // start address.
+ uint8_t * l_srcPtr = (uint8_t *) (i_hdrAddr);
+ uint8_t * l_destPtr = (uint8_t *) (i_hdrAddr->start_addr);
+ uint32_t l_numWords = i_hdrAddr->image_size;
+
+ while (l_numWords != 0 )
+ {
+ *l_destPtr = *l_srcPtr;
+ l_destPtr++;
+ l_srcPtr++;
+ l_numWords = l_numWords - 1;
+ }
+ }
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: boot_test_sram
+//
+// Description: This function tests SRAM by writing some bit pattern and
+// verifying it back through read
+//
+//
+// Flow: 06/22/2011 FN= boot_test_sram
+//
+// End Function Specification
+
+uint32_t boot_test_sram()
+{
+ uint32_t l_rc = 0;
+
+ // Point start to SRAM start address
+ uint32_t * l_startPtr = (uint32_t *) SRAM_TEST_START_ADDRESS;
+
+ // Copy bit pattern from start until SRAM end address
+ while( (uint32_t)l_startPtr < SRAM_TEST_END_ADDRESS )
+ {
+ *l_startPtr = SRAM_TEST_BIT_PATTERN;
+ l_startPtr++;
+ }
+
+ // Reset start pointer to point to SRAM start Address
+ l_startPtr = (uint32_t *) SRAM_TEST_START_ADDRESS;
+
+ //Read and verify bit pattern that was written. If pattern does not match,
+ // return address that failed to match the pattern.
+ while( (uint32_t)l_startPtr < SRAM_TEST_END_ADDRESS )
+ {
+ if( (*l_startPtr) != SRAM_TEST_BIT_PATTERN)
+ {
+ l_rc = (uint32_t)l_startPtr;
+ break;
+ }
+ l_startPtr++;
+ }
+
+ return l_rc;
+}
+
+
diff --git a/src/occBootLoader/bootMain.h b/src/occBootLoader/bootMain.h
new file mode 100755
index 0000000..0d836c5
--- /dev/null
+++ b/src/occBootLoader/bootMain.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+// @file bootMain.h
+// @brief OCC boot loader main defines
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section bootMain.h BOOTMAIN.H
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb000 pbavari 06/22/2011 Created
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @ai007 ailutsar 12/10/2012 Change OCC Image Header to reserve 64 bytes
+ * for SRAM Repair instead of 16
+ * @th030 thallet 02/03/2013 Need to reserve last 1kB for PORE-SLW
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _bootMain_h
+#define _bootMain_h
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#ifndef __ASSEMBLER__
+#include <common_types.h> // defines imageHdr_t and other types
+#endif /* __ASSEMBLER__ */
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define MACHINE_CHECK_ENABLE 0x00001000
+#define DATA_CACHE_BLOCK_ENABLE 0x00008000
+#define DATA_CACHE_BLOCK_ADDR 0x80000000
+#define DATA_CACHE_SIZE (16 * 1024)
+#define CACHE_LINE_SIZE 32
+#define DATA_CACHE_LINES (DATA_CACHE_SIZE/CACHE_LINE_SIZE)
+
+// Data cache address + 8K
+#define STACK_POINTER_ADDR ( DATA_CACHE_BLOCK_ADDR + 0x2000)
+
+#ifndef __ASSEMBLER__
+
+typedef enum CHKPOINT
+{
+ BOOT_TEST_SRAM_CHKPOINT = 0x00000001,
+ BOOT_LOAD_IMAGE_CHKPOINT = 0x00000002,
+ BOOT_CALCULTE_CHKSUM_CHKPOINT= 0x00000003,
+ BOOT_GET_NEST_FREQ_CHKPOINT = 0x00000004,
+ BOOT_SSX_BOOT_CALL_CHKPOINT = 0x00000005,
+ BOOT_SSX_RETURNED_CHKPOINT = 0x00000006
+}CHKPOINT;
+
+#endif /* __ASSEMBLER__ */
+
+#define SRAM_TEST_START_ADDRESS 0xFFF80040 // @ai007c
+#define SRAM_START_ADDRESS 0xFFF80000
+#define SRAM_TEST_END_ADDRESS 0xFFFFFBFF // @th030c
+#define SRAM_END_ADDRESS 0xFFFFFFFF
+#define SRAM_TEST_BIT_PATTERN 0xA5A5A5A5
+#define EYE_CATCHER_ADDRESS 0x1234ABCD
+
+#define BOOT_LOADER_ID "OCC Boot Image\0"
+
+// Define to write val to SPRG0 register
+#define WRITE_TO_SPRG0(val) \
+ ({__asm__ __volatile__ ("mtsprg0 %0;" ::"r"(val));})
+
+#define WRITE_TO_SPRG1_AND_HALT(rc) \
+ ({__asm__ __volatile__ ( "mtsprg1 %0;" "tw 31,0,0;": : "r" (rc));})
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+#endif // _bootMain_h
+
+
diff --git a/src/occBootLoader/bootfiles.mk b/src/occBootLoader/bootfiles.mk
new file mode 100755
index 0000000..f7b2cbc
--- /dev/null
+++ b/src/occBootLoader/bootfiles.mk
@@ -0,0 +1,28 @@
+# @file libofiles.mk
+#
+# @brief mk for libssx.a object files
+#
+# @page ChangeLogs Change Logs
+# @section ofiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/28/2012 Makefile ODE support
+# @rc004 882410 rickylie 05/10/2013 Pin OCC Firmware Level to an Address in Lid
+#
+# @endverbatim
+#
+##########################################################################
+# INCLUDES
+##########################################################################
+C-SOURCES = bootMain.c ../occ/occbuildname.c
+S-SOURCES = bootInit.S ../ssx/ppc32/savegpr.S
+
+BOOTLOADER_OBJECTS = $(C-SOURCES:.c=.o) $(S-SOURCES:.S=.o)
+
+
+
+
diff --git a/src/occBootLoader/imageHdrScript.c b/src/occBootLoader/imageHdrScript.c
new file mode 100755
index 0000000..77bb134
--- /dev/null
+++ b/src/occBootLoader/imageHdrScript.c
@@ -0,0 +1,877 @@
+/******************************************************************************
+// @file imageHdrScript.c
+// @brief Helper script to fix image header fields and other image related
+// support
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section imageHdrScript.c IMAGEHDRSCRIPT.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @pb000 pbavari 06/28/2011 Created
+ * @pb001 pbavari 07/21/2011 Changed the way image is being
+ * combined to support applet images
+ * @pb006 pbavari 09/16/2011 Display object size support
+ * @pb00A pbavari 11/17/2011 Added check for 128 bytes
+ * alignment for image size.
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb010 D856284 pbavari 10/05/2012 Fix displaySize option
+ * @ai004 ailutsar 11/06/2012 Improvement for imageHdrScript help text
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <common_types.h>
+#include <stddef.h>
+#include <string.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+#define CHECKSUM_FIELD_OFFSET offsetof(imageHdr_t, checksum)
+#define CHECKSUM_FIELD_LEN 4
+#define IMAGE_SZ_FIELD_OFFSET offsetof(imageHdr_t, image_size)
+#define IMAGE_SZ_FIELD_LEN 4
+#define FAILURE_RC -1
+#define SUCCESS_RC 0
+#define EP_BRANCH_INST_LEN 4
+#define EP_BRANCH_INST_OFFSET offsetof(imageHdr_t, ep_branch_inst)
+#define ADDRESS_OFFSET offsetof(imageHdr_t, ep_addr)
+#define ADDRESS_LEN 4
+#define VERSION_OFFSET offsetof(imageHdr_t, version)
+#define VERSION_LEN 4
+#define ID_STR_OFFSET offsetof(imageHdr_t, image_id_str)
+#define ID_STR_LEN IMAGE_ID_STR_SZ
+#define ADDRESS_MASK 0x03FFFFFC
+#define BRANCH_MASK 0x48000002
+#define DUMP_HDR_STR "dumpHdr"
+#define COMBINE_IMAGE_STR "combineImage"
+
+// >> gitprep
+#define FILE_TO_WRITE_ODE "/obj/ppc/occc/405/image.bin"
+#define FILE_TO_WRITE_GNU "image.bin"
+// << gitprep
+
+//@pb006a - start
+#define DISPLAY_SIZE "displaySize"
+#define READELF_CMD "readelf -S "
+#define PIPE_CMD " > elfdata "
+#define ELF_FILE "elfdata"
+#define ELF_FILE_REMOVE_CMD "rm elfdata"
+//@pb006a - end
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+//@pb006a
+// Function Specification
+//
+// Name: displaySize
+//
+// Description: Display size of the object file
+//
+// Flow: FN=None
+//
+// End Function Specification
+int displaySize(char * i_file)
+{
+ int l_rc = SUCCESS_RC;
+ unsigned long int l_size = 0;
+ FILE * l_file = NULL;
+ int l_delfile = 0;
+ do
+ {
+ // create command for the system call to display size using
+ // readelf tool and copy output into different file for parsing later.
+ if( i_file != NULL)
+ {
+ l_size = strlen(i_file);
+ }
+ l_size += strlen(READELF_CMD);
+ l_size += strlen(PIPE_CMD);
+ char l_cmd[l_size+1];
+ unsigned long int l_cnt = strlen(READELF_CMD);
+ strncpy(l_cmd,READELF_CMD,l_cnt);
+ strncpy(&l_cmd[l_cnt],i_file,strlen(i_file));
+ l_cnt += strlen(i_file);
+ strncpy(&l_cmd[l_cnt],PIPE_CMD,strlen(PIPE_CMD));
+ l_cnt += strlen(PIPE_CMD);
+ l_cmd[l_cnt] = '\0';
+ // do system call
+ system (l_cmd );
+ // set to indicate delete temporary file
+ l_delfile = 1;
+ // Open the file that was written with the system call for
+ // reading
+ l_file = fopen(ELF_FILE, "r");
+
+ if( NULL == l_file)
+ {
+ printf("Failed to open file %s for reading\n",ELF_FILE);
+ l_rc = FAILURE_RC;
+ break;
+ }
+ // seek to end to get size of file
+ l_rc = fseek(l_file, 0, SEEK_END);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek end of the file: %s,rc: %d\n",
+ i_file,l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+ // get size
+ l_size = ftell(l_file);
+
+ //Now seek back to the beginning to start parsing
+ l_rc = fseek(l_file, 0, SEEK_SET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek start after getting size of the file: %s, "
+ "rc: %d\n",i_file,l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ // parse data and display size
+ char l_data[l_size];
+ unsigned long int l_totalSz = 0;
+ char * l_str = NULL;
+ printf("===========================================================\n");
+ printf("Size display for %s:\n", i_file);
+ printf("%-25.25s : Address : Size \n","Section");
+ printf("===========================================================\n");
+ while (fgets(l_data,l_size,l_file) != NULL)
+ {
+ // Ignore lines that does not have BITS in them
+ if(strstr(l_data,"BITS") != NULL)
+ {
+ // If there is word debug on the line then we are done parsing
+ if(strstr(l_data,"debug") != NULL)
+ {
+ break;
+ }
+ //@pb010a - start
+ l_str = NULL;
+ // We need to parse 2 different options:
+ // 1) [ X] and 2) [XX] Where X is number.
+ // Example of data:
+ // Num Section Type Addr offset Size
+ // [ 9] .linear_wr PROGBITS ffff6000 046000 001000 00 WA 0 0 1
+ // [10] .linear_rd PROGBITS ffff7000 047000 001000 00 WA 0 0 1
+ // We are interested in Section, Address, offset and size.
+ // Everything else we can ignore. So for ease of parsing,
+ // ignore everything until first "]".
+ l_str = strstr(l_data,"]");
+ if( NULL != l_str )
+ {
+ char l_str1[l_size];
+ char l_sec[l_size];
+ unsigned long int l_addr = 0;
+ unsigned long int l_offset = 0;
+ unsigned long int l_size = 0;
+ sscanf(l_str,"%s %s %s %x %x %x ",l_str1,l_sec,
+ l_str1,&l_addr,&l_offset,&l_size);
+ printf("%-25.25s : 0x%08x : %d\t(HEX: %x ) \n",l_sec,
+ l_addr,(int)l_size,l_size);
+ l_totalSz += l_size;
+ }
+ //@pb010a - end
+ }
+ } // end while loop
+ printf("===========================================================\n");
+ printf("%-25.25s : : %d\t(HEX: %x ) \n","Total",
+ (int)l_totalSz,l_totalSz);
+ printf("===========================================================\n");
+
+ }while(0);
+
+ // Close file if it was open
+ if( l_file != NULL)
+ {
+ int l_rc2 = fclose( l_file);
+
+ if( l_rc2 != 0)
+ {
+ printf("Failed to close destination file: rc: %d\n",l_rc2);
+ }
+ }
+
+ if( l_delfile == 1)
+ {
+ // remove temporary file
+ system(ELF_FILE_REMOVE_CMD);
+ }
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: combineImage
+//
+// Description: Append input image to $sb/src/image.bin
+//
+// Flow: FN=None
+//
+// End Function Specification
+int combineImage(char * i_file1)
+{
+ FILE * l_file1 = NULL;
+ FILE * l_file2 = NULL;
+ FILE * l_file = NULL;
+ int l_rc = SUCCESS_RC;
+ unsigned long int l_size = 0;
+ // >> gitprep
+ bool l_odeBuild = TRUE;
+ // << gitprep
+
+ do
+ {
+ char * l_sbPath = getenv("SANDBOXBASE");
+ if( l_sbPath != NULL)
+ {
+ l_size = strlen(l_sbPath);
+ // >> gitprep
+ l_size += strlen(FILE_TO_WRITE_ODE);
+ // << gitprep
+ }
+ else
+ {
+ // >> gitprep
+ l_sbPath = getenv("OCCROOT");
+ if(l_sbPath != NULL)
+ {
+ l_size = strlen(l_sbPath);
+ l_size += strlen(FILE_TO_WRITE_GNU);
+ l_odeBuild = FALSE;
+ }
+ else
+ {
+ printf("Failed to get either SANDBOXBASE or OCCROOT environment variables\n");
+ l_rc = FAILURE_RC;
+ break;
+ }
+ // << gitprep
+ }
+ char l_fileToWrite[l_size+1];
+ strncpy(l_fileToWrite,l_sbPath,strlen(l_sbPath));
+
+ // >> gitprep
+ if ( TRUE == l_odeBuild )
+ {
+ strncpy(&l_fileToWrite[strlen(l_sbPath)],FILE_TO_WRITE_ODE,strlen(FILE_TO_WRITE_ODE));
+ }
+ else
+ {
+ strncpy(&l_fileToWrite[strlen(l_sbPath)],FILE_TO_WRITE_GNU,strlen(FILE_TO_WRITE_GNU));
+ }
+ // << gitprep
+ l_fileToWrite[l_size] = '\0';
+ // >> gitprep
+ printf("l_fileToWrite: %s\t\tl_sbPath: %s\n", l_fileToWrite, l_sbPath);
+ // << gitprep
+ // Open the file1
+ l_file1 = fopen(i_file1, "r");
+
+ if( NULL == l_file1)
+ {
+ printf("Failed to open file %s for reading\n",i_file1);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ // Open the destination file
+ l_file = fopen(l_fileToWrite, "a");
+
+ if( NULL == l_file)
+ {
+ printf("Failed to open file %s for reading\n",l_fileToWrite);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ // get size of file1
+ l_rc = fseek(l_file1, 0, SEEK_END);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek end of the file: %s,rc: %d\n",
+ i_file1,l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ unsigned long int l_sz1 = ftell(l_file1);
+
+ //Now seek back to the beginning
+ l_rc = fseek(l_file1, 0, SEEK_SET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek start after getting size of the file: %s, "
+ "rc: %d\n",i_file1,l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ // Read full file into buffer
+ unsigned int l_data[l_sz1];
+ size_t l_readSz = fread(&l_data[0], 1, l_sz1, l_file1);
+
+ if( l_readSz != l_sz1)
+ {
+ printf("Failed to read file: %s,readSz: 0x%x,l_sz: 0x%x\n",
+ i_file1,l_readSz,l_sz1);
+ l_rc = -1;
+ break;
+ }
+
+ // Write file1 data to destination file
+ size_t l_writeSz = fwrite( l_data,1,l_sz1,l_file);
+
+ if( l_writeSz != l_sz1)
+ {
+ printf("Error writing data. Written Sz :0x%x,Expected Sz:0x%x\n",
+ l_writeSz,l_sz1);
+ l_rc = FAILURE_RC;
+ }
+
+ }while(0);
+
+ // Close file1 if it was open
+ if( l_file1 != NULL)
+ {
+ int l_rc2 = fclose( l_file1);
+
+ if( l_rc2 != 0)
+ {
+ printf("Failed to close file: %s,rc: %d\n", i_file1,l_rc2);
+ }
+ }
+
+ // Close destination file if it was open
+ if( l_file != NULL)
+ {
+ int l_rc2 = fclose( l_file);
+
+ if( l_rc2 != 0)
+ {
+ printf("Failed to close destination file: rc: %d\n",l_rc2);
+ }
+ }
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: dumpHdr
+//
+// Description: Dump image header
+//
+// Flow: FN=None
+//
+// End Function Specification
+int dumpHdr(char * i_fileStr)
+{
+ FILE * l_filePtr = NULL;
+ int l_rc = SUCCESS_RC;
+ do
+ {
+ // Open the file
+ l_filePtr = fopen(i_fileStr, "rb");
+
+ if( NULL == l_filePtr)
+ {
+ printf("Failed to open file %s for reading\n",i_fileStr);
+ l_rc = FAILURE_RC;
+ break;
+ }
+ // file is open now
+ // get the file size
+ l_rc = fseek(l_filePtr, 0, SEEK_END);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek end of the file: %s,rc: %d\n",
+ i_fileStr,l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ unsigned long int l_sz = ftell(l_filePtr);
+
+ //Now seek back to the beginning
+ l_rc = fseek(l_filePtr, 0, SEEK_SET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek start after getting size of the file: %s, "
+ "rc: %d\n",i_fileStr,l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ l_sz = sizeof(imageHdr_t);
+
+ // Read header from the file
+ unsigned int l_hdrPtr[l_sz];
+ size_t l_readSz = fread(&l_hdrPtr[0], 1, l_sz, l_filePtr);
+
+ if( l_readSz != l_sz)
+ {
+ printf("Failed to read file: %s,readSz: 0x%x,l_sz: 0x%x\n",
+ i_fileStr,l_readSz,l_sz);
+ l_rc = -1;
+ break;
+ }
+
+ printf("==========================================================\n");
+ printf("SRAM Repair Reserved:\t ");
+ unsigned int idx = 0;
+ for(idx = 0; idx < SRAM_REPAIR_RESERVE_SZ/4; idx++)
+ {
+ printf("0x%08X ",htonl(l_hdrPtr[idx]) );
+ }
+ printf("\n");
+ printf("ep_branch_inst:\t\t 0x%08x\n",htonl( l_hdrPtr[idx++]));
+ printf("halt_inst:\t\t 0x%x\n",htonl( l_hdrPtr[idx++]));
+ printf("image_size:\t\t 0x%08x \n", htonl( l_hdrPtr[idx++]));
+ printf("start_addr:\t\t 0x%08x\n",htonl( l_hdrPtr[idx++]));
+ printf("readonly_size:\t\t 0x%08x \n",htonl( l_hdrPtr[idx++]));
+ printf("boot_writeable_addr:\t 0x%08x\n",htonl( l_hdrPtr[idx++]));
+ printf("boot_writeable_size:\t 0x%08x \n",htonl( l_hdrPtr[idx++]));
+ printf("zero_data_addr:\t\t 0x%08x\n", htonl( l_hdrPtr[idx++]));
+ printf("zero_data_size:\t\t 0x%08x \n", htonl( l_hdrPtr[idx++]));
+ printf("ep_addr:\t\t 0x%08x\n", htonl( l_hdrPtr[idx++]));
+ printf("checksum:\t\t 0x%08x\n", htonl( l_hdrPtr[idx++]));
+ printf("version:\t\t %.*s\n", VERSION_LEN,(char*)&l_hdrPtr[idx++]);
+ printf("image_id_str:\t\t %s\n",(char*)(&l_hdrPtr[idx]));
+ idx += (IMAGE_ID_STR_SZ/4);
+ unsigned int i = 0;
+ printf("Reserved:\t\t ");
+ for(i = 0; i < RESERVED_SZ/4; i++)
+ {
+ printf("0x%08X ",htonl(l_hdrPtr[idx++]) );
+ }
+ printf("\n");
+ printf("==========================================================\n");
+
+ }while(0);
+
+ // Close file if open
+ if( l_filePtr != NULL)
+ {
+ int l_rc2 = fclose( l_filePtr);
+
+ if( l_rc2 != 0)
+ {
+ printf("Failed to close file: %s,rc: %d\n", i_fileStr,l_rc2);
+ }
+ }
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: calImageChecksum
+//
+// Description: calculate image checksum
+//
+// Flow: FN=None
+//
+// End Function Specification
+unsigned long int calImageChecksum(FILE * i_filePtr)
+{
+ unsigned long int l_checksum = 0;
+
+ unsigned long int l_counter = 0;
+ int l_val = fgetc(i_filePtr);
+
+ while( l_val != EOF)
+ {
+ l_checksum += l_val;
+ l_counter += 1;
+ // Skip checksum field
+ if( l_counter == CHECKSUM_FIELD_OFFSET)
+ {
+ while( l_counter != (CHECKSUM_FIELD_OFFSET + CHECKSUM_FIELD_LEN))
+ {
+ l_counter++;
+ l_val = fgetc(i_filePtr);
+ }
+ }
+ l_val = fgetc(i_filePtr);
+ }
+
+ // >> gitprep
+ fprintf(stdout,"Checksum: 0x%08X\t\tSize: 0x%08X\n", l_checksum, l_counter);
+ // << gitprep
+ return l_checksum;
+}
+
+
+// Function Specification
+//
+// Name: write
+//
+// Description: Write given data to file at given offset
+//
+// Flow: FN=None
+//
+// End Function Specification
+int write(FILE * i_filePtr,
+ const void * i_dataPtr,
+ const unsigned long int i_dataSz,
+ const unsigned long int i_dataOffset)
+{
+ int l_rc = SUCCESS_RC;
+
+ l_rc = fseek(i_filePtr, i_dataOffset, SEEK_SET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek offset: [0x%x] while writing to file,rc: %d\n",
+ i_dataOffset,l_rc);
+ l_rc = FAILURE_RC;
+ }
+ else
+ {
+ size_t l_writeSz = fwrite( i_dataPtr,1,i_dataSz,i_filePtr);
+
+ if( l_writeSz != i_dataSz)
+ {
+ printf("Error writing data. Written Sz :0x%x,Expected Sz:0x%x\n",
+ l_writeSz,i_dataSz);
+ l_rc = FAILURE_RC;
+ }
+ }
+
+ return l_rc;
+}
+
+
+// Function Specification
+//
+// Name: printHelp
+//
+// Description: script usage
+//
+// Flow: FN=None
+//
+// End Function Specification
+void printHelp()
+{
+ // @ai004M
+ printf("Script Usage: imageHdrScript [FILE] [OPTIONS]\n\n");
+
+ printf("This OCC Image Header Script is used for handling different image header\n");
+ printf("fields and combining different OCC images into single image.\n");
+ // >> gitprep
+ if ( NULL != getenv("SANDBOXBASE") )
+ {
+ printf("The path to target image is $SANDBOXBASE%s\n\n", FILE_TO_WRITE_ODE);
+ }
+ else
+ {
+ printf("The path to target image is $OCCROOT%s\n\n", FILE_TO_WRITE_GNU);
+ }
+ // << gitprep
+ printf("Option for ELF executable file (file type: *.out):\n");
+ printf(" displaySize check section sizes in input file\n");
+ printf("Options for binary image file (file type: *.bin):\n");
+ printf(" combineImage append input image to the target image\n");
+ printf(" dumpHdr dump values of each header field in input image\n\n");
+
+ printf("If the option string is not equal to \"combineImage\", \"displaySize\", or\n");
+ printf("\"dumpHdr\", the script will use that string as image version, and start to\n");
+ printf("check/update image header fields.\n");
+ printf("Example:\n");
+ printf(" imageHdrScript IMAGE_FILE VERSION_STRING\n");
+ printf(" imageHdrScript IMAGE_FILE VERSION_STRING ID_STRING\n");
+}
+
+
+// Function Specification
+//
+// Name: main
+//
+// Description: main for the script
+//
+// Flow: FN=None
+//
+// End Function Specification
+int main(int argc, char* argv[])
+{
+ FILE * l_filePtr = NULL;
+ int l_rc = SUCCESS_RC;
+
+ do
+ {
+ if( argc <= 2)
+ {
+ printHelp();
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ if( (strcmp(argv[2],DUMP_HDR_STR)== 0))
+ {
+ printf("Dump Image Header\n");
+ l_rc = dumpHdr(argv[1]);
+
+ if( l_rc != 0)
+ {
+ printf("Problem dumping header for file: %s,rc: %d\n",
+ argv[1],l_rc);
+ l_rc = FAILURE_RC;
+ }
+ break;
+ }
+
+ if( (argc > 2) && (strcmp(argv[2],COMBINE_IMAGE_STR)== 0))
+ {
+ printf("Combining image from file: %s\n",argv[1]);
+ l_rc = combineImage(argv[1]);
+
+ if( l_rc != 0)
+ {
+ printf("Problem combining image: rc: %d\n",l_rc);
+ l_rc = FAILURE_RC;
+ }
+ break;
+ }
+ //@pb006a - display size
+ if( (argc > 2) && (strcmp(argv[2],DISPLAY_SIZE)== 0))
+ {
+ l_rc = displaySize(argv[1]);
+
+ if( l_rc != 0)
+ {
+ printf("Problem displaying size: rc: %d\n",l_rc);
+ l_rc = FAILURE_RC;
+ }
+ break;
+ }
+
+ // At this point we know there is atleast 1 argument to the program
+
+ // Open the file
+ l_filePtr = fopen(argv[1], "r+");
+
+ if( NULL == l_filePtr)
+ {
+ printf("Failed to open file %s for reading and writing\n",argv[1]);
+ l_rc = FAILURE_RC;
+ break;
+ }
+ // file is open now
+ // get the file size
+ l_rc = fseek(l_filePtr, 0, SEEK_END);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek end of the file: %s, rc: %d\n",argv[1],l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ unsigned long int l_sz = ftell(l_filePtr);
+
+ if( l_sz % 128 != 0)
+ {
+ printf("Image size:[%d] in file: [%s] is not 128-byte aligned\n",
+ l_sz,argv[1]);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ //Now seek back to the beginning
+ l_rc = fseek(l_filePtr, 0, SEEK_SET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek start after getting size of the file: %s, "
+ "rc: %d\n",argv[1],l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ l_sz = htonl(l_sz);
+
+ // Write image size to the image header
+ l_rc = write(l_filePtr, &l_sz, IMAGE_SZ_FIELD_LEN,IMAGE_SZ_FIELD_OFFSET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to write image size in the file: %s, "
+ "rc: %d,l_sz: 0x%x,IMAGE_SZ_FIELD_LEN: %d, "
+ "IMAGE_SZ_FIELD_OFFSET: %d\n",argv[1],l_rc,
+ IMAGE_SZ_FIELD_LEN,IMAGE_SZ_FIELD_OFFSET);
+ l_rc = FAILURE_RC;
+ break;
+
+ }
+
+ // Write image version
+ unsigned long int l_version = 0;
+ sprintf((char*)&l_version, "%s",argv[2]);
+ l_rc = write(l_filePtr, &l_version, VERSION_LEN, VERSION_OFFSET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to write version in the file: %s, "
+ "rc: %d,l_sz: 0x%x,: VERSION_LEN: %d, "
+ "VERSION_OFFSET: %d\n",VERSION_LEN,l_rc,
+ VERSION_LEN,VERSION_OFFSET);
+ l_rc = FAILURE_RC;
+ break;
+
+ }
+
+ // If user has passed in image id string, write it to the image
+ if( argc > 3)
+ {
+ l_rc = write(l_filePtr, argv[3], ID_STR_LEN, ID_STR_OFFSET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to write id_str in the file: %s, "
+ "rc: %d,l_sz: 0x%x,: ID_STR_LEN: %d, "
+ "ID_STR_OFFSET: %d\n",argv[1],l_rc,
+ ID_STR_LEN,ID_STR_OFFSET);
+ l_rc = FAILURE_RC;
+ break;
+
+ }
+ }
+
+ //Now seek to the ep_address field
+ l_rc = fseek(l_filePtr, ADDRESS_OFFSET, SEEK_SET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek ep_address offset: 0x%x of the file: %s, "
+ "rc: %d\n",ADDRESS_OFFSET,argv[1],l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+ unsigned long int l_addr = 0;
+ // read ep_addr field
+ size_t l_readSz = fread(&l_addr, 1, ADDRESS_LEN, l_filePtr);
+
+ if( l_readSz != ADDRESS_LEN)
+ {
+ printf("Failed to read address for ep_branch calculation.file: %s, "
+ "readSz: 0x%x,ADDRESS_LEN: 0x%x\n",argv[1],l_readSz,
+ ADDRESS_LEN);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ // calculate branch instruction to that address and write to
+ // ep_branch_inst field in the image header
+ l_addr = ntohl(l_addr);
+ l_addr &= ADDRESS_MASK;
+ l_addr |= BRANCH_MASK;
+
+ l_addr = htonl(l_addr);
+
+ l_rc = write(l_filePtr, &l_addr, EP_BRANCH_INST_LEN,
+ EP_BRANCH_INST_OFFSET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to write ep_branch_inst in the file: %s, "
+ "rc: %d,l_sz: 0x%x,: EP_BRANCH_INST_LEN: %d, "
+ "EP_BRANCH_INST_OFFSET: %d\n",argv[1],l_rc,
+ EP_BRANCH_INST_LEN,EP_BRANCH_INST_OFFSET);
+ l_rc = FAILURE_RC;
+ break;
+
+ }
+
+ //Now seek back to the beginning for calculating checksum
+ l_rc = fseek(l_filePtr, 0, SEEK_SET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to seek start before checksum calculation.file: %s,"
+ "rc: %d\n",argv[1],l_rc);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ // calculate checksum
+ unsigned long int l_checksum = calImageChecksum(l_filePtr);
+
+ l_checksum = htonl(l_checksum);
+
+ // Write checksum
+ l_rc = write(l_filePtr, &l_checksum,CHECKSUM_FIELD_LEN,
+ CHECKSUM_FIELD_OFFSET);
+
+ if( l_rc != 0)
+ {
+ printf("Failed to write image size in the file: %s, "
+ "rc: %d,l_sz: 0x%x,IMAGE_SZ_FIELD_LEN: %d, "
+ "IMAGE_SZ_FIELD_OFFSET: %d\n",argv[1],l_rc,
+ CHECKSUM_FIELD_LEN,CHECKSUM_FIELD_OFFSET);
+ l_rc = FAILURE_RC;
+ break;
+ }
+
+ }while(0);
+
+ // Close file if open
+ if( l_filePtr != NULL)
+ {
+ int l_rc2 = fclose( l_filePtr);
+
+ if( l_rc2 != 0)
+ {
+ printf("Failed to close file: %s,rc: %d\n", argv[1],l_rc2);
+ }
+ }
+
+
+ return l_rc;
+}
diff --git a/src/occBootLoader/linkboot.cmd b/src/occBootLoader/linkboot.cmd
new file mode 100755
index 0000000..544240e
--- /dev/null
+++ b/src/occBootLoader/linkboot.cmd
@@ -0,0 +1,117 @@
+
+// $Id$
+
+
+// This linker script for the OCC Firmware boot loader. This
+// script is processed through the C proprocessor to create
+// configuration-dependent images.
+// This creates image that is 4 byte aligned.
+
+#ifdef OCCMK
+INCLUDE occLinkInputFile
+#endif
+
+#define BOOT_IMAGE_START_ADDR 0x00000000
+#define BOOT_VECTORS 0x00000000
+#define BOOT_VECTORS_SIZE 0x00000740
+#define BOOT_BUILDNAME_ADDR (BOOT_IMAGE_START_ADDR + BOOT_VECTORS_SIZE)
+#define WRITE_DATA_SEC_ADDR 0x80000000
+#define BYTE_ALIGN 128
+#define pack_0000 bootMain.o(imageHeader)
+
+MEMORY
+{
+ writeableMem : ORIGIN = WRITE_DATA_SEC_ADDR, LENGTH = 0x4000
+}
+
+SECTIONS
+{
+ . = BOOT_IMAGE_START_ADDR;
+ . = BOOT_VECTORS;
+
+ __START_ADDR__ = .;
+
+ ////////////////////////////////
+ // start read-only section
+ ////////////////////////////////
+
+ ////////////////////////////////
+ // exception/vector section
+ ////////////////////////////////
+
+ .exceptions . : {
+ ___vectors = .;
+ bootInit.o(.vectors_0000)
+ pack_0000
+ . = ___vectors + 0x0100;
+ bootInit.o(.vectors_0100)
+ . = ___vectors + 0x0200;
+ bootInit.o(.vectors_0200)
+ . = ___vectors + 0x0300;
+ bootInit.o(.vectors_0300)
+ . = ___vectors + 0x0400;
+ bootInit.o(.vectors_0400)
+ . = ___vectors + 0x0500;
+ bootInit.o(.vectors_0500)
+ . = ___vectors + 0x0600;
+ bootInit.o(.vectors_0600)
+ . = ___vectors + 0x0700;
+ bootInit.o(.vectors_0700)
+ }
+
+ ////////////////////////////////
+ // buildname section 4 byte aligned
+ ////////////////////////////////
+ . = BOOT_BUILDNAME_ADDR;
+ .buildname . : { *(.buildname) }
+
+ ////////////////////////////////
+ // text section 4 byte aligned, follows buildname section
+ ////////////////////////////////
+ // >> gitprep
+ .text . : { *(.text) *(.text.*) . = ALIGN(BYTE_ALIGN);}
+ // << gitprep
+ ////////////////////////////////
+ // SDA2 section 4 byte aligned
+ ////////////////////////////////
+
+ _SDA2_BASE_ = .;
+ .sdata2 . : { *(.sdata2) . = ALIGN(BYTE_ALIGN); }
+ .sbss2 . : { *(.sbss2) . = ALIGN(BYTE_ALIGN);}
+
+ .rodata . : { *(.rodata*) *(.got2) . = ALIGN(BYTE_ALIGN);}
+
+ __READ_ONLY_DATA_LEN__ = . - BOOT_IMAGE_START_ADDR ;
+ __WRITEABLE_ADDR__ = .;
+
+ ////////////////////////////////
+ // start writeable section has different vritual and loadable memory address
+ ////////////////////////////////
+ __WRITEABLE_DATA_ADDR__ = WRITE_DATA_SEC_ADDR;
+ __CURADDR__ = WRITE_DATA_SEC_ADDR;
+
+ ////////////////////////////////
+ // read-write section
+ ////////////////////////////////
+ .rela __CURADDR__ : AT(__WRITEABLE_ADDR__ ) { *(.rela*) . = ALIGN(BYTE_ALIGN);} > writeableMem
+ __CURADDR__ = __CURADDR__ + SIZEOF(.rela);
+ .rwdata __CURADDR__ : AT(__WRITEABLE_ADDR__ + SIZEOF(.rela)) { *(.data) *(.bss) *(COMMON) . = ALIGN(BYTE_ALIGN);} > writeableMem
+ __CURADDR__ = __CURADDR__ + SIZEOF(.rwdata);
+
+ ////////////////////////////////
+ // SDA section
+ ////////////////////////////////
+ _SDA_BASE_ = __CURADDR__;
+ .sdata __CURADDR__ : AT(__WRITEABLE_ADDR__ + SIZEOF(.rela) + SIZEOF(.rwdata)) { *(.sdata) . = ALIGN(BYTE_ALIGN);} > writeableMem
+ __CURADDR__ = __CURADDR__ + SIZEOF(.sdata);
+ .sbss (__CURADDR__) : AT( __WRITEABLE_ADDR__ + SIZEOF(.rela) + SIZEOF(.rwdata) + SIZEOF(.sdata) ) { *(.sbss) . = ALIGN(BYTE_ALIGN); } > writeableMem
+ __CURADDR__ = __CURADDR__ + SIZEOF(.sbss);
+
+ ////////////////////////////////
+ // writeable section length is all writeable section except .sbss as
+ // .sbss section is not showing up in the binary unless there is some data
+ // in the section below it. Thus it is left at the end to get same
+ // behavior all the time.
+ ////////////////////////////////
+ __WRITEABLE_DATA_LEN__ = (__WRITEABLE_ADDR__ + SIZEOF(.sdata) + SIZEOF(.rela) + SIZEOF(.rwdata)) - __WRITEABLE_ADDR__;
+}
diff --git a/src/occBootLoader/occLinkInputFile b/src/occBootLoader/occLinkInputFile
new file mode 100644
index 0000000..6fe2f9a
--- /dev/null
+++ b/src/occBootLoader/occLinkInputFile
@@ -0,0 +1 @@
+INPUT ( bootMain.o ../occ/occbuildname.o bootInit.o ../ssx/ppc32/savegpr.o )
diff --git a/src/ssx/pgp/Makefile b/src/ssx/pgp/Makefile
new file mode 100755
index 0000000..417a452
--- /dev/null
+++ b/src/ssx/pgp/Makefile
@@ -0,0 +1,38 @@
+# $Id: Makefile,v 1.2 2013/12/12 16:12:28 bcbrock Exp $
+
+# This Makefile compiles all of the SSX code required for the PgP port
+# of SSX. See the "ssx.mk" file in this directory.
+
+include ssx.mk
+include ssxpgpfiles.mk
+
+
+ifeq "$(SSX_TIMER_SUPPORT)" "1"
+PGP_OBJECTS += ${PGP-TIMER-C-SOURCES:.c=.o} ${PGP-TIMER-S-SOURCES:.S=.o}
+endif
+
+ifeq "$(SSX_THREAD_SUPPORT)" "1"
+PGP_OBJECTS += ${PGP-THREAD-C-SOURCES:.c=.o} ${PGP-THREAD-S-SOURCES:.S=.o}
+endif
+
+ifeq "$(PGP_ASYNC_SUPPORT)" "1"
+PGP_OBJECTS += ${PGP-ASYNC-C-SOURCES:.c=.o} ${PGP-ASYNC-S-SOURCES:.S=.o}
+endif
+
+
+all: local
+ $(MAKE) -I ../pgp -C ../ssx
+ $(MAKE) -I ../pgp -C ../ppc405
+
+local: $(PGP_OBJECTS)
+
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.ps *.pdf
+ $(MAKE) -I ../pgp -C ../ssx clean
+ $(MAKE) -I ../pgp -C ../ppc405 clean
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(PGP_OBJECTS:.o=.d)
+endif
diff --git a/src/ssx/pgp/linkssx.cmd b/src/ssx/pgp/linkssx.cmd
new file mode 100755
index 0000000..0556a03
--- /dev/null
+++ b/src/ssx/pgp/linkssx.cmd
@@ -0,0 +1,499 @@
+// $Id: linkssx.cmd,v 1.2 2014/03/14 16:33:45 bcbrock Exp $
+
+// This linker script creates SRAM images of SSX applications for PgP. This
+// script is processed through the C proprocessor to create
+// configuration-dependent images.
+//
+// All sections with different MMU protection properties are 1KB-aligned, even
+// when linked in real-addressing mode.
+//
+// NB: According to *info* manual for ld, it should not be necessary to specify
+// the '.' in the section commands, e.g.,
+//
+// .data.startup . : { *(.data.startup) } > sram
+//
+// However without these the sections are not aligned properly, as the linker
+// seems to ignore the LC and move the section 'backwards' until it abuts
+// (aligned) with the previous one.
+//
+// Info on PPC binaries:
+// http://devpit.org/wiki/Debugging_PowerPC_ELF_Binaries
+
+// Need to do this so that elf32-powerpc is not modified!
+#undef powerpc
+
+#ifndef INITIAL_STACK_SIZE
+#define INITIAL_STACK_SIZE 2000
+#endif
+
+OUTPUT_FORMAT(elf32-powerpc);
+
+// Define the beginning of SRAM, the location of the PowerPC exception
+// vectors (must be 64K-aligned) and the location of the boot branch.
+
+// 512 KB SRAM at the top of the 32-bit address space
+
+#define origin 0xfff80000
+#define vectors 0xfff80000
+#define reset 0xffffffec
+#define sram_available (reset - origin)
+#define sram_size 0x00080000
+
+// The SRAM controller aliases the SRAM at 8 x 128MB boundaries to support
+// real-mode memory attributes using DCCR, ICCR etc. Noncacheable access is
+// the next-to-last 128MB PPC405 region. Write-though access is the
+// next-to-next-to-last 128MB PPC405 region
+
+#define noncacheable_offset 0x08000000
+#define noncacheable_origin (origin - 0x08000000)
+
+#define writethrough_offset 0x10000000
+#define writethrough_origin (origin - 0x10000000)
+
+// Define SSX kernel text sections to be packed into nooks and crannies of
+// the exception vector area. An option is provided _not_ to pack, to help
+// better judge the best way to pack. Note that any code eligible for packing
+// is considered 'core' code that will be needed by the application at
+// runtime. Any header data is _always_ packed into .vectors_0000 however.
+//
+// Note that in order to support MMU protection, we can't pack data along
+// with the text. All of the packed data sections are thus left empty.
+
+
+// .vectors_0000
+
+#define text_0000 \
+*(.vectors_0000)
+
+#define data_0000
+
+
+// .vectors_0100
+
+#define text_0100 \
+ppc405_core.o(.text) \
+ppc405_irq_core.o(.text)
+
+#define data_0100
+
+
+// .vectors_0c00
+
+#if SSX_TIMER_SUPPORT
+#define text_0c00_conditional
+#else
+#define text_0c00_conditional
+#endif
+
+
+#define text_0c00 \
+text_0c00_conditional \
+ppc405_cache_core.o(.text)
+
+#define data_0c00
+
+
+// .vectors_0f00
+
+#if SSX_TIMER_SUPPORT
+
+#if SSX_THREAD_SUPPORT
+#define text_0f00_conditional \
+ssx_timer_init.o(.text) \
+ssx_timer_core.o(.text) \
+ssx_semaphore_core.o(.text)
+#endif /* SSX_THREAD_SUPPORT */
+
+#if !SSX_THREAD_SUPPORT
+#define text_0f00_conditional \
+ssx_timer_init.o(.text) \
+ssx_timer_core.o(.text)
+#endif /* !SSX_THREAD_SUPPORT */
+
+#else /* SSX_TIMER_SUPPORT */
+
+#define text_0f00_conditional
+#endif /* SSX_TIMER_SUPPORT */
+
+#define text_0f00 \
+text_0f00_conditional
+
+#define data_0f00
+
+// .vectors_2000
+
+#if SSX_THREAD_SUPPORT
+#define thread_text \
+ssx_thread_init.o(.text) \
+ssx_thread_core.o(.text) \
+ppc405_irq_init.o(.text) \
+ppc405_thread_init.o(.text) \
+ssx_semaphore_init.o(.text)
+#else
+#define thread_text
+#endif
+
+#if PPC405_MMU_SUPPORT
+#define mmu_text \
+ppc405_mmu.o(.text)\
+ppc405_mmu_asm.o(.text)
+#else
+#define mmu_text
+#endif
+
+#define text_2000 \
+pgp_irq_init.o(.text) \
+ppc405_cache_init.o(.text) \
+ppc405_breakpoint.o(.text) \
+pgp_cache.o(.text) \
+ssx_stack_init.o(.text) \
+thread_text \
+mmu_text \
+pgp_async.o(.text) \
+pgp_async_pore.o(.text) \
+pgp_async_ocb.o(.text) \
+pgp_async_pba.o(.text) \
+pgp_pmc.o(.text) \
+pgp_ocb.o(.text) \
+pgp_pba.o(.text) \
+pgp_id.o(.text) \
+pgp_centaur.o(.text) \
+ppc405_lib_core.o(.text) \
+ssx_core.o(.text) \
+
+#define data_2000
+
+// .vectors_0000 is always packed with header information
+
+#define pack_0000 text_0000 data_0000
+#define nopack_0000
+
+#ifndef NO_PACK_SSX
+
+#define pack_0100 text_0100 data_0100
+#define nopack_0100
+
+#define pack_0c00 text_0c00 data_0c00
+#define nopack_0c00
+
+#define pack_0f00 text_0f00 data_0f00
+#define nopack_0f00
+
+#define pack_2000 text_2000 data_2000
+#define nopack_2000
+
+#else
+
+#define pack_0100
+#define nopack_0100 text_0100 data_0100
+
+#define pack_0c00
+#define nopack_0c00 text_0c00 data_0c00
+
+#define pack_0f00
+#define nopack_0f00 text_0f00 data_0f00
+
+#define pack_2000
+#define nopack_2000 text_2000 data_2000
+
+#endif
+
+#define init_text \
+ssx_init.o(.text) \
+ppc405_boot.o(.text) \
+ppc405_init.o(.text) \
+pgp_init.o(.text)
+
+// Define memory areas.
+
+MEMORY
+{
+ sram : ORIGIN = origin, LENGTH = sram_available
+ noncacheable : ORIGIN = noncacheable_origin, LENGTH = sram_available
+ writethrough : ORIGIN = writethrough_origin, LENGTH = sram_available
+ boot : ORIGIN = reset, LENGTH = 20
+}
+
+// NB: The code that sets up the MMU assumes that the linker script provides a
+// standard set of symbols that define the base address and size of each
+// expected section. Any section with a non-0 size will be mapped in the MMU
+// using protection attributes appropriate for the section. All sections
+// requiring different MMU attributes must be 1KB-aligned.
+
+SECTIONS
+{
+ . = origin;
+ . = vectors;
+
+ _MEMORY_ORIGIN = .;
+ _MEMORY_SIZE = sram_size;
+
+ ////////////////////////////////
+ // Text0
+ ////////////////////////////////
+
+ // Low-memory kernel code and any other code that would benefit from being
+ // resident in lower-latency SRAM
+
+ _TEXT0_SECTION_BASE = .;
+ _PPC405_VECTORS_BASE = .;
+
+ .exceptions . : {
+ ___vectors = .;
+ ppc405_exceptions.o(.vectors_0000)
+ pack_0000
+ . = ___vectors + 0x0100;
+ ppc405_exceptions.o(.vectors_0100)
+ pack_0100
+ . = ___vectors + 0x0c00;
+ ppc405_exceptions.o(.vectors_0c00)
+ pack_0c00
+ . = ___vectors + 0x0f00;
+ ppc405_exceptions.o(.vectors_0f00)
+ pack_0f00
+ . = ___vectors + 0x2000;
+ ppc405_exceptions.o(.vectors_2000)
+ pack_2000
+ } > sram
+
+ // If we're not packing, then place 'core' code immediately after the
+ // exception vectors.
+
+ .nopack . : { nopack_0000 nopack_0100 nopack_0c00 nopack_0f00 nopack_2000 } > sram
+
+ . = ALIGN(1024);
+ _TEXT0_SECTION_SIZE = . - _TEXT0_SECTION_BASE;
+
+ ////////////////////////////////
+ // Noncacheable and Write-through Data
+ ////////////////////////////////
+
+ // Non-cacheable and write-through data is placed in low memory to
+ // improve latency. PORE-private text and data is also placed here. PORE
+ // text and data are segregated to enable relocated PORE disassembly of
+ //.text.pore. PORE text is read-only to OCC, however PORE data is writable
+ // by OCC to allow shared data structures (e.g., PTS).
+
+ // When running without the MMU we need to carefully arrange things such
+ // that the noncacheable and writethrough data is linked at the correct
+ // aliased VMA while remaining loaded in contiguous LMA addresses.
+
+#if PPC405_MMU_SUPPORT
+
+#define ALIASED_SECTION(s) s . : {*(s)} > sram
+
+#else
+
+#define ALIASED_SECTION(s) \
+ _LMA = . + _lma_offset; \
+ s . : AT (_LMA) {*(s)}
+
+#endif
+
+#if !PPC405_MMU_SUPPORT
+ . = . - noncacheable_offset;
+ _lma_offset = noncacheable_offset;
+#endif
+
+ _NONCACHEABLE_RO_SECTION_BASE = .;
+
+ ALIASED_SECTION(.noncacheable_ro)
+ ALIASED_SECTION(.text.pore)
+
+ . = ALIGN(1024);
+ _NONCACHEABLE_RO_SECTION_SIZE = . - _NONCACHEABLE_RO_SECTION_BASE;
+
+
+ _NONCACHEABLE_SECTION_BASE = .;
+
+ ALIASED_SECTION(.noncacheable)
+ ALIASED_SECTION(.data.pore)
+
+ . = ALIGN(1024);
+ _NONCACHEABLE_SECTION_SIZE = . - _NONCACHEABLE_SECTION_BASE;
+
+
+#if !PPC405_MMU_SUPPORT
+ . = . + noncacheable_offset - writethrough_offset;
+ _lma_offset = writethrough_offset;
+#endif
+
+
+ _WRITETHROUGH_SECTION_BASE = .;
+
+ ALIASED_SECTION(.writethrough)
+
+ . = ALIGN(1024);
+ _WRITETHROUGH_SECTION_SIZE = . - _WRITETHROUGH_SECTION_BASE;
+
+#if !PPC405_MMU_SUPPORT
+ . = . + writethrough_offset;
+#endif
+
+
+ ////////////////////////////////
+ // Read-only Data
+ ////////////////////////////////
+
+ // Accesses of read-only data may or may not benefit from being in fast
+ // SRAM - we'll give it the benefit of the doubt.
+
+ _RODATA_SECTION_BASE = .;
+
+ // SDA2 constant sections .sdata2 and .sbss2 must be adjacent to each
+ // other. Our SDATA sections are small so we'll use strictly positive
+ // offsets.
+
+ _SDA2_BASE_ = .;
+ .sdata2 . : { *(.sdata2) } > sram
+ .sbss2 . : { *(.sbss2) } > sram
+
+ // The .rodata.vclcommand section contains read-only VclCommandRecord for
+ // the benefit of the vcl_console() command interpreter.
+
+ _VCL_COMMAND_SECTION_BASE = .;
+ .rodata.vclcommand . : { *(.rodata.vclcommand) } > sram
+ _VCL_COMMAND_SECTION_SIZE = . - _VCL_COMMAND_SECTION_BASE;
+
+ // The .rodata.vclthread section contains read-only VclThreadRecord for the
+ // benefit of the thread command.
+
+ _VCL_THREAD_SECTION_BASE = .;
+ .rodata.vclthread . : { *(.rodata.vclthread) } > sram
+ _VCL_THREAD_SECTION_SIZE = . - _VCL_THREAD_SECTION_BASE;
+
+ // The .rodata.vclpackage section contains read-only char* pointers for the
+ // benefit of the package command.
+
+ _VCL_PACKAGE_SECTION_BASE = .;
+ .rodata.vclpackage . : { *(.rodata.vclpackage) } > sram
+ _VCL_PACKAGE_SECTION_SIZE = . - _VCL_PACKAGE_SECTION_BASE;
+
+ // Other read-only data.
+
+ .rodata . : { *(.rodata*) *(.got2) } > sram
+
+ . = ALIGN(1024);
+ _RODATA_SECTION_SIZE = . - _RODATA_SECTION_BASE;
+
+ ////////////////////////////////
+ // Text1
+ ////////////////////////////////
+
+ // The default text section
+
+ _TEXT1_SECTION_BASE = .;
+
+ // Initialization text. If we ever do a scheme to get rid of
+ // initialization text then this will have to be moved if we're also doing
+ // MMU protection.
+
+ .itext . : { init_text } > sram
+
+ // Other text
+ // It's not clear why boot.S is generating empty .glink,.iplt
+
+ .otext . : { *(.text) *(.text.startup)} > sram
+ .glink . : { *(.glink) } > sram
+
+ . = ALIGN(1024);
+ _TEXT1_SECTION_SIZE = . - _TEXT1_SECTION_BASE;
+
+ ////////////////////////////////
+ // Read-write Data
+ ////////////////////////////////
+
+ _DATA_SECTION_BASE = .;
+
+ // SDA sections .sdata and .sbss must be adjacent to each
+ // other. Our SDATA sections are small so we'll use strictly positive
+ // offsets.
+
+ _SDA_BASE_ = .;
+ .sdata . : { *(.sdata) } > sram
+ .sbss . : { *(.sbss) } > sram
+
+ // Other read-write data
+ // It's not clear why boot.S is generating empty .glink,.iplt
+
+ .rela . : { *(.rela*) } > sram
+ .rwdata . : { *(.data) *(.bss) } > sram
+ .iplt . : { *(.iplt) } > sram
+
+
+ // Initialization-only data. This includes the stack of main, the data
+ // structures declared by INITCALL, and any other data areas that can be
+ // reclaimed to the heap after initialization.
+ //
+ // NB: If we ever do reclaim this space, we need to modify the concept of
+ // executable free space.
+
+ _INIT_ONLY_DATA_BASE = .;
+
+ _SSX_INITIAL_STACK_LIMIT = .;
+ . = . + INITIAL_STACK_SIZE;
+ _SSX_INITIAL_STACK = . - 1;
+
+ _INITCALL_SECTION_BASE = .;
+ .data.initcall . : { *(.data.initcall) } > sram
+ _INITCALL_SECTION_SIZE = . - _INITCALL_SECTION_BASE;
+
+ .data.startup . : { *(.data.startup) } > sram
+
+ _INIT_ONLY_DATA_SIZE = . - _INIT_ONLY_DATA_BASE;
+
+ ////////////////////////////////
+ // Free Space
+ ////////////////////////////////
+
+ // If the configuration allows executing from free space - i.e.,
+ // malloc()-ing a buffer and loading and executing code from it - then the
+ // free space is separated and aligned so that it can be marked executable.
+ // Otherwise it is simply read/write like the normal data sections.
+
+#ifndef EXECUTABLE_FREE_SPACE
+#define EXECUTABLE_FREE_SPACE 0
+#endif
+
+#if PPC405_MMU_SUPPORT && EXECUTABLE_FREE_SPACE
+ . = ALIGN(1024);
+#endif
+
+ // The free space available to the program starts here. This space does
+ // not include the initial stack used by the boot loader and main(). The
+ // initial stack space is considered part of the free 'section' for MMU
+ // purposes. Free space is always 8-byte aligned.
+ //
+ // Note that there is no data after _SSX_FREE_START. When binary images
+ // are created they can be padded to _SSX_FREE_START to guarantee
+ // that .bss and COMMON data are zeroed, and that the images contain an
+ // even multiple of 8 bytes (required for HW loaders).
+
+ . = ALIGN(8);
+ _EX_FREE_SECTION_BASE = .;
+ _SSX_FREE_START = .;
+
+#if EXECUTABLE_FREE_SPACE
+ _DATA_SECTION_SIZE = . - _DATA_SECTION_BASE;
+ _EX_FREE_SECTION_SIZE = 0 - _EX_FREE_SECTION_BASE;
+#else
+ _DATA_SECTION_SIZE = 0 - _DATA_SECTION_BASE;
+ _EX_FREE_SECTION_SIZE = 0;
+#endif
+
+ ////////////////////////////////
+ // Applet areas
+ ////////////////////////////////
+
+ // These symbols are currently unused, but required to be defined.
+
+ _APPLET0_SECTION_BASE = 0;
+ _APPLET0_SECTION_SIZE = 0;
+ _APPLET1_SECTION_BASE = 0;
+ _APPLET1_SECTION_SIZE = 0;
+
+ // The final 16 bytes of memory are reserved for the hardware boot branch
+
+ _SSX_FREE_END = reset - 1;
+}
+
diff --git a/src/ssx/pgp/pgp.h b/src/ssx/pgp/pgp.h
new file mode 100755
index 0000000..fb99e4f
--- /dev/null
+++ b/src/ssx/pgp/pgp.h
@@ -0,0 +1,328 @@
+#ifndef __PGP_H__
+#define __PGP_H__
+
+// $Id: pgp.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp.h
+/// \brief The PgP environment for SSX.
+
+// This is a 'circular' reference in SSX, but included here to simplify PGAS
+// programming.
+
+#ifndef CHIP_PGP
+#define CHIP_PGP
+#include "ppc405.h"
+#endif
+
+// Can't include this here due to ordering issues. It's included in
+// ppc405_irq.h.
+// #include "pgp_irq.h"
+
+// Required for MMU Map declarations
+#include "ppc405_mmu.h"
+
+#include "pgp_common.h"
+#include "pgp_core.h"
+#include "pgp_trace.h"
+#include "pgp_ocb.h"
+#include "pgp_pba.h"
+#include "pgp_pore.h"
+#include "pgp_pmc.h"
+#include "pgp_sramctl.h"
+#include "pgp_vrm.h"
+#include "pgp_id.h"
+#include "pgp_centaur.h"
+
+#include "pcbs_register_addresses.h"
+#include "pcbs_firmware_registers.h"
+
+#include "tod_register_addresses.h"
+#include "tod_firmware_registers.h"
+
+#include "plb_arbiter_register_addresses.h"
+#include "plb_arbiter_firmware_registers.h"
+
+#include "mcs_register_addresses.h"
+#include "mcs_firmware_registers.h"
+
+#include "centaur_firmware_registers.h"
+#include "centaur_register_addresses.h"
+
+#include "tpc_register_addresses.h"
+#include "tpc_firmware_registers.h"
+
+#include "oha_register_addresses.h"
+#include "oha_firmware_registers.h"
+
+
+// Include other driver headers
+
+#include "pgp_async.h"
+
+/// \defgroup memory_map Real-mode memory map setup for SRAM-resident applications
+///
+/// Below are the interpretations of the default settings of the real-mode
+/// memory control registers. All of the settings can be overridden as
+/// compile switches for special test purposes.
+///
+/// The final 128MB of memory (the SRAM) is mapped both I- and
+/// D-cacheable. The other 7 high-memory regions aliased by the SRAM remain
+/// uncacheable, however SRAM alias region 29 is marked write-through.
+///
+/// Low memory addresses (direct-map Mainstore via PBA) are I-cacheable
+/// but not D-cacheable to improve predicatability of execution times.
+/// However, we should not execute from mainstore after initialization.
+///
+/// OCI register space (Segment '0b01') is marked guarded and non-cacheable.
+///
+/// All memory is big-endian.
+///
+/// @{
+
+#ifndef PPC405_ICCR_INITIAL
+#define PPC405_ICCR_INITIAL 0xff000001
+#endif
+
+#ifndef PPC405_DCCR_INITIAL
+#define PPC405_DCCR_INITIAL 0x00000001
+#endif
+
+#ifndef PPC405_DCWR_INITIAL
+#define PPC405_DCWR_INITIAL 0x00000004
+#endif
+
+#ifndef PPC405_SGR_INITIAL
+#define PPC405_SGR_INITIAL 0x00ff0000
+#endif
+
+#ifndef PPC405_SU0R_INITIAL
+#define PPC405_SU0R_INITIAL 0x00000000
+#endif
+
+#ifndef PPC405_SLER_INITIAL
+#define PPC405_SLER_INITIAL 0x00000000
+#endif
+
+/// @}
+
+
+/// PgP always runs from a memory image
+
+#define SSX_RUN_FROM_MEMORY 1
+
+/// This is the initial value of Cache Control Register 0 (CCR0) for PgP.
+/// This definition can be overridden by the application.
+///
+/// The default setting:
+///
+/// - Enables parity checking in the caches and TLBs. The parity mode is not
+/// modified and defaults to 'imprecise'.
+///
+/// - Enables ICU prefetching for cacheable regions (Subject to final
+/// performance evaluation). Non-cacheable regions are not prefetched.
+///
+/// - Gives highest PLB priority to ICU fetches. This setting can be
+/// overriden by scan-only dials in the PgP design which force a fixed
+/// priority on the ICU.
+///
+/// - Sets priority bit 1 to '1' for DCU operations. The DCU sets priority
+/// bit 0 automatically. This setting can also be overridden by scan-only
+/// dials that force a fixed priority on the DCU
+///
+/// Other options can be set at run time with the API \c ppc405_ccr0_modify().
+
+#ifndef PPC405_CCR0_INITIAL
+#define PPC405_CCR0_INITIAL \
+ (CCR0_DPE | CCR0_IPE | CCR0_TPE | \
+ CCR0_PFC | \
+ CCR0_IPP0 | CCR0_IPP1 | \
+ CCR0_DPP1)
+#endif
+
+
+#ifndef __ASSEMBLER__
+
+/// \page noncacheable_support Non-cacheable modes for PgP
+///
+/// In order to support evaluation of cache management strategies on
+/// performance, DMA buffers read/written by DMA devices can be declared as
+/// NONCACHEABLE or NONCACHEABLE_RO, and DMA buffers read by DMA devices can
+/// be declared as WRITETHROUGH. However the code still does an explicit
+/// FLUSH of these buffers before activating DMA devices. The configuration
+/// option NONCACHEABLE_SUPPORT determines how NONCACHEABLE, NONCACAHEABLE_RO,
+/// WRITETHROUGH and FLUSH are defined.
+///
+/// When noncacheable support is configured, the linker will link the
+/// noncacheable and writethrough sections at a fixed offset from cacheable
+/// address, depending on where SSX is loaded. Non-cacheable read-only
+/// sections are enforced only if PPC405_MMU_SUPPORT is also configured.
+/// Writethrogh sections are assumed to be read-write.
+///
+/// PGP_HIGH_MEMORY_LOAD
+///
+/// cacheable : 0xfff8000 - 0xffffffff
+/// noncacheable : 0xf7f8000 - 0xf7ffffff [cacheable - 128MB]
+/// writethrough : 0xeff8000 - 0xefffffff [cacheable - 256MB]
+
+
+#ifndef NONCACHEABLE_SUPPORT
+#define NONCACHEABLE_SUPPORT 0
+#endif
+
+
+/// Declare an aligned data structure in a noncacheable RO section
+///
+/// This macro declares an aligned data structure in a noncacheable read-only
+/// section. The linker requires that data allocated in non-default sections
+/// be initialized - so an initialization declaration for at least one element
+/// of the data structure is required. Use a value of 8 as the default
+/// alignment.
+///
+/// See \ref noncacheable_support
+
+#if NONCACHEABLE_SUPPORT
+
+#define NONCACHEABLE_RO(declaration, alignment, initialization) \
+ declaration __attribute__ \
+ ((section (".noncacheable_ro"), aligned (alignment))) = initialization
+
+#else
+
+#define NONCACHEABLE_RO(declaration, alignment, initialization) \
+ declaration __attribute__ \
+ ((aligned (alignment))) = initialization
+
+#endif /* NONCACHEABLE_SUPPORT */
+
+
+/// Declare an aligned data structure in a noncacheable RW section
+///
+/// This macro declares an aligned data structure in a noncacheable read-write
+/// section. The linker requires that data allocated in non-default sections
+/// be initialized - so an initialization declaration for at least one element
+/// of the data structure is required. Use a value of 8 as the default
+/// alignment.
+///
+/// See \ref noncacheable_support
+
+#if NONCACHEABLE_SUPPORT
+
+#define NONCACHEABLE(declaration, alignment, initialization) \
+ declaration __attribute__ \
+ ((section (".noncacheable"), aligned (alignment))) = initialization
+
+#else
+
+#define NONCACHEABLE(declaration, alignment, initialization) \
+ declaration __attribute__ \
+ ((aligned (alignment))) = initialization
+
+#endif /* NONCACHEABLE_SUPPORT */
+
+
+/// Declare an aligned data structure in a write-through section
+///
+/// This macro declares an aligned data structure in a write-throgh section.
+/// The linker requires that data allocated in non-default sections be
+/// initialized - so an initialization declaration for at least one element of
+/// the data structure is required. Use a value of 8 as the default
+/// alignment.
+///
+/// See \ref noncacheable_support
+
+#if NONCACHEABLE_SUPPORT
+
+#define WRITETHROUGH(declaration, alignment, initialization) \
+ declaration __attribute__ \
+ ((section (".writethrough"), aligned (alignment))) = initialization
+
+#else
+
+#define WRITETHROUGH(declaration, alignment, initialization) \
+ declaration __attribute__ \
+ ((aligned (alignment))) = initialization
+
+#endif /* NONCACHEABLE_SUPPORT */
+
+
+/// Flush/invalidate a region of memory
+
+#if NONCACHEABLE_SUPPORT
+#define FLUSH(p, n) do {} while (0)
+#define INVALIDATE(p, n) do {} while (0)
+#else
+#define FLUSH(p, n) do {dcache_flush((p), (n));} while (0)
+#define INVALIDATE(p, n) do {dcache_invalidate((p), (n));} while (0)
+#endif /* NONCACHEABLE_SUPPORT */
+
+
+/// The type of linker symbols
+///
+/// C++ and current GCC versions do not allow us to declare (C++) or take the
+/// address of (C) a symbol of type void, which was an acceptable way to
+/// declare linker symbols in earlier versions of GCC. However if we declare
+/// them of type 'char' or another integral type, the compiler will try to
+/// make references to this 'data' appear to be in the small data areas (since
+/// we're compiling with the PPC EABI), which causes the link to fail since
+/// the symbols are actually defined in many different sections. The solution
+/// is to declare them to be external references of a bogus type,
+/// SsxLinkerSymbol, which is too large (9 bytes) to be stored in the small
+/// data area.
+///
+/// This type definition is considered a required definition for a port of
+/// SSX.
+
+typedef struct {
+ char bogus[9];
+} SsxLinkerSymbol;
+
+// Symbols defined by linkssx.cmd, used during MMU setup, byte-pool setup, and
+// other purposes.
+
+extern SsxLinkerSymbol _MEMORY_ORIGIN;
+extern SsxLinkerSymbol _MEMORY_SIZE;
+extern SsxLinkerSymbol _TEXT0_SECTION_BASE;
+extern SsxLinkerSymbol _TEXT0_SECTION_SIZE;
+extern SsxLinkerSymbol _TEXT1_SECTION_BASE;
+extern SsxLinkerSymbol _TEXT1_SECTION_SIZE;
+extern SsxLinkerSymbol _RODATA_SECTION_BASE;
+extern SsxLinkerSymbol _RODATA_SECTION_SIZE;
+extern SsxLinkerSymbol _NONCACHEABLE_RO_SECTION_BASE;
+extern SsxLinkerSymbol _NONCACHEABLE_RO_SECTION_SIZE;
+extern SsxLinkerSymbol _NONCACHEABLE_SECTION_BASE;
+extern SsxLinkerSymbol _NONCACHEABLE_SECTION_SIZE;
+extern SsxLinkerSymbol _WRITETHROUGH_SECTION_BASE;
+extern SsxLinkerSymbol _WRITETHROUGH_SECTION_SIZE;
+extern SsxLinkerSymbol _DATA_SECTION_BASE;
+extern SsxLinkerSymbol _DATA_SECTION_SIZE;
+extern SsxLinkerSymbol _EX_FREE_SECTION_BASE;
+extern SsxLinkerSymbol _EX_FREE_SECTION_SIZE;
+extern SsxLinkerSymbol _APPLET0_SECTION_BASE;
+extern SsxLinkerSymbol _APPLET0_SECTION_SIZE;
+extern SsxLinkerSymbol _APPLET1_SECTION_BASE;
+extern SsxLinkerSymbol _APPLET1_SECTION_SIZE;
+extern SsxLinkerSymbol _SSX_FREE_START;
+extern SsxLinkerSymbol _SSX_FREE_END;
+
+// Global MMU maps to allow remapping certain regions
+
+extern Ppc405MmuMap G_ex_free_mmu_map;
+extern Ppc405MmuMap G_applet0_mmu_map;
+extern Ppc405MmuMap G_applet1_mmu_map;
+
+#endif /* __ASSEMBLER__ */
+
+// PgP defines a private version of dcache_flush_all() that uses the undefined
+// OCI space at 0x80000000; See dcache_flush_all() in pgp_cache.S.
+
+#define USE_GENERIC_DCACHE_FLUSH_ALL 0
+#define PGP_FLUSH_ZERO_ADDRESS 0x80000000
+#define PGP_FLUSH_ZERO_DCCR 0x00008000
+
+#endif /* __PGP_H__ */
diff --git a/src/ssx/pgp/pgp_async.c b/src/ssx/pgp/pgp_async.c
new file mode 100755
index 0000000..3bf9a63
--- /dev/null
+++ b/src/ssx/pgp/pgp_async.c
@@ -0,0 +1,1024 @@
+// $Id: pgp_async.c,v 1.4 2014/02/14 12:18:05 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_async.c
+/// \brief Support for asynchronous request queuing and callback mechanisms
+///
+/// This file implements device drivers for asynchronous requests. The model
+/// for devices like the PORE engines and the PBA block copy engines is that
+/// the application creates self-contained requests for jobs to run on the
+/// engine. The application then schedules the request and continues normal
+/// processing, or threads can request to simply block in place until the
+/// request finishes. Queue management is handled in the interrupt handler
+/// for the engine. As each queued job finishes, the next request (if any) is
+/// started on the engine and the optional callback is invoked or scheduled.
+///
+/// The application can either use a polling protocol or the asynchronous
+/// callback mechanism to determine the state of the request. A timeout
+/// mechanism is also provided that cancels or kills a job that does not
+/// complete within a fixed time. Error handling in the event that the request
+/// does not complete in time or has failed is standardized by the
+/// implementation, but can be overridden by the application.
+///
+/// Asynchronous request interrupt handlers can run either as critical or
+/// noncritical handlers. Some engines may support queuing requests that
+/// complete immediately; therefore the kernel context of the callback may be
+/// either a thread or interupt context, and in general, callbacks should not
+/// make assumptions about the kernel context when they run.
+///
+/// If the callback is non-NULL and the request was created with \c
+/// ASYNC_CALLBACK_IMMEDIATE, the callback is then immediately invoked in the
+/// current context. In general, immediate callbacks should be short and sweet
+/// (to reduce interrupt latency) and should not make SSX kernel calls.
+///
+/// If the request has a non-NULL callback and was created with \c
+/// ASYNC_CALLBACK_DEFERRED then the callback will be deferred to a
+/// noncritical interrupt context. Deferred callbacks are queued, then run
+/// later in response to a reserved IPI. Deferred callbacks always run as
+/// noncritical interrupt handlers with noncritical interrupts \e enabled,
+/// similar to SSX timer callbacks.
+///
+/// If the request has a non-null callback and was created with \c
+/// ASYNC_CALLBACK_NONCRITICAL, then the callback will be run immediately from
+/// a noncritical handler or thread environment, or deferred from a critical
+/// interrupt context. Similar to immediate callbacks, callbacks marked
+/// noncritical should be short and sweet (to reduce interrupt latency), but
+/// may make SSX kernel calls.
+///
+/// Regardless of whether the callback is critical or noncritical, the
+/// callback is coded as a normal C or assembler subroutine with a single
+/// void* argument.
+///
+/// As a programming shortcut, the AsyncRequest includes a semaphore object.
+/// A special AsyncRequest option ASYNC_REQUEST_BLOCKING indicates that the
+/// thread scheduling the request should block on the semaphore of the
+/// AsyncRequest (with SSX_WAIT_FOREVER) until the request is complete. Note
+/// that a separate callback can be specified even if ASYNC_REQUEST_BLOCKING
+/// is specified.
+///
+/// Requests are always timestamped. The \a start_time field of the request is
+/// set from the SSX timebase when the request is first 'run' on the device.
+/// Request types that may require multiple back-to-back 'runs' (like PBA
+/// block copies with more than 4K data) only record the initial 'run'. The \a
+/// end_time field of the request is set from the SSX timebase when the job
+/// finishes on the hardware, but before any callback is run. These
+/// timestamps cover time intervals not visible to the application; The
+/// application is responsible for timestamping the period between request
+/// queing and the \a start_time, and between the \a end_time and callback
+/// completion if required. The timestamps can be robustly recovered from the
+/// request using the API async_request_timestamps_get().
+///
+/// This is largely a generic implementation, designed to reduce code space by
+/// allowing the PORE, PBA and OCB drivers to use the same generic data
+/// structures and code. This is supported by the 'single-inheritence class
+/// hierarchy' described in the comments for pgp_async.h.
+///
+/// <b> Request Completion and Callback States </b>
+///
+/// The application can determine what happend to the job by observing the
+/// request state and callback return code when the request becomes idle.
+/// A request is not considered idle until the job has run to completion or
+/// been aborted, any callback has been run, any timeout has been cancelled,
+/// and any thread pending on request completion has been maxde runnable.
+///
+/// Normally the application should see the request state (\a request->state)
+/// ASYNC_REQUEST_STATE_COMPLETE and a callback return code
+/// (\a request=->callback_rc) of 0 which indicates that the job and callback
+/// both completed normally. If the request did not complete normally it
+/// could be due to one of several reasons. For further analysis the request
+/// also includes a field \a abort_state that records the state the job was in
+/// when it was aborted (i.e., cancelled, killed, timed out or error-out).
+///
+/// <b> Timeout Semantics </b>
+///
+/// Any timeout other than SSX_WAIT_FOREVER specifies a timeout covering the
+/// interval spanning the time a job is scheduled until the time the job
+/// completes on the hardware. If the job is still wating to execute when it
+/// times out then the job is simply removed from the queue and marked as
+/// having timed out. If the job is running when it times out then the job is
+/// forceably removed from the hardware, which may have unintended or
+/// indeterminate consequences. The application may need to consider whether
+/// it is safe to continue after a forced timeout.
+///
+/// Specifying a timeout involves quite a bit of overhead, since a timer needs
+/// to be scheduled and cancelled each time a job is run. If the interrupt
+/// handler for a device is a critical handler then the timeout cancellation
+/// will need to be deferred to the callback queue, potentially increasing
+/// overhead even further.
+///
+/// <b> Implementation Notes </b>
+///
+/// - The \e queue objects will normally be global data structures that
+/// persist throughout the life of the application.
+///
+/// - The \e request objects may be either global or local data
+/// structures. However, since \e request objects are not copied, and pointers
+/// to them are stored in the \e queue objects, \a request objects should not
+/// be allocated on the stack if the stack frame could become invalid before
+/// the request completes.
+///
+/// \todo Once all function is developed and tested, convert interrupt
+/// handling to fast-mode assembler routines.
+
+#include "ssx.h"
+
+
+////////////////////////////////////////////////////////////////////////////
+// Global Data
+////////////////////////////////////////////////////////////////////////////
+
+/// Queue of deferred callbacks
+
+static SsxDeque G_async_callback_queue;
+
+
+////////////////////////////////////////////////////////////////////////////
+// FFDC
+////////////////////////////////////////////////////////////////////////////
+
+/// Collect FFDC for the PLB (OCI) arbiter
+///
+/// \param ffdc A pointer to an OciFfdc structure to be filled in.
+///
+/// \param master_id The PLB (OCI) master Id of the master of interest.
+///
+/// Note: The PEAR and PESR hold error information for all OCI masters
+/// _except_ the OCC ICU and DCU. ICU and DCU errors are in the STO_PESR and
+/// STO_PEAR. Currently there is no need to collect those DCRs for 'async'
+/// errors.
+
+void
+oci_ffdc(OciFfdc* ffdc, int master_id)
+{
+ uint32_t pesr_lock_mask;
+
+ ffdc->pearl.value = mfdcr(PLB_PEARL);
+ ffdc->pesr.value = mfdcr(PLB_PESR);
+
+ pesr_lock_mask = 0x30000000 >> (4 * master_id);
+ if (ffdc->pesr.value & pesr_lock_mask) {
+ ffdc->mine = 1;
+ mtdcr(PLB_PESR, pesr_lock_mask);
+ } else {
+ ffdc->mine = 0;
+ }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// AsyncQueue
+////////////////////////////////////////////////////////////////////////////
+
+// Start an asynchronous request on the device with timestamping. This will
+// always be called from a critical section, and any timestamp is collected
+// immediately before the request is kicked off on the device. Devices like
+// the BCE engines and the OCB queue drivers may run the same request multiple
+// times to get all of the data moved. Therefore the initial timestamp is only
+// captured the first time the request is run on the device.
+
+static inline int
+async_request_run(AsyncRequest *request)
+{
+ if (request->state != ASYNC_REQUEST_STATE_RUNNING) {
+ request->start_time = ssx_timebase_get();
+ }
+ request->state = ASYNC_REQUEST_STATE_RUNNING;
+ return request->run_method(request);
+}
+
+
+// Create (initialize) a generic AsyncQueue
+//
+// This is an internal API used to initialize generic request queues. The
+// caller is assumed to have done all error checking on the parameters.
+//
+// This is a simple initialization that resets the queues and sets the state
+// to QUEUE_STATE_IDLE. This routine should only be called on uninitialized
+// AsyncQueue objects.
+
+int
+async_queue_create(AsyncQueue *queue, AsyncEngine engine)
+{
+ ssx_deque_sentinel_create(&(queue->deque));
+ queue->current = 0;
+ queue->engine = engine;
+ queue->state = ASYNC_QUEUE_STATE_IDLE;
+
+ return 0;
+}
+
+
+// Generic completion of a request. This is called both by async_handler()
+// and async_request_deque().
+
+static void
+async_request_complete(AsyncRequest *request)
+{
+ SsxMachineContext ctx;
+ AsyncRequestCallback callback;
+ int completed;
+
+ // Handle callbacks and deferred processing of the job that just
+ // finished. No callback is easy. If the job does have a callback
+ // that we can execute immediately then that is done immediately.
+ // Note that 'completed' here means only that the callback is complete.
+
+ callback = request->callback;
+ if (!callback) {
+
+ completed = 1;
+
+ } else if ((request->options & ASYNC_CALLBACK_IMMEDIATE) ||
+ ((request->options & ASYNC_CALLBACK_NONCRITICAL) &&
+ !__ssx_kernel_context_critical_interrupt())) {
+
+ request->state = ASYNC_REQUEST_STATE_CALLBACK_RUNNING;
+ request->callback_rc = callback(request->arg);
+ completed = 1;
+
+ } else {
+
+ request->state = ASYNC_REQUEST_STATE_CALLBACK_QUEUED;
+ completed = 0;
+ }
+
+
+ // If the callback completed then we go ahead and cancel any timeout
+ // and/or wake the thread if possible. In critical interrupt contexts
+ // we always have to defer these operations, so we may lose 'complete'
+ // status.
+
+ if (completed &&
+ ((request->timeout != SSX_WAIT_FOREVER) ||
+ (request->options & ASYNC_REQUEST_BLOCKING))) {
+
+ if (__ssx_kernel_context_critical_interrupt()) {
+
+ request->state = ASYNC_REQUEST_STATE_POSTPROCESSING;
+ completed = 0;
+
+ } else {
+ if (request->timeout != SSX_WAIT_FOREVER) {
+ ssx_timer_cancel(&(request->timer));
+ }
+ if (request->options & ASYNC_REQUEST_BLOCKING) {
+ ssx_semaphore_post(&(request->sem));
+ }
+ }
+ }
+
+
+ // A truly completed job gets its completion state here. Otherwise we
+ // have to schedule the deferred postprocessing.
+
+ if (completed) {
+
+ request->state = request->completion_state;
+
+ } else {
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ if (request->options & ASYNC_CALLBACK_PRIORITY) {
+ ssx_deque_push_front(&G_async_callback_queue,
+ &(request->deque));
+ } else {
+ ssx_deque_push_back(&G_async_callback_queue,
+ &(request->deque));
+ }
+
+ ssx_critical_section_exit(&ctx);
+ ssx_irq_status_set(PGP_IRQ_ASYNC_IPI, 1);
+ }
+}
+
+
+// The generic handler for asynchonous device completion.
+//
+// This handler processes completions of generic device requests, as well as
+// the initial running of jobs when the queue is idle. Error completions are
+// initially handled by async_error_handler() which then calls async_handler()
+// to finish the failed job and start the next job if possible. The initial
+// device handler must manage interrupts and provide a method to run the
+// 'current' job in the queue. The engine-specific handler may also iterate
+// the current job until it is complete - this handler should only be called
+// when the current job is complete.
+//
+// Some engines may have jobs that can complete immediately. This handler
+// iterates over jobs in the queue as long as the run method of the current
+// job returns the code -ASYNC_REQUEST_COMPLETE.
+//
+// NB : Normally this call is made from an interrupt handler, however it may
+// be called from job scheduling code if the engine is idle. Regardless, the
+// caller must insure that any call for a queue is protected against
+// interrupts for that queue.
+
+void
+async_handler(AsyncQueue *queue)
+{
+ AsyncRequest *finished, *current;
+ int rc;
+
+ // This loop is repeated as long as any job started in a loop completes
+ // immediately.
+
+ do {
+
+ // This API may be called on an idle queue, which indicates that we
+ // should simply start the job on the head of the queue. Otherwise
+ // save a pointer to the job that just finished and update its
+ // end_time.
+
+ if (queue->state == ASYNC_QUEUE_STATE_IDLE) {
+
+ finished = 0;
+
+ } else {
+
+ finished = (AsyncRequest *)(queue->current);
+
+ if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) {
+ SSX_PANIC(ASYNC_PHANTOM_INTERRUPT);
+ }
+
+ finished->end_time = ssx_timebase_get();
+
+ }
+
+
+ // If the queue is in an error state we will not schedule any further
+ // jobs on this queue. Otherwise we start the next job running on the
+ // engine.
+
+ if (queue->state == ASYNC_QUEUE_STATE_ERROR) {
+
+ queue->current = 0;
+ rc = 0;
+
+ } else {
+
+ current = (AsyncRequest *)ssx_deque_pop_front(&(queue->deque));
+ queue->current = current;
+
+ if (current) {
+ queue->state = ASYNC_QUEUE_STATE_RUNNING;
+ rc = async_request_run(current);
+ } else {
+ queue->state = ASYNC_QUEUE_STATE_IDLE;
+ rc = 0;
+ }
+ }
+
+
+ // If no job just finished, continue with the loop. If the job we
+ // just enqueued finished immediately it will be 'finished' on the
+ // next loop (it would have given an rc ==
+ // -ASYNC_REQUEST_COMPLETE). Otherwise complete the request.
+
+ if (finished != 0) {
+
+ async_request_complete(finished);
+ }
+
+ } while (rc == -ASYNC_REQUEST_COMPLETE);
+}
+
+
+/// Schedule (queue for execution) a generic asynchronous request.
+///
+/// \param request An initialized and idle AsyncRequest
+///
+///
+/// The request is queued for execution with all of the parameters provided
+/// when the request was created. It is considered an error to (re)schedule a
+/// request that is currently scheduled, running, or has the callback queued or
+/// in execution. Requests either need to be idle, or must be explicitly
+/// cancelled or killed before thay can be (re)scheduled. Because engine queue
+/// interrupt handlers may run as critical interrupts, this routine operates in
+/// a short \c SSX_CRITICAL critical section.
+///
+/// If the request is made to an otherwise empty queue then the async_handler()
+/// must also be called immediately to begin the job. This will extend the
+/// critical section slightly. This routine will not start a request on a
+/// queue that has halted due to an error. The request will simply be enqueued
+/// in that case.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_SCHEDULE The \a request is NULL (0).
+///
+/// \retval -ASYNC_REQUEST_NOT_IDLE The \a request is (still) active in some
+/// way at entry.
+///
+/// \retval -ASYNC_REQUEST_NOT_COMPLETE This code is returned for requests that
+/// do not complete successfully, but only if ASYNC_REQUEST_BLOCKING is
+/// specified. The caller will need to examine the request state if necessary
+/// to determine whether the request failed, was cancelled or timed out.
+///
+/// \todo Consider making the critical section priority depend on the device
+/// queue priority here, by adding a priority field to the queue. Without this
+/// we always have to run the async_handler() in an SSX_CRITICAL critical
+/// section.
+
+int
+async_request_schedule(AsyncRequest *request)
+{
+ SsxMachineContext ctx = SSX_THREAD_MACHINE_CONTEXT_DEFAULT; // For GCC
+ AsyncQueue *queue;
+ int rc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(request == 0, ASYNC_INVALID_OBJECT_SCHEDULE);
+ }
+
+ rc = 0;
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ do {
+
+ // Check to insure the request is idle (which check must be done in
+ // the critical section), then start any required timeout.
+
+ if (SSX_ERROR_CHECK_API) {
+ if (!async_request_is_idle(request)) {
+ rc = -ASYNC_REQUEST_NOT_IDLE;
+ break;
+ }
+ }
+
+ if (request->timeout != SSX_WAIT_FOREVER) {
+ rc = ssx_timer_schedule(&(request->timer), request->timeout, 0);
+ if (rc) break;
+ }
+
+
+ // Enqueue the request and initialize the request state.
+
+ queue = request->queue;
+
+ if (request->options & ASYNC_REQUEST_PRIORITY) {
+ ssx_deque_push_front(&(queue->deque), &(request->deque));
+ } else {
+ ssx_deque_push_back(&(queue->deque), &(request->deque));
+ }
+
+ request->state = ASYNC_REQUEST_STATE_QUEUED;
+ request->completion_state = ASYNC_REQUEST_STATE_COMPLETE;
+ request->callback_rc = 0;
+
+
+ // If the queue is idle, call the async_handler() to start the job.
+ // Then block the calling thread if required.
+
+ if (queue->state == ASYNC_QUEUE_STATE_IDLE) {
+ async_handler(queue);
+ }
+
+ if (request->options & ASYNC_REQUEST_BLOCKING) {
+ rc = ssx_semaphore_pend(&(request->sem), SSX_WAIT_FOREVER);
+ if (rc) break;
+
+ if (!async_request_completed(request)) {
+ rc = -ASYNC_REQUEST_NOT_COMPLETE;
+ break;
+ }
+ }
+
+ } while (0);
+
+ ssx_critical_section_exit(&ctx);
+
+ return rc;
+}
+
+
+// The generic error handler
+//
+// This is a generic handler called in response to an error interrupt or
+// timeout. This handler calls a request-specific error method to stop the
+// hardware device, collect FFDC and make the hardware device runnable again
+// if possible. Then the current request is marked as having failed, and the
+// generic async_handler() is called which will start the next job (if any)
+// and take care of the callbacks for the failed request. If the error
+// method returns a non-0 return code then the error is non-recoverable and
+// the queue is marked with the error state.
+
+void
+async_error_handler(AsyncQueue* queue, uint8_t completion_state)
+{
+ AsyncRequest *finished;
+
+ finished = (AsyncRequest *)(queue->current);
+
+ if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) {
+ SSX_PANIC(ASYNC_PHANTOM_ERROR);
+ }
+
+ if (finished->error_method) {
+ if (finished->error_method(finished)) {
+ queue->state = ASYNC_QUEUE_STATE_ERROR;
+ }
+ }
+ finished->abort_state = finished->state;
+ finished->completion_state = completion_state;
+ async_handler(queue);
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// AsyncRequest
+////////////////////////////////////////////////////////////////////////////
+
+// Dequeue a queued AsyncRequest
+//
+// This is an internal API, always called from an SSX_CRITICAL critical
+// section. The request is known to be queued in one of the async queues. It
+// is removed from the queue and its state is updated.
+
+static void
+async_request_dequeue(AsyncRequest* request, uint8_t completion_state)
+{
+ ssx_deque_delete((SsxDeque*)request);
+ request->abort_state = request->state;
+ request->completion_state = completion_state;
+ async_request_complete(request);
+}
+
+
+// Time out an AsyncRequest
+//
+// This is an internal API, the timer callback used to time out long-running
+// AsyncRequest.
+//
+// This timer callback must run in an SSX_CRITICAL critical section to
+// guarantee atomic access to the AsyncRequest object.
+
+static void
+async_timeout(void* arg)
+{
+ AsyncRequest *request = (AsyncRequest*)arg;
+ SsxMachineContext ctx;
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ // The behavior at timeout depends on the mode. We'll handle the cases
+ // from easiest to hardest.
+
+ if (request->state & ASYNC_REQUEST_CALLBACK_GROUP) {
+
+ // If the request has already queued or is running the callback (which
+ // could happen due to interrupt interleaving) then the request is
+ // already finished, and it will eventually make a (redundant) call to
+ // ssx_timer_cancel() to cancel the timer. So there's nothing to do.
+
+
+ } else if (request->state & ASYNC_REQUEST_IDLE_GROUP) {
+
+ // If the request is idle we panic - This can't happen as it would
+ // indicate that the timer was not cancelled when the request
+ // finished.
+
+ SSX_PANIC(ASYNC_TIMEOUT_BUG);
+
+
+ } else if (request->state & ASYNC_REQUEST_QUEUED_GROUP) {
+
+ // If the request is still in the queue then we can simply cancel it,
+ // which includes running the callback.
+
+ async_request_dequeue(request, ASYNC_REQUEST_STATE_TIMED_OUT);
+
+
+ } else if (request->state & ASYNC_REQUEST_RUNNING_GROUP) {
+
+ // If the request is running on the hardware, then we need to call
+ // the async_error_handler() to remove the job and restart the
+ // hardware, which includes running the callback.
+
+ async_error_handler(request->queue, ASYNC_REQUEST_STATE_TIMED_OUT);
+
+
+ } else {
+
+ SSX_PANIC(ASYNC_INVALID_STATE);
+
+ }
+
+ ssx_critical_section_exit(&ctx);
+}
+
+
+// Create (initialize) a generic AsyncRequest
+//
+// This is an internal API used to initialize generic requests. However this
+// API does some error checking, and any errors will be returned by the
+// higher-level call.
+//
+// \retval -ASYNC_INVALID_OBJECT_REQUEST The \a request or \a queue was
+/// null (0).
+//
+// \retval -ASYNC_INVALID_OPTIONS The \a options argument contains invalid
+// options, or more than one callback protocol was selected.
+//
+// \retval -ASYNC_INVALID_ARGUMENT The \a run_method was null.
+//
+// \retval -ASYNC_CALLBACK_PROTOCOL_UNSPECIFIED The request includes a
+// non-NULL callback, but no protocol for running the callback was specified.
+
+int
+async_request_create(AsyncRequest *request,
+ AsyncQueue *queue,
+ AsyncRunMethod run_method,
+ AsyncErrorMethod error_method,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((request == 0) || (queue == 0),
+ ASYNC_INVALID_OBJECT_REQUEST);
+ SSX_ERROR_IF((options & ~ASYNC_GENERIC_OPTIONS) ||
+ (__builtin_popcount(options & ASYNC_CALLBACK_OPTIONS) > 1),
+ ASYNC_INVALID_OPTIONS);
+ SSX_ERROR_IF(run_method == 0, ASYNC_INVALID_ARGUMENT);
+ SSX_ERROR_IF((callback != 0) &&
+ ((options & ASYNC_CALLBACK_OPTIONS) == 0),
+ ASYNC_CALLBACK_PROTOCOL_UNSPECIFIED);
+ }
+
+ ssx_deque_element_create(&(request->deque));
+ request->queue = queue;
+ request->run_method = run_method;
+ request->error_method = error_method;
+ request->timeout = timeout;
+ request->state = ASYNC_REQUEST_STATE_INITIALIZED;
+ request->callback = callback;
+ request->arg = arg;
+ request->options = options;
+
+ if (request->timeout != SSX_WAIT_FOREVER) {
+ ssx_timer_create(&(request->timer), async_timeout, (void*)request);
+ }
+
+ if (options & ASYNC_REQUEST_BLOCKING) {
+ ssx_semaphore_create(&(request->sem), 0, 1);
+ }
+
+
+ return 0;
+}
+
+
+/// Get timestamps from an AsyncRequest object
+///
+/// \param request A pointer to an AsyncRequest
+///
+/// \param start_time A pointer to a location to get the \a start_time of the
+/// request, or NULL (0) if this data is not required.
+///
+/// \param end_time A pointer to a location to get the \a end_time of the
+/// request, or NULL (0) is this data is not required.
+///
+/// \retval 0 The request contains valid timestamps and they have been
+/// returned.
+///
+/// \retval -ASYNC_INVALID_TIMESTAMPS The caller's timestamps have been
+/// updated, but the timestamps are fully or partially invalid. This could be
+/// due to several reasons:
+///
+/// - The request has never been scheduled
+/// - The request has been scheduled but has not completed on the device
+/// - For space/time reasons, timestamps are not supported
+
+int
+async_request_timestamps_get(AsyncRequest* request,
+ SsxTimebase* start_time,
+ SsxTimebase* end_time)
+{
+ int rc;
+ SsxMachineContext ctx;
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ if (start_time) {
+ *start_time = request->start_time;
+ }
+ if (end_time) {
+ *end_time = request->end_time;
+ }
+
+ if ((request->state & ASYNC_REQUEST_IDLE_GROUP) &&
+ (request->state != ASYNC_REQUEST_STATE_INITIALIZED)) {
+ rc = 0;
+ } else {
+ rc = -ASYNC_INVALID_TIMESTAMPS;
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return rc;
+}
+
+
+/// Compute the latency of an AsyncRequest
+///
+/// \param request A pointer to an AsyncRequest
+///
+/// \param latency A pointer to a location to receive the latency (end time -
+/// start time) computed from the timestamps of \a request.
+///
+/// \retval 0 The request contains valid timestamps and they have been
+/// returned.
+///
+/// \retval -ASYNC_INVALID_TIMESTAMPS The latancy has been computed but may be
+/// invalid. This could be due to several reasons:
+///
+/// - The request has never been scheduled
+/// - The request has been scheduled but has not completed on the device
+/// - For space/time reasons, timestamps are not supported
+
+int
+async_request_latency(AsyncRequest* request, SsxTimebase* latency)
+{
+ int rc;
+ SsxTimebase start, end;
+
+ rc = async_request_timestamps_get(request, &start, &end);
+ *latency = end - start;
+ return rc;
+}
+
+
+// Dump an AsyncRequest
+
+void
+async_request_printk(AsyncRequest *request)
+{
+ printk("----------------------------------------\n");
+ printk("-- AsyncRequest @ %p\n", request);
+ printk("-- deque = %p\n", &(request->deque));
+ printk("-- start_time = 0x%016llx\n", request->start_time);
+ printk("-- end_time = 0x%016llx\n", request->end_time);
+ printk("-- sem = %p\n", &(request->sem));
+ printk("-- queue = %p\n", request->queue);
+ printk("-- run_method = %p\n", request->run_method);
+ printk("-- error_method = %p\n", request->error_method);
+ printk("-- callback = %p\n", request->callback);
+ printk("-- arg = %p\n", request->arg);
+ printk("-- state = 0x%02x\n", request->state);
+ printk("-- completion_state = 0x%02x\n", request->completion_state);
+ printk("-- options = 0x%04x\n", request->options);
+ printk("----------------------------------------\n");
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Callback Queue
+////////////////////////////////////////////////////////////////////////////
+
+SSX_IRQ_FAST2FULL(async_callback_handler, async_callback_handler_full);
+
+// The handler for the asynchronous callback queue
+//
+// This is a full-mode noncritical interrupt handler. It is activated to run
+// 1) all deferred callbacks, and 2) noncritical callbacks invoked from
+// critical interrupt handlers, and 3) Thread-unblock and/or timeout-cancel
+// requests that needed to be deferred to a noncritical context. The callback
+// is enqueued in the SsxDeque passed as the private argument, and an IPI is
+// used to activate this handler.
+//
+// This handler runs each callback in order. Since the callback queue may be
+// managed by critical interrupt handlers we need to disable critical
+// interrupts when popping the next element from the queue.
+//
+// Deferred callbacks are run with noncritical interrupts \e enabled, similar
+// to how timer callbacks are run.
+//
+// Noncritical callbacks that were deferred here (by being invoked from a
+// critical handler) run with interrupts \e disabled, to be consistent with
+// the expected environment. Interrupts are then renabled briefly for
+// interrupt latency mitigation.
+//
+// Note that NULL callbacks may be enqueued here but only in the state
+// ASYNC_REQUEST_STATE_POSTPROCESSING.
+
+// The handler runs with its own IRQ disabled to avoid infinite interrupt
+// loops caused by enabling interrupt preemption. The IRQ status can only be
+// cleared inside an SSX_CRITICAL critical section. For efficiency we only do
+// this when we know that no more callbacks are queued.
+
+// Final request completion has been broken out into a generic routine,
+// async_request_finalize(). This routine is also called by the PTS
+// completion queue handler, which handles its requests ion a slightly
+// different way from the other async handlers.
+
+void
+async_request_finalize(AsyncRequest* request)
+{
+ if (request->state == ASYNC_REQUEST_STATE_CALLBACK_QUEUED) {
+
+ request->state = ASYNC_REQUEST_STATE_CALLBACK_RUNNING;
+
+ if (request->options & ASYNC_CALLBACK_DEFERRED) {
+
+ ssx_interrupt_preemption_enable();
+ request->callback_rc = request->callback(request->arg);
+
+ } else {
+
+ request->callback_rc = request->callback(request->arg);
+ ssx_interrupt_preemption_enable();
+ }
+ ssx_interrupt_preemption_disable();
+ }
+
+ request->state = request->completion_state;
+
+ if (request->timeout != SSX_WAIT_FOREVER) {
+ ssx_timer_cancel(&(request->timer));
+ }
+
+ if (request->options & ASYNC_REQUEST_BLOCKING) {
+ ssx_semaphore_post(&(request->sem));
+ }
+}
+
+
+void
+async_callback_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ SsxMachineContext ctx;
+ SsxDeque *queue = (SsxDeque *)arg;
+ AsyncRequest *request;
+
+ ssx_irq_disable(irq);
+
+ do {
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ request = (AsyncRequest *)ssx_deque_pop_front(queue);
+ if (!request) {
+ ssx_irq_status_clear(irq);
+ break;
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ async_request_finalize(request);
+
+ } while (1);
+
+ ssx_critical_section_exit(&ctx);
+ ssx_irq_enable(irq);
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Initialization
+////////////////////////////////////////////////////////////////////////////
+
+// These initialization routines are for boot-time initialization, or
+// test-mode reinitialization of interface parameters when the interface is
+// known to be idle. They are not robust enough for mid-application
+// reset/reprogramming of the asynchronous interfaces in the event of errors.
+
+// For the interrupt setup, whether or not the interrupt is enabled at the
+// exit of setup depends on the particular driver being initialized.
+
+void
+async_edge_handler_setup(SsxIrqHandler handler,
+ void *arg,
+ SsxIrqId irq,
+ int priority)
+{
+ ssx_irq_disable(irq);
+ ssx_irq_setup(irq,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH,
+ SSX_IRQ_TRIGGER_EDGE_SENSITIVE);
+ ssx_irq_handler_set(irq, handler, arg, priority);
+ ssx_irq_status_clear(irq);
+}
+
+
+void
+async_level_handler_setup(SsxIrqHandler handler,
+ void *arg,
+ SsxIrqId irq,
+ int priority,
+ int polarity)
+{
+ ssx_irq_disable(irq);
+ ssx_irq_setup(irq,
+ polarity,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+ ssx_irq_handler_set(irq, handler, arg, priority);
+}
+
+
+void
+async_callbacks_initialize(SsxDeque *queue, SsxIrqId irq)
+{
+ ssx_deque_sentinel_create(queue);
+ async_edge_handler_setup(async_callback_handler,
+ (void *)queue,
+ irq, SSX_NONCRITICAL);
+ ssx_irq_enable(irq);
+}
+
+
+/// Create all of the PgP asynchronous request structures and install and
+/// activate the interrupt handlers.
+
+void
+async_initialize()
+{
+ // This is the callback queue used e.g. when critical interrupts need to
+ // run non-critical callbacks.
+
+ async_callbacks_initialize(&G_async_callback_queue, PGP_IRQ_ASYNC_IPI);
+
+ // PORE
+
+ async_pore_initialize(&G_pore_gpe0_queue, ASYNC_ENGINE_PORE_GPE0);
+ async_pore_initialize(&G_pore_gpe1_queue, ASYNC_ENGINE_PORE_GPE1);
+ async_pore_initialize(&G_pore_slw_queue, ASYNC_ENGINE_PORE_SLW);
+
+#if CONFIGURE_PTS
+ // PTS
+
+ async_pts_initialize(&G_pts_gpe0_queue, ASYNC_ENGINE_PORE_GPE0);
+ async_pts_initialize(&G_pts_gpe1_queue, ASYNC_ENGINE_PORE_GPE1);
+#endif
+
+ // BCE
+
+ async_bce_initialize(&G_pba_bcde_queue,
+ ASYNC_ENGINE_BCDE,
+ PGP_IRQ_PBA_BCDE_ATTN);
+
+ async_bce_initialize(&G_pba_bcue_queue,
+ ASYNC_ENGINE_BCUE,
+ PGP_IRQ_PBA_BCUE_ATTN);
+
+ // OCB
+
+ async_ocb_initialize(&(G_ocb_read_queue[0]),
+ ASYNC_ENGINE_OCB_PUSH0,
+ G_ocb_read0_buffer,
+ OCB_READ0_LENGTH,
+ OCB_READ0_PROTOCOL);
+
+ async_ocb_initialize(&(G_ocb_read_queue[1]),
+ ASYNC_ENGINE_OCB_PUSH1,
+ G_ocb_read1_buffer,
+ OCB_READ1_LENGTH,
+ OCB_READ1_PROTOCOL);
+
+ async_ocb_initialize(&(G_ocb_read_queue[2]),
+ ASYNC_ENGINE_OCB_PUSH2,
+ G_ocb_read2_buffer,
+ OCB_READ2_LENGTH,
+ OCB_READ2_PROTOCOL);
+
+ async_ocb_initialize(&(G_ocb_write_queue[0]),
+ ASYNC_ENGINE_OCB_PULL0,
+ G_ocb_write0_buffer,
+ OCB_WRITE0_LENGTH,
+ OCB_WRITE0_PROTOCOL);
+
+ async_ocb_initialize(&(G_ocb_write_queue[1]),
+ ASYNC_ENGINE_OCB_PULL1,
+ G_ocb_write1_buffer,
+ OCB_WRITE1_LENGTH,
+ OCB_WRITE1_PROTOCOL);
+
+ async_ocb_initialize(&(G_ocb_write_queue[2]),
+ ASYNC_ENGINE_OCB_PULL2,
+ G_ocb_write2_buffer,
+ OCB_WRITE2_LENGTH,
+ OCB_WRITE2_PROTOCOL);
+
+ // PBAX
+
+ async_pbax_initialize(&G_pbax_read_queue[0],
+ ASYNC_ENGINE_PBAX_PUSH0,
+ PGP_IRQ_PBA_OCC_PUSH0,
+ G_pbax_read0_buffer,
+ PBAX_READ0_LENGTH,
+ PBAX_READ0_PROTOCOL);
+
+ async_pbax_initialize(&G_pbax_read_queue[1],
+ ASYNC_ENGINE_PBAX_PUSH1,
+ PGP_IRQ_PBA_OCC_PUSH1,
+ G_pbax_read1_buffer,
+ PBAX_READ1_LENGTH,
+ PBAX_READ1_PROTOCOL);
+}
diff --git a/src/ssx/pgp/pgp_async.h b/src/ssx/pgp/pgp_async.h
new file mode 100755
index 0000000..ecd3ae2
--- /dev/null
+++ b/src/ssx/pgp/pgp_async.h
@@ -0,0 +1,1654 @@
+#ifndef __PGP_ASYNC_H__
+#define __PGP_ASYNC_H__
+
+// $Id: pgp_async.h,v 1.2 2014/02/03 01:30:34 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_async.h
+/// \brief Support for asynchronous request/callback mechanisms
+///
+/// The data structures defined here provide a 'C' implementation of multiple
+/// single-inheritance class hierarchies. The 'subclasses' always include the
+/// 'superclass' as the initial element of the structure, allowing subclass
+/// pointers to be safely cast to the superclass, and vice-versa (assuming
+/// that the subclass is known). One benefit of this approach is that it
+/// allows code sharing between requests targeting PORE-GPE, PORE-SW,
+/// PBA-BCDE, PBA-BCUE and the deferred callback queue.
+///
+/// The 'class hierarchy' :
+///
+/// SsxDeque
+/// AsyncRequest
+/// PoreRequest
+/// PoreFixed
+/// PoreFlex
+/// BceRequest
+/// OcbRequest
+/// Pbaxrequest
+///
+/// AsyncQueue
+/// PoreQueue
+/// BceQueue
+/// OcbQueue
+/// PbaxQueue
+///
+/// \bug We may need to redo how we start jobs since writing the EXE-TRIGGER
+/// does not guarantee a restart from a good state, although if we get our CCB
+/// request through it will.
+
+
+// PgP Execution engines for the purposes of the generic request mechanism.
+
+#define ASYNC_ENGINE_ANONYMOUS 0x00
+
+#define ASYNC_ENGINE_PORE 0x10
+#define ASYNC_ENGINE_PORE_GPE0 0x10
+#define ASYNC_ENGINE_PORE_GPE1 0x11
+#define ASYNC_ENGINE_PORE_SLW 0x12
+
+#define ASYNC_ENGINE_BCE 0x20
+#define ASYNC_ENGINE_BCDE 0x20
+#define ASYNC_ENGINE_BCUE 0x21
+
+// Indirect channel 3 no longer supports push/pull queues and they have been
+// removed.
+#define ASYNC_ENGINE_OCB 0x40
+#define ASYNC_ENGINE_OCB_PUSH0 0x41
+#define ASYNC_ENGINE_OCB_PUSH1 0x42
+#define ASYNC_ENGINE_OCB_PUSH2 0x43
+#define ASYNC_ENGINE_OCB_PULL0 0x45
+#define ASYNC_ENGINE_OCB_PULL1 0x46
+#define ASYNC_ENGINE_OCB_PULL2 0x47
+
+#define ASYNC_ENGINE_PBAX 0x80
+#define ASYNC_ENGINE_PBAX_PUSH0 0x81
+#define ASYNC_ENGINE_PBAX_PUSH1 0x82
+
+
+#ifndef __ASSEMBLER__
+
+typedef uint8_t AsyncEngine;
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// FFDC Structures
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// FFDC from the PLB (OCI) arbiter
+///
+/// The PLB arbiter records errors from all OCI masters, including the address
+/// of the transaction that caused the error. The PLB arbiter is set up to
+/// 'lock' the first error data until the lock is reset. This structure is
+/// included in all of the unit FFDC structures for peripherals that can
+/// master on the OCI (SLW/GPE/OCB/PBA). Note that OCI errors from the 405
+/// core will cause an immediate machine check exception.
+
+typedef struct {
+
+ /// PLB arbiter Error Address Register Low
+ ///
+ /// This is the address of the last PLB timeout or other error recorded in
+ /// the PEARL. This is an error for the unit in question only if the
+ /// \a mine data member is non-zero.
+ plb_pearl_t pearl;
+
+ /// PLB arbiter Error Status Register
+ ///
+ /// The PESR at the time of the error.
+ plb_pesr_t pesr;
+
+ /// Is the unit in question responsible for the error address recorded in
+ /// the PEARL?
+ int mine;
+
+} OciFfdc;
+
+void
+oci_ffdc(OciFfdc* ffdc, int master_id);
+
+#endif // __ASSEMBLER__
+
+
+////////////////////////////////////////////////////////////////////////////
+// AsyncRequest
+////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup async_request_states ASYNC Request States
+///
+/// Request states for async requests are group into 5 logical states for
+/// error handling and timeout handling purposes.
+///
+/// - Queued Group : Queued requests are still waiting to execute in the device queue,
+/// so these requests can be cancelled simply by removing them from the queue.
+///
+/// - Running Group : Running requests are running on the hardware, so killing
+/// these jobs may require a forced stop and restart of the device.
+///
+/// - Callback Group : By specification callbacks are always run if provided,
+/// even if a job dies or is timed out. This includes post-processing only
+/// work like unblocking blocked threads. These processes are not interrupted.
+///
+/// - Idle Group : These jobs are no longer in process, and their states are
+/// final.
+///
+/// Only idle requests can be (re)scheduled. Only jobs in the Queued or
+/// Running states can time out. Once the job has moved to the Callback group
+/// it is considered complete as far as timeout processing is concerned.
+///
+/// @{
+
+/// The request is waiting in the queue
+#define ASYNC_REQUEST_STATE_QUEUED 0x10
+
+
+/// The request is running on the hardware
+#define ASYNC_REQUEST_STATE_RUNNING 0x20
+
+
+/// The request is complete but a deferred callback has yet to run
+#define ASYNC_REQUEST_STATE_CALLBACK_QUEUED 0x40
+
+/// The request callback is running
+#define ASYNC_REQUEST_STATE_CALLBACK_RUNNING 0x41
+
+/// Thread unblocking and/or timeout cancellation has been deferred to a
+/// noncritical interrupt context.
+#define ASYNC_REQUEST_STATE_POSTPROCESSING 0x42
+
+
+/// The request has been initialized but never run
+#define ASYNC_REQUEST_STATE_INITIALIZED 0x80
+
+/// The request failed due to an error signalled by hardware
+#define ASYNC_REQUEST_STATE_FAILED 0x81
+
+/// The request completed normally
+#define ASYNC_REQUEST_STATE_COMPLETE 0x82
+
+/// The application cancelled the request
+#define ASYNC_REQUEST_STATE_CANCELLED 0x83
+
+/// The request timed out
+#define ASYNC_REQUEST_STATE_TIMED_OUT 0x84
+
+
+#define ASYNC_REQUEST_QUEUED_GROUP 0x10
+#define ASYNC_REQUEST_RUNNING_GROUP 0x20
+#define ASYNC_REQUEST_CALLBACK_GROUP 0x40
+#define ASYNC_REQUEST_IDLE_GROUP 0x80
+
+/// @}
+
+
+/// \defgroup async_request_options ASYNC Request Options
+///
+/// These are the option flags for the \a options field of the AsyncRequest.
+/// These are generic options applicable to all requests.
+///
+/// @{
+
+#define ASYNC_CALLBACK_IMMEDIATE 0x0001
+#define ASYNC_CALLBACK_DEFERRED 0x0002
+#define ASYNC_CALLBACK_NONCRITICAL 0x0004
+#define ASYNC_CALLBACK_OPTIONS 0x0007
+
+#define ASYNC_REQUEST_PRIORITY 0x0008
+#define ASYNC_CALLBACK_PRIORITY 0x0010
+
+#define ASYNC_REQUEST_BLOCKING 0x0020
+
+#define ASYNC_GENERIC_OPTIONS 0x003f
+
+/// @}
+
+#ifndef __ASSEMBLER__
+
+struct AsyncRequest;
+struct AsyncQueue;
+
+typedef int (*AsyncRunMethod)(struct AsyncRequest *request);
+
+typedef int (*AsyncErrorMethod)(struct AsyncRequest *request);
+
+typedef int (*AsyncRequestCallback)(void *);
+
+/// A generic request for the asynchronous request drivers
+///
+/// Note: Normally the application will not explicitly manipulate this
+/// structure, but will instead manipulate derived structures.
+///
+/// A request is queued for a particular engine, with a callback to be
+/// executed once the request has been processed by the engine. The \a
+/// callback may be NULL, but at a minimum the requestor can observe the \a
+/// state of the request to determine the state of request processing. If a
+/// deferred callback is requested, then once processing is done the generic
+/// handler will requeue the request in a callback queue.
+///
+/// The \a run_method is a "pure virtual" function of this class. The \a
+/// run_method encapsulates the procedure for starting a job on the
+/// engine. The \a run_method may make assumptions about and use data
+/// contained in the AsyncQueue class used to queue the requests.
+///
+/// The \a error_method is also "pure virtual" function of this class. The \a
+/// error_method encapsulates the procedure for collecting FFDC and preparing
+/// the engine to run the next job. The \a error_method may make assumptions
+/// about and use data contained in the AsyncQueue class used to queue the
+/// requests. If the \a error_method returns a non-0 code then the error is
+/// considered fatal and the queue stops.
+
+typedef struct AsyncRequest {
+
+ /// Generic queue management - the "base class"
+ SsxDeque deque;
+
+ /// The time the job was started on the hardware.
+ ///
+ /// For jobs requiring multiple passes on the hardware, e.g., BCE jobs
+ /// that move more data than the PBA supports with a single pass, this
+ /// time is the time the first hardware pass started. In this case the
+ /// interval time computed as the difference with \a start_time includes
+ /// interrupt handling overhead required to process the completion/restart
+ /// of intermediate passes.
+ ///
+ /// This timestamp is inserted into the request by the generic routine
+ /// async_request_run().
+ SsxTimebase start_time;
+
+ /// The time the job finished on the hardware.
+ ///
+ /// This timestamp is inserted into the request by the generic routine
+ /// async_handler().
+ SsxTimebase end_time;
+
+ /// A semaphore for thread-mode requests to block on if desired.
+ SsxSemaphore sem;
+
+ /// A timer used for timeout management
+ SsxTimer timer;
+
+ /// The engine queue the request is/was scheduled on
+ struct AsyncQueue *queue;
+
+ /// The "virtual" run method for the class
+ AsyncRunMethod run_method;
+
+ /// The "virtual" error handler method for the class
+ AsyncErrorMethod error_method;
+
+ /// The routine Called (or deferred) with the \a arg parameter once
+ /// the engine has completed the request.
+ ///
+ /// The callback may be NULL (0), in which case the \a arg parameter
+ /// is ignored, and the only status available to the requestor is the
+ /// request \a state.
+ AsyncRequestCallback callback;
+
+ /// The argument of the callback
+ void *arg;
+
+ /// The timeout value
+ ///
+ /// AsyncRequest objects with \a timeout other than SSX_WAIT_FOREVER are
+ /// governed by a private watchdog timer that will cancel a queued job or
+ /// kill a running job if the hardware operation does not complete before
+ /// it times out.
+ SsxInterval timeout;
+
+ /// The return value of the callback (if any) is stored here
+ ///
+ /// The success or failure of the callback is recorded here; it is not
+ /// recorded in the \a state variable. If there is no callback this field
+ /// will always read as 0 at job completion.
+ int callback_rc;
+
+ /// Options controlling request processing
+ uint8_t options;
+
+ /// The current state of the request
+ ///
+ /// This field is declared volatile because applications may poll this
+ /// field which is set asynchronously by the async interrupt handlers, and
+ /// optimizing compilers transform polling a variable into an infinite
+ /// loop if the variable is not set on the initial test!
+ volatile uint8_t state;
+
+ /// The state of the request when the request was aborted
+ ///
+ /// This field is valid when the state of the request is read as
+ /// ASYNC_REQUEST_STATE_FAILED, ASYNC_REQUEST_STATE_CANCELLED, or
+ /// ASYNC_REQUEST_STATE_TIMED_OUT. This field records the state of the
+ /// job when it was forceably cancelled or killed either due to the
+ /// application's request or due to a hardware error or timeout.
+ uint8_t abort_state;
+
+ /// The completion state of the request.
+ ///
+ /// This is the state that will be reported when the request completes and
+ /// the callback has been run. Normally this is
+ /// ASYNC_REQUEST_STATE_COMPLETE. However the specification requires that
+ /// even jobs that terminate due to an errors, timeouts or being cancelled
+ /// or killed must run their callbacks. In this case this variable will be
+ /// set to ASYNC_REQUEST_STATE_FAILED, ASYNC_REQUEST_STATE_TIMED_OUT,
+ /// ASYNC_REQUEST_STATE_CANCELLED or ASYNC_REQUEST_STATE_KILLED
+ /// respectively.
+ uint8_t completion_state;
+
+} AsyncRequest;
+
+
+int
+async_request_create(AsyncRequest *request,
+ struct AsyncQueue *queue,
+ AsyncRunMethod run_method,
+ AsyncErrorMethod error_method,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options);
+
+void
+async_request_finalize(AsyncRequest* request);
+
+
+/// Check that an asynchronous request is idle
+///
+/// \param request An initialized request
+///
+/// A request is considered idle if it is not attached to any of the
+/// asynchronous request queues, \e or the request has terminated with an
+/// error. This includes requests that have never been scheduled, have
+/// completed or been cancelled or killed. Only idle requests can be
+/// rescheduled.
+///
+/// \retval 0 The request is not idle
+///
+/// \retval 1 The request is idle
+
+static inline int
+async_request_is_idle(AsyncRequest *request)
+{
+ return (request->state & ASYNC_REQUEST_IDLE_GROUP) != 0;
+}
+
+
+/// Check an asynchronous request for successful completion
+///
+/// \param request A request that had been previosuly scheduled
+///
+/// Note that a request is not considered complete until both the engine job
+/// has finshed without error and any callback has run to completion. Thus
+/// jobs that have error-ed out, been cancelled or killed will be idle (and
+/// rescheduleable), but not complete.
+///
+/// \retval 0 The request has not yet completed successfully
+///
+/// \retval 1 The request has completed successfully.
+
+static inline int
+async_request_completed(AsyncRequest *request)
+{
+ return (request->state == ASYNC_REQUEST_STATE_COMPLETE);
+}
+
+
+int
+async_request_timestamps_get(AsyncRequest* request,
+ SsxTimebase* start_time,
+ SsxTimebase* end_time);
+
+int
+async_request_latency(AsyncRequest* request, SsxTimebase* latency);
+
+
+void
+async_request_printk(AsyncRequest *request);
+
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// AsyncQueue
+////////////////////////////////////////////////////////////////////////////
+
+#define ASYNC_QUEUE_STATE_IDLE 0x00
+#define ASYNC_QUEUE_STATE_RUNNING 0x01
+#define ASYNC_QUEUE_STATE_ERROR 0x02
+
+#ifndef __ASSEMBLER__
+
+/// A generic asynchronous request queue
+///
+/// Note: This structure is normally not manipulated directly by application
+/// code, but only by the device drivers.
+///
+/// Request queues support 2 priorities - Normal and High. Normal priority
+/// requests are queued FIFO order, while high-priority requests are queued
+/// LIFO order. Requests queued with high priority always execute before any
+/// queued with normal priority, however there is no concept of preemption of
+/// a currently running request.
+///
+/// Because high-priority requests are queued in LIFO order, multiple
+/// high-priority jobs will run in the reverse order from which they were
+/// enqueued.
+
+typedef struct AsyncQueue {
+
+ /// The sentinel of the request queue
+ SsxDeque deque;
+
+ /// The currently running request, or NULL (0)
+ AsyncRequest* current;
+
+ /// The engine associated with the queue.
+ AsyncEngine engine;
+
+ /// The state of the queue
+ uint8_t state;
+
+} AsyncQueue;
+
+
+int
+async_queue_create(AsyncQueue* queue, AsyncEngine engine);
+
+void
+async_handler(AsyncQueue* queue);
+
+int
+async_request_schedule(AsyncRequest* request);
+
+void
+async_error_handler(AsyncQueue* queue, uint8_t completion_state);
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// Async Initialization
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+void
+async_edge_handler_setup(SsxIrqHandler handler,
+ void *arg,
+ SsxIrqId irq,
+ int priority);
+
+void
+async_level_handler_setup(SsxIrqHandler handler,
+ void *arg,
+ SsxIrqId irq,
+ int priority,
+ int polarity);
+
+void
+async_callbacks_initialize(SsxDeque *queue, SsxIrqId irq);
+
+
+#endif // __ASSEMBLER__
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreRequest
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+struct PoreQueue;
+
+/// PORE FFDC
+///
+/// The PORE engine has 208 bytes of programmer-visible state - too much to
+/// allocate in every PoreRequest on the off-chance that a request may fail.
+/// This PoreFfdc structure is designed to capture a reasonble amount of data
+/// in the case of failure of a PoreFlex request, which does not include any
+/// PORE error handlers. This structure is currently 48 bytes.
+///
+/// The most common recoverable errors are expected to be erroneous PIB
+/// responses from deconfigured (garded) cores. These will show up as Error
+/// event 0 and can be debugged from the debug registers. We also include the
+/// instruction buffer registers to help debug error 2 - instruction
+/// fetch/decode errors.
+///
+/// To get a full picture in the event of OCI execution phase errors (error
+/// 1), the PORE memory-space address registers are captured. We also capture
+/// FFDC from the PLB arbiter, which can be used to debug illegal address-type
+/// problems.
+
+typedef struct {
+
+ /// FFDC from the PLB (OCI) arbiter
+ OciFfdc oci_ffdc;
+
+ /// PORE Debug Registers
+ ///
+ /// - [0] Contains PIB address and PIB return code
+ /// - [1] Contains failing PC and error status bits
+ uint64_t debug[2];
+
+ /// PORE Memory-space address registers.
+ ///
+ /// We only save the low-order 32 bits of each - the high-order bits are
+ /// implied/ignored for OCI-attached engines. If OCC managed the SBE then
+ /// we would require the high-order bits in an FFDC dump.
+ uint32_t address[2];
+
+ /// PORE Instruction buffer 0-2
+ ///
+ /// - [0] Contains the opcode and register/short operands
+ /// - [1:2] Contain the 64-bit immediate
+ uint32_t ibuf[3];
+
+} PoreFfdc;
+
+
+/// A PORE branch immediate address instruction, used in PORE jump tables.
+typedef struct {
+ uint32_t word[3];
+} PoreBraia;
+
+
+void
+pore_braia_create(PoreBraia* instr, uint32_t address);
+
+
+/// A request to run a PORE program
+///
+/// A PORE request extends the generic AsyncRequest request by the addition of
+/// several fields required to be set up in the engine before the job is run,
+/// including the program parameter for the routine. The PoreRequest is an
+/// internal class that is re-typed to create the PoreFixed and PoreFlex
+/// request classes, which differ only slightly in their behavior.
+///
+/// As long as the request is known to be idle the application is free to
+/// change the \a parameter value between executions of the PORE program,
+/// e.g., to do ping-pong buffer management. None of the other fields should
+/// be directly modified by the application.
+
+typedef struct {
+
+ /// The generic request
+ AsyncRequest request;
+
+ /// Error information
+ PoreFfdc ffdc;
+
+ /// The PORE Jump Table
+ PoreBraia* table;
+
+ /// The initial value of the high-order 32 bits of the ERROR_MASK register
+ uint32_t error_mask;
+
+ /// The entry point address of the routine.
+ ///
+ /// For PoreFlex this entry point will be non-0 and will be inserted into
+ /// D0, as PoreFlex jobs are kicked off by BRAD. For PoreFixed this
+ /// parameter will be zero and ignored.
+ uint32_t entry_point;
+
+ /// The single parameter of the PORE program - EXE-Trigger[32:63]
+ uint32_t parameter;
+
+ /// The high-order 32 bits of EXE-Trigger used to kick off the program.
+ ///
+ /// For PoreFlex this field is always 0, as PoreFlex only uses table entry
+ /// 0 which contains a BRAD. For PoreFixed this encodes the address of
+ /// the table entry to kick off.
+ uint32_t exe_trigger;
+
+} PoreRequest;
+
+
+typedef PoreRequest PoreFlex;
+
+typedef PoreRequest PoreFixed;
+
+int
+pore_run_method(AsyncRequest* request);
+
+int
+pore_error_method(AsyncRequest* request);
+
+#endif /* __ASSEMBLER__ */
+
+/// The (fixed) number of PORE jump table error handler slots
+#define PORE_ERROR_SLOTS 5
+
+/// The maximum number of PORE jump table EXE_TRIGGER slots
+#define PORE_TRIGGER_SLOTS 16
+
+/// Compute the address of error handler BRAIA entry n of a PORE branch table
+#define PORE_ERROR_BRANCH(table, n) ((table) + ((n) * 12))
+
+/// Compute the address of entry point BRAIA entry n of a PORE branch table
+#define PORE_ENTRY_BRANCH(table, n) \
+ ((table) + (((PORE_ERROR_SLOTS) + (n)) * 12))
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreFlex
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+int
+pore_flex_create(PoreFlex* request,
+ struct PoreQueue* queue,
+ PoreEntryPoint entry_point,
+ uint32_t parameter,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options);
+
+
+/// See async_request_schedule() for documentation.
+static inline int
+pore_flex_schedule(PoreFlex* request)
+{
+ return async_request_schedule((AsyncRequest *)request);
+}
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreFixed
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+int
+pore_fixed_create(PoreFixed *request,
+ struct PoreQueue *queue,
+ PoreBraia* table,
+ uint32_t error_mask,
+ int start_vector,
+ uint32_t parameter,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options);
+
+/// See async_request_schedule() for documentation.
+static inline int
+pore_fixed_schedule(PoreFixed *request)
+{
+ return async_request_schedule((AsyncRequest *)request);
+}
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreQueue
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// A PORE engine queue
+///
+/// A PORE queue consists of a generic AsyncQueue to manage jobs on the
+/// engine, the OCI base address of the PORE control register space of the
+/// engine, and interrupt information.
+
+typedef struct PoreQueue {
+
+ /// The generic request queue - the "base class"
+ AsyncQueue queue;
+
+ /// The base address of the OCI control register space for this engine.
+ uint32_t oci_base;
+
+ /// The IRQ associated with normal completion on the engine
+ ///
+ /// \todo Due to header reference ordering we can't define this as SsxIrqId
+ uint8_t irq;
+
+ /// The IRQ associated with error completion on the engine
+ ///
+ /// \todo Due to header reference ordering we can't define this as SsxIrqId
+ uint8_t error_irq;
+
+ /// The OCI master number of this engine; See pore_error_method()
+ uint8_t oci_master;
+
+} PoreQueue;
+
+
+int
+pore_queue_create(PoreQueue *queue,
+ int engine);
+
+#endif /* ASSEMBLER */
+
+
+////////////////////////////////////////////////////////////////////////////
+// PBA FFDC Structures
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// Common FFDC collected for each PBA subunit in the event that a particular
+/// subunit is implicated in an error. This structure contains generic
+/// data that may be useful in diagnosing any PBA error. Instances of this
+/// structure are embedded in higher-level structures for the PBA bridge, BCE
+/// engines, and PBAX mechanism.
+
+typedef struct {
+
+ /// FFDC from the PLB (OCI) arbiter
+ OciFfdc oci_ffdc;
+
+ /// The PBA MODE register
+ pba_mode_t mode;
+
+ /// The PBA FIR
+ pba_fir_t fir;
+
+ /// PBA Error Report 0
+ pba_errpt0_t errpt0;
+
+ /// PBA Error Report 1
+ pba_errpt1_t errpt1;
+
+ /// PBA Error Report 2
+ pba_errpt2_t errpt2;
+
+ /// PBA Read Buffer Valid Status
+ pba_rbufvaln_t rbufval[PBA_READ_BUFFERS];
+
+ /// PBA Write Buffer Valid Status
+ pba_wbufvaln_t wbufval[PBA_WRITE_BUFFERS];
+
+ /// PBA BARs
+ pba_barn_t bar[PBA_BARS];
+
+ /// PBA BAR masks
+ pba_barmskn_t barmsk[PBA_BARS];
+
+ /// Error status - non-0 if this structure contains error data
+ int error;
+
+} PbaCommonFfdc;
+
+
+/// FFDC collected for generic PBA bridge errors
+///
+/// These types of errors will almost certainly be attributable to the
+/// PORE-SLW or PORE-GPE, since the OCC is normally not allowed to perform
+/// direct bridge operations after OCC initialization. This structure extends
+/// the common PBA FFDC with information on how the slaves were programmed.
+
+typedef struct {
+
+ /// Common FFDC
+ PbaCommonFfdc common;
+
+ /// PBA Slave reset register
+ pba_slvrst_t slvrst;
+
+ /// PBA Slave control registers
+ pba_slvctln_t slvctl[PBA_SLAVES];
+
+} PbaBridgeFfdc;
+
+
+/// FFDC collected for the PBA BCUE/BCDE
+///
+/// The BCDE/BCUE control and status registers have identical layouts.
+/// Similar to the way the drivers are coded, the BCDE register forms are used
+/// to declare the structures.
+
+typedef struct {
+
+ /// Common FFDC
+ PbaCommonFfdc common;
+
+ /// BCE control register
+ pba_bcde_ctl_t ctl;
+
+ /// BCE setup register
+ pba_bcde_set_t set;
+
+ /// BCE PowerBus setup register
+ pba_bcde_pbadr_t pbadr;
+
+ /// BCE status register
+ pba_bcde_stat_t stat;
+
+} BceFfdc;
+
+
+/// FFDC collected for PBAX send errors
+
+typedef struct {
+
+ /// Common FFDC
+ PbaCommonFfdc common;
+
+ /// PBAX configuration register
+ pba_xcfg_t xcfg;
+
+ /// PBAX send transaction register
+ pba_xsndtx_t xsndtx;
+
+ /// PBAX send status register
+ pba_xsndstat_t xsndstat;
+
+} PbaxSendFfdc;
+
+
+/// FFDC collected for PBAX receive errors
+
+typedef struct {
+
+ /// Common FFDC
+ PbaCommonFfdc common;
+
+ /// PBAX configuration register
+ pba_xcfg_t xcfg;
+
+ /// PBAX receive status register
+ pba_xrcvstat_t xrcvstat;
+
+ /// PBAX push base registers
+ pba_xshbrn_t xshbrn[PBAX_QUEUES];
+
+ /// PBAX push control/status registers
+ pba_xshcsn_t xshcsn[PBAX_QUEUES];
+
+} PbaxReceiveFfdc;
+
+
+/// A single global structure containing FFDC for all PBA functions
+
+typedef struct {
+
+ /// FFDC for the generic bridge
+ PbaBridgeFfdc bridge;
+
+ /// FFDC for the BCDE
+ BceFfdc bcde;
+
+ /// FFDC for the BCUE
+ BceFfdc bcue;
+
+ /// FFDC for PBAX send
+ PbaxSendFfdc pbax_send;
+
+ /// FFDC for PBAX receive
+ PbaxReceiveFfdc pbax_receive;
+
+} PbaUnitFfdc;
+
+#endif // __ASSEMBLER__
+
+////////////////////////////////////////////////////////////////////////////
+// BceRequest
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+struct BceQueue;
+
+/// A request to move data through the PBA BCUE or BCDE
+///
+/// From a programming and control perspective the Block Copy Download Engine
+/// (BCDE) and Upload Engine (BCUE) are identical - they simply move a given
+/// number of 128-byte cache lines from/to system memory to/from SRAM.
+///
+/// Although the PBA BCE hardware can only move a maximum of 4KB at a time
+/// through the channel, the software layer allows any amount of data to be
+/// moved as a single request.
+
+typedef struct {
+
+ /// The generic request
+ AsyncRequest request;
+
+ /// FFDC collected in the event of an error in the request
+ BceFfdc ffdc;
+
+ /// Initial bridge address for read (BCDE) or write (BCUE) data. This
+ /// field is not modified by the drivers.
+ uint32_t bridge_address;
+
+ /// Initial OCI address for read (BCUE) or write (BCDE) data. This
+ /// field is not modified by the drivers.
+ uint32_t oci_address;
+
+ /// Number of bytes to move. This field is not modified by the drivers.
+ ///
+ /// Note that the PBA moves data in sets of 128 bytes (the PowerBus
+ /// cache line size). This field will always be a multiple of 128.
+ size_t bytes;
+
+ /// The next bridge address for read (BCDE) or write (BCUE) data. This
+ /// field is modified by the drivers as each maximum 4K block is copied.
+ uint32_t next_bridge_address;
+
+ /// Initial OCI address for read (BCUE) or write (BCDE) data. This
+ /// field is modified by the drivers as each maximum 4K block is copied.
+ uint32_t next_oci_address;
+
+ /// The number of bytes remaining to be moved.
+ size_t remaining;
+
+ /// The extended address, as a 64-bit PowerBus address
+ ///
+ /// Bits 23:36 of the field define bits 23:36 of the final PowerBus
+ /// address, subject to the final mask selection. This field is cleared by
+ /// the default constructor, and must be explicitly set if an extended
+ /// address is needed.
+ pba_extended_address_t extended_address;
+
+} BceRequest;
+
+int
+bce_request_create(BceRequest *request,
+ struct BceQueue *queue,
+ uint32_t bridge_address,
+ uint32_t oci_address,
+ size_t bytes,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options);
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// BceQueue
+////////////////////////////////////////////////////////////////////////////
+
+// NB: This assignment ordering is assumed by static initialization code.
+// These constants are used as array indices.
+
+#define BCE_ENGINE_BCDE 0
+#define BCE_ENGINE_BCUE 1
+
+#define BCE_ENGINES 2
+
+#ifndef __ASSEMBLER__
+
+
+/// A PBA Block Copy Engine queue
+///
+/// A PBA block copy request queue consists of a generic AsyncQueue to manage
+/// jobs on the engine and the PBA engine id. The BCDE and BCUE can use the
+/// same driver because their control interfaces are identical.
+
+typedef struct BceQueue {
+
+ /// The generic request queue
+ AsyncQueue queue;
+
+ /// The engine id of the BCE engine for control register address lookup
+ int engine;
+
+} BceQueue;
+
+
+int
+bce_queue_create(BceQueue *queue,
+ int engine);
+
+
+int
+bce_request_schedule(BceRequest *request);
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// PbaxRequest
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+struct PbaxQueue;
+
+/// A request to move data through a PBAX circular queue
+///
+/// The PBAX circular queues are modeled after the OCB circular queues. The
+/// queues are named and documented in the hardware specifications from the
+/// perspective of the PowerBus as "PUSH" queues. Here we name and document
+/// the queues from the perspective of OCC firmware as "READ" queues. Note
+/// that there are no PBAX "WRITE" queues. The PBAX write mechanism handles
+/// only a single datum at a time and has no interrupt. PBAX writes are
+/// handled by the pbax_send() and _pbax_send() APIs.
+///
+/// The PBAX queues support data buffers of from 8 to 256 bytes with an 8-byte
+/// granularity. The PBAX hardware requires that the data buffers be aligned
+/// to a power-of-2 boundary greater than or equal to the buffer size.
+/// The async drivers allow specification of any multiple of 8 bytes to read
+/// and handle all of the queue and split-request management.
+///
+/// Note : As long as the PbaxRequest is idle, the application is free to
+/// directly change the \a data and \a bytes fields to read/write different
+/// numbers of bytes to/from different locations the next time the request is
+/// scheduled.
+///
+/// The PBAX queues support both 'lazy' and 'aggressive' interrupt protocols.
+/// The aggressive protocols generate interrupts whenever read data is
+/// available. The lazy protocols require a full read buffer to trigger an
+/// interrupt. A lazy read protocol with a buffer size > 1 demands that
+/// communcations always consist of a known number of doublewords equal to the
+/// buffer size. For free-form communications an aggressive read protocol must
+/// be used.
+
+typedef struct {
+
+ /// The generic request
+ AsyncRequest request;
+
+ /// Initial pointer to the data area to hold read data.
+ ///
+ /// This field is not modified by the drivers. The application may modify
+ /// this field any time the PbaxRequest is idle.
+ uint64_t *data;
+
+ /// Number of bytes to move, which must be a multiple of 8.
+ ///
+ /// This field is not modified by the drivers. The application may modify
+ /// this field any time the PbaxRequest is idle.
+ size_t bytes;
+
+ /// Pointer to where to put the next read data.
+ ///
+ /// The application should never modify this field.
+ void* current;
+
+ /// Number of bytes remaining to be moved.
+ ///
+ /// The application should never modify this field.
+ size_t remaining;
+
+} PbaxRequest;
+
+
+int
+pbax_request_create(PbaxRequest *request,
+ struct PbaxQueue *queue,
+ uint64_t *data,
+ size_t bytes,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options);
+
+
+int
+pbax_request_schedule(PbaxRequest *request);
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// PbaxQueue
+////////////////////////////////////////////////////////////////////////////
+
+// NB: This assignment ordering is assumed by static initialization code in
+// pgp_async.c - these constants are used as array indices.
+
+#define PBAX_ENGINE_PUSH0 0
+#define PBAX_ENGINE_PUSH1 1
+
+#define PBAX_ENGINES 2
+
+#ifndef __ASSEMBLER__
+
+extern const SsxAddress pba_xshcsn[];
+extern const SsxAddress pba_xshbrn[];
+extern const SsxAddress pba_xshincn[];
+
+
+/// A PBAX Circular buffer queue
+///
+/// A PBAX circular buffer queue consists of a generic AsyncQueue to manage
+/// jobs on the engine, a pointer to the data area and the PBAX engine id.
+
+typedef struct PbaxQueue {
+
+ /// The generic request queue
+ AsyncQueue queue;
+
+ /// The base of the circular queue data area
+ ///
+ /// This data area must satisfy stringent alignment constraints; See the
+ /// documentation for PbaxRequest.
+ uint64_t *cq_base;
+
+ /// The number of 8-byte entries in the queue.
+ ///
+ /// This is included here to simplify APIs; The length is also encoded in
+ /// the PBAXSHCSn register for the queue.
+ size_t cq_entries;
+
+ /// The interrupt protocol implemented by the queue.
+ ///
+ /// This will either be PBAX_INTERRUPT_PROTOCOL_LAZY or
+ /// PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE.
+ int protocol;
+
+ /// The engine id for lookup of OCI control register addresses.
+ int engine;
+
+ /// The IRQ associated with normal completion on the engine
+ ///
+ /// \todo Due to header reference ordering we can't define this as SsxIrqId
+ uint8_t irq;
+
+} PbaxQueue;
+
+
+int
+pbax_queue_create(PbaxQueue *queue,
+ int engine,
+ uint64_t *cq_base,
+ size_t cq_entries,
+ int protocol);
+
+int
+pbax_queue_disable(PbaxQueue *queue);
+
+int
+pbax_queue_enable(PbaxQueue *queue);
+
+int
+pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read);
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// OcbRequest
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// OCB FFDC
+///
+/// This structure is used to store FFDC in two cases. 1) When an error can be
+/// reasonably attributed to an OCB channel under the control of OCC, and 2)
+/// general errors signalled by the OCB direct bridge. Due to the myriad ways
+/// that OCB channels can be used the FFDC for OCB direct bridge errors is
+/// stored globally rather than with particular requests or queues.
+///
+/// The OcbFfdc includes the PLB arbiter PEARL and PESR register state.
+/// This state is only collected if the error status indicates an OCI timeout
+/// for this channel.
+///
+/// Any error reasonably attributable to a channel will capture the FFDC and
+/// then disable the channel since any further communication through the
+/// channel must be considered compromised.
+
+typedef struct {
+
+ /// FFDC from the OCI (PLB) arbiter
+ OciFfdc oci_ffdc;
+
+ /// A copy of the OCB OCC_LFIR register at the time of the error
+ ocb_occlfir_t fir;
+
+ /// A copy of the OCB Control/Status register for the channel at the time
+ /// of the error.
+ ///
+ /// This field will be set to 0 for generic OCB bridge errors
+ ocb_ocbcsrn_t csr;
+
+ /// A copy of the OCB Stream Push Base [n] Register at the time of the
+ /// failure
+ ///
+ /// This field will be set to 0 for generic OCB bridge errors
+ ocb_ocbshbrn_t shbr;
+
+ /// A copy of the OCB Stream Push Control/Status [n] Register at the time
+ /// of the failure
+ ///
+ /// This field will be set to 0 for generic OCB bridge errors
+ ocb_ocbshcsn_t shcs;
+
+ /// A copy of the OCB Stream Pull Base [n] Register at the time of the
+ /// failure
+ ///
+ /// This field will be set to 0 for generic OCB bridge errors
+ ocb_ocbslbrn_t slbr;
+
+ /// A copy of the OCB Stream Pull Control/Status [n] Register at the time
+ /// of the failure
+ ///
+ /// This field will be set to 0 for generic OCB bridge errors
+ ocb_ocbslcsn_t slcs;
+
+ /// Is this record valid (does it contain captured error information)?
+ int error;
+
+} OcbFfdc;
+
+
+/// OCB Unit FFDC
+///
+/// Contains FFDC structures for each channel and the direct bridge
+
+typedef struct {
+
+ OcbFfdc channel[OCB_INDIRECT_CHANNELS];
+ OcbFfdc bridge;
+
+} OcbUnitFfdc;
+
+
+/// Global FFDC for OCB
+
+extern OcbUnitFfdc G_ocb_ffdc;
+
+
+struct OcbQueue;
+
+/// A request to move data through an OCB circular queue
+///
+/// The OCB circular queues are named and documented in the hardware specs
+/// from the perspective of the PIB - "PUSH" and "PULL" queues. Here we name
+/// and document the queues from the perspective of OCC firmware - "READ" and
+/// "WRITE" queues. The request is generic and becomes either a read or write
+/// request simply by which queue it is scheduled on.
+///
+/// The circular queues only support 8-byte granularity, require that the data
+/// areas be 8- or 32-byte aligned, and only support up to 256 byte
+/// queues. However the async drivers allow specification of any multiple of 8
+/// bytes to read or write, and handle all of the queue and split-request
+/// management.
+///
+/// Note : As long as the OcbRequest is idle, the application is free to
+/// directly change the \a data and \a bytes fields to read/write different
+/// numbers of bytes to/from different locations the next time the request is
+/// scheduled.
+///
+/// OCB requests always complete in an interrupt context. The OCB queues
+/// support both 'lazy' and 'aggressive' interrupt protocols. The aggressive
+/// protocols generate interrupts whenever read data is available or write
+/// space is available. The lazy protocols require a full read buffer or
+/// empty write buffer to trigger an interrupt. A lazy read protocol with a
+/// buffer size > 1 demands that communcations always consist of a known
+/// number of doublewords. For free-form communications an aggressive read
+/// protocol must be used. On average, an aggressive write protocol will
+/// shorten blocking periods of writers, and can guarantee that data is in the
+/// queue whenever data is avilable. Lazy write protocols will be preferred
+/// when reducing interrupt overhead is more important than reducing blocking
+/// time.
+///
+/// Completion of write requests does not guarantee that the communication
+/// partner has received the data, but simply that the data has been queued
+/// for reception and the caller may reuse/refill the data buffer if required.
+
+typedef struct {
+
+ /// The generic request
+ AsyncRequest request;
+
+ /// Initial pointer to the data to be moved for write data, or the
+ /// data area to hold read data. This field is not modified by the drivers.
+ uint64_t *data;
+
+ /// Number of bytes to move. This field is not modified by the drivers.
+ size_t bytes;
+
+ /// Pointer to data yet to be moved for write, or where to put the next
+ /// read data.
+ uint64_t* current;
+
+ /// Number of bytes remaining to be moved.
+ size_t remaining;
+
+} OcbRequest;
+
+
+int
+ocb_request_create(OcbRequest *request,
+ struct OcbQueue *queue,
+ uint64_t *data,
+ size_t bytes,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options);
+
+
+int
+ocb_request_schedule(OcbRequest *request);
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// OcbQueue
+////////////////////////////////////////////////////////////////////////////
+
+// NB: This assignment ordering is assumed by static initialization code in
+// pgp_async.c - these constants are used as array indices. The code also
+// assumes this ordering for the access of G_ocb_ocbsesn[], and for
+// determining whether the engine is a PUSH or PULL queue.
+// Note: push/pull queues for channel 3 have been deleted
+
+#define OCB_ENGINE_PUSH0 0
+#define OCB_ENGINE_PULL0 1
+#define OCB_ENGINE_PUSH1 2
+#define OCB_ENGINE_PULL1 3
+#define OCB_ENGINE_PUSH2 4
+#define OCB_ENGINE_PULL2 5
+
+#define OCB_ENGINES 6
+
+#ifndef __ASSEMBLER__
+
+/// An OCB Circular buffer queue
+///
+/// A OCB circular buffer queue consists of a generic AsyncQueue to manage
+/// jobs on the engine, a pointer to the data area and the OCB engine id.
+
+typedef struct OcbQueue {
+
+ /// The generic request queue
+ AsyncQueue queue;
+
+ /// The base of the circular queue data area - must be 8-byte aligned
+ uint64_t *cq_base;
+
+ /// The length of the queue in terms of the number of 8-byte entries in
+ /// the queue.
+ ///
+ /// This is for informational purposes only. The length is also encoded
+ /// in the OCBSxCSn register for the queue.
+ size_t cq_length;
+
+ /// The engine id for lookup of OCI control register addresses.
+ int engine;
+
+ /// The IRQ associated with normal completion on the engine
+ ///
+ /// \todo Due to header reference ordering we can't define this as SsxIrqId
+ uint8_t irq;
+
+} OcbQueue;
+
+
+int
+ocb_queue_create(OcbQueue *queue,
+ int engine,
+ uint64_t *cq_base,
+ size_t cq_length,
+ int protocol);
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// Miscellaneous/Initialization
+////////////////////////////////////////////////////////////////////////////
+
+// Error codes
+
+#define ASYNC_INVALID_OBJECT_REQUEST 0x00279600
+#define ASYNC_INVALID_OBJECT_SCHEDULE 0x00279601
+#define ASYNC_INVALID_OBJECT_OCB_REQUEST 0x00279602
+#define ASYNC_INVALID_OBJECT_OCB_QUEUE 0x00279603
+#define ASYNC_INVALID_OBJECT_PBAX_REQUEST 0x00279604
+#define ASYNC_INVALID_OBJECT_PBAX_DISABLE 0x00279605
+#define ASYNC_INVALID_OBJECT_PBAX_QUEUE 0x00279606
+#define ASYNC_INVALID_OBJECT_BCE_REQUEST 0x00279607
+#define ASYNC_INVALID_OBJECT_BCE_QUEUE 0x00279608
+#define ASYNC_INVALID_OBJECT_PORE_REQUEST 0x00279609
+#define ASYNC_INVALID_OBJECT_PORE_QUEUE 0x0027960a
+#define ASYNC_INVALID_OBJECT_PTS_REQUEST 0x0027960b
+#define ASYNC_INVALID_OBJECT_PTS_THREAD 0x0027960c
+#define ASYNC_INVALID_OBJECT_PTS_QUEUE 0x0027960d
+#define ASYNC_INVALID_OBJECT_PTS_START 0x0027960e
+#define ASYNC_INVALID_OBJECT_PTS_SCHEDULE 0x0027960f
+#define ASYNC_INVALID_ARGUMENT 0x00279610
+#define ASYNC_INVALID_ARGUMENT_OCB_READ 0x00279611
+#define ASYNC_INVALID_ARGUMENT_OCB_WRITE 0x00279612
+#define ASYNC_INVALID_ARGUMENT_OCB_QUEUE 0x00279613
+#define ASYNC_INVALID_ARGUMENT_OCB_QUEUE2 0x00279614
+#define ASYNC_INVALID_ARGUMENT_OCB_REQUEST 0x00279615
+#define ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE 0x00279616
+#define ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE 0x00279617
+#define ASYNC_INVALID_ARGUMENT_PBAX_READ 0x00279618
+#define ASYNC_INVALID_ARGUMENT_PBAX_REQUEST 0x00279619
+#define ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE 0x0027961a
+#define ASYNC_INVALID_ARGUMENT_PBAX_QUEUE 0x0027961b
+#define ASYNC_INVALID_ARGUMENT_PORE_REQUEST 0x0027961c
+#define ASYNC_INVALID_ARGUMENT_PTS_THREAD 0x0027961d
+#define ASYNC_INVALID_ARGUMENT_PTS_REQUEST 0x0027961e
+#define ASYNC_INVALID_ENGINE_OCB 0x0027961f
+#define ASYNC_INVALID_ENGINE_PBAX 0x00279620
+#define ASYNC_INVALID_ENGINE_BCE 0x00279621
+#define ASYNC_INVALID_ENGINE_PORE 0x00279622
+#define ASYNC_INVALID_ENGINE_PTS 0x00279623
+#define ASYNC_INVALID_OPTIONS 0x00279624
+#define ASYNC_INVALID_ASSIGNMENT 0x00279625
+#define ASYNC_CALLBACK_PROTOCOL_UNSPECIFIED 0x00279626
+#define ASYNC_REQUEST_NOT_IDLE 0x00279627
+#define ASYNC_REQUEST_NOT_IDLE_PTS 0x00279628
+#define ASYNC_REQUEST_COMPLETE 0x00279629
+#define ASYNC_INVALID_TIMESTAMPS 0x0027962a
+#define ASYNC_OCB_ERROR_READ_OLD 0x0027962b
+#define ASYNC_OCB_ERROR_READ_NEW 0x0027962c
+#define ASYNC_OCB_ERROR_WRITE_OLD 0x0027962d
+#define ASYNC_OCB_ERROR_WRITE_NEW 0x0027962e
+#define ASYNC_PBAX_ERROR_OLD 0x0027962f
+#define ASYNC_PBAX_ERROR_NEW 0x00279630
+#define ASYNC_REQUEST_NOT_COMPLETE 0x00279631
+#define ASYNC_REQUEST_NOT_COMPLETE_PTS 0x00279632
+
+// Panic codes
+
+#define ASYNC_PORE_FIXED_INVARIANT 0x00279633
+#define ASYNC_PHANTOM_INTERRUPT 0x00279634
+#define ASYNC_PHANTOM_INTERRUPT_OCB 0x00279635
+#define ASYNC_PHANTOM_INTERRUPT_BCE 0x00279636
+#define ASYNC_PHANTOM_INTERRUPT_PBAX 0x00279637
+#define ASYNC_SCOM_ERROR 0x00279638
+#define ASYNC_TIMEOUT_BUG 0x00279639
+#define ASYNC_INVALID_STATE 0x0027963a
+#define ASYNC_PHANTOM_ERROR 0x0027963b
+#define ASYNC_BUG_PORE_AT_CREATE 0x0027963c
+#define ASYNC_BUG_PTS_AT_CREATE 0x0027963d
+#define ASYNC_BUG_PTS_AT_RUN 0x0027963e
+
+////////////////////////////////////////////////////////////////////////////
+// Global Data and Constants
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+// PORE Queues
+
+extern PoreQueue G_pore_gpe0_queue;
+extern PoreQueue G_pore_gpe1_queue;
+extern PoreQueue G_pore_slw_queue;
+
+/// Define a PORE branch table. All error slots are always defined, but space
+/// can be saved if not all of the entry points are required.
+#define PORE_TABLE(var, slots) PoreBraia var[PORE_ERROR_SLOTS + (slots)]
+
+
+// PTS Queues
+//
+// These queues are only defined if CONFIGURE_PTS is non-zero. CONFIGURE_PTS
+// is 0 by default.
+
+#ifndef CONFIGURE_PTS
+#define CONFIGURE_PTS 0
+#endif
+
+#if CONFIGURE_PTS
+#include "pgp_async_pts.h"
+extern PtsQueue G_pts_gpe0_queue;
+extern PtsQueue G_pts_gpe1_queue;
+#endif
+
+
+// OCB Queues and FFDC
+
+// OCB circular queue naming is confusing, because PUSH/PULL are defined from
+// the perspective of the PIB. This driver uses the terms read/write
+// respectively and represents the hardware from the perspective of code
+// running on OCC.
+
+// OCB read/write queue lengths are defined in terms of doublewords, and must
+// be in a small defined range. Two meaningful interrupt protocols are
+// possible for a queue: 'LAZY' allows read/write queues to fill/empty
+// respectively before an interrupt is signalled. 'AGRESSIVE' signals an
+// interrupt whenever there is data to be read or a free slot to put write
+// data.
+
+// In a production system the lengths and protocols will likely vary based on
+// the particular application and the characteristics of the communication
+// partner. By default the queues take on their maximum lengths. Read queues
+// use the aggressive protocol which allows free-form communication. Write
+// queues use lazy protoclols which reduces interrupt overhead. Different
+// effective lengths and the interrupt protocols can be changed later if
+// desired - assuming the queues are idle when the changes are made.
+
+#define OCB_PUSH_PULL_LENGTH_MIN 1
+#define OCB_PUSH_PULL_LENGTH_MAX 32
+
+#define OCB_INTERRUPT_PROTOCOL_LAZY 0
+#define OCB_INTERRUPT_PROTOCOL_AGGRESSIVE 1
+
+#define OCB_READ0_LENGTH OCB_PUSH_PULL_LENGTH_MAX
+#define OCB_READ1_LENGTH OCB_PUSH_PULL_LENGTH_MAX
+#define OCB_READ2_LENGTH OCB_PUSH_PULL_LENGTH_MAX
+
+#define OCB_WRITE0_LENGTH OCB_PUSH_PULL_LENGTH_MAX
+#define OCB_WRITE1_LENGTH OCB_PUSH_PULL_LENGTH_MAX
+#define OCB_WRITE2_LENGTH OCB_PUSH_PULL_LENGTH_MAX
+
+#define OCB_READ0_PROTOCOL OCB_INTERRUPT_PROTOCOL_AGGRESSIVE
+#define OCB_READ1_PROTOCOL OCB_INTERRUPT_PROTOCOL_AGGRESSIVE
+#define OCB_READ2_PROTOCOL OCB_INTERRUPT_PROTOCOL_AGGRESSIVE
+
+#define OCB_WRITE0_PROTOCOL OCB_INTERRUPT_PROTOCOL_LAZY
+#define OCB_WRITE1_PROTOCOL OCB_INTERRUPT_PROTOCOL_LAZY
+#define OCB_WRITE2_PROTOCOL OCB_INTERRUPT_PROTOCOL_LAZY
+
+extern OcbUnitFfdc G_ocb_ffdc;
+
+extern OcbQueue G_ocb_read_queue[];
+extern OcbQueue G_ocb_write_queue[];
+
+extern uint64_t G_ocb_read0_buffer[];
+extern uint64_t G_ocb_read1_buffer[];
+extern uint64_t G_ocb_read2_buffer[];
+
+extern uint64_t G_ocb_write0_buffer[];
+extern uint64_t G_ocb_write1_buffer[];
+extern uint64_t G_ocb_write2_buffer[];
+
+
+// PBA Queues
+
+/// Block Copy Upload (OCI -> PowerBus) Engine job queue;
+extern BceQueue G_pba_bcue_queue;
+
+/// Block Copy Download Engine (PowerBus -> OCI) job queue;
+extern BceQueue G_pba_bcde_queue;
+
+
+// PBAX Queues
+
+// PBAX circular queue naming is confusing, because "PUSH" is defined from the
+// perspective of the PowerBus. This driver uses the term "READ" and
+// represents the hardware from the perspective of code running on OCC.
+
+// PBAX read queue lengths are defined in terms of 8-byte doublewords, and
+// must be in a small defined range. Two meaningful interrupt protocols are
+// possible for a queue: 'LAZY' allows read queues to fill before an interrupt
+// is signalled. 'AGRESSIVE' signals an interrupt whenever there is data to
+// be read.
+
+// In a production system the lengths and protocols will likely vary based on
+// the particular application and the characteristics of the communication
+// partner. By default the queues take on their maximum lengths. Read queues
+// use the aggressive protocol which allows free-form communication. Different
+// effective lengths and the interrupt protocols can be changed later if
+// desired - assuming the queues are idle when the changes are made.
+
+#define PBAX_PUSH_LENGTH_MIN 1
+#define PBAX_PUSH_LENGTH_MAX 32
+
+#define PBAX_INTERRUPT_PROTOCOL_LAZY 0
+#define PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE 1
+
+#define PBAX_READ0_LENGTH PBAX_PUSH_LENGTH_MAX
+#define PBAX_READ1_LENGTH PBAX_PUSH_LENGTH_MAX
+
+#define PBAX_READ0_PROTOCOL PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE
+#define PBAX_READ1_PROTOCOL PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE
+
+/// Job queues for the PBAX circular buffers
+extern PbaxQueue G_pbax_read_queue[];
+
+
+// PBAX read buffers must be cache-line aligned since they are invalidated,
+// and furthermore must be aligned to the next higher power-of-two of their
+// lengths. Some minor efficiencies could probably be obtained by a policy
+// that buffers be held in non-cacheable storage (and subsequent modifications
+// to the device driver code).
+//
+// Due to linker restrictions, only initialized data areas can be aligned.
+
+
+#define _PBAX_ALIGN_(length) \
+ (((length) <= 4) ? 32 : \
+ (((length) <= 8) ? 64 : \
+ (((length) <= 16) ? 128 : 256)))
+
+#define PBAX_CQ_READ_BUFFER(buffer, length) \
+ uint64_t buffer[length] \
+ __attribute__ ((aligned (_PBAX_ALIGN_(length)))) = {0}
+
+
+extern uint64_t G_pbax_read0_buffer[];
+extern uint64_t G_pbax_read1_buffer[];
+
+
+// Initialization APIs
+
+void
+async_pore_initialize(PoreQueue *queue, int engine);
+
+void
+async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq);
+
+
+void
+async_ocb_initialize(OcbQueue *queue, int engine,
+ uint64_t *buffer, size_t length, int protocol);
+
+
+void
+async_pbax_initialize(PbaxQueue *queue, int engine, SsxIrqId irq,
+ uint64_t *buffer, size_t length, int protocol);
+
+
+void
+async_initialize();
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PGP_ASYNC_H__ */
diff --git a/src/ssx/pgp/pgp_async_ocb.c b/src/ssx/pgp/pgp_async_ocb.c
new file mode 100755
index 0000000..b9ef4b8
--- /dev/null
+++ b/src/ssx/pgp/pgp_async_ocb.c
@@ -0,0 +1,953 @@
+// $Id: pgp_async_ocb.c,v 1.2 2014/02/03 01:30:34 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async_ocb.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_async_ocb.c
+/// \brief Async driver code for OCB
+
+#include "ssx.h"
+
+
+////////////////////////////////////////////////////////////////////////////
+// Global Data
+////////////////////////////////////////////////////////////////////////////
+
+OcbUnitFfdc G_ocb_ffdc = {{{{{0}}}}};
+
+OcbQueue G_ocb_read_queue[OCB_INDIRECT_CHANNELS];
+OcbQueue G_ocb_write_queue[OCB_INDIRECT_CHANNELS];
+
+
+#if OCB_READ0_LENGTH % CACHE_LINE_SIZE
+#error "OCB read buffer 0 alignment error"
+#endif
+#if OCB_READ1_LENGTH % CACHE_LINE_SIZE
+#error "OCB read buffer 1 alignment error"
+#endif
+#if OCB_READ2_LENGTH % CACHE_LINE_SIZE
+#error "OCB read buffer 2 alignment error"
+#endif
+#if OCB_READ3_LENGTH % CACHE_LINE_SIZE
+#error "OCB read buffer 3 alignment error"
+#endif
+
+// OCB circular queue write buffers must be 8-byte aligned per hardware
+// restrictions, whereas read buffers are cache-line aligned and must be an
+// even multiple of the cache line size since they must be invalidated. Some
+// minor efficiencies could probably be obtained by a policy that CQ buffers
+// be held in non-cacheable storage (and subsequent modifications to the
+// device driver code).
+//
+// Due to linker restrictions, only initialized data areas can be aligned.
+
+#define OCB_CQ_WRITE_BUFFER(buffer, length) \
+ uint64_t buffer[length] __attribute__ ((aligned (8))) = {0}
+
+#define OCB_CQ_READ_BUFFER(buffer, length) \
+ uint64_t buffer[length] __attribute__ ((aligned (CACHE_LINE_SIZE))) = {0}
+
+
+OCB_CQ_READ_BUFFER(G_ocb_read0_buffer, OCB_READ0_LENGTH);
+OCB_CQ_READ_BUFFER(G_ocb_read1_buffer, OCB_READ1_LENGTH);
+OCB_CQ_READ_BUFFER(G_ocb_read2_buffer, OCB_READ2_LENGTH);
+
+OCB_CQ_WRITE_BUFFER(G_ocb_write0_buffer, OCB_WRITE0_LENGTH);
+OCB_CQ_WRITE_BUFFER(G_ocb_write1_buffer, OCB_WRITE1_LENGTH);
+OCB_CQ_WRITE_BUFFER(G_ocb_write2_buffer, OCB_WRITE2_LENGTH);
+
+
+////////////////////////////////////////////////////////////////////////////
+// Local Data
+////////////////////////////////////////////////////////////////////////////
+
+/// \todo These addresses could/should simply be stored with the queue objects
+/// to avoid these static data declarations.
+
+/// OCB Stream Push/Pull Control/Status Register addresses
+
+static const SsxAddress G_ocb_ocbsxcsn[OCB_ENGINES] =
+ {OCB_OCBSHCS0, OCB_OCBSLCS0,
+ OCB_OCBSHCS1, OCB_OCBSLCS1,
+ OCB_OCBSHCS2, OCB_OCBSLCS2};
+
+/// OCB Stream Push/Pull Base Register addresses
+
+static const SsxAddress G_ocb_ocbsxbrn[OCB_ENGINES] =
+ {OCB_OCBSHBR0, OCB_OCBSLBR0,
+ OCB_OCBSHBR1, OCB_OCBSLBR1,
+ OCB_OCBSHBR2, OCB_OCBSLBR2};
+
+
+/// OCB Stream Push/Pull Increment Register addresses
+
+static const SsxAddress G_ocb_ocbsxin[OCB_ENGINES] =
+ {OCB_OCBSHI0, OCB_OCBSLI0,
+ OCB_OCBSHI1, OCB_OCBSLI1,
+ OCB_OCBSHI2, OCB_OCBSLI2};
+
+
+/// OCB Stream Error Status; There is only one register per OCB channel
+
+const SsxAddress G_ocb_ocbsesn[OCB_ENGINES / 2] =
+ {OCB_OCBSES0, OCB_OCBSES1, OCB_OCBSES2};
+
+
+////////////////////////////////////////////////////////////////////////////
+// OcbRequest
+////////////////////////////////////////////////////////////////////////////
+
+// Collect FFDC for an OCB channel
+//
+// This is an internal API, called either due to an OCB error interrupt or a
+// read/write error detected during the operation. See the comments for
+// OcbFfdc for a description of why this particular set of data is collected.
+// The special channel number -1 is used to denote the direct bridge.
+//
+// OCB FFDC collection procedure:
+//
+// - Collect the OCBSCR<n> for indirect channels
+//
+// - Collect PUSH/PULL queue setup for indirect channels and disable the queues.
+//
+// - Collect the OCB FIR
+//
+// - Collect FFDC from the PLB (OCI) arbiter
+//
+// FFDC is only collected for the first error, until the error flag is reset.
+
+static void
+ocb_ffdc(int channel)
+{
+ OcbFfdc* ffdc;
+
+ if (channel < 0) {
+ ffdc = &(G_ocb_ffdc.bridge);
+ } else {
+ ffdc = &(G_ocb_ffdc.channel[channel]);
+ }
+
+ if (ffdc->error == 0) {
+
+ if (channel < 0) {
+
+ memset(ffdc, 0, sizeof(OcbFfdc));
+
+ } else {
+
+ getscom(OCB_OCBCSRN(channel), &(ffdc->csr.value));
+
+ ffdc->shbr.value = in32(OCB_OCBSHBRN(channel));
+ ffdc->shcs.value = in32(OCB_OCBSHCSN(channel));
+ ffdc->slbr.value = in32(OCB_OCBSLBRN(channel));
+ ffdc->slcs.value = in32(OCB_OCBSLCSN(channel));
+
+ out32(OCB_OCBSHCSN(channel),
+ ffdc->shcs.value & ~OCB_OCBSHCSN_PUSH_ENABLE);
+ out32(OCB_OCBSLCSN(channel),
+ ffdc->slcs.value & ~OCB_OCBSLCSN_PULL_ENABLE);
+
+ }
+
+ getscom(OCB_OCCLFIR, &(ffdc->fir.value));
+
+ oci_ffdc(&(ffdc->oci_ffdc), OCI_MASTER_ID_OCB);
+
+ ffdc->error = 1;
+ }
+}
+
+
+/// Non-blocking read from an OCB PUSH (read) queue
+///
+/// \param queue The target OcbQueue
+///
+/// \param buf The caller's data buffer to receive the read data
+///
+/// \param bytes The maximum number of bytes to read. This value must be an
+/// even multiple of 8, as this API always reads multiples of 8 bytes.
+///
+/// \param read The number of bytes actually copied from the device buffer to
+/// the caller's buffer. This may be returned as any value from 0 to \a
+/// bytes in multiples of 8 bytes.
+///
+/// ocb_read() implements a non-blocking copy of data from an OCB read (PUSH)
+/// queue data area to the caller's data area, with the side effect of
+/// advancing the hardware queue pointers. ocb_read() does not implement
+/// locking, critical sections or any other type of synchronization for access
+/// to the OCB queue data - that is the responsibility of the caller.
+///
+/// ocb_read() may return an error code. This may indicate a preexisting
+/// error in the queue, or may be an error resulting from the current read.
+/// In either event any read data should be considered corrupted.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_OCB_READ The number of \a bytes is not
+/// an even multiple of 8.
+///
+/// \retval -ASYNC_OCB_ERROR_READ_OLD or -ASYNC_OCB_ERROR_READ_NEW This code
+/// indicates an error associated with the OCB channel represented by the queue.
+
+int
+ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read)
+{
+ ocb_ocbshcsn_t csr;
+ ocb_ocbsesn_t ses;
+ unsigned qlen, read_ptr, write_ptr, to_read;
+ uint64_t *pcq, *pbuf;
+ int rc;
+
+ do {
+
+ rc = 0;
+ *read = 0;
+
+ // If pre-existing errors exist then immediately abort the read.
+
+ if (G_ocb_ffdc.channel[queue->engine / 2].error) {
+ rc = -ASYNC_OCB_ERROR_READ_OLD;
+ break;
+ }
+
+ if (bytes % 8) {
+ rc = -ASYNC_INVALID_ARGUMENT_OCB_READ;
+ break;
+ }
+
+ // Determine the number of doubleword entries remaining to be read in
+ // the queue. The driver does not keep state, but instead reinterprets
+ // the control/status register each time ocb_read() is called.
+
+ // This may be confusing - remember that 'push' and 'pull' are from
+ // the PIB perspective - here we use 'read' and 'write' from OCC's
+ // perspective.
+
+ csr.value = in32(G_ocb_ocbsxcsn[queue->engine]);
+
+ qlen = csr.fields.push_length + 1;
+ read_ptr = csr.fields.push_read_ptr;
+
+ if (csr.fields.push_empty) {
+ break;
+
+ } else if (csr.fields.push_full) {
+ to_read = qlen;
+
+ } else {
+ write_ptr = csr.fields.push_write_ptr;
+ if (read_ptr > write_ptr) {
+ to_read = qlen - (read_ptr - write_ptr);
+ } else {
+ to_read = write_ptr - read_ptr;
+ }
+ }
+
+ // Copy the data from the CQ memory area to the user's buffer. For
+ // simplicty of dealing with cache management each doubleword invokes
+ // a line invalidate before refetching the fresh data from
+ // memory. Alignment requirements enforced on the data buffer
+ // guarantee the buffers are cache-line aligned and each doubleword is
+ // fully contained in a single D-cache line.
+ //
+ // Here the code models the evolution of the read_ptr as each datum is
+ // copied from the queue.
+
+ pbuf = (uint64_t*)buf;
+ while (bytes && to_read--) {
+
+ read_ptr++;
+ if (read_ptr == qlen) {
+ read_ptr = 0;
+ }
+ pcq = queue->cq_base + read_ptr;
+
+ dcache_invalidate_line(pcq);
+ *pbuf++ = *pcq;
+ out32(G_ocb_ocbsxin[queue->engine], 0);
+
+ bytes -= 8;
+ *read += 8;
+ }
+ } while (0);
+
+ // Check for underflow errors. If found, collect FFDC.
+
+ ses.value = in32(G_ocb_ocbsesn[queue->engine / 2]);
+ if (ses.fields.push_read_underflow) {
+ ocb_ffdc(queue->engine / 2);
+ rc = -ASYNC_OCB_ERROR_READ_NEW;
+ }
+
+ return rc;
+}
+
+
+/// Non-blocking write to an OCB PULL (write) queue
+///
+/// \param queue The target OcbQueue
+///
+/// \param buf The caller's data buffer containing the write data
+///
+/// \param bytes The maximum number of bytes to write. This value must be an
+/// even multiple of 8, as this API always writes multiples of 8 bytes.
+///
+/// \param written The number of bytes actually copied from the caller's buffer to
+/// the device buffer. This may be returned as any value from 0 to \a
+/// bytes in multiples of 8 bytes.
+///
+/// ocb_write() implements a non-blocking copy of data to an OCB write (PULL)
+/// queue, with the side effect of advancing the hardware queue pointers.
+/// ocb_write() does not implement locking, critical sections or any other
+/// type of synchronization for access to the OCB queue data - that is the
+/// responsibility of the caller.
+///
+/// ocb_write() may return an error code. This may indicate a preexisting
+/// error in the queue, or may be an error resulting from the current write.
+/// In either event any write data should be considered corrupted/nondelivered.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_OCB_WRITE The number of \a bytes is not
+/// an even multiple of 8.
+///
+/// \retval -ASYNC_OCB_ERROR_WRITE_OLD or -ASYNC_OCB_ERROR_WRITE_NEW This code
+/// indicates an error associated with the OCB channel represented by the queue.
+
+int
+ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written)
+{
+ ocb_ocbslcsn_t csr;
+ ocb_ocbsesn_t ses;
+ unsigned qlen, read_ptr, write_ptr, free;
+ uint64_t *pcq, *pbuf;
+ int rc;
+
+ do {
+
+ rc = 0;
+ *written = 0;
+
+ // Pre-existing errors immediately abort the read.
+
+ if (G_ocb_ffdc.channel[queue->engine / 2].error) {
+ rc = -ASYNC_OCB_ERROR_WRITE_OLD;
+ break;
+ }
+
+ if (bytes % 8) {
+ rc = -ASYNC_INVALID_ARGUMENT_OCB_WRITE;
+ break;
+ }
+
+ // Determine the number of free doubleword entries remaining in the
+ // queue. The driver does not keep state, but instead reinterprets the
+ // control/status register each time the write method is called.
+
+ // This is confusing - remember that 'push' and 'pull' are from the PIB
+ // perspective - here we use 'read' and 'write' from OCC's perspective.
+
+ csr.value = in32(G_ocb_ocbsxcsn[queue->engine]);
+
+ qlen = csr.fields.pull_length + 1;
+ write_ptr = csr.fields.pull_write_ptr;
+
+ if (csr.fields.pull_full) {
+ break;
+ }
+
+ if (csr.fields.pull_empty) {
+ free = qlen;
+ } else {
+ read_ptr = csr.fields.pull_read_ptr;
+ if (write_ptr > read_ptr) {
+ free = qlen - (write_ptr - read_ptr);
+ } else {
+ free = read_ptr - write_ptr;
+ }
+ }
+
+ // Copy the data into the CQ memory area. For simplicty of dealing
+ // with cache management each doubleword invokes a line flush before
+ // incrementing the hardware pointer. Alignment requirements enforced
+ // on the data buffer guarantee each doubleword is fully contained in
+ // a single D-cache line.
+ //
+ // Here the code models the evolution of the write_ptr as each datum is
+ // copied into the queue.
+
+ pbuf = (uint64_t*)buf;
+ while (bytes && free--) {
+
+ write_ptr++;
+ if (write_ptr == qlen) {
+ write_ptr = 0;
+ }
+ pcq = queue->cq_base + write_ptr;
+
+ *pcq = *pbuf++;
+ dcache_flush_line(pcq);
+ in32(G_ocb_ocbsxin[queue->engine]);
+
+ bytes -= 8;
+ *written += 8;
+ }
+ } while (0);
+
+ // Check for overflow. If found, collect FFDC.
+
+ ses.value = in32(G_ocb_ocbsesn[queue->engine / 2]);
+ if (ses.fields.pull_write_overflow) {
+ ocb_ffdc(queue->engine / 2);
+ rc = -ASYNC_OCB_ERROR_WRITE_NEW;
+ }
+
+ return rc;
+}
+
+
+// This is the internal 'run method' for reading through an OCB circular
+// queue. The run method simply enables the IRQ. The interrupt handler reads
+// data from the queue and leaves the interrupt enabled until the read is
+// satisfied.
+
+static int
+ocb_read_method(AsyncRequest *async_request)
+{
+ OcbRequest *request = (OcbRequest*)async_request;
+ OcbQueue *queue = (OcbQueue*)(async_request->queue);
+ int rc;
+
+ if (request->bytes == 0) {
+ rc = -ASYNC_REQUEST_COMPLETE;
+ } else {
+ ssx_irq_enable(queue->irq);
+ rc = 0;
+ }
+ return rc;
+}
+
+
+// This is the internal 'run method' for writing through an OCB circular
+// queue. The run method simply enables the IRQ. The interrupt handler writes
+// data from the queue and leaves the interrupt enabled until the write is
+// satisfied.
+
+static int
+ocb_write_method(AsyncRequest *async_request)
+{
+ OcbRequest *request = (OcbRequest *)async_request;
+ OcbQueue *queue = (OcbQueue*)(async_request->queue);
+ int rc;
+
+ if (request->bytes == 0) {
+ rc = -ASYNC_REQUEST_COMPLETE;
+ } else {
+ ssx_irq_enable(queue->irq);
+ rc = 0;
+ }
+ return rc;
+}
+
+
+// The async error method for OCB
+//
+// Collect FFDC. The return of -1 will disable the channel associated with
+// the request.
+
+static int
+ocb_async_error_method(AsyncRequest *request)
+{
+ OcbQueue *queue = (OcbQueue*)(request->queue);
+ ocb_ffdc(queue->engine / 2);
+ return -1;
+}
+
+
+/// Create a request for an OCB circular queue
+///
+/// \param request An uninitialized or otherwise idle OcbRequest.
+///
+/// \param queue An async queue for an OCB circular buffer. The queue \a
+/// engine determines whether this is a read or write request.
+///
+/// \param data A pointer to the data to be moved (for write) or where the
+/// data should be placed (for read).
+///
+/// \param bytes The number of bytes of data to move. The OCB
+/// circular buffers always move multiples of 8 bytes, and the number of bytes
+/// must be a multiple of 8. Higher-level abstractions will have to take care
+/// of cases where the numbers of bytes are not multiples of 8.
+///
+/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
+/// will be governed by a private watchdog timer that will cancel a queued job
+/// or kill a running job if the hardware operation does not complete before
+/// it times out.
+///
+/// \param callback The callback to execute when the data move completes, or
+/// NULL (0) to indicate no callback.
+///
+/// \param arg The parameter to the callback routine; ignored if the \a
+/// callback is NULL.
+///
+/// \param options Options to control request priority, callback context and
+/// blocking.
+///
+/// This routine has no way to know if the OcbRequest structure is currently
+/// in use, so this API should only be called on uninitialized or otherwise
+/// idle OcbRequest structures.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_OCB_REQUEST The \a request or \a queue were NULL (0), or
+/// the \a queue is not an initialized OcbQueue.
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_OCB_REQUEST The \a data pointer is
+/// NULL (0), or the number of bytes is not a multiple of 8.
+///
+/// See async_request_create() for other errors that may be returned by this
+/// call.
+
+int
+ocb_request_create(OcbRequest *request,
+ OcbQueue *queue,
+ uint64_t *data,
+ size_t bytes,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options)
+{
+ int rc;
+ AsyncRunMethod run_method = 0; // Make GCC Happy
+ AsyncQueue *async_queue = (AsyncQueue *)queue;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((request == 0) ||
+ (queue == 0) ||
+ !(async_queue->engine & ASYNC_ENGINE_OCB),
+ ASYNC_INVALID_OBJECT_OCB_REQUEST);
+ SSX_ERROR_IF((data == 0) ||
+ (bytes % 8),
+ ASYNC_INVALID_ARGUMENT_OCB_REQUEST);
+ }
+
+ switch (async_queue->engine) {
+
+ case ASYNC_ENGINE_OCB_PULL0:
+ case ASYNC_ENGINE_OCB_PULL1:
+ case ASYNC_ENGINE_OCB_PULL2:
+ run_method = ocb_write_method;
+ break;
+
+ case ASYNC_ENGINE_OCB_PUSH0:
+ case ASYNC_ENGINE_OCB_PUSH1:
+ case ASYNC_ENGINE_OCB_PUSH2:
+ run_method = ocb_read_method;
+ break;
+ }
+
+ rc = async_request_create(&(request->request),
+ async_queue,
+ run_method,
+ ocb_async_error_method,
+ timeout,
+ callback,
+ arg,
+ options);
+
+ request->data = data;
+ request->bytes = bytes;
+
+ return rc;
+}
+
+
+/// Schedule a request on an OCB circular queue.
+///
+/// \param request An initialized OcbRequest
+///
+/// Note : As long as the OcbRequest is idle, the application is free to
+/// directly change the \a data and \a bytes fields to read/write different
+/// numbers of bytes to/from different locations the next time the request is
+/// scheduled.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE The number of \a bytes
+/// currently requested is not a multiple of 8.
+///
+/// See async_request_schedule() for documentation of other errors
+
+int
+ocb_request_schedule(OcbRequest *request)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((request->bytes % 8), ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE);
+ }
+
+ request->current = request->data;
+ request->remaining = request->bytes;
+
+ return async_request_schedule((AsyncRequest *)request);
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// OcbQueue
+////////////////////////////////////////////////////////////////////////////
+
+/// Reset an OCB circular PUSH (read) queue
+///
+/// This API is normally used during initialization, and assumes that all of
+/// the parameters are valid. It resets and reprograms the hardware
+/// associated with an OCB circular buffer to be consistent with the queue
+/// engine, base address, length and interrupt protocol. The queue is enabled
+/// and its interrupts are disabled. Any data in the queue will be silently
+/// lost.
+///
+/// Note that this API \e does \e not put the OCB channel into circular mode -
+/// the communication method is controlled by the communication partner.
+///
+/// The function of this routine is to write a new value into the OCB Stream
+/// Push Control/Status register, which as a side effect resets the circular
+/// buffer. The base register is also set up.
+
+void
+ocb_read_engine_reset(OcbQueue *queue, size_t cq_length, int protocol)
+{
+ ocb_ocbshcsn_t cs;
+
+ // Disable interrupts and disable and clear the queue. The queue length
+ // field is updated (for informational purposes). Interrupts will be
+ // re-enabled when requests are made for the queue.
+
+ ssx_irq_disable(queue->irq);
+
+ queue->cq_length = cq_length;
+
+ cs.value = 0;
+ out32(G_ocb_ocbsxcsn[queue->engine], cs.value);
+
+
+ // Reinitialize the data buffer base address register
+
+ out32(G_ocb_ocbsxbrn[queue->engine], (uint32_t)(queue->cq_base));
+
+
+ // Reprogram and reenable/reset the queue
+
+ if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) {
+ cs.fields.push_intr_action = OCB_INTR_ACTION_FULL;
+ } else {
+ cs.fields.push_intr_action = OCB_INTR_ACTION_NOT_EMPTY;
+ }
+
+ cs.fields.push_length = cq_length - 1;
+ cs.fields.push_enable = 1;
+
+ out32(G_ocb_ocbsxcsn[queue->engine], cs.value);
+}
+
+
+/// Reset an OCB circular PULL (write) queue
+///
+/// This API is normally used during initialization, and assumes that all of
+/// the parameters are valid. It resets and reprograms the hardware
+/// associated with an OCB circular buffer to be consistent with the queue
+/// engine, base address, length and interrupt protocol. The queue is enabled
+/// and its interrupts are disabled. Any data in the queue will be silently
+/// lost.
+///
+/// Note that this API \e does \e not put the OCB channel into circular mode -
+/// the communication method is controlled by the communication partner.
+///
+/// The function of this routine is to write a new value into the OCB Stream
+/// Pull Control/Status register, which as a side effect resets the circular
+/// buffer. The base register is also set up.
+
+void
+ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol)
+{
+ ocb_ocbslcsn_t cs;
+
+ // Disable interrupts and disable and clear the queue. The queue length
+ // field is updated (for informational purposes). Interrupts will be
+ // re-enabled when requests are made for the queue.
+
+ ssx_irq_disable(queue->irq);
+
+ queue->cq_length = cq_length;
+
+ cs.value = 0;
+ out32(G_ocb_ocbsxcsn[queue->engine], cs.value);
+
+
+ // Reinitialize the data buffer base address register
+
+ out32(G_ocb_ocbsxbrn[queue->engine], (uint32_t)(queue->cq_base));
+
+
+ // Reprogram and reenable/reset the queue
+
+ if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) {
+ cs.fields.pull_intr_action = OCB_INTR_ACTION_EMPTY;
+ } else {
+ cs.fields.pull_intr_action = OCB_INTR_ACTION_NOT_FULL;
+ }
+
+ cs.fields.pull_length = cq_length - 1;
+ cs.fields.pull_enable = 1;
+
+ out32(G_ocb_ocbsxcsn[queue->engine], cs.value);
+}
+
+
+/// Create (initialize) an OcbQueue
+///
+/// \param queue An uninitialized or otherwise idle OcbQueue
+///
+/// \param engine A valid OCB engine id
+///
+/// \param cq_base The base address of the circular queue data area for the
+/// queue. This address must be 8-byte aligned for write queues. Read queues
+/// must be cache-line aligned and a multiple of the cache line in size.
+///
+/// \param cq_length The length of the circular queue measured in 8-byte
+/// increments.
+///
+/// \param protocol The interrupt protocol, either OCB_PUSH_PULL_PROTOCOL_LAZY
+/// or OCB_PUSH_PULL_PROTOCOL_AGGRESSIVE. Lazy means that read queues only
+/// interrupt when empty, and write queues only interrupt when full.
+/// Agressive means that read queues interrupt when not empty and write queues
+/// interrupt when not full. In general the lazy read protocol will only work
+/// for 1) queues of length 1, where lazy == aggressive, and 2) protocols
+/// where a known fixed number of 8-byte entries is always expected to be
+/// received.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_OCB_QUEUE The \a queue was NULL (0).
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \a cq_base is not properly
+/// aligned, or the \a cq_length is invalid, or the \a protocol is invalid.
+///
+/// \retval -ASYNC_INVALID_ENGINE_OCB The \a engine is not an OCB engine.
+///
+/// Other errors may be returned by async_queue_create().
+
+int
+ocb_queue_create(OcbQueue *queue,
+ int engine,
+ uint64_t *cq_base,
+ size_t cq_length,
+ int protocol)
+{
+ AsyncQueue *async_queue = (AsyncQueue *)queue;
+ int align_mask = 0;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_OCB_QUEUE);
+ SSX_ERROR_IF((cq_length < OCB_PUSH_PULL_LENGTH_MIN) ||
+ (cq_length > OCB_PUSH_PULL_LENGTH_MAX) ||
+ ((protocol != OCB_INTERRUPT_PROTOCOL_LAZY) &&
+ (protocol != OCB_INTERRUPT_PROTOCOL_AGGRESSIVE)),
+ ASYNC_INVALID_ARGUMENT_OCB_QUEUE);
+ }
+
+ queue->cq_base = cq_base;
+ queue->cq_length = cq_length;
+
+ switch (engine) {
+
+ // These are the read engines from OCC's perspective.
+
+ case ASYNC_ENGINE_OCB_PUSH0:
+ queue->irq = PGP_IRQ_STRM0_PUSH;
+ queue->engine = OCB_ENGINE_PUSH0;
+ goto read_engine;
+
+ case ASYNC_ENGINE_OCB_PUSH1:
+ queue->irq = PGP_IRQ_STRM1_PUSH;
+ queue->engine = OCB_ENGINE_PUSH1;
+ goto read_engine;
+
+ case ASYNC_ENGINE_OCB_PUSH2:
+ queue->irq = PGP_IRQ_STRM2_PUSH;
+ queue->engine = OCB_ENGINE_PUSH2;
+ goto read_engine;
+
+ read_engine:
+ align_mask = CACHE_LINE_SIZE - 1;
+ async_queue_create(async_queue, engine);
+ ocb_read_engine_reset(queue, cq_length, protocol);
+ break;
+
+ // These are the write engines from OCC's perspective.
+
+ case ASYNC_ENGINE_OCB_PULL0:
+ queue->irq = PGP_IRQ_STRM0_PULL;
+ queue->engine = OCB_ENGINE_PULL0;
+ goto write_engine;
+
+ case ASYNC_ENGINE_OCB_PULL1:
+ queue->irq = PGP_IRQ_STRM1_PULL;
+ queue->engine = OCB_ENGINE_PULL1;
+ goto write_engine;
+
+ case ASYNC_ENGINE_OCB_PULL2:
+ queue->irq = PGP_IRQ_STRM2_PULL;
+ queue->engine = OCB_ENGINE_PULL2;
+ goto write_engine;
+
+ write_engine:
+ align_mask = 8 - 1;
+ async_queue_create(async_queue, engine);
+ ocb_write_engine_reset(queue, cq_length, protocol);
+ break;
+
+ default:
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_OCB);
+ }
+ }
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(((uint32_t)cq_base & align_mask) != 0,
+ ASYNC_INVALID_ARGUMENT_OCB_QUEUE2);
+ }
+
+ return 0;
+}
+
+
+// The interrupt handler for asynchronous OCB CQ requests
+//
+// The circular buffer interupts are level sensitive, active high. There is
+// really no way to 'clear' them as they indicate a permanent status - so
+// instead they need to be enabled and disabled. Interrupts are enabled by the
+// run methods and disabled by the interrupt handlers once all data has been
+// transferred (or in the event of an error).
+//
+// This interrupt handler can process up to 256 bytes at once, plus the
+// overhead of scheduling the next job when this one completes. If interrupt
+// latency becomes a problem then this process could be run with interrupt
+// preemption enabled.
+
+SSX_IRQ_FAST2FULL(ocb_async_handler, ocb_async_handler_full);
+
+void
+ocb_async_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ AsyncQueue *async_queue = (AsyncQueue*)arg;
+ OcbQueue *queue = (OcbQueue*)async_queue;
+ OcbRequest *request = (OcbRequest*)(async_queue->current);
+ size_t processed;
+ int rc;
+
+ if (SSX_ERROR_CHECK_KERNEL && (request == 0)) {
+ SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_OCB);
+ }
+
+ if (queue->engine % 2) {
+ rc = ocb_write(queue, request->current, request->remaining, &processed);
+ } else {
+ rc = ocb_read(queue, request->current, request->remaining, &processed);
+ }
+
+ if (rc) {
+
+ ssx_irq_disable(queue->irq);
+ async_error_handler(async_queue, ASYNC_REQUEST_STATE_FAILED);
+
+ } else if (processed == request->remaining) {
+
+ ssx_irq_disable(queue->irq);
+ async_handler(async_queue);
+
+ } else {
+
+ request->current += (processed / 8);
+ request->remaining -= processed;
+ }
+}
+
+
+// The interrupt handler for the OCB error interrupt.
+//
+// There is one interrupt that covers all OCB indirect channels as well as the
+// direct bridge. When this interrupt fires we try to determine which unit is
+// responsible. If the error appears to be associated with a job running as
+// part of the async mechanism then we let the async_error_handler() mechanism
+// operate, otherwise simply collect FFDC. The \a error field of the FFDC
+// structure stops non-queued read/write requests. Note that we kill both read
+// and write jobs without regard to the error.
+//
+// If the error is due to the direct bridge we collect FFDC, but can't really
+// do anything else.
+
+/// \todo What action to take for bridge errors?
+
+
+SSX_IRQ_FAST2FULL(ocb_error_handler, ocb_error_handler_full);
+
+void
+ocb_error_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ ocb_occlfir_t fir;
+ int channel;
+ AsyncQueue* queue;
+
+ ssx_irq_status_clear(irq);
+
+ getscom(OCB_OCCLFIR, &(fir.value));
+
+ for (channel = 0; channel < OCB_INDIRECT_CHANNELS; channel++) {
+ if (fir.value & (OCB_OCCLFIR_OCB_IDC0_ERROR >> channel)) {
+
+ queue = (AsyncQueue*)(&(G_ocb_read_queue[channel]));
+ if (queue->state == ASYNC_QUEUE_STATE_RUNNING) {
+ async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED);
+ } else {
+ ocb_ffdc(channel);
+ }
+
+ queue = (AsyncQueue*)(&(G_ocb_write_queue[channel]));
+ if (queue->state == ASYNC_QUEUE_STATE_RUNNING) {
+ async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED);
+ } else {
+ ocb_ffdc(channel);
+ }
+ }
+ }
+
+ if (fir.fields.ocb_db_oci_timeout |
+ fir.fields.ocb_db_oci_read_data_parity |
+ fir.fields.ocb_db_oci_slave_error |
+ fir.fields.ocb_pib_addr_parity_err |
+ fir.fields.ocb_db_pib_data_parity_err) {
+
+ ocb_ffdc(-1);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Initialization
+////////////////////////////////////////////////////////////////////////////
+
+void
+async_ocb_initialize(OcbQueue *queue, int engine,
+ uint64_t *buffer, size_t length, int protocol)
+{
+ ocb_queue_create(queue, engine, buffer, length, protocol);
+ async_level_handler_setup(ocb_async_handler,
+ (void *)queue,
+ queue->irq,
+ SSX_NONCRITICAL,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH);
+ // Driver manages IRQ enable/disable
+}
diff --git a/src/ssx/pgp/pgp_async_pba.c b/src/ssx/pgp/pgp_async_pba.c
new file mode 100755
index 0000000..14b5619
--- /dev/null
+++ b/src/ssx/pgp/pgp_async_pba.c
@@ -0,0 +1,1201 @@
+// $Id: pgp_async_pba.c,v 1.2 2014/02/03 01:30:34 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async_pba.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_async_pba.c
+/// \brief Async device drivers for the PBA block copy engines and PBAX
+
+#include "ssx.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Global Data
+////////////////////////////////////////////////////////////////////////////
+
+BceQueue G_pba_bcue_queue;
+BceQueue G_pba_bcde_queue;
+
+PbaxQueue G_pbax_read_queue[PBAX_QUEUES];
+
+
+////////////////////////////////////////////////////////////////////////////
+// Local Data
+////////////////////////////////////////////////////////////////////////////
+
+
+/// Combined FFDC for all PBA subunits
+static PbaUnitFfdc G_pba_ffdc = {{{{{0}}}}};
+
+
+PBAX_CQ_READ_BUFFER(G_pbax_read0_buffer, PBAX_READ0_LENGTH);
+PBAX_CQ_READ_BUFFER(G_pbax_read1_buffer, PBAX_READ1_LENGTH);
+
+// The generic driver code stores an engine-specfic engine ID in the
+// queue. Here arrays are set up that contain the OCI control register
+// addresses for an engine indexed by the queue-specific value.
+//
+/// \todo Once the designers actually define register addresses, see about
+/// modifying these tables to be macros instead.
+///
+/// \todo Actually, why don't we just store this data directly in the queue?
+
+/// PBA BCDE/BCUE PowerBus BAR[0..31]
+static const SsxAddress G_bce_pbadr[BCE_ENGINES] =
+ {PBA_BCDE_PBADR, PBA_BCUE_PBADR};
+
+/// PBA BCDE/BCUE OCI BAR
+static const SsxAddress G_bce_ocibar[BCE_ENGINES] =
+ {PBA_BCDE_OCIBAR, PBA_BCUE_OCIBAR};
+
+/// PBA BCDE/BCUE SET register
+static const SsxAddress G_bce_set[BCE_ENGINES] =
+ {PBA_BCDE_SET, PBA_BCUE_SET};
+
+/// PBA BCDE/BCUE Control register
+static const SsxAddress G_bce_ctl[BCE_ENGINES] =
+ {PBA_BCDE_CTL, PBA_BCUE_CTL};
+
+/// PBA BCDE/BCUE Status register
+static const SsxAddress G_bce_stat[BCE_ENGINES] =
+ {PBA_BCDE_STAT, PBA_BCUE_STAT};
+
+/// PBAX Push Queue Control/Status Register addresses
+static const SsxAddress G_pba_xshcsn[PBAX_ENGINES] =
+ {PBA_XSHCS0, PBA_XSHCS1};
+
+/// PBAX Push Queue Base Register addresses
+static const SsxAddress G_pba_xshbrn[PBAX_ENGINES] =
+ {PBA_XSHBR0, PBA_XSHBR1};
+
+/// PBAX Push Queue Increment Register addresses
+static const SsxAddress G_pba_xshincn[PBAX_ENGINES] =
+ {PBA_XSHINC0, PBA_XSHINC1};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PBA FFDC Structures
+////////////////////////////////////////////////////////////////////////////
+
+// NB: Collection of FFDC for PBA will be very time consuming due to the large
+// amount of information required to fully diagnose any problem. This will be
+// done in a critical interrupt so it may have some impact on micro-timescale
+// realtime operations.
+
+// Collect PBA common FFDC
+//
+// Most of this is just collection of all of the setup registers required to
+// diagnose problems with the bridge and block copy engines. Not all of this
+// data is required for PBAX errors but we collect it anyway.
+//
+// FFDC is only collected for the first error, until the error flag is reset.
+
+static void
+pba_common_ffdc(PbaCommonFfdc* ffdc)
+{
+ int i;
+
+ if (ffdc->error == 0) {
+
+ oci_ffdc(&(ffdc->oci_ffdc), OCI_MASTER_ID_PBA);
+
+ ffdc->mode.value = in64(PBA_MODE);
+
+ for (i = 0; i < PBA_READ_BUFFERS; i++) {
+ getscom(PBA_RBUFVALN(i), &(ffdc->rbufval[i].value));
+ }
+
+ for (i = 0; i < PBA_WRITE_BUFFERS; i++) {
+ getscom(PBA_WBUFVALN(i), &(ffdc->wbufval[i].value));
+ }
+
+ for (i = 0; i < PBA_BARS; i++) {
+ getscom(PBA_BARN(i), &(ffdc->bar[i].value));
+ getscom(PBA_BARMSKN(i), &(ffdc->barmsk[i].value));
+ }
+
+ getscom(PBA_FIR, &(ffdc->fir.value));
+ getscom(PBA_ERRPT0, &(ffdc->errpt0.value));
+ getscom(PBA_ERRPT1, &(ffdc->errpt1.value));
+ getscom(PBA_ERRPT2, &(ffdc->errpt2.value));
+
+ ffdc->error = 1;
+ }
+}
+
+
+// Collect FFDC for generic PBA bridge errors
+//
+// This extends the common collection with PBA slave control/status
+// information.
+
+static void
+pba_bridge_ffdc(PbaBridgeFfdc* ffdc)
+{
+ int i;
+
+ if (ffdc->common.error == 0) {
+
+ pba_common_ffdc(&(ffdc->common));
+
+ ffdc->slvrst.value = in64(PBA_SLVRST);
+
+ for (i = 0; i > PBA_SLAVES; i++) {
+ ffdc->slvctl[i].value = in64(PBA_SLVCTLN(i));
+ }
+ }
+}
+
+
+// Collect FFDC for a particular Block Copy Engine
+//
+// The engine ID here is either 0 (BCDE) or 1 (BCUE)
+
+static void
+bce_ffdc(BceFfdc* ffdc, int engine)
+{
+ if (ffdc->common.error == 0) {
+
+ pba_common_ffdc(&(ffdc->common));
+
+ ffdc->ctl.value = in64(G_bce_ctl[engine]);
+ ffdc->set.value = in64(G_bce_set[engine]);
+ ffdc->pbadr.value = in64(G_bce_pbadr[engine]);
+ ffdc->stat.value = in64(G_bce_stat[engine]);
+ }
+}
+
+
+// Collect FFDC for PBAX send
+
+static void
+pbax_send_ffdc(PbaxSendFfdc* ffdc)
+{
+ if (ffdc->common.error == 0) {
+
+ pba_common_ffdc(&(ffdc->common));
+
+ ffdc->xcfg.value = in64(PBA_XCFG);
+ ffdc->xsndtx.value = in64(PBA_XSNDTX);
+ ffdc->xsndstat.value = in64(PBA_XSNDSTAT);
+ }
+}
+
+
+// Collect FFDC for PBAX receive
+//
+// The drivers currently do not distinguish errors between the two receive
+// queues as the hardware design does not provide a clean separation.
+
+static void
+pbax_receive_ffdc(PbaxReceiveFfdc* ffdc)
+{
+ int i;
+
+ if (ffdc->common.error == 0) {
+
+ pba_common_ffdc(&(ffdc->common));
+
+ ffdc->xcfg.value = in64(PBA_XCFG);
+ ffdc->xrcvstat.value = in64(PBA_XRCVSTAT);
+
+ for (i = 0; i < PBAX_ENGINES; i++) {
+ ffdc->xshbrn[i].value = in64(PBA_XSHBRN(i));
+ ffdc->xshcsn[i].value = in64(PBA_XSHCSN(i));
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// BceRequest
+////////////////////////////////////////////////////////////////////////////
+
+// Start a request running on a PBA Block Copy Engine
+//
+// \param queue A BceQueue upcast to an AsyncQueue
+//
+// \param request A BceRequest upcast to an AsyncRequest
+//
+// This routine takes a Bce objects cast to Async objects so that it can be
+// called from the generic Async interrupt handler.
+//
+// This is an internal API. This routine must be called from a context where
+// critical interrupts are disabled. Prior to this call, scheduling code will
+// have installed the new request as the \a current request of the queue, and
+// marked both the queue and the request as running.
+//
+// The PBA driver handles requests that require multiple runs of the PBA to
+// complete the request. Starting a PBA job requires setting up 3 registers,
+// hitting the "go" bit, and computing the amount of work remaining.
+//
+// Note that PBA will signal an error and lock up the system if the START bit
+// is written while a BC-engine is running.
+
+// Recall that the engines have identical control structures with identical
+// relative offsets between registers. So we use BCDE offsets and BCDE
+// register layout structures, but they work for BCUE as well.
+
+static int
+bce_async_run_method(AsyncRequest *async_request)
+{
+ BceQueue *queue = (BceQueue *)(async_request->queue);
+ BceRequest *request = (BceRequest *)async_request;
+ int rc, engine;
+ pba_bcde_pbadr_t pbadr;
+ pba_bcde_set_t set;
+ pba_bcde_ctl_t ctl;
+ size_t to_write;
+
+
+ if (request->remaining == 0) {
+
+ rc = -ASYNC_REQUEST_COMPLETE;
+
+ } else {
+
+ to_write = MIN(request->remaining, PBA_BCE_SIZE_MAX);
+
+ // Create the address offset register. The PowerBus offset is the
+ // cache-line address of the stored offset (ex the OCI region bits).
+
+ pbadr.value = 0;
+
+ pbadr.fields.pb_offset =
+ (request->next_bridge_address & 0x3FFFFFFF) /
+ POWERBUS_CACHE_LINE_SIZE;
+
+ pbadr.fields.extaddr =
+ request->extended_address.fields.extended_address;
+
+ // Create the setup register
+
+ set.value = 0;
+
+ set.fields.copy_length = to_write / POWERBUS_CACHE_LINE_SIZE;
+
+ // Set the START bit
+
+ ctl.value = PBA_BCDE_CTL_START;
+
+ // Start the BCE
+
+ engine = queue->engine;
+ out64(G_bce_pbadr[engine], pbadr.value);
+ out32(G_bce_ocibar[engine], request->next_oci_address);
+ out32(G_bce_set[engine], set.words.high_order);
+ out32(G_bce_ctl[engine], ctl.words.high_order);
+
+ // Update the work remaining to be done.
+
+ request->remaining -= to_write;
+ if (request->remaining != 0) {
+ request->next_bridge_address += to_write;
+ request->next_oci_address += to_write;
+ }
+
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+// The async error method for Block Copy Engines
+//
+// Collect FFDC and stop the engine. The return of -1 will disable the
+// channel associated with the request. The application will need to decide
+// whether to restart the queue.
+
+static int
+bce_async_error_method(AsyncRequest *request)
+{
+ BceQueue *queue = (BceQueue*)(request->queue);
+ int engine = queue->engine;
+
+ if (engine == BCE_ENGINE_BCDE) {
+
+ bce_ffdc(&(G_pba_ffdc.bcde), engine);
+ out32(PBA_BCDE_CTL, PBA_BCDE_CTL_STOP >> 32);
+
+ } else {
+
+ bce_ffdc(&(G_pba_ffdc.bcue), engine);
+ out32(PBA_BCUE_CTL, PBA_BCUE_CTL_STOP >> 32);
+
+ }
+
+ return -1;
+}
+
+
+/// Create a request for a PBA Block Copy engine
+///
+/// \param request An uninitialized or otherwise idle BceRequest.
+///
+/// \param queue An initialized BceQueue.
+///
+/// \param bridge_address The 32-bit bridge address that is translated to
+/// a PowerBus address associated with the copy. This address must be a
+/// PowerBus cache (128-byte) aligned address.
+///
+/// \param oci_address The 32-bit OCI address associated with the copy. This
+/// address must be 128-byte aligned.
+///
+/// \param bytes The number of bytes to move. This must be a multiple of 128,
+/// and the size must not obviously overflow the OCI address or the bridge
+/// address.
+///
+/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
+/// will be governed by a private watchdog timer that will cancel a queued job
+/// or kill a running job if the hardware operation does not complete before
+/// it times out.
+///
+/// \param callback The callback to execute when the PBA copy completes, or
+/// NULL (0) to indicate no callback.
+///
+/// \param arg The parameter to the callback routine; ignored if the \a
+/// callback is NULL.
+///
+/// \param options Options to control request priority and callback context.
+///
+/// Note that the setup for the BC engines includes an extended address and a
+/// PowerBus maximum priority. This API sets these to
+/// the default values in the request. If non-default values are required,
+/// they will need to be installed in the structure explicitly before
+/// scheduling.
+///
+/// This routine has no way to know if the BceRequest structure is currently
+/// in use, so this API should only be called on uninitialized or otherwise
+/// idle GpeRequest structures.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_BCE_REQUEST The \a request was NULL (0),
+/// or the \a queue was NULL (0) or not a BceQueue.
+///
+/// See async_request_create() for other errors that may be returned by this
+/// call.
+
+int
+bce_request_create(BceRequest *request,
+ BceQueue *queue,
+ uint32_t bridge_address,
+ uint32_t oci_address,
+ size_t bytes,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options)
+{
+ int rc;
+ AsyncQueue *async_queue = (AsyncQueue *)queue;
+
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((request == 0) ||
+ (queue == 0) ||
+ !(async_queue->engine & ASYNC_ENGINE_BCE),
+ ASYNC_INVALID_OBJECT_BCE_REQUEST);
+ }
+
+ rc = async_request_create(&(request->request),
+ async_queue,
+ bce_async_run_method,
+ bce_async_error_method,
+ timeout,
+ callback,
+ arg,
+ options);
+
+ request->bridge_address = bridge_address;
+ request->oci_address = oci_address;
+ request->bytes = bytes;
+ request->extended_address.value = 0;
+
+ return rc;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// BceQueue
+////////////////////////////////////////////////////////////////////////////
+
+/// Create (initialize) a BceQueue
+///
+/// \param queue An uninitialized of otherwise idle BceQueue
+///
+/// \param engine Either ASYNC_ENGINE_PBA_BCDE or ASYNC_ENGINE_PBA_BCUE
+///
+/// This API initializes the BceQueue structure based on the engine
+/// provided. There is really no special hardware initialization required as
+/// the BC-engines are pretty simple data movers.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_BCE_QUEUE The \a queue was NULL (0).
+///
+/// \retval -ASYNC_INVALID_ENGINE_BCE The \a engine is not a PBA engine.
+
+int
+bce_queue_create(BceQueue *queue,
+ int engine)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_BCE_QUEUE);
+ }
+
+ switch (engine) {
+
+ case ASYNC_ENGINE_BCDE:
+ async_queue_create(&(queue->queue), engine);
+ queue->engine = BCE_ENGINE_BCDE;
+ break;
+
+ case ASYNC_ENGINE_BCUE:
+ async_queue_create(&(queue->queue), engine);
+ queue->engine = BCE_ENGINE_BCUE;
+ break;
+
+ default:
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR(ASYNC_INVALID_ENGINE_BCE);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+/// Schedule a request on a PBA block-copy engine
+///
+/// Note : As long as the BceRequest is idle, the application is free to
+/// directly change the \a bridge_address, \a oci_address and \a bytes fields to
+/// read/write different numbers of bytes to/from different locations the next
+/// time the request is scheduled.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE Either the \a bridge_address
+/// is not 128-byte aligned, or the OCI address is not 128-byte aligned, or the
+/// number of bytes is not a multiple of 128.
+///
+/// See async_request_schedule() for documentation of other errors
+
+int
+bce_request_schedule(BceRequest *request)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((request->bridge_address % POWERBUS_CACHE_LINE_SIZE) ||
+ (request->oci_address % POWERBUS_CACHE_LINE_SIZE) ||
+ (request->bytes % POWERBUS_CACHE_LINE_SIZE),
+ ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE);
+ }
+
+ request->next_bridge_address = request->bridge_address;
+ request->next_oci_address = request->oci_address;
+ request->remaining = request->bytes;
+
+ return async_request_schedule((AsyncRequest *)request);
+}
+
+
+// The interrupt handler for asynchronous PBA Block Copy requests
+//
+// BC-engine 'done' interrupts are level-sensitive active high, so they need
+// to be cleared in the PBA by writing a 0 to the CTL register. We also get
+// the PBA 'done' even when jobs are killed, but the cancel/kill code is
+// responsible for setting the \a completion_state of the request.
+//
+// We only go to the generic handler once all data has been transferred.
+
+SSX_IRQ_FAST2FULL(bce_async_handler, bce_async_handler_full);
+
+void
+bce_async_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ AsyncQueue *async_queue = (AsyncQueue *)arg;
+ AsyncRequest *async_current = (AsyncRequest *)async_queue->current;
+ BceQueue *queue = (BceQueue *)async_queue;
+
+ out32(G_bce_ctl[queue->engine], 0);
+
+ if (SSX_ERROR_CHECK_KERNEL && (async_current == 0)) {
+ SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_BCE);
+ }
+
+ if (async_current->run_method(async_current) == -ASYNC_REQUEST_COMPLETE) {
+ async_handler(async_queue);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PbaxRequest
+////////////////////////////////////////////////////////////////////////////
+
+/// Non-blocking read from a PBAX PUSH (read) queue
+///
+/// \param queue The target PbaxQueue
+///
+/// \param buf The caller's data buffer to receive the read data
+///
+/// \param bytes The maximum number of bytes to read. This value should be an
+/// even multiple of 8, as this API always reads multiples of 8 bytes.
+///
+/// \param read The number of bytes actually copied from the device buffer to
+/// the caller's buffer. This may be returned as any value from 0 to \a
+/// bytes in multiples of 8 bytes.
+///
+/// pbax_read() implements a non-blocking copy of data from a PBAX read (PUSH)
+/// queue data area to the caller's data area, with the side effect of
+/// advancing the hardware queue pointers. pbax_read() does not implement
+/// locking, critical sections or any other type of synchronization for access
+/// to the PBAX queue data.
+///
+/// pbax_read() returns the error code -ASYNC_PBAX_ERROR_OLD or
+/// -ASYNC_PBAX_ERROR_NEW if PBAX receive error status is asserted.
+/// The error return code may be disjoint from the actual
+/// read: If data is available it may be copied to the caller's buffer, but
+/// this data should always be considered corrupted in the event of an error
+/// return code.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_READ The number of \a bytes is not
+/// an even multiple of 8.
+///
+/// \retval -ASYNC_PBAX_ERROR_OLD The PBA shows pre-existing error status
+///
+/// \retval -ASYNC_PBAX_ERROR_NEW The PBA shows current error status
+///
+/// \todo Once the HW design is finalized, we might consider modifying the
+/// error behavior to only return an error status if the receive error was
+/// associated with this particular queue.
+
+int
+pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read)
+{
+ pba_xshcsn_t csr;
+ pba_xrcvstat_t rsr;
+ unsigned qlen, read_ptr, write_ptr, to_read;
+ uint64_t *pcq, *pbuf;
+ int rc;
+
+ do {
+
+ rc = 0;
+ *read = 0;
+
+ // If pre-existing errors exist then immediately abort the read.
+
+ rsr.words.high_order = in32(PBA_XRCVSTAT);
+ if (rsr.fields.rcv_error) {
+ pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive));
+ rc = -ASYNC_PBAX_ERROR_OLD;
+ break;
+ }
+
+ if (bytes % 8) {
+ rc = -ASYNC_INVALID_ARGUMENT_PBAX_READ;
+ break;
+ }
+
+ // Determine the number of doubleword entries remaining to be read in
+ // the queue. The driver does not keep state, but instead reinterprets
+ // the control/status register each time the read method is called.
+
+ // This may be confusing - remember that 'push' is from the PowerBus
+ // perspective - here we use 'read' from OCC's perspective.
+
+ csr.words.high_order = in32(G_pba_xshcsn[queue->engine]);
+
+ qlen = csr.fields.push_length + 1;
+ read_ptr = csr.fields.push_read_ptr;
+
+ if (csr.fields.push_empty) {
+ break;
+
+ } else if (csr.fields.push_full) {
+ to_read = qlen;
+
+ } else {
+ write_ptr = csr.fields.push_write_ptr;
+ if (read_ptr > write_ptr) {
+ to_read = qlen - (read_ptr - write_ptr);
+ } else {
+ to_read = write_ptr - read_ptr;
+ }
+ }
+
+ // Copy the data from the CQ memory area. For simplicty of dealing with
+ // cache management each doubleword invokes a line invalidate before
+ // refetching the fresh data from memory. Alignment requirements enforced
+ // on the data buffer guarantee the buffers are cache-line aligned and
+ // each doubleword is fully contained in a single D-cache line.
+ //
+ // Here the code models the evolution of the read_ptr as each datum is
+ // copied from the queue.
+
+ pbuf = (uint64_t*) buf;
+ while (bytes && to_read--) {
+
+ read_ptr++;
+ if (read_ptr == qlen) {
+ read_ptr = 0;
+ }
+ pcq = queue->cq_base + read_ptr;
+
+ dcache_invalidate_line(pcq);
+ *pbuf++ = *pcq;
+ out32(G_pba_xshincn[queue->engine], 0);
+
+ bytes -= 8;
+ *read += 8;
+ }
+ } while(0);
+
+ // Check for errors that occurred during the read
+
+ rsr.words.high_order = in32(PBA_XRCVSTAT);
+ if (rsr.fields.rcv_error) {
+ pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive));
+ rc = -ASYNC_PBAX_ERROR_NEW;
+ }
+
+ return rc;
+}
+
+
+// This is the internal 'run method' for reading through a PBAX circular
+// queue. The run method simply enables the IRQ. The interrupt handler reads
+// data from the queue and leaves the interrupt enabled until the read is
+// satisfied.
+
+int
+pbax_read_method(AsyncRequest *async_request)
+{
+ PbaxRequest *request = (PbaxRequest*)async_request;
+ PbaxQueue *queue = (PbaxQueue*)(async_request->queue);
+ int rc;
+
+ if (request->bytes == 0) {
+ rc = -ASYNC_REQUEST_COMPLETE;
+ } else {
+ ssx_irq_enable(queue->irq);
+ rc = 0;
+ }
+ return rc;
+}
+
+
+// The async error method for PBAX
+//
+// Collect FFDC.
+
+static int
+pbax_async_error_method(AsyncRequest *request)
+{
+ pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive));
+ return -1;
+}
+
+
+/// Create a request for a PBAX read queue
+///
+/// \param request An uninitialized or otherwise idle PbaxRequest.
+///
+/// \param queue An async queue for a PBAX read buffer.
+///
+/// \param data A pointer to the data to where the data should be placed.
+///
+/// \param bytes The (maximum) number of bytes of data to move. The PBAX read
+/// queues always move multiples of 8 bytes, and the number of bytes must be a
+/// multiple of 8. Higher-level abstractions will have to take care of cases
+/// where the "actual" numbers of bytes are not multiples of 8.
+///
+/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
+/// will be governed by a private watchdog timer that will cancel a queued job
+/// or kill a running job if the hardware operation does not complete before
+/// it times out.
+///
+/// \param callback The callback to execute when the read completes, or
+/// NULL (0) to indicate no callback.
+///
+/// \param arg The parameter to the callback routine; ignored if the \a
+/// callback is NULL.
+///
+/// \param options Options to control request priority, callback context and
+/// blocking. See the documentation for the PbaxRequest object for information
+/// on the special ASYNC_NONBLOCKING_READ option.
+///
+/// This routine has no way to know if the PbaxRequest structure is currently
+/// in use, so this API should only be called on uninitialized or otherwise
+/// idle PbaxRequest structures.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_PBAX_REQUEST The \a request or \a queue
+/// were NULL (0), or the \a queue is not an initialized PbaxQueue.
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_REQUEST The \a data pointer is
+/// NULL (0), or the number of bytes is not a multiple of 8.
+///
+/// See async_request_create() for other errors that may be returned by this
+/// call.
+
+int
+pbax_request_create(PbaxRequest* request,
+ PbaxQueue* queue,
+ uint64_t* data,
+ size_t bytes,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void* arg,
+ int options)
+{
+ int rc;
+ AsyncQueue* async_queue = (AsyncQueue*)queue;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((request == 0) ||
+ (queue == 0) ||
+ !(async_queue->engine & ASYNC_ENGINE_PBAX),
+ ASYNC_INVALID_OBJECT_PBAX_REQUEST);
+ SSX_ERROR_IF((data == 0) ||
+ (bytes % 8),
+ ASYNC_INVALID_ARGUMENT_PBAX_REQUEST);
+ }
+
+ rc = async_request_create(&(request->request),
+ async_queue,
+ pbax_read_method,
+ pbax_async_error_method,
+ timeout,
+ callback,
+ arg,
+ options);
+
+ request->data = data;
+ request->bytes = bytes;
+
+ return rc;
+}
+
+
+/// Schedule a request on a PBAX read queue
+///
+/// Note : As long as the PbaxRequest is idle, the application is free to
+/// directly change the \a data and \a bytes fields to read different numbers of
+/// bytes into different locations the next time the request is scheduled.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE The number of \a bytes
+/// currently requested is not a multiple of 8.
+///
+/// See async_request_schedule() for documentation of other errors
+
+int
+pbax_request_schedule(PbaxRequest *request)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((request->bytes % 8),ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE);
+ }
+
+ request->current = request->data;
+ request->remaining = request->bytes;
+
+ return async_request_schedule((AsyncRequest *)request);
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PbaxQueue
+////////////////////////////////////////////////////////////////////////////
+
+/// Disable a PBAX circular PUSH (read) queue
+///
+/// \param queue An initialized PbaxQueue object.
+///
+/// Disable the PBAX recieve mechanism for a particular PBAX receive queue.
+/// Interrupts are disabled, and any data managed by the queue is effectively
+/// lost.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0)
+/// or otherwise invalid.
+
+int
+pbax_queue_disable(PbaxQueue *queue)
+{
+ pba_xshcsn_t cs;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PBAX_DISABLE);
+ }
+
+ ssx_irq_disable(queue->irq);
+
+ cs.value = 0;
+ out32(G_pba_xshcsn[queue->engine], cs.value);
+
+ return 0;
+}
+
+
+/// Enable a PBAX circular PUSH (read) queue
+///
+/// \param queue An initialized PbaxQueue object.
+///
+/// This API reprograms the queue hardware in accordance with the values
+/// present in the \a queue structure, and enables the queue to accept data.
+/// Any previous record of data present in the queue will be lost. The queue
+/// interrupt is also disabled by this API.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0)
+/// or otherwise invalid.
+
+int
+pbax_queue_enable(PbaxQueue *queue)
+{
+ int rc;
+ pba_xshcsn_t cs;
+
+ rc = pbax_queue_disable(queue);
+
+ if (!rc) {
+
+ // Reinitialize the data buffer base address register and
+ // reprogram/re-enable the queue.
+
+ out32(G_pba_xshbrn[queue->engine], (uint32_t)(queue->cq_base));
+
+ cs.value = 0;
+
+ if (queue->protocol == PBAX_INTERRUPT_PROTOCOL_LAZY) {
+ cs.fields.push_intr_action = PBAX_INTR_ACTION_FULL;
+ } else {
+ cs.fields.push_intr_action = PBAX_INTR_ACTION_NOT_EMPTY;
+ }
+
+ cs.fields.push_length = queue->cq_entries - 1;
+ cs.fields.push_enable = 1;
+
+ out32(G_pba_xshcsn[queue->engine], cs.words.high_order);
+ }
+ return 0;
+}
+
+
+/// Create (initialize) a PbaxQueue abstraction
+///
+/// \param queue An uninitialized or otherwise idle PbaxQueue
+///
+/// \param engine A valid PBAX engine id
+///
+/// \param cq_base The base address of the circular queue data area for the
+/// queue. This address must be aligned to the next higher power-of-two of the
+/// buffer size, with a minimum alignment of a cache line.
+///
+/// \param cq_entries The number of 8-byte entries in the queue
+///
+/// \param protocol The interrupt protocol, either PBAX_PUSH_PROTOCOL_LAZY or
+/// PBAX_PUSH_PROTOCOL_AGGRESSIVE. Lazy means that read queues only interrupt
+/// when full, and agressive means that read queues interrupt whenever they
+/// are not empty. In general the lazy read protocol will only work for 1)
+/// queues of length 1, where lazy == aggressive, and 2) protocols where a
+/// known fixed number of 8-byte entries is always expected to be received.
+///
+/// This API simply creates the PbaxQueue abstraction in the software space;
+/// The API does not modify any harwdare state. To enable/disable the PBAX
+/// hardware read queue use pbax_queue_enable().
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_PBAX_QUEUE The \a queue was NULL (0).
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_QUEUE The \a cq_base is not properly
+/// aligned, or the \a cq_length is invalid, or the \a protocol is invalid.
+///
+/// \retval -ASYNC_INVALID_ENGINE_PBAX The \a engine is not an PBAX engine.
+///
+/// Other errors may be returned by async_queue_create().
+
+int
+pbax_queue_create(PbaxQueue *queue,
+ int engine,
+ uint64_t *cq_base,
+ size_t cq_entries,
+ int protocol)
+{
+ AsyncQueue *async_queue = (AsyncQueue *)queue;
+
+ if (SSX_ERROR_CHECK_API) {
+ uint32_t align_mask =
+ POW2_32(MAX(CEILING_LOG2(cq_entries * 8),
+ LOG_CACHE_LINE_SIZE)) - 1;
+
+ SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PBAX_QUEUE);
+ SSX_ERROR_IF((((uint32_t)(cq_base) & align_mask) != 0) ||
+ (cq_entries < PBAX_PUSH_LENGTH_MIN) ||
+ (cq_entries > PBAX_PUSH_LENGTH_MAX) ||
+ ((protocol != PBAX_INTERRUPT_PROTOCOL_LAZY) &&
+ (protocol != PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE)),
+ ASYNC_INVALID_ARGUMENT_PBAX_QUEUE);
+ }
+
+ queue->cq_base = cq_base;
+ queue->cq_entries = cq_entries;
+ queue->protocol = protocol;
+
+ switch (engine) {
+
+ case ASYNC_ENGINE_PBAX_PUSH0:
+ queue->irq = PGP_IRQ_PBA_OCC_PUSH0;
+ queue->engine = PBAX_ENGINE_PUSH0;
+ break;
+
+ case ASYNC_ENGINE_PBAX_PUSH1:
+ queue->irq = PGP_IRQ_PBA_OCC_PUSH1;
+ queue->engine = PBAX_ENGINE_PUSH1;
+ break;
+
+ default:
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_PBAX);
+ }
+ }
+
+ async_queue_create(async_queue, engine);
+
+ return 0;
+}
+
+
+// The interrupt handler for asynchronous PBAX requests
+//
+// The circular buffer interupts are level sensitive, active high. There is
+// really no way to 'clear' them as they indicate a permanent status - so
+// instead they need to be enabled and disabled. This is done by the read
+// method. (Note that one could make them edge-triggered, but in general
+// device drivers [including this one] would not work correctly if they were
+// programmed that way.)
+//
+// This interrupt handler can process up to 256 bytes at once, plus the
+// overhead of scheduling the next job when this one completes. If interrupt
+// latency becomes a problem then this process could be run with interrupt
+// preemption enabled.
+
+SSX_IRQ_FAST2FULL(pbax_async_handler, pbax_async_handler_full);
+
+void
+pbax_async_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ AsyncQueue* async_queue = (AsyncQueue*)arg;
+ PbaxQueue* queue = (PbaxQueue*)async_queue;
+ PbaxRequest* request = (PbaxRequest*)(async_queue->current);
+ size_t read;
+ int rc;
+
+ if (SSX_ERROR_CHECK_KERNEL && (request == 0)) {
+ SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_PBAX);
+ }
+
+ rc = pbax_read(queue, request->current, request->remaining, &read);
+
+ if (rc) {
+
+ ssx_irq_disable(queue->irq);
+ async_error_handler(async_queue, ASYNC_REQUEST_STATE_FAILED);
+
+ } else if (read == request->remaining) {
+
+ ssx_irq_disable(queue->irq);
+ async_handler(async_queue);
+
+ } else {
+
+ request->current += (read / 8);
+ request->remaining -= read;
+ }
+}
+
+
+// The interrupt handler for the PBA error interrupt.
+//
+// There is one error interrupt that covers all PBA function - the generic
+// bridge, block copy engines and PBAX buffers. The PBA error pulses whenever
+// new error bits are logged in the PBA FIR, so it is possible for OCC to log
+// errors independently for the bridge, BCE and PBAX.
+//
+// When the PBA error interrupt fires we try to determine which unit is
+// responsible for the error and take appropriate action. The analysis is
+// currently not very deep, however it is not clear whether it is worth the
+// time and code space required to do more than this.
+//
+// - If the error appears to be associated with either a BCDE or BCUE job
+// running as part of the async mechanism then we let the
+// async_error_handler() mechanism operate. As a side effect the indicated
+// queue will be disabled. Note that further analysis (and storage space)
+// might allow jobs to be restarted on that engine, but this is currently not
+// done.
+//
+// - If the error appears to be associated with a PBAX send then the PBAX send
+// mechanism is already effectively disabled by the fact that the send status
+// register shows an error. FFDC is simply collected in this case.
+//
+// - If the error appears to be associated with a PBAX receive mechanism then
+// both receive queues are stopped. The receive may or may not be using the
+// job queues (the application may be polling using pbax_read()).
+//
+// If the error is due to the direct bridge we collect FFDC, but can't really
+// do anything else. Since OCC will not use the PBA bridge at run time
+// (except for lab-mode applications) this error is due either to a PORE
+// engine or FSP using the dedicated trusted channel to mainstore.
+//
+// This code is assumed to be activated as a critical interrupt.
+
+/// \todo What to do for generic PBA errors?
+
+SSX_IRQ_FAST2FULL(pba_error_handler, pba_error_handler_full);
+
+void
+pba_error_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ pba_fir_t fir;
+ pba_bcde_stat_t bcde_stat;
+ pba_bcue_stat_t bcue_stat;
+ pba_xsndstat_t xsndstat;
+ pba_xrcvstat_t xrcvstat;
+ int channel;
+ AsyncQueue* queue;
+
+ ssx_irq_status_clear(irq);
+
+ getscom(PBA_FIR, &(fir.value));
+ bcde_stat.words.high_order = in32(PBA_BCDE_STAT);
+ bcue_stat.words.high_order = in32(PBA_BCUE_STAT);
+ xsndstat.words.high_order = in32(PBA_XSNDSTAT);
+ xrcvstat.words.high_order = in32(PBA_XRCVSTAT);
+
+ queue = (AsyncQueue*)(&G_pba_bcde_queue);
+ if (bcde_stat.fields.error &&
+ (queue->state == ASYNC_QUEUE_STATE_RUNNING)) {
+ async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED);
+ }
+
+ queue = (AsyncQueue*)(&G_pba_bcue_queue);
+ if (bcue_stat.fields.error &&
+ (queue->state == ASYNC_QUEUE_STATE_RUNNING)) {
+ async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED);
+ }
+
+ if (xsndstat.fields.snd_error) {
+ pbax_send_ffdc(&G_pba_ffdc.pbax_send);
+ }
+
+ if (xrcvstat.fields.rcv_error) {
+ for (channel = 0; channel < PBAX_CHANNELS; channel++) {
+ queue = (AsyncQueue*)(&G_pbax_read_queue[channel]);
+ if (queue->state == ASYNC_REQUEST_STATE_RUNNING) {
+ async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED);
+ } else {
+ pbax_receive_ffdc(&G_pba_ffdc.pbax_receive);
+ }
+ }
+ }
+
+ // Any FIR bits not already attributable to previously handled errors are
+ // assumed to be due to the generic bridge.
+
+ if (fir.value &
+ (
+ PBA_FIR_OCI_APAR_ERR ||
+ PBA_FIR_PB_RDADRERR_FW ||
+ PBA_FIR_PB_RDDATATO_FW ||
+ PBA_FIR_PB_SUE_FW ||
+ PBA_FIR_PB_UE_FW ||
+ PBA_FIR_PB_CE_FW ||
+ PBA_FIR_OCI_SLAVE_INIT ||
+ PBA_FIR_OCI_WRPAR_ERR ||
+ PBA_FIR_OCI_REREQTO ||
+ PBA_FIR_PB_UNEXPCRESP ||
+ PBA_FIR_PB_UNEXPDATA ||
+ PBA_FIR_PB_PARITY_ERR ||
+ PBA_FIR_PB_WRADRERR_FW ||
+ PBA_FIR_PB_BADCRESP ||
+ PBA_FIR_PB_ACKDEAD_FW ||
+ PBA_FIR_PB_CRESPTO ||
+ // PBA_FIR_BCUE_SETUP_ERR ||
+ // PBA_FIR_BCUE_PB_ACK_DEAD ||
+ // PBA_FIR_BCUE_PB_ADRERR ||
+ // PBA_FIR_BCUE_OCI_DATAERR ||
+ // PBA_FIR_BCDE_SETUP_ERR ||
+ // PBA_FIR_BCDE_PB_ACK_DEAD ||
+ // PBA_FIR_BCDE_PB_ADRERR ||
+ // PBA_FIR_BCDE_RDDATATO_ERR ||
+ // PBA_FIR_BCDE_SUE_ERR ||
+ // PBA_FIR_BCDE_UE_ERR ||
+ // PBA_FIR_BCDE_CE ||
+ // PBA_FIR_BCDE_OCI_DATAERR ||
+ PBA_FIR_INTERNAL_ERR ||
+ PBA_FIR_ILLEGAL_CACHE_OP ||
+ PBA_FIR_OCI_BAD_REG_ADDR ||
+ // PBA_FIR_AXPUSH_WRERR ||
+ // PBA_FIR_AXRCV_DLO_ERR ||
+ // PBA_FIR_AXRCV_DLO_TO ||
+ // PBA_FIR_AXRCV_RSVDATA_TO ||
+ // PBA_FIR_AXFLOW_ERR ||
+ // PBA_FIR_AXSND_DHI_RTYTO ||
+ // PBA_FIR_AXSND_DLO_RTYTO ||
+ // PBA_FIR_AXSND_RSVTO ||
+ // PBA_FIR_AXSND_RSVERR ||
+ PBA_FIR_FIR_PARITY_ERR ||
+ PBA_FIR_FIR_PARITY_ERR2
+ )
+ ) {
+
+ pba_bridge_ffdc(&(G_pba_ffdc.bridge));
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Initialization
+////////////////////////////////////////////////////////////////////////////
+
+void
+async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq)
+{
+ bce_queue_create(queue, engine);
+ async_level_handler_setup(bce_async_handler,
+ (void *)queue,
+ irq,
+ SSX_CRITICAL,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH);
+ ssx_irq_enable(irq);
+}
+
+
+void
+async_pbax_initialize(PbaxQueue *queue, int engine, SsxIrqId irq,
+ uint64_t *buffer, size_t length, int protocol)
+{
+ pbax_queue_create(queue, engine, buffer, length, protocol);
+ pbax_queue_enable(queue);
+ async_level_handler_setup(pbax_async_handler,
+ (void *)queue,
+ irq,
+ SSX_NONCRITICAL,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH);
+ // Driver or application manages IRQ enable/disable
+}
+
+
diff --git a/src/ssx/pgp/pgp_async_pore.c b/src/ssx/pgp/pgp_async_pore.c
new file mode 100755
index 0000000..5f9b425
--- /dev/null
+++ b/src/ssx/pgp/pgp_async_pore.c
@@ -0,0 +1,644 @@
+// $Id: pgp_async_pore.c,v 1.5 2014/05/14 13:35:43 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async_pore.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_async_pore.c
+/// \brief PgP "async" drivers for PORE engines
+
+#include "ssx.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Global Data
+////////////////////////////////////////////////////////////////////////////
+
+// The PORE queue objects.
+
+PoreQueue G_pore_gpe0_queue;
+PoreQueue G_pore_gpe1_queue;
+PoreQueue G_pore_slw_queue;
+
+
+////////////////////////////////////////////////////////////////////////////
+// Local Data
+////////////////////////////////////////////////////////////////////////////
+
+/// PoreFlex entry point - See G_pore_flex_table.
+
+static uint32_t G_pore_flex_entry0 = PORE_BRAD_D0;
+
+
+/// Entry 0 of the PoreFlex branch table
+///
+/// This variable is the only thing we represent of the branch table for PORE
+/// flex requests. PoreFlex requests are forbidden from using PORE error
+/// handlers. Therefore they don't require the 60 redundant bytes of error
+/// handler entry points. They also only run trigger slot 0, and begin
+/// execution with a BRAD D0, so the only thing we represent is a single BRAD
+/// D0 instruction.
+
+static uint32_t* G_pore_flex_table = &G_pore_flex_entry0 - (PORE_ERROR_SLOTS * 3);
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreQueue
+////////////////////////////////////////////////////////////////////////////
+
+/// Create (initialize) a PoreQueue
+///
+/// \param queue An uninitialized of otherwise idle PoreQueue
+///
+/// \param engine The identifier of a PORE engine associated with this queue.
+///
+/// This API initializes the PoreQueue structure and also initializes the
+/// underlying PORE hardware to run in the OCC environment. Neither the
+/// branch table nor the error modes are specified here - those are considered
+/// application-specific functions that are set up each time a job is run on
+/// the engine.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_PORE_QUEUE The \a queue was NULL (0).
+///
+/// \retval -ASYNC_INVALID_ENGINE_PORE The \a engine is not a (valid)
+/// PORE engine.
+
+int
+pore_queue_create(PoreQueue *queue, int engine)
+{
+ pore_control_t control;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PORE_QUEUE);
+ SSX_ERROR_IF(!(engine & ASYNC_ENGINE_PORE), ASYNC_INVALID_ENGINE_PORE);
+ }
+
+ async_queue_create(&(queue->queue), engine);
+
+ switch (engine) {
+
+ case ASYNC_ENGINE_PORE_GPE0:
+ queue->oci_base = PORE_GPE0_OCI_BASE;
+ queue->irq = PGP_IRQ_PORE_GPE0_COMPLETE;
+ queue->error_irq = PGP_IRQ_PORE_GPE0_ERROR;
+ queue->oci_master = OCI_MASTER_ID_PORE_GPE;
+ break;
+
+ case ASYNC_ENGINE_PORE_GPE1:
+ queue->oci_base = PORE_GPE1_OCI_BASE;
+ queue->irq = PGP_IRQ_PORE_GPE1_COMPLETE;
+ queue->error_irq = PGP_IRQ_PORE_GPE1_ERROR;
+ queue->oci_master = OCI_MASTER_ID_PORE_GPE;
+ break;
+
+ case ASYNC_ENGINE_PORE_SLW:
+ queue->oci_base = PORE_SLW_OCI_BASE;
+ queue->irq = PGP_IRQ_PORE_SW_COMPLETE;
+ queue->error_irq = PGP_IRQ_PORE_SW_ERROR;
+ queue->oci_master = OCI_MASTER_ID_PORE_SLW;
+ break;
+
+ default:
+ SSX_PANIC(ASYNC_BUG_PORE_AT_CREATE);
+ }
+
+ // PORE engine setup
+ //
+ // Force the PORE to stop and set it up for OCC control. Neither the
+ // breakpoint address nor the trap enable setting are modified in case
+ // they are being controlled from Simics or a hardware debugger ab initio.
+ //
+ // Register field settings:
+ //
+ // The scanclk ratio is not modified.
+ // The EXE-Trigger register is unlocked
+ // The freeze action is not modified
+ // Instruction parity is ignored
+ // The PIB parity checking setting is not modified
+ // The TRAP enable is not modified
+ // The breakpoint address is not modified
+
+ control.value = in64(queue->oci_base + PORE_CONTROL_OFFSET);
+
+ control.fields.start_stop = 1;
+ control.fields.lock_exe_trig= 0;
+ control.fields.check_parity = 0;
+
+ out64(queue->oci_base + PORE_CONTROL_OFFSET, control.value);
+
+ return 0;
+}
+
+
+// The interrupt handler for asynchronous PORE errors
+//
+// The PORE interrupts are disabled here, then cleared and re-enabled when the
+// next job runs. This is to protect against "phantom" interrupts caused by
+// PORE freeze-on-checkstop behavior.
+
+SSX_IRQ_FAST2FULL(pore_async_error_handler, pore_async_error_handler_full);
+
+void
+pore_async_error_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ PoreQueue* queue = (PoreQueue*)arg;
+
+ ssx_irq_disable(queue->irq);
+ ssx_irq_disable(queue->error_irq);
+
+ async_error_handler((AsyncQueue *)arg, ASYNC_REQUEST_STATE_FAILED);
+}
+
+
+// The interrupt handler for asynchronous PORE requests
+//
+// The PORE interrupts are disabled here, then cleared and re-enabled when the
+// next job runs. This is to protect against "phantom" interrupts caused by
+// PORE freeze-on-checkstop behavior.
+//
+// Note that if the system checkstops and freezes the PORE we will get a
+// normal completion interrupt. Therefore we have to check to see if the
+// completion is associated with a freeze, and if so, fail the job.
+
+SSX_IRQ_FAST2FULL(pore_async_handler, pore_async_handler_full);
+
+void
+pore_async_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ PoreQueue* queue = (PoreQueue*)arg;
+ pore_status_t status;
+
+ status.value = in64(queue->oci_base + PORE_STATUS_OFFSET);
+ if (status.fields.freeze_action) {
+
+ pore_async_error_handler_full(arg, irq, priority);
+
+ } else {
+
+ ssx_irq_disable(queue->irq);
+ ssx_irq_disable(queue->error_irq);
+
+ async_handler((AsyncQueue *)arg);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreRequest
+////////////////////////////////////////////////////////////////////////////
+
+/// Create (initialize) the PoreRequest base class
+///
+/// \param request An uninitialized or otherwise idle PoreRequest.
+///
+/// \param queue An initialized PoreQueue
+///
+/// \param table The PORE branch table to install prior to kicking off the
+/// engine. All PoreFlex jobs use a common (stubbed) table. PoreFixed jobs
+/// must supply a fully-formed table.
+///
+/// \param error_mask The initial value of the PORE ERROR_MASK register to be
+/// installed before kicking off the engine.
+///
+/// \param entry_point The entry point address of the routine. For PoreFlex
+/// this entry point will be non-0 and will be inserted into D0, as PoreFlex
+/// jobs are kicked off by BRAD D0. For PoreFixed this parameter will be zero
+/// and ignored.
+///
+/// \param start_vector The TBAR start vector to execute. This will always be
+/// 0 for PoreFlex.
+///
+/// \param parameter The single 32-bit parameter to the PORE program. This
+/// value is stored in the low-order part of the \c EXE_TRIGGER register
+/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
+/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
+/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
+///
+/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
+/// will be governed by a private watchdog timer that will cancel a queued job
+/// or kill a running job if the hardware operation does not complete before
+/// it times out.
+///
+/// \param callback The callback to execute when the PORE program completes,
+/// or NULL (0) to indicate no callback.
+///
+/// \param arg The parameter to the callback routine; ignored if the \a
+/// callback is NULL.
+///
+/// \param options Options to control request priority and callback context.
+///
+/// This routine has no way to know if the PoreRequest structure is currently
+/// in use, so this API should only be called on uninitialized or otherwise
+/// idle PoreRequest structures.
+///
+/// \retval 0 Success
+///
+/// \retval -ASYNC_INVALID_OBJECT_PORE_REQUEST The \a request was NULL (0)
+/// or the \a queue was NULL (0) or not a PoreQueue.
+///
+/// \retval -ASYNC_INVALID_ARGUMENT_PORE_REQUEST The \a start_vector is invalid or any of
+/// the parameters that represent OCI addresses are not 4-byte aligned, , or
+/// the \a table was null.
+///
+/// See async_request_create() for other errors that may be returned by this
+/// call.
+
+int
+pore_request_create(PoreRequest *request,
+ PoreQueue *queue,
+ PoreBraia* table,
+ uint32_t error_mask,
+ uint32_t entry_point,
+ int start_vector,
+ uint32_t parameter,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options)
+{
+ AsyncQueue *async_queue = (AsyncQueue *)queue;
+ int rc;
+ pore_exe_trigger_t etr;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(!(async_queue->engine & ASYNC_ENGINE_PORE),
+ ASYNC_INVALID_OBJECT_PORE_REQUEST);
+ SSX_ERROR_IF((start_vector < 0) ||
+ (start_vector >= PORE_TRIGGER_SLOTS) ||
+ ((uint32_t) table % 4) ||
+ (entry_point % 4) ||
+ (table == 0),
+ ASYNC_INVALID_ARGUMENT_PORE_REQUEST);
+ }
+
+ rc = async_request_create(&(request->request),
+ async_queue,
+ pore_run_method,
+ pore_error_method,
+ timeout,
+ callback,
+ arg,
+ options);
+
+ if (!rc) {
+ request->table = table;
+ request->error_mask = error_mask;
+ request->entry_point = entry_point;
+ request->parameter = parameter;
+ etr.value = 0;
+ etr.fields.start_vector = start_vector;
+ request->exe_trigger = etr.words.high_order;
+ }
+
+ return rc;
+}
+
+
+// Start a PoreRequest on a PORE
+//
+// \param async_request A PoreRequest upcast to an AsyncRequest.
+//
+// This is an internal API. At entry both the completion and error interrupts
+// are disabled and may show status that needs to be cleared before they are
+// re-enabled.
+//
+// This routine implements a simple procedure:
+//
+// - Check to make sure the PORE is not frozen due to a checkstop, and if so,
+// collect FFDC and immediately fail the job.
+//
+// Otherwise:
+//
+// - Reset the PORE engine to clear up any error status that may remain from
+// the last job .
+// - Install the TBAR (Table Base Address Register) from the request as an OCI
+// address
+// - Set the EMR (Error Mask Register) from the request
+// - Install the parameter (ETR[32:63])
+// - If the entry point is non-0 then this is a PoreFlex job that is kicked
+// off by a BRAD D0, and the entry point is installed in D0 as a full OCI
+// address.
+// - Clear pending interrupt status
+// - Hit ETR[0:31] to start the job.
+// - Enable interrupts.
+//
+// If the PORE is frozen due to a system checkstop we fail the job immediately
+// right here. Note that there is still a small window where the system may
+// checkstop and the PORE may freeze after this check. Unfortunately the PORE
+// design locks out register writes while frozen, and instead of reporting
+// write access attempts as bus errors, silently ignores them and simply sets
+// a FIR bit. Originally the "frozen" check was done last to shrink the
+// window, however this practically guarantees these FIRs in a checkstopped
+// system (which the FW team finds problematic), so the check was moved to the
+// front of the procedure. (SW256621).
+//
+// Note that PORE interrupts remain masked unless the job starts successfully.
+
+int
+pore_run_method(AsyncRequest *async_request)
+{
+ PoreQueue *queue = (PoreQueue*)(async_request->queue);
+ PoreRequest *request = (PoreRequest*)async_request;
+ pore_status_t status;
+ pore_reset_t reset;
+ uint32_t oci_base;
+ int rc;
+
+ oci_base = queue->oci_base;
+
+ status.value = in64(oci_base + PORE_STATUS_OFFSET);
+ if (status.fields.freeze_action) {
+
+ pore_error_method(async_request);
+ async_request->completion_state = ASYNC_REQUEST_STATE_FAILED;
+ rc = -ASYNC_REQUEST_COMPLETE;
+
+ } else {
+
+ reset.value = 0;
+ reset.fields.fn_reset = 1;
+ out32(oci_base + PORE_RESET_OFFSET, reset.value);
+
+ out32(oci_base + PORE_TABLE_BASE_ADDR_OFFSET, PORE_ADDRESS_SPACE_OCI);
+ out32(oci_base + PORE_TABLE_BASE_ADDR_OFFSET + 4,
+ (uint32_t)(request->table));
+ out32(oci_base + PORE_ERROR_MASK_OFFSET, request->error_mask);
+ out32(oci_base + PORE_EXE_TRIGGER_OFFSET + 4, request->parameter);
+
+ if (request->entry_point != 0) {
+ out32(oci_base + PORE_SCRATCH1_OFFSET, PORE_ADDRESS_SPACE_OCI);
+ out32(oci_base + PORE_SCRATCH1_OFFSET + 4, request->entry_point);
+ }
+
+ ssx_irq_status_clear(queue->irq);
+ ssx_irq_status_clear(queue->error_irq);
+
+ out32(oci_base + PORE_EXE_TRIGGER_OFFSET, request->exe_trigger);
+
+ ssx_irq_enable(queue->irq);
+ ssx_irq_enable(queue->error_irq);
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+// PORE FFDC collection
+//
+// \param async_request A PoreRequest upcast to an AsyncRequest
+//
+// This is an internal API, called from an interrupt context when a PORE
+// engine signals an error interrupt. See the comments for PoreFfdc for a
+// description of why this particular set of data is collected.
+//
+// PORE error handling procedure:
+//
+// - Collect FFDC from the PLB arbiter
+//
+// - Collect FFDC from the failing engine
+//
+// Currently all PORE errors are treated as recoverable
+
+/// \todo Consider analyzing the errors to determine if the error should be
+/// considered fatal.
+
+int
+pore_error_method(AsyncRequest *async_request)
+{
+ PoreQueue *queue = (PoreQueue*)(async_request->queue);
+ PoreRequest *request = (PoreRequest*)async_request;
+ uint32_t oci_base;
+ PoreFfdc* ffdc;
+
+ oci_base = queue->oci_base;
+ ffdc = &(request->ffdc);
+
+ oci_ffdc(&(ffdc->oci_ffdc), queue->oci_master);
+
+ ffdc->debug[0] = in64(oci_base + PORE_DBG0_OFFSET);
+ ffdc->debug[1] = in64(oci_base + PORE_DBG1_OFFSET);
+ ffdc->address[0] = in32(oci_base + PORE_OCI_BASE_ADDRESS0_OFFSET + 4);
+ ffdc->address[1] = in32(oci_base + PORE_OCI_BASE_ADDRESS1_OFFSET + 4);
+ ffdc->ibuf[0] = in32(oci_base + PORE_IBUF_01_OFFSET);
+ ffdc->ibuf[1] = in32(oci_base + PORE_IBUF_01_OFFSET + 4);
+ ffdc->ibuf[2] = in32(oci_base + PORE_IBUF_2_OFFSET);
+
+ return 0;
+}
+
+
+/// Create (initialize) a PoreBraia branch table entry
+///
+/// \param instr A pointer to the BRAIA instruction to initialize. Use the
+/// macros PORE_ERROR_BRANCH(table, n) and PORE_ENTRY_BRANCH(table, n) to
+/// select one of 5 error branches or one of 16 entry point branches in a PORE
+/// branch table.
+///
+/// \param address The 32-bit OCI address of the error routine or entry point.
+///
+/// This routine initializes the given entry of a PORE branch table with an
+/// OCI-based BRAIA instruction, them flushes the entry from the D-Cache.
+
+// Note that we don't know the alignment of the jump table, so we need to
+// flush both the first and last jump address to ensure that the BRAI is
+// completely flushed. This assumes (correctly) that uint32_t are at least
+// 4-byte aligned.
+
+void
+pore_braia_create(PoreBraia* instr, uint32_t address) {
+ instr->word[0] = PORE_BRAI;
+ instr->word[1] = PORE_ADDRESS_SPACE_OCI;
+ instr->word[2] = address;
+ dcache_flush_line(&(instr->word[0]));
+ dcache_flush_line(&(instr->word[2]));
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreFlex
+////////////////////////////////////////////////////////////////////////////
+
+/// Create (initialize) a flex-mode PORE request
+///
+/// \param request An uninitialized or otherwise idle PoreFlex.
+///
+/// \param queue A pointer to a PoreQueue
+///
+/// \param entry_point The entry point of the PORE program. This must be a
+/// 32-bit, 4-byte aligned byte address in OCI space. The PoreEntryPoint
+/// typedef is provided to declare external PORE entry points. Note that an \a
+/// entry_point of 0 is considered an error - although it \e is conceivably a
+/// legal OCI address in mainstore via the PBA.
+///
+/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
+/// will be governed by a private watchdog timer that will cancel a queued job
+/// or kill a running job if the hardware operation does not complete before
+/// it times out.
+///
+/// \param parameter The single 32-bit parameter to the PORE program. This
+/// value is stored in the high-order part of the \c EXE_TRIGGER register
+/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
+/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
+/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
+///
+/// \param callback The callback to execute when the PORE program completes,
+/// or NULL (0) to indicate no callback.
+///
+/// \param arg The parameter to the callback routine; ignored if the \a
+/// callback is NULL.
+///
+/// \param options Options to control request priority and callback context.
+///
+/// This routine has no way to know if the PoreFlex structure is currently
+/// in use, so this API should only be called on uninitialized or
+/// otherwise idle PoreFlex structures.
+///
+/// \retval 0 Success
+///
+/// See pore_request_create() for error return codes that may be returned by
+/// this call.
+
+int
+pore_flex_create(PoreFlex *request,
+ PoreQueue *queue,
+ PoreEntryPoint entry_point,
+ uint32_t parameter,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options)
+{
+ uint32_t emr;
+
+ // PoreFlex jobs run w/o error handlers, and ignore sleeping cores. All
+ // errors are signalled on both error outputs of all PORE engines.
+
+ emr = (PORE_ERROR_MASK_ENABLE_ERR_OUTPUT0 |
+ PORE_ERROR_MASK_ENABLE_ERR_OUTPUT1 |
+ PORE_ERROR_MASK_ENABLE_ERR_OUTPUT2 |
+ PORE_ERROR_MASK_ENABLE_ERR_OUTPUT3 |
+ PORE_ERROR_MASK_ENABLE_ERR_OUTPUT4 |
+ PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 |
+ PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT1 |
+ PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT2 |
+ PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT3 |
+ PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT4 |
+ PORE_ERROR_MASK_STOP_EXE_ON_ERROR0 |
+ PORE_ERROR_MASK_STOP_EXE_ON_ERROR1 |
+ PORE_ERROR_MASK_STOP_EXE_ON_ERROR2 |
+ PORE_ERROR_MASK_STOP_EXE_ON_ERROR3 |
+ PORE_ERROR_MASK_STOP_EXE_ON_ERROR4) >> 32;
+
+ return pore_request_create((PoreRequest*)request,
+ queue,
+ (PoreBraia*)G_pore_flex_table,
+ emr,
+ (uint32_t)entry_point,
+ 0,
+ parameter,
+ timeout,
+ callback,
+ arg,
+ options);
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreFixed
+////////////////////////////////////////////////////////////////////////////
+
+/// Create (initialize) a fixed-mode PORE request
+///
+/// \param request An uninitialized or otherwise idle PoreFixed request.
+///
+/// \param queue A PoreQueue capable of running fixed requests.
+///
+/// \param table A PORE branch table containing all of the error handler and
+/// entry point assignments required for the request.
+///
+/// \param error_mask A value that will be loaded into the high-order 32-bits
+/// of the PORE Error Mask Register to control error behavior.
+///
+/// \param start_vector The branch table slot reserved for this request.
+///
+/// \param parameter The single 32-bit parameter to the PORE program. This
+/// value is stored in the high-order part of the \c EXE_TRIGGER register
+/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
+/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
+/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
+///
+/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
+/// will be governed by a private watchdog timer that will cancel a queued job
+/// or kill a running job if the hardware operation does not complete before
+/// it times out.
+///
+/// \param callback The callback to execute when the PORE program completes,
+/// or NULL (0) to indicate no callback.
+///
+/// \param arg The parameter to the callback routine; ignored if the \a
+/// callback is NULL.
+///
+/// \param options Options to control request priority and callback context.
+///
+/// This routine has no way to know if the PoreFixed structure is currently
+/// in use, so this API should only be called on uninitialized or
+/// otherwise idle PoreFlex structures.
+///
+/// \retval 0 Success
+///
+/// See pore_request_create() for error return codes that may be returned by
+/// this call.
+
+int
+pore_fixed_create(PoreFixed *request,
+ PoreQueue *queue,
+ PoreBraia* table,
+ uint32_t error_mask,
+ int start_vector,
+ uint32_t parameter,
+ SsxInterval timeout,
+ AsyncRequestCallback callback,
+ void *arg,
+ int options)
+{
+ return pore_request_create((PoreRequest*)request,
+ queue,
+ table,
+ error_mask,
+ 0,
+ start_vector,
+ parameter,
+ timeout,
+ callback,
+ arg,
+ options);
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Initialization
+////////////////////////////////////////////////////////////////////////////
+
+// Due to the fact that PORE signals a "complete" interrupt on a freeze event
+// (i.e., a checkstop, even if PORE is not running), we can not enable PORE
+// interrupts globally. They need to be carefully managed to avoid "phantom
+// interrupt" panics from async_handler().
+
+void
+async_pore_initialize(PoreQueue *queue,int engine)
+{
+ pore_queue_create(queue, engine);
+ async_edge_handler_setup(pore_async_handler,
+ (void *)queue,
+ queue->irq, SSX_CRITICAL);
+ async_edge_handler_setup(pore_async_error_handler,
+ (void *)queue,
+ queue->error_irq, SSX_CRITICAL);
+}
+
+
+
diff --git a/src/ssx/pgp/pgp_cache.S b/src/ssx/pgp/pgp_cache.S
new file mode 100755
index 0000000..4208f59
--- /dev/null
+++ b/src/ssx/pgp/pgp_cache.S
@@ -0,0 +1,99 @@
+// $Id: pgp_cache.S,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_cache.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_cache.S
+/// \brief Cache-management specific to PGP
+
+#include "ssx.h"
+
+/// \fn void dcache_flush_all()
+/// \brief Flush the entire D-Cache by 0-filling and invalidating
+///
+/// This API is necessary whenever it is required to change data cacheability
+/// after boot. This API operates in an SSX_SUPERCRITICAL critical section.
+/// This API always issues a sync() after the flush.
+///
+/// This API runs with data translation disabled. This is necessary for
+/// correctness, and also obviates the need to check whether a cache entry is
+/// valid before flushing the entry.
+///
+/// This algorithm works by filling the cache with 0s to displace any dirty
+/// lines. Then the cache is invalidated. In PgP the first 16 KB of the
+/// 0x80000000 address range are used as the zero-fill range. This memory is
+/// not mapped on the OCI so these lines must never escape the D-cache.
+///
+/// Note: Our Simics model includes this 16K memory area since Simics does not
+/// default to having a cache. Since we run PgP with the MMU enabled and we
+/// don't MMU-map this area, memory addressing bugs should not be able to slip
+/// through.
+#ifdef DOXYGEN_ONLY
+void dcache_flush_all();
+#endif
+/// \cond
+
+ .global_function dcache_flush_all
+dcache_flush_all:
+
+ ## %r3 used as scratch throughout
+
+ ## %r11 holds the original DCCR throughout
+ ## %r12 holds the original MSR throughout
+
+ ## Enter a super-critical section and go to real mode
+
+ _ssx_critical_section_enter SSX_SUPERCRITICAL, %r12, %r3
+
+ mfmsr %r3
+ _clrbit %r3, %r3, MSR_DR_BIT
+ mtmsr %r3
+ isync
+
+ ## Save the DCCR, and make 0x80000000 cacheable. This is necessary for
+ ## DCBZ to work.
+
+ mfdccr %r11
+ _liwa %r3, PGP_FLUSH_ZERO_DCCR
+ or %r3, %r3, %r11
+ mtdccr %r3
+ isync
+
+ ## Fill the cache with 0, displacing any dirty lines
+
+ li %r3, DCACHE_LINES
+ mtctr %r3
+ _liwa %r3, PGP_FLUSH_ZERO_ADDRESS
+1:
+ dcbz %r0, %r3
+ addi %r3, %r3, CACHE_LINE_SIZE
+ bdnz 1b
+
+ sync
+
+ ## Now invalidate the cache
+
+ li %r3, DCACHE_LINES
+ mtctr %r3
+ _liwa %r3, PGP_FLUSH_ZERO_ADDRESS
+1:
+ dcbi %r0, %r3
+ addi %r3, %r3, CACHE_LINE_SIZE
+ bdnz 1b
+
+ ## Restore the DCCR and MSR and return
+
+ mtdccr %r11
+ isync
+
+ _ssx_critical_section_exit %r12
+
+ blr
+
+ .epilogue dcache_flush_all
+
+/// \endcond
+
diff --git a/src/ssx/pgp/pgp_centaur.c b/src/ssx/pgp/pgp_centaur.c
new file mode 100644
index 0000000..a47600a
--- /dev/null
+++ b/src/ssx/pgp/pgp_centaur.c
@@ -0,0 +1,597 @@
+// $Id: pgp_centaur.c,v 1.2 2013/12/13 23:01:15 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_centaur.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_centaur.c
+/// \brief Support for Centaur access and configuration from OCC.
+///
+/// Generic PBA generated PowerBus Address in pictures and words:
+///
+/// \code
+///
+/// 1 2 3 4 5 6
+/// 0123456789012345678901234567890123456789012345678901234567890123
+/// | | | | | | | | | | | | | | |
+///
+/// ..............B-------BX------------XO-----OA------------------A
+///
+/// .: Unused
+/// B: Direct from PBA BAR, bits 14:22
+/// X: If PBA BAR MASK 23:36 == 0, then PBA BAR 23:36
+/// Else Extended Address 0:13
+/// O: If PBA BAR MASK 37:43 == 0, then PBA BAR 37:43
+/// Else OCI Address 5:11
+/// A: OCI Address 12:31
+///
+/// \endcode
+///
+/// The OCI address always selects the low-order 20 bits of the PowerBus
+/// address, i.e., the window size is always a multiple of 1MB. The PBA BAR
+/// mask allows up to a 128MB window into main memory without using the
+/// extended address. The extended address allows OCC to address up to 2^41
+/// bytes by manipulating the extended address, assuming PHYP sets up the mask
+/// correctly.
+///
+///
+/// Centaur in-band SCOM, sensor cache and SYNC addressing in pictures and words:
+///
+/// \code
+///
+/// 1 2 3 4 5 6
+/// 0123456789012345678901234567890123456789012345678901234567890123
+/// | | | | | | | | | | | | | | |
+///
+/// ..............B-------BX------------XO-----OA------------------A - See Above
+/// ..............M-----------M10S------------------------------S000 - SCOM
+/// ..............M-----------M1100000000000000000000000000000000000 - Sensor cache
+/// ..............M-----------M1110000000000000000000000000000000000 - Sync
+///
+/// .: Unused
+/// M: The base address of the Centaur, taken from the MCS MCFGPR.
+/// O: 1 Signifies that this access comes from the OCC.
+/// S: The 32-bit SCOM address
+/// 0: Zero
+///
+/// \endcode
+///
+/// In order to access the Centaur for in-band SCOM, the PBA BAR MASK must
+/// extend at least from bit 29 down to bit 43, in order to allow the OCC to
+/// generate these addresses. In practice the mask must allow all configured
+/// Centaur to be accessed. This means that all Centaur in-band address bits
+/// not controllable by OCC through the mask must be equal.
+///
+/// Note that the SCOM address must be split between the extended address and
+/// the OCI address.
+///
+/// We assume (and verify) that MCMODE0(36) will always be set which means
+/// that bit 27 is a flag indicating whether an access comes from FSP or
+/// OCC. All OCC (GPE) accesses set this flag to 1.
+
+#include "ssx.h"
+#include "gpe_scom.h"
+
+#if defined(VERIFICATION) || defined(LAB_VALIDATION)
+#define PRINTD(...) printk(__VA_ARGS__)
+#else
+#define PRINTD(...)
+#endif
+
+CentaurConfiguration G_centaurConfiguration
+SECTION_ATTRIBUTE(".noncacheable_ro") = {.configRc = CENTAUR_NOT_CONFIGURED};
+
+const uint16_t _pgp_mcs_offset[PGP_NMCS] = {
+ 0x0800, 0x0880, 0x0900, 0x0980, 0x0c00, 0x0c80, 0x0d00, 0x0d80
+};
+
+
+// All GpeScomParms structures are required to be noncacheable, so we have to
+// allocate a static instance rather than using the stack. For simplicity the
+// single-entry scomList_t required to collect the Centaur device IDs is
+// allocated statically as well.
+
+static GpeScomParms S_parms SECTION_ATTRIBUTE(".noncacheable") = {0};
+static scomList_t S_scomList SECTION_ATTRIBUTE(".noncacheable") = {{{0}}};
+
+int
+_centaur_configuration_create(int i_bar, int i_slave, int i_setup)
+{
+ CentaurConfiguration config;
+ int i, designatedSync, diffInit;
+ int64_t rc; /* Must be copied to global struct. */
+ mcfgpr_t mcfgpr;
+ mcsmode0_t mcsmode0;
+ pba_slvctln_t slvctl;
+ uint64_t diffMask, addrAccum, bar, mask, base;
+ PoreFlex request;
+
+ // Start by clearing the local structure and setting the error flag.
+ memset(&config, 0, sizeof(config));
+ config.configRc = CENTAUR_NOT_CONFIGURED;
+
+ designatedSync = -1;
+
+ do {
+ // Basic consistency checks
+
+ if ((i_bar < 0) || (i_bar >= PBA_BARS) ||
+ (i_slave < 0) || (i_slave >= PBA_SLAVES)) {
+
+ rc = CENTAUR_INVALID_ARGUMENT;
+ break;
+ }
+
+
+ // Create the setups for the GPE procedures. The 'dataParms' are the
+ // setup for accessing the Centaur sensor cache. The 'scomParms' are
+ // the setup for accessing Centaur SCOMs.
+
+ rc = gpe_pba_parms_create(&(config.dataParms),
+ PBA_SLAVE_PORE_GPE,
+ PBA_WRITE_TTYPE_CI_PR_W,
+ PBA_WRITE_TTYPE_DC,
+ PBA_READ_TTYPE_CL_RD_NC);
+ if (rc) {
+ rc = CENTAUR_DATA_SETUP_ERROR;
+ break;
+ }
+
+ rc = gpe_pba_parms_create(&(config.scomParms),
+ PBA_SLAVE_PORE_GPE,
+ PBA_WRITE_TTYPE_CI_PR_W,
+ PBA_WRITE_TTYPE_DC,
+ PBA_READ_TTYPE_CI_PR_RD);
+ if (rc) {
+ rc = CENTAUR_SCOM_SETUP_ERROR;
+ break;
+ }
+
+
+ // Go into each MCS on the chip, and for all enabled MCS get a couple
+ // of SCOMs and check configuration items for correctness. If any of
+ // the Centaur are configured, exactly one of the MCS must be
+ // designated to receive the SYNC commands.
+
+ // Note that the code uniformly treats SCOM failures of the MCFGPR
+ // registers as an unconfigured Centaur. This works both for Murano,
+ // which only defines the final 4 MCS, as well as for our VBU models
+ // where some of the "valid" MCS are not in the simulation models.
+
+ for (i = 0; i < PGP_NCENTAUR; i++) {
+
+ rc = _getscom(MCS_ADDRESS(MCFGPR, i), &(mcfgpr.value),
+ SCOM_TIMEOUT);
+ if (rc) {
+ rc = 0;
+ config.baseAddress[i] = 0;
+ continue;
+ }
+
+ if (!mcfgpr.fields.mcfgprq_valid) continue;
+
+ rc = _getscom(MCS_ADDRESS(MCSMODE0, i), &(mcsmode0.value),
+ SCOM_TIMEOUT);
+ if (rc) {
+ PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n",
+ (uint32_t)rc, i);
+ rc = CENTAUR_MCSMODE0_SCOM_FAILURE;
+ break;
+ }
+
+
+ // We require that the MCFGRP_19_IS_HO_BIT be set in the mode
+ // register. We do not support the option of this bit not being
+ // set, and all of our procedures will set bit 19 of the PowerBus
+ // address to indicate that OCC is making the access.
+
+ if (!mcsmode0.fields.mcfgrp_19_is_ho_bit) {
+
+ PRINTD("MCSMODE0(%d).mcfgrp_19_is_ho_bit == 0\n", i);
+ rc = CENTAUR_MCSMODE0_19_FAILURE;
+ break;
+ }
+
+
+ // The 14-bit base-address is moved to begin at bit 14 in the
+ // 64-bit PowerBus address. The low-order bit of this address (bit
+ // 19 mentioned above which is bit 27 as an address bit) must be 0
+ // - otherwise there is confusion over who's controlling this
+ // bit.
+
+ config.baseAddress[i] =
+ ((uint64_t)(mcfgpr.fields.mcfgprq_base_address)) <<
+ (64 - 14 - 14);
+
+ if (config.baseAddress[i] & 0x0000001000000000ull) {
+
+ PRINTD("Centaur base address %d has bit 27 set\n", i);
+ rc = CENTAUR_ADDRESS_27_FAILURE;
+ break;
+ }
+
+
+ // If this MCS is configured to be the designated SYNC unit, it
+ // must be the only one.
+
+ if (mcsmode0.fields.enable_centaur_sync) {
+
+ if (designatedSync > 0) {
+
+ PRINTD("Both MCS %d and %d are designated "
+ "for Centaur Sync\n",
+ designatedSync, i);
+ rc = CENTAUR_MULTIPLE_DESIGNATED_SYNC;
+ break;
+
+ } else {
+
+ designatedSync = i;
+ }
+ }
+
+
+ // Add the Centaur to the configuration
+
+ config.config |= (CHIP_CONFIG_MCS(i) | CHIP_CONFIG_CENTAUR(i));
+ }
+
+ if (rc) break;
+
+
+ // If Centaur are configured, make sure at least one of the MCS will
+ // handle the SYNC. If so, convert its base address into an address
+ // for issuing SYNC commands by setting bits 27 (OCC) 28 and 29
+ // (Sync), then insert this address into the extended address field of
+ // a PBA slave control register image. gsc_scom_centaur() then merges
+ // this extended address into the PBA slave control register (which
+ // has been set up for Centaur SCOM) to do the SYNC.
+
+ // In the override mode (i_setup > 1) we tag the first valid MCS
+ // to recieve the sync if the firmware has not set it up correctly.
+
+ if (config.config) {
+
+ if (designatedSync < 0) {
+
+ if (i_setup <= 1) {
+
+ PRINTD("No MCS is designated for Centaur SYNC\n");
+ rc = CENTAUR_NO_DESIGNATED_SYNC;
+ break;
+
+ } else {
+
+ designatedSync =
+ cntlz32(left_justify_mcs_config(config.config));
+
+ rc = _getscom(MCS_ADDRESS(MCSMODE0, designatedSync),
+ &(mcsmode0.value),
+ SCOM_TIMEOUT);
+ if (rc) {
+ PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n",
+ (uint32_t)rc, designatedSync);
+ rc = CENTAUR_MCSMODE0_SCOM_FAILURE;
+ break;
+ }
+
+ mcsmode0.fields.enable_centaur_sync = 1;
+
+ rc = _putscom(MCS_ADDRESS(MCSMODE0, designatedSync),
+ mcsmode0.value,
+ SCOM_TIMEOUT);
+ if (rc) {
+ PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n",
+ (uint32_t)rc, designatedSync);
+ rc = CENTAUR_MCSMODE0_SCOM_FAILURE;
+ break;
+ }
+ }
+ }
+
+ base = config.baseAddress[designatedSync] | 0x0000001c00000000ull;
+
+ slvctl.value = 0;
+ slvctl.fields.extaddr = (base & 0x000001fff8000000ull) >> 27;
+
+ config.syncSlaveControl = slvctl.value;
+ }
+
+
+ // At this point we have one or more enabled MCS and they pass the
+ // initial configuration sniff test. We can now implement the option
+ // to configure the PBA BAR and BAR MASK correctly to allow access to
+ // these Centaur. We do this by computing the minimum BAR mask that
+ // covers all of the Centaur base addresses. This is done by
+ // accumulating a difference mask of the base addresses and finding
+ // the first set bit in the mask.
+ //
+ // Note that we do the configuration here on demand, but always do the
+ // correctness checking as the next step.
+
+ if (i_setup && (config.config != 0)) {
+
+ diffInit = 0;
+ diffMask = 0; /* GCC happiness */
+ addrAccum = 0; /* GCC happiness */
+
+ for (i = 0; i < PGP_NCENTAUR; i++) {
+
+ if (config.baseAddress[i] != 0) {
+
+ if (!diffInit) {
+
+ diffInit = 1;
+ diffMask = 0;
+ addrAccum = config.baseAddress[i];
+
+ } else {
+
+ diffMask |=
+ (config.baseAddress[i] ^ addrAccum);
+ addrAccum |= config.baseAddress[i];
+ }
+
+ if (0) {
+
+ // Debug
+
+ printk("i:%d baseAddress: 0x%016llx "
+ "diffMask: 0x%016llx, addrAccum: 0x%016llx\n",
+ i, config.baseAddress[i], diffMask, addrAccum);
+ }
+ }
+ }
+
+ // The mask must cover all differences - and must also have at
+ // least bit 27 set. The mask register contains only the mask. The
+ // BAR is set to the accumulated address outside of the mask. The
+ // BAR also contains a scope field which defaults to 0 (Nodal
+ // Scope) for Centaur inband access.
+
+ diffMask |= 0x0000001000000000ull;
+ mask =
+ ((1ull << (64 - cntlz64(diffMask))) - 1) &
+ PBA_BARMSKN_MASK_MASK;
+
+ rc = _putscom(PBA_BARMSKN(i_bar), mask, SCOM_TIMEOUT);
+ if (rc) {
+ PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n",
+ (uint32_t)rc, i_bar);
+ rc = CENTAUR_BARMSKN_PUTSCOM_FAILURE;
+ break;
+ }
+
+ rc = _putscom(PBA_BARN(i_bar), addrAccum & ~mask, SCOM_TIMEOUT);
+ if (rc) {
+ PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n",
+ (uint32_t)rc, i_bar);
+ rc = CENTAUR_BARN_PUTSCOM_FAILURE;
+ break;
+ }
+ }
+
+
+ // Do an independent check that every Centaur base address
+ // can be generated by the combination of the current BAR and
+ // BAR Mask, along with the initial requirement that the mask must
+ // include at least bits 27:43.
+
+ if (config.config != 0) {
+
+ rc = _getscom(PBA_BARN(i_bar), &bar, SCOM_TIMEOUT);
+ if (rc) {
+ PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n",
+ (uint32_t)rc, i_bar);
+ rc = CENTAUR_BARN_GETSCOM_FAILURE;
+ break;
+ }
+
+ rc = _getscom(PBA_BARMSKN(i_bar), &mask, SCOM_TIMEOUT);
+
+ if (rc) {
+ PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n",
+ (uint32_t)rc, i_bar);
+ rc = CENTAUR_BARMSKN_GETSCOM_FAILURE;
+ break;
+ }
+
+ bar = bar & PBA_BARN_ADDR_MASK;
+ mask = mask & PBA_BARMSKN_MASK_MASK;
+
+ if ((mask & 0x0000001ffff00000ull) != 0x0000001ffff00000ull) {
+
+ PRINTD("PBA BAR mask (%d) does not cover bits 27:43\n", i_bar);
+ rc = CENTAUR_MASK_ERROR;
+ break;
+ }
+
+ for (i = 0; i < PGP_NCENTAUR; i++) {
+
+ if (config.baseAddress[i] != 0) {
+
+ if ((config.baseAddress[i] & ~mask) !=
+ (bar & ~mask)) {
+
+ PRINTD("BAR/Mask (%d) error for MCS/Centaur %d\n"
+ " base = 0x%016llx\n"
+ " bar = 0x%016llx\n"
+ " mask = 0x%016llx\n",
+
+ i_bar, i, config.baseAddress[i], bar, mask);
+ rc = CENTAUR_BAR_MASK_ERROR;
+ break;
+ }
+ }
+ }
+
+ if (rc) break;
+ }
+
+
+ // At this point the structure is initialized well-enough that it can
+ // be used by gpe_scom_centaur(). We run gpe_scom_centaur() to collect
+ // the CFAM ids of the chips. Prior to this we copy our local copy
+ // into the global read-only data structure. (Note that GPE can DMA
+ // under the OCC TLB memory protection.) In order for
+ // gpe_scom_centaur() to run the global configuration must be valid
+ // (configRc == 0) - so we provisionally mark it valid (and will
+ // invalidate it later if errors occur here).
+
+ // Note however that if no Centaur are present then we're already
+ // done.
+
+ // It's assumed that this procedure is being run before threads have
+ // started, therefore we must poll for completion of the GPE program.
+ // Assuming no contention for GPE1 this procedure should take a few
+ // microseconds at most to complete.
+
+ if (0) {
+
+ // Debug for Simics - only enable MCS 5
+
+ config.baseAddress[0] =
+ config.baseAddress[1] =
+ config.baseAddress[2] =
+ config.baseAddress[3] =
+ config.baseAddress[4] =
+ config.baseAddress[6] =
+ config.baseAddress[7] = 0;
+ }
+
+
+ config.configRc = 0;
+ memcpy_real(&G_centaurConfiguration, &config, sizeof(config));
+
+ if (config.config == 0) break;
+
+ S_scomList.scom = CENTAUR_DEVICE_ID;
+ S_scomList.commandType = GPE_SCOM_READ_VECTOR;
+ S_scomList.pData = G_centaurConfiguration.deviceId;
+
+ S_parms.scomList = CAST_POINTER(uint64_t, &S_scomList);
+ S_parms.entries = 1;
+ S_parms.options = 0;
+
+ pore_flex_create(&request,
+ &G_pore_gpe1_queue,
+ gpe_scom_centaur,
+ (uint32_t)(&S_parms),
+ SSX_MILLISECONDS(10), /* Timeout */
+ 0, 0, 0);
+
+ rc = pore_flex_schedule(&request);
+
+ if (rc) break;
+
+ while (!async_request_is_idle((AsyncRequest*)(&request)));
+
+ if (!async_request_completed((AsyncRequest*)(&request)) ||
+ (S_parms.rc != 0)) {
+
+ PRINTD("gpe_scom_centaur() for CENTAUR_DEVICE_ID failed:\n"
+ " Async state = 0x%02x\n"
+ " gpe_scom_centaur() rc = %u\n"
+ " gpe_scom_centaur() errorIndex = %d\n",
+ ((AsyncRequest*)(&request))->state,
+ S_parms.rc, S_parms.errorIndex);
+
+ rc = CENTAUR_READ_TPC_ID_FAILURE;
+ }
+
+ if (0) {
+
+ // Debug
+
+ slvctl.value = G_gsc_lastSlaveControl;
+
+ PRINTD("centaur_configuration_create:Debug\n"
+ " Last SCOM (PowerBus) address = 0x%016llx\n"
+ " Last Slave Control = 0x%016llx\n"
+ " Extended Address (positioned) = 0x%016llx\n"
+ " Last OCI Address = 0x%016llx\n",
+ G_gsc_lastScomAddress,
+ G_gsc_lastSlaveControl,
+ (unsigned long long)(slvctl.fields.extaddr) <<
+ (64 - 23 - 14),
+ G_gsc_lastOciAddress);
+ }
+
+ } while (0);
+
+ // Copy the final RC into the global structure and done.
+
+ memcpy_real(&(G_centaurConfiguration.configRc), &rc, sizeof(rc));
+
+ return rc;
+}
+
+
+// For now we have to handle configuring the PBA BAR and mask, and designating
+// a SYNC if the firmware forgot to.
+
+int
+centaur_configuration_create(void)
+{
+ return _centaur_configuration_create(PBA_BAR_CENTAUR,
+ PBA_SLAVE_PORE_GPE,
+ 2);
+}
+
+
+uint32_t mb_id(int i_mb)
+{
+ uint32_t rv;
+ centaur_device_id_t id;
+
+ if ((i_mb < 0) || (i_mb >= PGP_NCENTAUR) ||
+ (G_centaurConfiguration.configRc != 0)) {
+
+ rv = (uint32_t)-1;
+
+ } else {
+
+ id.value = G_centaurConfiguration.deviceId[i_mb];
+ rv = id.fields.cfam_id;
+ }
+
+ return rv;
+}
+
+
+uint8_t mb_chip_type(int i_mb)
+{
+ uint8_t rv;
+ cfam_id_t id;
+
+ if ((id.value = mb_id(i_mb)) == -1) {
+
+ rv = (uint8_t)-1;
+
+ } else {
+
+ rv = id.chipType;
+ }
+
+ return rv;
+}
+
+
+uint8_t mb_ec_level(int i_mb)
+{
+ uint8_t rv;
+ cfam_id_t id;
+
+ if ((id.value = mb_id(i_mb)) == -1) {
+
+ rv = (uint8_t)-1;
+
+ } else {
+
+ rv = (id.majorEc << 4) | id.minorEc;
+ }
+
+ return rv;
+}
diff --git a/src/ssx/pgp/pgp_centaur.h b/src/ssx/pgp/pgp_centaur.h
new file mode 100644
index 0000000..8c2ccee
--- /dev/null
+++ b/src/ssx/pgp/pgp_centaur.h
@@ -0,0 +1,254 @@
+#ifndef __PGP_CENTAUR_H__
+#define __PGP_CENTAUR_H__
+
+// $Id: pgp_centaur.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_centaur.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_centaur.h
+/// \brief Support for Centaur access and configuration from OCC.
+
+#include "gpe_pba.h"
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/// Compute the address of an MCS unit register from an index
+///
+/// The MCS units have a bizarre PIB addressing scheme. This macro generates
+/// MCS unit PIB addresses from a register name (w/o unit/index prefix),
+/// assuming a valid index in the range 0:7. In the big sceheme of things it
+/// probably saves space and time to do this with a table lookup rather than
+/// generating the code to compute the address modification. (If we ever need
+/// these in assembler code we'll have to implement a macro).
+
+#define MCS_ADDRESS(reg, index) (MCS0_##reg | _pgp_mcs_offset[index])
+
+extern const uint16_t _pgp_mcs_offset[PGP_NMCS];
+
+
+/// A description of the current Centaur configuration
+///
+/// \note Because this structure is read by the GPE engine it is strongly
+/// recommended to allocate instances of this structure in non-cacheable data
+/// sections, with the caveat that data structures assigned to non-default
+/// data sections must always be initialized. For example:
+///
+/// \code
+///
+/// CentaurConfiguration G_centaurConfiguration
+/// SECTION_ATTRIBUTE(".noncacheable_ro") =
+/// {.configRc = CENTAUR_NOT_CONFIGURED};
+///
+/// \endcode
+
+typedef struct {
+
+ /// Centaur base addresses for in-band operations
+ ///
+ /// These base addresses are used by GPE programs so it is most convenient
+ /// to store the entire 64 bits, even though only bits 23:26 of the base
+ /// address can be manipulated through the PBA BARs and BAR masks. A 0
+ /// value indicates an unconfigured Centaur (MCS).
+ uint64_t baseAddress[PGP_NCENTAUR];
+
+ /// Contents of Centaur device id registers
+ ///
+ /// These are the device ID SCOMs (0x000f000f) read from configured
+ /// Centaur during initialization. A 0 value indicates an unconfigured
+ /// Centaur. These values are deconstructed by the memory buffer (mb)
+ /// APIs mb_id(), mb_chip_type() and mb_ec_level().
+ uint64_t deviceId[PGP_NCENTAUR];
+
+ /// A "chip configuration" bit mask denoting valid Centaur
+ ///
+ /// It shoud always be true that a bit denoting a configured Centaur is
+ /// associated with a non-0 \a baseAddress and vice-versa.
+ ChipConfig config;
+
+ /// The image of the PBA slave control register to use for the SYNC command
+ ///
+ /// The PowerBus address used to accomplish a Centaur SYNC is
+ /// constant. To simplify the procedures the PBA slave control register
+ /// (containing the extended address portion of the address) is
+ /// pre-computed and stored here.
+ ///
+ /// \note One and Only one of the MCS units can be targeted with SYNC
+ /// commands. The design includes a private bus connecting all MCS on the
+ /// chip that allows this "SYNC master" to broadcast the SYNC to all other
+ /// MCS on the chip.
+ uint64_t syncSlaveControl;
+
+ /// A GpePbaParms parameter block for gpe_mem_data()
+ ///
+ /// This parameter block is set up in advance and used by the GPE
+ /// procedure gpe_mem_data(). Given the complexity of accessing Centaur
+ /// sensors and SCOM through the PBA it is simpler to set these up ahead
+ /// of time and simply have the GPE procedures access preconfigured global
+ /// data. The \a dataParms and \a scomParms members are distinguished by
+ /// the different way the PBA slave needs to be configured to access
+ /// either the Centaur sensor cache or Centaur SCOMs.
+ GpePbaParms dataParms;
+
+ /// A GpePbaParms parameter block for gpe_scom_centaur().
+ GpePbaParms scomParms;
+
+ /// The final return code from centaur_configuration_create().
+ ///
+ /// If initialization fails then this value can be used to diagnose what
+ /// happend. This field should be statically initialized to a non-0 value
+ /// (CENTAUR_NOT_CONFIGURED) and can then be checked against 0 to
+ /// determine if the structure has been correctly initialized.
+ int64_t configRc;
+
+} CentaurConfiguration;
+
+/// The global CentaurConfiguration created during initialization
+extern CentaurConfiguration G_centaurConfiguration;
+
+#else // __ASSEMBLER__
+
+ .set CENTAUR_CONFIGURATION_BASE_ADDRESS, 0x0
+
+ .set CENTAUR_CONFIGURATION_DEVICE_ID, \
+ (CENTAUR_CONFIGURATION_BASE_ADDRESS + (8 * PGP_NCENTAUR))
+
+ .set CENTAUR_CONFIGURATION_CONFIG, \
+ (CENTAUR_CONFIGURATION_DEVICE_ID + (8 * PGP_NCENTAUR))
+
+ .set CENTAUR_CONFIGURATION_SYNC_SLAVE_CONTROL, \
+ (CENTAUR_CONFIGURATION_CONFIG + 8)
+
+ .set CENTAUR_CONFIGURATION_DATA_PARMS, \
+ (CENTAUR_CONFIGURATION_SYNC_SLAVE_CONTROL + 8)
+
+ .set CENTAUR_CONFIGURATION_SCOM_PARMS, \
+ (CENTAUR_CONFIGURATION_DATA_PARMS + SIZEOF_GPEPBAPARMS)
+
+ .set CENTAUR_CONFIGURATION_CONFIG_RC, \
+ (CENTAUR_CONFIGURATION_SCOM_PARMS + SIZEOF_GPEPBAPARMS)
+
+ .set SIZEOF_CENTAUR_CONFIGURATION, \
+ (CENTAUR_CONFIGURATION_CONFIG_RC + 8)
+
+#endif // __ASSEMBLER__
+
+
+#ifndef __ASSEMBLER__
+
+/// Error return codes set/returned by centaur_configuration_create()
+
+enum CentaurConfigurationCreateRc{
+
+ CENTAUR_INVALID_ARGUMENT = 0x007ccc01,
+ CENTAUR_MCSMODE0_SCOM_FAILURE = 0x007ccc02,
+ CENTAUR_MCSMODE0_19_FAILURE = 0x007ccc03,
+ CENTAUR_ADDRESS_27_FAILURE = 0x007ccc04,
+ CENTAUR_MULTIPLE_DESIGNATED_SYNC = 0x007ccc05,
+ CENTAUR_NO_DESIGNATED_SYNC = 0x007ccc06,
+ CENTAUR_BAR_MASK_ERROR = 0x007ccc07,
+ CENTAUR_CONFIGURATION_FAILED = 0x007ccc08,
+ CENTAUR_DATA_SETUP_ERROR = 0x007ccc09,
+ CENTAUR_SCOM_SETUP_ERROR = 0x007ccc0a,
+ CENTAUR_NOT_CONFIGURED = 0x007ccc0b,
+ CENTAUR_MASK_ERROR = 0x007ccc0c,
+ CENTAUR_READ_TPC_ID_FAILURE = 0x007ccc0d,
+ CENTAUR_BARMSKN_PUTSCOM_FAILURE = 0x007ccc0e,
+ CENTAUR_BARN_PUTSCOM_FAILURE = 0x007ccc0f,
+ CENTAUR_BARMSKN_GETSCOM_FAILURE = 0x007ccc10,
+ CENTAUR_BARN_GETSCOM_FAILURE = 0x007ccc11,
+};
+
+
+/// Create (initialize) G_centaurConfiguration
+///
+/// G_centaurConfiguration is a global structure used by GPE procedures to
+/// access Centaur, and the mb_*() APIs to return CFAM-id type information
+/// about the Centaurs.
+///
+/// To complete Centaur configuration requires running the GPE program
+/// gpe_scom_centaur() on PORE-GPE1 to collect the TPC device Ids of the
+/// Centaur chips. This means that the "async" drivers must be set up prior to
+/// the call. We assume this API will be called before threads have started,
+/// thus it will poll the async request for completion. Assuming no other GPE
+/// programs are scheduled this should take a few microseconds at most.
+///
+/// \returns Either 0 for success or an element of the
+/// CentaurConfigurationCreateRc enumeration.
+int
+centaur_configuration_create(void);
+
+
+/// Create (initialize) G_centaurConfiguration (Internal API)
+///
+/// \param[in] i_bar The index of the PBA BAR reserved for access to
+/// Centaur. This will normally be passed as the constant PBA_BAR_CENTAUR but
+/// is allowed to be variable for special cases.
+///
+/// \param[in] i_slave The index of the PBA slave reserved for access from the
+/// GPE complex. This will normally be passed as the constant
+/// PBA_SLAVE_PORE_GPE but is allowed to be variable for special cases.
+///
+/// \param[in] i_setup If non-0, then this procedure will set up the PBA BAR
+/// correctly for access to Centaur. If > 1, then the procedure will also
+/// designate an MCS to recieve the Centaur SYNC if the firmware failed to do
+/// so.
+///
+/// This API must be run early in the initialization flow, likely before the
+/// real-time loop is activated. The API first scans the MBS configuration for
+/// correctness and (optionally) sets up the PBA BAR and mask for access to
+/// Centaur. The API then runs the gpe_scom_centaur() procedure to get the
+/// CFAM Id from each configured Centaur.
+///
+/// \note Normally we would implement test/bringup workarounds like the \a
+/// i_setup parameter separately, however the setup of Centaur is at a level
+/// of complexity where it makes sense to implement this override in a
+/// mainline procedure.
+int
+_centaur_configuration_create(int i_bar, int i_slave, int i_setup);
+
+
+/// Get a Centaur (MB) CFAM Chip Id
+///
+/// \param[in] i_mb The index (0..PGP_NCENTAUR - 1) of the memory buffer being
+/// queried.
+///
+/// \returns A 32-bit value to be compared against the enumeration of known
+/// CFAM ids. See \ref pgp_cfam_chip_ids. If the \a i_mb is invalid or the
+/// Centaur is not configured or the G_centaurConfiguration is not valid then
+/// (uint32_t)-1 is returned.
+uint32_t mb_id(int i_mb);
+
+
+/// Get a Centaur (MB) Chip Type
+///
+/// \param[in] i_mb The index (0..PGP_NCENTAUR - 1) of the memory buffer being
+/// queried.
+///
+/// \returns An 8-bit value to be compared against the enumeration of known
+/// CFAM chip types. See \ref pgp_cfam_chip_types. If the \a i_mb is invalid
+/// or the Centaur is not configured or the G_centaurConfiguration is not
+/// valid then (uint8_t)-1 is returned.
+uint8_t mb_chip_type(int i_mb);
+
+
+/// Get a Centaur (MB) CFAM Chip EC Level
+///
+/// \param[in] i_mb The index (0..PGP_NCENTAUR - 1) of the memory buffer being
+/// queried.
+///
+/// \returns An 8-bit value; The high-order nibble is the major EC level and
+/// the low-order nibble is the minor EC level. For example a value of 0x21
+/// indicates DD 2.1. If the \a i_mb is invalid or the Centaur is not
+/// configured or the G_centaurConfiguration is not valid then (uint8_t)-1 is
+/// returned.
+uint8_t mb_ec_level(int i_mb);
+
+#endif // __ASSEMBLER
+
+#endif // __PGP_CENTAUR_H__
diff --git a/src/ssx/pgp/pgp_common.h b/src/ssx/pgp/pgp_common.h
new file mode 100755
index 0000000..305f7c2
--- /dev/null
+++ b/src/ssx/pgp/pgp_common.h
@@ -0,0 +1,717 @@
+#ifndef __PGP_COMMON_H__
+#define __PGP_COMMON_H__
+
+// $Id: pgp_common.h,v 1.4 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_common.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_common.h
+/// \brief Common header for SSX and PMX versions of PgP
+///
+/// This header is maintained as part of the SSX port for PgP, but needs to be
+/// physically present in the PMX area to allow dropping PMX code as a whole
+/// to other teams.
+
+// -*- WARNING: This file is maintained as part of SSX. Do not edit in -*-
+// -*- the PMX area as your edits will be lost. -*-
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+extern unsigned int g_ocb_timer_divider; //grm
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+// Configuration
+////////////////////////////////////////////////////////////////////////////
+
+#define PGP_NCORES 16
+#define PGP_NCORE_PARTITIONS 4
+#define PGP_NMCS 8
+#define PGP_NCENTAUR 8
+#define PGP_NTHREADS 8
+#define PGP_NDTSCPM 4
+
+#ifndef PROCESSOR_EC_LEVEL
+#define MURANO_DD10 1
+#else
+#define MURANO_DD10 0
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////
+// Clocking
+////////////////////////////////////////////////////////////////////////////
+//
+// The SSX timebase is driven by the pervasive clock, which is nest / 4. This
+// will typically be 600MHz, but may be 500MHz for power-constrained system
+// designs.
+
+/// The pervasive hang timer divider used for the OCB timer
+///
+/// This is supposed to yield an approximately 1us timer, however for MURANO
+/// DD10 we need to use an approximate 64us timer
+
+#if MURANO_DD10
+#define OCB_TIMER_DIVIDER_DEFAULT (64 * 512)
+#else
+#define OCB_TIMER_DIVIDER_DEFAULT 512
+#endif
+
+/// This is set to the above default at compile time but may be updated
+/// at run time. grm
+#define OCB_TIMER_DIVIDER g_ocb_timer_divider
+
+/// The OCB timer frequency
+#define OCB_TIMER_FREQUENCY_HZ (SSX_TIMEBASE_FREQUENCY_HZ / OCB_TIMER_DIVIDER)
+
+/// The pervasive hang timer divider used for the PMC (same as OCB timer)
+#define PMC_TIMER_DIVIDER OCB_TIMER_DIVIDER
+
+/// The PMC hang pulse frequency
+#define PMC_HANG_PULSE_FREQUENCY_HZ \
+ (SSX_TIMEBASE_FREQUENCY_HZ / PMC_TIMER_DIVIDER)
+
+/// The pervasive hang timer divider for PCBS 'fast' timers
+///
+/// This timer yeilds an approximate 100ns pulse with a 2.4 GHz pervasive clock
+#define PCBS_FAST_TIMER_DIVIDER 64
+
+/// The pervasive hang timer divider for PCBS 'slow' timers
+///
+/// This timer yeilds an approximate 1us pulse with a 2.4 GHz pervasive clock
+#define PCBS_SLOW_TIMER_DIVIDER 512
+
+/// The PCBS slow divider frequency
+#define PCBS_SLOW_HANG_PULSE_FREQUENCY_HZ \
+ (SSX_TIMEBASE_FREQUENCY_HZ / PCBS_SLOW_TIMER_DIVIDER)
+
+/// The PCBS occ heartbeat pulse is predivided in hardware by 64
+#define PCBS_HEARTBEAT_DIVIDER \
+ (PCBS_SLOW_TIMER_DIVIDER * 64)
+
+/// The PCBS heartbeat pulse frequency
+#define PCBS_HEARTBEAT_PULSE_FREQUENCY_HZ \
+ (SSX_TIMEBASE_FREQUENCY_HZ / PCBS_HEARTBEAT_DIVIDER)
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// OCI
+////////////////////////////////////////////////////////////////////////////
+
+// OCI Master Id assigments - required for PBA slave programming. These Ids
+// also appear as bits 12:15 of the OCI register space addresses of the OCI
+// registers for each device that contains OCI-addressable registers (GPE,
+// PMC, PBA, SLW and OCB).
+
+#define OCI_MASTER_ID_PORE_GPE 0
+#define OCI_MASTER_ID_PMC 1
+#define OCI_MASTER_ID_PBA 2
+#define OCI_MASTER_ID_UNUSED 3
+#define OCI_MASTER_ID_PORE_SLW 4
+#define OCI_MASTER_ID_OCB 5
+#define OCI_MASTER_ID_OCC_ICU 6
+#define OCI_MASTER_ID_OCC_DCU 7
+
+
+////////////////////////////////////////////////////////////////////////////
+// IRQ
+////////////////////////////////////////////////////////////////////////////
+
+// The OCB interrupt controller consists of 2 x 32-bit controllers. Unlike
+// PPC ASICs, the OCB controllers are _not_ cascaded. The combined
+// controllers are presented to the application as if there were a single
+// 64-bit interrupt controller, while the code underlying the abstraction
+// manipulates the 2 x 32-bit controllers independently.
+//
+// Note that the bits named *RESERVED* are actually implemented in the
+// controller, but the interrupt input is tied low. That means they can also
+// be used as IPI targets. Logical bits 32..63 are not implemented.
+
+#define PGP_IRQ_DEBUGGER 0 /* 0x00 */
+#define PGP_IRQ_TRACE_TRIGGER 1 /* 0x01 */
+#define PGP_IRQ_OCC_ERROR 2 /* 0x02 */
+#define PGP_IRQ_PBA_ERROR 3 /* 0x03 */
+#define PGP_IRQ_SRT_ERROR 4 /* 0x04 */
+#define PGP_IRQ_PORE_SW_ERROR 5 /* 0x05 */
+#define PGP_IRQ_PORE_GPE0_FATAL_ERROR 6 /* 0x06 */
+#define PGP_IRQ_PORE_GPE1_FATAL_ERROR 7 /* 0x07 */
+#define PGP_IRQ_PORE_SBE_FATAL_ERROR 8 /* 0x08 */
+#define PGP_IRQ_PMC_ERROR 9 /* 0x09 */
+#define PGP_IRQ_OCB_ERROR 10 /* 0x0a */
+#define PGP_IRQ_SPIPSS_ERROR 11 /* 0x0b */
+#define PGP_IRQ_CHECK_STOP 12 /* 0x0c */
+#define PGP_IRQ_PMC_MALF_ALERT 13 /* 0x0d */
+#define PGP_IRQ_ADU_MALF_ALERT 14 /* 0x0e */
+#define PGP_IRQ_EXTERNAL_TRAP 15 /* 0x0f */
+#define PGP_IRQ_OCC_TIMER0 16 /* 0x10 */
+#define PGP_IRQ_OCC_TIMER1 17 /* 0x11 */
+#define PGP_IRQ_PORE_GPE0_ERROR 18 /* 0x12 */
+#define PGP_IRQ_PORE_GPE1_ERROR 19 /* 0x13 */
+#define PGP_IRQ_PORE_SBE_ERROR 20 /* 0x14 */
+#define PGP_IRQ_PMC_INTERCHIP_MSG_RECV 21 /* 0x15 */
+#define PGP_IRQ_RESERVED_22 22 /* 0x16 */
+#define PGP_IRQ_PORE_GPE0_COMPLETE 23 /* 0x17 */
+#define PGP_IRQ_PORE_GPE1_COMPLETE 24 /* 0x18 */
+#define PGP_IRQ_ADCFSM_ONGOING 25 /* 0x19 */
+#define PGP_IRQ_RESERVED_26 26 /* 0x1a */
+#define PGP_IRQ_PBA_OCC_PUSH0 27 /* 0x1b */
+#define PGP_IRQ_PBA_OCC_PUSH1 28 /* 0x1c */
+#define PGP_IRQ_PBA_BCDE_ATTN 29 /* 0x1d */
+#define PGP_IRQ_PBA_BCUE_ATTN 30 /* 0x1e */
+#define PGP_IRQ_RESERVED_31 31 /* 0x1f */
+
+#define PGP_IRQ_RESERVED_32 32 /* 0x20 */
+#define PGP_IRQ_RESERVED_33 33 /* 0x21 */
+#define PGP_IRQ_STRM0_PULL 34 /* 0x22 */
+#define PGP_IRQ_STRM0_PUSH 35 /* 0x23 */
+#define PGP_IRQ_STRM1_PULL 36 /* 0x24 */
+#define PGP_IRQ_STRM1_PUSH 37 /* 0x25 */
+#define PGP_IRQ_STRM2_PULL 38 /* 0x26 */
+#define PGP_IRQ_STRM2_PUSH 39 /* 0x27 */
+#define PGP_IRQ_STRM3_PULL 40 /* 0x28 */
+#define PGP_IRQ_STRM3_PUSH 41 /* 0x29 */
+#define PGP_IRQ_RESERVED_42 42 /* 0x2a */
+#define PGP_IRQ_RESERVED_43 43 /* 0x2b */
+#define PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING 44 /* 0x2c */
+#define PGP_IRQ_PMC_PROTOCOL_ONGOING 45 /* 0x2d */
+#define PGP_IRQ_PMC_SYNC 46 /* 0x2e */
+#define PGP_IRQ_PMC_PSTATE_REQUEST 47 /* 0x2f */
+#define PGP_IRQ_RESERVED_48 48 /* 0x30 */
+#define PGP_IRQ_RESERVED_49 49 /* 0x31 */
+#define PGP_IRQ_PMC_IDLE_EXIT 50 /* 0x32 */
+#define PGP_IRQ_PORE_SW_COMPLETE 51 /* 0x33 */
+#define PGP_IRQ_PMC_IDLE_ENTER 52 /* 0x34 */
+#define PGP_IRQ_RESERVED_53 53 /* 0x35 */
+#define PGP_IRQ_PMC_INTERCHIP_MSG_SEND_ONGOING 54 /* 0x36 */
+#define PGP_IRQ_OCI2SPIVID_ONGOING 55 /* 0x37 */
+#define PGP_IRQ_PMC_OCB_O2P_ONGOING 56 /* 0x38 */
+#define PGP_IRQ_PSSBRIDGE_ONGOING 57 /* 0x39 */
+#define PGP_IRQ_PORE_SBE_COMPLETE 58 /* 0x3a */
+#define PGP_IRQ_IPI0 59 /* 0x3b */
+#define PGP_IRQ_IPI1 60 /* 0x3c */
+#define PGP_IRQ_IPI2 61 /* 0x3d */
+#define PGP_IRQ_IPI3 62 /* 0x3e */
+#define PGP_IRQ_RESERVED_63 63 /* 0x3f */
+
+
+// Please keep the string definitions up-to-date as they are used for
+// reporting in the Simics simulation.
+
+#define PGP_IRQ_STRINGS(var) \
+ const char* var[64] = { \
+ "PGP_IRQ_DEBUGGER", \
+ "PGP_IRQ_TRACE_TRIGGER", \
+ "PGP_IRQ_OCC_ERROR", \
+ "PGP_IRQ_PBA_ERROR", \
+ "PGP_IRQ_SRT_ERROR", \
+ "PGP_IRQ_PORE_SW_ERROR", \
+ "PGP_IRQ_PORE_GPE0_FATAL_ERROR", \
+ "PGP_IRQ_PORE_GPE1_FATAL_ERROR", \
+ "PGP_IRQ_PORE_SBE_FATAL_ERROR", \
+ "PGP_IRQ_PMC_ERROR", \
+ "PGP_IRQ_OCB_ERROR", \
+ "PGP_IRQ_SPIPSS_ERROR", \
+ "PGP_IRQ_CHECK_STOP", \
+ "PGP_IRQ_PMC_MALF_ALERT", \
+ "PGP_IRQ_ADU_MALF_ALERT", \
+ "PGP_IRQ_EXTERNAL_TRAP", \
+ "PGP_IRQ_OCC_TIMER0", \
+ "PGP_IRQ_OCC_TIMER1", \
+ "PGP_IRQ_PORE_GPE0_ERROR", \
+ "PGP_IRQ_PORE_GPE1_ERROR", \
+ "PGP_IRQ_PORE_SBE_ERROR", \
+ "PGP_IRQ_PMC_INTERCHIP_MSG_RECV", \
+ "PGP_IRQ_RESERVED_22", \
+ "PGP_IRQ_PORE_GPE0_COMPLETE", \
+ "PGP_IRQ_PORE_GPE1_COMPLETE", \
+ "PGP_IRQ_ADCFSM_ONGOING", \
+ "PGP_IRQ_RESERVED_26", \
+ "PGP_IRQ_PBA_OCC_PUSH0", \
+ "PGP_IRQ_PBA_OCC_PUSH1", \
+ "PGP_IRQ_PBA_BCDE_ATTN", \
+ "PGP_IRQ_PBA_BCUE_ATTN", \
+ "PGP_IRQ_RESERVED_31", \
+ "PGP_IRQ_RESERVED_32", \
+ "PGP_IRQ_RESERVED_33", \
+ "PGP_IRQ_STRM0_PULL", \
+ "PGP_IRQ_STRM0_PUSH", \
+ "PGP_IRQ_STRM1_PULL", \
+ "PGP_IRQ_STRM1_PUSH", \
+ "PGP_IRQ_STRM2_PULL", \
+ "PGP_IRQ_STRM2_PUSH", \
+ "PGP_IRQ_STRM3_PULL", \
+ "PGP_IRQ_STRM3_PUSH", \
+ "PGP_IRQ_RESERVED_42", \
+ "PGP_IRQ_RESERVED_43", \
+ "PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING", \
+ "PGP_IRQ_PMC_PROTOCOL_ONGOING", \
+ "PGP_IRQ_PMC_SYNC", \
+ "PGP_IRQ_PMC_PSTATE_REQUEST", \
+ "PGP_IRQ_RESERVED_48", \
+ "PGP_IRQ_RESERVED_49", \
+ "PGP_IRQ_PMC_IDLE_EXIT", \
+ "PGP_IRQ_PORE_SW_COMPLETE", \
+ "PGP_IRQ_PMC_IDLE_ENTER", \
+ "PGP_IRQ_RESERVED_53", \
+ "PGP_IRQ_PMC_INTERCHIP_MSG_SEND_ONGOING", \
+ "PGP_IRQ_OCI2SPIVID_ONGOING", \
+ "PGP_IRQ_PMC_OCB_O2P_ONGOING", \
+ "PGP_IRQ_PSSBRIDGE_ONGOING", \
+ "PGP_IRQ_PORE_SBE_COMPLETE", \
+ "PGP_IRQ_IPI0", \
+ "PGP_IRQ_IPI1", \
+ "PGP_IRQ_IPI2", \
+ "PGP_IRQ_IPI3 (ASYNC-IPI)", \
+ "PGP_IRQ_RESERVED_63" \
+ };
+
+
+/// This constant is used to define the size of the table of interrupt handler
+/// structures as well as a limit for error checking. The entire 64-bit
+/// vector is now in use.
+
+#define PPC405_IRQS 64
+
+
+// Note: All standard-product IPI uses are declared here to avoid conflicts
+// Validation- and lab-only IPI uses are documented in validation.h
+
+/// The deferred callback queue interrupt
+///
+/// This IPI is reserved for use of the async deferred callback mechanism.
+/// This IPI is used by both critical and noncritical async handlers to
+/// activate the deferred callback mechanism.
+#define PGP_IRQ_ASYNC_IPI PGP_IRQ_IPI3
+
+
+/// The PTS completion queue intererupt
+///
+/// This IPI is reserved for use of the PTS completion queues. A single
+/// interrupt serves PTS for both GPE0 and GPE1. Note that as defined here,
+/// PTS completion takes precedence over other ASYNC processing, however in
+/// reality they both run callbacks preemptible so they will tend to be more
+/// or less at the same priority. If this is a problem then they could be
+/// combined onto a single interrupt and handled with the appropriate priority
+/// in the async_callback_handler_full().
+
+#define PGP_IRQ_PTS_IPI PGP_IRQ_IPI2
+
+
+#ifndef __ASSEMBLER__
+
+/// This expression recognizes only those IRQ numbers that have named
+/// (non-reserved) interrupts in the OCB interrupt controller.
+
+// There are so many invalid interrupts now that it's a slight improvement in
+// code size to let the compiler optimize the invalid IRQs to a bit mask for
+// the comparison.
+
+#define PGP_IRQ_VALID(irq) \
+ ({unsigned __irq = (unsigned)(irq); \
+ ((__irq < PPC405_IRQS) && \
+ ((PGP_IRQ_MASK64(__irq) & \
+ (PGP_IRQ_MASK64(PGP_IRQ_RESERVED_22) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_26) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_31) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_32) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_33) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_42) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_43) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_48) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_49) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_53) | \
+ PGP_IRQ_MASK64(PGP_IRQ_RESERVED_63))) == 0));})
+
+/// This is a 32-bit mask, with big-endian bit (irq % 32) set.
+#define PGP_IRQ_MASK32(irq) (((uint32_t)0x80000000) >> ((irq) % 32))
+
+/// This is a 64-bit mask, with big-endian bit 'irq' set.
+#define PGP_IRQ_MASK64(irq) (0x8000000000000000ull >> (irq))
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// OCB
+////////////////////////////////////////////////////////////////////////////
+
+/// The base address of the OCI control register space
+#define OCI_REGISTER_SPACE_BASE 0x40000000
+
+/// The base address of the entire PIB port mapped by the OCB. The
+/// OCB-contained PIB registers are based at OCB_PIB_BASE.
+#define OCB_PIB_SLAVE_BASE 0x00060000
+
+/// The size of the OCI control register address space
+///
+/// There are at most 8 slaves, each of which maps 2**16 bytes of register
+/// address space.
+#define OCI_REGISTER_SPACE_SIZE POW2_32(19)
+
+/// This macro converts an OCI register space address into a PIB address as
+/// seen through the OCB direct bridge.
+#define OCI2PIB(addr) ((((addr) & 0x0007ffff) >> 3) + OCB_PIB_SLAVE_BASE)
+
+
+// OCB communication channel constants
+
+#define OCB_INDIRECT_CHANNELS 4
+
+#define OCB_RW_READ 0
+#define OCB_RW_WRITE 1
+
+#define OCB_STREAM_MODE_DISABLED 0
+#define OCB_STREAM_MODE_ENABLED 1
+
+#define OCB_STREAM_TYPE_LINEAR 0
+#define OCB_STREAM_TYPE_CIRCULAR 1
+
+#define OCB_INTR_ACTION_FULL 0
+#define OCB_INTR_ACTION_NOT_FULL 1
+#define OCB_INTR_ACTION_EMPTY 2
+#define OCB_INTR_ACTION_NOT_EMPTY 3
+
+#ifndef __ASSEMBLER__
+
+// These macros select OCB interrupt controller registers based on the IRQ
+// number.
+
+#define OCB_OIMR_AND(irq) (((irq) & 0x20) ? OCB_OIMR1_AND : OCB_OIMR0_AND)
+#define OCB_OIMR_OR(irq) (((irq) & 0x20) ? OCB_OIMR1_OR : OCB_OIMR0_OR)
+
+#define OCB_OISR(irq) (((irq) & 0x20) ? OCB_OISR1 : OCB_OISR0)
+#define OCB_OISR_AND(irq) (((irq) & 0x20) ? OCB_OISR1_AND : OCB_OISR0_AND)
+#define OCB_OISR_OR(irq) (((irq) & 0x20) ? OCB_OISR1_OR : OCB_OISR0_OR)
+
+#define OCB_OIEPR(irq) (((irq) & 0x20) ? OCB_OIEPR1 : OCB_OIEPR0)
+#define OCB_OITR(irq) (((irq) & 0x20) ? OCB_OITR1 : OCB_OITR0)
+#define OCB_OCIR(irq) (((irq) & 0x20) ? OCB_OCIR1 : OCB_OCIR0)
+#define OCB_OUDER(irq) (((irq) & 0x20) ? OCB_OUDER1 : OCB_OUDER0)
+
+#endif /* __ASSEMBLER__ */
+
+
+////////////////////////////////////////////////////////////////////////////
+// PMC
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// A Pstate type
+///
+/// Pstates are signed, but our register access macros operate on unsigned
+/// values. To avoid bugs, Pstate register fields should always be extracted
+/// to a variable of type Pstate. If the size of Pstate variables ever
+/// changes we will have to revisit this convention.
+typedef int8_t Pstate;
+
+/// A DPLL frequency code
+///
+/// DPLL frequency codes moved from 8 to 9 bits going from P7 to P8
+typedef uint16_t DpllCode;
+
+/// A VRM11 VID code
+typedef uint8_t Vid11;
+
+#endif /* __ASSEMBLER__ */
+
+/// The minimum Pstate
+#define PSTATE_MIN -128
+
+/// The maximum Pstate
+#define PSTATE_MAX 127
+
+/// The minimum \e legal DPLL frequency code
+///
+/// This is ~1GHz with a 33.3MHz tick frequency.
+#define DPLL_MIN 0x01e
+
+/// The maximum DPLL frequency code
+#define DPLL_MAX 0x1ff
+
+/// The minimum \a legal (non-power-off) VRM11 VID code
+#define VID11_MIN 0x02
+
+/// The maximum \a legal (non-power-off) VRM11 VID code
+#define VID11_MAX 0xfd
+
+
+////////////////////////////////////////////////////////////////////////////
+// PCB
+////////////////////////////////////////////////////////////////////////////
+
+/// Convert a core chiplet 0 SCOM address to the equivalent address for any
+/// other core chiplet.
+///
+/// Note that it is unusual to address core chiplet SCOMs directly. Normally
+/// this is done as part of a GPE program where the program iterates over core
+/// chiplets, using the chiplet-0 address + a programmable offset held in a
+/// chiplet address register. Therefore the only address macro defined is the
+/// chiplet-0 address. This macro is used for the rare cases of explicit
+/// getscom()/ putscom() to a particular chiplet.
+
+#define CORE_CHIPLET_ADDRESS(addr, core) ((addr) + ((core) << 24))
+
+
+// PCB Error codes
+
+#define PCB_ERROR_NONE 0
+#define PCB_ERROR_RESOURCE_OCCUPIED 1
+#define PCB_ERROR_CHIPLET_OFFLINE 2
+#define PCB_ERROR_PARTIAL_GOOD 3
+#define PCB_ERROR_ADDRESS_ERROR 4
+#define PCB_ERROR_CLOCK_ERROR 5
+#define PCB_ERROR_PACKET_ERROR 6
+#define PCB_ERROR_TIMEOUT 7
+
+// PCB Multicast modes
+
+#define PCB_MULTICAST_OR 0
+#define PCB_MULTICAST_AND 1
+#define PCB_MULTICAST_SELECT 2
+#define PCB_MULTICAST_COMPARE 4
+#define PCB_MULTICAST_WRITE 5
+
+/// \defgroup pcb_multicast_groups PCB Multicast Groups
+///
+/// Technically the multicast groups are programmable; This is the multicast
+/// grouping established by proc_sbe_chiplet_init().
+///
+/// - Group 0 : All functional chiplets (PRV PB XBUS ABUS PCIE TPCEX)
+/// - Group 1 : All functional EX chiplets (no cores)
+/// - Group 2 : All functional EX chiplets (core only)
+/// - Group 3 : All functional chiplets except pervasive (PRV)
+///
+/// @{
+
+#define MC_GROUP_ALL 0
+#define MC_GROUP_EX 1
+#define MC_GROUP_EX_CORE 2
+#define MC_GROUP_ALL_BUT_PRV 3
+
+/// @}
+
+
+/// Convert any SCOM address to a multicast address
+#define MC_ADDRESS(address, group, mode) \
+ (((address) & 0x00ffffff) | ((0x40 | ((mode) << 3) | (group)) << 24))
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// PBA
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////
+// Macros for fields of PBA_MODECTL
+////////////////////////////////////
+
+/// The 64KB OCI HTM marker space is enabled by default at 0x40070000
+///
+/// See the comments for pgp_trace.h
+
+#define PBA_OCI_MARKER_BASE 0x40070000
+
+
+// SSX Kernel reserved trace addresses, see pgp_trace.h.
+
+#define SSX_TRACE_CRITICAL_IRQ_ENTRY_BASE 0xf000
+#define SSX_TRACE_CRITICAL_IRQ_EXIT_BASE 0xf100
+#define SSX_TRACE_NONCRITICAL_IRQ_ENTRY_BASE 0xf200
+#define SSX_TRACE_NONCRITICAL_IRQ_EXIT_BASE 0xf300
+#define SSX_TRACE_THREAD_SWITCH_BASE 0xf400
+#define SSX_TRACE_THREAD_SLEEP_BASE 0xf500
+#define SSX_TRACE_THREAD_WAKEUP_BASE 0xf600
+#define SSX_TRACE_THREAD_SEMAPHORE_PEND_BASE 0xf700
+#define SSX_TRACE_THREAD_SEMAPHORE_POST_BASE 0xf800
+#define SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT_BASE 0xf900
+#define SSX_TRACE_THREAD_SUSPENDED_BASE 0xfa00
+#define SSX_TRACE_THREAD_DELETED_BASE 0xfb00
+#define SSX_TRACE_THREAD_COMPLETED_BASE 0xfc00
+#define SSX_TRACE_THREAD_MAPPED_RUNNABLE_BASE 0xfd00
+#define SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND_BASE 0xfe00
+#define SSX_TRACE_THREAD_MAPPED_SLEEPING_BASE 0xff00
+
+
+// Please keep the string definitions up to date as they are used for
+// reporting in the Simics simulation.
+
+#define SSX_TRACE_STRINGS(var) \
+ const char* var[16] = { \
+ "Critical IRQ Entry ", \
+ "Critical IRQ Exit ", \
+ "Noncritical IRQ Entry ", \
+ "Noncritical IRQ Exit ", \
+ "Thread Switch ", \
+ "Thread Blocked : Sleep ", \
+ "Thread Unblocked : Wakeup ", \
+ "Thread Blocked : Semaphore ", \
+ "Thread Unblocked : Semaphore ", \
+ "Thread Unblocked : Sem. Timeout", \
+ "Thread Suspended ", \
+ "Thread Deleted ", \
+ "Thread Completed ", \
+ "Thread Mapped Runnable ", \
+ "Thread Mapped Semaphore Pend. ", \
+ "Thread Mapped Sleeping ", \
+ };
+
+
+// PBA transaction sizes for the block copy engines
+
+#define PBA_BCE_OCI_TRANSACTION_32_BYTES 0
+#define PBA_BCE_OCI_TRANSACTION_64_BYTES 1
+#define PBA_BCE_OCI_TRANSACTION_8_BYTES 2
+
+
+// PBAX communication channel constants
+
+#define PBAX_CHANNELS 2
+
+#define PBAX_INTR_ACTION_FULL 0
+#define PBAX_INTR_ACTION_NOT_FULL 1
+#define PBAX_INTR_ACTION_EMPTY 2
+#define PBAX_INTR_ACTION_NOT_EMPTY 3
+
+
+// PBA Write Buffer fields
+
+#define PBA_WBUFVALN_STATUS_EMPTY 0x01
+#define PBA_WBUFVALN_STATUS_GATHERING 0x02
+#define PBA_WBUFVALN_STATUS_WAIT 0x04
+#define PBA_WBUFVALN_STATUS_WRITING 0x08
+#define PBA_WBUFVALN_STATUS_CRESPERR 0x10
+
+
+////////////////////////////////////////////////////////////////////////////
+// VRM
+////////////////////////////////////////////////////////////////////////////
+
+// These are the command types recognized by the VRMs
+
+#define VRM_WRITE_VOLTAGE 0x0
+#define VRM_READ_STATE 0xc
+#define VRM_READ_VOLTAGE 0x3
+
+// Voltage rail designations for the read voltage command
+#define VRM_RD_VDD_RAIL 0x0
+#define VRM_RD_VCS_RAIL 0x1
+
+
+////////////////////////////////////////////////////////////////////////////
+// OHA
+////////////////////////////////////////////////////////////////////////////
+
+// Power proxy trace record idle state encodings. These encodings are unique
+// to the Power proxy trace record.
+
+#define PPT_IDLE_NON_IDLE 0x0
+#define PPT_IDLE_NAP 0x1
+#define PPT_IDLE_LIGHT_SLEEP 0x2
+#define PPT_IDLE_FAST_SLEEP 0x3
+#define PPT_IDLE_DEEP_SLEEP 0x4
+#define PPT_IDLE_LIGHT_WINKLE 0x5
+#define PPT_IDLE_FAST_WINKLE 0x6
+#define PPT_IDLE_DEEP_WINKLE 0x7
+
+
+////////////////////////////////////////////////////////////////////////////
+// PC
+////////////////////////////////////////////////////////////////////////////
+
+// SPRC numbers for PC counters. The low-order 3 bits are always defined as
+// 0. The address can also be modified by OR-ing in 0x400 to indicate
+// auto-increment addressing. Note that the frequency-sensitivity counters
+// are called "workrate" counters in the hardware documentation.
+//
+// Notes on the throttle counters:
+//
+// SPRN_IFU_THROTTLE_COUNTER
+// Cycles the IFU throttle was actually blocking fetch
+//
+// <= if_pc_didt_throttle_blocked
+//
+// SPRN_ISU_THROTTLE_COUNTER
+// Cycles that ISU throttle was active and modeably IFU throttle request
+// was not
+//
+// <= sd_pc_uthrottle_active AND
+// (NOT scom_isuonly_count_mode OR NOT trigger_didt_throttle)
+//
+// SPRN_IFU_ACTIVE_COUNTER
+// Cycles that IFU throttle active input is asserted
+//
+// <= if_pc_didt_throttle_active
+
+
+/// \note The OCC SPRC/SPRD hardware has a bug that makes it such that the OCC
+/// SPRC increments whenever the OCC SPRD is accessed, regardless of the
+/// setting of the SPRN_PC_AUTOINCREMENT bit. This bug won't be fixed.
+
+#define SPRN_CORE_INSTRUCTION_DISPATCH 0x200
+#define SPRN_CORE_INSTRUCTION_COMPLETE 0x208
+#define SPRN_CORE_FREQUENCY_SENSITIVITY_BUSY 0x210
+#define SPRN_CORE_FREQUENCY_SENSITIVITY_FINISH 0x218
+#define SPRN_CORE_RUN_CYCLE 0x220
+#define SPRN_CORE_RAW_CYCLE 0x228
+#define SPRN_CORE_MEM_HIER_A 0x230
+#define SPRN_CORE_MEM_HIER_B 0x238
+#define SPRN_CORE_MEM_C_LPAR(p) (0x240 + (8 * (p)))
+#define SPRN_WEIGHTED_INSTRUCTION_PROCESSING 0x260
+#define SPRN_WEIGHTED_GPR_REGFILE_ACCESS 0x268
+#define SPRN_WEIGHTED_VRF_REGFILE_ACCESS 0x270
+#define SPRN_WEIGHTED_FLOATING_POINT_ISSUE 0x278
+#define SPRN_WEIGHTED_CACHE_READ 0x280
+#define SPRN_WEIGHTED_CACHE_WRITE 0x288
+#define SPRN_WEIGHTED_ISSUE 0x290
+#define SPRN_WEIGHTED_CACHE_ACCESS 0x298
+#define SPRN_WEIGHTED_VSU_ISSUE 0x2a0
+#define SPRN_WEIGHTED_FXU_ISSUE 0x2a8
+
+#define SPRN_THREAD_RUN_CYCLES(t) (0x2b0 + (0x20 * (t)))
+#define SPRN_THREAD_INSTRUCTION_COMPLETE(t) (0x2b8 + (0x20 * (t)))
+#define SPRN_THREAD_MEM_HIER_A(t) (0x2c0 + (0x20 * (t)))
+#define SPRN_THREAD_MEM_HIER_B(t) (0x2c8 + (0x20 * (t)))
+
+#define SPRN_IFU_THROTTLE_COUNTER 0x3b0
+#define SPRN_ISU_THROTTLE_COUNTER 0x3b8
+#define SPRN_IFU_ACTIVE_COUNTER 0x3c0
+
+#define SPRN_PC_AUTOINCREMENT 0x400
+
+
+////////////////////////////////////////////////////////////////////////////
+// Centaur
+////////////////////////////////////////////////////////////////////////////
+
+// DIMM sensor status codes
+
+/// The next sampling period began before this sensor was read or the master
+/// enable is off, or the individual sensor is disabled. If the subsequent
+/// read completes on time, this will return to valid reading. Sensor data may
+/// be accurate, but stale. If due to a stall, the StallError FIR will be
+/// set.
+#define DIMM_SENSOR_STATUS_STALLED 0
+
+/// The sensor data was not returned correctly either due to parity
+/// error or PIB bus error code. Will return to valid if the next PIB
+/// access to this sensor is valid, but a FIR will be set; Refer to FIR
+/// for exact error. Sensor data should not be considered valid while
+/// this code is present.
+#define DIMM_SENSOR_STATUS_ERROR 1
+
+/// Sensor data is valid, and has been valid since the last time this
+/// register was read.
+#define DIMM_SENSOR_STATUS_VALID_OLD 2
+
+/// Sensor data is valid and has not yet been read by a SCOM. The status code
+/// return to DIMM_SENSOR_STATUS_VALID_OLD after this register is read.
+#define DIMM_SENSOR_STATUS_VALID_NEW 3
+
+
+#endif /* __PGP_COMMON_H__ */
diff --git a/src/ssx/pgp/pgp_core.h b/src/ssx/pgp/pgp_core.h
new file mode 100755
index 0000000..59edb26
--- /dev/null
+++ b/src/ssx/pgp/pgp_core.h
@@ -0,0 +1,20 @@
+#ifndef __PGP_CORE_H__
+#define __PGP_CORE_H__
+
+// $Id: pgp_core.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_core.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_core.h
+/// \brief PgP core units header. Local and mechanically generated macros.
+
+#include "pc_register_addresses.h"
+#include "pc_firmware_registers.h"
+#include "sensors_register_addresses.h"
+#include "sensors_firmware_registers.h"
+
+#endif /* __PGP_CORE_H__ */
diff --git a/src/ssx/pgp/pgp_id.c b/src/ssx/pgp/pgp_id.c
new file mode 100644
index 0000000..0b4d4d7
--- /dev/null
+++ b/src/ssx/pgp/pgp_id.c
@@ -0,0 +1,135 @@
+// $Id: pgp_id.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_id.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_id.h
+/// \brief PgP chip and EC-level identification + chip configuration
+
+#include "ssx.h"
+#include "pgp_config.h"
+
+
+// Note: These cached variables are all declared as 64 bits, noncacheable so
+// that that they are also available as-is to PORE programs.
+
+uint64_t G_node_id SECTION_ATTRIBUTE(".noncacheable") = 0;
+uint64_t G_chip_id SECTION_ATTRIBUTE(".noncacheable") = 0;
+uint64_t G_cfam_id SECTION_ATTRIBUTE(".noncacheable") = 0;
+uint64_t G_cfam_chip_type SECTION_ATTRIBUTE(".noncacheable") = 0;
+uint64_t G_cfam_ec_level SECTION_ATTRIBUTE(".noncacheable") = 0;
+
+void
+_pgp_get_ids(void)
+{
+ tpc_gp0_t gp0;
+ tpc_device_id_t deviceId;
+ cfam_id_t cfamId;
+
+ getscom(TPC_GP0, &(gp0.value));
+ G_node_id = gp0.fields.tc_node_id_dc;
+ G_chip_id = gp0.fields.tc_chip_id_dc;
+
+ getscom(TPC_DEVICE_ID, &(deviceId.value));
+ G_cfam_id = cfamId.value = deviceId.fields.cfam_id;
+ G_cfam_chip_type = cfamId.chipType;
+ G_cfam_ec_level = (cfamId.majorEc << 4) | cfamId.minorEc;
+}
+
+
+uint8_t
+node_id(void)
+{
+ return G_node_id;
+}
+
+uint8_t
+chip_id(void)
+{
+ return G_chip_id;
+}
+
+uint32_t
+cfam_id(void)
+{
+ return G_cfam_id;
+}
+
+uint8_t
+cfam_chip_type(void)
+{
+ return G_cfam_chip_type;
+}
+
+uint8_t
+cfam_ec_level(void)
+{
+ return G_cfam_ec_level;
+}
+
+
+// The chiplet configuration is computed by doing a "select-mode" multicast to
+// the all-functional-chiplets-core group. Correctness here depends on the
+// convention that the "select" bit number will always be 0. We check just to
+// be sure. Since this is called from initialization code there is no recourse
+// here except to panic in the event of error.
+
+// Note: Ex-chiplets start at chiplet 16 and are left-justified in the
+// ChipConfig.
+
+
+ChipConfig G_chip_configuration SECTION_ATTRIBUTE(".noncacheable") = 0;
+uint64_t G_core_configuration SECTION_ATTRIBUTE(".noncacheable") = 0;
+
+/// \bug This API currently only computes the core configuration. It needs to
+/// be extended to also compute the MC and Centaur configuration.
+///
+/// \bug in Simics we're doing this based on the PMC_CORE_DECONFIGURATION_REG
+/// pending Simics support for the base pervasive functionality
+
+void
+_pgp_get_chip_configuration(void)
+{
+ if (SIMICS_ENVIRONMENT) {
+
+ pmc_core_deconfiguration_reg_t pcdr;
+
+ pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG);
+ G_chip_configuration =
+ ~((uint64_t)(pcdr.fields.core_chiplet_deconf_vector) << 48);
+
+ } else {
+
+ uint64_t select, configuration;
+ int rc;
+
+ rc = getscom(0x000f0008, &select); /* TP CHIPLET SELECT */
+ if (rc) SSX_PANIC(PGP_ID_SCOM_ERROR_SELECT);
+ if (select != 0) SSX_PANIC(PGP_ID_SELECT_ERROR);
+
+ rc = getscom(MC_ADDRESS(0x000f0012,
+ MC_GROUP_EX_CORE,
+ PCB_MULTICAST_SELECT),
+ &configuration);
+ if (rc) SSX_PANIC(PGP_ID_SCOM_ERROR_CONFIG);
+
+ G_chip_configuration = (configuration << 16) & 0xffff000000000000ull;
+ }
+
+ G_core_configuration = G_chip_configuration & 0xffff000000000000ull;
+}
+
+
+uint32_t core_configuration(void)
+{
+ return G_core_configuration >> 32;
+}
+
+
+
+
+
+
diff --git a/src/ssx/pgp/pgp_id.h b/src/ssx/pgp/pgp_id.h
new file mode 100644
index 0000000..2b0ecab
--- /dev/null
+++ b/src/ssx/pgp/pgp_id.h
@@ -0,0 +1,183 @@
+#ifndef __PGP_ID_H__
+#define __PGP_ID_H__
+
+// $Id: pgp_id.h,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_id.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_id.h
+/// \brief PgP chip and EC-level identification + chip configuration
+///
+/// During initialization the device identification SCOM registers are read
+/// and cached.
+///
+/// The node and chip ids are read from TPC_GP0 and stored as global
+/// variables, accessible through the node_id() and chip_id() APIs. The
+/// global variables are available to PORE programs.
+///
+/// The TPC_DEVICE_ID register is also read, deconstructed and stored in
+/// global variables. APIs defined here provide access to the fields of the
+/// device identification to support run-time behavior based on the chip type
+/// and EC level of the POWER8 chip containing the OCC. The global variables
+/// are available to PORE programs.
+///
+/// - cfam_id() : Obtain the full chip identification as a 32-bit CFAM id
+/// - cfam_chip_type() : Obtain the 8-bit CFAM chip type
+/// - cfam_ec_level() : Obtain an 8-bit CFAM EC level
+///
+/// For example, to identify a chip as Murano DD1.0, one could use either
+/// method shown below:
+///
+/// \code
+///
+/// if (cfam_id() == CFAM_CHIP_ID_MURANO_10) { ... }
+///
+/// if ((cfam_chip_type() == CFAM_CHIP_TYPE_MURANO) &&
+/// (cfam_ec_level() == 0x10)) { ... }
+///
+/// \encode
+
+// Error/Panic Codes
+
+#define PGP_ID_SCOM_ERROR_SELECT 0x00747401
+#define PGP_ID_SCOM_ERROR_CONFIG 0x00747402
+#define PGP_ID_SELECT_ERROR 0x00747403
+
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+#include "tpc_firmware_registers.h"
+#include "pgp_config.h"
+
+
+/// Get TPC device identification (internal API, called once from __pgp_setup().
+void
+_pgp_get_ids(void);
+
+/// Get the TPC Node Id
+uint8_t node_id(void);
+
+/// Get the TPC Chip Id
+uint8_t chip_id(void);
+
+/// Get the CFAM Chip Id
+///
+/// \returns A 32-bit value to be compared against the enumeration of known
+/// CFAM ids. See \ref pgp_cfam_chip_ids.
+uint32_t cfam_id(void);
+
+/// Get the CFAM Chip Type
+///
+/// \returns An 8-bit value to be compared against the enumeration of known
+/// CFAM chip types. See \ref pgp_cfam_chip_types.
+uint8_t cfam_chip_type(void);
+
+/// Get the CFAM Chip EC Level
+///
+/// \returns An 8-bit value; The high-order nibble is the major EC level and
+/// the low-order nibble is the minor EC level. Fore example a value of 0x21
+/// indicates DD 2.1.
+uint8_t cfam_ec_level(void);
+
+
+/// Compute the chip configuration (internal API, called once from __pgp_setup().
+void
+_pgp_get_chip_configuration(void);
+
+/// Get the core configuration
+///
+/// The return value is a 32 bit integer with big-endian bits set to indicate
+/// valid cores.
+uint32_t
+core_configuration(void);
+
+
+#endif // __ASSEMBLER__
+
+
+/// \defgroup pgp_cfam_chip_types PGP CFAM Chip Types (Including Centaur)
+///
+/// The CFAM Chip Type is an 8-bit value that uniquely identfies a chip
+/// architecture.
+///
+/// @{
+
+#define CFAM_CHIP_TYPE_CENTAUR 0xe9
+#define CFAM_CHIP_TYPE_VENICE 0xea
+#define CFAM_CHIP_TYPE_MURANO 0xef
+
+/// @}
+
+
+/// \defgroup pgp_cfam_chip_ids PGP CFAM Chip Ids (Including Centaur)
+///
+/// The CFAM Chip ID is a 32-bit value that uniquely identfies a chip and its
+/// EC level.
+///
+/// The reference:
+///
+/// - https://eclipz.pok.ibm.com/sys/ras/docs/cfam_ids.txt
+///
+/// The interpretation:
+///
+/// MlmCC049
+///
+/// M - Major EC (RIT-A) level
+/// l - 2:Austin, 6:Poughkeepsie
+/// m - Minor EC (RIT-B) level
+/// CC - 0xE9:Centaur, 0xEA:Venice, 0xEF:Murano
+/// 049 - IBM (Except for buggy 0x001 in Murano DD1.X)
+///
+/// @{
+
+#define CFAM_CHIP_ID_VENICE_10 0x120ea049
+#define CFAM_CHIP_ID_VENICE_20 0x220ea049
+#define CFAM_CHIP_ID_VENICE_21 0x221ea049
+
+#define CFAM_CHIP_ID_MURANO_10 0x120ef001
+#define CFAM_CHIP_ID_MURANO_11 0x121ef001
+#define CFAM_CHIP_ID_MURANO_12 0x122ef001
+#define CFAM_CHIP_ID_MURANO_13 0x123ef001
+#define CFAM_CHIP_ID_MURANO_20 0x220ef049
+#define CFAM_CHIP_ID_MURANO_21 0x221ef049
+
+#define CFAM_CHIP_ID_CENTAUR_10 0x160e9049
+#define CFAM_CHIP_ID_CENTAUR_20 0x260e9049
+
+
+#ifndef __ASSEMBLER__
+
+/// The CFAM ID as a set of fields
+
+typedef union {
+#ifdef _BIG_ENDIAN
+ struct {
+ uint32_t majorEc : 4;
+ uint32_t location : 4;
+ uint32_t minorEc : 4;
+ uint32_t chipType : 8;
+ uint32_t vendor : 12;
+ };
+#else
+ struct {
+ uint32_t vendor : 12;
+ uint32_t chipType : 8;
+ uint32_t minorEc : 4;
+ uint32_t location : 4;
+ uint32_t majorEc : 4;
+ };
+#endif // _BIG_ENDIAN
+ uint32_t value;
+
+} cfam_id_t;
+
+#endif // __ASSEMBLER__
+
+/// @}
+
+#endif // __PGP_ID_H__
diff --git a/src/ssx/pgp/pgp_init.c b/src/ssx/pgp/pgp_init.c
new file mode 100755
index 0000000..4e28014
--- /dev/null
+++ b/src/ssx/pgp/pgp_init.c
@@ -0,0 +1,340 @@
+// $Id: pgp_init.c,v 1.2 2014/03/14 16:34:34 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_init.c
+/// \brief SSX initialization for PgP
+///
+/// The entry points in this routine are used during initialization. This
+/// code space can be deallocated and reassigned after application
+/// initialization if required.
+
+#include "ssx.h"
+#include "pgp_vrm.h"
+#include "simics_stdio.h"
+#include "string_stream.h"
+
+#if USE_RTX_IO
+// This file is not avilable to OCC FW builds
+#include "rtx_stdio.h"
+#endif
+
+// We need to make sure that the PLB arbiter is set up correctly to obtain
+// highest performance in the PgP environment, and that PLB error reporting is
+// appropriate.
+
+// The PLB arbiter is configured to support fair arbitration of equal-priority
+// requests, however we don't set priorities here. The default settings have
+// been found to be acceptible so far. We do enable arbiter pipelining however.
+
+// We do set the "plbarb_lockerr" bit so that the PLB arbiter will trap and
+// hold the first PLB timeout address.
+
+static void
+plb_arbiter_setup()
+{
+ plb_pacr_t pacr;
+ ocb_ocichsw_t oo;
+
+ pacr.value = 0;
+ pacr.fields.ppm = 1; /* Fair arbitration */
+ pacr.fields.hbu = 1; /* High bus utilization */
+ pacr.fields.rdp = 1; /* 2-deep read pipelining */
+ pacr.fields.wrp = 1; /* 2-deep write pipelining */
+ mtdcr(PLB_PACR, pacr.value);
+
+ oo.value = in32(OCB_OCICHSW);
+ oo.fields.plbarb_lockerr = 1;
+ out32(OCB_OCICHSW, oo.value);
+}
+
+
+#if PPC405_MMU_SUPPORT
+
+#include "ppc405_mmu.h"
+
+// MMU regions
+//
+// The linker script provides a standard set of symbols that define the base
+// address and size of each expected section. Any section with a non-0 size
+// will be mapped in the MMU using protection attributes appropriate for the
+// section. All sections requiring different MMU attributes must be
+// 1KB-aligned. The OCI control register space is fixed and also mapped by
+// the same mechanism.
+//
+// By default, caching is enabled for all sections other than the sections
+// explicitly cache-inhibited. Configuration options are provided to disable
+// caching of text, data and both. Note that sections that (may) contain code
+// and data will be marked cache-inhibited if either text or data is globally
+// configured as cache-inhibited. Also note that "writethrough" can only be
+// defined on cacheable data sections.
+
+#ifdef CACHE_INHIBIT_ALL
+#define CACHE_INHIBIT_TEXT 1
+#define CACHE_INHIBIT_DATA 1
+#endif
+
+#if CACHE_INHIBIT_TEXT
+#define TEXT_CACHEABILITY_FLAG TLBLO_I
+#else
+#define TEXT_CACHEABILITY_FLAG 0
+#endif
+
+#if CACHE_INHIBIT_DATA
+#define DATA_CACHEABILITY_FLAG TLBLO_I
+#define WRITETHROUGH_FLAG 0
+#else
+#define DATA_CACHEABILITY_FLAG 0
+#define WRITETHROUGH_FLAG TLBLO_W
+#endif
+
+
+// This structure contains all of the fields necessary to create a MMU
+// mapping.
+
+typedef struct {
+ SsxAddress base;
+ size_t size;
+ uint32_t tlbhi_flags;
+ uint32_t tlblo_flags;
+ Ppc405MmuMap* map;
+} MmuRegion;
+
+// The section table along with (default) MMU characteristics. Global
+// Ppc405MmuMap variables are defined for certain sections so that those
+// mappings may be later modified.
+
+Ppc405MmuMap G_ex_free_mmu_map;
+Ppc405MmuMap G_applet0_mmu_map;
+Ppc405MmuMap G_applet1_mmu_map;
+
+static const MmuRegion mmu_regions[] = {
+
+ {(SsxAddress)&_TEXT0_SECTION_BASE,
+ (size_t)&_TEXT0_SECTION_SIZE,
+ 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} ,
+
+ {(SsxAddress)&_TEXT1_SECTION_BASE,
+ (size_t)&_TEXT1_SECTION_SIZE,
+ 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} ,
+
+ {(SsxAddress)&_RODATA_SECTION_BASE,
+ (size_t)&_RODATA_SECTION_SIZE,
+ 0, DATA_CACHEABILITY_FLAG, 0} ,
+
+ {(SsxAddress)&_NONCACHEABLE_RO_SECTION_BASE,
+ (size_t)&_NONCACHEABLE_RO_SECTION_SIZE,
+ 0, TLBLO_I, 0} ,
+
+ {(SsxAddress)&_NONCACHEABLE_SECTION_BASE,
+ (size_t)&_NONCACHEABLE_SECTION_SIZE,
+ 0, TLBLO_I | TLBLO_WR, 0} ,
+
+ {(SsxAddress)&_WRITETHROUGH_SECTION_BASE,
+ (size_t)&_WRITETHROUGH_SECTION_SIZE,
+ 0, DATA_CACHEABILITY_FLAG | WRITETHROUGH_FLAG | TLBLO_WR, 0} ,
+
+ {(SsxAddress)&_DATA_SECTION_BASE,
+ (size_t)&_DATA_SECTION_SIZE,
+ 0, DATA_CACHEABILITY_FLAG | TLBLO_WR, 0} ,
+
+ {(SsxAddress)&_EX_FREE_SECTION_BASE,
+ (size_t)&_EX_FREE_SECTION_SIZE,
+ 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_EX | TLBLO_WR,
+ &G_ex_free_mmu_map},
+
+ {(SsxAddress)&_APPLET0_SECTION_BASE,
+ (size_t)&_APPLET0_SECTION_SIZE,
+ 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX,
+ &G_applet0_mmu_map},
+
+ {(SsxAddress)&_APPLET1_SECTION_BASE,
+ (size_t)&_APPLET1_SECTION_SIZE,
+ 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX,
+ &G_applet1_mmu_map},
+
+ {(SsxAddress)OCI_REGISTER_SPACE_BASE,
+ (size_t)OCI_REGISTER_SPACE_SIZE,
+ 0, TLBLO_WR | TLBLO_I | TLBLO_G, 0} ,
+};
+
+/// PgP MMU setup
+///
+/// Run down the mmu_regions[] array and map all regions with non-0 sizes.
+/// These are direct maps, setting the effective address to the physical
+/// address. Once the MMU is set up MMU protection is enabled.
+///
+/// Any OCC mappings of PBA space will have to be done elsewhere, as these
+/// memory areas are controlled by pHyp, and the product firmware has no plans
+/// to access main memory from the OCC.
+
+static void
+pgp_mmu_setup()
+{
+ int i, regions;
+
+ ppc405_mmu_reset();
+
+ regions = sizeof(mmu_regions) / sizeof(MmuRegion);
+ for (i = 0; i < regions; i++) {
+ if (mmu_regions[i].size != 0) {
+ ppc405_mmu_map(mmu_regions[i].base,
+ mmu_regions[i].base,
+ mmu_regions[i].size,
+ mmu_regions[i].tlbhi_flags,
+ mmu_regions[i].tlblo_flags,
+ mmu_regions[i].map);
+ }
+ }
+
+ ppc405_mmu_start();
+}
+
+#endif /* PPC405_MMU_SUPPORT */
+
+
+// I/O Initialization
+//
+// Initialize the SSX/Simics/Verification Serial I/O channels. This is done
+// early in the initialization to allow initialization code to use printk().
+// If the application does not select one of the I/O methods then 'ssxout'
+// defaults to the NULL stream and 'stdin', 'stdout' and 'stderr' are
+// undefined.
+
+#if USE_TRACE_IO || USE_EPM_IO
+
+WrappingStream G_ssxout
+SECTION_ATTRIBUTE(".noncacheable") = {{0}};
+
+uint8_t G_ssxout_buffer[SSXOUT_TRACE_BUFFER_SIZE]
+SECTION_ATTRIBUTE(".noncacheable") = {0};
+
+#endif // USE_TRACE_IO || USE_EPM_IO
+
+static void
+io_setup()
+{
+ //NB: These I/O options are listed in priority order - multiple options may
+ //be selected.
+#if USE_TRACE_IO
+
+ // If the application chooses to use trace buffer output, the application
+ // must define SSXOUT_TRACE_BUFFER_SIZE, and all output streams are merged
+ // into a single trace buffer which locks low-level file operations in an
+ // SSX_CRITICAL critical secton.
+
+ /// \todo Split trace I/O mode into multiple streams
+
+ wrapping_stream_create(&G_ssxout, &G_ssxout_buffer,
+ SSXOUT_TRACE_BUFFER_SIZE,
+ SSX_FILE_OP_LOCK_CRITICAL);
+
+ stdout = (FILE *)(&G_ssxout);
+ stderr = (FILE *)(&G_ssxout);
+ ssxout = (FILE *)(&G_ssxout);
+
+#elif USE_EPM_IO
+
+ linear_stream_create(&G_ssxout, &G_ssxout_buffer,
+ SSXOUT_TRACE_BUFFER_SIZE,
+ SSX_FILE_OP_LOCK_CRITICAL);
+
+ stdout = (FILE *)(&G_ssxout);
+ stderr = (FILE *)(&G_ssxout);
+ ssxout = (FILE *)(&G_ssxout);
+
+#elif USE_RTX_IO
+
+ rtx_stdin_create(&rtx_stdin);
+ rtx_stdout_create(&rtx_stdout);
+ rtx_stderr_create(&rtx_stderr);
+
+ stdin = (FILE *)(&rtx_stdin);
+ stdout = (FILE *)(&rtx_stdout);
+ stderr = (FILE *)(&rtx_stderr);
+ ssxout = (FILE *)(&rtx_stdout);
+
+ printf("Initialize the RTX stdio.\n");
+ printf("RTX stdin is not implemented.\n");
+
+#elif USE_SIMICS_IO
+
+ simics_stdin_create(&simics_stdin);
+ simics_stdout_create(&simics_stdout);
+ simics_stderr_create(&simics_stderr);
+
+ stdin = (FILE *)(&simics_stdin);
+ stdout = (FILE *)(&simics_stdout);
+ stderr = (FILE *)(&simics_stderr);
+ ssxout = (FILE *)(&simics_stdout);
+
+#endif // I/O Configuration
+}
+
+
+/// PgP environment initial setup.
+///
+/// This is setup common to all PgP applications. This setup takes place
+/// during boot, before main() is called.
+
+void
+__pgp_setup()
+{
+ // All OCB interrupts are masked. The SSX/PPC405 Boot code masks PPC405
+ // PIT, FIT, and Watchdog interrupts. All interrupts are also initially
+ // set up as noncritical, non-debugged, edge-triggered, active-high, and
+ // their status is cleared. This clarifies IPL debugging as it eliminates
+ // spurious "asserted" interrupts until the firmware comes in and actually
+ // sets up the interrupt.
+
+ out32(OCB_OIMR0, 0xffffffff); /* Masked */
+ out32(OCB_OIMR1, 0xffffffff);
+ out32(OCB_OITR0, 0xffffffff); /* Edge */
+ out32(OCB_OITR1, 0xffffffff);
+ out32(OCB_OIEPR0, 0xffffffff); /* Active High */
+ out32(OCB_OIEPR1, 0xffffffff);
+ out32(OCB_OCIR0, 0); /* Noncritical */
+ out32(OCB_OCIR1, 0);
+ out32(OCB_OISR0_AND, 0); /* Clear Status */
+ out32(OCB_OISR1_AND, 0);
+ out32(OCB_OUDER0, 0); /* No Unconditional Debug Event */
+ out32(OCB_OUDER1, 0);
+ out32(OCB_ODHER0, 0); /* No Debug Halt Event */
+ out32(OCB_ODHER1, 0);
+
+ // Setup requires SCOM, which requires a timeout. Therefore we need to set
+ // up a default timebase frequency, which may be overridden during
+ // ssx_initialize().
+
+ __ssx_timebase_frequency_hz = 600000000;
+ __ssx_timebase_frequency_khz = 600000;
+ __ssx_timebase_frequency_mhz = 600;
+
+ // Set up I/O. This is done early in the initialization so that
+ // initialization drivers can use printk().
+
+ io_setup();
+
+ // Cache the device identification and chip configuration
+ _pgp_get_ids();
+ _pgp_get_chip_configuration();
+
+ // Set up the PLB arbiter
+
+ plb_arbiter_setup();
+
+ // If the MMU is enabled the base image MMU programming is set up, and the
+ // MMU is activated.
+
+#if PPC405_MMU_SUPPORT
+ pgp_mmu_setup();
+#endif
+
+ // The PgP Async drivers are initialized.
+
+ async_initialize();
+}
diff --git a/src/ssx/pgp/pgp_irq.h b/src/ssx/pgp/pgp_irq.h
new file mode 100755
index 0000000..f45ed52
--- /dev/null
+++ b/src/ssx/pgp/pgp_irq.h
@@ -0,0 +1,252 @@
+#ifndef __PGP_IRQ_H__
+#define __PGP_IRQ_H__
+
+// $Id: pgp_irq.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_irq.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_irq.h
+/// \brief PPC405-PgP Interrupt handling for SSX
+///
+/// The PgP interrupt controller supports a maximum of 64 interrupts, split
+/// into 2 x 32-bit non-cascaded interrupt controllers with simple OR
+/// combining of the interrupt signals.
+///
+/// The PGP interrupt controller allows interrupt status to be set directly by
+/// software, as well as providing a mode that causes an enabled pending
+/// interrupt to trigger an Unconditional Debug Event. The PGP interrupt
+/// controller contains a 'mask' register, unlike other 405 interrupt
+/// controllers that have an 'enable' register. The PgP mask and status
+/// registers also have atomic AND/OR function so that it is never necessary
+/// to enter a critical section to enable/disable/clear interrupts and
+/// interrupt status.
+
+#include "pgp_common.h"
+#include "ocb_register_addresses.h"
+
+#ifndef __ASSEMBLER__
+
+/// Enable an interrupt by clearing the mask bit.
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+inline void
+ssx_irq_enable(SsxIrqId irq)
+{
+ out32(OCB_OIMR_AND(irq), ~PGP_IRQ_MASK32(irq));
+}
+
+
+/// Disable an interrupt by setting the mask bit.
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+inline void
+ssx_irq_disable(SsxIrqId irq)
+{
+ out32(OCB_OIMR_OR(irq), PGP_IRQ_MASK32(irq));
+}
+
+
+/// Clear interrupt status with an AND mask. Only meaningful for
+/// edge-triggered interrupts.
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+inline void
+ssx_irq_status_clear(SsxIrqId irq)
+{
+ out32(OCB_OISR_AND(irq), ~PGP_IRQ_MASK32(irq));
+}
+
+
+/// Get IRQ status as a 0 or non-0 integer
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+inline int
+ssx_irq_status_get(SsxIrqId irq)
+{
+ return (in32(OCB_OISR(irq)) & PGP_IRQ_MASK32(irq)) != 0;
+}
+
+
+/// Set or clear interrupt status explicitly.
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+inline void
+ssx_irq_status_set(SsxIrqId irq, int value)
+{
+ if (value) {
+ out32(OCB_OISR_OR(irq), PGP_IRQ_MASK32(irq));
+ } else {
+ out32(OCB_OISR_AND(irq), ~PGP_IRQ_MASK32(irq));
+ }
+}
+
+
+void
+ssx_irq_debug_set(SsxIrqId irq, int value);
+
+#endif /* __ASSEMBLER__ */
+
+/// \page pgp_irq_macros PgP IRQ API Assembler Macros
+///
+/// These macros encapsulate the SSX API for the PgP interrupt
+/// controller. These macros require 2 scratch registers in addition to the \c
+/// irq parameter register passed into the handler from SSX interrupt
+/// dispatch. These macros also modift CR0.
+///
+/// \arg \c rirq A register that holds the \c irq parameter passed to
+/// the handler from SSX interrupt dispatch. This register is not
+/// modified.
+/// \arg \c rmask A scratch register - At the end of macro execution this
+/// register contains the 32-bit mask form of the irq.
+///
+/// \arg \c raddr A scratch register - At the end of macro execution this
+/// register holds the address of the interrupt
+/// controller facility that implements the action.
+///
+/// \arg \c imm An immediate (0/non-0) value for certain macros.
+///
+/// Forms:
+///
+/// \b _ssx_irq_enable \a rirq, \a rmask, \a raddr - Enable an \c irq. \n
+/// \b _ssx_irq_disable \a rirq, \a rmask, \a raddr - Disable an \c irq. \n
+/// \b _ssx_irq_status_clear \a rirq, \a rmask, \a raddr - Clear \c irq
+/// interrupt status. \n
+/// \b _ssx_irq_status_set \a rirq, \a rmask, \a raddr, \a imm - Set \c irq status
+/// with an immediate (0/non-0) value. \n
+///
+/// \todo Once the logic design is locked down, revisit whether these macros
+/// (and C-code versions) can be implemented without branching. This could be
+/// done in theory by converting bit 26 into the byte offset between addresses
+/// in interupt controller 0 and interrupt controller 1 - assuming the
+/// distances are all the same power-of-two.
+///
+/// \cond
+
+// IRQ numbers are in the range 0..63. IRQs are converted to the 32-bit
+// residue used to compute the mask. CR0 is set as a test of IRQ > 32 - the
+// register \c raddr is used as scratch for these computations. Hopefully the
+// local labels 888 and 999 are unique enough.
+
+// Register names must be compared as strings - e.g., %r0 is not
+// a symbol, it is converted to "0" by the assembler.
+
+#ifdef __ASSEMBLER__
+
+ .macro .two_unique, ra, rb
+ .ifnc \ra, \rb
+ .exitm
+ .endif
+ .error "Both register arguments must be unique"
+ .endm
+
+
+ .macro .three_unique, ra, rb, rc
+ .ifnc \ra, \rb
+ .ifnc \rb, \rc
+ .ifnc \ra, \rc
+ .exitm
+ .endif
+ .endif
+ .endif
+ .error "All three register arguments must be unique"
+ .endm
+
+
+ .macro _pgp_irq_or_mask, rirq:req, rmask:req
+ .two_unique \rirq, \rmask
+ lis \rmask, 0x8000
+ srw \rmask, \rmask, \rirq
+ .endm
+
+ .macro _pgp_irq_and_mask, rirq:req, rmask:req
+ .two_unique \rirq, \rmask
+ _pgp_irq_or_mask \rirq, \rmask
+ not \rmask, \rmask
+ .endm
+
+
+ .macro _ssx_irq_enable, rirq:req, rmask:req, raddr:req
+ .three_unique \rirq, \rmask, \raddr
+
+ andi. \raddr, \rirq, 0x20
+ clrlwi \raddr, \rirq, 27
+ _pgp_irq_and_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OIMR0_AND
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OIMR1_AND
+999:
+ eieio
+ .endm
+
+
+ .macro _ssx_irq_disable, rirq:req, rmask:req, raddr:req
+ .three_unique \rirq, \rmask, \raddr
+
+ andi. \raddr, \rirq, 0x20
+ clrlwi \raddr, \rirq, 27
+ _pgp_irq_or_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OIMR0_OR
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OIMR1_OR
+999:
+ eieio
+ .endm
+
+
+ .macro _ssx_irq_status_clear, rirq:req, rmask:req, raddr:req
+ .three_unique \rirq, \rmask, \raddr
+
+ andi. \raddr, \rirq, 0x20
+ clrlwi \raddr, \rirq, 27
+ _pgp_irq_and_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OISR0_AND
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OISR1_AND
+999:
+ eieio
+ .endm
+
+
+ .macro _ssx_irq_status_set, rirq:req, rmask:req, raddr:req, imm:req
+ .three_unique \rirq, \rmask, \raddr
+
+ andi. \raddr, \rirq, 0x20
+ clrlwi \raddr, \rirq, 27
+
+ .if \imm
+ _pgp_irq_or_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OISR0_OR
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OISR1_OR
+
+ .else
+
+ _pgp_irq_and_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OISR0_AND
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OISR1_AND
+ .endif
+
+999:
+ eieio
+ .endm
+
+#endif /* __ASSEMBLER__ */
+
+/// \endcond
+
+#endif /* __PGP_IRQ_H__ */
diff --git a/src/ssx/pgp/pgp_irq_init.c b/src/ssx/pgp/pgp_irq_init.c
new file mode 100755
index 0000000..6719766
--- /dev/null
+++ b/src/ssx/pgp/pgp_irq_init.c
@@ -0,0 +1,155 @@
+// $Id: pgp_irq_init.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_irq_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_irq_init.c
+/// \brief PGP IRQ initialization code for SSX
+///
+/// The entry points in this file are initialization rotines that could be
+/// eliminated/deallocated by the application to free up storage if they are
+/// no longer needed after initialization.
+
+#include "ssx.h"
+
+/// Define the polarity and trigger condition for an interrupt.
+///
+/// It is up to the application to take care of any side effects that may
+/// occur from programming or reprogramming the interrupt controller. For
+/// example, changing edge/level sensitivity or active level may set or clear
+/// interrupt status in the controller.
+///
+/// Note that SSX allows this API to be called from any context, and changes
+/// to the interrupt controller are made from an SSX_CRITICAL critical
+/// section.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid,
+/// including an invalid \a irq, or invalid \a polarity or \a trigger parameters.
+
+int
+ssx_irq_setup(SsxIrqId irq,
+ int polarity,
+ int trigger)
+{
+ SsxMachineContext ctx;
+ uint32_t oitr, oeipr;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(!PGP_IRQ_VALID(irq) ||
+ !((polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) ||
+ (polarity == SSX_IRQ_POLARITY_ACTIVE_LOW)) ||
+ !((trigger == SSX_IRQ_TRIGGER_LEVEL_SENSITIVE) ||
+ (trigger == SSX_IRQ_TRIGGER_EDGE_SENSITIVE)),
+ SSX_INVALID_ARGUMENT_IRQ_SETUP);
+ }
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ oeipr = in32(OCB_OIEPR(irq));
+ if (polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) {
+ out32(OCB_OIEPR(irq), oeipr | PGP_IRQ_MASK32(irq));
+ } else {
+ out32(OCB_OIEPR(irq), oeipr & ~PGP_IRQ_MASK32(irq));
+ }
+
+ oitr = in32(OCB_OITR(irq));
+ if (trigger == SSX_IRQ_TRIGGER_EDGE_SENSITIVE) {
+ out32(OCB_OITR(irq), oitr | PGP_IRQ_MASK32(irq));
+ } else {
+ out32(OCB_OITR(irq), oitr & ~PGP_IRQ_MASK32(irq));
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// (Re)define the IRQ handler and priority for an interrupt.
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// Note that SSX allows this API to be called from any context, and changes
+/// to the interrupt controller are made from an SSX_CRITICAL critical
+/// section.
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are
+/// invalid, including an invalid \a irq, a null (0) \a handler,
+/// or invalid \a priority.
+
+int
+ssx_irq_handler_set(SsxIrqId irq,
+ SsxIrqHandler handler,
+ void *arg,
+ int priority)
+{
+ SsxMachineContext ctx;
+ uint32_t ocir;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(!PGP_IRQ_VALID(irq) ||
+ (handler == 0) ||
+ !((priority == SSX_NONCRITICAL) ||
+ (priority == SSX_CRITICAL)),
+ SSX_INVALID_ARGUMENT_IRQ_HANDLER);
+ }
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ ocir = in32(OCB_OCIR(irq));
+ if (priority == SSX_CRITICAL) {
+ out32(OCB_OCIR(irq), ocir | PGP_IRQ_MASK32(irq));
+ } else {
+ out32(OCB_OCIR(irq), ocir & ~PGP_IRQ_MASK32(irq));
+ }
+
+ __ppc405_irq_handlers[irq].handler = handler;
+ __ppc405_irq_handlers[irq].arg = arg;
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Set or clear interrupt debug mode explicitly.
+
+void
+ssx_irq_debug_set(SsxIrqId irq, int value)
+{
+ SsxMachineContext ctx;
+ uint32_t ouder;
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ ouder = in32(OCB_OUDER(irq));
+ if (value) {
+ out32(OCB_OUDER(irq), ouder | PGP_IRQ_MASK32(irq));
+ } else {
+ out32(OCB_OUDER(irq), ouder & ~PGP_IRQ_MASK32(irq));
+ }
+
+ ssx_critical_section_exit(&ctx);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ssx/pgp/pgp_ocb.c b/src/ssx/pgp/pgp_ocb.c
new file mode 100755
index 0000000..e39475e
--- /dev/null
+++ b/src/ssx/pgp/pgp_ocb.c
@@ -0,0 +1,335 @@
+// $Id: pgp_ocb.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_ocb.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_ocb.c
+/// \brief OCB-related drivers for PgP
+
+#include "ssx.h"
+
+//use compile-time default in case the OCB timer is never used -- grm
+unsigned int g_ocb_timer_divider = OCB_TIMER_DIVIDER_DEFAULT;
+
+/// Reset an OCB timer
+///
+/// \param timer A valid OCB timer index
+///
+/// \param auto_reload A non-0 value indicates to run the timer in auto-reload
+/// mode.
+///
+/// \param timeout_ns The timeout specified in nanoseconds. The actual timeout
+/// will be rounded down to the underlying timer tick, with a minimum 1 tick
+/// timeout. However if the \a timeout_ns argument is explicity 0, then the
+/// timer wil be initialized with a 0 timeout, effectively disabling the
+/// timer.
+///
+/// Reseting an OCB timer means rewriting the timer control register with a
+/// potentially new auto-reload enable and new timeout value. This API also
+/// clears any pending timer interrupt status.
+///
+/// \retval 0 Success
+///
+/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer
+/// numbers and illegal or unrepresntable timeouts.
+
+// Note that OCB_TIMER_FREQUENCY_HZ is in the range of 1-2 MHz.
+
+int
+ocb_timer_reset(int timer,
+ int auto_reload,
+ int timeout_ns)
+{
+ ocb_otrn_t otr;
+ int ticks;
+
+ //printk("ocb_timer_reset(%d, %d, %d)\n",
+ // timer, auto_reload, timeout_ns);
+
+ if (timeout_ns != 0) {
+ ticks = MAX(1, timeout_ns / (1000000000 / OCB_TIMER_FREQUENCY_HZ));
+ } else {
+ ticks = 0;
+ }
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((timer < 0) ||
+ (timer >= OCB_TIMERS) ||
+ (timeout_ns < 0) ||
+ (ticks != ((uint16_t)ticks)),
+ OCB_INVALID_ARGUMENT_TIMER);
+ }
+
+ otr.value = 0;
+
+ otr.fields.timeout = 1;
+ otr.fields.control = 1;
+ otr.fields.auto_reload = (auto_reload != 0);
+ otr.fields.timer = ticks;
+
+ out32(OCB_OTRN(timer), otr.value);
+
+ return 0;
+}
+
+
+/// Set up an OCB timer and interrupt handler
+///
+/// \param timer A valid OCB timer index
+///
+/// \param auto_reload A non-0 value indicates to run the timer in auto-reload
+/// mode.
+///
+/// \param timeout_ns The timeout specified in nanoseconds. The actual timeout
+/// will rounded down to the underlying timer tick, with a minimum 1 tick
+/// timeout. However if the \a timeout_ns argument is explicity 0, then the
+/// timer wil be initialized with a 0 timeout, effectively disabling the
+/// timer.
+///
+/// \param handler The interrupt handler for the timer interrupt
+///
+/// \param arg The private argument of the interrupt handler
+///
+/// \param priority The SSX/PPC405 interrupt priority to assign to the
+/// interrupt.
+///
+/// This API sets up and starts the timer and unmasks the timer
+/// interrupt. Once set up, the timer can be reset using ocb_timer_reset(). As
+/// a fine point of the specification, if a timer interrupt is already pending
+/// when this API is invoked then that interrupt will be cleared. Only the
+/// next interrupt (corresponding to the new programming) will be serviced by
+/// the newly installed handler.
+///
+/// Note that the interrupt handler is responsible for clearing the timer
+/// interrupt status. An API ocb_timer_status_clear() is available for this.
+///
+/// \retval 0 Success
+///
+/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer
+/// numbers and illegal or unrepresntable timeouts.
+///
+/// Other errors may be returned by the underlying calls to SSX routines that
+/// set up interrupts.
+
+int
+ocb_timer_setup(int timer,
+ int auto_reload,
+ int timeout_ns,
+ SsxIrqHandler handler,
+ void *arg,
+ int priority)
+{
+ int rc;
+ tpc_hpr2_t l_hpr2;
+
+ do
+ {
+ //Read Hang Pulse Register 2 to get the log base 2 of the ocb clock divider -- grm
+ rc = getscom(TPC_HPR2, &l_hpr2.value);
+ if(rc)
+ {
+ break;
+ }
+
+ g_ocb_timer_divider = 1 << l_hpr2.fields.hang_pulse_reg;
+
+ //printk("ocb_timer_setup(%d, %d, %d, %p, %p, %d)\n",
+ // timer, auto_reload, timeout_ns,
+ // handler, arg, priority);
+
+ ssx_irq_disable(PGP_IRQ_OCC_TIMER0 + timer);
+
+ ssx_irq_setup(PGP_IRQ_OCC_TIMER0 + timer,
+ SSX_IRQ_POLARITY_ACTIVE_HIGH,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+
+ ssx_irq_handler_set(PGP_IRQ_OCC_TIMER0 + timer,
+ handler,
+ arg,
+ priority);
+
+ rc = ocb_timer_reset(timer, auto_reload, timeout_ns);
+
+ ssx_irq_enable(PGP_IRQ_OCC_TIMER0 + timer);
+ }while(0);
+
+ return rc;
+}
+
+
+/// Generate an core interrupt via the PSI Host Bridge
+///
+/// Setting OCB_OCCMISC.core_ext_int to 1 causes a wire to pulse to the PSI
+/// Host Bridge to allow the presentation of an external interrupt to a core
+/// thread. The core thread to be interrupted is controlled by the XIVR - OCC
+/// register, SCOM 02010916. Normally the hypervisor will set up the PSI Host
+/// Bridge. This procedure allows OCC to send an interrupt to the hypervisor.
+///
+/// \retval 0 Success
+
+// The interrupt is generated by causing a 0->1 transation on
+// OCB_OCCMISC.core_ext_intr. This is implemented here using the WAND/WOR
+// forms of the register.
+
+int
+ocb_core_interrupt()
+{
+ ocb_occmisc_t oo;
+
+ oo.value = 0;
+ oo.fields.core_ext_intr = 1;
+ out32(OCB_OCCMISC_AND, ~oo.value);
+ out32(OCB_OCCMISC_OR, oo.value);
+
+ return 0;
+}
+
+
+/// Procedure to setup a linear window on an indirect channel
+///
+///
+/// Since the linear window access is restricted to the SRAM region of
+/// OCI space, Bits 0:4 of the base parameter are don't care and will be
+/// overwritten with b'11000'
+///
+///
+/// \todo double check SRAM region restriction
+///
+/// \param channel The indirect channel to use, in the range 0..2.
+///
+/// \param base The 32-bit PowerBus base address where the block starts. This
+/// address must be aligned to the \a log_size.
+///
+/// \param log_size The base 2 logarithm of the block size, in bytes. The
+/// minimum size is 8B (2**3), the maximum size is 32KB (2**15)
+///
+///
+/// \retval 0 Success
+///
+/// \retval OCB_INVALID_ARGUMENT_LW_INIT One or more of the parameter
+/// restrictions were violated.
+///
+/// \retval OCB_SCOM_ERROR An attempt to write a PBA SCOM register to set up
+/// the BARs produced a non-zero return code.
+
+int
+ocb_linear_window_initialize(int channel, uint32_t base, int log_size)
+{
+ uint32_t mask ;
+ ocb_ocblwcrn_t ocblwcrn;
+ ocb_ocblwsbrn_t ocblwsbrn;
+
+ // create mask for checking
+ mask = (0x1ull << log_size) - 1;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((channel < 0) ||
+ (channel > 2) ||
+ (log_size < OCB_LW_LOG_SIZE_MIN) ||
+ (log_size > OCB_LW_LOG_SIZE_MAX) ||
+ ((base & mask) != 0),
+ OCB_INVALID_ARGUMENT_LW_INIT);
+ }
+
+ // now invert mask for use in ocb linear window setup
+ mask = ~mask;
+
+
+ // Configure OCB Linear Write Control Register
+ ocblwcrn.fields.linear_window_enable = 1;
+ // base 13:28 (16 bits)
+ ocblwcrn.fields.linear_window_bar = (base >> 3) & 0xFFFF;
+ // mask 17:28 (12 bits)
+ ocblwcrn.fields.linear_window_mask = (mask >> 3) & 0xFFF;
+ out32(OCB_OCBLWCRN(channel), ocblwcrn.value);
+
+ // Configure OCB Linear Window Write Base Register
+ ocblwsbrn.fields.linear_window_region = 3; // SRAM only
+ // \todo: Are there constants for the OCI regions?
+ // base 2:9 (8 bits)
+ ocblwsbrn.fields.linear_window_base = (base >> 19) & 0xFF;
+ out32(OCB_OCBLWSBRN(channel), ocblwsbrn.value);
+
+ return 0 ;
+}
+
+/// Procedure to disable a linear window on an indirect channel
+///
+/// This procedure will disable the linear window while maintaining
+/// the linear_window_bar and linear_window_mask settings
+///
+/// \param channel The indirect channel to disable, in the range 0..2.
+///
+/// \retval 0 Success
+///
+/// \retval OCB_INVALID_ARGUMENT_LW_DISABLE One or more of the parameter
+/// restrictions were violated.
+///
+
+int
+ocb_linear_window_disable(int channel)
+{
+ ocb_ocblwcrn_t ocblwcrn;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((channel < 0) ||
+ (channel > 2),
+ OCB_INVALID_ARGUMENT_LW_DISABLE);
+ }
+
+ ocblwcrn.value = in32(OCB_OCBLWCRN(channel));
+ // Configure OCB Linear Write Control Register
+ ocblwcrn.fields.linear_window_enable = 0;
+ out32(OCB_OCBLWCRN(channel), ocblwcrn.value);
+
+ return 0 ;
+}
+
+
+/// Procedure for setting up untrusted mode for an indirect channel
+///
+/// Note that the OCC FW is expected to enable the channel for FSP
+/// access. As an untrusted master, the FSP cannot configure this
+/// in a chip running in trusted mode. The SBE is considered a trusted
+/// master.
+///
+///
+/// \param channel The indirect channel to use, in the range 0..2
+/// Note that this bit is not used for indirect channel 3.
+///
+///
+/// \param allow_untrusted Enable untrusted PIB masters
+/// access to the indirect channel being configured. If allow_untrusted is
+/// not enabled and the chip is running in trusted mode, then any untrusted
+/// PIB master will get an offline return code when attempting to write
+/// the indirect channel. 0 = Disable, 1 = Enable
+///
+/// \retval 0 Success
+///
+/// \retval OCB_INVALID_ARGUMENT_UNTRUST One or more of the parameter
+/// restrictions were violated.
+///
+
+
+int
+ocb_allow_untrusted_initialize(int channel, int allow_untrusted)
+{
+ ocb_ocbicrn_t ocbicrn;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((channel < 0) ||
+ (channel > 2) ||
+ (allow_untrusted < 0) ||
+ (allow_untrusted > 1),
+ OCB_INVALID_ARGUMENT_UNTRUST);
+ }
+
+ // Configure allow_unsecure_pib_masters bit
+ ocbicrn.fields.allow_unsecure_pib_masters = allow_untrusted;
+ out32(OCB_OCBICRN(channel), ocbicrn.value);
+
+ return 0 ;
+}
diff --git a/src/ssx/pgp/pgp_ocb.h b/src/ssx/pgp/pgp_ocb.h
new file mode 100755
index 0000000..fd36c9a
--- /dev/null
+++ b/src/ssx/pgp/pgp_ocb.h
@@ -0,0 +1,88 @@
+#ifndef __PGP_OCB_H__
+#define __PGP_OCB_H__
+
+// $Id: pgp_ocb.h,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_ocb.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_ocb.h
+/// \brief OCB unit header. Local and mechanically generated macros and APIs.
+
+#include "ssx.h"
+#include "ppc32.h"
+
+#include "pgp_common.h"
+#include "ocb_register_addresses.h"
+#include "ocb_firmware_registers.h"
+
+#include "ppc405_irq.h"
+
+#define OCB_TIMER0 0
+#define OCB_TIMER1 1
+
+#define OCB_TIMERS 2
+
+#define OCB_TIMER_ONE_SHOT 0
+#define OCB_TIMER_AUTO_RELOAD 1
+
+#define OCB_LW_LOG_SIZE_MIN 3
+#define OCB_LW_LOG_SIZE_MAX 15
+
+#define OCB_INVALID_ARGUMENT_TIMER 0x00622001
+#define OCB_INVALID_ARGUMENT_LW_INIT 0x00622002
+#define OCB_INVALID_ARGUMENT_LW_DISABLE 0x00622003
+#define OCB_INVALID_ARGUMENT_UNTRUST 0x00622004
+
+#ifndef __ASSEMBLER__
+
+int
+ocb_timer_reset(int timer,
+ int auto_reload,
+ int timeout_ns);
+
+#ifdef OCC
+int
+ocb_timer_setup(int timer,
+ int auto_reload,
+ int timeout_ns,
+ SsxIrqHandler handler,
+ void *arg,
+ int priority) INIT_SECTION;
+#else
+int
+ocb_timer_setup(int timer,
+ int auto_reload,
+ int timeout_ns,
+ SsxIrqHandler handler,
+ void *arg,
+ int priority);
+#endif
+
+/// Clear OCB timer status based on the IRQ
+///
+/// This API can be called from OCB timer interrupt handlers, using the IRQ
+/// provided to the handler. No error checks are provided.
+
+static inline void
+ocb_timer_status_clear(SsxIrqId irq)
+{
+ out32(OCB_OTRN(irq - PGP_IRQ_OCC_TIMER0), OCB_OTRN_TIMEOUT);
+}
+
+int
+ocb_linear_window_initialize(int channel, uint32_t base, int log_size);
+
+int
+ocb_linear_window_disable(int channel);
+
+int
+ocb_allow_untrusted_initialize(int channel, int allow_untrusted);
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PGP_OCB_H__ */
diff --git a/src/ssx/pgp/pgp_pba.c b/src/ssx/pgp/pgp_pba.c
new file mode 100755
index 0000000..0f5d2d9
--- /dev/null
+++ b/src/ssx/pgp/pgp_pba.c
@@ -0,0 +1,460 @@
+// $Id: pgp_pba.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pba.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_pba.c
+/// \brief procedures for pba setup and operation.
+
+#include "ssx.h"
+#include "pgp_pba.h"
+#include "pgp_pmc.h"
+#include "pgp_common.h"
+#include "polling.h"
+
+
+// Internal API to set up a PBA BAR
+
+static int
+pba_bar_set(int idx, uint64_t pb_base, uint8_t pb_scope)
+{
+ int rc ;
+ pba_barn_t bar ;
+
+ bar.fields.cmd_scope = pb_scope ;
+ bar.fields.addr = pb_base >> PBA_LOG_SIZE_MIN ;
+
+ rc = putscom(PBA_BARN(idx), bar.value);
+
+ return rc ;
+}
+
+
+// Internal API to set up a PBA BAR Mask. The mask covers bits 23:43, address
+// bits 44:63 are always allowed.
+
+static int
+pba_barmask_set(int idx, uint64_t mask)
+{
+ int rc ;
+ pba_barmskn_t barmask ;
+
+ barmask.value = mask & 0x000001FFFFF00000ull;
+
+ rc = putscom(PBA_BARMSKN(idx), barmask.value);
+
+ return rc ;
+}
+
+
+/// Procedure to allocate a PowerBus address block using the bridge.
+///
+/// \param idx The BAR set to use, in the range 0..3.
+///
+/// \param base The 50-bit PowerBus base address where the block starts. This
+/// address must be aligned to the \a log_size.
+///
+/// \param log_size The base 2 logarithm of the block size, in bytes. The
+/// minimum size is 1MB (2**20), the maximum size is 2TB (2**41)
+///
+/// This is a validation/test procedure only, since setting up the PBA BARs is
+/// normally reserved to pHyp and FSP. If the MMU is enabled and the PBA
+/// mapping will be referenced by the 405, then an MMU mapping will also have
+/// to be created (separately) for the block.
+///
+/// This procedure is not the complete setup for large memory areas. Memory
+/// areas that require the extended address will have to set that up
+/// separately.
+///
+/// \retval 0 Success
+///
+/// \retval PBA_INVALID_ARGUMENT_BARSET One or more of the parameter
+/// restrictions were violated.
+///
+/// \retval PBA_SCOM_ERROR1 or PBA_SCOM_ERROR2 An attempt to write a PBA SCOM
+/// register to set up the BARs produced a non-zero return code.
+
+int
+pba_barset_initialize(int idx, uint64_t base, int log_size)
+{
+ uint64_t mask ;
+
+ mask = (0x1ull << log_size) - 1;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((idx < 0) ||
+ (idx > 3) ||
+ (log_size < PBA_LOG_SIZE_MIN) ||
+ (log_size > PBA_LOG_SIZE_MAX) ||
+ ((base & mask) != 0),
+ PBA_INVALID_ARGUMENT_BARSET);
+ }
+
+ if (pba_bar_set(idx, base, PBA_POWERBUS_COMMAND_SCOPE_DEFAULT)) {
+ SSX_ERROR(PBA_SCOM_ERROR1);
+ }
+ if (pba_barmask_set(idx, mask)) {
+ SSX_ERROR(PBA_SCOM_ERROR2);
+ }
+
+ return 0 ;
+}
+
+
+// polling() function for PBA Slave reset
+//
+// Slave reset for PBA is a complex issue, especially in cases where the
+// entity requesting the reset may be executing from main memory, i.e.
+// continuing to read to or write from the slave being reset. To work around
+// potential issues if the 405 is attempting to reset its own slave, the code
+// that polls for reset is PowerBus cache-line aligned, and we re-hit the
+// reset button each time we get an unsuccessful poll for the reset being
+// done. This should guarantee that the slave will go to reset status as soon
+// as any PowerBus blockages (if any) clear and the master stops either
+// reading or writing the slave port. For details see HW228485.
+int
+_pba_slave_reset_poll(void* arg, int* done) ALIGNED_ATTRIBUTE(128);
+
+int
+_pba_slave_reset_poll(void* arg, int* done)
+{
+ int id;
+ pba_slvrst_t psr;
+
+ id = (int)arg;
+
+ psr.value = 0;
+ psr.fields.set = PBA_SLVRST_SET(id);
+ out64(PBA_SLVRST, psr.value);
+
+ psr.value = in64(PBA_SLVRST);
+ *done = !(psr.fields.in_prog & PBA_SLVRST_IN_PROG(id));
+
+ return 0;
+}
+
+
+/// Reset a PBA slave with explicit timeout.
+///
+/// \param id A PBA slave id in the range 0..3
+///
+/// \param timeout A value of SsxInterval type. The special value
+/// SSX_WAIT_FOREVER indicates no timeout.
+///
+/// \param sleep A value of SsxInterval type. Callers using the explicit
+/// timeout form can request that the thread sleeps between polls; See
+/// documentation for the polling() API.
+///
+/// This form of pba_slave_reset() gives the caller control over timeouts,
+/// sleeping and error handling.
+///
+/// \retval 0 Success
+///
+/// \retval -PBA_INVALID_ARGUMENT_RESET The slave \a id parameter
+/// is invalid.
+///
+/// \retval -PBA_SLVRST_TIMED_OUT1 The procedure timed out waiting for the PBA
+/// to reset the slave.
+
+
+int
+_pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep)
+{
+ int rc, closureRc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((id < 0) || (id >= PBA_SLAVES),
+ PBA_INVALID_ARGUMENT_RESET);
+ }
+
+ rc = polling(&closureRc, _pba_slave_reset_poll, (void*)id, timeout, sleep);
+ if (rc == POLLING_TIMEOUT) {
+ rc = -PBA_SLVRST_TIMED_OUT1;
+ }
+
+ return rc;
+}
+
+
+/// Reset a PBA slave with a default timeout
+///
+/// \param id A PBA slave id in the range 0..3
+///
+/// PBA slaves must be reset before being reprogrammed. Resetting a slave
+/// also flushes any write buffers and invalidates any read buffers associated
+/// with the slave. This procedure is for initialization/bringup/test only;
+/// it has a non-deterministic run time due to the PowerBus so should not be
+/// run as part of a hard real-time loop.
+///
+/// \retval 0 Success
+///
+/// \retval -SSX_INVALID_ARGUMENT_PBA_RESET The slave \a id parameter is
+/// invalid.
+///
+/// \retval -PBA_SLVRST_TIMED_OUT2 The procedure timed out waiting for the PBA
+/// to reset the slave.
+
+int
+pba_slave_reset(int id)
+{
+ int rc;
+
+ rc = _pba_slave_reset(id, PBA_SLAVE_RESET_TIMEOUT, 0);
+ if (rc) {
+ SSX_ERROR(PBA_SLVRST_TIMED_OUT2);
+ }
+
+ return rc;
+}
+
+
+/// Configure the PBAX mechanism
+///
+/// \param master If non-0, then this OCC will assume the role of the PBAX
+/// master processor in the power domain. To avoid PBAX livelock there can
+/// only be a single master in any power domain, and only the master is
+/// allowed to issue PBAX broadcast transactions.
+///
+/// \param node The PBAX Node Id of this OCC
+///
+/// \param chip The PBAX Chip Id of this OCC
+///
+/// \param group_mask A bit mask indicating the broadcast group(s) (power
+/// domain(s)) that this OCC belongs to.
+///
+/// This API sets up certain fields of the PBA_XCFG register according to the
+/// parameters. Other fields in the register controlling hardware timeouts and
+/// performance monitoring are unchanged.
+///
+/// \retval 0 Success
+///
+/// \retval -PBAX_INVALID_ARGUMENT_CONFIG One of the arguments is
+/// not valid for some reason.
+
+int
+pbax_configure(int master, int node, int chip, int group_mask)
+{
+ pba_xcfg_t pxc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((node < 0) ||
+ (node >= PBAX_NODES) ||
+ (chip < 0) ||
+ (chip >= PBAX_CHIPS) ||
+ (group_mask < 0) ||
+ (group_mask > PBAX_GROUP_MASK_MAX),
+ PBAX_INVALID_ARGUMENT_CONFIG);
+ }
+ pxc.value = in64(PBA_XCFG);
+ pxc.fields.reservation_en = (master != 0);
+ pxc.fields.rcv_nodeid = node;
+ pxc.fields.rcv_chipid = chip;
+ pxc.fields.rcv_brdcst_group = group_mask;
+ out64(PBA_XCFG, pxc.value);
+ return 0;
+}
+
+
+/// Create a PBAX abstract target
+///
+/// \param target An uninitialized or otherwise idle PbaxTarget object
+///
+/// \param type The transmission type, either PBAX_UNICAST or PBAX_BROADCAST
+///
+/// \param scope The PowerBus scope, either PBAX_GROUP or PBAX_SYSTEM
+///
+/// \param queue The receive queue index on the target, either 0 or 1
+///
+/// \param node The PBAX Node Id of the target
+///
+/// \param chip_or_group Either the PBAX Chip Id of the target (for unicast),
+/// or the PBAX Group Id of the target (for broadcast)
+///
+/// Create an abstraction of a communication target for PBAX send operations,
+/// for use with the _pbax_send() and _pbax_send() APIs. This API has no
+/// knowledge of how the PBAX is configured, and therefore accepts all node,
+/// chip and broadcast group ids as valid. However this API does assume that
+/// all broadcast transactions are "real-time" and require a reservation.
+///
+/// \retval 0 Success
+///
+/// \retval -PBAX_INVALID_OBJECT The \a target parameter is NULL (0) or
+/// otherwise invalid.
+///
+/// \retval -PBAX_INVALID_ARGUMENT_TARGET One or more of the arguments
+/// is invalid.
+
+int
+pbax_target_create(PbaxTarget* target,
+ int type, int scope, int queue,
+ int node, int chip_or_group)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(target == 0, PBAX_INVALID_OBJECT);
+ SSX_ERROR_IF(((type != PBAX_UNICAST) && (type != PBAX_BROADCAST)) ||
+ ((scope != PBAX_GROUP) && (scope != PBAX_SYSTEM)) ||
+ ((queue < 0) || (queue >= PBAX_QUEUES)),
+ PBAX_INVALID_ARGUMENT_TARGET);
+ }
+
+ target->target.value = 0;
+ target->target.fields.snd_scope = scope;
+ target->target.fields.snd_qid = queue;
+ target->target.fields.snd_type = type;
+ target->target.fields.snd_reservation = (type == PBAX_BROADCAST);
+ target->target.fields.snd_nodeid = node;
+ target->target.fields.snd_chipid = chip_or_group;
+
+ return 0;
+}
+
+
+
+/// Use PBAX to send 64 bits to a target with a caller-specified timeout
+///
+/// \param target An abstract PBAX target object
+///
+/// \param data The data to send
+///
+/// \param timeout The caller's timeout represented as an
+/// SsxInterval. Use SSX_WAIT_FOREVER to indicate the caller is willing to
+/// wait forever. A \a timeout of 0 indicates that the caller is not
+/// willing to wait at all, and the call will either succeed immediately or
+/// immediately return -PBAX_TIMEOUT.
+///
+/// The PBAX mechanism has a single outgoing channel that must be shared by
+/// all processes that need to send messages using PBAX. Since messages sent
+/// over PBAX may require an unknown amount of time to complete (due to
+/// PowerBus traffic and blockages), this driver implements an agressive
+/// policy that allows a sender to initiate a send transaction without waiting
+/// for the final completion status. However this opens a window where a
+/// subsequent writer may find the PBAX send mechanism already in use. Here
+/// the new sender is obligated to busy-wait until the send mechanism is free,
+/// as the PBAX send does not include an interrupt notification.
+///
+/// This form of the PBAX send operation accepts an explicit \a timeout value
+/// as previously described. The timeout represents the amount of time that
+/// the caller is willing to wait for a busy PBAX send mechanism to become
+/// free. The PBAX hardware also includes mechanisms to time out the hardware
+/// and modeably interrupt OCC in the event of lack of progress.
+///
+/// <em> This API does not operate in a critical section or enforce any
+/// synchronization protocol. Synchronization and software timeout management
+/// in the case of multiple senders is the responsibility of the
+/// application. </em>
+///
+/// Unlike most other driver APIs this API can not be configured to "panic",
+/// but instead always terminates with a 0 return code or an error status.
+///
+/// \retval 0 Success. Success only means that a transaction was sucessfully
+/// initiated on an idle PBAX send machine.
+///
+/// \retval -PBAX_TIMEOUT The caller-specified timeout expired before the PBAX
+/// send machine became free, but the PBAX send machine does not show error
+/// status.
+///
+/// \retval -PBAX_SEND_ERROR The PBAXSNDSTAT.snd_error bit is asserted. It
+/// is expected that this error will cause the PBA error interrupt to fire -
+/// FFDC is collected by the interrupt handler.
+
+int
+_pbax_send(PbaxTarget* target, uint64_t data, SsxInterval timeout)
+{
+ pba_xsndstat_t pss;
+ SsxTimebase start;
+ int rc, timed_out;
+
+ // The PBAX is always polled at least twice to guarantee that we always
+ // poll once after a timeout - unless the caller explicitly requested a 0
+ // timeout.
+
+ start = 0;
+ timed_out = 0;
+ do {
+ pss.words.high_order = in32(PBA_XSNDSTAT);
+ if (pss.fields.snd_error) {
+ rc = -PBAX_SEND_ERROR;
+ break;
+ }
+ if (!pss.fields.snd_in_progress) {
+ rc = 0;
+ break;
+ }
+ if (start == 0) {
+ start = ssx_timebase_get();
+ }
+ if ((timeout == 0) || timed_out) {
+ rc = -PBAX_SEND_TIMEOUT;
+ break;
+ }
+ timed_out =
+ ((timeout != SSX_WAIT_FOREVER) &&
+ ((ssx_timebase_get() - start) > timeout));
+ } while (1);
+
+ // Configure the send engine and initiate the write, which is kicked off
+ // by writing the high-order word of the send data register.
+
+ if (!rc) {
+ out32(PBA_XSNDTX, target->target.words.high_order);
+ out32(PBA_XSNDDAT + 4, data & 0xffffffff);
+ out32(PBA_XSNDDAT, data >> 32);
+ }
+
+ return rc;
+}
+
+
+/// Use PBAX to send 64 bits to a target with a default timeout
+///
+/// \param target An abstract PBAX target object
+///
+/// \param data The data to send
+///
+/// This form of the PBAX send operation uses a default timeout, and may be
+/// configured to panic in the event of timeouts or send errors. See
+/// _pbax_send() for the specification of the underlying API.
+///
+/// <em> This API does not operate in a critical section or enforce any
+/// synchronization protocol. Synchronization and software timeout management
+/// in the case of multiple senders is the responsibility of the
+/// application. </em>
+///
+/// \retval 0 Success. Success only means that a transaction was sucessfully
+/// initiated on an idle PBAX send machine.
+///
+/// \retval -PBAX_TIMEOUT The caller-specified timeout expired before the PBAX
+/// send machine became free.
+///
+/// \retval -PBAX_SEND_ERROR The PBAXSNDSTAT.snd_error bit is asserted.
+
+int
+pbax_send(PbaxTarget* target, uint64_t data)
+{
+ int rc;
+
+ rc = _pbax_send(target, data, PBAX_SEND_DEFAULT_TIMEOUT);
+ if (rc) {
+ if (rc == -PBAX_SEND_TIMEOUT) {
+ SSX_ERROR(PBAX_SEND_TIMEOUT);
+ } else {
+ SSX_ERROR(PBAX_SEND_ERROR);
+ }
+ }
+ return rc;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ssx/pgp/pgp_pba.h b/src/ssx/pgp/pgp_pba.h
new file mode 100755
index 0000000..647c334
--- /dev/null
+++ b/src/ssx/pgp/pgp_pba.h
@@ -0,0 +1,358 @@
+#ifndef __PGP_PBA_H__
+#define __PGP_PBA_H__
+
+// $Id: pgp_pba.h,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pba.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_pba.h
+/// \brief PBA unit header. Local and mechanically generated macros.
+
+/// \todo Add Doxygen grouping to constant groups
+
+#include "pba_register_addresses.h"
+#include "pba_firmware_registers.h"
+
+#define POWERBUS_CACHE_LINE_SIZE 128
+#define LOG_POWERBUS_CACHE_LINE_SIZE 7
+
+/// The PBA OCI region is always either 0 or 3
+#define PBA_OCI_REGION 0
+
+// It is assumed the the PBA BAR sets will be assigned according to the
+// following scheme. There are still many open questions concerning PBA
+// setup.
+
+/// The number of PBA Base Address Registers (BARS)
+#define PBA_BARS 4
+
+#define PBA_BAR_CHIP 0
+#define PBA_BAR_NODE 2
+#define PBA_BAR_SYSTEM 3
+#define PBA_BAR_CENTAUR 1
+
+#define PBA_BAR_OCC 0 /* OCC image (HOMER) */
+#define PBA_BAR_PORE_SLW 2 /* Redundant mapping for SLW offset into HOMER */
+
+// Standard PBA slave assignments, set up by FAPI procedure prior to releasing
+// OCC from reset.
+
+/// The number of PBA slaves
+#define PBA_SLAVES 4
+
+#define PBA_SLAVE_PORE_GPE 0 /* GPE0/1, but only 1 can access mainstore */
+#define PBA_SLAVE_OCC 1 /* 405 I- and D-cache */
+#define PBA_SLAVE_PORE_SLW 2
+#define PBA_SLAVE_OCB 3
+
+/// The maximum number of bytes a PBA block-copy engine can transfer at once
+#define PBA_BCE_SIZE_MAX 4096
+
+/// The base-2 log of the minimum PBA translation window size in bytes
+#define PBA_LOG_SIZE_MIN 20
+
+/// The base-2 log of the maximum PBA translation window size in bytes
+///
+/// Note that windows > 2**27 bytes require the extended address.
+#define PBA_LOG_SIZE_MAX 41
+
+/// The number of PBA slaves
+#define PBA_SLAVES 4
+
+/// The number of PBA read buffers
+#define PBA_READ_BUFFERS 6
+
+/// The number of PBA write buffers
+#define PBA_WRITE_BUFFERS 2
+
+
+////////////////////////////////////
+// Macros for fields of PBA_SLVCTLn
+////////////////////////////////////
+
+// PBA write Ttypes
+
+#define PBA_WRITE_TTYPE_DMA_PR_WR 0x0 /// DMA Partial Write
+#define PBA_WRITE_TTYPE_LCO_M 0x1 /// L3 LCO for IPL, Tsize denotes chiplet.
+#define PBA_WRITE_TTYPE_ATOMIC_RMW 0x2 /// Atomic operations
+#define PBA_WRITE_TTYPE_CACHE_INJECT 0x3 /// Cache inject after IPL
+#define PBA_WRITE_TTYPE_CI_PR_W 0x4 /// Cache-inhibited partial write for Centaur putscom().
+
+#define PBA_WRITE_TTYPE_DC PBA_WRITE_TTYPE_DMA_PR_WR // Don't care
+
+
+// PBA write Tsize is only required for PBA_WRITE_TTYPE_LCO_M (where it
+// actually specifies a core chiplet id) and PBA_WRITE_TTYPE_ATOMIC_RMW.
+
+#define PBA_WRITE_TSIZE_CHIPLET(chiplet) (chiplet)
+
+#define PBA_WRITE_TSIZE_ARMW_ADD 0x03
+#define PBA_WRITE_TSIZE_ARMW_AND 0x13
+#define PBA_WRITE_TSIZE_ARMW_OR 0x23
+#define PBA_WRITE_TSIZE_ARMW_XOR 0x33
+
+#define PBA_WRITE_TSIZE_DC 0x0
+
+
+// PBA write gather timeouts are defined in terms of the number of 'pulses'. A
+// pulse occurs every 64 OCI cycles. The timing of the last write of a
+// sequence is variable, so the timeout will occur somewhere between (N - 1) *
+// 64 and N * 64 OCI cycles. If write gather timeouts are disabled, the PBA
+// holds the data until some condition occurs that causes it to disgorge the
+// data. Slaves using cache-inhibited partial write never gather write
+// data. Note from spec. : "Write gather timeouts must NOT be disabled if
+// multiple masters are enabled to write through the PBA". The only case
+// where write gather timeouts will be disabled is for the IPL-time injection
+// of data into the L3 caches. Note that disabling write-gathering timeouts is
+// different from disabling write-gathering altogether with the
+// SLVCTL.dis_write_gather setting.
+
+#define PBA_WRITE_GATHER_TIMEOUT_DISABLE 0x0
+#define PBA_WRITE_GATHER_TIMEOUT_2_PULSES 0x4
+#define PBA_WRITE_GATHER_TIMEOUT_4_PULSES 0x5
+#define PBA_WRITE_GATHER_TIMEOUT_8_PULSES 0x6
+#define PBA_WRITE_GATHER_TIMEOUT_16_PULSES 0x7
+
+/// PBA write gather timeout don't care assignment - see gpe_pba_parms_create()
+#define PBA_WRITE_GATHER_TIMEOUT_DC -1
+
+
+// PBA read Ttype
+
+#define PBA_READ_TTYPE_CL_RD_NC 0x0 /// Cache line read
+#define PBA_READ_TTYPE_CI_PR_RD 0x1 /// Cache-inhibited partial read for Centaur getscom().
+
+/// PBA read TTYPE don't care assignment
+#define PBA_READ_TTYPE_DC PBA_READ_TTYPE_CL_RD_NC
+
+
+// PBA read prefetch options
+
+#define PBA_READ_PREFETCH_AUTO_EARLY 0x0 /// Aggressive prefetch
+#define PBA_READ_PREFETCH_NONE 0x1 /// No prefetch
+#define PBA_READ_PREFETCH_AUTO_LATE 0x2 /// Non-aggressive prefetch
+
+/// PBA read prefetch don't care assignment - see gpe_pba_parms_create()
+#define PBA_READ_PREFETCH_DC -1
+
+
+// PBA PowerBus command scope and priority, and PBA defaults
+
+/// Nodal, Local Node
+#define POWERBUS_COMMAND_SCOPE_NODAL 0x0
+
+/// Group, Local 4-chip, (aka, node pump)
+#define POWERBUS_COMMAND_SCOPE_GROUP 0x1
+
+/// System, All units in the system
+#define POWERBUS_COMMAND_SCOPE_SYSTEM 0x2
+
+/// RGP, All units in the system (aka, system pump)
+#define POWERBUS_COMMAND_SCOPE_RGP 0x3
+
+/// Foreign, All units on the local chip, local SMP, and remote chip (pivot
+/// nodes), In P8, only 100 and 101 are valid.
+#define POWERBUS_COMMAND_SCOPE_FOREIGN0 0x4
+
+/// Foreign, All units on the local chip, local SMP, and remote chip (pivot
+/// nodes), In P8, only 100 and 101 are valid.
+#define POWERBUS_COMMAND_SCOPE_FOREIGN1 0x5
+
+
+/// Default command scope for BCDE/BCUE transfers
+#define PBA_POWERBUS_COMMAND_SCOPE_DEFAULT POWERBUS_COMMAND_SCOPE_NODAL
+
+
+
+// Abstract fields of the PBA Slave Reset register used in pba_slave_reset(),
+// which checks 'n' for validity.p
+
+#define PBA_SLVRST_SET(n) (4 + (n))
+#define PBA_SLVRST_IN_PROG(n) (0x8 >> (n))
+
+/// The default timeout for pba_slave_reset().
+///
+/// Currently the procedure pba_slave_reset() is thought to be an
+/// initialization-only and/or lab-only procedure, so this long polling
+/// timeout is not a problem.
+#ifndef PBA_SLAVE_RESET_TIMEOUT
+#define PBA_SLAVE_RESET_TIMEOUT SSX_MICROSECONDS(100)
+#endif
+
+
+// PBA Error/Panic codes
+
+#define PBA_SCOM_ERROR1 0x00722001
+#define PBA_SCOM_ERROR2 0x00722002
+#define PBA_SLVRST_TIMED_OUT1 0x00722003
+#define PBA_SLVRST_TIMED_OUT2 0x00722004
+#define PBA_INVALID_ARGUMENT_BARSET 0x00779005
+#define PBA_INVALID_ARGUMENT_RESET 0x00779006
+#define PBAX_INVALID_ARGUMENT_CONFIG 0x00779007
+#define PBAX_INVALID_ARGUMENT_TARGET 0x00779008
+#define PBAX_INVALID_OBJECT 0x00722009
+
+#ifndef __ASSEMBLER__
+
+/// The PBA extended address in the form of a 'firmware register'
+///
+/// The extended address covers only bits 23:36 of the 50-bit PowerBus address.
+
+typedef union pba_extended_address {
+
+ uint64_t value;
+ uint32_t word[2];
+ struct {
+ uint64_t reserved0 : 23;
+ uint64_t extended_address : 14;
+ uint64_t reserved1 : 27;
+ } fields;
+} pba_extended_address_t;
+
+
+int
+pba_barset_initialize(int idx, uint64_t base, int log_size);
+
+int
+_pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep);
+
+int
+pba_slave_reset(int id);
+
+
+////////////////////////////////////////////////////////////////////////////
+// PBAX
+////////////////////////////////////////////////////////////////////////////
+
+// PBAX error/panic codes
+
+#define PBAX_SEND_TIMEOUT 0x00722901
+#define PBAX_SEND_ERROR 0x00722902
+#define PBAX_RECEIVE_ERROR 0x00722903
+
+/// The number of receive queues implemented by PBAX
+#define PBAX_QUEUES 2
+
+/// The number of PBAX Node Ids
+#define PBAX_NODES 8
+
+/// The number of PBAX Chip Ids (and group Ids)
+#define PBAX_CHIPS 8
+#define PBAX_GROUPS PBAX_CHIPS
+
+/// The maximum legal PBAX group mask
+#define PBAX_GROUP_MASK_MAX 0xff
+
+// PBAX Send Message Scope
+
+#define PBAX_GROUP 1
+#define PBAX_SYSTEM 2
+
+// PBAX Send Type
+
+#define PBAX_UNICAST 0
+#define PBAX_BROADCAST 1
+
+// Default timeout for pbax_send()
+
+#ifndef PBAX_SEND_DEFAULT_TIMEOUT
+#define PBAX_SEND_DEFAULT_TIMEOUT SSX_MICROSECONDS(30)
+#endif
+
+/// An abstract target for PBAX send operations
+///
+/// This structure contains an abstraction of a communication target for PBAX
+/// send operations. An application using PBAX to transmit data first creates
+/// an instance of the PbaxTarget for each abstract target using
+/// pbax_target_create(), then calls pbax_send() or _pbax_send() with a
+/// PbaxTarget and an 8-byte data packet to effect a transmission.
+///
+/// For applications that use GPE programs to implement PBAX sends, a pointer
+/// to this object could also be passed to the GPE program.
+
+typedef struct {
+
+ /// The abstract target
+ ///
+ /// pbax_target_create() condenses the target parameters into a copy of
+ /// the PBAXSNDTX register used to configure the transmission.
+ pba_xsndtx_t target;
+
+} PbaxTarget;
+
+
+int
+pbax_target_create(PbaxTarget* target,
+ int type, int scope, int queue,
+ int node, int chip_or_group);
+
+int
+pbax_configure(int master, int node, int chip, int group_mask);
+
+int
+_pbax_send(PbaxTarget* target, uint64_t data, SsxInterval timeout);
+
+int
+pbax_send(PbaxTarget* target, uint64_t data);
+
+
+/// Enable the PBAX send mechanism
+
+static inline void
+pbax_send_enable(void)
+{
+ pba_xcfg_t pxc;
+
+ pxc.words.high_order = in32(PBA_XCFG);
+ pxc.fields.pbax_en = 1;
+ out32(PBA_XCFG, pxc.words.high_order);
+
+}
+
+
+/// Disable the PBAX send mechanism
+
+static inline void
+pbax_send_disable(void)
+{
+ pba_xcfg_t pxc;
+
+ pxc.words.high_order = in32(PBA_XCFG);
+ pxc.fields.pbax_en = 0;
+ out32(PBA_XCFG, pxc.words.high_order);
+
+}
+
+
+/// Clear the PBAX send error condition
+
+static inline void
+pbax_clear_send_error(void)
+{
+ pba_xcfg_t pxc;
+
+ pxc.words.high_order = in32(PBA_XCFG);
+ pxc.fields.snd_reset = 1;
+ out32(PBA_XCFG, pxc.words.high_order);
+}
+
+
+/// Clear the PBAX receive error condition
+
+static inline void
+pbax_clear_receive_error(void)
+{
+ pba_xcfg_t pxc;
+
+ pxc.words.high_order = in32(PBA_XCFG);
+ pxc.fields.rcv_reset = 1;
+ out32(PBA_XCFG, pxc.words.high_order);
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PGP_PBA_H__ */
diff --git a/src/ssx/pgp/pgp_pmc.c b/src/ssx/pgp/pgp_pmc.c
new file mode 100755
index 0000000..bf3673b
--- /dev/null
+++ b/src/ssx/pgp/pgp_pmc.c
@@ -0,0 +1,366 @@
+// $Id: pgp_pmc.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pmc.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_pmc.c
+/// \brief PgP procedures and support for PMC operations
+///
+/// <b> SCOM Operations </b>
+///
+/// The PMC provides an indirect bridge from the OCI to the PIB/PCB. OCC
+/// firmware therefore has the ability to do immediate putscom()/getscom()
+/// operations in addition to the capabilities provided by the PORE-GPE
+/// engines. In PgP, SCOM latency from OCC is expected to be in the range of
+/// 150 - 1000 ns. The maximum latency of a PIB operation has a hard upper
+/// bound derived from the hardware implementation. The putscom()/getscom()
+/// drivers here take advantage of this upper bound and implement tight
+/// timeouts, enforced by polling the timebase while waiting for the SCOM
+/// operations to complete.
+///
+/// The latencies are small enough and so well understood that the
+/// getscom()/putscom() procedures operate in SSX_CRITICAL critical
+/// sections. There should be no problem for thread-based procedures to be
+/// written using getscom()/putscom() directly - in fact for short procedures
+/// it may be less overhead to use getscom()/putscom() than queuing a PORE-GPE
+/// program. All mainline procedures used by hard real-time code should
+/// remain as PORE-GPE programs however.
+///
+/// SCOM operations return non-zero error codes that may or may not indicate
+/// an actual error, depending on which SCOM is being accessed. This error
+/// code (or 0 for success) is returned as the value of getscom()/putscom().
+/// The error severity increases with the severity of the error:
+/// \code
+///
+/// #define PCB_ERROR_NONE 0
+/// #define PCB_ERROR_RESOURCE_OCCUPIED 1
+/// #define PCB_ERROR_CHIPLET_OFFLINE 2
+/// #define PCB_ERROR_PARTIAL_GOOD 3
+/// #define PCB_ERROR_ADDRESS_ERROR 4
+/// #define PCB_ERROR_CLOCK_ERROR 5
+/// #define PCB_ERROR_PACKET_ERROR 6
+/// #define PCB_ERROR_TIMEOUT 7
+/// \endcode
+///
+/// The default configuration variable SCOM_ERROR_LIMIT defines the maximum
+/// error code that will be returned - error codes above the limit (plus hard
+/// timeouts and other protocol errors) cause an immediate kernel panic. In
+/// the event of a non-0 error code, getscom() always sets the returned data
+/// to 0.
+///
+/// In addition to getscom()/putscom() that implement the above defined error
+/// protocols, the raw APIs _getscom()/_putscom() are also available and
+/// allow the application full control over timeouts and error handling on a
+/// SCOM-by-SCOM basis.
+///
+/// \bug Modify getscom/putscom to return the SSX error codes rather than
+/// 1-7.
+///
+/// \bug Implement and use a generic poll_with_timeout(f, arg, t)
+
+#include "ssx.h"
+#include "pgp_pmc.h"
+
+
+////////////////////////////////////////////////////////////////////////////
+// SCOM
+////////////////////////////////////////////////////////////////////////////
+
+// Common SCOM polling loop with software timeout. The PMC is always polled
+// at least twice to guarantee that we always poll once after a timeout.
+
+static int
+poll_scom(SsxInterval timeout, pmc_o2p_ctrl_status_reg_t *cs)
+{
+ SsxTimebase start;
+ int timed_out;
+
+ start = ssx_timebase_get();
+ timed_out = 0;
+ do {
+ cs->value = in32(PMC_O2P_CTRL_STATUS_REG);
+ if (!(cs->fields.o2p_ongoing)) {
+ break;
+ }
+ if (timed_out) {
+ return -SCOM_TIMEOUT_ERROR;
+ }
+ timed_out =
+ ((timeout != SSX_WAIT_FOREVER) &&
+ ((ssx_timebase_get() - start) > timeout));
+ } while (1);
+
+ return 0;
+}
+
+
+/// A raw getscom() through the PMC OCI/PIB bridge
+///
+/// \param address A standard 32-bit SCOM address, including multicast
+/// addresses.
+///
+/// \param data Points to a container for the returned data.
+///
+/// \param timeout The software timeout as an SSX interval (timebase ticks),
+/// or the special value SSX_WAIT_FOREVER to indicate no software timeout.
+///
+/// This routine executes in an SSX_CRITICAL critical section.
+///
+/// Unlike most other APIs, this API returns both positive and negative error
+/// codes, as well as the 0 code for success. In the event of PCB errors, the
+/// returned \a data is obtained from the PMC O2P data registers. In the
+/// event of non-PCB errors, the caller \a data is not modified.
+///
+/// If the transaction experiences a software timeout (controlled by the \a
+/// timeout parameter) or a protocol error, the PMC PIB master will be left in
+/// a state in which it is illegal to perform further SCOM access through the
+/// PMC until the ongoing transaction is finished.
+///
+/// \retval 0 Success
+///
+///\ retval 1-7 A PCB error code. See \c pcb_common.h
+///
+/// \retval -SCOM_TIMEOUT_ERROR The software timeout specified by the \a
+/// timeout parameter expired before the transaction completed.
+///
+/// retval -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY The PMC SCOM engine was busy when
+/// the call was made.
+
+int
+_getscom(uint32_t address, uint64_t *data, SsxInterval timeout)
+{
+ pmc_o2p_addr_reg_t addr;
+ pmc_o2p_ctrl_status_reg_t cs;
+ SsxMachineContext ctx;
+ Uint64 data64;
+ int rc;
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ // Check for a transaction already ongoing
+
+ cs.value = in32(PMC_O2P_CTRL_STATUS_REG);
+ if (cs.fields.o2p_ongoing) {
+ ssx_critical_section_exit(&ctx);
+ return -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY;
+ }
+
+ // Start the read. The 'read' bit is forced into the address. Writing
+ // the PMC_O2P_ADDR_REG starts the read.
+
+ addr.value = address;
+ addr.fields.o2p_read_not_write = 1;
+ out32(PMC_O2P_ADDR_REG, addr.value);
+
+ // Polling and return.
+
+ rc = poll_scom(timeout, &cs);
+
+ data64.word[0] = in32(PMC_O2P_RECV_DATA_HI_REG);
+ data64.word[1] = in32(PMC_O2P_RECV_DATA_LO_REG);
+ *data = data64.value;
+
+ ssx_critical_section_exit(&ctx);
+
+ if (rc) {
+ return rc;
+ } else {
+ return cs.fields.o2p_scresp;
+ }
+}
+
+
+/// getscom() through the PMC OCI/PIB bridge
+///
+/// \param address A standard 32-bit SCOM address, including multicast
+/// addresses.
+///
+/// \param data Points to a container for the returned data.
+///
+/// This routine executes in an SSX_CRITICAL critical section.
+///
+/// Unlike most other APIs, this API returns positive error
+/// codes, as well as the 0 code for success. In the event of PCB errors, the
+/// returned \a data is set to 0.
+///
+/// If the transaction experiences a software timeout (controlled by the \a
+/// timeout parameter), a protocol error, or a PCB error greater than the
+/// configuration constant SCOM_ERROR_LIMIT this routine causes a kernel
+/// panic. This may leave the PMC PIB master in a state in which it is illegal
+/// to perform further SCOM access through the PMC (until the ongoing
+/// transaction is finished.)
+///
+/// \retval 0 Success
+///
+///\ retval 1-7 A PCB error code. See \c pcb_common.h
+
+int
+getscom(uint32_t address, uint64_t *data)
+{
+ int rc;
+
+ rc = _getscom(address, data, SCOM_TIMEOUT);
+ if (rc == 0) {
+ return 0;
+ }
+
+ if ((rc > 0) && (rc <= SCOM_ERROR_LIMIT)) {
+ *data = 0;
+ } else {
+
+ printk("getscom(0x%08x, %p) : Failed with error %d\n",
+ address, data, rc);
+
+ if (rc > 0) {
+ switch (rc) {
+ case 1: SSX_PANIC(SCOM_PCB_ERROR_1_GETSCOM); break;
+ case 2: SSX_PANIC(SCOM_PCB_ERROR_2_GETSCOM); break;
+ case 3: SSX_PANIC(SCOM_PCB_ERROR_3_GETSCOM); break;
+ case 4: SSX_PANIC(SCOM_PCB_ERROR_4_GETSCOM); break;
+ case 5: SSX_PANIC(SCOM_PCB_ERROR_5_GETSCOM); break;
+ case 6: SSX_PANIC(SCOM_PCB_ERROR_6_GETSCOM); break;
+ default: SSX_PANIC(SCOM_PCB_ERROR_7_GETSCOM); break;
+ }
+ } else if (rc == -SCOM_TIMEOUT_ERROR) {
+ SSX_PANIC(SCOM_TIMEOUT_ERROR_GETSCOM);
+ } else {
+ SSX_PANIC(SCOM_PROTOCOL_ERROR_GETSCOM);
+ }
+ }
+
+ return rc;
+}
+
+
+/// A raw putscom() through the PMC OCI/PIB bridge
+///
+/// \param address A standard 32-bit SCOM address, including multicast
+/// addresses.
+///
+/// \param data The SCOM write data
+///
+/// \param timeout The software timeout as an SSX interval (timebase ticks),
+/// or the special value SSX_WAIT_FOREVER to indicate no timeout.
+///
+/// This routine executes in an SSX_CRITICAL critical section.
+///
+/// Unlike most other APIs, this API returns both positive and negative error
+/// codes, as well as the 0 code for success.
+///
+/// If the transaction experiences a software timeout (controlled by the \a
+/// timeout parameter) or a protocol error, the PMC PIB master will be left in
+/// a state in which it is illegal to perform further SCOM access through the
+/// PMC until the ongoing transaction is finished.
+///
+/// \retval 0 Success
+///
+/// \retval 1-7 A PCB error code. See \c pcb_common.h
+///
+/// \retval -SCOM_TIMEOUT The software timeout specified by the \a timeout
+/// parameter expired before the transaction completed.
+///
+/// \retval -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY The PMC SCOM engine was busy when
+/// the call was made.
+
+int
+_putscom(uint32_t address, uint64_t data, SsxInterval timeout)
+{
+ pmc_o2p_addr_reg_t addr;
+ pmc_o2p_ctrl_status_reg_t cs;
+ SsxMachineContext ctx;
+ Uint64 data64;
+ int rc;
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ // Check for a transaction already ongoing
+
+ cs.value = in32(PMC_O2P_CTRL_STATUS_REG);
+ if (cs.fields.o2p_ongoing) {
+ ssx_critical_section_exit(&ctx);
+ return -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY;
+ }
+
+ // Start the write. The 'write' bit is cleared in the address. Here the
+ // PIB write starts when the PMC_O2P_SEND_DATA_LO_REG is written.
+
+ addr.value = address;
+ addr.fields.o2p_read_not_write = 0;
+ out32(PMC_O2P_ADDR_REG, addr.value);
+
+ data64.value = data;
+ out32(PMC_O2P_SEND_DATA_HI_REG, data64.word[0]);
+ out32(PMC_O2P_SEND_DATA_LO_REG, data64.word[1]);
+
+ // Poll and return.
+
+ rc = poll_scom(timeout, &cs);
+
+ ssx_critical_section_exit(&ctx);
+
+ if (rc) {
+ return rc;
+ } else {
+ return cs.fields.o2p_scresp;
+ }
+}
+
+
+/// putscom() through the PMC OCI/PIB bridge
+///
+/// \param address A standard 32-bit SCOM address, including multicast
+/// addresses.
+///
+/// \param data The SCOM write data.
+///
+/// This routine executes in an SSX_CRITICAL critical section.
+///
+/// Unlike most other APIs, this API returns positive error
+/// codes, as well as the 0 code for success.
+///
+/// If the transaction experiences a software timeout (controlled by the \a
+/// timeout parameter), a protocol error, or a PCB error greater than the
+/// configuration constant SCOM_ERROR_LIMIT this routine causes a kernel
+/// panic. This may leave the PMC PIB master in a state in which it is illegal
+/// to perform further SCOM access through the PMC (until the ongoing
+/// transaction is finished.)
+///
+/// \retval 0 Success
+///
+/// \retval 1-7 A PCB error code. See \c pcb_common.h
+
+int
+putscom(uint32_t address, uint64_t data)
+{
+ int rc;
+
+ rc = _putscom(address, data, SCOM_TIMEOUT);
+
+ if ((rc == 0) || ((rc > 0) && (rc <= SCOM_ERROR_LIMIT))) {
+ return rc;
+ }
+
+ printk("putscom(0x%08x, 0x%016llx) : Failed with error %d\n",
+ address, data, rc);
+
+ if (rc > 0) {
+ switch (rc) {
+ case 1: SSX_PANIC(SCOM_PCB_ERROR_1_PUTSCOM); break;
+ case 2: SSX_PANIC(SCOM_PCB_ERROR_2_PUTSCOM); break;
+ case 3: SSX_PANIC(SCOM_PCB_ERROR_3_PUTSCOM); break;
+ case 4: SSX_PANIC(SCOM_PCB_ERROR_4_PUTSCOM); break;
+ case 5: SSX_PANIC(SCOM_PCB_ERROR_5_PUTSCOM); break;
+ case 6: SSX_PANIC(SCOM_PCB_ERROR_6_PUTSCOM); break;
+ default: SSX_PANIC(SCOM_PCB_ERROR_7_PUTSCOM); break;
+ }
+ } else if (rc == -SCOM_TIMEOUT_ERROR) {
+ SSX_PANIC(SCOM_TIMEOUT_ERROR_PUTSCOM);
+ } else {
+ SSX_PANIC(SCOM_PROTOCOL_ERROR_PUTSCOM);
+ }
+
+ return rc;
+}
diff --git a/src/ssx/pgp/pgp_pmc.h b/src/ssx/pgp/pgp_pmc.h
new file mode 100755
index 0000000..1b372db
--- /dev/null
+++ b/src/ssx/pgp/pgp_pmc.h
@@ -0,0 +1,105 @@
+#ifndef __PGP_PMC_H__
+#define __PGP_PMC_H__
+
+// $Id: pgp_pmc.h,v 1.2 2014/02/03 01:30:35 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pmc.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_pmc.h
+/// \brief PgP procedures and support for PMC operations
+
+#include "ssx.h"
+
+#include "pgp_common.h"
+#include "pmc_register_addresses.h"
+#include "pmc_firmware_registers.h"
+
+////////////////////////////////////////////////////////////////////////////
+// SCOM
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+int
+_getscom(uint32_t address, uint64_t *data, SsxInterval timeout);
+
+int
+getscom(uint32_t address, uint64_t *data);
+
+int
+_putscom(uint32_t address, uint64_t data, SsxInterval timeout);
+
+int
+putscom(uint32_t address, uint64_t data);
+
+#endif /* __ASSEMBLER__ */
+
+// Error/Panic Codes
+
+#define SCOM_PCB_ERROR_1_GETSCOM 0x00726601
+#define SCOM_PCB_ERROR_2_GETSCOM 0x00726602
+#define SCOM_PCB_ERROR_3_GETSCOM 0x00726603
+#define SCOM_PCB_ERROR_4_GETSCOM 0x00726604
+#define SCOM_PCB_ERROR_5_GETSCOM 0x00726605
+#define SCOM_PCB_ERROR_6_GETSCOM 0x00726606
+#define SCOM_PCB_ERROR_7_GETSCOM 0x00726607
+#define SCOM_PCB_ERROR_1_PUTSCOM 0x00726608
+#define SCOM_PCB_ERROR_2_PUTSCOM 0x00726609
+#define SCOM_PCB_ERROR_3_PUTSCOM 0x0072660a
+#define SCOM_PCB_ERROR_4_PUTSCOM 0x0072660b
+#define SCOM_PCB_ERROR_5_PUTSCOM 0x0072660c
+#define SCOM_PCB_ERROR_6_PUTSCOM 0x0072660d
+#define SCOM_PCB_ERROR_7_PUTSCOM 0x0072660e
+
+#define SCOM_TIMEOUT_ERROR 0x00726610
+#define SCOM_TIMEOUT_ERROR_GETSCOM 0x00726611
+#define SCOM_TIMEOUT_ERROR_PUTSCOM 0x00726612
+#define SCOM_PROTOCOL_ERROR_GETSCOM 0x00726613
+#define SCOM_PROTOCOL_ERROR_PUTSCOM 0x00726614
+#define SCOM_PROTOCOL_ERROR_GETSCOM_BUSY 0x00726615
+#define SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY 0x00726616
+
+
+/// The default timeout for getscom()/putscom()
+///
+/// This timeout is enforced by the firmware to guarantee a timeout regardless
+/// of the hardware setup.
+///
+/// The expectation is that the PgP hardware will be set up to enforce a PCB
+/// timeout of 8K cycles, or 16.384us @ 500 MHz. A timeout only occurs if
+/// someone erroneously issues a SCOM for a chiplet that does not exist. If
+/// this happens, then all other SCOMS waiting for the timed-out SCOM to
+/// finish will have to wait as well. Aside from the timeout error, the
+/// hardware arbitration and hard latency calculations guarantee that a SCOM
+/// from any master will complete in under 1us, regardless of PCB utilization.
+///
+/// Assuming that the PCB timeout is a rare event that will only happen when a
+/// console user types an illegal address for getscom/putscom, then we should
+/// be able to use 17us as a hard upper bound for a soft timeout. In practice
+/// this software timeout should never be observed - if it is, then something
+/// (either the setup, hardware or firmware) must be broken.
+
+#ifndef SCOM_TIMEOUT
+#define SCOM_TIMEOUT SSX_MICROSECONDS(17)
+#endif
+
+
+/// The default getscom()/putscom() error limit.
+///
+/// This defines the maximum PCB error return code which will not cause
+/// getscom()/putscom() to panic. The choice of this error limit is
+/// application dependent. For lab applications we should never try to SCOM a
+/// partial-good chiplet, so the limit is set at PCB_ERROR_CHIPLET_OFFLINE.
+/// For production applications it may be that notification of garded cores is
+/// late, so production code may need to handle PCB_ERROR_PARTIAL_GOOD as
+/// well.
+
+#ifndef SCOM_ERROR_LIMIT
+#define SCOM_ERROR_LIMIT PCB_ERROR_CHIPLET_OFFLINE
+#endif
+
+#endif // __PGP_PMC_H__
diff --git a/src/ssx/pgp/pgp_pore.h b/src/ssx/pgp/pgp_pore.h
new file mode 100755
index 0000000..e40ccac
--- /dev/null
+++ b/src/ssx/pgp/pgp_pore.h
@@ -0,0 +1,39 @@
+#ifndef __PGP_PORE_H__
+#define __PGP_PORE_H__
+
+// $Id: pgp_pore.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pore.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_pore.h
+/// \brief PORE unit header. Local and mechanically generated macros.
+
+#include "pore_register_addresses.h"
+#include "pore_firmware_registers.h"
+
+/// The parameter for GPE-protocol triggering is the low-order word of the
+/// EXE_TRIGGER register
+#define PORE_EXE_PARAMETER_OFFSET (PORE_EXE_TRIGGER_OFFSET + 4)
+
+/// The PORE OCI address space descriptor
+#define PORE_ADDRESS_SPACE_OCI 0x8000
+
+/// The PORE BRAI opcode
+#define PORE_BRAI 0xa2000000
+
+/// The PORE BRAD D0 opcode
+#define PORE_BRAD_D0 0x38500000
+
+
+#ifndef __ASSEMBLER__
+
+/// The putative type of PORE program entry points - to make GCC happy
+typedef void *(PoreEntryPoint)(void);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PGP_PORE_H__ */
diff --git a/src/ssx/pgp/pgp_sramctl.h b/src/ssx/pgp/pgp_sramctl.h
new file mode 100755
index 0000000..fe2ed69
--- /dev/null
+++ b/src/ssx/pgp/pgp_sramctl.h
@@ -0,0 +1,18 @@
+#ifndef __PGP_SRAMCTL_H__
+#define __PGP_SRAMCTL_H__
+
+// $Id: pgp_sramctl.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_sramctl.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_sramctl.h
+/// \brief SRAMCTL unit header. Local and mechanically generated macros.
+
+#include "sramctl_register_addresses.h"
+#include "sramctl_firmware_registers.h"
+
+#endif /* __PGP_SRAMCTL_H__ */
diff --git a/src/ssx/pgp/pgp_trace.h b/src/ssx/pgp/pgp_trace.h
new file mode 100755
index 0000000..3544ce0
--- /dev/null
+++ b/src/ssx/pgp/pgp_trace.h
@@ -0,0 +1,155 @@
+#ifndef __PGP_TRACE_H__
+#define __PGP_TRACE_H__
+
+// $Id: pgp_trace.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_trace.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_trace.h
+/// \brief Implementation of SSX_TRACE macros for PgP
+///
+/// Kernel and application tracing uses the PBA "OCI Marker Space", a 64KB OCI
+/// register space implemented by PBA. When enabled in the PBA, any OCI write
+/// transactions of any size are ACK'ed by the PBA and the data is ignored.
+/// This creates an OCI transaction record that can be captured by the NHTM
+/// for later analysis.
+///
+/// SSX provides a generic SSX_TRACE() macro that accepts a single
+/// parameter. On PgP, valid parameters are integers in the range
+/// 0x0,...,0xffff. The PgP SSX kernel reserves trace addresses
+/// 0xe000,...,0xffff for kernel event traces. Applications are free to use
+/// the other trace addresses in the range 0x0000,...,0xdfff as they see fit.
+///
+/// Application tracing is globally disabled by default, and is enabled by
+/// defining the switch SSX_TRACE_ENABLE=1. Kernel event tracing is also
+/// globally disabled by default, and is enabled by defining the switch
+/// SSX_KERNEL_TRACE_ENABLE=1. Kernel event tracing adds overhead to every
+/// interrupt handler and kernel API so should probably remain disabled unless
+/// required.
+///
+/// The Simics PBA model supports trace reporting, either to stdout or to a
+/// file. To enable trace reporting set pba->trace_report = 1. To capture
+/// traces to a file other than stdout, set pba->trace_file = \<filename\>. The
+/// Simics model understands SSX kernel trace events and produces a readable
+/// commentary of kernel traces events - user events will be reported simply
+/// as the integer tag.
+
+#include "pgp_common.h"
+
+/// Output an OCI Trace Marker
+///
+/// See the comments for the file pgp_trace.h
+
+#if SSX_TRACE_ENABLE
+#define SSX_TRACE(event) out8(PBA_OCI_MARKER_BASE + (event), 0)
+#endif
+
+#if SSX_KERNEL_TRACE_ENABLE
+
+// Note: The *BASE constants are defined in pgp_common.h
+
+#define SSX_KERNEL_TRACE(event) out8(PBA_OCI_MARKER_BASE + (event), 0)
+
+#define SSX_TRACE_THREAD_SLEEP(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SLEEP_BASE + priority)
+
+#define SSX_TRACE_THREAD_WAKEUP(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_WAKEUP_BASE + priority)
+
+#define SSX_TRACE_THREAD_SEMAPHORE_PEND(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SEMAPHORE_PEND_BASE + priority)
+
+#define SSX_TRACE_THREAD_SEMAPHORE_POST(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SEMAPHORE_POST_BASE + priority)
+
+#define SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT_BASE + priority)
+
+#define SSX_TRACE_THREAD_SUSPENDED(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SUSPENDED_BASE + priority)
+
+#define SSX_TRACE_THREAD_DELETED(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_DELETED_BASE + priority)
+
+#define SSX_TRACE_THREAD_COMPLETED(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_COMPLETED_BASE + priority)
+
+#define SSX_TRACE_THREAD_MAPPED_RUNNABLE(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_MAPPED_RUNNABLE_BASE + priority)
+
+#define SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND_BASE + priority)
+
+#define SSX_TRACE_THREAD_MAPPED_SLEEPING(priority) \
+ SSX_KERNEL_TRACE(SSX_TRACE_THREAD_MAPPED_SLEEPING_BASE + priority)
+
+#endif /* SSX_KERNEL_TRACE_ENABLE */
+
+
+#ifdef __ASSEMBLER__
+
+// NB: CPP macros are not expanded as arguments to .if in GAS macro
+// definitions. That's why e.g. we have to use _liw instead of _liwa.
+
+#if SSX_KERNEL_TRACE_ENABLE
+
+ .macro SSX_TRACE_CRITICAL_IRQ_ENTRY, irqreg, scratch
+ _liw \scratch, (PBA_OCI_MARKER_BASE + SSX_TRACE_CRITICAL_IRQ_ENTRY_BASE)
+ stbx \irqreg, \irqreg, \scratch
+ eieio
+ .endm
+
+ .macro SSX_TRACE_CRITICAL_IRQ_EXIT, scratch0, scratch1
+ _liw \scratch0, (PBA_OCI_MARKER_BASE + SSX_TRACE_CRITICAL_IRQ_EXIT_BASE)
+ mfusprg0 \scratch1
+ extrwi \scratch1, \scratch1, 8, 16
+ stbx \scratch1, \scratch0, \scratch1
+ eieio
+ .endm
+
+ .macro SSX_TRACE_NONCRITICAL_IRQ_ENTRY, irqreg, scratch
+ _liw \scratch, (PBA_OCI_MARKER_BASE + SSX_TRACE_NONCRITICAL_IRQ_ENTRY_BASE)
+ stbx \irqreg, \irqreg, \scratch
+ eieio
+ .endm
+
+ .macro SSX_TRACE_NONCRITICAL_IRQ_EXIT, scratch0, scratch1
+ _liw \scratch0, (PBA_OCI_MARKER_BASE + SSX_TRACE_NONCRITICAL_IRQ_EXIT_BASE)
+ mfusprg0 \scratch1
+ extrwi \scratch1, \scratch1, 8, 16
+ stbx \scratch1, \scratch0, \scratch1
+ eieio
+ .endm
+
+ .macro SSX_TRACE_THREAD_SWITCH, priority, scratch
+ _liw \scratch, (PBA_OCI_MARKER_BASE + SSX_TRACE_THREAD_SWITCH_BASE)
+ stbx \priority, \priority, \scratch
+ eieio
+ .endm
+
+#else /* SSX_KERNEL_TRACE_ENABLE */
+
+ .macro SSX_TRACE_CRITICAL_IRQ_ENTRY, irq, scratch
+ .endm
+
+ .macro SSX_TRACE_CRITICAL_IRQ_EXIT, scratch0, scratch1
+ .endm
+
+ .macro SSX_TRACE_NONCRITICAL_IRQ_ENTRY, irq, scratch
+ .endm
+
+ .macro SSX_TRACE_NONCRITICAL_IRQ_EXIT, scratch0, scratch1
+ .endm
+
+ .macro SSX_TRACE_THREAD_SWITCH, priority, scratch
+ .endm
+
+#endif /* SSX_KERNEL_TRACE_ENABLE */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PGP_TRACE_H__ */
diff --git a/src/ssx/pgp/pgp_vrm.h b/src/ssx/pgp/pgp_vrm.h
new file mode 100755
index 0000000..aaa6760
--- /dev/null
+++ b/src/ssx/pgp/pgp_vrm.h
@@ -0,0 +1,223 @@
+#ifndef __PGP_VRM_H__
+#define __PGP_VRM_H__
+
+// $Id: pgp_vrm.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_vrm.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pgp_vrm.h
+/// \brief Header for PgP VRM device drivers. Some constants are also held in
+/// pgp_common.h.
+
+#include "pgp_common.h"
+
+
+#ifndef __ASSEMBLER__
+
+/// VRM Command Header
+///
+/// This structure defines the values written on the SPI interface for
+/// 'read' commands.
+
+//typedef union {
+// uint64_t value;
+// uint32_t word[2];
+// struct {
+// uint64_t address : 4;
+// uint64_t command : 4;
+// } fields;
+//} vrm_command_t;
+
+
+/// VRM Write Transaction Command
+///
+/// The 8-bit \a phase_enable is an 8-bit VRM-11 VID code
+///
+/// The 8-bit \a vcs_offset is an 8-bit signed offset
+
+typedef union {
+ uint64_t value;
+ uint32_t word[2];
+ struct {
+ uint64_t command : 4;
+ uint64_t phase_enable : 4;
+ uint64_t vdd_vid : 8;
+ uint64_t vcs_offset : 8;
+ uint64_t master_crc : 8;
+ } fields;
+} vrm_write_transaction_t;
+
+
+/// VRM Write Transaction Response
+/// writes status is duplicated 3x for the minority detect feature.
+
+typedef union {
+ uint64_t value;
+ uint32_t word[2];
+ struct {
+ uint64_t write_status0 : 8;
+ uint64_t write_status1 : 8;
+ uint64_t write_status2 : 8;
+ uint64_t optional_crc : 8;
+ } fields;
+} vrm_write_resp_t;
+
+
+
+/// VRM Read State Command
+/// reserved field should be sent as 0s
+
+typedef union {
+ uint64_t value;
+ uint32_t word[2];
+ struct {
+ uint64_t command : 4;
+ uint64_t reserved : 20;
+ uint64_t master_crc : 8;
+ } fields;
+} vrm_read_state_t;
+
+
+/// VRM Read State Response
+/// Results are duplicated 3x for the minority detecte feature.
+
+typedef union {
+ uint64_t value;
+ uint32_t word[2];
+ struct {
+ uint64_t read_ready0 : 1;
+ uint64_t minus_nplus1_0 : 1;
+ uint64_t minus_n0 : 1;
+ uint64_t reserved1_0 : 1;
+ uint64_t vrm_fan0 : 1;
+ uint64_t vrm_overtemp0 : 1;
+ uint64_t reserved2_0 : 2;
+ uint64_t read_ready1 : 1;
+ uint64_t minus_nplus1_1 : 1;
+ uint64_t minus_n1 : 1;
+ uint64_t reserved1_1 : 1;
+ uint64_t vrm_fan1 : 1;
+ uint64_t vrm_overtemp1 : 1;
+ uint64_t reserved2_1 : 2;
+ uint64_t read_ready2 : 1;
+ uint64_t minus_nplus1_2 : 1;
+ uint64_t minus_n2 : 1;
+ uint64_t reserved1_2 : 1;
+ uint64_t vrm_fan2 : 1;
+ uint64_t vrm_overtemp2 : 1;
+ uint64_t reserved2_2 : 2;
+ uint64_t slave_crc : 8;
+ } fields;
+} vrm_read_state_resp_t;
+
+/// VRM Read Voltage Command
+/// reserved field should be sent as 0s
+
+typedef union {
+ uint64_t value;
+ uint32_t word[2];
+ struct {
+ uint64_t command : 4;
+ uint64_t rail : 4;
+ uint64_t reserved : 1;
+ uint64_t master_crc : 8;
+ } fields;
+} vrm_read_voltage_t;
+
+
+/// VRM Read Voltage Response
+/// Results are duplicated 3x for the minority detect feature.
+
+typedef union {
+ uint64_t value;
+ uint32_t word[2];
+ struct {
+ uint64_t vid0 : 8;
+ uint64_t vid1 : 8;
+ uint64_t vid2 : 8;
+ uint64_t slave_crc : 8;
+ } fields;
+} vrm_read_voltage_resp_t;
+
+
+/// VRM Read Current 1 Response
+///
+/// The 16-bit current readings come from 12-bit DACS; the DAC output is
+/// right-padded with 0b0000. The current units are 0.025 Ampere.
+
+//typedef union {
+// uint64_t value;
+// uint32_t word[2];
+// struct {
+// uint64_t header : 8;
+// uint64_t read_not_ready : 1;
+// uint64_t minus_nplus1 : 1;
+// uint64_t minus_n : 1;
+// uint64_t reserved0 : 1;
+// uint64_t vrm_fan : 1;
+// uint64_t vrm_overtemp : 1;
+// uint64_t reserved1 : 2;
+// uint64_t vdd_current : 16;
+// uint64_t vcs_current : 16;
+// uint64_t vio_current : 16;
+// } fields;
+//} vrm_read_current_1_t;
+
+
+/// VRM Read Current 2 Response
+///
+/// The 16-bit current readings come from 12-bit DACS; the DAC output is
+/// right-padded with 0b0000. The current units are 0.025 Ampere.
+
+//typedef union {
+// uint64_t value;
+// uint32_t word[2];
+// struct {
+// uint64_t header : 8;
+// uint64_t read_not_ready : 1;
+// uint64_t minus_nplus1 : 1;
+// uint64_t minus_n : 1;
+// uint64_t reserved0 : 1;
+// uint64_t vrm_fan : 1;
+// uint64_t vrm_overtemp : 1;
+// uint64_t reserved1 : 2;
+// uint64_t spare1_current : 16;
+// uint64_t spare2_current : 16;
+// uint64_t spare3_current : 16;
+// } fields;
+//} vrm_read_current_2_t;
+
+#endif /* __ASSEMBLER__ */
+
+// These are the default values for the SPIVRM/O2S interface
+
+#define SPIVRM_BITS 71 /* Actual # of bits minus 1 */
+#define SPIVRM_CPOL 0 /* Clock polarity */
+#define SPIVRM_CPHA 0 /* Clock phase */
+#define SPIVRM_FREQUENCY_HZ 16000000 /* 16 MHz */
+#define SPIVRM_ENABLE_ECC 1
+#define SPIVRM_NPORTS 3 /* Maximum # of ports supported by HW */
+#define SPIVRM_NRAILS 2 /* Maximum # of rails supported by read voltage cmd*/
+#define SPIVRM_ENABLED_PORTS 0x4 /* 3 bit mask, left justified */
+#define SPIVRM_PHASES 15 /* System dependent */
+
+/// Convert an integer index into a VRM designator (mask)
+#define SPIVRM_PORT(i) (1 << (SPIVRM_NPORTS - (i) - 1))
+
+// SPIVRM specific setup defaults
+
+#define SPIVRM_READ_STATUS_DELAY 48 /* Cycles, system dependent */
+#define SPIVRM_ADDRESS 0 /* First 4 bits of SPIVRM packet */
+
+// Default values for the O2S bridge
+
+#define O2S_BRIDGE_ENABLE 1
+#define O2S_READ_DELAY 48 /* Cycles, system dependent */
+#define O2S_ADDRESS 0 /* First 4 bits of O2S packet */
+
+
+#endif /* __PGP_VRM_H__ */
diff --git a/src/ssx/pgp/registers/centaur_firmware_registers.h b/src/ssx/pgp/registers/centaur_firmware_registers.h
new file mode 100755
index 0000000..39f168f
--- /dev/null
+++ b/src/ssx/pgp/registers/centaur_firmware_registers.h
@@ -0,0 +1,1496 @@
+#ifndef __CENTAUR_FIRMWARE_REGISTERS_H__
+#define __CENTAUR_FIRMWARE_REGISTERS_H__
+
+// $Id: centaur_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/centaur_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file centaur_firmware_registers.h
+/// \brief C register structs for the CENTAUR unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union centaur_device_id {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cfam_id : 32;
+ uint64_t module_id : 2;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t module_id : 2;
+ uint64_t cfam_id : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_device_id_t;
+
+
+
+typedef union centaur_mbs_fir_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t host_protocol_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t external_timeout : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t lru_error : 1;
+ uint64_t edram_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t edram_error : 1;
+ uint64_t lru_error : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t external_timeout : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t host_protocol_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbs_fir_reg_t;
+
+
+
+typedef union centaur_mbs_fir_reg_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t host_protocol_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t external_timeout : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t lru_error : 1;
+ uint64_t edram_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t edram_error : 1;
+ uint64_t lru_error : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t external_timeout : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t host_protocol_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbs_fir_reg_and_t;
+
+
+
+typedef union centaur_mbs_fir_reg_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t host_protocol_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t external_timeout : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t lru_error : 1;
+ uint64_t edram_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t edram_error : 1;
+ uint64_t lru_error : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t external_timeout : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t host_protocol_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbs_fir_reg_or_t;
+
+
+
+typedef union centaur_mbs_fir_mask_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t host_protocol_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t external_timeout : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t lru_error : 1;
+ uint64_t edram_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t edram_error : 1;
+ uint64_t lru_error : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t external_timeout : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t host_protocol_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbs_fir_mask_reg_t;
+
+
+
+typedef union centaur_mbs_fir_mask_reg_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t host_protocol_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t external_timeout : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t lru_error : 1;
+ uint64_t edram_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t edram_error : 1;
+ uint64_t lru_error : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t external_timeout : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t host_protocol_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbs_fir_mask_reg_and_t;
+
+
+
+typedef union centaur_mbs_fir_mask_reg_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t host_protocol_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t external_timeout : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t lru_error : 1;
+ uint64_t edram_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t edram_error : 1;
+ uint64_t lru_error : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t external_timeout : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t host_protocol_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbs_fir_mask_reg_or_t;
+
+
+
+typedef union centaur_mbs_fir_action0_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t host_protocol_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t external_timeout : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t lru_error : 1;
+ uint64_t edram_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t edram_error : 1;
+ uint64_t lru_error : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t external_timeout : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t host_protocol_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbs_fir_action0_reg_t;
+
+
+
+typedef union centaur_mbs_firact1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t host_protocol_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t external_timeout : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t lru_error : 1;
+ uint64_t edram_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t internal_scom_error_copy : 1;
+ uint64_t internal_scom_error : 1;
+ uint64_t spare_fir31 : 1;
+ uint64_t spare_fir30 : 1;
+ uint64_t dir_purge_ce : 1;
+ uint64_t srb_buffer_sue : 1;
+ uint64_t srb_buffer_ue : 1;
+ uint64_t srb_buffer_ce : 1;
+ uint64_t occ_inband_write_error : 1;
+ uint64_t occ_inband_read_error : 1;
+ uint64_t host_inband_write_error : 1;
+ uint64_t host_inband_read_error : 1;
+ uint64_t emergency_throttle_set : 1;
+ uint64_t edram_error : 1;
+ uint64_t lru_error : 1;
+ uint64_t dir_all_members_deleted : 1;
+ uint64_t dir_member_deleted : 1;
+ uint64_t dir_ue : 1;
+ uint64_t dir_ce : 1;
+ uint64_t cache_co_sue : 1;
+ uint64_t cache_co_ue : 1;
+ uint64_t cache_co_ce : 1;
+ uint64_t cache_srw_sue : 1;
+ uint64_t cache_srw_ue : 1;
+ uint64_t cache_srw_ce : 1;
+ uint64_t int_parity_error : 1;
+ uint64_t int_buffer_sue : 1;
+ uint64_t int_buffer_ue : 1;
+ uint64_t int_buffer_ce : 1;
+ uint64_t internal_timeout : 1;
+ uint64_t external_timeout : 1;
+ uint64_t invalid_address_error : 1;
+ uint64_t int_protocol_error : 1;
+ uint64_t host_protocol_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbs_firact1_t;
+
+
+
+typedef union centaur_mbscfgq {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t eccbp_exit_sel : 1;
+ uint64_t dram_ecc_bypass_dis : 1;
+ uint64_t mbs_scom_wat_trigger : 1;
+ uint64_t mbs_prq_ref_avoidance_en : 1;
+ uint64_t reserved4_6 : 3;
+ uint64_t occ_deadman_timer_sel : 4;
+ uint64_t sync_fsync_mba_strobe_en : 1;
+ uint64_t hca_timebase_op_mode : 1;
+ uint64_t hca_local_timer_inc_select : 3;
+ uint64_t mbs_01_rdtag_delay : 4;
+ uint64_t mbs_01_rdtag_force_dead_cycle : 1;
+ uint64_t sync_lat_pol_01 : 1;
+ uint64_t sync_lat_adj_01 : 2;
+ uint64_t mbs_23_rdtag_delay : 4;
+ uint64_t mbs_23_rdtag_force_dead_cycle : 1;
+ uint64_t sync_lat_pol_23 : 1;
+ uint64_t sync_lat_adj_23 : 2;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t sync_lat_adj_23 : 2;
+ uint64_t sync_lat_pol_23 : 1;
+ uint64_t mbs_23_rdtag_force_dead_cycle : 1;
+ uint64_t mbs_23_rdtag_delay : 4;
+ uint64_t sync_lat_adj_01 : 2;
+ uint64_t sync_lat_pol_01 : 1;
+ uint64_t mbs_01_rdtag_force_dead_cycle : 1;
+ uint64_t mbs_01_rdtag_delay : 4;
+ uint64_t hca_local_timer_inc_select : 3;
+ uint64_t hca_timebase_op_mode : 1;
+ uint64_t sync_fsync_mba_strobe_en : 1;
+ uint64_t occ_deadman_timer_sel : 4;
+ uint64_t reserved4_6 : 3;
+ uint64_t mbs_prq_ref_avoidance_en : 1;
+ uint64_t mbs_scom_wat_trigger : 1;
+ uint64_t dram_ecc_bypass_dis : 1;
+ uint64_t eccbp_exit_sel : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbscfgq_t;
+
+
+
+typedef union centaur_mbsemerthroq {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t emergency_throttle_ip : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t emergency_throttle_ip : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbsemerthroq_t;
+
+
+
+typedef union centaur_mbsocc01hq {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_01_rd_hit : 32;
+ uint64_t occ_01_wr_hit : 32;
+#else
+ uint64_t occ_01_wr_hit : 32;
+ uint64_t occ_01_rd_hit : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbsocc01hq_t;
+
+
+
+typedef union centaur_mbsocc23hq {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_23_rd_hit : 32;
+ uint64_t occ_23_wr_hit : 32;
+#else
+ uint64_t occ_23_wr_hit : 32;
+ uint64_t occ_23_rd_hit : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbsocc23hq_t;
+
+
+
+typedef union centaur_mbsoccitcq {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_cent_idle_th_cnt : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t occ_cent_idle_th_cnt : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbsoccitcq_t;
+
+
+
+typedef union centaur_mbsoccscanq {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_01_spec_can : 32;
+ uint64_t occ_23_spec_can : 32;
+#else
+ uint64_t occ_23_spec_can : 32;
+ uint64_t occ_01_spec_can : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbsoccscanq_t;
+
+
+
+typedef union centaur_mbarpc0qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cfg_lp2_entry_req : 1;
+ uint64_t cfg_lp2_state : 1;
+ uint64_t cfg_min_max_domains_enable : 1;
+ uint64_t cfg_min_max_domains : 3;
+ uint64_t cfg_pup_avail : 5;
+ uint64_t cfg_pdn_pup : 5;
+ uint64_t cfg_pup_pdn : 5;
+ uint64_t reserved0 : 1;
+ uint64_t cfg_min_domain_reduction_enable : 1;
+ uint64_t cfg_min_domain_reduction_on_time : 10;
+ uint64_t cfg_pup_after_activate_wait_enable : 1;
+ uint64_t cfg_pup_after_activate_wait_time : 8;
+ uint64_t cfg_force_spare_pup : 1;
+ uint64_t _reserved0 : 21;
+#else
+ uint64_t _reserved0 : 21;
+ uint64_t cfg_force_spare_pup : 1;
+ uint64_t cfg_pup_after_activate_wait_time : 8;
+ uint64_t cfg_pup_after_activate_wait_enable : 1;
+ uint64_t cfg_min_domain_reduction_on_time : 10;
+ uint64_t cfg_min_domain_reduction_enable : 1;
+ uint64_t reserved0 : 1;
+ uint64_t cfg_pup_pdn : 5;
+ uint64_t cfg_pdn_pup : 5;
+ uint64_t cfg_pup_avail : 5;
+ uint64_t cfg_min_max_domains : 3;
+ uint64_t cfg_min_max_domains_enable : 1;
+ uint64_t cfg_lp2_state : 1;
+ uint64_t cfg_lp2_entry_req : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbarpc0qn_t;
+
+
+
+typedef union centaur_mba_farb3qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cfg_nm_n_per_mba : 15;
+ uint64_t cfg_nm_n_per_chip : 16;
+ uint64_t cfg_nm_m : 14;
+ uint64_t cfg_nm_ras_weight : 3;
+ uint64_t cfg_nm_cas_weight : 3;
+ uint64_t cfg_nm_per_slot_enabled : 1;
+ uint64_t cfg_nm_count_other_mba_dis : 1;
+ uint64_t _reserved0 : 11;
+#else
+ uint64_t _reserved0 : 11;
+ uint64_t cfg_nm_count_other_mba_dis : 1;
+ uint64_t cfg_nm_per_slot_enabled : 1;
+ uint64_t cfg_nm_cas_weight : 3;
+ uint64_t cfg_nm_ras_weight : 3;
+ uint64_t cfg_nm_m : 14;
+ uint64_t cfg_nm_n_per_chip : 16;
+ uint64_t cfg_nm_n_per_mba : 15;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mba_farb3qn_t;
+
+
+
+typedef union centaur_mbapcn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t mode_hp_sub_cnt : 1;
+ uint64_t mode_lp_sub_cnt : 1;
+ uint64_t mode_static_idle_dly : 5;
+ uint64_t mode_emer_min_max_domain : 3;
+ uint64_t mode_pup_all_wr_pending : 2;
+ uint64_t mode_lp_ref_sim_enq : 1;
+ uint64_t _reserved0 : 51;
+#else
+ uint64_t _reserved0 : 51;
+ uint64_t mode_lp_ref_sim_enq : 1;
+ uint64_t mode_pup_all_wr_pending : 2;
+ uint64_t mode_emer_min_max_domain : 3;
+ uint64_t mode_static_idle_dly : 5;
+ uint64_t mode_lp_sub_cnt : 1;
+ uint64_t mode_hp_sub_cnt : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbapcn_t;
+
+
+
+typedef union centaur_mbasrqn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t emergency_m : 14;
+ uint64_t emergency_n : 15;
+ uint64_t _reserved0 : 35;
+#else
+ uint64_t _reserved0 : 35;
+ uint64_t emergency_n : 15;
+ uint64_t emergency_m : 14;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_mbasrqn_t;
+
+
+
+typedef union centaur_pmu0qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t read_count : 32;
+ uint64_t write_count : 32;
+#else
+ uint64_t write_count : 32;
+ uint64_t read_count : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_pmu0qn_t;
+
+
+
+typedef union centaur_pmu1qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t activate_count : 32;
+ uint64_t pu_counts : 32;
+#else
+ uint64_t pu_counts : 32;
+ uint64_t activate_count : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_pmu1qn_t;
+
+
+
+typedef union centaur_pmu2qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t frame_count : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t frame_count : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_pmu2qn_t;
+
+
+
+typedef union centaur_pmu3qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t low_idle_threshold : 16;
+ uint64_t med_idle_threshold : 16;
+ uint64_t high_idle_threshold : 32;
+#else
+ uint64_t high_idle_threshold : 32;
+ uint64_t med_idle_threshold : 16;
+ uint64_t low_idle_threshold : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_pmu3qn_t;
+
+
+
+typedef union centaur_pmu4qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t base_idle_count : 32;
+ uint64_t low_idle_count : 32;
+#else
+ uint64_t low_idle_count : 32;
+ uint64_t base_idle_count : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_pmu4qn_t;
+
+
+
+typedef union centaur_pmu5qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t med_idle_count : 32;
+ uint64_t high_idle_count : 32;
+#else
+ uint64_t high_idle_count : 32;
+ uint64_t med_idle_count : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_pmu5qn_t;
+
+
+
+typedef union centaur_pmu6qn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t total_gap_counts : 18;
+ uint64_t specific_gap_counts : 18;
+ uint64_t gap_length_adder : 3;
+ uint64_t specific_gap_condition : 4;
+ uint64_t cmd_to_cmd_count : 18;
+ uint64_t command_pattern_to_count : 3;
+#else
+ uint64_t command_pattern_to_count : 3;
+ uint64_t cmd_to_cmd_count : 18;
+ uint64_t specific_gap_condition : 4;
+ uint64_t gap_length_adder : 3;
+ uint64_t specific_gap_counts : 18;
+ uint64_t total_gap_counts : 18;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_pmu6qn_t;
+
+
+
+typedef union centaur_sensor_cache_data0_3 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t crittrip0 : 1;
+ uint64_t abovetrip0 : 1;
+ uint64_t belowtrip0 : 1;
+ uint64_t signbit0 : 1;
+ uint64_t temperature0 : 8;
+ uint64_t temp_frac0 : 2;
+ uint64_t status0 : 2;
+ uint64_t crittrip1 : 1;
+ uint64_t abovetrip1 : 1;
+ uint64_t belowtrip1 : 1;
+ uint64_t signbit1 : 1;
+ uint64_t temperature1 : 8;
+ uint64_t temp_frac1 : 2;
+ uint64_t status1 : 2;
+ uint64_t crittrip2 : 1;
+ uint64_t abovetrip2 : 1;
+ uint64_t belowtrip2 : 1;
+ uint64_t signbit2 : 1;
+ uint64_t temperature2 : 8;
+ uint64_t temp_frac2 : 2;
+ uint64_t status2 : 2;
+ uint64_t crittrip3 : 1;
+ uint64_t abovetrip3 : 1;
+ uint64_t belowtrip3 : 1;
+ uint64_t signbit3 : 1;
+ uint64_t temperature3 : 8;
+ uint64_t temp_frac3 : 2;
+ uint64_t status3 : 2;
+#else
+ uint64_t status3 : 2;
+ uint64_t temp_frac3 : 2;
+ uint64_t temperature3 : 8;
+ uint64_t signbit3 : 1;
+ uint64_t belowtrip3 : 1;
+ uint64_t abovetrip3 : 1;
+ uint64_t crittrip3 : 1;
+ uint64_t status2 : 2;
+ uint64_t temp_frac2 : 2;
+ uint64_t temperature2 : 8;
+ uint64_t signbit2 : 1;
+ uint64_t belowtrip2 : 1;
+ uint64_t abovetrip2 : 1;
+ uint64_t crittrip2 : 1;
+ uint64_t status1 : 2;
+ uint64_t temp_frac1 : 2;
+ uint64_t temperature1 : 8;
+ uint64_t signbit1 : 1;
+ uint64_t belowtrip1 : 1;
+ uint64_t abovetrip1 : 1;
+ uint64_t crittrip1 : 1;
+ uint64_t status0 : 2;
+ uint64_t temp_frac0 : 2;
+ uint64_t temperature0 : 8;
+ uint64_t signbit0 : 1;
+ uint64_t belowtrip0 : 1;
+ uint64_t abovetrip0 : 1;
+ uint64_t crittrip0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_sensor_cache_data0_3_t;
+
+
+
+typedef union centaur_sensor_cache_data4_7 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t crittrip4 : 1;
+ uint64_t abovetrip4 : 1;
+ uint64_t belowtrip4 : 1;
+ uint64_t signbit4 : 1;
+ uint64_t temperature4 : 8;
+ uint64_t temp_frac4 : 2;
+ uint64_t status4 : 2;
+ uint64_t crittrip5 : 1;
+ uint64_t abovetrip5 : 1;
+ uint64_t belowtrip5 : 1;
+ uint64_t signbit5 : 1;
+ uint64_t temperature5 : 8;
+ uint64_t temp_frac5 : 2;
+ uint64_t status5 : 2;
+ uint64_t crittrip6 : 1;
+ uint64_t abovetrip6 : 1;
+ uint64_t belowtrip6 : 1;
+ uint64_t signbit6 : 1;
+ uint64_t temperature6 : 8;
+ uint64_t temp_frac6 : 2;
+ uint64_t status6 : 2;
+ uint64_t crittrip7 : 1;
+ uint64_t abovetrip7 : 1;
+ uint64_t belowtrip7 : 1;
+ uint64_t signbit7 : 1;
+ uint64_t temperature7 : 8;
+ uint64_t temp_frac7 : 2;
+ uint64_t status7 : 2;
+#else
+ uint64_t status7 : 2;
+ uint64_t temp_frac7 : 2;
+ uint64_t temperature7 : 8;
+ uint64_t signbit7 : 1;
+ uint64_t belowtrip7 : 1;
+ uint64_t abovetrip7 : 1;
+ uint64_t crittrip7 : 1;
+ uint64_t status6 : 2;
+ uint64_t temp_frac6 : 2;
+ uint64_t temperature6 : 8;
+ uint64_t signbit6 : 1;
+ uint64_t belowtrip6 : 1;
+ uint64_t abovetrip6 : 1;
+ uint64_t crittrip6 : 1;
+ uint64_t status5 : 2;
+ uint64_t temp_frac5 : 2;
+ uint64_t temperature5 : 8;
+ uint64_t signbit5 : 1;
+ uint64_t belowtrip5 : 1;
+ uint64_t abovetrip5 : 1;
+ uint64_t crittrip5 : 1;
+ uint64_t status4 : 2;
+ uint64_t temp_frac4 : 2;
+ uint64_t temperature4 : 8;
+ uint64_t signbit4 : 1;
+ uint64_t belowtrip4 : 1;
+ uint64_t abovetrip4 : 1;
+ uint64_t crittrip4 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_sensor_cache_data4_7_t;
+
+
+
+typedef union centaur_dts_thermal_sensor_results {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dts0 : 12;
+ uint64_t thermal_trip0 : 2;
+ uint64_t spare0 : 1;
+ uint64_t valid0 : 1;
+ uint64_t dts1 : 12;
+ uint64_t thermal_trip1 : 2;
+ uint64_t spare1 : 1;
+ uint64_t valid1 : 1;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t valid1 : 1;
+ uint64_t spare1 : 1;
+ uint64_t thermal_trip1 : 2;
+ uint64_t dts1 : 12;
+ uint64_t valid0 : 1;
+ uint64_t spare0 : 1;
+ uint64_t thermal_trip0 : 2;
+ uint64_t dts0 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} centaur_dts_thermal_sensor_results_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __CENTAUR_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/centaur_register_addresses.h b/src/ssx/pgp/registers/centaur_register_addresses.h
new file mode 100755
index 0000000..7c9c095
--- /dev/null
+++ b/src/ssx/pgp/registers/centaur_register_addresses.h
@@ -0,0 +1,66 @@
+#ifndef __CENTAUR_REGISTER_ADDRESSES_H__
+#define __CENTAUR_REGISTER_ADDRESSES_H__
+
+// $Id: centaur_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/centaur_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file centaur_register_addresses.h
+/// \brief Symbolic addresses for the CENTAUR unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define CENTAUR_PIB_BASE 0
+#define CENTAUR_DEVICE_ID 0x000f000f
+#define CENTAUR_MBS_FIR_REG 0x02011400
+#define CENTAUR_MBS_FIR_REG_AND 0x02011401
+#define CENTAUR_MBS_FIR_REG_OR 0x02011402
+#define CENTAUR_MBS_FIR_MASK_REG 0x02011403
+#define CENTAUR_MBS_FIR_MASK_REG_AND 0x02011404
+#define CENTAUR_MBS_FIR_MASK_REG_OR 0x02011405
+#define CENTAUR_MBS_FIR_ACTION0_REG 0x02011406
+#define CENTAUR_MBS_FIRACT1 0x02011407
+#define CENTAUR_MBSCFGQ 0x02011411
+#define CENTAUR_MBSEMERTHROQ 0x0201142d
+#define CENTAUR_MBSOCC01HQ 0x02011429
+#define CENTAUR_MBSOCC23HQ 0x0201142a
+#define CENTAUR_MBSOCCITCQ 0x02011428
+#define CENTAUR_MBSOCCSCANQ 0x0201142b
+#define CENTAUR_MBARPC0QN(n) (CENTAUR_MBARPC0Q0 + ((CENTAUR_MBARPC0Q1 - CENTAUR_MBARPC0Q0) * (n)))
+#define CENTAUR_MBARPC0Q0 0x03010434
+#define CENTAUR_MBARPC0Q1 0x03010c34
+#define CENTAUR_MBA_FARB3QN(n) (CENTAUR_MBA_FARB3Q0 + ((CENTAUR_MBA_FARB3Q1 - CENTAUR_MBA_FARB3Q0) * (n)))
+#define CENTAUR_MBA_FARB3Q0 0x03010416
+#define CENTAUR_MBA_FARB3Q1 0x03010c16
+#define CENTAUR_PMU0QN(n) (CENTAUR_PMU0Q0 + ((CENTAUR_PMU0Q1 - CENTAUR_PMU0Q0) * (n)))
+#define CENTAUR_PMU0Q0 0x03010437
+#define CENTAUR_PMU0Q1 0x03010c37
+#define CENTAUR_PMU1QN(n) (CENTAUR_PMU1Q0 + ((CENTAUR_PMU1Q1 - CENTAUR_PMU1Q0) * (n)))
+#define CENTAUR_PMU1Q0 0x03010438
+#define CENTAUR_PMU1Q1 0x03010c38
+#define CENTAUR_PMU2QN(n) (CENTAUR_PMU2Q0 + ((CENTAUR_PMU2Q1 - CENTAUR_PMU2Q0) * (n)))
+#define CENTAUR_PMU2Q0 0x03010439
+#define CENTAUR_PMU2Q1 0x03010c39
+#define CENTAUR_PMU3QN(n) (CENTAUR_PMU3Q0 + ((CENTAUR_PMU3Q1 - CENTAUR_PMU3Q0) * (n)))
+#define CENTAUR_PMU3Q0 0x0301043a
+#define CENTAUR_PMU3Q1 0x03010c3a
+#define CENTAUR_PMU4QN(n) (CENTAUR_PMU4Q0 + ((CENTAUR_PMU4Q1 - CENTAUR_PMU4Q0) * (n)))
+#define CENTAUR_PMU4Q0 0x0301043b
+#define CENTAUR_PMU4Q1 0x03010c3b
+#define CENTAUR_PMU5QN(n) (CENTAUR_PMU5Q0 + ((CENTAUR_PMU5Q1 - CENTAUR_PMU5Q0) * (n)))
+#define CENTAUR_PMU5Q0 0x0301043c
+#define CENTAUR_PMU5Q1 0x03010c3c
+#define CENTAUR_PMU6QN(n) (CENTAUR_PMU6Q0 + ((CENTAUR_PMU6Q1 - CENTAUR_PMU6Q0) * (n)))
+#define CENTAUR_PMU6Q0 0x0301043d
+#define CENTAUR_PMU6Q1 0x03010c3d
+#define CENTAUR_SENSOR_CACHE_DATA0_3 0x020115ca
+#define CENTAUR_SENSOR_CACHE_DATA4_7 0x020115cb
+#define CENTAUR_DTS_THERMAL_SENSOR_RESULTS 0x02050000
+
+#endif // __CENTAUR_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/fasti2c_firmware_registers.h b/src/ssx/pgp/registers/fasti2c_firmware_registers.h
new file mode 100644
index 0000000..4390508
--- /dev/null
+++ b/src/ssx/pgp/registers/fasti2c_firmware_registers.h
@@ -0,0 +1,232 @@
+#ifndef __FASTI2C_FIRMWARE_REGISTERS_H__
+#define __FASTI2C_FIRMWARE_REGISTERS_H__
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+// $Id: fasti2c_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+
+/// \file fasti2c_firmware_registers.h
+/// \brief C register structs for the FASTI2C unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#include <stdint.h>
+
+
+
+typedef union fasti2c_control {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t with_start : 1;
+ uint64_t with_address : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_stop : 1;
+ uint64_t data_length : 4;
+ uint64_t device_address : 7;
+ uint64_t read_not_write : 1;
+ uint64_t speed : 2;
+ uint64_t port_number : 5;
+ uint64_t address_range : 3;
+ uint64_t _reserved0 : 6;
+ uint64_t data0 : 8;
+ uint64_t data1 : 8;
+ uint64_t data2 : 8;
+ uint64_t data3 : 8;
+#else
+ uint64_t data3 : 8;
+ uint64_t data2 : 8;
+ uint64_t data1 : 8;
+ uint64_t data0 : 8;
+ uint64_t _reserved0 : 6;
+ uint64_t address_range : 3;
+ uint64_t port_number : 5;
+ uint64_t speed : 2;
+ uint64_t read_not_write : 1;
+ uint64_t device_address : 7;
+ uint64_t data_length : 4;
+ uint64_t with_stop : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_address : 1;
+ uint64_t with_start : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} fasti2c_control_t;
+
+
+
+typedef union fasti2c_reset {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} fasti2c_reset_t;
+
+
+
+typedef union fasti2c_status {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pib_address_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t lb_parity_error : 1;
+ uint64_t read_data : 32;
+ uint64_t _reserved0 : 6;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_fifo_entry_count : 8;
+#else
+ uint64_t i2c_fifo_entry_count : 8;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t _reserved0 : 6;
+ uint64_t read_data : 32;
+ uint64_t lb_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_address_invalid : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} fasti2c_status_t;
+
+
+
+typedef union fasti2c_data {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} fasti2c_data_t;
+
+
+
+typedef union fasti2c_ecc_start {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} fasti2c_ecc_start_t;
+
+
+
+typedef union fasti2c_ecc_stop {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} fasti2c_ecc_stop_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __FASTI2C_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/fasti2c_register_addresses.h b/src/ssx/pgp/registers/fasti2c_register_addresses.h
new file mode 100644
index 0000000..b034831
--- /dev/null
+++ b/src/ssx/pgp/registers/fasti2c_register_addresses.h
@@ -0,0 +1,27 @@
+#ifndef __FASTI2C_REGISTER_ADDRESSES_H__
+#define __FASTI2C_REGISTER_ADDRESSES_H__
+
+// $Id: fasti2c_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+
+/// \file fasti2c_register_addresses.h
+/// \brief Symbolic addresses for the FASTI2C unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define FASTI2C_LPCM_PIB_BASE 0x0000000b
+#define FASTI2C_CONTROL_OFFSET 0x00000000
+#define FASTI2C_LPCM_CONTROL 0x0000000b
+#define FASTI2C_RESET_OFFSET 0x00000001
+#define FASTI2C_LPCM_RESET 0x0000000c
+#define FASTI2C_STATUS_OFFSET 0x00000002
+#define FASTI2C_LPCM_STATUS 0x0000000d
+#define FASTI2C_DATA_OFFSET 0x00000003
+#define FASTI2C_LPCM_DATA 0x0000000e
+#define FASTI2C_ECC_START_OFFSET 0x00000004
+#define FASTI2C_LPCM_ECC_START 0x0000000f
+#define FASTI2C_ECC_STOP_OFFSET 0x00000005
+#define FASTI2C_LPCM_ECC_STOP 0x00000010
+
+#endif // __FASTI2C_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/i2cengine_firmware_registers.h b/src/ssx/pgp/registers/i2cengine_firmware_registers.h
new file mode 100644
index 0000000..ed02574
--- /dev/null
+++ b/src/ssx/pgp/registers/i2cengine_firmware_registers.h
@@ -0,0 +1,710 @@
+#ifndef __I2CENGINE_FIRMWARE_REGISTERS_H__
+#define __I2CENGINE_FIRMWARE_REGISTERS_H__
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+// $Id: i2cengine_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+
+/// \file i2cengine_firmware_registers.h
+/// \brief C register structs for the I2CENGINE unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#include <stdint.h>
+
+
+
+typedef union i2cengine_fast_control {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t with_start : 1;
+ uint64_t with_address : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_stop : 1;
+ uint64_t data_length : 4;
+ uint64_t device_address : 7;
+ uint64_t read_not_write : 1;
+ uint64_t speed : 2;
+ uint64_t port_number : 5;
+ uint64_t address_range : 3;
+ uint64_t _reserved0 : 6;
+ uint64_t data0 : 8;
+ uint64_t data1 : 8;
+ uint64_t data2 : 8;
+ uint64_t data3 : 8;
+#else
+ uint64_t data3 : 8;
+ uint64_t data2 : 8;
+ uint64_t data1 : 8;
+ uint64_t data0 : 8;
+ uint64_t _reserved0 : 6;
+ uint64_t address_range : 3;
+ uint64_t port_number : 5;
+ uint64_t speed : 2;
+ uint64_t read_not_write : 1;
+ uint64_t device_address : 7;
+ uint64_t data_length : 4;
+ uint64_t with_stop : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_address : 1;
+ uint64_t with_start : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_fast_control_t;
+
+
+
+typedef union i2cengine_fast_reset {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_fast_reset_t;
+
+
+
+typedef union i2cengine_fast_status {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pib_address_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t lb_parity_error : 1;
+ uint64_t read_data : 32;
+ uint64_t _reserved0 : 6;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_fifo_entry_count : 8;
+#else
+ uint64_t i2c_fifo_entry_count : 8;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t _reserved0 : 6;
+ uint64_t read_data : 32;
+ uint64_t lb_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_address_invalid : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_fast_status_t;
+
+
+
+typedef union i2cengine_fast_data {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_fast_data_t;
+
+
+
+typedef union i2cengine_fifo_byte {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t data : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t data : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_fifo_byte_t;
+
+
+
+typedef union i2cengine_command {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t with_start : 1;
+ uint64_t with_address : 1;
+ uint64_t read_continue : 1;
+ uint64_t not_used : 1;
+ uint64_t reserved : 4;
+ uint64_t device_address : 7;
+ uint64_t read_not_write : 1;
+ uint64_t length_bytes : 16;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t length_bytes : 16;
+ uint64_t read_not_write : 1;
+ uint64_t device_address : 7;
+ uint64_t reserved : 4;
+ uint64_t not_used : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_address : 1;
+ uint64_t with_start : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_command_t;
+
+
+
+typedef union i2cengine_mode {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t bit_rate_divisor : 15;
+ uint64_t _reserved0 : 1;
+ uint64_t port_number : 6;
+ uint64_t reserved : 6;
+ uint64_t enhanced_mode : 1;
+ uint64_t diagnostic_mode : 1;
+ uint64_t pacing_allow_mode : 1;
+ uint64_t wrap_mode : 1;
+ uint64_t _reserved1 : 32;
+#else
+ uint64_t _reserved1 : 32;
+ uint64_t wrap_mode : 1;
+ uint64_t pacing_allow_mode : 1;
+ uint64_t diagnostic_mode : 1;
+ uint64_t enhanced_mode : 1;
+ uint64_t reserved : 6;
+ uint64_t port_number : 6;
+ uint64_t _reserved0 : 1;
+ uint64_t bit_rate_divisor : 15;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_mode_t;
+
+
+
+typedef union i2cengine_watermark {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 15;
+ uint64_t _reserved0 : 1;
+ uint64_t high_water_mark : 4;
+ uint64_t reserved1 : 4;
+ uint64_t low_water_mark : 4;
+ uint64_t reserved2 : 4;
+ uint64_t _reserved1 : 32;
+#else
+ uint64_t _reserved1 : 32;
+ uint64_t reserved2 : 4;
+ uint64_t low_water_mark : 4;
+ uint64_t reserved1 : 4;
+ uint64_t high_water_mark : 4;
+ uint64_t _reserved0 : 1;
+ uint64_t reserved : 15;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_watermark_t;
+
+
+
+typedef union i2cengine_interrupt_mask {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 16;
+ uint64_t invalid_command : 1;
+ uint64_t lbus_parity_error : 1;
+ uint64_t back_end_overrun_error : 1;
+ uint64_t back_end_access_error : 1;
+ uint64_t arbitration_lost_error : 1;
+ uint64_t nack_received_error : 1;
+ uint64_t data_request : 1;
+ uint64_t command_complete : 1;
+ uint64_t stop_error : 1;
+ uint64_t i2c_busy : 1;
+ uint64_t not_i2c_busy : 1;
+ uint64_t reserved1 : 1;
+ uint64_t scl_eq_1 : 1;
+ uint64_t scl_eq_0 : 1;
+ uint64_t sda_eq_1 : 1;
+ uint64_t sda_eq_0 : 1;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t sda_eq_0 : 1;
+ uint64_t sda_eq_1 : 1;
+ uint64_t scl_eq_0 : 1;
+ uint64_t scl_eq_1 : 1;
+ uint64_t reserved1 : 1;
+ uint64_t not_i2c_busy : 1;
+ uint64_t i2c_busy : 1;
+ uint64_t stop_error : 1;
+ uint64_t command_complete : 1;
+ uint64_t data_request : 1;
+ uint64_t nack_received_error : 1;
+ uint64_t arbitration_lost_error : 1;
+ uint64_t back_end_access_error : 1;
+ uint64_t back_end_overrun_error : 1;
+ uint64_t lbus_parity_error : 1;
+ uint64_t invalid_command : 1;
+ uint64_t reserved : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_interrupt_mask_t;
+
+
+
+typedef union i2cengine_interrupt_condition {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 16;
+ uint64_t invalid_command : 1;
+ uint64_t lbus_parity_error : 1;
+ uint64_t back_end_overrun_error : 1;
+ uint64_t back_end_access_error : 1;
+ uint64_t arbitration_lost_error : 1;
+ uint64_t nack_received_error : 1;
+ uint64_t data_request : 1;
+ uint64_t command_complete : 1;
+ uint64_t stop_error : 1;
+ uint64_t i2c_busy : 1;
+ uint64_t not_i2c_busy : 1;
+ uint64_t reserved1 : 1;
+ uint64_t scl_eq_1 : 1;
+ uint64_t scl_eq_0 : 1;
+ uint64_t sda_eq_1 : 1;
+ uint64_t sda_eq_0 : 1;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t sda_eq_0 : 1;
+ uint64_t sda_eq_1 : 1;
+ uint64_t scl_eq_0 : 1;
+ uint64_t scl_eq_1 : 1;
+ uint64_t reserved1 : 1;
+ uint64_t not_i2c_busy : 1;
+ uint64_t i2c_busy : 1;
+ uint64_t stop_error : 1;
+ uint64_t command_complete : 1;
+ uint64_t data_request : 1;
+ uint64_t nack_received_error : 1;
+ uint64_t arbitration_lost_error : 1;
+ uint64_t back_end_access_error : 1;
+ uint64_t back_end_overrun_error : 1;
+ uint64_t lbus_parity_error : 1;
+ uint64_t invalid_command : 1;
+ uint64_t reserved : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_interrupt_condition_t;
+
+
+
+typedef union i2cengine_interrupts {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 16;
+ uint64_t invalid_command : 1;
+ uint64_t lbus_parity_error : 1;
+ uint64_t back_end_overrun_error : 1;
+ uint64_t back_end_access_error : 1;
+ uint64_t arbitration_lost_error : 1;
+ uint64_t nack_received_error : 1;
+ uint64_t data_request : 1;
+ uint64_t command_complete : 1;
+ uint64_t stop_error : 1;
+ uint64_t i2c_busy : 1;
+ uint64_t not_i2c_busy : 1;
+ uint64_t reserved1 : 1;
+ uint64_t scl_eq_1 : 1;
+ uint64_t scl_eq_0 : 1;
+ uint64_t sda_eq_1 : 1;
+ uint64_t sda_eq_0 : 1;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t sda_eq_0 : 1;
+ uint64_t sda_eq_1 : 1;
+ uint64_t scl_eq_0 : 1;
+ uint64_t scl_eq_1 : 1;
+ uint64_t reserved1 : 1;
+ uint64_t not_i2c_busy : 1;
+ uint64_t i2c_busy : 1;
+ uint64_t stop_error : 1;
+ uint64_t command_complete : 1;
+ uint64_t data_request : 1;
+ uint64_t nack_received_error : 1;
+ uint64_t arbitration_lost_error : 1;
+ uint64_t back_end_access_error : 1;
+ uint64_t back_end_overrun_error : 1;
+ uint64_t lbus_parity_error : 1;
+ uint64_t invalid_command : 1;
+ uint64_t reserved : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_interrupts_t;
+
+
+
+typedef union i2cengine_status {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t invalid_command : 1;
+ uint64_t lbus_parity_error : 1;
+ uint64_t back_end_overrun_error : 1;
+ uint64_t back_end_access_error : 1;
+ uint64_t arbitration_lost_error : 1;
+ uint64_t nack_received_error : 1;
+ uint64_t data_request : 1;
+ uint64_t command_complete : 1;
+ uint64_t stop_error : 1;
+ uint64_t upper_threshold : 6;
+ uint64_t _reserved0 : 1;
+ uint64_t any_i2c_interrupt : 1;
+ uint64_t reserved1 : 3;
+ uint64_t scl_input_lvl : 1;
+ uint64_t sda_input_lvl : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t fifo_entry_count : 8;
+ uint64_t _reserved1 : 32;
+#else
+ uint64_t _reserved1 : 32;
+ uint64_t fifo_entry_count : 8;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t sda_input_lvl : 1;
+ uint64_t scl_input_lvl : 1;
+ uint64_t reserved1 : 3;
+ uint64_t any_i2c_interrupt : 1;
+ uint64_t _reserved0 : 1;
+ uint64_t upper_threshold : 6;
+ uint64_t stop_error : 1;
+ uint64_t command_complete : 1;
+ uint64_t data_request : 1;
+ uint64_t nack_received_error : 1;
+ uint64_t arbitration_lost_error : 1;
+ uint64_t back_end_access_error : 1;
+ uint64_t back_end_overrun_error : 1;
+ uint64_t lbus_parity_error : 1;
+ uint64_t invalid_command : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_status_t;
+
+
+
+typedef union i2cengine_extended_status {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t table_base_addr : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t table_base_addr : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_extended_status_t;
+
+
+
+typedef union i2cengine_residual_front_end_back_end_length {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t residual_front_end_length : 16;
+ uint64_t residual_back_end_length : 16;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t residual_back_end_length : 16;
+ uint64_t residual_front_end_length : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_residual_front_end_back_end_length_t;
+
+
+
+typedef union i2cengine_immediate_reset_s_scl {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t residual_front_end_length : 16;
+ uint64_t residual_back_end_length : 16;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t residual_back_end_length : 16;
+ uint64_t residual_front_end_length : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_immediate_reset_s_scl_t;
+
+
+
+typedef union i2cengine_immediate_set_s_sda {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t residual_front_end_length : 16;
+ uint64_t residual_back_end_length : 16;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t residual_back_end_length : 16;
+ uint64_t residual_front_end_length : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_immediate_set_s_sda_t;
+
+
+
+typedef union i2cengine_immediate_reset_s_sda {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t field : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t field : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_immediate_reset_s_sda_t;
+
+
+
+typedef union i2cengine_fifo_word {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t data : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t data : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} i2cengine_fifo_word_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __I2CENGINE_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/i2cengine_register_addresses.h b/src/ssx/pgp/registers/i2cengine_register_addresses.h
new file mode 100644
index 0000000..bbe9104
--- /dev/null
+++ b/src/ssx/pgp/registers/i2cengine_register_addresses.h
@@ -0,0 +1,33 @@
+#ifndef __I2CENGINE_REGISTER_ADDRESSES_H__
+#define __I2CENGINE_REGISTER_ADDRESSES_H__
+
+// $Id: i2cengine_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+
+/// \file i2cengine_register_addresses.h
+/// \brief Symbolic addresses for the I2CENGINE unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define I2CENGINE_PIB_BASE 0x00000000
+#define I2CENGINE_FAST_CONTROL 0x00000000
+#define I2CENGINE_FAST_RESET 0x00000001
+#define I2CENGINE_FAST_STATUS 0x00000002
+#define I2CENGINE_FAST_DATA 0x00000003
+#define I2CENGINE_FIFO_BYTE 0x00000004
+#define I2CENGINE_COMMAND 0x00000005
+#define I2CENGINE_MODE 0x00000006
+#define I2CENGINE_WATERMARK 0x00000007
+#define I2CENGINE_INTERRUPT_MASK 0x00000008
+#define I2CENGINE_INTERRUPT_CONDITION 0x00000009
+#define I2CENGINE_INTERRUPTS 0x0000000a
+#define I2CENGINE_STATUS 0x0000000b
+#define I2CENGINE_EXTENDED_STATUS 0x0000000c
+#define I2CENGINE_RESIDUAL_FRONT_END_BACK_END_LENGTH 0x0000000d
+#define I2CENGINE_IMMEDIATE_RESET_S_SCL 0x0000000f
+#define I2CENGINE_IMMEDIATE_SET_S_SDA 0x00000010
+#define I2CENGINE_IMMEDIATE_RESET_S_SDA 0x00000011
+#define I2CENGINE_FIFO_WORD 0x00000012
+
+#endif // __I2CENGINE_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/icp_firmware_registers.h b/src/ssx/pgp/registers/icp_firmware_registers.h
new file mode 100755
index 0000000..4e17a68
--- /dev/null
+++ b/src/ssx/pgp/registers/icp_firmware_registers.h
@@ -0,0 +1,189 @@
+#ifndef __ICP_FIRMWARE_REGISTERS_H__
+#define __ICP_FIRMWARE_REGISTERS_H__
+
+// $Id: icp_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/icp_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file icp_firmware_registers.h
+/// \brief C register structs for the ICP unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union icp_bar {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t icp_bar : 30;
+ uint64_t icp_bar_en : 1;
+ uint64_t _reserved0 : 33;
+#else
+ uint64_t _reserved0 : 33;
+ uint64_t icp_bar_en : 1;
+ uint64_t icp_bar : 30;
+#endif // _BIG_ENDIAN
+ } fields;
+} icp_bar_t;
+
+#endif // __ASSEMBLER__
+#define ICP_BAR_ICP_BAR_MASK SIXTYFOUR_BIT_CONSTANT(0xfffffffc00000000)
+#define ICP_BAR_ICP_BAR_EN SIXTYFOUR_BIT_CONSTANT(0x0000000200000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union icp_mode0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t priority : 8;
+ uint64_t reserved0 : 1;
+ uint64_t scope_initial : 3;
+ uint64_t reserved1 : 1;
+ uint64_t no_hang2status : 1;
+ uint64_t oper_disable_hang : 1;
+ uint64_t oper_hang_div : 5;
+ uint64_t reserved2 : 2;
+ uint64_t data_disable_hang : 1;
+ uint64_t data_hang_div : 5;
+ uint64_t backoff_disable : 1;
+ uint64_t fwd_que_fwd_conv_disable : 1;
+ uint64_t disa_wait4cresp_mode4ris : 1;
+ uint64_t disa_auto_no_retry4ris : 1;
+ uint64_t disa_retry_mode4ris : 1;
+ uint64_t hang_on_addr_error : 1;
+ uint64_t eoi_correction : 2;
+ uint64_t max_load_count : 4;
+ uint64_t max_store_count : 4;
+ uint64_t reserved3 : 3;
+ uint64_t enable_inject : 1;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t enable_inject : 1;
+ uint64_t reserved3 : 3;
+ uint64_t max_store_count : 4;
+ uint64_t max_load_count : 4;
+ uint64_t eoi_correction : 2;
+ uint64_t hang_on_addr_error : 1;
+ uint64_t disa_retry_mode4ris : 1;
+ uint64_t disa_auto_no_retry4ris : 1;
+ uint64_t disa_wait4cresp_mode4ris : 1;
+ uint64_t fwd_que_fwd_conv_disable : 1;
+ uint64_t backoff_disable : 1;
+ uint64_t data_hang_div : 5;
+ uint64_t data_disable_hang : 1;
+ uint64_t reserved2 : 2;
+ uint64_t oper_hang_div : 5;
+ uint64_t oper_disable_hang : 1;
+ uint64_t no_hang2status : 1;
+ uint64_t reserved1 : 1;
+ uint64_t scope_initial : 3;
+ uint64_t reserved0 : 1;
+ uint64_t priority : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} icp_mode0_t;
+
+#endif // __ASSEMBLER__
+#define ICP_MODE0_PRIORITY_MASK SIXTYFOUR_BIT_CONSTANT(0xff00000000000000)
+#define ICP_MODE0_SCOPE_INITIAL_MASK SIXTYFOUR_BIT_CONSTANT(0x0070000000000000)
+#define ICP_MODE0_NO_HANG2STATUS SIXTYFOUR_BIT_CONSTANT(0x0004000000000000)
+#define ICP_MODE0_OPER_DISABLE_HANG SIXTYFOUR_BIT_CONSTANT(0x0002000000000000)
+#define ICP_MODE0_OPER_HANG_DIV_MASK SIXTYFOUR_BIT_CONSTANT(0x0001f00000000000)
+#define ICP_MODE0_DATA_DISABLE_HANG SIXTYFOUR_BIT_CONSTANT(0x0000020000000000)
+#define ICP_MODE0_DATA_HANG_DIV_MASK SIXTYFOUR_BIT_CONSTANT(0x000001f000000000)
+#define ICP_MODE0_BACKOFF_DISABLE SIXTYFOUR_BIT_CONSTANT(0x0000000800000000)
+#define ICP_MODE0_FWD_QUE_FWD_CONV_DISABLE SIXTYFOUR_BIT_CONSTANT(0x0000000400000000)
+#define ICP_MODE0_DISA_WAIT4CRESP_MODE4RIS SIXTYFOUR_BIT_CONSTANT(0x0000000200000000)
+#define ICP_MODE0_DISA_AUTO_NO_RETRY4RIS SIXTYFOUR_BIT_CONSTANT(0x0000000100000000)
+#define ICP_MODE0_DISA_RETRY_MODE4RIS SIXTYFOUR_BIT_CONSTANT(0x0000000080000000)
+#define ICP_MODE0_HANG_ON_ADDR_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000040000000)
+#define ICP_MODE0_EOI_CORRECTION_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000030000000)
+#define ICP_MODE0_MAX_LOAD_COUNT_MASK SIXTYFOUR_BIT_CONSTANT(0x000000000f000000)
+#define ICP_MODE0_MAX_STORE_COUNT_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000000f00000)
+#define ICP_MODE0_ENABLE_INJECT SIXTYFOUR_BIT_CONSTANT(0x0000000000010000)
+#ifndef __ASSEMBLER__
+
+
+typedef union icp_iir {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t inject_target_core : 16;
+ uint64_t inject_target_thread : 8;
+ uint64_t reserved0 : 8;
+ uint64_t inject_level : 4;
+ uint64_t reserved1 : 4;
+ uint64_t inject_priority : 8;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t inject_priority : 8;
+ uint64_t reserved1 : 4;
+ uint64_t inject_level : 4;
+ uint64_t reserved0 : 8;
+ uint64_t inject_target_thread : 8;
+ uint64_t inject_target_core : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} icp_iir_t;
+
+#endif // __ASSEMBLER__
+#define ICP_IIR_INJECT_TARGET_CORE_MASK SIXTYFOUR_BIT_CONSTANT(0xffff000000000000)
+#define ICP_IIR_INJECT_TARGET_THREAD_MASK SIXTYFOUR_BIT_CONSTANT(0x0000ff0000000000)
+#define ICP_IIR_INJECT_LEVEL_MASK SIXTYFOUR_BIT_CONSTANT(0x00000000f0000000)
+#define ICP_IIR_INJECT_PRIORITY_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000000ff0000)
+#ifndef __ASSEMBLER__
+
+#endif // __ASSEMBLER__
+#endif // __ICP_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/icp_register_addresses.h b/src/ssx/pgp/registers/icp_register_addresses.h
new file mode 100755
index 0000000..7cb8350
--- /dev/null
+++ b/src/ssx/pgp/registers/icp_register_addresses.h
@@ -0,0 +1,24 @@
+#ifndef __ICP_REGISTER_ADDRESSES_H__
+#define __ICP_REGISTER_ADDRESSES_H__
+
+// $Id: icp_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/icp_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file icp_register_addresses.h
+/// \brief Symbolic addresses for the ICP unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define ICP_PIB_BASE 0x020109c0
+#define ICP_BAR 0x020109ca
+#define ICP_MODE0 0x020109cb
+#define ICP_IIR 0x020109cc
+
+#endif // __ICP_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/mcs_firmware_registers.h b/src/ssx/pgp/registers/mcs_firmware_registers.h
new file mode 100755
index 0000000..b71b888
--- /dev/null
+++ b/src/ssx/pgp/registers/mcs_firmware_registers.h
@@ -0,0 +1,161 @@
+#ifndef __MCS_FIRMWARE_REGISTERS_H__
+#define __MCS_FIRMWARE_REGISTERS_H__
+
+// $Id: mcs_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/mcs_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file mcs_firmware_registers.h
+/// \brief C register structs for the MCS unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union mcfgpr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t mcfgprq_valid : 1;
+ uint64_t reserved0 : 5;
+ uint64_t mcfgprq_base_address : 14;
+ uint64_t _reserved0 : 44;
+#else
+ uint64_t _reserved0 : 44;
+ uint64_t mcfgprq_base_address : 14;
+ uint64_t reserved0 : 5;
+ uint64_t mcfgprq_valid : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} mcfgpr_t;
+
+#endif // __ASSEMBLER__
+#define MCFGPR_MCFGPRQ_VALID SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define MCFGPR_MCFGPRQ_BASE_ADDRESS_MASK SIXTYFOUR_BIT_CONSTANT(0x03fff00000000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union mcsmode0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t enable_cmd_byp_stutter : 1;
+ uint64_t reserved1 : 1;
+ uint64_t enable_ns_rd_ao_sfu_for_dcbz : 1;
+ uint64_t enable_centaur_local_checkstop_command : 1;
+ uint64_t l3_prefetch_retry_threshold : 4;
+ uint64_t number_of_cl_entries_reserved_for_read : 4;
+ uint64_t number_of_cl_entries_reserved_for_mirrored_ops : 4;
+ uint64_t number_of_cl_entries_reserved_for_writes : 4;
+ uint64_t number_of_cl_entries_reserved_for_cp_writes : 4;
+ uint64_t number_of_cl_entries_reserved_for_cp_ig : 4;
+ uint64_t number_of_cl_entries_reserved_for_htm_ops : 4;
+ uint64_t number_of_cl_entries_reserved_for_ha_assist : 4;
+ uint64_t mcfgrp_19_is_ho_bit : 1;
+ uint64_t cl_channel_timeout_forces_channel_fail : 1;
+ uint64_t enable_fault_line_for_global_checkstop : 1;
+ uint64_t reserved39 : 5;
+ uint64_t address_collision_modes : 9;
+ uint64_t include_cp_ig_in_cp_write_fullness_group : 1;
+ uint64_t enable_dmawr_cmd_bit : 1;
+ uint64_t enable_read_lsfr_data : 1;
+ uint64_t force_channel_fail : 1;
+ uint64_t disable_read_crc_ecc_bypass_taken : 1;
+ uint64_t disable_cl_ao_queueus : 1;
+ uint64_t address_select_lfsr_value : 2;
+ uint64_t enable_centaur_sync : 1;
+ uint64_t write_data_buffer_ecc_check_disable : 1;
+ uint64_t write_data_buffer_ecc_correct_disable : 1;
+#else
+ uint64_t write_data_buffer_ecc_correct_disable : 1;
+ uint64_t write_data_buffer_ecc_check_disable : 1;
+ uint64_t enable_centaur_sync : 1;
+ uint64_t address_select_lfsr_value : 2;
+ uint64_t disable_cl_ao_queueus : 1;
+ uint64_t disable_read_crc_ecc_bypass_taken : 1;
+ uint64_t force_channel_fail : 1;
+ uint64_t enable_read_lsfr_data : 1;
+ uint64_t enable_dmawr_cmd_bit : 1;
+ uint64_t include_cp_ig_in_cp_write_fullness_group : 1;
+ uint64_t address_collision_modes : 9;
+ uint64_t reserved39 : 5;
+ uint64_t enable_fault_line_for_global_checkstop : 1;
+ uint64_t cl_channel_timeout_forces_channel_fail : 1;
+ uint64_t mcfgrp_19_is_ho_bit : 1;
+ uint64_t number_of_cl_entries_reserved_for_ha_assist : 4;
+ uint64_t number_of_cl_entries_reserved_for_htm_ops : 4;
+ uint64_t number_of_cl_entries_reserved_for_cp_ig : 4;
+ uint64_t number_of_cl_entries_reserved_for_cp_writes : 4;
+ uint64_t number_of_cl_entries_reserved_for_writes : 4;
+ uint64_t number_of_cl_entries_reserved_for_mirrored_ops : 4;
+ uint64_t number_of_cl_entries_reserved_for_read : 4;
+ uint64_t l3_prefetch_retry_threshold : 4;
+ uint64_t enable_centaur_local_checkstop_command : 1;
+ uint64_t enable_ns_rd_ao_sfu_for_dcbz : 1;
+ uint64_t reserved1 : 1;
+ uint64_t enable_cmd_byp_stutter : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} mcsmode0_t;
+
+#endif // __ASSEMBLER__
+#define MCSMODE0_ENABLE_CMD_BYP_STUTTER SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define MCSMODE0_ENABLE_NS_RD_AO_SFU_FOR_DCBZ SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define MCSMODE0_ENABLE_CENTAUR_LOCAL_CHECKSTOP_COMMAND SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define MCSMODE0_L3_PREFETCH_RETRY_THRESHOLD_MASK SIXTYFOUR_BIT_CONSTANT(0x0f00000000000000)
+#define MCSMODE0_MCFGRP_19_IS_HO_BIT SIXTYFOUR_BIT_CONSTANT(0x0000000008000000)
+#define MCSMODE0_CL_CHANNEL_TIMEOUT_FORCES_CHANNEL_FAIL SIXTYFOUR_BIT_CONSTANT(0x0000000004000000)
+#define MCSMODE0_ENABLE_FAULT_LINE_FOR_GLOBAL_CHECKSTOP SIXTYFOUR_BIT_CONSTANT(0x0000000002000000)
+#define MCSMODE0_ADDRESS_COLLISION_MODES_MASK SIXTYFOUR_BIT_CONSTANT(0x00000000000ff800)
+#define MCSMODE0_INCLUDE_CP_IG_IN_CP_WRITE_FULLNESS_GROUP SIXTYFOUR_BIT_CONSTANT(0x0000000000000400)
+#define MCSMODE0_ENABLE_DMAWR_CMD_BIT SIXTYFOUR_BIT_CONSTANT(0x0000000000000200)
+#define MCSMODE0_ENABLE_READ_LSFR_DATA SIXTYFOUR_BIT_CONSTANT(0x0000000000000100)
+#define MCSMODE0_FORCE_CHANNEL_FAIL SIXTYFOUR_BIT_CONSTANT(0x0000000000000080)
+#define MCSMODE0_DISABLE_READ_CRC_ECC_BYPASS_TAKEN SIXTYFOUR_BIT_CONSTANT(0x0000000000000040)
+#define MCSMODE0_DISABLE_CL_AO_QUEUEUS SIXTYFOUR_BIT_CONSTANT(0x0000000000000020)
+#define MCSMODE0_ADDRESS_SELECT_LFSR_VALUE_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000000000018)
+#define MCSMODE0_ENABLE_CENTAUR_SYNC SIXTYFOUR_BIT_CONSTANT(0x0000000000000004)
+#define MCSMODE0_WRITE_DATA_BUFFER_ECC_CHECK_DISABLE SIXTYFOUR_BIT_CONSTANT(0x0000000000000002)
+#define MCSMODE0_WRITE_DATA_BUFFER_ECC_CORRECT_DISABLE SIXTYFOUR_BIT_CONSTANT(0x0000000000000001)
+#ifndef __ASSEMBLER__
+
+#endif // __ASSEMBLER__
+#endif // __MCS_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/mcs_register_addresses.h b/src/ssx/pgp/registers/mcs_register_addresses.h
new file mode 100755
index 0000000..bc7f95c
--- /dev/null
+++ b/src/ssx/pgp/registers/mcs_register_addresses.h
@@ -0,0 +1,46 @@
+#ifndef __MCS_REGISTER_ADDRESSES_H__
+#define __MCS_REGISTER_ADDRESSES_H__
+
+// $Id: mcs_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/mcs_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file mcs_register_addresses.h
+/// \brief Symbolic addresses for the MCS unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define MCS0_PIB_BASE 0x02011800
+#define MCS1_PIB_BASE 0x02011880
+#define MCS2_PIB_BASE 0x02011900
+#define MCS3_PIB_BASE 0x02011980
+#define MCS4_PIB_BASE 0x02011C00
+#define MCS5_PIB_BASE 0x02011C80
+#define MCS6_PIB_BASE 0x02011D00
+#define MCS7_PIB_BASE 0x02011D80
+#define MCFGPR_OFFSET 0x00000002
+#define MCS0_MCFGPR 0x02011802
+#define MCS1_MCFGPR 0x02011882
+#define MCS2_MCFGPR 0x02011902
+#define MCS3_MCFGPR 0x02011982
+#define MCS4_MCFGPR 0x02011c02
+#define MCS5_MCFGPR 0x02011c82
+#define MCS6_MCFGPR 0x02011d02
+#define MCS7_MCFGPR 0x02011d82
+#define MCSMODE0_OFFSET 0x00000007
+#define MCS0_MCSMODE0 0x02011807
+#define MCS1_MCSMODE0 0x02011887
+#define MCS2_MCSMODE0 0x02011907
+#define MCS3_MCSMODE0 0x02011987
+#define MCS4_MCSMODE0 0x02011c07
+#define MCS5_MCSMODE0 0x02011c87
+#define MCS6_MCSMODE0 0x02011d07
+#define MCS7_MCSMODE0 0x02011d87
+
+#endif // __MCS_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/ocb_firmware_registers.h b/src/ssx/pgp/registers/ocb_firmware_registers.h
new file mode 100755
index 0000000..4a4ddb2
--- /dev/null
+++ b/src/ssx/pgp/registers/ocb_firmware_registers.h
@@ -0,0 +1,2668 @@
+#ifndef __OCB_FIRMWARE_REGISTERS_H__
+#define __OCB_FIRMWARE_REGISTERS_H__
+
+// $Id: ocb_firmware_registers.h,v 1.2 2014/03/14 15:33:03 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/ocb_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ocb_firmware_registers.h
+/// \brief C register structs for the OCB unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union ocb_oitr0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oitr0_t;
+
+
+
+typedef union ocb_oiepr0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oiepr0_t;
+
+
+
+typedef union ocb_ocir0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocir0_t;
+
+
+
+typedef union ocb_onisr0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_onisr0_t;
+
+
+
+typedef union ocb_ouder0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ouder0_t;
+
+
+
+typedef union ocb_ocisr0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocisr0_t;
+
+
+
+typedef union ocb_odher0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t dbg_halt_en : 32;
+#else
+ uint32_t dbg_halt_en : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_odher0_t;
+
+
+
+typedef union ocb_oisr0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t debugger : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t pba_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t spipss_error : 1;
+ uint32_t check_stop : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t external_trap : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t reserved_31 : 1;
+#else
+ uint32_t reserved_31 : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t external_trap : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t check_stop : 1;
+ uint32_t spipss_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pba_error : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t debugger : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oisr0_t;
+
+
+
+typedef union ocb_oisr0_and {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t debugger : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t pba_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t spipss_error : 1;
+ uint32_t check_stop : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t external_trap : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t reserved_31 : 1;
+#else
+ uint32_t reserved_31 : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t external_trap : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t check_stop : 1;
+ uint32_t spipss_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pba_error : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t debugger : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oisr0_and_t;
+
+
+
+typedef union ocb_oisr0_or {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t debugger : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t pba_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t spipss_error : 1;
+ uint32_t check_stop : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t external_trap : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t reserved_31 : 1;
+#else
+ uint32_t reserved_31 : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t external_trap : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t check_stop : 1;
+ uint32_t spipss_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pba_error : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t debugger : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oisr0_or_t;
+
+
+
+typedef union ocb_oimr0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t debugger : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t pba_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t spipss_error : 1;
+ uint32_t check_stop : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t external_trap : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t reserved_31 : 1;
+#else
+ uint32_t reserved_31 : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t external_trap : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t check_stop : 1;
+ uint32_t spipss_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pba_error : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t debugger : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oimr0_t;
+
+
+
+typedef union ocb_oimr0_and {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t debugger : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t pba_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t spipss_error : 1;
+ uint32_t check_stop : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t external_trap : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t reserved_31 : 1;
+#else
+ uint32_t reserved_31 : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t external_trap : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t check_stop : 1;
+ uint32_t spipss_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pba_error : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t debugger : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oimr0_and_t;
+
+
+
+typedef union ocb_oimr0_or {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t debugger : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t pba_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t spipss_error : 1;
+ uint32_t check_stop : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t external_trap : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t reserved_31 : 1;
+#else
+ uint32_t reserved_31 : 1;
+ uint32_t pba_bcue_attn : 1;
+ uint32_t pba_bcde_attn : 1;
+ uint32_t pba_occ_push1 : 1;
+ uint32_t pba_occ_push0 : 1;
+ uint32_t reserved_26 : 1;
+ uint32_t adcfsm_ongoing : 1;
+ uint32_t pore_gpe1_complete : 1;
+ uint32_t pore_gpe0_complete : 1;
+ uint32_t reserved_22 : 1;
+ uint32_t pmc_interchip_msg_recv : 1;
+ uint32_t pore_sbe_error : 1;
+ uint32_t pore_gpe1_error : 1;
+ uint32_t pore_gpe0_error : 1;
+ uint32_t occ_timer1 : 1;
+ uint32_t occ_timer0 : 1;
+ uint32_t external_trap : 1;
+ uint32_t adu_malf_alert : 1;
+ uint32_t pmc_malf_alert : 1;
+ uint32_t check_stop : 1;
+ uint32_t spipss_error : 1;
+ uint32_t ocb_error : 1;
+ uint32_t pmc_error : 1;
+ uint32_t pore_sbe_fatal_error : 1;
+ uint32_t pore_gpe1_fatal_error : 1;
+ uint32_t pore_gpe0_fatal_error : 1;
+ uint32_t pore_sw_error : 1;
+ uint32_t srt_error : 1;
+ uint32_t pba_error : 1;
+ uint32_t reserved_2 : 1;
+ uint32_t trace_trigger : 1;
+ uint32_t debugger : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oimr0_or_t;
+
+
+
+typedef union ocb_oitr1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oitr1_t;
+
+
+
+typedef union ocb_oiepr1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oiepr1_t;
+
+
+
+typedef union ocb_ocir1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocir1_t;
+
+
+
+typedef union ocb_onisr1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_onisr1_t;
+
+
+
+typedef union ocb_ouder1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ouder1_t;
+
+
+
+typedef union ocb_ocisr1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocisr1_t;
+
+
+
+typedef union ocb_odher1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t dbg_halt_en : 32;
+#else
+ uint32_t dbg_halt_en : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_odher1_t;
+
+
+
+typedef union ocb_oisr1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved_32 : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t ipi0 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t reserved_63 : 1;
+#else
+ uint32_t reserved_63 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi0 : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t reserved_32 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oisr1_t;
+
+
+
+typedef union ocb_oisr1_and {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved_32 : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t ipi0 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t reserved_63 : 1;
+#else
+ uint32_t reserved_63 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi0 : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t reserved_32 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oisr1_and_t;
+
+
+
+typedef union ocb_oisr1_or {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved_32 : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t ipi0 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t reserved_63 : 1;
+#else
+ uint32_t reserved_63 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi0 : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t reserved_32 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oisr1_or_t;
+
+
+
+typedef union ocb_oimr1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved_32 : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t ipi0 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t reserved_63 : 1;
+#else
+ uint32_t reserved_63 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi0 : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t reserved_32 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oimr1_t;
+
+
+
+typedef union ocb_oimr1_and {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved_32 : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t ipi0 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t reserved_63 : 1;
+#else
+ uint32_t reserved_63 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi0 : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t reserved_32 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oimr1_and_t;
+
+
+
+typedef union ocb_oimr1_or {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved_32 : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t ipi0 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t reserved_63 : 1;
+#else
+ uint32_t reserved_63 : 1;
+ uint32_t ipi3 : 1;
+ uint32_t ipi2 : 1;
+ uint32_t ipi1 : 1;
+ uint32_t ipi0 : 1;
+ uint32_t pore_sbe_complete : 1;
+ uint32_t pssbridge_ongoing : 1;
+ uint32_t pmc_ocb_o2p_ongoing : 1;
+ uint32_t oci2spivid_ongoing : 1;
+ uint32_t pmc_interchip_msg_send_ongoing : 1;
+ uint32_t reserved_53 : 1;
+ uint32_t pmc_idle_enter : 1;
+ uint32_t pore_sw_complete : 1;
+ uint32_t pmc_idle_exit : 1;
+ uint32_t reserved_49 : 1;
+ uint32_t reserved_48 : 1;
+ uint32_t pmc_pstate_change : 1;
+ uint32_t pmc_sync : 1;
+ uint32_t pmc_protocol_ongoing : 1;
+ uint32_t pmc_voltage_change_ongoing : 1;
+ uint32_t reserved_43 : 1;
+ uint32_t reserved_42 : 1;
+ uint32_t occ_strm3_push : 1;
+ uint32_t occ_strm3_pull : 1;
+ uint32_t occ_strm2_push : 1;
+ uint32_t occ_strm2_pull : 1;
+ uint32_t occ_strm1_push : 1;
+ uint32_t occ_strm1_pull : 1;
+ uint32_t occ_strm0_push : 1;
+ uint32_t occ_strm0_pull : 1;
+ uint32_t reserved_33 : 1;
+ uint32_t reserved_32 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oimr1_or_t;
+
+
+
+typedef union ocb_occmisc {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t core_ext_intr : 1;
+ uint32_t _reserved0 : 31;
+#else
+ uint32_t _reserved0 : 31;
+ uint32_t core_ext_intr : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occmisc_t;
+
+
+
+typedef union ocb_occmisc_and {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t core_ext_intr : 1;
+ uint32_t _reserved0 : 31;
+#else
+ uint32_t _reserved0 : 31;
+ uint32_t core_ext_intr : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occmisc_and_t;
+
+
+
+typedef union ocb_occmisc_or {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t core_ext_intr : 1;
+ uint32_t _reserved0 : 31;
+#else
+ uint32_t _reserved0 : 31;
+ uint32_t core_ext_intr : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occmisc_or_t;
+
+
+
+typedef union ocb_otrn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t timeout : 1;
+ uint32_t control : 1;
+ uint32_t auto_reload : 1;
+ uint32_t reserved : 13;
+ uint32_t timer : 16;
+#else
+ uint32_t timer : 16;
+ uint32_t reserved : 13;
+ uint32_t auto_reload : 1;
+ uint32_t control : 1;
+ uint32_t timeout : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_otrn_t;
+
+#endif // __ASSEMBLER__
+#define OCB_OTRN_TIMEOUT 0x80000000
+#define OCB_OTRN_CONTROL 0x40000000
+#define OCB_OTRN_AUTO_RELOAD 0x20000000
+#define OCB_OTRN_TIMER_MASK 0x0000ffff
+#ifndef __ASSEMBLER__
+
+
+typedef union ocb_ohtmcr {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t htm_src_sel : 2;
+ uint32_t htm_stop : 1;
+ uint32_t htm_marker_slave_adrs : 3;
+ uint32_t event2halt_mode : 2;
+ uint32_t event2halt_en : 11;
+ uint32_t reserved : 1;
+ uint32_t event2halt_halt : 1;
+ uint32_t _reserved0 : 11;
+#else
+ uint32_t _reserved0 : 11;
+ uint32_t event2halt_halt : 1;
+ uint32_t reserved : 1;
+ uint32_t event2halt_en : 11;
+ uint32_t event2halt_mode : 2;
+ uint32_t htm_marker_slave_adrs : 3;
+ uint32_t htm_stop : 1;
+ uint32_t htm_src_sel : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ohtmcr_t;
+
+
+
+typedef union ocb_oehdr {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t event2halt_delay : 20;
+ uint32_t _reserved0 : 12;
+#else
+ uint32_t _reserved0 : 12;
+ uint32_t event2halt_delay : 20;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oehdr_t;
+
+
+
+typedef union ocb_ocbslbrn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pull_oci_region : 2;
+ uint32_t pull_start : 27;
+ uint32_t _reserved0 : 3;
+#else
+ uint32_t _reserved0 : 3;
+ uint32_t pull_start : 27;
+ uint32_t pull_oci_region : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbslbrn_t;
+
+
+
+typedef union ocb_ocbshbrn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t push_oci_region : 2;
+ uint32_t push_start : 27;
+ uint32_t _reserved0 : 3;
+#else
+ uint32_t _reserved0 : 3;
+ uint32_t push_start : 27;
+ uint32_t push_oci_region : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbshbrn_t;
+
+
+
+typedef union ocb_ocbslcsn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pull_full : 1;
+ uint32_t pull_empty : 1;
+ uint32_t reserved0 : 2;
+ uint32_t pull_intr_action : 2;
+ uint32_t pull_length : 5;
+ uint32_t reserved1 : 2;
+ uint32_t pull_write_ptr : 5;
+ uint32_t reserved2 : 3;
+ uint32_t pull_read_ptr : 5;
+ uint32_t reserved3 : 5;
+ uint32_t pull_enable : 1;
+#else
+ uint32_t pull_enable : 1;
+ uint32_t reserved3 : 5;
+ uint32_t pull_read_ptr : 5;
+ uint32_t reserved2 : 3;
+ uint32_t pull_write_ptr : 5;
+ uint32_t reserved1 : 2;
+ uint32_t pull_length : 5;
+ uint32_t pull_intr_action : 2;
+ uint32_t reserved0 : 2;
+ uint32_t pull_empty : 1;
+ uint32_t pull_full : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbslcsn_t;
+
+#endif // __ASSEMBLER__
+#define OCB_OCBSLCSN_PULL_FULL 0x80000000
+#define OCB_OCBSLCSN_PULL_EMPTY 0x40000000
+#define OCB_OCBSLCSN_PULL_INTR_ACTION_MASK 0x0c000000
+#define OCB_OCBSLCSN_PULL_LENGTH_MASK 0x03e00000
+#define OCB_OCBSLCSN_PULL_WRITE_PTR_MASK 0x0007c000
+#define OCB_OCBSLCSN_PULL_READ_PTR_MASK 0x000007c0
+#define OCB_OCBSLCSN_PULL_ENABLE 0x00000001
+#ifndef __ASSEMBLER__
+
+
+typedef union ocb_ocbshcsn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t push_full : 1;
+ uint32_t push_empty : 1;
+ uint32_t reserved0 : 2;
+ uint32_t push_intr_action : 2;
+ uint32_t push_length : 5;
+ uint32_t reserved1 : 2;
+ uint32_t push_write_ptr : 5;
+ uint32_t reserved2 : 3;
+ uint32_t push_read_ptr : 5;
+ uint32_t reserved3 : 5;
+ uint32_t push_enable : 1;
+#else
+ uint32_t push_enable : 1;
+ uint32_t reserved3 : 5;
+ uint32_t push_read_ptr : 5;
+ uint32_t reserved2 : 3;
+ uint32_t push_write_ptr : 5;
+ uint32_t reserved1 : 2;
+ uint32_t push_length : 5;
+ uint32_t push_intr_action : 2;
+ uint32_t reserved0 : 2;
+ uint32_t push_empty : 1;
+ uint32_t push_full : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbshcsn_t;
+
+#endif // __ASSEMBLER__
+#define OCB_OCBSHCSN_PUSH_FULL 0x80000000
+#define OCB_OCBSHCSN_PUSH_EMPTY 0x40000000
+#define OCB_OCBSHCSN_PUSH_INTR_ACTION_MASK 0x0c000000
+#define OCB_OCBSHCSN_PUSH_LENGTH_MASK 0x03e00000
+#define OCB_OCBSHCSN_PUSH_WRITE_PTR_MASK 0x0007c000
+#define OCB_OCBSHCSN_PUSH_READ_PTR_MASK 0x000007c0
+#define OCB_OCBSHCSN_PUSH_ENABLE 0x00000001
+#ifndef __ASSEMBLER__
+
+
+typedef union ocb_ocbslin {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved : 32;
+#else
+ uint32_t reserved : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbslin_t;
+
+
+
+typedef union ocb_ocbshin {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved : 32;
+#else
+ uint32_t reserved : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbshin_t;
+
+
+
+typedef union ocb_ocbsesn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t push_read_underflow : 1;
+ uint32_t pull_write_overflow : 1;
+ uint32_t _reserved0 : 30;
+#else
+ uint32_t _reserved0 : 30;
+ uint32_t pull_write_overflow : 1;
+ uint32_t push_read_underflow : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbsesn_t;
+
+
+
+typedef union ocb_ocbicrn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t allow_unsecure_pib_masters : 1;
+ uint32_t _reserved0 : 31;
+#else
+ uint32_t _reserved0 : 31;
+ uint32_t allow_unsecure_pib_masters : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbicrn_t;
+
+
+
+typedef union ocb_ocblwcrn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t linear_window_enable : 1;
+ uint32_t spare_0 : 3;
+ uint32_t linear_window_bar : 16;
+ uint32_t linear_window_mask : 12;
+#else
+ uint32_t linear_window_mask : 12;
+ uint32_t linear_window_bar : 16;
+ uint32_t spare_0 : 3;
+ uint32_t linear_window_enable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocblwcrn_t;
+
+
+
+typedef union ocb_ocblwsrn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t linear_window_scresp : 3;
+ uint32_t spare_0 : 5;
+ uint32_t _reserved0 : 24;
+#else
+ uint32_t _reserved0 : 24;
+ uint32_t spare_0 : 5;
+ uint32_t linear_window_scresp : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocblwsrn_t;
+
+
+
+typedef union ocb_ocblwsbrn {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t linear_window_region : 2;
+ uint32_t linear_window_base : 8;
+ uint32_t _reserved0 : 22;
+#else
+ uint32_t _reserved0 : 22;
+ uint32_t linear_window_base : 8;
+ uint32_t linear_window_region : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocblwsbrn_t;
+
+
+
+typedef union ocb_ocichsw {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t m0_priority : 2;
+ uint32_t m1_priority : 2;
+ uint32_t m2_priority : 2;
+ uint32_t m3_priority : 2;
+ uint32_t m4_priority : 2;
+ uint32_t m5_priority : 2;
+ uint32_t m6_priority : 2;
+ uint32_t m7_priority : 2;
+ uint32_t dcu_priority_sel : 1;
+ uint32_t icu_priority_sel : 1;
+ uint32_t plbarb_lockerr : 1;
+ uint32_t _reserved0 : 13;
+#else
+ uint32_t _reserved0 : 13;
+ uint32_t plbarb_lockerr : 1;
+ uint32_t icu_priority_sel : 1;
+ uint32_t dcu_priority_sel : 1;
+ uint32_t m7_priority : 2;
+ uint32_t m6_priority : 2;
+ uint32_t m5_priority : 2;
+ uint32_t m4_priority : 2;
+ uint32_t m3_priority : 2;
+ uint32_t m2_priority : 2;
+ uint32_t m1_priority : 2;
+ uint32_t m0_priority : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocichsw_t;
+
+
+
+typedef union ocb_ocr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t core_reset : 1;
+ uint64_t chip_reset : 1;
+ uint64_t system_reset : 1;
+ uint64_t oci_arb_reset : 1;
+ uint64_t trace_disable : 1;
+ uint64_t trace_event : 1;
+ uint64_t dbg_unconditional_event : 1;
+ uint64_t ext_interrupt : 1;
+ uint64_t critical_interrupt : 1;
+ uint64_t spare : 7;
+ uint64_t _reserved0 : 48;
+#else
+ uint64_t _reserved0 : 48;
+ uint64_t spare : 7;
+ uint64_t critical_interrupt : 1;
+ uint64_t ext_interrupt : 1;
+ uint64_t dbg_unconditional_event : 1;
+ uint64_t trace_event : 1;
+ uint64_t trace_disable : 1;
+ uint64_t oci_arb_reset : 1;
+ uint64_t system_reset : 1;
+ uint64_t chip_reset : 1;
+ uint64_t core_reset : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocr_t;
+
+
+
+typedef union ocb_ocr_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t core_reset : 1;
+ uint64_t chip_reset : 1;
+ uint64_t system_reset : 1;
+ uint64_t oci_arb_reset : 1;
+ uint64_t trace_disable : 1;
+ uint64_t trace_event : 1;
+ uint64_t dbg_unconditional_event : 1;
+ uint64_t ext_interrupt : 1;
+ uint64_t critical_interrupt : 1;
+ uint64_t spare : 7;
+ uint64_t _reserved0 : 48;
+#else
+ uint64_t _reserved0 : 48;
+ uint64_t spare : 7;
+ uint64_t critical_interrupt : 1;
+ uint64_t ext_interrupt : 1;
+ uint64_t dbg_unconditional_event : 1;
+ uint64_t trace_event : 1;
+ uint64_t trace_disable : 1;
+ uint64_t oci_arb_reset : 1;
+ uint64_t system_reset : 1;
+ uint64_t chip_reset : 1;
+ uint64_t core_reset : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocr_and_t;
+
+
+
+typedef union ocb_ocr_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t core_reset : 1;
+ uint64_t chip_reset : 1;
+ uint64_t system_reset : 1;
+ uint64_t oci_arb_reset : 1;
+ uint64_t trace_disable : 1;
+ uint64_t trace_event : 1;
+ uint64_t dbg_unconditional_event : 1;
+ uint64_t ext_interrupt : 1;
+ uint64_t critical_interrupt : 1;
+ uint64_t spare : 7;
+ uint64_t _reserved0 : 48;
+#else
+ uint64_t _reserved0 : 48;
+ uint64_t spare : 7;
+ uint64_t critical_interrupt : 1;
+ uint64_t ext_interrupt : 1;
+ uint64_t dbg_unconditional_event : 1;
+ uint64_t trace_event : 1;
+ uint64_t trace_disable : 1;
+ uint64_t oci_arb_reset : 1;
+ uint64_t system_reset : 1;
+ uint64_t chip_reset : 1;
+ uint64_t core_reset : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocr_or_t;
+
+
+
+typedef union ocb_ocdbg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 12;
+ uint64_t _reserved0 : 52;
+#else
+ uint64_t _reserved0 : 52;
+ uint64_t value : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocdbg_t;
+
+
+
+typedef union ocb_ocbarn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_region : 2;
+ uint64_t ocb_address : 27;
+ uint64_t reserved : 3;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t reserved : 3;
+ uint64_t ocb_address : 27;
+ uint64_t oci_region : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbarn_t;
+
+#endif // __ASSEMBLER__
+#define OCB_OCBARN_OCI_REGION_MASK SIXTYFOUR_BIT_CONSTANT(0xc000000000000000)
+#define OCB_OCBARN_OCB_ADDRESS_MASK SIXTYFOUR_BIT_CONSTANT(0x3ffffff800000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union ocb_ocbcsrn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pull_read_underflow : 1;
+ uint64_t push_write_overflow : 1;
+ uint64_t pull_read_underflow_en : 1;
+ uint64_t push_write_overflow_en : 1;
+ uint64_t ocb_stream_mode : 1;
+ uint64_t ocb_stream_type : 1;
+ uint64_t reserved1 : 2;
+ uint64_t ocb_oci_timeout : 1;
+ uint64_t ocb_oci_read_data_parity : 1;
+ uint64_t ocb_oci_slave_error : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_pib_data_parity_err : 1;
+ uint64_t reserved2 : 1;
+ uint64_t ocb_fsm_err : 1;
+ uint64_t _reserved0 : 49;
+#else
+ uint64_t _reserved0 : 49;
+ uint64_t ocb_fsm_err : 1;
+ uint64_t reserved2 : 1;
+ uint64_t ocb_pib_data_parity_err : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_oci_slave_error : 1;
+ uint64_t ocb_oci_read_data_parity : 1;
+ uint64_t ocb_oci_timeout : 1;
+ uint64_t reserved1 : 2;
+ uint64_t ocb_stream_type : 1;
+ uint64_t ocb_stream_mode : 1;
+ uint64_t push_write_overflow_en : 1;
+ uint64_t pull_read_underflow_en : 1;
+ uint64_t push_write_overflow : 1;
+ uint64_t pull_read_underflow : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbcsrn_t;
+
+#endif // __ASSEMBLER__
+#define OCB_OCBCSRN_PULL_READ_UNDERFLOW SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define OCB_OCBCSRN_PUSH_WRITE_OVERFLOW SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define OCB_OCBCSRN_PULL_READ_UNDERFLOW_EN SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define OCB_OCBCSRN_PUSH_WRITE_OVERFLOW_EN SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define OCB_OCBCSRN_OCB_STREAM_MODE SIXTYFOUR_BIT_CONSTANT(0x0800000000000000)
+#define OCB_OCBCSRN_OCB_STREAM_TYPE SIXTYFOUR_BIT_CONSTANT(0x0400000000000000)
+#define OCB_OCBCSRN_OCB_OCI_TIMEOUT SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define OCB_OCBCSRN_OCB_OCI_READ_DATA_PARITY SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define OCB_OCBCSRN_OCB_OCI_SLAVE_ERROR SIXTYFOUR_BIT_CONSTANT(0x0020000000000000)
+#define OCB_OCBCSRN_OCB_PIB_ADDR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0010000000000000)
+#define OCB_OCBCSRN_OCB_PIB_DATA_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0008000000000000)
+#define OCB_OCBCSRN_OCB_FSM_ERR SIXTYFOUR_BIT_CONSTANT(0x0002000000000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union ocb_ocbcsrn_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pull_read_underflow : 1;
+ uint64_t push_write_overflow : 1;
+ uint64_t pull_read_underflow_en : 1;
+ uint64_t push_write_overflow_en : 1;
+ uint64_t ocb_stream_mode : 1;
+ uint64_t ocb_stream_type : 1;
+ uint64_t reserved1 : 2;
+ uint64_t ocb_oci_timeout : 1;
+ uint64_t ocb_oci_read_data_parity : 1;
+ uint64_t ocb_oci_slave_error : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_pib_data_parity_err : 1;
+ uint64_t reserved2 : 1;
+ uint64_t ocb_fsm_err : 1;
+ uint64_t _reserved0 : 49;
+#else
+ uint64_t _reserved0 : 49;
+ uint64_t ocb_fsm_err : 1;
+ uint64_t reserved2 : 1;
+ uint64_t ocb_pib_data_parity_err : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_oci_slave_error : 1;
+ uint64_t ocb_oci_read_data_parity : 1;
+ uint64_t ocb_oci_timeout : 1;
+ uint64_t reserved1 : 2;
+ uint64_t ocb_stream_type : 1;
+ uint64_t ocb_stream_mode : 1;
+ uint64_t push_write_overflow_en : 1;
+ uint64_t pull_read_underflow_en : 1;
+ uint64_t push_write_overflow : 1;
+ uint64_t pull_read_underflow : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbcsrn_and_t;
+
+
+
+typedef union ocb_ocbcsrn_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pull_read_underflow : 1;
+ uint64_t push_write_overflow : 1;
+ uint64_t pull_read_underflow_en : 1;
+ uint64_t push_write_overflow_en : 1;
+ uint64_t ocb_stream_mode : 1;
+ uint64_t ocb_stream_type : 1;
+ uint64_t reserved1 : 2;
+ uint64_t ocb_oci_timeout : 1;
+ uint64_t ocb_oci_read_data_parity : 1;
+ uint64_t ocb_oci_slave_error : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_pib_data_parity_err : 1;
+ uint64_t reserved2 : 1;
+ uint64_t ocb_fsm_err : 1;
+ uint64_t _reserved0 : 49;
+#else
+ uint64_t _reserved0 : 49;
+ uint64_t ocb_fsm_err : 1;
+ uint64_t reserved2 : 1;
+ uint64_t ocb_pib_data_parity_err : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_oci_slave_error : 1;
+ uint64_t ocb_oci_read_data_parity : 1;
+ uint64_t ocb_oci_timeout : 1;
+ uint64_t reserved1 : 2;
+ uint64_t ocb_stream_type : 1;
+ uint64_t ocb_stream_mode : 1;
+ uint64_t push_write_overflow_en : 1;
+ uint64_t pull_read_underflow_en : 1;
+ uint64_t push_write_overflow : 1;
+ uint64_t pull_read_underflow : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbcsrn_or_t;
+
+
+
+typedef union ocb_ocbesrn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ocb_error_addr : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t ocb_error_addr : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbesrn_t;
+
+
+
+typedef union ocb_ocbdrn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ocb_data : 64;
+#else
+ uint64_t ocb_data : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_ocbdrn_t;
+
+
+
+typedef union ocb_osbcr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_block_unsecure_masters : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t occ_block_unsecure_masters : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_osbcr_t;
+
+
+
+typedef union ocb_otdcr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t trace_bus_en : 1;
+ uint64_t ocb_trace_mux_sel : 1;
+ uint64_t occ_trace_mux_sel : 2;
+ uint64_t oci_trace_mux_sel : 4;
+ uint64_t _reserved0 : 56;
+#else
+ uint64_t _reserved0 : 56;
+ uint64_t oci_trace_mux_sel : 4;
+ uint64_t occ_trace_mux_sel : 2;
+ uint64_t ocb_trace_mux_sel : 1;
+ uint64_t trace_bus_en : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_otdcr_t;
+
+
+
+typedef union ocb_oppcinj {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_err_inj_dcu : 1;
+ uint64_t oci_err_inj_icu : 1;
+ uint64_t oci_err_inj_ce_ue : 1;
+ uint64_t oci_err_inj_singl_cont : 1;
+ uint64_t _reserved0 : 60;
+#else
+ uint64_t _reserved0 : 60;
+ uint64_t oci_err_inj_singl_cont : 1;
+ uint64_t oci_err_inj_ce_ue : 1;
+ uint64_t oci_err_inj_icu : 1;
+ uint64_t oci_err_inj_dcu : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_oppcinj_t;
+
+
+
+typedef union ocb_occlfir {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_fw0 : 1;
+ uint64_t occ_fw1 : 1;
+ uint64_t occ_fw2 : 1;
+ uint64_t occ_fw3 : 1;
+ uint64_t pmc_pore_sw_malf : 1;
+ uint64_t pmc_occ_hb_malf : 1;
+ uint64_t pore_gpe0_fatal_err : 1;
+ uint64_t pore_gpe1_fatal_err : 1;
+ uint64_t ocb_error : 1;
+ uint64_t pmc_error : 1;
+ uint64_t srt_ue : 1;
+ uint64_t srt_ce : 1;
+ uint64_t srt_read_error : 1;
+ uint64_t srt_write_error : 1;
+ uint64_t srt_oci_write_data_parity : 1;
+ uint64_t srt_oci_be_parity_err : 1;
+ uint64_t srt_oci_addr_parity_err : 1;
+ uint64_t pore_sw_error_err : 1;
+ uint64_t pore_gpe0_error_err : 1;
+ uint64_t pore_gpe1_error_err : 1;
+ uint64_t external_trap : 1;
+ uint64_t ppc405_core_reset : 1;
+ uint64_t ppc405_chip_reset : 1;
+ uint64_t ppc405_system_reset : 1;
+ uint64_t ppc405_dbgmsrwe : 1;
+ uint64_t ppc405_dbgstopack : 1;
+ uint64_t ocb_db_oci_timeout : 1;
+ uint64_t ocb_db_oci_read_data_parity : 1;
+ uint64_t ocb_db_oci_slave_error : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_db_pib_data_parity_err : 1;
+ uint64_t ocb_idc0_error : 1;
+ uint64_t ocb_idc1_error : 1;
+ uint64_t ocb_idc2_error : 1;
+ uint64_t ocb_idc3_error : 1;
+ uint64_t srt_fsm_err : 1;
+ uint64_t jtagacc_err : 1;
+ uint64_t ocb_dw_err : 1;
+ uint64_t c405_ecc_ue : 1;
+ uint64_t c405_ecc_ce : 1;
+ uint64_t c405_oci_machinecheck : 1;
+ uint64_t sram_spare_direct_error0 : 1;
+ uint64_t sram_spare_direct_error1 : 1;
+ uint64_t sram_spare_direct_error2 : 1;
+ uint64_t sram_spare_direct_error3 : 1;
+ uint64_t slw_ocislv_err : 1;
+ uint64_t gpe_ocislv_err : 1;
+ uint64_t ocb_ocislv_err : 1;
+ uint64_t c405icu_m_timeout : 1;
+ uint64_t c405dcu_m_timeout : 1;
+ uint64_t spare_fir : 12;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t fir_parity_err : 1;
+#else
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t spare_fir : 12;
+ uint64_t c405dcu_m_timeout : 1;
+ uint64_t c405icu_m_timeout : 1;
+ uint64_t ocb_ocislv_err : 1;
+ uint64_t gpe_ocislv_err : 1;
+ uint64_t slw_ocislv_err : 1;
+ uint64_t sram_spare_direct_error3 : 1;
+ uint64_t sram_spare_direct_error2 : 1;
+ uint64_t sram_spare_direct_error1 : 1;
+ uint64_t sram_spare_direct_error0 : 1;
+ uint64_t c405_oci_machinecheck : 1;
+ uint64_t c405_ecc_ce : 1;
+ uint64_t c405_ecc_ue : 1;
+ uint64_t ocb_dw_err : 1;
+ uint64_t jtagacc_err : 1;
+ uint64_t srt_fsm_err : 1;
+ uint64_t ocb_idc3_error : 1;
+ uint64_t ocb_idc2_error : 1;
+ uint64_t ocb_idc1_error : 1;
+ uint64_t ocb_idc0_error : 1;
+ uint64_t ocb_db_pib_data_parity_err : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_db_oci_slave_error : 1;
+ uint64_t ocb_db_oci_read_data_parity : 1;
+ uint64_t ocb_db_oci_timeout : 1;
+ uint64_t ppc405_dbgstopack : 1;
+ uint64_t ppc405_dbgmsrwe : 1;
+ uint64_t ppc405_system_reset : 1;
+ uint64_t ppc405_chip_reset : 1;
+ uint64_t ppc405_core_reset : 1;
+ uint64_t external_trap : 1;
+ uint64_t pore_gpe1_error_err : 1;
+ uint64_t pore_gpe0_error_err : 1;
+ uint64_t pore_sw_error_err : 1;
+ uint64_t srt_oci_addr_parity_err : 1;
+ uint64_t srt_oci_be_parity_err : 1;
+ uint64_t srt_oci_write_data_parity : 1;
+ uint64_t srt_write_error : 1;
+ uint64_t srt_read_error : 1;
+ uint64_t srt_ce : 1;
+ uint64_t srt_ue : 1;
+ uint64_t pmc_error : 1;
+ uint64_t ocb_error : 1;
+ uint64_t pore_gpe1_fatal_err : 1;
+ uint64_t pore_gpe0_fatal_err : 1;
+ uint64_t pmc_occ_hb_malf : 1;
+ uint64_t pmc_pore_sw_malf : 1;
+ uint64_t occ_fw3 : 1;
+ uint64_t occ_fw2 : 1;
+ uint64_t occ_fw1 : 1;
+ uint64_t occ_fw0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occlfir_t;
+
+#endif // __ASSEMBLER__
+#define OCB_OCCLFIR_OCC_FW0 SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define OCB_OCCLFIR_OCC_FW1 SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define OCB_OCCLFIR_OCC_FW2 SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define OCB_OCCLFIR_OCC_FW3 SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define OCB_OCCLFIR_PMC_PORE_SW_MALF SIXTYFOUR_BIT_CONSTANT(0x0800000000000000)
+#define OCB_OCCLFIR_PMC_OCC_HB_MALF SIXTYFOUR_BIT_CONSTANT(0x0400000000000000)
+#define OCB_OCCLFIR_PORE_GPE0_FATAL_ERR SIXTYFOUR_BIT_CONSTANT(0x0200000000000000)
+#define OCB_OCCLFIR_PORE_GPE1_FATAL_ERR SIXTYFOUR_BIT_CONSTANT(0x0100000000000000)
+#define OCB_OCCLFIR_OCB_ERROR SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define OCB_OCCLFIR_PMC_ERROR SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define OCB_OCCLFIR_SRT_UE SIXTYFOUR_BIT_CONSTANT(0x0020000000000000)
+#define OCB_OCCLFIR_SRT_CE SIXTYFOUR_BIT_CONSTANT(0x0010000000000000)
+#define OCB_OCCLFIR_SRT_READ_ERROR SIXTYFOUR_BIT_CONSTANT(0x0008000000000000)
+#define OCB_OCCLFIR_SRT_WRITE_ERROR SIXTYFOUR_BIT_CONSTANT(0x0004000000000000)
+#define OCB_OCCLFIR_SRT_OCI_WRITE_DATA_PARITY SIXTYFOUR_BIT_CONSTANT(0x0002000000000000)
+#define OCB_OCCLFIR_SRT_OCI_BE_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0001000000000000)
+#define OCB_OCCLFIR_SRT_OCI_ADDR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000800000000000)
+#define OCB_OCCLFIR_PORE_SW_ERROR_ERR SIXTYFOUR_BIT_CONSTANT(0x0000400000000000)
+#define OCB_OCCLFIR_PORE_GPE0_ERROR_ERR SIXTYFOUR_BIT_CONSTANT(0x0000200000000000)
+#define OCB_OCCLFIR_PORE_GPE1_ERROR_ERR SIXTYFOUR_BIT_CONSTANT(0x0000100000000000)
+#define OCB_OCCLFIR_EXTERNAL_TRAP SIXTYFOUR_BIT_CONSTANT(0x0000080000000000)
+#define OCB_OCCLFIR_PPC405_CORE_RESET SIXTYFOUR_BIT_CONSTANT(0x0000040000000000)
+#define OCB_OCCLFIR_PPC405_CHIP_RESET SIXTYFOUR_BIT_CONSTANT(0x0000020000000000)
+#define OCB_OCCLFIR_PPC405_SYSTEM_RESET SIXTYFOUR_BIT_CONSTANT(0x0000010000000000)
+#define OCB_OCCLFIR_PPC405_DBGMSRWE SIXTYFOUR_BIT_CONSTANT(0x0000008000000000)
+#define OCB_OCCLFIR_PPC405_DBGSTOPACK SIXTYFOUR_BIT_CONSTANT(0x0000004000000000)
+#define OCB_OCCLFIR_OCB_DB_OCI_TIMEOUT SIXTYFOUR_BIT_CONSTANT(0x0000002000000000)
+#define OCB_OCCLFIR_OCB_DB_OCI_READ_DATA_PARITY SIXTYFOUR_BIT_CONSTANT(0x0000001000000000)
+#define OCB_OCCLFIR_OCB_DB_OCI_SLAVE_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000800000000)
+#define OCB_OCCLFIR_OCB_PIB_ADDR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000400000000)
+#define OCB_OCCLFIR_OCB_DB_PIB_DATA_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000200000000)
+#define OCB_OCCLFIR_OCB_IDC0_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000100000000)
+#define OCB_OCCLFIR_OCB_IDC1_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000080000000)
+#define OCB_OCCLFIR_OCB_IDC2_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000040000000)
+#define OCB_OCCLFIR_OCB_IDC3_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000020000000)
+#define OCB_OCCLFIR_SRT_FSM_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000010000000)
+#define OCB_OCCLFIR_JTAGACC_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000008000000)
+#define OCB_OCCLFIR_OCB_DW_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000004000000)
+#define OCB_OCCLFIR_C405_ECC_UE SIXTYFOUR_BIT_CONSTANT(0x0000000002000000)
+#define OCB_OCCLFIR_C405_ECC_CE SIXTYFOUR_BIT_CONSTANT(0x0000000001000000)
+#define OCB_OCCLFIR_C405_OCI_MACHINECHECK SIXTYFOUR_BIT_CONSTANT(0x0000000000800000)
+#define OCB_OCCLFIR_SRAM_SPARE_DIRECT_ERROR0 SIXTYFOUR_BIT_CONSTANT(0x0000000000400000)
+#define OCB_OCCLFIR_SRAM_SPARE_DIRECT_ERROR1 SIXTYFOUR_BIT_CONSTANT(0x0000000000200000)
+#define OCB_OCCLFIR_SRAM_SPARE_DIRECT_ERROR2 SIXTYFOUR_BIT_CONSTANT(0x0000000000100000)
+#define OCB_OCCLFIR_SRAM_SPARE_DIRECT_ERROR3 SIXTYFOUR_BIT_CONSTANT(0x0000000000080000)
+#define OCB_OCCLFIR_SLW_OCISLV_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000040000)
+#define OCB_OCCLFIR_GPE_OCISLV_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000020000)
+#define OCB_OCCLFIR_OCB_OCISLV_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000010000)
+#define OCB_OCCLFIR_C405ICU_M_TIMEOUT SIXTYFOUR_BIT_CONSTANT(0x0000000000008000)
+#define OCB_OCCLFIR_C405DCU_M_TIMEOUT SIXTYFOUR_BIT_CONSTANT(0x0000000000004000)
+#define OCB_OCCLFIR_SPARE_FIR_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000000003ffc)
+#define OCB_OCCLFIR_FIR_PARITY_ERR_DUP SIXTYFOUR_BIT_CONSTANT(0x0000000000000002)
+#define OCB_OCCLFIR_FIR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000000001)
+#ifndef __ASSEMBLER__
+
+
+typedef union ocb_occlfir_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_fw0 : 1;
+ uint64_t occ_fw1 : 1;
+ uint64_t occ_fw2 : 1;
+ uint64_t occ_fw3 : 1;
+ uint64_t pmc_pore_sw_malf : 1;
+ uint64_t pmc_occ_hb_malf : 1;
+ uint64_t pore_gpe0_fatal_err : 1;
+ uint64_t pore_gpe1_fatal_err : 1;
+ uint64_t ocb_error : 1;
+ uint64_t pmc_error : 1;
+ uint64_t srt_ue : 1;
+ uint64_t srt_ce : 1;
+ uint64_t srt_read_error : 1;
+ uint64_t srt_write_error : 1;
+ uint64_t srt_oci_write_data_parity : 1;
+ uint64_t srt_oci_be_parity_err : 1;
+ uint64_t srt_oci_addr_parity_err : 1;
+ uint64_t pore_sw_error_err : 1;
+ uint64_t pore_gpe0_error_err : 1;
+ uint64_t pore_gpe1_error_err : 1;
+ uint64_t external_trap : 1;
+ uint64_t ppc405_core_reset : 1;
+ uint64_t ppc405_chip_reset : 1;
+ uint64_t ppc405_system_reset : 1;
+ uint64_t ppc405_dbgmsrwe : 1;
+ uint64_t ppc405_dbgstopack : 1;
+ uint64_t ocb_db_oci_timeout : 1;
+ uint64_t ocb_db_oci_read_data_parity : 1;
+ uint64_t ocb_db_oci_slave_error : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_db_pib_data_parity_err : 1;
+ uint64_t ocb_idc0_error : 1;
+ uint64_t ocb_idc1_error : 1;
+ uint64_t ocb_idc2_error : 1;
+ uint64_t ocb_idc3_error : 1;
+ uint64_t srt_fsm_err : 1;
+ uint64_t jtagacc_err : 1;
+ uint64_t ocb_dw_err : 1;
+ uint64_t c405_ecc_ue : 1;
+ uint64_t c405_ecc_ce : 1;
+ uint64_t c405_oci_machinecheck : 1;
+ uint64_t sram_spare_direct_error0 : 1;
+ uint64_t sram_spare_direct_error1 : 1;
+ uint64_t sram_spare_direct_error2 : 1;
+ uint64_t sram_spare_direct_error3 : 1;
+ uint64_t slw_ocislv_err : 1;
+ uint64_t gpe_ocislv_err : 1;
+ uint64_t ocb_ocislv_err : 1;
+ uint64_t c405icu_m_timeout : 1;
+ uint64_t c405dcu_m_timeout : 1;
+ uint64_t spare_fir : 12;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t fir_parity_err : 1;
+#else
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t spare_fir : 12;
+ uint64_t c405dcu_m_timeout : 1;
+ uint64_t c405icu_m_timeout : 1;
+ uint64_t ocb_ocislv_err : 1;
+ uint64_t gpe_ocislv_err : 1;
+ uint64_t slw_ocislv_err : 1;
+ uint64_t sram_spare_direct_error3 : 1;
+ uint64_t sram_spare_direct_error2 : 1;
+ uint64_t sram_spare_direct_error1 : 1;
+ uint64_t sram_spare_direct_error0 : 1;
+ uint64_t c405_oci_machinecheck : 1;
+ uint64_t c405_ecc_ce : 1;
+ uint64_t c405_ecc_ue : 1;
+ uint64_t ocb_dw_err : 1;
+ uint64_t jtagacc_err : 1;
+ uint64_t srt_fsm_err : 1;
+ uint64_t ocb_idc3_error : 1;
+ uint64_t ocb_idc2_error : 1;
+ uint64_t ocb_idc1_error : 1;
+ uint64_t ocb_idc0_error : 1;
+ uint64_t ocb_db_pib_data_parity_err : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_db_oci_slave_error : 1;
+ uint64_t ocb_db_oci_read_data_parity : 1;
+ uint64_t ocb_db_oci_timeout : 1;
+ uint64_t ppc405_dbgstopack : 1;
+ uint64_t ppc405_dbgmsrwe : 1;
+ uint64_t ppc405_system_reset : 1;
+ uint64_t ppc405_chip_reset : 1;
+ uint64_t ppc405_core_reset : 1;
+ uint64_t external_trap : 1;
+ uint64_t pore_gpe1_error_err : 1;
+ uint64_t pore_gpe0_error_err : 1;
+ uint64_t pore_sw_error_err : 1;
+ uint64_t srt_oci_addr_parity_err : 1;
+ uint64_t srt_oci_be_parity_err : 1;
+ uint64_t srt_oci_write_data_parity : 1;
+ uint64_t srt_write_error : 1;
+ uint64_t srt_read_error : 1;
+ uint64_t srt_ce : 1;
+ uint64_t srt_ue : 1;
+ uint64_t pmc_error : 1;
+ uint64_t ocb_error : 1;
+ uint64_t pore_gpe1_fatal_err : 1;
+ uint64_t pore_gpe0_fatal_err : 1;
+ uint64_t pmc_occ_hb_malf : 1;
+ uint64_t pmc_pore_sw_malf : 1;
+ uint64_t occ_fw3 : 1;
+ uint64_t occ_fw2 : 1;
+ uint64_t occ_fw1 : 1;
+ uint64_t occ_fw0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occlfir_and_t;
+
+
+
+typedef union ocb_occlfir_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_fw0 : 1;
+ uint64_t occ_fw1 : 1;
+ uint64_t occ_fw2 : 1;
+ uint64_t occ_fw3 : 1;
+ uint64_t pmc_pore_sw_malf : 1;
+ uint64_t pmc_occ_hb_malf : 1;
+ uint64_t pore_gpe0_fatal_err : 1;
+ uint64_t pore_gpe1_fatal_err : 1;
+ uint64_t ocb_error : 1;
+ uint64_t pmc_error : 1;
+ uint64_t srt_ue : 1;
+ uint64_t srt_ce : 1;
+ uint64_t srt_read_error : 1;
+ uint64_t srt_write_error : 1;
+ uint64_t srt_oci_write_data_parity : 1;
+ uint64_t srt_oci_be_parity_err : 1;
+ uint64_t srt_oci_addr_parity_err : 1;
+ uint64_t pore_sw_error_err : 1;
+ uint64_t pore_gpe0_error_err : 1;
+ uint64_t pore_gpe1_error_err : 1;
+ uint64_t external_trap : 1;
+ uint64_t ppc405_core_reset : 1;
+ uint64_t ppc405_chip_reset : 1;
+ uint64_t ppc405_system_reset : 1;
+ uint64_t ppc405_dbgmsrwe : 1;
+ uint64_t ppc405_dbgstopack : 1;
+ uint64_t ocb_db_oci_timeout : 1;
+ uint64_t ocb_db_oci_read_data_parity : 1;
+ uint64_t ocb_db_oci_slave_error : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_db_pib_data_parity_err : 1;
+ uint64_t ocb_idc0_error : 1;
+ uint64_t ocb_idc1_error : 1;
+ uint64_t ocb_idc2_error : 1;
+ uint64_t ocb_idc3_error : 1;
+ uint64_t srt_fsm_err : 1;
+ uint64_t jtagacc_err : 1;
+ uint64_t ocb_dw_err : 1;
+ uint64_t c405_ecc_ue : 1;
+ uint64_t c405_ecc_ce : 1;
+ uint64_t c405_oci_machinecheck : 1;
+ uint64_t sram_spare_direct_error0 : 1;
+ uint64_t sram_spare_direct_error1 : 1;
+ uint64_t sram_spare_direct_error2 : 1;
+ uint64_t sram_spare_direct_error3 : 1;
+ uint64_t slw_ocislv_err : 1;
+ uint64_t gpe_ocislv_err : 1;
+ uint64_t ocb_ocislv_err : 1;
+ uint64_t c405icu_m_timeout : 1;
+ uint64_t c405dcu_m_timeout : 1;
+ uint64_t spare_fir : 12;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t fir_parity_err : 1;
+#else
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t spare_fir : 12;
+ uint64_t c405dcu_m_timeout : 1;
+ uint64_t c405icu_m_timeout : 1;
+ uint64_t ocb_ocislv_err : 1;
+ uint64_t gpe_ocislv_err : 1;
+ uint64_t slw_ocislv_err : 1;
+ uint64_t sram_spare_direct_error3 : 1;
+ uint64_t sram_spare_direct_error2 : 1;
+ uint64_t sram_spare_direct_error1 : 1;
+ uint64_t sram_spare_direct_error0 : 1;
+ uint64_t c405_oci_machinecheck : 1;
+ uint64_t c405_ecc_ce : 1;
+ uint64_t c405_ecc_ue : 1;
+ uint64_t ocb_dw_err : 1;
+ uint64_t jtagacc_err : 1;
+ uint64_t srt_fsm_err : 1;
+ uint64_t ocb_idc3_error : 1;
+ uint64_t ocb_idc2_error : 1;
+ uint64_t ocb_idc1_error : 1;
+ uint64_t ocb_idc0_error : 1;
+ uint64_t ocb_db_pib_data_parity_err : 1;
+ uint64_t ocb_pib_addr_parity_err : 1;
+ uint64_t ocb_db_oci_slave_error : 1;
+ uint64_t ocb_db_oci_read_data_parity : 1;
+ uint64_t ocb_db_oci_timeout : 1;
+ uint64_t ppc405_dbgstopack : 1;
+ uint64_t ppc405_dbgmsrwe : 1;
+ uint64_t ppc405_system_reset : 1;
+ uint64_t ppc405_chip_reset : 1;
+ uint64_t ppc405_core_reset : 1;
+ uint64_t external_trap : 1;
+ uint64_t pore_gpe1_error_err : 1;
+ uint64_t pore_gpe0_error_err : 1;
+ uint64_t pore_sw_error_err : 1;
+ uint64_t srt_oci_addr_parity_err : 1;
+ uint64_t srt_oci_be_parity_err : 1;
+ uint64_t srt_oci_write_data_parity : 1;
+ uint64_t srt_write_error : 1;
+ uint64_t srt_read_error : 1;
+ uint64_t srt_ce : 1;
+ uint64_t srt_ue : 1;
+ uint64_t pmc_error : 1;
+ uint64_t ocb_error : 1;
+ uint64_t pore_gpe1_fatal_err : 1;
+ uint64_t pore_gpe0_fatal_err : 1;
+ uint64_t pmc_occ_hb_malf : 1;
+ uint64_t pmc_pore_sw_malf : 1;
+ uint64_t occ_fw3 : 1;
+ uint64_t occ_fw2 : 1;
+ uint64_t occ_fw1 : 1;
+ uint64_t occ_fw0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occlfir_or_t;
+
+
+
+typedef union ocb_occlfirmask {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occlfirmask_t;
+
+
+
+typedef union ocb_occlfirmask_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occlfirmask_and_t;
+
+
+
+typedef union ocb_occlfirmask_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occlfirmask_or_t;
+
+
+
+typedef union ocb_occlfiract0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occlfiract0_t;
+
+
+
+typedef union ocb_occlfiract1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occlfiract1_t;
+
+
+
+typedef union ocb_occerrrpt {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t sram_cerrrpt : 10;
+ uint64_t jtagacc_cerrrpt : 6;
+ uint64_t c405_dcu_ecc_ue_cerrrpt : 1;
+ uint64_t c405_dcu_ecc_ce_cerrrpt : 1;
+ uint64_t c405_icu_ecc_ue_cerrrpt : 1;
+ uint64_t c405_icu_ecc_ce_cerrrpt : 1;
+ uint64_t slw_ocislv_err : 7;
+ uint64_t gpe_ocislv_err : 7;
+ uint64_t ocb_ocislv_err : 6;
+ uint64_t _reserved0 : 24;
+#else
+ uint64_t _reserved0 : 24;
+ uint64_t ocb_ocislv_err : 6;
+ uint64_t gpe_ocislv_err : 7;
+ uint64_t slw_ocislv_err : 7;
+ uint64_t c405_icu_ecc_ce_cerrrpt : 1;
+ uint64_t c405_icu_ecc_ue_cerrrpt : 1;
+ uint64_t c405_dcu_ecc_ce_cerrrpt : 1;
+ uint64_t c405_dcu_ecc_ue_cerrrpt : 1;
+ uint64_t jtagacc_cerrrpt : 6;
+ uint64_t sram_cerrrpt : 10;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_occerrrpt_t;
+
+
+
+typedef union ocb_scan_dummy_1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 48;
+ uint64_t value : 16;
+#else
+ uint64_t value : 16;
+ uint64_t _reserved0 : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_scan_dummy_1_t;
+
+
+
+typedef union ocb_scan_dummy_2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 63;
+ uint64_t value : 1;
+#else
+ uint64_t value : 1;
+ uint64_t _reserved0 : 63;
+#endif // _BIG_ENDIAN
+ } fields;
+} ocb_scan_dummy_2_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __OCB_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/ocb_register_addresses.h b/src/ssx/pgp/registers/ocb_register_addresses.h
new file mode 100755
index 0000000..3290e59
--- /dev/null
+++ b/src/ssx/pgp/registers/ocb_register_addresses.h
@@ -0,0 +1,148 @@
+#ifndef __OCB_REGISTER_ADDRESSES_H__
+#define __OCB_REGISTER_ADDRESSES_H__
+
+// $Id: ocb_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/ocb_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ocb_register_addresses.h
+/// \brief Symbolic addresses for the OCB unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define OCB_OCI_BASE 0x40050000
+#define OCB_OITR0 0x40050040
+#define OCB_OIEPR0 0x40050048
+#define OCB_OCIR0 0x40050050
+#define OCB_ONISR0 0x40050058
+#define OCB_OUDER0 0x40050060
+#define OCB_OCISR0 0x40050068
+#define OCB_ODHER0 0x40050070
+#define OCB_OISR0 0x40050000
+#define OCB_OISR0_AND 0x40050008
+#define OCB_OISR0_OR 0x40050010
+#define OCB_OIMR0 0x40050020
+#define OCB_OIMR0_AND 0x40050028
+#define OCB_OIMR0_OR 0x40050030
+#define OCB_OITR1 0x400500c0
+#define OCB_OIEPR1 0x400500c8
+#define OCB_OCIR1 0x400500d0
+#define OCB_ONISR1 0x400500d8
+#define OCB_OUDER1 0x400500e0
+#define OCB_OCISR1 0x400500e8
+#define OCB_ODHER1 0x400500f0
+#define OCB_OISR1 0x40050080
+#define OCB_OISR1_AND 0x40050088
+#define OCB_OISR1_OR 0x40050090
+#define OCB_OIMR1 0x400500a0
+#define OCB_OIMR1_AND 0x400500a8
+#define OCB_OIMR1_OR 0x400500b0
+#define OCB_OCCMISC 0x40050100
+#define OCB_OCCMISC_AND 0x40050108
+#define OCB_OCCMISC_OR 0x40050110
+#define OCB_OTRN(n) (OCB_OTR0 + ((OCB_OTR1 - OCB_OTR0) * (n)))
+#define OCB_OTR0 0x40050800
+#define OCB_OTR1 0x40050808
+#define OCB_OHTMCR 0x40050118
+#define OCB_OEHDR 0x40050120
+#define OCB_OCBSLBRN(n) (OCB_OCBSLBR0 + ((OCB_OCBSLBR1 - OCB_OCBSLBR0) * (n)))
+#define OCB_OCBSLBR0 0x40051000
+#define OCB_OCBSLBR1 0x40051080
+#define OCB_OCBSLBR2 0x40051100
+#define OCB_OCBSHBRN(n) (OCB_OCBSHBR0 + ((OCB_OCBSHBR1 - OCB_OCBSHBR0) * (n)))
+#define OCB_OCBSHBR0 0x40051018
+#define OCB_OCBSHBR1 0x40051098
+#define OCB_OCBSHBR2 0x40051118
+#define OCB_OCBSLCSN(n) (OCB_OCBSLCS0 + ((OCB_OCBSLCS1 - OCB_OCBSLCS0) * (n)))
+#define OCB_OCBSLCS0 0x40051008
+#define OCB_OCBSLCS1 0x40051088
+#define OCB_OCBSLCS2 0x40051108
+#define OCB_OCBSHCSN(n) (OCB_OCBSHCS0 + ((OCB_OCBSHCS1 - OCB_OCBSHCS0) * (n)))
+#define OCB_OCBSHCS0 0x40051020
+#define OCB_OCBSHCS1 0x400510a0
+#define OCB_OCBSHCS2 0x40051120
+#define OCB_OCBSLIN(n) (OCB_OCBSLI0 + ((OCB_OCBSLI1 - OCB_OCBSLI0) * (n)))
+#define OCB_OCBSLI0 0x40051010
+#define OCB_OCBSLI1 0x40051090
+#define OCB_OCBSLI2 0x40051110
+#define OCB_OCBSHIN(n) (OCB_OCBSHI0 + ((OCB_OCBSHI1 - OCB_OCBSHI0) * (n)))
+#define OCB_OCBSHI0 0x40051028
+#define OCB_OCBSHI1 0x400510a8
+#define OCB_OCBSHI2 0x40051128
+#define OCB_OCBSESN(n) (OCB_OCBSES0 + ((OCB_OCBSES1 - OCB_OCBSES0) * (n)))
+#define OCB_OCBSES0 0x40051030
+#define OCB_OCBSES1 0x400510b0
+#define OCB_OCBSES2 0x40051130
+#define OCB_OCBICRN(n) (OCB_OCBICR0 + ((OCB_OCBICR1 - OCB_OCBICR0) * (n)))
+#define OCB_OCBICR0 0x40051038
+#define OCB_OCBICR1 0x400510b8
+#define OCB_OCBICR2 0x40051138
+#define OCB_OCBLWCRN(n) (OCB_OCBLWCR0 + ((OCB_OCBLWCR1 - OCB_OCBLWCR0) * (n)))
+#define OCB_OCBLWCR0 0x40051040
+#define OCB_OCBLWCR1 0x400510c0
+#define OCB_OCBLWCR2 0x40051140
+#define OCB_OCBLWSRN(n) (OCB_OCBLWSR0 + ((OCB_OCBLWSR1 - OCB_OCBLWSR0) * (n)))
+#define OCB_OCBLWSR0 0x40051050
+#define OCB_OCBLWSR1 0x400510d0
+#define OCB_OCBLWSR2 0x40051150
+#define OCB_OCBLWSBRN(n) (OCB_OCBLWSBR0 + ((OCB_OCBLWSBR1 - OCB_OCBLWSBR0) * (n)))
+#define OCB_OCBLWSBR0 0x40051060
+#define OCB_OCBLWSBR1 0x400510e0
+#define OCB_OCBLWSBR2 0x40051160
+#define OCB_OCICHSW 0x40050128
+#define OCB_PIB_BASE 0x0006a000
+#define OCB_OCR 0x0006b000
+#define OCB_OCR_AND 0x0006b001
+#define OCB_OCR_OR 0x0006b002
+#define OCB_OCDBG 0x0006b003
+#define OCB_OCBARN(n) (OCB_OCBAR0 + ((OCB_OCBAR1 - OCB_OCBAR0) * (n)))
+#define OCB_OCBAR0 0x0006b010
+#define OCB_OCBAR1 0x0006b030
+#define OCB_OCBAR2 0x0006b050
+#define OCB_OCBAR3 0x0006b070
+#define OCB_OCBCSRN(n) (OCB_OCBCSR0 + ((OCB_OCBCSR1 - OCB_OCBCSR0) * (n)))
+#define OCB_OCBCSR0 0x0006b011
+#define OCB_OCBCSR1 0x0006b031
+#define OCB_OCBCSR2 0x0006b051
+#define OCB_OCBCSR3 0x0006b071
+#define OCB_OCBCSRN_AND(n) (OCB_OCBCSR0_AND + ((OCB_OCBCSR1_AND - OCB_OCBCSR0_AND) * (n)))
+#define OCB_OCBCSR0_AND 0x0006b012
+#define OCB_OCBCSR1_AND 0x0006b032
+#define OCB_OCBCSR2_AND 0x0006b052
+#define OCB_OCBCSR3_AND 0x0006b072
+#define OCB_OCBCSRN_OR(n) (OCB_OCBCSR0_OR + ((OCB_OCBCSR1_OR - OCB_OCBCSR0_OR) * (n)))
+#define OCB_OCBCSR0_OR 0x0006b013
+#define OCB_OCBCSR1_OR 0x0006b033
+#define OCB_OCBCSR2_OR 0x0006b053
+#define OCB_OCBCSR3_OR 0x0006b073
+#define OCB_OCBESRN(n) (OCB_OCBESR0 + ((OCB_OCBESR1 - OCB_OCBESR0) * (n)))
+#define OCB_OCBESR0 0x0006b014
+#define OCB_OCBESR1 0x0006b034
+#define OCB_OCBESR2 0x0006b054
+#define OCB_OCBESR3 0x0006b074
+#define OCB_OCBDRN(n) (OCB_OCBDR0 + ((OCB_OCBDR1 - OCB_OCBDR0) * (n)))
+#define OCB_OCBDR0 0x0006b015
+#define OCB_OCBDR1 0x0006b035
+#define OCB_OCBDR2 0x0006b055
+#define OCB_OCBDR3 0x0006b075
+#define OCB_OSBCR 0x0006b100
+#define OCB_OTDCR 0x0006b110
+#define OCB_OPPCINJ 0x0006b111
+#define OCB_FIRPIB_BASE 0x01010800
+#define OCB_OCCLFIR 0x01010800
+#define OCB_OCCLFIR_AND 0x01010801
+#define OCB_OCCLFIR_OR 0x01010802
+#define OCB_OCCLFIRMASK 0x01010803
+#define OCB_OCCLFIRMASK_AND 0x01010804
+#define OCB_OCCLFIRMASK_OR 0x01010805
+#define OCB_OCCLFIRACT0 0x01010806
+#define OCB_OCCLFIRACT1 0x01010807
+#define OCB_OCCERRRPT 0x0101080a
+
+#endif // __OCB_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/oha_firmware_registers.h b/src/ssx/pgp/registers/oha_firmware_registers.h
new file mode 100755
index 0000000..cba1500
--- /dev/null
+++ b/src/ssx/pgp/registers/oha_firmware_registers.h
@@ -0,0 +1,1248 @@
+#ifndef __OHA_FIRMWARE_REGISTERS_H__
+#define __OHA_FIRMWARE_REGISTERS_H__
+
+// $Id: oha_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/oha_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file oha_firmware_registers.h
+/// \brief C register structs for the OHA unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union oha_activity_sample_mode_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t enable_activity_sampling : 1;
+ uint64_t enable_ppt_trace : 1;
+ uint64_t l2_act_count_is_free_running : 1;
+ uint64_t l3_act_count_is_free_running : 1;
+ uint64_t activity_sample_l2l3_enable : 1;
+ uint64_t core_activity_sample_enable : 1;
+ uint64_t disable_activity_proxy_reset : 1;
+ uint64_t power_proxy_activity_range_select_vcs : 5;
+ uint64_t power_proxy_activity_range_select_vdd : 5;
+ uint64_t memory_activity_range_select : 4;
+ uint64_t avg_freq_counter_scaler : 3;
+ uint64_t ppt_trace_timer_match_val : 11;
+ uint64_t disable_ppt_int_timer_reset : 1;
+ uint64_t ppt_int_timer_select : 2;
+ uint64_t disable_ppt_cycle_counter_reset : 1;
+ uint64_t ppt_cycle_counter_scaler : 3;
+ uint64_t ppt_squash_timer_match_val : 6;
+ uint64_t ppt_timer_timeout_enable : 1;
+ uint64_t ppt_lpar_change_enable : 1;
+ uint64_t ppt_global_actual_change_enable : 1;
+ uint64_t ppt_local_voltage_change_enable : 1;
+ uint64_t ppt_ivrm_bypass_change_enable : 1;
+ uint64_t ppt_idle_entry_enable : 1;
+ uint64_t ppt_idle_exit_enable : 1;
+ uint64_t ppt_timer_timeout_priority : 1;
+ uint64_t ppt_lpar_change_priority : 1;
+ uint64_t ppt_global_actual_change_priority : 1;
+ uint64_t ppt_local_voltage_change_priority : 1;
+ uint64_t ppt_ivrm_bypass_change_priority : 1;
+ uint64_t ppt_idle_entry_priority : 1;
+ uint64_t ppt_idle_exit_priority : 1;
+ uint64_t ppt_legacy_mode : 1;
+ uint64_t _reserved0 : 1;
+#else
+ uint64_t _reserved0 : 1;
+ uint64_t ppt_legacy_mode : 1;
+ uint64_t ppt_idle_exit_priority : 1;
+ uint64_t ppt_idle_entry_priority : 1;
+ uint64_t ppt_ivrm_bypass_change_priority : 1;
+ uint64_t ppt_local_voltage_change_priority : 1;
+ uint64_t ppt_global_actual_change_priority : 1;
+ uint64_t ppt_lpar_change_priority : 1;
+ uint64_t ppt_timer_timeout_priority : 1;
+ uint64_t ppt_idle_exit_enable : 1;
+ uint64_t ppt_idle_entry_enable : 1;
+ uint64_t ppt_ivrm_bypass_change_enable : 1;
+ uint64_t ppt_local_voltage_change_enable : 1;
+ uint64_t ppt_global_actual_change_enable : 1;
+ uint64_t ppt_lpar_change_enable : 1;
+ uint64_t ppt_timer_timeout_enable : 1;
+ uint64_t ppt_squash_timer_match_val : 6;
+ uint64_t ppt_cycle_counter_scaler : 3;
+ uint64_t disable_ppt_cycle_counter_reset : 1;
+ uint64_t ppt_int_timer_select : 2;
+ uint64_t disable_ppt_int_timer_reset : 1;
+ uint64_t ppt_trace_timer_match_val : 11;
+ uint64_t avg_freq_counter_scaler : 3;
+ uint64_t memory_activity_range_select : 4;
+ uint64_t power_proxy_activity_range_select_vdd : 5;
+ uint64_t power_proxy_activity_range_select_vcs : 5;
+ uint64_t disable_activity_proxy_reset : 1;
+ uint64_t core_activity_sample_enable : 1;
+ uint64_t activity_sample_l2l3_enable : 1;
+ uint64_t l3_act_count_is_free_running : 1;
+ uint64_t l2_act_count_is_free_running : 1;
+ uint64_t enable_ppt_trace : 1;
+ uint64_t enable_activity_sampling : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_activity_sample_mode_reg_t;
+
+
+
+typedef union oha_vcs_activity_cnt_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t l2_activity_count_24bit_vcs : 24;
+ uint64_t l3_activity_count_24bit_vcs : 24;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t l3_activity_count_24bit_vcs : 24;
+ uint64_t l2_activity_count_24bit_vcs : 24;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_vcs_activity_cnt_reg_t;
+
+
+
+typedef union oha_vdd_activity_cnt_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t l2_activity_count_24bit_vdd : 24;
+ uint64_t l3_activity_count_24bit_vdd : 24;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t l3_activity_count_24bit_vdd : 24;
+ uint64_t l2_activity_count_24bit_vdd : 24;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_vdd_activity_cnt_reg_t;
+
+
+
+typedef union oha_low_activity_detect_mode_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t low_activity_detect_sample_enable : 1;
+ uint64_t low_activity_detect_timer_select_for_entry : 8;
+ uint64_t low_activity_detect_timer_select_for_exit : 8;
+ uint64_t low_activity_detect_threshold_range : 4;
+ uint64_t low_activity_detect_threshold_entry : 16;
+ uint64_t low_activity_detect_threshold_exit : 16;
+ uint64_t _reserved0 : 11;
+#else
+ uint64_t _reserved0 : 11;
+ uint64_t low_activity_detect_threshold_exit : 16;
+ uint64_t low_activity_detect_threshold_entry : 16;
+ uint64_t low_activity_detect_threshold_range : 4;
+ uint64_t low_activity_detect_timer_select_for_exit : 8;
+ uint64_t low_activity_detect_timer_select_for_entry : 8;
+ uint64_t low_activity_detect_sample_enable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_low_activity_detect_mode_reg_t;
+
+
+
+typedef union oha_activity_and_frequ_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t low_activity_detect_engaged : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t low_activity_detect_engaged : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_activity_and_frequ_reg_t;
+
+
+
+typedef union oha_counter_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t base_counter : 16;
+ uint64_t idle_detec_timer : 16;
+ uint64_t tod_count_msbs : 16;
+ uint64_t ppt_cycle_count_ovfl : 1;
+ uint64_t ppt_parity_error : 1;
+ uint64_t _reserved0 : 14;
+#else
+ uint64_t _reserved0 : 14;
+ uint64_t ppt_parity_error : 1;
+ uint64_t ppt_cycle_count_ovfl : 1;
+ uint64_t tod_count_msbs : 16;
+ uint64_t idle_detec_timer : 16;
+ uint64_t base_counter : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_counter_reg_t;
+
+
+
+typedef union oha_proxy_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t average_frequency : 32;
+ uint64_t special_memory_activity_cnt : 24;
+ uint64_t _reserved0 : 8;
+#else
+ uint64_t _reserved0 : 8;
+ uint64_t special_memory_activity_cnt : 24;
+ uint64_t average_frequency : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_proxy_reg_t;
+
+
+
+typedef union oha_proxy_legacy_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t aproxy_vdd : 16;
+ uint64_t aproxy_vcs : 16;
+ uint64_t memory_activity_cnt : 16;
+ uint64_t scaled_average_frequency : 16;
+#else
+ uint64_t scaled_average_frequency : 16;
+ uint64_t memory_activity_cnt : 16;
+ uint64_t aproxy_vcs : 16;
+ uint64_t aproxy_vdd : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_proxy_legacy_reg_t;
+
+
+
+typedef union oha_skitter_ctrl_mode_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t start_skitter_mux_sel : 3;
+ uint64_t stop_skitter_mux_sel : 3;
+ uint64_t skitter_timer_start_mux_sel : 3;
+ uint64_t disable_skitter_qualification_mode : 1;
+ uint64_t skitter_timer_enable_freerun_mode : 1;
+ uint64_t skitter_timer_range_select : 4;
+ uint64_t _reserved0 : 49;
+#else
+ uint64_t _reserved0 : 49;
+ uint64_t skitter_timer_range_select : 4;
+ uint64_t skitter_timer_enable_freerun_mode : 1;
+ uint64_t disable_skitter_qualification_mode : 1;
+ uint64_t skitter_timer_start_mux_sel : 3;
+ uint64_t stop_skitter_mux_sel : 3;
+ uint64_t start_skitter_mux_sel : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_skitter_ctrl_mode_reg_t;
+
+
+
+typedef union oha_cpm_ctrl_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cpm_bit_sel : 2;
+ uint64_t cpm_bit_sel_trig_0 : 3;
+ uint64_t cpm_bit_sel_trig_1 : 3;
+ uint64_t scom_marker : 8;
+ uint64_t cpm_mark_select : 2;
+ uint64_t cpm_htm_mode : 1;
+ uint64_t cpm_scom_mask : 8;
+ uint64_t cpm_scom_mode : 2;
+ uint64_t cpm_data_mode : 1;
+ uint64_t _reserved0 : 34;
+#else
+ uint64_t _reserved0 : 34;
+ uint64_t cpm_data_mode : 1;
+ uint64_t cpm_scom_mode : 2;
+ uint64_t cpm_scom_mask : 8;
+ uint64_t cpm_htm_mode : 1;
+ uint64_t cpm_mark_select : 2;
+ uint64_t scom_marker : 8;
+ uint64_t cpm_bit_sel_trig_1 : 3;
+ uint64_t cpm_bit_sel_trig_0 : 3;
+ uint64_t cpm_bit_sel : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_cpm_ctrl_reg_t;
+
+
+
+typedef union oha_cpm_hist_reset_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t hist_reset : 1;
+ uint64_t pconly_special_wakeup : 1;
+ uint64_t _reserved0 : 62;
+#else
+ uint64_t _reserved0 : 62;
+ uint64_t pconly_special_wakeup : 1;
+ uint64_t hist_reset : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_cpm_hist_reset_reg_t;
+
+#endif // __ASSEMBLER__
+#define OHA_CPM_HIST_RESET_REG_HIST_RESET SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define OHA_CPM_HIST_RESET_REG_PCONLY_SPECIAL_WAKEUP SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union oha_ro_status_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t low_activity_detect_bit : 1;
+ uint64_t special_wakeup_completed : 1;
+ uint64_t architected_idle_state_from_core : 3;
+ uint64_t core_access_impossible : 1;
+ uint64_t eco_access_impossible : 1;
+ uint64_t spare_6bit : 6;
+ uint64_t current_aiss_fsm_state_vector : 7;
+ uint64_t eff_idle_state : 3;
+ uint64_t spare_1bit : 1;
+ uint64_t pc_tc_deep_idle_thread_state : 8;
+ uint64_t lpar_id : 12;
+ uint64_t ppt_fsm_l : 4;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t ppt_fsm_l : 4;
+ uint64_t lpar_id : 12;
+ uint64_t pc_tc_deep_idle_thread_state : 8;
+ uint64_t spare_1bit : 1;
+ uint64_t eff_idle_state : 3;
+ uint64_t current_aiss_fsm_state_vector : 7;
+ uint64_t spare_6bit : 6;
+ uint64_t eco_access_impossible : 1;
+ uint64_t core_access_impossible : 1;
+ uint64_t architected_idle_state_from_core : 3;
+ uint64_t special_wakeup_completed : 1;
+ uint64_t low_activity_detect_bit : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_ro_status_reg_t;
+
+#endif // __ASSEMBLER__
+#define OHA_RO_STATUS_REG_LOW_ACTIVITY_DETECT_BIT SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define OHA_RO_STATUS_REG_SPECIAL_WAKEUP_COMPLETED SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define OHA_RO_STATUS_REG_ARCHITECTED_IDLE_STATE_FROM_CORE_MASK SIXTYFOUR_BIT_CONSTANT(0x3800000000000000)
+#define OHA_RO_STATUS_REG_CORE_ACCESS_IMPOSSIBLE SIXTYFOUR_BIT_CONSTANT(0x0400000000000000)
+#define OHA_RO_STATUS_REG_ECO_ACCESS_IMPOSSIBLE SIXTYFOUR_BIT_CONSTANT(0x0200000000000000)
+#define OHA_RO_STATUS_REG_SPARE_6BIT_MASK SIXTYFOUR_BIT_CONSTANT(0x01f8000000000000)
+#define OHA_RO_STATUS_REG_CURRENT_AISS_FSM_STATE_VECTOR_MASK SIXTYFOUR_BIT_CONSTANT(0x0007f00000000000)
+#define OHA_RO_STATUS_REG_EFF_IDLE_STATE_MASK SIXTYFOUR_BIT_CONSTANT(0x00000e0000000000)
+#define OHA_RO_STATUS_REG_SPARE_1BIT SIXTYFOUR_BIT_CONSTANT(0x0000010000000000)
+#define OHA_RO_STATUS_REG_PC_TC_DEEP_IDLE_THREAD_STATE_MASK SIXTYFOUR_BIT_CONSTANT(0x000000ff00000000)
+#define OHA_RO_STATUS_REG_LPAR_ID_MASK SIXTYFOUR_BIT_CONSTANT(0x00000000fff00000)
+#define OHA_RO_STATUS_REG_PPT_FSM_L_MASK SIXTYFOUR_BIT_CONSTANT(0x00000000000f0000)
+#ifndef __ASSEMBLER__
+
+
+typedef union oha_mode_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t enable_ignore_recov_errors : 1;
+ uint64_t enable_arch_idle_mode_sequencer : 1;
+ uint64_t treat_sleep_as_nap : 1;
+ uint64_t treat_winkle_as_sleep : 1;
+ uint64_t enable_pstate_tracing : 1;
+ uint64_t enable_suppress_purges_and_pcb_fence : 1;
+ uint64_t idle_state_override_en : 1;
+ uint64_t idle_state_override_value : 3;
+ uint64_t disable_aiss_core_handshake : 1;
+ uint64_t aiss_hang_detect_timer_sel : 4;
+ uint64_t enable_l2_purge_abort : 1;
+ uint64_t enable_l3_purge_abort : 1;
+ uint64_t tod_pulse_count_match_val : 14;
+ uint64_t trace_debug_mode_select : 2;
+ uint64_t lpft_mode : 1;
+ uint64_t _reserved0 : 30;
+#else
+ uint64_t _reserved0 : 30;
+ uint64_t lpft_mode : 1;
+ uint64_t trace_debug_mode_select : 2;
+ uint64_t tod_pulse_count_match_val : 14;
+ uint64_t enable_l3_purge_abort : 1;
+ uint64_t enable_l2_purge_abort : 1;
+ uint64_t aiss_hang_detect_timer_sel : 4;
+ uint64_t disable_aiss_core_handshake : 1;
+ uint64_t idle_state_override_value : 3;
+ uint64_t idle_state_override_en : 1;
+ uint64_t enable_suppress_purges_and_pcb_fence : 1;
+ uint64_t enable_pstate_tracing : 1;
+ uint64_t treat_winkle_as_sleep : 1;
+ uint64_t treat_sleep_as_nap : 1;
+ uint64_t enable_arch_idle_mode_sequencer : 1;
+ uint64_t enable_ignore_recov_errors : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_mode_reg_t;
+
+
+
+typedef union oha_error_and_error_mask_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oha_error_mask : 8;
+ uint64_t oha_chiplet_errors : 8;
+ uint64_t _reserved0 : 48;
+#else
+ uint64_t _reserved0 : 48;
+ uint64_t oha_chiplet_errors : 8;
+ uint64_t oha_error_mask : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_error_and_error_mask_reg_t;
+
+
+
+typedef union oha_arch_idle_state_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t aiss_thold_sequence_select : 1;
+ uint64_t disable_waiting_on_l3 : 1;
+ uint64_t idle_seq_timer_select : 2;
+ uint64_t allow_aiss_interrupts : 1;
+ uint64_t enable_reset_of_counters_while_sleepwinkle : 1;
+ uint64_t select_p7p_seq_wait_time : 1;
+ uint64_t disable_auto_sleep_entry : 1;
+ uint64_t disable_auto_winkle_entry : 1;
+ uint64_t reset_idle_state_sequencer : 1;
+ uint64_t _reserved0 : 54;
+#else
+ uint64_t _reserved0 : 54;
+ uint64_t reset_idle_state_sequencer : 1;
+ uint64_t disable_auto_winkle_entry : 1;
+ uint64_t disable_auto_sleep_entry : 1;
+ uint64_t select_p7p_seq_wait_time : 1;
+ uint64_t enable_reset_of_counters_while_sleepwinkle : 1;
+ uint64_t allow_aiss_interrupts : 1;
+ uint64_t idle_seq_timer_select : 2;
+ uint64_t disable_waiting_on_l3 : 1;
+ uint64_t aiss_thold_sequence_select : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_arch_idle_state_reg_t;
+
+
+
+typedef union oha_pmu_config_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pmu_pstate_threshold_a : 8;
+ uint64_t pmu_pstate_threshold_b : 8;
+ uint64_t pmu_configuration : 3;
+ uint64_t _reserved0 : 45;
+#else
+ uint64_t _reserved0 : 45;
+ uint64_t pmu_configuration : 3;
+ uint64_t pmu_pstate_threshold_b : 8;
+ uint64_t pmu_pstate_threshold_a : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_pmu_config_reg_t;
+
+
+
+typedef union oha_aiss_io_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare_2bits_b : 2;
+ uint64_t tc_tp_chiplet_pm_state : 4;
+ uint64_t tc_pb_sleep : 1;
+ uint64_t tc_tc_pm_thold_ctrl : 3;
+ uint64_t tc_l3_fence_lco : 1;
+ uint64_t tc_ncu_fence : 1;
+ uint64_t chksw_hw237039dis : 1;
+ uint64_t tc_l3_init_dram : 1;
+ uint64_t tc_pb_purge : 1;
+ uint64_t tc_pc_pm_wake_up : 1;
+ uint64_t spare_entry_for_config_bit : 1;
+ uint64_t reset_of_counters_while_sleepwinkle : 1;
+ uint64_t tc_chtm_purge : 1;
+ uint64_t tc_tp_terminate_pcb : 1;
+ uint64_t tc_oha_therm_purge_lvl : 1;
+ uint64_t pscom_core_fence_lvl : 1;
+ uint64_t pb_eco_fence_lvl : 1;
+ uint64_t core2cache_fence_req : 1;
+ uint64_t cache2core_fence_req : 1;
+ uint64_t pervasive_eco_fence_req : 1;
+ uint64_t tc_oha_pmx_fence_req_lvl_l : 1;
+ uint64_t updateohafreq : 1;
+ uint64_t req_idle_state_change : 1;
+ uint64_t tc_l2_purge : 1;
+ uint64_t tc_l3_purge : 1;
+ uint64_t tc_ncu_purge : 1;
+ uint64_t tc_l2_purge_abort : 1;
+ uint64_t tc_l3_purge_abort : 1;
+ uint64_t pc_tc_pm_state : 3;
+ uint64_t l2_purge_is_done : 1;
+ uint64_t l3_ncu_chtm_purge_done : 3;
+ uint64_t tc_tc_xstop_err : 1;
+ uint64_t tc_tc_recov_err : 1;
+ uint64_t pb_tc_purge_active_lvl : 1;
+ uint64_t l3_tc_dram_ready_lvl : 1;
+ uint64_t core_fsm_non_idle : 1;
+ uint64_t tc_pscom_core_fence_done : 1;
+ uint64_t tc_pmx_oha_fence_done : 1;
+ uint64_t l2_purge_abort_sticky : 1;
+ uint64_t l3_purge_abort_sticky : 1;
+ uint64_t _reserved0 : 14;
+#else
+ uint64_t _reserved0 : 14;
+ uint64_t l3_purge_abort_sticky : 1;
+ uint64_t l2_purge_abort_sticky : 1;
+ uint64_t tc_pmx_oha_fence_done : 1;
+ uint64_t tc_pscom_core_fence_done : 1;
+ uint64_t core_fsm_non_idle : 1;
+ uint64_t l3_tc_dram_ready_lvl : 1;
+ uint64_t pb_tc_purge_active_lvl : 1;
+ uint64_t tc_tc_recov_err : 1;
+ uint64_t tc_tc_xstop_err : 1;
+ uint64_t l3_ncu_chtm_purge_done : 3;
+ uint64_t l2_purge_is_done : 1;
+ uint64_t pc_tc_pm_state : 3;
+ uint64_t tc_l3_purge_abort : 1;
+ uint64_t tc_l2_purge_abort : 1;
+ uint64_t tc_ncu_purge : 1;
+ uint64_t tc_l3_purge : 1;
+ uint64_t tc_l2_purge : 1;
+ uint64_t req_idle_state_change : 1;
+ uint64_t updateohafreq : 1;
+ uint64_t tc_oha_pmx_fence_req_lvl_l : 1;
+ uint64_t pervasive_eco_fence_req : 1;
+ uint64_t cache2core_fence_req : 1;
+ uint64_t core2cache_fence_req : 1;
+ uint64_t pb_eco_fence_lvl : 1;
+ uint64_t pscom_core_fence_lvl : 1;
+ uint64_t tc_oha_therm_purge_lvl : 1;
+ uint64_t tc_tp_terminate_pcb : 1;
+ uint64_t tc_chtm_purge : 1;
+ uint64_t reset_of_counters_while_sleepwinkle : 1;
+ uint64_t spare_entry_for_config_bit : 1;
+ uint64_t tc_pc_pm_wake_up : 1;
+ uint64_t tc_pb_purge : 1;
+ uint64_t tc_l3_init_dram : 1;
+ uint64_t chksw_hw237039dis : 1;
+ uint64_t tc_ncu_fence : 1;
+ uint64_t tc_l3_fence_lco : 1;
+ uint64_t tc_tc_pm_thold_ctrl : 3;
+ uint64_t tc_pb_sleep : 1;
+ uint64_t tc_tp_chiplet_pm_state : 4;
+ uint64_t spare_2bits_b : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_aiss_io_reg_t;
+
+
+
+typedef union oha_ppt_bar_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ppt_bar : 46;
+ uint64_t ppt_size_mask : 7;
+ uint64_t ppt_address_scope : 3;
+ uint64_t _reserved0 : 8;
+#else
+ uint64_t _reserved0 : 8;
+ uint64_t ppt_address_scope : 3;
+ uint64_t ppt_size_mask : 7;
+ uint64_t ppt_bar : 46;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_ppt_bar_reg_t;
+
+
+
+typedef union oha_l2_vcs_directory_read_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vcs_directory_read_weight_t;
+
+
+
+typedef union oha_l2_vcs_directory_write_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vcs_directory_write_weight_t;
+
+
+
+typedef union oha_l2_vcs_cache_full_read_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vcs_cache_full_read_weight_t;
+
+
+
+typedef union oha_l2_vcs_cache_targeted_read_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vcs_cache_targeted_read_weight_t;
+
+
+
+typedef union oha_l2_vcs_cache_write_cnt_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vcs_cache_write_cnt_weight_t;
+
+
+
+typedef union oha_l3_vcs_directory_read_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l3_vcs_directory_read_weight_t;
+
+
+
+typedef union oha_l3_vcs_directory_write_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l3_vcs_directory_write_weight_t;
+
+
+
+typedef union oha_l3_vcs_cache_access_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l3_vcs_cache_access_weight_t;
+
+
+
+typedef union oha_l2_vdd_directory_read_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vdd_directory_read_weight_t;
+
+
+
+typedef union oha_l2_vdd_directory_write_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vdd_directory_write_weight_t;
+
+
+
+typedef union oha_l2_vdd_cache_full_read_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vdd_cache_full_read_weight_t;
+
+
+
+typedef union oha_l2_vdd_cache_targeted_read_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vdd_cache_targeted_read_weight_t;
+
+
+
+typedef union oha_l2_vdd_cache_write_cnt_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l2_vdd_cache_write_cnt_weight_t;
+
+
+
+typedef union oha_l3_vdd_directory_read_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l3_vdd_directory_read_weight_t;
+
+
+
+typedef union oha_l3_vdd_directory_write_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l3_vdd_directory_write_weight_t;
+
+
+
+typedef union oha_l3_vdd_cache_access_weight {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 6;
+ uint64_t _reserved0 : 58;
+#else
+ uint64_t _reserved0 : 58;
+ uint64_t value : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_l3_vdd_cache_access_weight_t;
+
+
+
+typedef union oha_chksw_hw132623dis {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t value : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_chksw_hw132623dis_t;
+
+
+
+typedef union oha_activity_scale_factor_array {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 56;
+ uint64_t _reserved0 : 8;
+#else
+ uint64_t _reserved0 : 8;
+ uint64_t value : 56;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_activity_scale_factor_array_t;
+
+
+
+typedef union oha_activity_scale_shift_factor_array {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 42;
+ uint64_t _reserved0 : 22;
+#else
+ uint64_t _reserved0 : 22;
+ uint64_t value : 42;
+#endif // _BIG_ENDIAN
+ } fields;
+} oha_activity_scale_shift_factor_array_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __OHA_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/oha_register_addresses.h b/src/ssx/pgp/registers/oha_register_addresses.h
new file mode 100755
index 0000000..1f07b37
--- /dev/null
+++ b/src/ssx/pgp/registers/oha_register_addresses.h
@@ -0,0 +1,39 @@
+#ifndef __OHA_REGISTER_ADDRESSES_H__
+#define __OHA_REGISTER_ADDRESSES_H__
+
+// $Id: oha_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/oha_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file oha_register_addresses.h
+/// \brief Symbolic addresses for the OHA unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define OHA_PCB_BASE 0x10020000
+#define OHA_ACTIVITY_SAMPLE_MODE_REG 0x10020000
+#define OHA_VCS_ACTIVITY_CNT_REG 0x10020001
+#define OHA_VDD_ACTIVITY_CNT_REG 0x10020002
+#define OHA_LOW_ACTIVITY_DETECT_MODE_REG 0x10020003
+#define OHA_ACTIVITY_AND_FREQU_REG 0x10020004
+#define OHA_COUNTER_REG 0x10020005
+#define OHA_PROXY_REG 0x10020006
+#define OHA_PROXY_LEGACY_REG 0x10020007
+#define OHA_SKITTER_CTRL_MODE_REG 0x10020008
+#define OHA_CPM_CTRL_REG 0x1002000a
+#define OHA_CPM_HIST_RESET_REG 0x10020013
+#define OHA_RO_STATUS_REG 0x1002000b
+#define OHA_MODE_REG 0x1002000d
+#define OHA_ERROR_AND_ERROR_MASK_REG 0x1002000e
+#define OHA_ARCH_IDLE_STATE_REG 0x10020011
+#define OHA_PMU_CONFIG_REG 0x10020012
+#define OHA_AISS_IO_REG 0x10020014
+#define OHA_PPT_BAR_REG 0x10020015
+
+#endif // __OHA_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/pba_firmware_registers.h b/src/ssx/pgp/registers/pba_firmware_registers.h
new file mode 100755
index 0000000..502ef51
--- /dev/null
+++ b/src/ssx/pgp/registers/pba_firmware_registers.h
@@ -0,0 +1,2184 @@
+#ifndef __PBA_FIRMWARE_REGISTERS_H__
+#define __PBA_FIRMWARE_REGISTERS_H__
+
+// $Id: pba_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pba_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pba_firmware_registers.h
+/// \brief C register structs for the PBA unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union pba_barn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cmd_scope : 3;
+ uint64_t reserved0 : 1;
+ uint64_t reserved1 : 10;
+ uint64_t addr : 30;
+ uint64_t _reserved0 : 20;
+#else
+ uint64_t _reserved0 : 20;
+ uint64_t addr : 30;
+ uint64_t reserved1 : 10;
+ uint64_t reserved0 : 1;
+ uint64_t cmd_scope : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_barn_t;
+
+#endif // __ASSEMBLER__
+#define PBA_BARN_CMD_SCOPE_MASK SIXTYFOUR_BIT_CONSTANT(0xe000000000000000)
+#define PBA_BARN_ADDR_MASK SIXTYFOUR_BIT_CONSTANT(0x0003fffffff00000)
+#ifndef __ASSEMBLER__
+
+
+typedef union pba_barmskn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved0 : 23;
+ uint64_t mask : 21;
+ uint64_t _reserved0 : 20;
+#else
+ uint64_t _reserved0 : 20;
+ uint64_t mask : 21;
+ uint64_t reserved0 : 23;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_barmskn_t;
+
+#endif // __ASSEMBLER__
+#define PBA_BARMSKN_MASK_MASK SIXTYFOUR_BIT_CONSTANT(0x000001fffff00000)
+#ifndef __ASSEMBLER__
+
+
+typedef union pba_fir {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_fir_t;
+
+#endif // __ASSEMBLER__
+#define PBA_FIR_OCI_APAR_ERR SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define PBA_FIR_PB_RDADRERR_FW SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define PBA_FIR_PB_RDDATATO_FW SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define PBA_FIR_PB_SUE_FW SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define PBA_FIR_PB_UE_FW SIXTYFOUR_BIT_CONSTANT(0x0800000000000000)
+#define PBA_FIR_PB_CE_FW SIXTYFOUR_BIT_CONSTANT(0x0400000000000000)
+#define PBA_FIR_OCI_SLAVE_INIT SIXTYFOUR_BIT_CONSTANT(0x0200000000000000)
+#define PBA_FIR_OCI_WRPAR_ERR SIXTYFOUR_BIT_CONSTANT(0x0100000000000000)
+#define PBA_FIR_OCI_REREQTO SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define PBA_FIR_PB_UNEXPCRESP SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define PBA_FIR_PB_UNEXPDATA SIXTYFOUR_BIT_CONSTANT(0x0020000000000000)
+#define PBA_FIR_PB_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0010000000000000)
+#define PBA_FIR_PB_WRADRERR_FW SIXTYFOUR_BIT_CONSTANT(0x0008000000000000)
+#define PBA_FIR_PB_BADCRESP SIXTYFOUR_BIT_CONSTANT(0x0004000000000000)
+#define PBA_FIR_PB_ACKDEAD_FW SIXTYFOUR_BIT_CONSTANT(0x0002000000000000)
+#define PBA_FIR_PB_CRESPTO SIXTYFOUR_BIT_CONSTANT(0x0001000000000000)
+#define PBA_FIR_BCUE_SETUP_ERR SIXTYFOUR_BIT_CONSTANT(0x0000800000000000)
+#define PBA_FIR_BCUE_PB_ACK_DEAD SIXTYFOUR_BIT_CONSTANT(0x0000400000000000)
+#define PBA_FIR_BCUE_PB_ADRERR SIXTYFOUR_BIT_CONSTANT(0x0000200000000000)
+#define PBA_FIR_BCUE_OCI_DATAERR SIXTYFOUR_BIT_CONSTANT(0x0000100000000000)
+#define PBA_FIR_BCDE_SETUP_ERR SIXTYFOUR_BIT_CONSTANT(0x0000080000000000)
+#define PBA_FIR_BCDE_PB_ACK_DEAD SIXTYFOUR_BIT_CONSTANT(0x0000040000000000)
+#define PBA_FIR_BCDE_PB_ADRERR SIXTYFOUR_BIT_CONSTANT(0x0000020000000000)
+#define PBA_FIR_BCDE_RDDATATO_ERR SIXTYFOUR_BIT_CONSTANT(0x0000010000000000)
+#define PBA_FIR_BCDE_SUE_ERR SIXTYFOUR_BIT_CONSTANT(0x0000008000000000)
+#define PBA_FIR_BCDE_UE_ERR SIXTYFOUR_BIT_CONSTANT(0x0000004000000000)
+#define PBA_FIR_BCDE_CE SIXTYFOUR_BIT_CONSTANT(0x0000002000000000)
+#define PBA_FIR_BCDE_OCI_DATAERR SIXTYFOUR_BIT_CONSTANT(0x0000001000000000)
+#define PBA_FIR_INTERNAL_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000800000000)
+#define PBA_FIR_ILLEGAL_CACHE_OP SIXTYFOUR_BIT_CONSTANT(0x0000000400000000)
+#define PBA_FIR_OCI_BAD_REG_ADDR SIXTYFOUR_BIT_CONSTANT(0x0000000200000000)
+#define PBA_FIR_AXPUSH_WRERR SIXTYFOUR_BIT_CONSTANT(0x0000000100000000)
+#define PBA_FIR_AXRCV_DLO_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000080000000)
+#define PBA_FIR_AXRCV_DLO_TO SIXTYFOUR_BIT_CONSTANT(0x0000000040000000)
+#define PBA_FIR_AXRCV_RSVDATA_TO SIXTYFOUR_BIT_CONSTANT(0x0000000020000000)
+#define PBA_FIR_AXFLOW_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000010000000)
+#define PBA_FIR_AXSND_DHI_RTYTO SIXTYFOUR_BIT_CONSTANT(0x0000000008000000)
+#define PBA_FIR_AXSND_DLO_RTYTO SIXTYFOUR_BIT_CONSTANT(0x0000000004000000)
+#define PBA_FIR_AXSND_RSVTO SIXTYFOUR_BIT_CONSTANT(0x0000000002000000)
+#define PBA_FIR_AXSND_RSVERR SIXTYFOUR_BIT_CONSTANT(0x0000000001000000)
+#define PBA_FIR_PB_ACKDEAD_FW_WR SIXTYFOUR_BIT_CONSTANT(0x0000000000800000)
+#define PBA_FIR_FIR_PARITY_ERR2 SIXTYFOUR_BIT_CONSTANT(0x0000000000080000)
+#define PBA_FIR_FIR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000040000)
+#ifndef __ASSEMBLER__
+
+
+typedef union pba_fir_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_fir_and_t;
+
+
+
+typedef union pba_fir_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_fir_or_t;
+
+
+
+typedef union pba_firmask {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_firmask_t;
+
+
+
+typedef union pba_firmask_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_firmask_and_t;
+
+
+
+typedef union pba_firmask_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_firmask_or_t;
+
+
+
+typedef union pba_firact0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_firact0_t;
+
+
+
+typedef union pba_firact1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_firact1_t;
+
+
+
+typedef union pba_occact {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t oci_apar_err : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t internal_err : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t reserved41 : 3;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err2 : 1;
+ uint64_t reserved41 : 3;
+ uint64_t pb_ackdead_fw_wr : 1;
+ uint64_t axsnd_rsverr : 1;
+ uint64_t axsnd_rsvto : 1;
+ uint64_t axsnd_dlo_rtyto : 1;
+ uint64_t axsnd_dhi_rtyto : 1;
+ uint64_t axflow_err : 1;
+ uint64_t axrcv_rsvdata_to : 1;
+ uint64_t axrcv_dlo_to : 1;
+ uint64_t axrcv_dlo_err : 1;
+ uint64_t axpush_wrerr : 1;
+ uint64_t oci_bad_reg_addr : 1;
+ uint64_t illegal_cache_op : 1;
+ uint64_t internal_err : 1;
+ uint64_t bcde_oci_dataerr : 1;
+ uint64_t bcde_ce : 1;
+ uint64_t bcde_ue_err : 1;
+ uint64_t bcde_sue_err : 1;
+ uint64_t bcde_rddatato_err : 1;
+ uint64_t bcde_pb_adrerr : 1;
+ uint64_t bcde_pb_ack_dead : 1;
+ uint64_t bcde_setup_err : 1;
+ uint64_t bcue_oci_dataerr : 1;
+ uint64_t bcue_pb_adrerr : 1;
+ uint64_t bcue_pb_ack_dead : 1;
+ uint64_t bcue_setup_err : 1;
+ uint64_t pb_crespto : 1;
+ uint64_t pb_ackdead_fw : 1;
+ uint64_t pb_badcresp : 1;
+ uint64_t pb_wradrerr_fw : 1;
+ uint64_t pb_parity_err : 1;
+ uint64_t pb_unexpdata : 1;
+ uint64_t pb_unexpcresp : 1;
+ uint64_t oci_rereqto : 1;
+ uint64_t oci_wrpar_err : 1;
+ uint64_t oci_slave_init : 1;
+ uint64_t pb_ce_fw : 1;
+ uint64_t pb_ue_fw : 1;
+ uint64_t pb_sue_fw : 1;
+ uint64_t pb_rddatato_fw : 1;
+ uint64_t pb_rdadrerr_fw : 1;
+ uint64_t oci_apar_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_occact_t;
+
+
+
+typedef union pba_cfg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pbreq_slvfw_max_priority : 2;
+ uint64_t pbreq_bce_max_priority : 2;
+ uint64_t pbreq_data_hang_div : 5;
+ uint64_t pbreq_oper_hang_div : 5;
+ uint64_t pbreq_drop_priority_mask : 6;
+ uint64_t reserved20 : 4;
+ uint64_t chsw_hang_on_adrerror : 1;
+ uint64_t chsw_dis_ociabuspar_check : 1;
+ uint64_t chsw_dis_ocibepar_check : 1;
+ uint64_t chsw_hang_on_derror : 1;
+ uint64_t chsw_hang_on_rereq_timeout : 1;
+ uint64_t chsw_dis_write_match_rearb : 1;
+ uint64_t chsw_dis_ocidatapar_gen : 1;
+ uint64_t chsw_dis_ocidatapar_check : 1;
+ uint64_t chsw_dis_oper_hang : 1;
+ uint64_t chsw_dis_data_hang : 1;
+ uint64_t chsw_dis_ecc_check : 1;
+ uint64_t chsw_dis_retry_backoff : 1;
+ uint64_t chsw_hang_on_invalid_cresp : 1;
+ uint64_t chsw_en_scopeinc_on_bkill_inc : 1;
+ uint64_t chsw_dis_group_scope : 1;
+ uint64_t chsw_dis_rtag_parity_chk : 1;
+ uint64_t chsw_dis_pb_parity_chk : 1;
+ uint64_t _reserved0 : 23;
+#else
+ uint64_t _reserved0 : 23;
+ uint64_t chsw_dis_pb_parity_chk : 1;
+ uint64_t chsw_dis_rtag_parity_chk : 1;
+ uint64_t chsw_dis_group_scope : 1;
+ uint64_t chsw_en_scopeinc_on_bkill_inc : 1;
+ uint64_t chsw_hang_on_invalid_cresp : 1;
+ uint64_t chsw_dis_retry_backoff : 1;
+ uint64_t chsw_dis_ecc_check : 1;
+ uint64_t chsw_dis_data_hang : 1;
+ uint64_t chsw_dis_oper_hang : 1;
+ uint64_t chsw_dis_ocidatapar_check : 1;
+ uint64_t chsw_dis_ocidatapar_gen : 1;
+ uint64_t chsw_dis_write_match_rearb : 1;
+ uint64_t chsw_hang_on_rereq_timeout : 1;
+ uint64_t chsw_hang_on_derror : 1;
+ uint64_t chsw_dis_ocibepar_check : 1;
+ uint64_t chsw_dis_ociabuspar_check : 1;
+ uint64_t chsw_hang_on_adrerror : 1;
+ uint64_t reserved20 : 4;
+ uint64_t pbreq_drop_priority_mask : 6;
+ uint64_t pbreq_oper_hang_div : 5;
+ uint64_t pbreq_data_hang_div : 5;
+ uint64_t pbreq_bce_max_priority : 2;
+ uint64_t pbreq_slvfw_max_priority : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_cfg_t;
+
+
+
+typedef union pba_errpt0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cerr_pb_rddatato_fw : 6;
+ uint64_t cerr_pb_rdadrerr_fw : 6;
+ uint64_t cerr_pb_wradrerr_fw : 4;
+ uint64_t cerr_pb_ackdead_fw_rd : 6;
+ uint64_t cerr_pb_ackdead_fw_wr : 2;
+ uint64_t cerr_pb_unexpcresp : 11;
+ uint64_t cerr_pb_unexpdata : 6;
+ uint64_t _reserved0 : 23;
+#else
+ uint64_t _reserved0 : 23;
+ uint64_t cerr_pb_unexpdata : 6;
+ uint64_t cerr_pb_unexpcresp : 11;
+ uint64_t cerr_pb_ackdead_fw_wr : 2;
+ uint64_t cerr_pb_ackdead_fw_rd : 6;
+ uint64_t cerr_pb_wradrerr_fw : 4;
+ uint64_t cerr_pb_rdadrerr_fw : 6;
+ uint64_t cerr_pb_rddatato_fw : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_errpt0_t;
+
+
+
+typedef union pba_errpt1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cerr_pb_badcresp : 12;
+ uint64_t cerr_pb_crespto : 12;
+ uint64_t cerr_oci_rereqto : 6;
+ uint64_t cerr_bcde_setup_err : 2;
+ uint64_t cerr_bcue_setup_err : 2;
+ uint64_t cerr_bcue_oci_dataerr : 2;
+ uint64_t _reserved0 : 28;
+#else
+ uint64_t _reserved0 : 28;
+ uint64_t cerr_bcue_oci_dataerr : 2;
+ uint64_t cerr_bcue_setup_err : 2;
+ uint64_t cerr_bcde_setup_err : 2;
+ uint64_t cerr_oci_rereqto : 6;
+ uint64_t cerr_pb_crespto : 12;
+ uint64_t cerr_pb_badcresp : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_errpt1_t;
+
+
+
+typedef union pba_errpt2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cerr_slv_internal_err : 8;
+ uint64_t cerr_bcde_internal_err : 4;
+ uint64_t cerr_bcue_internal_err : 4;
+ uint64_t cerr_bar_parity_err : 1;
+ uint64_t cerr_scomtb_err : 1;
+ uint64_t reserved18 : 2;
+ uint64_t cerr_pbdout_parity_err : 1;
+ uint64_t cerr_pb_parity_err : 3;
+ uint64_t cerr_axflow_err : 5;
+ uint64_t cerr_axpush_wrerr : 2;
+ uint64_t _reserved0 : 33;
+#else
+ uint64_t _reserved0 : 33;
+ uint64_t cerr_axpush_wrerr : 2;
+ uint64_t cerr_axflow_err : 5;
+ uint64_t cerr_pb_parity_err : 3;
+ uint64_t cerr_pbdout_parity_err : 1;
+ uint64_t reserved18 : 2;
+ uint64_t cerr_scomtb_err : 1;
+ uint64_t cerr_bar_parity_err : 1;
+ uint64_t cerr_bcue_internal_err : 4;
+ uint64_t cerr_bcde_internal_err : 4;
+ uint64_t cerr_slv_internal_err : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_errpt2_t;
+
+
+
+typedef union pba_rbufvaln {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t rd_slvnum : 2;
+ uint64_t cur_rd_addr : 23;
+ uint64_t spare1 : 3;
+ uint64_t prefetch : 1;
+ uint64_t spare2 : 2;
+ uint64_t abort : 1;
+ uint64_t spare3 : 1;
+ uint64_t buffer_status : 7;
+ uint64_t spare4 : 1;
+ uint64_t masterid : 3;
+ uint64_t _reserved0 : 20;
+#else
+ uint64_t _reserved0 : 20;
+ uint64_t masterid : 3;
+ uint64_t spare4 : 1;
+ uint64_t buffer_status : 7;
+ uint64_t spare3 : 1;
+ uint64_t abort : 1;
+ uint64_t spare2 : 2;
+ uint64_t prefetch : 1;
+ uint64_t spare1 : 3;
+ uint64_t cur_rd_addr : 23;
+ uint64_t rd_slvnum : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_rbufvaln_t;
+
+
+
+typedef union pba_wbufvaln {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t wr_slvnum : 2;
+ uint64_t start_wr_addr : 30;
+ uint64_t spare1 : 3;
+ uint64_t wr_buffer_status : 5;
+ uint64_t spare2 : 1;
+ uint64_t wr_byte_count : 7;
+ uint64_t spare3 : 16;
+#else
+ uint64_t spare3 : 16;
+ uint64_t wr_byte_count : 7;
+ uint64_t spare2 : 1;
+ uint64_t wr_buffer_status : 5;
+ uint64_t spare1 : 3;
+ uint64_t start_wr_addr : 30;
+ uint64_t wr_slvnum : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_wbufvaln_t;
+
+
+
+typedef union pba_mode {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved0 : 4;
+ uint64_t dis_rearb : 1;
+ uint64_t dis_mstid_match_pref_inv : 1;
+ uint64_t dis_slave_rdpipe : 1;
+ uint64_t dis_slave_wrpipe : 1;
+ uint64_t en_marker_ack : 1;
+ uint64_t dis_slvmatch_order : 1;
+ uint64_t en_second_wrbuf : 1;
+ uint64_t dis_rerequest_to : 1;
+ uint64_t inject_type : 2;
+ uint64_t inject_mode : 2;
+ uint64_t pba_region : 2;
+ uint64_t oci_marker_space : 3;
+ uint64_t bcde_ocitrans : 2;
+ uint64_t bcue_ocitrans : 2;
+ uint64_t dis_master_rd_pipe : 1;
+ uint64_t dis_master_wr_pipe : 1;
+ uint64_t en_slave_fairness : 1;
+ uint64_t en_event_count : 1;
+ uint64_t pb_noci_event_sel : 1;
+ uint64_t slv_event_mux : 2;
+ uint64_t enable_debug_bus : 1;
+ uint64_t debug_pb_not_oci : 1;
+ uint64_t debug_oci_mode : 5;
+ uint64_t reserved2 : 1;
+ uint64_t ocislv_fairness_mask : 5;
+ uint64_t ocislv_rereq_hang_div : 5;
+ uint64_t dis_chgrate_count : 1;
+ uint64_t pbreq_event_mux : 2;
+ uint64_t _reserved0 : 11;
+#else
+ uint64_t _reserved0 : 11;
+ uint64_t pbreq_event_mux : 2;
+ uint64_t dis_chgrate_count : 1;
+ uint64_t ocislv_rereq_hang_div : 5;
+ uint64_t ocislv_fairness_mask : 5;
+ uint64_t reserved2 : 1;
+ uint64_t debug_oci_mode : 5;
+ uint64_t debug_pb_not_oci : 1;
+ uint64_t enable_debug_bus : 1;
+ uint64_t slv_event_mux : 2;
+ uint64_t pb_noci_event_sel : 1;
+ uint64_t en_event_count : 1;
+ uint64_t en_slave_fairness : 1;
+ uint64_t dis_master_wr_pipe : 1;
+ uint64_t dis_master_rd_pipe : 1;
+ uint64_t bcue_ocitrans : 2;
+ uint64_t bcde_ocitrans : 2;
+ uint64_t oci_marker_space : 3;
+ uint64_t pba_region : 2;
+ uint64_t inject_mode : 2;
+ uint64_t inject_type : 2;
+ uint64_t dis_rerequest_to : 1;
+ uint64_t en_second_wrbuf : 1;
+ uint64_t dis_slvmatch_order : 1;
+ uint64_t en_marker_ack : 1;
+ uint64_t dis_slave_wrpipe : 1;
+ uint64_t dis_slave_rdpipe : 1;
+ uint64_t dis_mstid_match_pref_inv : 1;
+ uint64_t dis_rearb : 1;
+ uint64_t reserved0 : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_mode_t;
+
+
+
+typedef union pba_slvrst {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t set : 3;
+ uint64_t notimp1 : 1;
+ uint64_t in_prog : 4;
+ uint64_t busy_status : 4;
+ uint64_t _reserved0 : 52;
+#else
+ uint64_t _reserved0 : 52;
+ uint64_t busy_status : 4;
+ uint64_t in_prog : 4;
+ uint64_t notimp1 : 1;
+ uint64_t set : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_slvrst_t;
+
+
+
+typedef union pba_slvctln {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t enable : 1;
+ uint64_t mid_match_value : 3;
+ uint64_t _reserved0 : 1;
+ uint64_t mid_care_mask : 3;
+ uint64_t write_ttype : 3;
+ uint64_t _reserved1 : 4;
+ uint64_t read_ttype : 1;
+ uint64_t read_prefetch_ctl : 2;
+ uint64_t buf_invalidate_ctl : 1;
+ uint64_t buf_alloc_w : 1;
+ uint64_t buf_alloc_a : 1;
+ uint64_t buf_alloc_b : 1;
+ uint64_t buf_alloc_c : 1;
+ uint64_t _reserved2 : 1;
+ uint64_t dis_write_gather : 1;
+ uint64_t wr_gather_timeout : 3;
+ uint64_t write_tsize : 7;
+ uint64_t extaddr : 14;
+ uint64_t _reserved3 : 15;
+#else
+ uint64_t _reserved3 : 15;
+ uint64_t extaddr : 14;
+ uint64_t write_tsize : 7;
+ uint64_t wr_gather_timeout : 3;
+ uint64_t dis_write_gather : 1;
+ uint64_t _reserved2 : 1;
+ uint64_t buf_alloc_c : 1;
+ uint64_t buf_alloc_b : 1;
+ uint64_t buf_alloc_a : 1;
+ uint64_t buf_alloc_w : 1;
+ uint64_t buf_invalidate_ctl : 1;
+ uint64_t read_prefetch_ctl : 2;
+ uint64_t read_ttype : 1;
+ uint64_t _reserved1 : 4;
+ uint64_t write_ttype : 3;
+ uint64_t mid_care_mask : 3;
+ uint64_t _reserved0 : 1;
+ uint64_t mid_match_value : 3;
+ uint64_t enable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_slvctln_t;
+
+
+
+typedef union pba_bcde_ctl {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t stop : 1;
+ uint64_t start : 1;
+ uint64_t _reserved0 : 62;
+#else
+ uint64_t _reserved0 : 62;
+ uint64_t start : 1;
+ uint64_t stop : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcde_ctl_t;
+
+#endif // __ASSEMBLER__
+#define PBA_BCDE_CTL_STOP SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define PBA_BCDE_CTL_START SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union pba_bcde_set {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 2;
+ uint64_t copy_length : 6;
+ uint64_t _reserved1 : 56;
+#else
+ uint64_t _reserved1 : 56;
+ uint64_t copy_length : 6;
+ uint64_t _reserved0 : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcde_set_t;
+
+
+
+typedef union pba_bcde_stat {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t running : 1;
+ uint64_t waiting : 1;
+ uint64_t wrcmp : 6;
+ uint64_t _reserved0 : 6;
+ uint64_t rdcmp : 6;
+ uint64_t debug : 9;
+ uint64_t stopped : 1;
+ uint64_t error : 1;
+ uint64_t done : 1;
+ uint64_t _reserved1 : 32;
+#else
+ uint64_t _reserved1 : 32;
+ uint64_t done : 1;
+ uint64_t error : 1;
+ uint64_t stopped : 1;
+ uint64_t debug : 9;
+ uint64_t rdcmp : 6;
+ uint64_t _reserved0 : 6;
+ uint64_t wrcmp : 6;
+ uint64_t waiting : 1;
+ uint64_t running : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcde_stat_t;
+
+
+
+typedef union pba_bcde_pbadr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 2;
+ uint64_t pb_offset : 23;
+ uint64_t _reserved1 : 2;
+ uint64_t extaddr : 14;
+ uint64_t _reserved2 : 23;
+#else
+ uint64_t _reserved2 : 23;
+ uint64_t extaddr : 14;
+ uint64_t _reserved1 : 2;
+ uint64_t pb_offset : 23;
+ uint64_t _reserved0 : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcde_pbadr_t;
+
+
+
+typedef union pba_bcde_ocibar {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t addr : 25;
+ uint64_t _reserved0 : 39;
+#else
+ uint64_t _reserved0 : 39;
+ uint64_t addr : 25;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcde_ocibar_t;
+
+
+
+typedef union pba_bcue_ctl {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t stop : 1;
+ uint64_t start : 1;
+ uint64_t _reserved0 : 62;
+#else
+ uint64_t _reserved0 : 62;
+ uint64_t start : 1;
+ uint64_t stop : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcue_ctl_t;
+
+#endif // __ASSEMBLER__
+#define PBA_BCUE_CTL_STOP SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define PBA_BCUE_CTL_START SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union pba_bcue_set {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 2;
+ uint64_t copy_length : 6;
+ uint64_t _reserved1 : 56;
+#else
+ uint64_t _reserved1 : 56;
+ uint64_t copy_length : 6;
+ uint64_t _reserved0 : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcue_set_t;
+
+
+
+typedef union pba_bcue_stat {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t running : 1;
+ uint64_t waiting : 1;
+ uint64_t wrcmp : 6;
+ uint64_t _reserved0 : 6;
+ uint64_t rdcmp : 6;
+ uint64_t debug : 9;
+ uint64_t stopped : 1;
+ uint64_t error : 1;
+ uint64_t done : 1;
+ uint64_t _reserved1 : 32;
+#else
+ uint64_t _reserved1 : 32;
+ uint64_t done : 1;
+ uint64_t error : 1;
+ uint64_t stopped : 1;
+ uint64_t debug : 9;
+ uint64_t rdcmp : 6;
+ uint64_t _reserved0 : 6;
+ uint64_t wrcmp : 6;
+ uint64_t waiting : 1;
+ uint64_t running : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcue_stat_t;
+
+
+
+typedef union pba_bcue_pbadr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 2;
+ uint64_t pb_offset : 23;
+ uint64_t _reserved1 : 2;
+ uint64_t extaddr : 14;
+ uint64_t _reserved2 : 23;
+#else
+ uint64_t _reserved2 : 23;
+ uint64_t extaddr : 14;
+ uint64_t _reserved1 : 2;
+ uint64_t pb_offset : 23;
+ uint64_t _reserved0 : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcue_pbadr_t;
+
+
+
+typedef union pba_bcue_ocibar {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t addr : 25;
+ uint64_t _reserved0 : 39;
+#else
+ uint64_t _reserved0 : 39;
+ uint64_t addr : 25;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_bcue_ocibar_t;
+
+
+
+typedef union pba_pbocrn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 16;
+ uint64_t event : 16;
+ uint64_t _reserved1 : 12;
+ uint64_t accum : 20;
+#else
+ uint64_t accum : 20;
+ uint64_t _reserved1 : 12;
+ uint64_t event : 16;
+ uint64_t _reserved0 : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_pbocrn_t;
+
+
+
+typedef union pba_xsndtx {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t snd_scope : 3;
+ uint64_t snd_qid : 1;
+ uint64_t snd_type : 1;
+ uint64_t snd_reservation : 1;
+ uint64_t spare6 : 2;
+ uint64_t snd_nodeid : 3;
+ uint64_t snd_chipid : 3;
+ uint64_t spare14 : 2;
+ uint64_t _reserved0 : 48;
+#else
+ uint64_t _reserved0 : 48;
+ uint64_t spare14 : 2;
+ uint64_t snd_chipid : 3;
+ uint64_t snd_nodeid : 3;
+ uint64_t spare6 : 2;
+ uint64_t snd_reservation : 1;
+ uint64_t snd_type : 1;
+ uint64_t snd_qid : 1;
+ uint64_t snd_scope : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_xsndtx_t;
+
+
+
+typedef union pba_xcfg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pbax_en : 1;
+ uint64_t reservation_en : 1;
+ uint64_t snd_reset : 1;
+ uint64_t rcv_reset : 1;
+ uint64_t rcv_nodeid : 3;
+ uint64_t rcv_chipid : 3;
+ uint64_t spare10 : 2;
+ uint64_t rcv_brdcst_group : 8;
+ uint64_t rcv_datato_div : 5;
+ uint64_t spare25 : 2;
+ uint64_t snd_retry_count_overcom : 1;
+ uint64_t snd_retry_thresh : 8;
+ uint64_t snd_rsvto_div : 5;
+ uint64_t _reserved0 : 23;
+#else
+ uint64_t _reserved0 : 23;
+ uint64_t snd_rsvto_div : 5;
+ uint64_t snd_retry_thresh : 8;
+ uint64_t snd_retry_count_overcom : 1;
+ uint64_t spare25 : 2;
+ uint64_t rcv_datato_div : 5;
+ uint64_t rcv_brdcst_group : 8;
+ uint64_t spare10 : 2;
+ uint64_t rcv_chipid : 3;
+ uint64_t rcv_nodeid : 3;
+ uint64_t rcv_reset : 1;
+ uint64_t snd_reset : 1;
+ uint64_t reservation_en : 1;
+ uint64_t pbax_en : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_xcfg_t;
+
+
+
+typedef union pba_xsndstat {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t snd_in_progress : 1;
+ uint64_t snd_error : 1;
+ uint64_t snd_status : 6;
+ uint64_t snd_retry_count : 8;
+ uint64_t _reserved0 : 48;
+#else
+ uint64_t _reserved0 : 48;
+ uint64_t snd_retry_count : 8;
+ uint64_t snd_status : 6;
+ uint64_t snd_error : 1;
+ uint64_t snd_in_progress : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_xsndstat_t;
+
+
+
+typedef union pba_xsnddat {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pbax_datahi : 32;
+ uint64_t pbax_datalo : 32;
+#else
+ uint64_t pbax_datalo : 32;
+ uint64_t pbax_datahi : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_xsnddat_t;
+
+
+
+typedef union pba_xrcvstat {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t rcv_in_progress : 1;
+ uint64_t rcv_error : 1;
+ uint64_t rcv_write_in_progress : 1;
+ uint64_t rcv_reservation_set : 1;
+ uint64_t rcv_capture : 14;
+ uint64_t _reserved0 : 46;
+#else
+ uint64_t _reserved0 : 46;
+ uint64_t rcv_capture : 14;
+ uint64_t rcv_reservation_set : 1;
+ uint64_t rcv_write_in_progress : 1;
+ uint64_t rcv_error : 1;
+ uint64_t rcv_in_progress : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_xrcvstat_t;
+
+
+
+typedef union pba_xshbrn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t push_start : 29;
+ uint64_t _reserved0 : 35;
+#else
+ uint64_t _reserved0 : 35;
+ uint64_t push_start : 29;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_xshbrn_t;
+
+
+
+typedef union pba_xshcsn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t push_full : 1;
+ uint64_t push_empty : 1;
+ uint64_t spare1 : 2;
+ uint64_t push_intr_action : 2;
+ uint64_t push_length : 5;
+ uint64_t notimp1 : 2;
+ uint64_t push_write_ptr : 5;
+ uint64_t notimp2 : 3;
+ uint64_t push_read_ptr : 5;
+ uint64_t notimp3 : 5;
+ uint64_t push_enable : 1;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t push_enable : 1;
+ uint64_t notimp3 : 5;
+ uint64_t push_read_ptr : 5;
+ uint64_t notimp2 : 3;
+ uint64_t push_write_ptr : 5;
+ uint64_t notimp1 : 2;
+ uint64_t push_length : 5;
+ uint64_t push_intr_action : 2;
+ uint64_t spare1 : 2;
+ uint64_t push_empty : 1;
+ uint64_t push_full : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_xshcsn_t;
+
+
+
+typedef union pba_xshincn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 64;
+#else
+ uint64_t reserved : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pba_xshincn_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __PBA_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/pba_register_addresses.h b/src/ssx/pgp/registers/pba_register_addresses.h
new file mode 100755
index 0000000..1703629
--- /dev/null
+++ b/src/ssx/pgp/registers/pba_register_addresses.h
@@ -0,0 +1,94 @@
+#ifndef __PBA_REGISTER_ADDRESSES_H__
+#define __PBA_REGISTER_ADDRESSES_H__
+
+// $Id: pba_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pba_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pba_register_addresses.h
+/// \brief Symbolic addresses for the PBA unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define TRUSTEDPIB_BASE 0x02013f00
+#define PBA_BARN(n) (PBA_BAR0 + ((PBA_BAR1 - PBA_BAR0) * (n)))
+#define PBA_BAR0 0x02013f00
+#define PBA_BAR1 0x02013f01
+#define PBA_BAR2 0x02013f02
+#define PBA_BAR3 0x02013f03
+#define PBA_BARMSKN(n) (PBA_BARMSK0 + ((PBA_BARMSK1 - PBA_BARMSK0) * (n)))
+#define PBA_BARMSK0 0x02013f04
+#define PBA_BARMSK1 0x02013f05
+#define PBA_BARMSK2 0x02013f06
+#define PBA_BARMSK3 0x02013f07
+#define PIB_BASE 0x02010840
+#define PBA_FIR 0x02010840
+#define PBA_FIR_AND 0x02010841
+#define PBA_FIR_OR 0x02010842
+#define PBA_FIRMASK 0x02010843
+#define PBA_FIRMASK_AND 0x02010844
+#define PBA_FIRMASK_OR 0x02010845
+#define PBA_FIRACT0 0x02010846
+#define PBA_FIRACT1 0x02010847
+#define PBA_OCCACT 0x0201084a
+#define PBA_CFG 0x0201084b
+#define PBA_ERRPT0 0x0201084c
+#define PBA_ERRPT1 0x0201084d
+#define PBA_ERRPT2 0x0201084e
+#define PBA_RBUFVALN(n) (PBA_RBUFVAL0 + ((PBA_RBUFVAL1 - PBA_RBUFVAL0) * (n)))
+#define PBA_RBUFVAL0 0x02010850
+#define PBA_RBUFVAL1 0x02010851
+#define PBA_RBUFVAL2 0x02010852
+#define PBA_RBUFVAL3 0x02010853
+#define PBA_RBUFVAL4 0x02010854
+#define PBA_RBUFVAL5 0x02010855
+#define PBA_WBUFVALN(n) (PBA_WBUFVAL0 + ((PBA_WBUFVAL1 - PBA_WBUFVAL0) * (n)))
+#define PBA_WBUFVAL0 0x02010858
+#define PBA_WBUFVAL1 0x02010859
+#define OCI_BASE 0x40020000
+#define PBA_MODE 0x40020000
+#define PBA_SLVRST 0x40020008
+#define PBA_SLVCTLN(n) (PBA_SLVCTL0 + ((PBA_SLVCTL1 - PBA_SLVCTL0) * (n)))
+#define PBA_SLVCTL0 0x40020020
+#define PBA_SLVCTL1 0x40020028
+#define PBA_SLVCTL2 0x40020030
+#define PBA_SLVCTL3 0x40020038
+#define PBA_BCDE_CTL 0x40020080
+#define PBA_BCDE_SET 0x40020088
+#define PBA_BCDE_STAT 0x40020090
+#define PBA_BCDE_PBADR 0x40020098
+#define PBA_BCDE_OCIBAR 0x400200a0
+#define PBA_BCUE_CTL 0x400200a8
+#define PBA_BCUE_SET 0x400200b0
+#define PBA_BCUE_STAT 0x400200b8
+#define PBA_BCUE_PBADR 0x400200c0
+#define PBA_BCUE_OCIBAR 0x400200c8
+#define PBA_PBOCRN(n) (PBA_PBOCR0 + ((PBA_PBOCR1 - PBA_PBOCR0) * (n)))
+#define PBA_PBOCR0 0x400200d0
+#define PBA_PBOCR1 0x400200d8
+#define PBA_PBOCR2 0x400200e0
+#define PBA_PBOCR3 0x400200e8
+#define PBA_PBOCR4 0x400200f0
+#define PBA_PBOCR5 0x400200f8
+#define PBA_XSNDTX 0x40020100
+#define PBA_XCFG 0x40020108
+#define PBA_XSNDSTAT 0x40020110
+#define PBA_XSNDDAT 0x40020118
+#define PBA_XRCVSTAT 0x40020120
+#define PBA_XSHBRN(n) (PBA_XSHBR0 + ((PBA_XSHBR1 - PBA_XSHBR0) * (n)))
+#define PBA_XSHBR0 0x40020130
+#define PBA_XSHBR1 0x40020150
+#define PBA_XSHCSN(n) (PBA_XSHCS0 + ((PBA_XSHCS1 - PBA_XSHCS0) * (n)))
+#define PBA_XSHCS0 0x40020138
+#define PBA_XSHCS1 0x40020158
+#define PBA_XSHINCN(n) (PBA_XSHINC0 + ((PBA_XSHINC1 - PBA_XSHINC0) * (n)))
+#define PBA_XSHINC0 0x40020140
+#define PBA_XSHINC1 0x40020160
+
+#endif // __PBA_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/pc_firmware_registers.h b/src/ssx/pgp/registers/pc_firmware_registers.h
new file mode 100755
index 0000000..2c86308
--- /dev/null
+++ b/src/ssx/pgp/registers/pc_firmware_registers.h
@@ -0,0 +1,442 @@
+#ifndef __PC_FIRMWARE_REGISTERS_H__
+#define __PC_FIRMWARE_REGISTERS_H__
+
+// $Id: pc_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pc_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pc_firmware_registers.h
+/// \brief C register structs for the PC unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union pc_pfth_modereg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pfth_cntr_dis : 1;
+ uint64_t pfth_charac_mode : 1;
+ uint64_t pfth_cntr_run_latch_gate_dis : 1;
+ uint64_t sprd_pfth_tx_run_latches : 8;
+ uint64_t tx_threads_stopped : 8;
+ uint64_t _reserved0 : 45;
+#else
+ uint64_t _reserved0 : 45;
+ uint64_t tx_threads_stopped : 8;
+ uint64_t sprd_pfth_tx_run_latches : 8;
+ uint64_t pfth_cntr_run_latch_gate_dis : 1;
+ uint64_t pfth_charac_mode : 1;
+ uint64_t pfth_cntr_dis : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_pfth_modereg_t;
+
+
+
+typedef union pc_occ_sprc {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved0 : 53;
+ uint64_t autoinc : 1;
+ uint64_t sprn : 7;
+ uint64_t reserved1 : 3;
+#else
+ uint64_t reserved1 : 3;
+ uint64_t sprn : 7;
+ uint64_t autoinc : 1;
+ uint64_t reserved0 : 53;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_occ_sprc_t;
+
+
+
+typedef union pc_occ_sprd {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_occ_sprd_t;
+
+
+
+typedef union pc_pfth_oha_instr_cnt_sel {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 62;
+ uint64_t value : 2;
+#else
+ uint64_t value : 2;
+ uint64_t _reserved0 : 62;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_pfth_oha_instr_cnt_sel_t;
+
+
+
+typedef union pc_pfth_throt_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t didt_trigger_enable : 1;
+ uint64_t isu_trigger_enable : 1;
+ uint64_t didt_throttle : 2;
+ uint64_t uthrottle : 2;
+ uint64_t force_suppress_speedup : 1;
+ uint64_t suppress_speedup_on_throttle : 1;
+ uint64_t core_slowdown : 1;
+ uint64_t suppress_on_slowdown : 1;
+ uint64_t isu_only_count_mode : 1;
+ uint64_t spare : 5;
+ uint64_t reserved : 48;
+#else
+ uint64_t reserved : 48;
+ uint64_t spare : 5;
+ uint64_t isu_only_count_mode : 1;
+ uint64_t suppress_on_slowdown : 1;
+ uint64_t core_slowdown : 1;
+ uint64_t suppress_speedup_on_throttle : 1;
+ uint64_t force_suppress_speedup : 1;
+ uint64_t uthrottle : 2;
+ uint64_t didt_throttle : 2;
+ uint64_t isu_trigger_enable : 1;
+ uint64_t didt_trigger_enable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_pfth_throt_reg_t;
+
+
+
+typedef union pc_direct_controln {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved0 : 42;
+ uint64_t dc_prestart_sleep : 1;
+ uint64_t dc_prestart_winkle : 1;
+ uint64_t dc_clear_maint : 1;
+ uint64_t dc_ntc_flush : 1;
+ uint64_t reserved46 : 1;
+ uint64_t dc_prestart_nap : 1;
+ uint64_t dc_cancel_lost : 1;
+ uint64_t dc_reset_maint : 1;
+ uint64_t reserved50 : 1;
+ uint64_t dc_set_maint : 1;
+ uint64_t dc_goto_quiesce_state : 1;
+ uint64_t reserved53 : 1;
+ uint64_t dc_inj_test_hang : 2;
+ uint64_t dc_core_running : 1;
+ uint64_t dc_hang_inject : 1;
+ uint64_t dc_smt_start_suppress : 1;
+ uint64_t reserved59 : 1;
+ uint64_t dc_sreset_request : 1;
+ uint64_t dc_core_step : 1;
+ uint64_t dc_core_start : 1;
+ uint64_t dc_core_stop : 1;
+#else
+ uint64_t dc_core_stop : 1;
+ uint64_t dc_core_start : 1;
+ uint64_t dc_core_step : 1;
+ uint64_t dc_sreset_request : 1;
+ uint64_t reserved59 : 1;
+ uint64_t dc_smt_start_suppress : 1;
+ uint64_t dc_hang_inject : 1;
+ uint64_t dc_core_running : 1;
+ uint64_t dc_inj_test_hang : 2;
+ uint64_t reserved53 : 1;
+ uint64_t dc_goto_quiesce_state : 1;
+ uint64_t dc_set_maint : 1;
+ uint64_t reserved50 : 1;
+ uint64_t dc_reset_maint : 1;
+ uint64_t dc_cancel_lost : 1;
+ uint64_t dc_prestart_nap : 1;
+ uint64_t reserved46 : 1;
+ uint64_t dc_ntc_flush : 1;
+ uint64_t dc_clear_maint : 1;
+ uint64_t dc_prestart_winkle : 1;
+ uint64_t dc_prestart_sleep : 1;
+ uint64_t reserved0 : 42;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_direct_controln_t;
+
+
+
+typedef union pc_ras_moderegn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved0 : 43;
+ uint64_t mr_thread_in_debug_mode : 1;
+ uint64_t mr_pmon_inhibit : 1;
+ uint64_t mr_fence_interrupts : 1;
+ uint64_t mr_stop_fetch : 1;
+ uint64_t mr_stop_prefetch : 1;
+ uint64_t mr_stop_dispatch : 1;
+ uint64_t mr_single_decode : 1;
+ uint64_t mr_do_single_mode : 1;
+ uint64_t mr_one_ppc_mode : 1;
+ uint64_t mr_hang_test_ctrl : 2;
+ uint64_t mr_attempt_gps_hr : 3;
+ uint64_t mr_hang_dis : 1;
+ uint64_t mr_on_corehng : 1;
+ uint64_t mr_on_ambihng : 1;
+ uint64_t mr_on_nesthng : 1;
+ uint64_t mr_recov_enable : 1;
+ uint64_t mr_block_hmi_on_maint : 1;
+ uint64_t mr_fence_intr_on_checkstop : 1;
+#else
+ uint64_t mr_fence_intr_on_checkstop : 1;
+ uint64_t mr_block_hmi_on_maint : 1;
+ uint64_t mr_recov_enable : 1;
+ uint64_t mr_on_nesthng : 1;
+ uint64_t mr_on_ambihng : 1;
+ uint64_t mr_on_corehng : 1;
+ uint64_t mr_hang_dis : 1;
+ uint64_t mr_attempt_gps_hr : 3;
+ uint64_t mr_hang_test_ctrl : 2;
+ uint64_t mr_one_ppc_mode : 1;
+ uint64_t mr_do_single_mode : 1;
+ uint64_t mr_single_decode : 1;
+ uint64_t mr_stop_dispatch : 1;
+ uint64_t mr_stop_prefetch : 1;
+ uint64_t mr_stop_fetch : 1;
+ uint64_t mr_fence_interrupts : 1;
+ uint64_t mr_pmon_inhibit : 1;
+ uint64_t mr_thread_in_debug_mode : 1;
+ uint64_t reserved0 : 43;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_ras_moderegn_t;
+
+
+
+typedef union pc_ras_statusn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t quiesce_status : 20;
+ uint64_t reserved20 : 1;
+ uint64_t reserved21 : 1;
+ uint64_t reserved22 : 1;
+ uint64_t other_thread_active : 1;
+ uint64_t hang_fsm : 3;
+ uint64_t reserved27 : 1;
+ uint64_t hang_hist0 : 1;
+ uint64_t hang_hist1 : 1;
+ uint64_t hang_hist2 : 1;
+ uint64_t hang_hist3 : 1;
+ uint64_t reserved32 : 1;
+ uint64_t hr_comp_cnt : 8;
+ uint64_t smt_dead_stop : 1;
+ uint64_t stop_fetch : 1;
+ uint64_t stop_dispatch : 1;
+ uint64_t stop_completion : 1;
+ uint64_t hold_decode : 1;
+ uint64_t reserved46 : 1;
+ uint64_t reserved47 : 1;
+ uint64_t thread_enabled : 1;
+ uint64_t pow_status_thread_state : 4;
+ uint64_t reserved53 : 1;
+ uint64_t maint_single_mode : 1;
+ uint64_t reserved55 : 1;
+ uint64_t reserved56 : 1;
+ uint64_t reserved57 : 7;
+#else
+ uint64_t reserved57 : 7;
+ uint64_t reserved56 : 1;
+ uint64_t reserved55 : 1;
+ uint64_t maint_single_mode : 1;
+ uint64_t reserved53 : 1;
+ uint64_t pow_status_thread_state : 4;
+ uint64_t thread_enabled : 1;
+ uint64_t reserved47 : 1;
+ uint64_t reserved46 : 1;
+ uint64_t hold_decode : 1;
+ uint64_t stop_completion : 1;
+ uint64_t stop_dispatch : 1;
+ uint64_t stop_fetch : 1;
+ uint64_t smt_dead_stop : 1;
+ uint64_t hr_comp_cnt : 8;
+ uint64_t reserved32 : 1;
+ uint64_t hang_hist3 : 1;
+ uint64_t hang_hist2 : 1;
+ uint64_t hang_hist1 : 1;
+ uint64_t hang_hist0 : 1;
+ uint64_t reserved27 : 1;
+ uint64_t hang_fsm : 3;
+ uint64_t other_thread_active : 1;
+ uint64_t reserved22 : 1;
+ uint64_t reserved21 : 1;
+ uint64_t reserved20 : 1;
+ uint64_t quiesce_status : 20;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_ras_statusn_t;
+
+
+
+typedef union pc_pow_statusn {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t thread_state : 4;
+ uint64_t thread_pow_state : 2;
+ uint64_t smt_mode : 3;
+ uint64_t hmi_intr : 1;
+ uint64_t maybe_ext_intr : 1;
+ uint64_t decr_intr : 1;
+ uint64_t maybe_debug_intr : 1;
+ uint64_t hdec_intr : 1;
+ uint64_t maybe_pmu_intr : 1;
+ uint64_t sp_attn_intr : 1;
+ uint64_t sreset_type : 3;
+ uint64_t reserved19 : 1;
+ uint64_t sreset_pending : 1;
+ uint64_t debug_fetch_stop : 1;
+ uint64_t async_pending : 1;
+ uint64_t core_pow_state : 3;
+ uint64_t reserved26 : 3;
+ uint64_t _reserved0 : 35;
+#else
+ uint64_t _reserved0 : 35;
+ uint64_t reserved26 : 3;
+ uint64_t core_pow_state : 3;
+ uint64_t async_pending : 1;
+ uint64_t debug_fetch_stop : 1;
+ uint64_t sreset_pending : 1;
+ uint64_t reserved19 : 1;
+ uint64_t sreset_type : 3;
+ uint64_t sp_attn_intr : 1;
+ uint64_t maybe_pmu_intr : 1;
+ uint64_t hdec_intr : 1;
+ uint64_t maybe_debug_intr : 1;
+ uint64_t decr_intr : 1;
+ uint64_t maybe_ext_intr : 1;
+ uint64_t hmi_intr : 1;
+ uint64_t smt_mode : 3;
+ uint64_t thread_pow_state : 2;
+ uint64_t thread_state : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pc_pow_statusn_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __PC_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/pc_register_addresses.h b/src/ssx/pgp/registers/pc_register_addresses.h
new file mode 100755
index 0000000..8b9baf2
--- /dev/null
+++ b/src/ssx/pgp/registers/pc_register_addresses.h
@@ -0,0 +1,61 @@
+#ifndef __PC_REGISTER_ADDRESSES_H__
+#define __PC_REGISTER_ADDRESSES_H__
+
+// $Id: pc_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pc_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pc_register_addresses.h
+/// \brief Symbolic addresses for the PC unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define PC_PCB_BASE 0x10010000
+#define PC_PFTH_MODEREG 0x100132a7
+#define PC_OCC_SPRC 0x100132ab
+#define PC_OCC_SPRD 0x100132ac
+#define PC_PFTH_THROT_REG 0x100132ad
+#define PC_DIRECT_CONTROLN(n) (PC_DIRECT_CONTROL0 + ((PC_DIRECT_CONTROL1 - PC_DIRECT_CONTROL0) * (n)))
+#define PC_DIRECT_CONTROL0 0x10013000
+#define PC_DIRECT_CONTROL1 0x10013010
+#define PC_DIRECT_CONTROL2 0x10013020
+#define PC_DIRECT_CONTROL3 0x10013030
+#define PC_DIRECT_CONTROL4 0x10013040
+#define PC_DIRECT_CONTROL5 0x10013050
+#define PC_DIRECT_CONTROL6 0x10013060
+#define PC_DIRECT_CONTROL7 0x10013070
+#define PC_RAS_MODEREGN(n) (PC_RAS_MODEREG0 + ((PC_RAS_MODEREG1 - PC_RAS_MODEREG0) * (n)))
+#define PC_RAS_MODEREG0 0x10013001
+#define PC_RAS_MODEREG1 0x10013011
+#define PC_RAS_MODEREG2 0x10013021
+#define PC_RAS_MODEREG3 0x10013031
+#define PC_RAS_MODEREG4 0x10013041
+#define PC_RAS_MODEREG5 0x10013051
+#define PC_RAS_MODEREG6 0x10013061
+#define PC_RAS_MODEREG7 0x10013071
+#define PC_RAS_STATUSN(n) (PC_RAS_STATUS0 + ((PC_RAS_STATUS1 - PC_RAS_STATUS0) * (n)))
+#define PC_RAS_STATUS0 0x10013002
+#define PC_RAS_STATUS1 0x10013012
+#define PC_RAS_STATUS2 0x10013022
+#define PC_RAS_STATUS3 0x10013032
+#define PC_RAS_STATUS4 0x10013042
+#define PC_RAS_STATUS5 0x10013052
+#define PC_RAS_STATUS6 0x10013062
+#define PC_RAS_STATUS7 0x10013072
+#define PC_POW_STATUSN(n) (PC_POW_STATUS0 + ((PC_POW_STATUS1 - PC_POW_STATUS0) * (n)))
+#define PC_POW_STATUS0 0x10013004
+#define PC_POW_STATUS1 0x10013014
+#define PC_POW_STATUS2 0x10013024
+#define PC_POW_STATUS3 0x10013034
+#define PC_POW_STATUS4 0x10013044
+#define PC_POW_STATUS5 0x10013054
+#define PC_POW_STATUS6 0x10013064
+#define PC_POW_STATUS7 0x10013074
+
+#endif // __PC_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/pcbs_firmware_registers.h b/src/ssx/pgp/registers/pcbs_firmware_registers.h
new file mode 100755
index 0000000..1d268a2
--- /dev/null
+++ b/src/ssx/pgp/registers/pcbs_firmware_registers.h
@@ -0,0 +1,2477 @@
+#ifndef __PCBS_FIRMWARE_REGISTERS_H__
+#define __PCBS_FIRMWARE_REGISTERS_H__
+
+// $Id: pcbs_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pcbs_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pcbs_firmware_registers.h
+/// \brief C register structs for the PCBS unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union pcbs_pmgp0_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pm_disable : 1;
+ uint64_t pmgp0_spare_bit1 : 1;
+ uint64_t tp_tc_restart_core_domain : 1;
+ uint64_t dpll_thold : 1;
+ uint64_t perv_thold : 1;
+ uint64_t cpm_cal_set_override_en : 1;
+ uint64_t cpm_cal_set_val : 1;
+ uint64_t pm_dpll_timer_ena : 1;
+ uint64_t dpll_lock_sense : 1;
+ uint64_t pmgp0_spare2 : 1;
+ uint64_t dpll_reset : 1;
+ uint64_t pmgp0_spare_bit11 : 1;
+ uint64_t dpll_testout_ctl : 8;
+ uint64_t tp_tc_cache2core_fence : 1;
+ uint64_t tp_tc_core2cache_fence : 1;
+ uint64_t tp_tc_pervasive_eco_fence : 1;
+ uint64_t chksw_hw257424_disable : 1;
+ uint64_t tp_clk_async_reset_dc : 3;
+ uint64_t tp_clkglm_sel_dc : 3;
+ uint64_t tp_clkglm_eco_sel_dc : 1;
+ uint64_t special_wkup_done : 1;
+ uint64_t tp_clkglm_core_sel_dc : 2;
+ uint64_t tp_clkglm_const_dc : 1;
+ uint64_t thold_timer_sel : 2;
+ uint64_t block_all_wakeup_sources : 1;
+ uint64_t tp_tc_dpll_testmode_dc : 1;
+ uint64_t pm_slv_winkle_fence : 1;
+ uint64_t l3_enable_switch : 1;
+ uint64_t tp_cplt_ivrm_refbypass_dc : 1;
+ uint64_t chksw_hw241939_disable : 1;
+ uint64_t chksw_hw273115_disable : 1;
+ uint64_t chksw_hw245103_disable : 1;
+ uint64_t chksw_hw257534_disable : 1;
+ uint64_t chksw_hw259509_enable : 1;
+ uint64_t pmgp0_spare3 : 1;
+ uint64_t wakeup_int_type : 2;
+ uint64_t dpll_lock : 1;
+ uint64_t special_wkup_all_sources_ored : 1;
+ uint64_t regular_wkup_available : 1;
+ uint64_t block_reg_wkup_sources : 1;
+ uint64_t _reserved0 : 10;
+#else
+ uint64_t _reserved0 : 10;
+ uint64_t block_reg_wkup_sources : 1;
+ uint64_t regular_wkup_available : 1;
+ uint64_t special_wkup_all_sources_ored : 1;
+ uint64_t dpll_lock : 1;
+ uint64_t wakeup_int_type : 2;
+ uint64_t pmgp0_spare3 : 1;
+ uint64_t chksw_hw259509_enable : 1;
+ uint64_t chksw_hw257534_disable : 1;
+ uint64_t chksw_hw245103_disable : 1;
+ uint64_t chksw_hw273115_disable : 1;
+ uint64_t chksw_hw241939_disable : 1;
+ uint64_t tp_cplt_ivrm_refbypass_dc : 1;
+ uint64_t l3_enable_switch : 1;
+ uint64_t pm_slv_winkle_fence : 1;
+ uint64_t tp_tc_dpll_testmode_dc : 1;
+ uint64_t block_all_wakeup_sources : 1;
+ uint64_t thold_timer_sel : 2;
+ uint64_t tp_clkglm_const_dc : 1;
+ uint64_t tp_clkglm_core_sel_dc : 2;
+ uint64_t special_wkup_done : 1;
+ uint64_t tp_clkglm_eco_sel_dc : 1;
+ uint64_t tp_clkglm_sel_dc : 3;
+ uint64_t tp_clk_async_reset_dc : 3;
+ uint64_t chksw_hw257424_disable : 1;
+ uint64_t tp_tc_pervasive_eco_fence : 1;
+ uint64_t tp_tc_core2cache_fence : 1;
+ uint64_t tp_tc_cache2core_fence : 1;
+ uint64_t dpll_testout_ctl : 8;
+ uint64_t pmgp0_spare_bit11 : 1;
+ uint64_t dpll_reset : 1;
+ uint64_t pmgp0_spare2 : 1;
+ uint64_t dpll_lock_sense : 1;
+ uint64_t pm_dpll_timer_ena : 1;
+ uint64_t cpm_cal_set_val : 1;
+ uint64_t cpm_cal_set_override_en : 1;
+ uint64_t perv_thold : 1;
+ uint64_t dpll_thold : 1;
+ uint64_t tp_tc_restart_core_domain : 1;
+ uint64_t pmgp0_spare_bit1 : 1;
+ uint64_t pm_disable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmgp0_reg_t;
+
+
+
+typedef union pcbs_pmgp0_reg_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pm_disable : 1;
+ uint64_t pmgp0_spare_bit1 : 1;
+ uint64_t tp_tc_restart_core_domain : 1;
+ uint64_t dpll_thold : 1;
+ uint64_t perv_thold : 1;
+ uint64_t cpm_cal_set_override_en : 1;
+ uint64_t cpm_cal_set_val : 1;
+ uint64_t pm_dpll_timer_ena : 1;
+ uint64_t dpll_lock_sense : 1;
+ uint64_t pmgp0_spare2 : 1;
+ uint64_t dpll_reset : 1;
+ uint64_t pmgp0_spare_bit11 : 1;
+ uint64_t dpll_testout_ctl : 8;
+ uint64_t tp_tc_cache2core_fence : 1;
+ uint64_t tp_tc_core2cache_fence : 1;
+ uint64_t tp_tc_pervasive_eco_fence : 1;
+ uint64_t chksw_hw257424_disable : 1;
+ uint64_t tp_clk_async_reset_dc : 3;
+ uint64_t tp_clkglm_sel_dc : 3;
+ uint64_t tp_clkglm_eco_sel_dc : 1;
+ uint64_t special_wkup_done : 1;
+ uint64_t tp_clkglm_core_sel_dc : 2;
+ uint64_t tp_clkglm_const_dc : 1;
+ uint64_t thold_timer_sel : 2;
+ uint64_t block_all_wakeup_sources : 1;
+ uint64_t tp_tc_dpll_testmode_dc : 1;
+ uint64_t pm_slv_winkle_fence : 1;
+ uint64_t l3_enable_switch : 1;
+ uint64_t tp_cplt_ivrm_refbypass_dc : 1;
+ uint64_t chksw_hw241939_disable : 1;
+ uint64_t chksw_hw273115_disable : 1;
+ uint64_t chksw_hw245103_disable : 1;
+ uint64_t chksw_hw257534_disable : 1;
+ uint64_t chksw_hw259509_enable : 1;
+ uint64_t pmgp0_spare3 : 1;
+ uint64_t wakeup_int_type : 2;
+ uint64_t dpll_lock : 1;
+ uint64_t special_wkup_all_sources_ored : 1;
+ uint64_t regular_wkup_available : 1;
+ uint64_t block_reg_wkup_sources : 1;
+ uint64_t _reserved0 : 10;
+#else
+ uint64_t _reserved0 : 10;
+ uint64_t block_reg_wkup_sources : 1;
+ uint64_t regular_wkup_available : 1;
+ uint64_t special_wkup_all_sources_ored : 1;
+ uint64_t dpll_lock : 1;
+ uint64_t wakeup_int_type : 2;
+ uint64_t pmgp0_spare3 : 1;
+ uint64_t chksw_hw259509_enable : 1;
+ uint64_t chksw_hw257534_disable : 1;
+ uint64_t chksw_hw245103_disable : 1;
+ uint64_t chksw_hw273115_disable : 1;
+ uint64_t chksw_hw241939_disable : 1;
+ uint64_t tp_cplt_ivrm_refbypass_dc : 1;
+ uint64_t l3_enable_switch : 1;
+ uint64_t pm_slv_winkle_fence : 1;
+ uint64_t tp_tc_dpll_testmode_dc : 1;
+ uint64_t block_all_wakeup_sources : 1;
+ uint64_t thold_timer_sel : 2;
+ uint64_t tp_clkglm_const_dc : 1;
+ uint64_t tp_clkglm_core_sel_dc : 2;
+ uint64_t special_wkup_done : 1;
+ uint64_t tp_clkglm_eco_sel_dc : 1;
+ uint64_t tp_clkglm_sel_dc : 3;
+ uint64_t tp_clk_async_reset_dc : 3;
+ uint64_t chksw_hw257424_disable : 1;
+ uint64_t tp_tc_pervasive_eco_fence : 1;
+ uint64_t tp_tc_core2cache_fence : 1;
+ uint64_t tp_tc_cache2core_fence : 1;
+ uint64_t dpll_testout_ctl : 8;
+ uint64_t pmgp0_spare_bit11 : 1;
+ uint64_t dpll_reset : 1;
+ uint64_t pmgp0_spare2 : 1;
+ uint64_t dpll_lock_sense : 1;
+ uint64_t pm_dpll_timer_ena : 1;
+ uint64_t cpm_cal_set_val : 1;
+ uint64_t cpm_cal_set_override_en : 1;
+ uint64_t perv_thold : 1;
+ uint64_t dpll_thold : 1;
+ uint64_t tp_tc_restart_core_domain : 1;
+ uint64_t pmgp0_spare_bit1 : 1;
+ uint64_t pm_disable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmgp0_reg_and_t;
+
+
+
+typedef union pcbs_pmgp0_reg_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pm_disable : 1;
+ uint64_t pmgp0_spare_bit1 : 1;
+ uint64_t tp_tc_restart_core_domain : 1;
+ uint64_t dpll_thold : 1;
+ uint64_t perv_thold : 1;
+ uint64_t cpm_cal_set_override_en : 1;
+ uint64_t cpm_cal_set_val : 1;
+ uint64_t pm_dpll_timer_ena : 1;
+ uint64_t dpll_lock_sense : 1;
+ uint64_t pmgp0_spare2 : 1;
+ uint64_t dpll_reset : 1;
+ uint64_t pmgp0_spare_bit11 : 1;
+ uint64_t dpll_testout_ctl : 8;
+ uint64_t tp_tc_cache2core_fence : 1;
+ uint64_t tp_tc_core2cache_fence : 1;
+ uint64_t tp_tc_pervasive_eco_fence : 1;
+ uint64_t chksw_hw257424_disable : 1;
+ uint64_t tp_clk_async_reset_dc : 3;
+ uint64_t tp_clkglm_sel_dc : 3;
+ uint64_t tp_clkglm_eco_sel_dc : 1;
+ uint64_t special_wkup_done : 1;
+ uint64_t tp_clkglm_core_sel_dc : 2;
+ uint64_t tp_clkglm_const_dc : 1;
+ uint64_t thold_timer_sel : 2;
+ uint64_t block_all_wakeup_sources : 1;
+ uint64_t tp_tc_dpll_testmode_dc : 1;
+ uint64_t pm_slv_winkle_fence : 1;
+ uint64_t l3_enable_switch : 1;
+ uint64_t tp_cplt_ivrm_refbypass_dc : 1;
+ uint64_t chksw_hw241939_disable : 1;
+ uint64_t chksw_hw273115_disable : 1;
+ uint64_t chksw_hw245103_disable : 1;
+ uint64_t chksw_hw257534_disable : 1;
+ uint64_t chksw_hw259509_enable : 1;
+ uint64_t pmgp0_spare3 : 1;
+ uint64_t wakeup_int_type : 2;
+ uint64_t dpll_lock : 1;
+ uint64_t special_wkup_all_sources_ored : 1;
+ uint64_t regular_wkup_available : 1;
+ uint64_t block_reg_wkup_sources : 1;
+ uint64_t _reserved0 : 10;
+#else
+ uint64_t _reserved0 : 10;
+ uint64_t block_reg_wkup_sources : 1;
+ uint64_t regular_wkup_available : 1;
+ uint64_t special_wkup_all_sources_ored : 1;
+ uint64_t dpll_lock : 1;
+ uint64_t wakeup_int_type : 2;
+ uint64_t pmgp0_spare3 : 1;
+ uint64_t chksw_hw259509_enable : 1;
+ uint64_t chksw_hw257534_disable : 1;
+ uint64_t chksw_hw245103_disable : 1;
+ uint64_t chksw_hw273115_disable : 1;
+ uint64_t chksw_hw241939_disable : 1;
+ uint64_t tp_cplt_ivrm_refbypass_dc : 1;
+ uint64_t l3_enable_switch : 1;
+ uint64_t pm_slv_winkle_fence : 1;
+ uint64_t tp_tc_dpll_testmode_dc : 1;
+ uint64_t block_all_wakeup_sources : 1;
+ uint64_t thold_timer_sel : 2;
+ uint64_t tp_clkglm_const_dc : 1;
+ uint64_t tp_clkglm_core_sel_dc : 2;
+ uint64_t special_wkup_done : 1;
+ uint64_t tp_clkglm_eco_sel_dc : 1;
+ uint64_t tp_clkglm_sel_dc : 3;
+ uint64_t tp_clk_async_reset_dc : 3;
+ uint64_t chksw_hw257424_disable : 1;
+ uint64_t tp_tc_pervasive_eco_fence : 1;
+ uint64_t tp_tc_core2cache_fence : 1;
+ uint64_t tp_tc_cache2core_fence : 1;
+ uint64_t dpll_testout_ctl : 8;
+ uint64_t pmgp0_spare_bit11 : 1;
+ uint64_t dpll_reset : 1;
+ uint64_t pmgp0_spare2 : 1;
+ uint64_t dpll_lock_sense : 1;
+ uint64_t pm_dpll_timer_ena : 1;
+ uint64_t cpm_cal_set_val : 1;
+ uint64_t cpm_cal_set_override_en : 1;
+ uint64_t perv_thold : 1;
+ uint64_t dpll_thold : 1;
+ uint64_t tp_tc_restart_core_domain : 1;
+ uint64_t pmgp0_spare_bit1 : 1;
+ uint64_t pm_disable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmgp0_reg_or_t;
+
+
+
+typedef union pcbs_pmgp1_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t sleep_power_down_en : 1;
+ uint64_t sleep_power_up_en : 1;
+ uint64_t sleep_power_off_sel : 1;
+ uint64_t winkle_power_down_en : 1;
+ uint64_t winkle_power_up_en : 1;
+ uint64_t winkle_power_off_sel : 1;
+ uint64_t oha_wkup_override_en : 1;
+ uint64_t oha_pm_wkup_override : 1;
+ uint64_t oha_spc_wkup_override : 1;
+ uint64_t endp_reset_pm_only : 1;
+ uint64_t dpll_freq_override_enable : 1;
+ uint64_t pm_spr_override_en : 1;
+ uint64_t force_safe_mode : 1;
+ uint64_t ivrm_safe_mode_en : 1;
+ uint64_t ivrm_safe_mode_force_active : 1;
+ uint64_t pmicr_latency_en : 1;
+ uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1;
+ uint64_t serialize_pfet_powerdown : 1;
+ uint64_t serialize_pfet_powerup : 1;
+ uint64_t disable_force_deep_to_fast_sleep : 1;
+ uint64_t disable_force_deep_to_fast_winkle : 1;
+ uint64_t _reserved0 : 43;
+#else
+ uint64_t _reserved0 : 43;
+ uint64_t disable_force_deep_to_fast_winkle : 1;
+ uint64_t disable_force_deep_to_fast_sleep : 1;
+ uint64_t serialize_pfet_powerup : 1;
+ uint64_t serialize_pfet_powerdown : 1;
+ uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1;
+ uint64_t pmicr_latency_en : 1;
+ uint64_t ivrm_safe_mode_force_active : 1;
+ uint64_t ivrm_safe_mode_en : 1;
+ uint64_t force_safe_mode : 1;
+ uint64_t pm_spr_override_en : 1;
+ uint64_t dpll_freq_override_enable : 1;
+ uint64_t endp_reset_pm_only : 1;
+ uint64_t oha_spc_wkup_override : 1;
+ uint64_t oha_pm_wkup_override : 1;
+ uint64_t oha_wkup_override_en : 1;
+ uint64_t winkle_power_off_sel : 1;
+ uint64_t winkle_power_up_en : 1;
+ uint64_t winkle_power_down_en : 1;
+ uint64_t sleep_power_off_sel : 1;
+ uint64_t sleep_power_up_en : 1;
+ uint64_t sleep_power_down_en : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmgp1_reg_t;
+
+
+
+typedef union pcbs_pmgp1_reg_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t sleep_power_down_en : 1;
+ uint64_t sleep_power_up_en : 1;
+ uint64_t sleep_power_off_sel : 1;
+ uint64_t winkle_power_down_en : 1;
+ uint64_t winkle_power_up_en : 1;
+ uint64_t winkle_power_off_sel : 1;
+ uint64_t oha_wkup_override_en : 1;
+ uint64_t oha_pm_wkup_override : 1;
+ uint64_t oha_spc_wkup_override : 1;
+ uint64_t endp_reset_pm_only : 1;
+ uint64_t dpll_freq_override_enable : 1;
+ uint64_t pm_spr_override_en : 1;
+ uint64_t force_safe_mode : 1;
+ uint64_t ivrm_safe_mode_en : 1;
+ uint64_t ivrm_safe_mode_force_active : 1;
+ uint64_t pmicr_latency_en : 1;
+ uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1;
+ uint64_t serialize_pfet_powerdown : 1;
+ uint64_t serialize_pfet_powerup : 1;
+ uint64_t disable_force_deep_to_fast_sleep : 1;
+ uint64_t disable_force_deep_to_fast_winkle : 1;
+ uint64_t _reserved0 : 43;
+#else
+ uint64_t _reserved0 : 43;
+ uint64_t disable_force_deep_to_fast_winkle : 1;
+ uint64_t disable_force_deep_to_fast_sleep : 1;
+ uint64_t serialize_pfet_powerup : 1;
+ uint64_t serialize_pfet_powerdown : 1;
+ uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1;
+ uint64_t pmicr_latency_en : 1;
+ uint64_t ivrm_safe_mode_force_active : 1;
+ uint64_t ivrm_safe_mode_en : 1;
+ uint64_t force_safe_mode : 1;
+ uint64_t pm_spr_override_en : 1;
+ uint64_t dpll_freq_override_enable : 1;
+ uint64_t endp_reset_pm_only : 1;
+ uint64_t oha_spc_wkup_override : 1;
+ uint64_t oha_pm_wkup_override : 1;
+ uint64_t oha_wkup_override_en : 1;
+ uint64_t winkle_power_off_sel : 1;
+ uint64_t winkle_power_up_en : 1;
+ uint64_t winkle_power_down_en : 1;
+ uint64_t sleep_power_off_sel : 1;
+ uint64_t sleep_power_up_en : 1;
+ uint64_t sleep_power_down_en : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmgp1_reg_and_t;
+
+
+
+typedef union pcbs_pmgp1_reg_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t sleep_power_down_en : 1;
+ uint64_t sleep_power_up_en : 1;
+ uint64_t sleep_power_off_sel : 1;
+ uint64_t winkle_power_down_en : 1;
+ uint64_t winkle_power_up_en : 1;
+ uint64_t winkle_power_off_sel : 1;
+ uint64_t oha_wkup_override_en : 1;
+ uint64_t oha_pm_wkup_override : 1;
+ uint64_t oha_spc_wkup_override : 1;
+ uint64_t endp_reset_pm_only : 1;
+ uint64_t dpll_freq_override_enable : 1;
+ uint64_t pm_spr_override_en : 1;
+ uint64_t force_safe_mode : 1;
+ uint64_t ivrm_safe_mode_en : 1;
+ uint64_t ivrm_safe_mode_force_active : 1;
+ uint64_t pmicr_latency_en : 1;
+ uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1;
+ uint64_t serialize_pfet_powerdown : 1;
+ uint64_t serialize_pfet_powerup : 1;
+ uint64_t disable_force_deep_to_fast_sleep : 1;
+ uint64_t disable_force_deep_to_fast_winkle : 1;
+ uint64_t _reserved0 : 43;
+#else
+ uint64_t _reserved0 : 43;
+ uint64_t disable_force_deep_to_fast_winkle : 1;
+ uint64_t disable_force_deep_to_fast_sleep : 1;
+ uint64_t serialize_pfet_powerup : 1;
+ uint64_t serialize_pfet_powerdown : 1;
+ uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1;
+ uint64_t pmicr_latency_en : 1;
+ uint64_t ivrm_safe_mode_force_active : 1;
+ uint64_t ivrm_safe_mode_en : 1;
+ uint64_t force_safe_mode : 1;
+ uint64_t pm_spr_override_en : 1;
+ uint64_t dpll_freq_override_enable : 1;
+ uint64_t endp_reset_pm_only : 1;
+ uint64_t oha_spc_wkup_override : 1;
+ uint64_t oha_pm_wkup_override : 1;
+ uint64_t oha_wkup_override_en : 1;
+ uint64_t winkle_power_off_sel : 1;
+ uint64_t winkle_power_up_en : 1;
+ uint64_t winkle_power_down_en : 1;
+ uint64_t sleep_power_off_sel : 1;
+ uint64_t sleep_power_up_en : 1;
+ uint64_t sleep_power_down_en : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmgp1_reg_or_t;
+
+
+
+typedef union pcbs_pfvddcntlstat_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t core_vdd_pfet_force_state : 2;
+ uint64_t eco_vdd_pfet_force_state : 2;
+ uint64_t core_vdd_pfet_val_override : 1;
+ uint64_t core_vdd_pfet_sel_override : 1;
+ uint64_t eco_vdd_pfet_val_override : 1;
+ uint64_t eco_vdd_pfet_sel_override : 1;
+ uint64_t core_vdd_pfet_enable_regulation_finger : 1;
+ uint64_t eco_vdd_pfet_enable_regulation_finger : 1;
+ uint64_t core_vdd_pfet_enable_value : 12;
+ uint64_t core_vdd_pfet_sel_value : 4;
+ uint64_t eco_vdd_pfet_enable_value : 12;
+ uint64_t eco_vdd_pfet_sel_value : 4;
+ uint64_t core_vdd_pg_state : 4;
+ uint64_t core_vdd_pg_sel : 4;
+ uint64_t eco_vdd_pg_state : 4;
+ uint64_t eco_vdd_pg_sel : 4;
+ uint64_t _reserved0 : 6;
+#else
+ uint64_t _reserved0 : 6;
+ uint64_t eco_vdd_pg_sel : 4;
+ uint64_t eco_vdd_pg_state : 4;
+ uint64_t core_vdd_pg_sel : 4;
+ uint64_t core_vdd_pg_state : 4;
+ uint64_t eco_vdd_pfet_sel_value : 4;
+ uint64_t eco_vdd_pfet_enable_value : 12;
+ uint64_t core_vdd_pfet_sel_value : 4;
+ uint64_t core_vdd_pfet_enable_value : 12;
+ uint64_t eco_vdd_pfet_enable_regulation_finger : 1;
+ uint64_t core_vdd_pfet_enable_regulation_finger : 1;
+ uint64_t eco_vdd_pfet_sel_override : 1;
+ uint64_t eco_vdd_pfet_val_override : 1;
+ uint64_t core_vdd_pfet_sel_override : 1;
+ uint64_t core_vdd_pfet_val_override : 1;
+ uint64_t eco_vdd_pfet_force_state : 2;
+ uint64_t core_vdd_pfet_force_state : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pfvddcntlstat_reg_t;
+
+
+
+typedef union pcbs_pfvcscntlstat_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t core_vcs_pfet_force_state : 2;
+ uint64_t eco_vcs_pfet_force_state : 2;
+ uint64_t core_vcs_pfet_val_override : 1;
+ uint64_t core_vcs_pfet_sel_override : 1;
+ uint64_t eco_vcs_pfet_val_override : 1;
+ uint64_t eco_vcs_pfet_sel_override : 1;
+ uint64_t core_vcs_pfet_enable_regulation_finger : 1;
+ uint64_t eco_vcs_pfet_enable_regulation_finger : 1;
+ uint64_t core_vcs_pfet_enable_value : 12;
+ uint64_t core_vcs_pfet_sel_value : 4;
+ uint64_t eco_vcs_pfet_enable_value : 12;
+ uint64_t eco_vcs_pfet_sel_value : 4;
+ uint64_t core_vcs_pg_state : 4;
+ uint64_t core_vcs_pg_sel : 4;
+ uint64_t eco_vcs_pg_state : 4;
+ uint64_t eco_vcs_pg_sel : 4;
+ uint64_t _reserved0 : 6;
+#else
+ uint64_t _reserved0 : 6;
+ uint64_t eco_vcs_pg_sel : 4;
+ uint64_t eco_vcs_pg_state : 4;
+ uint64_t core_vcs_pg_sel : 4;
+ uint64_t core_vcs_pg_state : 4;
+ uint64_t eco_vcs_pfet_sel_value : 4;
+ uint64_t eco_vcs_pfet_enable_value : 12;
+ uint64_t core_vcs_pfet_sel_value : 4;
+ uint64_t core_vcs_pfet_enable_value : 12;
+ uint64_t eco_vcs_pfet_enable_regulation_finger : 1;
+ uint64_t core_vcs_pfet_enable_regulation_finger : 1;
+ uint64_t eco_vcs_pfet_sel_override : 1;
+ uint64_t eco_vcs_pfet_val_override : 1;
+ uint64_t core_vcs_pfet_sel_override : 1;
+ uint64_t core_vcs_pfet_val_override : 1;
+ uint64_t eco_vcs_pfet_force_state : 2;
+ uint64_t core_vcs_pfet_force_state : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pfvcscntlstat_reg_t;
+
+
+
+typedef union pcbs_pfsense_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t tp_core_vdd_pfet_enable_sense : 12;
+ uint64_t tp_eco_vdd_pfet_enable_sense : 12;
+ uint64_t tp_core_vcs_pfet_enable_sense : 12;
+ uint64_t tp_eco_vcs_pfet_enable_sense : 12;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t tp_eco_vcs_pfet_enable_sense : 12;
+ uint64_t tp_core_vcs_pfet_enable_sense : 12;
+ uint64_t tp_eco_vdd_pfet_enable_sense : 12;
+ uint64_t tp_core_vdd_pfet_enable_sense : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pfsense_reg_t;
+
+
+
+typedef union pcbs_pmerrsum_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pm_error : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t pm_error : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmerrsum_reg_t;
+
+
+
+typedef union pcbs_pmerr_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pcbs_sleep_entry_notify_pmc_hang_err : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_assist_hang_err : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_err : 1;
+ uint64_t pcbs_sleep_exit_invoke_pore_err : 1;
+ uint64_t pcbs_winkle_entry_notify_pmc_err : 1;
+ uint64_t pcbs_winkle_entry_send_int_assist_err : 1;
+ uint64_t pcbs_winkle_exit_notify_pmc_err : 1;
+ uint64_t pcbs_wait_dpll_lock_err : 1;
+ uint64_t pcbs_spare8_err : 1;
+ uint64_t pcbs_winkle_exit_send_int_assist_err : 1;
+ uint64_t pcbs_winkle_exit_send_int_powup_assist_err : 1;
+ uint64_t pcbs_write_fsm_goto_reg_in_invalid_state_err : 1;
+ uint64_t pcbs_write_pmgp0_in_invalid_state_err : 1;
+ uint64_t pcbs_freq_overflow_in_pstate_mode_err : 1;
+ uint64_t pcbs_eco_rs_bypass_confusion_err : 1;
+ uint64_t pcbs_core_rs_bypass_confusion_err : 1;
+ uint64_t pcbs_read_lpst_in_pstate_mode_err : 1;
+ uint64_t pcbs_lpst_read_corr_err : 1;
+ uint64_t pcbs_lpst_read_uncorr_err : 1;
+ uint64_t pcbs_pfet_strength_overflow_err : 1;
+ uint64_t pcbs_vds_lookup_err : 1;
+ uint64_t pcbs_idle_interrupt_timeout_err : 1;
+ uint64_t pcbs_pstate_interrupt_timeout_err : 1;
+ uint64_t pcbs_global_actual_sync_interrupt_timeout_err : 1;
+ uint64_t pcbs_pmax_sync_interrupt_timeout_err : 1;
+ uint64_t pcbs_global_actual_pstate_protocol_err : 1;
+ uint64_t pcbs_pmax_protocol_err : 1;
+ uint64_t pcbs_ivrm_gross_or_fine_err : 1;
+ uint64_t pcbs_ivrm_range_err : 1;
+ uint64_t pcbs_dpll_cpm_fmin_err : 1;
+ uint64_t pcbs_dpll_dco_full_err : 1;
+ uint64_t pcbs_dpll_dco_empty_err : 1;
+ uint64_t pcbs_dpll_int_err : 1;
+ uint64_t pcbs_fmin_and_not_cpmbit_err : 1;
+ uint64_t pcbs_dpll_faster_than_fmax_plus_delta1_err : 1;
+ uint64_t pcbs_dpll_slower_than_fmin_minus_delta2_err : 1;
+ uint64_t pcbs_resclk_csb_instr_vector_chg_in_invalid_state_err : 1;
+ uint64_t pcbs_reslkc_band_boundary_chg_in_invalid_state_err : 1;
+ uint64_t pcbs_occ_heartbeat_loss_err : 1;
+ uint64_t pcbs_spare39_err : 1;
+ uint64_t pcbs_spare40_err : 1;
+ uint64_t pcbs_spare41_err : 1;
+ uint64_t pcbs_spare42_err : 1;
+ uint64_t _reserved0 : 21;
+#else
+ uint64_t _reserved0 : 21;
+ uint64_t pcbs_spare42_err : 1;
+ uint64_t pcbs_spare41_err : 1;
+ uint64_t pcbs_spare40_err : 1;
+ uint64_t pcbs_spare39_err : 1;
+ uint64_t pcbs_occ_heartbeat_loss_err : 1;
+ uint64_t pcbs_reslkc_band_boundary_chg_in_invalid_state_err : 1;
+ uint64_t pcbs_resclk_csb_instr_vector_chg_in_invalid_state_err : 1;
+ uint64_t pcbs_dpll_slower_than_fmin_minus_delta2_err : 1;
+ uint64_t pcbs_dpll_faster_than_fmax_plus_delta1_err : 1;
+ uint64_t pcbs_fmin_and_not_cpmbit_err : 1;
+ uint64_t pcbs_dpll_int_err : 1;
+ uint64_t pcbs_dpll_dco_empty_err : 1;
+ uint64_t pcbs_dpll_dco_full_err : 1;
+ uint64_t pcbs_dpll_cpm_fmin_err : 1;
+ uint64_t pcbs_ivrm_range_err : 1;
+ uint64_t pcbs_ivrm_gross_or_fine_err : 1;
+ uint64_t pcbs_pmax_protocol_err : 1;
+ uint64_t pcbs_global_actual_pstate_protocol_err : 1;
+ uint64_t pcbs_pmax_sync_interrupt_timeout_err : 1;
+ uint64_t pcbs_global_actual_sync_interrupt_timeout_err : 1;
+ uint64_t pcbs_pstate_interrupt_timeout_err : 1;
+ uint64_t pcbs_idle_interrupt_timeout_err : 1;
+ uint64_t pcbs_vds_lookup_err : 1;
+ uint64_t pcbs_pfet_strength_overflow_err : 1;
+ uint64_t pcbs_lpst_read_uncorr_err : 1;
+ uint64_t pcbs_lpst_read_corr_err : 1;
+ uint64_t pcbs_read_lpst_in_pstate_mode_err : 1;
+ uint64_t pcbs_core_rs_bypass_confusion_err : 1;
+ uint64_t pcbs_eco_rs_bypass_confusion_err : 1;
+ uint64_t pcbs_freq_overflow_in_pstate_mode_err : 1;
+ uint64_t pcbs_write_pmgp0_in_invalid_state_err : 1;
+ uint64_t pcbs_write_fsm_goto_reg_in_invalid_state_err : 1;
+ uint64_t pcbs_winkle_exit_send_int_powup_assist_err : 1;
+ uint64_t pcbs_winkle_exit_send_int_assist_err : 1;
+ uint64_t pcbs_spare8_err : 1;
+ uint64_t pcbs_wait_dpll_lock_err : 1;
+ uint64_t pcbs_winkle_exit_notify_pmc_err : 1;
+ uint64_t pcbs_winkle_entry_send_int_assist_err : 1;
+ uint64_t pcbs_winkle_entry_notify_pmc_err : 1;
+ uint64_t pcbs_sleep_exit_invoke_pore_err : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_err : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_assist_hang_err : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_hang_err : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmerr_reg_t;
+
+
+
+typedef union pcbs_pmerrmask_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pcbs_sleep_entry_notify_pmc_hang_err_mask : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_assist_hang_err_mask : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_err_mask : 1;
+ uint64_t pcbs_sleep_exit_invoke_pore_err_mask : 1;
+ uint64_t pcbs_winkle_entry_notify_pmc_err_mask : 1;
+ uint64_t pcbs_winkle_entry_send_int_assist_err_mask : 1;
+ uint64_t pcbs_winkle_exit_notify_pmc_err_mask : 1;
+ uint64_t pcbs_wait_dpll_lock_err_mask : 1;
+ uint64_t pcbs_spare8_err_mask : 1;
+ uint64_t pcbs_winkle_exit_send_int_assist_err_mask : 1;
+ uint64_t pcbs_winkle_exit_send_int_powup_assist_err_mask : 1;
+ uint64_t pcbs_write_fsm_goto_reg_in_invalid_state_err_mask : 1;
+ uint64_t pcbs_write_pmgp0_in_invalid_state_err_mask : 1;
+ uint64_t pcbs_freq_overflow_in_pstate_mode_err_mask : 1;
+ uint64_t pcbs_eco_rs_bypass_confusion_err_mask : 1;
+ uint64_t pcbs_core_rs_bypass_confusion_err_mask : 1;
+ uint64_t pcbs_read_lpst_in_pstate_mode_err_mask : 1;
+ uint64_t pcbs_lpst_read_corr_err_mask : 1;
+ uint64_t pcbs_lpst_read_uncorr_err_mask : 1;
+ uint64_t pcbs_pfet_strength_overflow_err_mask : 1;
+ uint64_t pcbs_vds_lookup_err_mask : 1;
+ uint64_t pcbs_idle_interrupt_timeout_err_mask : 1;
+ uint64_t pcbs_pstate_interrupt_timeout_err_mask : 1;
+ uint64_t pcbs_global_actual_sync_interrupt_timeout_err_mask : 1;
+ uint64_t pcbs_pmax_sync_interrupt_timeout_err_mask : 1;
+ uint64_t pcbs_global_actual_pstate_protocol_err_mask : 1;
+ uint64_t pcbs_pmax_protocol_err_mask : 1;
+ uint64_t pcbs_ivrm_gross_or_fine_err_mask : 1;
+ uint64_t pcbs_ivrm_range_err_mask : 1;
+ uint64_t pcbs_dpll_cpm_fmin_err_mask : 1;
+ uint64_t pcbs_dpll_dco_full_err_mask : 1;
+ uint64_t pcbs_dpll_dco_empty_err_mask : 1;
+ uint64_t pcbs_dpll_int_err_mask : 1;
+ uint64_t pcbs_fmin_and_not_cpmbit_err_mask : 1;
+ uint64_t pcbs_dpll_faster_than_fmax_plus_delta1_err_mask : 1;
+ uint64_t pcbs_dpll_slower_than_fmin_minus_delta2_err_mask : 1;
+ uint64_t pcbs_resclk_csb_instr_vector_chg_in_invalid_state_err_mask : 1;
+ uint64_t pcbs_reslkc_band_boundary_chg_in_invalid_state_err_mask : 1;
+ uint64_t pcbs_occ_heartbeat_loss_err_mask : 1;
+ uint64_t pcbs_spare39_err_mask : 1;
+ uint64_t pcbs_spare40_err_mask : 1;
+ uint64_t pcbs_spare41_err_mask : 1;
+ uint64_t pcbs_spare42_err_mask : 1;
+ uint64_t _reserved0 : 21;
+#else
+ uint64_t _reserved0 : 21;
+ uint64_t pcbs_spare42_err_mask : 1;
+ uint64_t pcbs_spare41_err_mask : 1;
+ uint64_t pcbs_spare40_err_mask : 1;
+ uint64_t pcbs_spare39_err_mask : 1;
+ uint64_t pcbs_occ_heartbeat_loss_err_mask : 1;
+ uint64_t pcbs_reslkc_band_boundary_chg_in_invalid_state_err_mask : 1;
+ uint64_t pcbs_resclk_csb_instr_vector_chg_in_invalid_state_err_mask : 1;
+ uint64_t pcbs_dpll_slower_than_fmin_minus_delta2_err_mask : 1;
+ uint64_t pcbs_dpll_faster_than_fmax_plus_delta1_err_mask : 1;
+ uint64_t pcbs_fmin_and_not_cpmbit_err_mask : 1;
+ uint64_t pcbs_dpll_int_err_mask : 1;
+ uint64_t pcbs_dpll_dco_empty_err_mask : 1;
+ uint64_t pcbs_dpll_dco_full_err_mask : 1;
+ uint64_t pcbs_dpll_cpm_fmin_err_mask : 1;
+ uint64_t pcbs_ivrm_range_err_mask : 1;
+ uint64_t pcbs_ivrm_gross_or_fine_err_mask : 1;
+ uint64_t pcbs_pmax_protocol_err_mask : 1;
+ uint64_t pcbs_global_actual_pstate_protocol_err_mask : 1;
+ uint64_t pcbs_pmax_sync_interrupt_timeout_err_mask : 1;
+ uint64_t pcbs_global_actual_sync_interrupt_timeout_err_mask : 1;
+ uint64_t pcbs_pstate_interrupt_timeout_err_mask : 1;
+ uint64_t pcbs_idle_interrupt_timeout_err_mask : 1;
+ uint64_t pcbs_vds_lookup_err_mask : 1;
+ uint64_t pcbs_pfet_strength_overflow_err_mask : 1;
+ uint64_t pcbs_lpst_read_uncorr_err_mask : 1;
+ uint64_t pcbs_lpst_read_corr_err_mask : 1;
+ uint64_t pcbs_read_lpst_in_pstate_mode_err_mask : 1;
+ uint64_t pcbs_core_rs_bypass_confusion_err_mask : 1;
+ uint64_t pcbs_eco_rs_bypass_confusion_err_mask : 1;
+ uint64_t pcbs_freq_overflow_in_pstate_mode_err_mask : 1;
+ uint64_t pcbs_write_pmgp0_in_invalid_state_err_mask : 1;
+ uint64_t pcbs_write_fsm_goto_reg_in_invalid_state_err_mask : 1;
+ uint64_t pcbs_winkle_exit_send_int_powup_assist_err_mask : 1;
+ uint64_t pcbs_winkle_exit_send_int_assist_err_mask : 1;
+ uint64_t pcbs_spare8_err_mask : 1;
+ uint64_t pcbs_wait_dpll_lock_err_mask : 1;
+ uint64_t pcbs_winkle_exit_notify_pmc_err_mask : 1;
+ uint64_t pcbs_winkle_entry_send_int_assist_err_mask : 1;
+ uint64_t pcbs_winkle_entry_notify_pmc_err_mask : 1;
+ uint64_t pcbs_sleep_exit_invoke_pore_err_mask : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_err_mask : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_assist_hang_err_mask : 1;
+ uint64_t pcbs_sleep_entry_notify_pmc_hang_err_mask : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmerrmask_reg_t;
+
+
+
+typedef union pcbs_pmspcwkupfsp_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t fsp_special_wakeup : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t fsp_special_wakeup : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmspcwkupfsp_reg_t;
+
+
+
+typedef union pcbs_pmspcwkupocc_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_special_wakeup : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t occ_special_wakeup : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmspcwkupocc_reg_t;
+
+
+
+typedef union pcbs_pmspcwkupphyp_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t phyp_special_wakeup : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t phyp_special_wakeup : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmspcwkupphyp_reg_t;
+
+
+
+typedef union pcbs_pmstatehistphyp_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t phyp_pm_state : 3;
+ uint64_t phyp_past_core_instruct_stop : 1;
+ uint64_t phyp_past_core_clk_stop : 1;
+ uint64_t phyp_past_core_pwr_off : 1;
+ uint64_t phyp_past_eco_clk_stop : 1;
+ uint64_t phyp_past_eco_pwr_off : 1;
+ uint64_t _reserved0 : 56;
+#else
+ uint64_t _reserved0 : 56;
+ uint64_t phyp_past_eco_pwr_off : 1;
+ uint64_t phyp_past_eco_clk_stop : 1;
+ uint64_t phyp_past_core_pwr_off : 1;
+ uint64_t phyp_past_core_clk_stop : 1;
+ uint64_t phyp_past_core_instruct_stop : 1;
+ uint64_t phyp_pm_state : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmstatehistphyp_reg_t;
+
+
+
+typedef union pcbs_pmstatehistfsp_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t fsp_pm_state : 3;
+ uint64_t fsp_past_core_instruct_stop : 1;
+ uint64_t fsp_past_core_clk_stop : 1;
+ uint64_t fsp_past_core_pwr_off : 1;
+ uint64_t fsp_past_eco_clk_stop : 1;
+ uint64_t fsp_past_eco_pwr_off : 1;
+ uint64_t _reserved0 : 56;
+#else
+ uint64_t _reserved0 : 56;
+ uint64_t fsp_past_eco_pwr_off : 1;
+ uint64_t fsp_past_eco_clk_stop : 1;
+ uint64_t fsp_past_core_pwr_off : 1;
+ uint64_t fsp_past_core_clk_stop : 1;
+ uint64_t fsp_past_core_instruct_stop : 1;
+ uint64_t fsp_pm_state : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmstatehistfsp_reg_t;
+
+
+
+typedef union pcbs_pmstatehistocc_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_pm_state : 3;
+ uint64_t occ_past_core_instruct_stop : 1;
+ uint64_t occ_past_core_clk_stop : 1;
+ uint64_t occ_past_core_pwr_off : 1;
+ uint64_t occ_past_eco_clk_stop : 1;
+ uint64_t occ_past_eco_pwr_off : 1;
+ uint64_t _reserved0 : 56;
+#else
+ uint64_t _reserved0 : 56;
+ uint64_t occ_past_eco_pwr_off : 1;
+ uint64_t occ_past_eco_clk_stop : 1;
+ uint64_t occ_past_core_pwr_off : 1;
+ uint64_t occ_past_core_clk_stop : 1;
+ uint64_t occ_past_core_instruct_stop : 1;
+ uint64_t occ_pm_state : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmstatehistocc_reg_t;
+
+
+
+typedef union pcbs_pmstatehistperf_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t perf_pm_state : 3;
+ uint64_t perf_past_core_instruct_stop : 1;
+ uint64_t perf_past_core_clk_stop : 1;
+ uint64_t perf_past_core_pwr_off : 1;
+ uint64_t perf_past_eco_clk_stop : 1;
+ uint64_t perf_past_eco_pwr_off : 1;
+ uint64_t _reserved0 : 56;
+#else
+ uint64_t _reserved0 : 56;
+ uint64_t perf_past_eco_pwr_off : 1;
+ uint64_t perf_past_eco_clk_stop : 1;
+ uint64_t perf_past_core_pwr_off : 1;
+ uint64_t perf_past_core_clk_stop : 1;
+ uint64_t perf_past_core_instruct_stop : 1;
+ uint64_t perf_pm_state : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmstatehistperf_reg_t;
+
+
+
+typedef union pcbs_idlefsmgotocmd_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t idle_fsm_goto_cmd : 2;
+ uint64_t babystp_trigger_sleep_entry : 1;
+ uint64_t babystp_trigger_winkle_entry : 1;
+ uint64_t babystp_trigger_wakeup : 1;
+ uint64_t _reserved0 : 59;
+#else
+ uint64_t _reserved0 : 59;
+ uint64_t babystp_trigger_wakeup : 1;
+ uint64_t babystp_trigger_winkle_entry : 1;
+ uint64_t babystp_trigger_sleep_entry : 1;
+ uint64_t idle_fsm_goto_cmd : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_idlefsmgotocmd_reg_t;
+
+
+
+typedef union pcbs_corepfpudly_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t core_powup_dly0 : 4;
+ uint64_t core_powup_dly1 : 4;
+ uint64_t core_power_up_delay_sel : 12;
+ uint64_t _reserved0 : 44;
+#else
+ uint64_t _reserved0 : 44;
+ uint64_t core_power_up_delay_sel : 12;
+ uint64_t core_powup_dly1 : 4;
+ uint64_t core_powup_dly0 : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_corepfpudly_reg_t;
+
+
+
+typedef union pcbs_corepfpddly_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t core_powdn_dly0 : 4;
+ uint64_t core_powdn_dly1 : 4;
+ uint64_t core_power_dn_delay_sel : 12;
+ uint64_t _reserved0 : 44;
+#else
+ uint64_t _reserved0 : 44;
+ uint64_t core_power_dn_delay_sel : 12;
+ uint64_t core_powdn_dly1 : 4;
+ uint64_t core_powdn_dly0 : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_corepfpddly_reg_t;
+
+
+
+typedef union pcbs_corepfvret_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t core_vret_sel : 4;
+ uint64_t core_voff_sel : 4;
+ uint64_t _reserved0 : 56;
+#else
+ uint64_t _reserved0 : 56;
+ uint64_t core_voff_sel : 4;
+ uint64_t core_vret_sel : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_corepfvret_reg_t;
+
+
+
+typedef union pcbs_ecopfpudly_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t eco_powup_dly0 : 4;
+ uint64_t eco_powup_dly1 : 4;
+ uint64_t eco_power_up_delay_sel : 12;
+ uint64_t _reserved0 : 44;
+#else
+ uint64_t _reserved0 : 44;
+ uint64_t eco_power_up_delay_sel : 12;
+ uint64_t eco_powup_dly1 : 4;
+ uint64_t eco_powup_dly0 : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_ecopfpudly_reg_t;
+
+
+
+typedef union pcbs_ecopfpddly_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t eco_powdn_dly0 : 4;
+ uint64_t eco_powdn_dly1 : 4;
+ uint64_t eco_power_dn_delay_sel : 12;
+ uint64_t _reserved0 : 44;
+#else
+ uint64_t _reserved0 : 44;
+ uint64_t eco_power_dn_delay_sel : 12;
+ uint64_t eco_powdn_dly1 : 4;
+ uint64_t eco_powdn_dly0 : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_ecopfpddly_reg_t;
+
+
+
+typedef union pcbs_ecopfvret_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t eco_vret_sel : 4;
+ uint64_t eco_voff_sel : 4;
+ uint64_t _reserved0 : 56;
+#else
+ uint64_t _reserved0 : 56;
+ uint64_t eco_voff_sel : 4;
+ uint64_t eco_vret_sel : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_ecopfvret_reg_t;
+
+
+
+typedef union pcbs_freq_ctrl_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dpll_fmin : 9;
+ uint64_t dpll_fmax : 9;
+ uint64_t dpll_fmax_bias : 4;
+ uint64_t frequ_at_pstate0 : 9;
+ uint64_t _reserved0 : 33;
+#else
+ uint64_t _reserved0 : 33;
+ uint64_t frequ_at_pstate0 : 9;
+ uint64_t dpll_fmax_bias : 4;
+ uint64_t dpll_fmax : 9;
+ uint64_t dpll_fmin : 9;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_freq_ctrl_reg_t;
+
+
+
+typedef union pcbs_dpll_cpm_parm_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t lf_slewratexpi : 8;
+ uint64_t lf_use_cpmxpi : 1;
+ uint64_t ff_use_cpmxpi : 1;
+ uint64_t cpm_filter_enable : 1;
+ uint64_t ff_bypassxpi : 1;
+ uint64_t dco_override : 1;
+ uint64_t dco_incr : 1;
+ uint64_t dco_decr : 1;
+ uint64_t dpll_lock_timer_replacement_value : 9;
+ uint64_t pre_vret_pstate : 8;
+ uint64_t override_pcbs_dpll_synchronizer : 1;
+ uint64_t dpll_char_delta1 : 4;
+ uint64_t dpll_char_delta2 : 4;
+ uint64_t _reserved0 : 23;
+#else
+ uint64_t _reserved0 : 23;
+ uint64_t dpll_char_delta2 : 4;
+ uint64_t dpll_char_delta1 : 4;
+ uint64_t override_pcbs_dpll_synchronizer : 1;
+ uint64_t pre_vret_pstate : 8;
+ uint64_t dpll_lock_timer_replacement_value : 9;
+ uint64_t dco_decr : 1;
+ uint64_t dco_incr : 1;
+ uint64_t dco_override : 1;
+ uint64_t ff_bypassxpi : 1;
+ uint64_t cpm_filter_enable : 1;
+ uint64_t ff_use_cpmxpi : 1;
+ uint64_t lf_use_cpmxpi : 1;
+ uint64_t lf_slewratexpi : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_dpll_cpm_parm_reg_t;
+
+
+
+typedef union pcbs_power_management_status_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ int64_t global_pstate_actual : 8;
+ int64_t local_pstate_actual : 8;
+ int64_t pv_min : 8;
+ int64_t pvf_max : 8;
+ uint64_t spr_em_disabled : 1;
+ uint64_t psafe_mode_active : 1;
+ uint64_t ivrm_safe_mode_active : 1;
+ uint64_t ivrm_enable : 1;
+ uint64_t all_fsms_in_safe_state : 1;
+ uint64_t pmsr_spares : 4;
+ uint64_t _reserved0 : 23;
+#else
+ uint64_t _reserved0 : 23;
+ uint64_t pmsr_spares : 4;
+ uint64_t all_fsms_in_safe_state : 1;
+ uint64_t ivrm_enable : 1;
+ uint64_t ivrm_safe_mode_active : 1;
+ uint64_t psafe_mode_active : 1;
+ uint64_t spr_em_disabled : 1;
+ int64_t pvf_max : 8;
+ int64_t pv_min : 8;
+ int64_t local_pstate_actual : 8;
+ int64_t global_pstate_actual : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_power_management_status_reg_t;
+
+
+
+typedef union pcbs_ivrm_control_status_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivrm_fsm_enable : 1;
+ uint64_t use_ivrm_for_vret : 1;
+ uint64_t binsearch_cal_ena : 1;
+ uint64_t pvref_en : 1;
+ uint64_t ivrm_core_vdd_bypass_b : 1;
+ uint64_t ivrm_core_vdd_poweron : 1;
+ uint64_t ivrm_core_vcs_bypass_b : 1;
+ uint64_t ivrm_core_vcs_poweron : 1;
+ uint64_t ivrm_eco_vdd_bypass_b : 1;
+ uint64_t ivrm_eco_vdd_poweron : 1;
+ uint64_t ivrm_eco_vcs_bypass_b : 1;
+ uint64_t ivrm_eco_vcs_poweron : 1;
+ uint64_t ivrm_vret_vdd : 7;
+ uint64_t ivrm_vret_vcs : 7;
+ uint64_t ivrm_vret_core_vdd_pfet_strength : 5;
+ uint64_t ivrm_vret_core_vcs_pfet_strength : 5;
+ uint64_t ivrm_vret_eco_vdd_pfet_strength : 5;
+ uint64_t ivrm_vret_eco_vcs_pfet_strength : 5;
+ uint64_t pvref_fail : 1;
+ uint64_t ivrm_pref_error_gross : 1;
+ uint64_t ivrm_pref_error_fine : 1;
+ uint64_t ivrm_core_vdd_range_hi : 1;
+ uint64_t ivrm_core_vdd_range_lo : 1;
+ uint64_t ivrm_eco_vdd_range_hi : 1;
+ uint64_t ivrm_eco_vdd_range_lo : 1;
+ uint64_t ivrm_core_vcs_range_hi : 1;
+ uint64_t ivrm_core_vcs_range_lo : 1;
+ uint64_t ivrm_eco_vcs_range_hi : 1;
+ uint64_t ivrm_eco_vcs_range_lo : 1;
+ uint64_t binsearch_cal_done : 1;
+ uint64_t ivrm_core_vdd_pfet_low_vout : 1;
+ uint64_t ivrm_core_vcs_pfet_low_vout : 1;
+ uint64_t ivrm_eco_vdd_pfet_low_vout : 1;
+ uint64_t ivrm_eco_vcs_pfet_low_vout : 1;
+ uint64_t ivrm_power_down_disable : 1;
+ uint64_t _reserved0 : 1;
+#else
+ uint64_t _reserved0 : 1;
+ uint64_t ivrm_power_down_disable : 1;
+ uint64_t ivrm_eco_vcs_pfet_low_vout : 1;
+ uint64_t ivrm_eco_vdd_pfet_low_vout : 1;
+ uint64_t ivrm_core_vcs_pfet_low_vout : 1;
+ uint64_t ivrm_core_vdd_pfet_low_vout : 1;
+ uint64_t binsearch_cal_done : 1;
+ uint64_t ivrm_eco_vcs_range_lo : 1;
+ uint64_t ivrm_eco_vcs_range_hi : 1;
+ uint64_t ivrm_core_vcs_range_lo : 1;
+ uint64_t ivrm_core_vcs_range_hi : 1;
+ uint64_t ivrm_eco_vdd_range_lo : 1;
+ uint64_t ivrm_eco_vdd_range_hi : 1;
+ uint64_t ivrm_core_vdd_range_lo : 1;
+ uint64_t ivrm_core_vdd_range_hi : 1;
+ uint64_t ivrm_pref_error_fine : 1;
+ uint64_t ivrm_pref_error_gross : 1;
+ uint64_t pvref_fail : 1;
+ uint64_t ivrm_vret_eco_vcs_pfet_strength : 5;
+ uint64_t ivrm_vret_eco_vdd_pfet_strength : 5;
+ uint64_t ivrm_vret_core_vcs_pfet_strength : 5;
+ uint64_t ivrm_vret_core_vdd_pfet_strength : 5;
+ uint64_t ivrm_vret_vcs : 7;
+ uint64_t ivrm_vret_vdd : 7;
+ uint64_t ivrm_eco_vcs_poweron : 1;
+ uint64_t ivrm_eco_vcs_bypass_b : 1;
+ uint64_t ivrm_eco_vdd_poweron : 1;
+ uint64_t ivrm_eco_vdd_bypass_b : 1;
+ uint64_t ivrm_core_vcs_poweron : 1;
+ uint64_t ivrm_core_vcs_bypass_b : 1;
+ uint64_t ivrm_core_vdd_poweron : 1;
+ uint64_t ivrm_core_vdd_bypass_b : 1;
+ uint64_t pvref_en : 1;
+ uint64_t binsearch_cal_ena : 1;
+ uint64_t use_ivrm_for_vret : 1;
+ uint64_t ivrm_fsm_enable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_ivrm_control_status_reg_t;
+
+
+
+typedef union pcbs_ivrm_value_setting_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivrm_core_vdd_ivid : 8;
+ uint64_t ivrm_core_vcs_ivid : 8;
+ uint64_t ivrm_eco_vdd_ivid : 8;
+ uint64_t ivrm_eco_vcs_ivid : 8;
+ uint64_t ivrm_core_vdd_pfet_strength : 5;
+ uint64_t ivrm_core_vcs_pfet_strength : 5;
+ uint64_t ivrm_eco_vdd_pfet_strength : 5;
+ uint64_t ivrm_eco_vcs_pfet_strength : 5;
+ uint64_t ivrm_vdd_core_pfetstr_valid : 1;
+ uint64_t ivrm_vcs_core_pfetstr_valid : 1;
+ uint64_t ivrm_vdd_eco_pfetstr_valid : 1;
+ uint64_t ivrm_vcs_eco_pfetstr_valid : 1;
+ uint64_t core_vdd_vpump_en : 1;
+ uint64_t core_vcs_vpump_en : 1;
+ uint64_t eco_vdd_vpump_en : 1;
+ uint64_t eco_vcs_vpump_en : 1;
+ uint64_t _reserved0 : 4;
+#else
+ uint64_t _reserved0 : 4;
+ uint64_t eco_vcs_vpump_en : 1;
+ uint64_t eco_vdd_vpump_en : 1;
+ uint64_t core_vcs_vpump_en : 1;
+ uint64_t core_vdd_vpump_en : 1;
+ uint64_t ivrm_vcs_eco_pfetstr_valid : 1;
+ uint64_t ivrm_vdd_eco_pfetstr_valid : 1;
+ uint64_t ivrm_vcs_core_pfetstr_valid : 1;
+ uint64_t ivrm_vdd_core_pfetstr_valid : 1;
+ uint64_t ivrm_eco_vcs_pfet_strength : 5;
+ uint64_t ivrm_eco_vdd_pfet_strength : 5;
+ uint64_t ivrm_core_vcs_pfet_strength : 5;
+ uint64_t ivrm_core_vdd_pfet_strength : 5;
+ uint64_t ivrm_eco_vcs_ivid : 8;
+ uint64_t ivrm_eco_vdd_ivid : 8;
+ uint64_t ivrm_core_vcs_ivid : 8;
+ uint64_t ivrm_core_vdd_ivid : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_ivrm_value_setting_reg_t;
+
+
+
+typedef union pcbs_pcbspm_mode_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t enable_pstate_mode : 1;
+ uint64_t global_pstate_change_for_idle_state_enabled : 1;
+ uint64_t enable_global_pstate_req : 1;
+ uint64_t enable_winkle_with_cpm_mode : 1;
+ uint64_t enable_clipping_of_global_pstate_req : 1;
+ uint64_t chksw_hw214553 : 1;
+ uint64_t enable_pmc_pmax_sync_notification : 1;
+ uint64_t dpll_lock_replacement_timer_mode_en : 1;
+ uint64_t dpll_freqout_mode_en : 1;
+ uint64_t dpll_flock_mode_en : 1;
+ uint64_t enable_sense_delay_characterization : 1;
+ uint64_t sense_delay_timer_val : 7;
+ uint64_t cpm_fmin_clip_error_sel : 2;
+ uint64_t dbg_trace_sel : 4;
+ uint64_t trace_data_sel : 2;
+ uint64_t tp_cplt_ivrm_vpp_tune : 4;
+ uint64_t _reserved0 : 34;
+#else
+ uint64_t _reserved0 : 34;
+ uint64_t tp_cplt_ivrm_vpp_tune : 4;
+ uint64_t trace_data_sel : 2;
+ uint64_t dbg_trace_sel : 4;
+ uint64_t cpm_fmin_clip_error_sel : 2;
+ uint64_t sense_delay_timer_val : 7;
+ uint64_t enable_sense_delay_characterization : 1;
+ uint64_t dpll_flock_mode_en : 1;
+ uint64_t dpll_freqout_mode_en : 1;
+ uint64_t dpll_lock_replacement_timer_mode_en : 1;
+ uint64_t enable_pmc_pmax_sync_notification : 1;
+ uint64_t chksw_hw214553 : 1;
+ uint64_t enable_clipping_of_global_pstate_req : 1;
+ uint64_t enable_winkle_with_cpm_mode : 1;
+ uint64_t enable_global_pstate_req : 1;
+ uint64_t global_pstate_change_for_idle_state_enabled : 1;
+ uint64_t enable_pstate_mode : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pcbspm_mode_reg_t;
+
+#endif // __ASSEMBLER__
+#define PCBS_PCBSPM_MODE_REG_ENABLE_PSTATE_MODE SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define PCBS_PCBSPM_MODE_REG_GLOBAL_PSTATE_CHANGE_FOR_IDLE_STATE_ENABLED SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define PCBS_PCBSPM_MODE_REG_ENABLE_GLOBAL_PSTATE_REQ SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define PCBS_PCBSPM_MODE_REG_ENABLE_WINKLE_WITH_CPM_MODE SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define PCBS_PCBSPM_MODE_REG_ENABLE_CLIPPING_OF_GLOBAL_PSTATE_REQ SIXTYFOUR_BIT_CONSTANT(0x0800000000000000)
+#define PCBS_PCBSPM_MODE_REG_CHKSW_HW214553 SIXTYFOUR_BIT_CONSTANT(0x0400000000000000)
+#define PCBS_PCBSPM_MODE_REG_ENABLE_PMC_PMAX_SYNC_NOTIFICATION SIXTYFOUR_BIT_CONSTANT(0x0200000000000000)
+#define PCBS_PCBSPM_MODE_REG_DPLL_LOCK_REPLACEMENT_TIMER_MODE_EN SIXTYFOUR_BIT_CONSTANT(0x0100000000000000)
+#define PCBS_PCBSPM_MODE_REG_DPLL_FREQOUT_MODE_EN SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define PCBS_PCBSPM_MODE_REG_DPLL_FLOCK_MODE_EN SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define PCBS_PCBSPM_MODE_REG_ENABLE_SENSE_DELAY_CHARACTERIZATION SIXTYFOUR_BIT_CONSTANT(0x0020000000000000)
+#define PCBS_PCBSPM_MODE_REG_SENSE_DELAY_TIMER_VAL_MASK SIXTYFOUR_BIT_CONSTANT(0x001fc00000000000)
+#define PCBS_PCBSPM_MODE_REG_CPM_FMIN_CLIP_ERROR_SEL_MASK SIXTYFOUR_BIT_CONSTANT(0x0000300000000000)
+#define PCBS_PCBSPM_MODE_REG_DBG_TRACE_SEL_MASK SIXTYFOUR_BIT_CONSTANT(0x00000f0000000000)
+#define PCBS_PCBSPM_MODE_REG_TRACE_DATA_SEL_MASK SIXTYFOUR_BIT_CONSTANT(0x000000c000000000)
+#define PCBS_PCBSPM_MODE_REG_TP_CPLT_IVRM_VPP_TUNE_MASK SIXTYFOUR_BIT_CONSTANT(0x0000003c00000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union pcbs_ivrm_pfetstr_sense_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivrm_core_vdd_pfetstr_sns : 5;
+ uint64_t ivrm_core_vcs_pfetstr_sns : 5;
+ uint64_t ivrm_eco_vdd_pfetstr_sns : 5;
+ uint64_t ivrm_eco_vcs_pfetstr_sns : 5;
+ uint64_t ivrm_vdd_core_pfetstr_valid_sns : 1;
+ uint64_t ivrm_vcs_core_pfetstr_valid_sns : 1;
+ uint64_t ivrm_vdd_eco_pfetstr_valid_sns : 1;
+ uint64_t ivrm_vcs_eco_pfetstr_valid_sns : 1;
+ uint64_t core_vdd_bypass_b_sense : 1;
+ uint64_t core_vcs_bypass_b_sense : 1;
+ uint64_t eco_vdd_bypass_b_sense : 1;
+ uint64_t eco_vcs_bypass_b_sense : 1;
+ uint64_t core_vdd_poweron_sense : 1;
+ uint64_t core_vcs_poweron_sense : 1;
+ uint64_t eco_vdd_poweron_sense : 1;
+ uint64_t eco_vcs_poweron_sense : 1;
+ uint64_t core_vdd_vpump_en_sense : 1;
+ uint64_t core_vcs_vpump_en_sense : 1;
+ uint64_t eco_vdd_vpump_en_sense : 1;
+ uint64_t eco_vcs_vpump_en_sense : 1;
+ uint64_t core_vdd_pfet_low_vout_sns : 1;
+ uint64_t core_vcs_pfet_low_vout_sns : 1;
+ uint64_t eco_vdd_pfet_low_vout_sns : 1;
+ uint64_t eco_vcs_pfet_low_vout_sns : 1;
+ uint64_t _reserved0 : 24;
+#else
+ uint64_t _reserved0 : 24;
+ uint64_t eco_vcs_pfet_low_vout_sns : 1;
+ uint64_t eco_vdd_pfet_low_vout_sns : 1;
+ uint64_t core_vcs_pfet_low_vout_sns : 1;
+ uint64_t core_vdd_pfet_low_vout_sns : 1;
+ uint64_t eco_vcs_vpump_en_sense : 1;
+ uint64_t eco_vdd_vpump_en_sense : 1;
+ uint64_t core_vcs_vpump_en_sense : 1;
+ uint64_t core_vdd_vpump_en_sense : 1;
+ uint64_t eco_vcs_poweron_sense : 1;
+ uint64_t eco_vdd_poweron_sense : 1;
+ uint64_t core_vcs_poweron_sense : 1;
+ uint64_t core_vdd_poweron_sense : 1;
+ uint64_t eco_vcs_bypass_b_sense : 1;
+ uint64_t eco_vdd_bypass_b_sense : 1;
+ uint64_t core_vcs_bypass_b_sense : 1;
+ uint64_t core_vdd_bypass_b_sense : 1;
+ uint64_t ivrm_vcs_eco_pfetstr_valid_sns : 1;
+ uint64_t ivrm_vdd_eco_pfetstr_valid_sns : 1;
+ uint64_t ivrm_vcs_core_pfetstr_valid_sns : 1;
+ uint64_t ivrm_vdd_core_pfetstr_valid_sns : 1;
+ uint64_t ivrm_eco_vcs_pfetstr_sns : 5;
+ uint64_t ivrm_eco_vdd_pfetstr_sns : 5;
+ uint64_t ivrm_core_vcs_pfetstr_sns : 5;
+ uint64_t ivrm_core_vdd_pfetstr_sns : 5;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_ivrm_pfetstr_sense_reg_t;
+
+
+
+typedef union pcbs_power_management_idle_control_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ int64_t nap_pstate_req : 8;
+ uint64_t nap_pstate_en : 1;
+ uint64_t nap_global_en : 1;
+ uint64_t nap_latency : 2;
+ uint64_t reserved_ppmicr_0 : 4;
+ int64_t sleep_pstate_req : 8;
+ uint64_t sleep_pstate_en : 1;
+ uint64_t sleep_global_en : 1;
+ uint64_t sleep_latency : 2;
+ uint64_t reserved_ppmicr_1 : 4;
+ int64_t winkle_pstate_req : 8;
+ uint64_t winkle_pstate_en : 1;
+ uint64_t winkle_global_en : 1;
+ uint64_t winkle_latency : 2;
+ uint64_t reserved_ppmicr_2 : 4;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t reserved_ppmicr_2 : 4;
+ uint64_t winkle_latency : 2;
+ uint64_t winkle_global_en : 1;
+ uint64_t winkle_pstate_en : 1;
+ int64_t winkle_pstate_req : 8;
+ uint64_t reserved_ppmicr_1 : 4;
+ uint64_t sleep_latency : 2;
+ uint64_t sleep_global_en : 1;
+ uint64_t sleep_pstate_en : 1;
+ int64_t sleep_pstate_req : 8;
+ uint64_t reserved_ppmicr_0 : 4;
+ uint64_t nap_latency : 2;
+ uint64_t nap_global_en : 1;
+ uint64_t nap_pstate_en : 1;
+ int64_t nap_pstate_req : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_power_management_idle_control_reg_t;
+
+
+
+typedef union pcbs_power_management_control_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ int64_t global_pstate_req : 8;
+ int64_t local_pstate_req : 8;
+ uint64_t auto_override0_pstate_limit_en : 1;
+ uint64_t auto_override1_pstate_limit_en : 1;
+ uint64_t reserved_ppmcr : 6;
+ int64_t auto_override_pstate0 : 8;
+ int64_t auto_override_pstate1 : 8;
+ uint64_t _reserved0 : 24;
+#else
+ uint64_t _reserved0 : 24;
+ int64_t auto_override_pstate1 : 8;
+ int64_t auto_override_pstate0 : 8;
+ uint64_t reserved_ppmcr : 6;
+ uint64_t auto_override1_pstate_limit_en : 1;
+ uint64_t auto_override0_pstate_limit_en : 1;
+ int64_t local_pstate_req : 8;
+ int64_t global_pstate_req : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_power_management_control_reg_t;
+
+
+
+typedef union pcbs_pmc_vf_ctrl_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ int64_t pglobal_actual : 8;
+ uint64_t maxregvcs : 8;
+ uint64_t maxregvdd : 8;
+ uint64_t evidvcs_eff : 8;
+ uint64_t evidvdd_eff : 8;
+ uint64_t _reserved0 : 24;
+#else
+ uint64_t _reserved0 : 24;
+ uint64_t evidvdd_eff : 8;
+ uint64_t evidvcs_eff : 8;
+ uint64_t maxregvdd : 8;
+ uint64_t maxregvcs : 8;
+ int64_t pglobal_actual : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pmc_vf_ctrl_reg_t;
+
+
+
+typedef union pcbs_undervolting_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ int64_t puv_min : 8;
+ int64_t puv_max : 8;
+ uint64_t kuv : 6;
+ uint64_t _reserved0 : 42;
+#else
+ uint64_t _reserved0 : 42;
+ uint64_t kuv : 6;
+ int64_t puv_max : 8;
+ int64_t puv_min : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_undervolting_reg_t;
+
+
+
+typedef union pcbs_pstate_index_bound_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t lpsi_min : 8;
+ uint64_t lpsi_entries_minus_1 : 7;
+ uint64_t _reserved0 : 49;
+#else
+ uint64_t _reserved0 : 49;
+ uint64_t lpsi_entries_minus_1 : 7;
+ uint64_t lpsi_min : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pstate_index_bound_reg_t;
+
+
+
+typedef union pcbs_power_management_bounds_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ int64_t pmin_clip : 8;
+ int64_t pmax_clip : 8;
+ uint64_t _reserved0 : 48;
+#else
+ uint64_t _reserved0 : 48;
+ int64_t pmax_clip : 8;
+ int64_t pmin_clip : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_power_management_bounds_reg_t;
+
+
+
+typedef union pcbs_pstate_table_ctrl_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pstate_table_address : 7;
+ uint64_t _reserved0 : 57;
+#else
+ uint64_t _reserved0 : 57;
+ uint64_t pstate_table_address : 7;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pstate_table_ctrl_reg_t;
+
+
+
+typedef union pcbs_pstate_table_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pstate_data : 64;
+#else
+ uint64_t pstate_data : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pstate_table_reg_t;
+
+
+
+typedef union pcbs_pstate_step_target_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ int64_t local_pstate_eff_req : 8;
+ int64_t local_pstate_target : 8;
+ int64_t local_core_pstate_step_target : 8;
+ int64_t local_eco_pstate_step_target : 8;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ int64_t local_eco_pstate_step_target : 8;
+ int64_t local_core_pstate_step_target : 8;
+ int64_t local_pstate_target : 8;
+ int64_t local_pstate_eff_req : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_pstate_step_target_reg_t;
+
+
+
+typedef union pcbs_dpll_status_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dpll_ff_freqout : 15;
+ uint64_t dpll_frequ_change : 1;
+ uint64_t dpll_status_spare_bit1 : 1;
+ uint64_t pmax_sync_pending : 1;
+ uint64_t ga_ack_pending : 1;
+ int64_t capped_global_pstate_req : 8;
+ uint64_t dpll_fmax_and_cpmbit2 : 1;
+ uint64_t dpll_fmax_and_cpmbit3 : 1;
+ uint64_t dpll_fmax_and_cpmbit4 : 1;
+ uint64_t dpll_fmin_and_not_cpmbit2 : 1;
+ uint64_t dpll_fmin_and_not_cpmbit1 : 1;
+ uint64_t dpll_fmin_and_not_cpmbit0 : 1;
+ uint64_t dpll_faster_than_fmax_plus_delta1 : 1;
+ uint64_t dpll_slower_than_fmin_minus_delta2 : 1;
+ uint64_t dpll_max_freqout_after_last_read : 14;
+ uint64_t dpll_min_freqout_after_last_read : 14;
+ uint64_t _reserved0 : 1;
+#else
+ uint64_t _reserved0 : 1;
+ uint64_t dpll_min_freqout_after_last_read : 14;
+ uint64_t dpll_max_freqout_after_last_read : 14;
+ uint64_t dpll_slower_than_fmin_minus_delta2 : 1;
+ uint64_t dpll_faster_than_fmax_plus_delta1 : 1;
+ uint64_t dpll_fmin_and_not_cpmbit0 : 1;
+ uint64_t dpll_fmin_and_not_cpmbit1 : 1;
+ uint64_t dpll_fmin_and_not_cpmbit2 : 1;
+ uint64_t dpll_fmax_and_cpmbit4 : 1;
+ uint64_t dpll_fmax_and_cpmbit3 : 1;
+ uint64_t dpll_fmax_and_cpmbit2 : 1;
+ int64_t capped_global_pstate_req : 8;
+ uint64_t ga_ack_pending : 1;
+ uint64_t pmax_sync_pending : 1;
+ uint64_t dpll_status_spare_bit1 : 1;
+ uint64_t dpll_frequ_change : 1;
+ uint64_t dpll_ff_freqout : 15;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_dpll_status_reg_t;
+
+
+
+typedef union pcbs_ivrm_vid_control_reg0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivrm_req_pstate_stepdelay_rising : 8;
+ uint64_t ivrm_req_pstate_stepdelay_lowering : 8;
+ uint64_t _reserved0 : 48;
+#else
+ uint64_t _reserved0 : 48;
+ uint64_t ivrm_req_pstate_stepdelay_lowering : 8;
+ uint64_t ivrm_req_pstate_stepdelay_rising : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_ivrm_vid_control_reg0_t;
+
+
+
+typedef union pcbs_ivrm_vid_control_reg1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivrm_stabilize_delay_run : 8;
+ uint64_t ivrm_stabilize_delay_idle : 8;
+ uint64_t ivrm_pfstr_prop_delay : 8;
+ uint64_t ivrm_pfstrvalid_prop_delay : 8;
+ uint64_t ivrm_vpump_poweron_time : 8;
+ uint64_t ivrm_bypass_delay : 8;
+ uint64_t pfet_vpump_enable_delay : 8;
+ uint64_t ivrm_vid_vout_threshold : 7;
+ uint64_t _reserved0 : 1;
+#else
+ uint64_t _reserved0 : 1;
+ uint64_t ivrm_vid_vout_threshold : 7;
+ uint64_t pfet_vpump_enable_delay : 8;
+ uint64_t ivrm_bypass_delay : 8;
+ uint64_t ivrm_vpump_poweron_time : 8;
+ uint64_t ivrm_pfstrvalid_prop_delay : 8;
+ uint64_t ivrm_pfstr_prop_delay : 8;
+ uint64_t ivrm_stabilize_delay_idle : 8;
+ uint64_t ivrm_stabilize_delay_run : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_ivrm_vid_control_reg1_t;
+
+
+
+typedef union pcbs_occ_heartbeat_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t occ_heartbeat_time : 8;
+ uint64_t occ_heartbeat_enable : 1;
+ uint64_t occ_heartbeat_reg_addr_offset : 8;
+ int64_t psafe : 8;
+ uint64_t _reserved0 : 39;
+#else
+ uint64_t _reserved0 : 39;
+ int64_t psafe : 8;
+ uint64_t occ_heartbeat_reg_addr_offset : 8;
+ uint64_t occ_heartbeat_enable : 1;
+ uint64_t occ_heartbeat_time : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_occ_heartbeat_reg_t;
+
+
+
+typedef union pcbs_resonant_clock_control_reg0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t resclk_dis : 1;
+ uint64_t resclk_control_mode : 1;
+ uint64_t resclk_sync_pw : 3;
+ uint64_t res_sync_delay_cnt : 7;
+ uint64_t res_csb_str_instr_lo : 15;
+ uint64_t res_csb_str_instr_hi : 15;
+ uint64_t _reserved0 : 22;
+#else
+ uint64_t _reserved0 : 22;
+ uint64_t res_csb_str_instr_hi : 15;
+ uint64_t res_csb_str_instr_lo : 15;
+ uint64_t res_sync_delay_cnt : 7;
+ uint64_t resclk_sync_pw : 3;
+ uint64_t resclk_control_mode : 1;
+ uint64_t resclk_dis : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_resonant_clock_control_reg0_t;
+
+
+
+typedef union pcbs_resonant_clock_control_reg1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ int64_t full_csb_ps : 8;
+ int64_t res_low_lower_ps : 8;
+ int64_t res_low_upper_ps : 8;
+ int64_t res_high_lower_ps : 8;
+ int64_t res_high_upper_ps : 8;
+ uint64_t nonres_csb_value_ti : 4;
+ uint64_t full_csb_value_ti : 4;
+ uint64_t resclk_value : 9;
+ uint64_t resclk_core_sync_value : 1;
+ uint64_t csb_eco_sync_value : 1;
+ uint64_t _reserved0 : 5;
+#else
+ uint64_t _reserved0 : 5;
+ uint64_t csb_eco_sync_value : 1;
+ uint64_t resclk_core_sync_value : 1;
+ uint64_t resclk_value : 9;
+ uint64_t full_csb_value_ti : 4;
+ uint64_t nonres_csb_value_ti : 4;
+ int64_t res_high_upper_ps : 8;
+ int64_t res_high_lower_ps : 8;
+ int64_t res_low_upper_ps : 8;
+ int64_t res_low_lower_ps : 8;
+ int64_t full_csb_ps : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_resonant_clock_control_reg1_t;
+
+
+
+typedef union pcbs_resonant_clock_status_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t resclk_state : 1;
+ uint64_t res_hi_induct_en : 1;
+ uint64_t resclk_inprogress : 1;
+ uint64_t resclk_full_csb : 1;
+ uint64_t _reserved0 : 60;
+#else
+ uint64_t _reserved0 : 60;
+ uint64_t resclk_full_csb : 1;
+ uint64_t resclk_inprogress : 1;
+ uint64_t res_hi_induct_en : 1;
+ uint64_t resclk_state : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_resonant_clock_status_reg_t;
+
+
+
+typedef union pcbs_local_pstate_frequency_target_control_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t delay_time : 3;
+ uint64_t record_transitions : 1;
+ uint64_t multiplier : 15;
+ uint64_t enable_lpft_function : 1;
+ uint64_t _reserved0 : 44;
+#else
+ uint64_t _reserved0 : 44;
+ uint64_t enable_lpft_function : 1;
+ uint64_t multiplier : 15;
+ uint64_t record_transitions : 1;
+ uint64_t delay_time : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_local_pstate_frequency_target_control_reg_t;
+
+
+
+typedef union pcbs_local_pstate_frequency_target_status_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t valid : 1;
+ uint64_t cpm_dpll : 1;
+ uint64_t ivrm : 1;
+ uint64_t transition : 1;
+ uint64_t stable : 1;
+ uint64_t delta : 24;
+ uint64_t cumulative : 24;
+ uint64_t pstate : 8;
+ uint64_t _reserved0 : 3;
+#else
+ uint64_t _reserved0 : 3;
+ uint64_t pstate : 8;
+ uint64_t cumulative : 24;
+ uint64_t delta : 24;
+ uint64_t stable : 1;
+ uint64_t transition : 1;
+ uint64_t ivrm : 1;
+ uint64_t cpm_dpll : 1;
+ uint64_t valid : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_local_pstate_frequency_target_status_reg_t;
+
+
+
+typedef union pcbs_fsm_monitor1_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t babystep_main_fsm : 7;
+ uint64_t babystep_slave_fsm : 5;
+ uint64_t core_railstepper_main_fsm : 5;
+ uint64_t eco_railstepper_main_fsm : 5;
+ uint64_t core_railstepper_sub_fsm : 4;
+ uint64_t eco_railstepper_sub_fsm : 4;
+ uint64_t core_railstepper_byp_fsm : 5;
+ uint64_t eco_railstepper_byp_fsm : 5;
+ uint64_t ivrm_core_vdd_sequencer_fsm : 6;
+ uint64_t ivrm_core_vcs_sequencer_fsm : 6;
+ uint64_t ivrm_eco_vdd_sequencer_fsm : 6;
+ uint64_t ivrm_eco_vcs_sequencer_fsm : 6;
+#else
+ uint64_t ivrm_eco_vcs_sequencer_fsm : 6;
+ uint64_t ivrm_eco_vdd_sequencer_fsm : 6;
+ uint64_t ivrm_core_vcs_sequencer_fsm : 6;
+ uint64_t ivrm_core_vdd_sequencer_fsm : 6;
+ uint64_t eco_railstepper_byp_fsm : 5;
+ uint64_t core_railstepper_byp_fsm : 5;
+ uint64_t eco_railstepper_sub_fsm : 4;
+ uint64_t core_railstepper_sub_fsm : 4;
+ uint64_t eco_railstepper_main_fsm : 5;
+ uint64_t core_railstepper_main_fsm : 5;
+ uint64_t babystep_slave_fsm : 5;
+ uint64_t babystep_main_fsm : 7;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_fsm_monitor1_reg_t;
+
+
+
+typedef union pcbs_fsm_monitor2_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t resclk_band_fsm : 7;
+ uint64_t resclk_lowres_fsm : 4;
+ uint64_t resclk_highres_fsm : 4;
+ uint64_t resclk_fullcsb_fsm : 4;
+ uint64_t resclk_update_fsm : 4;
+ uint64_t idle_transition_fsm : 7;
+ uint64_t peco_step_target_uv : 8;
+ uint64_t pcore_step_target_uv : 8;
+ uint64_t _reserved0 : 18;
+#else
+ uint64_t _reserved0 : 18;
+ uint64_t pcore_step_target_uv : 8;
+ uint64_t peco_step_target_uv : 8;
+ uint64_t idle_transition_fsm : 7;
+ uint64_t resclk_update_fsm : 4;
+ uint64_t resclk_fullcsb_fsm : 4;
+ uint64_t resclk_highres_fsm : 4;
+ uint64_t resclk_lowres_fsm : 4;
+ uint64_t resclk_band_fsm : 7;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_fsm_monitor2_reg_t;
+
+
+
+typedef union pcbs_chksw_unassisted_interrupts {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 1;
+ uint64_t _reserved0 : 63;
+#else
+ uint64_t _reserved0 : 63;
+ uint64_t value : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pcbs_chksw_unassisted_interrupts_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __PCBS_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/pcbs_register_addresses.h b/src/ssx/pgp/registers/pcbs_register_addresses.h
new file mode 100755
index 0000000..8c465d1
--- /dev/null
+++ b/src/ssx/pgp/registers/pcbs_register_addresses.h
@@ -0,0 +1,74 @@
+#ifndef __PCBS_REGISTER_ADDRESSES_H__
+#define __PCBS_REGISTER_ADDRESSES_H__
+
+// $Id: pcbs_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:24 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pcbs_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pcbs_register_addresses.h
+/// \brief Symbolic addresses for the PCBS unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define PCBS_PIB_BASE 0x100f0100
+#define PCBS_PMGP0_REG 0x100f0100
+#define PCBS_PMGP0_REG_AND 0x100f0101
+#define PCBS_PMGP0_REG_OR 0x100f0102
+#define PCBS_PMGP1_REG 0x100f0103
+#define PCBS_PMGP1_REG_AND 0x100f0104
+#define PCBS_PMGP1_REG_OR 0x100f0105
+#define PCBS_PFVDDCNTLSTAT_REG 0x100f0106
+#define PCBS_PFVCSCNTLSTAT_REG 0x100f010e
+#define PCBS_PFSENSE_REG 0x100f0107
+#define PCBS_PMERRSUM_REG 0x100f0108
+#define PCBS_PMERR_REG 0x100f0109
+#define PCBS_PMERRMASK_REG 0x100f010a
+#define PCBS_PMSPCWKUPFSP_REG 0x100f010b
+#define PCBS_PMSPCWKUPOCC_REG 0x100f010c
+#define PCBS_PMSPCWKUPPHYP_REG 0x100f010d
+#define PCBS_PMSTATEHISTPHYP_REG 0x100f0110
+#define PCBS_PMSTATEHISTFSP_REG 0x100f0111
+#define PCBS_PMSTATEHISTOCC_REG 0x100f0112
+#define PCBS_PMSTATEHISTPERF_REG 0x100f0113
+#define PCBS_IDLEFSMGOTOCMD_REG 0x100f0114
+#define PCBS_COREPFPUDLY_REG 0x100f012c
+#define PCBS_COREPFPDDLY_REG 0x100f012d
+#define PCBS_COREPFVRET_REG 0x100f0130
+#define PCBS_ECOPFPUDLY_REG 0x100f014c
+#define PCBS_ECOPFPDDLY_REG 0x100f014d
+#define PCBS_ECOPFVRET_REG 0x100f0150
+#define PCBS_FREQ_CTRL_REG 0x100f0151
+#define PCBS_DPLL_CPM_PARM_REG 0x100f0152
+#define PCBS_POWER_MANAGEMENT_STATUS_REG 0x100f0153
+#define PCBS_IVRM_CONTROL_STATUS_REG 0x100f0154
+#define PCBS_IVRM_VALUE_SETTING_REG 0x100f0155
+#define PCBS_PCBSPM_MODE_REG 0x100f0156
+#define PCBS_IVRM_PFETSTR_SENSE_REG 0x100f0157
+#define PCBS_POWER_MANAGEMENT_IDLE_CONTROL_REG 0x100f0158
+#define PCBS_POWER_MANAGEMENT_CONTROL_REG 0x100f0159
+#define PCBS_PMC_VF_CTRL_REG 0x100f015a
+#define PCBS_UNDERVOLTING_REG 0x100f015b
+#define PCBS_PSTATE_INDEX_BOUND_REG 0x100f015c
+#define PCBS_POWER_MANAGEMENT_BOUNDS_REG 0x100f015d
+#define PCBS_PSTATE_TABLE_CTRL_REG 0x100f015e
+#define PCBS_PSTATE_TABLE_REG 0x100f015f
+#define PCBS_PSTATE_STEP_TARGET_REG 0x100f0160
+#define PCBS_DPLL_STATUS_REG 0x100f0161
+#define PCBS_IVRM_VID_CONTROL_REG0 0x100f0162
+#define PCBS_IVRM_VID_CONTROL_REG1 0x100f0163
+#define PCBS_OCC_HEARTBEAT_REG 0x100f0164
+#define PCBS_RESONANT_CLOCK_CONTROL_REG0 0x100f0165
+#define PCBS_RESONANT_CLOCK_CONTROL_REG1 0x100f0166
+#define PCBS_RESONANT_CLOCK_STATUS_REG 0x100f0167
+#define PCBS_LOCAL_PSTATE_FREQUENCY_TARGET_CONTROL_REG 0x100f0168
+#define PCBS_LOCAL_PSTATE_FREQUENCY_TARGET_STATUS_REG 0x100f0169
+#define PCBS_FSM_MONITOR1_REG 0x100f0170
+#define PCBS_FSM_MONITOR2_REG 0x100f0171
+
+#endif // __PCBS_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/pibmem_firmware_registers.h b/src/ssx/pgp/registers/pibmem_firmware_registers.h
new file mode 100644
index 0000000..3b36fc1
--- /dev/null
+++ b/src/ssx/pgp/registers/pibmem_firmware_registers.h
@@ -0,0 +1,264 @@
+#ifndef __PIBMEM_FIRMWARE_REGISTERS_H__
+#define __PIBMEM_FIRMWARE_REGISTERS_H__
+
+// $Id: pibmem_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pibmem_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pibmem_firmware_registers.h
+/// \brief C register structs for the PIBMEM unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union pibmem_data0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_data0_t;
+
+
+
+typedef union pibmem_control {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t auto_pre_increment : 1;
+ uint64_t auto_post_decrement : 1;
+ uint64_t _reserved0 : 62;
+#else
+ uint64_t _reserved0 : 62;
+ uint64_t auto_post_decrement : 1;
+ uint64_t auto_pre_increment : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_control_t;
+
+
+
+typedef union pibmem_address {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved0 : 48;
+ uint64_t address : 16;
+#else
+ uint64_t address : 16;
+ uint64_t reserved0 : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_address_t;
+
+
+
+typedef union pibmem_data {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_data_t;
+
+
+
+typedef union pibmem_data_inc {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_data_inc_t;
+
+
+
+typedef union pibmem_data_dec {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_data_dec_t;
+
+
+
+typedef union pibmem_status {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t addr_invalid : 1;
+ uint64_t write_invalid : 1;
+ uint64_t read_invalid : 1;
+ uint64_t ecc_uncorrected_error : 1;
+ uint64_t ecc_corrected_error : 1;
+ uint64_t bad_array_address : 1;
+ uint64_t reserved6 : 5;
+ uint64_t fsm_present_state : 7;
+ uint64_t _reserved0 : 46;
+#else
+ uint64_t _reserved0 : 46;
+ uint64_t fsm_present_state : 7;
+ uint64_t reserved6 : 5;
+ uint64_t bad_array_address : 1;
+ uint64_t ecc_corrected_error : 1;
+ uint64_t ecc_uncorrected_error : 1;
+ uint64_t read_invalid : 1;
+ uint64_t write_invalid : 1;
+ uint64_t addr_invalid : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_status_t;
+
+
+
+typedef union pibmem_reset {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reset_code : 2;
+ uint64_t _reserved0 : 62;
+#else
+ uint64_t _reserved0 : 62;
+ uint64_t reset_code : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_reset_t;
+
+
+
+typedef union pibmem_repair {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pibmem_repair_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __PIBMEM_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/pibmem_register_addresses.h b/src/ssx/pgp/registers/pibmem_register_addresses.h
new file mode 100644
index 0000000..0cffaa2
--- /dev/null
+++ b/src/ssx/pgp/registers/pibmem_register_addresses.h
@@ -0,0 +1,30 @@
+#ifndef __PIBMEM_REGISTER_ADDRESSES_H__
+#define __PIBMEM_REGISTER_ADDRESSES_H__
+
+// $Id: pibmem_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pibmem_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pibmem_register_addresses.h
+/// \brief Symbolic addresses for the PIBMEM unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define PIBMEM_PIB_BASE 0x00080000
+#define PIBMEM_DATA0 0x00080000
+#define PIBMEM_CONTROL 0x00088000
+#define PIBMEM_ADDRESS 0x00088001
+#define PIBMEM_DATA 0x00088002
+#define PIBMEM_DATA_INC 0x00088003
+#define PIBMEM_DATA_DEC 0x00088004
+#define PIBMEM_STATUS 0x00088005
+#define PIBMEM_RESET 0x00088006
+#define PIBMEM_REPAIR 0x00088007
+
+#endif // __PIBMEM_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/plb_arbiter_firmware_registers.h b/src/ssx/pgp/registers/plb_arbiter_firmware_registers.h
new file mode 100755
index 0000000..583e95d
--- /dev/null
+++ b/src/ssx/pgp/registers/plb_arbiter_firmware_registers.h
@@ -0,0 +1,215 @@
+#ifndef __PLB_ARBITER_FIRMWARE_REGISTERS_H__
+#define __PLB_ARBITER_FIRMWARE_REGISTERS_H__
+
+// $Id: plb_arbiter_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/plb_arbiter_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file plb_arbiter_firmware_registers.h
+/// \brief C register structs for the PLB_ARBITER unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union plb_prev {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} plb_prev_t;
+
+
+
+typedef union plb_pacr {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t ppm : 1;
+ uint32_t ppo : 3;
+ uint32_t hbu : 1;
+ uint32_t rdp : 2;
+ uint32_t wrp : 1;
+ uint32_t _reserved0 : 24;
+#else
+ uint32_t _reserved0 : 24;
+ uint32_t wrp : 1;
+ uint32_t rdp : 2;
+ uint32_t hbu : 1;
+ uint32_t ppo : 3;
+ uint32_t ppm : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} plb_pacr_t;
+
+
+
+typedef union plb_pesr {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pte0 : 1;
+ uint32_t rw0 : 1;
+ uint32_t flk0 : 1;
+ uint32_t alk0 : 1;
+ uint32_t pte1 : 1;
+ uint32_t rw1 : 1;
+ uint32_t flk1 : 1;
+ uint32_t alk1 : 1;
+ uint32_t pte2 : 1;
+ uint32_t rw2 : 1;
+ uint32_t flk2 : 1;
+ uint32_t alk2 : 1;
+ uint32_t pte3 : 1;
+ uint32_t rw3 : 1;
+ uint32_t flk3 : 1;
+ uint32_t alk3 : 1;
+ uint32_t pte4 : 1;
+ uint32_t rw4 : 1;
+ uint32_t flk4 : 1;
+ uint32_t alk4 : 1;
+ uint32_t pte5 : 1;
+ uint32_t rw5 : 1;
+ uint32_t flk5 : 1;
+ uint32_t alk5 : 1;
+ uint32_t pte6 : 1;
+ uint32_t rw6 : 1;
+ uint32_t flk6 : 1;
+ uint32_t alk6 : 1;
+ uint32_t pte7 : 1;
+ uint32_t rw7 : 1;
+ uint32_t flk7 : 1;
+ uint32_t alk7 : 1;
+#else
+ uint32_t alk7 : 1;
+ uint32_t flk7 : 1;
+ uint32_t rw7 : 1;
+ uint32_t pte7 : 1;
+ uint32_t alk6 : 1;
+ uint32_t flk6 : 1;
+ uint32_t rw6 : 1;
+ uint32_t pte6 : 1;
+ uint32_t alk5 : 1;
+ uint32_t flk5 : 1;
+ uint32_t rw5 : 1;
+ uint32_t pte5 : 1;
+ uint32_t alk4 : 1;
+ uint32_t flk4 : 1;
+ uint32_t rw4 : 1;
+ uint32_t pte4 : 1;
+ uint32_t alk3 : 1;
+ uint32_t flk3 : 1;
+ uint32_t rw3 : 1;
+ uint32_t pte3 : 1;
+ uint32_t alk2 : 1;
+ uint32_t flk2 : 1;
+ uint32_t rw2 : 1;
+ uint32_t pte2 : 1;
+ uint32_t alk1 : 1;
+ uint32_t flk1 : 1;
+ uint32_t rw1 : 1;
+ uint32_t pte1 : 1;
+ uint32_t alk0 : 1;
+ uint32_t flk0 : 1;
+ uint32_t rw0 : 1;
+ uint32_t pte0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} plb_pesr_t;
+
+
+
+typedef union plb_pearl {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} plb_pearl_t;
+
+
+
+typedef union plb_pearh {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} plb_pearh_t;
+
+
+
+typedef union plb_sto_pesr {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t icu_te : 1;
+ uint32_t icu_rw : 1;
+ uint32_t reserved2 : 2;
+ uint32_t dcu_te : 1;
+ uint32_t dcu_rw : 1;
+ uint32_t reserved6 : 2;
+ uint32_t _reserved0 : 24;
+#else
+ uint32_t _reserved0 : 24;
+ uint32_t reserved6 : 2;
+ uint32_t dcu_rw : 1;
+ uint32_t dcu_te : 1;
+ uint32_t reserved2 : 2;
+ uint32_t icu_rw : 1;
+ uint32_t icu_te : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} plb_sto_pesr_t;
+
+
+
+typedef union plb_sto_pear {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t value : 32;
+#else
+ uint32_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} plb_sto_pear_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __PLB_ARBITER_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/plb_arbiter_register_addresses.h b/src/ssx/pgp/registers/plb_arbiter_register_addresses.h
new file mode 100755
index 0000000..2bc2f41
--- /dev/null
+++ b/src/ssx/pgp/registers/plb_arbiter_register_addresses.h
@@ -0,0 +1,28 @@
+#ifndef __PLB_ARBITER_REGISTER_ADDRESSES_H__
+#define __PLB_ARBITER_REGISTER_ADDRESSES_H__
+
+// $Id: plb_arbiter_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:24 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/plb_arbiter_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file plb_arbiter_register_addresses.h
+/// \brief Symbolic addresses for the PLB_ARBITER unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define PLB_DCR_BASE 0x90
+#define PLB_PREV 0x00000092
+#define PLB_PACR 0x00000093
+#define PLB_PESR 0x00000094
+#define PLB_PEARL 0x00000096
+#define PLB_PEARH 0x00000097
+#define PLB_STO_PESR 0x00000099
+#define PLB_STO_PEAR 0x00000098
+
+#endif // __PLB_ARBITER_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/pmc_firmware_registers.h b/src/ssx/pgp/registers/pmc_firmware_registers.h
new file mode 100755
index 0000000..76642a4
--- /dev/null
+++ b/src/ssx/pgp/registers/pmc_firmware_registers.h
@@ -0,0 +1,3140 @@
+#ifndef __PMC_FIRMWARE_REGISTERS_H__
+#define __PMC_FIRMWARE_REGISTERS_H__
+
+// $Id: pmc_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pmc_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pmc_firmware_registers.h
+/// \brief C register structs for the PMC unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union pmc_mode_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t enable_hw_pstate_mode : 1;
+ uint32_t enable_fw_auction_pstate_mode : 1;
+ uint32_t enable_fw_pstate_mode : 1;
+ uint32_t enable_pstate_voltage_changes : 1;
+ uint32_t enable_global_actual_pstate_forwarding : 1;
+ uint32_t halt_pstate_master_fsm : 1;
+ uint32_t enable_interchip_interface : 1;
+ uint32_t interchip_mode : 1;
+ uint32_t enable_interchip_pstate_in_haps : 1;
+ uint32_t enable_pstate_stepping : 1;
+ uint32_t honor_oha_idle_state_requests : 1;
+ uint32_t vid_endianess : 1;
+ uint32_t reset_all_pmc_registers : 1;
+ uint32_t safe_mode_without_spivid : 1;
+ uint32_t halt_idle_state_master_fsm : 1;
+ uint32_t interchip_halt_if : 1;
+ uint32_t unfreeze_pstate_processing : 1;
+ uint32_t spivid_reset_if : 1;
+ uint32_t unfreeze_istate_processing : 1;
+ uint32_t _reserved0 : 13;
+#else
+ uint32_t _reserved0 : 13;
+ uint32_t unfreeze_istate_processing : 1;
+ uint32_t spivid_reset_if : 1;
+ uint32_t unfreeze_pstate_processing : 1;
+ uint32_t interchip_halt_if : 1;
+ uint32_t halt_idle_state_master_fsm : 1;
+ uint32_t safe_mode_without_spivid : 1;
+ uint32_t reset_all_pmc_registers : 1;
+ uint32_t vid_endianess : 1;
+ uint32_t honor_oha_idle_state_requests : 1;
+ uint32_t enable_pstate_stepping : 1;
+ uint32_t enable_interchip_pstate_in_haps : 1;
+ uint32_t interchip_mode : 1;
+ uint32_t enable_interchip_interface : 1;
+ uint32_t halt_pstate_master_fsm : 1;
+ uint32_t enable_global_actual_pstate_forwarding : 1;
+ uint32_t enable_pstate_voltage_changes : 1;
+ uint32_t enable_fw_pstate_mode : 1;
+ uint32_t enable_fw_auction_pstate_mode : 1;
+ uint32_t enable_hw_pstate_mode : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_mode_reg_t;
+
+
+
+typedef union pmc_hardware_auction_pstate_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t haps : 8;
+ uint32_t kuv_actual : 8;
+ uint32_t kuv_received : 8;
+ uint32_t _reserved0 : 8;
+#else
+ uint32_t _reserved0 : 8;
+ uint32_t kuv_received : 8;
+ uint32_t kuv_actual : 8;
+ int32_t haps : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_hardware_auction_pstate_reg_t;
+
+
+
+typedef union pmc_pstate_monitor_and_ctrl_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t gpst_val : 8;
+ int32_t gpsst : 8;
+ int32_t gpsa : 8;
+ int32_t gapr : 8;
+#else
+ int32_t gapr : 8;
+ int32_t gpsa : 8;
+ int32_t gpsst : 8;
+ int32_t gpst_val : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pstate_monitor_and_ctrl_reg_t;
+
+
+
+typedef union pmc_rail_bounds_register {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t pmin_rail : 8;
+ int32_t pmax_rail : 8;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ int32_t pmax_rail : 8;
+ int32_t pmin_rail : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_rail_bounds_register_t;
+
+
+
+typedef union pmc_global_pstate_bounds_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t gpsi_min : 8;
+ uint32_t gpst_number_of_entries_minus_one : 7;
+ uint32_t _reserved0 : 17;
+#else
+ uint32_t _reserved0 : 17;
+ uint32_t gpst_number_of_entries_minus_one : 7;
+ uint32_t gpsi_min : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_global_pstate_bounds_reg_t;
+
+
+
+typedef union pmc_parameter_reg0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pstate_stepsize : 7;
+ uint32_t vrm_stepdelay_range : 4;
+ uint32_t vrm_stepdelay_value : 4;
+ uint32_t hangpulse_predivider : 6;
+ uint32_t gpsa_timeout_value : 8;
+ uint32_t gpsa_timeout_value_sel : 1;
+ uint32_t _reserved0 : 2;
+#else
+ uint32_t _reserved0 : 2;
+ uint32_t gpsa_timeout_value_sel : 1;
+ uint32_t gpsa_timeout_value : 8;
+ uint32_t hangpulse_predivider : 6;
+ uint32_t vrm_stepdelay_value : 4;
+ uint32_t vrm_stepdelay_range : 4;
+ uint32_t pstate_stepsize : 7;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_parameter_reg0_t;
+
+
+
+typedef union pmc_parameter_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t ba_sram_pstate_table : 22;
+ int32_t pvsafe : 8;
+ uint32_t _reserved0 : 2;
+#else
+ uint32_t _reserved0 : 2;
+ int32_t pvsafe : 8;
+ uint32_t ba_sram_pstate_table : 22;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_parameter_reg1_t;
+
+
+
+typedef union pmc_eff_global_actual_voltage_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t maxreg_vdd : 8;
+ uint32_t maxreg_vcs : 8;
+ uint32_t eff_evid_vdd : 8;
+ uint32_t eff_evid_vcs : 8;
+#else
+ uint32_t eff_evid_vcs : 8;
+ uint32_t eff_evid_vdd : 8;
+ uint32_t maxreg_vcs : 8;
+ uint32_t maxreg_vdd : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_eff_global_actual_voltage_reg_t;
+
+
+
+typedef union pmc_global_actual_voltage_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t evid_vdd : 8;
+ uint32_t evid_vcs : 8;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t evid_vcs : 8;
+ uint32_t evid_vdd : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_global_actual_voltage_reg_t;
+
+
+
+typedef union pmc_status_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pstate_processing_is_suspended : 1;
+ uint32_t gpsa_bdcst_error : 1;
+ uint32_t gpsa_bdcst_resp_info : 3;
+ uint32_t gpsa_vchg_error : 1;
+ uint32_t gpsa_timeout_error : 1;
+ uint32_t gpsa_chg_ongoing : 1;
+ uint32_t volt_chg_ongoing : 1;
+ uint32_t brd_cst_ongoing : 1;
+ uint32_t gps_table_error : 1;
+ uint32_t pstate_interchip_error : 1;
+ uint32_t istate_processing_is_suspended : 1;
+ uint32_t safe_mode_engaged : 1;
+ uint32_t _reserved0 : 18;
+#else
+ uint32_t _reserved0 : 18;
+ uint32_t safe_mode_engaged : 1;
+ uint32_t istate_processing_is_suspended : 1;
+ uint32_t pstate_interchip_error : 1;
+ uint32_t gps_table_error : 1;
+ uint32_t brd_cst_ongoing : 1;
+ uint32_t volt_chg_ongoing : 1;
+ uint32_t gpsa_chg_ongoing : 1;
+ uint32_t gpsa_timeout_error : 1;
+ uint32_t gpsa_vchg_error : 1;
+ uint32_t gpsa_bdcst_resp_info : 3;
+ uint32_t gpsa_bdcst_error : 1;
+ uint32_t pstate_processing_is_suspended : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_status_reg_t;
+
+
+
+typedef union pmc_phase_enable_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t phase_enable : 4;
+ uint32_t _reserved0 : 28;
+#else
+ uint32_t _reserved0 : 28;
+ uint32_t phase_enable : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_phase_enable_reg_t;
+
+
+
+typedef union pmc_undervolting_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t puv_min : 8;
+ int32_t puv_max : 8;
+ uint32_t kuv_request : 8;
+ uint32_t _reserved0 : 8;
+#else
+ uint32_t _reserved0 : 8;
+ uint32_t kuv_request : 8;
+ int32_t puv_max : 8;
+ int32_t puv_min : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_undervolting_reg_t;
+
+
+
+typedef union pmc_core_deconfiguration_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t core_chiplet_deconf_vector : 16;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t core_chiplet_deconf_vector : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_core_deconfiguration_reg_t;
+
+
+
+typedef union pmc_intchp_ctrl_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t interchip_ga_fsm_enable : 1;
+ uint32_t interchip_recv_done_valid_without_if_en : 1;
+ uint32_t pmcic1_reserved_2 : 1;
+ uint32_t interchip_cpha : 1;
+ uint32_t interchip_clock_divider : 10;
+ uint32_t pmcicr1_reserved_14_17 : 4;
+ uint32_t pmcicr1_reserved_18_20 : 3;
+ uint32_t _reserved0 : 11;
+#else
+ uint32_t _reserved0 : 11;
+ uint32_t pmcicr1_reserved_18_20 : 3;
+ uint32_t pmcicr1_reserved_14_17 : 4;
+ uint32_t interchip_clock_divider : 10;
+ uint32_t interchip_cpha : 1;
+ uint32_t pmcic1_reserved_2 : 1;
+ uint32_t interchip_recv_done_valid_without_if_en : 1;
+ uint32_t interchip_ga_fsm_enable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_ctrl_reg1_t;
+
+
+
+typedef union pmc_intchp_ctrl_reg2 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t interchip_ping_send : 1;
+ uint32_t interchip_ping_detect_clear : 1;
+ uint32_t interchip_ping_mode : 1;
+ uint32_t pmcic2_reserved3 : 1;
+ uint32_t pmcic2_reserved4 : 1;
+ uint32_t pmcic2_reserved5_7 : 3;
+ uint32_t _reserved0 : 24;
+#else
+ uint32_t _reserved0 : 24;
+ uint32_t pmcic2_reserved5_7 : 3;
+ uint32_t pmcic2_reserved4 : 1;
+ uint32_t pmcic2_reserved3 : 1;
+ uint32_t interchip_ping_mode : 1;
+ uint32_t interchip_ping_detect_clear : 1;
+ uint32_t interchip_ping_send : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_ctrl_reg2_t;
+
+
+
+typedef union pmc_intchp_ctrl_reg4 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t interchip_ecc_gen_en : 1;
+ uint32_t interchip_ecc_check_en : 1;
+ uint32_t interchip_msg_rcv_overflow_check_en : 1;
+ uint32_t interchip_ecc_ue_block_en : 1;
+ uint32_t chksw_hw221732 : 1;
+ uint32_t slave_occ_timeout_forces_safe_mode_disable : 1;
+ uint32_t pmcic4_reserved6_7 : 2;
+ uint32_t _reserved0 : 24;
+#else
+ uint32_t _reserved0 : 24;
+ uint32_t pmcic4_reserved6_7 : 2;
+ uint32_t slave_occ_timeout_forces_safe_mode_disable : 1;
+ uint32_t chksw_hw221732 : 1;
+ uint32_t interchip_ecc_ue_block_en : 1;
+ uint32_t interchip_msg_rcv_overflow_check_en : 1;
+ uint32_t interchip_ecc_check_en : 1;
+ uint32_t interchip_ecc_gen_en : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_ctrl_reg4_t;
+
+
+
+typedef union pmc_intchp_status_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t interchip_ga_ongoing : 1;
+ uint32_t interchip_ecc_ue : 1;
+ uint32_t interchip_ecc_ce : 1;
+ uint32_t interchip_ping_detected : 1;
+ uint32_t interchip_ping_ack_detected : 1;
+ uint32_t interchip_msg_send_ongoing : 1;
+ uint32_t interchip_msg_recv_detected : 1;
+ uint32_t interchip_fsm_err : 1;
+ uint32_t interchip_ping_detect_count : 8;
+ uint32_t interchip_slave_error_code : 4;
+ uint32_t interchip_msg_snd_overflow_detected : 1;
+ uint32_t interchip_msg_rcv_overflow_detected : 1;
+ uint32_t interchip_ecc_ue_err : 1;
+ uint32_t _reserved0 : 9;
+#else
+ uint32_t _reserved0 : 9;
+ uint32_t interchip_ecc_ue_err : 1;
+ uint32_t interchip_msg_rcv_overflow_detected : 1;
+ uint32_t interchip_msg_snd_overflow_detected : 1;
+ uint32_t interchip_slave_error_code : 4;
+ uint32_t interchip_ping_detect_count : 8;
+ uint32_t interchip_fsm_err : 1;
+ uint32_t interchip_msg_recv_detected : 1;
+ uint32_t interchip_msg_send_ongoing : 1;
+ uint32_t interchip_ping_ack_detected : 1;
+ uint32_t interchip_ping_detected : 1;
+ uint32_t interchip_ecc_ce : 1;
+ uint32_t interchip_ecc_ue : 1;
+ uint32_t interchip_ga_ongoing : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_status_reg_t;
+
+
+
+typedef union pmc_intchp_command_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t interchip_reset_if : 1;
+ uint32_t interchip_halt_msg_fsm : 1;
+ uint32_t interchip_clear_sticky_bits : 1;
+ uint32_t _reserved0 : 29;
+#else
+ uint32_t _reserved0 : 29;
+ uint32_t interchip_clear_sticky_bits : 1;
+ uint32_t interchip_halt_msg_fsm : 1;
+ uint32_t interchip_reset_if : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_command_reg_t;
+
+
+
+typedef union pmc_intchp_msg_wdata {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t interchip_msg_wdata : 32;
+#else
+ uint32_t interchip_msg_wdata : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_msg_wdata_t;
+
+
+
+typedef union pmc_intchp_msg_rdata {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t interchip_msg_rdata : 32;
+#else
+ uint32_t interchip_msg_rdata : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_msg_rdata_t;
+
+
+
+typedef union pmc_intchp_pstate_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t pstate_interchip : 8;
+ uint32_t _reserved0 : 24;
+#else
+ uint32_t _reserved0 : 24;
+ int32_t pstate_interchip : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_pstate_reg_t;
+
+
+
+typedef union pmc_intchp_globack_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t gaack_interchip : 1;
+ int32_t gaack_interchip_pstate : 8;
+ uint32_t _reserved0 : 23;
+#else
+ uint32_t _reserved0 : 23;
+ int32_t gaack_interchip_pstate : 8;
+ uint32_t gaack_interchip : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_intchp_globack_reg_t;
+
+
+
+typedef union pmc_fsmstate_status_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t mis_fsm_state : 3;
+ uint32_t mps_fsm_state : 5;
+ uint32_t svs_fsm_state : 4;
+ uint32_t o2s_fsm_state : 4;
+ uint32_t m2p_fsm_state : 4;
+ uint32_t o2p_fsm_state : 4;
+ uint32_t icp_msg_fsm_state : 5;
+ uint32_t _reserved0 : 3;
+#else
+ uint32_t _reserved0 : 3;
+ uint32_t icp_msg_fsm_state : 5;
+ uint32_t o2p_fsm_state : 4;
+ uint32_t m2p_fsm_state : 4;
+ uint32_t o2s_fsm_state : 4;
+ uint32_t svs_fsm_state : 4;
+ uint32_t mps_fsm_state : 5;
+ uint32_t mis_fsm_state : 3;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_fsmstate_status_reg_t;
+
+
+
+typedef union pmc_trace_mode_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pmc_trace_mode : 4;
+ uint32_t trace_sel_data : 2;
+ uint32_t _reserved0 : 26;
+#else
+ uint32_t _reserved0 : 26;
+ uint32_t trace_sel_data : 2;
+ uint32_t pmc_trace_mode : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_trace_mode_reg_t;
+
+
+
+typedef union pmc_spiv_ctrl_reg0a {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t spivid_frame_size : 6;
+ uint32_t spivid_out_count1 : 6;
+ uint32_t spivid_in_delay1 : 6;
+ uint32_t spivid_in_count1 : 6;
+ uint32_t _reserved0 : 8;
+#else
+ uint32_t _reserved0 : 8;
+ uint32_t spivid_in_count1 : 6;
+ uint32_t spivid_in_delay1 : 6;
+ uint32_t spivid_out_count1 : 6;
+ uint32_t spivid_frame_size : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_spiv_ctrl_reg0a_t;
+
+
+
+typedef union pmc_spiv_ctrl_reg0b {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t spivid_out_count2 : 6;
+ uint32_t spivid_in_delay2 : 6;
+ uint32_t spivid_in_count2 : 6;
+ uint32_t _reserved0 : 14;
+#else
+ uint32_t _reserved0 : 14;
+ uint32_t spivid_in_count2 : 6;
+ uint32_t spivid_in_delay2 : 6;
+ uint32_t spivid_out_count2 : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_spiv_ctrl_reg0b_t;
+
+
+
+typedef union pmc_spiv_ctrl_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t spivid_fsm_enable : 1;
+ uint32_t pmcscr1_reserved_1 : 1;
+ uint32_t spivid_cpol : 1;
+ uint32_t spivid_cpha : 1;
+ uint32_t spivid_clock_divider : 10;
+ uint32_t pmcscr1_reserved_2 : 4;
+ uint32_t spivid_port_enable : 3;
+ uint32_t _reserved0 : 11;
+#else
+ uint32_t _reserved0 : 11;
+ uint32_t spivid_port_enable : 3;
+ uint32_t pmcscr1_reserved_2 : 4;
+ uint32_t spivid_clock_divider : 10;
+ uint32_t spivid_cpha : 1;
+ uint32_t spivid_cpol : 1;
+ uint32_t pmcscr1_reserved_1 : 1;
+ uint32_t spivid_fsm_enable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_spiv_ctrl_reg1_t;
+
+
+
+typedef union pmc_spiv_ctrl_reg2 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t spivid_inter_frame_delay_write_status : 17;
+ uint32_t _reserved0 : 15;
+#else
+ uint32_t _reserved0 : 15;
+ uint32_t spivid_inter_frame_delay_write_status : 17;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_spiv_ctrl_reg2_t;
+
+
+
+typedef union pmc_spiv_ctrl_reg3 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t spivid_inter_retry_delay : 17;
+ uint32_t pmc_100ns_pls_range : 6;
+ uint32_t _reserved0 : 9;
+#else
+ uint32_t _reserved0 : 9;
+ uint32_t pmc_100ns_pls_range : 6;
+ uint32_t spivid_inter_retry_delay : 17;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_spiv_ctrl_reg3_t;
+
+
+
+typedef union pmc_spiv_ctrl_reg4 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t spivid_crc_gen_en : 1;
+ uint32_t spivid_crc_check_en : 1;
+ uint32_t spivid_majority_vote_en : 1;
+ uint32_t spivid_max_retries : 5;
+ uint32_t spivid_crc_polynomial_enables : 8;
+ uint32_t spivid_crc_const_gen_enable : 1;
+ uint32_t spivid_crc_const_check_enable : 1;
+ uint32_t spivid_frame_sync_wrong_enable : 1;
+ uint32_t _reserved0 : 13;
+#else
+ uint32_t _reserved0 : 13;
+ uint32_t spivid_frame_sync_wrong_enable : 1;
+ uint32_t spivid_crc_const_check_enable : 1;
+ uint32_t spivid_crc_const_gen_enable : 1;
+ uint32_t spivid_crc_polynomial_enables : 8;
+ uint32_t spivid_max_retries : 5;
+ uint32_t spivid_majority_vote_en : 1;
+ uint32_t spivid_crc_check_en : 1;
+ uint32_t spivid_crc_gen_en : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_spiv_ctrl_reg4_t;
+
+
+
+typedef union pmc_spiv_status_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t spivid_ongoing : 1;
+ uint32_t spivid_crc_error0 : 1;
+ uint32_t spivid_crc_error1 : 1;
+ uint32_t spivid_crc_error2 : 1;
+ uint32_t spivid_retry_timeout : 1;
+ uint32_t pmcssr_reserved_1 : 2;
+ uint32_t spivid_fsm_err : 1;
+ uint32_t spivid_majority_detected_a_minority0 : 1;
+ uint32_t spivid_majority_detected_a_minority1 : 1;
+ uint32_t spivid_majority_detected_a_minority2 : 1;
+ uint32_t spivid_majority_nr_of_minorities0 : 4;
+ uint32_t spivid_majority_nr_of_minorities1 : 4;
+ uint32_t spivid_majority_nr_of_minorities2 : 4;
+ uint32_t _reserved0 : 9;
+#else
+ uint32_t _reserved0 : 9;
+ uint32_t spivid_majority_nr_of_minorities2 : 4;
+ uint32_t spivid_majority_nr_of_minorities1 : 4;
+ uint32_t spivid_majority_nr_of_minorities0 : 4;
+ uint32_t spivid_majority_detected_a_minority2 : 1;
+ uint32_t spivid_majority_detected_a_minority1 : 1;
+ uint32_t spivid_majority_detected_a_minority0 : 1;
+ uint32_t spivid_fsm_err : 1;
+ uint32_t pmcssr_reserved_1 : 2;
+ uint32_t spivid_retry_timeout : 1;
+ uint32_t spivid_crc_error2 : 1;
+ uint32_t spivid_crc_error1 : 1;
+ uint32_t spivid_crc_error0 : 1;
+ uint32_t spivid_ongoing : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_spiv_status_reg_t;
+
+
+
+typedef union pmc_spiv_command_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t spivid_halt_fsm : 1;
+ uint32_t _reserved0 : 31;
+#else
+ uint32_t _reserved0 : 31;
+ uint32_t spivid_halt_fsm : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_spiv_command_reg_t;
+
+
+
+typedef union pmc_o2s_ctrl_reg0a {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_frame_size : 6;
+ uint32_t o2s_out_count1 : 6;
+ uint32_t o2s_in_delay1 : 6;
+ uint32_t o2s_in_count1 : 6;
+ uint32_t _reserved0 : 8;
+#else
+ uint32_t _reserved0 : 8;
+ uint32_t o2s_in_count1 : 6;
+ uint32_t o2s_in_delay1 : 6;
+ uint32_t o2s_out_count1 : 6;
+ uint32_t o2s_frame_size : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_ctrl_reg0a_t;
+
+
+
+typedef union pmc_o2s_ctrl_reg0b {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_out_count2 : 6;
+ uint32_t o2s_in_delay2 : 6;
+ uint32_t o2s_in_count2 : 6;
+ uint32_t _reserved0 : 14;
+#else
+ uint32_t _reserved0 : 14;
+ uint32_t o2s_in_count2 : 6;
+ uint32_t o2s_in_delay2 : 6;
+ uint32_t o2s_out_count2 : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_ctrl_reg0b_t;
+
+
+
+typedef union pmc_o2s_ctrl_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_bridge_enable : 1;
+ uint32_t pmcocr1_reserved_1 : 1;
+ uint32_t o2s_cpol : 1;
+ uint32_t o2s_cpha : 1;
+ uint32_t o2s_clock_divider : 10;
+ uint32_t pmcocr1_reserved_2 : 3;
+ uint32_t o2s_nr_of_frames : 1;
+ uint32_t o2s_port_enable : 3;
+ uint32_t _reserved0 : 11;
+#else
+ uint32_t _reserved0 : 11;
+ uint32_t o2s_port_enable : 3;
+ uint32_t o2s_nr_of_frames : 1;
+ uint32_t pmcocr1_reserved_2 : 3;
+ uint32_t o2s_clock_divider : 10;
+ uint32_t o2s_cpha : 1;
+ uint32_t o2s_cpol : 1;
+ uint32_t pmcocr1_reserved_1 : 1;
+ uint32_t o2s_bridge_enable : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_ctrl_reg1_t;
+
+
+
+typedef union pmc_o2s_ctrl_reg2 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_inter_frame_delay : 17;
+ uint32_t _reserved0 : 15;
+#else
+ uint32_t _reserved0 : 15;
+ uint32_t o2s_inter_frame_delay : 17;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_ctrl_reg2_t;
+
+
+
+typedef union pmc_o2s_ctrl_reg4 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_crc_gen_en : 1;
+ uint32_t o2s_crc_check_en : 1;
+ uint32_t o2s_majority_vote_en : 1;
+ uint32_t o2s_max_retries : 5;
+ uint32_t pmcocr4_reserved8_15 : 8;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t pmcocr4_reserved8_15 : 8;
+ uint32_t o2s_max_retries : 5;
+ uint32_t o2s_majority_vote_en : 1;
+ uint32_t o2s_crc_check_en : 1;
+ uint32_t o2s_crc_gen_en : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_ctrl_reg4_t;
+
+
+
+typedef union pmc_o2s_status_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_ongoing : 1;
+ uint32_t o2s_crc_error0 : 1;
+ uint32_t o2s_crc_error1 : 1;
+ uint32_t o2s_crc_error2 : 1;
+ uint32_t o2s_retry_timeout : 1;
+ uint32_t o2s_write_while_bridge_busy_err : 1;
+ uint32_t pmcosr_reserved_6 : 1;
+ uint32_t o2s_fsm_err : 1;
+ uint32_t o2s_majority_detected_a_minority0 : 1;
+ uint32_t o2s_majority_detected_a_minority1 : 1;
+ uint32_t o2s_majority_detected_a_minority2 : 1;
+ uint32_t o2s_majority_nr_of_minorities0 : 4;
+ uint32_t o2s_majority_nr_of_minorities1 : 4;
+ uint32_t o2s_majority_nr_of_minorities2 : 4;
+ uint32_t _reserved0 : 9;
+#else
+ uint32_t _reserved0 : 9;
+ uint32_t o2s_majority_nr_of_minorities2 : 4;
+ uint32_t o2s_majority_nr_of_minorities1 : 4;
+ uint32_t o2s_majority_nr_of_minorities0 : 4;
+ uint32_t o2s_majority_detected_a_minority2 : 1;
+ uint32_t o2s_majority_detected_a_minority1 : 1;
+ uint32_t o2s_majority_detected_a_minority0 : 1;
+ uint32_t o2s_fsm_err : 1;
+ uint32_t pmcosr_reserved_6 : 1;
+ uint32_t o2s_write_while_bridge_busy_err : 1;
+ uint32_t o2s_retry_timeout : 1;
+ uint32_t o2s_crc_error2 : 1;
+ uint32_t o2s_crc_error1 : 1;
+ uint32_t o2s_crc_error0 : 1;
+ uint32_t o2s_ongoing : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_status_reg_t;
+
+
+
+typedef union pmc_o2s_command_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_halt_retries : 1;
+ uint32_t o2s_clear_sticky_bits : 1;
+ uint32_t _reserved0 : 30;
+#else
+ uint32_t _reserved0 : 30;
+ uint32_t o2s_clear_sticky_bits : 1;
+ uint32_t o2s_halt_retries : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_command_reg_t;
+
+
+
+typedef union pmc_o2s_wdata_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_wdata : 32;
+#else
+ uint32_t o2s_wdata : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_wdata_reg_t;
+
+
+
+typedef union pmc_o2s_rdata_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2s_rdata : 32;
+#else
+ uint32_t o2s_rdata : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2s_rdata_reg_t;
+
+
+
+typedef union pmc_o2p_addr_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2p_write_plus_read : 1;
+ uint32_t o2p_mc : 1;
+ uint32_t o2p_slave_addr : 6;
+ uint32_t o2p_read_not_write : 1;
+ uint32_t reserved_bit_pmco2par2 : 3;
+ uint32_t o2p_pcb_port : 4;
+ uint32_t o2p_pcb_reg_addr : 16;
+#else
+ uint32_t o2p_pcb_reg_addr : 16;
+ uint32_t o2p_pcb_port : 4;
+ uint32_t reserved_bit_pmco2par2 : 3;
+ uint32_t o2p_read_not_write : 1;
+ uint32_t o2p_slave_addr : 6;
+ uint32_t o2p_mc : 1;
+ uint32_t o2p_write_plus_read : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2p_addr_reg_t;
+
+
+
+typedef union pmc_o2p_ctrl_status_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2p_ongoing : 1;
+ uint32_t o2p_scresp : 3;
+ uint32_t o2p_write_while_bridge_busy_err : 1;
+ uint32_t o2p_fsm_err : 1;
+ uint32_t o2p_abort : 1;
+ uint32_t o2p_parity_error : 1;
+ uint32_t o2p_clear_sticky_bits : 1;
+ uint32_t _reserved0 : 23;
+#else
+ uint32_t _reserved0 : 23;
+ uint32_t o2p_clear_sticky_bits : 1;
+ uint32_t o2p_parity_error : 1;
+ uint32_t o2p_abort : 1;
+ uint32_t o2p_fsm_err : 1;
+ uint32_t o2p_write_while_bridge_busy_err : 1;
+ uint32_t o2p_scresp : 3;
+ uint32_t o2p_ongoing : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2p_ctrl_status_reg_t;
+
+
+
+typedef union pmc_o2p_send_data_hi_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2p_send_data_hi : 32;
+#else
+ uint32_t o2p_send_data_hi : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2p_send_data_hi_reg_t;
+
+
+
+typedef union pmc_o2p_send_data_lo_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2p_send_data_lo : 32;
+#else
+ uint32_t o2p_send_data_lo : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2p_send_data_lo_reg_t;
+
+
+
+typedef union pmc_o2p_recv_data_hi_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2p_receive_data_hi : 32;
+#else
+ uint32_t o2p_receive_data_hi : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2p_recv_data_hi_reg_t;
+
+
+
+typedef union pmc_o2p_recv_data_lo_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t o2p_receive_data_lo : 32;
+#else
+ uint32_t o2p_receive_data_lo : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_o2p_recv_data_lo_reg_t;
+
+
+
+typedef union pmc_occ_heartbeat_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pmc_occ_heartbeat_time : 16;
+ uint32_t pmc_occ_heartbeat_en : 1;
+ uint32_t _reserved0 : 15;
+#else
+ uint32_t _reserved0 : 15;
+ uint32_t pmc_occ_heartbeat_en : 1;
+ uint32_t pmc_occ_heartbeat_time : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_occ_heartbeat_reg_t;
+
+
+
+typedef union pmc_error_int_mask_hi_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pmc_error_int_mask_hi : 32;
+#else
+ uint32_t pmc_error_int_mask_hi : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_error_int_mask_hi_reg_t;
+
+
+
+typedef union pmc_error_int_mask_lo_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pmc_error_int_mask_lo : 32;
+#else
+ uint32_t pmc_error_int_mask_lo : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_error_int_mask_lo_reg_t;
+
+
+
+typedef union pmc_idle_suspend_mask_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pmc_idle_suspend_mask : 16;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t pmc_idle_suspend_mask : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_idle_suspend_mask_reg_t;
+
+
+
+typedef union pmc_pend_idle_req_reg0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t idle_pending_0 : 1;
+ uint32_t idle_op_0 : 2;
+ uint32_t idle_type_0 : 1;
+ uint32_t idle_scope_0 : 1;
+ uint32_t assist_mode_0 : 1;
+ uint32_t reserved_pirr_0 : 2;
+ uint32_t idle_pending_1 : 1;
+ uint32_t idle_op_1 : 2;
+ uint32_t idle_type_1 : 1;
+ uint32_t idle_scope_1 : 1;
+ uint32_t assist_mode_1 : 1;
+ uint32_t reserved_pirr_1 : 2;
+ uint32_t idle_pending_2 : 1;
+ uint32_t idle_op_2 : 2;
+ uint32_t idle_type_2 : 1;
+ uint32_t idle_scope_2 : 1;
+ uint32_t assist_mode_2 : 1;
+ uint32_t reserved_pirr_2 : 2;
+ uint32_t idle_pending_3 : 1;
+ uint32_t idle_op_3 : 2;
+ uint32_t idle_type_3 : 1;
+ uint32_t idle_scope_3 : 1;
+ uint32_t assist_mode_3 : 1;
+ uint32_t reserved_pirr_3 : 2;
+#else
+ uint32_t reserved_pirr_3 : 2;
+ uint32_t assist_mode_3 : 1;
+ uint32_t idle_scope_3 : 1;
+ uint32_t idle_type_3 : 1;
+ uint32_t idle_op_3 : 2;
+ uint32_t idle_pending_3 : 1;
+ uint32_t reserved_pirr_2 : 2;
+ uint32_t assist_mode_2 : 1;
+ uint32_t idle_scope_2 : 1;
+ uint32_t idle_type_2 : 1;
+ uint32_t idle_op_2 : 2;
+ uint32_t idle_pending_2 : 1;
+ uint32_t reserved_pirr_1 : 2;
+ uint32_t assist_mode_1 : 1;
+ uint32_t idle_scope_1 : 1;
+ uint32_t idle_type_1 : 1;
+ uint32_t idle_op_1 : 2;
+ uint32_t idle_pending_1 : 1;
+ uint32_t reserved_pirr_0 : 2;
+ uint32_t assist_mode_0 : 1;
+ uint32_t idle_scope_0 : 1;
+ uint32_t idle_type_0 : 1;
+ uint32_t idle_op_0 : 2;
+ uint32_t idle_pending_0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pend_idle_req_reg0_t;
+
+
+
+typedef union pmc_pend_idle_req_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t idle_pending_4 : 1;
+ uint32_t idle_op_4 : 2;
+ uint32_t idle_type_4 : 1;
+ uint32_t idle_scope_4 : 1;
+ uint32_t assist_mode_4 : 1;
+ uint32_t reserved_pirr_4 : 2;
+ uint32_t idle_pending_5 : 1;
+ uint32_t idle_op_5 : 2;
+ uint32_t idle_type_5 : 1;
+ uint32_t idle_scope_5 : 1;
+ uint32_t assist_mode_5 : 1;
+ uint32_t reserved_pirr_5 : 2;
+ uint32_t idle_pending_6 : 1;
+ uint32_t idle_op_6 : 2;
+ uint32_t idle_type_6 : 1;
+ uint32_t idle_scope_6 : 1;
+ uint32_t assist_mode_6 : 1;
+ uint32_t reserved_pirr_6 : 2;
+ uint32_t idle_pending_7 : 1;
+ uint32_t idle_op_7 : 2;
+ uint32_t idle_type_7 : 1;
+ uint32_t idle_scope_7 : 1;
+ uint32_t assist_mode_7 : 1;
+ uint32_t reserved_pirr_7 : 2;
+#else
+ uint32_t reserved_pirr_7 : 2;
+ uint32_t assist_mode_7 : 1;
+ uint32_t idle_scope_7 : 1;
+ uint32_t idle_type_7 : 1;
+ uint32_t idle_op_7 : 2;
+ uint32_t idle_pending_7 : 1;
+ uint32_t reserved_pirr_6 : 2;
+ uint32_t assist_mode_6 : 1;
+ uint32_t idle_scope_6 : 1;
+ uint32_t idle_type_6 : 1;
+ uint32_t idle_op_6 : 2;
+ uint32_t idle_pending_6 : 1;
+ uint32_t reserved_pirr_5 : 2;
+ uint32_t assist_mode_5 : 1;
+ uint32_t idle_scope_5 : 1;
+ uint32_t idle_type_5 : 1;
+ uint32_t idle_op_5 : 2;
+ uint32_t idle_pending_5 : 1;
+ uint32_t reserved_pirr_4 : 2;
+ uint32_t assist_mode_4 : 1;
+ uint32_t idle_scope_4 : 1;
+ uint32_t idle_type_4 : 1;
+ uint32_t idle_op_4 : 2;
+ uint32_t idle_pending_4 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pend_idle_req_reg1_t;
+
+
+
+typedef union pmc_pend_idle_req_reg2 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t idle_pending_8 : 1;
+ uint32_t idle_op_8 : 2;
+ uint32_t idle_type_8 : 1;
+ uint32_t idle_scope_8 : 1;
+ uint32_t assist_mode_8 : 1;
+ uint32_t reserved_pirr_8 : 2;
+ uint32_t idle_pending_9 : 1;
+ uint32_t idle_op_9 : 2;
+ uint32_t idle_type_9 : 1;
+ uint32_t idle_scope_9 : 1;
+ uint32_t assist_mode_9 : 1;
+ uint32_t reserved_pirr_9 : 2;
+ uint32_t idle_pending_10 : 1;
+ uint32_t idle_op_10 : 2;
+ uint32_t idle_type_10 : 1;
+ uint32_t idle_scope_10 : 1;
+ uint32_t assist_mode_10 : 1;
+ uint32_t reserved_pirr_10 : 2;
+ uint32_t idle_pending_11 : 1;
+ uint32_t idle_op_11 : 2;
+ uint32_t idle_type_11 : 1;
+ uint32_t idle_scope_11 : 1;
+ uint32_t assist_mode_11 : 1;
+ uint32_t reserved_pirr_11 : 2;
+#else
+ uint32_t reserved_pirr_11 : 2;
+ uint32_t assist_mode_11 : 1;
+ uint32_t idle_scope_11 : 1;
+ uint32_t idle_type_11 : 1;
+ uint32_t idle_op_11 : 2;
+ uint32_t idle_pending_11 : 1;
+ uint32_t reserved_pirr_10 : 2;
+ uint32_t assist_mode_10 : 1;
+ uint32_t idle_scope_10 : 1;
+ uint32_t idle_type_10 : 1;
+ uint32_t idle_op_10 : 2;
+ uint32_t idle_pending_10 : 1;
+ uint32_t reserved_pirr_9 : 2;
+ uint32_t assist_mode_9 : 1;
+ uint32_t idle_scope_9 : 1;
+ uint32_t idle_type_9 : 1;
+ uint32_t idle_op_9 : 2;
+ uint32_t idle_pending_9 : 1;
+ uint32_t reserved_pirr_8 : 2;
+ uint32_t assist_mode_8 : 1;
+ uint32_t idle_scope_8 : 1;
+ uint32_t idle_type_8 : 1;
+ uint32_t idle_op_8 : 2;
+ uint32_t idle_pending_8 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pend_idle_req_reg2_t;
+
+
+
+typedef union pmc_pend_idle_req_reg3 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t idle_pending_12 : 1;
+ uint32_t idle_op_12 : 2;
+ uint32_t idle_type_12 : 1;
+ uint32_t idle_scope_12 : 1;
+ uint32_t assist_mode_12 : 1;
+ uint32_t reserved_pirr_12 : 2;
+ uint32_t idle_pending_13 : 1;
+ uint32_t idle_op_13 : 2;
+ uint32_t idle_type_13 : 1;
+ uint32_t idle_scope_13 : 1;
+ uint32_t assist_mode_13 : 1;
+ uint32_t reserved_pirr_13 : 2;
+ uint32_t idle_pending_14 : 1;
+ uint32_t idle_op_14 : 2;
+ uint32_t idle_type_14 : 1;
+ uint32_t idle_scope_14 : 1;
+ uint32_t assist_mode_14 : 1;
+ uint32_t reserved_pirr_14 : 2;
+ uint32_t idle_pending_15 : 1;
+ uint32_t idle_op_15 : 2;
+ uint32_t idle_type_15 : 1;
+ uint32_t idle_scope_15 : 1;
+ uint32_t assist_mode_15 : 1;
+ uint32_t reserved_pirr_15 : 2;
+#else
+ uint32_t reserved_pirr_15 : 2;
+ uint32_t assist_mode_15 : 1;
+ uint32_t idle_scope_15 : 1;
+ uint32_t idle_type_15 : 1;
+ uint32_t idle_op_15 : 2;
+ uint32_t idle_pending_15 : 1;
+ uint32_t reserved_pirr_14 : 2;
+ uint32_t assist_mode_14 : 1;
+ uint32_t idle_scope_14 : 1;
+ uint32_t idle_type_14 : 1;
+ uint32_t idle_op_14 : 2;
+ uint32_t idle_pending_14 : 1;
+ uint32_t reserved_pirr_13 : 2;
+ uint32_t assist_mode_13 : 1;
+ uint32_t idle_scope_13 : 1;
+ uint32_t idle_type_13 : 1;
+ uint32_t idle_op_13 : 2;
+ uint32_t idle_pending_13 : 1;
+ uint32_t reserved_pirr_12 : 2;
+ uint32_t assist_mode_12 : 1;
+ uint32_t idle_scope_12 : 1;
+ uint32_t idle_type_12 : 1;
+ uint32_t idle_op_12 : 2;
+ uint32_t idle_pending_12 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pend_idle_req_reg3_t;
+
+
+
+typedef union pmc_sleep_int_req_vec_reg0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t fastsleepentry_int_req_vec : 32;
+#else
+ uint32_t fastsleepentry_int_req_vec : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_sleep_int_req_vec_reg0_t;
+
+
+
+typedef union pmc_sleep_int_req_vec_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t deepsleepentry_int_req_vec : 32;
+#else
+ uint32_t deepsleepentry_int_req_vec : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_sleep_int_req_vec_reg1_t;
+
+
+
+typedef union pmc_sleep_int_req_vec_reg2 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t fastsleepexit_int_req_vec : 32;
+#else
+ uint32_t fastsleepexit_int_req_vec : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_sleep_int_req_vec_reg2_t;
+
+
+
+typedef union pmc_sleep_int_req_vec_reg3 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t deepsleepexit_int_req_vec : 32;
+#else
+ uint32_t deepsleepexit_int_req_vec : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_sleep_int_req_vec_reg3_t;
+
+
+
+typedef union pmc_winkle_int_req_vec_reg0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t fastwinkleentry_int_req_vec : 32;
+#else
+ uint32_t fastwinkleentry_int_req_vec : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_winkle_int_req_vec_reg0_t;
+
+
+
+typedef union pmc_winkle_int_req_vec_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t deepwinkleentry_int_req_vec : 32;
+#else
+ uint32_t deepwinkleentry_int_req_vec : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_winkle_int_req_vec_reg1_t;
+
+
+
+typedef union pmc_winkle_int_req_vec_reg2 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t fastwinkleexit_int_req_vec : 32;
+#else
+ uint32_t fastwinkleexit_int_req_vec : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_winkle_int_req_vec_reg2_t;
+
+
+
+typedef union pmc_winkle_int_req_vec_reg3 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t deepwinkleexit_int_req_vec : 32;
+#else
+ uint32_t deepwinkleexit_int_req_vec : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_winkle_int_req_vec_reg3_t;
+
+
+
+typedef union pmc_nap_int_req_vec_reg0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t napentry_int_req_vec : 16;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t napentry_int_req_vec : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_nap_int_req_vec_reg0_t;
+
+
+
+typedef union pmc_nap_int_req_vec_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t napexit_int_req_vec : 25;
+ uint32_t _reserved0 : 7;
+#else
+ uint32_t _reserved0 : 7;
+ uint32_t napexit_int_req_vec : 25;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_nap_int_req_vec_reg1_t;
+
+
+
+typedef union pmc_pore_req_reg0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t porrr_reserved0 : 8;
+ uint32_t porrr_start_vector : 4;
+ uint32_t porrr_reserved1 : 8;
+ uint32_t porrr_pore_busy : 1;
+ uint32_t porrr_pore_suspended : 1;
+ uint32_t porrr_porrtc_busy : 1;
+ uint32_t _reserved0 : 9;
+#else
+ uint32_t _reserved0 : 9;
+ uint32_t porrr_porrtc_busy : 1;
+ uint32_t porrr_pore_suspended : 1;
+ uint32_t porrr_pore_busy : 1;
+ uint32_t porrr_reserved1 : 8;
+ uint32_t porrr_start_vector : 4;
+ uint32_t porrr_reserved0 : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pore_req_reg0_t;
+
+
+
+typedef union pmc_pore_req_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t porrr_chiplet_enable_0 : 1;
+ uint32_t porrr_chiplet_enable_1 : 1;
+ uint32_t porrr_chiplet_enable_2 : 1;
+ uint32_t porrr_chiplet_enable_3 : 1;
+ uint32_t porrr_chiplet_enable_4 : 1;
+ uint32_t porrr_chiplet_enable_5 : 1;
+ uint32_t porrr_chiplet_enable_6 : 1;
+ uint32_t porrr_chiplet_enable_7 : 1;
+ uint32_t porrr_chiplet_enable_8 : 1;
+ uint32_t porrr_chiplet_enable_9 : 1;
+ uint32_t porrr_chiplet_enable_10 : 1;
+ uint32_t porrr_chiplet_enable_11 : 1;
+ uint32_t porrr_chiplet_enable_12 : 1;
+ uint32_t porrr_chiplet_enable_13 : 1;
+ uint32_t porrr_chiplet_enable_14 : 1;
+ uint32_t porrr_chiplet_enable_15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t porrr_chiplet_enable_15 : 1;
+ uint32_t porrr_chiplet_enable_14 : 1;
+ uint32_t porrr_chiplet_enable_13 : 1;
+ uint32_t porrr_chiplet_enable_12 : 1;
+ uint32_t porrr_chiplet_enable_11 : 1;
+ uint32_t porrr_chiplet_enable_10 : 1;
+ uint32_t porrr_chiplet_enable_9 : 1;
+ uint32_t porrr_chiplet_enable_8 : 1;
+ uint32_t porrr_chiplet_enable_7 : 1;
+ uint32_t porrr_chiplet_enable_6 : 1;
+ uint32_t porrr_chiplet_enable_5 : 1;
+ uint32_t porrr_chiplet_enable_4 : 1;
+ uint32_t porrr_chiplet_enable_3 : 1;
+ uint32_t porrr_chiplet_enable_2 : 1;
+ uint32_t porrr_chiplet_enable_1 : 1;
+ uint32_t porrr_chiplet_enable_0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pore_req_reg1_t;
+
+
+
+typedef union pmc_pore_req_stat_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t porrs_reserved0 : 8;
+ uint32_t porrs_start_vector : 4;
+ uint32_t pore_rc : 8;
+ uint32_t porrs_reserved1 : 1;
+ uint32_t porrs_recovery_write : 1;
+ uint32_t _reserved0 : 10;
+#else
+ uint32_t _reserved0 : 10;
+ uint32_t porrs_recovery_write : 1;
+ uint32_t porrs_reserved1 : 1;
+ uint32_t pore_rc : 8;
+ uint32_t porrs_start_vector : 4;
+ uint32_t porrs_reserved0 : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pore_req_stat_reg_t;
+
+
+
+typedef union pmc_pore_req_tout_th_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t porrtt_timeout_threshold : 8;
+ uint32_t porrtc_no_predivide : 1;
+ uint32_t _reserved0 : 23;
+#else
+ uint32_t _reserved0 : 23;
+ uint32_t porrtc_no_predivide : 1;
+ uint32_t porrtt_timeout_threshold : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pore_req_tout_th_reg_t;
+
+
+
+typedef union pmc_deep_exit_mask_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t chiplet_deep_exit_mask0 : 1;
+ uint32_t chiplet_deep_exit_mask1 : 1;
+ uint32_t chiplet_deep_exit_mask2 : 1;
+ uint32_t chiplet_deep_exit_mask3 : 1;
+ uint32_t chiplet_deep_exit_mask4 : 1;
+ uint32_t chiplet_deep_exit_mask5 : 1;
+ uint32_t chiplet_deep_exit_mask6 : 1;
+ uint32_t chiplet_deep_exit_mask7 : 1;
+ uint32_t chiplet_deep_exit_mask8 : 1;
+ uint32_t chiplet_deep_exit_mask9 : 1;
+ uint32_t chiplet_deep_exit_mask10 : 1;
+ uint32_t chiplet_deep_exit_mask11 : 1;
+ uint32_t chiplet_deep_exit_mask12 : 1;
+ uint32_t chiplet_deep_exit_mask13 : 1;
+ uint32_t chiplet_deep_exit_mask14 : 1;
+ uint32_t chiplet_deep_exit_mask15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t chiplet_deep_exit_mask15 : 1;
+ uint32_t chiplet_deep_exit_mask14 : 1;
+ uint32_t chiplet_deep_exit_mask13 : 1;
+ uint32_t chiplet_deep_exit_mask12 : 1;
+ uint32_t chiplet_deep_exit_mask11 : 1;
+ uint32_t chiplet_deep_exit_mask10 : 1;
+ uint32_t chiplet_deep_exit_mask9 : 1;
+ uint32_t chiplet_deep_exit_mask8 : 1;
+ uint32_t chiplet_deep_exit_mask7 : 1;
+ uint32_t chiplet_deep_exit_mask6 : 1;
+ uint32_t chiplet_deep_exit_mask5 : 1;
+ uint32_t chiplet_deep_exit_mask4 : 1;
+ uint32_t chiplet_deep_exit_mask3 : 1;
+ uint32_t chiplet_deep_exit_mask2 : 1;
+ uint32_t chiplet_deep_exit_mask1 : 1;
+ uint32_t chiplet_deep_exit_mask0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_deep_exit_mask_reg_t;
+
+
+
+typedef union pmc_deep_exit_mask_reg_and {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t chiplet_deep_exit_mask0 : 1;
+ uint32_t chiplet_deep_exit_mask1 : 1;
+ uint32_t chiplet_deep_exit_mask2 : 1;
+ uint32_t chiplet_deep_exit_mask3 : 1;
+ uint32_t chiplet_deep_exit_mask4 : 1;
+ uint32_t chiplet_deep_exit_mask5 : 1;
+ uint32_t chiplet_deep_exit_mask6 : 1;
+ uint32_t chiplet_deep_exit_mask7 : 1;
+ uint32_t chiplet_deep_exit_mask8 : 1;
+ uint32_t chiplet_deep_exit_mask9 : 1;
+ uint32_t chiplet_deep_exit_mask10 : 1;
+ uint32_t chiplet_deep_exit_mask11 : 1;
+ uint32_t chiplet_deep_exit_mask12 : 1;
+ uint32_t chiplet_deep_exit_mask13 : 1;
+ uint32_t chiplet_deep_exit_mask14 : 1;
+ uint32_t chiplet_deep_exit_mask15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t chiplet_deep_exit_mask15 : 1;
+ uint32_t chiplet_deep_exit_mask14 : 1;
+ uint32_t chiplet_deep_exit_mask13 : 1;
+ uint32_t chiplet_deep_exit_mask12 : 1;
+ uint32_t chiplet_deep_exit_mask11 : 1;
+ uint32_t chiplet_deep_exit_mask10 : 1;
+ uint32_t chiplet_deep_exit_mask9 : 1;
+ uint32_t chiplet_deep_exit_mask8 : 1;
+ uint32_t chiplet_deep_exit_mask7 : 1;
+ uint32_t chiplet_deep_exit_mask6 : 1;
+ uint32_t chiplet_deep_exit_mask5 : 1;
+ uint32_t chiplet_deep_exit_mask4 : 1;
+ uint32_t chiplet_deep_exit_mask3 : 1;
+ uint32_t chiplet_deep_exit_mask2 : 1;
+ uint32_t chiplet_deep_exit_mask1 : 1;
+ uint32_t chiplet_deep_exit_mask0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_deep_exit_mask_reg_and_t;
+
+
+
+typedef union pmc_deep_exit_mask_reg_or {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t chiplet_deep_exit_mask0 : 1;
+ uint32_t chiplet_deep_exit_mask1 : 1;
+ uint32_t chiplet_deep_exit_mask2 : 1;
+ uint32_t chiplet_deep_exit_mask3 : 1;
+ uint32_t chiplet_deep_exit_mask4 : 1;
+ uint32_t chiplet_deep_exit_mask5 : 1;
+ uint32_t chiplet_deep_exit_mask6 : 1;
+ uint32_t chiplet_deep_exit_mask7 : 1;
+ uint32_t chiplet_deep_exit_mask8 : 1;
+ uint32_t chiplet_deep_exit_mask9 : 1;
+ uint32_t chiplet_deep_exit_mask10 : 1;
+ uint32_t chiplet_deep_exit_mask11 : 1;
+ uint32_t chiplet_deep_exit_mask12 : 1;
+ uint32_t chiplet_deep_exit_mask13 : 1;
+ uint32_t chiplet_deep_exit_mask14 : 1;
+ uint32_t chiplet_deep_exit_mask15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t chiplet_deep_exit_mask15 : 1;
+ uint32_t chiplet_deep_exit_mask14 : 1;
+ uint32_t chiplet_deep_exit_mask13 : 1;
+ uint32_t chiplet_deep_exit_mask12 : 1;
+ uint32_t chiplet_deep_exit_mask11 : 1;
+ uint32_t chiplet_deep_exit_mask10 : 1;
+ uint32_t chiplet_deep_exit_mask9 : 1;
+ uint32_t chiplet_deep_exit_mask8 : 1;
+ uint32_t chiplet_deep_exit_mask7 : 1;
+ uint32_t chiplet_deep_exit_mask6 : 1;
+ uint32_t chiplet_deep_exit_mask5 : 1;
+ uint32_t chiplet_deep_exit_mask4 : 1;
+ uint32_t chiplet_deep_exit_mask3 : 1;
+ uint32_t chiplet_deep_exit_mask2 : 1;
+ uint32_t chiplet_deep_exit_mask1 : 1;
+ uint32_t chiplet_deep_exit_mask0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_deep_exit_mask_reg_or_t;
+
+
+
+typedef union pmc_core_pstate_reg0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t pstate_core0 : 8;
+ int32_t pstate_core1 : 8;
+ int32_t pstate_core2 : 8;
+ int32_t pstate_core3 : 8;
+#else
+ int32_t pstate_core3 : 8;
+ int32_t pstate_core2 : 8;
+ int32_t pstate_core1 : 8;
+ int32_t pstate_core0 : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_core_pstate_reg0_t;
+
+
+
+typedef union pmc_core_pstate_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t pstate_core4 : 8;
+ int32_t pstate_core5 : 8;
+ int32_t pstate_core6 : 8;
+ int32_t pstate_core7 : 8;
+#else
+ int32_t pstate_core7 : 8;
+ int32_t pstate_core6 : 8;
+ int32_t pstate_core5 : 8;
+ int32_t pstate_core4 : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_core_pstate_reg1_t;
+
+
+
+typedef union pmc_core_pstate_reg2 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t pstate_core8 : 8;
+ int32_t pstate_core9 : 8;
+ int32_t pstate_core10 : 8;
+ int32_t pstate_core11 : 8;
+#else
+ int32_t pstate_core11 : 8;
+ int32_t pstate_core10 : 8;
+ int32_t pstate_core9 : 8;
+ int32_t pstate_core8 : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_core_pstate_reg2_t;
+
+
+
+typedef union pmc_core_pstate_reg3 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ int32_t pstate_core12 : 8;
+ int32_t pstate_core13 : 8;
+ int32_t pstate_core14 : 8;
+ int32_t pstate_core15 : 8;
+#else
+ int32_t pstate_core15 : 8;
+ int32_t pstate_core14 : 8;
+ int32_t pstate_core13 : 8;
+ int32_t pstate_core12 : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_core_pstate_reg3_t;
+
+
+
+typedef union pmc_core_power_donation_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t power_donation_core0 : 1;
+ uint32_t power_donation_core1 : 1;
+ uint32_t power_donation_core2 : 1;
+ uint32_t power_donation_core3 : 1;
+ uint32_t power_donation_core4 : 1;
+ uint32_t power_donation_core5 : 1;
+ uint32_t power_donation_core6 : 1;
+ uint32_t power_donation_core7 : 1;
+ uint32_t power_donation_core8 : 1;
+ uint32_t power_donation_core9 : 1;
+ uint32_t power_donation_core10 : 1;
+ uint32_t power_donation_core11 : 1;
+ uint32_t power_donation_core12 : 1;
+ uint32_t power_donation_core13 : 1;
+ uint32_t power_donation_core14 : 1;
+ uint32_t power_donation_core15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t power_donation_core15 : 1;
+ uint32_t power_donation_core14 : 1;
+ uint32_t power_donation_core13 : 1;
+ uint32_t power_donation_core12 : 1;
+ uint32_t power_donation_core11 : 1;
+ uint32_t power_donation_core10 : 1;
+ uint32_t power_donation_core9 : 1;
+ uint32_t power_donation_core8 : 1;
+ uint32_t power_donation_core7 : 1;
+ uint32_t power_donation_core6 : 1;
+ uint32_t power_donation_core5 : 1;
+ uint32_t power_donation_core4 : 1;
+ uint32_t power_donation_core3 : 1;
+ uint32_t power_donation_core2 : 1;
+ uint32_t power_donation_core1 : 1;
+ uint32_t power_donation_core0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_core_power_donation_reg_t;
+
+
+
+typedef union pmc_pmax_sync_collection_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pmax_sync0 : 1;
+ uint32_t pmax_sync1 : 1;
+ uint32_t pmax_sync2 : 1;
+ uint32_t pmax_sync3 : 1;
+ uint32_t pmax_sync4 : 1;
+ uint32_t pmax_sync5 : 1;
+ uint32_t pmax_sync6 : 1;
+ uint32_t pmax_sync7 : 1;
+ uint32_t pmax_sync8 : 1;
+ uint32_t pmax_sync9 : 1;
+ uint32_t pmax_sync10 : 1;
+ uint32_t pmax_sync11 : 1;
+ uint32_t pmax_sync12 : 1;
+ uint32_t pmax_sync13 : 1;
+ uint32_t pmax_sync14 : 1;
+ uint32_t pmax_sync15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t pmax_sync15 : 1;
+ uint32_t pmax_sync14 : 1;
+ uint32_t pmax_sync13 : 1;
+ uint32_t pmax_sync12 : 1;
+ uint32_t pmax_sync11 : 1;
+ uint32_t pmax_sync10 : 1;
+ uint32_t pmax_sync9 : 1;
+ uint32_t pmax_sync8 : 1;
+ uint32_t pmax_sync7 : 1;
+ uint32_t pmax_sync6 : 1;
+ uint32_t pmax_sync5 : 1;
+ uint32_t pmax_sync4 : 1;
+ uint32_t pmax_sync3 : 1;
+ uint32_t pmax_sync2 : 1;
+ uint32_t pmax_sync1 : 1;
+ uint32_t pmax_sync0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pmax_sync_collection_reg_t;
+
+
+
+typedef union pmc_pmax_sync_collection_mask_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t pmax_sync_mask0 : 1;
+ uint32_t pmax_sync_mask1 : 1;
+ uint32_t pmax_sync_mask2 : 1;
+ uint32_t pmax_sync_mask3 : 1;
+ uint32_t pmax_sync_mask4 : 1;
+ uint32_t pmax_sync_mask5 : 1;
+ uint32_t pmax_sync_mask6 : 1;
+ uint32_t pmax_sync_mask7 : 1;
+ uint32_t pmax_sync_mask8 : 1;
+ uint32_t pmax_sync_mask9 : 1;
+ uint32_t pmax_sync_mask10 : 1;
+ uint32_t pmax_sync_mask11 : 1;
+ uint32_t pmax_sync_mask12 : 1;
+ uint32_t pmax_sync_mask13 : 1;
+ uint32_t pmax_sync_mask14 : 1;
+ uint32_t pmax_sync_mask15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t pmax_sync_mask15 : 1;
+ uint32_t pmax_sync_mask14 : 1;
+ uint32_t pmax_sync_mask13 : 1;
+ uint32_t pmax_sync_mask12 : 1;
+ uint32_t pmax_sync_mask11 : 1;
+ uint32_t pmax_sync_mask10 : 1;
+ uint32_t pmax_sync_mask9 : 1;
+ uint32_t pmax_sync_mask8 : 1;
+ uint32_t pmax_sync_mask7 : 1;
+ uint32_t pmax_sync_mask6 : 1;
+ uint32_t pmax_sync_mask5 : 1;
+ uint32_t pmax_sync_mask4 : 1;
+ uint32_t pmax_sync_mask3 : 1;
+ uint32_t pmax_sync_mask2 : 1;
+ uint32_t pmax_sync_mask1 : 1;
+ uint32_t pmax_sync_mask0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pmax_sync_collection_mask_reg_t;
+
+
+
+typedef union pmc_gpsa_ack_collection_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t gpsa_ack0 : 1;
+ uint32_t gpsa_ack1 : 1;
+ uint32_t gpsa_ack2 : 1;
+ uint32_t gpsa_ack3 : 1;
+ uint32_t gpsa_ack4 : 1;
+ uint32_t gpsa_ack5 : 1;
+ uint32_t gpsa_ack6 : 1;
+ uint32_t gpsa_ack7 : 1;
+ uint32_t gpsa_ack8 : 1;
+ uint32_t gpsa_ack9 : 1;
+ uint32_t gpsa_ack10 : 1;
+ uint32_t gpsa_ack11 : 1;
+ uint32_t gpsa_ack12 : 1;
+ uint32_t gpsa_ack13 : 1;
+ uint32_t gpsa_ack14 : 1;
+ uint32_t gpsa_ack15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t gpsa_ack15 : 1;
+ uint32_t gpsa_ack14 : 1;
+ uint32_t gpsa_ack13 : 1;
+ uint32_t gpsa_ack12 : 1;
+ uint32_t gpsa_ack11 : 1;
+ uint32_t gpsa_ack10 : 1;
+ uint32_t gpsa_ack9 : 1;
+ uint32_t gpsa_ack8 : 1;
+ uint32_t gpsa_ack7 : 1;
+ uint32_t gpsa_ack6 : 1;
+ uint32_t gpsa_ack5 : 1;
+ uint32_t gpsa_ack4 : 1;
+ uint32_t gpsa_ack3 : 1;
+ uint32_t gpsa_ack2 : 1;
+ uint32_t gpsa_ack1 : 1;
+ uint32_t gpsa_ack0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_gpsa_ack_collection_reg_t;
+
+
+
+typedef union pmc_gpsa_ack_collection_mask_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t gpsa_ack_mask0 : 1;
+ uint32_t gpsa_ack_mask1 : 1;
+ uint32_t gpsa_ack_mask2 : 1;
+ uint32_t gpsa_ack_mask3 : 1;
+ uint32_t gpsa_ack_mask4 : 1;
+ uint32_t gpsa_ack_mask5 : 1;
+ uint32_t gpsa_ack_mask6 : 1;
+ uint32_t gpsa_ack_mask7 : 1;
+ uint32_t gpsa_ack_mask8 : 1;
+ uint32_t gpsa_ack_mask9 : 1;
+ uint32_t gpsa_ack_mask10 : 1;
+ uint32_t gpsa_ack_mask11 : 1;
+ uint32_t gpsa_ack_mask12 : 1;
+ uint32_t gpsa_ack_mask13 : 1;
+ uint32_t gpsa_ack_mask14 : 1;
+ uint32_t gpsa_ack_mask15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t gpsa_ack_mask15 : 1;
+ uint32_t gpsa_ack_mask14 : 1;
+ uint32_t gpsa_ack_mask13 : 1;
+ uint32_t gpsa_ack_mask12 : 1;
+ uint32_t gpsa_ack_mask11 : 1;
+ uint32_t gpsa_ack_mask10 : 1;
+ uint32_t gpsa_ack_mask9 : 1;
+ uint32_t gpsa_ack_mask8 : 1;
+ uint32_t gpsa_ack_mask7 : 1;
+ uint32_t gpsa_ack_mask6 : 1;
+ uint32_t gpsa_ack_mask5 : 1;
+ uint32_t gpsa_ack_mask4 : 1;
+ uint32_t gpsa_ack_mask3 : 1;
+ uint32_t gpsa_ack_mask2 : 1;
+ uint32_t gpsa_ack_mask1 : 1;
+ uint32_t gpsa_ack_mask0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_gpsa_ack_collection_mask_reg_t;
+
+
+
+typedef union pmc_pore_scratch_reg0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t porscr_scratch0 : 32;
+#else
+ uint32_t porscr_scratch0 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pore_scratch_reg0_t;
+
+
+
+typedef union pmc_pore_scratch_reg1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t porscr_scratch1 : 32;
+#else
+ uint32_t porscr_scratch1 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pore_scratch_reg1_t;
+
+
+
+typedef union pmc_deep_idle_exit_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t deep_exit_pending_and_masked_0 : 1;
+ uint32_t deep_exit_pending_and_masked_1 : 1;
+ uint32_t deep_exit_pending_and_masked_2 : 1;
+ uint32_t deep_exit_pending_and_masked_3 : 1;
+ uint32_t deep_exit_pending_and_masked_4 : 1;
+ uint32_t deep_exit_pending_and_masked_5 : 1;
+ uint32_t deep_exit_pending_and_masked_6 : 1;
+ uint32_t deep_exit_pending_and_masked_7 : 1;
+ uint32_t deep_exit_pending_and_masked_8 : 1;
+ uint32_t deep_exit_pending_and_masked_9 : 1;
+ uint32_t deep_exit_pending_and_masked_10 : 1;
+ uint32_t deep_exit_pending_and_masked_11 : 1;
+ uint32_t deep_exit_pending_and_masked_12 : 1;
+ uint32_t deep_exit_pending_and_masked_13 : 1;
+ uint32_t deep_exit_pending_and_masked_14 : 1;
+ uint32_t deep_exit_pending_and_masked_15 : 1;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t deep_exit_pending_and_masked_15 : 1;
+ uint32_t deep_exit_pending_and_masked_14 : 1;
+ uint32_t deep_exit_pending_and_masked_13 : 1;
+ uint32_t deep_exit_pending_and_masked_12 : 1;
+ uint32_t deep_exit_pending_and_masked_11 : 1;
+ uint32_t deep_exit_pending_and_masked_10 : 1;
+ uint32_t deep_exit_pending_and_masked_9 : 1;
+ uint32_t deep_exit_pending_and_masked_8 : 1;
+ uint32_t deep_exit_pending_and_masked_7 : 1;
+ uint32_t deep_exit_pending_and_masked_6 : 1;
+ uint32_t deep_exit_pending_and_masked_5 : 1;
+ uint32_t deep_exit_pending_and_masked_4 : 1;
+ uint32_t deep_exit_pending_and_masked_3 : 1;
+ uint32_t deep_exit_pending_and_masked_2 : 1;
+ uint32_t deep_exit_pending_and_masked_1 : 1;
+ uint32_t deep_exit_pending_and_masked_0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_deep_idle_exit_reg_t;
+
+
+
+typedef union pmc_deep_status_reg {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t deep_idle_state_core0 : 1;
+ uint32_t deep_idle_state_core1 : 1;
+ uint32_t deep_idle_state_core2 : 1;
+ uint32_t deep_idle_state_core3 : 1;
+ uint32_t deep_idle_state_core4 : 1;
+ uint32_t deep_idle_state_core5 : 1;
+ uint32_t deep_idle_state_core6 : 1;
+ uint32_t deep_idle_state_core7 : 1;
+ uint32_t deep_idle_state_core8 : 1;
+ uint32_t deep_idle_state_core9 : 1;
+ uint32_t deep_idle_state_core10 : 1;
+ uint32_t deep_idle_state_core11 : 1;
+ uint32_t deep_idle_state_core12 : 1;
+ uint32_t deep_idle_state_core13 : 1;
+ uint32_t deep_idle_state_core14 : 1;
+ uint32_t deep_idle_state_core15 : 1;
+ uint32_t winkle_state_core0 : 1;
+ uint32_t winkle_state_core1 : 1;
+ uint32_t winkle_state_core2 : 1;
+ uint32_t winkle_state_core3 : 1;
+ uint32_t winkle_state_core4 : 1;
+ uint32_t winkle_state_core5 : 1;
+ uint32_t winkle_state_core6 : 1;
+ uint32_t winkle_state_core7 : 1;
+ uint32_t winkle_state_core8 : 1;
+ uint32_t winkle_state_core9 : 1;
+ uint32_t winkle_state_core10 : 1;
+ uint32_t winkle_state_core11 : 1;
+ uint32_t winkle_state_core12 : 1;
+ uint32_t winkle_state_core13 : 1;
+ uint32_t winkle_state_core14 : 1;
+ uint32_t winkle_state_core15 : 1;
+#else
+ uint32_t winkle_state_core15 : 1;
+ uint32_t winkle_state_core14 : 1;
+ uint32_t winkle_state_core13 : 1;
+ uint32_t winkle_state_core12 : 1;
+ uint32_t winkle_state_core11 : 1;
+ uint32_t winkle_state_core10 : 1;
+ uint32_t winkle_state_core9 : 1;
+ uint32_t winkle_state_core8 : 1;
+ uint32_t winkle_state_core7 : 1;
+ uint32_t winkle_state_core6 : 1;
+ uint32_t winkle_state_core5 : 1;
+ uint32_t winkle_state_core4 : 1;
+ uint32_t winkle_state_core3 : 1;
+ uint32_t winkle_state_core2 : 1;
+ uint32_t winkle_state_core1 : 1;
+ uint32_t winkle_state_core0 : 1;
+ uint32_t deep_idle_state_core15 : 1;
+ uint32_t deep_idle_state_core14 : 1;
+ uint32_t deep_idle_state_core13 : 1;
+ uint32_t deep_idle_state_core12 : 1;
+ uint32_t deep_idle_state_core11 : 1;
+ uint32_t deep_idle_state_core10 : 1;
+ uint32_t deep_idle_state_core9 : 1;
+ uint32_t deep_idle_state_core8 : 1;
+ uint32_t deep_idle_state_core7 : 1;
+ uint32_t deep_idle_state_core6 : 1;
+ uint32_t deep_idle_state_core5 : 1;
+ uint32_t deep_idle_state_core4 : 1;
+ uint32_t deep_idle_state_core3 : 1;
+ uint32_t deep_idle_state_core2 : 1;
+ uint32_t deep_idle_state_core1 : 1;
+ uint32_t deep_idle_state_core0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_deep_status_reg_t;
+
+
+
+typedef union pmc_ba_pore_exe_trigger_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_ba_pore_exe_trigger_reg_t;
+
+
+
+typedef union pmc_pcbs_gaps_brdcast_addr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t value : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_pcbs_gaps_brdcast_addr_t;
+
+
+
+typedef union pmc_lfir_err_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t lfir_pstate_oci_master_rderr : 1;
+ uint64_t lfir_pstate_oci_master_rddata_parity_err : 1;
+ uint64_t lfir_pstate_gpst_checkbyte_err : 1;
+ uint64_t lfir_pstate_gack_to_err : 1;
+ uint64_t lfir_pstate_pib_master_nonoffline_err : 1;
+ uint64_t lfir_pstate_pib_master_offline_err : 1;
+ uint64_t lfir_pstate_oci_master_to_err : 1;
+ uint64_t lfir_pstate_interchip_ue_err : 1;
+ uint64_t lfir_pstate_interchip_errorframe_err : 1;
+ uint64_t lfir_pstate_ms_fsm_err : 1;
+ uint64_t lfir_ms_comp_parity_err : 1;
+ uint64_t lfir_idle_poresw_fatal_err : 1;
+ uint64_t lfir_idle_poresw_status_rc_err : 1;
+ uint64_t lfir_idle_poresw_status_value_err : 1;
+ uint64_t lfir_idle_poresw_write_while_inactive_err : 1;
+ uint64_t lfir_idle_poresw_timeout_err : 1;
+ uint64_t lfir_idle_oci_master_write_timeout_err : 1;
+ uint64_t lfir_idle_internal_err : 1;
+ uint64_t lfir_int_comp_parity_err : 1;
+ uint64_t lfir_pmc_occ_heartbeat_timeout : 1;
+ uint64_t lfir_spivid_crc_error0 : 1;
+ uint64_t lfir_spivid_crc_error1 : 1;
+ uint64_t lfir_spivid_crc_error2 : 1;
+ uint64_t lfir_spivid_retry_timeout : 1;
+ uint64_t lfir_spivid_fsm_err : 1;
+ uint64_t lfir_spivid_majority_detected_a_minority : 1;
+ uint64_t lfir_o2s_crc_error0 : 1;
+ uint64_t lfir_o2s_crc_error1 : 1;
+ uint64_t lfir_o2s_crc_error2 : 1;
+ uint64_t lfir_o2s_retry_timeout : 1;
+ uint64_t lfir_o2s_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_fsm_err : 1;
+ uint64_t lfir_o2s_majority_detected_a_minority : 1;
+ uint64_t lfir_o2p_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2p_fsm_err : 1;
+ uint64_t lfir_oci_slave_err : 1;
+ uint64_t lfir_if_comp_parity_error : 1;
+ uint64_t spare_fir : 10;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t spare_fir : 10;
+ uint64_t lfir_if_comp_parity_error : 1;
+ uint64_t lfir_oci_slave_err : 1;
+ uint64_t lfir_o2p_fsm_err : 1;
+ uint64_t lfir_o2p_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_majority_detected_a_minority : 1;
+ uint64_t lfir_o2s_fsm_err : 1;
+ uint64_t lfir_o2s_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_retry_timeout : 1;
+ uint64_t lfir_o2s_crc_error2 : 1;
+ uint64_t lfir_o2s_crc_error1 : 1;
+ uint64_t lfir_o2s_crc_error0 : 1;
+ uint64_t lfir_spivid_majority_detected_a_minority : 1;
+ uint64_t lfir_spivid_fsm_err : 1;
+ uint64_t lfir_spivid_retry_timeout : 1;
+ uint64_t lfir_spivid_crc_error2 : 1;
+ uint64_t lfir_spivid_crc_error1 : 1;
+ uint64_t lfir_spivid_crc_error0 : 1;
+ uint64_t lfir_pmc_occ_heartbeat_timeout : 1;
+ uint64_t lfir_int_comp_parity_err : 1;
+ uint64_t lfir_idle_internal_err : 1;
+ uint64_t lfir_idle_oci_master_write_timeout_err : 1;
+ uint64_t lfir_idle_poresw_timeout_err : 1;
+ uint64_t lfir_idle_poresw_write_while_inactive_err : 1;
+ uint64_t lfir_idle_poresw_status_value_err : 1;
+ uint64_t lfir_idle_poresw_status_rc_err : 1;
+ uint64_t lfir_idle_poresw_fatal_err : 1;
+ uint64_t lfir_ms_comp_parity_err : 1;
+ uint64_t lfir_pstate_ms_fsm_err : 1;
+ uint64_t lfir_pstate_interchip_errorframe_err : 1;
+ uint64_t lfir_pstate_interchip_ue_err : 1;
+ uint64_t lfir_pstate_oci_master_to_err : 1;
+ uint64_t lfir_pstate_pib_master_offline_err : 1;
+ uint64_t lfir_pstate_pib_master_nonoffline_err : 1;
+ uint64_t lfir_pstate_gack_to_err : 1;
+ uint64_t lfir_pstate_gpst_checkbyte_err : 1;
+ uint64_t lfir_pstate_oci_master_rddata_parity_err : 1;
+ uint64_t lfir_pstate_oci_master_rderr : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_err_reg_t;
+
+
+
+typedef union pmc_lfir_err_reg_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t lfir_pstate_oci_master_rderr : 1;
+ uint64_t lfir_pstate_oci_master_rddata_parity_err : 1;
+ uint64_t lfir_pstate_gpst_checkbyte_err : 1;
+ uint64_t lfir_pstate_gack_to_err : 1;
+ uint64_t lfir_pstate_pib_master_nonoffline_err : 1;
+ uint64_t lfir_pstate_pib_master_offline_err : 1;
+ uint64_t lfir_pstate_oci_master_to_err : 1;
+ uint64_t lfir_pstate_interchip_ue_err : 1;
+ uint64_t lfir_pstate_interchip_errorframe_err : 1;
+ uint64_t lfir_pstate_ms_fsm_err : 1;
+ uint64_t lfir_ms_comp_parity_err : 1;
+ uint64_t lfir_idle_poresw_fatal_err : 1;
+ uint64_t lfir_idle_poresw_status_rc_err : 1;
+ uint64_t lfir_idle_poresw_status_value_err : 1;
+ uint64_t lfir_idle_poresw_write_while_inactive_err : 1;
+ uint64_t lfir_idle_poresw_timeout_err : 1;
+ uint64_t lfir_idle_oci_master_write_timeout_err : 1;
+ uint64_t lfir_idle_internal_err : 1;
+ uint64_t lfir_int_comp_parity_err : 1;
+ uint64_t lfir_pmc_occ_heartbeat_timeout : 1;
+ uint64_t lfir_spivid_crc_error0 : 1;
+ uint64_t lfir_spivid_crc_error1 : 1;
+ uint64_t lfir_spivid_crc_error2 : 1;
+ uint64_t lfir_spivid_retry_timeout : 1;
+ uint64_t lfir_spivid_fsm_err : 1;
+ uint64_t lfir_spivid_majority_detected_a_minority : 1;
+ uint64_t lfir_o2s_crc_error0 : 1;
+ uint64_t lfir_o2s_crc_error1 : 1;
+ uint64_t lfir_o2s_crc_error2 : 1;
+ uint64_t lfir_o2s_retry_timeout : 1;
+ uint64_t lfir_o2s_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_fsm_err : 1;
+ uint64_t lfir_o2s_majority_detected_a_minority : 1;
+ uint64_t lfir_o2p_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2p_fsm_err : 1;
+ uint64_t lfir_oci_slave_err : 1;
+ uint64_t lfir_if_comp_parity_error : 1;
+ uint64_t spare_fir : 10;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t spare_fir : 10;
+ uint64_t lfir_if_comp_parity_error : 1;
+ uint64_t lfir_oci_slave_err : 1;
+ uint64_t lfir_o2p_fsm_err : 1;
+ uint64_t lfir_o2p_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_majority_detected_a_minority : 1;
+ uint64_t lfir_o2s_fsm_err : 1;
+ uint64_t lfir_o2s_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_retry_timeout : 1;
+ uint64_t lfir_o2s_crc_error2 : 1;
+ uint64_t lfir_o2s_crc_error1 : 1;
+ uint64_t lfir_o2s_crc_error0 : 1;
+ uint64_t lfir_spivid_majority_detected_a_minority : 1;
+ uint64_t lfir_spivid_fsm_err : 1;
+ uint64_t lfir_spivid_retry_timeout : 1;
+ uint64_t lfir_spivid_crc_error2 : 1;
+ uint64_t lfir_spivid_crc_error1 : 1;
+ uint64_t lfir_spivid_crc_error0 : 1;
+ uint64_t lfir_pmc_occ_heartbeat_timeout : 1;
+ uint64_t lfir_int_comp_parity_err : 1;
+ uint64_t lfir_idle_internal_err : 1;
+ uint64_t lfir_idle_oci_master_write_timeout_err : 1;
+ uint64_t lfir_idle_poresw_timeout_err : 1;
+ uint64_t lfir_idle_poresw_write_while_inactive_err : 1;
+ uint64_t lfir_idle_poresw_status_value_err : 1;
+ uint64_t lfir_idle_poresw_status_rc_err : 1;
+ uint64_t lfir_idle_poresw_fatal_err : 1;
+ uint64_t lfir_ms_comp_parity_err : 1;
+ uint64_t lfir_pstate_ms_fsm_err : 1;
+ uint64_t lfir_pstate_interchip_errorframe_err : 1;
+ uint64_t lfir_pstate_interchip_ue_err : 1;
+ uint64_t lfir_pstate_oci_master_to_err : 1;
+ uint64_t lfir_pstate_pib_master_offline_err : 1;
+ uint64_t lfir_pstate_pib_master_nonoffline_err : 1;
+ uint64_t lfir_pstate_gack_to_err : 1;
+ uint64_t lfir_pstate_gpst_checkbyte_err : 1;
+ uint64_t lfir_pstate_oci_master_rddata_parity_err : 1;
+ uint64_t lfir_pstate_oci_master_rderr : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_err_reg_and_t;
+
+
+
+typedef union pmc_lfir_err_reg_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t lfir_pstate_oci_master_rderr : 1;
+ uint64_t lfir_pstate_oci_master_rddata_parity_err : 1;
+ uint64_t lfir_pstate_gpst_checkbyte_err : 1;
+ uint64_t lfir_pstate_gack_to_err : 1;
+ uint64_t lfir_pstate_pib_master_nonoffline_err : 1;
+ uint64_t lfir_pstate_pib_master_offline_err : 1;
+ uint64_t lfir_pstate_oci_master_to_err : 1;
+ uint64_t lfir_pstate_interchip_ue_err : 1;
+ uint64_t lfir_pstate_interchip_errorframe_err : 1;
+ uint64_t lfir_pstate_ms_fsm_err : 1;
+ uint64_t lfir_ms_comp_parity_err : 1;
+ uint64_t lfir_idle_poresw_fatal_err : 1;
+ uint64_t lfir_idle_poresw_status_rc_err : 1;
+ uint64_t lfir_idle_poresw_status_value_err : 1;
+ uint64_t lfir_idle_poresw_write_while_inactive_err : 1;
+ uint64_t lfir_idle_poresw_timeout_err : 1;
+ uint64_t lfir_idle_oci_master_write_timeout_err : 1;
+ uint64_t lfir_idle_internal_err : 1;
+ uint64_t lfir_int_comp_parity_err : 1;
+ uint64_t lfir_pmc_occ_heartbeat_timeout : 1;
+ uint64_t lfir_spivid_crc_error0 : 1;
+ uint64_t lfir_spivid_crc_error1 : 1;
+ uint64_t lfir_spivid_crc_error2 : 1;
+ uint64_t lfir_spivid_retry_timeout : 1;
+ uint64_t lfir_spivid_fsm_err : 1;
+ uint64_t lfir_spivid_majority_detected_a_minority : 1;
+ uint64_t lfir_o2s_crc_error0 : 1;
+ uint64_t lfir_o2s_crc_error1 : 1;
+ uint64_t lfir_o2s_crc_error2 : 1;
+ uint64_t lfir_o2s_retry_timeout : 1;
+ uint64_t lfir_o2s_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_fsm_err : 1;
+ uint64_t lfir_o2s_majority_detected_a_minority : 1;
+ uint64_t lfir_o2p_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2p_fsm_err : 1;
+ uint64_t lfir_oci_slave_err : 1;
+ uint64_t lfir_if_comp_parity_error : 1;
+ uint64_t spare_fir : 10;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t fir_parity_err : 1;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t fir_parity_err : 1;
+ uint64_t fir_parity_err_dup : 1;
+ uint64_t spare_fir : 10;
+ uint64_t lfir_if_comp_parity_error : 1;
+ uint64_t lfir_oci_slave_err : 1;
+ uint64_t lfir_o2p_fsm_err : 1;
+ uint64_t lfir_o2p_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_majority_detected_a_minority : 1;
+ uint64_t lfir_o2s_fsm_err : 1;
+ uint64_t lfir_o2s_write_while_bridge_busy_err : 1;
+ uint64_t lfir_o2s_retry_timeout : 1;
+ uint64_t lfir_o2s_crc_error2 : 1;
+ uint64_t lfir_o2s_crc_error1 : 1;
+ uint64_t lfir_o2s_crc_error0 : 1;
+ uint64_t lfir_spivid_majority_detected_a_minority : 1;
+ uint64_t lfir_spivid_fsm_err : 1;
+ uint64_t lfir_spivid_retry_timeout : 1;
+ uint64_t lfir_spivid_crc_error2 : 1;
+ uint64_t lfir_spivid_crc_error1 : 1;
+ uint64_t lfir_spivid_crc_error0 : 1;
+ uint64_t lfir_pmc_occ_heartbeat_timeout : 1;
+ uint64_t lfir_int_comp_parity_err : 1;
+ uint64_t lfir_idle_internal_err : 1;
+ uint64_t lfir_idle_oci_master_write_timeout_err : 1;
+ uint64_t lfir_idle_poresw_timeout_err : 1;
+ uint64_t lfir_idle_poresw_write_while_inactive_err : 1;
+ uint64_t lfir_idle_poresw_status_value_err : 1;
+ uint64_t lfir_idle_poresw_status_rc_err : 1;
+ uint64_t lfir_idle_poresw_fatal_err : 1;
+ uint64_t lfir_ms_comp_parity_err : 1;
+ uint64_t lfir_pstate_ms_fsm_err : 1;
+ uint64_t lfir_pstate_interchip_errorframe_err : 1;
+ uint64_t lfir_pstate_interchip_ue_err : 1;
+ uint64_t lfir_pstate_oci_master_to_err : 1;
+ uint64_t lfir_pstate_pib_master_offline_err : 1;
+ uint64_t lfir_pstate_pib_master_nonoffline_err : 1;
+ uint64_t lfir_pstate_gack_to_err : 1;
+ uint64_t lfir_pstate_gpst_checkbyte_err : 1;
+ uint64_t lfir_pstate_oci_master_rddata_parity_err : 1;
+ uint64_t lfir_pstate_oci_master_rderr : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_err_reg_or_t;
+
+
+
+typedef union pmc_lfir_err_mask_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pmc_lfir_mask_0 : 1;
+ uint64_t pmc_lfir_mask_1 : 1;
+ uint64_t pmc_lfir_mask_2 : 1;
+ uint64_t pmc_lfir_mask_3 : 1;
+ uint64_t pmc_lfir_mask_4 : 1;
+ uint64_t pmc_lfir_mask_5 : 1;
+ uint64_t pmc_lfir_mask_6 : 1;
+ uint64_t pmc_lfir_mask_7 : 1;
+ uint64_t pmc_lfir_mask_8 : 1;
+ uint64_t pmc_lfir_mask_9 : 1;
+ uint64_t pmc_lfir_mask_10 : 1;
+ uint64_t pmc_lfir_mask_11 : 1;
+ uint64_t pmc_lfir_mask_12 : 1;
+ uint64_t pmc_lfir_mask_13 : 1;
+ uint64_t pmc_lfir_mask_14 : 1;
+ uint64_t pmc_lfir_mask_15 : 1;
+ uint64_t pmc_lfir_mask_16 : 1;
+ uint64_t pmc_lfir_mask_17 : 1;
+ uint64_t pmc_lfir_mask_18 : 1;
+ uint64_t pmc_lfir_mask_19 : 1;
+ uint64_t pmc_lfir_mask_20 : 1;
+ uint64_t pmc_lfir_mask_21 : 1;
+ uint64_t pmc_lfir_mask_22 : 1;
+ uint64_t pmc_lfir_mask_23 : 1;
+ uint64_t pmc_lfir_mask_24 : 1;
+ uint64_t pmc_lfir_mask_25 : 1;
+ uint64_t pmc_lfir_mask_26 : 1;
+ uint64_t pmc_lfir_mask_27 : 1;
+ uint64_t pmc_lfir_mask_28 : 1;
+ uint64_t pmc_lfir_mask_29 : 1;
+ uint64_t pmc_lfir_mask_30 : 1;
+ uint64_t pmc_lfir_mask_31 : 1;
+ uint64_t pmc_lfir_mask_32 : 1;
+ uint64_t pmc_lfir_mask_33 : 1;
+ uint64_t pmc_lfir_mask_34 : 1;
+ uint64_t pmc_lfir_mask_35 : 1;
+ uint64_t pmc_lfir_mask_36 : 1;
+ uint64_t pmc_lfir_mask1_37_46 : 10;
+ uint64_t pmc_lfir_mask1_47 : 1;
+ uint64_t pmc_lfir_mask1_48 : 1;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t pmc_lfir_mask1_48 : 1;
+ uint64_t pmc_lfir_mask1_47 : 1;
+ uint64_t pmc_lfir_mask1_37_46 : 10;
+ uint64_t pmc_lfir_mask_36 : 1;
+ uint64_t pmc_lfir_mask_35 : 1;
+ uint64_t pmc_lfir_mask_34 : 1;
+ uint64_t pmc_lfir_mask_33 : 1;
+ uint64_t pmc_lfir_mask_32 : 1;
+ uint64_t pmc_lfir_mask_31 : 1;
+ uint64_t pmc_lfir_mask_30 : 1;
+ uint64_t pmc_lfir_mask_29 : 1;
+ uint64_t pmc_lfir_mask_28 : 1;
+ uint64_t pmc_lfir_mask_27 : 1;
+ uint64_t pmc_lfir_mask_26 : 1;
+ uint64_t pmc_lfir_mask_25 : 1;
+ uint64_t pmc_lfir_mask_24 : 1;
+ uint64_t pmc_lfir_mask_23 : 1;
+ uint64_t pmc_lfir_mask_22 : 1;
+ uint64_t pmc_lfir_mask_21 : 1;
+ uint64_t pmc_lfir_mask_20 : 1;
+ uint64_t pmc_lfir_mask_19 : 1;
+ uint64_t pmc_lfir_mask_18 : 1;
+ uint64_t pmc_lfir_mask_17 : 1;
+ uint64_t pmc_lfir_mask_16 : 1;
+ uint64_t pmc_lfir_mask_15 : 1;
+ uint64_t pmc_lfir_mask_14 : 1;
+ uint64_t pmc_lfir_mask_13 : 1;
+ uint64_t pmc_lfir_mask_12 : 1;
+ uint64_t pmc_lfir_mask_11 : 1;
+ uint64_t pmc_lfir_mask_10 : 1;
+ uint64_t pmc_lfir_mask_9 : 1;
+ uint64_t pmc_lfir_mask_8 : 1;
+ uint64_t pmc_lfir_mask_7 : 1;
+ uint64_t pmc_lfir_mask_6 : 1;
+ uint64_t pmc_lfir_mask_5 : 1;
+ uint64_t pmc_lfir_mask_4 : 1;
+ uint64_t pmc_lfir_mask_3 : 1;
+ uint64_t pmc_lfir_mask_2 : 1;
+ uint64_t pmc_lfir_mask_1 : 1;
+ uint64_t pmc_lfir_mask_0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_err_mask_reg_t;
+
+
+
+typedef union pmc_lfir_err_mask_reg_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pmc_lfir_mask_0 : 1;
+ uint64_t pmc_lfir_mask_1 : 1;
+ uint64_t pmc_lfir_mask_2 : 1;
+ uint64_t pmc_lfir_mask_3 : 1;
+ uint64_t pmc_lfir_mask_4 : 1;
+ uint64_t pmc_lfir_mask_5 : 1;
+ uint64_t pmc_lfir_mask_6 : 1;
+ uint64_t pmc_lfir_mask_7 : 1;
+ uint64_t pmc_lfir_mask_8 : 1;
+ uint64_t pmc_lfir_mask_9 : 1;
+ uint64_t pmc_lfir_mask_10 : 1;
+ uint64_t pmc_lfir_mask_11 : 1;
+ uint64_t pmc_lfir_mask_12 : 1;
+ uint64_t pmc_lfir_mask_13 : 1;
+ uint64_t pmc_lfir_mask_14 : 1;
+ uint64_t pmc_lfir_mask_15 : 1;
+ uint64_t pmc_lfir_mask_16 : 1;
+ uint64_t pmc_lfir_mask_17 : 1;
+ uint64_t pmc_lfir_mask_18 : 1;
+ uint64_t pmc_lfir_mask_19 : 1;
+ uint64_t pmc_lfir_mask_20 : 1;
+ uint64_t pmc_lfir_mask_21 : 1;
+ uint64_t pmc_lfir_mask_22 : 1;
+ uint64_t pmc_lfir_mask_23 : 1;
+ uint64_t pmc_lfir_mask_24 : 1;
+ uint64_t pmc_lfir_mask_25 : 1;
+ uint64_t pmc_lfir_mask_26 : 1;
+ uint64_t pmc_lfir_mask_27 : 1;
+ uint64_t pmc_lfir_mask_28 : 1;
+ uint64_t pmc_lfir_mask_29 : 1;
+ uint64_t pmc_lfir_mask_30 : 1;
+ uint64_t pmc_lfir_mask_31 : 1;
+ uint64_t pmc_lfir_mask_32 : 1;
+ uint64_t pmc_lfir_mask_33 : 1;
+ uint64_t pmc_lfir_mask_34 : 1;
+ uint64_t pmc_lfir_mask_35 : 1;
+ uint64_t pmc_lfir_mask_36 : 1;
+ uint64_t pmc_lfir_mask1_37_46 : 10;
+ uint64_t pmc_lfir_mask1_47 : 1;
+ uint64_t pmc_lfir_mask1_48 : 1;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t pmc_lfir_mask1_48 : 1;
+ uint64_t pmc_lfir_mask1_47 : 1;
+ uint64_t pmc_lfir_mask1_37_46 : 10;
+ uint64_t pmc_lfir_mask_36 : 1;
+ uint64_t pmc_lfir_mask_35 : 1;
+ uint64_t pmc_lfir_mask_34 : 1;
+ uint64_t pmc_lfir_mask_33 : 1;
+ uint64_t pmc_lfir_mask_32 : 1;
+ uint64_t pmc_lfir_mask_31 : 1;
+ uint64_t pmc_lfir_mask_30 : 1;
+ uint64_t pmc_lfir_mask_29 : 1;
+ uint64_t pmc_lfir_mask_28 : 1;
+ uint64_t pmc_lfir_mask_27 : 1;
+ uint64_t pmc_lfir_mask_26 : 1;
+ uint64_t pmc_lfir_mask_25 : 1;
+ uint64_t pmc_lfir_mask_24 : 1;
+ uint64_t pmc_lfir_mask_23 : 1;
+ uint64_t pmc_lfir_mask_22 : 1;
+ uint64_t pmc_lfir_mask_21 : 1;
+ uint64_t pmc_lfir_mask_20 : 1;
+ uint64_t pmc_lfir_mask_19 : 1;
+ uint64_t pmc_lfir_mask_18 : 1;
+ uint64_t pmc_lfir_mask_17 : 1;
+ uint64_t pmc_lfir_mask_16 : 1;
+ uint64_t pmc_lfir_mask_15 : 1;
+ uint64_t pmc_lfir_mask_14 : 1;
+ uint64_t pmc_lfir_mask_13 : 1;
+ uint64_t pmc_lfir_mask_12 : 1;
+ uint64_t pmc_lfir_mask_11 : 1;
+ uint64_t pmc_lfir_mask_10 : 1;
+ uint64_t pmc_lfir_mask_9 : 1;
+ uint64_t pmc_lfir_mask_8 : 1;
+ uint64_t pmc_lfir_mask_7 : 1;
+ uint64_t pmc_lfir_mask_6 : 1;
+ uint64_t pmc_lfir_mask_5 : 1;
+ uint64_t pmc_lfir_mask_4 : 1;
+ uint64_t pmc_lfir_mask_3 : 1;
+ uint64_t pmc_lfir_mask_2 : 1;
+ uint64_t pmc_lfir_mask_1 : 1;
+ uint64_t pmc_lfir_mask_0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_err_mask_reg_and_t;
+
+
+
+typedef union pmc_lfir_err_mask_reg_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pmc_lfir_mask_0 : 1;
+ uint64_t pmc_lfir_mask_1 : 1;
+ uint64_t pmc_lfir_mask_2 : 1;
+ uint64_t pmc_lfir_mask_3 : 1;
+ uint64_t pmc_lfir_mask_4 : 1;
+ uint64_t pmc_lfir_mask_5 : 1;
+ uint64_t pmc_lfir_mask_6 : 1;
+ uint64_t pmc_lfir_mask_7 : 1;
+ uint64_t pmc_lfir_mask_8 : 1;
+ uint64_t pmc_lfir_mask_9 : 1;
+ uint64_t pmc_lfir_mask_10 : 1;
+ uint64_t pmc_lfir_mask_11 : 1;
+ uint64_t pmc_lfir_mask_12 : 1;
+ uint64_t pmc_lfir_mask_13 : 1;
+ uint64_t pmc_lfir_mask_14 : 1;
+ uint64_t pmc_lfir_mask_15 : 1;
+ uint64_t pmc_lfir_mask_16 : 1;
+ uint64_t pmc_lfir_mask_17 : 1;
+ uint64_t pmc_lfir_mask_18 : 1;
+ uint64_t pmc_lfir_mask_19 : 1;
+ uint64_t pmc_lfir_mask_20 : 1;
+ uint64_t pmc_lfir_mask_21 : 1;
+ uint64_t pmc_lfir_mask_22 : 1;
+ uint64_t pmc_lfir_mask_23 : 1;
+ uint64_t pmc_lfir_mask_24 : 1;
+ uint64_t pmc_lfir_mask_25 : 1;
+ uint64_t pmc_lfir_mask_26 : 1;
+ uint64_t pmc_lfir_mask_27 : 1;
+ uint64_t pmc_lfir_mask_28 : 1;
+ uint64_t pmc_lfir_mask_29 : 1;
+ uint64_t pmc_lfir_mask_30 : 1;
+ uint64_t pmc_lfir_mask_31 : 1;
+ uint64_t pmc_lfir_mask_32 : 1;
+ uint64_t pmc_lfir_mask_33 : 1;
+ uint64_t pmc_lfir_mask_34 : 1;
+ uint64_t pmc_lfir_mask_35 : 1;
+ uint64_t pmc_lfir_mask_36 : 1;
+ uint64_t pmc_lfir_mask1_37_46 : 10;
+ uint64_t pmc_lfir_mask1_47 : 1;
+ uint64_t pmc_lfir_mask1_48 : 1;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t pmc_lfir_mask1_48 : 1;
+ uint64_t pmc_lfir_mask1_47 : 1;
+ uint64_t pmc_lfir_mask1_37_46 : 10;
+ uint64_t pmc_lfir_mask_36 : 1;
+ uint64_t pmc_lfir_mask_35 : 1;
+ uint64_t pmc_lfir_mask_34 : 1;
+ uint64_t pmc_lfir_mask_33 : 1;
+ uint64_t pmc_lfir_mask_32 : 1;
+ uint64_t pmc_lfir_mask_31 : 1;
+ uint64_t pmc_lfir_mask_30 : 1;
+ uint64_t pmc_lfir_mask_29 : 1;
+ uint64_t pmc_lfir_mask_28 : 1;
+ uint64_t pmc_lfir_mask_27 : 1;
+ uint64_t pmc_lfir_mask_26 : 1;
+ uint64_t pmc_lfir_mask_25 : 1;
+ uint64_t pmc_lfir_mask_24 : 1;
+ uint64_t pmc_lfir_mask_23 : 1;
+ uint64_t pmc_lfir_mask_22 : 1;
+ uint64_t pmc_lfir_mask_21 : 1;
+ uint64_t pmc_lfir_mask_20 : 1;
+ uint64_t pmc_lfir_mask_19 : 1;
+ uint64_t pmc_lfir_mask_18 : 1;
+ uint64_t pmc_lfir_mask_17 : 1;
+ uint64_t pmc_lfir_mask_16 : 1;
+ uint64_t pmc_lfir_mask_15 : 1;
+ uint64_t pmc_lfir_mask_14 : 1;
+ uint64_t pmc_lfir_mask_13 : 1;
+ uint64_t pmc_lfir_mask_12 : 1;
+ uint64_t pmc_lfir_mask_11 : 1;
+ uint64_t pmc_lfir_mask_10 : 1;
+ uint64_t pmc_lfir_mask_9 : 1;
+ uint64_t pmc_lfir_mask_8 : 1;
+ uint64_t pmc_lfir_mask_7 : 1;
+ uint64_t pmc_lfir_mask_6 : 1;
+ uint64_t pmc_lfir_mask_5 : 1;
+ uint64_t pmc_lfir_mask_4 : 1;
+ uint64_t pmc_lfir_mask_3 : 1;
+ uint64_t pmc_lfir_mask_2 : 1;
+ uint64_t pmc_lfir_mask_1 : 1;
+ uint64_t pmc_lfir_mask_0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_err_mask_reg_or_t;
+
+
+
+typedef union pmc_lfir_action0_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pmc_lfir_action0_0 : 1;
+ uint64_t pmc_lfir_action0_1 : 1;
+ uint64_t pmc_lfir_action0_2 : 1;
+ uint64_t pmc_lfir_action0_3 : 1;
+ uint64_t pmc_lfir_action0_4 : 1;
+ uint64_t pmc_lfir_action0_5 : 1;
+ uint64_t pmc_lfir_action0_6 : 1;
+ uint64_t pmc_lfir_action0_7 : 1;
+ uint64_t pmc_lfir_action0_8 : 1;
+ uint64_t pmc_lfir_action0_9 : 1;
+ uint64_t pmc_lfir_action0_10 : 1;
+ uint64_t pmc_lfir_action0_11 : 1;
+ uint64_t pmc_lfir_action0_12 : 1;
+ uint64_t pmc_lfir_action0_13 : 1;
+ uint64_t pmc_lfir_action0_14 : 1;
+ uint64_t pmc_lfir_action0_15 : 1;
+ uint64_t pmc_lfir_action0_16 : 1;
+ uint64_t pmc_lfir_action0_17 : 1;
+ uint64_t pmc_lfir_action0_18 : 1;
+ uint64_t pmc_lfir_action0_19 : 1;
+ uint64_t pmc_lfir_action0_20 : 1;
+ uint64_t pmc_lfir_action0_21 : 1;
+ uint64_t pmc_lfir_action0_22 : 1;
+ uint64_t pmc_lfir_action0_23 : 1;
+ uint64_t pmc_lfir_action0_24 : 1;
+ uint64_t pmc_lfir_action0_25 : 1;
+ uint64_t pmc_lfir_action0_26 : 1;
+ uint64_t pmc_lfir_action0_27 : 1;
+ uint64_t pmc_lfir_action0_28 : 1;
+ uint64_t pmc_lfir_action0_29 : 1;
+ uint64_t pmc_lfir_action0_30 : 1;
+ uint64_t pmc_lfir_action0_31 : 1;
+ uint64_t pmc_lfir_action0_32 : 1;
+ uint64_t pmc_lfir_action0_33 : 1;
+ uint64_t pmc_lfir_action0_34 : 1;
+ uint64_t pmc_lfir_action0_35 : 1;
+ uint64_t pmc_lfir_action0_36 : 1;
+ uint64_t pmc_lfir_action0_37_46 : 10;
+ uint64_t pmc_lfir_action0_47 : 1;
+ uint64_t pmc_lfir_action0_48 : 1;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t pmc_lfir_action0_48 : 1;
+ uint64_t pmc_lfir_action0_47 : 1;
+ uint64_t pmc_lfir_action0_37_46 : 10;
+ uint64_t pmc_lfir_action0_36 : 1;
+ uint64_t pmc_lfir_action0_35 : 1;
+ uint64_t pmc_lfir_action0_34 : 1;
+ uint64_t pmc_lfir_action0_33 : 1;
+ uint64_t pmc_lfir_action0_32 : 1;
+ uint64_t pmc_lfir_action0_31 : 1;
+ uint64_t pmc_lfir_action0_30 : 1;
+ uint64_t pmc_lfir_action0_29 : 1;
+ uint64_t pmc_lfir_action0_28 : 1;
+ uint64_t pmc_lfir_action0_27 : 1;
+ uint64_t pmc_lfir_action0_26 : 1;
+ uint64_t pmc_lfir_action0_25 : 1;
+ uint64_t pmc_lfir_action0_24 : 1;
+ uint64_t pmc_lfir_action0_23 : 1;
+ uint64_t pmc_lfir_action0_22 : 1;
+ uint64_t pmc_lfir_action0_21 : 1;
+ uint64_t pmc_lfir_action0_20 : 1;
+ uint64_t pmc_lfir_action0_19 : 1;
+ uint64_t pmc_lfir_action0_18 : 1;
+ uint64_t pmc_lfir_action0_17 : 1;
+ uint64_t pmc_lfir_action0_16 : 1;
+ uint64_t pmc_lfir_action0_15 : 1;
+ uint64_t pmc_lfir_action0_14 : 1;
+ uint64_t pmc_lfir_action0_13 : 1;
+ uint64_t pmc_lfir_action0_12 : 1;
+ uint64_t pmc_lfir_action0_11 : 1;
+ uint64_t pmc_lfir_action0_10 : 1;
+ uint64_t pmc_lfir_action0_9 : 1;
+ uint64_t pmc_lfir_action0_8 : 1;
+ uint64_t pmc_lfir_action0_7 : 1;
+ uint64_t pmc_lfir_action0_6 : 1;
+ uint64_t pmc_lfir_action0_5 : 1;
+ uint64_t pmc_lfir_action0_4 : 1;
+ uint64_t pmc_lfir_action0_3 : 1;
+ uint64_t pmc_lfir_action0_2 : 1;
+ uint64_t pmc_lfir_action0_1 : 1;
+ uint64_t pmc_lfir_action0_0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_action0_reg_t;
+
+
+
+typedef union pmc_lfir_action1_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pmc_lfir_action1_0 : 1;
+ uint64_t pmc_lfir_action1_1 : 1;
+ uint64_t pmc_lfir_action1_2 : 1;
+ uint64_t pmc_lfir_action1_3 : 1;
+ uint64_t pmc_lfir_action1_4 : 1;
+ uint64_t pmc_lfir_action1_5 : 1;
+ uint64_t pmc_lfir_action1_6 : 1;
+ uint64_t pmc_lfir_action1_7 : 1;
+ uint64_t pmc_lfir_action1_8 : 1;
+ uint64_t pmc_lfir_action1_9 : 1;
+ uint64_t pmc_lfir_action1_10 : 1;
+ uint64_t pmc_lfir_action1_11 : 1;
+ uint64_t pmc_lfir_action1_12 : 1;
+ uint64_t pmc_lfir_action1_13 : 1;
+ uint64_t pmc_lfir_action1_14 : 1;
+ uint64_t pmc_lfir_action1_15 : 1;
+ uint64_t pmc_lfir_action1_16 : 1;
+ uint64_t pmc_lfir_action1_17 : 1;
+ uint64_t pmc_lfir_action1_18 : 1;
+ uint64_t pmc_lfir_action1_19 : 1;
+ uint64_t pmc_lfir_action1_20 : 1;
+ uint64_t pmc_lfir_action1_21 : 1;
+ uint64_t pmc_lfir_action1_22 : 1;
+ uint64_t pmc_lfir_action1_23 : 1;
+ uint64_t pmc_lfir_action1_24 : 1;
+ uint64_t pmc_lfir_action1_25 : 1;
+ uint64_t pmc_lfir_action1_26 : 1;
+ uint64_t pmc_lfir_action1_27 : 1;
+ uint64_t pmc_lfir_action1_28 : 1;
+ uint64_t pmc_lfir_action1_29 : 1;
+ uint64_t pmc_lfir_action1_30 : 1;
+ uint64_t pmc_lfir_action1_31 : 1;
+ uint64_t pmc_lfir_action1_32 : 1;
+ uint64_t pmc_lfir_action1_33 : 1;
+ uint64_t pmc_lfir_action1_34 : 1;
+ uint64_t pmc_lfir_action1_35 : 1;
+ uint64_t pmc_lfir_action1_36 : 1;
+ uint64_t pmc_lfir_action1_37_46 : 10;
+ uint64_t pmc_lfir_action1_47 : 1;
+ uint64_t pmc_lfir_action1_48 : 1;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t pmc_lfir_action1_48 : 1;
+ uint64_t pmc_lfir_action1_47 : 1;
+ uint64_t pmc_lfir_action1_37_46 : 10;
+ uint64_t pmc_lfir_action1_36 : 1;
+ uint64_t pmc_lfir_action1_35 : 1;
+ uint64_t pmc_lfir_action1_34 : 1;
+ uint64_t pmc_lfir_action1_33 : 1;
+ uint64_t pmc_lfir_action1_32 : 1;
+ uint64_t pmc_lfir_action1_31 : 1;
+ uint64_t pmc_lfir_action1_30 : 1;
+ uint64_t pmc_lfir_action1_29 : 1;
+ uint64_t pmc_lfir_action1_28 : 1;
+ uint64_t pmc_lfir_action1_27 : 1;
+ uint64_t pmc_lfir_action1_26 : 1;
+ uint64_t pmc_lfir_action1_25 : 1;
+ uint64_t pmc_lfir_action1_24 : 1;
+ uint64_t pmc_lfir_action1_23 : 1;
+ uint64_t pmc_lfir_action1_22 : 1;
+ uint64_t pmc_lfir_action1_21 : 1;
+ uint64_t pmc_lfir_action1_20 : 1;
+ uint64_t pmc_lfir_action1_19 : 1;
+ uint64_t pmc_lfir_action1_18 : 1;
+ uint64_t pmc_lfir_action1_17 : 1;
+ uint64_t pmc_lfir_action1_16 : 1;
+ uint64_t pmc_lfir_action1_15 : 1;
+ uint64_t pmc_lfir_action1_14 : 1;
+ uint64_t pmc_lfir_action1_13 : 1;
+ uint64_t pmc_lfir_action1_12 : 1;
+ uint64_t pmc_lfir_action1_11 : 1;
+ uint64_t pmc_lfir_action1_10 : 1;
+ uint64_t pmc_lfir_action1_9 : 1;
+ uint64_t pmc_lfir_action1_8 : 1;
+ uint64_t pmc_lfir_action1_7 : 1;
+ uint64_t pmc_lfir_action1_6 : 1;
+ uint64_t pmc_lfir_action1_5 : 1;
+ uint64_t pmc_lfir_action1_4 : 1;
+ uint64_t pmc_lfir_action1_3 : 1;
+ uint64_t pmc_lfir_action1_2 : 1;
+ uint64_t pmc_lfir_action1_1 : 1;
+ uint64_t pmc_lfir_action1_0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_action1_reg_t;
+
+
+
+typedef union pmc_lfir_wof_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pmc_lfir_wof : 49;
+ uint64_t _reserved0 : 15;
+#else
+ uint64_t _reserved0 : 15;
+ uint64_t pmc_lfir_wof : 49;
+#endif // _BIG_ENDIAN
+ } fields;
+} pmc_lfir_wof_reg_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __PMC_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/pmc_register_addresses.h b/src/ssx/pgp/registers/pmc_register_addresses.h
new file mode 100755
index 0000000..96f8dac
--- /dev/null
+++ b/src/ssx/pgp/registers/pmc_register_addresses.h
@@ -0,0 +1,116 @@
+#ifndef __PMC_REGISTER_ADDRESSES_H__
+#define __PMC_REGISTER_ADDRESSES_H__
+
+// $Id: pmc_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pmc_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pmc_register_addresses.h
+/// \brief Symbolic addresses for the PMC unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define PMC_OCI_BASE 0x40010000
+#define PMC_MODE_REG 0x40010000
+#define PMC_HARDWARE_AUCTION_PSTATE_REG 0x40010008
+#define PMC_PSTATE_MONITOR_AND_CTRL_REG 0x40010010
+#define PMC_RAIL_BOUNDS_REGISTER 0x40010018
+#define PMC_GLOBAL_PSTATE_BOUNDS_REG 0x40010020
+#define PMC_PARAMETER_REG0 0x40010028
+#define PMC_PARAMETER_REG1 0x40010030
+#define PMC_EFF_GLOBAL_ACTUAL_VOLTAGE_REG 0x40010038
+#define PMC_GLOBAL_ACTUAL_VOLTAGE_REG 0x40010040
+#define PMC_STATUS_REG 0x40010048
+#define PMC_PHASE_ENABLE_REG 0x40010050
+#define PMC_UNDERVOLTING_REG 0x40010060
+#define PMC_CORE_DECONFIGURATION_REG 0x40010068
+#define PMC_INTCHP_CTRL_REG1 0x40010080
+#define PMC_INTCHP_CTRL_REG2 0x40010088
+#define PMC_INTCHP_CTRL_REG4 0x40010090
+#define PMC_INTCHP_STATUS_REG 0x40010098
+#define PMC_INTCHP_COMMAND_REG 0x400100a0
+#define PMC_INTCHP_MSG_WDATA 0x400100a8
+#define PMC_INTCHP_MSG_RDATA 0x400100b0
+#define PMC_INTCHP_PSTATE_REG 0x400100b8
+#define PMC_INTCHP_GLOBACK_REG 0x400100c0
+#define PMC_FSMSTATE_STATUS_REG 0x40010100
+#define PMC_TRACE_MODE_REG 0x40010180
+#define PMC_SPIV_CTRL_REG0A 0x40010200
+#define PMC_SPIV_CTRL_REG0B 0x40010208
+#define PMC_SPIV_CTRL_REG1 0x40010210
+#define PMC_SPIV_CTRL_REG2 0x40010218
+#define PMC_SPIV_CTRL_REG3 0x40010220
+#define PMC_SPIV_CTRL_REG4 0x40010228
+#define PMC_SPIV_STATUS_REG 0x40010230
+#define PMC_SPIV_COMMAND_REG 0x40010238
+#define PMC_O2S_CTRL_REG0A 0x40010280
+#define PMC_O2S_CTRL_REG0B 0x40010288
+#define PMC_O2S_CTRL_REG1 0x40010290
+#define PMC_O2S_CTRL_REG2 0x40010298
+#define PMC_O2S_CTRL_REG4 0x400102a8
+#define PMC_O2S_STATUS_REG 0x400102b0
+#define PMC_O2S_COMMAND_REG 0x400102b8
+#define PMC_O2S_WDATA_REG 0x400102c0
+#define PMC_O2S_RDATA_REG 0x400102c8
+#define PMC_O2P_ADDR_REG 0x40010300
+#define PMC_O2P_CTRL_STATUS_REG 0x40010308
+#define PMC_O2P_SEND_DATA_HI_REG 0x40010310
+#define PMC_O2P_SEND_DATA_LO_REG 0x40010318
+#define PMC_O2P_RECV_DATA_HI_REG 0x40010320
+#define PMC_O2P_RECV_DATA_LO_REG 0x40010328
+#define PMC_OCC_HEARTBEAT_REG 0x40010330
+#define PMC_ERROR_INT_MASK_HI_REG 0x40010338
+#define PMC_ERROR_INT_MASK_LO_REG 0x40010340
+#define PMC_IDLE_SUSPEND_MASK_REG 0x40010348
+#define PMC_PEND_IDLE_REQ_REG0 0x40010400
+#define PMC_PEND_IDLE_REQ_REG1 0x40010408
+#define PMC_PEND_IDLE_REQ_REG2 0x40010410
+#define PMC_PEND_IDLE_REQ_REG3 0x40010418
+#define PMC_SLEEP_INT_REQ_VEC_REG0 0x40010420
+#define PMC_SLEEP_INT_REQ_VEC_REG1 0x40010428
+#define PMC_SLEEP_INT_REQ_VEC_REG2 0x40010430
+#define PMC_SLEEP_INT_REQ_VEC_REG3 0x40010438
+#define PMC_WINKLE_INT_REQ_VEC_REG0 0x40010440
+#define PMC_WINKLE_INT_REQ_VEC_REG1 0x40010448
+#define PMC_WINKLE_INT_REQ_VEC_REG2 0x40010450
+#define PMC_WINKLE_INT_REQ_VEC_REG3 0x40010458
+#define PMC_NAP_INT_REQ_VEC_REG0 0x40010460
+#define PMC_NAP_INT_REQ_VEC_REG1 0x40010468
+#define PMC_PORE_REQ_REG0 0x40010470
+#define PMC_PORE_REQ_REG1 0x40010478
+#define PMC_PORE_REQ_STAT_REG 0x40010480
+#define PMC_PORE_REQ_TOUT_TH_REG 0x40010488
+#define PMC_DEEP_EXIT_MASK_REG 0x40010490
+#define PMC_DEEP_EXIT_MASK_REG_AND 0x40010500
+#define PMC_DEEP_EXIT_MASK_REG_OR 0x40010508
+#define PMC_CORE_PSTATE_REG0 0x400104a0
+#define PMC_CORE_PSTATE_REG1 0x400104a8
+#define PMC_CORE_PSTATE_REG2 0x400104b0
+#define PMC_CORE_PSTATE_REG3 0x400104b8
+#define PMC_CORE_POWER_DONATION_REG 0x400104c0
+#define PMC_PMAX_SYNC_COLLECTION_REG 0x400104c8
+#define PMC_PMAX_SYNC_COLLECTION_MASK_REG 0x400104d0
+#define PMC_GPSA_ACK_COLLECTION_REG 0x400104d8
+#define PMC_GPSA_ACK_COLLECTION_MASK_REG 0x400104e0
+#define PMC_PORE_SCRATCH_REG0 0x400104e8
+#define PMC_PORE_SCRATCH_REG1 0x400104f0
+#define PMC_DEEP_IDLE_EXIT_REG 0x400104f8
+#define PMC_DEEP_STATUS_REG 0x40010510
+#define PMC_PIB_BASE 0x01010840
+#define PMC_LFIR_ERR_REG 0x01010840
+#define PMC_LFIR_ERR_REG_AND 0x01010841
+#define PMC_LFIR_ERR_REG_OR 0x01010842
+#define PMC_LFIR_ERR_MASK_REG 0x01010843
+#define PMC_LFIR_ERR_MASK_REG_AND 0x01010844
+#define PMC_LFIR_ERR_MASK_REG_OR 0x01010845
+#define PMC_LFIR_ACTION0_REG 0x01010846
+#define PMC_LFIR_ACTION1_REG 0x01010847
+#define PMC_LFIR_WOF_REG 0x01010848
+
+#endif // __PMC_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/pore_firmware_registers.h b/src/ssx/pgp/registers/pore_firmware_registers.h
new file mode 100755
index 0000000..76127d9
--- /dev/null
+++ b/src/ssx/pgp/registers/pore_firmware_registers.h
@@ -0,0 +1,906 @@
+#ifndef __PORE_FIRMWARE_REGISTERS_H__
+#define __PORE_FIRMWARE_REGISTERS_H__
+
+// $Id: pore_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pore_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pore_firmware_registers.h
+/// \brief C register structs for the PORE unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union pore_status {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cur_state : 8;
+ uint64_t freeze_action : 1;
+ uint64_t interrupt_pending : 1;
+ uint64_t spare : 2;
+ uint64_t stack_pointer : 4;
+ uint64_t pc : 48;
+#else
+ uint64_t pc : 48;
+ uint64_t stack_pointer : 4;
+ uint64_t spare : 2;
+ uint64_t interrupt_pending : 1;
+ uint64_t freeze_action : 1;
+ uint64_t cur_state : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_status_t;
+
+#endif // __ASSEMBLER__
+#define PORE_STATUS_CUR_STATE_MASK SIXTYFOUR_BIT_CONSTANT(0xff00000000000000)
+#define PORE_STATUS_FREEZE_ACTION SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define PORE_STATUS_INTERRUPT_PENDING SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define PORE_STATUS_SPARE_MASK SIXTYFOUR_BIT_CONSTANT(0x0030000000000000)
+#define PORE_STATUS_STACK_POINTER_MASK SIXTYFOUR_BIT_CONSTANT(0x000f000000000000)
+#define PORE_STATUS_PC_MASK SIXTYFOUR_BIT_CONSTANT(0xffffffffffffffff)
+#ifndef __ASSEMBLER__
+
+
+typedef union pore_control {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t start_stop : 1;
+ uint64_t continue_step : 1;
+ uint64_t skip : 1;
+ uint64_t set_pc : 1;
+ uint64_t set_tp_scan_clk : 3;
+ uint64_t lock_exe_trig : 1;
+ uint64_t freeze_mask : 1;
+ uint64_t check_parity : 1;
+ uint64_t prv_parity : 1;
+ uint64_t trap_enable : 1;
+ uint64_t narrow_mode_trace : 1;
+ uint64_t interruptible : 1;
+ uint64_t pore_done_override : 1;
+ uint64_t interruptible_en : 1;
+ uint64_t pc_brk_pt : 48;
+#else
+ uint64_t pc_brk_pt : 48;
+ uint64_t interruptible_en : 1;
+ uint64_t pore_done_override : 1;
+ uint64_t interruptible : 1;
+ uint64_t narrow_mode_trace : 1;
+ uint64_t trap_enable : 1;
+ uint64_t prv_parity : 1;
+ uint64_t check_parity : 1;
+ uint64_t freeze_mask : 1;
+ uint64_t lock_exe_trig : 1;
+ uint64_t set_tp_scan_clk : 3;
+ uint64_t set_pc : 1;
+ uint64_t skip : 1;
+ uint64_t continue_step : 1;
+ uint64_t start_stop : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_control_t;
+
+#endif // __ASSEMBLER__
+#define PORE_CONTROL_START_STOP SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define PORE_CONTROL_CONTINUE_STEP SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define PORE_CONTROL_SKIP SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define PORE_CONTROL_SET_PC SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define PORE_CONTROL_SET_TP_SCAN_CLK_MASK SIXTYFOUR_BIT_CONSTANT(0x0e00000000000000)
+#define PORE_CONTROL_LOCK_EXE_TRIG SIXTYFOUR_BIT_CONSTANT(0x0100000000000000)
+#define PORE_CONTROL_FREEZE_MASK SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define PORE_CONTROL_CHECK_PARITY SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define PORE_CONTROL_PRV_PARITY SIXTYFOUR_BIT_CONSTANT(0x0020000000000000)
+#define PORE_CONTROL_TRAP_ENABLE SIXTYFOUR_BIT_CONSTANT(0x0010000000000000)
+#define PORE_CONTROL_NARROW_MODE_TRACE SIXTYFOUR_BIT_CONSTANT(0x0008000000000000)
+#define PORE_CONTROL_INTERRUPTIBLE SIXTYFOUR_BIT_CONSTANT(0x0004000000000000)
+#define PORE_CONTROL_PORE_DONE_OVERRIDE SIXTYFOUR_BIT_CONSTANT(0x0002000000000000)
+#define PORE_CONTROL_INTERRUPTIBLE_EN SIXTYFOUR_BIT_CONSTANT(0x0001000000000000)
+#define PORE_CONTROL_PC_BRK_PT_MASK SIXTYFOUR_BIT_CONSTANT(0xffffffffffffffff)
+#ifndef __ASSEMBLER__
+
+
+typedef union pore_reset {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t fn_reset : 1;
+ uint64_t oci_reset : 1;
+ uint64_t _reserved0 : 62;
+#else
+ uint64_t _reserved0 : 62;
+ uint64_t oci_reset : 1;
+ uint64_t fn_reset : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_reset_t;
+
+
+
+typedef union pore_error_mask {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t enable_err_handler0 : 1;
+ uint64_t enable_err_handler1 : 1;
+ uint64_t enable_err_handler2 : 1;
+ uint64_t enable_err_handler3 : 1;
+ uint64_t enable_err_handler4 : 1;
+ uint64_t enable_err_output0 : 1;
+ uint64_t enable_err_output1 : 1;
+ uint64_t enable_err_output2 : 1;
+ uint64_t enable_err_output3 : 1;
+ uint64_t enable_err_output4 : 1;
+ uint64_t enable_fatal_err_output0 : 1;
+ uint64_t enable_fatal_err_output1 : 1;
+ uint64_t enable_fatal_err_output2 : 1;
+ uint64_t enable_fatal_err_output3 : 1;
+ uint64_t enable_fatal_err_output4 : 1;
+ uint64_t stop_exe_on_error0 : 1;
+ uint64_t stop_exe_on_error1 : 1;
+ uint64_t stop_exe_on_error2 : 1;
+ uint64_t stop_exe_on_error3 : 1;
+ uint64_t stop_exe_on_error4 : 1;
+ uint64_t gate_chiplet_offline_err : 1;
+ uint64_t i2c_bad_status_0 : 1;
+ uint64_t i2c_bad_status_1 : 1;
+ uint64_t i2c_bad_status_2 : 1;
+ uint64_t i2c_bad_status_3 : 1;
+ uint64_t group_parity_error_0 : 1;
+ uint64_t group_parity_error_1 : 1;
+ uint64_t group_parity_error_2 : 1;
+ uint64_t group_parity_error_3 : 1;
+ uint64_t group_parity_error_4 : 1;
+ uint64_t _reserved0 : 34;
+#else
+ uint64_t _reserved0 : 34;
+ uint64_t group_parity_error_4 : 1;
+ uint64_t group_parity_error_3 : 1;
+ uint64_t group_parity_error_2 : 1;
+ uint64_t group_parity_error_1 : 1;
+ uint64_t group_parity_error_0 : 1;
+ uint64_t i2c_bad_status_3 : 1;
+ uint64_t i2c_bad_status_2 : 1;
+ uint64_t i2c_bad_status_1 : 1;
+ uint64_t i2c_bad_status_0 : 1;
+ uint64_t gate_chiplet_offline_err : 1;
+ uint64_t stop_exe_on_error4 : 1;
+ uint64_t stop_exe_on_error3 : 1;
+ uint64_t stop_exe_on_error2 : 1;
+ uint64_t stop_exe_on_error1 : 1;
+ uint64_t stop_exe_on_error0 : 1;
+ uint64_t enable_fatal_err_output4 : 1;
+ uint64_t enable_fatal_err_output3 : 1;
+ uint64_t enable_fatal_err_output2 : 1;
+ uint64_t enable_fatal_err_output1 : 1;
+ uint64_t enable_fatal_err_output0 : 1;
+ uint64_t enable_err_output4 : 1;
+ uint64_t enable_err_output3 : 1;
+ uint64_t enable_err_output2 : 1;
+ uint64_t enable_err_output1 : 1;
+ uint64_t enable_err_output0 : 1;
+ uint64_t enable_err_handler4 : 1;
+ uint64_t enable_err_handler3 : 1;
+ uint64_t enable_err_handler2 : 1;
+ uint64_t enable_err_handler1 : 1;
+ uint64_t enable_err_handler0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_error_mask_t;
+
+#endif // __ASSEMBLER__
+#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER0 SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER1 SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER2 SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER3 SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER4 SIXTYFOUR_BIT_CONSTANT(0x0800000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT0 SIXTYFOUR_BIT_CONSTANT(0x0400000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT1 SIXTYFOUR_BIT_CONSTANT(0x0200000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT2 SIXTYFOUR_BIT_CONSTANT(0x0100000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT3 SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT4 SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 SIXTYFOUR_BIT_CONSTANT(0x0020000000000000)
+#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT1 SIXTYFOUR_BIT_CONSTANT(0x0010000000000000)
+#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT2 SIXTYFOUR_BIT_CONSTANT(0x0008000000000000)
+#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT3 SIXTYFOUR_BIT_CONSTANT(0x0004000000000000)
+#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT4 SIXTYFOUR_BIT_CONSTANT(0x0002000000000000)
+#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR0 SIXTYFOUR_BIT_CONSTANT(0x0001000000000000)
+#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR1 SIXTYFOUR_BIT_CONSTANT(0x0000800000000000)
+#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR2 SIXTYFOUR_BIT_CONSTANT(0x0000400000000000)
+#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR3 SIXTYFOUR_BIT_CONSTANT(0x0000200000000000)
+#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR4 SIXTYFOUR_BIT_CONSTANT(0x0000100000000000)
+#define PORE_ERROR_MASK_GATE_CHIPLET_OFFLINE_ERR SIXTYFOUR_BIT_CONSTANT(0x0000080000000000)
+#define PORE_ERROR_MASK_I2C_BAD_STATUS_0 SIXTYFOUR_BIT_CONSTANT(0x0000040000000000)
+#define PORE_ERROR_MASK_I2C_BAD_STATUS_1 SIXTYFOUR_BIT_CONSTANT(0x0000020000000000)
+#define PORE_ERROR_MASK_I2C_BAD_STATUS_2 SIXTYFOUR_BIT_CONSTANT(0x0000010000000000)
+#define PORE_ERROR_MASK_I2C_BAD_STATUS_3 SIXTYFOUR_BIT_CONSTANT(0x0000008000000000)
+#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_0 SIXTYFOUR_BIT_CONSTANT(0x0000004000000000)
+#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_1 SIXTYFOUR_BIT_CONSTANT(0x0000002000000000)
+#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_2 SIXTYFOUR_BIT_CONSTANT(0x0000001000000000)
+#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_3 SIXTYFOUR_BIT_CONSTANT(0x0000000800000000)
+#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_4 SIXTYFOUR_BIT_CONSTANT(0x0000000400000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union pore_prv_base_address0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare : 25;
+ uint64_t mc : 1;
+ uint64_t chiplet_id : 6;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t chiplet_id : 6;
+ uint64_t mc : 1;
+ uint64_t spare : 25;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_prv_base_address0_t;
+
+
+
+typedef union pore_prv_base_address1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare : 25;
+ uint64_t mc : 1;
+ uint64_t chiplet_id : 6;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t chiplet_id : 6;
+ uint64_t mc : 1;
+ uint64_t spare : 25;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_prv_base_address1_t;
+
+
+
+typedef union pore_oci_base_address0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare : 18;
+ uint64_t oci_mem_route : 14;
+ uint64_t oci_base_address : 32;
+#else
+ uint64_t oci_base_address : 32;
+ uint64_t oci_mem_route : 14;
+ uint64_t spare : 18;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_oci_base_address0_t;
+
+
+
+typedef union pore_oci_base_address1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare : 18;
+ uint64_t oci_mem_route : 14;
+ uint64_t oci_base_address : 32;
+#else
+ uint64_t oci_base_address : 32;
+ uint64_t oci_mem_route : 14;
+ uint64_t spare : 18;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_oci_base_address1_t;
+
+
+
+typedef union pore_table_base_addr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 16;
+ uint64_t memory_space : 16;
+ uint64_t table_base_address : 32;
+#else
+ uint64_t table_base_address : 32;
+ uint64_t memory_space : 16;
+ uint64_t reserved : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_table_base_addr_t;
+
+
+
+typedef union pore_exe_trigger {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 8;
+ uint64_t start_vector : 4;
+ uint64_t zeroes : 8;
+ uint64_t unused : 12;
+ uint64_t mc_chiplet_select_mask : 32;
+#else
+ uint64_t mc_chiplet_select_mask : 32;
+ uint64_t unused : 12;
+ uint64_t zeroes : 8;
+ uint64_t start_vector : 4;
+ uint64_t reserved : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_exe_trigger_t;
+
+
+
+typedef union pore_scratch0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t zeroes : 8;
+ uint64_t scratch0 : 24;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t scratch0 : 24;
+ uint64_t zeroes : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_scratch0_t;
+
+
+
+typedef union pore_scratch1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t scratch1 : 64;
+#else
+ uint64_t scratch1 : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_scratch1_t;
+
+
+
+typedef union pore_scratch2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t scratch2 : 64;
+#else
+ uint64_t scratch2 : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_scratch2_t;
+
+
+
+typedef union pore_ibuf_01 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ibuf0 : 32;
+ uint64_t ibuf1 : 32;
+#else
+ uint64_t ibuf1 : 32;
+ uint64_t ibuf0 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_ibuf_01_t;
+
+
+
+typedef union pore_ibuf_2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ibuf2 : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t ibuf2 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_ibuf_2_t;
+
+
+
+typedef union pore_dbg0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t last_completed_address : 32;
+ uint64_t last_pib_parity_fail : 1;
+ uint64_t last_ret_code_prv : 3;
+ uint64_t i2c_bad_status0 : 1;
+ uint64_t i2c_bad_status1 : 1;
+ uint64_t i2c_bad_status2 : 1;
+ uint64_t i2c_bad_status3 : 1;
+ uint64_t group_parity_error0 : 1;
+ uint64_t group_parity_error1 : 1;
+ uint64_t group_parity_error2 : 1;
+ uint64_t group_parity_error3 : 1;
+ uint64_t group_parity_error4 : 1;
+ uint64_t interrupt_counter : 8;
+ uint64_t _reserved0 : 11;
+#else
+ uint64_t _reserved0 : 11;
+ uint64_t interrupt_counter : 8;
+ uint64_t group_parity_error4 : 1;
+ uint64_t group_parity_error3 : 1;
+ uint64_t group_parity_error2 : 1;
+ uint64_t group_parity_error1 : 1;
+ uint64_t group_parity_error0 : 1;
+ uint64_t i2c_bad_status3 : 1;
+ uint64_t i2c_bad_status2 : 1;
+ uint64_t i2c_bad_status1 : 1;
+ uint64_t i2c_bad_status0 : 1;
+ uint64_t last_ret_code_prv : 3;
+ uint64_t last_pib_parity_fail : 1;
+ uint64_t last_completed_address : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_dbg0_t;
+
+
+
+typedef union pore_dbg1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pc_last_access : 48;
+ uint64_t oci_master_rd_parity_err : 1;
+ uint64_t last_ret_code_oci : 3;
+ uint64_t bad_instr_parity : 1;
+ uint64_t invalid_instr_code : 1;
+ uint64_t pc_overflow_underrun : 1;
+ uint64_t bad_scan_crc : 1;
+ uint64_t pc_stack_ovflw_undrn_err : 1;
+ uint64_t instruction_fetch_error : 1;
+ uint64_t invalid_instruction_operand : 1;
+ uint64_t invalid_instruction_path : 1;
+ uint64_t invalid_start_vector : 1;
+ uint64_t fast_i2c_protocol_hang : 1;
+ uint64_t spare : 1;
+ uint64_t debug_regs_locked : 1;
+#else
+ uint64_t debug_regs_locked : 1;
+ uint64_t spare : 1;
+ uint64_t fast_i2c_protocol_hang : 1;
+ uint64_t invalid_start_vector : 1;
+ uint64_t invalid_instruction_path : 1;
+ uint64_t invalid_instruction_operand : 1;
+ uint64_t instruction_fetch_error : 1;
+ uint64_t pc_stack_ovflw_undrn_err : 1;
+ uint64_t bad_scan_crc : 1;
+ uint64_t pc_overflow_underrun : 1;
+ uint64_t invalid_instr_code : 1;
+ uint64_t bad_instr_parity : 1;
+ uint64_t last_ret_code_oci : 3;
+ uint64_t oci_master_rd_parity_err : 1;
+ uint64_t pc_last_access : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_dbg1_t;
+
+
+
+typedef union pore_pc_stack0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pc_stack0 : 48;
+ uint64_t _reserved0 : 11;
+ uint64_t set_new_stack_pointer : 1;
+ uint64_t new_stack_pointer : 4;
+#else
+ uint64_t new_stack_pointer : 4;
+ uint64_t set_new_stack_pointer : 1;
+ uint64_t _reserved0 : 11;
+ uint64_t pc_stack0 : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_pc_stack0_t;
+
+
+
+typedef union pore_pc_stack1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pc_stack1 : 48;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t pc_stack1 : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_pc_stack1_t;
+
+
+
+typedef union pore_pc_stack2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pc_stack2 : 48;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t pc_stack2 : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_pc_stack2_t;
+
+
+
+typedef union pore_id_flags {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved0 : 32;
+ uint64_t pib_parity_fail : 1;
+ uint64_t pib_status : 3;
+ uint64_t oci_parity_fail : 1;
+ uint64_t oci_status : 3;
+ uint64_t reserved1 : 8;
+ uint64_t ugt : 1;
+ uint64_t ult : 1;
+ uint64_t sgt : 1;
+ uint64_t slt : 1;
+ uint64_t c : 1;
+ uint64_t o : 1;
+ uint64_t n : 1;
+ uint64_t z : 1;
+ uint64_t reserved2 : 4;
+ uint64_t ibuf_id : 4;
+#else
+ uint64_t ibuf_id : 4;
+ uint64_t reserved2 : 4;
+ uint64_t z : 1;
+ uint64_t n : 1;
+ uint64_t o : 1;
+ uint64_t c : 1;
+ uint64_t slt : 1;
+ uint64_t sgt : 1;
+ uint64_t ult : 1;
+ uint64_t ugt : 1;
+ uint64_t reserved1 : 8;
+ uint64_t oci_status : 3;
+ uint64_t oci_parity_fail : 1;
+ uint64_t pib_status : 3;
+ uint64_t pib_parity_fail : 1;
+ uint64_t reserved0 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_id_flags_t;
+
+
+
+typedef union pore_data0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t data0 : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t data0 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_data0_t;
+
+
+
+typedef union pore_memory_reloc {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 30;
+ uint64_t memory_reloc_region : 2;
+ uint64_t memory_reloc_base : 20;
+ uint64_t _reserved1 : 12;
+#else
+ uint64_t _reserved1 : 12;
+ uint64_t memory_reloc_base : 20;
+ uint64_t memory_reloc_region : 2;
+ uint64_t _reserved0 : 30;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_memory_reloc_t;
+
+
+
+typedef union pore_i2c_en_param {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t i2c_engine_identifier : 4;
+ uint64_t reserved0 : 1;
+ uint64_t i2c_engine_address_range : 3;
+ uint64_t reserved1 : 3;
+ uint64_t i2c_engine_port : 5;
+ uint64_t reserved2 : 1;
+ uint64_t i2c_engine_device_id : 7;
+ uint64_t reserved3 : 2;
+ uint64_t i2c_engine_speed : 2;
+ uint64_t i2c_poll_threshold : 4;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t i2c_poll_threshold : 4;
+ uint64_t i2c_engine_speed : 2;
+ uint64_t reserved3 : 2;
+ uint64_t i2c_engine_device_id : 7;
+ uint64_t reserved2 : 1;
+ uint64_t i2c_engine_port : 5;
+ uint64_t reserved1 : 3;
+ uint64_t i2c_engine_address_range : 3;
+ uint64_t reserved0 : 1;
+ uint64_t i2c_engine_identifier : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_i2c_en_param_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __PORE_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/pore_register_addresses.h b/src/ssx/pgp/registers/pore_register_addresses.h
new file mode 100755
index 0000000..0fc769b
--- /dev/null
+++ b/src/ssx/pgp/registers/pore_register_addresses.h
@@ -0,0 +1,130 @@
+#ifndef __PORE_REGISTER_ADDRESSES_H__
+#define __PORE_REGISTER_ADDRESSES_H__
+
+// $Id: pore_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pore_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pore_register_addresses.h
+/// \brief Symbolic addresses for the PORE unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define PORE_GPE0_OCI_BASE 0x40000000
+#define PORE_GPE1_OCI_BASE 0x40000100
+#define PORE_SLW_OCI_BASE 0x40040000
+#define PORE_STATUS_OFFSET 0x00000000
+#define PORE_GPE0_STATUS 0x40000000
+#define PORE_GPE1_STATUS 0x40000100
+#define PORE_SLW_STATUS 0x40040000
+#define PORE_CONTROL_OFFSET 0x00000008
+#define PORE_GPE0_CONTROL 0x40000008
+#define PORE_GPE1_CONTROL 0x40000108
+#define PORE_SLW_CONTROL 0x40040008
+#define PORE_RESET_OFFSET 0x00000010
+#define PORE_GPE0_RESET 0x40000010
+#define PORE_GPE1_RESET 0x40000110
+#define PORE_SLW_RESET 0x40040010
+#define PORE_ERROR_MASK_OFFSET 0x00000018
+#define PORE_GPE0_ERROR_MASK 0x40000018
+#define PORE_GPE1_ERROR_MASK 0x40000118
+#define PORE_SLW_ERROR_MASK 0x40040018
+#define PORE_PRV_BASE_ADDRESS0_OFFSET 0x00000020
+#define PORE_GPE0_PRV_BASE_ADDRESS0 0x40000020
+#define PORE_GPE1_PRV_BASE_ADDRESS0 0x40000120
+#define PORE_SLW_PRV_BASE_ADDRESS0 0x40040020
+#define PORE_PRV_BASE_ADDRESS1_OFFSET 0x00000028
+#define PORE_GPE0_PRV_BASE_ADDRESS1 0x40000028
+#define PORE_GPE1_PRV_BASE_ADDRESS1 0x40000128
+#define PORE_SLW_PRV_BASE_ADDRESS1 0x40040028
+#define PORE_OCI_BASE_ADDRESS0_OFFSET 0x00000030
+#define PORE_GPE0_OCI_BASE_ADDRESS0 0x40000030
+#define PORE_GPE1_OCI_BASE_ADDRESS0 0x40000130
+#define PORE_SLW_OCI_BASE_ADDRESS0 0x40040030
+#define PORE_OCI_BASE_ADDRESS1_OFFSET 0x00000038
+#define PORE_GPE0_OCI_BASE_ADDRESS1 0x40000038
+#define PORE_GPE1_OCI_BASE_ADDRESS1 0x40000138
+#define PORE_SLW_OCI_BASE_ADDRESS1 0x40040038
+#define PORE_TABLE_BASE_ADDR_OFFSET 0x00000040
+#define PORE_GPE0_TABLE_BASE_ADDR 0x40000040
+#define PORE_GPE1_TABLE_BASE_ADDR 0x40000140
+#define PORE_SLW_TABLE_BASE_ADDR 0x40040040
+#define PORE_EXE_TRIGGER_OFFSET 0x00000048
+#define PORE_GPE0_EXE_TRIGGER 0x40000048
+#define PORE_GPE1_EXE_TRIGGER 0x40000148
+#define PORE_SLW_EXE_TRIGGER 0x40040048
+#define PORE_SCRATCH0_OFFSET 0x00000050
+#define PORE_GPE0_SCRATCH0 0x40000050
+#define PORE_GPE1_SCRATCH0 0x40000150
+#define PORE_SLW_SCRATCH0 0x40040050
+#define PORE_SCRATCH1_OFFSET 0x00000058
+#define PORE_GPE0_SCRATCH1 0x40000058
+#define PORE_GPE1_SCRATCH1 0x40000158
+#define PORE_SLW_SCRATCH1 0x40040058
+#define PORE_SCRATCH2_OFFSET 0x00000060
+#define PORE_GPE0_SCRATCH2 0x40000060
+#define PORE_GPE1_SCRATCH2 0x40000160
+#define PORE_SLW_SCRATCH2 0x40040060
+#define PORE_IBUF_01_OFFSET 0x00000068
+#define PORE_GPE0_IBUF_01 0x40000068
+#define PORE_GPE1_IBUF_01 0x40000168
+#define PORE_SLW_IBUF_01 0x40040068
+#define PORE_IBUF_2_OFFSET 0x00000070
+#define PORE_GPE0_IBUF_2 0x40000070
+#define PORE_GPE1_IBUF_2 0x40000170
+#define PORE_SLW_IBUF_2 0x40040070
+#define PORE_DBG0_OFFSET 0x00000078
+#define PORE_GPE0_DBG0 0x40000078
+#define PORE_GPE1_DBG0 0x40000178
+#define PORE_SLW_DBG0 0x40040078
+#define PORE_DBG1_OFFSET 0x00000080
+#define PORE_GPE0_DBG1 0x40000080
+#define PORE_GPE1_DBG1 0x40000180
+#define PORE_SLW_DBG1 0x40040080
+#define PORE_PC_STACK0_OFFSET 0x00000088
+#define PORE_GPE0_PC_STACK0 0x40000088
+#define PORE_GPE1_PC_STACK0 0x40000188
+#define PORE_SLW_PC_STACK0 0x40040088
+#define PORE_PC_STACK1_OFFSET 0x00000090
+#define PORE_GPE0_PC_STACK1 0x40000090
+#define PORE_GPE1_PC_STACK1 0x40000190
+#define PORE_SLW_PC_STACK1 0x40040090
+#define PORE_PC_STACK2_OFFSET 0x00000098
+#define PORE_GPE0_PC_STACK2 0x40000098
+#define PORE_GPE1_PC_STACK2 0x40000198
+#define PORE_SLW_PC_STACK2 0x40040098
+#define PORE_ID_FLAGS_OFFSET 0x000000a0
+#define PORE_GPE0_ID_FLAGS 0x400000a0
+#define PORE_GPE1_ID_FLAGS 0x400001a0
+#define PORE_SLW_ID_FLAGS 0x400400a0
+#define PORE_DATA0_OFFSET 0x000000a8
+#define PORE_GPE0_DATA0 0x400000a8
+#define PORE_GPE1_DATA0 0x400001a8
+#define PORE_SLW_DATA0 0x400400a8
+#define PORE_MEMORY_RELOC_OFFSET 0x000000b0
+#define PORE_GPE0_MEMORY_RELOC 0x400000b0
+#define PORE_GPE1_MEMORY_RELOC 0x400001b0
+#define PORE_SLW_MEMORY_RELOC 0x400400b0
+#define PORE_I2C_E0_PARAM_OFFSET 0x000000b8
+#define PORE_I2C_E1_PARAM_OFFSET 0x000000c0
+#define PORE_I2C_E2_PARAM_OFFSET 0x000000c8
+#define PORE_GPE0_I2C_EN_PARAM(n) (PORE_GPE0_I2C_E0_PARAM + ((PORE_GPE0_I2C_E1_PARAM - PORE_GPE0_I2C_E0_PARAM) * (n)))
+#define PORE_GPE1_I2C_EN_PARAM(n) (PORE_GPE1_I2C_E0_PARAM + ((PORE_GPE1_I2C_E1_PARAM - PORE_GPE1_I2C_E0_PARAM) * (n)))
+#define PORE_SLW_I2C_EN_PARAM(n) (PORE_SLW_I2C_E0_PARAM + ((PORE_SLW_I2C_E1_PARAM - PORE_SLW_I2C_E0_PARAM) * (n)))
+#define PORE_GPE0_I2C_E0_PARAM 0x400000b8
+#define PORE_GPE1_I2C_E0_PARAM 0x400001b8
+#define PORE_SLW_I2C_E0_PARAM 0x400400b8
+#define PORE_GPE0_I2C_E1_PARAM 0x400000c0
+#define PORE_GPE1_I2C_E1_PARAM 0x400001c0
+#define PORE_SLW_I2C_E1_PARAM 0x400400c0
+#define PORE_GPE0_I2C_E2_PARAM 0x400000c8
+#define PORE_GPE1_I2C_E2_PARAM 0x400001c8
+#define PORE_SLW_I2C_E2_PARAM 0x400400c8
+
+#endif // __PORE_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/sbe_firmware_registers.h b/src/ssx/pgp/registers/sbe_firmware_registers.h
new file mode 100644
index 0000000..8175c11
--- /dev/null
+++ b/src/ssx/pgp/registers/sbe_firmware_registers.h
@@ -0,0 +1,906 @@
+#ifndef __SBE_FIRMWARE_REGISTERS_H__
+#define __SBE_FIRMWARE_REGISTERS_H__
+
+// $Id: sbe_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sbe_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file sbe_firmware_registers.h
+/// \brief C register structs for the SBE unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union pore_sbe_status {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cur_state : 8;
+ uint64_t freeze_action : 1;
+ uint64_t interrupt_pending : 1;
+ uint64_t spare : 2;
+ uint64_t stack_pointer : 4;
+ uint64_t pc : 48;
+#else
+ uint64_t pc : 48;
+ uint64_t stack_pointer : 4;
+ uint64_t spare : 2;
+ uint64_t interrupt_pending : 1;
+ uint64_t freeze_action : 1;
+ uint64_t cur_state : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_status_t;
+
+#endif // __ASSEMBLER__
+#define PORE_SBE_STATUS_CUR_STATE_MASK SIXTYFOUR_BIT_CONSTANT(0xff00000000000000)
+#define PORE_SBE_STATUS_FREEZE_ACTION SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define PORE_SBE_STATUS_INTERRUPT_PENDING SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define PORE_SBE_STATUS_SPARE_MASK SIXTYFOUR_BIT_CONSTANT(0x0030000000000000)
+#define PORE_SBE_STATUS_STACK_POINTER_MASK SIXTYFOUR_BIT_CONSTANT(0x000f000000000000)
+#define PORE_SBE_STATUS_PC_MASK SIXTYFOUR_BIT_CONSTANT(0xffffffffffffffff)
+#ifndef __ASSEMBLER__
+
+
+typedef union pore_sbe_control {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t start_stop : 1;
+ uint64_t continue_step : 1;
+ uint64_t skip : 1;
+ uint64_t set_pc : 1;
+ uint64_t set_tp_scan_clk : 3;
+ uint64_t lock_exe_trig : 1;
+ uint64_t freeze_mask : 1;
+ uint64_t check_parity : 1;
+ uint64_t prv_parity : 1;
+ uint64_t trap_enable : 1;
+ uint64_t narrow_mode_trace : 1;
+ uint64_t interruptible : 1;
+ uint64_t pore_done_override : 1;
+ uint64_t interruptible_en : 1;
+ uint64_t pc_brk_pt : 48;
+#else
+ uint64_t pc_brk_pt : 48;
+ uint64_t interruptible_en : 1;
+ uint64_t pore_done_override : 1;
+ uint64_t interruptible : 1;
+ uint64_t narrow_mode_trace : 1;
+ uint64_t trap_enable : 1;
+ uint64_t prv_parity : 1;
+ uint64_t check_parity : 1;
+ uint64_t freeze_mask : 1;
+ uint64_t lock_exe_trig : 1;
+ uint64_t set_tp_scan_clk : 3;
+ uint64_t set_pc : 1;
+ uint64_t skip : 1;
+ uint64_t continue_step : 1;
+ uint64_t start_stop : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_control_t;
+
+#endif // __ASSEMBLER__
+#define PORE_SBE_CONTROL_START_STOP SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define PORE_SBE_CONTROL_CONTINUE_STEP SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define PORE_SBE_CONTROL_SKIP SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define PORE_SBE_CONTROL_SET_PC SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define PORE_SBE_CONTROL_SET_TP_SCAN_CLK_MASK SIXTYFOUR_BIT_CONSTANT(0x0e00000000000000)
+#define PORE_SBE_CONTROL_LOCK_EXE_TRIG SIXTYFOUR_BIT_CONSTANT(0x0100000000000000)
+#define PORE_SBE_CONTROL_FREEZE_MASK SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define PORE_SBE_CONTROL_CHECK_PARITY SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define PORE_SBE_CONTROL_PRV_PARITY SIXTYFOUR_BIT_CONSTANT(0x0020000000000000)
+#define PORE_SBE_CONTROL_TRAP_ENABLE SIXTYFOUR_BIT_CONSTANT(0x0010000000000000)
+#define PORE_SBE_CONTROL_NARROW_MODE_TRACE SIXTYFOUR_BIT_CONSTANT(0x0008000000000000)
+#define PORE_SBE_CONTROL_INTERRUPTIBLE SIXTYFOUR_BIT_CONSTANT(0x0004000000000000)
+#define PORE_SBE_CONTROL_PORE_DONE_OVERRIDE SIXTYFOUR_BIT_CONSTANT(0x0002000000000000)
+#define PORE_SBE_CONTROL_INTERRUPTIBLE_EN SIXTYFOUR_BIT_CONSTANT(0x0001000000000000)
+#define PORE_SBE_CONTROL_PC_BRK_PT_MASK SIXTYFOUR_BIT_CONSTANT(0xffffffffffffffff)
+#ifndef __ASSEMBLER__
+
+
+typedef union pore_sbe_reset {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t fn_reset : 1;
+ uint64_t oci_reset : 1;
+ uint64_t _reserved0 : 62;
+#else
+ uint64_t _reserved0 : 62;
+ uint64_t oci_reset : 1;
+ uint64_t fn_reset : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_reset_t;
+
+
+
+typedef union pore_sbe_error_mask {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t enable_err_handler0 : 1;
+ uint64_t enable_err_handler1 : 1;
+ uint64_t enable_err_handler2 : 1;
+ uint64_t enable_err_handler3 : 1;
+ uint64_t enable_err_handler4 : 1;
+ uint64_t enable_err_output0 : 1;
+ uint64_t enable_err_output1 : 1;
+ uint64_t enable_err_output2 : 1;
+ uint64_t enable_err_output3 : 1;
+ uint64_t enable_err_output4 : 1;
+ uint64_t enable_fatal_err_output0 : 1;
+ uint64_t enable_fatal_err_output1 : 1;
+ uint64_t enable_fatal_err_output2 : 1;
+ uint64_t enable_fatal_err_output3 : 1;
+ uint64_t enable_fatal_err_output4 : 1;
+ uint64_t stop_exe_on_error0 : 1;
+ uint64_t stop_exe_on_error1 : 1;
+ uint64_t stop_exe_on_error2 : 1;
+ uint64_t stop_exe_on_error3 : 1;
+ uint64_t stop_exe_on_error4 : 1;
+ uint64_t gate_chiplet_offline_err : 1;
+ uint64_t i2c_bad_status_0 : 1;
+ uint64_t i2c_bad_status_1 : 1;
+ uint64_t i2c_bad_status_2 : 1;
+ uint64_t i2c_bad_status_3 : 1;
+ uint64_t group_parity_error_0 : 1;
+ uint64_t group_parity_error_1 : 1;
+ uint64_t group_parity_error_2 : 1;
+ uint64_t group_parity_error_3 : 1;
+ uint64_t group_parity_error_4 : 1;
+ uint64_t _reserved0 : 34;
+#else
+ uint64_t _reserved0 : 34;
+ uint64_t group_parity_error_4 : 1;
+ uint64_t group_parity_error_3 : 1;
+ uint64_t group_parity_error_2 : 1;
+ uint64_t group_parity_error_1 : 1;
+ uint64_t group_parity_error_0 : 1;
+ uint64_t i2c_bad_status_3 : 1;
+ uint64_t i2c_bad_status_2 : 1;
+ uint64_t i2c_bad_status_1 : 1;
+ uint64_t i2c_bad_status_0 : 1;
+ uint64_t gate_chiplet_offline_err : 1;
+ uint64_t stop_exe_on_error4 : 1;
+ uint64_t stop_exe_on_error3 : 1;
+ uint64_t stop_exe_on_error2 : 1;
+ uint64_t stop_exe_on_error1 : 1;
+ uint64_t stop_exe_on_error0 : 1;
+ uint64_t enable_fatal_err_output4 : 1;
+ uint64_t enable_fatal_err_output3 : 1;
+ uint64_t enable_fatal_err_output2 : 1;
+ uint64_t enable_fatal_err_output1 : 1;
+ uint64_t enable_fatal_err_output0 : 1;
+ uint64_t enable_err_output4 : 1;
+ uint64_t enable_err_output3 : 1;
+ uint64_t enable_err_output2 : 1;
+ uint64_t enable_err_output1 : 1;
+ uint64_t enable_err_output0 : 1;
+ uint64_t enable_err_handler4 : 1;
+ uint64_t enable_err_handler3 : 1;
+ uint64_t enable_err_handler2 : 1;
+ uint64_t enable_err_handler1 : 1;
+ uint64_t enable_err_handler0 : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_error_mask_t;
+
+#endif // __ASSEMBLER__
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER0 SIXTYFOUR_BIT_CONSTANT(0x8000000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER1 SIXTYFOUR_BIT_CONSTANT(0x4000000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER2 SIXTYFOUR_BIT_CONSTANT(0x2000000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER3 SIXTYFOUR_BIT_CONSTANT(0x1000000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER4 SIXTYFOUR_BIT_CONSTANT(0x0800000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT0 SIXTYFOUR_BIT_CONSTANT(0x0400000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT1 SIXTYFOUR_BIT_CONSTANT(0x0200000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT2 SIXTYFOUR_BIT_CONSTANT(0x0100000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT3 SIXTYFOUR_BIT_CONSTANT(0x0080000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT4 SIXTYFOUR_BIT_CONSTANT(0x0040000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 SIXTYFOUR_BIT_CONSTANT(0x0020000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT1 SIXTYFOUR_BIT_CONSTANT(0x0010000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT2 SIXTYFOUR_BIT_CONSTANT(0x0008000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT3 SIXTYFOUR_BIT_CONSTANT(0x0004000000000000)
+#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT4 SIXTYFOUR_BIT_CONSTANT(0x0002000000000000)
+#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR0 SIXTYFOUR_BIT_CONSTANT(0x0001000000000000)
+#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR1 SIXTYFOUR_BIT_CONSTANT(0x0000800000000000)
+#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR2 SIXTYFOUR_BIT_CONSTANT(0x0000400000000000)
+#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR3 SIXTYFOUR_BIT_CONSTANT(0x0000200000000000)
+#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR4 SIXTYFOUR_BIT_CONSTANT(0x0000100000000000)
+#define PORE_SBE_ERROR_MASK_GATE_CHIPLET_OFFLINE_ERR SIXTYFOUR_BIT_CONSTANT(0x0000080000000000)
+#define PORE_SBE_ERROR_MASK_I2C_BAD_STATUS_0 SIXTYFOUR_BIT_CONSTANT(0x0000040000000000)
+#define PORE_SBE_ERROR_MASK_I2C_BAD_STATUS_1 SIXTYFOUR_BIT_CONSTANT(0x0000020000000000)
+#define PORE_SBE_ERROR_MASK_I2C_BAD_STATUS_2 SIXTYFOUR_BIT_CONSTANT(0x0000010000000000)
+#define PORE_SBE_ERROR_MASK_I2C_BAD_STATUS_3 SIXTYFOUR_BIT_CONSTANT(0x0000008000000000)
+#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_0 SIXTYFOUR_BIT_CONSTANT(0x0000004000000000)
+#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_1 SIXTYFOUR_BIT_CONSTANT(0x0000002000000000)
+#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_2 SIXTYFOUR_BIT_CONSTANT(0x0000001000000000)
+#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_3 SIXTYFOUR_BIT_CONSTANT(0x0000000800000000)
+#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_4 SIXTYFOUR_BIT_CONSTANT(0x0000000400000000)
+#ifndef __ASSEMBLER__
+
+
+typedef union pore_sbe_prv_base_address0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare : 25;
+ uint64_t mc : 1;
+ uint64_t chiplet_id : 6;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t chiplet_id : 6;
+ uint64_t mc : 1;
+ uint64_t spare : 25;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_prv_base_address0_t;
+
+
+
+typedef union pore_sbe_prv_base_address1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare : 25;
+ uint64_t mc : 1;
+ uint64_t chiplet_id : 6;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t chiplet_id : 6;
+ uint64_t mc : 1;
+ uint64_t spare : 25;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_prv_base_address1_t;
+
+
+
+typedef union pore_sbe_oci_base_address0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare : 18;
+ uint64_t oci_mem_route : 14;
+ uint64_t oci_base_address : 32;
+#else
+ uint64_t oci_base_address : 32;
+ uint64_t oci_mem_route : 14;
+ uint64_t spare : 18;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_oci_base_address0_t;
+
+
+
+typedef union pore_sbe_oci_base_address1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t spare : 18;
+ uint64_t oci_mem_route : 14;
+ uint64_t oci_base_address : 32;
+#else
+ uint64_t oci_base_address : 32;
+ uint64_t oci_mem_route : 14;
+ uint64_t spare : 18;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_oci_base_address1_t;
+
+
+
+typedef union pore_sbe_table_base_addr {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 16;
+ uint64_t memory_space : 16;
+ uint64_t table_base_address : 32;
+#else
+ uint64_t table_base_address : 32;
+ uint64_t memory_space : 16;
+ uint64_t reserved : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_table_base_addr_t;
+
+
+
+typedef union pore_sbe_exe_trigger {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved : 8;
+ uint64_t start_vector : 4;
+ uint64_t zeroes : 8;
+ uint64_t unused : 12;
+ uint64_t mc_chiplet_select_mask : 32;
+#else
+ uint64_t mc_chiplet_select_mask : 32;
+ uint64_t unused : 12;
+ uint64_t zeroes : 8;
+ uint64_t start_vector : 4;
+ uint64_t reserved : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_exe_trigger_t;
+
+
+
+typedef union pore_sbe_scratch0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t zeroes : 8;
+ uint64_t scratch0 : 24;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t scratch0 : 24;
+ uint64_t zeroes : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_scratch0_t;
+
+
+
+typedef union pore_sbe_scratch1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t scratch1 : 64;
+#else
+ uint64_t scratch1 : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_scratch1_t;
+
+
+
+typedef union pore_sbe_scratch2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t scratch2 : 64;
+#else
+ uint64_t scratch2 : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_scratch2_t;
+
+
+
+typedef union pore_sbe_ibuf_01 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ibuf0 : 32;
+ uint64_t ibuf1 : 32;
+#else
+ uint64_t ibuf1 : 32;
+ uint64_t ibuf0 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_ibuf_01_t;
+
+
+
+typedef union pore_sbe_ibuf_2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ibuf2 : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t ibuf2 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_ibuf_2_t;
+
+
+
+typedef union pore_sbe_dbg0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t last_completed_address : 32;
+ uint64_t last_pib_parity_fail : 1;
+ uint64_t last_ret_code_prv : 3;
+ uint64_t i2c_bad_status0 : 1;
+ uint64_t i2c_bad_status1 : 1;
+ uint64_t i2c_bad_status2 : 1;
+ uint64_t i2c_bad_status3 : 1;
+ uint64_t group_parity_error0 : 1;
+ uint64_t group_parity_error1 : 1;
+ uint64_t group_parity_error2 : 1;
+ uint64_t group_parity_error3 : 1;
+ uint64_t group_parity_error4 : 1;
+ uint64_t interrupt_counter : 8;
+ uint64_t _reserved0 : 11;
+#else
+ uint64_t _reserved0 : 11;
+ uint64_t interrupt_counter : 8;
+ uint64_t group_parity_error4 : 1;
+ uint64_t group_parity_error3 : 1;
+ uint64_t group_parity_error2 : 1;
+ uint64_t group_parity_error1 : 1;
+ uint64_t group_parity_error0 : 1;
+ uint64_t i2c_bad_status3 : 1;
+ uint64_t i2c_bad_status2 : 1;
+ uint64_t i2c_bad_status1 : 1;
+ uint64_t i2c_bad_status0 : 1;
+ uint64_t last_ret_code_prv : 3;
+ uint64_t last_pib_parity_fail : 1;
+ uint64_t last_completed_address : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_dbg0_t;
+
+
+
+typedef union pore_sbe_dbg1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pc_last_access : 48;
+ uint64_t oci_master_rd_parity_err : 1;
+ uint64_t last_ret_code_oci : 3;
+ uint64_t bad_instr_parity : 1;
+ uint64_t invalid_instr_code : 1;
+ uint64_t pc_overflow_underrun : 1;
+ uint64_t bad_scan_crc : 1;
+ uint64_t pc_stack_ovflw_undrn_err : 1;
+ uint64_t instruction_fetch_error : 1;
+ uint64_t invalid_instruction_operand : 1;
+ uint64_t invalid_instruction_path : 1;
+ uint64_t invalid_start_vector : 1;
+ uint64_t fast_i2c_protocol_hang : 1;
+ uint64_t spare : 1;
+ uint64_t debug_regs_locked : 1;
+#else
+ uint64_t debug_regs_locked : 1;
+ uint64_t spare : 1;
+ uint64_t fast_i2c_protocol_hang : 1;
+ uint64_t invalid_start_vector : 1;
+ uint64_t invalid_instruction_path : 1;
+ uint64_t invalid_instruction_operand : 1;
+ uint64_t instruction_fetch_error : 1;
+ uint64_t pc_stack_ovflw_undrn_err : 1;
+ uint64_t bad_scan_crc : 1;
+ uint64_t pc_overflow_underrun : 1;
+ uint64_t invalid_instr_code : 1;
+ uint64_t bad_instr_parity : 1;
+ uint64_t last_ret_code_oci : 3;
+ uint64_t oci_master_rd_parity_err : 1;
+ uint64_t pc_last_access : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_dbg1_t;
+
+
+
+typedef union pore_sbe_pc_stack0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pc_stack0 : 48;
+ uint64_t _reserved0 : 11;
+ uint64_t set_new_stack_pointer : 1;
+ uint64_t new_stack_pointer : 4;
+#else
+ uint64_t new_stack_pointer : 4;
+ uint64_t set_new_stack_pointer : 1;
+ uint64_t _reserved0 : 11;
+ uint64_t pc_stack0 : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_pc_stack0_t;
+
+
+
+typedef union pore_sbe_pc_stack1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pc_stack1 : 48;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t pc_stack1 : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_pc_stack1_t;
+
+
+
+typedef union pore_sbe_pc_stack2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pc_stack2 : 48;
+ uint64_t _reserved0 : 16;
+#else
+ uint64_t _reserved0 : 16;
+ uint64_t pc_stack2 : 48;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_pc_stack2_t;
+
+
+
+typedef union pore_sbe_id_flags {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t reserved0 : 32;
+ uint64_t pib_parity_fail : 1;
+ uint64_t pib_status : 3;
+ uint64_t oci_parity_fail : 1;
+ uint64_t oci_status : 3;
+ uint64_t reserved1 : 8;
+ uint64_t ugt : 1;
+ uint64_t ult : 1;
+ uint64_t sgt : 1;
+ uint64_t slt : 1;
+ uint64_t c : 1;
+ uint64_t o : 1;
+ uint64_t n : 1;
+ uint64_t z : 1;
+ uint64_t reserved2 : 4;
+ uint64_t ibuf_id : 4;
+#else
+ uint64_t ibuf_id : 4;
+ uint64_t reserved2 : 4;
+ uint64_t z : 1;
+ uint64_t n : 1;
+ uint64_t o : 1;
+ uint64_t c : 1;
+ uint64_t slt : 1;
+ uint64_t sgt : 1;
+ uint64_t ult : 1;
+ uint64_t ugt : 1;
+ uint64_t reserved1 : 8;
+ uint64_t oci_status : 3;
+ uint64_t oci_parity_fail : 1;
+ uint64_t pib_status : 3;
+ uint64_t pib_parity_fail : 1;
+ uint64_t reserved0 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_id_flags_t;
+
+
+
+typedef union pore_sbe_data0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t data0 : 32;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t data0 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_data0_t;
+
+
+
+typedef union pore_sbe_memory_reloc {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t _reserved0 : 30;
+ uint64_t memory_reloc_region : 2;
+ uint64_t memory_reloc_base : 20;
+ uint64_t _reserved1 : 12;
+#else
+ uint64_t _reserved1 : 12;
+ uint64_t memory_reloc_base : 20;
+ uint64_t memory_reloc_region : 2;
+ uint64_t _reserved0 : 30;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_memory_reloc_t;
+
+
+
+typedef union pore_sbe_i2c_en_param {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t i2c_engine_identifier : 4;
+ uint64_t reserved0 : 1;
+ uint64_t i2c_engine_address_range : 3;
+ uint64_t reserved1 : 3;
+ uint64_t i2c_engine_port : 5;
+ uint64_t reserved2 : 1;
+ uint64_t i2c_engine_device_id : 7;
+ uint64_t reserved3 : 2;
+ uint64_t i2c_engine_speed : 2;
+ uint64_t i2c_poll_threshold : 4;
+ uint64_t _reserved0 : 32;
+#else
+ uint64_t _reserved0 : 32;
+ uint64_t i2c_poll_threshold : 4;
+ uint64_t i2c_engine_speed : 2;
+ uint64_t reserved3 : 2;
+ uint64_t i2c_engine_device_id : 7;
+ uint64_t reserved2 : 1;
+ uint64_t i2c_engine_port : 5;
+ uint64_t reserved1 : 3;
+ uint64_t i2c_engine_address_range : 3;
+ uint64_t reserved0 : 1;
+ uint64_t i2c_engine_identifier : 4;
+#endif // _BIG_ENDIAN
+ } fields;
+} pore_sbe_i2c_en_param_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __SBE_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/sbe_register_addresses.h b/src/ssx/pgp/registers/sbe_register_addresses.h
new file mode 100644
index 0000000..794acea
--- /dev/null
+++ b/src/ssx/pgp/registers/sbe_register_addresses.h
@@ -0,0 +1,48 @@
+#ifndef __SBE_REGISTER_ADDRESSES_H__
+#define __SBE_REGISTER_ADDRESSES_H__
+
+// $Id: sbe_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sbe_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file sbe_register_addresses.h
+/// \brief Symbolic addresses for the SBE unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define PORE_SBE_PIB_BASE 0x000e0000
+#define PORE_SBE_STATUS 0x000e0000
+#define PORE_SBE_CONTROL 0x000e0001
+#define PORE_SBE_RESET 0x000e0002
+#define PORE_SBE_ERROR_MASK 0x000e0003
+#define PORE_SBE_PRV_BASE_ADDRESS0 0x000e0004
+#define PORE_SBE_PRV_BASE_ADDRESS1 0x000e0005
+#define PORE_SBE_OCI_BASE_ADDRESS0 0x000e0006
+#define PORE_SBE_OCI_BASE_ADDRESS1 0x000e0007
+#define PORE_SBE_TABLE_BASE_ADDR 0x000e0008
+#define PORE_SBE_EXE_TRIGGER 0x000e0009
+#define PORE_SBE_SCRATCH0 0x000e000a
+#define PORE_SBE_SCRATCH1 0x000e000b
+#define PORE_SBE_SCRATCH2 0x000e000c
+#define PORE_SBE_IBUF_01 0x000e000d
+#define PORE_SBE_IBUF_2 0x000e000e
+#define PORE_SBE_DBG0 0x000e000f
+#define PORE_SBE_DBG1 0x000e0010
+#define PORE_SBE_PC_STACK0 0x000e0011
+#define PORE_SBE_PC_STACK1 0x000e0012
+#define PORE_SBE_PC_STACK2 0x000e0013
+#define PORE_SBE_ID_FLAGS 0x000e0014
+#define PORE_SBE_DATA0 0x000e0015
+#define PORE_SBE_MEMORY_RELOC 0x000e0016
+#define PORE_SBE_I2C_EN_PARAM(n) (PORE_SBE_I2C_E0_PARAM + ((PORE_SBE_I2C_E1_PARAM - PORE_SBE_I2C_E0_PARAM) * (n)))
+#define PORE_SBE_I2C_E0_PARAM 0x000e0017
+#define PORE_SBE_I2C_E1_PARAM 0x000e0018
+#define PORE_SBE_I2C_E2_PARAM 0x000e0019
+
+#endif // __SBE_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/sensors_firmware_registers.h b/src/ssx/pgp/registers/sensors_firmware_registers.h
new file mode 100755
index 0000000..9cb252e
--- /dev/null
+++ b/src/ssx/pgp/registers/sensors_firmware_registers.h
@@ -0,0 +1,668 @@
+#ifndef __SENSORS_FIRMWARE_REGISTERS_H__
+#define __SENSORS_FIRMWARE_REGISTERS_H__
+
+// $Id: sensors_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sensors_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file sensors_firmware_registers.h
+/// \brief C register structs for the SENSORS unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union sensors_v0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dts0 : 12;
+ uint64_t thermal_trip0 : 2;
+ uint64_t spare0 : 1;
+ uint64_t valid0 : 1;
+ uint64_t dts1 : 12;
+ uint64_t thermal_trip1 : 2;
+ uint64_t spare1 : 1;
+ uint64_t valid1 : 1;
+ uint64_t dts2 : 12;
+ uint64_t thermal_trip2 : 2;
+ uint64_t spare2 : 1;
+ uint64_t valid2 : 1;
+ uint64_t dts3 : 12;
+ uint64_t thermal_trip3 : 2;
+ uint64_t spare3 : 1;
+ uint64_t valid3 : 1;
+#else
+ uint64_t valid3 : 1;
+ uint64_t spare3 : 1;
+ uint64_t thermal_trip3 : 2;
+ uint64_t dts3 : 12;
+ uint64_t valid2 : 1;
+ uint64_t spare2 : 1;
+ uint64_t thermal_trip2 : 2;
+ uint64_t dts2 : 12;
+ uint64_t valid1 : 1;
+ uint64_t spare1 : 1;
+ uint64_t thermal_trip1 : 2;
+ uint64_t dts1 : 12;
+ uint64_t valid0 : 1;
+ uint64_t spare0 : 1;
+ uint64_t thermal_trip0 : 2;
+ uint64_t dts0 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v0_t;
+
+
+
+typedef union sensors_v1 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dts4 : 12;
+ uint64_t thermal_trip4 : 2;
+ uint64_t spare4 : 1;
+ uint64_t valid4 : 1;
+ uint64_t dts5 : 12;
+ uint64_t thermal_trip5 : 2;
+ uint64_t spare5 : 1;
+ uint64_t valid5 : 1;
+ uint64_t dts6 : 12;
+ uint64_t thermal_trip6 : 2;
+ uint64_t spare6 : 1;
+ uint64_t valid6 : 1;
+ uint64_t dts7 : 12;
+ uint64_t thermal_trip7 : 2;
+ uint64_t spare7 : 1;
+ uint64_t valid7 : 1;
+#else
+ uint64_t valid7 : 1;
+ uint64_t spare7 : 1;
+ uint64_t thermal_trip7 : 2;
+ uint64_t dts7 : 12;
+ uint64_t valid6 : 1;
+ uint64_t spare6 : 1;
+ uint64_t thermal_trip6 : 2;
+ uint64_t dts6 : 12;
+ uint64_t valid5 : 1;
+ uint64_t spare5 : 1;
+ uint64_t thermal_trip5 : 2;
+ uint64_t dts5 : 12;
+ uint64_t valid4 : 1;
+ uint64_t spare4 : 1;
+ uint64_t thermal_trip4 : 2;
+ uint64_t dts4 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v1_t;
+
+
+
+typedef union sensors_v2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dts8 : 12;
+ uint64_t thermal_trip8 : 2;
+ uint64_t spare8 : 1;
+ uint64_t valid8 : 1;
+ uint64_t dts9 : 12;
+ uint64_t thermal_trip9 : 2;
+ uint64_t spare9 : 1;
+ uint64_t valid9 : 1;
+ uint64_t dts10 : 12;
+ uint64_t thermal_trip10 : 2;
+ uint64_t spare10 : 1;
+ uint64_t valid10 : 1;
+ uint64_t dts12 : 12;
+ uint64_t thermal_trip12 : 2;
+ uint64_t spare12 : 1;
+ uint64_t valid12 : 1;
+#else
+ uint64_t valid12 : 1;
+ uint64_t spare12 : 1;
+ uint64_t thermal_trip12 : 2;
+ uint64_t dts12 : 12;
+ uint64_t valid10 : 1;
+ uint64_t spare10 : 1;
+ uint64_t thermal_trip10 : 2;
+ uint64_t dts10 : 12;
+ uint64_t valid9 : 1;
+ uint64_t spare9 : 1;
+ uint64_t thermal_trip9 : 2;
+ uint64_t dts9 : 12;
+ uint64_t valid8 : 1;
+ uint64_t spare8 : 1;
+ uint64_t thermal_trip8 : 2;
+ uint64_t dts8 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v2_t;
+
+
+
+typedef union sensors_v3 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t unknown : 64;
+#else
+ uint64_t unknown : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v3_t;
+
+
+
+typedef union sensors_v5 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t raw_cpm0 : 12;
+ uint64_t spare0 : 4;
+ uint64_t raw_cpm1 : 12;
+ uint64_t spare1 : 4;
+ uint64_t raw_cpm2 : 12;
+ uint64_t spare2 : 4;
+ uint64_t raw_cpm3 : 12;
+ uint64_t spare3 : 4;
+#else
+ uint64_t spare3 : 4;
+ uint64_t raw_cpm3 : 12;
+ uint64_t spare2 : 4;
+ uint64_t raw_cpm2 : 12;
+ uint64_t spare1 : 4;
+ uint64_t raw_cpm1 : 12;
+ uint64_t spare0 : 4;
+ uint64_t raw_cpm0 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v5_t;
+
+
+
+typedef union sensors_v6 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t raw_cpm4 : 12;
+ uint64_t spare4 : 4;
+ uint64_t raw_cpm5 : 12;
+ uint64_t spare5 : 4;
+ uint64_t raw_cpm6 : 12;
+ uint64_t spare6 : 4;
+ uint64_t raw_cpm7 : 12;
+ uint64_t spare7 : 4;
+#else
+ uint64_t spare7 : 4;
+ uint64_t raw_cpm7 : 12;
+ uint64_t spare6 : 4;
+ uint64_t raw_cpm6 : 12;
+ uint64_t spare5 : 4;
+ uint64_t raw_cpm5 : 12;
+ uint64_t spare4 : 4;
+ uint64_t raw_cpm4 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v6_t;
+
+
+
+typedef union sensors_v7 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t raw_cpm8 : 12;
+ uint64_t spare8 : 4;
+ uint64_t raw_cpm9 : 12;
+ uint64_t spare9 : 4;
+ uint64_t raw_cpm10 : 12;
+ uint64_t spare10 : 4;
+ uint64_t raw_cpm11 : 12;
+ uint64_t spare11 : 4;
+#else
+ uint64_t spare11 : 4;
+ uint64_t raw_cpm11 : 12;
+ uint64_t spare10 : 4;
+ uint64_t raw_cpm10 : 12;
+ uint64_t spare9 : 4;
+ uint64_t raw_cpm9 : 12;
+ uint64_t spare8 : 4;
+ uint64_t raw_cpm8 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v7_t;
+
+
+
+typedef union sensors_v8 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dts0 : 12;
+ uint64_t thermal_trip0 : 2;
+ uint64_t spare0 : 1;
+ uint64_t valid0 : 1;
+ uint64_t dts1 : 12;
+ uint64_t thermal_trip1 : 2;
+ uint64_t spare1 : 1;
+ uint64_t valid1 : 1;
+ uint64_t dts2 : 12;
+ uint64_t thermal_trip2 : 2;
+ uint64_t spare2 : 1;
+ uint64_t valid2 : 1;
+ uint64_t encoded_cpm0 : 4;
+ uint64_t encoded_cpm1 : 4;
+ uint64_t encoded_cpm2 : 4;
+ uint64_t encoded_cpm3 : 4;
+#else
+ uint64_t encoded_cpm3 : 4;
+ uint64_t encoded_cpm2 : 4;
+ uint64_t encoded_cpm1 : 4;
+ uint64_t encoded_cpm0 : 4;
+ uint64_t valid2 : 1;
+ uint64_t spare2 : 1;
+ uint64_t thermal_trip2 : 2;
+ uint64_t dts2 : 12;
+ uint64_t valid1 : 1;
+ uint64_t spare1 : 1;
+ uint64_t thermal_trip1 : 2;
+ uint64_t dts1 : 12;
+ uint64_t valid0 : 1;
+ uint64_t spare0 : 1;
+ uint64_t thermal_trip0 : 2;
+ uint64_t dts0 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v8_t;
+
+
+
+typedef union sensors_v9 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dts4 : 12;
+ uint64_t thermal_trip4 : 2;
+ uint64_t spare4 : 1;
+ uint64_t valid4 : 1;
+ uint64_t dts5 : 12;
+ uint64_t thermal_trip5 : 2;
+ uint64_t spare5 : 1;
+ uint64_t valid5 : 1;
+ uint64_t dts6 : 12;
+ uint64_t thermal_trip6 : 2;
+ uint64_t spare6 : 1;
+ uint64_t valid6 : 1;
+ uint64_t encoded_cpm4 : 4;
+ uint64_t encoded_cpm5 : 4;
+ uint64_t encoded_cpm6 : 4;
+ uint64_t encoded_cpm7 : 4;
+#else
+ uint64_t encoded_cpm7 : 4;
+ uint64_t encoded_cpm6 : 4;
+ uint64_t encoded_cpm5 : 4;
+ uint64_t encoded_cpm4 : 4;
+ uint64_t valid6 : 1;
+ uint64_t spare6 : 1;
+ uint64_t thermal_trip6 : 2;
+ uint64_t dts6 : 12;
+ uint64_t valid5 : 1;
+ uint64_t spare5 : 1;
+ uint64_t thermal_trip5 : 2;
+ uint64_t dts5 : 12;
+ uint64_t valid4 : 1;
+ uint64_t spare4 : 1;
+ uint64_t thermal_trip4 : 2;
+ uint64_t dts4 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v9_t;
+
+
+
+typedef union sensors_v10 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dts8 : 12;
+ uint64_t thermal_trip8 : 2;
+ uint64_t spare8 : 1;
+ uint64_t valid8 : 1;
+ uint64_t dts9 : 12;
+ uint64_t thermal_trip9 : 2;
+ uint64_t spare9 : 1;
+ uint64_t valid9 : 1;
+ uint64_t dts10 : 12;
+ uint64_t thermal_trip10 : 2;
+ uint64_t spare10 : 1;
+ uint64_t valid10 : 1;
+ uint64_t encoded_cpm8 : 4;
+ uint64_t encoded_cpm9 : 4;
+ uint64_t encoded_cpm10 : 4;
+ uint64_t encoded_cpm11 : 4;
+#else
+ uint64_t encoded_cpm11 : 4;
+ uint64_t encoded_cpm10 : 4;
+ uint64_t encoded_cpm9 : 4;
+ uint64_t encoded_cpm8 : 4;
+ uint64_t valid10 : 1;
+ uint64_t spare10 : 1;
+ uint64_t thermal_trip10 : 2;
+ uint64_t dts10 : 12;
+ uint64_t valid9 : 1;
+ uint64_t spare9 : 1;
+ uint64_t thermal_trip9 : 2;
+ uint64_t dts9 : 12;
+ uint64_t valid8 : 1;
+ uint64_t spare8 : 1;
+ uint64_t thermal_trip8 : 2;
+ uint64_t dts8 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v10_t;
+
+
+
+typedef union sensors_v11 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dvs0 : 12;
+ uint64_t spare00 : 1;
+ uint64_t trip0 : 1;
+ uint64_t spare01 : 1;
+ uint64_t valid0 : 1;
+ uint64_t dvs1 : 12;
+ uint64_t spare10 : 1;
+ uint64_t trip1 : 1;
+ uint64_t spare11 : 1;
+ uint64_t valid1 : 1;
+ uint64_t dvs2 : 12;
+ uint64_t spare20 : 1;
+ uint64_t trip2 : 1;
+ uint64_t spare21 : 1;
+ uint64_t valid2 : 1;
+ uint64_t dvs3 : 12;
+ uint64_t spare30 : 1;
+ uint64_t trip3 : 1;
+ uint64_t spare31 : 1;
+ uint64_t valid3 : 1;
+#else
+ uint64_t valid3 : 1;
+ uint64_t spare31 : 1;
+ uint64_t trip3 : 1;
+ uint64_t spare30 : 1;
+ uint64_t dvs3 : 12;
+ uint64_t valid2 : 1;
+ uint64_t spare21 : 1;
+ uint64_t trip2 : 1;
+ uint64_t spare20 : 1;
+ uint64_t dvs2 : 12;
+ uint64_t valid1 : 1;
+ uint64_t spare11 : 1;
+ uint64_t trip1 : 1;
+ uint64_t spare10 : 1;
+ uint64_t dvs1 : 12;
+ uint64_t valid0 : 1;
+ uint64_t spare01 : 1;
+ uint64_t trip0 : 1;
+ uint64_t spare00 : 1;
+ uint64_t dvs0 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v11_t;
+
+
+
+typedef union sensors_v12 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dvs4 : 12;
+ uint64_t spare40 : 1;
+ uint64_t trip4 : 1;
+ uint64_t spare41 : 1;
+ uint64_t valid4 : 1;
+ uint64_t dvs5 : 12;
+ uint64_t spare50 : 1;
+ uint64_t trip5 : 1;
+ uint64_t spare51 : 1;
+ uint64_t valid5 : 1;
+ uint64_t dvs6 : 12;
+ uint64_t spare60 : 1;
+ uint64_t trip6 : 1;
+ uint64_t spare61 : 1;
+ uint64_t valid6 : 1;
+ uint64_t dvs7 : 12;
+ uint64_t spare70 : 1;
+ uint64_t trip7 : 1;
+ uint64_t spare71 : 1;
+ uint64_t valid7 : 1;
+#else
+ uint64_t valid7 : 1;
+ uint64_t spare71 : 1;
+ uint64_t trip7 : 1;
+ uint64_t spare70 : 1;
+ uint64_t dvs7 : 12;
+ uint64_t valid6 : 1;
+ uint64_t spare61 : 1;
+ uint64_t trip6 : 1;
+ uint64_t spare60 : 1;
+ uint64_t dvs6 : 12;
+ uint64_t valid5 : 1;
+ uint64_t spare51 : 1;
+ uint64_t trip5 : 1;
+ uint64_t spare50 : 1;
+ uint64_t dvs5 : 12;
+ uint64_t valid4 : 1;
+ uint64_t spare41 : 1;
+ uint64_t trip4 : 1;
+ uint64_t spare40 : 1;
+ uint64_t dvs4 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v12_t;
+
+
+
+typedef union sensors_v13 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t dvs8 : 12;
+ uint64_t spare80 : 1;
+ uint64_t trip8 : 1;
+ uint64_t spare81 : 1;
+ uint64_t valid8 : 1;
+ uint64_t dvs9 : 12;
+ uint64_t spare90 : 1;
+ uint64_t trip9 : 1;
+ uint64_t spare91 : 1;
+ uint64_t valid9 : 1;
+ uint64_t dvs10 : 12;
+ uint64_t spare100 : 1;
+ uint64_t trip10 : 1;
+ uint64_t spare101 : 1;
+ uint64_t valid10 : 1;
+ uint64_t dvs11 : 12;
+ uint64_t spare110 : 1;
+ uint64_t trip11 : 1;
+ uint64_t spare111 : 1;
+ uint64_t valid11 : 1;
+#else
+ uint64_t valid11 : 1;
+ uint64_t spare111 : 1;
+ uint64_t trip11 : 1;
+ uint64_t spare110 : 1;
+ uint64_t dvs11 : 12;
+ uint64_t valid10 : 1;
+ uint64_t spare101 : 1;
+ uint64_t trip10 : 1;
+ uint64_t spare100 : 1;
+ uint64_t dvs10 : 12;
+ uint64_t valid9 : 1;
+ uint64_t spare91 : 1;
+ uint64_t trip9 : 1;
+ uint64_t spare90 : 1;
+ uint64_t dvs9 : 12;
+ uint64_t valid8 : 1;
+ uint64_t spare81 : 1;
+ uint64_t trip8 : 1;
+ uint64_t spare80 : 1;
+ uint64_t dvs8 : 12;
+#endif // _BIG_ENDIAN
+ } fields;
+} sensors_v13_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __SENSORS_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/sensors_register_addresses.h b/src/ssx/pgp/registers/sensors_register_addresses.h
new file mode 100755
index 0000000..c815ace
--- /dev/null
+++ b/src/ssx/pgp/registers/sensors_register_addresses.h
@@ -0,0 +1,47 @@
+#ifndef __SENSORS_REGISTER_ADDRESSES_H__
+#define __SENSORS_REGISTER_ADDRESSES_H__
+
+// $Id: sensors_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sensors_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file sensors_register_addresses.h
+/// \brief Symbolic addresses for the SENSORS unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define SENSORS_CORE_PCB_BASE 0x10050000
+#define SENSORS_V0_OFFSET 0x00000000
+#define SENSORS_CORE_V0 0x10050000
+#define SENSORS_V1_OFFSET 0x00000001
+#define SENSORS_CORE_V1 0x10050001
+#define SENSORS_V2_OFFSET 0x00000002
+#define SENSORS_CORE_V2 0x10050002
+#define SENSORS_V3_OFFSET 0x00000003
+#define SENSORS_CORE_V3 0x10050003
+#define SENSORS_V5_OFFSET 0x00000005
+#define SENSORS_CORE_V5 0x10050005
+#define SENSORS_V6_OFFSET 0x00000006
+#define SENSORS_CORE_V6 0x10050006
+#define SENSORS_V7_OFFSET 0x00000007
+#define SENSORS_CORE_V7 0x10050007
+#define SENSORS_V8_OFFSET 0x00000008
+#define SENSORS_CORE_V8 0x10050008
+#define SENSORS_V9_OFFSET 0x00000009
+#define SENSORS_CORE_V9 0x10050009
+#define SENSORS_V10_OFFSET 0x0000000a
+#define SENSORS_CORE_V10 0x1005000a
+#define SENSORS_V11_OFFSET 0x0000000b
+#define SENSORS_CORE_V11 0x1005000b
+#define SENSORS_V12_OFFSET 0x0000000c
+#define SENSORS_CORE_V12 0x1005000c
+#define SENSORS_V13_OFFSET 0x0000000d
+#define SENSORS_CORE_V13 0x1005000d
+
+#endif // __SENSORS_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/sramctl_firmware_registers.h b/src/ssx/pgp/registers/sramctl_firmware_registers.h
new file mode 100755
index 0000000..c8a7c26
--- /dev/null
+++ b/src/ssx/pgp/registers/sramctl_firmware_registers.h
@@ -0,0 +1,211 @@
+#ifndef __SRAMCTL_FIRMWARE_REGISTERS_H__
+#define __SRAMCTL_FIRMWARE_REGISTERS_H__
+
+// $Id: sramctl_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:24 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sramctl_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file sramctl_firmware_registers.h
+/// \brief C register structs for the SRAMCTL unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union sramctl_srbar {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t sram_region_qualifier : 2;
+ uint32_t reserved : 3;
+ uint32_t sram_bar_region : 8;
+ uint32_t _reserved0 : 19;
+#else
+ uint32_t _reserved0 : 19;
+ uint32_t sram_bar_region : 8;
+ uint32_t reserved : 3;
+ uint32_t sram_region_qualifier : 2;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srbar_t;
+
+
+
+typedef union sramctl_srmr {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t sram_enable_remap : 1;
+ uint32_t sram_arb_en_send_all_writes : 1;
+ uint32_t sram_disable_lfsr : 1;
+ uint32_t sram_lfsr_fairness_mask : 5;
+ uint32_t sram_error_inject_enable : 1;
+ uint32_t sram_ctl_trace_en : 1;
+ uint32_t sram_ctl_trace_sel : 1;
+ uint32_t reserved : 5;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t reserved : 5;
+ uint32_t sram_ctl_trace_sel : 1;
+ uint32_t sram_ctl_trace_en : 1;
+ uint32_t sram_error_inject_enable : 1;
+ uint32_t sram_lfsr_fairness_mask : 5;
+ uint32_t sram_disable_lfsr : 1;
+ uint32_t sram_arb_en_send_all_writes : 1;
+ uint32_t sram_enable_remap : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srmr_t;
+
+
+
+typedef union sramctl_srmap {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t reserved : 1;
+ uint32_t sram_remap_source : 12;
+ uint32_t _reserved0 : 1;
+ uint32_t reserved1 : 3;
+ uint32_t sram_remap_dest : 13;
+ uint32_t reserved2 : 2;
+#else
+ uint32_t reserved2 : 2;
+ uint32_t sram_remap_dest : 13;
+ uint32_t reserved1 : 3;
+ uint32_t _reserved0 : 1;
+ uint32_t sram_remap_source : 12;
+ uint32_t reserved : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srmap_t;
+
+
+
+typedef union sramctl_srear {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t sram_error_address : 16;
+ uint32_t _reserved0 : 16;
+#else
+ uint32_t _reserved0 : 16;
+ uint32_t sram_error_address : 16;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srear_t;
+
+
+
+typedef union sramctl_srbv0 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t boot_vector_word0 : 32;
+#else
+ uint32_t boot_vector_word0 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srbv0_t;
+
+
+
+typedef union sramctl_srbv1 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t boot_vector_word1 : 32;
+#else
+ uint32_t boot_vector_word1 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srbv1_t;
+
+
+
+typedef union sramctl_srbv2 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t boot_vector_word2 : 32;
+#else
+ uint32_t boot_vector_word2 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srbv2_t;
+
+
+
+typedef union sramctl_srbv3 {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t boot_vector_word3 : 32;
+#else
+ uint32_t boot_vector_word3 : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srbv3_t;
+
+
+
+typedef union sramctl_srchsw {
+
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t chksw_wrfsm_dly_dis : 1;
+ uint32_t chksw_allow1_rd : 1;
+ uint32_t chksw_allow1_wr : 1;
+ uint32_t chksw_allow1_rdwr : 1;
+ uint32_t chksw_oci_parchk_dis : 1;
+ uint32_t chksw_tank_rddata_parchk_dis : 1;
+ uint32_t chksw_tank_sr_rderr_dis : 1;
+ uint32_t chksw_val_be_addr_chk_dis : 1;
+ uint32_t chksw_so_spare : 2;
+ uint32_t _reserved0 : 22;
+#else
+ uint32_t _reserved0 : 22;
+ uint32_t chksw_so_spare : 2;
+ uint32_t chksw_val_be_addr_chk_dis : 1;
+ uint32_t chksw_tank_sr_rderr_dis : 1;
+ uint32_t chksw_tank_rddata_parchk_dis : 1;
+ uint32_t chksw_oci_parchk_dis : 1;
+ uint32_t chksw_allow1_rdwr : 1;
+ uint32_t chksw_allow1_wr : 1;
+ uint32_t chksw_allow1_rd : 1;
+ uint32_t chksw_wrfsm_dly_dis : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} sramctl_srchsw_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __SRAMCTL_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/sramctl_register_addresses.h b/src/ssx/pgp/registers/sramctl_register_addresses.h
new file mode 100755
index 0000000..baec5d5
--- /dev/null
+++ b/src/ssx/pgp/registers/sramctl_register_addresses.h
@@ -0,0 +1,30 @@
+#ifndef __SRAMCTL_REGISTER_ADDRESSES_H__
+#define __SRAMCTL_REGISTER_ADDRESSES_H__
+
+// $Id: sramctl_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sramctl_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file sramctl_register_addresses.h
+/// \brief Symbolic addresses for the SRAMCTL unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define SRAMCTL_OCI_BASE 0x40030000
+#define SRAMCTL_SRBAR 0x40030000
+#define SRAMCTL_SRMR 0x40030008
+#define SRAMCTL_SRMAP 0x40030010
+#define SRAMCTL_SREAR 0x40030018
+#define SRAMCTL_SRBV0 0x40030020
+#define SRAMCTL_SRBV1 0x40030028
+#define SRAMCTL_SRBV2 0x40030030
+#define SRAMCTL_SRBV3 0x40030038
+#define SRAMCTL_SRCHSW 0x40030040
+
+#endif // __SRAMCTL_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/tod_firmware_registers.h b/src/ssx/pgp/registers/tod_firmware_registers.h
new file mode 100755
index 0000000..7a700d7
--- /dev/null
+++ b/src/ssx/pgp/registers/tod_firmware_registers.h
@@ -0,0 +1,58 @@
+#ifndef __TOD_FIRMWARE_REGISTERS_H__
+#define __TOD_FIRMWARE_REGISTERS_H__
+
+// $Id: tod_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/tod_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file tod_firmware_registers.h
+/// \brief C register structs for the TOD unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union tod_value_reg {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t tod_incrementer : 60;
+ uint64_t tod_wof : 4;
+#else
+ uint64_t tod_wof : 4;
+ uint64_t tod_incrementer : 60;
+#endif // _BIG_ENDIAN
+ } fields;
+} tod_value_reg_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __TOD_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/tod_register_addresses.h b/src/ssx/pgp/registers/tod_register_addresses.h
new file mode 100755
index 0000000..ac7d136
--- /dev/null
+++ b/src/ssx/pgp/registers/tod_register_addresses.h
@@ -0,0 +1,22 @@
+#ifndef __TOD_REGISTER_ADDRESSES_H__
+#define __TOD_REGISTER_ADDRESSES_H__
+
+// $Id: tod_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/tod_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file tod_register_addresses.h
+/// \brief Symbolic addresses for the TOD unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define TOD_PIB_BASE 0x00040000
+#define TOD_VALUE_REG 0x00040020
+
+#endif // __TOD_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/registers/tpc_firmware_registers.h b/src/ssx/pgp/registers/tpc_firmware_registers.h
new file mode 100644
index 0000000..62f1c42
--- /dev/null
+++ b/src/ssx/pgp/registers/tpc_firmware_registers.h
@@ -0,0 +1,213 @@
+#ifndef __TPC_FIRMWARE_REGISTERS_H__
+#define __TPC_FIRMWARE_REGISTERS_H__
+
+// $Id: tpc_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/tpc_firmware_registers.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file tpc_firmware_registers.h
+/// \brief C register structs for the TPC unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+#ifndef SIXTYFOUR_BIT_CONSTANT
+#ifdef __ASSEMBLER__
+#define SIXTYFOUR_BIT_CONSTANT(x) x
+#else
+#define SIXTYFOUR_BIT_CONSTANT(x) x##ull
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+
+
+
+typedef union tpc_perv_gp3 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t tp_chiplet_chiplet_en_dc : 1;
+ uint64_t put_in_later0 : 25;
+ uint64_t tp_chiplet_fence_pcb_dc : 1;
+ uint64_t put_in_later1 : 37;
+#else
+ uint64_t put_in_later1 : 37;
+ uint64_t tp_chiplet_fence_pcb_dc : 1;
+ uint64_t put_in_later0 : 25;
+ uint64_t tp_chiplet_chiplet_en_dc : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+} tpc_perv_gp3_t;
+
+
+
+typedef union tpc_gp0 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t put_in_later0 : 40;
+ uint64_t tc_node_id_dc : 3;
+ uint64_t tc_chip_id_dc : 3;
+ uint64_t put_in_later1 : 18;
+#else
+ uint64_t put_in_later1 : 18;
+ uint64_t tc_chip_id_dc : 3;
+ uint64_t tc_node_id_dc : 3;
+ uint64_t put_in_later0 : 40;
+#endif // _BIG_ENDIAN
+ } fields;
+} tpc_gp0_t;
+
+
+
+typedef union tpc_gp0_and {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t put_in_later0 : 40;
+ uint64_t tc_node_id_dc : 3;
+ uint64_t tc_chip_id_dc : 3;
+ uint64_t put_in_later1 : 18;
+#else
+ uint64_t put_in_later1 : 18;
+ uint64_t tc_chip_id_dc : 3;
+ uint64_t tc_node_id_dc : 3;
+ uint64_t put_in_later0 : 40;
+#endif // _BIG_ENDIAN
+ } fields;
+} tpc_gp0_and_t;
+
+
+
+typedef union tpc_gp0_or {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t put_in_later0 : 40;
+ uint64_t tc_node_id_dc : 3;
+ uint64_t tc_chip_id_dc : 3;
+ uint64_t put_in_later1 : 18;
+#else
+ uint64_t put_in_later1 : 18;
+ uint64_t tc_chip_id_dc : 3;
+ uint64_t tc_node_id_dc : 3;
+ uint64_t put_in_later0 : 40;
+#endif // _BIG_ENDIAN
+ } fields;
+} tpc_gp0_or_t;
+
+
+
+typedef union tpc_hpr2 {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t hang_pulse_reg : 6;
+ uint64_t suppress_hang : 1;
+ uint64_t _reserved0 : 57;
+#else
+ uint64_t _reserved0 : 57;
+ uint64_t suppress_hang : 1;
+ uint64_t hang_pulse_reg : 6;
+#endif // _BIG_ENDIAN
+ } fields;
+} tpc_hpr2_t;
+
+
+
+typedef union tpc_device_id {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t cfam_id : 32;
+ uint64_t fuse_nx_allow_crypto : 1;
+ uint64_t fuse_vmx_crypto_dis : 1;
+ uint64_t fuse_fp_throttle_en : 1;
+ uint64_t reserved32 : 1;
+ uint64_t socket_id : 3;
+ uint64_t chippos_id : 1;
+ uint64_t _reserved0 : 24;
+#else
+ uint64_t _reserved0 : 24;
+ uint64_t chippos_id : 1;
+ uint64_t socket_id : 3;
+ uint64_t reserved32 : 1;
+ uint64_t fuse_fp_throttle_en : 1;
+ uint64_t fuse_vmx_crypto_dis : 1;
+ uint64_t fuse_nx_allow_crypto : 1;
+ uint64_t cfam_id : 32;
+#endif // _BIG_ENDIAN
+ } fields;
+} tpc_device_id_t;
+
+
+#endif // __ASSEMBLER__
+#endif // __TPC_FIRMWARE_REGISTERS_H__
+
diff --git a/src/ssx/pgp/registers/tpc_register_addresses.h b/src/ssx/pgp/registers/tpc_register_addresses.h
new file mode 100644
index 0000000..50c7e97
--- /dev/null
+++ b/src/ssx/pgp/registers/tpc_register_addresses.h
@@ -0,0 +1,30 @@
+#ifndef __TPC_REGISTER_ADDRESSES_H__
+#define __TPC_REGISTER_ADDRESSES_H__
+
+// $Id: tpc_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:24 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/tpc_register_addresses.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file tpc_register_addresses.h
+/// \brief Symbolic addresses for the TPC unit
+
+// *** WARNING *** - This file is generated automatically, do not edit.
+
+
+#define TPC_PERVPIB_BASE 0x00050000
+#define TPC_PERV_GP3 0x0005001b
+#define TPC_PIB_BASE 0x01000000
+#define TPC_GP0 0x01000000
+#define TPC_GP0_AND 0x01000004
+#define TPC_GP0_OR 0x01000005
+#define TPC_MISCPIB_BASE 0x010f0000
+#define TPC_HPR2 0x010f0022
+#define TPC_TPCHIP_BASE 0x000f0000
+#define TPC_DEVICE_ID 0x000f000f
+
+#endif // __TPC_REGISTER_ADDRESSES_H__
+
diff --git a/src/ssx/pgp/ssx.mk b/src/ssx/pgp/ssx.mk
new file mode 100755
index 0000000..348718d
--- /dev/null
+++ b/src/ssx/pgp/ssx.mk
@@ -0,0 +1,424 @@
+# $Id: ssx.mk,v 1.2 2014/06/26 12:55:39 cmolsen Exp $
+# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/ssx.mk,v $
+# Make header for PgP SSX builds
+#
+# The application may define the following variables to control the
+# build process:
+#
+# APP_INCLUDES : Aplication-specific header search paths
+#
+# DEFS : A string of -D<symbol>[=<value>] to control compilation
+#
+# SSX : Default ..; The path to the SSX source code.
+# The default is set for building the SSX
+# subdirectories.
+#
+# SSX_THREAD_SUPPORT : (0/1, default 1); Compile SSX thread and
+# semaphore suppprt
+#
+# SSX_TIMER_SUPPORT : (0/1, default 1); Compile SSX timer suppprt
+#
+# PPC405_MMU_SUPPORT : (0/1, default 1); Compile for PPC405 simple MMU protection
+#
+# SIMICS_ENVIRONMENT : (0/1, current default 0); Compile for Simics
+#
+# SIMICS_MAGIC_PANIC : (0/1, current default 0); Use Simics Magic
+# breakpoint for SSX_PANIC() instead of PowerPC trap.
+# Note that Simics does not model trap correctly in
+# external debug mode.
+#
+# GCC-O-LEVEL : The optimization level passed to GCC (default -Os). May
+# also be defined empty (GCC-O-LEVEL=) to disable
+# optimization. This variable can also be used to pass
+# any other non-default setting to GCC, e.g.
+# make GCC-O-LEVEL="-Os -fno-branch-count-reg"
+#
+# GCC-TOOL-PREFIX : The full path (including executable file prefixes) to
+# the GCC cross-development tools to use. The default is
+# "ppcnf-mcp5-"
+#
+# CTEPATH : This variable defaults to the afs/awd CTE tool
+# installation - The PORE binutils are stored there. If
+# you are not in Austin be sure to define CTEPATH in
+# your .profile.
+
+# >> gitprep
+# Use fips tracepp
+TRACEPP = /afs/austin/projects/esw/fips820/Builds/built/tools/x86/tracepp
+export OCCROOT = $(dir $(lastword $(MAKEFILE_LIST)))../../
+
+ifndef SIMICS_ENVIRONMENT
+SIMICS_ENVIRONMENT=0
+endif
+# << gitprep
+
+ifndef GCC-TOOL-PREFIX
+# >> gitprep
+# The new compiler for GNU builds
+GCC-TOOL-PREFIX = powerpc64-unknown-linux-gnu-
+endif
+
+ifndef HOST-PREFIX
+HOST-PREFIX = x86_64-pc-linux-gnu-
+endif
+
+JAIL = $(HOST-PREFIX)jail
+CC_ASM = $(GCC-TOOL-PREFIX)gcc # Assembly still doesn't use tracepp
+CC = $(TRACEPP) $(GCC-TOOL-PREFIX)gcc
+AS = $(JAIL) /usr/bin/as
+AR = $(JAIL) /usr/bin/ar
+LD = $(GCC-TOOL-PREFIX)ld
+OBJDUMP = $(GCC-TOOL-PREFIX)objdump
+OBJCOPY = $(JAIL) /usr/bin/objcopy
+CPP = $(JAIL) /usr/bin/cpp
+# << gitprep
+
+
+ifndef CTEPATH
+$(warning The CTEPATH variable is not defined; Defaulting to /afs/awd)
+CTEPATH = /afs/awd/projects/cte
+endif
+
+PORE-AS = $(CTEPATH)/tools/porebinutils/prod/bin/pore-elf64-as
+PORE-AS = $(CTEPATH)/tools/porebinutils/prod/bin/pore-elf64-as
+PORE-LD = $(CTEPATH)/tools/porebinutils/prod/bin/pore-elf64-ld
+PORE-OBJCOPY = $(CTEPATH)/tools/porebinutils/prod/bin/pore-elf64-objcopy
+
+ifeq "$(SSX)" ""
+SSX = ..
+endif
+
+ifeq "$(LIB)" ""
+LIB = ../../lib
+endif
+
+ifeq "$(SSX_TIMER_SUPPORT)" ""
+SSX_TIMER_SUPPORT = 1
+endif
+
+ifeq "$(SSX_THREAD_SUPPORT)" ""
+SSX_THREAD_SUPPORT = 1
+endif
+
+ifeq "$(PPC405_MMU_SUPPORT)" ""
+PPC405_MMU_SUPPORT = 1
+endif
+
+ifeq "$(PGP_ASYNC_SUPPORT)" ""
+PGP_ASYNC_SUPPORT = 1
+endif
+
+ifndef GCC-O-LEVEL
+GCC-O-LEVEL = -Os
+endif
+
+# >> gitprep
+GCC-DEFS += -DSIMICS_ENVIRONMENT=$(SIMICS_ENVIRONMENT)
+# << gitprep
+GCC-DEFS += -DSSX_TIMER_SUPPORT=$(SSX_TIMER_SUPPORT)
+GCC-DEFS += -DSSX_THREAD_SUPPORT=$(SSX_THREAD_SUPPORT)
+GCC-DEFS += -DPPC405_MMU_SUPPORT=$(PPC405_MMU_SUPPORT)
+DEFS += $(GCC-DEFS) -DPGAS_PPC=1 -DCONFIGURE_PTS_SLW=0
+PORE-DEFS += $(GCC-DEFS)
+
+############################################################################
+
+INCLUDES += $(APP_INCLUDES) \
+ -I$(SSX)/ssx -I$(SSX)/ppc32 -I$(SSX)/ppc405 \
+ -I$(SSX)/pgp -I$(SSX)/pgp/registers \
+ -I$(LIB)
+
+PIPE-CFLAGS = -pipe -Wa,-m405
+
+# >> gitprep
+# Update compile flags for GNU build, allow warnings
+GCC-CFLAGS += -g -Wall -fsigned-char -msoft-float \
+ -m32 -mcpu=405 -mmultiple -mstring \
+ -meabi -msdata=eabi -ffreestanding -fno-common \
+ -fno-inline-functions-called-once
+# << gitprep
+
+CFLAGS = -c $(GCC-CFLAGS) $(PIPE-CFLAGS) $(GCC-O-LEVEL) $(INCLUDES)
+PORE-CFLAGS = -E $(GCC-CFLAGS) $(OPT) $(INCLUDES)
+# >> gitprep
+# Add compile flags needed for the GNU build
+CPPFLAGS += -m32 -mcpu=405 -msdata=eabi -meabi -mstring -mmultiple
+# << gitprep
+
+############################################################################
+
+# Build object code
+#
+# %.o: %.c - Compile C code
+#
+# %.o: %.S - Compile PowerPC assembler (including PGAS-PPC assembly)
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(DEFS) -o $@ $<
+
+%.o: %.S
+ $(CC_ASM) $(CFLAGS) $(DEFS) -o $@ $<
+
+#Temporary always use PGAS PPC Assembler for compiling .pS files.
+#relocatable symbols are being added to the GPE (.pS) files and
+#so need new way to compile using GNU assembler.
+PGAS_PPC=1
+
+# use "make PGAS_PPC=1" to compile .pS file using PGAS PPC assembler.
+# If PGAS_PPC=1 is not part of the make command, then GNU assembler is
+# used for compiling .pS files.
+ifdef PGAS_PPC
+
+ifneq ($(MAKE_PORE_HOOKS),)
+
+# This Makefile included here defines how to convert *.pS into both the object
+# file and the hooks object file.
+
+include $(MAKE_PORE_HOOKS)
+
+else
+
+%.o: %.pS
+# >> gitprep
+# Force use of PORE assembler for GNU builds
+# $(CC_ASM) -x assembler-with-cpp $(CFLAGS) $(DEFS) -o $@ $<
+ $(CC_ASM) -x assembler-with-cpp $(PORE-CFLAGS) $(PORE-DEFS) $< | $(PORE-AS) - -o $@
+# << gitprep
+endif
+
+%.lst: %.pS
+ $(CC_ASM) -x assembler-with-cpp $(CFLAGS) $(DEFS) \
+ -Wa,-al -Wa,--listing-cont-lines=20 $< > $@
+
+else
+%.o: %.pS
+ $(CPP_ASM) -x assembler-with-cpp $(PORE-CFLAGS) $(PORE-DEFS) $< | $(PORE-AS) - -o $@
+endif
+
+# Other useful targets
+#
+# %.S: %.c - See what the assembler produces from the C code, however you can
+# also just look at the final disassembly.
+#
+# %.lst: %.S - Get an assembler listing
+#
+# %.cpp: %.S - Preprocess PowerPC assembler source to stdout
+#
+# %.cpp: %.pS - Preprocess PORE assembler source to stdout
+#
+# %.cpp: %.c - Preprocess C source to stdout
+
+%.S: %.c
+ $(CC) $(CFLAGS) $(DEFS) -S -o $@ $<
+
+%.lst: %.S
+ $(CC_ASM) $(CFLAGS) $(DEFS) -Wa,-al -Wa,--listing-cont-lines=20 $< > $@
+
+%.cpp: %.S
+ $(CC_ASM) $(CFLAGS) $(DEFS) -E $<
+
+%.cpp: %.pS
+ $(CC) -x assembler-with-cpp $(CFLAGS) $(DEFS) -E $<
+
+%.cpp: %.c
+ $(CC) $(CFLAGS) $(DEFS) -E $<
+
+# From the GNU 'Make' manual - these scripts uses the preprocessor to
+# create dependency files (*.d), then mungs them slightly to make them
+# work as Make targets. The *.d files are include-ed in the
+# subdirectory Makefiles.
+
+%.d: %.c
+ @set -e; rm -f $@; \
+ $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+%.d: %.S
+ @set -e; rm -f $@; \
+ $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+%.d: %.pS
+ @set -e; rm -f $@; \
+ $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) -x assembler-with-cpp $(DEFS) $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+############################################################################
+#
+# GCC Compiler flags used in these builds. Comments, or reasons for
+# non-obvious choices appear in [] after the GCC documentation.
+#
+#`-Os'
+# Optimize for size. `-Os' enables all `-O2' optimizations that do
+# not typically increase code size. It also performs further
+# optimizations designed to reduce code size.
+#
+# `-Os' disables the following optimization flags:
+# -falign-functions -falign-jumps -falign-loops
+# -falign-labels -freorder-blocks -freorder-blocks-and-partition
+# -fprefetch-loop-arrays -ftree-vect-loop-version
+#
+# If you use multiple `-O' options, with or without level numbers,
+# the last such option is the one that is effective.
+#
+#`-g'
+# Produce debugging information in the operating system's native
+# format (stabs, COFF, XCOFF, or DWARF 2). GDB can work with this
+# debugging information.
+#
+# On most systems that use stabs format, `-g' enables use of extra
+# debugging information that only GDB can use; this extra information
+# makes debugging work better in GDB but will probably make other
+# debuggers crash or refuse to read the program. If you want to
+# control for certain whether to generate the extra information, use
+# `-gstabs+', `-gstabs', `-gxcoff+', `-gxcoff', or `-gvms' (see
+# below).
+#
+# GCC allows you to use `-g' with `-O'. The shortcuts taken by
+# optimized code may occasionally produce surprising results: some
+# variables you declared may not exist at all; flow of control may
+# briefly move where you did not expect it; some statements may not
+# be executed because they compute constant results or their values
+# were already at hand; some statements may execute in different
+# places because they were moved out of loops.
+#
+# Nevertheless it proves possible to debug optimized output. This
+# makes it reasonable to use the optimizer for programs that might
+# have bugs.
+#
+#`-Wall'
+# Turns on all optional warnings which are desirable for normal code.
+# At present this is `-Wcomment', `-Wtrigraphs', `-Wmultichar' and a
+# warning about integer promotion causing a change of sign in `#if'
+# expressions. Note that many of the preprocessor's warnings are on
+# by default and have no options to control them.
+#
+#`-Werror'
+# Make all warnings into errors.
+#
+#`-fsigned-char'
+# Let the type `char' be signed, like `signed char'.
+#
+# Note that this is equivalent to `-fno-unsigned-char', which is the
+# negative form of `-funsigned-char'. Likewise, the option
+# `-fno-signed-char' is equivalent to `-funsigned-char'.
+#
+#`-msoft-float'
+# Generate output containing library calls for floating point.
+# *Warning:* the requisite libraries are not available for all ARM
+# targets. Normally the facilities of the machine's usual C
+# compiler are used, but this cannot be done directly in
+# cross-compilation. You must make your own arrangements to provide
+# suitable library functions for cross-compilation.
+#
+# `-msoft-float' changes the calling convention in the output file;
+# therefore, it is only useful if you compile _all_ of a program with
+# this option. In particular, you need to compile `libgcc.a', the
+# library that comes with GCC, with `-msoft-float' in order for this
+# to work.
+#
+#`-pipe'
+# Use pipes rather than temporary files for communication between the
+# various stages of compilation. This fails to work on some systems
+# where the assembler is unable to read from a pipe; but the GNU
+# assembler has no trouble.
+#
+#`-mmultiple'
+#`-mno-multiple'
+# Generate code that uses (does not use) the load multiple word
+# instructions and the store multiple word instructions. These
+# instructions are generated by default on POWER systems, and not
+# generated on PowerPC systems. Do not use `-mmultiple' on little
+# endian PowerPC systems, since those instructions do not work when
+# the processor is in little endian mode. The exceptions are PPC740
+# and PPC750 which permit the instructions usage in little endian
+# mode.
+#
+#`-mstring'
+#`-mno-string'
+# Generate code that uses (does not use) the load string instructions
+# and the store string word instructions to save multiple registers
+# and do small block moves. These instructions are generated by
+# default on POWER systems, and not generated on PowerPC systems.
+# Do not use `-mstring' on little endian PowerPC systems, since those
+# instructions do not work when the processor is in little endian
+# mode. The exceptions are PPC740 and PPC750 which permit the
+# instructions usage in little endian mode.
+#
+#`-meabi'
+#`-mno-eabi'
+# On System V.4 and embedded PowerPC systems do (do not) adhere to
+# the Embedded Applications Binary Interface (eabi) which is a set of
+# modifications to the System V.4 specifications. Selecting `-meabi'
+# means that the stack is aligned to an 8 byte boundary, a function
+# `__eabi' is called to from `main' to set up the eabi environment,
+# and the `-msdata' option can use both `r2' and `r13' to point to
+# two separate small data areas. Selecting `-mno-eabi' means that
+# the stack is aligned to a 16 byte boundary, do not call an
+# initialization function from `main', and the `-msdata' option will
+# only use `r13' to point to a single small data area. The `-meabi'
+# option is on by default if you configured GCC using one of the
+# `powerpc*-*-eabi*' options.
+#
+# [We elected to use the EABI to reduce stack requirements and possibly reduce
+# code size and improve performance. In practice it probably has little real
+# effect since the code size and performance improvements only apply to global
+# variables <= 8 bytes, and our applications will not have deeply nested call
+# trees. Still, much of the assembler code requires/assumes the EABI is in
+# place, and it certainly doesn't hurt anything to use it.]
+#
+#`-msdata=eabi'
+# On System V.4 and embedded PowerPC systems, put small initialized
+# `const' global and static data in the `.sdata2' section, which is
+# pointed to by register `r2'. Put small initialized non-`const'
+# global and static data in the `.sdata' section, which is pointed
+# to by register `r13'. Put small uninitialized global and static
+# data in the `.sbss' section, which is adjacent to the `.sdata'
+# section. The `-msdata=eabi' option is incompatible with the
+# `-mrelocatable' option. The `-msdata=eabi' option also sets the
+# `-memb' option.
+#
+#`-memb'
+# On embedded PowerPC systems, set the PPC_EMB bit in the ELF flags
+# header to indicate that `eabi' extended relocations are used.
+#
+#`-ffreestanding'
+# Assert that compilation takes place in a freestanding environment.
+# This implies `-fno-builtin'. A freestanding environment is one
+# in which the standard library may not exist, and program startup
+# may not necessarily be at `main'. The most obvious example is an
+# OS kernel. This is equivalent to `-fno-hosted'.
+#
+#`-fno-common'
+# In C, allocate even uninitialized global variables in the data
+# section of the object file, rather than generating them as common
+# blocks. This has the effect that if the same variable is declared
+# (without `extern') in two different compilations, you will get an
+# error when you link them. The only reason this might be useful is
+# if you wish to verify that the program will work on other systems
+# which always work this way.
+#
+# [It is always assumed to be an error if two C source files declare global
+# variables of the same name, since it is not clear whether this was intended
+# or not.]
+#
+#`-finline-functions-called-once'
+#`-fno-inline-functions-called-once'
+# Consider all `static' functions called once for inlining into their
+# caller even if they are not marked `inline'. If a call to a given
+# function is integrated, then the function is not output as
+# assembler code in its own right.
+#
+# Enabled if `-funit-at-a-time' is enabled.
+#
+# [There is a 'bug' in GCC related to inlining static, called-once
+# functions. GCC allocates stack space in the caller for the stacks of ALL
+# inlined functions of this type, even if they are called sequentially,
+# leading in some cases to kilobytes of wasted stack space. If you want to
+# inline a static called-once function you will need to explicity declare it
+# as 'inline'.]
+
+
diff --git a/src/ssx/pgp/ssx_port.h b/src/ssx/pgp/ssx_port.h
new file mode 100755
index 0000000..613ac43
--- /dev/null
+++ b/src/ssx/pgp/ssx_port.h
@@ -0,0 +1,19 @@
+#ifndef __SSX_PORT_H__
+#define __SSX_PORT_H__
+
+// $Id: ssx_port.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/ssx_port.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_port.h
+/// \brief The top-level PGP environment header for SSX.
+
+#define CHIP_PGP
+
+#include "ppc405.h"
+
+#endif /* __SSX_PORT_H__ */
diff --git a/src/ssx/pgp/ssxpgpfiles.mk b/src/ssx/pgp/ssxpgpfiles.mk
new file mode 100755
index 0000000..dd12da1
--- /dev/null
+++ b/src/ssx/pgp/ssxpgpfiles.mk
@@ -0,0 +1,37 @@
+# $Id: ssxpgpfiles.mk,v 1.4 2014/06/26 12:56:28 cmolsen Exp $
+# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/ssxpgpfiles.mk,v $
+# @file ssxpgpfiles.mk
+#
+# @brief mk for including pgp object files
+#
+# @page ChangeLogs Change Logs
+# @section ssxpgpfiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/11/2012 Makefile ODE support
+#
+# @endverbatim
+#
+##########################################################################
+# Object Files
+##########################################################################
+PGP-C-SOURCES = pgp_init.c pgp_irq_init.c pgp_pmc.c pgp_ocb.c pgp_pba.c \
+ pgp_id.c pgp_centaur.c
+PGP-S-SOURCES = pgp_cache.S
+
+PGP-TIMER-C-SOURCES =
+PGP-TIMER-S-SOURCES =
+
+PGP-THREAD-C-SOURCES =
+PGP-THREAD-S-SOURCES =
+
+PGP-ASYNC-C-SOURCES = pgp_async.c pgp_async_pore.c pgp_async_ocb.c \
+ pgp_async_pba.c
+PGP-ASYNC-S-SOURCES =
+
+PGP_OBJECTS += $(PGP-C-SOURCES:.c=.o) $(PGP-S-SOURCES:.S=.o)
+
diff --git a/src/ssx/ppc32/Makefile b/src/ssx/ppc32/Makefile
new file mode 100755
index 0000000..920144e
--- /dev/null
+++ b/src/ssx/ppc32/Makefile
@@ -0,0 +1,33 @@
+# $Id: Makefile,v 1.2 2013/12/12 16:12:37 bcbrock Exp $
+
+# This Makefile is designed to be invoked with the -I argument set to
+# the location of the "ssx.mk" for the build.
+#
+# This makefile creates the libppc32.a library.
+
+# >> gitprep
+# Path cleanup for GNU builds
+SSX = ..
+PGP = $(SSX)/pgp
+
+include $(PGP)/ssx.mk
+# << gitprep
+include ssxppc32files.mk
+
+
+
+libppc32.a: ${PPC32_OBJECTS}
+ $(AR) crs libppc32.a ${PPC32_OBJECTS}
+
+.PHONY : clean
+clean:
+ rm -f *.o *.a *.d *.d.*
+
+
+# This clause prevents the dependencies from creating errors during a clean.
+# Whenever a header file is added or deleted it will likely be necessary to
+# 'make clean' to force recomputation of dependencies.
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(PPC32_OBJECTS:.o=.d)
+endif \ No newline at end of file
diff --git a/src/ssx/ppc32/div64.S b/src/ssx/ppc32/div64.S
new file mode 100755
index 0000000..04ee008
--- /dev/null
+++ b/src/ssx/ppc32/div64.S
@@ -0,0 +1,255 @@
+// $Id: div64.S,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/div64.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file div64.S
+/// \brief Unsigned 64/64 bit division
+///
+/// This is IBM code, originally part of OS Open. The code has been slightly
+/// modified from its original form, both to be compatible with SSX and to
+/// change the function prototype slightly.
+///
+/// The code was provided by Matt Tyrlik in Raleigh.
+
+/* @#START#@
+**
+** PSCN (Power Service and Control Network)
+** Cage Controller OS Open Code
+**
+** (C) Copyright International Business Machines Corporation 2002
+** All Rights Reserved
+** Licensed Material - Program Property of I B M
+** Refer to copyright instructions: Form G120-2083
+**
+** Module:
+** div64.s
+**
+** Description:
+** Divide 64 bit unsigned values on 32 bit CPU
+** div64(uint64_t dividen, uint64_t divisor,
+** uint64_t *quotient, uint64_t *remainder)
+**
+** Original source from:
+** "The PowerPC Compiler Writer's Guide", pp62-65 by
+** Steve Hoxey, Faraydon Karim, Bill Hay, Hank Warray,
+** published by Warthman Associates, 240 Hamilton Avenue,
+** Palo Alto, CA 94301, USA, 1996 for IBM.
+** ISBN 0-9649654-0-2.
+**
+** This version checks for divisor equal to zero.
+**
+** Environment:
+** OS Open (XCOFF)
+**
+** Linkage:
+** AIX 4.3.3
+**
+** @author
+** Thomas Richter
+**
+** History:
+** Date Author Description
+** -----------------------------------------------------------------------------
+** 23-Sep-02 Richter Created
+**
+** @#END#@*/
+
+ .nolist
+#include "ssx.h"
+ .list
+
+ .set r0, 0
+ .set r1, 1
+ .set r2, 2
+ .set r3, 3
+ .set r4, 4
+ .set r5, 5
+ .set r6, 6
+ .set r7, 7
+ .set r8, 8
+ .set r9, 9
+ .set r10, 10
+ .set r11, 11
+ .set r12, 12
+
+ .global_function __ppc32_udiv64
+
+ /*
+ ** Code comment notation:
+ ** msw = most-significant (high-order) word, i.e. bits 0..31
+ ** lsw = least-significant (low-order) word, i.e. bits 32..63
+ ** LZ = Leading Zeroes
+ ** SD = Significant Digits
+ **
+ ** R3:R4 = Input parameter, dividend.
+ ** R5:R6 = Input parameter, divisor.
+ ** R7 = Output parameter, pointer to quotient.
+ ** R8 = Output parameter, pointer to remainder.
+ **
+ ** Pointer arguments point to a uint64_t.
+ **
+ ** Division is achieved using a shift/rotate/substract algorithsm
+ ** described above.
+ ** The registers are used as follows:
+ ** R3:R4 = dividend (upper 32bits:lower 32bits)
+ ** R5:R6 = divisor (upper 32bits:lower 32bits)
+ **
+ ** R7:R8 = temporary 64 bit register (upper 32bits:lower 32bits)
+ ** count the number of leading 0s in the dividend
+ **
+ ** Here is the description from the book. The dividend is placed
+ ** in the low order part of a 4 (32bit) register sequence named
+ ** tmp-high:tmp-low:dividend-high:dividend:low or tmp:dvd for short.
+ **
+ ** Each iteration includes the following steps:
+ ** 1. Shift tmp:dvd by one bit to the left.
+ ** 2. Subtract the divisor from tmp. This is a 64 bit operation.
+ ** 3. If result is greater than or equal, place result in tmp and
+ ** set the low order bit of dividend
+ ** 4. If result is negative, do not modify tmp and
+ ** clear the low order bit of dividend
+ ** 5. If the number of iterations is less than the width of the
+ ** dividend, goto step 1.
+ **
+ ** Now the algorithm can be improved by reducing the number of
+ ** iterations to be executed.
+ ** 1. Calculate the leading zeroes of the dividend.
+ ** 2. Calculate the leading zeroes of the divisor.
+ ** 3. Calculate the significant ones of the dividend.
+ ** 4. Calculate the significant ones of the divisor.
+ **
+ ** Initial tmp := dvd >> (dvd.SD - dvs.SD)
+ ** Initial dvd := dvd << (dvd.LZ + dvs.SD)
+ ** Loops: dvd.SD - dvs.SD.
+ **
+ ** Warning: Special care must be taken if dvd.LZ == dvs.LZ. The code
+ ** below does so by reducing the number of dvs.SD by one. This leads
+ ** to the loop being executed 1 more time than really necessary,
+ ** but avoids to check for the case when dvd.LZ == dvs.LZ.
+ ** This case (dvd.LZ == dvs.LZ) only checks for the number of leading
+ ** zeroes, but does not check if dividend is really greater than the
+ ** divisor.
+ ** Consider 16/17, both have an LZ value of 59. The code sets dvs.LZ
+ ** 60. This resutls in dvs.SD to 4, thus one iteration after which
+ ** tmp is the remainder 16.
+ */
+
+__ppc32_udiv64: // SSX
+ /* Save result pointers on volatile spare registers */
+ ori r12, r8, 0 /* Save remainder address */
+ ori r11, r7, 0 /* Save quotient address */
+
+ /* count the number of leading 0s in the dividend */
+ cmpwi cr0, r3, 0 /* dvd.msw == 0? */
+ cntlzw r0, r3 /* R0 = dvd.msw.LZ */
+ cntlzw r9, r4 /* R9 = dvd.lsw.LZ */
+ bne cr0, lab1 /* if(dvd.msw == 0) dvd.LZ = dvd.msw.LZ */
+ addi r0, r9, 32 /* dvd.LZ = dvd.lsw.LZ + 32 */
+lab1:
+ /* count the number of leading 0s in the divisor */
+ cmpwi cr0, r5, 0 /* dvd.msw == 0? */
+ cmpwi cr1, r6, 0 /* dvd.lsw == 0? */
+ cntlzw r9, r5 /* R9 = dvs.msw.LZ */
+ cntlzw r10, r6 /* R10 = dvs.lsw.LZ */
+ bne cr0, lab2 /* if(dvs.msw == 0) dvs.LZ = dvs.msw.LZ */
+ beq cr1, lab10 /* dvs.msw == 0 */
+ addi r9, r10, 32 /* dvs.LZ = dvs.lsw.LZ + 32 */
+
+lab2:
+ /* Determine shift amounts to minimize the number of iterations */
+ cmpw cr0, r0, r9 /* Compare dvd.LZ to dvs.LZ */
+ subfic r10, r0, 64 /* R10 = dvd.SD */
+ bgt cr0, lab9 /* if(dvs > dvd) quotient = 0 */
+ addi r9, r9, 1 /* See comment above. ++dvs.LZ (or --dvs.SD) */
+ subfic r9, r9, 64 /* R9 = dvs.SD */
+ add r0, r0, r9 /* (dvd.LZ + dvs.SD) = left shift of dvd for */
+ /* initial dvd */
+ subf r9, r9, r10 /* (dvd.SD - dvs.SD) = right shift of dvd for */
+ /* initial tmp */
+ mtctr r9 /* Number of iterations = dvd.SD - dvs.SD */
+
+ /* R7:R8 = R3:R4 >> R9 */
+ cmpwi cr0, r9, 32 /* compare R9 to 32 */
+ addi r7, r9, -32
+ blt cr0, lab3 /* if(R9 < 32) jump to lab3 */
+ srw r8, r3, r7 /* tmp.lsw = dvd.msw >> (R9 - 32) */
+ addi r7, r0, 0 /* tmp.msw = 0 */
+ b lab4
+
+lab3:
+ srw r8, r4, r9 /* R8 = dvd.lsw >> R9 */
+ subfic r7, r9, 32
+ slw r7,r3,r7 /* R7 = dvd.msw << 32 - R9 */
+ or r8, r8,r7 /* tmp.lsw = R8 | R7 */
+ srw r7,r3,r9 /* tmp.msw = dvd.msw >> R9 */
+lab4:
+ /* R3:R4 = R3:R4 << R0 */
+ cmpwi cr0, r0, 32 /* Compare R0 to 32 */
+ addic r9, r0, -32
+ blt cr0, lab5 /* if(R0 < 32) jump to lab5 */
+ slw r3, r4, r9 /* dvd.msw = dvd.lsw << R9 */
+ addi r4, r0, 0 /* dvd.lsw = 0 */
+ b lab6
+
+lab5:
+ slw r3, r3, r0 /* r3 = dvd.msw << r0 */
+ subfic r9, r0, 32
+ srw r9, r4, r9 /* r9 = dvd.lsw >> 32 - r0 */
+ or r3, r3, r9 /* dvd.msw = r3 | r9 */
+ slw r4, r4, r0 /* dvd.lsw = dvd.lsw << r0 */
+lab6:
+ /* Restoring division shift and subtract loop */
+ addi r10, r0, -1 /* r10 = -1 */
+ addic r7, r7, 0 /* Clear carry bit before loop starts */
+lab7:
+ /*
+ ** tmp:dvd is considered one large register
+ ** each portion is shifted left 1 bit by adding it to itself
+ ** adde sums the carry from the previous and creates a new carry
+ */
+ adde r4, r4, r4 /* Shift dvd.lsw left 1 bit */
+ adde r3, r3, r3 /* Shift dvd.msw to left 1 bit */
+ adde r8, r8, r8 /* Shift tmp.lsw to left 1 bit */
+ adde r7, r7, r7 /* Shift tmp.msw to left 1 bit */
+ subfc r0, r6, r8 /* tmp.lsw - dvs.lsw */
+ subfe. r9, r5, r7 /* tmp.msw - dvs.msw */
+ blt cr0, lab8 /* if(result < 0) clear carry bit */
+ or r8, r0, r0 /* Move lsw */
+ or r7, r9, r9 /* Move msw */
+ addic r0, r10, 1 /* Set carry bit */
+
+lab8:
+ bdnz lab7
+
+ /* Write quotient and remainder */
+ adde r4, r4, r4 /* quo.lsw (lsb = CA) */
+ adde r3, r3, r3 /* quo.msw (lsb from lsw) */
+ stw r4, 4(r11)
+ stw r3, 0(r11)
+ stw r8, 4(r12) /* rem.lsw */
+ stw r7, 0(r12) /* rem.msw */
+ blr
+
+lab9:
+ /* Qoutient is 0, divisor > dividend */
+ addi r0, r0, 0
+ stw r3, 0(r12) /* Store remainder */
+ stw r4, 4(r12)
+ stw r0, 0(r11) /* Set quotient to zero */
+ stw r0, 4(r11)
+ blr
+
+lab10:
+ /* Divisor is 0 */
+ addi r0, r0, -1
+ stw r0, 0(r12) /* Set remainder to zero */
+ stw r0, 4(r12)
+ stw r0, 0(r11) /* Set quotient to zero */
+ stw r0, 4(r11)
+ blr
+
+ .epilogue __ppc32_udiv64
diff --git a/src/ssx/ppc32/gnu/stubs-32.h b/src/ssx/ppc32/gnu/stubs-32.h
new file mode 100644
index 0000000..3da2fb2
--- /dev/null
+++ b/src/ssx/ppc32/gnu/stubs-32.h
@@ -0,0 +1,21 @@
+/* This file is automatically generated.
+ It defines a symbol `__stub_FUNCTION' for each function
+ in the C library which is a stub, meaning it will fail
+ every time called, usually setting errno to ENOSYS. */
+
+#ifdef _LIBC
+ #error Applications may not define the macro _LIBC
+#endif
+
+#define __stub___kernel_rem_pio2l
+#define __stub_chflags
+#define __stub_fattach
+#define __stub_fchflags
+#define __stub_fdetach
+#define __stub_gtty
+#define __stub_lchmod
+#define __stub_revoke
+#define __stub_setlogin
+#define __stub_sigreturn
+#define __stub_sstk
+#define __stub_stty
diff --git a/src/ssx/ppc32/ppc32.h b/src/ssx/ppc32/ppc32.h
new file mode 100755
index 0000000..e7f7bf8
--- /dev/null
+++ b/src/ssx/ppc32/ppc32.h
@@ -0,0 +1,171 @@
+#ifndef __PPC32_H__
+#define __PPC32_H__
+
+// $Id: ppc32.h,v 1.2 2014/03/14 15:11:46 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ppc32.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc32.h
+/// \brief Generic 32-bit PowerPC header for SSX
+///
+/// The synchronization macros defined here all create a compiler
+/// memory barrier that will cause GCC to flush/invalidate all memory data
+/// held in registers before the macro. This is consistent with other systems,
+/// e.g., the PowerPC Linux kernel, and is the safest way to define these
+/// macros.
+
+
+#include "ppc32_asm.h"
+#include "ppc32_gcc.h"
+
+// Condition register fields
+
+#define CR_LT(n) (0x80000000u >> (4 * (n)))
+#define CR_GT(n) (0x40000000u >> (4 * (n)))
+#define CR_EQ(n) (0x20000000u >> (4 * (n)))
+#define CR_SO(n) (0x10000000u >> (4 * (n)))
+
+
+#ifndef __ASSEMBLER__
+
+#include "stdint.h"
+
+/// ssize_t is defined explictly rather than bringing in all of <unistd.h>
+#ifndef __ssize_t_defined
+#define __ssize_t_defined
+typedef int ssize_t;
+#endif
+
+/// A memory barrier
+#define barrier() asm volatile ("" : : : "memory")
+
+/// Ensure In-order Execution of Input/Output
+#define eieio() asm volatile ("eieio" : : : "memory")
+
+/// Memory barrier
+#define sync() asm volatile ("sync" : : : "memory")
+
+/// Instruction barrier
+#define isync() asm volatile ("isync" : : : "memory")
+
+/// CouNT Leading Zeros Word
+#define cntlzw(x) \
+({uint32_t __x = (x); \
+ uint32_t __lzw; \
+ asm volatile ("cntlzw %0, %1" : "=r" (__lzw) : "r" (__x)); \
+ __lzw;})
+
+/// CouNT Leading Zeros : uint32_t
+static inline int
+cntlz32(uint32_t x) {
+ return cntlzw(x);
+}
+
+/// CouNT Leading Zeros : uint64_t
+static inline int
+cntlz64(uint64_t x) {
+ if (x > 0xffffffff) {
+ return cntlz32(x >> 32);
+ } else {
+ return 32 + cntlz32(x);
+ }
+}
+
+
+/// 32-bit population count
+static inline int
+popcount32(uint32_t x)
+{
+ return __builtin_popcount(x);
+}
+
+
+/// 64-bit population count
+static inline int
+popcount64(uint64_t x)
+{
+ return __builtin_popcountll(x);
+}
+
+
+// NB: Normally we wouldn't like to force coercion inside a macro because it
+// can mask programming errors, but for the MMIO macros the addresses are
+// typically manifest constants or 32-bit unsigned integer expressions so we
+// embed the coercion to avoid warnings.
+
+/// 8-bit MMIO Write
+#define out8(addr, data) \
+do {*(volatile uint8_t *)(addr) = (data); eieio();} while(0)
+
+/// 8-bit MMIO Read
+#define in8(addr) \
+({uint8_t __data = *(volatile uint8_t *)(addr); eieio(); __data;})
+
+/// 16-bit MMIO Write
+#define out16(addr, data) \
+do {*(volatile uint16_t *)(addr) = (data); eieio();} while(0)
+
+/// 16-bit MMIO Read
+#define in16(addr) \
+({uint16_t __data = *(volatile uint16_t *)(addr); eieio(); __data;})
+
+/// 32-bit MMIO Write
+#define out32(addr, data) \
+do {*(volatile uint32_t *)(addr) = (data); eieio();} while(0)
+
+/// 32-bit MMIO Read
+#define in32(addr) \
+({uint32_t __data = *(volatile uint32_t *)(addr); eieio(); __data;})
+
+/// 64-bit MMIO Write
+#define out64(addr, data) \
+ do { \
+ uint64_t __data = (data); \
+ volatile uint32_t *__addr_hi = (uint32_t *)(addr); \
+ volatile uint32_t *__addr_lo = __addr_hi + 1; \
+ *__addr_hi = (__data >> 32); \
+ eieio(); \
+ *__addr_lo = (__data & 0xffffffff); \
+ eieio(); \
+ } while(0)
+
+/// 64-bit MMIO Read
+#define in64(addr) \
+ ({ \
+ uint64_t __data; \
+ volatile uint32_t *__addr_hi = (uint32_t *)(addr); \
+ volatile uint32_t *__addr_lo = __addr_hi + 1; \
+ __data = *__addr_hi; \
+ eieio(); \
+ __data = (__data << 32) | *__addr_lo; \
+ eieio(); \
+ __data;})
+
+#endif /* __ASSEMBLER__ */
+
+
+#ifndef __ASSEMBLER__
+
+/// Store revision information as a (global) string constant
+#define REVISION_STRING(symbol, rev) const char* symbol = rev;
+
+#else // __ASSEMBLER__
+
+/// Store revision information as a global string constant
+ .macro .revision_string, symbol:req, rev:req
+ .pushsection .rodata
+ .balign 4
+ .global \symbol
+\symbol\():
+ .asciz "\rev"
+ .balign 4
+ .popsection
+ .endm
+
+#endif // __ASSEMBLER__
+
+#endif /* __PPC32_H__ */
diff --git a/src/ssx/ppc32/ppc32_asm.h b/src/ssx/ppc32/ppc32_asm.h
new file mode 100755
index 0000000..0207c22
--- /dev/null
+++ b/src/ssx/ppc32/ppc32_asm.h
@@ -0,0 +1,408 @@
+#ifndef __PPC32_ASM_H__
+#define __PPC32_ASM_H__
+
+// $Id: ppc32_asm.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ppc32_asm.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc32_asm.h
+/// \brief Generic assembler macros for 32-bit PowerPC
+
+// Doxygen is confused by assembler; the best I know how to make it
+// work is to put all of the documentation at the beginning like below
+// and effectively comment out the code using Doxygen cond/endcond.
+
+/// \page ppc32_asm Generic assembler macros for 32-bit PowerPC
+///
+///
+/// \section _lxzi _l<w,h,b>zi - Load register and Zero from Immediate address
+///
+/// These macros encapsulate the 2-instruction sequence required to
+/// load from a 32-bit immediate address.
+///
+/// \arg \c dreg A register to receive the load data.
+/// \arg \c areg A register to hold the immediate address. This can \e
+/// not be register 0. Note that if \a areg != \a dreg
+/// then \a areg will contain the address at the end of
+/// the macro sequence.
+/// \arg \c addr A 32-bit immediate address, which may be either an
+/// absolute or relocatable expression.
+///
+/// Forms:
+///
+/// \b _lbzi \a dreg, \a areg, \a addr - Load Byte and Zero from Immediate address \n
+/// \b _lhzi \a dreg, \a areg, \a addr - Load Halfword and Zero from Immediate address \n
+/// \b _lwzi \a dreg, \a areg, \a addr - Load Word and Zero from Immediate address \n
+///
+///
+/// \section _stxi _st<w,h,b>i - STore register to Immediate address
+///
+/// These macros encapsulate the 2-instruction sequence required to
+/// store to a 32-bit immediate address.
+///
+/// \arg \c dreg The register to store.
+/// \arg \c areg A register to hold the immediate address. This can \e
+/// not be register 0, and can not be the same as \a dreg.
+/// Note that \a areg will contain the address at the end of
+/// the macro sequence.
+/// \arg \c addr A 32-bit immediate address, which may be either an
+/// absolute or relocatable expression.
+///
+/// Forms:
+///
+/// \b _stbi \a dreg, \a areg, \a addr - STore Byte to Immediate address \n
+/// \b _sthi \a dreg, \a areg, \a addr - STore Halfword to Immediate address \n
+/// \b _stwi \a dreg, \a areg, \a addr - STore Word to Immediate address \n
+///
+///
+/// \section _lstzsd _<l,st><w,h,b><z>sd - Load/STore register from/to Small Data area
+///
+/// These macros encapulate the small data area relocations for access
+/// to storage in the small data sections .sbss, .sdata, .sbss2 and
+/// .sdata2. Use of these macros implies small data area support in
+/// the compile environment (for variables shared between compiled and
+/// assembled code) and initialization code that sets up the small data
+/// area registers R13 (and optionally R2).
+///
+/// The relocations generated by this macro will work for both SVR4 ABI
+/// and EABI environments. In particular, for EABI environments
+/// the link editor will insert offsets to either R13 or R2 depending
+/// on the section of the symbol.
+///
+/// \arg \c dreg The register to load or store.
+/// \arg \c addr A 32-bit immediate address, assumed to be a
+/// relocatable address in one of the small data sections.
+///
+/// Forms:
+///
+/// \b _lbzsd \a dreg, \a addr - Load Byte and Zero from Small Data area \n
+/// \b _lhzsd \a dreg, \a addr - Load Halfword and Zero from Small Data area \n
+/// \b _lwzsd \a dreg, \a addr - Load Word and Zero from Small Data area \n
+/// \b _stbsd \a dreg, \a addr - STore Byte to Small Data area \n
+/// \b _sthsd \a dreg, \a addr - STore Halfword to Small Data area \n
+/// \b _stwsd \a dreg, \a addr - STore Word to Small Data area \n
+///
+///
+/// \section _liw _liw<a> - Load Immediate Word (Absolute)
+///
+/// These macros encapsulate the two instructions required to load a
+/// 32-bit immediate value into a register. If the immediate is an
+/// absolute expression, then the \c 'a' form may be able to optimize
+/// to a single instruction depending on whether only the high- or
+/// low-order bits of the immediate are non-zero.
+///
+/// Forms:
+///
+/// \b _liw \a rd, \a imm - Load register \a rd with the 32-bit immediate \a imm \n
+/// \b _liwa \a rd, \a imm - Load register \a rd with the 32-bit absolute immediate \a imm \n
+///
+///
+/// \section _oriwa _oriwa - OR Immediate Word Absolute
+///
+/// This macro encapsulates the logical OR of a 32-bit immediate with a
+/// register. The immediate value must be an absolute expression.
+///
+/// The PowerPC has instructions for OR-ing 16-bit immediates into the
+/// upper (\c oris) and lower (\c ori) portions of a register. This
+/// macro optimizes the generated code based on which bits (if any) of
+/// the absolte immediate are non-zero.
+///
+/// This special macro is only provided for the OR function. For other
+/// logical operations and recording forms it is necessary in general
+/// to first load the 32-bit immediate into a register (e.g., with \c
+/// _liwa) then perform the logical operation.
+///
+/// \arg \c rd The destination register; at the end will contain \c rs
+/// OR \a imm
+/// \arg \c rs The source register.
+/// \arg \c imm 32-bit absolute expression.
+///
+/// Forms:
+///
+/// \b _oriwa \a rd, \a rs, \a imm - \a rd gets \a rs OR \a imm \n
+///
+///
+/// \section _incr64_fast - 64-bit increment for fast interrupt handlers
+///
+/// This macros implements 64-bit counter update in fast interrupt handlers
+/// which are forbidden from using the carry-bit in the XER (without
+/// saving/restoring it.)
+///
+/// \arg \c rs Scratch register
+/// \arg \c ra Register containing the counter address at entry
+///
+/// \a rs and \a ra must be unique. At the end of the macro the count
+/// is updated to memory and \a ra is unmodified.
+///
+///
+/// \section _setclear_bits Set/Clear/Copy Bits from Immediate Positions
+///
+/// There are situations where it is easier/faster to clear individual bits
+/// and bit fields, set bits or copy fields, based on immediate bit numbers
+/// and locations, rather than loading masks, since setting up a mask
+/// requires 2 instruction in general, whereas these macros generate a single
+/// instruction.
+///
+/// \arg \c rd - The destination register
+/// \arg \c rs - The source register
+/// \arg \c n - An immediate size of a bit field, in the range 0 to 32
+/// \arg \c b - An immediate big-endian bit number in the range 0 to 31
+///
+/// Forms:
+///
+/// \b _clrfield \a rd, \a rs, \a n, \a b - Clear an \a n bit field from \a rs
+/// to \a rd starting from bit \a b \n
+/// \b _clrbit \a rd, \a rs, \a b - Clear bit \a b \n
+/// \b _setbit \a rd, \a rs, \a b - Set bit \a b \n
+/// \b _copyfield \a rd, \a rs, \a n, \a b - Copy an n-bit field from \a rs to
+/// \a rd starting from bit \a b \n
+///
+///
+/// \section pseudo_ops Assembler Pseudo-Ops Macros
+///
+/// Several macros define new 'pseudo-ops'.
+///
+/// \subsection cache_align .cache_align
+///
+/// The \c .cache_align pseudo-op is used to force alignment on a
+/// cache-line boundary. It requires a preprocessor symbol definition for
+/// \c LOG_CACHE_LINE_SIZE
+///
+/// Forms:
+///
+/// \b .cache_align \n
+///
+///
+/// \subsection global_function Local and Global Functions
+///
+/// The \c .function and \c .global_function pseudo-ops define function
+/// symbols in the \c .text section.
+///
+/// Forms:
+///
+/// \b .function \a symbol - Define a local function \a symbol \n
+/// \b .global_function \a symbol - Define a global function \a symbol \n
+///
+///
+/// \subsection epilogue .epilogue
+///
+/// The \c .epilogue pseudo-op adds size and type information for
+/// functions defined in assembler.
+///
+/// \arg \c symbol - Assembler epilogue for the function \a symbol.
+///
+/// Forms:
+///
+/// \b .epilogue \a symbol \n
+///
+///
+/// \cond
+
+#ifdef __ASSEMBLER__
+
+### ****************************************************************************
+### _l<b,h,w>zi
+### _st<b,h,w>i
+### ****************************************************************************
+
+ .macro _lbzi dreg, areg, addr
+ lis \areg, \addr@ha
+ .ifc \areg, \dreg
+ lbz \dreg, \addr@l(\areg)
+ .else
+ lbzu \dreg, \addr@l(\areg)
+ .endif
+ .endm
+
+ .macro _lhzi dreg, areg, addr
+ lis \areg, \addr@ha
+ .ifc \areg, \dreg
+ lhz \dreg, \addr@l(\areg)
+ .else
+ lhzu \dreg, \addr@l(\areg)
+ .endif
+ .endm
+
+ .macro _lwzi dreg, areg, addr
+ lis \areg, \addr@ha
+ .ifc \areg, \dreg
+ lwz \dreg, \addr@l(\areg)
+ .else
+ lwzu \dreg, \addr@l(\areg)
+ .endif
+ .endm
+
+ .macro _stbi dreg, areg, addr
+ .ifc \areg, \dreg
+ .err
+ .endif
+ lis \areg, \addr@ha
+ stbu \dreg, \addr@l(\areg)
+ .endm
+
+ .macro _sthi dreg, areg, addr
+ .ifc \areg, \dreg
+ .err
+ .endif
+ lis \areg, \addr@ha
+ sthu \dreg, \addr@l(\areg)
+ .endm
+
+ .macro _stwi dreg, areg, addr
+ .ifc \areg, \dreg
+ .err
+ .endif
+ lis \areg, \addr@ha
+ stwu \dreg, \addr@l(\areg)
+ .endm
+
+
+### ****************************************************************************
+### _l<b,h,w>zsd
+### _st<b,h,w>sd
+### ****************************************************************************
+
+ .macro _lbzsd dreg, addr
+ lbz \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _lhzsd dreg, addr
+ lhz \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _lwzsd dreg, addr
+ lwz \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _stbsd dreg, addr
+ stb \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _sthsd dreg, addr
+ sth \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _stwsd dreg, addr
+ stw \dreg, \addr@sda21(0)
+ .endm
+
+
+### ****************************************************************************
+### _liw<a>
+### _oriwa
+### ****************************************************************************
+
+ .macro _liw rd, imm
+ lis \rd, \imm@h
+ ori \rd, \rd, \imm@l
+ .endm
+
+ .macro _liwa rd, imm
+ .if (\imm & 0xffff0000)
+ lis \rd, \imm@h
+ .if (\imm & 0xffff)
+ ori \rd, \rd, \imm@l
+ .endif
+ .else
+ li \rd, \imm@l
+ .endif
+ .endm
+
+ .macro _oriwa rd, rs, imm
+ .if (\imm & 0xffff0000)
+ oris \rd, \rs, \imm@h
+ .if (\imm & 0xffff)
+ ori \rd, \rd, \imm@l
+ .endif
+ .else
+ ori \rd, \rs, \imm@l
+ .endif
+ .endm
+
+### ****************************************************************************
+### _incr64_fast
+### ****************************************************************************
+
+ .macro _incr64_fast, rs:req, ra:req
+
+ lwz \rs, 4(\ra)
+ addi \rs, \rs, 1
+ cmpwi \rs, 0
+ stw \rs, 4(\ra)
+ bne 233643278f
+
+ lwz \rs, 0(\ra)
+ addi \rs, \rs, 1
+ stw \rs, 0(\ra)
+233643278:
+
+ .endm
+
+### ****************************************************************************
+### _clrfield
+### _clrbit
+### _setbit
+### _copyfield
+### ****************************************************************************
+
+ .macro _clrfield, rd, rs, n, b
+ rlwinm \rd, \rs, 0, (\b + \n) & 0x1f, (\b - 1) & 0x1f
+ .endm
+
+ .macro _clrbit, rd, rs, b
+ _clrfield \rd, \rs, 1, \b
+ .endm
+
+ .macro _setbit, rd, rs, b
+ .ifle \b - 15
+ oris \rd, \rs, 1 << (15 - \b)
+ .else
+ ori \rd, \rs, 1 << (31 - \b)
+ .endif
+ .endm
+
+ .macro _copyfield, rd, rs, n, b
+ rlwimi \rd, \rs, 0, \b , (\b + \n - 1)
+ .endm
+
+### ****************************************************************************
+### .cache_align
+### .<global_>function
+### .epilogue
+### ****************************************************************************
+
+ .set _log_cache_line_size, LOG_CACHE_LINE_SIZE
+
+ .macro .cache_align
+ .align _log_cache_line_size
+ .endm
+
+ .macro .function symbol
+ .text
+ .align 2
+ .endm
+
+ .macro .global_function symbol
+ .text
+ .align 2
+ .global \symbol
+ .endm
+
+ .macro .epilogue symbol
+ .type \symbol, @function
+ .size \symbol, . - \symbol
+ .endm
+
+#endif /* __ASSEMBLER__ */
+
+/// \endcond
+
+// Local Variables:
+// mode:asm
+// End:
+
+#endif /* __PPC32_ASM_H__ */
diff --git a/src/ssx/ppc32/ppc32_gcc.c b/src/ssx/ppc32/ppc32_gcc.c
new file mode 100755
index 0000000..a00ab48
--- /dev/null
+++ b/src/ssx/ppc32/ppc32_gcc.c
@@ -0,0 +1,309 @@
+// $Id: ppc32_gcc.c,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ppc32_gcc.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc32_gcc.h
+/// \brief 32-bit PowerPC functions expected by GCC
+///
+/// GCC expects certain built-in functions to be defined in the environment.
+/// Since SSX applications are statically linked, we must define these
+/// functions ourselves to avoid a static link with the GCC libraries, which
+/// would legaly require us to distribute (at least) the binary forms of SSX
+/// applications.
+///
+/// We obviously had to look at some GCC library code to understand the
+/// specifications of these routines. However, all of the code here is new -
+/// no structure definitions or lines of executable code were copied from the
+/// GCC sources.
+
+#include "ssx.h"
+#include "ppc32_gcc.h"
+
+/// A 64-bit logical right shift.
+///
+/// Note that shifts with negative shift counts or shifts with shift counts
+/// longer than 63 bits are undefined.
+
+uint64_t
+__lshrdi3(uint64_t x, int i)
+{
+ Uint64 input, result;
+
+ if (i == 0) {
+ return x;
+ }
+
+ input.value = x;
+
+ if (i >= 32) {
+ result.word[0] = 0;
+ result.word[1] = input.word[0] >> (i - 32);
+ } else {
+ result.word[0] = input.word[0] >> i;
+ result.word[1] = (input.word[1] >> i) | (input.word[0] << (32 - i));
+ }
+
+ return result.value;
+}
+
+
+/// A 64 bit arithmetic left shift.
+///
+/// Note that shifts with negative shift counts or shifts with shift counts
+/// longer than 63 bits are undefined.
+
+uint64_t
+__ashldi3(uint64_t x, int i)
+{
+ Uint64 input, result;
+
+ if (i == 0) {
+ return x;
+ }
+
+ input.value = x;
+
+ if (i >= 32) {
+ result.word[1] = 0;
+ result.word[0] = input.word[1] << (i - 32);
+ } else {
+ result.word[1] = input.word[1] << i;
+ result.word[0] = (input.word[0] << i) | (input.word[1] >> (32 - i));
+ }
+
+ return result.value ;
+
+}
+
+
+/// A 64 bit arithmetic right shift.
+///
+/// Note that shifts with negative shift counts or shifts with shift counts
+/// longer than 63 bits are undefined.
+
+uint64_t
+__ashrdi3(uint64_t x, int i)
+{
+ Int64 input, result;
+
+ if (i == 0) {
+ return x;
+ }
+
+ input.value = x;
+
+ if (i >= 32) {
+ result.word[0] = input.word[0] >> 31;
+ result.word[1] = input.word[0] >> (i - 32);
+ } else {
+ result.word[0] = input.word[0] >> i;
+ result.word[1] =
+ (((uint32_t)input.word[1]) >> i) |
+ (input.word[0] << (32 - i));
+ }
+
+ return result.value ;
+
+}
+
+
+/// 32-bit Population count
+
+// This is a well-known divide-and-conquer algorithm, e.g. look on Wikipedia
+// under "Hamming Weight". The idea is to compute sums of adjacent bit
+// segments in parallel, in place. This compiles to 22 PPC405 instructions.
+
+int
+__popcountsi2(uint32_t x)
+{
+ uint32_t m1 = 0x55555555;
+ uint32_t m2 = 0x33333333;
+ uint32_t m4 = 0x0f0f0f0f;
+ x -= (x >> 1) & m1; /* Sum pairs of bits */
+ x = (x & m2) + ((x >> 2) & m2);/* Sum 4-bit segments */
+ x = (x + (x >> 4)) & m4; /* Sum 8-bit segments */
+ x += x >> 8; /* Sum 16-bit segments */
+ return (x + (x >> 16)) & 0x3f; /* Final sum */
+}
+
+
+/// 64-bit Population count
+
+int
+__popcountdi2(uint64_t x)
+{
+ return __popcountsi2(x >> 32) + __popcountsi2(x & 0xffffffff);
+}
+
+
+// 64-bit divides
+//
+// For the unsigned case, note that divide by 0 returns quotient = remainder =
+// 0.
+//
+// For the signed case, in general we perform the division on the absolute
+// values and fix the signs of the quotient and remainder at the end.
+//
+// For the signed case, the convention in other libraries seems to be to
+// ignore the case of the most-negative integer. Although it seems "wrong" to
+// return the wrong answer when the right answer can be easily computed, in
+// the interest of code size we follow the convention here and ignore the most
+// negative integer.
+//
+// The assembler routine __ppc32_udiv64() assembles to 304 bytes. The full C
+// routine __ppc_sdiv64 compiles to 416 bytes with the most-negative checks,
+// but only 184 bytes as configured here.
+
+#if 0
+// For the signed cases, we need to handle the special case that the dividend
+// or divisor is the most negative integer.
+//
+// If the dividend is the most negative integer, then dividing this integer by
+// -1 would overflow as a positive quotient, so we set quotient and remainder
+// to 0 in this case. For divide by 1, the quotient is the most negative
+// integer. Otherwise we adjust the dividend by the absolute value of the
+// divisor, then fix up the quotient later by adding or subtracting 1.
+//
+// If the divisor is the most negative integer, then the quotient is always 0
+// unless the dividend is also the most negative integer, in which case the
+// quotient is 1 and the remainder is 0.
+//
+#endif
+
+uint64_t
+__udivdi3(uint64_t u, uint64_t v)
+{
+ uint64_t quotient, remainder;
+
+ __ppc32_udiv64(u, v, &quotient, &remainder);
+ return quotient;
+}
+
+
+uint64_t
+__umoddi3(uint64_t u, uint64_t v)
+{
+ uint64_t quotient, remainder;
+
+ __ppc32_udiv64(u, v, &quotient, &remainder);
+ return remainder;
+}
+
+
+#if 0
+#define INT64_T_MIN ((int64_t)(0x8000000000000000ull))
+#endif
+
+void
+__ppc32_sdiv64(int64_t u, int64_t v,
+ int64_t *quotient, int64_t *remainder)
+{
+ int q_negate, r_negate;
+ uint64_t uu, uv;
+#if 0
+ int fixup = 0;
+#endif
+
+ q_negate = (u < 0) ^ (v < 0);
+ r_negate = (u < 0);
+ uu = (u < 0 ? -u : u);
+ uv = (v < 0 ? -v : v);
+
+#if 0
+ if (u == INT64_T_MIN) {
+ if (v == -1) {
+ *quotient = 0;
+ *remainder = 0;
+ return;
+ } else if (v == 1) {
+ *quotient = INT64_T_MIN;
+ *remainder = 0;
+ return;
+ } else if (v == INT64_T_MIN) {
+ *quotient = 1;
+ *remainder = 0;
+ return;
+ } else {
+ fixup = 1;
+ u += (v < 0 ? -v : v);
+ }
+ } else if (v == INT64_T_MIN) {
+ *quotient = 0;
+ *remainder = u;
+ return;
+ }
+#endif
+
+ __ppc32_udiv64(uu, uv, (uint64_t *)quotient, (uint64_t *)remainder);
+
+#if 0
+ if (fixup) {
+ *quotient += 1;
+ }
+#endif
+ if (q_negate) {
+ *quotient = -(*quotient);
+ }
+ if (r_negate) {
+ *remainder = -(*remainder);
+ }
+}
+
+
+int64_t
+__divdi3(int64_t u, int64_t v)
+{
+ int64_t quotient, remainder;
+
+ __ppc32_sdiv64(u, v, &quotient, &remainder);
+ return quotient;
+}
+
+
+int64_t
+__moddi3(int64_t u, int64_t v)
+{
+ int64_t quotient, remainder;
+
+ __ppc32_sdiv64(u, v, &quotient, &remainder);
+ return remainder;
+}
+
+
+/// 64-bit unsigned compare as a function, returning 0 (<), 1 (==) or 2 (>).
+
+int
+__ucmpdi2(uint64_t i_a, uint64_t i_b)
+{
+ Uint64 a, b;
+ int rv;
+
+ a.value = i_a;
+ b.value = i_b;
+
+ if (a.word[0] < b.word[0]) {
+ rv = 0;
+ } else if (a.word[0] > b.word[0]) {
+ rv = 2;
+ } else if (a.word[1] < b.word[1]) {
+ rv = 0;
+ } else if (a.word[1] > b.word[1]) {
+ rv = 2;
+ } else {
+ rv = 1;
+ }
+
+ return rv;
+}
+
+
+
+
+
+
+
+
diff --git a/src/ssx/ppc32/ppc32_gcc.h b/src/ssx/ppc32/ppc32_gcc.h
new file mode 100755
index 0000000..1925107
--- /dev/null
+++ b/src/ssx/ppc32/ppc32_gcc.h
@@ -0,0 +1,75 @@
+#ifndef __PPC32_GCC_H__
+#define __PPC32_GCC_H__
+
+// $Id: ppc32_gcc.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ppc32_gcc.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc32_gcc.h
+/// \brief 32-bit PowerPC functions expected by GCC
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/// A 64-bit unsigned integer type
+
+typedef union {
+ uint64_t value;
+ uint32_t word[2];
+} Uint64;
+
+/// A 64-bit signed integer type
+
+typedef union {
+ int64_t value;
+ int32_t word[2];
+} Int64;
+
+uint64_t
+__lshrdi3(uint64_t x, int i);
+
+uint64_t
+__ashldi3(uint64_t x, int i);
+
+uint64_t
+__ashrdi3(uint64_t x, int i);
+
+int
+__popcountsi2(uint32_t x);
+
+int
+__popcountdi2(uint64_t x);
+
+/// Unsigned 64/64 bit divide, returning quotient and remainder via pointers.
+
+void
+__ppc32_udiv64(uint64_t u, uint64_t v, uint64_t *q, uint64_t *r);
+
+/// Signed 64/64 bit divide, returning quotient and remainder via pointers.
+
+void
+__ppc32_sdiv64(int64_t u, int64_t v, int64_t *q, int64_t *r);
+
+uint64_t
+__udivdi3(uint64_t u, uint64_t v);
+
+int64_t
+__divdi3(int64_t u, int64_t v);
+
+int64_t
+__moddi3(int64_t u, int64_t v);
+
+uint64_t
+__umoddi3(uint64_t u, uint64_t v);
+
+int
+__ucmpdi2(uint64_t a, uint64_t b);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPC32_GCC_H__ */
diff --git a/src/ssx/ppc32/savegpr.S b/src/ssx/ppc32/savegpr.S
new file mode 100755
index 0000000..854f22b
--- /dev/null
+++ b/src/ssx/ppc32/savegpr.S
@@ -0,0 +1,78 @@
+// $Id: savegpr.S,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/savegpr.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+///
+/// \file savegpr.S
+/// \brief Push registers onto or load registers from the stack
+///
+/// This code was developed due to missing references to _savegpr_{X}
+/// and _restgpr_{X}_x that surfaced when moving to GCC 4.5.1 and
+/// using the -Os optimization level.
+///
+/// The open-source code was viewed to get the spec, but no
+/// code was copied.
+///
+
+
+ .macro SAVE reg
+ .global _savegpr_\reg
+ _savegpr_\reg\():
+ stw \reg,(((31-\reg)*4 +4)*-1)(11)
+ .endm
+
+ SAVE 14
+ SAVE 15
+ SAVE 16
+ SAVE 17
+ SAVE 18
+ SAVE 19
+ SAVE 20
+ SAVE 21
+ SAVE 22
+ SAVE 23
+ SAVE 24
+ SAVE 25
+ SAVE 26
+ SAVE 27
+ SAVE 28
+ SAVE 29
+ SAVE 30
+ SAVE 31
+ blr
+
+ .macro RESTX reg
+ .global _restgpr_\reg\()_x
+ _restgpr_\reg\()_x:
+ .ifeq (31-\reg)
+ lwz 0,4(11)
+ .endif
+ lwz \reg,(((31-\reg)*4 +4)*-1)(11)
+
+ .endm
+
+ RESTX 14
+ RESTX 15
+ RESTX 16
+ RESTX 17
+ RESTX 18
+ RESTX 19
+ RESTX 20
+ RESTX 21
+ RESTX 22
+ RESTX 23
+ RESTX 24
+ RESTX 25
+ RESTX 26
+ RESTX 27
+ RESTX 28
+ RESTX 29
+ RESTX 30
+ RESTX 31
+ mtlr 0
+ mr 1,11
+ blr
diff --git a/src/ssx/ppc32/ssxppc32files.mk b/src/ssx/ppc32/ssxppc32files.mk
new file mode 100755
index 0000000..8697550
--- /dev/null
+++ b/src/ssx/ppc32/ssxppc32files.mk
@@ -0,0 +1,29 @@
+# $Id: ssxppc32files.mk,v 1.2 2014/06/26 12:58:31 cmolsen Exp $
+# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ssxppc32files.mk,v $
+# @file ssxppc32files.mk
+#
+# @brief mk for including ppc32 object files
+#
+# @page ChangeLogs Change Logs
+# @section ssxppc32files.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/11/2012 Makefile ODE support
+#
+# @endverbatim
+#
+
+##########################################################################
+# Object Files
+##########################################################################
+PPC32-C-SOURCES = ppc32_gcc.c
+PPC32-S-SOURCES = div64.S savegpr.S
+
+PPC32_OBJECTS = $(PPC32-C-SOURCES:.c=.o) $(PPC32-S-SOURCES:.S=.o)
+
+
+
diff --git a/src/ssx/ppc405/Makefile b/src/ssx/ppc405/Makefile
new file mode 100755
index 0000000..89c2c58
--- /dev/null
+++ b/src/ssx/ppc405/Makefile
@@ -0,0 +1,40 @@
+# $Id: Makefile,v 1.2 2013/12/12 16:12:38 bcbrock Exp $
+
+# This Makefile is designed to be invoked with the -I argument set to
+# the location of the "ssx.mk" for the build
+
+# >> gitprep
+# Path cleanup for GNU builds
+SSX = ..
+PGP = $(SSX)/pgp
+
+include $(PGP)/ssx.mk
+# << gitprep
+include ssxppc405files.mk
+
+ifeq "$(SSX_TIMER_SUPPORT)" "1"
+PPC405_OBJECTS += ${PPC405-TIMER-C-SOURCES:.c=.o} ${PPC405-TIMER-S-SOURCES:.S=.o}
+endif
+
+ifeq "$(SSX_THREAD_SUPPORT)" "1"
+PPC405_OBJECTS += ${PPC405-THREAD-C-SOURCES:.c=.o} ${PPC405-THREAD-S-SOURCES:.S=.o}
+endif
+
+ifeq "$(PPC405_MMU_SUPPORT)" "1"
+PPC405_OBJECTS += ${PPC405-MMU-C-SOURCES:.c=.o} ${PPC405-MMU-S-SOURCES:.S=.o}
+endif
+
+
+all: local
+ $(MAKE) -I ../pgp -C ../ppc32
+
+local: $(PPC405_OBJECTS)
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.*
+ $(MAKE) -I ../pgp -C ../ppc32 clean
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(PPC405_OBJECTS:.o=.d)
+endif \ No newline at end of file
diff --git a/src/ssx/ppc405/ppc405.h b/src/ssx/ppc405/ppc405.h
new file mode 100755
index 0000000..18b0c53
--- /dev/null
+++ b/src/ssx/ppc405/ppc405.h
@@ -0,0 +1,771 @@
+#ifndef __PPC405_H__
+#define __PPC405_H__
+
+// $Id: ppc405.h,v 1.3 2014/02/03 01:30:42 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405.h
+/// \brief PowerPC 405 port header for SSX
+
+// The 405 has a 32-byte line and 2-way set associative caches. The cache
+// configuration varies by chip/ASIC.
+//
+// Regarding the DCACHE_TAG_MASK, used by dcache_flush_all: The IBM
+// documentation on the D-cache tag sizes doesn't make any sense to me - it
+// claims the tag size is constant regardless of the size of the cache.
+// However the Xilinx documentation for their 405 core (which has the same
+// 16KB cache as PgP) is consistent with the way the DCACHE_TAG_MASK is
+// defined here.
+
+#define CACHE_LINE_SIZE 32
+#define LOG_CACHE_LINE_SIZE 5
+
+#define ICACHE_WAYS 2
+#define DCACHE_WAYS 2
+
+#define LOG_ICACHE_WAYS 1
+#define LOG_DCACHE_WAYS 1
+
+#define ICACHE_LINES (ICACHE_SIZE / CACHE_LINE_SIZE)
+#define DCACHE_LINES (DCACHE_SIZE / CACHE_LINE_SIZE)
+
+#define DCACHE_TAG_MASK \
+ ((0xffffffff << (LOG_DCACHE_SIZE - LOG_DCACHE_WAYS)) & 0xffffffff)
+
+#ifdef CHIP_PGP
+
+#define ICACHE_SIZE (16 * 1024)
+#define DCACHE_SIZE (16 * 1024)
+
+#define LOG_ICACHE_SIZE 14
+#define LOG_DCACHE_SIZE 14
+
+#else
+#error "Please define the cache configuration of the processor"
+#endif
+
+// Macros to define where declared code is actually compiled
+
+#ifdef __PPC405_C__
+#define IF__PPC405_CORE_C__(x) x
+#define UNLESS__PPC405_CORE_C__(x)
+#else
+#define IF__PPC405_CORE_C__(x)
+#define UNLESS__PPC405_CORE_C__(x) x
+#endif
+
+#ifdef __PPC405_IRQ_CORE_C__
+#define IF__PPC405_IRQ_CORE_C__(x) x
+#define UNLESS__PPC405_IRQ_CORE_C__(x)
+#else
+#define IF__PPC405_IRQ_CORE_C__(x)
+#define UNLESS__PPC405_IRQ_CORE_C__(x) x
+#endif
+
+
+#ifdef CHIP_PGP
+#include "pgp.h"
+#endif
+
+#include "ppc32.h"
+#include "ppc405_dcr.h"
+#include "ppc405_spr.h"
+#include "ppc405_msr.h"
+#include "ppc405_irq.h"
+#include "ppc405_cache.h"
+
+#if PPC405_MMU_SUPPORT
+
+#include "ppc405_mmu.h"
+
+#ifndef PPC405_IR_SUPPORT
+#define PPC405_IR_SUPPORT 1
+#endif
+
+#ifndef PPC405_DR_SUPPORT
+#define PPC405_DR_SUPPORT 1
+#endif
+
+#define PPC405_RELOCATION_MODE \
+ ((PPC405_IR_SUPPORT * MSR_IR) | (PPC405_DR_SUPPORT * MSR_DR))
+
+#ifndef __ASSEMBLER__
+void*
+memcpy_real(void* dest, const void* src, size_t n);
+#endif
+
+#else /* PPC405_MMU_SUPPORT */
+
+#define PPC405_RELOCATION_MODE 0
+
+#ifndef __ASSEMBLER__
+static inline void*
+memcpy_real(void* dest, const void* src, size_t n)
+{
+ memcpy(dest, src, n);
+ icache_invalidate_all();
+ return dest;
+}
+#endif
+
+#endif /* PPC405_MMU_SUPPORT */
+
+/// By default, in MMU mode free space is read/write only, just like normal
+/// data. Saome applications may need to execute from free space however, and
+/// can override this default.
+
+#ifndef EXECUTABLE_FREE_SPACE
+#define EXECUTABLE_FREE_SPACE 0
+#endif
+
+#include "ppc405_context.h"
+
+// PPC405 stack characteristics for SSX. The pre-pattern pattern is selected
+// to be easily recognizable yet be an illegal instruction.
+
+#define SSX_STACK_DIRECTION -1
+#define SSX_STACK_PRE_DECREMENT 1
+#define SSX_STACK_ALIGNMENT 8
+#define SSX_STACK_TYPE unsigned int
+#define SSX_STACK_PATTERN 0x03abcdef
+
+// Kernel data structure offsets for assembler code
+
+#define SSX_THREAD_OFFSET_SAVED_STACK_POINTER 0
+#define SSX_THREAD_OFFSET_STACK_LIMIT 4
+#define SSX_THREAD_OFFSET_STACK_BASE 8
+
+// SSX boot loader panic codes
+
+#define PPC405_BOOT_CCR0_MODIFY_FAILED 0x00405000
+#define PPC405_BOOT_VECTORS_NOT_ALIGNED 0x00405001
+
+// Interrupt handler panic codes
+
+#define PPC405_DEFAULT_IRQ_HANDLER 0x00405010
+#define PPC405_DEFAULT_SPECIAL_HANDLER 0x00405011
+#define PPC405_PHANTOM_INTERRUPT 0x00405012
+#define PPC405_PROGRAM_HALT 0x00405013
+
+
+// Exception handling invariant panic codes
+
+#define PPC405_IRQ_FULL_EXIT_INVARIANT 0x00405020
+#define PPC405_IRQ_FAST2FULL_INVARIANT 0x00405021
+
+
+// API error panic codes
+
+#define PPC405_CACHE_ALIGNMENT 0x00405030
+
+// Application-overrideable definitions
+
+/// The default thread machine context has MSR[CE], MSR[EE] and MSR[ME] set,
+/// and all other MSR bits cleared.
+///
+/// The default definition allows critical, non-critical and machine check
+/// exceptions. Debug interrupts are not enabled by default. This definition
+/// can be overriden by the application. If MMU protection is enabled then
+/// the IR/DR bits are also modeably set.
+
+#ifndef SSX_THREAD_MACHINE_CONTEXT_DEFAULT
+#define SSX_THREAD_MACHINE_CONTEXT_DEFAULT \
+ (MSR_CE | MSR_EE | MSR_ME | PPC405_RELOCATION_MODE)
+#endif
+
+
+#ifndef __ASSEMBLER__
+
+/// The SSX kernel default panic sequence for C code
+///
+/// By default a kernel panic from C code forces external debug mode then
+/// generates a \c trap instruction followed by the error code. The \a code
+/// argument must be a compile-time integer immediate. This definition can be
+/// overriden by the application.
+///
+/// The OCC may be running in internal debug mode for various reasons, and
+/// TRAP-ing in internal debug mode would lead to an infinite loop in the
+/// default Program Interrupt handler - which itself would be a TRAP (since
+/// that's the default implementation of SSX_PANIC(). Therefore by default
+/// the panic is implemented as a special code sequence that forces the core
+/// into external debug mode before issuing a TRAP which will halt the core.
+/// To preserve the state we use the special global variables
+/// __ssx_panic_save_dbcr0 and __ssx_panic_save_r3 defined in ppc405_core.c.
+/// The original value of DBCR0 is destroyed, but can be recovered from the
+/// global. In the end %r3 is reloaded from temporary storage and will be
+/// unchanged at the halt.
+///
+/// Note that there is a small chance that an interrupt will fire and
+/// interrupt this code before the halt - in general there is no way around
+/// this.
+///
+/// The Simics environment does not model Debug events correctly. It executes
+/// the TRAP as an illegal instruction and branches to the Program Interrupt
+/// handler, destroying the contents of SRR0 and SRR1. Therefore we always
+/// insert a special Simics magic breakpoint (which is an effective NOP)
+/// before the hardware trap. The special-form magic instruction is
+/// recognized by our Simics support scripts which decode the kernel state and
+/// try to help the user interpret what happened based on the TRAP code.
+
+#ifndef SSX_PANIC
+
+#define SSX_PANIC(code) \
+ do { \
+ barrier(); \
+ asm volatile ("stw %r3, __ssx_panic_save_r3@sda21(0)"); \
+ asm volatile ("mfdbcr0 %r3"); \
+ asm volatile ("stw %r3, __ssx_panic_save_dbcr0@sda21(0)"); \
+ asm volatile ("lwz %r3, __ssx_panic_dbcr0@sda21(0)"); \
+ asm volatile ("mtdbcr0 %r3"); \
+ asm volatile ("isync"); \
+ asm volatile ("lwz %r3, __ssx_panic_save_r3@sda21(0)"); \
+ asm volatile ("rlwimi 1,1,0,0,0"); \
+ asm volatile ("trap"); \
+ asm volatile (".long %0" : : "i" (code)); \
+ } while (0)
+
+// These variables are used by the SSX_PANIC() definition above to save and
+// restore state. __ssx_panic_dbcr0 is the value loaded into DBCR0 to force
+// traps to halt the OCC and freeze the timers.
+
+#ifdef __PPC405_CORE_C__
+uint32_t __ssx_panic_save_r3;
+uint32_t __ssx_panic_save_dbcr0;
+uint32_t __ssx_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT;
+#endif
+
+#endif // SSX_PANIC
+
+/// This is the Simics 'magic breakpoint' instruction.
+///
+/// Note that this form does not include a memory barrier, as doing so might
+/// change the semantics of the program. There is an alternative form
+/// SIMICS_MAGIC_BREAKPOINT_BARRIER that does include a barrier.
+
+#define SIMICS_MAGIC_BREAKPOINT asm volatile ("rlwimi 0,0,0,0,0")
+
+/// This is the Simics 'magic breakpoint' instruction including a memory
+/// barrier.
+///
+/// Note that the memory barrier guarantees that all variables held in
+/// registers are flushed to memory before the breakpoint, however this might
+/// change the semantics of the program. There is an alternative form of
+/// SIMICS_MAGIC_BREAKPOINT that does not include a barrier. If the idea is
+/// to use the breakpoint for tracing code execution in Simics, the barrier
+/// form may be preferred so that variable values will be visible in memory.
+
+#define SIMICS_MAGIC_BREAKPOINT_BARRIER \
+ asm volatile ("rlwimi 0,0,0,0,0" : : : "memory")
+
+
+#else // __ASSEMBLER__
+
+/// This is the Simics 'magic breakpoint' instruction. An assembler macro
+/// form is also provided for use within macros.
+
+#define SIMICS_MAGIC_BREAKPOINT rlwimi 0,0,0,0,0
+
+ .macro _simics_magic_breakpoint
+ rlwimi 0,0,0,0,0
+ .endm
+
+/// The SSX kernel panic default panic sequence for assembler code
+///
+/// By default a kernel panic from assembler forces external debug mode then
+/// generates a \c trap instruction followed by the error code. The \a code
+/// argument must be a compile-time integer immediate. This definition can be
+/// overriden by the application.
+///
+/// See the comments for the non-ASSEMBLER version for further details. Note
+/// that the code space reserved for exception handlers is only 8
+/// instructions, so in the assembler context we don't save DBCR0 as doing so
+/// would require 10.
+
+#ifndef SSX_PANIC
+
+#define SSX_PANIC(code) _ssx_panic code
+
+ .macro _ssx_panic, code
+ _stwsd %r3, __ssx_panic_save_r3
+ _lwzsd %r3, __ssx_panic_dbcr0
+ mtdbcr0 %r3
+ isync
+ _lwzsd %r3, __ssx_panic_save_r3
+ rlwimi 1,1,0,0,0
+ trap
+ .long \code
+ .endm
+
+#endif // SSX_PANIC
+
+#endif // __ASSEMBLER__
+
+
+// Application-overridible definitions for the SSX boot loader
+
+/// In order to enable the default kernel panic (a trap) to halt the machine,
+/// the Debug Control Register 0 (DBCR0) is initialized in externel debug
+/// mode, with the Trap Debug Event enabled so that the trap will not cause a
+/// program exception, and the FT bit set so that the timers will freeze.
+/// This definition can be overridden by the application.
+///
+/// NB: It is expected that a reliable production system will redefine all of
+/// the 'panic' macros and the default DBCR0 setup.
+
+#ifndef PPC405_DBCR0_INITIAL
+#define PPC405_DBCR0_INITIAL (DBCR0_EDM | DBCR0_TDE | DBCR0_FT)
+#endif
+
+/// This is the value of the MSR used during initialization. Once SSX threads
+/// are started (with \c ssx_start_threads()), all machine contexts derive
+/// from the default thread context \c
+/// SSX_THREAD_MACHINE_CONTEXT_DEFAULT. This definition can be overriden by
+/// the application.
+///
+/// The default is to enable machine checks only.
+
+#ifndef PPC405_MSR_INITIAL
+#define PPC405_MSR_INITIAL MSR_ME
+#endif
+
+/// This is the initial value of Cache Control Register 0 (CCR0). This
+/// definition can be overridden by the application.
+///
+/// The default sets the CCR0 to give priority to DCU and ICU operations. The
+/// user should consider setting other options in this register that affect
+/// performance, e.g., ICU prefetching. Other options can be set at run time
+/// with the API \c ppc405_ccr0_modify().
+
+#ifndef PPC405_CCR0_INITIAL
+#define PPC405_CCR0_INITIAL (CCR0_DPP1 | CCR0_IPP0 | CCR0_IPP1)
+#endif
+
+/// The \a argc argument passed to \c main(). This definition can be overriden
+/// by the application.
+
+#ifndef PPC405_ARGC_INITIAL
+#define PPC405_ARGC_INITIAL 0
+#endif
+
+/// The \a argv argument passed to \c main(). This definition can be overriden
+/// by the application.
+
+#ifndef PPC405_ARGV_INITIAL
+#define PPC405_ARGV_INITIAL 0
+#endif
+
+/// Optionally trap the reset for the debugger, which means that the PPC405
+/// will simply spin at the symbol \c __reset_trap after a chip reset. Set R0
+/// to a non-zero value in the debugger to continue execution. This definition
+/// can be overriden by the application.
+
+#ifndef PPC405_RESET_TRAP
+#define PPC405_RESET_TRAP 0
+#endif
+
+#ifndef __ASSEMBLER__
+
+/// The PPC405 SSX machine context is simply the MSR, a 32-bit integer.
+
+typedef uint32_t SsxMachineContext;
+
+/// Disable interrupts at the given priority level, and return the current
+/// context.
+///
+/// \param priority The interrupt priority level to disable, either \c
+/// SSX_NONCRITICAL, \c SSX_CRITICAL or \c SSX_SUPERCRITICAL. For best
+/// efficiency, the \a priority parameter should be a manifest constant.
+///
+/// \param context A pointer to an SsxMachineContext, this is the context that
+/// existed before interrupts were disabled. Typically this
+/// context is restored at the end of a critical section.
+///
+/// The PPC405 supports a 'super-critical' context in which every possible
+/// maskable exception is disabled.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_INTERRUPT An illegal priority was specified.
+
+UNLESS__PPC405_CORE_C__(extern)
+inline int
+ssx_interrupt_disable(int priority, SsxMachineContext *context)
+{
+ *context = mfmsr();
+
+ if (priority == SSX_NONCRITICAL) {
+
+ wrteei(0);
+
+ } else if (priority == SSX_CRITICAL) {
+
+ mtmsr(*context & ~(MSR_EE | MSR_CE));
+
+ } else if (priority == SSX_SUPERCRITICAL) {
+
+ mtmsr(*context & ~(MSR_APE | MSR_WE | MSR_CE | MSR_EE | MSR_ME |
+ MSR_DWE | MSR_DE));
+
+ } else if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR(SSX_INVALID_ARGUMENT_INTERRUPT);
+ }
+
+ return SSX_OK;
+}
+
+
+/// Set the machine context.
+///
+/// \param context A pointer to an SsxMachineContext
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_CONTEXT_SET A null pointer was provided as
+/// the \a context argument or an illegal machine context was specified.
+
+UNLESS__PPC405_CORE_C__(extern)
+inline int
+ssx_machine_context_set(SsxMachineContext *context)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(context == 0, SSX_INVALID_ARGUMENT_CONTEXT_SET);
+ }
+
+ mtmsr(*context);
+
+ return SSX_OK;
+}
+
+
+/// Get the machine context.
+///
+/// \param context A pointer to an SsxMachineContext.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_CONTEXT_GET A null pointer was provided as
+/// the \a context argument.
+
+UNLESS__PPC405_CORE_C__(extern)
+inline int
+ssx_machine_context_get(SsxMachineContext *context)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(context == 0, SSX_INVALID_ARGUMENT_CONTEXT_GET);
+ }
+
+ *context = mfmsr();
+
+ return SSX_OK;
+}
+
+
+/// The SSX kernel thread context switch - PPC405 uses the system call
+/// exception.
+
+#define __ssx_switch() asm volatile ("sc")
+
+
+/// In the PowerPC EABI all initial stack frames require 8 bytes - the 4 bytes
+/// at the SP are zeroed to indicate the end of the stack, and the 4 bytes
+/// behind the SP are for the initial subroutine's LR.
+
+static inline void
+__ssx_stack_create_initial_frame(SsxAddress *stack, size_t *size) \
+{
+ *stack -= 8;
+ *size -= 8;
+ *((SSX_STACK_TYPE *)(*stack)) = 0;
+}
+
+
+/// The SSX Kernel Context for PPC405
+///
+/// The SSX portable kernel does not define how the kernel keeps track of
+/// whether SSX is running, interrupt levels, and other debug
+/// information. Instead it defines an API that the port must provide to the
+/// portable kernel.
+///
+/// In the PPC405 port, the kernel context is maintained in USPRG0. This
+/// 32-bit value is treated as 5 distinct fields as indicated in the structure
+/// definition. For certain tests it's also helpful to look at the two
+/// interrupt counters as a single 0/non-0 field.
+
+typedef union {
+
+ uint32_t value;
+
+ struct {
+
+ /// The critical interrupt nesting level. If this field is non-zero,
+ /// then interrupt priority and preemption rules guarantee that a
+ /// critical interrupt handler is running, and the \c irq field will
+ /// contain the SsxIrqId of the currently active critical interrupt.
+ unsigned critical_interrupts : 8;
+
+ /// The non-critical interrupt nesting level. If this field is
+ /// non-zero and the \c critical_interrupts field is 0, then interrupt
+ /// priority and preemption rules guarantee that a noncritical
+ /// interrupt handler is running, and the \c irq field will contain
+ /// the SsxIrqId of the currently active noncritical interrupt.
+ unsigned noncritical_interrupts : 8;
+
+ /// The SsxIrqId of the currently running (or last run) handler. If
+ /// either of the interrupt nesting levels are non-0, then this is the
+ /// SsxIrqId of the IRQ that is currently executing.
+ unsigned irq : 8;
+
+ /// A flag indicating that SSX is in thread mode after a call of
+ /// ssx_start_threads().
+ unsigned thread_mode : 1;
+
+ /// The priority of the currently running thread. In an interrupt
+ /// context, this is the priority of the thread that was interrupted.
+ unsigned thread_priority : 7;
+
+ } fields;
+
+ struct {
+
+ /// Used as a 0/non-0 flag for interrupt context.
+ unsigned interrupt_context : 16;
+
+ /// Ignore
+ unsigned ignore : 16;
+
+ } merged_fields;
+
+} __SsxKernelContext;
+
+
+// These APIs are provided to the SSX portable kernel by the port.
+
+/// SSX threads have been started by a call of ssx_start_threads().
+
+#define __ssx_kernel_mode_thread() \
+ ({ \
+ __SsxKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_USPRG0); \
+ __ctx.fields.thread_mode;})
+
+
+/// SSX is executing in a thread context (not an interrupt handler).
+
+#define __ssx_kernel_context_thread() \
+ ({ \
+ __SsxKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_USPRG0); \
+ __ctx.fields.thread_mode && !__ctx.merged_fields.interrupt_context;})
+
+
+/// SSX is executing an interrupt handler of any priority.
+
+#define __ssx_kernel_context_any_interrupt() \
+ ({ \
+ __SsxKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_USPRG0); \
+ __ctx.merged_fields.interrupt_context;})
+
+
+/// SSX is executing a critical interrupt handler.
+
+#define __ssx_kernel_context_critical_interrupt() \
+ ({ \
+ __SsxKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_USPRG0); \
+ __ctx.fields.critical_interrupts;})
+
+
+/// SSX is executing a non-critical interrupt handler.
+
+#define __ssx_kernel_context_noncritical_interrupt() \
+ ({ \
+ __SsxKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_USPRG0); \
+ __ctx.fields.noncritical_interrupts && \
+ !__ctx.fields.critical_interrupts;})
+
+
+/// Return the noncritical interrupt nesting level
+
+#define __ssx_noncritical_level() \
+ ({ \
+ __SsxKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_USPRG0); \
+ __ctx.fields.noncritical_interrupts; })
+
+
+/// Return the critical interrupt nesting level
+
+#define __ssx_critical_level() \
+ ({ \
+ __SsxKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_USPRG0); \
+ __ctx.fields.critical_interrupts; })
+
+
+// SSX requires the port to define the type SsxThreadQueue, which is a
+// priority queue (where 0 is the highest priority). This queue must be able
+// to handle SSX_THREADS + 1 priorities (the last for the idle thread) The
+// port must also define methods for clearing, insertion, deletion and min
+// (with assumed legal priorities). The min operation returns SSX_THREADS if
+// the queue is empty (or a queue could be initialized with that entry always
+// present - SSX code never tries to delete the idle thread from a thread
+// queue).
+//
+// These queues are used both for the run queue and the pending queue
+// associated with every semaphore.
+//
+// On PPC405 with 32 threads (implied), this is a job for a uint32_t and
+// cntlzw().
+
+static inline void
+__ssx_thread_queue_clear(volatile SsxThreadQueue *queue)
+{
+ *queue = 0;
+}
+
+static inline void
+__ssx_thread_queue_insert(volatile SsxThreadQueue *queue, SsxThreadPriority priority)
+{
+ *queue |= (0x80000000u >> priority);
+}
+
+static inline void
+__ssx_thread_queue_delete(volatile SsxThreadQueue *queue, SsxThreadPriority priority)
+{
+ *queue &= ~(0x80000000u >> priority);
+}
+
+static inline SsxThreadPriority
+__ssx_thread_queue_min(volatile SsxThreadQueue *queue)
+{
+ return cntlzw(*queue);
+}
+
+static inline int
+__ssx_thread_queue_member(volatile SsxThreadQueue *queue, SsxThreadPriority priority)
+{
+ return ((*queue >> (31 - priority)) & 1);
+}
+
+static inline void
+__ssx_thread_queue_union(volatile SsxThreadQueue *queue0,
+ volatile SsxThreadQueue *queue1)
+{
+ *queue0 |= *queue1;
+}
+
+static inline int
+__ssx_thread_queue_count(volatile SsxThreadQueue* queue)
+{
+ return __builtin_popcount(*queue);
+}
+
+
+/// This macro is used to call __ssx_start_threads() using the kernel stack,
+/// in a SSX_NONCRITICAL critical section.
+
+#define __ssx_call_ssx_start_threads() \
+ do { \
+ SsxMachineContext ctx; \
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); \
+ asm volatile ("mr 1, %0; mtlr %1; blrl" : : \
+ "r" (__ssx_noncritical_stack), \
+ "r" (__ssx_start_threads)); \
+ SSX_PANIC(SSX_START_THREADS_RETURNED); \
+ } while (0)
+
+
+#endif /* __ASSEMBLER__ */
+
+/// The __SsxKernelContext 'thread_mode' bit as a flag
+
+#define PPC405_THREAD_MODE 0x80
+
+
+#ifndef __ASSEMBLER__
+
+/// Code breakpoints for PPC405
+///
+/// This macro inserts a special PPC405-only breakpoint into the object code
+/// at the place the macro invocation appears. This facility is designed for
+/// VBU/VPO procedure debugging. This type of breakpoint may not be required
+/// on real hardware as we will then have the full power of RISCWatch, gdb,
+/// etc. Once inserted into the code, code breakpoints can be enabled or
+/// disabled by manipulating the global variable _code_breakpoint_enable,
+/// which defaults to 1.
+///
+/// The code breakpoint is implemented as a setup routine and a teardown
+/// routine, executed in an SSX_CRITICAL critical section. The actual break
+/// will occur at the address of the call of the teardown routine, in the
+/// context of the calling code. The setup routine saves the state of DBCR0/1
+/// and IAC4, then programs the DBCR for an external debug mode, IAC4
+/// breakpoint. The IAC4 breakpoint is set for the address of the call of the
+/// teardown routine. The teardown routine simply restores the state of the
+/// debug registers that existed before the code breakpoint.
+///
+/// Once hit, restarting from the break requires clearing IAC4 and restarting
+/// instructions:
+///
+/// \code
+///
+/// putspr pu.occ iac4 0
+/// cipinstruct pu.occ start
+///
+/// \endcode
+///
+/// The above restart processes is also encapsulated as the p8_tclEcmd
+/// procedure 'unbreakOcc'.
+///
+/// In code built for the Simics environment (i.e., with the preprocessor
+/// macro SIMICS_ENVIRONMENT=1) this macro simply expands into
+/// SIMICS_MAGIC_BREAKPOINT, and simulation can be continued from the break as
+/// normal. This Simics magic breakpoint is also under the control of
+/// _code_breakpoint_enable. In code not built with SIMICS_ENVIROMENT=1, note
+/// that the CODE_BREAKPOINT is ignored by the Simics PPC405 model as it does
+/// not model debug events.
+
+#if defined(SIMICS_ENVIRONMENT) && (SIMICS_ENVIRONMENT != 0)
+#define CODE_BREAKPOINT \
+ do { \
+ if (_code_breakpoint_enable) { \
+ SIMICS_MAGIC_BREAKPOINT; \
+ } \
+ } while (0)
+#else
+#define CODE_BREAKPOINT \
+ do { \
+ if (_code_breakpoint_enable) { \
+ SsxMachineContext __ctx; \
+ ssx_critical_section_enter(SSX_CRITICAL, &__ctx); \
+ _code_breakpoint_prologue(); \
+ _code_breakpoint_epilogue(); \
+ ssx_critical_section_exit(&__ctx); \
+ } \
+ } while (0)
+#endif
+
+void
+_code_breakpoint_prologue(void);
+
+void
+_code_breakpoint_epilogue(void);
+
+extern uint32_t _code_breakpoint_enable;
+
+#endif // __ASSEMBLER__
+
+
+#endif /* __PPC405_H__ */
diff --git a/src/ssx/ppc405/ppc405_boot.S b/src/ssx/ppc405/ppc405_boot.S
new file mode 100755
index 0000000..1f4a4f9
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_boot.S
@@ -0,0 +1,242 @@
+// $Id: ppc405_boot.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_boot.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_boot.S
+/// \brief SSX bootloader for PPC405
+
+ .nolist
+#include "ssx.h"
+ .list
+
+### SSX Bootloader for PPC405
+###
+### This is the basic restart initialization of the processor.
+### Parts of this code were derived from examples in the IBM OSopen
+### OpenBIOS for the 405GP written by James Burke.
+###
+### This code does not really do very much, just makes sure that there will
+### be a reasonable state in the machine when control is turned over to
+### the SSX application. Any core setup that requires SPR access will be done
+### here. All other setup is expected to take place in system-specific
+### routines.
+###
+### From the PowerPC 405-S Embedded Core User's manual:
+###
+### "In general, the contents of SPRs are undefined after a core, chip or
+### system reset. Some SPRs retain the content they had before the reset
+### occurred."
+###
+### Registers fully reset:
+### DBCR1 - Data compares disabled
+### DCCR - Data cache disabled
+### DCWR - Data cache write-through disabled
+### ESR - No exception syndromes
+### ICCR - Instruction cache disabled
+### MSR - No exceptions/interrupts are allowed
+### SLER - Storage is big-endian
+### SU0R - Storage is uncompressed
+###
+### Registers partially reset:
+### CCR0 = 0x00700000 - Sets ICU and DCU PLB Priority
+### DBCR0 [EDM] = 0 - External debug mode disabled
+### [RST] = 0 - No reset action
+### DBSR [MRR] = x - x indicates most recent reset action
+### SGR = 0xffffffff - Storage is guarded
+### TCR [WRC] = 0 - Watchdog timer reset disabled
+### TSR [WRS] = x - x is a copy of TCR[WRC] Watchdog reset status
+### [PIS] = x - undefined
+
+ .global_function __ssx_boot
+ .global __reset_trap
+
+__ssx_boot:
+
+ ## Trap the reset for the debugger. Set R0 to a non-zero value in the
+ ## debugger to continue.
+
+ .if PPC405_RESET_TRAP
+ li %r0, 0
+__reset_trap:
+ cmpwi %r0, 0
+ beq __reset_trap
+ .endif
+
+ ## First the real-mode memory parameters are set up as configured
+ ## for the system and/or application. There are no defaults for these 6
+ ## configuration options - they must always be supplied.
+
+ _liwa %r3, PPC405_ICCR_INITIAL
+ mticcr %r3
+ _liwa %r3, PPC405_DCCR_INITIAL
+ mtdccr %r3
+ _liwa %r3, PPC405_DCWR_INITIAL
+ mtdcwr %r3
+ _liwa %r3, PPC405_SGR_INITIAL
+ mtsgr %r3
+ _liwa %r3, PPC405_SU0R_INITIAL
+ mtsu0r %r3
+ _liwa %r3, PPC405_SLER_INITIAL
+ mtsler %r3
+
+ ## Next the I and D caches are invalidated.
+ ## NB: The only reason we can do a BL at this point is because we
+ ## know that these routines do not try to save the LR on the stack.
+
+ bl icache_invalidate_all
+ bl dcache_invalidate_all
+
+ ## Set up PowerPC EABI constant registers. These registers are never
+ ## again touched by the SSX kernel or the application (if they are
+ ## behaving).
+
+ _liw %r2, _SDA2_BASE_
+ _liw %r13, _SDA_BASE_
+
+ ## Clear the timer control register. This masks all timer interrupts.
+
+ mttcr %r3
+
+ ## Several options are available for dynamic memory ...
+ ## If none of these options are defined, then it is assumed that
+ ## the memory area is already set up.
+
+#if defined(SSX_RUN_FROM_DCACHE)
+
+ ## SSX can run from the DCACHE. In order for this to work, the
+ ## the linker script must set the symbol __ssx_ram_vma to the
+ ## beginning of a 128MB memory region marked as cacheable in the
+ ## application-defined PPC405_DCCR_INITIAL.
+ ##
+ ## Note that there is typically no backing store for this data. Before
+ ## going further, all data cache blocks must be allocated with 'dcbz'.
+ ## Should a subsequent programming error cause the eviction of
+ ## a dirty line, a machine check exception will result.
+
+ _liw %r3, __ssx_ram_vma
+ _liwa %r4, DCACHE_LINES
+ mtctr %r4
+
+dcbz_loop:
+ dcbz %r0, %r3
+ addi %r3, %r3, CACHE_LINE_SIZE
+ bdnz dcbz_loop
+
+#elif defined(SSX_RUN_FROM_MEMORY)
+
+ ## Nothing to do here...
+
+#else
+
+#error "One of SSX_RUN_FROM_DCACHE or SSX_RUN_FROM_MEMORY must be defined"
+
+#endif /* SSX_RUN_FROM_xxx */
+
+ ## The stack pointer is initialized for use by the remainder of the
+ ## initialization, including the application main(). The linker script
+ ## defines the initial stack area.
+ ##
+ ## Stacks are always 8-byte aligned. A '0' is stored at the
+ ## stack pointer to indicate the end of the stack chain. Stack frames
+ ## always consist of at least 8 bytes - the backchain pointer and the
+ ## slot above the backchain pointer for the callee's LR.
+
+ _liw %r1, _SSX_INITIAL_STACK
+ _clrfield %r1, %r1, 3, 29 # 8-byte align
+ li %r3, 0
+ stwu %r3, -8(%r1)
+
+ ## USPRG0 (__SsxKernelContext) is initialized to 0
+ ## indicating that the SSX kernel is not in thread mode, and no
+ ## interrupts are active.
+
+ li %r3, 0
+ mtusprg0 %r3
+
+ ## Set up the initial value of Debug Control Register 0. Note that
+ ## DBCR1 is specified to be cleared at reset. VBU simulation requested
+ ## an option that this register not be modified so that they could
+ ## completely control debug behavior from reset of the 405.
+
+#ifndef NO_INIT_DBCR0
+ _liwa %r3, PPC405_DBCR0_INITIAL
+ mtdbcr0 %r3
+#endif
+
+ ## The exception vector prefix is set - it must be 64KB aligned.
+
+ _liw %r3, __vectors
+ andi. %r4, %r3, 0xffff
+ beq 1f
+ _ssx_panic PPC405_BOOT_VECTORS_NOT_ALIGNED
+1:
+ mtevpr %r3
+ isync
+
+ ## The MSR to be used during the rest of intialization is
+ ## established. This MSR should NOT enable critical or non-critical
+ ## interrupts, but could enable machine check exceptions.
+
+ _liwa %r3, PPC405_MSR_INITIAL
+ mtmsr %r3
+ isync
+
+ ## Initialize the CCR0. If it returns non-zero, panic.
+
+ _liwa %r4, PPC405_CCR0_INITIAL # bits_to_set
+ not %r3, %r4 # bits_to_clear
+ bl ppc405_ccr0_modify
+ cmpwi %r3, 0
+ beq 1f
+ _ssx_panic PPC405_BOOT_CCR0_MODIFY_FAILED
+1:
+
+#ifdef SSX_BOOT_FROM_ROM
+
+ ## NB: I don't think the old linker scripts were necessarily the most
+ ## optimal. We need to revisit this if we actually do ROM boots in SSX
+ ## Version 2. Not sure the comments are correct.
+
+ ## Data is copied from the initial ROM image to the RAM. The
+ ## address symbols are defined in the linker command file. The linker
+ ## will have zeroed this area in the ROM image.
+
+ liw %r3, __ssx_ram_lma - 4 # src
+ liw %r4, __ssx_ram_vma - 4 # dest
+ liw %r5, __ssx_ram_size
+ liw %r6, 2
+ srw %r5, %r5, %r6 # Number of word transfers
+ mtctr %r5
+
+copy_loop:
+ lwzu %r5, 4(%r3)
+ stwu %r5, 4(%r4)
+ bdnz copy_loop
+
+#endif /* SSX_BOOT_FROM_ROM */
+
+
+ ## Call the system setup code.
+
+ bl __ppc405_system_setup
+
+ ## Call the application. If for some reason we return from
+ ## the call of the application we call an alternate entry point of the
+ ## idle thread.
+ ##
+ ## An initial argc/argv can be passed into main(). argc is expected to
+ ## be a 32-bit immediate integer, and argv is expected to be a 32-bit
+ ## absolute or relocatable expression.
+
+ _liwa %r3, PPC405_ARGC_INITIAL
+ _liw %r4, PPC405_ARGV_INITIAL
+ bl __ssx_main
+
+ b __ssx_idle_thread_from_bootloader
+
+ .epilogue __ssx_boot
+
diff --git a/src/ssx/ppc405/ppc405_breakpoint.S b/src/ssx/ppc405/ppc405_breakpoint.S
new file mode 100644
index 0000000..3adbd13
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_breakpoint.S
@@ -0,0 +1,103 @@
+// $Id: ppc405_breakpoint.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_breakpoint.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file breakpoint.S
+/// \brief Implementation of code breakpoints for VBU/VPO
+///
+/// The operation of these short assembler routines is introduced as part of
+/// the documentation for the CODE_BREAKPOINT macro.
+
+ .nolist
+#include "ssx.h"
+ .list
+
+#ifdef DOXYGEN_ONLY
+void _code_breakpoint_prologue(void);
+#endif
+
+/// \cond
+
+ _sprinstrs iac4, SPRN_IAC4
+
+ .global_function _code_breakpoint_prologue
+_code_breakpoint_prologue:
+
+ // Save the DBCR0/1 and IAC4
+
+ mfdbcr0 %r3
+ mfdbcr1 %r4
+ mfiac4 %r5
+ _stwsd %r3, _saved_dbcr0
+ _stwsd %r4, _saved_dbcr1
+ _stwsd %r5, _saved_iac4
+
+ // Set IAC4 to the contents of LR, which will cause a break in the
+ // caller's context.
+
+ mflr %r3
+ mtiac4 %r3
+
+ // Reprogram to external debug mode, trigger on IAC4 compare, freeze
+ // timers. Clear data compare setup for good measure.
+
+ _liwa %r3, DBCR0_EDM | DBCR0_IA4 | DBCR0_FT
+ mtdbcr0 %r3
+ _liwa %r3, 0
+ mtdbcr1 %r3
+
+ isync
+ blr
+
+ .epilogue _code_breakpoint_prologue
+
+ .section .sdata
+ .balign 4
+
+ .global _code_breakpoint_enable
+_code_breakpoint_enable:
+ .long 1
+
+_saved_dbcr0:
+ .long 0
+_saved_dbcr1:
+ .long 0
+_saved_iac4:
+ .long 0
+
+/// \endcond
+
+
+#ifdef DOXYGEN_ONLY
+void _code_breakpoint_epilogue(void);
+#endif
+
+/// \cond
+
+ .global_function _code_breakpoint_epilogue
+_code_breakpoint_epilogue:
+
+ // Restore the DBCR0/1 and IAC4
+
+ _lwzsd %r3, _saved_dbcr0
+ _lwzsd %r4, _saved_dbcr1
+ _lwzsd %r5, _saved_iac4
+ mtdbcr0 %r3
+ mtdbcr1 %r4
+ mtiac4 %r5
+
+ // Clear IA4 status
+
+ _liwa %r3, DBSR_IA4
+ mtdbsr %r3
+
+ isync
+ blr
+
+ .epilogue _code_breakpoint_epilogue
+
+/// \endcond
diff --git a/src/ssx/ppc405/ppc405_cache.h b/src/ssx/ppc405/ppc405_cache.h
new file mode 100755
index 0000000..02bd4f5
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_cache.h
@@ -0,0 +1,113 @@
+#ifndef __PPC405_CACHE_H__
+#define __PPC405_CACHE_H__
+
+// $Id: ppc405_cache.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_cache.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_cache.h
+/// \brief PowerPC 405 cache management header for SSX
+///
+/// The data cache flush/invalidate macros defined here create a compiler
+/// memory barrier that will cause GCC to flush/invalidate all memory data
+/// held in registers before the macro.
+
+#ifndef __ASSEMBLER__
+
+/// Determine cache-alignment of a pointer or byte-count
+#define cache_aligned(x) \
+ ((((unsigned long)(x)) & (POW2_32(LOG_CACHE_LINE_SIZE) - 1)) == 0)
+
+/// Cache-align a pointer or byte count. If the 'direction' is <= 0 then we
+/// round down, else round up.
+#define cache_align(x, direction) \
+ ({ \
+ unsigned long __x = (unsigned long)(x); \
+ unsigned long __r; \
+ if ((direction) <= 0) { \
+ __r = __x & ~(((unsigned long)CACHE_LINE_SIZE) - 1); \
+ } else { \
+ if (__x % CACHE_LINE_SIZE) { \
+ __r = __x + (CACHE_LINE_SIZE - (__x % CACHE_LINE_SIZE)); \
+ } \
+ } \
+ (void *)__r; \
+ })
+
+/// Data Cache Block Flush
+#define dcbf(p) asm volatile ("dcbf 0, %0" : : "r" (p) : "memory")
+
+/// Data Cache Block Touch
+#define dcbt(p) asm volatile ("dcbt 0, %0" : : "r" (p) : "memory")
+
+/// Data Cache Block Invalidate (Privileged)
+#define dcbi(p) asm volatile ("dcbi 0, %0" : : "r" (p) : "memory")
+
+/// Instruction Cache Block Invalidate
+#define icbi(p) asm volatile ("icbi 0, %0" : : "r" (p) : "memory")
+
+/// Instruction Cache Block Touch
+#define icbt(p) asm volatile ("icbt 0, %0" : : "r" (p) : "memory")
+
+void
+icache_invalidate_all(void);
+
+void
+dcache_invalidate_all(void);
+
+void
+dcache_flush_all(void);
+
+void
+dcache_invalidate(void *p, size_t bytes);
+
+void
+dcache_flush(void *p, size_t bytes);
+
+/// Invalidate a line in the D-cache
+///
+/// \param p An address withing the cache line to be invalidated.
+///
+/// The dcache_invalidate_line() API is used to invalidate a single cache line
+/// containing the address \a p. Note that invalidation is a destructive
+/// operation that may cause the loss of information. It is the caller's
+/// responsibility to insure that no useful data is inadverdently invalidated.
+/// D-cache invalidation is more-or-less a no-op for data either not in the
+/// cache or marked as non-cacheable.
+///
+/// This API always issues a sync() after the invalidation.
+
+static inline void
+dcache_invalidate_line(void *p)
+{
+ dcbi(p);
+ sync();
+}
+
+/// Flush and invalidate a line from the D-cache
+///
+/// \param p An address within the cache line to be flushed.
+///
+/// The dcache_flush_line() API can be used as a shortcut to flush and
+/// invalidate a single cache line. Note that flushing is not a destructive
+/// operation in the sense that no information is lost, however the caller
+/// must make sure that the entirity of the data to be flushed is contained in
+/// the line that includes the address \a p. D-cache flush is more-or-less a
+/// no-op for data either not in the cache or marked as non-cacheable.
+///
+/// This API always issues a sync() after the flush.
+
+static inline void
+dcache_flush_line(void *p)
+{
+ dcbf(p);
+ sync();
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPC405_CAHE_H__ */
diff --git a/src/ssx/ppc405/ppc405_cache_core.c b/src/ssx/ppc405/ppc405_cache_core.c
new file mode 100755
index 0000000..a03f5e2
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_cache_core.c
@@ -0,0 +1,115 @@
+// $Id: ppc405_cache_core.c,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_cache_core.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_cache_core.c
+/// \brief Core cache management routines required of any PPC405 configuration
+/// of SSX that interacts with DMA devices using cacheable memory.
+///
+/// The entry points in this file are considered 'core' routines that will
+/// always be present at runtime in any SSX application.
+///
+/// \todo The compiler generates wierd assembly language for these cache
+/// management APIs - probably due to the "volatile" asm - it may be best to
+/// recode them directly in assembler.
+
+#include "ssx.h"
+
+/// Invalidate a range of addresses from the D-cache
+///
+/// \param p A pointer to the memory area to be invalidated.
+///
+/// \param bytes The size (in bytes) of the area to invalidate.
+///
+/// The dcache_invalidate() API is used to invalidate an arbitrary range of
+/// memory in the cache. Note that invalidation is a destructive operation
+/// that may cause the loss of information. This API will invalidate all
+/// cache lines from the line containing the address \a p, to the line
+/// containing the address \a p + \a size - 1. (If \a size == 0 this call is
+/// a NOP.) It is the caller's responsibility to insure that no useful data is
+/// inadverdently invalidated. D-cache invalidation is more-or-less a no-op
+/// for data either not in the cache or marked as non-cacheable.
+///
+/// This API always issues a sync() after the invalidation, even in the event
+/// of \a size == 0.
+///
+/// \note For invalidating small blocks of data where some alignmment
+/// constraints are known it may be more efficient to use
+/// dcache_invalidate_line() rather than this API.
+
+void
+dcache_invalidate(void *p, size_t bytes)
+{
+ size_t lines;
+
+ if (bytes != 0) {
+ lines = 1;
+ bytes -=
+ MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)),
+ bytes);
+ lines += bytes / CACHE_LINE_SIZE;
+ if (!cache_aligned(bytes)) {
+ lines++;
+ }
+ while (lines--) {
+ dcbi(p);
+ p += CACHE_LINE_SIZE;
+ }
+ }
+ sync();
+}
+
+
+/// Flush and invalidate a range of addresses from the D-cache
+///
+/// \param p A pointer to a memory area to be invalidated.
+///
+/// \param bytes The size (in bytes) of the area to invalidate.
+///
+/// The dcache_flush() API is used to flush and invalidate an arbitrary range
+/// of memory from the D-cache. Note that flushing is not a destructive
+/// operation in the sense that no information is lost. This API will flush
+/// and invalidate all cache lines from the line containing the address \a p,
+/// to the line containing the address \a p + \a size - 1. (If \a size == 0
+/// this call is a NOP.) D-cache flush is more-or-less a no-op for data
+/// either not in the cache or marked as non-cacheable.
+///
+/// This API always issues a sync() after the flush, even in the event of \a
+/// size == 0.
+///
+/// \note For flushing small blocks of data where some alignmment constraints
+/// are known it may be more efficient to use dcache_flush_line() rather than
+/// this API.
+
+
+void
+dcache_flush(void *p, size_t bytes)
+{
+ size_t lines;
+
+ if (bytes != 0) {
+ lines = 1;
+ bytes -=
+ MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)),
+ bytes);
+ lines += bytes / CACHE_LINE_SIZE;
+ if (!cache_aligned(bytes)) {
+ lines++;
+ }
+ while (lines--) {
+ dcbf(p);
+ p += CACHE_LINE_SIZE;
+ }
+ }
+ sync();
+}
+
+
+
+
+
+
diff --git a/src/ssx/ppc405/ppc405_cache_init.S b/src/ssx/ppc405/ppc405_cache_init.S
new file mode 100755
index 0000000..c4bed0e
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_cache_init.S
@@ -0,0 +1,314 @@
+// $Id: ppc405_cache_init.S,v 1.3 2014/06/26 12:59:35 cmolsen Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_cache_init.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_cache_init.S
+/// \brief PPC405-specific procedures required for cache initialization
+///
+/// The routines in this file are not part of SSX per se, but are included
+/// with SSX because they are used during initialialization and boot.
+///
+/// These are 'initialization' routines used by the SSX bootloader and other
+/// application initialization code and may not be needed after
+/// boot/initialization of the SSX application.
+///
+/// See the documents './doc/PowerPC 405-S Core Errata' and './doc/PowerPC
+/// 405-S Core Errata Impact on PGP OCC Firmware' for information on the
+/// CPU_xxx errata.
+
+ .nolist
+#include "ssx.h"
+#include "ppc405_context.h"
+ .list
+
+/// \fn void icache_invalidate_all()
+/// \brief Invalidate the entire I-Cache
+///
+/// In the PPC405 a single instruction invalidates the entire I-Cache,
+/// therefore this routine need not be executed from a critical section.
+///
+///
+/// This API always issues an isync() after the invalidation.
+#ifdef DOXYGEN_ONLY
+void icache_invalidate_all();
+#endif
+/// \cond
+
+ .global_function icache_invalidate_all
+
+icache_invalidate_all:
+
+ _ssx_critical_section_enter SSX_SUPERCRITICAL, %r5, %r6
+
+ # Workaround for CPU_121: The iccci instruction may errantly
+ # cause a Data TLB exception. Workaround avoids this erratum by
+ # temporarily disabling data address translation.
+
+ mfmsr %r3
+ andi. %r4, %r3, 0xffef
+ mtmsr %r4
+ isync
+
+ ## On the 405, iccci invalidates the entire I-Cache.
+
+ iccci %r0,%r0
+
+ # Restore MSR/DR bit
+ mtmsr %r3
+ isync
+
+ _ssx_critical_section_exit %r5
+
+ blr
+
+ .epilogue icache_invalidate_all
+
+/// \endcond
+
+
+/// \fn void dcache_invalidate_all()
+/// \brief Invalidate the entire D-Cache
+///
+/// This API operates in an SSX_SUPERCRITICAL critical section. This API always
+/// issues a sync() after the invalidation.
+#ifdef DOXYGEN_ONLY
+void dcache_invalidate_all();
+#endif
+/// \cond
+
+ .global_function dcache_invalidate_all
+
+dcache_invalidate_all:
+
+ _ssx_critical_section_enter SSX_SUPERCRITICAL, %r5, %r6
+
+ ## We loop through addresses 0 ... (DCACHE_SIZE / DCACHE_WAYS) - 1
+ ## invalidating the D-Cache. The dccci instruction on the 405
+ ## invalidates both ways.
+
+ li %r3, 0
+ _liwa %r4, (DCACHE_LINES / DCACHE_WAYS)
+ mtctr %r4
+
+1:
+ dccci %r0, %r3
+ addi %r3, %r3, CACHE_LINE_SIZE
+ bdnz 1b
+
+ sync
+
+ _ssx_critical_section_exit %r5
+
+ blr
+
+ .epilogue dcache_invalidate_all
+
+/// \endcond
+
+
+#ifndef USE_GENERIC_DCACHE_FLUSH_ALL
+#define USE_GENERIC_DCACHE_FLUSH_ALL 1
+#endif
+
+/// \fn void dcache_flush_all()
+/// \brief Flush the entire D-Cache (Generic)
+///
+/// This API is necessary whenever it is required to change data cacheability
+/// after boot. The D-cache is scanned, and any lines present in the cache are
+/// flushed. This API operates in an SSX_SUPERCRITICAL critical section. This
+/// API always issues a sync() after the flush.
+///
+/// This is a generic implementation that should work on all PPC405
+/// systems. If something is known about the memory configuration then SSX
+/// ports can implement better/more efficient flush-all algorithms.
+///
+/// This API runs with data translation disabled. This is necessary for
+/// correctness, and also obviates the need to check whether a cache entry is
+/// valid before flushing the entry.
+///
+/// This API is currently a NOP in Simics simulations which complain that the
+/// dcread instruction is implemented as a NOP.
+#ifdef DOXYGEN_ONLY
+void dcache_flush_all();
+#endif
+/// \cond
+
+#if USE_GENERIC_DCACHE_FLUSH_ALL
+
+ .global_function dcache_flush_all
+dcache_flush_all:
+
+#if !SIMICS_ENVIRONMENT
+
+ ## %r3 used as temp throughout
+ ## %r4 holds the original MSR throughout
+ ## %r8 used as a temp throughout
+ ## %r9 used as a temp throughout
+
+ _ssx_critical_section_enter SSX_SUPERCRITICAL, %r4, %r3
+
+ mfmsr %r3
+ _clrbit %r3, %r3, MSR_DR_BIT
+ mtmsr %r3
+ isync
+
+ ## %r5 counts the congruence class address
+ ## CTR counts the number of congruence classes
+
+ li %r5, 0
+ _liwa %r9, (DCACHE_LINES / DCACHE_WAYS)
+ mtctr %r9
+
+ ## %r6 has the CCR0 value for reading DCACHE tag on way A
+ ## %r7 has the CCR0 value for reading DCACHE tag on way B
+ ## %r8 has the cache tag mask
+
+ mfccr0 %r6
+ _liwa %r9, 0x00000011
+ andc %r6, %r6, %r9 # Clear DCREAD control bits
+ ori %r6, %r6, 0x0010
+ ori %r7, %r6, 0x0001
+ _liwa %r8, DCACHE_TAG_MASK # Cache tag mask
+
+dflush_loop:
+
+ ## Way A
+
+ mtccr0 %r6 # Set CCR0 for DCREAD
+ dcread %r9, %r0, %r5
+ and %r9, %r9, %r8 # Mask out cache tag
+ or %r9, %r9, %r5 # OR in the congruence class address
+ dcbf %r0, %r9 # Flush the line
+
+ ## Way B
+
+ mtccr0 %r7 # Set CCR0 for DCREAD
+ dcread %r9, %r0, %r5
+ and %r9, %r9, %r8 # Mask out cache tag
+ or %r9, %r9, %r5 # OR in the congruence class address
+ dcbf %r0, %r9 # Flush the line
+
+ addi %r5, %r5, CACHE_LINE_SIZE
+ bdnz dflush_loop
+
+ ## Restore the MSR and return
+
+ _ssx_critical_section_exit %r4
+
+#endif // SIMICS_ENVIRONMENT
+
+ blr
+
+ .epilogue dcache_flush_all
+
+#endif // USE_GENERIC_DCACHE_FLUSH_ALL
+
+/// \endcond
+
+/// \fn int ppc405_ccr0_modify(uint32_t bits_to_clear, uint32_t bits_to_set)
+/// \brief A special code sequence to modify the Cache Control Register 0 (CCR0)
+///
+/// \param bits_to_clear A positive mask of bits in CCR0 that will be cleared
+/// by this call.
+///
+/// \param bits_to_set A positive mask of bits in CCR0 that will be set by
+/// this call.
+///
+/// The code that implements this procedure \e must be in I-cacheable memory.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_PPC405_CACHE The code implementing the API
+/// is not cacheable.
+///
+#ifdef DOXYGEN_ONLY
+int ppc405_ccr0_modify(uint32_t bits_to_clear, uint32_t bits_to_set);
+#endif
+/// \cond
+
+ ## The implementation is based on an example from the 405GP manual.
+
+ .global_function ppc405_ccr0_modify
+
+ppc405_ccr0_modify:
+
+ ## %r3 is parameter bits_to_clear
+ ## %r4 is parameter bits_to_set
+ ## %r5 will hold the original MSR
+ ## %r6 will hold the address of the update code.
+ ## %r7, %r8, %r9 are used for computation.
+
+ ## Disable external and critical interrupts
+
+ mfmsr %r5
+ _liwa %r6, (MSR_CE | MSR_EE)
+ andc %r6, %r5, %r6
+ mtmsr %r6 # Interrupts disabled
+ sync
+
+ .if SSX_ERROR_CHECK_API
+
+ ## Check for cacheability of the code sequence
+
+ _liw %r6, ccr0_modify_doit
+ extrwi %r7, %r6, 5, 0 # Upper 5 bits are address range
+ mficcr %r8
+ _liwa %r9, 0x80000000
+ srw %r9, %r9, %r7 # %r9 holds bit to check in %r8
+ and. %r9, %r9, %r8
+ bne ccr0_modify_continue
+
+ ## Whoops! Code not cacheable; restore MSR and return error code.
+
+ .if SSX_ERROR_PANIC
+
+ _ssx_panic SSX_ILLEGAL_CONTEXT_PPC405_CACHE
+
+ .else
+
+ _liwa %r3, -SSX_ILLEGAL_CONTEXT_PPC405_CACHE
+ mtmsr %r5
+ isync
+
+ .endif
+
+ blr
+
+ .endif
+
+ ## Touch the code sequence into the I-Cache and do it.
+
+ccr0_modify_continue:
+ icbt %r0, %r6
+ isync # Erratum CPU_208
+ b ccr0_modify_doit
+
+ ## The ICBT is repeated to insure that the code is really in
+ ## the cache. The bits are cleared, set, updated and we exit.
+
+ .cache_align # Must be cache-line aligned
+ccr0_modify_doit:
+ icbt %r0, %r6
+ isync
+ mfccr0 %r7
+ andc %r7, %r7, %r3 # Clear some bits
+ or %r7, %r7, %r4 # Set some bits
+ mtccr0 %r7
+ isync
+
+ ## Restore MSR and return 0.
+
+ li %r3, 0
+ mtmsr %r5
+ isync
+ blr
+
+ .epilogue ppc405_ccr0_modify
+
+/// \endcond
diff --git a/src/ssx/ppc405/ppc405_context.h b/src/ssx/ppc405/ppc405_context.h
new file mode 100755
index 0000000..3019358
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_context.h
@@ -0,0 +1,594 @@
+#ifndef __PPC405_CONTEXT_H__
+#define __PPC405_CONTEXT_H__
+
+// $Id: ppc405_context.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_context.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_context.h
+/// \brief PPC405 Machine and Thread context for SSX
+
+/// \page ppc405_machine_context PPC405 Assembler Macros for SSX Machine
+/// Context (Critical Sections)
+///
+/// \section _ssx_enter_critical \b _ssx_critical_section_enter/exit
+///
+/// These macro encapsulates the instruction sequences required to enter and
+/// exit critical sections, along with the machine context save for later
+/// exiting the critical section.
+///
+/// \arg \c priority Either \c SSX_CRITICAL, \c SSX_NON_CRITICAL or
+/// SSX_SUPERCRITICAL (for \c ssx_critical_section_enter).
+///
+/// \arg \c ctxreg A register that will hold (holds) the machine context (MSR)
+/// prior to entering the critical section (to be restored) for \c
+/// _ssx_critical_section_enter (\c _ssx_critical_section_exit).
+///
+/// \arg \c scrreg A scratch register required for the computation of
+/// \c _ssx_critical_section_enter.
+///
+/// Forms:
+///
+/// \b _ssx_critical_section_enter \a priority, \a ctxreg, \a scrreg - Enter a
+/// critical section \n
+/// \b _ssx_critical_section_exit \a ctxreg - Exit a critical section
+
+#ifdef __ASSEMBLER__
+
+ .set _msr_ee_bit, MSR_EE_BIT
+ .set _msr_ce_bit, MSR_CE_BIT
+
+ .macro _ssx_critical_section_enter priority, ctxreg, scrreg
+ mfmsr \ctxreg
+ .if ((\priority) == SSX_CRITICAL)
+ _clrbit \scrreg, \ctxreg, _msr_ee_bit
+ _clrbit \scrreg, \scrreg, _msr_ce_bit
+ mtmsr \scrreg
+ .elseif ((\priority) == SSX_SUPERCRITICAL)
+ _liwa \scrreg, (MSR_APE | MSR_WE | MSR_CE | MSR_EE | MSR_ME | MSR_DWE | MSR_DE)
+ andc \scrreg, \ctxreg, \scrreg
+ mtmsr \scrreg
+ .elseif ((\priority) == SSX_NONCRITICAL)
+ wrteei 0
+ .else
+ .error "'priority' was not one of SSX_CRITICAL, SSX_NONCRITICAL or SSX_SUPERCRITICAL"
+ .endif
+ isync
+ .endm
+
+ .macro _ssx_critical_section_exit ctxreg
+ mtmsr \ctxreg
+ isync
+ .endm
+
+// ****************************************************************************
+// SSX context save/restore macros for 32-bit Embedded PowerPC
+// ****************************************************************************
+
+// All stack frames are 8-byte aligned in conformance with the EABI. SSX
+// never saves or restores GPR2 or GPR13. GPR13 is constant in (E)ABI
+// applications - the base of the read-write small data area. GPR2 is
+// system-reserved in ABI applications, and is the base for read-only small data
+// in EABI applications.
+
+// A fair amount of complexity is involved in handling the non-critical and
+// critical interrupt levels, and the emphasis on performance of fast-mode
+// interrupt handlers. Several different approaches and philosophies could
+// have been implemented - this is only one. In this implementation
+// critical/non-critical interrupt levels are treated more or less the same,
+// and the interrupt priority is just that - a kind of preemption priority.
+// Critical interrupt handling does have a little less overhead because it
+// does not have a thread scheduling step at the end.
+
+// A full context save takes place in 3 or 4 steps. Thread switches always do
+// steps 1, 2 and 3.
+// 1. The fast context that is always saved in response to every interrupt;
+// 1a. The optional save/update of the kernel context for interrupts.
+// 2. The (volatile - fast) context that is saved if an interrupt handler
+// switches from fast-mode to full-mode.
+// 3. The non-volatile context that is saved when a thread is switched out.
+
+// USPRG0 holds the __SsxKernelContext structure (defined in ppc405.h) that
+// represents the current kernel context. The layout is as follows:
+//
+// Bits Meaning
+// ==============
+// 0:7 The critical interrupt count
+// 8:15 The non-critical interrupt count
+// 16:23 The IRQ currently being processed
+// 24 The 'thread_mode' flag
+// 25:31 The thread priority of the running thread
+//
+// When SSX is initialized USPRG0 is initialized to 0. When thread-mode is
+// entered (by ssx_start_threads()) bit 24 is set to 1. In order to support
+// PgP/OCC firmware, once initialized (with ssx_initialize()) SSX can simply
+// handle interrupts, reverting back to the non-thread-mode idle loop when
+// there's nothing to do.
+//
+// Note that it would require a serious error for the interrupt counts to ever
+// equal or exceed 2**8 as this would imply runaway reentrancy and stack
+// overflow. In fact it is most likely an error if an interrupt handler is
+// ever re-entered while active.
+
+// Registers SRR2 and SRR3 are always saved in IRQ context because
+// __ssx_irq_fast2full must save the (volatile - fast) context to provide
+// working registers before it can look at USPRG0 to determine critical
+// vs. non-critical context. However, when restoring a non-critical interrupt
+// or thread these registers need not be restored. SRR2 and SRR3 are never
+// saved or restored for thread context switches, because threads always
+// operate at noncritical level.
+
+// When MMU protection is enabled, relocation/protection is re-established
+// immediately upon entry to the interrupt handler, before any memory
+// operations (load/store) take place. This requires using SPRG0 and SPGR4
+// for temporary storage for noncritical/critical handlers respectively in
+// accordance with the SSX conventions for SPRGn usage by fast-mode
+// interrupts.
+
+ ## ------------------------------------------------------------
+ ## Unused registers for embedded PowerPC
+ ## ------------------------------------------------------------
+
+ ## Registers GPR2 and GPR13 are never saved or restored. In ABI and
+ ## EABI applications these registers are constant.
+
+ .set UNUSED_GPR2, 0x2 # Dedicated; EABI read-only small data area
+ .set UNUSED_GPR13, 0xd # Dedicated; (E)ABI read-write small data area
+
+ ## ------------------------------------------------------------
+ ## Flags for context push/pop
+ ## ------------------------------------------------------------
+
+ .set SSX_THREAD_CONTEXT, 0
+ .set SSX_IRQ_CONTEXT, 1
+
+ ## ------------------------------------------------------------
+ ## The SSX fast context layout for Embedded PowerPC
+ ## ------------------------------------------------------------
+
+ .set SSX_FAST_CTX_GPR1, 0x00 # Dedicated; Stack pointer
+ .set SSX_FAST_CTX_HANDLER_LR, 0x04 # Slot for handler to store LR
+ .set SSX_FAST_CTX_GPR3, 0x08 # Volatile; Parameter; Return Value
+ .set SSX_FAST_CTX_GPR4, 0x0c # Volatile; Parameter
+ .set SSX_FAST_CTX_GPR5, 0x10 # Volatile; Parameter
+ .set SSX_FAST_CTX_GPR6, 0x14 # Volatile; Parameter
+ .set SSX_FAST_CTX_GPR7, 0x18 # Volatile; Parameter
+ .set SSX_FAST_CTX_CR, 0x1c # Condition register
+ .set SSX_FAST_CTX_LR, 0x20 # Link register SPRN 0x008
+ .set SSX_FAST_CTX_KERNEL_CTX, 0x24 # Saved __SsxKernelContext for IRQ
+
+ .set SSX_FAST_CTX_SIZE, 0x28 # Must be 8-byte aligned
+
+ ## ------------------------------------------------------------
+ ## The SSX (volatile - fast) context layout for Embedded PowerPC
+ ## ------------------------------------------------------------
+
+ .set SSX_VOL_FAST_CTX_GPR1, 0x00 # Dedicated; Stack pointer
+ .set SSX_VOL_FAST_CTX_HANDLER_LR, 0x04 # Slot for handler to store LR
+ .set SSX_VOL_FAST_CTX_GPR0, 0x08 # Volatile; Language specific
+ .set SSX_VOL_FAST_CTX_GPR8, 0x0c # Volatile; Parameter
+ .set SSX_VOL_FAST_CTX_GPR9, 0x10 # Volatile; Parameter
+ .set SSX_VOL_FAST_CTX_GPR10, 0x14 # Volatile; Parameter
+ .set SSX_VOL_FAST_CTX_GPR11, 0x18 # Volatile
+ .set SSX_VOL_FAST_CTX_GPR12, 0x1c # Volatile
+ .set SSX_VOL_FAST_CTX_XER, 0x20 # Fixed-point exception register SPRN 0x001
+ .set SSX_VOL_FAST_CTX_CTR, 0x24 # Count register SPRN 0x009
+ .set SSX_VOL_FAST_CTX_SRR0, 0x28 # Save/restore register 0 SPRN 0x01a
+ .set SSX_VOL_FAST_CTX_SRR1, 0x2c # Save/restore register 1 SPRN 0x01b
+ .set SSX_VOL_FAST_CTX_SRR2, 0x30 # Save/restore register 2 SPRN 0x3de
+ .set SSX_VOL_FAST_CTX_SRR3, 0x34 # Save/restore register 3 SPRN 0x3df
+
+ .set SSX_VOL_FAST_CTX_SIZE, 0x38 # Must be 8-byte aligned
+
+ ## ------------------------------------------------------------
+ ## The SSX non-volatile context layout for Embedded PowerPC
+ ## ------------------------------------------------------------
+
+ ## The 'preferred form' for stmw is for the LSB of R31 to fall into the
+ ## end of a 16-byte aligned block.
+
+ .set SSX_NON_VOL_CTX_GPR1, 0x0 # Dedicated; Stack Pointer
+ .set SSX_NON_VOL_CTX_HANDLER_LR, 0x4 # Slot for handler to store LR
+ .set SSX_NON_VOL_CTX_GPR14, 0x8 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR15, 0xc # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR16, 0x10 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR17, 0x14 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR18, 0x18 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR19, 0x1c # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR20, 0x20 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR21, 0x24 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR22, 0x28 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR23, 0x2c # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR24, 0x30 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR25, 0x34 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR26, 0x38 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR27, 0x3c # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR28, 0x40 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR29, 0x44 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR30, 0x48 # Non-volatile
+ .set SSX_NON_VOL_CTX_GPR31, 0x4c # Non-volatile
+
+ .set SSX_NON_VOL_CTX_SIZE, 0x50 # Must be 8-byte aligned
+
+ ## ------------------------------------------------------------
+ ## Save/restore the fast context
+ ##
+ ## 11 Instructions, 8 Loads/Stores : If MMU is disabled
+ ## 17 Instructions, 8 Loads/Stores : If MMU is enabled
+ ## ------------------------------------------------------------
+ ##
+ ## Without MMU support, an EIEIO is always executed at the entry point
+ ## to gauarantee that all memory operations (especially MMIO
+ ## operations) have completed prior to execution of the interrupt
+ ## handler.
+ ##
+ ## If MMU support is enabled, address translation is re-established
+ ## immediately at the entry of each interrupt, prior to performing any
+ ## loads or stores. SSX currently only supports using the MMU for
+ ## protection, not for address translation. Therfore it is 'legal'
+ ## to change translation modes a with an MTMSR followed by an
+ ## ISYNC. This is much simpler then the complex instruction sequence
+ ## that would be required if we had to set up RFI/RFCI sequences to
+ ## change the execution context at this point.
+ ##
+ ## Note that since we are not really doing address translation, it
+ ## would also be in keeping with the 'fast interrupt' idea to defer
+ ## reenabling translation (protection) until the fast-to-full sequence
+ ## was executed for full-mode interrupts, and run fast-mode interrupts
+ ## unprotected. However here we chose to run all interrupts with MMU
+ ## protection.
+ ##
+ ## Unfortunately the simple MTMSR;ISYNC sequence exposes a serious bug
+ ## in the 405-S core that causes the stack-pointer store instruction
+ ## to generate a seemingly random, *real-mode* address in certain cases
+ ## when this instruction in a noncritical interrupt prologue is
+ ## interrupted by a critical interrupt. This bug is described in
+ ## HW239446. The workaround is to follow the ISYNC sith a SYNC - which
+ ## eliminates the problem for reasons still unknown. On the bright side
+ ## this SYNC might also serve the same purpose as the EIEIO in the
+ ## non-MMU case, guaranteeing that all MMIO has completed prior to the
+ ## interrupt handler. However without the initial EIEIO we still
+ ## experience failures, so this seemingly redundant instruction also
+ ## remains in place. This requirement is assumed to be related to the
+ ## HW239446 issue.
+
+ .macro _ssx_fast_ctx_push, critical
+
+ .if !PPC405_MMU_SUPPORT
+
+ eieio
+
+ .elseif \critical
+
+ eieio # HW239446?
+ mtsprg4 %r3
+ mfmsr %r3
+ ori %r3, %r3, PPC405_RELOCATION_MODE
+ mtmsr %r3
+ isync
+#ifndef ALLOW_HW239446
+ sync # HW239446!
+#endif
+ mfsprg4 %r3
+
+ .else
+
+ eieio # HW239446?
+ mtsprg0 %r3
+ mfmsr %r3
+ ori %r3, %r3, PPC405_RELOCATION_MODE
+ mtmsr %r3
+ isync
+#ifndef ALLOW_HW239446
+ sync # HW239446!
+#endif
+ mfsprg0 %r3
+
+ .endif
+
+ stwu %r1, -SSX_FAST_CTX_SIZE(%r1) # May be corrupted w/o HW239446
+
+ stw %r3, SSX_FAST_CTX_GPR3(%r1)
+ stw %r4, SSX_FAST_CTX_GPR4(%r1)
+ stw %r5, SSX_FAST_CTX_GPR5(%r1)
+ stw %r6, SSX_FAST_CTX_GPR6(%r1)
+ stw %r7, SSX_FAST_CTX_GPR7(%r1)
+
+ mfcr %r3
+ mflr %r4
+
+ stw %r3, SSX_FAST_CTX_CR(%r1)
+ stw %r4, SSX_FAST_CTX_LR(%r1)
+
+ .endm
+
+
+ .macro _ssx_fast_ctx_pop
+
+ lwz %r3, SSX_FAST_CTX_CR(%r1)
+ lwz %r4, SSX_FAST_CTX_LR(%r1)
+
+ mtcr %r3
+ mtlr %r4
+
+ lwz %r3, SSX_FAST_CTX_GPR3(%r1)
+ lwz %r4, SSX_FAST_CTX_GPR4(%r1)
+ lwz %r5, SSX_FAST_CTX_GPR5(%r1)
+ lwz %r6, SSX_FAST_CTX_GPR6(%r1)
+ lwz %r7, SSX_FAST_CTX_GPR7(%r1)
+
+ lwz %r1, 0(%r1)
+
+ .endm
+
+ ## ------------------------------------------------------------
+ ## Save/update the kernel context in response to an interrupt. This is
+ ## not part of the fast context save because for external interupts the
+ ## IRQ is not determined until later.
+ ## ------------------------------------------------------------
+
+ ## The kernel context is saved, then updated with the currently active
+ ## IRQ in bits 16:23. The correct interrupt count is incremented and
+ ## the context is returned to USPRG0.
+
+ .macro _save_update_kernel_context critical, irqreg, ctxreg
+
+ .if \critical
+ SSX_TRACE_CRITICAL_IRQ_ENTRY \irqreg, \ctxreg
+ .else
+ SSX_TRACE_NONCRITICAL_IRQ_ENTRY \irqreg, \ctxreg
+ .endif
+
+ mfusprg0 \ctxreg
+ stw \ctxreg, SSX_FAST_CTX_KERNEL_CTX(%r1)
+ rlwimi \ctxreg, \irqreg, 8, 16, 23
+ .if \critical
+ addis \ctxreg, \ctxreg, 0x0100
+ .else
+ addis \ctxreg, \ctxreg, 0x0001
+ .endif
+ mtusprg0 \ctxreg
+
+ .endm
+
+ ## ------------------------------------------------------------
+ ## Fast-mode context pop and RF(C)I. This is only used by
+ ## interrupt handlers - the thread context switch has its own
+ ## code to handle updating USPRG0 for thread mode.
+ ## ------------------------------------------------------------
+
+ .macro _ssx_fast_ctx_pop_exit critical
+
+ .if SSX_KERNEL_TRACE_ENABLE
+ .if \critical
+ bl __ssx_trace_critical_irq_exit
+ .else
+ bl __ssx_trace_noncritical_irq_exit
+ .endif
+ .endif
+
+ lwz %r3, SSX_FAST_CTX_KERNEL_CTX(%r1)
+ mtusprg0 %r3
+ _ssx_fast_ctx_pop
+ .if \critical
+ rfci
+ .else
+ rfi
+ .endif
+
+ .endm
+
+ ## ------------------------------------------------------------
+ ## Save/restore the (volatile - fast) context
+ ##
+ ## Thread - 15 Instructions, 11 Loads/Stores
+ ## IRQ - 19(15) Instructions, 13(11) Loads/Stores
+ ## ------------------------------------------------------------
+
+ .macro _ssx_vol_fast_ctx_push, irq_context, critical=1
+
+ stwu %r1, -SSX_VOL_FAST_CTX_SIZE(%r1)
+
+ stw %r0, SSX_VOL_FAST_CTX_GPR0(%r1)
+ stw %r8, SSX_VOL_FAST_CTX_GPR8(%r1)
+ stw %r9, SSX_VOL_FAST_CTX_GPR9(%r1)
+ stw %r10, SSX_VOL_FAST_CTX_GPR10(%r1)
+ stw %r11, SSX_VOL_FAST_CTX_GPR11(%r1)
+ stw %r12, SSX_VOL_FAST_CTX_GPR12(%r1)
+
+ mfxer %r8
+ mfctr %r9
+ mfsrr0 %r10
+ mfsrr1 %r11
+
+ stw %r8, SSX_VOL_FAST_CTX_XER(%r1)
+ stw %r9, SSX_VOL_FAST_CTX_CTR(%r1)
+ stw %r10, SSX_VOL_FAST_CTX_SRR0(%r1)
+ stw %r11, SSX_VOL_FAST_CTX_SRR1(%r1)
+
+ .if (\irq_context & \critical)
+ mfsrr2 %r8
+ mfsrr3 %r9
+
+ stw %r8, SSX_VOL_FAST_CTX_SRR2(%r1)
+ stw %r9, SSX_VOL_FAST_CTX_SRR3(%r1)
+ .endif
+
+ .endm
+
+
+ .macro _ssx_vol_fast_ctx_pop, irq_context, critical
+
+ .if (\irq_context & \critical)
+ lwz %r8, SSX_VOL_FAST_CTX_SRR2(%r1)
+ lwz %r9, SSX_VOL_FAST_CTX_SRR3(%r1)
+
+ mtsrr2 %r8
+ mtsrr3 %r9
+ .endif
+
+ lwz %r8, SSX_VOL_FAST_CTX_XER(%r1)
+ lwz %r9, SSX_VOL_FAST_CTX_CTR(%r1)
+ lwz %r10, SSX_VOL_FAST_CTX_SRR0(%r1)
+ lwz %r11, SSX_VOL_FAST_CTX_SRR1(%r1)
+
+ mtxer %r8
+ mtctr %r9
+ mtsrr0 %r10
+ mtsrr1 %r11
+
+ lwz %r0, SSX_VOL_FAST_CTX_GPR0(%r1)
+ lwz %r8, SSX_VOL_FAST_CTX_GPR8(%r1)
+ lwz %r9, SSX_VOL_FAST_CTX_GPR9(%r1)
+ lwz %r10, SSX_VOL_FAST_CTX_GPR10(%r1)
+ lwz %r11, SSX_VOL_FAST_CTX_GPR11(%r1)
+ lwz %r12, SSX_VOL_FAST_CTX_GPR12(%r1)
+
+ lwz %r1, 0(%r1)
+
+ .endm
+
+ ## ------------------------------------------------------------
+ ## Save/restore the non-volatile context on the stack
+ ##
+ ## 2 Instructions, 19 Loads/Stores
+ ## ------------------------------------------------------------
+
+ .macro _ssx_non_vol_ctx_push
+
+ stwu %r1, -SSX_NON_VOL_CTX_SIZE(%r1)
+ stmw %r14, SSX_NON_VOL_CTX_GPR14(%r1)
+
+ .endm
+
+
+ .macro _ssx_non_vol_ctx_pop
+
+ lmw %r14, SSX_NON_VOL_CTX_GPR14(%r1)
+ lwz %r1, 0(%r1)
+
+ .endm
+
+#else /* __ASSEMBLER__ */
+
+/// SSX thread context layout as a C structure.
+///
+/// This is the structure of the stack area pointed to by
+/// thread->saved_stack_pointer when a thread is fully context-switched out.
+
+typedef struct {
+
+ uint32_t r1_nv;
+ uint32_t link_nv;
+ uint32_t r14;
+ uint32_t r15;
+ uint32_t r16;
+ uint32_t r17;
+ uint32_t r18;
+ uint32_t r19;
+ uint32_t r20;
+ uint32_t r21;
+ uint32_t r22;
+ uint32_t r23;
+ uint32_t r24;
+ uint32_t r25;
+ uint32_t r26;
+ uint32_t r27;
+ uint32_t r28;
+ uint32_t r29;
+ uint32_t r30;
+ uint32_t r31;
+ uint32_t r1_vf;
+ uint32_t link_vf;
+ uint32_t r0;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t r12;
+ uint32_t xer;
+ uint32_t ctr;
+ uint32_t srr0;
+ uint32_t srr1;
+ uint32_t srr2;
+ uint32_t srr3;
+ uint32_t r1;
+ uint32_t link_fast;
+ uint32_t r3;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t cr;
+ uint32_t lr;
+ uint32_t usprg0;
+
+} SsxThreadContext;
+
+
+/// SSX thread context of an interrupted thread (full-mode handler)
+///
+/// When a thread is interrupted by a full-mode interrupt handler, this is the
+/// layout of the stack area pointed to by either __ssx_saved_sp_noncritical
+/// or __ssx_saved_sp_critical.
+
+typedef struct {
+
+ uint32_t r1_vf;
+ uint32_t link_vf;
+ uint32_t r0;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t r12;
+ uint32_t xer;
+ uint32_t ctr;
+ uint32_t srr0;
+ uint32_t srr1;
+ uint32_t srr2;
+ uint32_t srr3;
+ uint32_t r1;
+ uint32_t link_fast;
+ uint32_t r3;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t cr;
+ uint32_t lr;
+ uint32_t usprg0;
+
+} SsxThreadContextFullIrq;
+
+
+/// SSX thread context of an interrupted thread (fast-mode handler)
+///
+/// When a thread is interrupted by a fast-mode interrupt handler, this is the
+/// layout of the stack area pointed to by R1 - unless the fast-mode interrupt
+/// handler extends the stack.
+
+typedef struct {
+
+ uint32_t r1;
+ uint32_t link_fast;
+ uint32_t r3;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t cr;
+ uint32_t lr;
+ uint32_t usprg0;
+
+} SsxThreadContextFastIrq;
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPC405_CONTEXT_H__ */
+
+
diff --git a/src/ssx/ppc405/ppc405_core.c b/src/ssx/ppc405/ppc405_core.c
new file mode 100755
index 0000000..5df0967
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_core.c
@@ -0,0 +1,183 @@
+// $Id: ppc405_core.c,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_core.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_core.c
+/// \brief The final bits of SSX runtime code required to complete the PPC405
+/// port.
+///
+/// The entry points in this file are considered 'core' routines that will
+/// always be present during runtime in any SSX application.
+
+#define __PPC405_CORE_C__
+
+#include "ssx.h"
+
+/// Get the 64-bit timebase following the PowerPC protocol
+///
+/// Note that the only way to guarantee that the value returned is the value
+/// \e right \e now is to call this API from a critical section.
+
+SsxTimebase
+ssx_timebase_get(void)
+{
+ Uint64 tb;
+ uint32_t high;
+
+ do {
+ tb.word[0] = mftbu();
+ tb.word[1] = mftb();
+ high = mftbu();
+ } while (high != tb.word[0]);
+
+ return tb.value;
+}
+
+
+/// Set the 64-bit timebase in an SSX_CRITICAL critical section
+///
+/// It is assumed that the caller knows what they are doing; e.g., is aware of
+/// what may happen when time warps as a result of this call.
+
+void
+ssx_timebase_set(SsxTimebase timebase)
+{
+ SsxMachineContext ctx;
+ Uint64 tb;
+
+ tb.value = timebase;
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ mttbl(0);
+ mttbu(tb.word[0]);
+ mttbl(tb.word[1]);
+
+ ssx_critical_section_exit(&ctx);
+}
+
+
+/// Enable interrupt preemption
+///
+/// This API can only be called from an interrupt context. Threads will
+/// always be preempted by interrupts unless they explicitly disable
+/// interrupts with the \c ssx_interrupt_disable() API. It is legal to call
+/// this API redundantly.
+///
+/// Be careful when enabling interrupt handler preemption that the interrupt
+/// being handled does not/can not trigger again, as this could rapidly lead
+/// to stack overflows.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_ILLEGAL_CONTEXT The API call was not made from an interrupt
+/// context.
+
+int
+ssx_interrupt_preemption_enable()
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT();
+ }
+
+ if (__ssx_kernel_context_noncritical_interrupt()) {
+ wrteei(1);
+ } else {
+ or_msr(MSR_CE);
+ }
+
+ return SSX_OK;
+}
+
+
+/// Disable interrupt preemption
+///
+/// This API can only be called from an interrupt context. Threads will
+/// always be preempted by interrupts unless they explicitly disable
+/// interrupts with the \c ssx_interrupt_disable() API. It is legal to call
+/// this API redundantly.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_ILLEGAL_CONTEXT The API call was not made from an interrupt
+/// context.
+
+int
+ssx_interrupt_preemption_disable()
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT();
+ }
+
+ if (__ssx_kernel_context_noncritical_interrupt()) {
+ wrteei(0);
+ } else {
+ andc_msr(MSR_CE);
+ }
+
+ return SSX_OK;
+}
+
+
+#if SSX_TIMER_SUPPORT
+
+// The tickless kernel timer mechanism for PPC405
+//
+// This routine must be called from an SSX_NONCRITICAL critical section.
+//
+// Tickless timeouts are provided by programming the PIT timer based on when
+// the next timeout will occur. If the timeout is for the end of time there's
+// nothing to do - SSX does not use auto-reload mode so no more PIT interrupts
+// will be arriving. Otherwise, if the timeout is longer than the 32-bit PIT
+// timer can handle, we simply schedule the timeout for 2**32 - 1 and
+// __ssx_timer_handler() will keep rescheduling it until it finally occurs.
+// If the \a timeout is in the past, we schedule the PIT interrupt for 1 tick
+// in the future in accordance with the SSX specification.
+
+void
+__ssx_schedule_hardware_timeout(SsxTimebase timeout)
+{
+ SsxTimebase now;
+ uint32_t pit;
+
+ if (timeout != SSX_TIMEBASE_MAX) {
+
+ now = ssx_timebase_get();
+
+ if (timeout <= now) {
+ pit = 1;
+ } else if ((timeout - now) > 0xffffffff) {
+ pit = 0xffffffff;
+ } else {
+ pit = timeout - now;
+ }
+
+ mtspr(SPRN_PIT, pit);
+ }
+}
+
+
+// Cancel the PPC405 tickless kernel timeout
+//
+// This routine must be called from an SSX_NONCRITICAL critical section. SSX
+// does not use auto-reload mode of the PIT, so simply writing the PIT with 0
+// effectively cancels the timer.
+
+void
+__ssx_cancel_hardware_timeout()
+{
+ mtspr(SPRN_PIT, 0);
+}
+
+
+#endif /* SSX_TIMER_SUPPORT */
+
+#undef __PPC405_CORE_C__
diff --git a/src/ssx/ppc405/ppc405_dcr.h b/src/ssx/ppc405/ppc405_dcr.h
new file mode 100755
index 0000000..1f389bf
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_dcr.h
@@ -0,0 +1,55 @@
+#ifndef __PPC405_DCR_H__
+#define __PPC405_DCR_H__
+
+// $Id: ppc405_dcr.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_dcr.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_dcr.h
+/// \brief Everything related to PPC405-specific DCRs
+///
+/// DCRs are chip-specific. This file only defines DCR access methods; DCR
+/// numbers will be defined by chip-specific headers.
+
+/// Move From DCR
+///
+/// Note that \a dcrn must be a compile-time constant.
+
+#define mfdcr(dcrn) \
+ ({uint32_t __value; \
+ asm volatile ("mfdcr %0, %1" : "=r" (__value) : "i" (dcrn)); \
+ __value;})
+
+
+/// Move to DCR
+///
+/// Note that \a dcrn must be a compile-time constant.
+
+#define mtdcr(dcrn, value) \
+ ({uint32_t __value = (value); \
+ asm volatile ("mtdcr %0, %1" : : "i" (dcrn), "r" (__value)); \
+ })
+
+
+/// Read-Modify-Write a DCR with OR (Set DCR bits)
+///
+/// Note that \a dcrn must be a compile-time constant. This operation is only
+/// guaranteed atomic in a critical section.
+
+#define or_dcr(dcrn, x) \
+ mtdcr(dcrn, mfdcr(dcrn) | (x))
+
+
+/// Read-Modify-Write a DCR with AND complement (Clear DCR bits)
+///
+/// Note that \a dcrn must be a compile-time constant. This operation is only
+/// guaranteed atomic in a critical section.
+
+#define andc_dcr(dcrn, x) \
+ mtdcr(dcrn, mfdcr(dcrn) & ~(x))
+
+#endif /* __PPC405_DCR_H__ */
diff --git a/src/ssx/ppc405/ppc405_exceptions.S b/src/ssx/ppc405/ppc405_exceptions.S
new file mode 100755
index 0000000..c8be2e3
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_exceptions.S
@@ -0,0 +1,832 @@
+// $Id: ppc405_exceptions.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_exceptions.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_exceptions.S
+/// \brief PPC405 exception vector area.
+///
+/// The PowerPC exception vector area has many small and large 'holes' in the
+/// SSX implementation. These are due to numerous unhandled exceptions and
+/// unimplemented exceptions in the exception vector area that comprises 8KB
+/// in the 405. SSX interrupt handling and other code is 'packed' into these
+/// holes to reduce the effective code footprint of SSX. The packing is done
+/// (hopefully) on a reasonable basis - we haven't tried to squeeze every last
+/// byte by chopping up routines willy-nilly and stitching them together with
+/// random branches - but some fragmentation has occurred in the interrupt
+/// handling code.
+///
+/// To facilitate the packing, the exception vector area is divided into 5 ELF
+/// sections (addresses are offsets into the exception area)
+///
+/// .vectors_0000 - Empty section for adding image header
+///
+/// .vectors_0100 - From 0x0100 to 0x0bff. The beginning of the table through
+/// the large space prior to the system call vector.
+///
+/// .vectors_0c00 - From 0x0c00 to 0x0eff. This is a moderately large area
+/// after the system call vector.
+///
+/// .vectors_0f00 - From 0x0f00 to 0x1fff. From the APU Unavailable vector
+/// through the major 3.5K hole above the Debug vector.
+///
+/// .vectors_2000 - From 0x2000 to 0x2003 - branch to the Debug handler.
+///
+/// The exception vector area must be aligned on a 64KB boundary.
+///
+/// Note that PgP mainstore boot and interrupt controller handling is
+/// currently hard-coded into this file - but it can easily be generalized if
+/// a port to another environment is required, assuming the new environment
+/// has something similar to a PgP or 405 ASIC interrupt controller.
+///
+/// \cond
+
+ .nolist
+#include "ssx.h"
+ .list
+
+### ****************************************************************************
+### .vectors_0000 - Empty section ( Image header will be placed in this section
+### from the linker command file )
+### ****************************************************************************
+
+ .section .vectors_0000, "a", @progbits
+ .global __vectors
+ .global __vectors_0000
+__vectors:
+__vectors_0000:
+
+### ****************************************************************************
+### .vectors_0100
+### ****************************************************************************
+ .section .vectors_0100, "ax", @progbits
+
+ .global __vectors_0100
+
+__vectors_0100:
+
+ ############################################################
+ # 0x0100 : Critical Interrupt
+ ############################################################
+
+__critical_interrupt:
+
+ ## The critical interrupt handler entry point is re-entrant - A handler
+ ## may allow preemption, which could cause another entry here.
+
+ ## Entry invariants:
+ ## 1. Critical interupts are disabled;
+ ## 2. The SP points to a thread stack, the non-critical stack or
+ ## critical stack
+
+ ## Since fast-mode handlers can not use SSX services or alter the
+ ## machine context, the exit of a fast mode handler is a simple RF(C)I.
+
+ ## Begin by pushing the fast context on the stack.
+
+ _ssx_fast_ctx_push SSX_CRITICAL
+
+ ## Load critical status 0 and the handler array base address. Check
+ ## for interrupts pending in status register 0 while the IRQ is
+ ## computed and R5 is loaded with the critical flag.
+
+ _lwzi %r3, %r3, OCB_OCISR0
+ _liw %r6, __ppc405_irq_handlers
+ cmpwi %r3, 0
+ cntlzw %r4, %r3
+ li %r5, SSX_CRITICAL
+ bne+ critical_irq_found
+
+ ## No IRQ pending in interrupt set 0. Try set 1.
+
+ _lwzi %r3, %r3, OCB_OCISR1
+ cmpwi %r3, 0
+ cntlzw %r4, %r3
+ addi %r4, %r4, 32
+ beq- critical_phantom
+
+ ## An active IRQ was found. At entry here R6 has the handler table
+ ## base address, R4 has the IRQ number, and R5 has the critical
+ ## flag. The IRQ is converted into a pointer to an 8-byte handler
+ ## structure, and the handler is dispatched. The call is made with the
+ ## parameters:
+
+ ## R3 = private
+ ## R4 = irq
+ ## R5 = SSX_CRITICAL
+
+critical_irq_found:
+
+ _save_update_kernel_context SSX_CRITICAL, %r4, %r7
+ slwi %r3, %r4, 3
+ lwzux %r7, %r6, %r3
+ lwz %r3, 4(%r6)
+ mtlr %r7
+ blrl
+
+ ## Pop the stack/RFCI when (if) it returns here.
+
+fast_exit_critical:
+
+ _ssx_fast_ctx_pop_exit SSX_CRITICAL
+
+ ## This is a phantom interrupt - we got interrupted but no status bits
+ ## are set. The interrupt is marked as #64. The register used for the
+ ## handler table address (R6) is set to the special structure for the
+ ## phantom interrupt, with it's address adjusted to make it appear to
+ ## be the 64th entry in the table.
+
+critical_phantom:
+
+ _liw %r6, __ppc405_phantom_irq
+ subi %r6, %r6, (64 * 8)
+ b critical_irq_found
+
+
+ ############################################################
+ # 0x0200 : Machine Check, Data or Instruction
+ ############################################################
+
+ .org __vectors_0100 + 0x0100
+__machine_check:
+
+ PPC405_MACHINE_CHECK_HANDLER
+
+ .org __machine_check + 0x20
+
+ .global __ssx_irq_fast2full
+__ssx_irq_fast2full:
+
+ ## Convert a fast-mode to a full-mode interrupt by saving the
+ ## (volatile - fast) context, and switching to the appropriate system
+ ## stack.
+
+ ## Entry invariants:
+ ## 1. The SP/stack must be exactly as it was when the fast-mode
+ ## handler was entered.
+ ## 2. No changes have been made to the MSR - the interrupt level must
+ ## remain disabled.
+ ## 3. The handler owns the fast context and has not modified the other
+ ## register context. This routine can only use the (volatile -
+ ## fast) register context.
+
+ ## 41 (linear) instructions plus alignmenmt
+
+ ## Start by pushing the (volatile - fast) context. Technically we also
+ ## need to save the CR as our contract with the handler is not to
+ ## disturb any of its register state.
+
+ _ssx_vol_fast_ctx_push SSX_IRQ_CONTEXT
+ mfcr %r12
+
+ ## USPRG0 tells whether this is a critical or non-critical interrupt.
+ ## The high-order 8 bits of USPRG0 counts critical interrupt nesting,
+ ## and the SSX preemption rules guarantee that if the count is > 0 then
+ ## we are in a critical handler.
+
+ mfusprg0 %r8
+ extrwi. %r9, %r8, 8, 0
+ beq fast2full_noncritical
+
+ ## If the critical interrupt count is > 1, we are already in a
+ ## nested critical interrupt, so we're already on the critical stack
+ ## and there's nothing left to do.
+
+ cmpwi %r9, 1
+ bne 1f
+
+ ## Otherwise, save the current stack pointer and switch to the critical
+ ## stack.
+
+ _stwsd %r1, __ssx_saved_sp_critical
+ _lwzsd %r1, __ssx_critical_stack
+
+ ## Restore the CR and return to the now full-mode handler.
+
+1:
+ mtcr %r12
+ blr
+
+ ## Non-critical interrupts are handled analogously to the above,
+ ## except that bits 8:15 of R7 are the non-critical
+ ## count. At entry here the (volatile - fast) context has been pushed,
+ ## R8 has USPRG0 and R12 contains the saved CR.
+
+ ## Note that it would violate a kernel/API invariant if this routine
+ ## were entered from outside an interrupt context.
+
+ .cache_align
+fast2full_noncritical:
+
+ extrwi %r9, %r8, 8, 8
+ cmpwi %r9, 1
+ bne 1f
+
+ _stwsd %r1, __ssx_saved_sp_noncritical
+ _lwzsd %r1, __ssx_noncritical_stack
+
+1:
+
+ .if (SSX_ERROR_CHECK_KERNEL | SSX_ERROR_CHECK_API)
+ cmpwi %r9, 0
+ bne 2f
+ _ssx_panic PPC405_IRQ_FAST2FULL_INVARIANT
+2:
+ .endif
+
+ mtcr %r12
+ blr
+
+
+ ############################################################
+ # 0x0300 : Data Storage Interrupt
+ ############################################################
+
+ .org __vectors_0100 + 0x0200
+__data_storage:
+
+ PPC405_DATA_STORAGE_HANDLER
+
+ .org __data_storage + 0x20
+
+ .global __ssx_irq_full_mode_exit
+__ssx_irq_full_mode_exit:
+
+ ## Exit a full-mode handler.
+
+ ## Entry invariants:
+ ## 1. The SP/stack must be in exactly the same state it was left in at
+ ## the exit of __ssx_irq_fast2full.
+ ## 2. It is assumed the the preemption rules of SSX have been followed
+ ## - in particular that critical handlers have not enabled
+ ## non-critical interrupts.
+
+ ## We can freely modify the volatile context here - the handler is done
+ ## and we will restore the interrupted volatile context.
+
+ ## 22 linear instructions
+
+ ## If the critical count is non-zero, then the SSX preemption rules
+ ## guarantee that we are exiting from a critical interrupt
+ ## handler. This test is safe to make even if critical interrupts are
+ ## enabled, because the variable is set exactly once in a critical
+ ## section.
+
+ mfusprg0 %r3
+ extrwi. %r4, %r3, 8, 0
+ beq full_exit_noncritical
+
+ ## The context restore must be done from a critical section, in case
+ ## the handler enabled preemption.
+
+ _ssx_critical_section_enter SSX_CRITICAL, %r5, %r6
+
+ ## If the critical count (R4) is > 1 then this is a nested interrupt
+ ## and we can simply pop the context and RFCI.
+
+ cmpwi %r4, 1
+ bne full_exit_critical
+
+ ## Otherwise, restore the saved stack pointer before popping and RFCI.
+
+ _lwzsd %r1, __ssx_saved_sp_critical
+
+full_exit_critical:
+ _ssx_vol_fast_ctx_pop SSX_IRQ_CONTEXT, SSX_CRITICAL
+ b fast_exit_critical
+
+
+ ############################################################
+ # 0x0400 : Instruction Storage Interrupt
+ ############################################################
+
+ .org __vectors_0100 + 0x0300
+__instruction_storage:
+
+ PPC405_INSTRUCTION_STORAGE_HANDLER
+
+ .org __instruction_storage + 0x20
+
+ ## The idle thread has no permanent register context. The idle thread
+ ## entry point is re-entered whenever the idle thread is scheduled.
+
+ .global __ssx_idle_thread
+ .global __ssx_idle_thread_from_bootloader
+
+__ssx_idle_thread:
+
+ ## The idle thread 'uses' the non-critical stack. Any register context
+ ## pushed here is redundant and is wiped out/ignored every time the
+ ## idle thread is re-scheduled.
+
+ ## The idle thread simply establishes a default machine context and
+ ## enters the wait-enable state. The idle thread is always entered
+ ## with non-critical interrupts disabled.
+ ##
+ ## The kernel context is initialized to indicate that the idle thread
+ ## is running - the idle thread priority is SSX_THREADS, and the
+ ## 'thread-mode' bit is asserted as well.
+ ##
+ ## This loop can also be called from the SSX bootloader if main()
+ ## returns - in which case we don't muck with the USPRG0 or the stack
+ ## pointer.
+
+ li %r3, (SSX_THREADS | PPC405_THREAD_MODE)
+ mtusprg0 %r3
+ _lwzsd %r1, __ssx_noncritical_stack
+
+__ssx_idle_thread_from_bootloader:
+
+ li %r3, SSX_THREADS
+ SSX_TRACE_THREAD_SWITCH %r3, %r4
+ _lwzsd %r3, __ssx_thread_machine_context_default
+ _oriwa %r3, %r3, MSR_WE
+ mtmsr %r3
+ b .
+
+ ## ssx_halt() is implemented on the PPC405 by disabling all
+ ## interrupts, forcing external debug mode, and executing a trap. A
+ ## 0x0 word appears after the trap instruction similar to the default
+ ## SSX_PANIC macro. The caller may also call ssx_halt() with
+ ## parameters which will appear in R3, R4, etc. In the Simics
+ ## environment we use the Simics 'trap' since Simics does not handle
+ ## the PPC405 TRAP instruction correctly.
+
+ .global ssx_halt
+ssx_halt:
+ li %r31, 0
+ mtmsr %r31
+ isync
+ _liwa %r31, (DBCR0_EDM | DBCR0_TDE)
+ mtdbcr0 %r31
+ isync
+#if SIMICS_ENVIRONMENT
+ rlwimi 1, 1, 0, 0, 0
+#else
+ trap
+#endif
+ .long 0
+
+ ############################################################
+ # 0x0500 : External Interrupt
+ ############################################################
+
+ .org __vectors_0100 + 0x0400
+__external_interrupt:
+
+ ## The non-critical interrupt handler entry point is re-entrant - A
+ ## handler may allow preemption, which could cause another entry here.
+
+ ## Entry invariants:
+ ## 1. Non-critical interupts are disabled;
+ ## 2. The SP points to a thread stack or the non-critical stack.
+
+ ## Since fast-mode handlers can not use SSX services or alter the
+ ## machine context, the exit of a fast mode handler is a simple RF(C)I.
+
+ ## Begin by pushing the fast context on the current stack.
+
+ _ssx_fast_ctx_push SSX_NONCRITICAL
+
+ ## Load noncritical status 0 and the handler array base address. Check
+ ## for interrupts pending in status register 0 while the IRQ is
+ ## computed and R5 is loaded with the noncritical flag.
+
+ _lwzi %r3, %r3, OCB_ONISR0
+ _liw %r6, __ppc405_irq_handlers
+ cmpwi %r3, 0
+ cntlzw %r4, %r3
+ li %r5, SSX_NONCRITICAL
+ bne+ noncritical_irq_found
+
+ ## No IRQ pending in interrupt set 0. Try set 1.
+
+ _lwzi %r3, %r3, OCB_ONISR1
+ cmpwi %r3, 0
+ cntlzw %r4, %r3
+ addi %r4, %r4, 32
+ beq- noncritical_phantom
+
+ ## An active IRQ was found. At entry here R6 has the handler table
+ ## base address, R4 has the IRQ number, and R5 has the noncritical
+ ## flag. The IRQ is converted into a pointer to an 8-byte handler
+ ## structure, and the handler is dispatched. The call is made with the
+ ## parameters:
+
+ ## R3 = private
+ ## R4 = irq
+ ## R5 = SSX_NONCRITICAL
+
+noncritical_irq_found:
+
+ _save_update_kernel_context SSX_NONCRITICAL, %r4, %r7
+ slwi %r3, %r4, 3
+ lwzux %r7, %r6, %r3
+ lwz %r3, 4(%r6)
+ mtlr %r7
+ blrl
+
+ ## Pop the stack/RFI when (if) it returns here.
+
+fast_exit_noncritical:
+
+ _ssx_fast_ctx_pop_exit SSX_NONCRITICAL
+
+ ## This is a phantom interrupt - we got interrupted but no status bits
+ ## are set. The interrupt is marked as #64. The register used for the
+ ## handler table address (R6) is set to the special structure for the
+ ## phantom interrupt, with it's address adjusted to make it appear to
+ ## be the 64th entry in the table.
+
+noncritical_phantom:
+
+ _liw %r6, __ppc405_phantom_irq
+ subi %r6, %r6, (64 * 8)
+ b noncritical_irq_found
+
+ ############################################################
+ # 0x0600 : Alignment Exception
+ ############################################################
+
+ .org __vectors_0100 + 0x0500
+__alignment_exception:
+
+ PPC405_ALIGNMENT_HANDLER
+
+ .org __alignment_exception + 0x20
+pit_handler:
+
+ ## The portable timer handler of SSX a full-mode handler with the prototype:
+ ## void (*ssx_timer_handler)(void).
+ ##
+ ## To support the portable specification, the kernel clears the
+ ## interrupt by writing the PIS back into the TSR before calling the
+ ## handler. SSX does not use the PIT in auto-reload mode - it is
+ ## tickless - so the interrupt will not fire again until reprogrammed
+ ## by the timer handler. The timer handler does not take any arguments.
+
+ ## 21 instructions
+
+ _ssx_fast_ctx_push SSX_NONCRITICAL
+ li %r3, PPC405_IRQ_PIT
+ _save_update_kernel_context SSX_NONCRITICAL, %r3, %r4
+
+ _liwa %r3, TSR_PIS
+ mttsr %r3
+ isync
+
+ _ssx_irq_fast2full __ssx_timer_handler
+
+
+ ############################################################
+ # 0x0700 : Program Interrupt
+ ############################################################
+
+ .org __vectors_0100 + 0x0600
+__program_interrupt:
+
+ PPC405_PROGRAM_HANDLER
+
+ .org __program_interrupt + 0x20
+
+ ## Exiting a full-mode non-critical handler is more complex than the
+ ## critical case, because the handler may have made a new
+ ## highest-priority thread runnable and we may need to go through a
+ ## delayed scheduling step.
+
+ ## Note that the idle thread is treated as a special case. The idle
+ ## thread has no permanent register context. To avoid having to
+ ## allocate a stack area for the idle thread, the idle thread
+ ## 'uses' the non-critical stack. When the idle thread is interrupted
+ ## the (redundant) context is pushed, but is then effectively lost.
+ ## Whenever we restore the idle thread we simply reenter the idle
+ ## thread entry point.
+
+ ## At entry:
+ ## 1. R3 holds the value of USPRG0 (__SsxKernelContext)
+
+ ## 33 linear instructions.
+
+full_exit_noncritical:
+
+ ## Enter a critical section for the return from interrupt, in the event
+ ## that the handler enabled preemption.
+
+ _ssx_critical_section_enter SSX_NONCRITICAL, %r4, %r5
+
+ ## If the non-critical count is > 1 then this is a nested interrupt
+ ## and we can simply pop the context and RFI. Note that it would
+ ## violate a kernel/API invariant if this routine were entered from
+ ## outside an interrupt context (interrupt level == 0).
+
+ extrwi. %r4, %r3, 8, 8
+
+ .if (SSX_ERROR_CHECK_KERNEL | SSX_ERROR_CHECK_API)
+ bne 1f
+ _ssx_panic PPC405_IRQ_FULL_EXIT_INVARIANT
+1:
+ .endif
+
+ cmpwi %r4, 1
+ bne exit_noncritical_without_switch
+
+ ## Otherwise, restore the saved stack pointer and continue.
+
+ _lwzsd %r1, __ssx_saved_sp_noncritical
+
+ ## If we are not in thread mode (i.e., we took an interrupt in an
+ ## interupt-only configuration of SSX or after ssx_initialize() but
+ ## before ssx_start_threads) simply pop the context and RFI - in this
+ ## case we'll most likely be returning to main() or the non-thread-mode
+ ## idle thread.
+
+ andi. %r4, %r3, PPC405_THREAD_MODE
+ beq exit_noncritical_without_switch
+
+ ## Now, check for a delayed context switch. If none is pending, we can
+ ## exit (after a check for the idle thread special case).
+
+ _lwzsd %r3, __ssx_delayed_switch
+ cmpwi %r3, 0
+ bne noncritical_switch
+
+ _lwzsd %r3, __ssx_current_thread
+ cmpwi %r3, 0
+ beq __ssx_idle_thread
+
+exit_noncritical_without_switch:
+ _ssx_vol_fast_ctx_pop SSX_IRQ_CONTEXT, SSX_NONCRITICAL
+ b fast_exit_noncritical
+
+ ## The non-critical interrupt activated a delayed context switch. The
+ ## C-level code has taken care of the scheduling decisions - we simply
+ ## need to implement them here.
+
+noncritical_switch:
+
+ ## Clear the delayed switch flag and go to the context switch code to
+ ## finish the switch.
+
+ li %r3, 0
+ _stwsd %r3, __ssx_delayed_switch
+
+ b thread_save_non_volatile_and_switch
+
+
+ ############################################################
+ # 0x0800 : FPU Unavailable
+ ############################################################
+
+ .org __vectors_0100 + 0x0700
+__fpu_unavailable:
+
+ PPC405_FPU_UNAVAILABLE_HANDLER
+
+ .org __fpu_unavailable + 0x20
+
+
+ ## Exit traces are moved here because the code area (0x100 bytes)
+ ## reserved for individual interrupts is overflowing when tracing is
+ ## enabled. This is kind of a hack: We know that this trace only
+ ## occurs when we're about to exit the fast context, at a place
+ ## where we can use any of the fast registers.
+
+__ssx_trace_critical_irq_exit:
+ SSX_TRACE_CRITICAL_IRQ_EXIT %r3, %r4
+ blr
+
+__ssx_trace_noncritical_irq_exit:
+ SSX_TRACE_NONCRITICAL_IRQ_EXIT %r3, %r4
+ blr
+
+ ## >>>>>>>>>> Pack .vectors_0100 here. Room for ~900 bytes. <<<<<<<<<<
+
+### ****************************************************************************
+### .vectors_0c00
+### ****************************************************************************
+
+ .section .vectors_0c00, "ax", @progbits
+ .global __vectors_0c00
+__vectors_0c00:
+
+ ############################################################
+ # 0x0c00 : System Call
+ ############################################################
+
+ .org __vectors_0c00 + 0x0
+ .global __ssx_next_thread_resume
+
+__system_call:
+
+ ## The system call exception is used by SSX as a handy way to start a
+ ## context switch, as the continuation address and MSR of the thread to
+ ## be swapped out are saved in SRR0 and SRR1.
+
+ ## Non-critical interrupts are disabled at entry.
+
+ ## Note that the system call exception begins a large free area
+ ## so there is plenty of room for the context switch code.
+
+ ## Begin by saving the volatile context of the current thread.
+
+ _ssx_fast_ctx_push SSX_NONCRITICAL
+ _ssx_vol_fast_ctx_push SSX_THREAD_CONTEXT
+
+thread_save_non_volatile_and_switch:
+
+ ## Finish the thread context save by pushing the non-volatile context
+ ## and saving the resulting stack pointer in the thread structure. If
+ ## the current thread is the idle thread this step is bypassed.
+
+ ## This symbol is also used as an entry point by the non-critical
+ ## interrupt handler - non-critical interrupts are disabled here.
+
+ _lwzsd %r3, __ssx_current_thread
+ cmpwi %r3, 0
+ beq __ssx_next_thread_resume
+
+ _ssx_non_vol_ctx_push
+ stw %r1, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3)
+
+ ## The next thread becomes the current thread, and we switch to its
+ ## stack - unless the new thread is the idle thread, in which case it
+ ## (the idle thread) is simply resumed.
+
+__ssx_next_thread_resume:
+
+ _lwzsd %r3, __ssx_next_thread
+ _stwsd %r3, __ssx_current_thread
+
+ cmpwi %r3, 0
+ beq __ssx_idle_thread
+
+ lwz %r1, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3)
+
+ ## Restore the thread context and resume the new thread. The kernel
+ ## context in thread mode is simply the thread priority OR'ed with the
+ ## thread-mode flag. All other fields are cleared.
+
+ _ssx_non_vol_ctx_pop
+ _ssx_vol_fast_ctx_pop SSX_THREAD_CONTEXT, SSX_NONCRITICAL
+
+ _lbzsd %r3, __ssx_next_priority
+ SSX_TRACE_THREAD_SWITCH %r3, %r4
+ ori %r3, %r3, PPC405_THREAD_MODE
+ mtusprg0 %r3
+
+ _ssx_fast_ctx_pop
+ rfi
+
+ ## >>>>>>>> Pack .vectors_0c00 here - room for ~500 bytes <<<<<<<
+
+### ****************************************************************************
+### .vectors_0f00
+### ****************************************************************************
+
+ .section .vectors_0f00, "ax", @progbits
+ .global __vectors_0f00
+__vectors_0f00:
+
+ ############################################################
+ # 0x0f20 : APU Unavailable
+ ############################################################
+
+ .org __vectors_0f00 + 0x20 # 0x0f20
+__apu_unavailable:
+
+ PPC405_APU_UNAVAILABLE_HANDLER
+
+ .org __vectors_0f00 + 0x40 # 0x0f40
+
+fit_handler:
+
+ ## The FIT handler is user defined, and is a fast-mode handler. By
+ ## convention the kernel clears the interrupt by writing the FIS back
+ ## into the TSR.
+
+ _ssx_fast_ctx_push SSX_NONCRITICAL
+
+ _lwzsd %r3, __ppc405_fit_arg
+ li %r4, PPC405_IRQ_FIT
+ li %r5, SSX_NONCRITICAL
+
+ _save_update_kernel_context SSX_NONCRITICAL, %r4, %r6
+
+ _liwa %r6, TSR_FIS
+ mttsr %r6
+ isync
+
+ _lwzsd %r6, __ppc405_fit_routine
+ mtlr %r6
+ blrl
+
+ b fast_exit_noncritical
+
+
+ ############################################################
+ # 0x10x0 : PIT, FIT and Watchdog Interrupts
+ ############################################################
+
+ .org __vectors_0f00 + 0x100 # 0x1000
+__pit_interrupt:
+
+ b pit_handler
+
+ .org __vectors_0f00 + 0x110 # 0x1010
+__fit_interrupt:
+
+ b fit_handler
+
+ .org __vectors_0f00 + 0x120 # 0x1020
+__watchdog_interrupt:
+
+ ## Watchdog setup is described in the SSX Specification.
+ ## The kernel clears TSR[WIS] prior to calling the handler.
+ ## The watchdog handler is a critical, fast-mode handler.
+
+ _ssx_fast_ctx_push SSX_CRITICAL
+
+ _lwzsd %r3, __ppc405_watchdog_arg
+ li %r4, PPC405_IRQ_WATCHDOG
+ li %r5, SSX_CRITICAL
+
+ _save_update_kernel_context SSX_CRITICAL, %r4, %r6
+
+ _liwa %r6, TSR_WIS
+ mttsr %r6
+ isync
+
+ _lwzsd %r6, __ppc405_watchdog_routine
+ mtlr %r6
+ blrl
+
+ b fast_exit_critical
+
+
+ ############################################################
+ # 0x1100 : Data TLB Miss
+ ############################################################
+
+ .org __vectors_0f00 + 0x200 # 0x1100
+__data_tlb_miss:
+
+ PPC405_DATA_TLB_MISS_HANDLER
+
+ .org __data_tlb_miss + 0x20
+debug_handler:
+
+ ## SSX does nothing upon reception of the debug interrupt other
+ ## than calling the handler (if non-0). The debug handler is a
+ ## fast-mode handler.
+
+ _ssx_fast_ctx_push SSX_CRITICAL
+
+ _lwzsd %r3, __ppc405_debug_arg
+ li %r4, PPC405_IRQ_DEBUG
+ li %r5, SSX_CRITICAL
+
+ _save_update_kernel_context SSX_CRITICAL, %r4, %r6
+
+ _lwzsd %r6, __ppc405_debug_routine
+ cmpwi %r6, 0
+ mtlr %r6
+ beq debug_exit
+ blrl
+
+debug_exit:
+ b fast_exit_critical
+
+
+ ############################################################
+ # 0x1200 : Instruction TLB Miss
+ ############################################################
+
+ .org __vectors_0f00 + 0x300 # 0x1200
+__instruction_tlb_miss:
+
+ PPC405_INSTRUCTION_TLB_MISS_HANDLER
+
+ .org __instruction_tlb_miss + 0x20
+
+ ## >>>>>> Pack .vectors_0f00 A huge hole here - ~3.5KB <<<<<<
+
+### ****************************************************************************
+### .vectors_2000
+### ****************************************************************************
+
+ .section .vectors_2000, "ax", @progbits
+
+ .global __vectors_2000
+__vectors_2000:
+
+ ############################################################
+ # 0x2000 : Debug Interrupt
+ ############################################################
+
+__debug_interrupt:
+ b debug_handler
+
+/// \endcond
diff --git a/src/ssx/ppc405/ppc405_init.c b/src/ssx/ppc405/ppc405_init.c
new file mode 100755
index 0000000..e818737
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_init.c
@@ -0,0 +1,80 @@
+// $Id: ppc405_init.c,v 1.1.1.1 2013/12/11 21:03:26 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_init.c
+/// \brief PPC405 initialization routines
+///
+/// The entry points in this file are routines that are typically used during
+/// initialization, and their code space could be deallocated and recovered if
+/// no longer needed by the application after initialization.
+
+#include "ssx.h"
+
+// Note that __ppc405_system_setup() is called from the SSX bootloader early
+// in the initialization, at a point before the aplication has enabled
+// critical or external interruts.
+
+void
+__ppc405_system_setup()
+{
+ SsxIrqId irq;
+
+ // Initialize the interrupt vectors.
+
+ for (irq = 0; irq < PPC405_IRQS; irq++) {
+ __ppc405_irq_handlers[irq].handler = __ppc405_default_irq_handler;
+ __ppc405_irq_handlers[irq].arg = 0;
+ }
+
+ __ppc405_phantom_irq.handler = __ppc405_phantom_irq_handler;
+ __ppc405_phantom_irq.arg = 0;
+
+ // Initialize special interrupt handlers
+
+ __ppc405_fit_routine = __ppc405_default_irq_handler;
+ __ppc405_fit_arg = 0;
+
+ __ppc405_watchdog_routine = __ppc405_default_irq_handler;
+ __ppc405_watchdog_arg = 0;
+
+ __ppc405_debug_routine = __ppc405_default_irq_handler;
+ __ppc405_debug_arg = 0;
+
+ // Enable the PIT interrupt, but not auto-reload mode. Clear the status
+ // of all timers for good measure.
+
+ andc_spr(SPRN_TCR, TCR_ARE);
+ or_spr(SPRN_TCR, TCR_PIE);
+
+ or_spr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
+
+ // Call system-specific setup
+
+#ifdef CHIP_PGP
+ void __pgp_setup();
+ __pgp_setup();
+#endif
+
+}
+
+
+// Set the timebase using the PowerPC protocol.
+
+void
+__ssx_timebase_set(SsxTimebase t)
+{
+ Uint64 tb;
+
+ tb.value = t;
+
+ mttbl(0);
+ mttbu(tb.word[0]);
+ mttbl(tb.word[1]);
+}
+
+
diff --git a/src/ssx/ppc405/ppc405_irq.h b/src/ssx/ppc405/ppc405_irq.h
new file mode 100755
index 0000000..d85e9ce
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_irq.h
@@ -0,0 +1,342 @@
+#ifndef __PPC405_IRQ_H__
+#define __PPC405_IRQ_H__
+
+// $Id: ppc405_irq.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_irq.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_irq.h
+/// \brief PPC405 interrupt handling for SSX
+///
+/// Interrupt handling protocols and interrupt controller programming are
+/// inherently non-portable, however SSX defines APIs that may be useful among
+/// different machines.
+///
+/// The interrupt controllers in PPC405 ASICS and PGP allow interrupts to be
+/// programmed as critical or non-critical, with programmable polarity and
+/// edge or level sensitivity.
+
+
+// Define pseudo-IRQ numbers for PPC405 built-in interrupts. These numbers
+// will appear in bits 16:23 of USPRG0 (__SsxKernelContext) when the handlers
+// are active, and are also passed as the second argument of the handlers when
+// they are invoked.
+
+#define PPC405_IRQ_PIT 0x80
+#define PPC405_IRQ_FIT 0x81
+#define PPC405_IRQ_WATCHDOG 0x82
+#define PPC405_IRQ_DEBUG 0x83
+
+// These are suggested values to use for the IRQ in the __SsxKernelContext if
+// the application defines handlers for any of the 'unhandled exceptions'.
+
+#define PPC405_EXC_MACHINE_CHECK 0x90
+#define PPC405_EXC_DATA_STORAGE 0x91
+#define PPC405_EXC_INSTRUCTION_STORAGE 0x92
+#define PPC405_EXC_ALIGNMENT 0x93
+#define PPC405_EXC_PROGRAM 0x94
+#define PPC405_EXC_FPU_UNAVAILABLE 0x95
+#define PPC405_EXC_APU_UNAVAILABLE 0x96
+#define PPC405_EXC_DATA_TLB_MISS 0x97
+#define PPC405_EXC_INSTRUCTION_TLB_MISS 0x98
+
+
+// Unhandled exceptions default to a kernel panic, but the application can
+// override these definition. Note that the exception area only allocates 32
+// bytes (8 instructions) to an unhandled exception, so any redefinition
+// would most likely be a branch to an application-defined handler.
+
+#ifndef PPC405_MACHINE_CHECK_HANDLER
+#define PPC405_MACHINE_CHECK_HANDLER SSX_PANIC(0x0200)
+#endif
+
+#ifndef PPC405_DATA_STORAGE_HANDLER
+#define PPC405_DATA_STORAGE_HANDLER SSX_PANIC(0x0300)
+#endif
+
+#ifndef PPC405_INSTRUCTION_STORAGE_HANDLER
+#define PPC405_INSTRUCTION_STORAGE_HANDLER SSX_PANIC(0x0400)
+#endif
+
+#ifndef PPC405_ALIGNMENT_HANDLER
+#define PPC405_ALIGNMENT_HANDLER SSX_PANIC(0x0600)
+#endif
+
+#ifndef PPC405_PROGRAM_HANDLER
+#define PPC405_PROGRAM_HANDLER SSX_PANIC(0x0700)
+#endif
+
+#ifndef PPC405_FPU_UNAVAILABLE_HANDLER
+#define PPC405_FPU_UNAVAILABLE_HANDLER SSX_PANIC(0x0800)
+#endif
+
+#ifndef PPC405_APU_UNAVAILABLE_HANDLER
+#define PPC405_APU_UNAVAILABLE_HANDLER SSX_PANIC(0x0f20)
+#endif
+
+#ifndef PPC405_DATA_TLB_MISS_HANDLER
+#define PPC405_DATA_TLB_MISS_HANDLER SSX_PANIC(0x1100)
+#endif
+
+#ifndef PPC405_INSTRUCTION_TLB_MISS_HANDLER
+#define PPC405_INSTRUCTION_TLB_MISS_HANDLER SSX_PANIC(0x1200)
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////
+// SSX API
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// An IRQ handler takes 3 arguments:
+/// \arg \c arg - Private handler data installed by \c ssx_irq_setup() or
+/// \c ssx_irq_handler_set().
+/// \arg \c irq - The IRQ id; to enable a generic handler to manipulate
+/// its own interrupt status .
+/// \arg \c priority - One of the values \c SSX_CRITICAL or \c
+/// SSX_NONCRITICAL; to enable a generic handler to choose
+/// a behavior appropriate for the interrupt priority.
+
+typedef void (*SsxIrqHandler)(void* arg,
+ SsxIrqId irq,
+ int priority);
+
+/// Declare a subroutine as an IRQ handler
+
+#define SSX_IRQ_HANDLER(f) void f(void *arg, SsxIrqId irq, int priority)
+
+int ssx_irq_setup(SsxIrqId irq,
+ int polarity,
+ int trigger);
+
+int ssx_irq_handler_set(SsxIrqId irq,
+ SsxIrqHandler handler,
+ void* arg,
+ int priority);
+
+void ssx_irq_enable(SsxIrqId irq);
+void ssx_irq_disable(SsxIrqId irq);
+void ssx_irq_statusclear(SsxIrqId irq);
+
+SSX_IRQ_HANDLER(__ppc405_default_irq_handler);
+SSX_IRQ_HANDLER(__ppc405_phantom_irq_handler);
+
+
+int
+ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg);
+
+
+/// The address of the optional FIT interrupt handler
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+volatile
+SsxIrqHandler __ppc405_fit_routine;
+
+
+/// The private data of the optional FIT interrupt handler
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+volatile
+void* __ppc405_fit_arg;
+
+
+int
+ppc405_watchdog_setup(int tcr_wp, int tcr_wrc,
+ SsxIrqHandler handler, void* arg);
+
+
+/// The address of the optional Watchdog interrupt handler
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+volatile
+SsxIrqHandler __ppc405_watchdog_routine;
+
+
+/// The private data of the optional Watchdog interrupt handler
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+volatile
+void* __ppc405_watchdog_arg;
+
+
+int
+ppc405_debug_setup(SsxIrqHandler handler, void* arg);
+
+
+/// The address of the optional Debug interrupt handler
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+volatile
+SsxIrqHandler __ppc405_debug_routine;
+
+
+/// The private data of the optional Watchdog interrupt handler
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+volatile
+void* __ppc405_debug_arg;
+
+
+// Note: Why SSX_IRQ_FAST2FULL (below) is implemented so strangely.
+//
+// I am adamant that I want to have a a macro in the 'C' environment to create
+// these bridge functions. However the limitations of the C preprocessor and
+// the intelligence of the GCC 'asm' facility consipre against a
+// straightforward solution. The only way that I was able to find to get
+// naked assembly code into the output stream is to use 'asm' with simple
+// strings - I couldn't make it work with any kind of argument, as 'asm' would
+// reinterpret the arguments and resulting assembler code in various ways.
+//
+// There is another alternative that I tried wherby I created a subroutine
+// call and then filled in the subroutine body with 'asm' code. However, the
+// subroutine wrapper that GCC creates only works for PowerPC fast-mode
+// handlers if GCC is invoked with optimization, which ensures that the
+// wrapper doesn't touch the stack pointer or other registers. True, we'll
+// always use optimization, but I did not want to have to make this
+// requirement for using this macro.
+
+/// This macro creates a 'bridge' handler that converts the initial fast-mode
+/// IRQ dispatch into a call of a full-mode IRQ handler. The full-mode
+/// handler is defined by the user (presumably as a \c C subroutine) and has
+/// the same prototype (type SsxIrqHandler) as the fast handler.
+///
+/// \param fast_handler This will be the global function name of the fast
+/// IRQ handler created by this macro. This is the symbol
+/// that should be passed in as the \a handler argument
+/// of \c ssx_irq_setup() and \c ssx_irq_handler_set().
+///
+/// \param full_handler This is the name of the user-defined full-mode
+/// handler which is invoked through this bridge.
+///
+/// \e BUG \e ALERT : Beware of passing the \c full_handler to IRQ setup
+/// APIs. This won't be caught by the compiler (because the \c full_handler
+/// has the correct prototype) and will lead to nasty bugs. Always pass in
+/// the \c fast_handler symbol to IRQ setup APIS.
+///
+/// The code stream injected into the GCC assembler output in response to
+///
+/// SSX_IRQ_FAST2FULL(fast_handler, full_handler)
+///
+/// is (comments added for clarification) :
+///
+/// \code
+/// .text
+/// .global fast_handler
+/// .align 5 # Hard-coded PPC405 cache-line alignment
+/// fast_handler = . # Can't macro expand LABEL: - this is equivalent
+/// bl __ssx_irq_fast2full # The fast-mode to full-mode conversion sequence
+/// bl full_handler
+/// b __ssx_irq_full_mode_exit
+/// \endcode
+///
+/// The macro also declares the prototype of the fast handler:
+///
+/// \code
+/// SSX_IRQ_HANDLER(fast_handler);
+/// \endcode
+///
+
+#define SSX_IRQ_FAST2FULL(fast_handler, full_handler) \
+ SSX_IRQ_HANDLER(fast_handler); \
+ __SSX_IRQ_FAST2FULL(.global fast_handler, fast_handler = ., bl full_handler)
+
+#define __SSX_IRQ_FAST2FULL(global, label, call) \
+asm(".text"); \
+asm(#global); \
+asm(".align 5"); \
+asm(#label); \
+asm("bl __ssx_irq_fast2full"); \
+asm(#call); \
+asm("b __ssx_irq_full_mode_exit");
+
+#endif /* __ASSEMBLER__ */
+
+// It's hard to be portable and get all of the definitions and headers in the
+// correct order. We need to bring in the system IRQ header here.
+
+#ifdef CHIP_PGP
+#include "pgp_irq.h"
+#endif
+
+/// \page ppc405_irq_macros_page PPC405 SSX IRQ Assembler Macros
+///
+///
+/// \section fast2full_asm Fast-Mode to Full-Mode Handler Conversion
+///
+/// This macro produces the calling sequence required to convert a
+/// fast-mode interrupt handler to a full-mode interrupt handler. The
+/// full-mode handler is implemented by another subroutine. The
+/// requirements for invoking this macro are:
+///
+/// \li The stack pointer and stack must be exactly as they were when the
+/// fast-mode handler was entered.
+///
+/// \li No changes have been made to the MSR - the interrupt level must
+/// remain disabled.
+///
+/// \li The handler owns the fast context and has not modified the other
+/// register context. The conversion process will not modify any
+/// register in the fast context (other than the LR used for
+/// subroutine linkage).
+///
+/// The final condition above means that the \a full_handler will
+/// begin with the fast-mode context exactly as it was (save for LR)
+/// at conversion, including the contents of GPR3-7 (the first 5
+/// PowerPC ABI paramater passing registers) and the entire CR.
+///
+/// Forms:
+///
+/// \c _ssx_irq_fast2full \a full_handler
+/// \cond
+
+#ifdef __ASSEMBLER__
+
+ .macro _ssx_irq_fast2full full_handler
+ bl __ssx_irq_fast2full
+ bl \full_handler
+ b __ssx_irq_full_mode_exit
+ .endm
+
+#endif /* __ASSEMBLER__ */
+
+/// \endcond
+
+#ifndef __ASSEMBLER__
+
+
+/// This structure holds the interrupt handler routine addresses and private
+/// data. Assembler code assumes the given structure layout, so any changes
+/// to this structure will need to be reflected down into the interrupt
+/// dispatch assembler code.
+
+typedef struct {
+ SsxIrqHandler handler;
+ void *arg;
+} Ppc405IrqHandler;
+
+
+/// Interrupt handlers for real (implemented interrupts)
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+Ppc405IrqHandler __ppc405_irq_handlers[PPC405_IRQS];
+
+
+/// The 'phantom interrupt' handler
+///
+/// A 'phantom' interrupt occurs when the interrupt handling code in the
+/// kernel is entered, but no interrupt is found pending in the controller.
+/// This is considered a serious bug, as it indictates a short window
+/// condition where a level-sensitive interrupt has been asserted and then
+/// quickly deasserted before it can be handled.
+
+UNLESS__PPC405_IRQ_CORE_C__(extern)
+Ppc405IrqHandler __ppc405_phantom_irq;
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPC405_IRQ_H__ */
diff --git a/src/ssx/ppc405/ppc405_irq_core.c b/src/ssx/ppc405/ppc405_irq_core.c
new file mode 100755
index 0000000..3cd7469
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_irq_core.c
@@ -0,0 +1,49 @@
+// $Id: ppc405_irq_core.c,v 1.1.1.1 2013/12/11 21:03:26 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_irq_core.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_irq_core.c
+/// \brief Core IRQ routines required of any PPC405 configuration of SSX
+///
+/// This file is mostly only a placeholder - where 'extern inline' API
+/// functions and 'extern' variables are realized. A couple of default
+/// handlers are also installed here. The entry points in this file are
+/// considered 'core' routines that will always be present at runtime in any
+/// SSX application.
+
+#define __PPC405_IRQ_CORE_C__
+
+#include "ssx.h"
+
+/// This function is installed by default for interrupts not explicitly set up
+/// by the application. These interrupts should never fire.
+
+void
+__ppc405_default_irq_handler(void *arg,
+ SsxIrqId irq,
+ int critical)
+{
+ SSX_PANIC(PPC405_DEFAULT_IRQ_HANDLER);
+}
+
+
+/// This function is installed by default to handle the case that the
+/// interrupt dispatch code is entered in response to an external critical or
+/// non-critical interrupt, but no interrupt is found pending in the interrupt
+/// controller. This should never happen, as it would indicate that a
+/// 'glitch' occurred on the external noncritical or critical interrupt input
+/// to the PPC405 core.
+
+void __ppc405_phantom_irq_handler(void *arg,
+ SsxIrqId irq,
+ int critical)
+{
+ SSX_PANIC(PPC405_PHANTOM_INTERRUPT);
+}
+
+
+#undef __PPC405_IRQ_CORE_C__
diff --git a/src/ssx/ppc405/ppc405_irq_init.c b/src/ssx/ppc405/ppc405_irq_init.c
new file mode 100755
index 0000000..da33947
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_irq_init.c
@@ -0,0 +1,169 @@
+// $Id: ppc405_irq_init.c,v 1.2 2014/02/03 01:30:42 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_irq_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_irq_init.c
+/// \brief PPC405 IRQ initialization routines
+///
+/// The entry points in this file are routines that are typically used during
+/// initialization, and their code space could be deallocated and recovered if
+/// no longer needed by the application after initialization.
+
+#include "ssx.h"
+
+/// Set up a PPC405 Fixed Interval Timer (FIT) handler
+///
+/// See the SSX specification for full details on setting up a FIT handler.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_PPC405_FIT The \a tcr_fp argument was
+/// invalid when called with a non-null (non-0) \a handler.
+
+// Since the SSX_CRITICAL Watchdog interrupt is also controlled by the TCR, we
+// need to enter an SSX_CRITICAL critical section to manipulate the TCR.
+
+int
+ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg)
+{
+ SsxMachineContext ctx;
+ Ppc405TCR tcr;
+
+ if (SSX_ERROR_CHECK_API && handler) {
+ SSX_ERROR_IF((tcr_fp < 0) ||
+ (tcr_fp > 3),
+ SSX_INVALID_ARGUMENT_PPC405_FIT);
+ }
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ tcr.value = mfspr(SPRN_TCR);
+
+ if (handler) {
+
+ tcr.fields.fp = tcr_fp;
+ tcr.fields.fie = 1;
+
+ __ppc405_fit_routine = handler;
+ __ppc405_fit_arg = arg;
+
+ } else {
+
+ tcr.fields.fie = 0;
+ }
+
+ mtspr(SPRN_TCR, tcr.value);
+ isync();
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Set up a PPC405 Watchdog interrupt handler
+///
+/// See the SSX specification for full details on setting up a watchdog
+/// handler.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_PPC405_WATCHDOG One or more of the \a tcr_wp
+/// or \a tcr_wrc arguments were invalid.
+
+int
+ppc405_watchdog_setup(int tcr_wp, int tcr_wrc,
+ SsxIrqHandler handler, void* arg)
+{
+ SsxMachineContext ctx;
+ Ppc405TCR tcr;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((tcr_wp < 0) ||
+ (tcr_wp > 3) ||
+ (tcr_wrc < 0) ||
+ (tcr_wrc > 3),
+ SSX_INVALID_ARGUMENT_PPC405_WATCHDOG);
+ }
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS);
+
+ tcr.value = mfspr(SPRN_TCR);
+
+ tcr.fields.wp = tcr_wp;
+ tcr.fields.wrc = tcr_wrc;
+
+ if (handler == 0) {
+
+ // Reinstall the default handler and clear the interrupt enable. Then
+ // clear any pending interrupt status.
+ // WIS.
+
+ __ppc405_watchdog_routine = __ppc405_default_irq_handler;
+ __ppc405_watchdog_arg = 0;
+
+ tcr.fields.wie = 0;
+ mtspr(SPRN_TCR, tcr.value);
+ isync();
+
+ mtspr(SPRN_TSR, TSR_WIS);
+ isync();
+
+ } else {
+
+ // Install the new handler and enable the watchdog interrup.
+
+ __ppc405_watchdog_routine = handler;
+ __ppc405_watchdog_arg = arg;
+
+ tcr.fields.wie = 1;
+ mtspr(SPRN_TCR, tcr.value);
+ isync();
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Set up a PPC405 Debug interrupt handler
+///
+/// See the SSX specification for full details on setting up a debug handler.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_PPC405_DEBUG The \a handler argument
+/// is null (0).
+
+// The debug handler is installed in an SSX_CRITICAL critical section with all
+// debug interrupts disabled as well.
+
+int
+ppc405_debug_setup(SsxIrqHandler handler, void* arg)
+{
+ SsxMachineContext ctx;
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+ andc_msr(MSR_DE | MSR_DWE);
+
+ __ppc405_debug_routine = handler;
+ __ppc405_debug_arg = arg;
+ isync();
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
diff --git a/src/ssx/ppc405/ppc405_lib_core.c b/src/ssx/ppc405/ppc405_lib_core.c
new file mode 100755
index 0000000..3086efb
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_lib_core.c
@@ -0,0 +1,42 @@
+// $Id: ppc405_lib_core.c,v 1.2 2014/06/26 13:00:11 cmolsen Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_lib_core.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_lib_core.c
+/// \brief PPC405-specific library procedures
+///
+/// The routines in this file are not part of SSX per se, but are included
+/// with SSX because they may be considered OS services.
+///
+/// These are core routines that will present in all PPC405 SSX applications.
+
+#include "ssx.h"
+
+/// Cause a PPC405 core reset by an action on DBCR0
+
+void
+ppc405_core_reset()
+{
+ or_spr(SPRN_DBCR0, DBCR0_RST_CORE);
+}
+
+/// Cause a PPC405 chip reset by an action on DBCR0
+
+void
+ppc405_chip_reset()
+{
+ or_spr(SPRN_DBCR0, DBCR0_RST_CHIP);
+}
+
+/// Cause a PPC405 system reset by an action on DBCR0
+
+void
+ppc405_system_reset()
+{
+ or_spr(SPRN_DBCR0, DBCR0_RST_SYSTEM);
+}
+
diff --git a/src/ssx/ppc405/ppc405_mmu.c b/src/ssx/ppc405/ppc405_mmu.c
new file mode 100755
index 0000000..1affc67
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_mmu.c
@@ -0,0 +1,474 @@
+// $Id: ppc405_mmu.c,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_mmu.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_mmu.c
+/// \brief Functions related to the PPC405 MMU and its use in SSX.
+///
+/// SSX currently only supports using the PPC405 MMU for instruction and data
+/// area translation and protection for the global SSX application and kernel.
+/// No support for demand paging, user vs. kernel protection or
+/// thread-specific protection is provided.
+///
+/// Instead, the ppc405_mmu_map() API is provided. This API sets up TLB
+/// entries that provide address translation and protection for a region of
+/// memory. TLB entries are "locked", that is, once a TLB entry is defined it
+/// is permanently defined. SSX makes use of the variable page sizes provided
+/// by the PPC405 to protect regions using the minimum number of TLB entries.
+/// The minimum page size is 1K, and all regions to be protected must be 1K
+/// aligned and have sizes that are multiples of 1K.
+///
+/// The ppc405_mmu_map() API optionally returns a Ppc405MmuMap descriptor.
+/// This descriptor can be later used as the argument to ppc405_mmu_unmap() to
+/// unmap the region.
+///
+/// The overall SSX configuration option is PPC405_MMU_SUPPORT, with
+/// suboptions PPC405_IR_SUPPORT and PPC405_DR_SUPPORT. The IR (instruction
+/// relocate) and DR (data relocate) bits of the MSR must be set to enable
+/// instruction and data translation/protection respectively. In SSX this is
+/// handled by the definition of a macro PPC405_RELOCATION_MODE that contains
+/// the IR and/or DR bits as configured. This macro is OR'ed with the default
+/// PPC405 SSX_THREAD_MACHINE_CONTEXT_DEFAULT. If the application defines its
+/// own SSX_THREAD_MACHINE_CONTEXT_DEFAULT then the application will have to
+/// take care of ensuring that the correct IR/DR settings go into the default.
+///
+/// During interrupts and context switches the relocation mode is
+/// re-established before any loads or stores take place which provides
+/// complete protection for interrupt handlers. Note the
+/// assumption/requirement that all kernel, interrupt and thread code will be
+/// run under the PPC405_RELOCATION_MODE.
+
+#include "ssx.h"
+#include "ppc405_mmu.h"
+
+// A map of free TLB entries.
+//
+// It's handy that the PPC405 TLB has 64 entries. Thus we can use a 64-bit
+// bit mask to represent free entries. The next free entry is quickly found
+// using cntlz64().
+uint64_t __ppc405_tlb_free = 0;
+
+/// Reset the PPC405 simple MMU translation/protection scheme
+///
+/// This API invalidates the TLB, clears the zone protection register, and
+/// otherwise resets the SSX simple translation/protcetion scheme for the
+/// PPC405. The application must not be running in a translated mode when
+/// this API is invoked.
+///
+/// \retval 0 Success
+///
+/// \retval -PPC405_MMU_ILLEGAL_CONTEXT The API was called with translation
+/// enabled.
+
+int
+ppc405_mmu_reset()
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(mfmsr() & (MSR_IR | MSR_DR),
+ PPC405_MMU_ILLEGAL_CONTEXT);
+ }
+
+ tlbia();
+ mtspr(SPRN_PID, 0);
+ mtspr(SPRN_ZPR, 0);
+ __ppc405_tlb_free = 0xffffffffffffffffull;
+ isync();
+
+ return 0;
+}
+
+
+/// Define a memory region for MMU protection purposes
+///
+/// \param effective_address The effective (virtual) base address of the
+/// region. This address must be at least 1KB aligned.
+///
+/// \param real_address The real base address of the region. This address
+/// must be at least 1KB aligned.
+///
+/// \param size The size of the region in bytes. The size must be a multiple
+/// of 1KB. A \a size of 0 is legal and creates no entries.
+///
+/// \param tlbhi_flags An OR combination of PPC405_TLBHI_* bits (excluding the
+/// V-bit). This parameter is unlikely to be non-0 as it contains only the
+/// little-endian (E) and U0 flags.
+///
+/// - TLBHI_E : Little Endian
+/// - TLBHI_U0 : U0 mode access
+///
+/// \param tlblo_flags An OR combination of PPC405_TLBLO_* bits. This
+/// parameter defines WR and EX protection, as well as the 'WIMG' bits.
+///
+/// - TLBLO_EX : Executable code
+/// - TLBLO_WR : Writable data
+/// - TLBLO_W : Write-through mode
+/// - TLBLO_I : Cache-inhibited
+/// - TLBLO_M : Memory Coherent (Implemented but Ignored)
+/// - TLBLO_G : Guarded
+///
+/// \param map If non-0, then a Ppc405TlbMap for the region is returned.
+/// This map can be later used as an argument to ppc405_mmu_unmap() to unmap
+/// the region.
+///
+/// This API creates fixed TLB entries that provide virtual-to-real address
+/// translation and protection using a minimum number of TLB entries. The
+/// number of TLB entries is fixed, so there is no guarantee in general that
+/// any particular memory map is feasible. In general it is helpful to make
+/// sure that the effective and real memory ranges have similar alignment,
+/// otherwise the algorithm will be forced to use small page sizes.
+///
+/// The caller is responsible for cache-correctness of this API. If necessary
+/// the caller should flush or invalidate memory areas whose protection
+/// attributes have changed prior to and/or after invoking this API.
+///
+/// Note the the simple translation/protection protocol supported by this SSX
+/// API does not support the "zone selection" field of the PPC405 TLB
+/// entry. In SSX the PID is always 0.
+///
+/// If SSX_ERROR_CHECK_API is configured, the API checks each new TLB entry to
+/// ensure that it does not duplicate an existing entry. The check only
+/// covers duplicated effective addresses (which are not supported by the
+/// hardware), not the real addresses.
+///
+/// \retval 0 Success
+///
+/// \retval -PPC405_MMU_INVALID_ARGUMENT Can be signalled by numerous errors
+/// including improperly aigned memory regions, region size not a multiple of
+/// 1KB, and illegal flags.
+///
+/// \retval -PPC405_TOO_MANY_TLB_ENTRIES There are not enough TLB entries left
+/// to completely map the region. The state of the TLB at this point may be
+/// inconsistent.
+///
+/// \retval -PPC405_DUPLICATE_TLB_ENTRY The requested mapping would duplicate
+/// all or part of a currently existing TLB entry. Duplicate entries are not
+/// supported in the 405 core and will cause a TLB miss if an address in a
+/// duplicated range is accessed.
+
+int
+ppc405_mmu_map(SsxAddress effective_address,
+ SsxAddress real_address,
+ size_t size, int tlbhi_flags, int tlblo_flags,
+ Ppc405MmuMap *map)
+{
+ size_t log_page_size;
+ size_t page_size = 0;
+ Ppc405Tlbhi tlbhi;
+ Ppc405Tlblo tlblo;
+ Ppc405MmuMap local_map = 0;
+ int tlb_entry;
+ uint64_t bit;
+ SsxMachineContext ctx;
+
+ if (SSX_ERROR_CHECK_API) {
+ uint64_t allocated;
+ SsxAddress this_effective_address;
+ int entry, overlap;
+
+ // Check alignment, wrapping and legal flags.
+
+ SSX_ERROR_IF((effective_address % PPC405_PAGE_SIZE_MIN) ||
+ (real_address % PPC405_PAGE_SIZE_MIN) ||
+ (size % PPC405_PAGE_SIZE_MIN) ||
+ ((effective_address + size - 1) < effective_address) ||
+ (tlbhi_flags & ~TLBHI_LEGAL_FLAGS) ||
+ (tlblo_flags & ~TLBLO_LEGAL_FLAGS),
+ PPC405_MMU_INVALID_ARGUMENT);
+
+ // The check for duplicate entries needs to be done iteratively since
+ // we don't use a fixed page size. Since this API will probably only
+ // be called during initialization or from thread contexts, and since
+ // the TLB size is small, this overhead is not considered too onerous.
+ // For complete correctness this check would need to be done in its
+ // entirity in an SSX_CRITICAL critical section. In order to reduce
+ // SSX_CRITICAL interrupt latency we simply check against the TLB
+ // entries that were allocated at the time of the API call. This code
+ // may not protect against multiple threads simultaneously creating
+ // mappings that duplicate each other (a super-bug), but it should
+ // protect against bugs in a single thread's updating of the TLB.
+
+ if (size != 0) {
+
+ // See if the requested effective address is already mapped in the
+ // TLB
+
+ overlap = tlbsx(effective_address, &entry);
+
+ // Iteratively check the other overlap condition, which is the
+ // case that the effective address of any TLB entry is in the
+ // range of the new request.
+
+ allocated = ~__ppc405_tlb_free;
+ while (!overlap && (allocated != 0)) {
+
+ entry = cntlz64(allocated);
+ allocated &= ~((uint64_t)1 << (63 - entry));
+
+ tlbhi.value = tlbrehi(entry);
+ if (tlbhi.fields.v) {
+
+ this_effective_address =
+ tlbhi.fields.epn << PPC405_LOG_PAGE_SIZE_MIN;
+
+
+ // See if the first byte of this entry is inside the
+ // requested effective address range. NB: use actual
+ // address ranges (addr + size - 1) to compute overlap to
+ // avoid overflow.
+
+ overlap |=
+ (this_effective_address >=
+ effective_address) &&
+ (this_effective_address <=
+ (effective_address + size - 1));
+ }
+ }
+ SSX_ERROR_IF(overlap, PPC405_DUPLICATE_TLB_ENTRY);
+ }
+ }
+
+ // NB: PPC405 page sizes go from 1K to 16M by factors of 4. This is a
+ // 'greedy' algorithm that packs the region into the fewest number of
+ // pages, by using the largest possible (aligned) page size for the
+ // remaining memory area.
+
+ while (size != 0) {
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL(__ppc405_tlb_free == 0,
+ PPC405_TOO_MANY_TLB_ENTRIES,
+ &ctx);
+ }
+
+ tlb_entry = cntlz64(__ppc405_tlb_free);
+ bit = 0x8000000000000000ull >> tlb_entry;
+ __ppc405_tlb_free &= ~bit;
+ local_map |= bit;
+
+ ssx_critical_section_exit(&ctx);
+
+ log_page_size = PPC405_LOG_PAGE_SIZE_MAX;
+ do {
+ page_size = POW2_32(log_page_size);
+ if ((size >= page_size) &&
+ ((effective_address & (page_size - 1)) == 0) &&
+ ((real_address & (page_size - 1)) == 0)) {
+ break;
+ } else {
+ log_page_size -= 2;
+ }
+ } while (1);
+
+ size -= page_size;
+
+ // Create and install the TLB entries. The installation is done in a
+ // critical section to avoid any chance of another entity seeing an
+ // inconsistent TLB.
+
+ tlbhi.value = tlbhi_flags;
+ tlbhi.fields.epn = effective_address >> PPC405_LOG_PAGE_SIZE_MIN;
+ tlbhi.fields.size = (log_page_size - PPC405_LOG_PAGE_SIZE_MIN) / 2;
+ tlbhi.fields.v = 1;
+
+ tlblo.value = tlblo_flags;
+ tlblo.fields.rpn = real_address >> PPC405_LOG_PAGE_SIZE_MIN;
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ tlbwelo(tlb_entry, tlblo.value);
+ tlbwehi(tlb_entry, tlbhi.value);
+ isync();
+
+ ssx_critical_section_exit(&ctx);
+
+ effective_address += page_size;
+ real_address += page_size;
+ }
+
+ if (map) {
+ *map = local_map;
+ }
+
+ return 0;
+}
+
+
+/// Un-define a memory region for MMU protection purposes
+///
+/// \param map A pointer to a Ppc405MmuMap object created by ppc405_mmu_map()
+/// when the memory region was mapped. This map is used to invalidate the TLB
+/// entries associated with the map, then the map itself is invalidated.
+///
+/// The caller is responsible for cache-correctness of this API. If necessary
+/// the caller should flush or invalidate memory areas whose protection
+/// attributes have changed prior to and/or after invoking this API.
+///
+/// \retval 0 Success
+///
+/// \retval -PPC405_MMU_INVALID_ARGUMENT The \a map pointer is null (0).
+
+int
+ppc405_mmu_unmap(Ppc405MmuMap *map)
+{
+ int tlb_entry;
+ uint64_t bit;
+ SsxMachineContext ctx;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(map == 0, PPC405_MMU_INVALID_ARGUMENT);
+ }
+
+ while ((tlb_entry = cntlz64(*map)) != 64) {
+
+ bit = 0x8000000000000000ull >> tlb_entry;
+ *map &= ~bit;
+ tlbwehi(tlb_entry, 0);
+ isync();
+
+ ssx_critical_section_enter(SSX_CRITICAL, &ctx);
+
+ __ppc405_tlb_free |= bit;
+
+ ssx_critical_section_exit(&ctx);
+ }
+
+ return 0;
+}
+
+
+/// Produce a dump of the TLB
+///
+/// \param[in] i_stream The output stream for the dump
+///
+/// \param[in] i_map An optional pointer. If NULL (0) then a full report is
+/// printed. If non-null then only the entries recorded in the \a i_map are
+/// printed.
+
+void
+ppc405_mmu_report(FILE* i_stream, Ppc405MmuMap* i_map)
+{
+ size_t i;
+ Ppc405Tlbhi tlbhi;
+ Ppc405Tlblo tlblo;
+ uint32_t size, eff_lo, eff_hi, real_lo, real_hi;
+ const char *size_string[] = {
+ " 1K", " 4K", " 16K", " 64K", "256K", " 1M", " 4M", " 16M"
+ };
+ Ppc405MmuMap map;
+
+ fprintf(i_stream, "------------------------------------------------------------------------------\n");
+ if (i_map == 0) {
+ fprintf(i_stream, "-- PPC405 MMU : Full Report --\n");
+ } else {
+ fprintf(i_stream, "-- PPC405 MMU : Partial Report --\n");
+ }
+ fprintf(i_stream, "------------------------------------------------------------------------------\n");
+ fprintf(i_stream, "-- # Effective Real Size EX/WR WIMG Other --\n");
+ fprintf(i_stream, "------------------------------------------------------------------------------\n");
+
+ if (i_map == 0) {
+ map = __ppc405_tlb_free;
+ } else {
+ map = ~*i_map;
+ }
+
+ for (i = 0; i < PPC405_TLB_ENTRIES; i++, map <<= 1) {
+
+ if (map & 0x8000000000000000ull) {
+ continue;
+ }
+
+ tlbhi.value = tlbrehi(i);
+ tlblo.value = tlbrelo(i);
+
+ if (tlbhi.fields.v) {
+
+ size =
+ POW2_32(PPC405_LOG_PAGE_SIZE_MIN) << (2 * tlbhi.fields.size);
+
+ eff_lo = tlbhi.fields.epn << PPC405_LOG_PAGE_SIZE_MIN;
+ eff_hi = eff_lo + size - 1;
+
+ real_lo = tlblo.fields.rpn << PPC405_LOG_PAGE_SIZE_MIN;
+ real_hi = real_lo + size - 1;
+
+ fprintf(i_stream, "-- %2d : %08x:%08x -> %08x:%08x : %s : %s %s : %s%s%s%s : %s%s --\n",
+ i,
+ eff_lo, eff_hi,
+ real_lo, real_hi,
+ size_string[tlbhi.fields.size],
+ tlblo.fields.ex ? "EX" : " ",
+ tlblo.fields.wr ? "WR" : " ",
+ tlblo.fields.w ? "W" : " ",
+ tlblo.fields.i ? "I" : " ",
+ tlblo.fields.m ? "M" : " ",
+ tlblo.fields.g ? "G" : " ",
+ tlbhi.fields.e ? "E" : " ",
+ tlbhi.fields.u0 ? "U0" : " ");
+ } else {
+ fprintf(i_stream, "-- %2d : ENTRY NOT VALID\n", i);
+ }
+ }
+
+ fprintf(i_stream, "------------------------------------------------------------------------------\n");
+}
+
+
+/// Perform a memcpy() without address translation (protection)
+///
+/// It sometimes arises that "read-only" data needs to be initialized at
+/// run-time. This can be accomplished in general by temporarily disabling
+/// translation (protection) while the "read-only" data is altered. Another
+/// option is to use the memcpy_real() API to copy an image of the data from
+/// writable memory to memory marked read-only by the MMU.
+///
+/// The memcpy_real() function copies \a n bytes from memory area \a src to
+/// memory area \a dest, with translation disabled. The memory areas should
+/// not overlap. The memcpy_real() function returns a pointer to dest.
+///
+/// This is a general-purpose API that makes no assumption about the
+/// cacheability of the data, and can also be used to move code from data
+/// areas to text areas as the I-cache is always invalidated after the copy.
+/// The algorithm is as follows:
+///
+/// - Flush the \a dest data from the D-cache
+/// - Disable translation
+/// - memcpy() the \a src to the \a dest
+/// - Flush the \a dest data from the D-cache
+/// - Invalidate the I-cache
+/// - Re-enable translation (if it had been previously enabled)
+///
+/// \note Any synchronization access required for \a dest or \a src is the
+/// responsibility of the caller.
+void*
+memcpy_real(void* dest, const void* src, size_t n)
+{
+ uint32_t msr;
+
+ dcache_flush(dest, n);
+
+ msr = mfmsr();
+ mtmsr(msr & ~(MSR_IR | MSR_DR));
+ sync(); /* HW239446! */
+
+ memcpy(dest, src, n);
+
+ dcache_flush(dest, n);
+
+ icache_invalidate_all();
+
+ mtmsr(msr);
+ sync(); /* HW239446! */
+
+ return dest;
+}
+
+
+
+
diff --git a/src/ssx/ppc405/ppc405_mmu.h b/src/ssx/ppc405/ppc405_mmu.h
new file mode 100755
index 0000000..cd7e249
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_mmu.h
@@ -0,0 +1,170 @@
+#ifndef __PPC405_MMU_H__
+#define __PPC405_MMU_H__
+
+// $Id: ppc405_mmu.h,v 1.1.1.1 2013/12/11 21:03:26 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_mmu.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_mmu.h
+/// \brief Definitions related to the PPC405 MMU and its use in SSX.
+
+#ifndef __ASSEMBLER__
+
+#include "ssx_io.h"
+#include <stdint.h>
+
+/// The PPC405 TLBHI (tag) structure
+///
+/// Note that in hardware this is a 36-bit register, as it includes the TID
+/// field. When writing, TID is set from the current PID, and when reading PID
+/// is set from the TID entry of the register.
+
+typedef union {
+ uint32_t value;
+ struct {
+ uint32_t epn : 22;
+ uint32_t size : 3;
+ uint32_t v : 1;
+ uint32_t e : 1;
+ uint32_t u0 : 1;
+ } fields;
+} Ppc405Tlbhi;
+
+
+/// The PPC405 TLBLO (Data) structure
+
+typedef union {
+ uint32_t value;
+ struct {
+ uint32_t rpn : 22;
+ uint32_t ex : 1;
+ uint32_t wr : 1;
+ uint32_t zsel : 4;
+ uint32_t w : 1;
+ uint32_t i : 1;
+ uint32_t m : 1;
+ uint32_t g : 1;
+ } fields;
+} Ppc405Tlblo;
+
+#endif /* __ASSEMBLER__ */
+
+// TLBHI contains little-endian and U0 flags (probably never used)
+
+#define TLBHI_E 0x00000020
+#define TLBHI_U0 0x00000010
+
+#define TLBHI_LEGAL_FLAGS (TLBHI_E | TLBHI_U0)
+
+// TLBLO contains WIMG + EX/WR bits
+
+#define TLBLO_EX 0x00000200
+#define TLBLO_WR 0x00000100
+#define TLBLO_W 0x00000008
+#define TLBLO_I 0x00000004
+#define TLBLO_M 0x00000002
+#define TLBLO_G 0x00000001
+
+#define TLBLO_LEGAL_FLAGS \
+ (TLBLO_EX | TLBLO_WR | TLBLO_W | TLBLO_I | TLBLO_M | TLBLO_G)
+
+
+#define PPC405_TLB_ENTRIES 64
+
+#define PPC405_PAGE_SIZE_MIN 1024
+#define PPC405_PAGE_SIZE_MAX (16 * 1024 * 1024)
+
+#define PPC405_LOG_PAGE_SIZE_MIN 10
+#define PPC405_LOG_PAGE_SIZE_MAX 24
+
+#define PPC405_PAGE_SIZE_1K 0
+#define PPC405_PAGE_SIZE_4K 1
+#define PPC405_PAGE_SIZE_16K 2
+#define PPC405_PAGE_SIZE_64K 3
+#define PPC405_PAGE_SIZE_256K 4
+#define PPC405_PAGE_SIZE_1M 5
+#define PPC405_PAGE_SIZE_4M 6
+#define PPC405_PAGE_SIZE_16M 7
+
+// PPC405 MMU error and panic codes
+
+#define PPC405_MMU_ILLEGAL_CONTEXT 0x00668001
+#define PPC405_MMU_INVALID_ARGUMENT 0x00668002
+#define PPC405_TOO_MANY_TLB_ENTRIES 0x00668003
+#define PPC405_DUPLICATE_TLB_ENTRY 0x00668004
+
+
+#ifndef __ASSEMBLER__
+
+/// A descriptor of a memory region statically defined in the TLB
+///
+/// These maps are returned by ppc405_mmu_map(), and can be used later
+/// to unmap the region with ppc405_mmu_unmap(). They can also be used to
+/// control what gets printed by ppc405_mmu_report().
+typedef uint64_t Ppc405MmuMap;
+
+/// TLBIA
+#define tlbia() asm volatile ("tlbia" : : : "memory")
+
+/// TLBWEHI
+#define tlbwehi(entry, tlbhi) \
+asm volatile ("tlbwehi %0, %1" : : "r" (tlbhi), "r" (entry) : "memory")
+
+/// TLBWELO
+#define tlbwelo(entry, tlblo) \
+asm volatile ("tlbwelo %0, %1" : : "r" (tlblo), "r" (entry) : "memory")
+
+/// TLBREHI
+#define tlbrehi(entry) \
+ ({ \
+ uint32_t __tlbhi; \
+ asm volatile ("tlbrehi %0, %1" : "=r" (__tlbhi) : "r" (entry)); \
+ __tlbhi;})
+
+/// TLBRELO
+#define tlbrelo(entry) \
+ ({ \
+ uint32_t __tlblo; \
+ asm volatile ("tlbrelo %0, %1" : "=r" (__tlblo) : "r" (entry)); \
+ __tlblo;})
+
+/// TLBSX
+///
+/// Returns 1 if the address is mapped, else 0. If positive the integer
+/// pointed to by \a entry is updated with the TLB index of the matching
+/// entry, otherwise the return value is undefined.
+#define tlbsx(address, entry) \
+ ({ \
+ uint32_t __cr, __entry; \
+ asm volatile ("tlbsx. %0, 0, %2; mfcr %1" : \
+ "=r" (__entry), "=r" (__cr) : "r" (address)); \
+ *(entry) = __entry; \
+ ((__cr & CR_EQ(0)) != 0);})
+
+
+int
+ppc405_mmu_reset(void);
+
+int
+ppc405_mmu_map(SsxAddress effective_address,
+ SsxAddress real_address,
+ size_t size, int tlbhi_flags, int tlblo_flags,
+ Ppc405MmuMap *map);
+
+int
+ppc405_mmu_unmap(Ppc405MmuMap *map);
+
+void
+ppc405_mmu_start(void);
+
+void
+ppc405_mmu_report(FILE* stream, Ppc405MmuMap* map);
+
+#endif /* __ASSEMBLER__ */
+
+
+#endif /* __PPC405_MMU_H__ */
diff --git a/src/ssx/ppc405/ppc405_mmu_asm.S b/src/ssx/ppc405/ppc405_mmu_asm.S
new file mode 100755
index 0000000..1118779
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_mmu_asm.S
@@ -0,0 +1,73 @@
+// $Id: ppc405_mmu_asm.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_mmu_asm.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_mmu_asm.S
+/// \brief Assembler support for PPC405 MMU operations
+///
+/// Currently the only API in this file - ppc405_mmu_start() - is likely an
+/// initialization-only API that could be removed from the run-time image.
+
+ .nolist
+#include "ssx.h"
+ .list
+
+/// Start MMU mode on the PPC405
+///
+/// This API enables PPC405 address translation of the type supported by SSX -
+/// simple 1 to 1 effective - real translation for the purpose of
+/// protection. It is coded in assembler to ensure that this transition is
+/// done as cache-safely as generically possible. The API enters a critical
+/// section and flushes the data cache and invalidates the I-cache, then
+/// enables the translation modes specifed by PPC405_RELOCATION_MODE.
+/// Following is a final invalidation of the I-cache.
+///
+/// \cond
+
+ .global_function ppc405_mmu_start
+ppc405_mmu_start:
+
+ ## Create and link a stack frame
+
+ stwu %r1, -16(%r1)
+ mflr %r0
+ stw %r0, 20(%r1)
+
+ ## Enter critical section, save original MSR in R31
+
+ stw %r31, 8(%r1)
+ _ssx_critical_section_enter SSX_CRITICAL, %r31, %r4
+
+ ## Flush D-cache, Invalidate I-Cache
+
+ bl dcache_flush_all
+ bl icache_invalidate_all
+
+ ## Enter translation mode on original MSR (removing critical section)
+
+ _liw %r3, 1f
+ mtsrr0 %r3
+ _liwa %r3, PPC405_RELOCATION_MODE
+ or %r3, %r31, %r3
+ mtsrr1 %r3
+ rfi
+1:
+ ## Invalidate I-cache again
+
+ bl icache_invalidate_all
+
+ ## Restore R31, Unwind stack and return
+
+ lwz %r31, 8(%r1)
+ lwz %r0, 20(%r1)
+ mtlr %r0
+ addi %r1, %r1, 16
+ blr
+
+ .epilogue ppc405_mmu_start
+
+/// \endcond
diff --git a/src/ssx/ppc405/ppc405_msr.h b/src/ssx/ppc405/ppc405_msr.h
new file mode 100755
index 0000000..645a052
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_msr.h
@@ -0,0 +1,85 @@
+#ifndef __PPC405_MSR_H__
+#define __PPC405_MSR_H__
+
+// $Id: ppc405_msr.h,v 1.1.1.1 2013/12/11 21:03:26 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_msr.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_msr.h
+/// \brief Everything related to the PPC405 Machine State Register
+///
+/// All of the macros defined here that \e modify the MSR create a compiler
+/// memory barrier that will cause GCC to flush/invalidate all memory data
+/// held in registers before the macro. This is consistent with other systems,
+/// e.g., the PowerPC Linux kernel, and is the safest way to define these
+/// macros as it guarantess for example that kernel data structure updates
+/// have completed before exiting a critical section.
+
+#define MSR_AP 0x02000000 /* APU Available */
+#define MSR_APE 0x00080000 /* APU Exception Enable */
+#define MSR_WE 0x00040000 /* Wait State Enable */
+#define MSR_CE 0x00020000 /* Critical Interrupt Enable */
+#define MSR_EE 0x00008000 /* External Interrupt Enable */
+#define MSR_PR 0x00004000 /* Problem State */
+#define MSR_ME 0x00001000 /* Machine Check Exception Enable */
+#define MSR_FE0 0x00000800 /* Floating-Point Exception Mode 0 */
+#define MSR_DWE 0x00000400 /* Debug Wait Enable */
+#define MSR_DE 0x00000200 /* Debug Interrupt Enable */
+#define MSR_IR 0x00000020 /* Instruction Relocation */
+#define MSR_DR 0x00000010 /* Data Relocation */
+
+#define MSR_CE_BIT 14
+#define MSR_EE_BIT 16
+#define MSR_IR_BIT 26
+#define MSR_DR_BIT 27
+
+#ifndef __ASSEMBLER__
+
+/// Move From MSR
+
+#define mfmsr() \
+ ({uint32_t __msr; \
+ asm volatile ("mfmsr %0" : "=r" (__msr)); \
+ __msr;})
+
+
+/// Move to MSR
+
+#define mtmsr(value) \
+ asm volatile ("mtmsr %0; isync" : : "r" (value) : "memory")
+
+
+/// Read-Modify-Write the MSR with OR (Set MSR bits). This operation is only
+/// guaranteed atomic in a critical section.
+
+#define or_msr(x) \
+ mtmsr(mfmsr() | (x))
+
+
+/// Read-Modify-Write the MSR with AND complement (Clear MSR bits). This
+/// operation is only guaranteed atomic in a critical section.
+
+#define andc_msr(x) \
+ mtmsr(mfmsr() & ~(x))
+
+
+/// Write MSR[EE] with an immediate value (0/1)
+///
+/// Note that the immediate value \a i must be a compile-time constant.
+
+#define wrteei(i) \
+ asm volatile ("wrteei %0; isync" : : "i" (i) : "memory")
+
+
+/// Write MSR[EE] from the EE bit of another MSR
+
+#define wrtee(other_msr) \
+ asm volatile ("wrtee %0; isync" : : "r" (other_msr) : "memory")
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPC405_MSR_H__ */
diff --git a/src/ssx/ppc405/ppc405_spr.h b/src/ssx/ppc405/ppc405_spr.h
new file mode 100755
index 0000000..ede91cb
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_spr.h
@@ -0,0 +1,319 @@
+#ifndef __PPC405_SPR_H__
+#define __PPC405_SPR_H__
+
+// $Id: ppc405_spr.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_spr.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppc405_spr.h
+/// \brief Everything related to PPC405-specific SPRs
+
+/// \defgroup ppc405_sprs PowerPC 405 SPRs
+///
+/// These are the documented SPRs of the PPC405. Most of these SPRs are
+/// available in RISCWatch and eCmd using the defined names (minus SPRN_). In
+/// some cases RISCWatch/eCMD use different names, which appear in square
+/// brackets in the brief comments for each register. RISCWatch/eCMD also
+/// allow CR, MSR and IAR (Instruction Address Register) to be accessed as
+/// SPRs.
+///
+/// @{
+
+#define SPRN_CCR0 0x3b3 /// Core configuration register 0
+#define SPRN_CCR1 0x378 /// Core configuration register 1
+#define SPRN_CTR 0x009 /// Count register
+#define SPRN_DAC1 0x3f6 /// Data address compare 1
+#define SPRN_DAC2 0x3f7 /// Data address compare 2
+#define SPRN_DBCR0 0x3f2 /// Debug control register 0
+#define SPRN_DBCR1 0x3bd /// Debug control register 1
+#define SPRN_DBSR 0x3f0 /// Debug status register
+#define SPRN_DCCR 0x3fa /// Data cacheability (real mode)
+#define SPRN_DCWR 0x3ba /// Data cache writeback (real mode)
+#define SPRN_DEAR 0x3d5 /// Data exception address register
+#define SPRN_DVC1 0x3b6 /// Data value compare 1
+#define SPRN_DVC2 0x3b7 /// Data value compare 2
+#define SPRN_ESR 0x3d4 /// Exception syndrome register
+#define SPRN_EVPR 0x3d6 /// Exception. vec. prefix reg.
+#define SPRN_IAC1 0x3f4 /// Instruction address compare 1
+#define SPRN_IAC2 0x3f5 /// Instruction address compare 2
+#define SPRN_IAC3 0x3b4 /// Instruction address compare 3
+#define SPRN_IAC4 0x3b5 /// Instruction address compare 4
+#define SPRN_ICCR 0x3fb /// Instruction cache. (real mode)
+#define SPRN_ICDBDR 0x3d3 /// Instruction cache debug data reg.
+#define SPRN_LR 0x008 /// Link register
+#define SPRN_MCSR 0x23c /// Machine check syndrome register
+#define SPRN_PID 0x3b1 /// Process ID
+#define SPRN_PIT 0x3db /// Programmable interrupt timer
+#define SPRN_PVR 0x11f /// Processor version register
+#define SPRN_SGR 0x3b9 /// Storage guarded (real mode)
+#define SPRN_SLER 0x3bb /// Storage little-endian (real mode)
+#define SPRN_SPRG0 0x110 /// SPR general register 0
+#define SPRN_SPRG1 0x111 /// SPR general register 1
+#define SPRN_SPRG2 0x112 /// SPR general register 2
+#define SPRN_SPRG3 0x113 /// SPR general register 3
+#define SPRN_SPRG4 0x114 /// SPR general register 4 [SPRG4_W]
+#define SPRN_SPRG5 0x115 /// SPR general register 5 [SPRG5_W]
+#define SPRN_SPRG6 0x116 /// SPR general register 6 [SPRG6_W]
+#define SPRN_SPRG7 0x117 /// SPR general register 7 [SPRG7_W]
+#define SPRN_SRR0 0x01a /// Save/restore register 0
+#define SPRN_SRR1 0x01b /// Save/restore register 1
+#define SPRN_SRR2 0x3de /// Save/restore register 2
+#define SPRN_SRR3 0x3df /// Save/restore register 3
+#define SPRN_SU0R 0x3bc /// Storage user 0 (real mode)
+#define SPRN_TBL 0x11c /// Time base lower [TBL_W]
+#define SPRN_TBU 0x11d /// Time base upper [TBU_W]
+#define SPRN_TCR 0x3da /// Timer control register
+#define SPRN_TSR 0x3d8 /// Timer status register
+#define SPRN_USPRG0 0x100 /// User read/write SPR general 0
+#define SPRN_XER 0x001 /// Fixed-point exception register
+#define SPRN_ZPR 0x3b0 /// Zone protection register
+#define SPRN_UR_SPRG4 0x104 /// User-readable SPRG4 [SPRG4_R]
+#define SPRN_UR_SPRG5 0x105 /// User-readable SPRG5 [SPRG5_R]
+#define SPRN_UR_SPRG6 0x106 /// User-readable SPRG6 [SPRG6_R]
+#define SPRN_UR_SPRG7 0x107 /// User-readable SPRG7 [SPRG7_R]
+#define SPRN_UR_TBL 0x10c /// User-readable TBL [TBL, TBL_R]
+#define SPRN_UR_TBU 0x10d /// User-readable TBU [TBU, TBU_R]
+
+/// @}
+
+/// \defgroup ppc405_undocumented_sprs PowerPC 405 Undocumented SPRs
+///
+/// These are undocumented SPRs related to RISCWatch and debugging. These
+/// registers are also available in RISCWatch/eCMD.
+///
+/// - DBDR is a scratch register used by RISCwatch when "RAM-ing" data in/out of
+/// the core. This register can be read and written.
+///
+/// - DBSRS and TSRS are "hidden" registers connected to DBSR and TSR
+/// respectively. These are write-only registers. When written, any 1 bits in
+/// the write data are OR-ed into the DBSR and TSR respectively, as a way to
+/// force status bits and cause interrupts.
+///
+/// @{
+
+#define SPRN_DBDR 0x3f3 /// Debug data register 0x3f3 */
+#define SPRN_DBSRS 0x3f1 /// Debug status register set 0x3f1 */
+#define SPRN_TSRS 0x3d9 /// Timer status register set 0x3d9 */
+
+/// @}
+
+/* CCR0 - Cache Control Register 0 */
+
+#define CCR0_LWL 0x02000000 /* Load Word as Line */
+#define CCR0_LWOA 0x01000000 /* Load Without Allocate */
+#define CCR0_SWOA 0x00800000 /* Store Without Allocate */
+#define CCR0_DPP1 0x00400000 /* DCU PLB Priority Bit 1 */
+#define CCR0_IPP0 0x00200000 /* ICU PLB Priority Bit 0 */
+#define CCR0_IPP1 0x00100000 /* ICU PLB Priority Bit 1 */
+#define CCR0_DPE 0x00080000 /* Data Cache Parity Enable */
+#define CCR0_DPP 0x00040000 /* DCU Parity is Precise (0/1) */
+#define CCR0_U0XE 0x00020000 /* Enable U0 Exception */
+#define CCR0_LDBE 0x00010000 /* Load Debug Enable */
+#define CCR0_IPE 0x00002000 /* Instruction Cache Parity Enable */
+#define CCR0_TPE 0x00001000 /* TLB Parity Enable */
+#define CCR0_PFC 0x00000800 /* ICU Prefetching for Cacheable Regions */
+#define CCR0_PFNC 0x00000400 /* ICU Prefetching for Non-Cacheable Regions */
+#define CCR0_NCRS 0x00000200 /* Non-Cacheable ICU request is 16(0)/32(1)B */
+#define CCR0_FWOA 0x00000100 /* Fetch Without Allocate */
+#define CCR0_CIS 0x00000010 /* Cache Information Select Data(0)/Tag(1) */
+#define CCR0_PRS 0x00000008 /* Parity Read Select */
+#define CCR0_CWS 0x00000001 /* Cache Way Select A(0)/B(1) */
+
+/* CCR1 - Cache Control Register 1 */
+
+#define CCR1_ICTE 0x80000000 /* Instruction Cache Tag Parity Insertion */
+#define CCR1_ICDE 0x40000000 /* Instruction Cache Data Parity Insertion */
+#define CCR1_DCTE 0x20000000 /* Data Cache Tag Parity Insertion */
+#define CCR1_DCDE 0x10000000 /* Data Cache Data Parity Insertion */
+#define CCR1_TLBE 0x08000000 /* TLB Parity Insertion */
+
+/* DBCR0 - Debug Control Register 0 */
+
+#define DBCR0_EDM 0x80000000 /* External Debug Mode */
+#define DBCR0_IDM 0x40000000 /* Internal Debug Mode */
+#define DBCR0_RST_MASK 0x30000000 /* ReSeT */
+#define DBCR0_RST_NONE 0x00000000 /* No action */
+#define DBCR0_RST_CORE 0x10000000 /* Core reset */
+#define DBCR0_RST_CHIP 0x20000000 /* Chip reset */
+#define DBCR0_RST_SYSTEM 0x30000000 /* System reset */
+#define DBCR0_IC 0x08000000 /* Instruction Completion debug event */
+#define DBCR0_BT 0x04000000 /* Branch Taken debug event */
+#define DBCR0_EDE 0x02000000 /* Exception Debug Event */
+#define DBCR0_TDE 0x01000000 /* Trap Debug Event */
+#define DBCR0_IA1 0x00800000 /* IAC (Instruction Address Compare) 1 debug event */
+#define DBCR0_IA2 0x00400000 /* IAC 2 debug event */
+#define DBCR0_IA12 0x00200000 /* Instruction Address Range Compare 1-2 */
+#define DBCR0_IA12X 0x00100000 /* IA12 eXclusive */
+#define DBCR0_IA3 0x00080000 /* IAC 3 debug event */
+#define DBCR0_IA4 0x00040000 /* IAC 4 debug event */
+#define DBCR0_IA34 0x00020000 /* Instruction Address Range Compare 3-4 */
+#define DBCR0_IA34X 0x00010000 /* IA34 eXclusive */
+#define DBCR0_IA12T 0x00008000 /* Instruction Address Range Compare 1-2 range Toggle */
+#define DBCR0_IA34T 0x00004000 /* Instruction Address Range Compare 3-4 range Toggle */
+#define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */
+
+/* DBSR - Debug Status Register */
+
+#define DBSR_IC 0x80000000 /* Instruction completion debug event */
+#define DBSR_BT 0x40000000 /* Branch Taken debug event */
+#define DBSR_EDE 0x20000000 /* Exception debug event */
+#define DBSR_TIE 0x10000000 /* Trap Instruction debug event */
+#define DBSR_UDE 0x08000000 /* Unconditional debug event */
+#define DBSR_IA1 0x04000000 /* IAC1 debug event */
+#define DBSR_IA2 0x02000000 /* IAC2 debug event */
+#define DBSR_DR1 0x01000000 /* DAC1 Read debug event */
+#define DBSR_DW1 0x00800000 /* DAC1 Write debug event */
+#define DBSR_DR2 0x00400000 /* DAC2 Read debug event */
+#define DBSR_DW2 0x00200000 /* DAC2 Write debug event */
+#define DBSR_IDE 0x00100000 /* Imprecise debug event */
+#define DBSR_IA3 0x00080000 /* IAC3 debug event */
+#define DBSR_IA4 0x00040000 /* IAC4 debug event */
+#define DBSR_MRR 0x00000300 /* Most recent reset */
+
+/* TCR - Timer Control Register */
+
+#define TCR_WP_MASK 0xc0000000 /* Watchdog Period mask */
+#define TCR_WP_2_17 0x00000000 /* 2**17 clocks */
+#define TCR_WP_2_21 0x40000000 /* 2**21 clocks */
+#define TCR_WP_2_25 0x80000000 /* 2**25 clocks */
+#define TCR_WP_2_29 0xc0000000 /* 2**29 clocks */
+#define TCR_WRC_MASK 0x30000000 /* Watchdog Reset Control mask */
+#define TCR_WRC_NONE 0x00000000 /* No watchdog reset */
+#define TCR_WRC_CORE 0x10000000 /* Core reset */
+#define TCR_WRC_CHIP 0x20000000 /* Chip reset */
+#define TCR_WRC_SYSTEM 0x30000000 /* System reset */
+#define TCR_WIE 0x08000000 /* Watchdog Interrupt Enable */
+#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */
+#define TCR_FP_MASK 0x03000000 /* FIT Period */
+#define TCR_FP_2_9 0x00000000 /* 2**9 clocks */
+#define TCR_FP_2_13 0x01000000 /* 2**13 clocks */
+#define TCR_FP_2_17 0x02000000 /* 2**17 clocks */
+#define TCR_FP_2_21 0x03000000 /* 2**21 clocks */
+#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */
+#define TCR_ARE 0x00400000 /* Auto-reload Enable */
+
+#ifndef __ASSEMBLER__
+
+typedef union {
+ uint32_t value;
+ struct {
+ unsigned int wp : 2;
+ unsigned int wrc : 2;
+ unsigned int wie : 1;
+ unsigned int pie : 1;
+ unsigned int fp : 2;
+ unsigned int fie : 1;
+ unsigned int are : 1;
+ unsigned int reserved : 22;
+ } fields;
+} Ppc405TCR;
+
+#endif /* __ASSEMBLER__ */
+
+/* TSR - Timer Status Register */
+
+#define TSR_ENW 0x80000000 /* Enable Next Watchdog */
+#define TSR_WIS 0x40000000 /* Watchdog Interrupt Status */
+#define TSR_WRS_MASK 0x30000000 /* Watchdog Reset Status */
+#define TSR_WRS_NONE 0x00000000 /* No watchdog reset has occurred */
+#define TSR_WRS_CORE 0x10000000 /* Core reset was forced by the watchdog */
+#define TSR_WRS_CHIP 0x20000000 /* Chip reset was forced by the watchdog */
+#define TSR_WRS_SYSTEM 0x30000000 /* System reset was forced by the watchdog */
+#define TSR_PIS 0x08000000 /* PIT Interrupt Status */
+#define TSR_FIS 0x04000000 /* FIT Interrupt Status */
+
+#ifndef __ASSEMBLER__
+
+/// Move From SPR
+///
+/// Note that \a sprn must be a compile-time constant.
+
+#define mfspr(sprn) \
+ ({uint32_t __value; \
+ asm volatile ("mfspr %0, %1" : "=r" (__value) : "i" (sprn)); \
+ __value;})
+
+
+/// Move to SPR
+///
+/// Note that \a sprn must be a compile-time constant.
+
+#define mtspr(sprn, value) \
+ ({uint32_t __value = (value); \
+ asm volatile ("mtspr %0, %1" : : "i" (sprn), "r" (__value)); \
+ })
+
+
+/// Read-Modify-Write an SPR with OR (Set SPR bits)
+///
+/// Note that \a sprn must be a compile-time constant. This operation is only
+/// guaranteed atomic in a critical section.
+
+#define or_spr(sprn, x) \
+ mtspr(sprn, mfspr(sprn) | (x))
+
+
+/// Read-Modify-Write an SPR with AND complement (Clear SPR bits)
+///
+/// Note that \a sprn must be a compile-time constant. This operation is only
+/// guaranteed atomic in a critical section.
+
+#define andc_spr(sprn, x) \
+ mtspr(sprn, mfspr(sprn) & ~(x))
+
+
+/// Move From Time Base (Lower)
+
+#define mftb() mfspr(SPRN_TBL)
+
+/// Move To Time Base (Lower)
+
+#define mttbl(x) mtspr(SPRN_TBL, (x))
+
+/// Move From Time Base (Upper)
+
+#define mftbu() mfspr(SPRN_TBU)
+
+/// Move To Time Base (UPPER)
+
+#define mttbu(x) mtspr(SPRN_TBU, (x))
+
+#endif /* __ASSEMBLER__ */
+
+#ifdef __ASSEMBLER__
+
+ /// \cond
+
+ // Use this macro to define new mt<spr> and mf<spr> instructions that
+ // may not exist in the assembler.
+
+ .macro _sprinstrs, name, num
+ .macro mt\name, reg
+ mtspr \num, \reg
+ .endm
+ .macro mf\name, reg
+ mfspr \reg, \num
+ .endm
+ .endm
+
+ _sprinstrs ccr0, SPRN_CCR0
+ _sprinstrs ccr1, SPRN_CCR1
+ _sprinstrs dbcr0, SPRN_DBCR0
+ _sprinstrs dbcr1, SPRN_DBCR1
+ _sprinstrs dcwr, SPRN_DCWR
+ _sprinstrs mcsr, SPRN_MCSR
+ _sprinstrs pid, SPRN_PID
+ _sprinstrs sgr, SPRN_SGR
+ _sprinstrs sler, SPRN_SLER
+ _sprinstrs su0r, SPRN_SU0R
+ _sprinstrs usprg0, SPRN_USPRG0
+
+ /// \endcond
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPC405_SPR_H__ */
diff --git a/src/ssx/ppc405/ppc405_thread_init.S b/src/ssx/ppc405/ppc405_thread_init.S
new file mode 100755
index 0000000..47f5813
--- /dev/null
+++ b/src/ssx/ppc405/ppc405_thread_init.S
@@ -0,0 +1,126 @@
+// $Id: ppc405_thread_init.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+
+/// \file ppc405_thread_init.S
+/// \brief PPC405-specific thread initialization
+///
+/// The entry points in this file are routines that are typically used during
+/// initialization, and their code space could be deallocated and recovered if
+/// no longer needed by the application after initialization.
+
+ .nolist
+#include "ssx.h"
+ .list
+
+/// \fn void __ssx_thread_context_initialize(SsxThread *thread, SsxThreadRoutine thread_routine, void *private)
+/// \brief Create the initial thread context on the stack
+///
+/// The non-reserved GPRs are prepatterned with 0x0000\<rn\>\<rn\> where \<rn\> is
+/// the register number (as decimal). The initial context is set up with the
+/// thread running in the default machine context, and when the thread is
+/// switched in it will begin executing at the entry point of the thread
+/// routine with the \c private parameter in R3. The LR is initialized such
+/// that when the thread returns, it will return to the entry point of \c
+/// ssx_complete().
+#ifdef DOXYGEN_ONLY
+void
+__ssx_thread_context_initialize(SsxThread *thread,
+ SsxThreadRoutine thread_routine,
+ void *private);
+#endif// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_thread_init.S,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \cond
+
+ .global_function __ssx_thread_context_initialize
+
+__ssx_thread_context_initialize:
+
+ ## R3 = thread (param)
+ ## R4 = thread_routine (param)
+ ## R5 = private (param)
+ ## R6 = thread stack pointer (computed)
+ ## R7 = scratch
+
+ .macro _gpr_init, prefix, reg, val
+ li %r7, \val
+ stw %r7, \prefix\reg(%r6)
+ .endm
+
+ ## Initialize a fast context on the thread stack. The CR is cleared,
+ ## the LR = ssx_complete(), R3 has the private parameter.
+
+ lwz %r6, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3)
+
+ stwu %r6, -SSX_FAST_CTX_SIZE(%r6)
+
+ li %r7, 0
+ stw %r7, SSX_FAST_CTX_CR(%r6)
+
+ _liw %r7, ssx_complete
+ stw %r7, SSX_FAST_CTX_LR(%r6)
+
+ stw %r5, SSX_FAST_CTX_GPR3(%r6)
+
+ _gpr_init SSX_FAST_CTX_GPR, 4, 0x0404
+ _gpr_init SSX_FAST_CTX_GPR, 5, 0x0505
+ _gpr_init SSX_FAST_CTX_GPR, 6, 0x0606
+ _gpr_init SSX_FAST_CTX_GPR, 7, 0x0707
+
+ ## Initialize the (volatile - fast) context on the thread stack. XER
+ ## and CTR are clear, SRR0 = thread_routine, SRR1 = default machine
+ ## context.
+
+ stwu %r6, -SSX_VOL_FAST_CTX_SIZE(%r6)
+
+ li %r7, 0
+ stw %r7, SSX_VOL_FAST_CTX_XER(%r6)
+ stw %r7, SSX_VOL_FAST_CTX_CTR(%r6)
+
+ stw %r4, SSX_VOL_FAST_CTX_SRR0(%r6)
+
+ _lwzsd %r7, __ssx_thread_machine_context_default
+ stw %r7, SSX_VOL_FAST_CTX_SRR1(%r6)
+
+ _gpr_init SSX_VOL_FAST_CTX_GPR, 0, 0x0000
+ _gpr_init SSX_VOL_FAST_CTX_GPR, 8, 0x0808
+ _gpr_init SSX_VOL_FAST_CTX_GPR, 9, 0x0909
+ _gpr_init SSX_VOL_FAST_CTX_GPR, 10, 0x1010
+ _gpr_init SSX_VOL_FAST_CTX_GPR, 11 0x1111
+ _gpr_init SSX_VOL_FAST_CTX_GPR, 12 0x1212
+
+ ## Initialize the non-volatile context on the thread stack.
+
+ stwu %r6, -SSX_NON_VOL_CTX_SIZE(%r6)
+
+ _gpr_init SSX_NON_VOL_CTX_GPR, 14, 0x1414
+ _gpr_init SSX_NON_VOL_CTX_GPR, 15, 0x1515
+ _gpr_init SSX_NON_VOL_CTX_GPR, 16, 0x1616
+ _gpr_init SSX_NON_VOL_CTX_GPR, 17, 0x1717
+ _gpr_init SSX_NON_VOL_CTX_GPR, 18, 0x1818
+ _gpr_init SSX_NON_VOL_CTX_GPR, 19, 0x1919
+ _gpr_init SSX_NON_VOL_CTX_GPR, 20, 0x2020
+ _gpr_init SSX_NON_VOL_CTX_GPR, 21, 0x2121
+ _gpr_init SSX_NON_VOL_CTX_GPR, 22, 0x2222
+ _gpr_init SSX_NON_VOL_CTX_GPR, 23, 0x2323
+ _gpr_init SSX_NON_VOL_CTX_GPR, 24, 0x2424
+ _gpr_init SSX_NON_VOL_CTX_GPR, 25, 0x2525
+ _gpr_init SSX_NON_VOL_CTX_GPR, 26, 0x2626
+ _gpr_init SSX_NON_VOL_CTX_GPR, 27, 0x2727
+ _gpr_init SSX_NON_VOL_CTX_GPR, 28, 0x2828
+ _gpr_init SSX_NON_VOL_CTX_GPR, 29, 0x2929
+ _gpr_init SSX_NON_VOL_CTX_GPR, 30, 0x3030
+ _gpr_init SSX_NON_VOL_CTX_GPR, 31, 0x3131
+
+ ## Initialization is done - the stack pointer is stored back in the
+ ## thread.
+
+ stw %r6, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3)
+ blr
+
+ .epilogue __ssx_thread_context_initialize
+
+/// \endcond
diff --git a/src/ssx/ppc405/ssx_port_types.h b/src/ssx/ppc405/ssx_port_types.h
new file mode 100755
index 0000000..f57951d
--- /dev/null
+++ b/src/ssx/ppc405/ssx_port_types.h
@@ -0,0 +1,44 @@
+#ifndef __SSX_PORT_TYPES_H__
+#define __SSX_PORT_TYPES_H__
+
+// $Id: ssx_port_types.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ssx_port_types.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_port_types.h
+/// \brief Type definitions required by the SSX port.
+///
+/// \todo GCC provides a portable version of cntlzw called __builtin_clz().
+/// We should make the SSX priority queues portable by using this facility.
+///
+/// \todo I think that if more of the port-dependent types were moved here, we
+/// could break the circular dependencies in some of the header inclusion and
+/// simplify the way the SSX/port/chip headers are included.
+
+/// An SsxIrqId is an integer in the range of valid interrupts defined by the
+/// interrupt controller.
+
+typedef uint8_t SsxIrqId;
+
+/// SSX requires the port to define the type SsxThreadQueue, which is a
+/// priority queue (where 0 is the highest priority). This queue must be able
+/// to handle SSX_THREADS + 1 priorities (the last for the idle thread). The
+/// port must also define methods for clearing, insertion, deletion and min
+/// (with assumed legal priorities). The min operation returns SSX_THREADS if
+/// the queue is empty. (Or a queue could be initialized with the SSX_THREADS
+/// entry always present - SSX code never tries to delete the idle thread from
+/// a thread queue).
+///
+/// These queues are used both for the run queue and the pending queue
+/// associated with every semaphore.
+///
+/// On PPC405 with 32 threads (implied), this is a job for a uint32_t and
+/// cntlzw().
+
+typedef uint32_t SsxThreadQueue;
+
+#endif /* __SSX_PORT_TYPES_H__ */
diff --git a/src/ssx/ppc405/ssxppc405files.mk b/src/ssx/ppc405/ssxppc405files.mk
new file mode 100755
index 0000000..72d5ecb
--- /dev/null
+++ b/src/ssx/ppc405/ssxppc405files.mk
@@ -0,0 +1,53 @@
+# $Id: ssxppc405files.mk,v 1.2 2014/06/26 13:00:55 cmolsen Exp $
+# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ssxppc405files.mk,v $
+# @file ssxppc405files.mk
+#
+# @brief mk for including ppc405 object files
+#
+# @page ChangeLogs Change Logs
+# @section ssxppc405files.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/11/2012 Makefile ODE support
+#
+# @endverbatim
+#
+##########################################################################
+# Include Files
+##########################################################################
+
+
+
+##########################################################################
+# Object Files
+##########################################################################
+PPC405-C-SOURCES = ppc405_core.c \
+ ppc405_lib_core.c \
+ ppc405_cache_core.c \
+ ppc405_init.c \
+ ppc405_irq_core.c \
+ ppc405_irq_init.c
+
+PPC405-S-SOURCES = ppc405_boot.S \
+ ppc405_exceptions.S \
+ ppc405_cache_init.S \
+ ppc405_mmu_asm.S \
+ ppc405_breakpoint.S
+
+PPC405-TIMER-C-SOURCES =
+PPC405-TIMER-S-SOURCES =
+
+PPC405-THREAD-C-SOURCES +=
+PPC405-THREAD-S-SOURCES += ppc405_thread_init.S
+
+PPC405-MMU-C-SOURCES += ppc405_mmu.c
+PPC405-MMU-S-SOURCES +=
+
+PPC405_OBJECTS += $(PPC405-C-SOURCES:.c=.o) $(PPC405-S-SOURCES:.S=.o)
+
+
+
diff --git a/src/ssx/ssx/Makefile b/src/ssx/ssx/Makefile
new file mode 100755
index 0000000..ce1116f
--- /dev/null
+++ b/src/ssx/ssx/Makefile
@@ -0,0 +1,25 @@
+# $Id: Makefile,v 1.2 2013/12/12 16:12:38 bcbrock Exp $
+
+# This Makefile is designed to be invoked with the -I argument set to
+# the location of the "ssx.mk" for the build
+
+include ../pgp/ssx.mk
+include ssxssxfiles.mk
+
+ifeq "$(SSX_TIMER_SUPPORT)" "1"
+SSX_OBJECTS += ${SSX-TIMER-C-SOURCES:.c=.o}
+endif
+
+ifeq "$(SSX_THREAD_SUPPORT)" "1"
+SSX_OBJECTS += ${SSX-THREAD-C-SOURCES:.c=.o}
+endif
+
+all: $(SSX_OBJECTS)
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.*
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(SSX_OBJECTS:.o=.d)
+endif
diff --git a/src/ssx/ssx/ssx.h b/src/ssx/ssx/ssx.h
new file mode 100755
index 0000000..5470968
--- /dev/null
+++ b/src/ssx/ssx/ssx.h
@@ -0,0 +1,126 @@
+#ifndef __SSX_H__
+#define __SSX_H__
+
+// $Id: ssx.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx.h
+/// \brief The combined header of the SSX kernel.
+///
+/// This header will be included in any C or assembler source file that
+/// requires any of the SSX API. All headers defined by SSX and co-compiled
+/// code should be protected such that they can be included without error into
+/// assembly.
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#include <stddef.h>
+#endif /* __ASSEMBLER__ */
+
+#define __SSX__
+
+/// The application environment specifies whether or not it will provide an
+/// application configuration file, which must be named "ssx_app_cfg.h".
+
+#ifndef USE_SSX_APP_CFG_H
+#define USE_SSX_APP_CFG_H 0
+#endif
+
+#if USE_SSX_APP_CFG_H
+#include "ssx_app_cfg.h"
+#endif
+
+#include "ssx_macros.h"
+#include "ssx_api.h"
+#include "ssx_port.h"
+#include "ssx_kernel.h"
+#include "ssx_io.h"
+
+#ifndef __ASSEMBLER__
+
+#define MIN(X, Y) \
+ ({ \
+ typeof (X) __x = (X); \
+ typeof (Y) __y = (Y); \
+ (__x < __y) ? __x : __y; })
+
+#define MAX(X, Y) \
+ ({ \
+ typeof (X) __x = (X); \
+ typeof (Y) __y = (Y); \
+ (__x > __y) ? __x : __y; \
+ })
+
+/// \todo These don't require 32/64 bit versions, can always promote 32->64.
+
+#define FLOOR_LOG2_32(x) (32 - 1 - cntlz32(x))
+#define FLOOR_LOG2_64(x) (64 - 1 - cntlz64(x))
+
+#define CEILING_LOG2(x) \
+ ({ \
+ uint64_t __x = (uint64_t)(x); \
+ int __y; \
+ __y = FLOOR_LOG2_64(__x); \
+ if ((__x & (__x - 1)) != 0) { \
+ __y++; \
+ } \
+ __y;})
+
+
+#define POW2_32(x) ((uint32_t)1 << (x))
+#define POW2_64(x) ((uint64_t)1 << (x))
+
+/// Cast a pointer to another type
+///
+/// This macro is necessary when casting a pointer to a longer integer type.
+/// The pointer is first cast to the equivalent integer type 'unsigned long',
+/// then cast to the final type. You can also use this to cast integers longer
+/// than pointers back to pointers.
+
+#define CAST_POINTER(t, p) ((t)((unsigned long)(p)))
+
+
+/// Create an alignment attribute.
+#define ALIGNED_ATTRIBUTE(alignment) __attribute__ ((aligned (alignment)))
+
+/// Create a specific-section attribute
+///
+/// Note that the section \a s here must be a string. Also note that data
+/// specified to reside in specific sections must always be
+/// initialized. Otherwise it confuses the linker which wants to put
+/// uninitialized data into .bss sections.
+///
+/// \code
+///
+/// int foo SECTION_ATTRIBUTE(".noncacheable") = 0;
+/// int bar[10] SECTION_ATTRIBUTE(".noncacheable") = {0};
+///
+/// \endcode
+#define SECTION_ATTRIBUTE(s) __attribute__ ((section (s)))
+
+/// Create a 'used' attribute
+///
+/// This is required for example to avoid "function unused" warnings when a
+/// function is declared static but only referenced by inline assembler:
+///
+/// \code
+///
+/// static USED_ATTRIBUTE void
+/// _checkstop(void* arg, SsxIrqId irq, int priority)
+/// {
+/// SSX_PANIC(VALIDATION_CHECKSTOP);
+/// }
+///
+/// SSX_IRQ_FAST2FULL(_validationCheckstopHandler, _checkstop);
+///
+/// \endcode
+#define USED_ATTRIBUTE __attribute__ ((used))
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __SSX_H__ */
diff --git a/src/ssx/ssx/ssx_api.h b/src/ssx/ssx/ssx_api.h
new file mode 100755
index 0000000..c9657e4
--- /dev/null
+++ b/src/ssx/ssx/ssx_api.h
@@ -0,0 +1,888 @@
+#ifndef __SSX_API_H__
+#define __SSX_API_H__
+
+// $Id: ssx_api.h,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_api.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_api.h
+/// \brief Macros and declarations for the SSX API.
+
+// Basic constants
+
+/// Although the number of threads is defined as a manifest constant,
+/// numerous parts of the SSX code assume this definition. The number of
+/// supported threads _can not_ be changed simply by changing this constant.
+
+#define SSX_THREADS 32
+
+#define SSX_IDLE_THREAD_PRIORITY SSX_THREADS
+
+// Interrupt API
+
+#define SSX_NONCRITICAL 0
+#define SSX_CRITICAL 1
+#define SSX_SUPERCRITICAL 2
+
+#define SSX_IRQ_POLARITY_ACTIVE_LOW 0
+#define SSX_IRQ_POLARITY_ACTIVE_HIGH 1
+
+#define SSX_IRQ_TRIGGER_LEVEL_SENSITIVE 0
+#define SSX_IRQ_TRIGGER_EDGE_SENSITIVE 1
+
+// API return codes
+
+#define SSX_OK 0
+#define SSX_ILLEGAL_CONTEXT_CRITICAL_INTERRUPT 0x00779001
+#define SSX_ILLEGAL_CONTEXT_THREAD_CONTEXT 0x00779002
+#define SSX_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT 0x00779003
+#define SSX_ILLEGAL_CONTEXT_THREAD 0x00779004
+#define SSX_ILLEGAL_CONTEXT_TIMER 0x00779005
+#define SSX_ILLEGAL_CONTEXT_PPC405_CACHE 0x00779006
+#define SSX_INVALID_THREAD_AT_RESUME1 0x00779007
+#define SSX_INVALID_THREAD_AT_RESUME2 0x00779008
+#define SSX_INVALID_THREAD_AT_SUSPEND1 0x00779009
+#define SSX_INVALID_THREAD_AT_SUSPEND2 0x0077900a
+#define SSX_INVALID_THREAD_AT_DELETE 0x0077900b
+#define SSX_INVALID_THREAD_AT_INFO 0x0077900c
+#define SSX_INVALID_THREAD_AT_CHANGE 0x0077900d
+#define SSX_INVALID_THREAD_AT_SWAP1 0x0077900e
+#define SSX_INVALID_THREAD_AT_SWAP2 0x0077900f
+#define SSX_INVALID_THREAD_AT_CREATE 0x00779010
+#define SSX_INVALID_SEMAPHORE_AT_POST 0x00779011
+#define SSX_INVALID_SEMAPHORE_AT_PEND 0x00779012
+#define SSX_INVALID_SEMAPHORE_AT_RELEASE 0x00779013
+#define SSX_INVALID_SEMAPHORE_AT_INFO 0x00779014
+#define SSX_INVALID_SEMAPHORE_AT_CREATE 0x00779015
+#define SSX_INVALID_TIMER_AT_SCHEDULE 0x00779016
+#define SSX_INVALID_TIMER_AT_CANCEL 0x00779017
+#define SSX_INVALID_TIMER_AT_INFO 0x00779018
+#define SSX_INVALID_TIMER_AT_CREATE 0x00779019
+#define SSX_INVALID_ARGUMENT_IRQ_SETUP 0x0077901a
+#define SSX_INVALID_ARGUMENT_IRQ_HANDLER 0x0077901b
+#define SSX_INVALID_ARGUMENT_INTERRUPT 0x00779024
+#define SSX_INVALID_ARGUMENT_CONTEXT_SET 0x00779025
+#define SSX_INVALID_ARGUMENT_CONTEXT_GET 0x00779026
+#define SSX_INVALID_ARGUMENT_PPC405_FIT 0x00779027
+#define SSX_INVALID_ARGUMENT_PPC405_WATCHDOG 0x00779028
+#define SSX_INVALID_ARGUMENT_INIT 0x00779029
+#define SSX_INVALID_ARGUMENT_SEMAPHORE 0x0077902a
+#define SSX_INVALID_ARGUMENT_THREAD_CHANGE 0x0077902b
+#define SSX_INVALID_ARGUMENT_THREAD_PRIORITY 0x0077902c
+#define SSX_INVALID_ARGUMENT_THREAD1 0x0077902d
+#define SSX_INVALID_ARGUMENT_THREAD2 0x0077902e
+#define SSX_INVALID_ARGUMENT_THREAD3 0x0077902f
+#define SSX_STACK_OVERFLOW 0x00779030
+#define SSX_TIMER_ACTIVE 0x00779031
+#define SSX_TIMER_NOT_ACTIVE 0x00779032
+#define SSX_PRIORITY_IN_USE_AT_RESUME 0x00779033
+#define SSX_PRIORITY_IN_USE_AT_CHANGE 0x00779034
+#define SSX_PRIORITY_IN_USE_AT_SWAP 0x00779035
+#define SSX_SEMAPHORE_OVERFLOW 0x00779036
+#define SSX_SEMAPHORE_PEND_NO_WAIT 0x00779037
+#define SSX_SEMAPHORE_PEND_TIMED_OUT 0x00779038
+#define SSX_SEMAPHORE_PEND_WOULD_BLOCK 0x00779039
+#define SSX_INVALID_DEQUE_SENTINEL 0x0077903a
+#define SSX_INVALID_DEQUE_ELEMENT 0x0077903b
+#define SSX_INVALID_OBJECT 0x0077903c
+
+// Kernel panics
+
+#define SSX_NO_TIMER_SUPPORT 0x0077903d
+#define SSX_START_THREADS_RETURNED 0x0077903e
+#define SSX_UNIMPLEMENTED 0x0077903f
+#define SSX_SCHEDULING_INVARIANT 0x00779040
+#define SSX_TIMER_HANDLER_INVARIANT 0x00779041
+#define SSX_THREAD_TIMEOUT_STATE 0x00779045
+
+
+/// \defgroup ssx_thread_states SSX Thread States
+///
+/// Threads are created in the state SSX_THREAD_STATE_SUSPENDED_RUNNABLE.
+/// When the thread is mapped it transitions to state SSX_THREAD_STATE_MAPPED.
+/// A mapped thread is runnable if it appears in the run queue; there is no
+/// other flag or status to indicate a runnable thread. If a blocked thread
+/// is suspended it goes into state SSX_THREAD_STATE_SUSPENDED_BLOCKED. For
+/// all threads the reason for blockage is detailed in the \a flags field of
+/// the thread; See \ref ssx_thread_flags. SSX_THREAD_STATE_DELETED and
+/// SSX_THREAD_STATE_COMPLETED are effectively equivalent but named
+/// individually for reporting purposes.
+///
+/// \note This separation of the thread \a state and \a flags allows the use
+/// of an SSX semaphore as a thread barrier, as it supports a non-iterative
+/// implementation of ssx_semaphore_release_all() in which all threads blocked
+/// on the semaphore are simultaneously inserted into the run queue with an
+/// atomic operation, followed by each individual thread readjusting its flags
+/// appropriately once the thread runs again.
+///
+/// @{
+
+#define SSX_THREAD_STATE_SUSPENDED_RUNNABLE 1
+#define SSX_THREAD_STATE_MAPPED 2
+#define SSX_THREAD_STATE_SUSPENDED_BLOCKED 3
+#define SSX_THREAD_STATE_COMPLETED 4
+#define SSX_THREAD_STATE_DELETED 5
+
+/// @}
+
+
+/// \defgroup ssx_thread_flags SSX Thread Flags
+///
+/// The \a flag field of the thread extends the information contained in the
+/// \a state field; See \ref ssx_thread_states. Blocked threads will show
+/// SSX_THREAD_FLAG_SEMAPHORE_PEND, SSX_THREAD_FLAG_TIMER_PEND or both (if
+/// blocked on a semaphore with timeout). The flag SSX_THREAD_FLAG_TIMED_OUT
+/// indicates that a thread timer timed out before the thread became
+/// runnable. Currently only the semaphore-pend-with-timeout code uses this
+/// flag.
+///
+/// Note that a thread can be mapped and runnable (in the run queue) even
+/// though SSX_THREAD_FLAG_SEMAPHORE_PEND and/or SSX_THREAD_FLAG_TIMER_PEND
+/// are set. These flags are always cleared by the thread itself, not the code
+/// that unblocks the thread. This allows the implementation of the
+/// ssx_semaphore_release_all() as explained in \ref ssx_thread_states.
+///
+/// @{
+
+#define SSX_THREAD_FLAG_SEMAPHORE_PEND 0x1
+#define SSX_THREAD_FLAG_TIMER_PEND 0x2
+#define SSX_THREAD_FLAG_TIMED_OUT 0x4
+
+/// @}
+
+
+// Critical Sections
+
+/// Enter a critical section of a given priority, saving the current machine
+/// context.
+
+#define ssx_critical_section_enter(priority, pctx) \
+ ssx_interrupt_disable(priority, pctx)
+
+/// Exit a critical section by restoring the previous machine context.
+
+#define ssx_critical_section_exit(pctx) \
+ ssx_machine_context_set(pctx)
+
+
+/// Execute a statement atomically, in a particular interrupt priority
+/// context.
+
+#define SSX_ATOMIC(priority, stmt) \
+ do { \
+ SsxMachineContext __ctx; \
+ ssx_critical_section_enter((priority), &__ctx); \
+ stmt; \
+ ssx_critical_section_exit(&__ctx); \
+ } while (0)
+
+
+// Application-overrideable definitions
+
+/// Control whether or not the API functions check for errors.
+///
+/// This definition can be overriden by the application.
+
+#ifndef SSX_ERROR_CHECK_API
+#define SSX_ERROR_CHECK_API 1
+#endif
+
+/// Control whether API errors cause kernel panics or return negative error
+/// codes.
+///
+/// This selection is only valid if \c SSX_ERROR_CHECK_API is defined
+/// non-0. This definition can be overriden by the application.
+
+#ifndef SSX_ERROR_PANIC
+#define SSX_ERROR_PANIC 1
+#endif
+
+/// Control whether or not the SSX kernel checks key invariants.
+///
+/// Violations of kernel invariants always cause kernel panics. This
+/// definition can be overriden by the application.
+
+#ifndef SSX_ERROR_CHECK_KERNEL
+#define SSX_ERROR_CHECK_KERNEL 1
+#endif
+
+/// Define the time interval type, which must be an unsigned type of a size
+/// less then or equal to the size of \c SsxTimebase. This definition can be
+/// overridden by the application.
+
+#ifndef SSX_TIME_INTERVAL_TYPE
+#define SSX_TIME_INTERVAL_TYPE uint32_t
+#endif
+
+/// Provide support for the SsxTimer APIs in addition to the default
+/// initerrupt APIs. This definition can be overridden by the application.
+
+#ifndef SSX_TIMER_SUPPORT
+#define SSX_TIMER_SUPPORT 1
+#endif
+
+/// Provide support for the all SSX APIs. Thread support requires/implies
+/// support for time services and semaphores. This definition can be
+/// overridden by the application.
+
+#ifndef SSX_THREAD_SUPPORT
+#define SSX_THREAD_SUPPORT 1
+#endif
+
+/// Control the level of stack checking.
+///
+/// This definition can be overriden by the application.
+///
+/// 0 : No stack prepatterning or checking is made for thread and kernel
+/// stacks.
+///
+/// 1 : Kernel interrupt stacks are prepatterned during
+/// \c ssx_initialize(). Thread stacks are prepatterned during
+/// \c ssx_thread_create().
+///
+/// 2 : (\b Default - Currently Unimplemented) In addition to prepatterning,
+/// stack utilization is computed at the exit of context switches and
+/// noncritical interrupt processing. The maximum utilization is stored in
+/// the thread data structure. The kernel will panic if stack overflow is
+/// detected. Stack utilization is not computed for the idle thread.
+
+#ifndef SSX_STACK_CHECK
+#define SSX_STACK_CHECK 1
+#endif
+
+/// A hook for main()
+///
+/// This hook macro is expanded in the body of __ssx_main() prior to the call
+/// of the application main(). The application can redefine this hook macro
+/// in (or in headers referred to in) the application header
+/// ssx_app_cfg.h. The SSX_MAIN_HOOK will run on the stack of main().
+
+#ifndef SSX_MAIN_HOOK
+#define SSX_MAIN_HOOK do {} while (0)
+#endif
+
+/// A hook for ssx_start_threads()
+///
+/// This hook macro is expanded in the call-tree of ssx_start_threads() before
+/// threads are actually started. The application can redefine this hook
+/// macro in (or in headers referred to in) the application header
+/// ssx_app_cfg.h.
+///
+/// The SSX_START_THREADS_HOOK runs as a pseudo-interrupt handler on the
+/// noncritical interrupt stack, with noncritical interrupts disabled.
+
+#ifndef SSX_START_THREADS_HOOK
+#define SSX_START_THREADS_HOOK do {} while (0)
+#endif
+
+/// The maximum value of the \c SsxTimebase type.
+
+#define SSX_TIMEBASE_MAX ((SsxTimebase)-1)
+
+/// A special value that specifies that the timebase will not be reset during
+/// ssx_init().
+
+#define SSX_TIMEBASE_CONTINUES SSX_TIMEBASE_MAX
+
+/// By convention, a timeout value indicating 'no waiting' in a call of \c
+/// ssx_semaphore_pend().
+
+#define SSX_NO_WAIT 0
+
+/// By convention, a timeout value indicating 'wait forever' in a call of \c
+/// ssx_semaphore_pend().
+
+#define SSX_WAIT_FOREVER ((SsxInterval)-1)
+
+/// The SSX timebase frequency in Hz
+///
+/// Earlier version of SSX defined the timbase frequency as a preprocessor
+/// macro. Now, the timebase frequency is specified as a parameter of the
+/// ssx_initialize() API. The macro remains defined for backwards
+/// compatibility, however all kernel uses of the timebase frequency are now
+/// optimized around the timebase parameter.
+
+#define SSX_TIMEBASE_FREQUENCY_HZ __ssx_timebase_frequency_hz
+
+/// Convert a time in integral seconds to a time interval - overflows are
+/// ignored. The application can redefine this macro.
+
+#ifndef SSX_SECONDS
+#define SSX_SECONDS(s) ((SsxInterval)(__ssx_timebase_frequency_hz * (SsxInterval)(s)))
+#endif
+
+/// Convert a time in integral milliseconds to a time interval - overflows are
+/// ignored, and a frequency evenly (or closely) divisible by 1000 is
+/// assumed. The application can redefine this macro.
+
+#ifndef SSX_MILLISECONDS
+#define SSX_MILLISECONDS(m) ((SsxInterval)(__ssx_timebase_frequency_khz * (SsxInterval)(m)))
+#endif
+
+/// Convert a time in integral microseconds to a time interval - overflows are
+/// ignored, and a frequncy evenly (or closely) divisible by 1,000,000 is
+/// assumed. The application can redefine this macro.
+
+#ifndef SSX_MICROSECONDS
+#define SSX_MICROSECONDS(u) ((SsxInterval)(__ssx_timebase_frequency_mhz * (SsxInterval)(u)))
+#endif
+
+/// Convert a time in integral nanoseconds to a time interval - overflows are
+/// ignored, and a frequeyncy evenly (or closely) divisible by 1,000,000 is
+/// assumed. The application can redefine this macro.
+
+#ifndef SSX_NANOSECONDS
+#define SSX_NANOSECONDS(n) \
+ ((SsxInterval)((__ssx_timebase_frequency_mhz * (SsxInterval)(n)) / 1000))
+#endif
+
+
+// Application and kernel tracing. Tracing can only be enabled if the port
+// defines the trace macros in that case.
+
+/// Enable SSX application tracing
+#ifndef SSX_TRACE_ENABLE
+#define SSX_TRACE_ENABLE 0
+#endif
+
+/// Enable SSX kernel tracing
+#ifndef SSX_KERNEL_TRACE_ENABLE
+#define SSX_KERNEL_TRACE_ENABLE 0
+#endif
+
+#if !SSX_TRACE_ENABLE
+#define SSX_TRACE(event)
+#endif
+
+#if !SSX_KERNEL_TRACE_ENABLE
+
+#define SSX_TRACE_THREAD_SLEEP(priority)
+#define SSX_TRACE_THREAD_WAKEUP(priority)
+#define SSX_TRACE_THREAD_SEMAPHORE_PEND(priority)
+#define SSX_TRACE_THREAD_SEMAPHORE_POST(priority)
+#define SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT(priority)
+#define SSX_TRACE_THREAD_SUSPENDED(priority)
+#define SSX_TRACE_THREAD_DELETED(priority)
+#define SSX_TRACE_THREAD_COMPLETED(priority)
+#define SSX_TRACE_THREAD_MAPPED_RUNNABLE(priority)
+#define SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND(priority)
+#define SSX_TRACE_THREAD_MAPPED_SLEEPING(priority)
+
+
+#endif /* SSX_KERNEL_TRACE_ENABLE */
+
+
+#ifndef __ASSEMBLER__
+
+#include <stddef.h>
+#include <stdint.h>
+
+/// The timebase frequency in Hz; A parameter to ssx_initialize()
+extern uint32_t __ssx_timebase_frequency_hz;
+
+/// The timebase frequency in KHz
+extern uint32_t __ssx_timebase_frequency_khz;
+
+/// The timebase frequency in Mhz
+extern uint32_t __ssx_timebase_frequency_mhz;
+
+
+typedef unsigned long int SsxAddress;
+
+typedef uint8_t SsxThreadState;
+
+typedef uint8_t SsxThreadPriority;
+
+typedef uint8_t SsxThreadFlags;
+
+typedef uint32_t SsxSemaphoreCount;
+
+typedef uint64_t SsxTimebase;
+
+typedef SSX_TIME_INTERVAL_TYPE SsxInterval;
+
+#include "ssx_port_types.h"
+
+typedef struct {
+
+ /// A priority queue of threads pending on the semaphore.
+ SsxThreadQueue pending_threads;
+
+ /// The current semaphore count.
+ SsxSemaphoreCount count;
+
+ /// The maximum allowable count - for error checking.
+ SsxSemaphoreCount max_count;
+
+} SsxSemaphore;
+
+
+/// Compile-time initialize an SsxSemaphore structure
+///
+/// This low-level macro creates a structure initializatin of an SsxSemaphore
+/// structure. This can be used for example to create compile-time initialized
+/// arrays of semaphores.
+#define SSX_SEMAPHORE_INITIALIZATION(_initial_count, _max_count) \
+ {.pending_threads = 0, \
+ .count = (_initial_count), \
+ .max_count = (_max_count)}
+
+
+/// Declare and initialize a semaphore
+#define SSX_SEMAPHORE(sem, initial_count, max_count) \
+ SsxSemaphore sem = SSX_SEMAPHORE_INITIALIZATION(initial_count, max_count)
+
+
+/// A generic doubly-linked list object
+///
+/// This object functions both as a sentinel mode for a deque as well as a
+/// pointer container for elements in deques. The SSX API assumes that
+/// queueable structures will be defined with an SsxDeque structure as the
+/// initial 'data member' of the structure. This allows a pointer to a queue
+/// element to be cast to a pointer to an SsxDeque and vice-versa.
+
+typedef struct SsxDeque {
+
+ /// Pointer to the head or the next element in a deque.
+ ///
+ /// When an SsxDeque is used as the sentinel node for a queue, \a next
+ /// points to the head of the queue, and the condition (next == \<self\>)
+ /// indicates an empty SsxDeque. By convention the condition (\a next ==
+ /// 0) is used to indicate that a queue element is not enqueued.
+ struct SsxDeque* next;
+
+ /// Pointer to the tail or previous element in a deque.
+ ///
+ /// When a DQueue is used as the sentinel node for a queue, \a previous
+ /// points to the tail of the queue.
+ struct SsxDeque* previous;
+
+} SsxDeque;
+
+
+typedef void (*SsxTimerCallback)(void *);
+
+#define SSX_TIMER_CALLBACK(callback) void callback(void *)
+
+struct SsxTimer;
+
+/// The SSX timer object
+
+typedef struct SsxTimer {
+
+ /// The time queue management pointers
+ ///
+ /// This pointer container is defined as the first element of the
+ /// structure to allow the SsxTimer to be cast to an SsxDeque and
+ /// vice-versa.
+ SsxDeque deque;
+
+ /// The absolute timeout of the timer.
+ SsxTimebase timeout;
+
+ /// The timer period
+ ///
+ /// If not 0, then this is a periodic timer and it will be automatically
+ /// rescheduled in absolute time from the previous timeout.
+ SsxInterval period;
+
+ /// The timer callback
+ ///
+ /// For SSX thread timers used to implement Sleep and semaphore pend
+ /// timeouts this field is initialized to __ssx_thread_timeout().
+ SsxTimerCallback callback;
+
+ /// Private data passed to the callback.
+ ///
+ /// For SSX thread timers used to implement Sleep and semaphore pend this
+ /// field is initialized to a pointer to the thread.
+ void *arg;
+
+ /// Options for timer processing; See \ref ssx_timer_options
+ uint8_t options;
+
+} SsxTimer;
+
+/// \defgroup ssx_timer_options SSX Timer Options
+/// @{
+
+/// Allow interrupt preemption during the callback
+///
+/// This is the normal mode for SsxTimer objects scheduled by SSX kernal
+/// mechanisms. The timer callbacks effectively run as if inside a
+/// highest-priority thread, allowing other interrupts to preempt them.
+#define SSX_TIMER_CALLBACK_PREEMPTIBLE 0x1
+
+/// @}
+
+
+// Threads
+
+typedef void (*SsxThreadRoutine)(void *arg);
+
+#define SSX_THREAD_ROUTINE(f) void f(void *arg);
+
+typedef struct {
+
+ /// Stack pointer saved during context switches. Assembler code expects
+ /// this to always be at address offset 0 from the thread pointer.
+ SsxAddress saved_stack_pointer;
+
+ /// This is 1 past the last valid byte address of the thread stack.
+ /// Assembler code expects this to always be at address offset (sizeof
+ /// SsxAddress) from the thread pointer.
+ SsxAddress stack_limit;
+
+ /// This is the original base of the stack.
+ /// Assembler code expects this to always be at address offset 2 * (sizeof
+ /// SsxAddress) from the thread pointer.
+ SsxAddress stack_base;
+
+ /// If the thread is blocked on a semaphore, then this is the semaphore the
+ /// thread is blocked on.
+ SsxSemaphore *semaphore;
+
+ /// The thread priority.
+ SsxThreadPriority priority;
+
+ /// The thread state; See \ref ssx_thread_states
+ SsxThreadState state;
+
+ /// Thread flags; See \ref ssx_thread_flags
+ SsxThreadFlags flags;
+
+ /// The timer structure handles Sleep and blocking on a semaphore with
+ /// timeout.
+ SsxTimer timer;
+
+} SsxThread;
+
+
+// Initialization APIs
+
+int
+ssx_initialize(SsxAddress noncritical_stack,
+ size_t noncritical_stack_size,
+ SsxAddress critical_stack,
+ size_t critical_stack_size,
+ SsxTimebase initial_timebase,
+ uint32_t timebase_frequency_hz);
+
+
+// Timebase APIs
+
+SsxTimebase
+ssx_timebase_get(void);
+
+void
+ssx_timebase_set(SsxTimebase timebase);
+
+// Interrupt preemption APIs
+
+int
+ssx_interrupt_preemption_enable(void);
+
+int
+ssx_interrupt_preemption_disable(void);
+
+// Timer APIs
+
+int
+ssx_timer_create(SsxTimer *timer,
+ SsxTimerCallback callback,
+ void *arg);
+
+int
+ssx_timer_create_nonpreemptible(SsxTimer *timer,
+ SsxTimerCallback callback,
+ void *arg);
+
+int
+ssx_timer_schedule_absolute(SsxTimer *timer,
+ SsxTimebase time,
+ SsxInterval period);
+
+int
+ssx_timer_schedule(SsxTimer *timer,
+ SsxInterval interval,
+ SsxInterval period);
+
+int
+ssx_timer_cancel(SsxTimer *timer);
+
+int
+ssx_timer_info_get(SsxTimer *timer,
+ SsxTimebase *timeout,
+ int *active);
+
+// Thread APIs
+
+int
+ssx_thread_create(SsxThread *thread,
+ SsxThreadRoutine thread_routine,
+ void *arg,
+ SsxAddress stack,
+ size_t stack_size,
+ SsxThreadPriority priority);
+
+int
+ssx_start_threads(void);
+
+int
+ssx_thread_resume(SsxThread *thread);
+
+int
+ssx_thread_suspend(SsxThread *thread);
+
+int
+ssx_thread_delete(SsxThread *thread);
+
+int
+ssx_complete(void);
+
+int
+ssx_sleep_absolute(SsxTimebase time);
+
+int
+ssx_sleep(SsxInterval interval);
+
+int
+ssx_thread_info_get(SsxThread *thread,
+ SsxThreadState *state,
+ SsxThreadPriority *priority,
+ int *runnable);
+
+int
+ssx_thread_priority_change(SsxThread *thread,
+ SsxThreadPriority new_priority,
+ SsxThreadPriority *old_priority);
+
+int
+ssx_thread_at_priority(SsxThreadPriority priority,
+ SsxThread **thread);
+
+int
+ssx_thread_priority_swap(SsxThread* thread_a, SsxThread* thread_b);
+
+
+// Semaphore APIs
+
+int
+ssx_semaphore_create(SsxSemaphore *semaphore,
+ SsxSemaphoreCount initial_count,
+ SsxSemaphoreCount max_count);
+
+int
+ssx_semaphore_post(SsxSemaphore *semaphore);
+
+int
+ssx_semaphore_pend(SsxSemaphore *semaphore,
+ SsxInterval timeout);
+
+int
+ssx_semaphore_release_all(SsxSemaphore *semaphore);
+
+
+int
+ssx_semaphore_info_get(SsxSemaphore *semaphore,
+ SsxSemaphoreCount *count,
+ int *pending);
+
+void
+ssx_semaphore_post_handler(void *arg,
+ SsxIrqId irq,
+ int priority);
+
+// Misc. APIs
+
+void
+ssx_halt() __attribute__ ((noreturn));
+
+// Deque APIs
+
+int
+ssx_deque_sentinel_create(SsxDeque *deque);
+
+int
+ssx_deque_element_create(SsxDeque *element);
+
+
+/// Check for an empty SsxDeque
+///
+/// \param deque The sentinel node of a deque
+///
+/// \retval 0 The SsxDeque is not empty
+///
+/// \retval 1 The SsxDeque is empty
+
+static inline int
+ssx_deque_is_empty(SsxDeque *deque)
+{
+ return (deque == deque->next);
+}
+
+
+/// Check if an SsxDeque element is currently enqueued
+///
+/// \param element Typically the SsxDeque object of a queable structure
+///
+/// \retval 0 The element is not currently enqueued
+///
+/// \retval 1 The element is currently enqueued
+
+static inline int
+ssx_deque_is_queued(SsxDeque *element)
+{
+ return (element->next != 0);
+}
+
+
+/// Append an element to the tail of a deque (FIFO order)
+///
+/// \param deque The sentinel node of a deque
+///
+/// \param element Typically the SsxDeque object of a queable structure
+///
+/// It is an error to call this API on an element that is already enqueued,
+/// but the API does not check for this error.
+
+static inline void
+ssx_deque_push_back(SsxDeque *deque, SsxDeque *element)
+{
+ deque->previous->next = element;
+ element->previous = deque->previous;
+ element->next = deque;
+ deque->previous = element;
+}
+
+
+/// Push an element at the head of a deque (LIFO order)
+///
+/// \param deque The sentinel node of a deque
+///
+/// \param element Typically the SsxDeque object of a queable structure
+///
+/// It is an error to call this API on an element that is already enqueued,
+/// but the API does not check for this error.
+
+static inline void
+ssx_deque_push_front(SsxDeque *deque, SsxDeque *element)
+{
+ deque->next->previous = element;
+ element->next = deque->next;
+ element->previous = deque;
+ deque->next = element;
+}
+
+/// Pop an element from the head of a deque
+///
+/// \param deque The sentinel node of a deque
+///
+/// \retval 0 The SsxDeque was empty prior to the call
+///
+/// \retval non-0 A pointer to the previous head of the deque, which has been
+/// removed from the deque and marked as no longer queued.
+
+// The cast of 'head' is used to remove the 'volatile' attribute.
+
+static inline SsxDeque *
+ssx_deque_pop_front(SsxDeque *deque)
+{
+ SsxDeque *head;
+
+ if (ssx_deque_is_empty(deque)) {
+ return 0;
+ } else {
+ head = (SsxDeque *)(deque->next);
+ deque->next = head->next;
+ deque->next->previous = deque;
+ head->next = 0;
+ return head;
+ }
+}
+
+
+/// Remove a deque element from any position in the deque
+///
+/// \param element Typically the SsxDeque object of a queable structure
+///
+/// It is an error to call this API on an element that is not currently
+/// enqueued, but the API does not check for this error.
+
+static inline void
+ssx_deque_delete(SsxDeque *element)
+{
+ element->previous->next = element->next;
+ element->next->previous = element->previous;
+ element->next = 0;
+}
+
+
+/// Cast a pointer to another type, in a way that won't cause warnings
+
+#define SSX_CAST_POINTER(t, p) ((t)((SsxAddress)(p)))
+
+
+/// \page ssx_errors SSX API and Kernel Error Handling
+///
+/// Error checking in the SSX API consumes a significant amount of code space.
+/// Approximately 20% of the object code in the PPC405 port is devoted to
+/// error checking. Presumably a like amount of time overhead is also added to
+/// SSX API calls by this checking.
+///
+/// API error checking can be disabled to save space and time in the kernel.
+/// API errors can also be configured to cause kernel panics, allowing
+/// applications to be coded without the overhead of error checking but still
+/// providing an escape in the event of application errors or (unlikely)
+/// hardware failures. The SSX default is to check for API errors and kernel
+/// invariants, and panic should errors occur.
+///
+/// SSX follows the Unix convention that a successful call of an API returns 0
+/// (SSX_OK), but returns a negative code in the event of failure, or to
+/// provide further information. The error codes are all defined as manifest
+/// constants.
+///
+/// Some negative codes returned by SSX APIs are not considered errors. These
+/// conditions are always checked, never cause a panic if they occur, and
+/// their interpretation is always left to the application. See the detailed
+/// documentation for each API for lists of error and non-error codes returned
+/// by the API.
+///
+/// There are three configuration options that control error handling in the
+/// SSX API and kernel:
+///
+/// \c SSX_ERROR_CHECK_API
+///
+/// \arg \b 0 - No SSX API error checking. APIs that potentially return error
+/// codes will always return 0 (SSX_OK) instead of an error code. Those
+/// APIs that return negative codes that are not errors (see Table 1.5)
+/// always return the negative non-error codes when appropriate.
+///
+/// \arg \b 1 - (Default) All SSX API errors are checked. The behavior in
+/// the event of an error is defined by the configuration option
+/// SSX_ERROR_PANIC.
+///
+/// \c SSX_ERROR_CHECK_KERNEL
+///
+/// \arg \b 0 - No kernel invariant error checking is done.
+///
+/// \arg \b 1 - (Default) Selected kernel invariants are checked. The overhead
+/// for these checks should be minimal.
+///
+/// \c SSX_ERROR_PANIC
+///
+/// \arg \b 0 - SSX API calls return negative error codes in the event of
+/// errors. Note that SSX kernel invariants always cause a panic if
+/// violations occur.
+///
+/// \arg \b 1 - (Default) In the event of errors SSX APIs invoke SSX_PANIC(code),
+/// where code is a positive error code. Kernel invariant checks always
+/// cause a panic if violations are detected.
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __SSX_API_H__ */
diff --git a/src/ssx/ssx/ssx_core.c b/src/ssx/ssx/ssx_core.c
new file mode 100755
index 0000000..7fa484a
--- /dev/null
+++ b/src/ssx/ssx/ssx_core.c
@@ -0,0 +1,81 @@
+// $Id: ssx_core.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_core.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_core.c
+/// \brief Core routines for the SSX kernel.
+///
+/// The entry points in this file are routines that are expected to be needed
+/// at runtime by all SSX applications. This file also serves as a place for
+/// kernel global variables to be realized.
+
+#define __SSX_CORE_C__
+
+#include "ssx.h"
+
+#if !SSX_TIMER_SUPPORT
+
+/// If there is no timer support, then any call of the timer interrupt handler
+/// is considered a fatal error.
+
+void
+__ssx_timer_handler()
+{
+ SSX_PANIC(SSX_NO_TIMER_SUPPORT);
+}
+
+#endif /* SSX_TIMER_SUPPORT */
+
+
+/// Initialize an SsxDeque sentinel node
+///
+/// \param deque The sentinel node of the deque
+///
+/// SSX has no way of knowing whether the \a deque is currently in use, so
+/// this API must only be called on unitialized or otherwise unused sentinel
+/// nodes.
+///
+/// \retval 0 success
+///
+/// \retval -SSX_INVALID_DEQUE_SENTINEL The \a deque pointer was null
+
+int
+ssx_deque_sentinel_create(SsxDeque *deque)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(deque == 0, SSX_INVALID_DEQUE_SENTINEL);
+ }
+
+ deque->next = deque->previous = deque;
+ return 0;
+}
+
+
+/// Initialize an SsxDeque element
+///
+/// \param element Typically the SsxDeque object of a queable structure
+///
+/// SSX has no way of knowing whether the \a element is currently in use, so
+/// this API must only be called on unitialized or otherwise unused deque
+/// elements.
+///
+/// \retval 0 success
+///
+/// \retval -SSX_INVALID_DEQUE_ELEMENT The \a element pointer was null
+
+int
+ssx_deque_element_create(SsxDeque *element)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(element == 0, SSX_INVALID_DEQUE_ELEMENT);
+ }
+
+ element->next = 0;
+ return 0;
+}
+
+#undef __SSX_CORE_C__
diff --git a/src/ssx/ssx/ssx_init.c b/src/ssx/ssx/ssx_init.c
new file mode 100755
index 0000000..fc12a9b
--- /dev/null
+++ b/src/ssx/ssx/ssx_init.c
@@ -0,0 +1,159 @@
+// $Id: ssx_init.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_init.c
+/// \brief SSX initialization
+///
+/// The entry points in this file are initialization routines - they are never
+/// needed after SSX initialization and their code space could be reclaimed by
+/// the application after initialization if required.
+
+#include "ssx.h"
+
+uint32_t __ssx_timebase_frequency_hz;
+uint32_t __ssx_timebase_frequency_khz;
+uint32_t __ssx_timebase_frequency_mhz;
+
+
+/// Initialize SSX.
+///
+/// \param noncritical_stack A stack area for noncritical interrupt handlers.
+///
+/// \param noncritical_stack_size The size (in bytes) of the stack area for
+/// noncritical interrupt handlers.
+///
+/// \param critical_stack A stack area for critical interrupt handlers.
+///
+/// \param critical_stack_size The size (in bytes) of the stack area for
+/// critical interrupt handlers.
+///
+/// \param initial_timebase The initial value of the SSX timebase. If this
+/// argument is given as the special value \c SSX_TIMEBASE_CONTINUE, then the
+/// timebase is not reset.
+///
+/// \param timebase_frequency_hz The frequency of the SSX timebase in Hz.
+///
+/// This routine \e must be called before any other SSX / routines, and \e
+/// should be called before any interrupts are enabled.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_ARGUMENT_INIT A stack pointer is 0 or is given
+/// a 0 size.
+///
+/// \retval -SSX_STACK_OVERFLOW One or both stacks are not large enough to
+/// support a minimum context save in the event of an interrupt.
+
+// Note that SSX does not rely on any static initialization of dynamic
+// variables. In debugging sessions using RAM-resident SSX images it is
+// assumed that the processor may be reset at any time, so we always need to
+// reset everything at initialization.
+
+int
+ssx_initialize(SsxAddress noncritical_stack,
+ size_t noncritical_stack_size,
+ SsxAddress critical_stack,
+ size_t critical_stack_size,
+ SsxTimebase initial_timebase,
+ uint32_t timebase_frequency_hz)
+{
+ int rc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((noncritical_stack == 0) ||
+ (noncritical_stack_size == 0) ||
+ (critical_stack == 0) ||
+ (critical_stack_size == 0),
+ SSX_INVALID_ARGUMENT_INIT);
+ }
+
+ if (initial_timebase != SSX_TIMEBASE_CONTINUES) {
+ __ssx_timebase_set(initial_timebase);
+ }
+
+ __ssx_timebase_frequency_hz = timebase_frequency_hz;
+ __ssx_timebase_frequency_khz = timebase_frequency_hz / 1000;
+ __ssx_timebase_frequency_mhz = timebase_frequency_hz / 1000000;
+
+ __ssx_thread_machine_context_default = SSX_THREAD_MACHINE_CONTEXT_DEFAULT;
+
+ rc = __ssx_stack_init(&noncritical_stack, &noncritical_stack_size);
+ if (rc) {
+ return rc;
+ }
+
+ __ssx_noncritical_stack = noncritical_stack;
+ __ssx_noncritical_stack_size = noncritical_stack_size;
+
+ rc = __ssx_stack_init(&critical_stack, &critical_stack_size);
+ if (rc) {
+ return rc;
+ }
+
+ __ssx_critical_stack = critical_stack;
+ __ssx_critical_stack_size = critical_stack_size;
+
+#if SSX_TIMER_SUPPORT
+
+ // Initialize the time queue sentinel as a circular queue, set the next
+ // timeout and clear the cursor.
+
+ ssx_deque_sentinel_create((SsxDeque*)&__ssx_time_queue);
+ __ssx_time_queue.cursor = 0;
+ __ssx_time_queue.next_timeout = SSX_TIMEBASE_MAX;
+
+#endif /* SSX_TIMER_SUPPORT */
+
+#if SSX_THREAD_SUPPORT
+
+ // Clear the priority map. The final entry [SSX_THREADS] is for the idle
+ // thread.
+
+ int i;
+ for (i = 0; i <= SSX_THREADS; i++) {
+ __ssx_priority_map[i] = 0;
+ }
+
+ // Initialize the thread scheduler
+
+ __ssx_thread_queue_clear(&__ssx_run_queue);
+ __ssx_current_thread = 0;
+ __ssx_next_thread = 0;
+ __ssx_delayed_switch = 0;
+
+#endif /* SSX_THREAD_SUPPORT */
+
+ return SSX_OK;
+}
+
+
+/// Call the application main()
+///
+/// __ssx_main() is called from the bootloader. It's only purpose is to
+/// provide a place for the SSX_MAIN_HOOK to be called before main() is
+/// called.
+
+void
+__ssx_main(int argc, char **argv)
+{
+ SSX_MAIN_HOOK;
+
+ int main(int argc, char **argv);
+ main(argc, argv);
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/ssx/ssx/ssx_kernel.h b/src/ssx/ssx/ssx_kernel.h
new file mode 100755
index 0000000..c6a70ca
--- /dev/null
+++ b/src/ssx/ssx/ssx_kernel.h
@@ -0,0 +1,281 @@
+#ifndef __SSX_KERNEL_H__
+#define __SSX_KERNEL_H__
+
+// $Id: ssx_kernel.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_kernel.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_kernel.h
+/// \brief SSX portable kernel (non-API) data and data structures
+///
+/// \todo In theory, as long as the critical section entry/exit macros use GCC
+/// memory barriers, we should be able to eliminate all of the 'volatile'
+/// declarations in SSX code. These have been added to the PPC405 port, so
+/// we should try it.
+
+#ifdef __SSX_CORE_C__
+#define IF__SSX_CORE_C__(x) x
+#define UNLESS__SSX_CORE_C__(x)
+#else
+#define IF__SSX_CORE_C__(x)
+#define UNLESS__SSX_CORE_C__(x) x
+#endif
+
+#if SSX_MINIMIZE_KERNEL_CODE_SPACE
+#define IF_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) x
+#define UNLESS_SSX_MINIMIZE_KERNEL_CODE_SPACE(x)
+#else
+#define IF_SSX_MINIMIZE_KERNEL_CODE_SPACE(x)
+#define UNLESS_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) x
+#endif
+
+
+#ifndef __ASSEMBLER__
+
+/// This is the stack pointer saved when switching from a thread or
+/// non-critical interrupt context to a full-mode critical interrupt context.
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxAddress __ssx_saved_sp_critical;
+
+/// The critical interrupt stack; constant once defined by the call of
+/// ssx_initialize().
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxAddress __ssx_critical_stack;
+
+/// This is the stack pointer saved when switching from a thread context to a
+/// full-mode non-critical interrupt context.
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxAddress __ssx_saved_sp_noncritical;
+
+/// The non-critical interrupt stack; constant once defined by the call of
+/// ssx_initialize().
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxAddress __ssx_noncritical_stack;
+
+/// This is the run queue - the queue of mapped runnable tasks.
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxThreadQueue __ssx_run_queue;
+
+/// This flag is set by \c __ssx_schedule() if a new highest-priority thread
+/// becomes runnable during an interrupt handler. The context switch will
+/// take place at the end of non-critical interrupt processing, and the
+/// interrupt handling code will clear the flag.
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+int __ssx_delayed_switch;
+
+/// The currently running thread, or NULL (0) to indicate the idle thread
+///
+/// \a __ssx_current_thread holds a pointer to the currently executing
+/// thread. This pointer will be NULL (0) under the following conditions:
+///
+/// - After ssx_initialize() but prior to ssx_start_threads()
+///
+/// - After ssx_start_threads(), when no threads are runnable. In this case
+/// the NULL (0) value indicates that the SSX idle thread is 'running'.
+///
+/// - After ssx_start_threads(), when the current (non-idle) thread has
+/// completed or been deleted.
+///
+/// If \a __ssx_current_thread == 0 then there is no requirement to save any
+/// register state on a context switch, either because the SSX idle thread has
+/// no permanent context, or because any thread context on the kernel stack is
+/// associated with a deleted thread.
+///
+/// If \a __ssx_current_thread != 0 then \a __ssx_current_thread is a pointer
+/// to the currently executing thread. In an interrupt handler \a
+/// ssx_current_thread is a pointer to the thread whose context is saved on
+/// the kernel stack.
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxThread* __ssx_current_thread;
+
+/// The thread to switch to during the next context switch, or NULL (0).
+///
+/// \a __ssx_next_thread is computed by __ssx_schedule(). \a
+/// __ssx_next_thread holds a pointer to the thread to switch to at the next
+/// context switch. In a thread context the switch happens immediately if \a
+/// __ssx_next_thread == 0 or \a __ssx_next_thread != \a __ssx_current_thread.
+/// In an interrupt context the check happens at the end of processing all
+/// SSX_NONCRITICAL interrupts.
+///
+/// \a __ssx_next_thread may be NULL (0) under the following
+/// conditions:
+///
+/// - After ssx_initialize() but prior to ssx_start_threads(), assuming no
+/// threads have been made runnable.
+///
+/// - After ssx_start_threads(), when no threads are runnable. In this case
+/// the NULL (0) value indicates that the SSX idle thread is the next thread
+/// to 'run'.
+///
+/// If \a __ssx_next_thread == 0 then there is no requirement to restore
+/// any register state on a context switch, because the SSX idle thread has
+/// no permanent context.
+///
+/// If \a __ssx_next_thread != 0 then \a __ssx_next_thread is a pointer
+/// to the thread whose context will be restored at the next context switch.
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxThread* __ssx_next_thread;
+
+/// The priority of \a __ssx_next_thread
+///
+/// If \a __ssx_next_thread == 0, the \a __ssx_next_priority == SSX_THREADS.
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxThreadPriority __ssx_next_priority;
+
+/// This variable holds the default thread machine context for newly created
+/// threads. The idle thread also uses this context. This variable is normally
+/// constant after the call of \c ssx_initialize().
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxMachineContext __ssx_thread_machine_context_default;
+
+
+/// The size of the noncritical stack (bytes).
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+size_t __ssx_noncritical_stack_size;
+
+/// The size of the critical stack (bytes).
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+size_t __ssx_critical_stack_size;
+
+/// This table maps priorities to threads, and contains SSX_THREADS + 1
+/// entries. The final entry is for the idle thread and will always be null
+/// after initizlization.
+
+UNLESS__SSX_CORE_C__(extern)
+volatile
+SsxThread* __ssx_priority_map[SSX_THREADS + 1];
+
+/// The SSX time queue structure
+///
+/// This structure is defined for use by the kernel, however applications
+/// could also use this structure to define their own time queues.
+
+typedef struct {
+
+ /// A sentinel node for the time queue.
+ ///
+ /// The time queue is an SsxDeque managed as a FIFO queue for queue
+ /// management purpose, although events time out in time order.
+ ///
+ /// This pointer container is defined as the first element of the
+ /// structure to allow the SsxTimeQueue to be cast to an SsxDeque.
+ SsxDeque queue;
+
+ /// The next timeout in absolute time.
+ SsxTimebase next_timeout;
+
+ /// A pointer to allow preemption of time queue processing
+ ///
+ /// If non-0, then this is the next timer in the time queue to handle, or
+ /// a pointer to the \a queue object indicating no more timers to handle.
+ ///
+ /// \a cursor != 0 implies that time queue handler is in the midst of
+ /// processing the time queue, but has enabled interrupt preemption for
+ /// processing a timer handler. This means that 1) if the timer pointed to
+ /// by \a cursor is deleted then the cursor must be assigned to the
+ /// next timer in the queue; and 2) if a new timer is scheduled then
+ /// activating the next timeout will be handled by the timer handler.
+ SsxDeque* cursor;
+
+} SsxTimeQueue;
+
+UNLESS__SSX_CORE_C__(extern)
+SsxTimeQueue __ssx_time_queue;
+
+/// Return a pointer to the SsxThread object of the currently running thread,
+/// or NULL (0) if SSX is idle or has not been started.
+///
+/// In this API the current thread is not volatile - it will never change
+/// inside application code - thus the 'volatile' is cast away. The SSX kernel
+/// does not (must not) use this API.
+
+UNLESS__SSX_CORE_C__(extern)
+inline SsxThread *
+ssx_current(void)
+{
+ return (SsxThread *)__ssx_current_thread;
+}
+
+
+/// Set the timebase. This is only called at initialization. Machine
+/// specific.
+
+void
+__ssx_timebase_set(SsxTimebase t);
+
+/// Schedule the next timeout in a machine-specific way.
+
+void
+__ssx_schedule_hardware_timeout(SsxTimebase timeout);
+
+/// Cancel the next timeout in a machine-specific way.
+
+void
+__ssx_cancel_hardware_timeout(void);
+
+/// The thread timeout handler. Portable.
+
+SSX_TIMER_CALLBACK(__ssx_thread_timeout);
+
+/// Generic stack initialization. Portable.
+
+int
+__ssx_stack_init(SsxAddress *stack,
+ size_t *size);
+
+/// Machine-specific thread context initialization.
+
+void
+__ssx_thread_context_initialize(SsxThread *thread,
+ SsxThreadRoutine thread_routine,
+ void *arg);
+
+/// Machine specific resumption of __ssx_next_thread at __ssx_next_priority
+/// without saving the current context.
+void
+__ssx_next_thread_resume(void);
+
+/// Schedule a timer in the time queue. Portable.
+void
+__ssx_timer_schedule(SsxTimer *timer);
+
+/// Remove a timer from the time queue. Portable.
+int
+__ssx_timer_cancel(SsxTimer *timer);
+
+void
+__ssx_schedule(void);
+
+
+// Call the application main(). Portable.
+
+void
+__ssx_main(int argc, char **argv);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __SSX_KERNEL_H__ */
diff --git a/src/ssx/ssx/ssx_macros.h b/src/ssx/ssx/ssx_macros.h
new file mode 100755
index 0000000..76d3ba7
--- /dev/null
+++ b/src/ssx/ssx/ssx_macros.h
@@ -0,0 +1,119 @@
+#ifndef __SSX_MACROS_H__
+#define __SSX_MACROS_H__
+
+// $Id: ssx_macros.h,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_macros.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_macros.h
+/// \brief Boilerplate macros for SSX
+
+/// This macro encapsulates error handling boilerplate for code that uses the
+/// SSX API-type error handling, for errors that do not occur in critical
+/// sections.
+
+#define SSX_ERROR(code) \
+ do { \
+ if (SSX_ERROR_PANIC) { \
+ SSX_PANIC(code); \
+ } else { \
+ return -(code); \
+ } \
+ } while (0)
+
+
+/// This macro encapsulates error handling boilerplate in the SSX API
+/// functions, for errors that do not occur in critical sections.
+
+#define SSX_ERROR_IF(condition, code) \
+ do { \
+ if (condition) { \
+ SSX_ERROR(code); \
+ } \
+ } while (0)
+
+
+/// This macro encapsulates error handling boilerplate in the SSX API
+/// functions, for errors that do not occur in critical sections and always
+/// force a kernel panic, indicating a kernel or API bug.
+
+#define SSX_PANIC_IF(condition, code) \
+ do { \
+ if (condition) { \
+ SSX_PANIC(code); \
+ } \
+ } while (0)
+
+
+/// This macro encapsulates error handling boilerplate in the SSX API
+/// functions, for errors that do not occur in critical sections.
+/// The error handling will only be enabled when SSX_ERROR_CHECK_API
+/// is enabled.
+
+#define SSX_ERROR_IF_CHECK_API(condition, code) \
+ do { \
+ if (SSX_ERROR_CHECK_API) { \
+ SSX_ERROR_IF(condition, code); \
+ } \
+ } while (0)
+
+/// This macro encapsulates error handling boilerplate in the SSX API
+/// functions, for errors that occur in critical sections.
+
+#define SSX_ERROR_IF_CRITICAL(condition, code, context) \
+ do { \
+ if (condition) { \
+ if (SSX_ERROR_PANIC) { \
+ SSX_PANIC(code); \
+ ssx_critical_section_exit(context); \
+ } else { \
+ ssx_critical_section_exit(context); \
+ return -(code); \
+ } \
+ } \
+ } while (0)
+
+
+/// This is a general macro for errors that require cleanup before returning
+/// the error code.
+
+#define SSX_ERROR_IF_CLEANUP(condition, code, cleanup) \
+ do { \
+ if (condition) { \
+ if (SSX_ERROR_PANIC) { \
+ SSX_PANIC(code); \
+ cleanup; \
+ } else { \
+ cleanup; \
+ return -(code); \
+ } \
+ } \
+ } while (0)
+
+
+/// Most SSX APIs can not be called from critical interrupt contexts.
+
+#define SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT() \
+ SSX_ERROR_IF(__ssx_kernel_context_critical_interrupt(), \
+ SSX_ILLEGAL_CONTEXT_CRITICAL_INTERRUPT)
+
+
+/// Some SSX APIs can only be called from thread contexts - these are APIs
+/// that threads call on 'themselves'.
+
+#define SSX_ERROR_UNLESS_THREAD_CONTEXT() \
+ SSX_ERROR_IF(!__ssx_kernel_context_thread(), \
+ SSX_ILLEGAL_CONTEXT_THREAD_CONTEXT)
+
+
+/// Some SSX APIs must be called from an interrupt context only.
+
+#define SSX_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT() \
+ SSX_ERROR_IF(!__ssx_kernel_context_any_interrupt(), \
+ SSX_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT)
+
+#endif /* __SSX_MACROS_H__ */
diff --git a/src/ssx/ssx/ssx_semaphore_core.c b/src/ssx/ssx/ssx_semaphore_core.c
new file mode 100755
index 0000000..f1f64e8
--- /dev/null
+++ b/src/ssx/ssx/ssx_semaphore_core.c
@@ -0,0 +1,331 @@
+// $Id: ssx_semaphore_core.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_semaphore_core.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_semaphore_core.c
+/// \brief SSX semaphore APIs
+///
+/// The entry points in this file are considered 'core' routines that will
+/// always be present at runtime in any SSX application that enables
+/// semaphores.
+
+#include "ssx.h"
+
+/// Post a count to a semaphore
+///
+/// \param semaphore A pointer to the semaphore
+///
+/// If any thread is pending on the semaphore, the highest priority thread
+/// will be made runnable and the internal count will remain 0.
+///
+/// If no thread is pending on the semaphore then the internal count will be
+/// incremented by 1, with overflow wrapping the internal count through 0. If
+/// the \a max_count argument supplied when the semaphore was created is
+/// non-zero and the new internal count is greater than the \a max_count, an
+/// overflow error will be signalled.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt
+/// context.
+///
+/// \retval -SSX_INVALID_SEMAPHORE_AT_POST The \a semaphore is a null (0) pointer.
+///
+/// \retval -SSX_SEMAPHORE_OVERFLOW The \a max_count argument supplied when
+/// the semaphore was created is non-zero and the new internal count is
+/// greater than the \a max_count.
+
+int
+ssx_semaphore_post(SsxSemaphore *semaphore)
+{
+ SsxMachineContext ctx;
+ SsxThreadPriority priority;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_POST);
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ priority = __ssx_thread_queue_min(&(semaphore->pending_threads));
+
+ if (priority != SSX_IDLE_THREAD_PRIORITY) {
+
+ __ssx_thread_queue_delete(&(semaphore->pending_threads), priority);
+ __ssx_thread_queue_insert(&__ssx_run_queue, priority);
+
+ SSX_TRACE_THREAD_SEMAPHORE_POST(priority);
+
+ __ssx_schedule();
+
+ } else {
+
+ semaphore->count++;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((semaphore->max_count > 0) &&
+ (semaphore->count > semaphore->max_count),
+ SSX_SEMAPHORE_OVERFLOW);
+ }
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Pend on a semaphore with timeout
+///
+/// \param semaphore A pointer to the semaphore
+///
+/// \param timeout A relative timeout in SSX timebase ticks, including the
+/// special values SSX_NO_WAIT and SSX_WAIT_FOREVER
+///
+/// This API is normally called from threads, and can only be successfully
+/// called from interupt handlers under special conditions.
+///
+/// If the internal count of the \a semaphore is non-zero, the internal count
+/// is decremented by one and execution of the caller continues.
+///
+/// If the internal count of the \a semaphore is zero and the \a timeout is
+/// SSX_NO_WAIT (0) then the call returns immediately with the informational
+/// code -SSX_SEMAPHORE_PEND_NO_WAIT.
+///
+/// If the internal count of the \a semaphore is zero and the \a timeout is
+/// non-zero then a thread will block until either a semaphore count is
+/// acquired or the relative timeout expires. If this condition occurs in a
+/// call from an interrupt context or before threads have been started then
+/// the call will fail with the error \c -SSX_SEMAPHORE_PEND_WOULD_BLOCK.
+///
+/// Once timed out the thread is removed from the semaphore pending queue and
+/// made runnable, and the ssx_semaphore_pend() operation will fail, even if
+/// the semaphore count becomes available before the thread runs again. The
+/// ssx_semaphore_pend() API returns the informational code
+/// -SSX_SEMAPHORE_PEND_TIMED_OUT in this case.
+///
+/// By convention, a timeout interval equal to the maximum possible value of
+/// the \c SsxInterval type is taken to mean "wait forever". A thread blocked
+/// on a semaphore in this mode will never time out. SSX provides this
+/// constant as \c SSX_WAIT_FOREVER.
+///
+/// Return values other than SSX_OK (0) are not necessarily errors; see \ref
+/// ssx_errors
+///
+/// The following return codes are non-error codes:
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_SEMAPHORE_PEND_NO_WAIT timeout is set to SSX_NO_WAIT
+///
+/// \retval -SSX_SEMAPHORE_PEND_TIMED_OUT The semaphore was not acquired
+/// before the timeout expired.
+///
+/// The following return codes are error codes:
+///
+/// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt
+/// context.
+///
+/// \retval -SSX_INVALID_SEMAPHORE_AT_PEND The \a semaphore is a null (0)
+/// pointer.
+///
+/// \retval -SSX_SEMAPHORE_PEND_WOULD_BLOCK The call was made from an
+/// interrupt context (or before threads have been started), the semaphore
+/// internal count was 0 and a non-zero timeout was specified.
+
+// Note: Casting __ssx_current_thread removes the 'volatile' attribute.
+
+int
+ssx_semaphore_pend(SsxSemaphore *semaphore,
+ SsxInterval timeout)
+{
+ SsxMachineContext ctx;
+ SsxThreadPriority priority;
+ SsxThread *thread;
+ SsxTimer *timer = 0;
+ int rc = SSX_OK;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_PEND);
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ if (semaphore->count != 0) {
+
+ semaphore->count--;
+
+ } else if (timeout == SSX_NO_WAIT) {
+
+ rc = -SSX_SEMAPHORE_PEND_NO_WAIT;
+
+ } else {
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL(!__ssx_kernel_context_thread(),
+ SSX_SEMAPHORE_PEND_WOULD_BLOCK,
+ &ctx);
+ }
+
+ thread = (SsxThread *)__ssx_current_thread;
+ priority = thread->priority;
+
+ __ssx_thread_queue_insert(&(semaphore->pending_threads), priority);
+
+ thread->semaphore = semaphore;
+ thread->flags |= SSX_THREAD_FLAG_SEMAPHORE_PEND;
+
+ SSX_TRACE_THREAD_SEMAPHORE_PEND(priority);
+
+ if (timeout != SSX_WAIT_FOREVER) {
+ timer = &(thread->timer);
+ timer->timeout = ssx_timebase_get() + timeout;
+ __ssx_timer_schedule(timer);
+ thread->flags |= SSX_THREAD_FLAG_TIMER_PEND;
+ }
+
+ __ssx_thread_queue_delete(&__ssx_run_queue, priority);
+ __ssx_schedule();
+
+ thread->flags &= ~SSX_THREAD_FLAG_SEMAPHORE_PEND;
+
+ if (thread->flags & SSX_THREAD_FLAG_TIMER_PEND) {
+ if (thread->flags & SSX_THREAD_FLAG_TIMED_OUT) {
+ rc = -SSX_SEMAPHORE_PEND_TIMED_OUT;
+ } else {
+ __ssx_timer_cancel(timer);
+ }
+ thread->flags &=
+ ~(SSX_THREAD_FLAG_TIMER_PEND | SSX_THREAD_FLAG_TIMED_OUT);
+ }
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return rc;
+}
+
+
+/// Release all threads blocked on a semaphore
+///
+/// \param semaphore A pointer to a semaphore
+///
+/// This API is provided to allow an SSX semaphore to be used as a thread
+/// barrier. ssx_semaphore_release_all() simultaneously unblocks all threads
+/// (if any) currently pending on a semaphore. A semaphore to be used as a
+/// thread barrier will typically be initialized with
+/// ssx_semaphore_create(\a sem, 0, 0), and sxx_semaphore_post() would never be
+/// called on the \a sem.
+///
+/// This API never modifies the \a count field of the semaphore; If any
+/// threads are blocked on a semaphore the semaphore count is 0 by definition.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt
+/// context.
+///
+/// \retval -SSX_INVALID_SEMAPHORE_AT_RELEASE The \a semaphore is a null (0)
+/// pointer.
+
+int
+ssx_semaphore_release_all(SsxSemaphore* semaphore)
+{
+ SsxMachineContext ctx;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_RELEASE);
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ __ssx_thread_queue_union(&__ssx_run_queue, &(semaphore->pending_threads));
+ __ssx_thread_queue_clear(&(semaphore->pending_threads));
+ __ssx_schedule();
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Get information about a semaphore.
+///
+/// \param semaphore A pointer to the SsxSemaphore to query
+///
+/// \param count The value returned through this pointer is the current count
+/// of the semaphore. The caller can set this parameter to the null pointer
+/// (0) if this information is not required.
+///
+/// \param pending The value returned through this pointer is the current
+/// number of threads pending on the semaphore. The caller can set this
+/// parameter to the null pointer (0) if this information is not required.
+///
+/// The information returned by this API can only be guaranteed consistent if
+/// the API is called from an SSX_NONCRITICAL critical section. Since the
+/// implementation of this API does not require a critical section, it is not
+/// an error to call this API from a critical interrupt context.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_SEMAPHORE_AT_INFO The \a semaphore is a null (0)
+/// pointer.
+
+int
+ssx_semaphore_info_get(SsxSemaphore* semaphore,
+ SsxSemaphoreCount* count,
+ int* pending)
+
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_INFO);
+ }
+
+ if (count) {
+ *count = semaphore->count;
+ }
+ if (pending) {
+ *pending = __ssx_thread_queue_count(&(semaphore->pending_threads));
+ }
+
+ return SSX_OK;
+}
+
+
+/// An simple interrupt handler that posts to a semaphore.
+///
+/// To implement basic event-driven blocking of a thread, install
+/// ssx_semaphore_post_handler() as the handler for a non-critical interrupt
+/// and provide a pointer to the semaphore as the \a arg argument in
+/// ssx_irq_handler_set(). The semaphore should be initialized with
+/// ssx_semaphore_create(&sem, 0, 1). This handler simply disables (masks)
+/// the interrupt, clears the status and calls ssx_semaphore_post() on the
+/// semaphore.
+///
+/// Note that clearing the status in the interrupt controller as done here is
+/// effectively a no-op for level-sensitive interrupts. In the level-sensitive
+/// case any thread pending on the semaphore must reset the interrupt
+/// condition in the device before re-enabling the interrupt.
+
+void
+ssx_semaphore_post_handler_full(void *arg, SsxIrqId irq, int priority)
+{
+ ssx_irq_disable(irq);
+ ssx_irq_status_clear(irq);
+ ssx_semaphore_post((SsxSemaphore *)arg);
+}
+
+SSX_IRQ_FAST2FULL(ssx_semaphore_post_handler, ssx_semaphore_post_handler_full);
diff --git a/src/ssx/ssx/ssx_semaphore_init.c b/src/ssx/ssx/ssx_semaphore_init.c
new file mode 100755
index 0000000..98bba89
--- /dev/null
+++ b/src/ssx/ssx/ssx_semaphore_init.c
@@ -0,0 +1,84 @@
+// $Id: ssx_semaphore_init.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_semaphore_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_semaphore_init.c
+/// \brief SSX semaphore API initialization routines
+///
+/// The entry points in this file are routines that are typically used during
+/// initialization, and their code space could be deallocated and recovered if
+/// no longer needed by the application after initialization.
+
+#include "ssx.h"
+
+/// Create (initialize) a semaphore
+///
+/// \param semaphore A pointer to an SsxSemaphore structure to initialize
+///
+/// \param initial_count The initial count of the semaphore
+///
+/// \param max_count The maximum count allowed in the semaphore, for error
+/// checking
+///
+/// Semaphores are created (initialized) by a call of \c
+/// ssx_semaphore_create(), using an application-provided instance of an \c
+/// SsxSemaphore structure. This structure \e is the semaphore, so the
+/// application must never modify the structure if the semaphore is in use.
+/// SSX has no way to know if an \c SsxSemaphore structure provided to
+/// \c ssx_semaphore_create() is safe to use as a semaphore, and will silently
+/// modify whatever memory is provided.
+///
+/// SSX provides two simple overflow semantics based on the value of max_count
+/// in the call of \c ssx_semaphore_create().
+///
+/// If \a max_count = 0, then posting to the semaphore first increments the
+/// internal count by 1. Overflows are ignored and will wrap the internal
+/// count through 0.
+///
+/// If \a max_count != 0, then posting to the semaphore first increments the
+/// internal count by 1, wrapping through 0 in the event of overflow. If the
+/// resulting count is greater than max_count, \c ssx_semaphore_post() will
+/// return the error \c -SSX_SEMAPHORE_POST_OVERFLOW to the caller.
+///
+/// In most applications it is probably best to use the \a max_count != 0
+/// semantics to trap programming errors, unless there is a specific
+/// application where overflow is expected and ignorable. As a fine point of
+/// the specification, a \a max_count of 0 is equivalent to a max_count of
+/// 0xFFFFFFFF.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_SEMAPHORE_AT_CREATE The \a semaphore is a null (0)
+/// pointer.
+///
+/// \retval -SSX_INVALID_ARGUMENT_SEMAPHORE The \a max_count is non-zero
+/// and less than the \a initial_count.
+
+int
+ssx_semaphore_create(SsxSemaphore *semaphore,
+ SsxSemaphoreCount initial_count,
+ SsxSemaphoreCount max_count)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_CREATE);
+ SSX_ERROR_IF((max_count != 0) && (initial_count > max_count),
+ SSX_INVALID_ARGUMENT_SEMAPHORE);
+ }
+
+ __ssx_thread_queue_clear(&(semaphore->pending_threads));
+ semaphore->count = initial_count;
+ semaphore->max_count = max_count;
+
+ return SSX_OK;
+}
+
+
+
+
+
diff --git a/src/ssx/ssx/ssx_stack_init.c b/src/ssx/ssx/ssx_stack_init.c
new file mode 100755
index 0000000..9d6331a
--- /dev/null
+++ b/src/ssx/ssx/ssx_stack_init.c
@@ -0,0 +1,87 @@
+// $Id: ssx_stack_init.c,v 1.1.1.1 2013/12/11 21:03:28 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_stack_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_stack_init.c
+/// \brief SSX stack initialization
+///
+/// The entry points in this file are initialization routines - they are never
+/// needed after SSX initialization and their code space could be reclaimed by
+/// the application after initialization if required.
+///
+/// This code was split out from "ssx_init.c" because it may be needed in a
+/// thread configuration if threads are being created dynamically. in an
+/// interrupt-only configuration it is not needed after \c ssx_initialize().
+
+#include "ssx.h"
+
+/// Initialize a stack area.
+///
+/// \param stack A pointer to the smallest legal address of the stack. The
+/// stack address is modified as the stack is aligned and initialized.
+///
+/// \param size A pointer to the size of the stack (in bytes). The size is
+/// modified as the stack is aligned and initialized. At exit this is the
+/// final usable stack area size aligned to the size of the SSX_STACK_TYPE.
+///
+/// SSX makes no assumptions about size or alignment of the area provided as a
+/// stack, and carefully aligns and initializes the stack. Regardless of how
+/// the stack grows, the \a stack parameter is considered to be the lowest
+/// legal address of the stack.
+
+int
+__ssx_stack_init(SsxAddress *stack,
+ size_t *size)
+{
+ SsxAddress mask;
+ size_t excess, i, count;
+ SSX_STACK_TYPE *p;
+
+ if (SSX_STACK_DIRECTION < 0) {
+
+ // Stacks grow down. The initial stack pointer is set to just above
+ // the last allocated stack address. This is legal for pre-decrement
+ // stacks, otherwise the initial address is first brought into range
+ // before alignment. The stack is aligned downward, then the size is
+ // adjusted to a multiple of the stack type. Stacks are optionally
+ // prepatterned. Alignment is assumed to be a power of 2.
+
+ *stack += *size;
+
+ if (!SSX_STACK_PRE_DECREMENT) {
+ *stack -= sizeof(SSX_STACK_TYPE);
+ *size -= sizeof(SSX_STACK_TYPE);
+ }
+
+ mask = SSX_STACK_ALIGNMENT - 1;
+ excess = *stack & mask;
+ *stack -= excess;
+ *size -= excess;
+ *size = (*size / sizeof(SSX_STACK_TYPE)) * sizeof(SSX_STACK_TYPE);
+
+ if (SSX_STACK_CHECK) {
+ p = (SSX_STACK_TYPE *)(*stack);
+ count = *size / sizeof(SSX_STACK_TYPE);
+ for (i = 0; i < count; i++) {
+ if (SSX_STACK_PRE_DECREMENT) {
+ *(--p) = SSX_STACK_PATTERN;
+ } else {
+ *(p--) = SSX_STACK_PATTERN;
+ }
+ }
+ }
+
+ __ssx_stack_create_initial_frame(stack, size);
+
+ } else {
+
+ SSX_PANIC(SSX_UNIMPLEMENTED);
+ }
+
+ return SSX_OK;
+}
+
diff --git a/src/ssx/ssx/ssx_thread_core.c b/src/ssx/ssx/ssx_thread_core.c
new file mode 100755
index 0000000..d6124e8
--- /dev/null
+++ b/src/ssx/ssx/ssx_thread_core.c
@@ -0,0 +1,946 @@
+// $Id: ssx_thread_core.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_thread_core.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_thread_core.c
+/// \brief SSX thread APIs
+///
+/// The entry points in this file are considered 'core' routines that will
+/// always be present at runtime in any SSX application that enables threads.
+
+#include "ssx.h"
+
+#define __SSX_THREAD_CORE_C__
+
+
+// This routine is only used locally. Noncritical interrupts must be disabled
+// at entry.
+
+static inline int
+__ssx_thread_is_active(SsxThread *thread)
+{
+ return ((thread->state != SSX_THREAD_STATE_COMPLETED) &&
+ (thread->state != SSX_THREAD_STATE_DELETED));
+}
+
+
+// This routine is only used locally. Noncritical interrupts must be disabled
+// at entry.
+
+static inline int
+__ssx_thread_is_mapped(SsxThread *thread)
+{
+ return (thread->state == SSX_THREAD_STATE_MAPPED);
+}
+
+
+// This routine is only used locally. Noncritical interrupts must be disabled
+// at entry. This is only called on mapped threads.
+
+static inline int
+__ssx_thread_is_runnable(SsxThread *thread)
+{
+ return __ssx_thread_queue_member(&__ssx_run_queue, thread->priority);
+}
+
+
+// This routine is only used locally. Noncritical interrupts must be disabled
+// at entry.
+
+static inline SsxThread*
+__ssx_thread_at_priority(SsxThreadPriority priority)
+{
+ return (SsxThread*)__ssx_priority_map[priority];
+}
+
+
+// This routine is only used locally. Noncritical interrupts must be disabled
+// at entry. The caller must also have checked that the priority is free.
+// This routine is only called on threads known to be in a suspended state,
+// either SSX_THREAD_STATE_SUSPENDED_RUNNABLE or
+// SSX_THREAD_STATE_SUSPENDED_BLOCKED. Mapping a runnable thread adds it to
+// the run queue. Mapping a thread pending on a semaphore either takes the
+// count and becomes runnable or adds the thread to the pending queue for the
+// semaphore. Mapping a sleeping thread requires no further action
+// here. Scheduling after the map must be handled by the caller.
+
+void
+__ssx_thread_map(SsxThread* thread)
+{
+ SsxThreadPriority priority;
+
+ priority = thread->priority;
+ __ssx_priority_map[priority] = thread;
+
+ if (thread->state == SSX_THREAD_STATE_SUSPENDED_RUNNABLE) {
+
+ __ssx_thread_queue_insert(&__ssx_run_queue, priority);
+
+ } else if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) {
+
+ if (thread->semaphore->count) {
+
+ thread->semaphore->count--;
+ __ssx_thread_queue_insert(&__ssx_run_queue, priority);
+
+ } else {
+
+ __ssx_thread_queue_insert(&(thread->semaphore->pending_threads),
+ priority);
+ }
+ }
+
+ thread->state = SSX_THREAD_STATE_MAPPED;
+
+ if (SSX_KERNEL_TRACE_ENABLE) {
+ if (__ssx_thread_is_runnable(thread)) {
+ SSX_TRACE_THREAD_MAPPED_RUNNABLE(priority);
+ } else if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) {
+ SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND(priority);
+ } else {
+ SSX_TRACE_THREAD_MAPPED_SLEEPING(priority);
+ }
+ }
+}
+
+
+// This routine is only used locally. Noncritical interrupts must be disabled
+// at entry. This routine is only ever called on threads in the
+// SSX_THREAD_STATE_MAPPED. Unmapping a thread removes it from the priority
+// map, the run queue and any semaphore pend, but does not cancel any
+// timers. Scheduling must be handled by the code calling
+// __ssx_thread_unmap().
+
+void
+__ssx_thread_unmap(SsxThread *thread)
+{
+ SsxThreadPriority priority;
+
+ priority = thread->priority;
+ __ssx_priority_map[priority] = 0;
+
+ if (__ssx_thread_is_runnable(thread)) {
+
+ thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE;
+ __ssx_thread_queue_delete(&__ssx_run_queue, priority);
+
+ } else {
+
+ thread->state = SSX_THREAD_STATE_SUSPENDED_BLOCKED;
+ if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) {
+ __ssx_thread_queue_delete(&(thread->semaphore->pending_threads),
+ priority);
+ }
+ }
+}
+
+
+// Schedule and run the highest-priority mapped runnable thread.
+//
+// The priority of the next thread to run is first computed. This may be
+// SSX_THREADS, indicating that the only thread to run is the idle thread.
+// This will always cause (or defer) a 'context switch' to the idle thread.
+// Otherwise, if the new thread is not equal to the current thread this will
+// also cause (or defer) a context switch. Note that scheduling is defined in
+// terms of priorities but actually implemented in terms of SsxThread pointers.
+//
+// If we are not yet in thread mode we're done - threads will be started by
+// ssx_start_threads() later. If we're in thread context a context switch
+// happens immediately. In an interrupt context the switch is deferred to the
+// end of SSX_NONCRITICAL interrupt processing.
+
+void
+__ssx_schedule(void)
+{
+ __ssx_next_priority = __ssx_thread_queue_min(&__ssx_run_queue);
+ __ssx_next_thread = __ssx_priority_map[__ssx_next_priority];
+
+ if ((__ssx_next_thread == 0) ||
+ (__ssx_next_thread != __ssx_current_thread)) {
+
+ if (__ssx_kernel_mode_thread()) {
+ if (__ssx_kernel_context_thread()) {
+ if (__ssx_current_thread != 0) {
+ __ssx_switch();
+ } else {
+ __ssx_next_thread_resume();
+ }
+ } else {
+ __ssx_delayed_switch = 1;
+ }
+ }
+ }
+}
+
+
+// This routine is only used locally.
+//
+// Completion and deletion are pretty much the same thing. Completion is
+// simply self-deletion of the current thread (which is mapped by
+// definition.) The complete/delete APIs have slightly different error
+// conditions but are otherwise the same.
+//
+// Deleting a mapped thread first unmaps (suspends) the thread, which takes
+// care of removing the thread from any semaphores it may be pending on. Then
+// any outstanding timer is also cancelled.
+//
+// If the current thread is being deleted we install the idle thread as
+// __ssx_current_thread, so scheduling is forced and no context is saved on
+// the context switch.
+//
+// Note that we do not create trace events for unmapped threads since the trace
+// tag only encodes the priority, which may be in use by a mapped thread.
+
+void
+__ssx_thread_delete(SsxThread *thread, SsxThreadState final_state)
+{
+ SsxMachineContext ctx;
+ int mapped;
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ mapped = __ssx_thread_is_mapped(thread);
+
+ if (mapped) {
+ __ssx_thread_unmap(thread);
+ }
+
+ __ssx_timer_cancel(&(thread->timer));
+ thread->state = final_state;
+
+ if (mapped) {
+
+ if (SSX_KERNEL_TRACE_ENABLE) {
+ if (final_state == SSX_THREAD_STATE_DELETED) {
+ SSX_TRACE_THREAD_DELETED(thread->priority);
+ } else {
+ SSX_TRACE_THREAD_COMPLETED(thread->priority);
+ }
+ }
+
+ if (thread == __ssx_current_thread) {
+ __ssx_current_thread = 0;
+ }
+ __ssx_schedule();
+ }
+
+ ssx_critical_section_exit(&ctx);
+}
+
+
+// Generic thread timeout
+//
+// This routine is called as a timer callback either because a sleeping thread
+// has timed out or a thread pending on a semaphore has timed out. If the
+// thread is not already runnable then the the timeout flag is set, and if the
+// thread is mapped it is scheduled.
+//
+// This implementation allows that a thread blocked on a timer may have been
+// made runnable by some other mechanism, such as acquiring a semaphore. In
+// order to provide an iteration-free implementation of
+// ssx_semaphore_release_all(), cancelling any semaphore timeouts is deferred
+// until the thread runs again.
+//
+// __ssx_thread_timeout() is currenly the only timer interrupt called from a
+// critical section.
+//
+// Note that we do not create trace events for unmapped threads since the trace
+// tag only encodes the priority, which may be in use by a mapped thread.
+
+void
+__ssx_thread_timeout(void *arg)
+{
+ SsxThread *thread = (SsxThread *)arg;
+
+ switch (thread->state) {
+
+ case SSX_THREAD_STATE_MAPPED:
+ if (!__ssx_thread_is_runnable(thread)) {
+ thread->flags |= SSX_THREAD_FLAG_TIMED_OUT;
+ __ssx_thread_queue_insert(&__ssx_run_queue, thread->priority);
+ __ssx_schedule();
+ }
+ break;
+
+ case SSX_THREAD_STATE_SUSPENDED_RUNNABLE:
+ break;
+
+ case SSX_THREAD_STATE_SUSPENDED_BLOCKED:
+ thread->flags |= SSX_THREAD_FLAG_TIMED_OUT;
+ thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE;
+ break;
+
+ default:
+ SSX_PANIC(SSX_THREAD_TIMEOUT_STATE);
+ }
+}
+
+
+// This routine serves as a container for the SSX_START_THREADS_HOOK and
+// actually starts threads. The helper routine __ssx_call_ssx_start_threads()
+// arranges this routine to be called with interrupts disabled while running
+// on the noncritical interrupt stack.
+//
+// The reason for this roundabout is that we want to be able to run a hook
+// routine (transparent to the application) that can hand over every last byte
+// of free memory to "malloc()" - including the stack of main(). Since we
+// always need to run on some stack, we chose to run the hook on the kernel
+// noncritical interrupt stack. However to do this safely we need to make sure
+// that no interrupts will happen during this time. When __ssx_thread_resume()
+// is finally called all stack-based context is lost but it doesn't matter at
+// that point - it's a one-way street into thread execution.
+//
+// This is considered part of ssx_start_threads() and so is also considered a
+// 'core' routine.
+
+void
+__ssx_start_threads(void)
+{
+ SSX_START_THREADS_HOOK;
+
+ __ssx_next_thread_resume();
+
+ SSX_PANIC(SSX_START_THREADS_RETURNED);
+}
+
+
+/// Start SSX threads
+///
+/// This routine starts the SSX thread scheduler infrastructure. This routine
+/// must be called after a call of \c ssx_initialize(). This routine never
+/// returns. Interrupt (+ timer) only configurations of SSX need not call this
+/// routine.
+///
+/// Note: This tiny routine is considered a 'core' routine so that the
+/// initialziation code can safely recover all 'init' code space before
+/// starting threads.
+///
+/// This routine typically does not return - any return value indicates an
+/// error; see \ref ssx_errors
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called twice.
+
+int
+ssx_start_threads(void)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(__ssx_kernel_mode_thread(), SSX_ILLEGAL_CONTEXT_THREAD);
+ }
+
+ __ssx_call_ssx_start_threads();
+
+ return 0;
+}
+
+
+/// Resume a suspended thread
+///
+/// \param thread The thread to resume
+///
+/// SSX only allows one thread at a time to run at a given priority, and
+/// implements the notion of a thread \e claiming a priority. A suspended
+/// thread claims a priority when it is mapped by a call of
+/// ssx_thread_resume(). This API will succeed only if no other active thread
+/// is currently mapped at the priority assigned to the thread. SSX provides
+/// the ssx_thread_at_priority() API which allows an application-level
+/// scheduler to correctly manage multiple threads running at the same
+/// priority.
+///
+/// If the thread was sleeping while suspended it remains asleep. However if
+/// the sleep timer timed out while the thread was suspended it will be
+/// resumed runnable.
+///
+/// If the thread was blocked on a semaphore when it was suspended, then when
+/// the thread is resumed it will attempt to reacquire the semaphore.
+/// However, if the thread was blocked on a semaphore with timeout while
+/// suspended and the timeout interval has passed, the thread will be resumed
+/// runnable and see that the semaphore pend timed out.
+///
+/// It is not an error to call ssx_thread_resume() on a mapped
+/// thread. However it is an error to call ssx_thread_resume() on a completed
+/// or deleted thread.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion, including calls on a \a thread that is
+/// already mapped.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called
+/// from a critical interrupt context.
+///
+/// \retval -SSX_INVALID_THREAD_AT_RESUME1 The \a thread is a null (0) pointer.
+///
+/// \retval -SSX_INVALID_THREAD_AT_RESUME2 The \a thread is not active,
+/// i.e. has completed or been deleted.
+///
+/// \retval -SSX_PRIORITY_IN_USE_AT_RESUME Another thread is already mapped at
+/// the priority of the \a thread.
+
+int
+ssx_thread_resume(SsxThread *thread)
+{
+ SsxMachineContext ctx;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_RESUME1);
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL(!__ssx_thread_is_active(thread),
+ SSX_INVALID_THREAD_AT_RESUME2,
+ &ctx);
+ }
+
+ if (!__ssx_thread_is_mapped(thread)) {
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL(__ssx_priority_map[thread->priority] != 0,
+ SSX_PRIORITY_IN_USE_AT_RESUME,
+ &ctx);
+ }
+ __ssx_thread_map(thread);
+ __ssx_schedule();
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Suspend a thread
+///
+/// Any active thread can be suspended. A suspended thread 1) remains active
+/// but will not be scheduled; 2) relinquishes its priority assignment,
+/// allowing another thread to be resumed at the suspended thread's priority;
+/// and 3) disassociates from any semaphore mutual exclusion it may have been
+/// participating in.
+///
+/// If a sleeping thread is suspended, the sleep timer remains active but a
+/// timeout of the timer simply marks the thread as runnable, but does not
+/// resume the thread.
+///
+/// If a thread blocked on a semaphore is suspended, the thread no longer
+/// participates in the semaphore mutual exclusion. If the thread is later
+/// resumed it will attempt to acquire the semaphore again the next time it
+/// runs (unless it was blocked with a timeout and the timeout has expired).
+///
+/// If a thread blocked on a semaphore with timeout is suspended, the
+/// semaphore timeout timer continues to run. If the timer times out while the
+/// thread is suspended the thread is simply marked runnable. If the thread is
+/// later resumed, the suspended call of \c ssx_semaphore_pend() will return the
+/// timeout code -SSX_SEMAPHORE_PEND_TIMED_OUT.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion, including calls on a \a thread that is
+/// already suspended.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called from a critical
+/// interrupt context.
+///
+/// \retval -SSX_INVALID_THREAD_AT_SUSPEND1 The \a thread is a null (0) pointer
+///
+/// \retval -SSX_INVALID_THREAD_AT_SUSPEND2 The \a thread is not active,
+/// i.e. has completed or been deleted.
+
+int
+ssx_thread_suspend(SsxThread *thread)
+{
+ SsxMachineContext ctx;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF((thread == 0), SSX_INVALID_THREAD_AT_SUSPEND1);
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL(!__ssx_thread_is_active(thread),
+ SSX_INVALID_THREAD_AT_SUSPEND2,
+ &ctx);
+ }
+
+ if (__ssx_thread_is_mapped(thread)) {
+
+ SSX_TRACE_THREAD_SUSPENDED(thread->priority);
+ __ssx_thread_unmap(thread);
+ __ssx_schedule();
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Delete a thread
+///
+/// Any active thread can be deleted. If a thread is deleted it is removed
+/// from the run queue, deleted from the timer queue (if sleeping or blocked
+/// on a semaphore with timeout), and deleted from the semaphore mutual
+/// exclusion if blocked on a semaphore. The thread control block is then
+/// marked as deleted.
+///
+/// Once a thread has completed or been deleted the thread structure and
+/// thread stack areas can be used for other purposes.
+///
+/// \param thread The thread to delete
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors. If a
+/// thread deletes itself this API does not return at all.
+///
+/// \retval 0 Successful completion, including calls on a \a thread that has
+/// completed or had already been deleted.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called from a critical
+/// interrupt context.
+///
+/// \retval -SSX_INVALID_THREAD_AT_DELETE The \a thread is a null (0) pointer.
+
+int
+ssx_thread_delete(SsxThread *thread)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_DELETE);
+ }
+
+ __ssx_thread_delete(thread, SSX_THREAD_STATE_DELETED);
+
+ return SSX_OK;
+}
+
+
+/// Complete a thread
+///
+/// If a thread ever returns from the subroutine defining the thread entry
+/// point, the thread is removed from all SSX kernel data structures and
+/// marked completed. The thread routine can also use the API ssx_complete()
+/// to make this more explicit if desired. SSX makes no distinction between
+/// completed and deleted threads, but provides these indications for
+/// the benefit of the application.
+///
+/// Note that this API is only available from the current thread to mark its
+/// own completion.
+///
+/// Once a thread has completed or been deleted the thread structure and
+/// thread stack areas can be used for other purposes.
+///
+/// Any return value indicates an error; see \ref ssx_errors. In the event of
+/// a successful completion this API does not return to the caller, which is
+/// always the thread context being completed.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread
+/// context.
+
+// Note: Casting __ssx_current_thread removes the 'volatile' attribute.
+
+int
+ssx_complete(void)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_UNLESS_THREAD_CONTEXT();
+ }
+
+ __ssx_thread_delete((SsxThread *)__ssx_current_thread,
+ SSX_THREAD_STATE_COMPLETED);
+
+ return SSX_OK;
+}
+
+
+/// Sleep a thread until an absolute time
+///
+/// \param time An absolute time as measured by the SSX timebase
+///
+/// Threads can use this API to sleep until an absolute time. Sleeping threads
+/// are not scheduled, although they maintain their priorities. This differs
+/// from thread suspension, where the suspended thread relinquishes its
+/// priority. When the sleep timer times out the thread becomes runnable
+/// again, and will run as soon as it becomes the highest-priority mapped
+/// runnable thread.
+///
+/// Sleeping threads may also be later suspended. In this case the Sleep timer
+/// continues to run, and if it times out before the thread is resumed the
+/// thread will be immediately runnable when it is resumed.
+///
+/// See the SSX specification for a full discussion of how SSX handles
+/// scheduling events at absolute times "in the past". Briefly stated, if the
+/// \a time is in the past, the thread will Sleep for the briefest possible
+/// period supported by the hardware.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread
+/// context.
+
+// Note: Casting __ssx_current_thread removes the 'volatile' attribute.
+
+int
+ssx_sleep_absolute(SsxTimebase time)
+{
+ SsxMachineContext ctx;
+ SsxThread *current;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_UNLESS_THREAD_CONTEXT();
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ current = (SsxThread *)__ssx_current_thread;
+
+ current->timer.timeout = time;
+ __ssx_timer_schedule(&(current->timer));
+
+ current->flags |= SSX_THREAD_FLAG_TIMER_PEND;
+
+ SSX_TRACE_THREAD_SLEEP(current->priority);
+
+ __ssx_thread_queue_delete(&__ssx_run_queue, current->priority);
+ __ssx_schedule();
+
+ current->flags &= ~(SSX_THREAD_FLAG_TIMER_PEND | SSX_THREAD_FLAG_TIMED_OUT);
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+/// Sleep a thread for an interval relative to the current time.
+///
+/// \param interval A time interval relative to the current timebase.
+///
+/// Threads can use this API to sleep for a time relative to the current
+/// timebase. The absolute timeout is \c ssx_timebase_get() + \a interval.
+///
+/// Sleeping threads are not scheduled, although they maintain their
+/// priorities. This differs from thread suspension, where the suspended
+/// thread relinquishes its priority. When the sleep timer times out the
+/// thread becomes runnable again, and will run as soon as it becomes the
+/// highest-priority mapped runnable thread.
+///
+/// Sleeping threads may also be later suspended. In this case the Sleep timer
+/// continues to run, and if it times out before the thread is resumed the
+/// thread will be immediately runnable when it is resumed.
+///
+/// See the SSX specification for a full discussion of how SSX handles
+/// scheduling events at absolute times "in the past". Briefly stated, if the
+/// \a interval is 0 or is so small that the absolute time becomes a "past"
+/// time before the Sleep is actually scheduled, the thread will Sleep for the
+/// briefest possible period supported by the hardware.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread
+/// context.
+
+int
+ssx_sleep(SsxInterval interval)
+{
+ return ssx_sleep_absolute(ssx_timebase_get() + interval);
+}
+
+
+/// Get information about a thread.
+///
+/// \param thread A pointer to the SsxThread to query
+///
+/// \param state The value returned through this pointer is the current state
+/// of the thread; See \ref ssx_thread_states. The caller can set this
+/// parameter to the null pointer (0) if this information is not required.
+///
+/// \param priority The value returned through this pointer is the current
+/// priority of the thread. The caller can set this parameter to the null
+/// pointer (0) if this information is not required.
+///
+/// \param runnable The value returned through this pointer is 1 if the thread
+/// is in state SSX_THREAD_STATE_MAPPED and is currently in the run queue
+/// (i.e., neither blocked on a semaphore nor sleeping), otherwise 0. The
+/// caller can set this parameter to the null pointer (0) if this information
+/// is not required.
+///
+/// The information returned by this API can only be guaranteed consistent if
+/// the API is called from an SSX_NONCRITICAL critical section. Since the
+/// implementation of this API does not enforce a critical section, it is not
+/// an error to call this API from a critical interrupt context.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_THREAD_AT_INFO The \a thread is a null (0) pointer.
+
+int
+ssx_thread_info_get(SsxThread *thread,
+ SsxThreadState *state,
+ SsxThreadPriority *priority,
+ int *runnable)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_INFO);
+ }
+
+ if (state) {
+ *state = thread->state;
+ }
+ if (priority) {
+ *priority = thread->priority;
+ }
+ if (runnable) {
+ *runnable = ((thread->state == SSX_THREAD_STATE_MAPPED) &&
+ __ssx_thread_queue_member(&__ssx_run_queue,
+ thread->priority));
+ }
+ return SSX_OK;
+}
+
+
+/// Change the priority of a thread.
+///
+/// \param thread The thread whose priority will be changed
+///
+/// \param new_priority The new priority of the thread
+///
+/// \param old_priority The value returned through this pointer is the
+/// old priority of the thread prior to the change. The caller can set
+/// this parameter to the null pointer (0) if this information is not
+/// required.
+///
+/// Thread priorities can be changed by the \c ssx_thread_priority_change()
+/// API. This call will fail if the thread pointer is invalid or if the thread
+/// is mapped and the new priority is currently in use. The call will succeed
+/// even if the \a thread is suspended, completed or deleted. The
+/// application-level scheduling algorithm is completely responsible for the
+/// correctness of the application in the event of suspended, completed or
+/// deleted threads.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion, including the redundant case of
+/// attempting to change the priority of the thread to its current priority.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD the API was called from a critical
+/// interrupt context.
+///
+/// \retval -SSX_INVALID_THREAD_AT_CHANGE The \a thread is null (0) or
+/// otherwise invalid.
+///
+/// \retval -SSX_INVALID_ARGUMENT_THREAD_CHANGE The \a new_priority is invalid.
+///
+/// \retval -SSX_PRIORITY_IN_USE_AT_CHANGE The \a thread is mapped and the \a
+/// new_priority is currently in use by another thread.
+
+int
+ssx_thread_priority_change(SsxThread *thread,
+ SsxThreadPriority new_priority,
+ SsxThreadPriority *old_priority)
+{
+ SsxMachineContext ctx;
+ SsxThreadPriority priority;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_CHANGE);
+ SSX_ERROR_IF(new_priority > SSX_THREADS,
+ SSX_INVALID_ARGUMENT_THREAD_CHANGE);
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ priority = thread->priority;
+
+ if (priority != new_priority) {
+
+ if (!__ssx_thread_is_mapped(thread)) {
+
+ thread->priority = new_priority;
+
+ } else {
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL(__ssx_priority_map[new_priority] != 0,
+ SSX_PRIORITY_IN_USE_AT_CHANGE,
+ &ctx);
+ }
+
+ __ssx_thread_unmap(thread);
+ thread->priority = new_priority;
+ __ssx_thread_map(thread);
+ __ssx_schedule();
+ }
+ }
+
+ if (old_priority) {
+ *old_priority = priority;
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Return a pointer to the thread (if any) mapped at a given priority.
+///
+/// \param priority The thread priority of interest
+///
+/// \param thread The value returned through this pointer is a pointer to the
+/// thread currently mapped at the given priority level. If no thread is
+/// mapped, or if the \a priority is the priority of the idle thread, the
+/// pointer returned will be null (0).
+///
+/// The information returned by this API can only be guaranteed consistent if
+/// the API is called from an SSX_NONCRITICAL critical section. Since the
+/// implementation of this API does not require a critical section, it is not
+/// an error to call this API from a critical interrupt context.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion.
+///
+/// \retval -SSX_INVALID_ARGUMENT_THREAD_PRIORITY The \a priority is invalid
+/// or the \a thread parameter is null (0).
+
+int
+ssx_thread_at_priority(SsxThreadPriority priority,
+ SsxThread **thread)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((priority > SSX_THREADS) || (thread == 0),
+ SSX_INVALID_ARGUMENT_THREAD_PRIORITY);
+ }
+
+ *thread = __ssx_thread_at_priority(priority);
+
+ return SSX_OK;
+}
+
+
+/// Swap thread priorities
+///
+/// \param thread_a A pointer to an initialized SsxThread
+///
+/// \param thread_b A pointer to an initialized SsxThread
+///
+/// This API swaps the priorities of \a thread_a and \a thread_b. The API is
+/// provided to support general and efficient application-directed scheduling
+/// algorithms. The requirements on the \a thread_a and \a thread_b arguments
+/// are that they are valid pointers to initialized SsxThread structures, that
+/// the current thread priorities of both threads are legal, and that if a
+/// thread is currently mapped, that the new thread priority is not otherwise
+/// in use.
+///
+/// The API does not require either thread to be mapped, or even to be active.
+/// It is legal for one or both of the swap partners to be suspended, deleted
+/// or completed threads. The application is completely responsible for the
+/// correctness of scheduling algorithms that might operate on inactive or
+/// suspended threads.
+///
+/// The API does not change the mapped status of a thread. A thread will be
+/// mapped after the call of ssx_thread_priority_swap() if and only if it was
+/// mapped prior to the call. If the new priority of a mapped thread is
+/// currently in use (by a thread other than the swap partner), then the
+/// SSX_PRIORITY_IN_USE_AT_SWAP error is signalled and the swap does not take
+/// place. This could only happen if the swap partner is not currently mapped.
+///
+/// It is legal for a thread to swap its own priority with another thread. The
+/// degenerate case that \a thread_a and \a thread_b are equal is also legal -
+/// but has no effect.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion, including the redundant cases that do not
+/// actually change priorities, or the cases that assign new priorities to
+/// suspended, completed or deleted threads.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_THREAD the API was called from a critical
+/// interrupt context.
+///
+/// \retval -SSX_INVALID_THREAD_AT_SWAP1 One or both of \a thread_a and
+/// \a thread_b is null (0) or otherwise invalid,
+///
+/// \retval -SSX_INVALID_THREAD_AT_SWAP2 the priorities of One or both of
+/// \a thread_a and \a thread_b are invalid.
+///
+/// \retval -SSX_INVALID_ARGUMENT One or both of the priorities
+/// of \a thread_a and \a thread_b is invalid.
+///
+/// \retval -SSX_PRIORITY_IN_USE_AT_SWAP Returned if a thread is mapped and the
+/// new thread priority is currently in use by another thread (other than the
+/// swap partner).
+
+int
+ssx_thread_priority_swap(SsxThread* thread_a, SsxThread* thread_b)
+{
+ SsxMachineContext ctx;
+ SsxThreadPriority priority_a, priority_b;
+ int mapped_a, mapped_b;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF((thread_a == 0) || (thread_b == 0),
+ SSX_INVALID_THREAD_AT_SWAP1);
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ if (thread_a != thread_b) {
+
+ mapped_a = __ssx_thread_is_mapped(thread_a);
+ mapped_b = __ssx_thread_is_mapped(thread_b);
+ priority_a = thread_a->priority;
+ priority_b = thread_b->priority;
+
+ if (SSX_ERROR_CHECK_API) {
+ int priority_in_use;
+ SSX_ERROR_IF_CRITICAL((priority_a > SSX_THREADS) ||
+ (priority_b > SSX_THREADS),
+ SSX_INVALID_THREAD_AT_SWAP2,
+ &ctx);
+ priority_in_use =
+ (mapped_a && !mapped_b &&
+ (__ssx_thread_at_priority(priority_b) != 0)) ||
+ (!mapped_a && mapped_b &&
+ (__ssx_thread_at_priority(priority_a) != 0));
+ SSX_ERROR_IF_CRITICAL(priority_in_use,
+ SSX_PRIORITY_IN_USE_AT_SWAP, &ctx);
+ }
+
+ if (mapped_a) {
+ __ssx_thread_unmap(thread_a);
+ }
+ if (mapped_b) {
+ __ssx_thread_unmap(thread_b);
+ }
+ thread_a->priority = priority_b;
+ thread_b->priority = priority_a;
+ if (mapped_a) {
+ __ssx_thread_map(thread_a);
+ }
+ if (mapped_b) {
+ __ssx_thread_map(thread_b);
+ }
+ __ssx_schedule();
+ }
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+#undef __SSX_THREAD_CORE_C__
diff --git a/src/ssx/ssx/ssx_thread_init.c b/src/ssx/ssx/ssx_thread_init.c
new file mode 100755
index 0000000..c1a71b5
--- /dev/null
+++ b/src/ssx/ssx/ssx_thread_init.c
@@ -0,0 +1,140 @@
+// $Id: ssx_thread_init.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_thread_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_thread_init.c
+/// \brief SSX thread API initialization routines
+///
+/// The entry points in this file are routines that are typically used during
+/// initialization, and their code space could be deallocated and recovered if
+/// no longer needed by the application after initialization.
+
+#include "ssx.h"
+
+/// Create (initialize) a thread
+///
+/// \param thread A pointer to an SsxThread structure to initialize
+///
+/// \param thread_routine The subroutine that implements the thread
+///
+/// \param arg Private data to be passed as the argument to the thread
+/// routine when it begins execution
+///
+/// \param stack The stack space of the thread
+///
+/// \param stack_size The size of the stack in bytes
+///
+/// \param priority The initial priority of the thread
+///
+/// The \a thread argument must be a pointer to an uninitialized or completed
+/// or deleted thread. This \c SsxThread structure \em is the thread, so this
+/// memory area must not be modified by the application until the thread
+/// completes or is deleted. SSX can not tell if an SsxThread structure is
+/// currently in use as a thread control block.ssx_thread_create() will
+/// silently overwrite an SsxThread structure that is currently in use.
+///
+/// The stack area must be large enough to hold the dynamic stack requirements
+/// of the entry point routine, and all subroutines and functions that might
+/// be invoked on any path from the entry point. The stack must also always
+/// be able to hold the thread context in the event the thread is preempted,
+/// plus other critical context. SSX aligns stack areas in machine-specific
+/// ways, so that the actual stack area may reduced in size slightly if it is
+/// not already aligned.
+///
+/// Threads are created runnable but unmapped. A newly created thread will
+/// not be eligible to run until a call of ssx_thread_resume() targets the
+/// thread.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_THREAD_AT_CREATE The \a thread is a null (0) pointer.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt
+/// context.
+///
+/// \retval -SSX_INVALID_ARGUMENT_THREAD1 the \a thread_routine is null (0)
+///
+/// \retval -SSX_INVALID_ARGUMENT_THREAD2 the \a priority is invalid,
+///
+/// \retval -SSX_INVALID_ARGUMENT_THREAD3 the stack area wraps around
+/// the end of memory.
+///
+/// \retval -SSX_STACK_OVERFLOW The stack area at thread creation is smaller
+/// than the minimum safe size.
+
+int
+ssx_thread_create(SsxThread *thread,
+ SsxThreadRoutine thread_routine,
+ void *arg,
+ SsxAddress stack,
+ size_t stack_size,
+ SsxThreadPriority priority)
+{
+ int rc;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_CREATE);
+ SSX_ERROR_IF((thread_routine == 0) ||
+ (priority >= SSX_THREADS),
+ SSX_INVALID_ARGUMENT_THREAD1);
+ }
+
+ rc = __ssx_stack_init(&stack, &stack_size);
+ if (rc) {
+ return rc;
+ }
+
+ thread->saved_stack_pointer = stack;
+ thread->stack_base = stack;
+
+ if (SSX_STACK_DIRECTION < 0) {
+
+ thread->stack_limit = stack - stack_size;
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(thread->stack_limit > thread->stack_base,
+ SSX_INVALID_ARGUMENT_THREAD2);
+ }
+
+ } else {
+
+ thread->stack_limit = stack + stack_size;
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(thread->stack_limit < thread->stack_base,
+ SSX_INVALID_ARGUMENT_THREAD3);
+ }
+ }
+
+ thread->semaphore = 0;
+ thread->priority = priority;
+ thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE;
+ thread->flags = 0;
+
+ ssx_timer_create_nonpreemptible(&(thread->timer),
+ __ssx_thread_timeout,
+ (void *)thread);
+
+ __ssx_thread_context_initialize(thread, thread_routine, arg);
+
+ return rc;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ssx/ssx/ssx_timer_core.c b/src/ssx/ssx/ssx_timer_core.c
new file mode 100755
index 0000000..8153acf
--- /dev/null
+++ b/src/ssx/ssx/ssx_timer_core.c
@@ -0,0 +1,447 @@
+// $Id: ssx_timer_core.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_timer_core.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_timer_core.c
+/// \brief SSX portable kernel timer handler
+///
+/// This file contains core routines that would be needed by any application
+/// that requires SSX timer support at runtime.
+///
+/// SSX implements a 'tickless' kernel - all events are scheduled at absolute
+/// times of the SSX timebase. This approach gives the application full
+/// control over granularity of event scheduling. Scheduling in absolute time
+/// opens up the possibility of scheduling events "in the past". SSX
+/// uniformly handles this case by scheduling "past" events to occur 1
+/// timebase tick in the future, so that timer callbacks are always run in the
+/// expected noncritical interrupt context.
+///
+/// SSX implements the time queue as a simple unordered list of events, plus a
+/// dedicated variable that holds the earliest timeout of any event in the
+/// list. This is thought to be an appropriate data structure for the
+/// following reasons:
+///
+/// - SSX applications will be small and will not schedule a large number of
+/// events. Therefore the cost of scanning the list each time an event times
+/// out is balanced against the cost of maintaining the list as a sorted data
+/// structure each time an event is added or removed from the event queue.
+///
+/// - SSX applications may schedule and cancel many, many more events (safety
+/// timeouts) than are ever allowed to expire. Events can be added and deleted
+/// from the simple DEQUE very quickly since there is no sorting
+/// overhead.
+///
+/// Events are added to the queue simply by placing them at the end of the
+/// queue. If the new event times out earlier than the previous earliest
+/// event, the hardware timeout is rescheduled for the new event time. Events
+/// are deleted from the queue (cancelled) simply by deleting them. Deletion
+/// does not affect the hardware timeout, even if the deleted event would have
+/// been the next to time out. It is not an error for the timer handler to
+/// take a timer interrupt and find no events pending. Pending events can
+/// also be rescheduled in place.
+///
+/// When a timeout occurs the event list is scanned from the beginning, and
+/// any event that has timed out is rescheduled if necessary (periodic events)
+/// and its callback is processed. Since event and callback processing take
+/// time, the list is potentially scanned multiple times until there are no
+/// more timed-out events in the list.
+///
+/// Note that callbacks are not necessarily processed in time-order. In this
+/// sense the SSX time queue is like a traditional tick-based time queue in
+/// that events are effectively lumped into groups of events that time out
+/// together. In a tick-based kernel the 'lump' is the tick interval; here
+/// the 'lump' is a variable interval that corresponds to the time it takes to
+/// process the entire event list.
+///
+/// Timer callbacks are typically run with interrupt preemption enabled.
+/// Special callbacks may run without preemption. This is the only part of
+/// the SSX kernel where data structures of indeterminate size are processed.
+/// During processing of the event list by the timer interrupt handler, the
+/// consideration of each event always includes a window of preemptability.
+
+#define __SSX_TIMER_CORE_C__
+
+#include "ssx.h"
+
+// This routine is only used in this file, and will always be called in
+// critical section.
+
+static inline int
+timer_active(SsxTimer* timer)
+{
+ return ssx_deque_is_queued((SsxDeque*)timer);
+}
+
+
+// This is the kernel version of ssx_timer_cancel().
+//
+// This routine is used here and by thread and semaphore routines.
+// Noncritical interrupts must be disabled at entry.
+//
+// If the timer is active, then there is a special case if we are going to
+// delete the 'cursor' - that is the timer that __ssx_timer_handler() is going
+// to handle next. In this case we need to move the cursor to the next timer
+// in the queue.
+//
+// Note that cancelling a timer does not cause a re-evaluation of the next
+// timeout. This will happen naturally when the current timeout expires.
+
+int
+__ssx_timer_cancel(SsxTimer *timer)
+{
+ int rc;
+ SsxDeque* timer_deque = (SsxDeque*)timer;
+ SsxTimeQueue* tq = &__ssx_time_queue;
+
+ if (!timer_active(timer)) {
+
+ rc = -SSX_TIMER_NOT_ACTIVE;
+
+ } else {
+
+ if (timer_deque == tq->cursor) {
+ tq->cursor = tq->cursor->next;
+ }
+ ssx_deque_delete(timer_deque);
+ rc = 0;
+ }
+ return rc;
+}
+
+
+// This is the kernel version of ssx_timer_schedule().
+//
+// This routine is used here and by thread and semaphore routines.
+// Noncritical interrupts must be disabled at entry.
+//
+// Unless the timer is already active it is enqueued in the doubly-linked
+// timer list by inserting the timer at the end of the queue. Then the
+// hardware timeout is scheduled if necessary. If the time queue 'cursor' != 0
+// we are in the midst of processing the time queue, and the end of time queue
+// processing will schedule the next hardware timemout.
+
+void
+__ssx_timer_schedule(SsxTimer* timer)
+{
+ SsxTimeQueue* tq = &__ssx_time_queue;
+
+ if (!timer_active(timer)) {
+ ssx_deque_push_back((SsxDeque*)tq, (SsxDeque*)timer);
+ }
+
+ if (timer->timeout < tq->next_timeout) {
+ tq->next_timeout = timer->timeout;
+ if (tq->cursor == 0) {
+ __ssx_schedule_hardware_timeout(tq->next_timeout);
+ }
+ }
+}
+
+
+// The tickless timer mechanism has timed out. Note that due to timer
+// deletions and other factors, there may not actually be a timer in the queue
+// that has timed out - but it doesn't matter (other than for efficiency).
+//
+// Noncritical interrupts are (must be) disabled at entry, and this invariant
+// is checked. This routine must not be entered reentrantly.
+//
+// First, time out any timers that have expired. Timers in the queue are
+// unordered, so we have to check every one. Since passing through the
+// loop takes time, we may have to make multiple passes until we know
+// that there are no timers in the queue that have already timed
+// out. Note that it would also work to only go through the loop once and
+// let the hardware scheduler take care of looping, but that would imply
+// more overhead than the current implementation.
+//
+// On each pass through the loop tq->next_timeout computes the minimum timeout
+// of events remaining in the queue. This is the only part of the kernel that
+// searches a list of indefinite length. Kernel interrupt latency is mitigated
+// by running callbacks with interrupts disabled either during or after the
+// call for timed out events, and also after every check for events that have
+// not timed out.
+//
+// Because interrupt preemption is enabled during processing, and preempting
+// handlers may invoke time queue operations, we need to establish a pointer
+// to the next entry to be examined (tq->cursor) before enabling interupts.
+// It's possible that this pointer will be changed by other interrupt handlers
+// that cancel the timer pointed to by tq->cursor.
+//
+// The main loop iterates on the SsxDeque form of the time queue, casting each
+// element back up to the SsxTimer as it is processed.
+
+void
+__ssx_timer_handler()
+{
+ SsxTimeQueue* tq;
+ SsxTimebase now;
+ SsxTimer* timer;
+ SsxDeque* timer_deque;
+ SsxTimerCallback callback;
+
+ tq = &__ssx_time_queue;
+
+ if (SSX_ERROR_CHECK_KERNEL) {
+ if (tq->cursor != 0) {
+ SSX_PANIC(SSX_TIMER_HANDLER_INVARIANT);
+ }
+ }
+
+ while ((now = ssx_timebase_get()) >= tq->next_timeout) {
+
+ tq->next_timeout = SSX_TIMEBASE_MAX;
+ timer_deque = ((SsxDeque*)tq)->next;
+
+ while (timer_deque != (SsxDeque*)tq) {
+
+ timer = (SsxTimer*)timer_deque;
+ tq->cursor = timer_deque->next;
+
+ if (timer->timeout <= now) {
+
+ // The timer timed out. It is removed from the queue unless
+ // it is a peridic timer that needs to be rescheduled. We do
+ // rescheduling here in the critical section to correctly
+ // handle timers whose callbacks may cancel the timer. The
+ // timer is rescheduled in absolute time.
+ //
+ // The callback may be made with interrupt preemption enabled
+ // or disabled. However to mitigate kernel interrupt latency
+ // we go ahead and open up to interrupts after the callback if
+ // the callback itself was not preemptible.
+
+ if (timer->period == 0) {
+ ssx_deque_delete(timer_deque);
+ } else {
+ timer->timeout += timer->period;
+ tq->next_timeout = MIN(timer->timeout, tq->next_timeout);
+ }
+
+ callback = timer->callback;
+ if (callback) {
+ if (timer->options & SSX_TIMER_CALLBACK_PREEMPTIBLE) {
+ ssx_interrupt_preemption_enable();
+ callback(timer->arg);
+ } else {
+ callback(timer->arg);
+ ssx_interrupt_preemption_enable();
+ }
+ }
+ ssx_interrupt_preemption_disable();
+
+ } else {
+
+ // This timer has not timed out. Its timeout will simply
+ // participate in the computation of the next timeout. For
+ // interrupt latency reasons we always allow a period of
+ // interrupt preemption.
+
+ tq->next_timeout = MIN(timer->timeout, tq->next_timeout);
+ ssx_interrupt_preemption_enable();
+ ssx_interrupt_preemption_disable();
+ }
+
+ timer_deque = tq->cursor;
+ }
+ }
+
+ tq->cursor = 0;
+
+ // Finally, reschedule the next timeout
+
+ __ssx_schedule_hardware_timeout(tq->next_timeout);
+}
+
+
+/// Schedule a timer in absolute time.
+///
+/// \param timer The SsxTimer to schedule.
+///
+/// \param timeout The timer will be scheduled to time out at this absolute
+/// time. Note that if the \a timeout is less than the current time then the
+/// timer will be scheduled at a minimum timeout in the future and the
+/// callback will be executed in an interrupt context.
+///
+/// \param period If non-0, then when the timer times out it will rescheduled
+/// to time out again at the absolute time equal to the last timeout time plus
+/// the \a period. By convention a \a period of 0 indicates a one-shot
+/// timer that is not rescheduled.
+///
+/// Once created with ssx_timer_create() a timer can be \e scheduled, which
+/// queues the timer in the kernel time queue. It is not an error to call
+/// ssx_timer_schedule() on a timer that is already scheduled in the time
+/// queue - the timer is simply rescheduled with the new characteristics.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as
+/// the \a timer argument.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical
+/// interrupt context.
+
+int
+ssx_timer_schedule_absolute(SsxTimer *timer,
+ SsxTimebase timeout,
+ SsxInterval period)
+
+{
+ SsxMachineContext ctx;
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_SCHEDULE);
+ SSX_ERROR_IF(__ssx_kernel_context_critical_interrupt(),
+ SSX_ILLEGAL_CONTEXT_TIMER);
+ }
+
+ timer->timeout = timeout;
+ timer->period = period;
+ __ssx_timer_schedule(timer);
+
+ ssx_critical_section_exit(&ctx);
+
+ return SSX_OK;
+}
+
+
+/// Schedule a timer for an interval relative to the current time.
+///
+/// \param timer The SsxTimer to schedule.
+///
+/// \param interval The timer will be scheduled to time out at the current
+/// time (ssx_timebase_get()) plus this \a interval.
+///
+/// \param period If non-0, then when the timer times out it will rescheduled
+/// to time out again at the absolute time equal to the last timeout time plus
+/// the \a period. By convention a \a period of 0 indicates a one-shot
+/// timer that is not rescheduled.
+///
+/// Once created with ssx_timer_create() a timer can be \e scheduled, which
+/// queues the timer in the kernel time queue. It is not an error to call \c
+/// ssx_timer_schedule() on a timer that is already scheduled in the time
+/// queue - the timer is simply rescheduled with the new characteristics.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as
+/// the \a timer argument.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical
+/// interrupt context.
+
+int
+ssx_timer_schedule(SsxTimer *timer,
+ SsxInterval interval,
+ SsxInterval period)
+{
+ return ssx_timer_schedule_absolute(timer,
+ ssx_timebase_get() + interval,
+ period);
+}
+
+
+/// Cancel (dequeue) a timer.
+///
+/// \param timer The SsxTimer to cancel.
+///
+/// Timers can be canceled at any time. It is never an error to call
+/// ssx_timer_cancel() on an SsxTimer object after it is created. Memory used
+/// by an SsxTimer can be safely reused for another purpose after a successful
+/// call ofssx_timer_cancel().
+///
+/// Return values other than SSX_OK (0) are not necessarily errors; see \ref
+/// ssx_errors
+///
+/// The following return codes are non-error codes:
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_TIMER_NOT_ACTIVE The \a timer is not currently scheduled,
+/// i.e. it was never scheduled or has timed out. This code is returned for
+/// information only and is not considered an error.
+///
+/// The following return codes are error codes:
+///
+/// \retval -SSX_INVALID_TIMER_AT_CANCEL The \a timer is a null (0) pointer.
+///
+/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical
+/// interrupt context.
+///
+
+int
+ssx_timer_cancel(SsxTimer *timer)
+{
+ SsxMachineContext ctx;
+ int rc = SSX_OK;
+
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT();
+ SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_CANCEL);
+ }
+
+ ssx_critical_section_enter(SSX_NONCRITICAL, &ctx);
+
+ rc = __ssx_timer_cancel(timer);
+
+ ssx_critical_section_exit(&ctx);
+
+ return rc;
+}
+
+
+/// Get information about a timer.
+///
+/// \param timer The SsxTimer to query
+///
+/// \param timeout The API returns the absolute timeout of the timer through
+/// this pointer. If the timer is active, this is the current timeout. If
+/// the timer has timed out then this is the previous absolute timeout. If
+/// the timer was never scheduled this will be 0. The caller can set this
+/// parameter to the null pointer (0) if this information is not required.
+///
+/// \param active If the value returned through this pointer is 1 then the
+/// timer is active (currently scheduled), otherwise the value will be 0
+/// indicating an inactive timer. The caller can set this parameter to the
+/// null pointer (0) if this information is not required.
+///
+/// The information returned by this API can only be guaranteed consistent if
+/// the API is called from an SSX_NONCRITICAL critical section. Since the
+/// implementation of this API does not require a critical section, it is not
+/// an error to call this API from a critical interrupt context.
+///
+/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_TIMER_AT_INFO The \a timer is a null (0) pointer.
+
+int
+ssx_timer_info_get(SsxTimer *timer,
+ SsxTimebase *timeout,
+ int *active)
+
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_INFO);
+ }
+
+ if (timeout) {
+ *timeout = timer->timeout;
+ }
+ if (active) {
+ *active = timer_active(timer);
+ }
+
+ return SSX_OK;
+}
+
+#undef __SSX_TIMER_CORE_C__
diff --git a/src/ssx/ssx/ssx_timer_init.c b/src/ssx/ssx/ssx_timer_init.c
new file mode 100755
index 0000000..6c35ea6
--- /dev/null
+++ b/src/ssx/ssx/ssx_timer_init.c
@@ -0,0 +1,124 @@
+// $Id: ssx_timer_init.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_timer_init.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_timer_init.c
+/// \brief SSX timer initialization
+///
+/// The entry points in this file might only be used during initialization of
+/// the application. In this case the code space for these routines could be
+/// recovered and reused after initialization.
+
+#include "ssx.h"
+
+// Implementation of timer creation
+
+static int
+_ssx_timer_create(SsxTimer *timer,
+ SsxTimerCallback callback,
+ void *arg,
+ int options)
+{
+ if (SSX_ERROR_CHECK_API) {
+ SSX_ERROR_IF((timer == 0), SSX_INVALID_TIMER_AT_CREATE);
+ }
+
+ ssx_deque_element_create((SsxDeque*)timer);
+ timer->timeout = 0;
+ timer->period = 0;
+ timer->callback = callback;
+ timer->arg = arg;
+ timer->options = options;
+
+ return SSX_OK;
+}
+
+
+/// Create (initialize) a preemptible timer.
+///
+/// \param timer The SsxTimer to initialize.
+///
+/// \param callback The timer callback
+///
+/// \param arg Private data provided to the callback.
+///
+/// Once created with ssx_timer_create() a timer can be scheduled with
+/// ssx_timer_schedule() or ssx_timer_schedule_absolute(), which queues the
+/// timer in the kernel time queue. Timers can be cancelled by a call of
+/// ssx_timer_cancel().
+///
+/// Timers created with ssx_timer_create() are always run as noncritical
+/// interrupt handlers with interrupt preemption enabled. Timer callbacks are
+/// free to enter critical sections of any priorioty if required, but must
+/// always exit with noncritical interrupts enabled.
+///
+/// Caution: SSX has no way to know if an SsxTimer structure provided to
+/// ssx_timer_create() is safe to use as a timer, and will silently modify
+/// whatever memory is provided.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_TIMER_AT_CREATE The \a timer is a null (0) pointer.
+
+int
+ssx_timer_create(SsxTimer *timer,
+ SsxTimerCallback callback,
+ void *arg)
+{
+ return _ssx_timer_create(timer, callback, arg,
+ SSX_TIMER_CALLBACK_PREEMPTIBLE);
+}
+
+
+/// Create (initialize) a nonpreemptible timer.
+///
+/// \param timer The SsxTimer to initialize.
+///
+/// \param callback The timer callback
+///
+/// \param arg Private data provided to the callback.
+///
+/// Once created with ssx_timer_create_preemptible() a timer can be scheduled
+/// with ssx_timer_schedule() or ssx_timer_schedule_absolute(), which queues
+/// the timer in the kernel time queue. Timers can be cancelled by a call of
+/// ssx_timer_cancel().
+///
+/// Timers created with ssx_timer_create_nonpreemptible() are always run as
+/// noncritical interrupt handlers with interrupt preemption disabled. Timer
+/// callbacks are free to later enable preemption if desired, but must always
+/// exit with noncritical interrupts disabled.
+///
+/// \note The use of ssx_timer_create_nonpreemptible() should be rare, and the
+/// timer callbacks should be short and sweet to avoid long interrupt
+/// latencies for other interrupts. This API was initially introduced for use
+/// by the SSX kernel itself when scheduling thread-timer callbacks to avoid
+/// potential race conditions with other interrupts that may modify thread
+/// state or the state of the time queue. Applications may also require this
+/// facility to guarantee a consistent state in the event that other
+/// interrupts may cancel the timer.
+///
+/// Caution: SSX has no way to know if an SsxTimer structure provided to
+/// ssx_timer_create() is safe to use as a timer, and will silently modify
+/// whatever memory is provided.
+///
+/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -SSX_INVALID_TIMER_AT_CREATE The \a timer is a null (0) pointer.
+
+int
+ssx_timer_create_nonpreemptible(SsxTimer *timer,
+ SsxTimerCallback callback,
+ void *arg)
+{
+ return _ssx_timer_create(timer, callback, arg, 0);
+}
+
+
diff --git a/src/ssx/ssx/ssxssxfiles.mk b/src/ssx/ssx/ssxssxfiles.mk
new file mode 100755
index 0000000..e78e986
--- /dev/null
+++ b/src/ssx/ssx/ssxssxfiles.mk
@@ -0,0 +1,35 @@
+# $Id: ssxssxfiles.mk,v 1.2 2014/06/26 13:02:00 cmolsen Exp $
+# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssxssxfiles.mk,v $
+# @file ssxpgpfiles.mk
+#
+# @brief mk for including pgp object files
+#
+# @page ChangeLogs Change Logs
+# @section ssxpgpfiles.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+# @pb00E pbavari 03/11/2012 Makefile ODE support
+#
+# @endverbatim
+#
+##########################################################################
+# Include
+##########################################################################
+
+
+##########################################################################
+# Object Files
+##########################################################################
+SSX-C-SOURCES = ssx_core.c ssx_init.c ssx_stack_init.c
+
+SSX-TIMER-C-SOURCES += ssx_timer_core.c ssx_timer_init.c
+
+SSX-THREAD-C-SOURCES += ssx_thread_init.c ssx_thread_core.c \
+ ssx_semaphore_init.c ssx_semaphore_core.c
+
+SSX_OBJECTS += $(SSX-C-SOURCES:.c=.o)
+
OpenPOWER on IntegriCloud