Refactor link handling code (incomplete).
* Moved routines into dbLink.h and dbLink.c * Created separate routines for DB_LINK processing * Added dbinitLink() and dbAddLink() * Started a Link Support Entry Table, not used yet * Everything should still work as before...
This commit is contained in:
@@ -21,6 +21,7 @@ INC += dbChannel.h
|
||||
INC += dbConvert.h
|
||||
INC += dbConvertFast.h
|
||||
INC += dbEvent.h
|
||||
INC += dbLink.h
|
||||
INC += dbLock.h
|
||||
INC += dbNotify.h
|
||||
INC += dbScan.h
|
||||
@@ -57,6 +58,7 @@ dbCore_SRCS += dbBkpt.c
|
||||
dbCore_SRCS += dbChannel.c
|
||||
dbCore_SRCS += dbConvert.c
|
||||
dbCore_SRCS += dbFastLinkConv.c
|
||||
dbCore_SRCS += dbLink.c
|
||||
dbCore_SRCS += dbNotify.c
|
||||
dbCore_SRCS += dbScan.c
|
||||
dbCore_SRCS += dbEvent.c
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "dbAddr.h"
|
||||
#include "callback.h"
|
||||
#include "dbScan.h"
|
||||
#include "dbLink.h"
|
||||
#include "dbLock.h"
|
||||
#include "dbEvent.h"
|
||||
#include "dbConvert.h"
|
||||
@@ -90,17 +91,6 @@ static short mapDBFToDBR[DBF_NTYPES] = {
|
||||
/* The following is to handle SPC_AS */
|
||||
static SPC_ASCALLBACK spcAsCallback = 0;
|
||||
|
||||
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;
|
||||
case pvlOptMS: recGblSetSevr(pdest,LINK_ALARM,sevr); break;
|
||||
case pvlOptMSS: recGblSetSevr(pdest,stat,sevr); break;
|
||||
}
|
||||
}
|
||||
|
||||
void epicsShareAPI dbSpcAsRegisterCallback(SPC_ASCALLBACK func)
|
||||
{
|
||||
spcAsCallback = func;
|
||||
@@ -420,10 +410,10 @@ long epicsShareAPI dbPutAttribute(
|
||||
|
||||
int epicsShareAPI dbIsValueField(const struct dbFldDes *pdbFldDes)
|
||||
{
|
||||
if(pdbFldDes->pdbRecordType->indvalFlddes == pdbFldDes->indRecordType)
|
||||
return(TRUE);
|
||||
if (pdbFldDes->pdbRecordType->indvalFlddes == pdbFldDes->indRecordType)
|
||||
return TRUE;
|
||||
else
|
||||
return(FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int epicsShareAPI dbGetFieldIndex(const struct dbAddr *paddr)
|
||||
@@ -431,50 +421,6 @@ int epicsShareAPI dbGetFieldIndex(const struct dbAddr *paddr)
|
||||
return paddr->pfldDes->indRecordType;
|
||||
}
|
||||
|
||||
long epicsShareAPI dbGetNelements(const struct link *plink,long *nelements)
|
||||
{
|
||||
switch(plink->type) {
|
||||
case CONSTANT:
|
||||
*nelements = 0;
|
||||
return(0);
|
||||
case DB_LINK: {
|
||||
DBADDR *paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
*nelements = paddr->no_elements;
|
||||
return(0);
|
||||
}
|
||||
case CA_LINK:
|
||||
return(dbCaGetNelements(plink,nelements));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return(S_db_badField);
|
||||
}
|
||||
|
||||
int epicsShareAPI dbIsLinkConnected(const struct link *plink)
|
||||
{
|
||||
switch(plink->type) {
|
||||
case DB_LINK: return(TRUE);
|
||||
case CA_LINK: return(dbCaIsLinkConnected(plink));
|
||||
default: break;
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
int epicsShareAPI dbGetLinkDBFtype(const struct link *plink)
|
||||
{
|
||||
switch(plink->type) {
|
||||
case DB_LINK:
|
||||
{
|
||||
DBADDR *paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
|
||||
return((int)paddr->field_type);
|
||||
}
|
||||
case CA_LINK: return(dbCaGetLinkDBFtype(plink));
|
||||
default: break;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a record if its scan field is passive.
|
||||
* Will notify if processing is complete by callback.
|
||||
@@ -482,48 +428,13 @@ int epicsShareAPI dbGetLinkDBFtype(const struct link *plink)
|
||||
*/
|
||||
long epicsShareAPI dbScanPassive(dbCommon *pfrom, dbCommon *pto)
|
||||
{
|
||||
long status;
|
||||
|
||||
/* if not passive just return success */
|
||||
if(pto->scan != 0) return(0);
|
||||
if (pto->scan != 0)
|
||||
return 0;
|
||||
|
||||
if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto);
|
||||
status = dbProcess(pto);
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*KLUDGE: Following needed so that dbPutLink to PROC field works correctly*/
|
||||
long epicsShareAPI dbScanLink(dbCommon *pfrom, dbCommon *pto)
|
||||
{
|
||||
long status;
|
||||
unsigned char pact;
|
||||
|
||||
if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto);
|
||||
pact = pfrom->pact;
|
||||
pfrom->pact = TRUE;
|
||||
status = dbProcess(pto);
|
||||
pfrom->pact = pact;
|
||||
return(status);
|
||||
}
|
||||
|
||||
void epicsShareAPI dbScanFwdLink(struct link *plink)
|
||||
{
|
||||
dbCommon *precord;
|
||||
struct pv_link *pvlink;
|
||||
short fwdLinkValue;
|
||||
|
||||
if(plink->type!=DB_LINK && plink->type!=CA_LINK) return;
|
||||
pvlink = &plink->value.pv_link;
|
||||
precord = pvlink->precord;
|
||||
if(plink->type==DB_LINK) {
|
||||
dbAddr *paddr = (dbAddr *)plink->value.pv_link.pvt;
|
||||
dbScanPassive(precord,paddr->precord);
|
||||
return;
|
||||
}
|
||||
if(!(pvlink->pvlMask & pvlOptFWD)) return;
|
||||
fwdLinkValue = 1;
|
||||
dbCaPutLink(plink,DBR_SHORT,&fwdLinkValue,1);
|
||||
return;
|
||||
if (pfrom && pfrom->ppn)
|
||||
dbNotifyAdd(pfrom,pto);
|
||||
return dbProcess(pto);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -537,119 +448,125 @@ void epicsShareAPI dbScanFwdLink(struct link *plink)
|
||||
*/
|
||||
long epicsShareAPI dbProcess(dbCommon *precord)
|
||||
{
|
||||
struct rset *prset = precord->rset;
|
||||
dbRecordType *pdbRecordType = precord->rdes;
|
||||
unsigned char tpro=precord->tpro;
|
||||
long status = 0;
|
||||
int *ptrace;
|
||||
int set_trace=FALSE;
|
||||
dbFldDes *pdbFldDes;
|
||||
int callNotifyCompletion = FALSE;
|
||||
struct rset *prset = precord->rset;
|
||||
dbRecordType *pdbRecordType = precord->rdes;
|
||||
unsigned char tpro = precord->tpro;
|
||||
long status = 0;
|
||||
int *ptrace;
|
||||
int set_trace = FALSE;
|
||||
dbFldDes *pdbFldDes;
|
||||
int callNotifyCompletion = FALSE;
|
||||
|
||||
ptrace = dbLockSetAddrTrace(precord);
|
||||
ptrace = dbLockSetAddrTrace(precord);
|
||||
/*
|
||||
* Note that it is likely that if any changes are made
|
||||
* to dbProcess() corresponding changes will have to
|
||||
* be made in the breakpoint handler.
|
||||
*/
|
||||
|
||||
/* see if there are any stopped records or breakpoints */
|
||||
if (lset_stack_count != 0) {
|
||||
/*
|
||||
* Note that it is likely that if any changes are made
|
||||
* to dbProcess() corresponding changes will have to
|
||||
* be made in the breakpoint handler.
|
||||
* Check to see if the record should be processed
|
||||
* and activate breakpoint accordingly. If this
|
||||
* function call returns non-zero, skip record
|
||||
* support and fall out of dbProcess(). This is
|
||||
* done so that a dbContTask() can be spawned to
|
||||
* take over record processing for the lock set
|
||||
* containing a breakpoint.
|
||||
*/
|
||||
if (dbBkpt(precord))
|
||||
goto all_done;
|
||||
}
|
||||
|
||||
/* see if there are any stopped records or breakpoints */
|
||||
if (lset_stack_count != 0) {
|
||||
/*
|
||||
* Check to see if the record should be processed
|
||||
* and activate breakpoint accordingly. If this
|
||||
* function call returns non-zero, skip record
|
||||
* support and fall out of dbProcess(). This is
|
||||
* done so that a dbContTask() can be spawned to
|
||||
* take over record processing for the lock set
|
||||
* containing a breakpoint.
|
||||
*/
|
||||
if (dbBkpt(precord))
|
||||
goto all_done;
|
||||
/* check for trace processing*/
|
||||
if (tpro) {
|
||||
if(*ptrace==0) {
|
||||
*ptrace = 1;
|
||||
set_trace = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for trace processing*/
|
||||
if (tpro) {
|
||||
if(*ptrace==0) {
|
||||
*ptrace = 1;
|
||||
set_trace = TRUE;
|
||||
}
|
||||
}
|
||||
/* If already active dont process */
|
||||
if (precord->pact) {
|
||||
unsigned short monitor_mask;
|
||||
|
||||
/* If already active dont process */
|
||||
if (precord->pact) {
|
||||
unsigned short monitor_mask;
|
||||
if (*ptrace)
|
||||
printf("%s: Active %s\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
/* raise scan alarm after MAX_LOCK times */
|
||||
if (precord->stat==SCAN_ALARM) goto all_done;
|
||||
if (precord->lcnt++ !=MAX_LOCK) goto all_done;
|
||||
if (precord->sevr>=INVALID_ALARM) goto all_done;
|
||||
recGblSetSevr(precord, SCAN_ALARM, INVALID_ALARM);
|
||||
monitor_mask = recGblResetAlarms(precord);
|
||||
monitor_mask |= DBE_VALUE|DBE_LOG;
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
|
||||
db_post_events(precord,
|
||||
(void *)(((char *)precord) + pdbFldDes->offset),
|
||||
monitor_mask);
|
||||
goto all_done;
|
||||
}
|
||||
else precord->lcnt = 0;
|
||||
|
||||
if (*ptrace) printf("%s: Active %s\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
/* raise scan alarm after MAX_LOCK times */
|
||||
if (precord->stat==SCAN_ALARM) goto all_done;
|
||||
if (precord->lcnt++ !=MAX_LOCK) goto all_done;
|
||||
if (precord->sevr>=INVALID_ALARM) goto all_done;
|
||||
recGblSetSevr(precord, SCAN_ALARM, INVALID_ALARM);
|
||||
monitor_mask = recGblResetAlarms(precord);
|
||||
monitor_mask |= DBE_VALUE|DBE_LOG;
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
|
||||
db_post_events(precord,
|
||||
(void *)(((char *)precord) + pdbFldDes->offset),
|
||||
monitor_mask);
|
||||
goto all_done;
|
||||
}
|
||||
else precord->lcnt = 0;
|
||||
/*
|
||||
* Check the record disable link. A record will not be
|
||||
* processed if the value retrieved through this link
|
||||
* is equal to constant set in the record's disv field.
|
||||
*/
|
||||
status = dbGetLink(&precord->sdis, DBR_SHORT, &precord->disa, 0, 0);
|
||||
|
||||
/*
|
||||
* Check the record disable link. A record will not be
|
||||
* processed if the value retrieved through this link
|
||||
* is equal to constant set in the record's disv field.
|
||||
*/
|
||||
status = dbGetLink(&(precord->sdis),DBR_SHORT,&(precord->disa),0,0);
|
||||
/* if disabled check disable alarm severity and return success */
|
||||
if (precord->disa == precord->disv) {
|
||||
if(*ptrace)
|
||||
printf("%s: Disabled %s\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
|
||||
/* if disabled check disable alarm severity and return success */
|
||||
if (precord->disa == precord->disv) {
|
||||
if(*ptrace) printf("%s: Disabled %s\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
/*take care of caching and notifyCompletion*/
|
||||
precord->rpro = FALSE;
|
||||
precord->putf = FALSE;
|
||||
callNotifyCompletion = TRUE;
|
||||
/* raise disable alarm */
|
||||
if (precord->stat==DISABLE_ALARM) goto all_done;
|
||||
precord->sevr = precord->diss;
|
||||
precord->stat = DISABLE_ALARM;
|
||||
precord->nsev = 0;
|
||||
precord->nsta = 0;
|
||||
db_post_events(precord, &precord->stat, DBE_VALUE);
|
||||
db_post_events(precord, &precord->sevr, DBE_VALUE);
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
|
||||
db_post_events(precord,
|
||||
(void *)(((char *)precord) + pdbFldDes->offset),
|
||||
DBE_VALUE|DBE_ALARM);
|
||||
goto all_done;
|
||||
}
|
||||
/*take care of caching and notifyCompletion*/
|
||||
precord->rpro = FALSE;
|
||||
precord->putf = FALSE;
|
||||
callNotifyCompletion = TRUE;
|
||||
|
||||
/* locate record processing routine */
|
||||
/* put this in iocInit() !!! */
|
||||
if (!(prset=precord->rset) || !(prset->process)) {
|
||||
callNotifyCompletion = TRUE;
|
||||
precord->pact=1;/*set pact TRUE so error is issued only once*/
|
||||
recGblRecordError(S_db_noRSET, (void *)precord, "dbProcess");
|
||||
status = S_db_noRSET;
|
||||
if (*ptrace) printf("%s: No RSET for %s\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
goto all_done;
|
||||
}
|
||||
if(*ptrace) printf("%s: Process %s\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
/* process record */
|
||||
status = (*prset->process)(precord);
|
||||
/* Print record's fields if PRINT_MASK set in breakpoint field */
|
||||
if (lset_stack_count != 0) {
|
||||
dbPrint(precord);
|
||||
}
|
||||
/* raise disable alarm */
|
||||
if (precord->stat==DISABLE_ALARM) goto all_done;
|
||||
precord->sevr = precord->diss;
|
||||
precord->stat = DISABLE_ALARM;
|
||||
precord->nsev = 0;
|
||||
precord->nsta = 0;
|
||||
db_post_events(precord, &precord->stat, DBE_VALUE);
|
||||
db_post_events(precord, &precord->sevr, DBE_VALUE);
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
|
||||
db_post_events(precord,
|
||||
(void *)(((char *)precord) + pdbFldDes->offset),
|
||||
DBE_VALUE|DBE_ALARM);
|
||||
goto all_done;
|
||||
}
|
||||
|
||||
/* locate record processing routine */
|
||||
/* FIXME: put this in iocInit() !!! */
|
||||
if (!(prset=precord->rset) || !(prset->process)) {
|
||||
callNotifyCompletion = TRUE;
|
||||
precord->pact=1;/*set pact TRUE so error is issued only once*/
|
||||
recGblRecordError(S_db_noRSET, (void *)precord, "dbProcess");
|
||||
status = S_db_noRSET;
|
||||
if (*ptrace)
|
||||
printf("%s: No RSET for %s\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
goto all_done;
|
||||
}
|
||||
if(*ptrace)
|
||||
printf("%s: Process %s\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
/* process record */
|
||||
status = (*prset->process)(precord);
|
||||
/* Print record's fields if PRINT_MASK set in breakpoint field */
|
||||
if (lset_stack_count != 0) {
|
||||
dbPrint(precord);
|
||||
}
|
||||
all_done:
|
||||
if (set_trace) *ptrace = 0;
|
||||
if(callNotifyCompletion && precord->ppn) dbNotifyCompletion(precord);
|
||||
return(status);
|
||||
if (set_trace) *ptrace = 0;
|
||||
if(callNotifyCompletion && precord->ppn) dbNotifyCompletion(precord);
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -776,121 +693,6 @@ int epicsShareAPI dbLoadRecords(const char* file, const char* subs)
|
||||
}
|
||||
|
||||
|
||||
long epicsShareAPI dbGetLinkValue(struct link *plink, short dbrType,
|
||||
void *pbuffer, long *poptions, long *pnRequest)
|
||||
{
|
||||
long status = 0;
|
||||
|
||||
if (plink->type == CONSTANT) {
|
||||
if (poptions) *poptions = 0;
|
||||
if (pnRequest) *pnRequest = 0;
|
||||
} else if (plink->type == DB_LINK) {
|
||||
struct pv_link *ppv_link = &(plink->value.pv_link);
|
||||
DBADDR *paddr = ppv_link->pvt;
|
||||
dbCommon *precord = plink->value.pv_link.precord;
|
||||
|
||||
/* scan passive records with links that are process passive */
|
||||
if (ppv_link->pvlMask&pvlOptPP) {
|
||||
dbCommon *pfrom = paddr->precord;
|
||||
unsigned char pact;
|
||||
|
||||
pact = precord->pact;
|
||||
precord->pact = TRUE;
|
||||
status = dbScanPassive(precord,pfrom);
|
||||
precord->pact = pact;
|
||||
if (status) return status;
|
||||
}
|
||||
if(precord!= paddr->precord) {
|
||||
inherit_severity(ppv_link,precord,paddr->precord->stat,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;
|
||||
long no_elements = paddr->no_elements;
|
||||
|
||||
if (dbrType < 0 || dbrType > DBR_ENUM ||
|
||||
dbfType > DBF_DEVICE) {
|
||||
status = S_db_badDbrtype;
|
||||
recGblRecordError(status, precord, "GetLinkValue Failed");
|
||||
recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
|
||||
return status;
|
||||
}
|
||||
/* attempt to make a fast link */
|
||||
if ((!poptions || *poptions == 0) &&
|
||||
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 = 0;
|
||||
status = dbGet(paddr, dbrType, pbuffer, poptions, pnRequest, NULL);
|
||||
}
|
||||
}
|
||||
ppv_link->lastGetdbrType = dbrType;
|
||||
if (status) {
|
||||
recGblRecordError(status, precord, "dbGetLinkValue");
|
||||
recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
|
||||
}
|
||||
} else if (plink->type == CA_LINK) {
|
||||
struct dbCommon *precord = plink->value.pv_link.precord;
|
||||
const struct pv_link *pcalink = &plink->value.pv_link;
|
||||
epicsEnum16 sevr, stat;
|
||||
|
||||
status=dbCaGetLink(plink,dbrType,pbuffer,&stat,&sevr,pnRequest);
|
||||
if (status) {
|
||||
recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
|
||||
} else {
|
||||
inherit_severity(pcalink,precord,stat,sevr);
|
||||
}
|
||||
if (poptions) *poptions = 0;
|
||||
} else {
|
||||
cantProceed("dbGetLinkValue: Illegal link type");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
long epicsShareAPI dbPutLinkValue(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest)
|
||||
{
|
||||
long status = 0;
|
||||
|
||||
if (plink->type == DB_LINK) {
|
||||
struct dbCommon *psource = plink->value.pv_link.precord;
|
||||
struct pv_link *ppv_link = &plink->value.pv_link;
|
||||
DBADDR *paddr = (DBADDR *)ppv_link->pvt;
|
||||
dbCommon *pdest = paddr->precord;
|
||||
|
||||
status = dbPut(paddr, dbrType, pbuffer, nRequest);
|
||||
inherit_severity(ppv_link,pdest,psource->nsta,psource->nsev);
|
||||
if (status) return status;
|
||||
|
||||
if (paddr->pfield == &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 { /* otherwise ask for the record to be processed*/
|
||||
status = dbScanLink(psource, pdest);
|
||||
}
|
||||
}
|
||||
if (status)
|
||||
recGblSetSevr(psource, LINK_ALARM, INVALID_ALARM);
|
||||
} else if (plink->type == CA_LINK) {
|
||||
struct dbCommon *psource = plink->value.pv_link.precord;
|
||||
|
||||
status = dbCaPutLink(plink, dbrType, pbuffer, nRequest);
|
||||
if (status < 0)
|
||||
recGblSetSevr(psource, LINK_ALARM, INVALID_ALARM);
|
||||
} else {
|
||||
cantProceed("dbPutLinkValue: Illegal link type");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static long getLinkValue(DBADDR *paddr, short dbrType,
|
||||
char *pbuf, long *nRequest)
|
||||
{
|
||||
@@ -1076,10 +878,9 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
dbCommon *precord = paddr->precord;
|
||||
dbFldDes *pfldDes = paddr->pfldDes;
|
||||
long special = paddr->special;
|
||||
DBLINK *plink = (DBLINK *)paddr->pfield;
|
||||
struct link *plink = (struct link *)paddr->pfield;
|
||||
const char *pstring = (const char *)pbuffer;
|
||||
DBENTRY dbEntry;
|
||||
DBADDR dbaddr;
|
||||
struct dsxt *old_dsxt = NULL;
|
||||
struct dset *new_dset = NULL;
|
||||
struct dsxt *new_dsxt = NULL;
|
||||
@@ -1150,21 +951,8 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
|
||||
switch (plink->type) { /* Old link type */
|
||||
case DB_LINK:
|
||||
free(plink->value.pv_link.pvt);
|
||||
plink->value.pv_link.pvt = 0;
|
||||
plink->type = PV_LINK;
|
||||
plink->value.pv_link.getCvt = 0;
|
||||
plink->value.pv_link.pvlMask = 0;
|
||||
plink->value.pv_link.lastGetdbrType = 0;
|
||||
dbLockSetSplit(precord);
|
||||
break;
|
||||
|
||||
case CA_LINK:
|
||||
dbCaRemoveLink(plink);
|
||||
plink->type = PV_LINK;
|
||||
plink->value.pv_link.getCvt = 0;
|
||||
plink->value.pv_link.pvlMask = 0;
|
||||
plink->value.pv_link.lastGetdbrType = 0;
|
||||
dbRemoveLink(plink);
|
||||
break;
|
||||
|
||||
case CONSTANT:
|
||||
@@ -1211,35 +999,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
|
||||
switch (plink->type) { /* New link type */
|
||||
case PV_LINK:
|
||||
if (plink == &precord->tsel)
|
||||
recGblTSELwasModified(plink);
|
||||
plink->value.pv_link.precord = precord;
|
||||
|
||||
if (!(plink->value.pv_link.pvlMask & (pvlOptCA|pvlOptCP|pvlOptCPP)) &&
|
||||
(dbNameToAddr(plink->value.pv_link.pvname, &dbaddr) == 0)) {
|
||||
/* It's a DB link */
|
||||
DBADDR *pdbAddr;
|
||||
|
||||
plink->type = DB_LINK;
|
||||
pdbAddr = dbMalloc(sizeof(struct dbAddr));
|
||||
*pdbAddr = dbaddr; /* NB: structure copy */;
|
||||
plink->value.pv_link.pvt = pdbAddr;
|
||||
dbLockSetRecordLock(pdbAddr->precord);
|
||||
dbLockSetMerge(precord, pdbAddr->precord);
|
||||
} else { /* Make it a CA link */
|
||||
char *pperiod;
|
||||
|
||||
plink->type = CA_LINK;
|
||||
if (pfldDes->field_type == DBF_INLINK) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
}
|
||||
dbCaAddLink(plink);
|
||||
if (pfldDes->field_type == DBF_FWDLINK) {
|
||||
pperiod = strrchr(plink->value.pv_link.pvname, '.');
|
||||
if (pperiod && strstr(pperiod, "PROC"))
|
||||
plink->value.pv_link.pvlMask |= pvlOptFWD;
|
||||
}
|
||||
}
|
||||
dbAddLink(precord, plink, pfldDes->field_type);
|
||||
break;
|
||||
|
||||
case CONSTANT:
|
||||
@@ -1267,7 +1027,7 @@ restoreScan:
|
||||
}
|
||||
postScanEvent:
|
||||
if (scan != precord->scan)
|
||||
db_post_events(precord, &precord->scan, DBE_VALUE|DBE_LOG);
|
||||
db_post_events(precord, &precord->scan, DBE_VALUE | DBE_LOG);
|
||||
unlock:
|
||||
dbLockSetGblUnlock();
|
||||
finish:
|
||||
@@ -1424,139 +1184,3 @@ long epicsShareAPI dbPut(DBADDR *paddr, short dbrType,
|
||||
return status;
|
||||
}
|
||||
|
||||
/* various utility routines */
|
||||
long epicsShareAPI dbGetControlLimits(
|
||||
const struct link *plink,double *low, double *high)
|
||||
{
|
||||
struct buffer {
|
||||
DBRctrlDouble
|
||||
double value;
|
||||
} buffer;
|
||||
DBADDR *paddr;
|
||||
long options = DBR_CTRL_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status;
|
||||
|
||||
if(plink->type == CA_LINK) return(dbCaGetControlLimits(plink,low,high));
|
||||
if(plink->type !=DB_LINK) return(S_db_notFound);
|
||||
paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
|
||||
if(status) return(status);
|
||||
*low = buffer.lower_ctrl_limit;
|
||||
*high = buffer.upper_ctrl_limit;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbGetGraphicLimits(
|
||||
const struct link *plink,double *low, double *high)
|
||||
{
|
||||
struct buffer {
|
||||
DBRgrDouble
|
||||
double value;
|
||||
} buffer;
|
||||
DBADDR *paddr;
|
||||
long options = DBR_GR_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status;
|
||||
|
||||
if(plink->type == CA_LINK) return(dbCaGetGraphicLimits(plink,low,high));
|
||||
if(plink->type !=DB_LINK) return(S_db_notFound);
|
||||
paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
|
||||
if(status) return(status);
|
||||
*low = buffer.lower_disp_limit;
|
||||
*high = buffer.upper_disp_limit;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbGetAlarmLimits(const struct link *plink,
|
||||
double *lolo, double *low, double *high, double *hihi)
|
||||
{
|
||||
struct buffer {
|
||||
DBRalDouble
|
||||
double value;
|
||||
} buffer;
|
||||
DBADDR *paddr;
|
||||
long options = DBR_AL_DOUBLE;
|
||||
long number_elements = 0;
|
||||
long status;
|
||||
|
||||
if(plink->type == CA_LINK)
|
||||
return(dbCaGetAlarmLimits(plink,lolo,low,high,hihi));
|
||||
if(plink->type !=DB_LINK) return(S_db_notFound);
|
||||
paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
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);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbGetPrecision(const struct link *plink,short *precision)
|
||||
{
|
||||
struct buffer {
|
||||
DBRprecision
|
||||
double value;
|
||||
} buffer;
|
||||
DBADDR *paddr;
|
||||
long options = DBR_PRECISION;
|
||||
long number_elements = 0;
|
||||
long status;
|
||||
|
||||
if(plink->type == CA_LINK) return(dbCaGetPrecision(plink,precision));
|
||||
if(plink->type !=DB_LINK) return(S_db_notFound);
|
||||
paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
|
||||
if(status) return(status);
|
||||
*precision = buffer.precision.dp;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbGetUnits(
|
||||
const struct link *plink,char *units,int unitsSize)
|
||||
{
|
||||
struct buffer {
|
||||
DBRunits
|
||||
double value;
|
||||
} buffer;
|
||||
DBADDR *paddr;
|
||||
long options = DBR_UNITS;
|
||||
long number_elements = 0;
|
||||
long status;
|
||||
|
||||
if(plink->type == CA_LINK) return(dbCaGetUnits(plink,units,unitsSize));
|
||||
if(plink->type !=DB_LINK) return(S_db_notFound);
|
||||
paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
|
||||
if(status) return(status);
|
||||
strncpy(units,buffer.units,unitsSize);
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbGetAlarm(const struct link *plink,
|
||||
epicsEnum16 *status,epicsEnum16 *severity)
|
||||
{
|
||||
DBADDR *paddr;
|
||||
|
||||
if(plink->type == CA_LINK) return(dbCaGetAlarm(plink,status,severity));
|
||||
if(plink->type !=DB_LINK) return(S_db_notFound);
|
||||
paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
if (status) *status = paddr->precord->stat;
|
||||
if (severity) *severity = paddr->precord->sevr;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbGetTimeStamp(const struct link *plink,epicsTimeStamp *pstamp)
|
||||
{
|
||||
DBADDR *paddr;
|
||||
|
||||
if (plink->type == CA_LINK)
|
||||
return dbCaGetTimeStamp(plink,pstamp);
|
||||
if (plink->type != DB_LINK)
|
||||
return S_db_notFound;
|
||||
paddr = (DBADDR *)plink->value.pv_link.pvt;
|
||||
*pstamp = paddr->precord->time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* 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
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* dbAccess.h */
|
||||
@@ -22,6 +21,7 @@
|
||||
#include "dbAddr.h"
|
||||
#include "dbLock.h"
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbLink.h"
|
||||
#include "dbCa.h"
|
||||
#include "dbCommon.h"
|
||||
#include "db_field_log.h"
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* 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
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* dbAccessDefs.h */
|
||||
@@ -199,76 +198,30 @@ struct dbr_alDouble {DBRalDouble};
|
||||
#define S_db_cntCont (M_dbAccess|65) /*Cannot resume dbContTask*/
|
||||
#define S_db_noMemory (M_dbAccess|66) /*unable to allocate data structure from pool*/
|
||||
|
||||
/* Global Database Access Routines*/
|
||||
#define dbGetLink(PLNK, DBRTYPE, PBUFFER, OPTIONS, NREQUEST) \
|
||||
( ( ( (PLNK)->type == CONSTANT ) && \
|
||||
( (NREQUEST) == 0) &&\
|
||||
( (OPTIONS) == 0) ) \
|
||||
? 0 \
|
||||
: dbGetLinkValue((PLNK),(DBRTYPE), \
|
||||
(void *)(PBUFFER), (OPTIONS), (NREQUEST) ) )
|
||||
#define dbPutLink(PLNK, DBRTYPE, PBUFFER, NREQUEST) \
|
||||
( ( (PLNK)->type == CONSTANT) \
|
||||
? 0 \
|
||||
: dbPutLinkValue( (PLNK), (DBRTYPE), (void *)(PBUFFER), (NREQUEST) ) )
|
||||
#define dbGetPdbAddrFromLink(PLNK) \
|
||||
( ( (PLNK)->type != DB_LINK ) \
|
||||
? 0 \
|
||||
: ( ( (struct dbAddr *)( (PLNK)->value.pv_link.pvt) ) ) )
|
||||
#define dbGetSevr(PLINK,PSEVERITY) \
|
||||
dbGetAlarm((PLINK),NULL,(PSEVERITY))
|
||||
|
||||
epicsShareFunc long epicsShareAPI dbPutSpecial(struct dbAddr *paddr,int pass);
|
||||
epicsShareFunc struct rset * epicsShareAPI dbGetRset(const struct dbAddr *paddr);
|
||||
epicsShareFunc long epicsShareAPI dbPutAttribute(
|
||||
const char *recordTypename,const char *name,const char*value);
|
||||
epicsShareFunc int epicsShareAPI dbIsValueField(const struct dbFldDes *pdbFldDes);
|
||||
epicsShareFunc int epicsShareAPI dbGetFieldIndex(const struct dbAddr *paddr);
|
||||
epicsShareFunc long epicsShareAPI dbGetNelements(
|
||||
const struct link *plink,long *nelements);
|
||||
epicsShareFunc int epicsShareAPI dbIsLinkConnected(const struct link *plink);
|
||||
epicsShareFunc int epicsShareAPI dbGetLinkDBFtype(const struct link *plink);
|
||||
epicsShareFunc long epicsShareAPI dbScanLink(
|
||||
struct dbCommon *pfrom, struct dbCommon *pto);
|
||||
epicsShareFunc long epicsShareAPI dbScanPassive(
|
||||
struct dbCommon *pfrom,struct dbCommon *pto);
|
||||
epicsShareFunc void epicsShareAPI dbScanFwdLink(struct link *plink);
|
||||
epicsShareFunc long epicsShareAPI dbProcess(struct dbCommon *precord);
|
||||
epicsShareFunc long epicsShareAPI dbNameToAddr(
|
||||
const char *pname,struct dbAddr *);
|
||||
epicsShareFunc devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *prdes, int dtyp);
|
||||
epicsShareFunc devSup* epicsShareAPI dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset);
|
||||
epicsShareFunc long epicsShareAPI dbGetLinkValue(
|
||||
struct link *,short dbrType,void *pbuffer,long *options,long *nRequest);
|
||||
epicsShareFunc long epicsShareAPI dbGetField(
|
||||
struct dbAddr *,short dbrType,void *pbuffer,long *options,
|
||||
long *nRequest,void *pfl);
|
||||
epicsShareFunc long epicsShareAPI dbGet(
|
||||
struct dbAddr *,short dbrType,void *pbuffer,long *options,
|
||||
long *nRequest,void *pfl);
|
||||
epicsShareFunc long epicsShareAPI dbPutLinkValue(
|
||||
struct link *,short dbrType,const void *pbuffer,long nRequest);
|
||||
epicsShareFunc long epicsShareAPI dbPutField(
|
||||
struct dbAddr *,short dbrType,const void *pbuffer,long nRequest);
|
||||
epicsShareFunc long epicsShareAPI dbPut(
|
||||
struct dbAddr *,short dbrType,const void *pbuffer,long nRequest);
|
||||
|
||||
/* various utility routines */
|
||||
epicsShareFunc long epicsShareAPI dbGetControlLimits(
|
||||
const struct link *plink,double *low, double *high);
|
||||
epicsShareFunc long epicsShareAPI dbGetGraphicLimits(
|
||||
const struct link *plink,double *low, double *high);
|
||||
epicsShareFunc long epicsShareAPI dbGetAlarmLimits(
|
||||
const struct link *plink,double *lolo, double *low, double *high, double *hihi);
|
||||
epicsShareFunc long epicsShareAPI dbGetPrecision(
|
||||
const struct link *plink,short *precision);
|
||||
epicsShareFunc long epicsShareAPI dbGetUnits(
|
||||
const struct link *plink,char *units,int unitsSize);
|
||||
epicsShareFunc long epicsShareAPI dbGetAlarm(
|
||||
const struct link *plink, epicsEnum16 *status,epicsEnum16 *severity);
|
||||
epicsShareFunc long epicsShareAPI dbGetTimeStamp(
|
||||
const struct link *plink,epicsTimeStamp *pstamp);
|
||||
|
||||
typedef void(*SPC_ASCALLBACK)(struct dbCommon *);
|
||||
/*dbSpcAsRegisterCallback called by access security */
|
||||
epicsShareFunc void epicsShareAPI dbSpcAsRegisterCallback(SPC_ASCALLBACK func);
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
#include "dbAddr.h"
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbScan.h"
|
||||
#include "dbLink.h"
|
||||
#include "dbLock.h"
|
||||
#include "recGbl.h"
|
||||
#include "dbTest.h"
|
||||
|
||||
@@ -411,6 +411,13 @@ int dbCaIsLinkConnected(const struct link *plink)
|
||||
return pca->isConnected;
|
||||
}
|
||||
|
||||
void dbCaScanFwdLink(struct link *plink) {
|
||||
short fwdLinkValue = 1;
|
||||
|
||||
if (plink->value.pv_link.pvlMask & pvlOptFWD)
|
||||
dbCaPutLink(plink, DBR_SHORT, &fwdLinkValue, 1);
|
||||
}
|
||||
|
||||
#define pcaGetCheck \
|
||||
assert(plink); \
|
||||
if (plink->type != CA_LINK) return -1; \
|
||||
@@ -639,7 +646,7 @@ done:
|
||||
static void eventCallback(struct event_handler_args arg)
|
||||
{
|
||||
caLink *pca = (caLink *)arg.usr;
|
||||
DBLINK *plink;
|
||||
struct link *plink;
|
||||
size_t size;
|
||||
dbCommon *precord = 0;
|
||||
struct dbr_time_double *pdbr_time_double;
|
||||
|
||||
@@ -40,6 +40,7 @@ epicsShareFunc long dbCaPutLinkCallback(struct link *plink,
|
||||
#define dbCaPutLink(plink, dbrType, pbuffer, nRequest) \
|
||||
dbCaPutLinkCallback((plink), (dbrType), (pbuffer), (nRequest), 0, 0)
|
||||
epicsShareFunc int dbCaIsLinkConnected(const struct link *plink);
|
||||
epicsShareFunc void dbCaScanFwdLink(struct link *plink);
|
||||
|
||||
/* The following are available after the link is connected*/
|
||||
epicsShareFunc long dbCaGetNelements(const struct link *plink,
|
||||
|
||||
623
src/ioc/db/dbLink.c
Normal file
623
src/ioc/db/dbLink.c
Normal file
@@ -0,0 +1,623 @@
|
||||
/*************************************************************************\
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/* dbLink.c */
|
||||
/* $Id$ */
|
||||
/*
|
||||
* 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 "dbDefs.h"
|
||||
#include "epicsThread.h"
|
||||
#include "errlog.h"
|
||||
#include "cantProceed.h"
|
||||
#include "cvtFast.h"
|
||||
#include "epicsTime.h"
|
||||
#include "alarm.h"
|
||||
#include "ellLib.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "dbBase.h"
|
||||
#include "link.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "recSup.h"
|
||||
#include "devSup.h"
|
||||
#include "caeventmask.h"
|
||||
#include "db_field_log.h"
|
||||
#include "dbCommon.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "special.h"
|
||||
#include "errMdef.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbAddr.h"
|
||||
#include "dbLink.h"
|
||||
#include "callback.h"
|
||||
#include "dbScan.h"
|
||||
#include "dbLock.h"
|
||||
#include "dbEvent.h"
|
||||
#include "dbConvert.h"
|
||||
#include "dbConvertFast.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "dbCa.h"
|
||||
#include "dbBkpt.h"
|
||||
#include "dbNotify.h"
|
||||
#include "dbAccessDefs.h"
|
||||
#include "recGbl.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;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** Constant Links *****************************/
|
||||
|
||||
static long dbConstGetNelements(const struct link *plink, long *nelements)
|
||||
{
|
||||
*nelements = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbConstGetLink(struct link *plink, short dbrType, void *pbuffer,
|
||||
epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest)
|
||||
{
|
||||
if (pnRequest)
|
||||
*pnRequest = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************** Database Links *****************************/
|
||||
|
||||
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->type = DB_LINK;
|
||||
pdbAddr = dbCalloc(1, sizeof(struct dbAddr));
|
||||
*pdbAddr = dbaddr; /* structure copy */
|
||||
plink->value.pv_link.pvt = pdbAddr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dbDbAddLink(struct link *plink, short dbfType)
|
||||
{
|
||||
long status = dbDbInitLink(plink, dbfType);
|
||||
|
||||
if (!status) {
|
||||
DBADDR *pdbAddr = (DBADDR *) plink->value.pv_link.pvt;
|
||||
dbCommon *precord = plink->value.pv_link.precord;
|
||||
|
||||
dbLockSetRecordLock(pdbAddr->precord);
|
||||
dbLockSetMerge(precord, pdbAddr->precord);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void dbDbRemoveLink(struct link *plink)
|
||||
{
|
||||
free(plink->value.pv_link.pvt);
|
||||
plink->value.pv_link.pvt = 0;
|
||||
plink->value.pv_link.getCvt = 0;
|
||||
plink->value.pv_link.lastGetdbrType = 0;
|
||||
dbLockSetSplit(plink->value.pv_link.precord);
|
||||
}
|
||||
|
||||
static int dbDbIsLinkConnected(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->value.pv_link.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 = 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 = ppv_link->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->value.pv_link.precord;
|
||||
dbAddr *paddr = (dbAddr *) plink->value.pv_link.pvt;
|
||||
|
||||
dbScanPassive(precord, paddr->precord);
|
||||
}
|
||||
|
||||
lset dbDb_lset = { dbDbInitLink, dbDbAddLink, dbDbRemoveLink,
|
||||
dbDbIsLinkConnected, dbDbGetDBFtype, dbDbGetElements, dbDbGetValue,
|
||||
dbDbGetControlLimits, dbDbGetGraphicLimits, dbDbGetAlarmLimits,
|
||||
dbDbGetPrecision, dbDbGetUnits, dbDbGetAlarm, dbDbGetTimeStamp,
|
||||
dbDbPutValue, dbDbScanFwdLink };
|
||||
|
||||
/***************************** Generic Link API *****************************/
|
||||
|
||||
void dbInitLink(struct dbCommon *precord, struct link *plink, short dbfType)
|
||||
{
|
||||
plink->value.pv_link.precord = precord;
|
||||
|
||||
if (plink == &precord->tsel)
|
||||
recGblTSELwasModified(plink);
|
||||
|
||||
if (!(plink->value.pv_link.pvlMask & (pvlOptCA | pvlOptCP | pvlOptCPP))) {
|
||||
/* Make it a DB link if possible */
|
||||
if (!dbDbInitLink(plink, dbfType))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make it a CA link */
|
||||
if (dbfType == DBF_INLINK)
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
|
||||
dbCaAddLink(plink);
|
||||
if (dbfType == DBF_FWDLINK) {
|
||||
char *pperiod = strrchr(plink->value.pv_link.pvname, '.');
|
||||
|
||||
if (pperiod && strstr(pperiod, "PROC")) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptFWD;
|
||||
} else {
|
||||
errlogPrintf("%s.FLNK is a Channel Access Link "
|
||||
" but does not link to a PROC field\n", precord->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dbAddLink(struct dbCommon *precord, struct link *plink, short dbfType)
|
||||
{
|
||||
plink->value.pv_link.precord = precord;
|
||||
|
||||
if (plink == &precord->tsel)
|
||||
recGblTSELwasModified(plink);
|
||||
|
||||
if (!(plink->value.pv_link.pvlMask & (pvlOptCA | pvlOptCP | pvlOptCPP))) {
|
||||
/* Make it a DB link if possible */
|
||||
if (!dbDbAddLink(plink, dbfType))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make it a CA link */
|
||||
if (dbfType == DBF_INLINK)
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
|
||||
dbCaAddLink(plink);
|
||||
if (dbfType == DBF_FWDLINK) {
|
||||
char *pperiod = strrchr(plink->value.pv_link.pvname, '.');
|
||||
|
||||
if (pperiod && strstr(pperiod, "PROC"))
|
||||
plink->value.pv_link.pvlMask |= pvlOptFWD;
|
||||
}
|
||||
}
|
||||
|
||||
void dbRemoveLink(struct link *plink)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
dbDbRemoveLink(plink);
|
||||
break;
|
||||
case CA_LINK:
|
||||
dbCaRemoveLink(plink);
|
||||
break;
|
||||
default:
|
||||
cantProceed("dbRemoveLink: Unexpected link type %d\n", plink->type);
|
||||
}
|
||||
plink->type = PV_LINK;
|
||||
plink->value.pv_link.pvlMask = 0;
|
||||
}
|
||||
|
||||
int dbIsLinkConnected(const struct link *plink)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbIsLinkConnected(plink);
|
||||
case CA_LINK:
|
||||
return dbCaIsLinkConnected(plink);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int dbGetLinkDBFtype(const struct link *plink)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbGetDBFtype(plink);
|
||||
case CA_LINK:
|
||||
return dbCaGetLinkDBFtype(plink);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
long dbGetNelements(const struct link *plink, long *nelements)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case CONSTANT:
|
||||
return dbConstGetNelements(plink, nelements);
|
||||
case DB_LINK:
|
||||
return dbDbGetElements(plink, nelements);
|
||||
case CA_LINK:
|
||||
return dbCaGetNelements(plink, nelements);
|
||||
}
|
||||
return S_db_badField;
|
||||
}
|
||||
|
||||
long dbGetLinkValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *poptions, long *pnRequest)
|
||||
{
|
||||
struct dbCommon *precord = plink->value.pv_link.precord;
|
||||
epicsEnum16 sevr = 0, stat = 0;
|
||||
long status;
|
||||
|
||||
if (poptions && *poptions) {
|
||||
printf("dbGetLinkValue: Use of poptions no longer supported\n");
|
||||
*poptions = 0;
|
||||
}
|
||||
|
||||
switch (plink->type) {
|
||||
case CONSTANT:
|
||||
status = dbConstGetLink(plink, dbrType, pbuffer, &stat, &sevr,
|
||||
pnRequest);
|
||||
break;
|
||||
case DB_LINK:
|
||||
status = dbDbGetValue(plink, dbrType, pbuffer, &stat, &sevr, pnRequest);
|
||||
break;
|
||||
case CA_LINK:
|
||||
status = dbCaGetLink(plink, dbrType, pbuffer, &stat, &sevr, pnRequest);
|
||||
break;
|
||||
default:
|
||||
cantProceed("dbGetLinkValue: Illegal link type");
|
||||
}
|
||||
if (status) {
|
||||
recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
|
||||
} else {
|
||||
inherit_severity(&plink->value.pv_link, precord, stat, sevr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
long dbGetControlLimits(const struct link *plink, double *low, double *high)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbGetControlLimits(plink, low, high);
|
||||
case CA_LINK:
|
||||
return dbCaGetControlLimits(plink, low, high);
|
||||
}
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
long dbGetGraphicLimits(const struct link *plink, double *low, double *high)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbGetGraphicLimits(plink, low, high);
|
||||
case CA_LINK:
|
||||
return dbCaGetGraphicLimits(plink, low, high);
|
||||
}
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
long dbGetAlarmLimits(const struct link *plink, double *lolo, double *low,
|
||||
double *high, double *hihi)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbGetAlarmLimits(plink, lolo, low, high, hihi);
|
||||
case CA_LINK:
|
||||
return dbCaGetAlarmLimits(plink, lolo, low, high, hihi);
|
||||
}
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
long dbGetPrecision(const struct link *plink, short *precision)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbGetPrecision(plink, precision);
|
||||
case CA_LINK:
|
||||
return dbCaGetPrecision(plink, precision);
|
||||
}
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
long dbGetUnits(const struct link *plink, char *units, int unitsSize)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbGetUnits(plink, units, unitsSize);
|
||||
case CA_LINK:
|
||||
return dbCaGetUnits(plink, units, unitsSize);
|
||||
}
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
long dbGetAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbGetAlarm(plink, status, severity);
|
||||
case CA_LINK:
|
||||
return dbCaGetAlarm(plink, status, severity);
|
||||
}
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
return dbDbGetTimeStamp(plink, pstamp);
|
||||
case CA_LINK:
|
||||
return dbCaGetTimeStamp(plink, pstamp);
|
||||
}
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
long dbPutLinkValue(struct link *plink, short dbrType, const void *pbuffer,
|
||||
long nRequest)
|
||||
{
|
||||
long status;
|
||||
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
status = dbDbPutValue(plink, dbrType, pbuffer, nRequest);
|
||||
break;
|
||||
case CA_LINK:
|
||||
status = dbCaPutLink(plink, dbrType, pbuffer, nRequest);
|
||||
break;
|
||||
default:
|
||||
cantProceed("dbPutLinkValue: Illegal link type %d", plink->type);
|
||||
}
|
||||
if (status) {
|
||||
struct dbCommon *precord = plink->value.pv_link.precord;
|
||||
|
||||
recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void dbScanFwdLink(struct link *plink)
|
||||
{
|
||||
switch (plink->type) {
|
||||
case DB_LINK:
|
||||
dbDbScanFwdLink(plink);
|
||||
break;
|
||||
case CA_LINK:
|
||||
dbCaScanFwdLink(plink);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
87
src/ioc/db/dbLink.h
Normal file
87
src/ioc/db/dbLink.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2010 The 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* dbLink.h
|
||||
*
|
||||
* Created on: Mar 21, 2010
|
||||
* Author: Andrew Johnson
|
||||
*/
|
||||
|
||||
#ifndef INC_dbLink_H
|
||||
#define INC_dbLink_H
|
||||
|
||||
#include "link.h"
|
||||
#include "shareLib.h"
|
||||
|
||||
typedef struct lset {
|
||||
long (*initLink)(struct link *plink, short dbfType);
|
||||
long (*addLink)(struct link *plink, short dbfType);
|
||||
void (*removeLink)(struct link *plink);
|
||||
int (*isLinkConnected)(const struct link *plink);
|
||||
int (*getDBFtype)(const struct link *plink);
|
||||
long (*getElements)(const struct link *plink, long *nelements);
|
||||
long (*getValue)(struct link *plink, short dbrType, void *pbuffer,
|
||||
epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest);
|
||||
long (*getControlLimits)(const struct link *plink, double *lo, double *hi);
|
||||
long (*getGraphicLimits)(const struct link *plink, double *lo, double *hi);
|
||||
long (*getAlarmLimits)(const struct link *plink, double *lolo, double *lo,
|
||||
double *hi, double *hihi);
|
||||
long (*getPrecision)(const struct link *plink, short *precision);
|
||||
long (*getUnits)(const struct link *plink, char *units, int unitsSize);
|
||||
long (*getAlarm)(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity);
|
||||
long (*getTimeStamp)(const struct link *plink, epicsTimeStamp *pstamp);
|
||||
long (*putValue)(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest);
|
||||
void (*scanFwdLink)(struct link *plink);
|
||||
} lset;
|
||||
|
||||
#define dbGetLink(PLNK, DBRTYPE, PBUFFER, OPTIONS, NREQUEST) \
|
||||
( ( ( (PLNK)->type == CONSTANT ) && \
|
||||
( (NREQUEST) == 0) && \
|
||||
( (OPTIONS) == 0) ) \
|
||||
? 0 \
|
||||
: dbGetLinkValue((PLNK),(DBRTYPE), \
|
||||
(void *)(PBUFFER), (OPTIONS), (NREQUEST) ) )
|
||||
|
||||
#define dbPutLink(PLNK, DBRTYPE, PBUFFER, NREQUEST) \
|
||||
( ( (PLNK)->type == CONSTANT) \
|
||||
? 0 \
|
||||
: dbPutLinkValue( (PLNK), (DBRTYPE), (void *)(PBUFFER), (NREQUEST) ) )
|
||||
|
||||
#define dbGetSevr(PLINK, PSEVERITY) \
|
||||
dbGetAlarm((PLINK), NULL, (PSEVERITY));
|
||||
|
||||
epicsShareFunc void dbInitLink(struct dbCommon *precord, struct link *plink, short dbfType);
|
||||
epicsShareFunc void dbAddLink(struct dbCommon *precord, struct link *plink, short dbfType);
|
||||
epicsShareFunc void dbRemoveLink(struct link *plink);
|
||||
epicsShareFunc long dbGetNelements(const struct link *plink, long *nelements);
|
||||
epicsShareFunc int dbIsLinkConnected(const struct link *plink);
|
||||
epicsShareFunc int dbGetLinkDBFtype(const struct link *plink);
|
||||
epicsShareFunc long dbGetLinkValue(struct link *, short dbrType, void *pbuffer,
|
||||
long *options, long *nRequest);
|
||||
epicsShareFunc long dbGetControlLimits(const struct link *plink, double *low,
|
||||
double *high);
|
||||
epicsShareFunc long dbGetGraphicLimits(const struct link *plink, double *low,
|
||||
double *high);
|
||||
epicsShareFunc long dbGetAlarmLimits(const struct link *plink, double *lolo,
|
||||
double *low, double *high, double *hihi);
|
||||
epicsShareFunc long dbGetPrecision(const struct link *plink, short *precision);
|
||||
epicsShareFunc long dbGetUnits(const struct link *plink, char *units,
|
||||
int unitsSize);
|
||||
epicsShareFunc long dbGetAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity);
|
||||
epicsShareFunc long dbGetTimeStamp(const struct link *plink,
|
||||
epicsTimeStamp *pstamp);
|
||||
epicsShareFunc long dbPutLinkValue(struct link *, short dbrType,
|
||||
const void *pbuffer, long nRequest);
|
||||
epicsShareFunc void dbScanFwdLink(struct link *plink);
|
||||
|
||||
|
||||
#endif /* INC_dbLink_H */
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "caeventmask.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbLink.h"
|
||||
#include "dbNotify.h"
|
||||
#include "dbCa.h"
|
||||
#include "dbEvent.h"
|
||||
|
||||
@@ -1,27 +1,24 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* 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 Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* link.h */
|
||||
/* base/include $Revision-Id$ */
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Original Author: Bob Dalesio
|
||||
* Current Author: Marty Kraimer
|
||||
* Date: 6-1-90
|
||||
* Original Authors: Bob Dalesio, Marty Kraimer
|
||||
*/
|
||||
|
||||
#ifndef INC_link_H
|
||||
#define INC_link_H
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifndef INClinkh
|
||||
#define INClinkh 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -55,8 +52,8 @@ epicsShareExtern maplinkType pamaplinkType[];
|
||||
/* structure of a PV_LINK DB_LINK and a CA_LINK */
|
||||
/*Options defined by pvlMask */
|
||||
#define pvlOptMsMode 0x3 /*Maximize Severity mode selection*/
|
||||
#define pvlOptNMS 0 /*Dont Maximize Severity*/
|
||||
#define pvlOptMS 1 /*Maximize Severity allways*/
|
||||
#define pvlOptNMS 0 /*Don't Maximize Severity*/
|
||||
#define pvlOptMS 1 /*Maximize Severity always*/
|
||||
#define pvlOptMSI 2 /*Maximize Severity if INVALID*/
|
||||
#define pvlOptMSS 3 /*Maximize Severity and copy Status*/
|
||||
#define pvlOptPP 0x4 /*Process Passive*/
|
||||
@@ -77,14 +74,15 @@ struct macro_link {
|
||||
};
|
||||
|
||||
struct dbCommon;
|
||||
struct pvlet;
|
||||
|
||||
struct pv_link {
|
||||
char *pvname; /*pvname to link to*/
|
||||
struct dbCommon *precord; /*Address of record containing link*/
|
||||
void *pvt; /*CA or DB private*/
|
||||
LINKCVT getCvt; /*input conversion function*/
|
||||
short pvlMask; /*Options mask*/
|
||||
short lastGetdbrType; /*last dbrType for DB or CA get*/
|
||||
char *pvname; /* pvname link points to */
|
||||
struct dbCommon *precord; /* Address of record owning link */
|
||||
void *pvt; /* CA or DB private */
|
||||
LINKCVT getCvt; /* input conversion function */
|
||||
short pvlMask; /* Options mask */
|
||||
short lastGetdbrType; /* last dbrType for DB or CA get */
|
||||
};
|
||||
|
||||
/* structure of a VME io channel */
|
||||
@@ -150,13 +148,12 @@ struct bbgpibio {
|
||||
|
||||
/* structure of an instrument io link */
|
||||
struct instio {
|
||||
char *string; /* the cat of location.
|
||||
signal.parameter */
|
||||
char *string;
|
||||
};
|
||||
|
||||
/* structure of a vxi link */
|
||||
struct vxiio{
|
||||
short flag; /* 0 = frame/slot, 1 = SA */
|
||||
short flag; /* 0 = frame/slot, 1 = SA */
|
||||
short frame;
|
||||
short slot;
|
||||
short la; /* logical address if flag =1 */
|
||||
@@ -165,7 +162,7 @@ struct vxiio{
|
||||
};
|
||||
|
||||
/* union of possible address structures */
|
||||
union value{
|
||||
union value {
|
||||
char *constantStr; /*constant string*/
|
||||
struct macro_link macro_link; /* link containing macro substitution*/
|
||||
struct pv_link pv_link; /* link to process variable*/
|
||||
@@ -180,9 +177,9 @@ union value{
|
||||
struct vxiio vxiio; /* vxi io */
|
||||
};
|
||||
|
||||
struct link{
|
||||
union value value;
|
||||
short type;
|
||||
struct link {
|
||||
union value value;
|
||||
short type;
|
||||
char *text; /* original INP/OUT link text */
|
||||
};
|
||||
|
||||
@@ -191,4 +188,4 @@ typedef struct link DBLINK;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*INClinkh*/
|
||||
#endif /* INC_link_H */
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "taskwd.h"
|
||||
#include "callback.h"
|
||||
#include "dbCommon.h"
|
||||
#include "dbLock.h"
|
||||
#include "devSup.h"
|
||||
#include "drvSup.h"
|
||||
#include "menuConvert.h"
|
||||
@@ -426,48 +425,18 @@ static void doInitRecord0(dbRecordType *pdbRecordType, dbCommon *precord,
|
||||
static void doResolveLinks(dbRecordType *pdbRecordType, dbCommon *precord,
|
||||
void *user)
|
||||
{
|
||||
dbFldDes **papFldDes = pdbRecordType->papFldDes;
|
||||
short *link_ind = pdbRecordType->link_ind;
|
||||
devSup *pdevSup;
|
||||
int j;
|
||||
|
||||
/* Convert all PV_LINKs to DB_LINKs or CA_LINKs */
|
||||
/* For all the links in the record type... */
|
||||
for (j = 0; j < pdbRecordType->no_links; j++) {
|
||||
dbFldDes *pdbFldDes =
|
||||
pdbRecordType->papFldDes[pdbRecordType->link_ind[j]];
|
||||
dbFldDes *pdbFldDes = papFldDes[link_ind[j]];
|
||||
DBLINK *plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
|
||||
|
||||
if (plink->type == PV_LINK) {
|
||||
DBADDR dbaddr;
|
||||
|
||||
if (plink == &precord->tsel) recGblTSELwasModified(plink);
|
||||
if (!(plink->value.pv_link.pvlMask&(pvlOptCA|pvlOptCP|pvlOptCPP))
|
||||
&& (dbNameToAddr(plink->value.pv_link.pvname,&dbaddr)==0)) {
|
||||
DBADDR *pdbAddr;
|
||||
|
||||
plink->type = DB_LINK;
|
||||
pdbAddr = dbCalloc(1,sizeof(struct dbAddr));
|
||||
*pdbAddr = dbaddr; /*structure copy*/;
|
||||
plink->value.pv_link.pvt = pdbAddr;
|
||||
} else {/*It is a CA link*/
|
||||
|
||||
if (pdbFldDes->field_type == DBF_INLINK) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
}
|
||||
dbCaAddLink(plink);
|
||||
if (pdbFldDes->field_type == DBF_FWDLINK) {
|
||||
char *pperiod =
|
||||
strrchr(plink->value.pv_link.pvname,'.');
|
||||
|
||||
if (pperiod && strstr(pperiod,"PROC")) {
|
||||
plink->value.pv_link.pvlMask |= pvlOptFWD;
|
||||
} else {
|
||||
errlogPrintf("%s.FLNK is a Channel Access Link "
|
||||
" but does not link to a PROC field\n",
|
||||
precord->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (plink->type == PV_LINK)
|
||||
dbInitLink(precord, plink, pdbFldDes->field_type);
|
||||
}
|
||||
pdevSup = dbDTYPtoDevSup(pdbRecordType, precord->dtyp);
|
||||
if (pdevSup) {
|
||||
|
||||
Reference in New Issue
Block a user