Commit d57380bb authored by franksen's avatar franksen
Browse files

redesign!

parent 20fddb7f
......@@ -9,6 +9,9 @@
* HwClient device support for aiRecord
*
* $Log: devAiHwClient.c,v $
* Revision 1.3 1999/02/12 14:41:56 franksen
* redesign!
*
* Revision 1.2 1999/02/04 20:30:04 franksen
* changed revision numbers to 1.2
*
......@@ -103,9 +106,9 @@ static long init_record(struct aiRecord *prec)
printf("Can't malloc dpvt structure!\n");
return ERROR;
}
pdpvt->user.prec = (struct dbCommon*)prec;
/* set target of notify copy */
pdpvt->user.pdest = &prec->rval;
pdpvt->pclient = (struct dbCommon*)prec;
pdpvt->prval = &prec->rval;
pdpvt->dbrType = DBR_LONG;
prec->dpvt = pdpvt;
status = devHwClientInitRecord(pdpvt, &prec->inp);
if(status != OK) return status;
......
......@@ -9,6 +9,9 @@
* HwClient device support for aoRecord
*
* $Log: devAoHwClient.c,v $
* Revision 1.3 1999/02/12 14:42:00 franksen
* redesign!
*
* Revision 1.2 1999/02/04 20:30:04 franksen
* changed revision numbers to 1.2
*
......@@ -101,9 +104,10 @@ static long init_record(struct aoRecord *prec)
printf("Can't malloc dpvt structure!\n");
return ERROR;
}
pdpvt->user.prec = (struct dbCommon*)prec;
/* set target of notify copy */
pdpvt->user.pdest = &prec->rval;
pdpvt->pclient = (struct dbCommon*)prec;
pdpvt->prval = &prec->rval;
pdpvt->prdbval = &prec->rbv;
pdpvt->dbrType = DBR_LONG;
prec->dpvt = pdpvt;
status = devHwClientInitRecord(pdpvt, &prec->out);
if(status == OK)
......@@ -125,7 +129,7 @@ static long write_value(struct aoRecord *prec)
pdpvt->info.bumpless = FALSE; /* only once */
if(status == OK)
{
double value = prec->rval;
double value = prec->rbv;
/* this is copied from init_record in aoRecord.c: */
if(prec->aslo!=0.0) value *= prec->aslo;
......
......@@ -9,6 +9,9 @@
* HwClient device support for biRecord
*
* $Log: devBiHwClient.c,v $
* Revision 1.4 1999/02/12 14:42:04 franksen
* redesign!
*
* Revision 1.3 1999/02/08 16:57:25 franksen
* bugfix (need to set mask in init_record)
*
......@@ -99,9 +102,9 @@ static long init_record(struct biRecord *prec)
printf("Can't malloc dpvt structure!\n");
return ERROR;
}
pdpvt->user.prec = (struct dbCommon*)prec;
/* set target of notify copy */
pdpvt->user.pdest = (long *)(&prec->rval); /* readback destination */
pdpvt->pclient = (struct dbCommon*)prec;
pdpvt->prval = &prec->rval;
pdpvt->dbrType = DBR_ULONG;
prec->dpvt = pdpvt;
status = devHwClientInitRecord(pdpvt, &prec->inp);
prec->mask = (1 << pdpvt->info.nobits) - 1;
......
......@@ -9,6 +9,9 @@
* HwClient device support for boRecord
*
* $Log: devBoHwClient.c,v $
* Revision 1.4 1999/02/12 14:42:07 franksen
* redesign!
*
* Revision 1.3 1999/02/08 16:57:26 franksen
* bugfix (need to set mask in init_record)
*
......@@ -99,9 +102,10 @@ static long init_record(struct boRecord *prec)
printf("Can't malloc dpvt structure!\n");
return ERROR;
}
pdpvt->user.prec = (struct dbCommon*)prec;
/* set target of notify copy */
pdpvt->user.pdest = (long *)(&prec->rval); /* readback destination */
pdpvt->pclient = (struct dbCommon*)prec;
pdpvt->prval = &prec->rval;
pdpvt->prdbval = &prec->rbv;
pdpvt->dbrType = DBR_ULONG;
prec->dpvt = pdpvt;
status = devHwClientInitRecord(pdpvt, &prec->out);
prec->mask = (1 << pdpvt->info.nobits) - 1;
......@@ -128,7 +132,7 @@ static long write_value(struct boRecord *prec)
pdpvt->info.bumpless = FALSE; /* only once */
if(status == OK)
{
prec->val = (unsigned short)prec->rval;
prec->val = (unsigned short)prec->rbv;
prec->udf = FALSE;
}
}
......
......@@ -9,6 +9,9 @@
* Library for HwClient device supports
*
* $Log: devHwClientLib.c,v $
* Revision 1.4 1999/02/12 14:42:11 franksen
* redesign!
*
* Revision 1.3 1999/02/09 11:40:15 franksen
* cleaned up out-ifdef'ed parts
*
......@@ -50,29 +53,35 @@
* Notes:
*
* The purpose of this module is to provide a device support library for
* records that are connected (via in or out link) to so called hardware
* records that are connected (via INP or OUT link) to so called hardware
* records. Records that have HwClient support read/write their raw values
* by a call to dbGetLink/dbPutLink. The hardware record MUST provide
* an RSET function called get_hw_info (in addition to its standard RSET
* functions). This functin is called by init_record of this device support
* which, in turn, should be called by record support's SECOND call to
* init_record.
* functions). This function is used to (1) obtain raw value information
* such as the max and min raw values, (2) to obtain information about
* synchronous/asynchronous processing of the hardware record as well as
* its bumbless reboot abilities and (3) to register a callback in order
* for the hw record to call the client's process() whenever
* it has completed (asynchronous) processing itself. Get_hw_info() may
* only be called during record support's SECOND call to init_record.
*
* Generally, if hw record's processing is asynchronous then this record's
* is also. This is because potential readback values must be retrieved
* from the hw record, when the latter has completed processing. It is
* achieved by giving the hw record a callback structure. The hw record is
* responsible for arranging the readback callback after it has got the value.
* Generally, the client record's processing is asynchronous if its INP or OUT
* link is PP and if the hw record's processing is asynchronous.
* This is because read(-back) values must be retrieved from the hw record,
* only after the latter has completed processing. The hw record is
* responsible for requesting the callback of all client records that have
* registered themselves by calling get_hw_info.
*
* Output records can do bumpless reboot if record processing is asynchronous
* and the hw record supports it. In this case the hw record responds to
* get_hw_info with bumpless=TRUE. init_record is then left with pact==TRUE
* so that, when hw record initiates readback by itself and notifies the
* hwClient record via the usual asynch readback callback, the raw value
* Output records do bumpless reboot if the hw record supports it
* (as indicated by the field 'bumpless' of the info structure).
* This is implemented by simulating the start of an asynchronous processing in
* init_record (i.e. init_record is left with pact==TRUE) so that,
* when the hw record initiates readback by itself and notifies the
* hwClient record via the usual callback, the raw value
* can be re-converted to engeneering units. Unfortunately this
* makes the bumpless reboot re-conversion code in the init_record functions
* of record supports useless: it comes to early. Instead it must be
* performed by the device support.
* performed by the device support modules.
*
*/
#include <vxWorks.h>
......@@ -100,7 +109,7 @@ static void devHwClientCallback(CALLBACK *pcallback);
long devHwClientInitRecord(HW_CLIENT_DPVT *pdpvt, struct link *plink)
{
struct dbCommon *prec = pdpvt->user.prec;
struct dbCommon *prec = pdpvt->pclient;
DBADDR hwaddr;
DBADDR *phwaddr = NULL;
HW_RSET *prset;
......@@ -145,19 +154,14 @@ long devHwClientInitRecord(HW_CLIENT_DPVT *pdpvt, struct link *plink)
return(S_db_badField);
}
/* Prepare to be processed when hw record completes asynch processing; */
/* beware: pdpvt->user.psrc may be overwritten by get_hw_info. */
pdpvt->user.psrc = (long *)(phwaddr->pfield);
pdpvt->user.prec = prec;
pdpvt->prval = pdpvt->user.pdest;
pdpvt->ptgt = pdpvt->user.psrc;
/* pdpvt->user.pdest already set by calling device support */
pdpvt->phwrec = phwaddr->precord;
/* prepare to make make link asynchronous if it's a PP link */
pdpvt->info.asynch = plink->value.pv_link.pvlMask & pvlOptPP;
callbackSetCallback(devHwClientCallback, &pdpvt->info.notify.callback);
callbackSetUser(&pdpvt->user, &pdpvt->info.notify.callback);
callbackSetUser(prec, &pdpvt->info.notify.callback);
/* in the same step get back information about raw values,
asyncronous processing and bumpless reboot */
/* get information about raw values, asyncronous processing and bumpless reboot */
if(prset->get_hw_info(phwaddr->precord, &pdpvt->info) != OK)
{
recGblRecordError(S_db_badField, prec,
......@@ -165,10 +169,16 @@ long devHwClientInitRecord(HW_CLIENT_DPVT *pdpvt, struct link *plink)
return(S_db_badField);
}
if(pdpvt->info.asynch)
{
/* make link NPP because we are going to call dbScanPassive anyway */
plink->value.pv_link.pvlMask &= ~pvlOptPP;
}
if(pdpvt->info.bumpless)
{
/* simulate start of asynchronous processing; will complete as usual */
pdpvt->user.doit = TRUE;
pdpvt->info.notify.doit = TRUE;
prec->pact = TRUE;
}
return OK;
......@@ -177,55 +187,71 @@ long devHwClientInitRecord(HW_CLIENT_DPVT *pdpvt, struct link *plink)
long devHwClientRead(HW_CLIENT_DPVT *pdpvt, struct link *pinp)
{
long status = OK;
dbCommon *prec = pdpvt->user.prec;
long *prval = pdpvt->user.pdest;
struct dbCommon *prec = pdpvt->pclient;
if(!pdpvt->info.asynch) /* do synchronous processing */
if(!pdpvt->info.asynch && !pdpvt->info.bumpless) /* do synch processing */
{
PRF(2,("devHwClientRead(%s): do synch proc\n", prec->name));
status = dbGetLink(pinp, DBR_LONG, prval, NULL, NULL);
status = dbGetLink(pinp, pdpvt->dbrType, pdpvt->prval, NULL, NULL);
}
else if(!prec->pact) /* start asynchronous processing */
{
PRF(2,("devHwClientRead(%s): start asynch proc\n", prec->name));
status = dbGetLink(pinp, DBR_LONG, prval, NULL, NULL);
pdpvt->user.doit = TRUE;
prec->pact = TRUE;
status = dbScanPassive(prec,pdpvt->phwrec);
if(status != OK)
{
recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
prec->pact = FALSE;
}
else
pdpvt->info.notify.doit = TRUE;
}
else /* complete asynchronous processing */
{
PRF(2,("devHwClientRead(%s): complete asynch proc, stat %d, sevr %d\n",
prec->name, prec->nsta, prec->nsev));
/* get the readback data */
status = dbGetLink(pinp, pdpvt->dbrType, pdpvt->prval, NULL, NULL);
/* everything's done now */
status = OK;
}
PRF(2,("devHwClientRead(%s): returning with rval = %d, status = %d\n",
prec->name, *prval, status));
prec->name, pdpvt->prval, status));
return status;
}
long devHwClientWrite(HW_CLIENT_DPVT *pdpvt, struct link *pout)
{
long status = OK;
dbCommon *prec = pdpvt->user.prec;
long *prval = pdpvt->prval;
struct dbCommon *prec = pdpvt->pclient;
if(!pdpvt->info.asynch) /* do synchronous processing */
if(!pdpvt->info.asynch && !pdpvt->info.bumpless) /* do synch processing */
{
PRF(2,("devHwClientWrite(%s): do synch proc\n", prec->name));
status = dbPutLink(pout, DBR_LONG, prval, 1);
status = dbPutLink(pout, pdpvt->dbrType, pdpvt->prval, 1);
}
else if(!prec->pact) /* start asynchronous processing */
{
PRF(2,("devHwClientWrite(%s): start asynch proc\n", prec->name));
status = dbPutLink(pout, DBR_LONG, prval, 1);
pdpvt->user.doit = TRUE;
prec->pact = TRUE;
status = dbPutLink(pout, pdpvt->dbrType, pdpvt->prval, 1);
if(status == OK)
{
prec->pact = TRUE;
status = dbScanPassive(prec,pdpvt->phwrec);
if(status != OK)
{
recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
prec->pact = FALSE;
}
else
pdpvt->info.notify.doit = TRUE;
}
}
else /* complete asynchronous processing */
/* if pdpvt->info.bumpless is set this completes a read (!) */
......@@ -233,6 +259,11 @@ long devHwClientWrite(HW_CLIENT_DPVT *pdpvt, struct link *pout)
PRF(2,("devHwClientWrite(%s): complete asynch proc, stat %d, sevr %d\n",
prec->name, prec->nsta, prec->nsev));
/* get the readback data */
if(pdpvt->prdbval)
status = dbGetLink(pout, pdpvt->dbrType, pdpvt->prdbval, NULL, NULL);
else
status = dbGetLink(pout, pdpvt->dbrType, pdpvt->prval, NULL, NULL);
/* everything's done now */
status = OK;
}
......@@ -243,39 +274,28 @@ long devHwClientIointInfo(int cmd, struct dbCommon *prec, IOSCANPVT *ppvt)
{
HW_CLIENT_DPVT *pdpvt = (HW_CLIENT_DPVT *)prec->dpvt;
if(!pdpvt->info.ioscanpvt)
{
recGblRecordError(ERROR, prec,
"devHwClientLib (get_ioint_info) no ioscanpvt\n");
return(ERROR);
}
*ppvt = pdpvt->info.ioscanpvt;
return OK;
}
static void devHwClientCallback(CALLBACK *pcallback)
{
HW_CALLBACK_USER *puser = NULL;
struct rset *prset;
struct dbCommon *prec = NULL;
callbackGetUser(puser, pcallback);
if(!puser || !puser->prec || !puser->prec->rset)
{
PRF(1,("Fatal error in devHwClientCallback\n"));
return;
}
prset = (struct rset *)puser->prec->rset;
callbackGetUser(prec, pcallback);
prset = (struct rset *)prec->rset;
PRF(3,("Entering devHwClientCallback for record %s\n", puser->prec->name));
PRF(3,("process callback for record %s\n", prec->name));
dbScanLock(puser->prec);
if(puser->doit)
{
/* THIS is the place where readback data is exchanged: */
*(puser->pdest) = *(puser->psrc);
PRF(2,("devHwClientCallback, record %s, stat %d, sevr %d\n",
puser->prec->name, puser->status, puser->severity));
/* implement a 'backward maximize severity' */
recGblSetSevr(puser->prec, puser->status, puser->severity);
puser->doit = FALSE;
prset->process(puser->prec);
}
dbScanUnlock(puser->prec);
dbScanLock(prec);
prset->process(prec);
dbScanUnlock(prec);
}
......@@ -9,6 +9,9 @@
* Interface to library for HwClient device supports
*
* $Log: devHwClientLib.h,v $
* Revision 1.3 1999/02/12 14:42:14 franksen
* redesign!
*
* Revision 1.2 1999/02/04 20:30:05 franksen
* changed revision numbers to 1.2
*
......@@ -47,13 +50,7 @@
* Notes:
*
* HwClient device supports using this module must have a dpvt structure
* that starts like
*
* {
* HW_INFO info;
* HW_CALLBACK_USER user;
* ... more fields
* }
* that starts with HW_CLIENT_DPVT.
*
*/
#ifndef INCdevHwClientLibH
......@@ -68,26 +65,14 @@ typedef struct hwRset
RECSUPFUN get_hw_info;
} HW_RSET;
/*
* Filled by hw client dev sup; for copying raw values & notifying
*/
typedef struct hwCallbackUser
{
unsigned short doit; /* process only if TRUE */
unsigned short status; /* new alarm status and severity */
unsigned short severity;/* for "backward maximize severity" */
long *psrc; /* location where readback values are read */
long *pdest; /* location to write readback values */
dbCommon *prec; /* the record demanding to be called */
} HW_CALLBACK_USER;
/*
* List node for callbacks
*/
typedef struct hwNotifyNode
{
ELLNODE node;
CALLBACK callback;
ELLNODE node;
CALLBACK callback;
unsigned short doit; /* request callback only if TRUE */
} HW_NOTIFY_NODE;
/*
......@@ -102,13 +87,13 @@ typedef struct hwNotifyNode
*/
typedef struct hwInfo
{
long rawmin; /* minimum raw value */
long rawmax; /* maximum raw value */
unsigned short nobits; /* number of significant bits */
unsigned char asynch; /* is processing asynchronous? */
unsigned char bumpless; /* can we do bumpless reboot? */
IOSCANPVT ioscanpvt; /* to forward I/O events to client records */
HW_NOTIFY_NODE notify; /* call me back when asyn proc completed */
long rawmin; /* minimum raw value */
long rawmax; /* maximum raw value */
unsigned short nobits; /* number of significant bits */
unsigned char asynch; /* is processing asynchronous? */
unsigned char bumpless; /* can we do bumpless reboot? */
IOSCANPVT ioscanpvt; /* to forward I/O events to client records */
HW_NOTIFY_NODE notify; /* call me back when asyn proc completed */
} HW_INFO;
/*
......@@ -116,10 +101,14 @@ typedef struct hwInfo
*/
typedef struct hwClientDpvt
{
HW_INFO info;
HW_CALLBACK_USER user;
long *ptgt;
long *prval;
/* following are set by library */
HW_INFO info;
struct dbCommon *phwrec; /* address of hw record */
/* following are set by client modules, i.e. device supports */
struct dbCommon *pclient; /* address of client record */
void *prval; /* location of primary (raw) data */
void *prdbval; /* location of readback (raw) data */
unsigned short dbrType; /* database request type for data */
} HW_CLIENT_DPVT;
extern long devHwClientInitRecord(HW_CLIENT_DPVT *pdpvt, struct link *plink);
......
......@@ -9,6 +9,9 @@
* HwClient device support for mbbiDirectRecord
*
* $Log: devMbbiDirectHwClient.c,v $
* Revision 1.3 1999/02/12 14:42:18 franksen
* redesign!
*
* Revision 1.2 1999/02/04 20:30:05 franksen
* changed revision numbers to 1.2
*
......@@ -96,9 +99,9 @@ static long init_record(struct mbbiDirectRecord *prec)
printf("Can't malloc dpvt structure!\n");
return ERROR;
}
pdpvt->user.prec = (struct dbCommon*)prec;
/* set target of notify copy */
pdpvt->user.pdest = (long *)(&prec->rval); /* readback destination */
pdpvt->pclient = (struct dbCommon*)prec;
pdpvt->prval = &prec->rval;
pdpvt->dbrType = DBR_ULONG;
prec->dpvt = pdpvt;
status = devHwClientInitRecord(pdpvt, &prec->inp);
if(status == OK)
......
......@@ -9,6 +9,9 @@
* HwClient device support for mbbiRecord
*
* $Log: devMbbiHwClient.c,v $
* Revision 1.3 1999/02/12 14:42:21 franksen
* redesign!
*
* Revision 1.2 1999/02/04 20:30:05 franksen
* changed revision numbers to 1.2
*
......@@ -96,9 +99,9 @@ static long init_record(struct mbbiRecord *prec)
printf("Can't malloc dpvt structure!\n");
return ERROR;
}
pdpvt->user.prec = (struct dbCommon*)prec;
/* set target of notify copy */
pdpvt->user.pdest = (long *)(&prec->rval); /* readback destination */
pdpvt->pclient = (struct dbCommon*)prec;
pdpvt->prval = &prec->rval;
pdpvt->dbrType = DBR_ULONG;
prec->dpvt = pdpvt;
status = devHwClientInitRecord(pdpvt, &prec->inp);
if(status == OK)
......
......@@ -9,6 +9,9 @@
* HwClient device support for mbboDirectRecord
*
* $Log: devMbboDirectHwClient.c,v $
* Revision 1.3 1999/02/12 14:42:25 franksen
* redesign!
*
* Revision 1.2 1999/02/04 20:30:05 franksen
* changed revision numbers to 1.2
*
......@@ -96,9 +99,10 @@ static long init_record(struct mbboDirectRecord *prec)
printf("Can't malloc dpvt structure!\n");
return ERROR;
}
pdpvt->user.prec = (struct dbCommon*)prec;
/* set target of notify copy */
pdpvt->user.pdest = (long *)(&prec->rval); /* readback destination */
pdpvt->pclient = (struct dbCommon*)prec;
pdpvt->prval = &prec->rval;
pdpvt->prdbval = &prec->rbv;
pdpvt->dbrType = DBR_ULONG;
prec->dpvt = pdpvt;
status = devHwClientInitRecord(pdpvt, &prec->out);
if(status == OK)
......
......@@ -9,6 +9,9 @@
* HwClient device support for mbboRecord
*
* $Log: devMbboHwClient.c,v $
* Revision 1.3 1999/02/12 14:42:28 franksen
* redesign!
*
* Revision 1.2 1999/02/04 20:30:06 franksen
* changed revision numbers to 1.2
*
......@@ -96,9 +99,10 @@ static long init_record(struct mbboRecord *prec)
printf("Can't malloc dpvt structure!\n");
return ERROR;
}
pdpvt->user.prec = (struct dbCommon*)prec;
/* set target of notify copy */
pdpvt->user.pdest = (long *)(&prec->rval); /* readback destination */
pdpvt->pclient = (struct dbCommon*)prec;
pdpvt->prval = &prec->rval;
pdpvt->prdbval = &prec->rbv;
pdpvt->dbrType = DBR_ULONG;
prec->dpvt = pdpvt;
status = devHwClientInitRecord(pdpvt, &prec->out);
if(status == OK)
......@@ -133,7 +137,7 @@ static long write_value(struct mbboRecord *prec)
pdpvt->info.bumpless = FALSE; /* only once */
if(status == OK)
{
prec->val = (unsigned short)prec->rval; /* SHFT is 0 */
prec->val = (unsigned short)prec->rbv; /* SHFT is 0 */
prec->udf = FALSE;
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment