From 076c4e7c5d7f837409032e13763a11ff05f55a14 Mon Sep 17 00:00:00 2001
From: Lucas Russo <lerwys@gmail.com>
Date: Tue, 17 May 2016 09:18:08 -0300
Subject: [PATCH] sm_io/*/trigger_mux/*: add trigger mux module

---
 .../trigger_mux/sm_io_trigger_mux_codes.h     |  34 +++
 .../trigger_mux/sm_io_trigger_mux_core.c      |  64 +++++
 .../trigger_mux/sm_io_trigger_mux_core.h      |  22 ++
 .../trigger_mux/sm_io_trigger_mux_defaults.c  |  76 ++++++
 .../trigger_mux/sm_io_trigger_mux_defaults.h  |  23 ++
 .../trigger_mux/sm_io_trigger_mux_exp.c       | 242 ++++++++++++++++++
 .../trigger_mux/sm_io_trigger_mux_exp.h       |  18 ++
 .../trigger_mux/sm_io_trigger_mux_exports.c   |  73 ++++++
 .../trigger_mux/sm_io_trigger_mux_exports.h   |  21 ++
 src/sm_io/modules/trigger_mux/trigger_mux.mk  |   6 +
 10 files changed, 579 insertions(+)
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_codes.h
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_core.c
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_core.h
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_defaults.c
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_defaults.h
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exp.c
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exp.h
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exports.c
 create mode 100644 src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exports.h
 create mode 100644 src/sm_io/modules/trigger_mux/trigger_mux.mk

diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_codes.h b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_codes.h
new file mode 100644
index 00000000..8dc3576c
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_codes.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+ */
+
+#ifndef _SM_IO_TRIGGER_MUX_CODES_H_
+#define _SM_IO_TRIGGER_MUX_CODES_H_
+
+/* Messaging OPCODES */
+#define TRIGGER_MUX_OPCODE_TYPE                           uint32_t
+#define TRIGGER_MUX_OPCODE_SIZE                           (sizeof (TRIGGER_MUX_OPCODE_TYPE))
+
+#define TRIGGER_MUX_OPCODE_RCV_SRC                        0
+#define TRIGGER_MUX_NAME_RCV_SRC                          "trigger_mux_rcv_src"
+#define TRIGGER_MUX_OPCODE_RCV_IN_SEL                     1
+#define TRIGGER_MUX_NAME_RCV_IN_SEL                       "trigger_mux_rcv_in_sel"
+#define TRIGGER_MUX_OPCODE_TRANSM_SRC                     2
+#define TRIGGER_MUX_NAME_TRANSM_SRC                       "trigger_mux_transm_src"
+#define TRIGGER_MUX_OPCODE_TRANSM_OUT_SEL                 3
+#define TRIGGER_MUX_NAME_TRANSM_OUT_SEL                   "trigger_mux_transm_out_sel"
+#define TRIGGER_MUX_OPCODE_END                            4
+
+/* Messaging Reply OPCODES */
+#define TRIGGER_MUX_REPLY_TYPE                            uint32_t
+#define TRIGGER_MUX_REPLY_SIZE                            (sizeof (TRIGGER_MUX_REPLY_TYPE))
+
+#define TRIGGER_MUX_OK                                    0   /* Operation was successful */
+#define TRIGGER_MUX_ERR                                   1   /* Could not set/get value */
+#define TRIGGER_MUX_UNINPL                                2   /* Unimplemented function or operation */
+#define TRIGGER_MUX_REPLY_END                             3   /* End marker */
+
+#endif
diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_core.c b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_core.c
new file mode 100644
index 00000000..c45c64d8
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_core.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+ */
+
+#include "bpm_server.h"
+/* Private headers */
+#include "sm_io_trigger_mux_defaults.h"
+#include "sm_io_trigger_mux_core.h"
+
+/* Undef ASSERT_ALLOC to avoid conflicting with other ASSERT_ALLOC */
+#ifdef ASSERT_TEST
+#undef ASSERT_TEST
+#endif
+#define ASSERT_TEST(test_boolean, err_str, err_goto_label, /* err_core */ ...)  \
+    ASSERT_HAL_TEST(test_boolean, SM_IO, "[sm_io_trigger_mux_core]",          \
+            err_str, err_goto_label, /* err_core */ __VA_ARGS__)
+
+#ifdef ASSERT_ALLOC
+#undef ASSERT_ALLOC
+#endif
+#define ASSERT_ALLOC(ptr, err_goto_label, /* err_core */ ...)                   \
+    ASSERT_HAL_ALLOC(ptr, SM_IO, "[sm_io_trigger_mux_core]",                  \
+            smio_err_str(SMIO_ERR_ALLOC),                                       \
+            err_goto_label, /* err_core */ __VA_ARGS__)
+
+#ifdef CHECK_ERR
+#undef CHECK_ERR
+#endif
+#define CHECK_ERR(err, err_type)                                                \
+    CHECK_HAL_ERR(err, SM_IO, "[sm_io_trigger_mux_core]",                     \
+            smio_err_str (err_type))
+
+/* Creates a new instance of Device Information */
+smio_trigger_mux_t * smio_trigger_mux_new (smio_t *parent)
+{
+    (void) parent;
+
+    smio_trigger_mux_t *self = (smio_trigger_mux_t *) zmalloc (sizeof *self);
+    ASSERT_ALLOC(self, err_self_alloc);
+
+    return self;
+
+err_self_alloc:
+    return NULL;
+}
+
+/* Destroy an instance of the Device Information */
+smio_err_e smio_trigger_mux_destroy (smio_trigger_mux_t **self_p)
+{
+    assert (self_p);
+
+    if (*self_p) {
+        smio_trigger_mux_t *self = *self_p;
+
+        free (self);
+        *self_p = NULL;
+    }
+
+    return SMIO_SUCCESS;
+}
+
diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_core.h b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_core.h
new file mode 100644
index 00000000..a243b9d2
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_core.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+*/
+
+#ifndef _SM_IO_TRIGGER_MUX_CORE_H_
+#define _SM_IO_TRIGGER_MUX_CORE_H_
+
+typedef struct {
+    const uint32_t example;
+} smio_trigger_mux_t;
+
+/***************** Our methods *****************/
+
+/* Creates a new instance of the smio realization */
+smio_trigger_mux_t * smio_trigger_mux_new (smio_t *parent);
+/* Destroys the smio realizationn */
+smio_err_e smio_trigger_mux_destroy (smio_trigger_mux_t **self_p);
+
+#endif
diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_defaults.c b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_defaults.c
new file mode 100644
index 00000000..40bd5828
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_defaults.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+ */
+
+#include "bpm_server.h"
+/* Private headers */
+#include "sm_io_trigger_mux_defaults.h"
+
+/* Undef ASSERT_ALLOC to avoid conflicting with other ASSERT_ALLOC */
+#ifdef ASSERT_TEST
+#undef ASSERT_TEST
+#endif
+#define ASSERT_TEST(test_boolean, err_str, err_goto_label, /* err_core */ ...) \
+    ASSERT_HAL_TEST(test_boolean, SM_IO, "[sm_io:trigger_mux_defaults]",    \
+            err_str, err_goto_label, /* err_core */ __VA_ARGS__)
+
+#ifdef ASSERT_ALLOC
+#undef ASSERT_ALLOC
+#endif
+#define ASSERT_ALLOC(ptr, err_goto_label, /* err_core */ ...)               \
+    ASSERT_HAL_ALLOC(ptr, SM_IO, "[sm_io:trigger_mux_defaults]",            \
+            smio_err_str(SMIO_ERR_ALLOC),                                   \
+            err_goto_label, /* err_core */ __VA_ARGS__)
+
+#ifdef CHECK_ERR
+#undef CHECK_ERR
+#endif
+#define CHECK_ERR(err, err_type)                                            \
+    CHECK_HAL_ERR(err, SM_IO, "[sm_io:trigger_mux_defaults]",               \
+            smio_err_str (err_type))
+
+#define SMIO_TRIGGER_MUX_LIBBPMCLIENT_LOG_MODE                "a"
+#define SMIO_TRIGGER_MUX_MAX_CHAN                             24
+
+/* We use the actual libclient to send and configure our default values,
+ * maintaining internal consistency. So, in fact, we are sending ourselves
+ * a message containing the default values. Because of this approach, we
+ * only get to default our values when the functions are already exported
+ * to the broker, which happens on a late stage. This could cause a fast
+ * client to get an inconsistent state from our server */
+/* TODO: Avoid exporting the functions before we have initialized
+ * our server with the default values */
+smio_err_e trigger_mux_config_defaults (char *broker_endp, char *service,
+       const char *log_file_name)
+{
+    (void) log_file_name;
+    DBE_DEBUG (DBG_SM_IO | DBG_LVL_INFO, "[sm_io:trigger_mux_defaults] Configuring SMIO "
+            "TRIGGER_MUX with default values ...\n");
+    bpm_client_err_e client_err = BPM_CLIENT_SUCCESS;
+    smio_err_e err = SMIO_SUCCESS;
+
+    bpm_client_t *config_client = bpm_client_new_log_mode (broker_endp, 0,
+            log_file_name, SMIO_TRIGGER_MUX_LIBBPMCLIENT_LOG_MODE);
+    ASSERT_ALLOC(config_client, err_alloc_client);
+
+    uint32_t chan;
+    for (chan = 0; chan < SMIO_TRIGGER_MUX_MAX_CHAN; ++chan) {
+        client_err = bpm_set_trigger_dir (config_client, service, chan, TRIGGER_MUX_DFLT_DIR);
+        client_err |= bpm_set_trigger_rcv_count_rst (config_client, service, chan, TRIGGER_MUX_DFLT_RCV_RST);
+        client_err |= bpm_set_trigger_transm_count_rst (config_client, service, chan, TRIGGER_MUX_DFLT_TRANSM_RST);
+        client_err |= bpm_set_trigger_rcv_len (config_client, service, chan, TRIGGER_MUX_DFLT_RCV_LEN);
+    }
+
+    ASSERT_TEST(client_err == BPM_CLIENT_SUCCESS, "Could set trigger mux defaults",
+            err_param_set, SMIO_ERR_CONFIG_DFLT);
+
+err_param_set:
+    bpm_client_destroy (&config_client);
+err_alloc_client:
+    DBE_DEBUG (DBG_SM_IO | DBG_LVL_INFO, "[sm_io:trigger_mux_defaults] Exiting Config thread %s\n",
+        service);
+    return err;
+}
diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_defaults.h b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_defaults.h
new file mode 100644
index 00000000..e991633d
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_defaults.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+ */
+
+#ifndef _TRIGGER_MUX_DEFAULTS_H_
+#define _TRIGGER_MUX_DEFAULTS_H_
+
+#include "sm_io_err.h"
+
+#define TRIGGER_MUX_DFLT_DIR                      1      /* Input */
+#define TRIGGER_MUX_DFLT_RCV_RST                  1      /* Pulse Reset */
+#define TRIGGER_MUX_DFLT_TRANSM_RST               1      /* Pulse Reset */
+#define TRIGGER_MUX_DFLT_RCV_LEN                  1      /* Debounce Length */
+#define TRIGGER_MUX_DFLT_TRANSM_LEN               1      /* Pulse Extension Length */
+
+smio_err_e trigger_mux_config_defaults (char *broker_endp, char *service,
+        const char *log_file_name);
+
+#endif
+
diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exp.c b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exp.c
new file mode 100644
index 00000000..a57ecb9b
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exp.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+ */
+
+#include "bpm_server.h"
+/* Private headers */
+#include "sm_io_trigger_mux_codes.h"
+#include "sm_io_trigger_mux_defaults.h"
+#include "sm_io_trigger_mux_exports.h"
+#include "sm_io_trigger_mux_core.h"
+#include "sm_io_trigger_mux_exp.h"
+#include "hw/wb_trigger_mux_regs.h"
+
+/* Undef ASSERT_ALLOC to avoid conflicting with other ASSERT_ALLOC */
+#ifdef ASSERT_TEST
+#undef ASSERT_TEST
+#endif
+#define ASSERT_TEST(test_boolean, err_str, err_goto_label, /* err_core */ ...)  \
+    ASSERT_HAL_TEST(test_boolean, SM_IO, "[sm_io:trigger_mux_exp]",             \
+            err_str, err_goto_label, /* err_core */ __VA_ARGS__)
+
+#ifdef ASSERT_ALLOC
+#undef ASSERT_ALLOC
+#endif
+#define ASSERT_ALLOC(ptr, err_goto_label, /* err_core */ ...)                   \
+    ASSERT_HAL_ALLOC(ptr, SM_IO, "[sm_io:trigger_mux_exp]",                     \
+            smio_err_str(SMIO_ERR_ALLOC),                                       \
+            err_goto_label, /* err_core */ __VA_ARGS__)
+
+#ifdef CHECK_ERR
+#undef CHECK_ERR
+#endif
+#define CHECK_ERR(err, err_type)                                                \
+    CHECK_HAL_ERR(err, SM_IO, "[sm_io:trigger_mux_exp]",                        \
+            smio_err_str (err_type))
+
+/* This must match the FPGA maximum number of channels */
+#define TRIGGER_MUX_NUM_CHAN                          24
+#define TRIGGER_MUX_CHAN_OFFSET                       0x008 /* 2 32-bit registers */
+
+/*****************************************************************/
+/************ Specific TRIGGER MUX Operations **************/
+/*****************************************************************/
+
+#define BPM_TRIGGER_MUX_RCV_SRC_MIN                         0 /* Trigger Source Selection (= Trigger Backplane) */
+#define BPM_TRIGGER_MUX_RCV_SRC_MAX                         1 /* Trigger Source Selection (= FPGA internal) */
+RW_PARAM_FUNC(trigger_mux, rcv_src) {
+    SET_GET_PARAM_CHANNEL(trigger_mux, WB_TRIGGER_MUX_RAW_REG_OFFS, WB_TRIG_MUX,
+            CH0_CTL, RCV_SRC, TRIGGER_MUX_CHAN_OFFSET, TRIGGER_MUX_NUM_CHAN, SINGLE_BIT_PARAM,
+            BPM_TRIGGER_MUX_RCV_SRC_MIN, BPM_TRIGGER_MUX_RCV_SRC_MAX, NO_CHK_FUNC,
+            NO_FMT_FUNC, SET_FIELD);
+}
+
+#define BPM_TRIGGER_MUX_RCV_IN_SEL_MIN                       0              /* Minimum selection */
+#define BPM_TRIGGER_MUX_RCV_IN_SEL_MAX                       ((1 << 8) -1)  /* Maximum selection */
+RW_PARAM_FUNC(trigger_mux, rcv_in_sel) {
+    SET_GET_PARAM_CHANNEL(trigger_mux, WB_TRIGGER_MUX_RAW_REG_OFFS, WB_TRIG_MUX,
+            CH0_CTL, RCV_IN_SEL, TRIGGER_MUX_CHAN_OFFSET, TRIGGER_MUX_NUM_CHAN, MULT_BIT_PARAM,
+            BPM_TRIGGER_MUX_RCV_IN_SEL_MIN, BPM_TRIGGER_MUX_RCV_IN_SEL_MAX, NO_CHK_FUNC,
+            NO_FMT_FUNC, SET_FIELD);
+}
+
+#define BPM_TRIGGER_MUX_TRANSM_SRC_MIN                       0 /* Trigger Source Selection (= Trigger Backplane) */
+#define BPM_TRIGGER_MUX_TRANSM_SRC_MAX                       1 /* Trigger Source Selection (= FPGA internal) */
+RW_PARAM_FUNC(trigger_mux, transm_src) {
+    SET_GET_PARAM_CHANNEL(trigger_mux, WB_TRIGGER_MUX_RAW_REG_OFFS, WB_TRIG_MUX,
+            CH0_CTL, TRANSM_SRC, TRIGGER_MUX_CHAN_OFFSET, TRIGGER_MUX_NUM_CHAN, SINGLE_BIT_PARAM,
+            BPM_TRIGGER_MUX_TRANSM_SRC_MIN, BPM_TRIGGER_MUX_TRANSM_SRC_MAX, NO_CHK_FUNC,
+            NO_FMT_FUNC, SET_FIELD);
+}
+
+#define BPM_TRIGGER_MUX_TRANSM_OUT_SEL_MIN                   0              /* Minimum selection */
+#define BPM_TRIGGER_MUX_TRANSM_OUT_SEL_MAX                   ((1 << 8) -1)  /* Maximum selection */
+RW_PARAM_FUNC(trigger_mux, transm_out_sel) {
+    SET_GET_PARAM_CHANNEL(trigger_mux, WB_TRIGGER_MUX_RAW_REG_OFFS, WB_TRIG_MUX,
+            CH0_CTL, TRANSM_OUT_SEL, TRIGGER_MUX_CHAN_OFFSET, TRIGGER_MUX_NUM_CHAN, MULT_BIT_PARAM,
+            BPM_TRIGGER_MUX_TRANSM_OUT_SEL_MIN, BPM_TRIGGER_MUX_TRANSM_OUT_SEL_MAX, NO_CHK_FUNC,
+            NO_FMT_FUNC, SET_FIELD);
+}
+
+/* Exported function pointers */
+const disp_table_func_fp trigger_mux_exp_fp [] = {
+    RW_PARAM_FUNC_NAME(trigger_mux, rcv_src),
+    RW_PARAM_FUNC_NAME(trigger_mux, rcv_in_sel),
+    RW_PARAM_FUNC_NAME(trigger_mux, transm_src),
+    RW_PARAM_FUNC_NAME(trigger_mux, transm_out_sel),
+    NULL
+};
+
+/************************************************************/
+/***************** Export methods functions *****************/
+/************************************************************/
+
+static smio_err_e _trigger_mux_do_op (void *owner, void *msg);
+
+/* Attach an instance of sm_io to dev_io function pointer */
+smio_err_e trigger_mux_attach (smio_t *self, devio_t *parent)
+{
+    (void) self;
+    (void) parent;
+    return SMIO_ERR_FUNC_NOT_IMPL;
+}
+
+/* Deattach an instance of sm_io to dev_io function pointer */
+smio_err_e trigger_mux_deattach (smio_t *self)
+{
+    (void) self;
+    return SMIO_ERR_FUNC_NOT_IMPL;
+}
+
+/* Export (register) sm_io to handle operations function pointer */
+smio_err_e trigger_mux_export_ops (smio_t *self,
+        const disp_op_t** smio_exp_ops)
+{
+    (void) self;
+    (void) smio_exp_ops;
+    return SMIO_ERR_FUNC_NOT_IMPL;
+}
+
+/* Unexport (unregister) sm_io to handle operations function pointer */
+smio_err_e trigger_mux_unexport_ops (smio_t *self)
+{
+    (void) self;
+    return SMIO_ERR_FUNC_NOT_IMPL;
+}
+
+
+/* Generic wrapper for receiving opcodes and arguments to specific funtions function pointer */
+/* FIXME: Code repetition! _devio_do_smio_op () function does almost the same!!! */
+smio_err_e _trigger_mux_do_op (void *owner, void *msg)
+{
+    (void) owner;
+    (void) msg;
+    return SMIO_ERR_FUNC_NOT_IMPL;
+}
+
+smio_err_e trigger_mux_do_op (void *self, void *msg)
+{
+    return _trigger_mux_do_op (self, msg);
+}
+
+const smio_ops_t trigger_mux_ops = {
+    .attach             = trigger_mux_attach,          /* Attach sm_io instance to dev_io */
+    .deattach           = trigger_mux_deattach,        /* Deattach sm_io instance to dev_io */
+    .export_ops         = trigger_mux_export_ops,      /* Export sm_io operations to dev_io */
+    .unexport_ops       = trigger_mux_unexport_ops,    /* Unexport sm_io operations to dev_io */
+    .do_op              = trigger_mux_do_op            /* Generic wrapper for handling specific operations */
+};
+
+/************************************************************/
+/****************** Bootstrap Operations ********************/
+/************************************************************/
+
+smio_err_e trigger_mux_init (smio_t * self)
+{
+    DBE_DEBUG (DBG_SM_IO | DBG_LVL_TRACE, "[sm_io:trigger_mux_exp] Initializing trigger_mux\n");
+
+    smio_err_e err = SMIO_SUCCESS;
+
+    err = smio_set_id (self, TRIGGER_MUX_SDB_DEVID);
+    ASSERT_TEST(err == SMIO_SUCCESS, "Could not set SMIO id", err_set_id);
+    err = smio_set_name (self, TRIGGER_MUX_SDB_NAME);
+    ASSERT_TEST(err == SMIO_SUCCESS, "Could not set SMIO name", err_set_name);
+
+    /* Set SMIO ops pointers */
+    err = smio_set_ops (self, &trigger_mux_ops);
+    ASSERT_TEST(err == SMIO_SUCCESS, "Could not set SMIO operations",
+            err_smio_set_ops);
+    err = smio_set_thsafe_client_ops (self, &smio_thsafe_client_zmq_ops);
+    ASSERT_TEST(err == SMIO_SUCCESS, "Could not set SMIO thsafe operations",
+            err_smio_set_thsafe_ops);
+
+    /* Fill the disp_op_t description structure with the callbacks. */
+
+    /* disp_op_t structure is const and all of the functions performing on it
+     * obviously receives a const argument, but here (and only on the SMIO
+     * initialization) we need to make an exception if we want to keep the
+     * functions' description and the function pointers separate */
+    err = smio_init_exp_ops (self, (disp_op_t **) trigger_mux_exp_ops,
+            trigger_mux_exp_fp);
+    ASSERT_TEST(err == SMIO_SUCCESS, "Could not fill SMIO "
+            "function descriptors with the callbacks", err_fill_desc);
+
+    err = smio_set_exp_ops (self, trigger_mux_exp_ops);
+    ASSERT_TEST(err == SMIO_SUCCESS, "Could not set SMIO exported operations",
+            err_smio_set_exp_ops);
+
+    /* Initialize specific structure */
+    smio_trigger_mux_t *smio_handler = smio_trigger_mux_new (self);
+    ASSERT_ALLOC(smio_handler, err_smio_handler_alloc, SMIO_ERR_ALLOC);
+    err = smio_set_handler (self, smio_handler);
+    ASSERT_TEST(err == SMIO_SUCCESS, "Could not set SMIO handler",
+            err_smio_set_handler);
+
+    return err;
+
+err_smio_set_handler:
+    smio_trigger_mux_destroy (&smio_handler);
+err_smio_handler_alloc:
+    smio_set_exp_ops (self, NULL);
+err_smio_set_exp_ops:
+err_fill_desc:
+    smio_set_thsafe_client_ops (self, NULL);
+err_smio_set_thsafe_ops:
+    smio_set_ops (self, NULL);
+err_smio_set_ops:
+err_set_name:
+err_set_id:
+    return err;
+}
+
+/* Destroy sm_io instance of trigger_mux */
+smio_err_e trigger_mux_shutdown (smio_t *self)
+{
+    DBE_DEBUG (DBG_SM_IO | DBG_LVL_TRACE, "[sm_io:trigger_mux_exp] Shutting down trigger_mux\n");
+
+    smio_err_e err = SMIO_SUCCESS;
+    smio_trigger_mux_t *trig_iface = smio_get_handler (self);
+    ASSERT_TEST(trig_iface != NULL, "Could not get trig_iface handler",
+            err_trig_iface_handler, SMIO_ERR_ALLOC /* FIXME: improve return code */);
+
+    /* Destroy SMIO instance */
+    smio_trigger_mux_destroy (&trig_iface);
+    /* Nullify operation pointers */
+    smio_set_exp_ops (self, NULL);
+    smio_set_thsafe_client_ops (self, NULL);
+    smio_set_ops (self, NULL);
+
+err_trig_iface_handler:
+    return err;
+}
+
+const smio_bootstrap_ops_t trigger_mux_bootstrap_ops = {
+    .init = trigger_mux_init,
+    .shutdown = trigger_mux_shutdown,
+    .config_defaults = trigger_mux_config_defaults
+};
+
+SMIO_MOD_DECLARE(TRIGGER_MUX_SDB_DEVID, TRIGGER_MUX_SDB_NAME, trigger_mux_bootstrap_ops)
diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exp.h b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exp.h
new file mode 100644
index 00000000..2105a78f
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exp.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+ */
+
+#ifndef _TRIGGER_MUX_H_
+#define _TRIGGER_MUX_H_
+
+/* Known modules IDs (from SDB records defined in FPGA) */
+#define TRIGGER_MUX_SDB_DEVID       0x84b6a5ac
+#define TRIGGER_MUX_SDB_NAME        "TRIGGER_MUX"
+
+extern const smio_bootstrap_ops_t trigger_mux_bootstrap_ops;
+
+#endif
+
diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exports.c b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exports.c
new file mode 100644
index 00000000..a7ff1611
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exports.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+ */
+
+#include "sm_io_exports_helper.h"
+#include "sm_io_codes.h"
+
+/* Description SMIO TRIGGER_MUX functions */
+
+disp_op_t trigger_mux_rcv_src_exp = {
+    .name = TRIGGER_MUX_NAME_RCV_SRC,
+    .opcode = TRIGGER_MUX_OPCODE_RCV_SRC,
+    .retval = DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+    .retval_owner = DISP_OWNER_OTHER,
+    .args = {
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_END
+    }
+};
+
+disp_op_t trigger_mux_rcv_in_sel_exp = {
+    .name = TRIGGER_MUX_NAME_RCV_IN_SEL,
+    .opcode = TRIGGER_MUX_OPCODE_RCV_IN_SEL,
+    .retval = DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+    .retval_owner = DISP_OWNER_OTHER,
+    .args = {
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_END
+    }
+};
+
+disp_op_t trigger_mux_transm_src_exp = {
+    .name = TRIGGER_MUX_NAME_TRANSM_SRC,
+    .opcode = TRIGGER_MUX_OPCODE_TRANSM_SRC,
+    .retval = DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+    .retval_owner = DISP_OWNER_OTHER,
+    .args = {
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_END
+    }
+};
+
+disp_op_t trigger_mux_transm_out_sel_exp = {
+    .name = TRIGGER_MUX_NAME_TRANSM_OUT_SEL,
+    .opcode = TRIGGER_MUX_OPCODE_TRANSM_OUT_SEL,
+    .retval = DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+    .retval_owner = DISP_OWNER_OTHER,
+    .args = {
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_ENCODE(DISP_ATYPE_UINT32, uint32_t),
+        DISP_ARG_END
+    }
+};
+
+/* Exported function description */
+const disp_op_t *trigger_mux_exp_ops [] = {
+    &trigger_mux_rcv_src_exp,
+    &trigger_mux_rcv_in_sel_exp,
+    &trigger_mux_transm_src_exp,
+    &trigger_mux_transm_out_sel_exp,
+    NULL
+};
+
diff --git a/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exports.h b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exports.h
new file mode 100644
index 00000000..48cb5671
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/sm_io_trigger_mux_exports.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 LNLS (www.lnls.br)
+ * Author: Lucas Russo <lucas.russo@lnls.br>
+ *
+ * Released according to the GNU GPL, version 3 or any later version.
+ */
+
+#ifndef _SM_IO_TRIGGER_MUX_EXPORTS_H_
+#define _SM_IO_TRIGGER_MUX_EXPORTS_H_
+
+#include "disptable.h"
+
+extern disp_op_t trigger_mux_rcv_src_exp;
+extern disp_op_t trigger_mux_rcv_in_sel_exp;
+extern disp_op_t trigger_mux_transm_src_exp;
+extern disp_op_t trigger_mux_transm_out_sel_exp;
+
+extern const disp_op_t *trigger_mux_exp_ops [];
+
+#endif
+
diff --git a/src/sm_io/modules/trigger_mux/trigger_mux.mk b/src/sm_io/modules/trigger_mux/trigger_mux.mk
new file mode 100644
index 00000000..e3345fd7
--- /dev/null
+++ b/src/sm_io/modules/trigger_mux/trigger_mux.mk
@@ -0,0 +1,6 @@
+sm_io_trigger_mux_DIR = $(SRC_DIR)/sm_io/modules/trigger_mux
+
+sm_io_trigger_mux_OBJS = $(sm_io_trigger_mux_DIR)/sm_io_trigger_mux_core.o \
+				$(sm_io_trigger_mux_DIR)/sm_io_trigger_mux_exp.o \
+				$(sm_io_trigger_mux_DIR)/sm_io_trigger_mux_exports.o \
+				$(sm_io_trigger_mux_DIR)/sm_io_trigger_mux_defaults.o
-- 
GitLab