From cb4e50e6e61fadba768756897d0d0ca3e5ffe94a Mon Sep 17 00:00:00 2001
From: Juliano Murari <juliano.murari@ess.eu>
Date: Thu, 21 Jul 2022 13:59:18 +0200
Subject: [PATCH] Add separated PV for fiber out data enabling

---
 sis8300bcmApp/Db/sis8300bcm-fiber.template | 22 ++++++++-
 sis8300bcmApp/src/sis8300bcm.cpp           | 12 +++++
 sis8300bcmApp/src/sis8300bcm.h             |  2 +
 vendor/ess/lib/sis8300drvbcm.c             | 55 ++++++++++++++++++++--
 vendor/ess/lib/sis8300drvbcm.h             |  2 +
 5 files changed, 88 insertions(+), 5 deletions(-)

diff --git a/sis8300bcmApp/Db/sis8300bcm-fiber.template b/sis8300bcmApp/Db/sis8300bcm-fiber.template
index 2b90696..9c18497 100644
--- a/sis8300bcmApp/Db/sis8300bcm-fiber.template
+++ b/sis8300bcmApp/Db/sis8300bcm-fiber.template
@@ -10,7 +10,7 @@ record(longout, "$(P)$(R)OutDataSelect")
     field(DTYP, "asynInt32")
     field(OUT,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.OUT_DATA_SELECT")
 #    field(ASG,  "critical")
-    info(autosaveFields, "VAL")
+#    info(autosaveFields, "VAL")
 }
 
 record(longin, "$(P)$(R)OutDataSelectR")
@@ -20,6 +20,26 @@ record(longin, "$(P)$(R)OutDataSelectR")
     field(SCAN, "I/O Intr")
 }
 
