diff options
Diffstat (limited to 'src/usr/initservice/istepdispatcher')
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.C | 546 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.H | 135 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/isteplist.H | 81 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/makefile | 3 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/splesscommand.C | 113 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/splesscommon.H | 269 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/splessstatus.C | 93 |
7 files changed, 1060 insertions, 180 deletions
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C index 5dfb5a53e..002cc59d4 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.C +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C @@ -24,7 +24,9 @@ /** * @file istepdispatcher.C * - * IStep Dispatcher interface. Launched from Extended Initialization Service + * IStep Dispatcher code. Launched from Extended Initialization Service + * + * PNOR Driver and Trace should be available by the time this is launched. * */ @@ -36,12 +38,18 @@ #include <stdio.h> #include <string.h> -#include <sys/task.h> // tid_t, task_create, etc -#include <trace/interface.H> // trace support -#include <errl/errlentry.H> // errlHndl_t +#include <sys/task.h> // tid_t, task_create, etc +#include <sys/time.h> // nanosleep +#include <trace/interface.H> // trace support +#include <errl/errlentry.H> // errlHndl_t +#include <devicefw/userif.H> // targeting +#include <sys/mmio.h> // mmio_scratch_read() #include "istepdispatcher.H" -#include "isteplist.H" + +#include "splesscommon.H" + +#include <isteps/isteplist.H> namespace INITSERVICE @@ -53,102 +61,502 @@ namespace INITSERVICE extern trace_desc_t *g_trac_initsvc; /** - * @brief set up _start() task entry procedure using the macro + * @enum + * SPLess Task return codes + * + * task return codes for SPless single step + * @note future errors will be passed from task_create() and task_exec() + * and should be documented in errno.h + * + */ +enum { + SPLESS_TASKRC_INVALID_ISTEP = -3, // invalid istep or substep + SPLESS_TASKRC_LAUNCH_FAIL = -4, // failed to launch the task + SPLESS_TASKRC_RETURNED_ERRLOG = -5, // istep returned an errorlog + SPLESS_TASKRC_TERMINATED = -6, // terminated the polling loop +}; + +/** + * @note SPLess PAUSE - These two constants are used in a nanosleep() call + * below to sleep between polls of the StatusReg. Typically this will + * be about 100 ms - the actual value will be determined empirically. + * + * @debug simics "feature" - set polling time to 1 sec for demo + * + */ + +const uint64_t SINGLESTEP_PAUSE_S = 1; +const uint64_t SINGLESTEP_PAUSE_NS = 100000000; + + +/** + * @brief set up _start() task entry procedure using the macro in taskargs.H */ TASK_ENTRY_MACRO( IStepDispatcher::getTheInstance().init ); -IStepDispatcher::IStepDispatcher() -: iv_istepmodeflag(false), - iv_nextistep( 0 ), - iv_cancontinueflag(false) +const TaskInfo *IStepDispatcher::findTaskInfo( const uint16_t i_IStep, + const uint16_t i_SubStep ) const { + const TaskInfo *l_pistep = NULL; + + TRACDCOMP( g_trac_initsvc, + "g_isteps[%d].numitems = 0x%x", + i_IStep, + g_isteps[i_IStep].numitems ); + + // apply filters + do + { + + // check input range - IStep + if ( i_IStep >= MAX_ISTEPS ) + { + TRACDCOMP( g_trac_initsvc, + "IStep 0x%x out of range.", + i_IStep ); + break; // break out with l_pistep set to NULL + } + + // check input range - ISubStep + if ( i_SubStep >= g_isteps[i_IStep].numitems ) + { + TRACDCOMP( g_trac_initsvc, + "IStep 0x%x Substep 0x%x out of range.", + i_IStep, + i_SubStep ); + break; // break out with l_pistep set to NULL + } + + // check for end of list. + if ( g_isteps[i_IStep].pti[i_SubStep].taskflags.task_type + == END_TASK_LIST ) + { + TRACDCOMP( g_trac_initsvc, + "IStep 0x%x SubSStep 0x%x task_type==END_TASK_LIST.", + i_IStep, + i_SubStep ); + break; + } + + // looks good, send it back to the caller + TRACDCOMP( g_trac_initsvc, + "Found TaskInfo 0x%x 0x%x", + i_IStep, + i_SubStep ); + l_pistep = &( g_isteps[i_IStep].pti[i_SubStep] ); + } while ( 0 ); + + return l_pistep; } -IStepDispatcher::~IStepDispatcher() +void IStepDispatcher::init( void * io_ptr ) { + TRACFCOMP( g_trac_initsvc, + ENTER_MRK "starting IStepDispatcher, io_ptr=%p ", + io_ptr ); + + if ( getIStepMode() ) + { + TRACFCOMP( g_trac_initsvc, + "IStep single-step" ); + // IStep single-step + singleStepISteps( io_ptr ); + } + else + { + TRACFCOMP( g_trac_initsvc, + "IStep run all" ); + // Run all the ISteps sequentially + runAllISteps( io_ptr ); + } // endelse + + + TRACFCOMP( g_trac_initsvc, + EXIT_MRK "IStepDispatcher finished."); } -IStepDispatcher& IStepDispatcher::getTheInstance() +bool IStepDispatcher::getIStepMode( ) const { - return Singleton<IStepDispatcher>::instance(); + + return iv_istepmodeflag; +} + + +/** + * @todo revisit this when PNOR Driver is implemented + * + */ +void IStepDispatcher::initIStepMode( ) +{ + uint64_t l_readData = 0; + + l_readData = mmio_scratch_read( MMIO_SCRATCH_IPLSTEP_CONFIG ); + + TRACDCOMP( g_trac_initsvc, + "SCOM ScratchPad read, Offset 0x%x, Data 0x%llx", + MMIO_SCRATCH_IPLSTEP_CONFIG, + l_readData ); + + // check for IStep Mode signature + if ( l_readData == ISTEP_MODE_SIGNATURE ) + { + iv_istepmodeflag = true; + } + else + { + iv_istepmodeflag = false; + } + } -void IStepDispatcher::init( void * ptr ) +void IStepDispatcher::singleStepISteps( void * io_ptr ) const { - errlHndl_t errl = NULL; - uint64_t nextIStep = 0; - const TaskInfo *pistep = NULL; - TaskArgs::TaskArgs args; + errlHndl_t l_errl = NULL; + TaskArgs::TaskArgs l_args; + const TaskInfo *l_pistep = NULL; + bool l_gobit = false; + uint16_t l_nextIStep = 0; + uint16_t l_nextSubstep = 0; + uint16_t l_taskStatus = 0; + uint16_t l_istepStatus = 0; + uint32_t l_progresscode = 0; + uint64_t l_isteprc = 0; + + TRACFCOMP( g_trac_initsvc, "Start IStep single-step.\n" ); + + // initialize command reg + SPLESSCMD::write( false, // go bit is false + 0, // istep = 0 + 0 ); // substep = 0 + + SPLESSSTS::write( false, // running bit + true, // ready bit + 0, // istep running + 0, // substep running + 0, // task status + 0 ); // istep status + + // + // @note Start the polling loop. + // Currently this has no exit, user should reset the machine and/or + // load the payload, which will wipe HostBoot from memory. + // Loop forever, unless something Very Bad happens. + // + while( 1 ) + { + // read command reg, updates l_gobit, l_nextIStep, l_nextSubstep + SPLESSCMD::read( l_gobit, + l_nextIStep, + l_nextSubstep ); - TRACFCOMP( g_trac_initsvc, - ENTER_MRK "starting IStepDispatcher, ptr=%p. &args=%p", - ptr, &args ); + // process any commands + if ( l_gobit ) + { + TRACDCOMP( g_trac_initsvc, + "gobit turned on, istep=0x%x, substep=0x%x", + l_nextIStep, + l_nextSubstep ); + + // look up istep+substep + l_pistep = findTaskInfo( l_nextIStep, + l_nextSubstep ); + if ( l_pistep == NULL ) + { + // no istep TaskInfo returned, update status & drop to end. + TRACFCOMP( g_trac_initsvc, + "Invalid IStep 0x%x / substep 0x%x, try again.", + l_nextIStep, + l_nextSubstep ); + SPLESSSTS::write( false, + true, + l_nextIStep, + l_nextSubstep, + SPLESS_TASKRC_INVALID_ISTEP, + 0 ); + } + else + { + // set running bit, fill in istep and substep + SPLESSSTS::write( true, // set running bit + true, // ready bit + l_nextIStep, // running istep + l_nextSubstep, // running substep + 0, // task status (=0) + 0 ); // istep status(=0) + + /** + * @todo placeholder - set progress code before starting + * This will not be finalized until the progress code driver + * is designed and implemented. + */ + l_progresscode = ( (l_nextIStep<<16) | l_nextSubstep ); + InitService::getTheInstance().setProgressCode( l_progresscode ); + + // launch the istep + TRACDCOMP( g_trac_initsvc, + "execute Istep=0x%x / Substep=0x%x", + l_nextIStep, + l_nextSubStep ); + + // clear status, etc for the next istep + l_taskStatus = 0; + l_istepStatus = 0; + l_args.clear(); + + // launch the istep + l_errl = InitService::getTheInstance().executeFn( l_pistep, + &l_args ); + // filter errors returning from executeFn + if ( l_errl ) + { + // handle an errorlog from the parent. This means the + // launch failed, set the task Status to Bad. + // no need to process child info, thus the else. + // set the taskStatus to LAUNCH_FAIL; this will fall + // out the bottom and be written to SPLESS Status + l_taskStatus = SPLESS_TASKRC_LAUNCH_FAIL; + TRACFCOMP( g_trac_initsvc, + "ERROR 0x%x: function launch FAIL", + l_taskStatus ); + errlCommit( l_errl ); + } + else + { + // process information returned from the IStep. + // make local copies of the info; this has a secondary + // effect of clearing the errorlog pointer inside + // the TaskArgs struct. + l_isteprc = l_args.getReturnCode(); // local copy + l_errl = l_args.getErrorLog(); // local copy + + TRACDCOMP( g_trac_initsvc, + "IStep TaskArgs return 0x%llx, errlog=%p", + l_isteprc, + l_errl ); + + // check for child errorlog + if ( l_errl ) + { + // tell the user that the IStep returned an errorlog + l_taskStatus = SPLESS_TASKRC_RETURNED_ERRLOG; + // go ahead and commit the child errorlog + errlCommit( l_errl); + } + + // massage the return code from the IStep - + // If the istep did not set an errorcode, + // then we report 0 + if ( l_isteprc == TASKARGS_UNDEFINED64 ) + { + l_istepStatus = 0; + } + else + { + // truncate IStep return status to 16 bits. + l_isteprc &= 0x000000000000ffff; + l_istepStatus = static_cast<uint16_t>(l_isteprc); + } + + } // end else parent errlog + + // l_taskStatus and l_istepStatus should be set correctly now, + // send it to the user. + // clear runningbit, report status + TRACDCOMP( g_trac_initsvc, + "Write IStep Status: istep=0x%x, substep=0x%x, taskstatus=0x%x, istepstatus=0x%x", + l_nextIStep, + l_nextSubstep, + l_taskStatus, + l_istepStatus ); + SPLESSSTS::write( false, // clear running bit + true, // ready bit + l_nextIStep, // running istep + l_nextSubstep, // running substep + l_taskStatus, // task status + l_istepStatus // istepStatus + ); + + SPLESSCMD::setgobit( false ); // clear gobit + } // end else l_pistep + } // endif gobit + + // sleep, and wait for user to give us something else to do. + nanosleep( SINGLESTEP_PAUSE_S, SINGLESTEP_PAUSE_NS ); + } // endwhile + + + // @note + // Fell out of loop, clear sts reg and turn off readybit + // Currently this will never be reached. Later there may be + // a reason to break out of the loop, if this happens we want to + // disable the ready bit so the user knows. + SPLESSSTS::write( false, + false, + 0, + 0, + SPLESS_TASKRC_TERMINATED, + 0 + ); + + // all errorlogs should have been committed in the loop, we should + // not have any errorlogs still set. + if ( l_errl ) + { + // if we do then commit it and stop here. + errlCommit( l_errl ); + assert(0); + } + +} - for ( nextIStep=0; - nextIStep<INITSERVICE::MAX_ISTEPS; - nextIStep++ ) + +void IStepDispatcher::runAllISteps( void * io_ptr ) const +{ + errlHndl_t l_errl = NULL; + uint16_t l_IStep = 0; + uint16_t l_SubStep = 0; + const TaskInfo *l_pistep = NULL; + TaskArgs::TaskArgs l_args; + uint64_t l_progresscode = 0; + uint64_t l_isteprc = 0; + + for ( l_IStep=0; + l_IStep<INITSERVICE::MAX_ISTEPS; + l_IStep++ ) { - pistep = &(g_isteps[nextIStep]); - if ( pistep->taskflags.task_type == END_TASK_LIST ) + for ( l_SubStep=0; + l_SubStep < INITSERVICE::MAX_SUBSTEPS; + l_SubStep++) { TRACDCOMP( g_trac_initsvc, - "End of IStep list.\n" ); - break; - } + "Find IStep=%d, SubStep=%d", + l_IStep, + l_SubStep ); + l_pistep = findTaskInfo( l_IStep, + l_SubStep ); + if ( l_pistep == NULL ) + { - args.clear(); // clear the args struct for the next istep - errl = InitService::getTheInstance().executeFn( pistep, - &args ); + TRACDCOMP( g_trac_initsvc, + "End of ISubStep list." ); + break; // break out of inner for loop + } - // handle an errorlog from the parent, if it exists - InitService::getTheInstance().reportError( errl ); + // @todo placeholder until progress codes are defined and + // progress code driver is implemented. + l_progresscode = ( (l_IStep<<16) | l_SubStep ); + InitService::getTheInstance().setProgressCode( l_progresscode ); - /** - * @todo call getCanContinueProcedure when we have some ISteps that - * require them. - */ + l_args.clear(); - if ( args.getReturnCode() != TASKARGS_UNDEFINED64 ) - { TRACFCOMP( g_trac_initsvc, - ERR_MRK "IStep TaskArgs returned 0x%llx, errlog=%p", - args.getReturnCode(), - args.getErrorLog() - ); + "Run IStep 0x%x / Substep 0x%x", + l_IStep, + l_SubStep ); + + l_errl = InitService::getTheInstance().executeFn( l_pistep, + &l_args ); + if ( l_errl ) + { + // Handle an errorlog from the parent, if it exists + // an error here is probably fatal, it means we can't + // launch the task or it doesn't exist. In either + // case we should exit the loop. + // Can't commit the errorlog here because we are using it + // as a flag to exit the loop. + break; + } + + // make local copies of the status returned from the istep. + // note that this also removes the errorlog from the TaskArgs + // struct - it is read-once. See taskargs.H for details + l_isteprc = l_args.getReturnCode(); + l_errl = l_args.getErrorLog(); + + TRACDCOMP( g_trac_initsvc, + "IStep TaskArgs returned 0x%llx, errlog=%p", + l_isteprc, + l_errl ); + if ( l_errl ) + { + // if we have an errorlog, break out of the inner loop + // and handle it. + break; + } + else + { + // Check child results for a valid nonzero return code. + // If we have one, and no errorlog, then we create an + // errorlog here. + if ( ( l_isteprc != TASKARGS_UNDEFINED64 ) + && ( l_isteprc != 0 ) + ) + { + TRACFCOMP( g_trac_initsvc, + "istep returned 0x%llx, no errlog", + l_isteprc ); + + /*@ errorlog tag + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid see task list + * @reasoncode ISTEP_FAILED_NO_ERRLOG + * @userdata1 returncode from istep + * @userdata2 0 + * + * @devdesc The Istep returned with an error, + * but there was no errorlog posted + * from the IStep. + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + l_pistep->taskflags.module_id, + INITSERVICE::ISTEP_FAILED_NO_ERRLOG, + l_isteprc, + 0 ); + // drop out of inner loop with errlog set. + break; + } // end if ( ) + } + } // endfor l_SubStep + + if ( l_errl ) + { + // something left an error log in the inner loop, breakout + break; } + } // endfor l_IStep - // report an error from the child, if it exists. - reportIStepErrorLog( pistep, args.getErrorLog() ); - } // endfor + /** + * @todo detect Can-Continue condition here and reset/rerun ISteps. + * For now this is pushed to a later sprint. + */ - TRACFCOMP( g_trac_initsvc, - EXIT_MRK "IStepDispatcher finished."); + // Post any errorlogs. If one exists, stop here. Otherwise, return + // to caller. + if ( l_errl ) + { + TRACFCOMP( g_trac_initsvc, + "ERROR: istep=0x%x, substep=0x%x, committing errorlog %p", + l_IStep, + l_SubStep, + l_errl ); + errlCommit( l_errl ); + assert( 0 ); + } } -/** - * @note IStep Mode is hardwired to false for now - * - * @todo revisit this when PNOR Driver is implemented - */ -bool IStepDispatcher::getIStepMode( ) const -{ - - return false; -} - - bool IStepDispatcher::getCanContinueProcedure( const TaskInfo &i_failingIStep, errlHndl_t &i_failingError, @@ -159,11 +567,21 @@ bool IStepDispatcher::getCanContinueProcedure( const TaskInfo &i_failingIStep, return false; } -void IStepDispatcher::reportIStepErrorLog( const TaskInfo *i_failingIStep, - errlHndl_t io_errl ) + +IStepDispatcher& IStepDispatcher::getTheInstance() +{ + return Singleton<IStepDispatcher>::instance(); +} + + +IStepDispatcher::IStepDispatcher() { + initIStepMode(); // set up internal flag - InitService::getTheInstance().reportError( io_errl ); } + +IStepDispatcher::~IStepDispatcher() +{ } + } // namespace diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H index 46f4f87e3..352b0f450 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.H +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H @@ -21,8 +21,8 @@ // // IBM_PROLOG_END -#ifndef __ISTEP_DISPATCHER_H -#define __ISTEP_DISPATCHER_H +#ifndef __ISTEPDISPATCHER_ISTEPDISPATCHER_H +#define __ISTEPDISPATCHER_ISTEPDISPATCHER_H /** * @file istepdispatcher.H * @@ -34,21 +34,22 @@ /******************************************************************************/ // Includes /******************************************************************************/ -#include <stdint.h> -#include <sys/vfs.h> // VFS_MODULE_NAME_MAX +#include <stdint.h> +#include <util/singleton.H> -#include <errl/errlentry.H> -#include <initservice/taskargs.H> -#include <initservice/initsvcreasoncodes.H> +#include <errl/errlentry.H> +#include <initservice/taskargs.H> +#include <initservice/initsvcreasoncodes.H> +#include <initservice/initsvcstructs.H> -#include "../baseinitsvc/initservice.H" -#include "../common/initsvcstructs.H" +#include "../baseinitsvc/initservice.H" + +#include "splesscommon.H" namespace INITSERVICE { - /******************************************************************************/ // Globals/Constants /******************************************************************************/ @@ -58,7 +59,7 @@ namespace INITSERVICE /******************************************************************************/ /******************************************************************************/ -// Class +// Class IStepDispatcher /******************************************************************************/ /** @@ -85,6 +86,8 @@ public: * * @param[in] i_pargs pointer to any arguments passed in from * _start(). + * + * @return nothing */ void init( void *i_pargs); @@ -109,51 +112,115 @@ private: IStepDispatcher(const IStepDispatcher& i_right); IStepDispatcher& operator=(const IStepDispatcher& i_right); + /** - * @brief getIStepMode - * call into PNOR and fetch the "IStepMode flag" . - * This will tell us if we are locked to the SP (IStepMode=ON) or - * can run all the ISteps available (IStepMode=OFF). + * @brief init iv_istepmode flag, called in constructor + * + * Call into PNOR and fetch the "IStepMode flag" . + * + * @todo currently this calls into the kernel to get the value of + * an SCOM Scratch Reg - this will change when PNOR is finished + * + * @return nothing * - * @return false if IStep Mode is "OFF" + */ + void initIStepMode( ); + + + /** + * @brief getIStepMode - return value of IStep Mode + * + * @return bool - value of iv_istepmodeflag + * @retval false if IStep Mode is "OFF" * true if IStep Mode is "ON" */ - bool getIStepMode( ) const; + bool getIStepMode( ) const; + + + /** + * @brief Find a TaskInfo struct in the global istep list(s), + * addressed by { IStep, SubStep } + * + * + * @param[in] i_IStep - IStepNumber + * @param[in] i_SubStep - SubStepNumber + * + * @return pointer to a TaskInfo struct + * @retval pointer to a TaskInfo struct, or NULL + * + */ + const TaskInfo *findTaskInfo( uint16_t i_IStep, + uint16_t i_SubStep ) const; + + + /** + * @brief singleStepISteps + * + * Stop and wait for SP to send the next IStep to run. Run that, then + * wait for the next one. + * This is not expected to return - errors etc are sent to the user to + * handle. + * + * @param[in,out] io_ptr - pointer to any args passed in from + * ExtInitSvc. This may be a pointer to an + * TaskArgs struct (or something else) which + * can be filled out on return + * + * @return none + */ + void singleStepISteps( void * io_ptr ) const; + + + /** + * @brief runAllISteps + * + * Run all available ISteps sequentially. + * If an IStep gets an error, report it and stop. + * Otherwise, return. + * + * @param[in,out] io_ptr - pointer to a TaskArgs struct on input + * command, returncode and errorlog will be + * clear on input + * one or more may be filled in on return + * + * @return none + */ + void runAllISteps( void * io_ptr ) const; /** * @brief getCanContinueProcedure * If an IStep fails, this routine will fetch the recovery procedure + * This is only used in "normal" mode, it will not be used when IStep Mode + * is ON (i.e. it will not be used when single-stepping). * - * @param[in] reference to IStepInfo struct for failing Istep - * @param[in] reference to errorlog for the failure - * @param[in,out] reference to IStepInfo struct for next IStep to run + * @param[in] i_failingIStep - ref to IStepInfo struct for failing + * Istep + * @param[in] i_failingError - ref to errorlog for the failure + * @param[in,out] io_nextIStep - ref to TaskInfo struct for next + * IStep to run. struct will be filled + * out with info on the next IStep to + * run. * - * @return false if there is no Can-Continue procedure + * @return bool + * @retval false if there is no Can-Continue procedure, * true otherwise * + * @todo 2011-08-22 currently the defs for this procedure are pretty + * vague - requirements for Can-Continue behaviour have not been + * defined yet. */ bool getCanContinueProcedure( const TaskInfo &i_failingIStep, errlHndl_t &i_failingError, - TaskInfo &io_nextIstep ) const; - - /** - * @brief reportIStepErrorLog - * If an IStep returns an error log, commit it. - * - * @todo Later there may be some decision about whether to report it - * based on the IStep. - */ - void reportIStepErrorLog( const TaskInfo *i_failingIStep, - errlHndl_t io_errl ); + TaskInfo &io_nextIStep ) const; + // ----- internal vars ----------------------------- bool iv_istepmodeflag; - uint64_t iv_nextistep; - bool iv_cancontinueflag; }; // class IStepDispatcher + } // namespace #endif diff --git a/src/usr/initservice/istepdispatcher/isteplist.H b/src/usr/initservice/istepdispatcher/isteplist.H deleted file mode 100644 index 612fde725..000000000 --- a/src/usr/initservice/istepdispatcher/isteplist.H +++ /dev/null @@ -1,81 +0,0 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/usr/initservice/istepdispatcher/isteplist.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END - -#ifndef __ISTEPS_H -#define __ISTEPS_H - -/** - * @file isteplist.H - * - * TaskInfo structs for each task that will run in the extended image. - */ - -#include <initservice/initsvcreasoncodes.H> -#include "istepdispatcher.H" -#include "../../isteps/isteps.H" - -namespace INITSERVICE -{ - -const uint64_t MAX_ISTEPS = 25; - -const TaskInfo g_isteps[] = { - - // ----- ISteps Image ------------------------------------------ - - /** - * @brief targeting task, initializes extended module area - */ - { - "istep1" , // istep name - ISTEPS::IStep1, // pointer to fn - { - NONE, // task type - EXT_IMAGE, // Extended Module - ISTEP_1_ERRL_ID, // module id - } - }, - - // --------------------------------------------------------------- - // ----- END OF LIST!!! --------------------------------------- - // --------------------------------------------------------------- - - /** - * @brief last task in the list - */ - { - "end" , // dummy string - NULL, // pointer to fn - { - END_TASK_LIST, // end of list - UNDEFINED_MT, // dummy module type - UNDEFINED_MODULE_ERRL_ID, // dummy errorlog - } - }, - -}; - - -}; // namespace - -#endif diff --git a/src/usr/initservice/istepdispatcher/makefile b/src/usr/initservice/istepdispatcher/makefile index 013c6a8f9..d18adfc4f 100644 --- a/src/usr/initservice/istepdispatcher/makefile +++ b/src/usr/initservice/istepdispatcher/makefile @@ -20,10 +20,11 @@ # Origin: 30 # # IBM_PROLOG_END + ROOTPATH = ../../../.. MODULE = istepdisp -OBJS = istepdispatcher.o +OBJS = istepdispatcher.o splesscommand.o splessstatus.o ## SUBDIRS = test.d diff --git a/src/usr/initservice/istepdispatcher/splesscommand.C b/src/usr/initservice/istepdispatcher/splesscommand.C new file mode 100644 index 000000000..563a4be3a --- /dev/null +++ b/src/usr/initservice/istepdispatcher/splesscommand.C @@ -0,0 +1,113 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/initservice/istepdispatcher/splesscommand.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END + +/** + * @file splesscommand.C + * + * Collection of routines to read/write the spless command reg + * + */ + + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include <errl/errlentry.H> // errlHndl_t +#include <sys/mmio.h> // mmio_scratch_read/write + +#include "splesscommon.H" + + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ + +/******************************************************************************/ +// Typedef/Enumerations +/******************************************************************************/ + +namespace SPLESSCMD +{ + + +void read( bool &io_rgobit, + uint16_t &io_ristep, + uint16_t &io_rsubstep ) +{ + InternalCommand l_cmd; + + l_cmd.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_COMMAND); + + io_rgobit = l_cmd.f.gobit; + io_ristep = l_cmd.f.istep; + io_rsubstep = l_cmd.f.substep; + +} + + +void write( const bool i_gobit, + const uint16_t i_istep, + const uint16_t i_substep ) +{ + InternalCommand l_cmd; + + // copy into union + l_cmd.f.gobit = i_gobit; + l_cmd.f.istep = i_istep; + l_cmd.f.substep = i_substep; + + mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_COMMAND, l_cmd.val64 ); + +} + + +void getgobit( bool &o_rgobit ) +{ + uint16_t l_istep = 0; + uint16_t l_substep = 0; + + // re-use above call... + read( o_rgobit, + l_istep, + l_substep ); + +} + + +void setgobit( const bool i_gobit ) +{ + InternalCommand l_cmd; + + l_cmd.val64 = mmio_scratch_read( MMIO_SCRATCH_IPLSTEP_COMMAND); + + l_cmd.f.gobit = i_gobit; + + mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_COMMAND, l_cmd.val64 ); + +} + +} // namespace diff --git a/src/usr/initservice/istepdispatcher/splesscommon.H b/src/usr/initservice/istepdispatcher/splesscommon.H new file mode 100644 index 000000000..113d712fd --- /dev/null +++ b/src/usr/initservice/istepdispatcher/splesscommon.H @@ -0,0 +1,269 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/initservice/istepdispatcher/splesscommon.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END + +#ifndef __ISTEPDISP_SPLESS_COMMON_H +#define __ISTEPDISP_SPLESS_COMMON_H +/** + * @file splesscommon.H + * + * Prototypes for routines to access SPLESS Command and + * and SPLESS Status interfaces + * + */ + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ +const uint64_t ISTEP_MODE_SIGNATURE = 0x4057b0074057b007; + +/******************************************************************************/ +// SPLESS Command Prototypes +/******************************************************************************/ + +/** + * @namespace SPLESSCMD + * + * Contains functions to manipulate the SPLESS Command Register + * @todo overload these later to get command and seq fields + * + */ +namespace SPLESSCMD +{ + +/** + * @union InternalCommand + * + * define the fields within the 64-bit Command Register + * + + * Bit numbers are in ppc notation, where bit 0 is the most significant bit. + * Go Bit : bit 0 (ppc notation, msbit) + * - set to 1 by the user to start the IStep + * - cleared to 0 by HostBoot + * Reserved: bit 1: always 0 + * Sequence #: bits 2-7 + * Command Number: bits 8:15 - always 0 (for now) + * Reserved: bits 16:31 + * Reserved: bits 32:39 - always 0 + * IStep Number: bits 40:47 + * Substep Number: bits 48:63gobit: + * + */ +union InternalCommand +{ + uint64_t val64; + struct + { + bool gobit:1; + uint8_t reserved0:1; + uint8_t seqnum:6; + uint8_t cmdnum; + + uint16_t reserved2; + + uint16_t reserved3:2; + uint16_t istep:14; + + uint16_t substep; + } f PACKED; + + // init struct to 0 + InternalCommand() : val64(0) {}; +} ; + + +/** + * @brief Read the command register and return the necessary fields. + * + * @param[in,out] io_rgobit - ref to a gobit var that will be filled in + * on return + * @param[in,out] io_ristep - ref to a istep var that will be filled in + * on return + * @param[in,out] io_rsubstep - ref to a substep var that will be filled + * in on return + * + * @return pointer to errorlog + * @retval NULL if success, filled-in errorlog if failure + * + */ +void read( bool &io_rgobit, + uint16_t &io_ristep, + uint16_t &io_rsubstep ); + + +/** + * @brief Write all the necessary fields to the command reg. + * + * Normally the user writes the command reg; this is only used to + * init the command reg at the beginning + * + * @param[in] i_gobit - gobit value to write + * @param[in] i_istep - istep value to write + * @param[in] i_substep - substep value to write + * + * @return errorlog pointer + * @retval NULL if success, filled-in errorlog if failure + * + */ +void write( const bool i_gobit, + const uint16_t i_istep, + const uint16_t i_substep ); + + +/** + * @brief Read the gobit from the command register + * + * @param o_rgobit - ref to a gobit var that will be filled in + * on return. + * + * @return errorlog pointer + * @retval NULL if success, filled-in errorlog on failure + */ +void getgobit( bool &o_rgobit ); + + +/** + * @brief Write the gobit to the command register + * + * @param i_gobit - gobit value to be written + * + * @return pointer to errlog + * @retval NULL if success, filled-in errorlog on failure + */ +void setgobit( const bool i_gobit ) ; + +} // namespace + + +/******************************************************************************/ +// SPLESS Status Prototypes +/******************************************************************************/ + +/** + * @namespace SPLESSSTS + * + * Contains functions to manipulate the SPLESS Status Register + * @todo overload these to get seq # later + * + */ +namespace SPLESSSTS +{ + +/** + * @union InternalStatus + * + * define the fields within the 64-bit status register + * Running bit, bit 0 (ppc notation, msbit): + * = 1 when IStep is running + * = 0 when IStep is finished + * Ready bit, bit 1: + * = 1 when IStep Dispatcher is ready to run individual ISteps + * = 0 if IStep Dispatcher is not ready: + * - System has not loaded the IStep Dispatcher yet + * - IStep Mode Flag = 0 + * Sequence # : bits 2-7 - echoes the sequence number in the associated + * command frame. + * IStep Running, bits 8:15 - the IStep number that is currently running. + * Sub-step Running, bits 16:31 - the substep that is currently running. + * Task Status, bits 32:47 - the status that IStep Dispatcher returns when + * trying to run the task. For example: + * -3 IStep number is invalid + * -1, -2 (return code from kernel) IStep could not be launched as a + * task or as a function within a task + * IStep Status, bits 48:63 - status returned from the IStep. + * + */ +union InternalStatus { + uint64_t val64; + struct { + bool runningbit:1; // | + bool readybit:1; // | + uint8_t seqnum:6; // | + uint8_t istep; // | 16 bits + uint16_t substep; // 16 bits + uint16_t taskStatus; // 16 bits + uint16_t istepStatus; // 16 bits + } f PACKED; + + // init struct to 0 + InternalStatus() : val64(0) {}; +} ; + + + +/** + * @brief Read the SPLess Status SCOM Reg and return all its fields + * + * @param[in,out] io_rrunningbit - ref to runningbit var, to be + * filled in on return + * @param[in,out] io_rreadybit - ref to readybit var, to be filled in + * on return + * @param[in,out] io_ristep - ref to istep var, to be filled in on + * return + * @param[in,out] io_rsubstep - ref to substep var, to be filled in + * on return + * @param[in,out] io_rtaskStatus - ref to taskStatus var, to be filled + * in on return + * @param[in,out] io_ristepStatus - ref to istepStatus var, to be filled + * in on return + * + * @return none. + */ +void read( bool &io_rrunningbit, + bool &io_rreadybit, + uint16_t &io_ristep, + uint16_t &io_rsubstep, + uint16_t &io_rtaskStatus, + uint16_t &io_ristepStatus ); + +/** + * @brief write + * + * Read the SPLess Status SCOM Reg and return all its fields + * + * @param[in] i_runningbit - runningbit val to write + * @param[in] i_readybit - readybit val to write + * @param[in] i_istep - istep val to write + * @param[in] i_substep - substep val to write + * @param[in] i_taskStatus - taskStatus val to write + * @param[in] i_istepStatus - istepStatus val to write + * + * @return none + */ +void write( const bool i_runningbit, + const bool i_readybit, + const uint16_t i_istep, + const uint16_t i_substep, + const uint16_t i_taskStatus, + const uint16_t i_istepStatus ); + +} // namespace + +#endif diff --git a/src/usr/initservice/istepdispatcher/splessstatus.C b/src/usr/initservice/istepdispatcher/splessstatus.C new file mode 100644 index 000000000..30818778c --- /dev/null +++ b/src/usr/initservice/istepdispatcher/splessstatus.C @@ -0,0 +1,93 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/initservice/istepdispatcher/splessstatus.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file splessstatus.C + * + * Routines to read and write spless status reg + * + */ + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include <errl/errlentry.H> // errlHndl_t +#include <sys/mmio.h> // mmio_scratch_read/write + +#include "splesscommon.H" + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ + +/******************************************************************************/ +// Typedef/Enumerations +/******************************************************************************/ + + +void SPLESSSTS::read( bool &io_rrunningbit, + bool &io_rreadybit, + uint16_t &io_ristep, + uint16_t &io_rsubstep, + uint16_t &io_rtaskStatus, + uint16_t &io_ristepStatus ) +{ + InternalStatus l_sts; + + l_sts.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_STATUS); + + // read was good + io_rrunningbit = l_sts.f.runningbit; + io_rreadybit = l_sts.f.readybit; + io_ristep = l_sts.f.istep; + io_rsubstep = l_sts.f.substep; + io_rtaskStatus = l_sts.f.taskStatus; + io_ristepStatus = l_sts.f.istepStatus; + +} + + +void SPLESSSTS::write( const bool i_runningbit, + const bool i_readybit, + const uint16_t i_istep, + const uint16_t i_substep, + const uint16_t i_taskStatus, + const uint16_t i_istepStatus ) +{ + InternalStatus l_sts; + + // copy in all the values + l_sts.f.runningbit = i_runningbit; + l_sts.f.readybit = i_readybit; + l_sts.f.istep = i_istep; + l_sts.f.substep = i_substep; + l_sts.f.taskStatus = i_taskStatus; + l_sts.f.istepStatus = i_istepStatus; + + mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_STATUS, l_sts.val64 ); + +} + |