From 38f121079af24e17060a631796ee2a2c5f833ce8 Mon Sep 17 00:00:00 2001
From: Juliano Murari <juliano.murari@ess.eu>
Date: Thu, 21 Jul 2022 10:07:01 +0200
Subject: [PATCH] Change fiber status to be per bit

---
 sis8300bcmApp/Db/sis8300bcm-fiber.template | 42 ++++++++++-
 sis8300bcmApp/src/sis8300bcm.cpp           | 36 ++++++++--
 sis8300bcmApp/src/sis8300bcm.h             | 12 +++-
 vendor/ess/lib/sis8300drvbcm.c             | 82 +++++++++++++++++++++-
 vendor/ess/lib/sis8300drvbcm.h             |  6 +-
 5 files changed, 166 insertions(+), 12 deletions(-)

diff --git a/sis8300bcmApp/Db/sis8300bcm-fiber.template b/sis8300bcmApp/Db/sis8300bcm-fiber.template
index e9eea32..2b90696 100644
--- a/sis8300bcmApp/Db/sis8300bcm-fiber.template
+++ b/sis8300bcmApp/Db/sis8300bcm-fiber.template
@@ -20,10 +20,48 @@ record(longin, "$(P)$(R)OutDataSelectR")
     field(SCAN, "I/O Intr")
 }
 
-record(longin, "$(P)$(R)StatusR")
+record(bi, "$(P)$(R)SFPPresentR")
 {
     field(DTYP, "asynInt32")
-    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.STATUS")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.SFP_PRESENT")
+    field(ZNAM, "No")
+    field(ONAM, "Yes")
+    field(SCAN, "I/O Intr")
+}
+
+record(bi, "$(P)$(R)LaneUpR")
+{
+    field(DTYP, "asynInt32")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.LANE_UP")
+    field(ZNAM, "No")
+    field(ONAM, "Yes")
+    field(SCAN, "I/O Intr")
+}
+
+record(bi, "$(P)$(R)ChannelUpR")
+{
+    field(DTYP, "asynInt32")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.CHANNEL_UP")
+    field(ZNAM, "No")
+    field(ONAM, "Yes")
+    field(SCAN, "I/O Intr")
+}
+
+record(bi, "$(P)$(R)HardwareErrorR")
+{
+    field(DTYP, "asynInt32")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.HARDWARE_ERROR")
+    field(ZNAM, "No")
+    field(ONAM, "Yes")
+    field(SCAN, "I/O Intr")
+}
+
+record(bi, "$(P)$(R)SoftwareErrorR")
+{
+    field(DTYP, "asynInt32")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.FIBER.SOFTWARE_ERROR")
+    field(ZNAM, "No")
+    field(ONAM, "Yes")
     field(SCAN, "I/O Intr")
 }
 