+record(bo, "$(P)$(R)OutDataEnable")
+{
+    field(DTYP, "asynInt32")
+    field(OUT,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.OUT_DATA_ENABLE")
+    field(ZNAM, "Disabled")
+    field(ONAM, "Enabled")
+    field(VAL,  "0")
+    field(PINI, "YES")
+#    field(ASG,  "critical")
+#    info(autosaveFields, "VAL")
+}
+record(bi, "$(P)$(R)OutDataEnableR")
+{
+    field(DTYP, "asynInt32")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.OUT_DATA_ENABLE")
+    field(ZNAM, "Disabled")
+    field(ONAM, "Enabled")
+    field(SCAN, "I/O Intr")
+}
+
 record(bi, "$(P)$(R)SFPPresentR")
 {
     field(DTYP, "asynInt32")
diff --git a/sis8300bcmApp/src/sis8300bcm.cpp b/sis8300bcmApp/src/sis8300bcm.cpp
index b57bde2..cab2bc3 100644
--- a/sis8300bcmApp/src/sis8300bcm.cpp
+++ b/sis8300bcmApp/src/sis8300bcm.cpp
@@ -317,6 +317,7 @@ sis8300bcm::sis8300bcm(const char *portName, const char *devicePath,
     createParam(BCMProbeSourceString,                       asynParamInt32,     &BCMProbeSource);
     // FIBER block, channel specific
     createParam(BCMFiberOutDataSelectString,                asynParamInt32,     &BCMFiberOutDataSelect);
+    createParam(BCMFiberOutDataEnableString,                asynParamInt32,     &BCMFiberOutDataEnable);
     createParam(BCMFiberSFPPresentString,                   asynParamInt32,     &BCMFiberSFPPresent);
     createParam(BCMFiberLaneUpString,                       asynParamInt32,     &BCMFiberLaneUp);
     createParam(BCMFiberChannelUpString,                    asynParamInt32,     &BCMFiberChannelUp);
@@ -1132,6 +1133,12 @@ int sis8300bcm::readbackParameters()
             return ret;
         }
         setIntegerParam(addr, BCMFiberOutDataSelect, uintValue);
+        ret = sis8300drvbcm_get_fiber_out_data_enable(mDeviceHandle, addr, &uintValue);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_fiber_out_data_enable returned %d", ret);
+            return ret;
+        }
+        setIntegerParam(addr, BCMFiberOutDataEnable, uintValue);
         ret = sis8300drvbcm_get_fiber_sfp_present(mDeviceHandle, addr, &uintValue);
         if (ret) {
             asynPrintError(pasynUserSelf, "sis8300drvbcm_get_fiber_sfp_present returned %d", ret);
@@ -1920,6 +1927,11 @@ asynStatus sis8300bcm::writeInt32(asynUser *pasynUser, epicsInt32 value)
         if (ret) {
             asynPrintError(pasynUserSelf, "sis8300drvbcm_set_fiber_out_data_select returned %d", ret);
         }
+    } else if (function == BCMFiberOutDataEnable) {
+        ret = sis8300drvbcm_set_fiber_out_data_enable(mDeviceHandle, addr, value);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_set_fiber_out_data_enable returned %d", ret);
+        }
     } else {
         if (function < BCM_FIRST_PARAM) {
             status = sis8300::writeInt32(pasynUser, value);
diff --git a/sis8300bcmApp/src/sis8300bcm.h b/sis8300bcmApp/src/sis8300bcm.h
index 850032a..b23167b 100644
--- a/sis8300bcmApp/src/sis8300bcm.h
+++ b/sis8300bcmApp/src/sis8300bcm.h
@@ -213,6 +213,7 @@
 #define BCMProbeSourceString                         "BCM.PROBE.SOURCE"
 // FIBER block, channel specific
 #define BCMFiberOutDataSelectString                  "BCM.FIBER.OUT_DATA_SELECT"
+#define BCMFiberOutDataEnableString                  "BCM.FIBER.OUT_DATA_ENABLE"
 #define BCMFiberSFPPresentString                     "BCM.FIBER.SFP_PRESENT"
 #define BCMFiberLaneUpString                         "BCM.FIBER.LANE_UP"
 #define BCMFiberChannelUpString                      "BCM.FIBER.CHANNEL_UP"
@@ -431,6 +432,7 @@ protected:
     int BCMProbeSource;
     // FIBER block, channel specific
     int BCMFiberOutDataSelect;
+    int BCMFiberOutDataEnable;
     int BCMFiberSFPPresent;
     int BCMFiberLaneUp;
     int BCMFiberChannelUp;
diff --git a/vendor/ess/lib/sis8300drvbcm.c b/vendor/ess/lib/sis8300drvbcm.c
index a7afd5b..e455edd 100644
--- a/vendor/ess/lib/sis8300drvbcm.c
+++ b/vendor/ess/lib/sis8300drvbcm.c
@@ -2799,9 +2799,16 @@ int sis8300drvbcm_set_fiber_out_data_select(sis8300drv_usr *sisuser, unsigned in
             (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
             SIS8300BCM_FIBR_BANK_OFF + \
             SIS8300BCM_FIBR_X_OUT_DATA_SELECT_OFF;
+    unsigned int value;
     // register has lowest 5 bits defined
-    selection &= 0x1F;
-    int ret = sis8300drv_reg_write(sisuser, reg, selection);
+    int ret = sis8300drv_reg_read(sisuser, reg, &value);
+    if (ret) {
+        return ret;
+    }
+    // out data select is controlled by lowest 4 bits
+    selection &= 0xF;
+    selection += (value & (1 << 4));  // preserve enable bit
+    ret = sis8300drv_reg_write(sisuser, reg, selection);
     return ret;
 }
 
@@ -2811,12 +2818,52 @@ int sis8300drvbcm_get_fiber_out_data_select(sis8300drv_usr *sisuser, unsigned in
             (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
             SIS8300BCM_FIBR_BANK_OFF + \
             SIS8300BCM_FIBR_X_OUT_DATA_SELECT_OFF;
-    // register has lowest 5 bits defined
+    // register has lowest 4 bits defined
     int ret = sis8300drv_reg_read(sisuser, reg, selection);
     if (ret) {
         return ret;
     }
-    *selection &= 0x1F;
+    *selection &= 0xF;
+    return ret;
+}
+
+int sis8300drvbcm_set_fiber_out_data_enable(sis8300drv_usr *sisuser, unsigned int channel, unsigned int enable)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+            (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+            SIS8300BCM_FIBR_BANK_OFF + \
+            SIS8300BCM_FIBR_X_OUT_DATA_SELECT_OFF;
+    unsigned int value;
+    // register has lowest 5 bits defined
+    int ret = sis8300drv_reg_read(sisuser, reg, &value);
+    if (ret) {
+        return ret;
+    }
+    value &= 0x1F;
+    // out data enable is controlled by bit 4
+    if (enable) {
+        value |= (1 << 4);
+    } else {
+        value &= ~(1 << 4);
+    }
+    ret = sis8300drv_reg_write(sisuser, reg, value);
+    return ret;
+}
+
+int sis8300drvbcm_get_fiber_out_data_enable(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *enable)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+            (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+            SIS8300BCM_FIBR_BANK_OFF + \
+            SIS8300BCM_FIBR_X_OUT_DATA_SELECT_OFF;
+    unsigned int value;
+    // register has lowest 5 bits defined
+    int ret = sis8300drv_reg_read(sisuser, reg, &value);
+    if (ret) {
+        return ret;
+    }
+    // out data select enable is in bit 4
+    *enable = (value & (1 << 4)) ? 1 : 0;
     return ret;
 }
 
diff --git a/vendor/ess/lib/sis8300drvbcm.h b/vendor/ess/lib/sis8300drvbcm.h
index 5006668..98dd3e2 100644
--- a/vendor/ess/lib/sis8300drvbcm.h
+++ b/vendor/ess/lib/sis8300drvbcm.h
@@ -294,6 +294,8 @@ int sis8300drvbcm_set_enable_calibration_pulse(sis8300drv_usr *sisuser, unsigned
 int sis8300drvbcm_get_calibration_sample(sis8300drv_usr *sisuser, unsigned int channel, unsigned int index, double *sample);
 int sis8300drvbcm_set_fiber_out_data_select(sis8300drv_usr *sisuser, unsigned int channel, unsigned int selection);
 int sis8300drvbcm_get_fiber_out_data_select(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *selection);
+int sis8300drvbcm_set_fiber_out_data_enable(sis8300drv_usr *sisuser, unsigned int channel, unsigned int enable);
+int sis8300drvbcm_get_fiber_out_data_enable(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *enable);
 int sis8300drvbcm_get_fiber_sfp_present(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *sfp_present);
 int sis8300drvbcm_get_fiber_lane_up(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *lane_up);
 int sis8300drvbcm_get_fiber_channel_up(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *channel_up);
-- 
GitLab