summaryrefslogtreecommitdiffstats
path: root/ucs2-lib/src/ucs_sys_diag.c
diff options
context:
space:
mode:
Diffstat (limited to 'ucs2-lib/src/ucs_sys_diag.c')
-rw-r--r--ucs2-lib/src/ucs_sys_diag.c1343
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 */
+/*------------------------------------------------------------------------------------------------*/
+