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
+ + + +
mbboDirect
+ + +

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; + } }