diff --git a/sis8300bcmApp/src/sis8300bcm.cpp b/sis8300bcmApp/src/sis8300bcm.cpp
index f1afdf6..b57bde2 100644
--- a/sis8300bcmApp/src/sis8300bcm.cpp
+++ b/sis8300bcmApp/src/sis8300bcm.cpp
@@ -317,7 +317,11 @@ sis8300bcm::sis8300bcm(const char *portName, const char *devicePath,
     createParam(BCMProbeSourceString,                       asynParamInt32,     &BCMProbeSource);
     // FIBER block, channel specific
     createParam(BCMFiberOutDataSelectString,                asynParamInt32,     &BCMFiberOutDataSelect);
-    createParam(BCMFiberStatusString,                       asynParamInt32,     &BCMFiberStatus);
+    createParam(BCMFiberSFPPresentString,                   asynParamInt32,     &BCMFiberSFPPresent);
+    createParam(BCMFiberLaneUpString,                       asynParamInt32,     &BCMFiberLaneUp);
+    createParam(BCMFiberChannelUpString,                    asynParamInt32,     &BCMFiberChannelUp);
+    createParam(BCMFiberHardwareErrorString,                asynParamInt32,     &BCMFiberHardwareError);
+    createParam(BCMFiberSoftwareErrorString,                asynParamInt32,     &BCMFiberSoftwareError);
     // LUT, channel specific
     char buf[255];
     for (int i = 0; i < BCM_LUT_SIZE; i++) {
@@ -1128,12 +1132,36 @@ int sis8300bcm::readbackParameters()
             return ret;
         }
         setIntegerParam(addr, BCMFiberOutDataSelect, uintValue);
-        ret = sis8300drvbcm_get_fiber_status(mDeviceHandle, addr, &uintValue);
+        ret = sis8300drvbcm_get_fiber_sfp_present(mDeviceHandle, addr, &uintValue);
         if (ret) {
-            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_fiber_status returned %d", ret);
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_fiber_sfp_present returned %d", ret);
             return ret;
         }
-        setIntegerParam(addr, BCMFiberStatus, uintValue);
+        setIntegerParam(addr, BCMFiberSFPPresent, uintValue);
+        ret = sis8300drvbcm_get_fiber_lane_up(mDeviceHandle, addr, &uintValue);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_fiber_lane_up returned %d", ret);
+            return ret;
+        }
+        setIntegerParam(addr, BCMFiberLaneUp, uintValue);
+        ret = sis8300drvbcm_get_fiber_channel_up(mDeviceHandle, addr, &uintValue);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_fiber_channel_up returned %d", ret);
+            return ret;
+        }
+        setIntegerParam(addr, BCMFiberChannelUp, uintValue);
+        ret = sis8300drvbcm_get_fiber_hardware_error(mDeviceHandle, addr, &uintValue);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_fiber_hardware_error returned %d", ret);
+            return ret;
+        }
+        setIntegerParam(addr, BCMFiberHardwareError, uintValue);
+        ret = sis8300drvbcm_get_fiber_software_error(mDeviceHandle, addr, &uintValue);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_fiber_software_error returned %d", ret);
+            return ret;
+        }
+        setIntegerParam(addr, BCMFiberSoftwareError, uintValue);
 
     }
 
diff --git a/sis8300bcmApp/src/sis8300bcm.h b/sis8300bcmApp/src/sis8300bcm.h
index 5a50abe..850032a 100644
--- a/sis8300bcmApp/src/sis8300bcm.h
+++ b/sis8300bcmApp/src/sis8300bcm.h
@@ -213,7 +213,11 @@
 #define BCMProbeSourceString                         "BCM.PROBE.SOURCE"
 // FIBER block, channel specific
 #define BCMFiberOutDataSelectString                  "BCM.FIBER.OUT_DATA_SELECT"
-#define BCMFiberStatusString                         "BCM.FIBER.STATUS"
+#define BCMFiberSFPPresentString                     "BCM.FIBER.SFP_PRESENT"
+#define BCMFiberLaneUpString                         "BCM.FIBER.LANE_UP"
+#define BCMFiberChannelUpString                      "BCM.FIBER.CHANNEL_UP"
+#define BCMFiberHardwareErrorString                  "BCM.FIBER.HARDWARE_ERROR"
+#define BCMFiberSoftwareErrorString                  "BCM.FIBER.SOFTWARE_ERROR"
 // LUT, board specific, 16 locations
 #define BCMLutDestinationIDString                    "BCM.LUT%d.DEST_ID"
 #define BCMLutMinTriggerPeriodString                 "BCM.LUT%d.MIN_TRIGGER_PERIOD"
@@ -427,7 +431,11 @@ protected:
     int BCMProbeSource;
     // FIBER block, channel specific
     int BCMFiberOutDataSelect;
-    int BCMFiberStatus;
+    int BCMFiberSFPPresent;
+    int BCMFiberLaneUp;
+    int BCMFiberChannelUp;
+    int BCMFiberHardwareError;
+    int BCMFiberSoftwareError;
     // LUT, board specific
     int BCMLutDestinationID[BCM_LUT_SIZE];
     int BCMLutMinTriggerPeriod[BCM_LUT_SIZE];
diff --git a/vendor/ess/lib/sis8300drvbcm.c b/vendor/ess/lib/sis8300drvbcm.c
index 4c438f1..a7afd5b 100644
--- a/vendor/ess/lib/sis8300drvbcm.c
+++ b/vendor/ess/lib/sis8300drvbcm.c
@@ -2820,18 +2820,94 @@ int sis8300drvbcm_get_fiber_out_data_select(sis8300drv_usr *sisuser, unsigned in
     return ret;
 }
 
