diff options
Diffstat (limited to 'ucs2-lib/src/ucs_sys_diag.c')
-rw-r--r-- | ucs2-lib/src/ucs_sys_diag.c | 1343 |
1 files changed, 1343 insertions, 0 deletions
diff --git a/ucs2-lib/src/ucs_sys_diag.c b/ucs2-lib/src/ucs_sys_diag.c new file mode 100644 index 0000000..0c80eb6 --- /dev/null +++ b/ucs2-lib/src/ucs_sys_diag.c @@ -0,0 +1,1343 @@ +/*------------------------------------------------------------------------------------------------*/ +/* UNICENS V2.1.0-3491 */ +/* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */ +/* */ +/* This program is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* */ +/* You may also obtain this software under a propriety license from Microchip. */ +/* Please contact Microchip for further information. */ +/*------------------------------------------------------------------------------------------------*/ + +/*! + * \file + * \brief Implementation of the System Diagnosis class + * \details Performs the System Diagnosis + * + * \cond UCS_INTERNAL_DOC + * \addtogroup G_SYS_DIAG + * @{ + */ + +/*------------------------------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------------------------------*/ +#include "ucs_misc.h" +#include "ucs_ret_pb.h" +#include "ucs_sys_diag.h" +/*#include "ucs_mnsa.h"*/ + + + +/*------------------------------------------------------------------------------------------------*/ +/* Internal constants */ +/*------------------------------------------------------------------------------------------------*/ +#define SYS_DIAG_NUM_STATES 10U /*!< \brief Number of state machine states */ +#define SYS_DIAG_NUM_EVENTS 17U /*!< \brief Number of state machine events */ + +#define SD_NUM_HELLO 10U /*!< \brief Number of Hello.Get Retries */ +#define SD_TIMEOUT_HELLO 150U /*!< \brief timeout used for repeating Hello.Get messages */ +#define SD_TIMEOUT_COMMAND 100U /*!< \brief timeout used for supervising INIC commands */ +#define SD_TIMEOUT_CABLE_DIAGNOSIS 3000U /*!< \brief timeout used for supervising cable link diagnosis */ +#define SD_DIAG_ADDR_BASE 0x0500U /*!< \brief Diagnosis Node Address of own node */ + +#define SD_WELCOME_SUCCESS 0U /*!< \brief Welcome.Result reports success */ + +#define SD_SIGNATURE_VERSION 1U /*!< \brief signature version used for System Diagnosis */ + + +/*------------------------------------------------------------------------------------------------*/ +/* Service parameters */ +/*------------------------------------------------------------------------------------------------*/ +/*! Priority of the System Diagnosis service used by scheduler */ +static const uint8_t SD_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ +/*! Main event for the System Diagnosis service */ +static const Srv_Event_t SD_EVENT_SERVICE = 1U; + + +/*------------------------------------------------------------------------------------------------*/ +/* Internal enumerators */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief Possible events of the system diagnosis state machine */ +typedef enum SysDiag_Events_ +{ + SD_E_NIL = 0U, /*!< \brief NIL Event */ + SD_E_STARTDIAG = 1U, /*!< \brief StartDiag API function was called */ + SD_E_SD_RES_OK = 2U, /*!< \brief MOSTNetworkSystemDiagnosis.Result received */ + SD_E_ABORT = 3U, /*!< \brief Application requires stop of System Diagnosis */ + SD_E_HELLO_OK = 4U, /*!< \brief Hello.Status received */ + SD_E_HELLO_RETRY = 5U, /*!< \brief Retry the Hello.Get command */ + SD_E_HELLO_ALL_DONE = 6U, /*!< \brief All retries of the Hello.Get command are done */ + SD_E_WELCOME = 7U, /*!< \brief Welcome.Result, may be Ok or NotOk*/ + SD_E_ALL_DONE = 8U, /*!< \brief All branches and segments of the network were explored*/ + SD_E_PORT_FOUND = 9U, /*!< \brief An unexplored port was found */ + SD_E_PORT_ENABLED = 10U, /*!< \brief A port was succesful enabled */ + SD_E_PORT_DISABLED = 11U, /*!< \brief A port was succesful disabled */ + SD_E_BRANCH_FOUND = 12U, /*!< \brief Another branch was found */ + SD_E_CABLE_LINK_RES = 13U, /*!< \brief The CableLinkDiagnosis reported a result */ + SD_E_ERROR = 14U, /*!< \brief An error was detected */ + SD_E_TIMEOUT = 15U, /*!< \brief An timeout has been occurred */ + SD_E_NO_SUCCESS = 16U /*!< \brief Welcome result was NoSuccess */ +} SysDiag_Events_t; + +/*! \brief States of the system diagnosis state machine */ +typedef enum SysDiag_State_ +{ + SD_S_IDLE = 0U, /*!< \brief Idle state */ + SD_S_WAIT_DIAG = 1U, /*!< \brief System Diagnosis started */ + SD_S_WAIT_HELLO = 2U, /*!< \brief Hello command sent */ + SD_S_HELLO_TIMEOUT = 3U, /*!< \brief Hello command timed out */ + SD_S_WAIT_WELCOME = 4U, /*!< \brief Welcome sent */ + SD_S_NEXT_PORT = 5U, /*!< \brief Next port found to be tested */ + SD_S_WAIT_ENABLE = 6U, /*!< \brief Port Enable sent */ + SD_S_WAIT_DISABLE = 7U, /*!< \brief Port Disable sent */ + SD_S_CABLE_LINK_DIAG = 8U, /*!< \brief Wait for CableL Link Diagnosis Result */ + SD_S_END = 9U /*!< \brief Wait for System Diagnosis stop */ +} SysDiag_State_t; + + + +/*------------------------------------------------------------------------------------------------*/ +/* Internal prototypes */ +/*------------------------------------------------------------------------------------------------*/ +static void Sd_Service(void *self); + +static void Sd_SysDiagInit(void* self); +static void Sd_SysDiagStart(void *self); +static void Sd_SysDiagStop(void *self); +static void Sd_SendHello(void *self); +static void Sd_Error(void *self); +static void Sd_ErrorWelcome(void *self); +static void Sd_SendWelcome(void *self); +static void Sd_CableLinkDiagnosis(void *self); +static void Sd_CalcPort(void *self); +static void Sd_AllDone(void *self); +static void Sd_EnablePort(void *self); +static void Sd_DisablePort(void *self); +static void Sd_Finish(void *self); +static void Sd_Abort(void *self); +static void Sd_StopDiagFailed(void *self); + +static void Sd_HelloTimeout(void *self); +static void Sd_SysDiagTimeout(void *self); +static void Sd_WelcomeTimeout(void *self); +static void Sd_EnablePortTimeout(void *self); +static void Sd_DisablePortTimeout(void *self); +static void Sd_CableLinkDiagnosisTimeout(void *self); + +static void Sd_SysDiagStartResultCb(void *self, void *result_ptr); +static void Sd_SysDiagStopResultCb(void *self, void *result_ptr); +static void Sd_HelloStatusCb(void *self, void *result_ptr); +static void Sd_WelcomeResultCb(void *self, void *result_ptr); +static void Sd_EnablePortResultCb(void *self, void *result_ptr); +static void Sd_DisablePortResultCb(void *self, void *result_ptr); +static void Sd_CableLinkDiagnosisResultCb(void *self, void *result_ptr); +static void Sd_OnTerminateEventCb(void *self, void *result_ptr); +static void Sd_TimerCb(void *self); + + + + +/*------------------------------------------------------------------------------------------------*/ +/* State transition table (used by finite state machine) */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief State transition table */ +static const Fsm_StateElem_t sys_diag_trans_tab[SYS_DIAG_NUM_STATES][SYS_DIAG_NUM_EVENTS] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ +{ + + { /* State SD_S_IDLE */ + /* SD_E_NIL */ {NULL, SD_S_IDLE }, + /* SD_E_STARTDIAG */ {&Sd_SysDiagStart, SD_S_WAIT_DIAG }, + /* SD_E_SD_RES_OK */ {NULL, SD_S_IDLE }, + /* SD_E_ABORT */ {NULL, SD_S_IDLE }, + /* SD_E_HELLO_OK */ {NULL, SD_S_IDLE }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_IDLE }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_IDLE }, + /* SD_E_WELCOME */ {NULL, SD_S_IDLE }, + /* SD_E_ALL_DONE */ {NULL, SD_S_IDLE }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_IDLE }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_IDLE }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_IDLE }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_IDLE }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_IDLE }, + /* SD_E_ERROR */ {NULL, SD_S_IDLE }, + /* SD_E_TIMEOUT */ {NULL, SD_S_IDLE }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_IDLE } + }, + + { /* State SD_S_WAIT_DIAG */ + /* SD_E_NIL */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_SD_RES_OK */ {&Sd_SendHello, SD_S_WAIT_HELLO }, + /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, + /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_WELCOME */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_DIAG }, + /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, + /* SD_E_TIMEOUT */ {&Sd_SysDiagTimeout, SD_S_END }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_DIAG } + }, + + { /* State SD_S_WAIT_HELLO*/ + /* SD_E_NIL */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, + /* SD_E_HELLO_OK */ {&Sd_SendWelcome, SD_S_WAIT_WELCOME }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_WELCOME */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_HELLO }, + /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, + /* SD_E_TIMEOUT */ {&Sd_HelloTimeout, SD_S_HELLO_TIMEOUT }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_HELLO } + }, + + { /* State SD_S_HELLO_TIMEOUT */ + /* SD_E_NIL */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_STARTDIAG */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_SD_RES_OK */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, + /* SD_E_HELLO_OK */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_HELLO_RETRY */ {&Sd_SendHello, SD_S_WAIT_HELLO }, + /* SD_E_HELLO_ALL_DONE */ {&Sd_CableLinkDiagnosis, SD_S_CABLE_LINK_DIAG }, + /* SD_E_WELCOME */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_ALL_DONE */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, + /* SD_E_TIMEOUT */ {NULL, SD_S_HELLO_TIMEOUT }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_HELLO_TIMEOUT } + }, + + { /* State SD_S_WAIT_WELCOME */ + /* SD_E_NIL */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, + /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_WELCOME */ {&Sd_CalcPort, SD_S_NEXT_PORT }, + /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_WELCOME }, + /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, + /* SD_E_TIMEOUT */ {&Sd_WelcomeTimeout, SD_S_END }, + /* SD_E_NO_SUCCESS */ {&Sd_ErrorWelcome, SD_S_END } + }, + + { /* State SD_S_NEXT_PORT */ + /* SD_E_NIL */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_STARTDIAG */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_SD_RES_OK */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, + /* SD_E_HELLO_OK */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_WELCOME */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_ALL_DONE */ {&Sd_AllDone, SD_S_END }, + /* SD_E_PORT_FOUND */ {&Sd_EnablePort, SD_S_WAIT_ENABLE }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_BRANCH_FOUND */ {&Sd_DisablePort, SD_S_WAIT_DISABLE }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, + /* SD_E_TIMEOUT */ {NULL, SD_S_NEXT_PORT }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_NEXT_PORT } + }, + + { /* State SD_S_WAIT_ENABLE */ + /* SD_E_NIL */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, + /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_WELCOME */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_PORT_ENABLED */ {&Sd_SendHello, SD_S_WAIT_HELLO }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_ENABLE }, + /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, + /* SD_E_TIMEOUT */ {&Sd_EnablePortTimeout, SD_S_END }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_ENABLE } + }, + + { /* State SD_S_WAIT_DISABLE */ + /* SD_E_NIL */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, + /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_WELCOME */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_PORT_DISABLED */ {&Sd_EnablePort, SD_S_WAIT_ENABLE }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_DISABLE }, + /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, + /* SD_E_TIMEOUT */ {&Sd_DisablePortTimeout, SD_S_END }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_DISABLE } + }, + + { /* State SD_S_CABLE_LINK_DIAG */ + /* SD_E_NIL */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_STARTDIAG */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_SD_RES_OK */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, + /* SD_E_HELLO_OK */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_WELCOME */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_ALL_DONE */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_CABLE_LINK_DIAG }, + /* SD_E_CABLE_LINK_RES */ {&Sd_CalcPort, SD_S_NEXT_PORT }, + /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, + /* SD_E_TIMEOUT */ {&Sd_CableLinkDiagnosisTimeout, SD_S_END }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_CABLE_LINK_DIAG } + }, + + { /* State SD_S_END */ + /* SD_E_NIL */ {NULL, SD_S_END }, + /* SD_E_STARTDIAG */ {NULL, SD_S_END }, + /* SD_E_SD_RES_OK */ {Sd_Finish, SD_S_IDLE }, + /* SD_E_ABORT */ {NULL, SD_S_END }, + /* SD_E_HELLO_OK */ {NULL, SD_S_END }, + /* SD_E_HELLO_RETRY */ {NULL, SD_S_END }, + /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_END }, + /* SD_E_WELCOME */ {NULL, SD_S_END }, + /* SD_E_ALL_DONE */ {NULL, SD_S_END }, + /* SD_E_PORT_FOUND */ {NULL, SD_S_END }, + /* SD_E_PORT_ENABLED */ {NULL, SD_S_END }, + /* SD_E_PORT_DISABLED */ {NULL, SD_S_END }, + /* SD_E_BRANCH_FOUND */ {NULL, SD_S_END }, + /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_END }, + /* SD_E_ERROR */ {Sd_StopDiagFailed, SD_S_IDLE }, + /* SD_E_TIMEOUT */ {Sd_StopDiagFailed, SD_S_IDLE }, + /* SD_E_NO_SUCCESS */ {NULL, SD_S_END } + } + +}; + + + +/*------------------------------------------------------------------------------------------------*/ +/* Implementation */ +/*------------------------------------------------------------------------------------------------*/ + +/*! \brief Constructor of class CSysDiag. + * \param self Reference to CSysDiag instance + * \param inic Reference to CInic instance + * \param base Reference to CBase instance + * \param exc Reference to CExc instance + */ + void SysDiag_Ctor(CSysDiag *self, CInic *inic, CBase *base, CExc *exc) +{ + MISC_MEM_SET((void *)self, 0, sizeof(*self)); + + self->inic = inic; + self->exc = exc; + self->base = base; + + Fsm_Ctor(&self->fsm, self, &(sys_diag_trans_tab[0][0]), SYS_DIAG_NUM_EVENTS, SD_E_NIL); + + Sobs_Ctor(&self->sys_diag_start, self, &Sd_SysDiagStartResultCb); + Sobs_Ctor(&self->sys_diag_stop, self, &Sd_SysDiagStopResultCb); + Sobs_Ctor(&self->sys_hello, self, &Sd_HelloStatusCb); + Sobs_Ctor(&self->sys_welcome, self, &Sd_WelcomeResultCb); + Sobs_Ctor(&self->sys_enable_port, self, &Sd_EnablePortResultCb); + Sobs_Ctor(&self->sys_disable_port, self, &Sd_DisablePortResultCb); + Sobs_Ctor(&self->sys_cable_link_diagnosis, self, &Sd_CableLinkDiagnosisResultCb); + + /* register termination events */ + Mobs_Ctor(&self->sys_terminate, self, EH_M_TERMINATION_EVENTS, &Sd_OnTerminateEventCb); + Eh_AddObsrvInternalEvent(&self->base->eh, &self->sys_terminate); + + /* Initialize System Diagnosis service */ + Srv_Ctor(&self->sd_srv, SD_SRV_PRIO, self, &Sd_Service); + /* Add System Diagnosis service to scheduler */ + (void)Scd_AddService(&self->base->scd, &self->sd_srv); + +} + +/*! \brief Service function of the System Diagnosis service. + * \param self Reference to System Diagnosis object + */ +static void Sd_Service(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + Srv_Event_t event_mask; + Srv_GetEvent(&self_->sd_srv, &event_mask); + if(SD_EVENT_SERVICE == (event_mask & SD_EVENT_SERVICE)) /* Is event pending? */ + { + Fsm_State_t result; + Srv_ClearEvent(&self_->sd_srv, SD_EVENT_SERVICE); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured)); + result = Fsm_Service(&self_->fsm); + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", (result != FSM_STATE_ERROR)); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "FSM -> %d", 1U, self_->fsm.current_state)); + MISC_UNUSED(result); + } +} + + +/*! \brief Starts the System Diagnosis State machine + * + * \param *self Reference to System Diagnosis object + * \param *obs_ptr Observer pointer + * \return UCS_RET_SUCCESS Operation successful + * \return UCS_RET_ERR_API_LOCKED System Diagnosis was already started + * \return UCS_RET_ERR_BUFFER_OVERFLOW Invalid observer + */ +Ucs_Return_t SysDiag_Run(CSysDiag *self, CSingleObserver *obs_ptr) +{ + Ucs_Return_t ret_val = UCS_RET_SUCCESS; + + if (self->startup_locked == false) + { + Ssub_Ret_t ret_ssub; + + ret_ssub = Ssub_AddObserver(&self->sysdiag, obs_ptr); + if (ret_ssub != SSUB_UNKNOWN_OBSERVER) /* obs_ptr == NULL ? */ + { + self->startup_locked = true; + + Sd_SysDiagInit(self); + + Fsm_SetEvent(&self->fsm, SD_E_STARTDIAG); + Srv_SetEvent(&self->sd_srv, SD_EVENT_SERVICE); + + TR_INFO((self->base->ucs_user_ptr, "[SD]", "SysDiag_Run", 0U)); + } + else + { + ret_val = UCS_RET_ERR_BUFFER_OVERFLOW; /* obs_ptr was invalid */ + } + } + else + { + ret_val = UCS_RET_ERR_API_LOCKED; + } + + return ret_val; +} + + +/*! \brief Aborts the System Diagnosis State machine + * + * \param *self Reference to System Diagnosis object + * \return UCS_RET_SUCCESS Operation successful + * \return UCS_RET_ERR_NOT_AVAILABLE System Diagnosis not running + */ +Ucs_Return_t SysDiag_Abort(CSysDiag *self) +{ + Ucs_Return_t ret_val = UCS_RET_SUCCESS; + + if (self->startup_locked == true) /* check if System Diagnosis was started */ + { + Tm_ClearTimer(&self->base->tm, &self->timer); + + Fsm_SetEvent(&self->fsm, SD_E_ABORT); + Srv_SetEvent(&self->sd_srv, SD_EVENT_SERVICE); + TR_INFO((self->base->ucs_user_ptr, "[SD]", "SysDiag_Abort", 0U)); + } + else + { + ret_val = UCS_RET_ERR_NOT_AVAILABLE; + } + + return ret_val; +} + +/*! Initialize the System Diagnosis + * + * \param self Reference to System Diagnosis object + */ +static void Sd_SysDiagInit(void* self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + self_->hello_retry = SD_NUM_HELLO; + self_->segment_nr = 0U; + self_->num_ports = 0U; + self_->curr_branch = 0U; + self_->source.node_address = 0xFFFFU; + self_->source.available = false; + self_->last_result = SD_INIT; + + self_->target.node_address = 0x0001U; /* address of own INIC */ + self_->target.available = false; + + self_->admin_node_address = SD_DIAG_ADDR_BASE; +} + + +/*! FSM action function: sets the INIC into System Diagnosis Mode + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_SysDiagStart(void *self) +{ + Ucs_Return_t ret_val; + + CSysDiag *self_ = (CSysDiag *)self; + + ret_val = Inic_NwSysDiagnosis(self_->inic, &self_->sys_diag_start); + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStart", 0U)); + + Tm_SetTimer(&self_->base->tm, + &self_->timer, + &Sd_TimerCb, + self_, + SD_TIMEOUT_COMMAND, + 0U); + + MISC_UNUSED(ret_val); +} + + +/*! Callback function for the Inic_NwSysDiagnosis() command + * + * \param *self Reference to System Diagnosis object + * \param *result_ptr Result of the Inic_NwSysDiagnosis() command + */ +static void Sd_SysDiagStartResultCb(void *self, void *result_ptr) +{ + CSysDiag *self_ = (CSysDiag *)self; + Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; + + Tm_ClearTimer(&self_->base->tm, &self_->timer); + + if (result_ptr_->result.code == UCS_RES_SUCCESS) + { + Fsm_SetEvent(&self_->fsm, SD_E_SD_RES_OK); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStartResultCb SD_E_SD_RES_OK", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStartResultCb SD_E_ERROR", 0U)); + } + + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); +} + + +/*! FSM action function: Timeout occured + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_SysDiagTimeout(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + Sd_SysDiagStop(self_); +} + +/*! FSM action function: Timeout occured + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_EnablePortTimeout(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + Sd_SysDiagStop(self_); +} + +/*! FSM action function: Timeout occured + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_DisablePortTimeout(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + Sd_SysDiagStop(self_); +} + +/*! Helper function. Stops the System Diagnosis + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_SysDiagStop(void *self) +{ + Ucs_Return_t ret_val; + + CSysDiag *self_ = (CSysDiag *)self; + + ret_val = Inic_NwSysDiagEnd(self_->inic, &self_->sys_diag_stop); + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStop", 0U)); + if (ret_val == UCS_RET_SUCCESS) + { + Tm_SetTimer(&self_->base->tm, + &self_->timer, + &Sd_TimerCb, + self_, + SD_TIMEOUT_COMMAND, + 0U); + } + else + { + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_STOP_SYSDIAG_FAILED; + + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); + } +} + + +/*! \brief Callback function for the Inic_NwSysDiagEnd() command + * + * \param *self Reference to System Diagnosis object + * \param *result_ptr Result of the Inic_NwSysDiagEnd() command + */ +static void Sd_SysDiagStopResultCb(void *self, void *result_ptr) +{ + CSysDiag *self_ = (CSysDiag *)self; + Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; + + Tm_ClearTimer(&self_->base->tm, &self_->timer); + + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", UCS_RES_SUCCESS == result_ptr_->result.code); + + if (result_ptr_->result.code == UCS_RES_SUCCESS) + { + Fsm_SetEvent(&self_->fsm, SD_E_SD_RES_OK); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStopResultCb SD_E_SD_RES_OK", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStopResultCb SD_E_ERROR", 0U)); + } + + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); +} + + + +/*! FSM action function: Send Hello.Get command + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_SendHello(void *self) +{ + Ucs_Return_t ret_val; + + CSysDiag *self_ = (CSysDiag *)self; + + ret_val = Exc_Hello_Get(self_->exc, + UCS_ADDR_BROADCAST_BLOCKING, + SD_SIGNATURE_VERSION, + &self_->sys_hello); + Tm_SetTimer(&self_->base->tm, + &self_->timer, + &Sd_TimerCb, + self_, + SD_TIMEOUT_HELLO, + 0U); + + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); + MISC_UNUSED(ret_val); +} + +/*! Callback function for the Enc.Hello.Status message + * + * \param *self Reference to System Diagnosis object + * \param *result_ptr Result of the Exc_Hello_Get() command + */ +static void Sd_HelloStatusCb(void *self, void *result_ptr) +{ + CSysDiag *self_ = (CSysDiag *)self; + Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; + + Tm_ClearTimer(&self_->base->tm, &self_->timer); + + if (result_ptr_->result.code == UCS_RES_SUCCESS) + { + /* read signature and store it for the Welcome command */ + self_->target.signature = (*(Exc_HelloStatus_t *)(result_ptr_->data_info)).signature; + self_->target.version = (*(Exc_HelloStatus_t *)(result_ptr_->data_info)).version; + + if (self_->segment_nr != 0U) + { + self_->target.node_address = self_->segment_nr + 0x0400U; + + } + + Fsm_SetEvent(&self_->fsm, SD_E_HELLO_OK); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloStatusCb SD_E_SD_RES_OK", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloStatusCb SD_E_ERROR", 0U)); + } + + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); +} + +/*! \brief Timer callback used for supervising INIC command timeouts. + * \param self Reference to System Diagnosis object + */ +static void Sd_TimerCb(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + Fsm_SetEvent(&self_->fsm, SD_E_TIMEOUT); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_TimerCb SD_E_TIMEOUT", 0U)); + + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); +} + + +/*! FSM action function: retry hello command or start CableLinkDiagnosis + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_HelloTimeout(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + if (self_->hello_retry > 0U) + { + --self_->hello_retry; + Fsm_SetEvent(&self_->fsm, SD_E_HELLO_RETRY); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloTimeout SD_E_HELLO_RETRY", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, SD_E_HELLO_ALL_DONE); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloTimeout SD_E_HELLO_ALL_DONE", 0U)); + } + + /*Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE);*/ +} + + +/*! FSM action function: Send Welcome message + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_SendWelcome(void *self) +{ + Ucs_Return_t ret_val; + CSysDiag *self_ = (CSysDiag *)self; + + self_->admin_node_address = SD_DIAG_ADDR_BASE + self_->segment_nr; + + ret_val = Exc_Welcome_Sr(self_->exc, + self_->target.node_address, + self_->admin_node_address, + SD_SIGNATURE_VERSION, + self_->target.signature, + &self_->sys_welcome); + Tm_SetTimer(&self_->base->tm, + &self_->timer, + &Sd_TimerCb, + self_, + SD_TIMEOUT_COMMAND, + 0U); + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); + MISC_UNUSED(ret_val); +} + + +/*! \brief Function is called on reception of the Welcome.Result messsage + * \param self Reference to System Diagnosis object + * \param result_ptr Pointer to the result of the Welcome message + */ +static void Sd_WelcomeResultCb(void *self, void *result_ptr) +{ + CSysDiag *self_ = (CSysDiag *)self; + Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; + + Tm_ClearTimer(&self_->base->tm, &self_->timer); + + if (result_ptr_->result.code == UCS_RES_SUCCESS) + { + /* read signature and store it for the Welcome command */ + self_->target.result = (*(Exc_WelcomeResult_t *)(result_ptr_->data_info)).res; + + if (self_->target.result == SD_WELCOME_SUCCESS) + { + self_->target.available = true; + + if (self_->segment_nr == 0U) + { + self_->num_ports = self_->target.signature.num_ports; + } + else + { + self_->last_result = SD_SEGMENT; + } + /* do not report result for own node */ + if (self_->segment_nr != 0U) + { + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + + self_->report.code = UCS_SD_TARGET_FOUND; + self_->report.segment.branch = self_->curr_branch; + self_->report.segment.num = self_->segment_nr; + self_->report.segment.source = self_->source.signature; + self_->report.segment.target = self_->target.signature; + /*self_->report.cable_link_info = 0U;*/ /* element is not written deliberately */ + /*self_->report.err_info = 0U;*/ /* element is not written deliberately */ + + Ssub_Notify(&self_->sysdiag, &self_->report, false); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb ReportSegment", 0U)); + } + + Fsm_SetEvent(&self_->fsm, SD_E_WELCOME); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb SD_E_WELCOME", 0U)); + } + else + { + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + + self_->report.code = UCS_SD_ERROR; + self_->report.segment.branch = self_->curr_branch; + self_->report.segment.num = self_->segment_nr; + self_->report.segment.source = self_->source.signature; + self_->report.segment.target = self_->target.signature; + /*self_->report.cable_link_info = 0U;*/ /* element is not written deliberately */ + self_->report.err_info = UCS_SD_ERR_WELCOME_NO_SUCCESS; + + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + Fsm_SetEvent(&self_->fsm, SD_E_NO_SUCCESS); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb reported NoSuccess", 0U)); + } + + } + else + { + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb Error SD_E_ERROR 0x%x", 1U, result_ptr_->result.code)); + + } + + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); +} + + +/*! \brief FSM action function: Calculate the next port tobe examined + * \param self Reference to System Diagnosis object + */ +static void Sd_CalcPort(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + switch (self_->last_result) + { + case SD_INIT: + self_->curr_branch = 0U; /* Master device has at least one port */ + self_->source = self_->target; + self_->master = self_->target; + + MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); + self_->last_result = SD_SEGMENT; + Fsm_SetEvent(&self_->fsm, SD_E_PORT_FOUND); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_PORT_FOUND", 0U)); + break; + + case SD_SEGMENT: + if (self_->target.signature.num_ports > 1U) + { + self_->source = self_->target; + MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); + Fsm_SetEvent(&self_->fsm, SD_E_PORT_FOUND); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_PORT_FOUND", 0U)); + } + else /* switch to next branch if possible*/ + { + if (self_->num_ports == (self_->curr_branch + 1U)) /* last branch */ + { + Fsm_SetEvent(&self_->fsm, SD_E_ALL_DONE); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_ALL_DONE", 0U)); + } + else + { + self_->segment_nr = 1U; /* reset segment number */ + self_->curr_branch++; /* switch to next port */ + self_->source = self_->master; + MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); + Fsm_SetEvent(&self_->fsm, SD_E_BRANCH_FOUND); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_BRANCH_FOUND", 0U)); + } + } + break; + + case SD_CABLE_LINK: + if (self_->num_ports == (self_->curr_branch + 1U)) /* last branch */ + { + Fsm_SetEvent(&self_->fsm, SD_E_ALL_DONE); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_ALL_DONE", 0U)); + } + else + { + self_->segment_nr = 1U; /* reset segment number */ + self_->curr_branch++; /* switch to next port */ + self_->source = self_->master; + MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); + Fsm_SetEvent(&self_->fsm, SD_E_BRANCH_FOUND); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_BRANCH_FOUND", 0U)); + } + break; + + default: + break; + } + + /*Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE);*/ +} + + +/*! \brief FSM action function: Enable port + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_EnablePort(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + uint16_t target_address; + uint8_t port_number; + Ucs_Return_t ret_val; + + if (self_->segment_nr == 0U) + { + port_number = self_->curr_branch; + target_address = 0x0001U; + } + else + { + port_number = 1U; + target_address = self_->source.node_address; + } + + ret_val = Exc_EnablePort_Sr(self_->exc, target_address, port_number, true, &self_->sys_enable_port); + Tm_SetTimer(&self_->base->tm, + &self_->timer, + &Sd_TimerCb, + self_, + SD_TIMEOUT_COMMAND, + 0U); + + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); + MISC_UNUSED(ret_val); +} + + +/*! Function is called on reception of the EnablePort.Result messsage + * + * \param *self Reference to System Diagnosis object + * \param *result_ptr + */ +static void Sd_EnablePortResultCb(void *self, void *result_ptr) +{ + CSysDiag *self_ = (CSysDiag *)self; + Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; + + Tm_ClearTimer(&self_->base->tm, &self_->timer); + + if (result_ptr_->result.code == UCS_RES_SUCCESS) + { + self_->segment_nr++; + Fsm_SetEvent(&self_->fsm, SD_E_PORT_ENABLED); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_EnablePortResultCb SD_E_PORT_ENABLED", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_EnablePortResultCb SD_E_ERROR", 0U)); + } + + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); +} + + +/*! \brief FSM action function: + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_DisablePort(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + uint16_t target_address; + uint8_t port_number; + Ucs_Return_t ret_val; + + target_address = self_->admin_node_address; + port_number = self_->curr_branch; + + ret_val = Exc_EnablePort_Sr(self_->exc, target_address, port_number, false, &self_->sys_disable_port); + Tm_SetTimer(&self_->base->tm, + &self_->timer, + &Sd_TimerCb, + self_, + SD_TIMEOUT_COMMAND, + 0U); + + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); + MISC_UNUSED(ret_val); +} + + +static void Sd_DisablePortResultCb(void *self, void *result_ptr) +{ + CSysDiag *self_ = (CSysDiag *)self; + Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; + + Tm_ClearTimer(&self_->base->tm, &self_->timer); + + if (result_ptr_->result.code == UCS_RES_SUCCESS) + { + Fsm_SetEvent(&self_->fsm, SD_E_PORT_DISABLED); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_DisablePortResultCb SD_E_PORT_DISABLED", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_DisablePortResultCb SD_E_ERROR", 0U)); + } + + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); +} + + +/*! \brief FSM action function: Start CableLinkDiagnosis + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_CableLinkDiagnosis(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + uint16_t target_address; + uint8_t port_number; + Ucs_Return_t ret_val; + + + if (self_->segment_nr != 0U) /* do not start CableLinkDiagnosis when connecting to local INIC */ + { + target_address = self_->source.node_address; + + if (self_->segment_nr == 1U) + { + port_number = self_->curr_branch; + } + else + { + port_number = 1U; /* OS81119: always port 1 */ + } + + self_->last_result = SD_CABLE_LINK; + + ret_val = Exc_CableLinkDiagnosis_Start(self_->exc, target_address, port_number, &self_->sys_cable_link_diagnosis); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosis", 0U)); + + Tm_SetTimer(&self_->base->tm, + &self_->timer, + &Sd_TimerCb, + self_, + SD_TIMEOUT_CABLE_DIAGNOSIS, + 0U); + + TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); + MISC_UNUSED(ret_val); +} + else /* stop SystemDiagnosis when connecting to local INIC failed */ + { + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); + } +} + + +static void Sd_CableLinkDiagnosisResultCb(void *self, void *result_ptr) +{ + CSysDiag *self_ = (CSysDiag *)self; + + Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; + + Tm_ClearTimer(&self_->base->tm, &self_->timer); + + if (result_ptr_->result.code == UCS_RES_SUCCESS) + { + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + + self_->report.code = UCS_SD_CABLE_LINK_RES; + self_->report.segment.branch = self_->curr_branch; + self_->report.segment.num = self_->segment_nr; + self_->report.segment.source = self_->source.signature; + /*self_->report.segment.target = self_->target.signature;*/ /* structure is not written deliberately */ + self_->report.cable_link_info = (*(Exc_CableLinkDiagResult_t *)(result_ptr_->data_info)).result; + /*self_->report.err_info = 0U;*/ /* element is not written deliberately */ + + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + + Fsm_SetEvent(&self_->fsm, SD_E_CABLE_LINK_RES); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosisResultCb SD_E_CABLE_LINK_RES", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, SD_E_ERROR); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosisResultCb SD_E_ERROR %02X %02X %02X", 3U, result_ptr_->result.info_ptr[0], result_ptr_->result.info_ptr[1], result_ptr_->result.info_ptr[2])); + } + + Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); + +} + + +/*! \brief FSM action function: React on Timeout of CableLinkDiagnosis + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_CableLinkDiagnosisTimeout(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); + Sd_SysDiagStop(self_); +} + +/*! \brief FSM action function: React on Timeout of Welcome + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_WelcomeTimeout(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); + Sd_SysDiagStop(self_); +} + + + + +/*! \brief FSM action function: All branches and segments explored, finish System Diagnosis + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_AllDone(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_AllDone", 0U)); + + Sd_SysDiagStop(self_); +} + + +/*! \brief FSM action function: INIC system Diagnosis mode ended + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_Finish(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + + self_->report.code = UCS_SD_FINISHED; + Ssub_Notify(&self_->sysdiag, &self_->report, true); + + self_->startup_locked = false; + + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Finish", 0U)); +} + +/*! \brief FSM action function: An unexpected error occurred. + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_Error(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + Sd_SysDiagStop(self_); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Error", 0U)); +} + +/*! \brief FSM action function: Welcome reports NoSuccess. + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_ErrorWelcome(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + Sd_SysDiagStop(self_); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_ErrorWelcome", 0U)); +} + +/*! \brief FSM action function: stopping system diagnosis mode failed + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_StopDiagFailed(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_STOP_SYSDIAG_FAILED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + /* always finish the System Diagnosis with event UCS_SD_FINISHED */ + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_FINISHED; + Ssub_Notify(&self_->sysdiag, &self_->report, true); /* remove the observer function */ + + self_->startup_locked = false; + + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_StopDiagFailed", 0U)); +} + +/*! \brief FSM action function: Application requested to abort the System Diagnosis. + * + * \param *self Reference to System Diagnosis object + */ +static void Sd_Abort(void *self) +{ + CSysDiag *self_ = (CSysDiag *)self; + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ABORTED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + Sd_SysDiagStop(self_); + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Abort", 0U)); +} + + + +/*! Function is called on severe internal errors + * + * \param *self Reference to System Diagnosis object + * \param *result_ptr Reference to data + */ +static void Sd_OnTerminateEventCb(void *self, void *result_ptr) +{ + CSysDiag *self_ = (CSysDiag *)self; + + MISC_UNUSED(result_ptr); + + if (self_->fsm.current_state != SD_S_IDLE) + { + Tm_ClearTimer(&self_->base->tm, &self_->timer); + + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_ERROR; + self_->report.err_info = UCS_SD_ERR_TERMINATED; + Ssub_Notify(&self_->sysdiag, &self_->report, false); + + /* always finish the System Diagnosis with event UCS_SD_FINISHED */ + MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); + self_->report.code = UCS_SD_FINISHED; + Ssub_Notify(&self_->sysdiag, &self_->report, true); /* remove the observer function */ + + TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_OnTerminateEventCb", 0U)); + + /* reset FSM */ + self_->startup_locked = false; + Sd_SysDiagInit(self_); + self_->fsm.current_state = SD_S_IDLE; + } +} + + + + +/*! + * @} + * \endcond + */ + +/*------------------------------------------------------------------------------------------------*/ +/* End of file */ +/*------------------------------------------------------------------------------------------------*/ + |