From 04ff9eb8a145ffc4ee69e4610300c7c367ce6ba0 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Tue, 11 Dec 2012 18:25:01 -0600
Subject: [PATCH] rec: mbbiDirect and mbboDirect refactoring
This includes changes to functionality, documented.
---
documentation/RELEASE_NOTES.html | 32 ++
src/std/dev/devMbboDirectSoft.c | 64 +---
src/std/dev/devMbboDirectSoftCallback.c | 70 ++--
src/std/dev/devMbboDirectSoftRaw.c | 72 ++--
src/std/dev/devMbboSoftRaw.c | 68 ++--
src/std/rec/mbbiDirectRecord.c | 325 ++++++++--------
src/std/rec/mbboDirectRecord.c | 468 ++++++++++++------------
7 files changed, 523 insertions(+), 576 deletions(-)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index b9ba24961..fd3dc4673 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -15,6 +15,38 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.
Changes between 3.15.0.1 and 3.15.0.2
+mbboDirect and mbbiDirect records
+
+These record types have undergone some significant rework, and will behave
+slightly differently than they did in their 3.14 versions. The externally
+visible changes are as follows:
+
+mbbiDirect
+
+
+ - If the MASK field is set in a database file, it will not be over-written
+ when the record is initialized. This allows non-contiguous masks to be set,
+ although only the device support actually uses the MASK field.
+ - If process() finds the UDF field to be set, the record will raise a
+ UDF/INVALID alarm.
+
+
+mbboDirect
+
+
+ - If the MASK field is set in a database file, it will not be over-written
+ when the record is initialized. This allows non-contiguous masks to be set,
+ although only the device support actually uses the MASK field.
+ - After the device support's init_record() routine returns during record
+ initialization, if OMSL is
supervisory
and UDF is clear the fields
+ B0-BF will be set from the current VAL field.
+ - When a put to the OMSL field sets it to
supervisory
, the fields
+ B0-BF will be set from the current VAL field. This did not used to happen,
+ the individual bit fields were previously never modified by the record.
+ Note that this change may require some databases to be modified, if they
+ were designed to take advantage of the previous behavior.
+
+
Redirection of the errlog console stream
A new routine has been added to the errlog facility which allows the console
diff --git a/src/std/dev/devMbboDirectSoft.c b/src/std/dev/devMbboDirectSoft.c
index 7bf995fb6..0c0851980 100644
--- a/src/std/dev/devMbboDirectSoft.c
+++ b/src/std/dev/devMbboDirectSoft.c
@@ -1,64 +1,36 @@
/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devMbboDirectSoft.c */
-/* base/src/dev $Revision-Id$ */
/*
- * Original Author: Bob Dalesio
- * Current Author: Matthew Needes
- * Date: 10-08-93
+ * Original Author: Bob Dalesio
+ * Date: 10-08-93
*/
-#include
-#include
-#include
-#include "alarm.h"
-#include "dbDefs.h"
+#include
+
#include "dbAccess.h"
-#include "recGbl.h"
-#include "recSup.h"
#include "devSup.h"
#include "mbboDirectRecord.h"
#include "epicsExport.h"
-/* Create the dset for devMbboSoft */
-static long init_record(mbboDirectRecord *prec);
-static long write_mbbo(mbboDirectRecord *prec);
-struct {
- long number;
- DEVSUPFUN report;
- DEVSUPFUN init;
- DEVSUPFUN init_record;
- DEVSUPFUN get_ioint_info;
- DEVSUPFUN write_mbbo;
-}devMbboDirectSoft={
- 5,
- NULL,
- NULL,
- init_record,
- NULL,
- write_mbbo
-};
-epicsExportAddress(dset,devMbboDirectSoft);
-
-static long init_record(mbboDirectRecord *prec)
-{
- long status = 0;
-
- /* dont convert */
- status = 2;
- return status;
-
-} /* end init_record() */
-
static long write_mbbo(mbboDirectRecord *prec)
{
- dbPutLink(&prec->out,DBR_USHORT,&prec->val,1);
+ dbPutLink(&prec->out, DBR_USHORT, &prec->val, 1);
return 0;
}
+
+/* Create the dset for devMbboDirectSoft */
+struct {
+ dset common;
+ DEVSUPFUN write;
+} devMbboDirectSoft = {
+ {5, NULL, NULL, NULL, NULL},
+ write_mbbo
+};
+epicsExportAddress(dset, devMbboDirectSoft);
diff --git a/src/std/dev/devMbboDirectSoftCallback.c b/src/std/dev/devMbboDirectSoftCallback.c
index c5639d4f5..8c71ef77e 100644
--- a/src/std/dev/devMbboDirectSoftCallback.c
+++ b/src/std/dev/devMbboDirectSoftCallback.c
@@ -1,66 +1,56 @@
/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devMbboDirectSoftCallback.c */
/*
- * Author: Marty Kraimer
- * Date: 04NOV2003
+ * Original Author: Marty Kraimer
+ * Date: 04NOV2003
*/
-#include
#include
-#include
#include "alarm.h"
-#include "dbDefs.h"
#include "dbAccess.h"
#include "recGbl.h"
-#include "recSup.h"
#include "devSup.h"
#include "mbboDirectRecord.h"
#include "epicsExport.h"
-/* Create the dset for devMbboSoft */
-static long write_mbbo(mbboDirectRecord *prec);
-struct {
- long number;
- DEVSUPFUN report;
- DEVSUPFUN init;
- DEVSUPFUN init_record;
- DEVSUPFUN get_ioint_info;
- DEVSUPFUN write_mbbo;
-}devMbboDirectSoftCallback={
- 5,
- NULL,
- NULL,
- NULL,
- NULL,
- write_mbbo
-};
-epicsExportAddress(dset,devMbboDirectSoftCallback);
-
-static long write_mbbo(mbboDirectRecord *prec)
+static long write_mbbo(mbboDirectRecord *prec)
{
struct link *plink = &prec->out;
long status;
- if(prec->pact) return(0);
- if(plink->type!=CA_LINK) {
- status = dbPutLink(plink,DBR_USHORT,&prec->val,1);
- return(status);
+ if (prec->pact)
+ return 0;
+
+ if (plink->type != CA_LINK) {
+ status = dbPutLink(plink, DBR_USHORT, &prec->val, 1);
+ return status;
}
- status = dbCaPutLinkCallback(plink,DBR_USHORT,&prec->val,1,
- dbCaCallbackProcess,plink);
- if(status) {
- recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
- return(status);
+
+ status = dbCaPutLinkCallback(plink, DBR_USHORT, &prec->val, 1,
+ dbCaCallbackProcess, plink);
+ if (status) {
+ recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM);
+ return status;
}
+
prec->pact = TRUE;
- return(0);
+ return 0;
}
+
+/* Create the dset for devMbboSoft */
+struct {
+ dset common;
+ DEVSUPFUN write;
+} devMbboDirectSoftCallback = {
+ {5, NULL, NULL, NULL, NULL},
+ write_mbbo
+};
+epicsExportAddress(dset, devMbboDirectSoftCallback);
diff --git a/src/std/dev/devMbboDirectSoftRaw.c b/src/std/dev/devMbboDirectSoftRaw.c
index 931f212cb..c3bbdc898 100644
--- a/src/std/dev/devMbboDirectSoftRaw.c
+++ b/src/std/dev/devMbboDirectSoftRaw.c
@@ -1,70 +1,50 @@
/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devMbboDirectSoftRaw.c */
-/* base/src/dev $Revision-Id$ */
/*
- * Author: Janet Anderson
- * Current Author: Matthew Needes
- * Date: 10-08-93
+ * Original Author: Janet Anderson
+ * Date: 10-08-93
*/
-#include
-#include
-#include
-#include "alarm.h"
-#include "dbDefs.h"
+#include
+
#include "dbAccess.h"
-#include "recGbl.h"
-#include "recSup.h"
+#include "epicsTypes.h"
#include "devSup.h"
#include "mbboDirectRecord.h"
#include "epicsExport.h"
-
-/* Create the dset for devMbboDirectSoftRaw */
-static long init_record(mbboDirectRecord *prec);
-static long write_mbbo(mbboDirectRecord *prec);
-struct {
- long number;
- DEVSUPFUN report;
- DEVSUPFUN init;
- DEVSUPFUN init_record;
- DEVSUPFUN get_ioint_info;
- DEVSUPFUN write_mbbo;
-}devMbboDirectSoftRaw={
- 5,
- NULL,
- NULL,
- init_record,
- NULL,
- write_mbbo
-};
-epicsExportAddress(dset,devMbboDirectSoftRaw);
-
static long init_record(mbboDirectRecord *prec)
{
- long status = 0;
-
- if (prec->out.type != PV_LINK)
- status = 2;
- /*to preserve old functionality*/
- if(prec->nobt == 0) prec->mask = 0xffffffff;
+ if (prec->nobt == 0)
+ prec->mask = 0xffffffff;
+
prec->mask <<= prec->shft;
- return status;
-} /* end init_record() */
+
+ return 2; /* Don't convert */
+}
static long write_mbbo(mbboDirectRecord *prec)
{
- unsigned long data;
+ epicsUInt32 data;
data = prec->rval & prec->mask;
- dbPutLink(&prec->out,DBR_LONG, &data,1);
+ dbPutLink(&prec->out, DBR_ULONG, &data, 1);
return 0;
}
+
+/* Create the dset for devMbboDirectSoftRaw */
+struct {
+ dset common;
+ DEVSUPFUN write;
+} devMbboDirectSoftRaw = {
+ {5, NULL, NULL, init_record, NULL},
+ write_mbbo
+};
+epicsExportAddress(dset, devMbboDirectSoftRaw);
diff --git a/src/std/dev/devMbboSoftRaw.c b/src/std/dev/devMbboSoftRaw.c
index e80c6ac62..092b6a8a7 100644
--- a/src/std/dev/devMbboSoftRaw.c
+++ b/src/std/dev/devMbboSoftRaw.c
@@ -1,66 +1,50 @@
/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devMbboSoftRaw.c */
-/* base/src/dev $Revision-Id$ */
/*
- * Author: Janet Anderson
- * Date: 3-28-92
+ * Original Author: Janet Anderson
+ * Date: 3-28-92
*/
-#include
-#include
-#include
-#include "alarm.h"
-#include "dbDefs.h"
+#include
+
#include "dbAccess.h"
-#include "recGbl.h"
-#include "recSup.h"
+#include "epicsTypes.h"
#include "devSup.h"
#include "mbboRecord.h"
#include "epicsExport.h"
-/* Create the dset for devMbboSoftRaw */
-static long init_record(mbboRecord *prec);
-static long write_mbbo(mbboRecord *prec);
-struct {
- long number;
- DEVSUPFUN report;
- DEVSUPFUN init;
- DEVSUPFUN init_record;
- DEVSUPFUN get_ioint_info;
- DEVSUPFUN write_mbbo;
-}devMbboSoftRaw={
- 5,
- NULL,
- NULL,
- init_record,
- NULL,
- write_mbbo
-};
-epicsExportAddress(dset,devMbboSoftRaw);
-
static long init_record(mbboRecord *prec)
{
- /*to preserve old functionality*/
- if (prec->nobt == 0) prec->mask = 0xffffffff;
+ if (prec->nobt == 0)
+ prec->mask = 0xffffffff;
+
prec->mask <<= prec->shft;
- /*dont convert*/
- return 2;
-
-} /* end init_record() */
+
+ return 2; /* Don't convert */
+}
static long write_mbbo(mbboRecord *prec)
{
- unsigned long data;
+ epicsUInt32 data;
data = prec->rval & prec->mask;
- dbPutLink(&prec->out,DBR_LONG, &data,1);
+ dbPutLink(&prec->out, DBR_ULONG, &data, 1);
return 0;
}
+
+/* Create the dset for devMbboSoftRaw */
+struct {
+ dset common;
+ DEVSUPFUN write;
+} devMbboSoftRaw = {
+ {5, NULL, NULL, init_record, NULL},
+ write_mbbo
+};
+epicsExportAddress(dset, devMbboSoftRaw);
diff --git a/src/std/rec/mbbiDirectRecord.c b/src/std/rec/mbbiDirectRecord.c
index 08ea4c8f6..f905db8e5 100644
--- a/src/std/rec/mbbiDirectRecord.c
+++ b/src/std/rec/mbbiDirectRecord.c
@@ -1,5 +1,5 @@
/*************************************************************************\
-* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
+* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
@@ -11,9 +11,10 @@
/* $Revision-Id$ */
-/* recMbbiDirect.c - Record Support routines for mbboDirect records */
+/* mbbiDirectRecord.c - Record Support routines for mbboDirect records */
/*
- * Original Author: Bob Dalesio and Matthew Needes 10-07-93
+ * Original Authors: Bob Dalesio and Matthew Needes
+ * Date: 10-07-93
*/
#include
@@ -23,7 +24,7 @@
#include
#include "dbDefs.h"
-#include "epicsPrint.h"
+#include "errlog.h"
#include "alarm.h"
#include "dbAccess.h"
#include "dbEvent.h"
@@ -59,219 +60,203 @@ static long process(mbbiDirectRecord *);
#define get_alarm_double NULL
rset mbbiDirectRSET={
- RSETNUMBER,
- report,
- initialize,
- init_record,
- process,
- special,
- get_value,
- cvt_dbaddr,
- get_array_info,
- put_array_info,
- get_units,
- get_precision,
- get_enum_str,
- get_enum_strs,
- put_enum_str,
- get_graphic_double,
- get_control_double,
- get_alarm_double
+ RSETNUMBER,
+ report,
+ initialize,
+ init_record,
+ process,
+ special,
+ get_value,
+ cvt_dbaddr,
+ get_array_info,
+ put_array_info,
+ get_units,
+ get_precision,
+ get_enum_str,
+ get_enum_strs,
+ put_enum_str,
+ get_graphic_double,
+ get_control_double,
+ get_alarm_double
};
epicsExportAddress(rset,mbbiDirectRSET);
struct mbbidset { /* multi bit binary input dset */
- long number;
- DEVSUPFUN dev_report;
- DEVSUPFUN init;
- DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
- DEVSUPFUN get_ioint_info;
- DEVSUPFUN read_mbbi;/*(0,2)=>(success, success no convert)*/
+ long number;
+ DEVSUPFUN dev_report;
+ DEVSUPFUN init;
+ DEVSUPFUN init_record; /*returns: (-1,0)=>(failure, success)*/
+ DEVSUPFUN get_ioint_info;
+ DEVSUPFUN read_mbbi; /*returns: (0,2)=>(success, success no convert)*/
};
-static void refresh_bits(mbbiDirectRecord *, unsigned short);
static void monitor(mbbiDirectRecord *);
static long readValue(mbbiDirectRecord *);
-#define NUM_BITS 16
-
-/* refreshes all the bit fields based on a hardware value
- and sends monitors if the bit's value or the record's
- severity/status have changed */
-static void refresh_bits(mbbiDirectRecord *prec,
- unsigned short monitor_mask)
-{
- unsigned short i;
- unsigned short mask = 1;
- unsigned short momask;
- unsigned char *bit;
-
- bit = &(prec->b0);
- for (i=0; ival & mask) {
- if (*bit == 0) {
- *bit = 1;
- momask |= DBE_VALUE | DBE_LOG;
- }
- } else {
- if (*bit != 0) {
- *bit = 0;
- momask |= DBE_VALUE | DBE_LOG;
- }
- }
- if (momask)
- db_post_events(prec,bit,momask);
- }
-}
+#define NUM_BITS 16
static long init_record(mbbiDirectRecord *prec, int pass)
{
- struct mbbidset *pdset;
- long status;
+ struct mbbidset *pdset = (struct mbbidset *) prec->dset;
+ long status = 0;
- if (pass==0) return(0);
+ if (pass == 0)
+ return status;
- /* siml must be a CONSTANT or a PV_LINK or a DB_LINK or a CA_LINK*/
- if (prec->siml.type == CONSTANT) {
- recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
+ if (!pdset) {
+ recGblRecordError(S_dev_noDSET, prec, "mbbiDirect: init_record");
+ return S_dev_noDSET;
}
- /* siol must be a CONSTANT or a PV_LINK or a DB_LINK */
- if (prec->siol.type == CONSTANT) {
- recGblInitConstantLink(&prec->siol,DBF_USHORT,&prec->sval);
+ if ((pdset->number < 5) || (pdset->read_mbbi == NULL)) {
+ recGblRecordError(S_dev_missingSup, prec, "mbbiDirect: init_record");
+ return S_dev_missingSup;
}
- if(!(pdset = (struct mbbidset *)(prec->dset))) {
- recGblRecordError(S_dev_noDSET,(void *)prec,"mbbiDirect: init_record");
- return(S_dev_noDSET);
- }
- /* must have read_mbbi function defined */
- if( (pdset->number < 5) || (pdset->read_mbbi == NULL) ) {
- recGblRecordError(S_dev_missingSup,(void *)prec,"mbbiDirect: init_record");
- return(S_dev_missingSup);
- }
- /* initialize mask*/
- prec->mask = (1 << prec->nobt) - 1;
+ if (prec->siml.type == CONSTANT)
+ recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
- if( pdset->init_record ) {
- if((status=(*pdset->init_record)(prec))) return(status);
- refresh_bits(prec, 0);
+ if (prec->siol.type == CONSTANT)
+ recGblInitConstantLink(&prec->siol, DBF_USHORT, &prec->sval);
+
+ /* Initialize MASK if the user didn't */
+ if (prec->mask == 0)
+ prec->mask = (1 << prec->nobt) - 1;
+
+ if (pdset->init_record) {
+ status = pdset->init_record(prec);
+ if (status == 0) {
+ epicsUInt16 val = prec->val;
+ epicsUInt8 *pBn = &prec->b0;
+ int i;
+
+ /* Initialize B0 - BF from VAL */
+ for (i = 0; i < NUM_BITS; i++, pBn++, val >>= 1)
+ *pBn = !! (val & 1);
+ }
}
+
prec->mlst = prec->val;
prec->oraw = prec->rval;
- return(0);
+ return status;
}
static long process(mbbiDirectRecord *prec)
{
- struct mbbidset *pdset = (struct mbbidset *)(prec->dset);
- long status;
- unsigned char pact=prec->pact;
+ struct mbbidset *pdset = (struct mbbidset *) prec->dset;
+ long status;
+ int pact = prec->pact;
- if( (pdset==NULL) || (pdset->read_mbbi==NULL) ) {
- prec->pact=TRUE;
- recGblRecordError(S_dev_missingSup,(void *)prec,"read_mbbi");
- return(S_dev_missingSup);
- }
+ if ((pdset == NULL) || (pdset->read_mbbi == NULL)) {
+ prec->pact = TRUE;
+ recGblRecordError(S_dev_missingSup, prec, "read_mbbi");
+ return S_dev_missingSup;
+ }
- status=readValue(prec); /* read the new value */
- /* check if device support set pact */
- if ( !pact && prec->pact ) return(0);
- prec->pact = TRUE;
+ status = readValue(prec);
- recGblGetTimeStamp(prec);
+ /* Done if device support set PACT */
+ if (!pact && prec->pact)
+ return 0;
- if(status==0) { /* convert the value */
- epicsUInt32 rval = prec->rval;
+ prec->pact = TRUE;
+ recGblGetTimeStamp(prec);
- if(prec->shft>0) rval >>= prec->shft;
- prec->val = (unsigned short)rval;
- prec->udf=FALSE;
+ if (status == 0) {
+ /* Convert RVAL to VAL */
+ epicsUInt32 rval = prec->rval;
- }
- else if(status == 2) status = 0;
+ if (prec->shft > 0)
+ rval >>= prec->shft;
- /* check event list */
- monitor(prec);
+ prec->val = rval;
+ prec->udf = FALSE;
+ }
+ else if (status == 2)
+ status = 0;
- /* process the forward scan link record */
- recGblFwdLink(prec);
+ if (prec->udf)
+ recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM);
- prec->pact=FALSE;
- return(status);
+ monitor(prec);
+
+ /* Wrap up */
+ recGblFwdLink(prec);
+ prec->pact = FALSE;
+ return status;
}
static void monitor(mbbiDirectRecord *prec)
{
- unsigned short monitor_mask;
+ epicsUInt16 events = recGblResetAlarms(prec);
+ epicsUInt16 vl_events = events | DBE_VALUE | DBE_LOG;
+ epicsUInt16 val = prec->val;
+ epicsUInt8 *pBn = &prec->b0;
+ int i;
- monitor_mask = recGblResetAlarms(prec);
+ /* Update B0 - BF from VAL and post monitors */
+ for (i = 0; i < NUM_BITS; i++, pBn++, val >>= 1) {
+ epicsUInt8 oBn = *pBn;
- /* send out bit field monitors (value change and sevr change) */
- refresh_bits(prec, monitor_mask);
+ *pBn = !! (val & 1);
+ if (oBn != *pBn)
+ db_post_events(prec, pBn, vl_events);
+ else if (events)
+ db_post_events(prec, pBn, events);
+ }
- /* check for value change */
- if (prec->mlst != prec->val) {
- /* post events for value change and archive change */
- monitor_mask |= (DBE_VALUE | DBE_LOG);
- /* update last value monitored */
- prec->mlst = prec->val;
- }
- /* send out monitors connected to the value field */
- if (monitor_mask){
- db_post_events(prec,&prec->val,monitor_mask);
- }
- if(prec->oraw!=prec->rval) {
- db_post_events(prec,&prec->rval,
- monitor_mask|DBE_VALUE|DBE_LOG);
- prec->oraw = prec->rval;
- }
- return;
+ if (prec->mlst != prec->val) {
+ events = vl_events;
+ prec->mlst = prec->val;
+ }
+ if (events)
+ db_post_events(prec, &prec->val, events);
+
+ if (prec->oraw != prec->rval) {
+ db_post_events(prec, &prec->rval, vl_events);
+ prec->oraw = prec->rval;
+ }
}
-
+
static long readValue(mbbiDirectRecord *prec)
{
- long status;
- struct mbbidset *pdset = (struct mbbidset *) (prec->dset);
+ struct mbbidset *pdset = (struct mbbidset *) prec->dset;
+ long status;
- if (prec->pact == TRUE){
- status=(*pdset->read_mbbi)(prec);
- return(status);
- }
+ if (prec->pact)
+ return pdset->read_mbbi(prec);
- status=dbGetLink(&(prec->siml),DBR_ENUM,
- &(prec->simm),0,0);
- if (status)
- return(status);
+ status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0);
+ if (status)
+ return status;
- if (prec->simm == menuSimmNO){
- status=(*pdset->read_mbbi)(prec);
- return(status);
- }
- if (prec->simm == menuSimmYES){
- status=dbGetLink(&(prec->siol),
- DBR_ULONG,&(prec->sval),0,0);
- if (status==0){
- prec->val=(unsigned short)prec->sval;
- prec->udf=FALSE;
- }
- status=2; /* don't convert */
- }
- else if (prec->simm == menuSimmRAW){
- status=dbGetLink(&(prec->siol),
- DBR_ULONG,&(prec->sval),0,0);
- if (status==0){
- prec->rval=prec->sval;
- prec->udf=FALSE;
- }
- status=0; /* convert since we've written RVAL */
- } else {
- status=-1;
- recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
- return(status);
- }
- recGblSetSevr(prec,SIMM_ALARM,prec->sims);
+ switch (prec->simm) {
+ case menuSimmNO:
+ return pdset->read_mbbi(prec);
- return(status);
+ case menuSimmYES:
+ status = dbGetLink(&prec->siol, DBR_ULONG, &prec->sval, 0, 0);
+ if (status == 0) {
+ prec->val = prec->sval;
+ prec->udf = FALSE;
+ }
+ status = 2; /* Don't convert */
+ break;
+
+ case menuSimmRAW:
+ status = dbGetLink(&prec->siol, DBR_ULONG, &prec->sval, 0, 0);
+ if (status == 0) {
+ prec->rval = prec->sval;
+ prec->udf = FALSE;
+ }
+ status = 0; /* Convert RVAL */
+ break;
+
+ default:
+ recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
+ return -1;
+ }
+
+ recGblSetSevr(prec, SIMM_ALARM, prec->sims);
+ return status;
}
diff --git a/src/std/rec/mbboDirectRecord.c b/src/std/rec/mbboDirectRecord.c
index 2d52131d7..c1179c21d 100644
--- a/src/std/rec/mbboDirectRecord.c
+++ b/src/std/rec/mbboDirectRecord.c
@@ -1,20 +1,20 @@
/*************************************************************************\
-* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
+* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* $Revision-Id$ */
-/* recMbboDirect.c - Record Support for mbboDirect records */
+/* mbboDirectRecord.c - Record Support for mbboDirect records */
/*
* Original Author: Bob Dalesio
* Date: 10-06-93
*/
-
+
#include
#include
#include
@@ -22,7 +22,7 @@
#include
#include "dbDefs.h"
-#include "epicsPrint.h"
+#include "errlog.h"
#include "alarm.h"
#include "dbAccess.h"
#include "dbEvent.h"
@@ -59,35 +59,35 @@ static long special(DBADDR *, int);
#define get_control_double NULL
#define get_alarm_double NULL
-rset mbboDirectRSET={
- RSETNUMBER,
- report,
- initialize,
- init_record,
- process,
- special,
- get_value,
- cvt_dbaddr,
- get_array_info,
- put_array_info,
- get_units,
- get_precision,
- get_enum_str,
- get_enum_strs,
- put_enum_str,
- get_graphic_double,
- get_control_double,
- get_alarm_double
+rset mbboDirectRSET = {
+ RSETNUMBER,
+ report,
+ initialize,
+ init_record,
+ process,
+ special,
+ get_value,
+ cvt_dbaddr,
+ get_array_info,
+ put_array_info,
+ get_units,
+ get_precision,
+ get_enum_str,
+ get_enum_strs,
+ put_enum_str,
+ get_graphic_double,
+ get_control_double,
+ get_alarm_double
};
-epicsExportAddress(rset,mbboDirectRSET);
+epicsExportAddress(rset, mbboDirectRSET);
struct mbbodset { /* multi bit binary output dset */
- long number;
- DEVSUPFUN dev_report;
- DEVSUPFUN init;
- DEVSUPFUN init_record; /*returns: (0,2)=>(success,success no convert)*/
- DEVSUPFUN get_ioint_info;
- DEVSUPFUN write_mbbo; /*returns: (0,2)=>(success,success no convert)*/
+ long number;
+ DEVSUPFUN dev_report;
+ DEVSUPFUN init;
+ DEVSUPFUN init_record; /*returns: (0, 2)=>(success, success no convert)*/
+ DEVSUPFUN get_ioint_info;
+ DEVSUPFUN write_mbbo; /*returns: (0, 2)=>(success, success no convert)*/
};
@@ -95,264 +95,268 @@ static void convert(mbboDirectRecord *);
static void monitor(mbboDirectRecord *);
static long writeValue(mbboDirectRecord *);
-#define NUM_BITS 16
+#define NUM_BITS 16
static long init_record(mbboDirectRecord *prec, int pass)
{
- struct mbbodset *pdset;
+ struct mbbodset *pdset = (struct mbbodset *) prec->dset;
long status = 0;
- int i;
- if (pass==0) return(0);
+ if (pass == 0)
+ return 0;
- /* mbboDirect.siml must be a CONSTANT or a PV_LINK or a DB_LINK */
- if (prec->siml.type == CONSTANT) {
- recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
+ if (!pdset) {
+ recGblRecordError(S_dev_noDSET, prec, "mbboDirect: init_record");
+ return S_dev_noDSET;
}
- if(!(pdset = (struct mbbodset *)(prec->dset))) {
- recGblRecordError(S_dev_noDSET,(void *)prec,"mbboDirect: init_record");
- return(S_dev_noDSET);
+ if ((pdset->number < 5) || (pdset->write_mbbo == NULL)) {
+ recGblRecordError(S_dev_missingSup, prec, "mbboDirect: init_record");
+ return S_dev_missingSup;
}
- /* must have write_mbbo function defined */
- if( (pdset->number < 5) || (pdset->write_mbbo == NULL) ) {
- recGblRecordError(S_dev_missingSup,(void *)prec,"mbboDirect: init_record");
- return(S_dev_missingSup);
- }
- if (prec->dol.type == CONSTANT){
- if(recGblInitConstantLink(&prec->dol,DBF_USHORT,&prec->val))
- prec->udf = FALSE;
- }
- /* initialize mask*/
- prec->mask = 0;
- for (i=0; inobt; i++) {
- prec->mask <<= 1; /* shift left 1 bit*/
- prec->mask |= 1; /* set low order bit*/
- }
- if(pdset->init_record) {
- epicsUInt32 rval;
- status=(*pdset->init_record)(prec);
- /* init_record might set status */
- if(status==0){
- rval = prec->rval;
- if(prec->shft>0) rval >>= prec->shft;
- prec->val = (unsigned short)rval;
- prec->udf = FALSE;
- } else if (status == 2) status = 0;
+ if (prec->siml.type == CONSTANT)
+ recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
+
+ if (prec->dol.type == CONSTANT)
+ if (recGblInitConstantLink(&prec->dol, DBF_USHORT, &prec->val))
+ prec->udf = FALSE;
+
+ /* Initialize MASK if the user didn't */
+ if (prec->mask == 0)
+ prec->mask = (1 << prec->nobt) - 1;
+
+ if (pdset->init_record) {
+ status = pdset->init_record(prec);
+ if (status == 0) {
+ /* Convert initial read-back */
+ epicsUInt32 rval = prec->rval;
+
+ if (prec->shft > 0)
+ rval >>= prec->shft;
+
+ prec->val = rval;
+ prec->udf = FALSE;
+ }
+ else if (status == 2)
+ status = 0;
}
+
+ if (!prec->udf &&
+ prec->omsl == menuOmslsupervisory) {
+ /* Set initial B0 - BF from VAL */
+ epicsUInt16 val = prec->val;
+ epicsUInt8 *pBn = &prec->b0;
+ int i;
+
+ for (i = 0; i < NUM_BITS; i++) {
+ *pBn++ = !! (val & 1);
+ val >>= 1;
+ }
+ }
+
prec->mlst = prec->val;
prec->oraw = prec->rval;
prec->orbv = prec->rbv;
- return(status);
+ return status;
}
static long process(mbboDirectRecord *prec)
{
- struct mbbodset *pdset = (struct mbbodset *)(prec->dset);
- long status=0;
- unsigned char pact=prec->pact;
+ struct mbbodset *pdset = (struct mbbodset *)(prec->dset);
+ long status = 0;
+ int pact = prec->pact;
- if( (pdset==NULL) || (pdset->write_mbbo==NULL) ) {
- prec->pact=TRUE;
- recGblRecordError(S_dev_missingSup,(void *)prec,"write_mbbo");
- return(S_dev_missingSup);
+ if ((pdset == NULL) || (pdset->write_mbbo == NULL)) {
+ prec->pact = TRUE;
+ recGblRecordError(S_dev_missingSup, prec, "write_mbbo");
+ return S_dev_missingSup;
}
- if (!prec->pact) {
- if(prec->dol.type!=CONSTANT && prec->omsl==menuOmslclosed_loop){
- long status;
- unsigned short val;
+ if (!pact) {
+ if (prec->dol.type != CONSTANT &&
+ prec->omsl == menuOmslclosed_loop) {
+ epicsUInt16 val;
- status = dbGetLink(&prec->dol,DBR_USHORT,&val,0,0);
- if(status==0) {
- prec->val= val;
- prec->udf= FALSE;
- }
- else {
- recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
- goto CONTINUE;
- }
- }
- if(prec->udf) {
- recGblSetSevr(prec,UDF_ALARM,INVALID_ALARM);
- goto CONTINUE;
- }
- if(prec->nsev < INVALID_ALARM
- && prec->sevr == INVALID_ALARM
- && prec->omsl == menuOmslsupervisory) {
- /* reload value field with B0 - B15 */
- int offset = 1, i;
- unsigned char *bit = &(prec->b0);
- for (i=0; ival |= offset;
- else
- prec->val &= ~offset;
- }
- }
- /* convert val to rval */
- convert(prec);
+ if (dbGetLink(&prec->dol, DBR_USHORT, &val, 0, 0)) {
+ recGblSetSevr(prec, LINK_ALARM, INVALID_ALARM);
+ goto CONTINUE;
+ }
+ prec->val = val;
+ }
+ else if (prec->omsl == menuOmslsupervisory) {
+ epicsUInt8 *pBn = &prec->b0;
+ epicsUInt16 val = 0;
+ epicsUInt16 bit = 1;
+ int i;
+
+ /* Construct VAL from B0 - BF */
+ for (i = 0; i < NUM_BITS; i++, bit <<= 1)
+ if (*pBn++)
+ val |= bit;
+ prec->val = val;
+ }
+ else if (prec->udf) {
+ recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM);
+ goto CONTINUE;
+ }
+
+ prec->udf = FALSE;
+ /* Convert VAL to RVAL */
+ convert(prec);
}
CONTINUE:
- if (prec->nsev < INVALID_ALARM )
- status=writeValue(prec); /* write the new value */
- else
- switch (prec->ivoa) {
- case (menuIvoaContinue_normally) :
- status=writeValue(prec); /* write the new value */
- break;
- case (menuIvoaDon_t_drive_outputs) :
- break;
- case (menuIvoaSet_output_to_IVOV) :
- if (prec->pact == FALSE){
- prec->val=prec->ivov;
- convert(prec);
- }
- status=writeValue(prec); /* write the new value */
- break;
- default :
- status=-1;
- recGblRecordError(S_db_badField,(void *)prec,
- "mbboDirect: process Illegal IVOA field");
- }
+ if (prec->nsev < INVALID_ALARM)
+ status = writeValue(prec);
+ else {
+ switch (prec->ivoa) {
+ case menuIvoaSet_output_to_IVOV:
+ if (!prec->pact) {
+ prec->val = prec->ivov;
+ convert(prec);
+ }
+ /* No break, fall through... */
+ case menuIvoaContinue_normally:
+ status = writeValue(prec);
+ break;
+ case menuIvoaDon_t_drive_outputs:
+ break;
+ default:
+ status = -1;
+ recGblRecordError(S_db_badField, prec,
+ "mbboDirect: process Illegal IVOA field");
+ }
+ }
+
+ /* Done if device support set PACT */
+ if (!pact && prec->pact)
+ return 0;
- /* check if device support set pact */
- if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
-
recGblGetTimeStamp(prec);
- /* check event list */
monitor(prec);
- /* process the forward scan link record */
+
+ /* Wrap up */
recGblFwdLink(prec);
- prec->pact=FALSE;
- return(status);
+ prec->pact = FALSE;
+ return status;
}
static long special(DBADDR *paddr, int after)
{
- mbboDirectRecord *prec = (mbboDirectRecord *)(paddr->precord);
- int special_type = paddr->special, offset = 1, i;
- unsigned char *bit;
+ mbboDirectRecord *prec = (mbboDirectRecord *) paddr->precord;
- if(!after) return(0);
- switch(special_type) {
- case(SPC_MOD):
- /*
- * Set a bit in VAL corresponding to the bit changed
- * offset equals the offset in bit array. Only do
- * this if in supervisory mode.
- */
- if (prec->omsl == menuOmslclosed_loop)
- return(0);
+ if (!after)
+ return 0;
- offset = 1 << (((unsigned char *)paddr->pfield) - &(prec->b0));
-
- if (*((char *)paddr->pfield)) {
- /* set field */
- prec->val |= offset;
- }
- else {
- /* zero field */
- prec->val &= ~offset;
- }
- prec->udf = FALSE;
-
- convert(prec);
- return(0);
- case(SPC_RESET):
- /*
- * If OMSL changes from closed_loop to supervisory,
- * reload value field with B0 - B15
- */
- bit = &(prec->b0);
+ switch (paddr->special) {
+ case SPC_MOD: /* Bn field modified */
if (prec->omsl == menuOmslsupervisory) {
- for (i=0; ival |= offset;
- else
- prec->val &= ~offset;
+ /* Adjust VAL corresponding to the bit changed */
+ epicsUInt8 *pBn = (epicsUInt8 *) paddr->pfield;
+ int bit = 1 << (pBn - &prec->b0);
+
+ if (*pBn)
+ prec->val |= bit;
+ else
+ prec->val &= ~bit;
+
+ prec->udf = FALSE;
+ convert(prec);
+ }
+ break;
+
+ case SPC_RESET: /* OMSL field modified */
+ if (prec->omsl == menuOmslclosed_loop) {
+ /* Construct VAL from B0 - BF */
+ epicsUInt8 *pBn = &prec->b0;
+ epicsUInt16 val = 0, bit = 1;
+ int i;
+
+ for (i = 0; i < NUM_BITS; i++, bit <<= 1)
+ if (*pBn++)
+ val |= bit;
+ prec->val = val;
+ }
+ else if (prec->omsl == menuOmslsupervisory) {
+ /* Set B0 - BF from VAL and post monitors */
+ epicsUInt16 val = prec->val;
+ epicsUInt8 *pBn = &prec->b0;
+ int i;
+
+ for (i = 0; i < NUM_BITS; i++, pBn++, val >>= 1) {
+ epicsUInt8 oBn = *pBn;
+
+ *pBn = !! (val & 1);
+ if (oBn != *pBn)
+ db_post_events(prec, pBn, DBE_VALUE | DBE_LOG);
}
}
- prec->udf = FALSE;
+ break;
- return(0);
- default:
- recGblDbaddrError(S_db_badChoice,paddr,"mbboDirect: special");
- return(S_db_badChoice);
+ default:
+ recGblDbaddrError(S_db_badChoice, paddr, "mbboDirect: special");
+ return S_db_badChoice;
}
+
+ prec->udf = FALSE;
+ return 0;
}
static void monitor(mbboDirectRecord *prec)
{
- unsigned short monitor_mask;
+ epicsUInt16 events = recGblResetAlarms(prec);
- monitor_mask = recGblResetAlarms(prec);
+ if (prec->mlst != prec->val) {
+ events |= DBE_VALUE | DBE_LOG;
+ prec->mlst = prec->val;
+ }
+ if (events)
+ db_post_events(prec, &prec->val, events);
- /* check for value change */
- if (prec->mlst != prec->val){
- /* post events for value change and archive change */
- monitor_mask |= (DBE_VALUE | DBE_LOG);
- /* update last value monitored */
- prec->mlst = prec->val;
- }
- /* send out monitors connected to the value field */
- if (monitor_mask){
- db_post_events(prec,&prec->val,monitor_mask);
- }
- if(prec->oraw!=prec->rval) {
- db_post_events(prec,&prec->rval,
- monitor_mask|DBE_VALUE|DBE_LOG);
- prec->oraw = prec->rval;
- }
- if(prec->orbv!=prec->rbv) {
- db_post_events(prec,&prec->rbv,
- monitor_mask|DBE_VALUE|DBE_LOG);
- prec->orbv = prec->rbv;
- }
- return;
+ events |= DBE_VALUE | DBE_LOG;
+ if (prec->oraw != prec->rval) {
+ db_post_events(prec, &prec->rval, events);
+ prec->oraw = prec->rval;
+ }
+ if (prec->orbv != prec->rbv) {
+ db_post_events(prec, &prec->rbv, events);
+ prec->orbv = prec->rbv;
+ }
}
-
+
static void convert(mbboDirectRecord *prec)
{
- /* convert val to rval */
- prec->rval = (epicsUInt32)(prec->val);
- if(prec->shft>0)
- prec->rval <<= prec->shft;
+ /* Convert VAL to RVAL */
+ prec->rval = prec->val;
- return;
+ if (prec->shft > 0)
+ prec->rval <<= prec->shft;
}
static long writeValue(mbboDirectRecord *prec)
{
- long status;
- struct mbbodset *pdset = (struct mbbodset *) (prec->dset);
+ long status;
+ struct mbbodset *pdset = (struct mbbodset *) prec->dset;
- if (prec->pact == TRUE){
- status=(*pdset->write_mbbo)(prec);
- return(status);
- }
+ if (prec->pact)
+ return pdset->write_mbbo(prec);
- status=dbGetLink(&(prec->siml),
- DBR_ENUM,&(prec->simm),0,0);
- if (status)
- return(status);
+ status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0);
+ if (status)
+ return status;
- if (prec->simm == menuYesNoNO){
- status=(*pdset->write_mbbo)(prec);
- return(status);
- }
- if (prec->simm == menuYesNoYES){
- status=dbPutLink(&prec->siol,DBR_USHORT,
- &prec->val,1);
- } else {
- status=-1;
- recGblSetSevr(prec,SOFT_ALARM,INVALID_ALARM);
- return(status);
- }
- recGblSetSevr(prec,SIMM_ALARM,prec->sims);
+ switch (prec->simm) {
+ case menuYesNoNO:
+ return pdset->write_mbbo(prec);
- return(status);
+ case menuYesNoYES:
+ recGblSetSevr(prec, SIMM_ALARM, prec->sims);
+ return dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1);
+
+ default:
+ recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
+ return -1;
+ }
}