-int sis8300drvbcm_get_fiber_status(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *status)
+// used to control fiber status bits
+int sis8300drvbcm_get_fiber_sfp_present(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *sfp_present)
 {
     unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
             (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
             SIS8300BCM_FIBR_BANK_OFF + \
             SIS8300BCM_FIBR_X_STATUS_OFF;
+    unsigned int value;
+    // register has lowest 5 bits defined
+    int ret = sis8300drv_reg_read(sisuser, reg, &value);
+    if (ret) {
+        return ret;
+    }
+    // SFP present status is in bit 0
+    *sfp_present = (value & (1 << 0)) ? 1 : 0;
+    //printf("%s: channel %d, fiber status: 0x%x, sfp_present: %d\n", __func__, channel, value, *sfp_present);
+    return ret;
+}
+
+int sis8300drvbcm_get_fiber_lane_up(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *lane_up)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+            (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+            SIS8300BCM_FIBR_BANK_OFF + \
+            SIS8300BCM_FIBR_X_STATUS_OFF;
+    unsigned int value;
+    // register has lowest 5 bits defined
+    int ret = sis8300drv_reg_read(sisuser, reg, &value);
+    if (ret) {
+        return ret;
+    }
+    // lane up status is in bit 1
+    *lane_up = (value & (1 << 1)) ? 1 : 0;
+    //printf("%s: channel %d, fiber status: 0x%x, lane_up: %d\n", __func__, channel, value, *lane_up);
+    return ret;
+}
+
+int sis8300drvbcm_get_fiber_channel_up(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *channel_up)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+            (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+            SIS8300BCM_FIBR_BANK_OFF + \
+            SIS8300BCM_FIBR_X_STATUS_OFF;
+    unsigned int value;
     // register has lowest 5 bits defined
-    int ret = sis8300drv_reg_read(sisuser, reg, status);
+    int ret = sis8300drv_reg_read(sisuser, reg, &value);
+    if (ret) {
+        return ret;
+    }
+    // channel up status is in bit 2
+    *channel_up = (value & (1 << 2)) ? 1 : 0;
+    //printf("%s: channel %d, fiber status: 0x%x, channel_up: %d\n", __func__, channel, value, *channel_up);
+    return ret;
+}
+
+int sis8300drvbcm_get_fiber_hardware_error(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *hardware_error)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+            (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+            SIS8300BCM_FIBR_BANK_OFF + \
+            SIS8300BCM_FIBR_X_STATUS_OFF;
+    unsigned int value;
+    // register has lowest 5 bits defined
+    int ret = sis8300drv_reg_read(sisuser, reg, &value);
+    if (ret) {
+        return ret;
+    }
+    // hardware error status is in bit 3
+    *hardware_error = (value & (1 << 3)) ? 1 : 0;
+    //printf("%s: channel %d, fiber status: 0x%x, hardware_error: %d\n", __func__, channel, value, *hardware_error);
+    return ret;
+}
+
+int sis8300drvbcm_get_fiber_software_error(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *software_error)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+            (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+            SIS8300BCM_FIBR_BANK_OFF + \
+            SIS8300BCM_FIBR_X_STATUS_OFF;
+    unsigned int value;
+    // register has lowest 5 bits defined
+    int ret = sis8300drv_reg_read(sisuser, reg, &value);
     if (ret) {
         return ret;
     }
-    *status &= 0x1F;
+    // software error status is in bit 4
+    *software_error = (value & (1 << 4)) ? 1 : 0;
+    //printf("%s: channel %d, fiber status: 0x%x, software_error: %d\n", __func__, channel, value, *software_error);
     return ret;
 }
 
diff --git a/vendor/ess/lib/sis8300drvbcm.h b/vendor/ess/lib/sis8300drvbcm.h
index 33ddbea..5006668 100644
--- a/vendor/ess/lib/sis8300drvbcm.h
+++ b/vendor/ess/lib/sis8300drvbcm.h
@@ -294,7 +294,11 @@ 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_get_fiber_status(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *status);
+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);
+int sis8300drvbcm_get_fiber_hardware_error(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *hardware_error);
+int sis8300drvbcm_get_fiber_software_error(sis8300drv_usr *sisuser, unsigned int channel, unsigned int *software_error);
 
 #ifdef __cplusplus
 }
-- 
GitLab