Move DBLINK support code into its own source file
This commit is contained in:
+3
-1
@@ -14,12 +14,13 @@ SRC_DIRS += $(IOCDIR)/db
|
||||
INC += callback.h
|
||||
INC += dbAccess.h
|
||||
INC += dbAccessDefs.h
|
||||
INC += dbCa.h
|
||||
INC += dbAddr.h
|
||||
INC += dbBkpt.h
|
||||
INC += dbCa.h
|
||||
INC += dbChannel.h
|
||||
INC += dbConvert.h
|
||||
INC += dbConvertFast.h
|
||||
INC += dbDbLink.h
|
||||
INC += dbExtractArray.h
|
||||
INC += dbEvent.h
|
||||
INC += dbLink.h
|
||||
@@ -65,6 +66,7 @@ dbCore_SRCS += dbAccess.c
|
||||
dbCore_SRCS += dbBkpt.c
|
||||
dbCore_SRCS += dbChannel.c
|
||||
dbCore_SRCS += dbConvert.c
|
||||
dbCore_SRCS += dbDbLink.c
|
||||
dbCore_SRCS += dbFastLinkConv.c
|
||||
dbCore_SRCS += dbExtractArray.c
|
||||
dbCore_SRCS += dbLink.c
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2010 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.
|
||||
\*************************************************************************/
|
||||
/* dbDbLink.c
|
||||
*
|
||||
* Original Authors: Bob Dalesio, Marty Kraimer
|
||||
* Current Author: Andrew Johnson
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alarm.h"
|
||||
#include "cantProceed.h"
|
||||
#include "cvtFast.h"
|
||||
#include "dbDefs.h"
|
||||
#include "ellLib.h"
|
||||
#include "epicsTime.h"
|
||||
#include "errlog.h"
|
||||
|
||||
#include "caeventmask.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbAddr.h"
|
||||
#include "dbBase.h"
|
||||
#include "dbBkpt.h"
|
||||
#include "dbCommon.h"
|
||||
#include "dbConvertFast.h"
|
||||
#include "dbConvert.h"
|
||||
#include "db_field_log.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "dbLink.h"
|
||||
#include "dbLockPvt.h"
|
||||
#include "dbNotify.h"
|
||||
#include "dbScan.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "devSup.h"
|
||||
#include "link.h"
|
||||
#include "recGbl.h"
|
||||
#include "recSup.h"
|
||||
#include "special.h"
|
||||
|
||||
/***************************** Database Links *****************************/
|
||||
|
||||
/* Forward definition */
|
||||
static lset dbDb_lset;
|
||||
|
||||
long dbDbInitLink(struct link *plink, short dbfType)
|
||||
{
|
||||
DBADDR dbaddr;
|
||||
long status;
|
||||
DBADDR *pdbAddr;
|
||||
|
||||
status = dbNameToAddr(plink->value.pv_link.pvname, &dbaddr);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
plink->lset = &dbDb_lset;
|
||||
plink->type = DB_LINK;
|
||||
pdbAddr = dbCalloc(1, sizeof(struct dbAddr));
|
||||
*pdbAddr = dbaddr; /* structure copy */
|
||||
plink->value.pv_link.pvt = pdbAddr;
|
||||
ellAdd(&dbaddr.precord->bklnk, &plink->value.pv_link.backlinknode);
|
||||
/* merging into the same lockset is deferred to the caller.
|
||||
* cf. initPVLinks()
|
||||
*/
|
||||
dbLockSetMerge(NULL, plink->precord, dbaddr.precord);
|
||||
assert(plink->precord->lset->plockSet == dbaddr.precord->lset->plockSet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dbDbAddLink(dbLocker *locker, struct link *plink, short dbfType, DBADDR *ptarget)
|
||||
{
|
||||
plink->lset = &dbDb_lset;
|
||||
plink->type = DB_LINK;
|
||||
plink->value.pv_link.pvt = ptarget;
|
||||
ellAdd(&ptarget->precord->bklnk, &plink->value.pv_link.backlinknode);
|
||||
|
||||
/* target record is already locked in dbPutFieldLink() */
|
||||
dbLockSetMerge(locker, plink->precord, ptarget->precord);
|
||||
}
|
||||
|
||||
static void dbDbRemoveLink(dbLocker *locker, struct link *plink)
|
||||
{
|
||||
DBADDR *pdbAddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
plink->value.pv_link.pvt = 0;
|
||||
plink->value.pv_link.getCvt = 0;
|
||||
plink->value.pv_link.pvlMask = 0;
|
||||
plink->value.pv_link.lastGetdbrType = 0;
|
||||
plink->type = PV_LINK;
|
||||
plink->lset = NULL;
|
||||
ellDelete(&pdbAddr->precord->bklnk, &plink->value.pv_link.backlinknode);
|
||||
dbLockSetSplit(locker, plink->precord, pdbAddr->precord);
|
||||
free(pdbAddr);
|
||||
}
|
||||
|
||||
static int dbDbIsConnected(const struct link *plink)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int dbDbGetDBFtype(const struct link *plink)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
|
||||
return paddr->field_type;
|
||||
}
|
||||
|
||||
static long dbDbGetElements(const struct link *plink, long *nelements)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
|
||||
*nelements = paddr->no_elements;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest)
|
||||
{
|
||||
struct pv_link *ppv_link = &plink->value.pv_link;
|
||||
DBADDR *paddr = ppv_link->pvt;
|
||||
dbCommon *precord = plink->precord;
|
||||
long status;
|
||||
|
||||
/* scan passive records if link is process passive */
|
||||
if (ppv_link->pvlMask & pvlOptPP) {
|
||||
unsigned char pact = precord->pact;
|
||||
|
||||
precord->pact = TRUE;
|
||||
status = dbScanPassive(precord, paddr->precord);
|
||||
precord->pact = pact;
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
*pstat = paddr->precord->stat;
|
||||
*psevr = paddr->precord->sevr;
|
||||
|
||||
if (ppv_link->getCvt && ppv_link->lastGetdbrType == dbrType) {
|
||||
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
|
||||
} else {
|
||||
unsigned short dbfType = paddr->field_type;
|
||||
|
||||
if (dbrType < 0 || dbrType > DBR_ENUM || dbfType > DBF_DEVICE)
|
||||
return S_db_badDbrtype;
|
||||
|
||||
if (paddr->no_elements == 1 && (!pnRequest || *pnRequest == 1)
|
||||
&& paddr->special != SPC_ATTRIBUTE) {
|
||||
ppv_link->getCvt = dbFastGetConvertRoutine[dbfType][dbrType];
|
||||
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
|
||||
} else {
|
||||
ppv_link->getCvt = NULL;
|
||||
status = dbGet(paddr, dbrType, pbuffer, NULL, pnRequest, NULL);
|
||||
}
|
||||
ppv_link->lastGetdbrType = dbrType;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static long dbDbGetControlLimits(const struct link *plink, double *low,
|
||||
double *high)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRctrlDouble
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_CTRL_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
NULL);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*low = buffer.lower_ctrl_limit;
|
||||
*high = buffer.upper_ctrl_limit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetGraphicLimits(const struct link *plink, double *low,
|
||||
double *high)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRgrDouble
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_GR_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
NULL);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*low = buffer.lower_disp_limit;
|
||||
*high = buffer.upper_disp_limit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetAlarmLimits(const struct link *plink, double *lolo,
|
||||
double *low, double *high, double *hihi)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRalDouble
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_AL_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
0);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*lolo = buffer.lower_alarm_limit;
|
||||
*low = buffer.lower_warning_limit;
|
||||
*high = buffer.upper_warning_limit;
|
||||
*hihi = buffer.upper_alarm_limit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetPrecision(const struct link *plink, short *precision)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRprecision
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_PRECISION;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
0);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*precision = (short) buffer.precision.dp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRunits
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_UNITS;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
0);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
strncpy(units, buffer.units, unitsSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
|
||||
if (status)
|
||||
*status = paddr->precord->stat;
|
||||
if (severity)
|
||||
*severity = paddr->precord->sevr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
|
||||
*pstamp = paddr->precord->time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbPutValue(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest)
|
||||
{
|
||||
struct pv_link *ppv_link = &plink->value.pv_link;
|
||||
struct dbCommon *psrce = plink->precord;
|
||||
DBADDR *paddr = (DBADDR *) ppv_link->pvt;
|
||||
dbCommon *pdest = paddr->precord;
|
||||
long status = dbPut(paddr, dbrType, pbuffer, nRequest);
|
||||
|
||||
recGblInheritSevr(ppv_link->pvlMask & pvlOptMsMode, pdest, psrce->nsta,
|
||||
psrce->nsev);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (paddr->pfield == (void *) &pdest->proc ||
|
||||
(ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
|
||||
/* if dbPutField caused asyn record to process */
|
||||
/* ask for reprocessing*/
|
||||
if (pdest->putf) {
|
||||
pdest->rpro = TRUE;
|
||||
} else { /* process dest record with source's PACT true */
|
||||
unsigned char pact;
|
||||
|
||||
if (psrce && psrce->ppn)
|
||||
dbNotifyAdd(psrce, pdest);
|
||||
pact = psrce->pact;
|
||||
psrce->pact = TRUE;
|
||||
status = dbProcess(pdest);
|
||||
psrce->pact = pact;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void dbDbScanFwdLink(struct link *plink)
|
||||
{
|
||||
dbCommon *precord = plink->precord;
|
||||
dbAddr *paddr = (dbAddr *) plink->value.pv_link.pvt;
|
||||
|
||||
dbScanPassive(precord, paddr->precord);
|
||||
}
|
||||
|
||||
static lset dbDb_lset = {
|
||||
dbDbRemoveLink,
|
||||
dbDbIsConnected,
|
||||
dbDbGetDBFtype, dbDbGetElements,
|
||||
dbDbGetValue,
|
||||
dbDbGetControlLimits, dbDbGetGraphicLimits, dbDbGetAlarmLimits,
|
||||
dbDbGetPrecision, dbDbGetUnits,
|
||||
dbDbGetAlarm, dbDbGetTimeStamp,
|
||||
dbDbPutValue,
|
||||
dbDbScanFwdLink
|
||||
};
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 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.
|
||||
\*************************************************************************/
|
||||
/* dbDbLink.h
|
||||
*
|
||||
* Created on: April 3rd, 2016
|
||||
* Author: Andrew Johnson
|
||||
*/
|
||||
|
||||
#ifndef INC_dbDbLink_H
|
||||
#define INC_dbDbLink_H
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct link;
|
||||
struct dbLocker;
|
||||
|
||||
epicsShareFunc long dbDbInitLink(struct link *plink, short dbfType);
|
||||
epicsShareFunc void dbDbAddLink(struct dbLocker *locker, struct link *plink,
|
||||
short dbfType, DBADDR *ptarget);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INC_dbDbLink_H */
|
||||
+3
-312
@@ -39,6 +39,7 @@
|
||||
#include "dbCommon.h"
|
||||
#include "dbConvertFast.h"
|
||||
#include "dbConvert.h"
|
||||
#include "dbDbLink.h"
|
||||
#include "dbEvent.h"
|
||||
#include "db_field_log.h"
|
||||
#include "dbFldTypes.h"
|
||||
@@ -56,25 +57,6 @@
|
||||
#include "recSup.h"
|
||||
#include "special.h"
|
||||
|
||||
static void inherit_severity(const struct pv_link *ppv_link, dbCommon *pdest,
|
||||
epicsEnum16 stat, epicsEnum16 sevr)
|
||||
{
|
||||
switch (ppv_link->pvlMask & pvlOptMsMode) {
|
||||
case pvlOptNMS:
|
||||
break;
|
||||
case pvlOptMSI:
|
||||
if (sevr < INVALID_ALARM)
|
||||
break;
|
||||
/* Fall through */
|
||||
case pvlOptMS:
|
||||
recGblSetSevr(pdest, LINK_ALARM, sevr);
|
||||
break;
|
||||
case pvlOptMSS:
|
||||
recGblSetSevr(pdest, stat, sevr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* How to identify links in error messages */
|
||||
static const char * link_field_name(const struct link *plink)
|
||||
{
|
||||
@@ -150,298 +132,6 @@ static lset dbConst_lset = {
|
||||
NULL
|
||||
};
|
||||
|
||||
/***************************** Database Links *****************************/
|
||||
|
||||
/* Forward definition */
|
||||
static lset dbDb_lset;
|
||||
|
||||
static long dbDbInitLink(struct link *plink, short dbfType)
|
||||
{
|
||||
DBADDR dbaddr;
|
||||
long status;
|
||||
DBADDR *pdbAddr;
|
||||
|
||||
status = dbNameToAddr(plink->value.pv_link.pvname, &dbaddr);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
plink->lset = &dbDb_lset;
|
||||
plink->type = DB_LINK;
|
||||
pdbAddr = dbCalloc(1, sizeof(struct dbAddr));
|
||||
*pdbAddr = dbaddr; /* structure copy */
|
||||
plink->value.pv_link.pvt = pdbAddr;
|
||||
ellAdd(&dbaddr.precord->bklnk, &plink->value.pv_link.backlinknode);
|
||||
/* merging into the same lockset is deferred to the caller.
|
||||
* cf. initPVLinks()
|
||||
*/
|
||||
dbLockSetMerge(NULL, plink->precord, dbaddr.precord);
|
||||
assert(plink->precord->lset->plockSet == dbaddr.precord->lset->plockSet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dbDbAddLink(dbLocker *locker, struct link *plink, short dbfType, DBADDR *ptarget)
|
||||
{
|
||||
plink->lset = &dbDb_lset;
|
||||
plink->type = DB_LINK;
|
||||
plink->value.pv_link.pvt = ptarget;
|
||||
ellAdd(&ptarget->precord->bklnk, &plink->value.pv_link.backlinknode);
|
||||
|
||||
/* target record is already locked in dbPutFieldLink() */
|
||||
dbLockSetMerge(locker, plink->precord, ptarget->precord);
|
||||
}
|
||||
|
||||
static void dbDbRemoveLink(dbLocker *locker, struct link *plink)
|
||||
{
|
||||
DBADDR *pdbAddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
plink->value.pv_link.pvt = 0;
|
||||
plink->value.pv_link.getCvt = 0;
|
||||
plink->value.pv_link.pvlMask = 0;
|
||||
plink->value.pv_link.lastGetdbrType = 0;
|
||||
plink->type = PV_LINK;
|
||||
plink->lset = NULL;
|
||||
ellDelete(&pdbAddr->precord->bklnk, &plink->value.pv_link.backlinknode);
|
||||
dbLockSetSplit(locker, plink->precord, pdbAddr->precord);
|
||||
free(pdbAddr);
|
||||
}
|
||||
|
||||
static int dbDbIsConnected(const struct link *plink)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int dbDbGetDBFtype(const struct link *plink)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
|
||||
return paddr->field_type;
|
||||
}
|
||||
|
||||
static long dbDbGetElements(const struct link *plink, long *nelements)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
|
||||
*nelements = paddr->no_elements;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest)
|
||||
{
|
||||
struct pv_link *ppv_link = &plink->value.pv_link;
|
||||
DBADDR *paddr = ppv_link->pvt;
|
||||
dbCommon *precord = plink->precord;
|
||||
long status;
|
||||
|
||||
/* scan passive records if link is process passive */
|
||||
if (ppv_link->pvlMask & pvlOptPP) {
|
||||
unsigned char pact = precord->pact;
|
||||
|
||||
precord->pact = TRUE;
|
||||
status = dbScanPassive(precord, paddr->precord);
|
||||
precord->pact = pact;
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
*pstat = paddr->precord->stat;
|
||||
*psevr = paddr->precord->sevr;
|
||||
|
||||
if (ppv_link->getCvt && ppv_link->lastGetdbrType == dbrType) {
|
||||
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
|
||||
} else {
|
||||
unsigned short dbfType = paddr->field_type;
|
||||
|
||||
if (dbrType < 0 || dbrType > DBR_ENUM || dbfType > DBF_DEVICE)
|
||||
return S_db_badDbrtype;
|
||||
|
||||
if (paddr->no_elements == 1 && (!pnRequest || *pnRequest == 1)
|
||||
&& paddr->special != SPC_ATTRIBUTE) {
|
||||
ppv_link->getCvt = dbFastGetConvertRoutine[dbfType][dbrType];
|
||||
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
|
||||
} else {
|
||||
ppv_link->getCvt = NULL;
|
||||
status = dbGet(paddr, dbrType, pbuffer, NULL, pnRequest, NULL);
|
||||
}
|
||||
ppv_link->lastGetdbrType = dbrType;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static long dbDbGetControlLimits(const struct link *plink, double *low,
|
||||
double *high)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRctrlDouble
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_CTRL_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
NULL);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*low = buffer.lower_ctrl_limit;
|
||||
*high = buffer.upper_ctrl_limit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetGraphicLimits(const struct link *plink, double *low,
|
||||
double *high)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRgrDouble
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_GR_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
NULL);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*low = buffer.lower_disp_limit;
|
||||
*high = buffer.upper_disp_limit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetAlarmLimits(const struct link *plink, double *lolo,
|
||||
double *low, double *high, double *hihi)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRalDouble
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_AL_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
0);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*lolo = buffer.lower_alarm_limit;
|
||||
*low = buffer.lower_warning_limit;
|
||||
*high = buffer.upper_warning_limit;
|
||||
*hihi = buffer.upper_alarm_limit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetPrecision(const struct link *plink, short *precision)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRprecision
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_PRECISION;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
0);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*precision = (short) buffer.precision.dp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
struct buffer {
|
||||
DBRunits
|
||||
double value;
|
||||
} buffer;
|
||||
long options = DBR_UNITS;
|
||||
long number_elements = 0;
|
||||
long status = dbGet(paddr, DBR_DOUBLE, &buffer, &options, &number_elements,
|
||||
0);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
strncpy(units, buffer.units, unitsSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
|
||||
if (status)
|
||||
*status = paddr->precord->stat;
|
||||
if (severity)
|
||||
*severity = paddr->precord->sevr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp)
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
|
||||
*pstamp = paddr->precord->time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbPutValue(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest)
|
||||
{
|
||||
struct pv_link *ppv_link = &plink->value.pv_link;
|
||||
struct dbCommon *psrce = plink->precord;
|
||||
DBADDR *paddr = (DBADDR *) ppv_link->pvt;
|
||||
dbCommon *pdest = paddr->precord;
|
||||
long status = dbPut(paddr, dbrType, pbuffer, nRequest);
|
||||
|
||||
inherit_severity(ppv_link, pdest, psrce->nsta, psrce->nsev);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (paddr->pfield == (void *) &pdest->proc ||
|
||||
(ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
|
||||
/* if dbPutField caused asyn record to process */
|
||||
/* ask for reprocessing*/
|
||||
if (pdest->putf) {
|
||||
pdest->rpro = TRUE;
|
||||
} else { /* process dest record with source's PACT true */
|
||||
unsigned char pact;
|
||||
|
||||
if (psrce && psrce->ppn)
|
||||
dbNotifyAdd(psrce, pdest);
|
||||
pact = psrce->pact;
|
||||
psrce->pact = TRUE;
|
||||
status = dbProcess(pdest);
|
||||
psrce->pact = pact;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void dbDbScanFwdLink(struct link *plink)
|
||||
{
|
||||
dbCommon *precord = plink->precord;
|
||||
dbAddr *paddr = (dbAddr *) plink->value.pv_link.pvt;
|
||||
|
||||
dbScanPassive(precord, paddr->precord);
|
||||
}
|
||||
|
||||
static lset dbDb_lset = {
|
||||
dbDbRemoveLink,
|
||||
dbDbIsConnected,
|
||||
dbDbGetDBFtype, dbDbGetElements,
|
||||
dbDbGetValue,
|
||||
dbDbGetControlLimits, dbDbGetGraphicLimits, dbDbGetAlarmLimits,
|
||||
dbDbGetPrecision, dbDbGetUnits,
|
||||
dbDbGetAlarm, dbDbGetTimeStamp,
|
||||
dbDbPutValue,
|
||||
dbDbScanFwdLink
|
||||
};
|
||||
|
||||
/***************************** Generic Link API *****************************/
|
||||
|
||||
void dbInitLink(struct link *plink, short dbfType)
|
||||
@@ -587,7 +277,8 @@ long dbGetLink(struct link *plink, short dbrType, void *pbuffer,
|
||||
if (status) {
|
||||
recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
|
||||
} else {
|
||||
inherit_severity(&plink->value.pv_link, precord, stat, sevr);
|
||||
recGblInheritSevr(plink->value.pv_link.pvlMask & pvlOptMsMode, precord,
|
||||
stat, sevr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
+22
-1
@@ -17,6 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "alarm.h"
|
||||
#include "dbDefs.h"
|
||||
#include "epicsMath.h"
|
||||
#include "epicsPrint.h"
|
||||
@@ -214,7 +215,27 @@ int recGblSetSevr(void *precord, epicsEnum16 new_stat, epicsEnum16 new_sevr)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat,
|
||||
epicsEnum16 sevr)
|
||||
{
|
||||
switch (msMode) {
|
||||
case pvlOptNMS:
|
||||
break;
|
||||
case pvlOptMSI:
|
||||
if (sevr < INVALID_ALARM)
|
||||
break;
|
||||
/* Fall through */
|
||||
case pvlOptMS:
|
||||
recGblSetSevr(precord, LINK_ALARM, sevr);
|
||||
break;
|
||||
case pvlOptMSS:
|
||||
recGblSetSevr(precord, stat, sevr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void recGblFwdLink(void *precord)
|
||||
{
|
||||
dbCommon *pdbc = precord;
|
||||
|
||||
@@ -59,6 +59,8 @@ epicsShareFunc int recGblInitConstantLink(struct link *plink,
|
||||
epicsShareFunc unsigned short recGblResetAlarms(void *precord);
|
||||
epicsShareFunc int recGblSetSevr(void *precord, epicsEnum16 new_stat,
|
||||
epicsEnum16 new_sevr);
|
||||
epicsShareFunc void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat,
|
||||
epicsEnum16 sevr);
|
||||
epicsShareFunc void recGblFwdLink(void *precord);
|
||||
epicsShareFunc void recGblGetTimeStamp(void *precord);
|
||||
epicsShareFunc void recGblTSELwasModified(struct link *plink);
|
||||
|
||||
Reference in New Issue
Block a user