Extended Device Support interface.
This commit is contained in:
@@ -13,6 +13,21 @@
|
||||
|
||||
<h2 align="center">Changes since 3.14.7</h2>
|
||||
|
||||
<h4>Runtime Hardware Address Changes</h4>
|
||||
|
||||
<p>An Extended Device Support mechanism has been introduced which is
|
||||
designed as a safe way to widen the API between iocCore and the device
|
||||
support software it interfaces with. An extended device support can
|
||||
now be notified of changes to a record's hardware address, and is
|
||||
given the chance to approve or reject that change.</p>
|
||||
|
||||
<p>As a result of introducing this notification mechanism, any device
|
||||
support that was capable of handling runtime address changes in prior
|
||||
versions of Base will have to be updated to provide the new interface,
|
||||
since the absence of extended device support is now taken to mean that
|
||||
runtime address changes are not understood by the device support.
|
||||
This requirement is not expected to affect many EPICS sites.</p>
|
||||
|
||||
<h4>POSIX thread priority scheduling</h4>
|
||||
<p>POSIX thread priority scheduling is now supported. There is a new
|
||||
user option USE_POSIX_THREAD_PRIORITY_SCHEDULING in the CONFIG_SITE
|
||||
@@ -32,6 +47,7 @@ should contain location definitions for EPICS modules only.</p>
|
||||
configure/RELEASE and moved to configure/os/CONFIG_SITE.Common.RTEMS. The
|
||||
configure/RELEASE* files should contain location definitions for EPICS modules
|
||||
only.</p>
|
||||
|
||||
<h4>event generator and event receiver record support </h3>
|
||||
All apsEvent specific record support has been removed from base
|
||||
|
||||
@@ -51,7 +67,6 @@ of the standard tasks failed. This is because they were passing
|
||||
their threadid rather than using epicsThreadGetIdSelf.
|
||||
It was possible to call taskwdInsert before the threadid was actually set.</p>
|
||||
|
||||
|
||||
<h4>dbLock and dbBkpt</h4>
|
||||
<p>dbLockGetLockId incorrectly always returned 0. dbBkpt (database breakpoint
|
||||
facility) is the only code that needed this. This caused unknown errors
|
||||
@@ -63,7 +78,6 @@ if the dbBkpt facility is used.</p>
|
||||
<h4>epicsExport.h</h4>
|
||||
<p>Add additional cast to prevent 'strict aliaising' warnings.</p>
|
||||
|
||||
|
||||
<h4>iocsh</h4>
|
||||
<p>I/O redirection from vxWorks startup scripts now works.</p>
|
||||
|
||||
@@ -83,7 +97,6 @@ server required.</p>
|
||||
<p>Set IOC_NAME and IOC_STARTUP_SCRIPT environment variables from bootstrap
|
||||
parameters.</p>
|
||||
|
||||
|
||||
<h4>OS X</h4>
|
||||
<p>Builds on Tiger.</p>
|
||||
<p>Readline now used by default.</p>
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "link.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "recSup.h"
|
||||
#include "devSup.h"
|
||||
#include "caeventmask.h"
|
||||
#include "db_field_log.h"
|
||||
#include "dbCommon.h"
|
||||
@@ -1029,6 +1030,188 @@ long epicsShareAPI dbGet(DBADDR *paddr,short dbrType,
|
||||
return(status);
|
||||
}
|
||||
|
||||
devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *pdbRecordType, int dtyp) {
|
||||
return (devSup *)ellNth(&pdbRecordType->devList, dtyp+1);
|
||||
}
|
||||
|
||||
devSup* epicsShareAPI dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset) {
|
||||
devSup *pdevSup = (devSup *)ellFirst(&prdes->devList);
|
||||
while (pdevSup) {
|
||||
if (pdset == pdevSup->pdset) return pdevSup;
|
||||
pdevSup = (devSup *)ellNext(&pdevSup->node);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static long dbPutFieldLink(
|
||||
DBADDR *paddr,short dbrType,const void *pbuffer,long nRequest)
|
||||
{
|
||||
long status = 0;
|
||||
long special=paddr->special;
|
||||
dbCommon *precord = (dbCommon *)(paddr->precord);
|
||||
DBLINK *plink = (DBLINK *)paddr->pfield;
|
||||
const char *pstring = (const char *)pbuffer;
|
||||
DBENTRY dbEntry;
|
||||
dbFldDes *pfldDes = (dbFldDes *)paddr->pfldDes;
|
||||
DBADDR dbaddr;
|
||||
devSup *pdevSup = NULL;
|
||||
struct dset *new_dset = NULL;
|
||||
struct dsxt *new_dsxt = NULL;
|
||||
int inpOut;
|
||||
short scan;
|
||||
|
||||
if ((dbrType!=DBR_STRING) && (dbrType!=DBR_CHAR) && (dbrType!=DBR_UCHAR))
|
||||
return S_db_badDbrtype;
|
||||
|
||||
if (((dbrType==DBR_CHAR) || (dbrType==DBR_UCHAR)) &&
|
||||
(pstring[nRequest] != '\0'))
|
||||
return S_db_badField;
|
||||
|
||||
dbInitEntry(pdbbase,&dbEntry);
|
||||
status=dbFindRecord(&dbEntry,precord->name);
|
||||
if (!status) status=dbFindField(&dbEntry,pfldDes->name);
|
||||
if (status) return status;
|
||||
|
||||
inpOut = !(strcmp(pfldDes->name,"INP") && strcmp(pfldDes->name,"OUT"));
|
||||
|
||||
dbLockSetGblLock();
|
||||
dbLockSetRecordLock(precord);
|
||||
|
||||
if (inpOut) {
|
||||
pdevSup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
|
||||
if (pdevSup == NULL ||
|
||||
(new_dset = pdevSup->pdset) == NULL ||
|
||||
(new_dsxt = pdevSup->pdsxt) == NULL ||
|
||||
new_dsxt->add_record == NULL ||
|
||||
(precord->dset &&
|
||||
((pdevSup = dbDSETtoDevSup(precord->rdes, precord->dset)) == NULL ||
|
||||
pdevSup->pdsxt == NULL ||
|
||||
pdevSup->pdsxt->del_record == NULL))) {
|
||||
status = S_db_noSupport;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
scan = precord->scan;
|
||||
if (inpOut && (scan==SCAN_IO_EVENT)) {
|
||||
scanDelete(precord);
|
||||
precord->scan = SCAN_PASSIVE;
|
||||
}
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
case CONSTANT:
|
||||
break; /* do nothing */
|
||||
|
||||
case PV_LINK:
|
||||
case MACRO_LINK:
|
||||
break; /* should never get here */
|
||||
|
||||
default: /* Hardware address */
|
||||
if (!inpOut)
|
||||
status = S_db_badHWaddr;
|
||||
else
|
||||
status = pdevSup->pdsxt->del_record(precord);
|
||||
if (status) goto restoreScan;
|
||||
break;
|
||||
}
|
||||
|
||||
if (special) status = putSpecial(paddr,0);
|
||||
if (!status) status=dbPutString(&dbEntry,pstring);
|
||||
|
||||
if (inpOut) {
|
||||
precord->dset = new_dset;
|
||||
precord->dpvt = NULL;
|
||||
precord->pact = FALSE;
|
||||
}
|
||||
|
||||
if (!status && special) status = putSpecial(paddr,1);
|
||||
if (status) goto restoreScan;
|
||||
|
||||
switch (plink->type) { /* New link type */
|
||||
case PV_LINK:
|
||||
if (plink==&precord->tsel) recGblTSELwasModified(plink);
|
||||
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 = dbCalloc(1,sizeof(struct dbAddr));
|
||||
*pdbAddr = dbaddr; /* NB: structure copy */;
|
||||
plink->value.pv_link.precord = precord;
|
||||
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;
|
||||
plink->value.pv_link.precord = precord;
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CONSTANT:
|
||||
break;
|
||||
|
||||
case DB_LINK:
|
||||
case CA_LINK:
|
||||
case MACRO_LINK:
|
||||
break; /* should never get here */
|
||||
|
||||
default: /* Hardware address */
|
||||
if (!inpOut)
|
||||
status = S_db_badHWaddr;
|
||||
else
|
||||
status = new_dsxt->add_record(precord);
|
||||
if (status) {
|
||||
precord->dset = 0;
|
||||
precord->pact = TRUE;
|
||||
goto restoreScan;
|
||||
}
|
||||
break;
|
||||
}
|
||||
db_post_events(precord,plink,DBE_VALUE|DBE_LOG);
|
||||
|
||||
restoreScan:
|
||||
if (inpOut && (scan==SCAN_IO_EVENT)) { /* undo scanDelete() */
|
||||
precord->scan = scan;
|
||||
scanAdd(precord);
|
||||
}
|
||||
if (scan != precord->scan)
|
||||
db_post_events(precord, &precord->scan, DBE_VALUE|DBE_LOG);
|
||||
unlock:
|
||||
dbLockSetGblUnlock();
|
||||
dbFinishEntry(&dbEntry);
|
||||
return status;
|
||||
}
|
||||
|
||||
long epicsShareAPI dbPutField(
|
||||
DBADDR *paddr,short dbrType,const void *pbuffer,long nRequest)
|
||||
{
|
||||
@@ -1038,107 +1221,17 @@ long epicsShareAPI dbPutField(
|
||||
dbCommon *precord = (dbCommon *)(paddr->precord);
|
||||
short dbfType = paddr->field_type;
|
||||
|
||||
if(special==SPC_ATTRIBUTE) return(S_db_noMod);
|
||||
if(special==SPC_ATTRIBUTE)
|
||||
return S_db_noMod;
|
||||
|
||||
/*check for putField disabled*/
|
||||
if(precord->disp) {
|
||||
if((void *)(&precord->disp) != paddr->pfield) return(S_db_putDisabled);
|
||||
}
|
||||
if(dbfType>=DBF_INLINK && dbfType<=DBF_FWDLINK) {
|
||||
DBLINK *plink = (DBLINK *)paddr->pfield;
|
||||
DBENTRY dbEntry;
|
||||
dbFldDes *pfldDes = (dbFldDes *)paddr->pfldDes;
|
||||
char buffer[MAX_STRING_SIZE+2];
|
||||
int len,j;
|
||||
char *lastblank;
|
||||
if (precord->disp &&
|
||||
(void *)(&precord->disp) != paddr->pfield)
|
||||
return(S_db_putDisabled);
|
||||
|
||||
if(dbrType!=DBR_STRING) return(S_db_badDbrtype);
|
||||
/*begin kludge for old db_access MAX_STRING_SIZE*/
|
||||
/*Allow M for MS and (N or NM) for NMS */
|
||||
if(strlen((char *)pbuffer)>=MAX_STRING_SIZE) {
|
||||
errlogPrintf("dbPutField input string length >= MAX_STRING_SIZE");
|
||||
return(S_db_badField);
|
||||
}
|
||||
strncpy(buffer,(char *)pbuffer,MAX_STRING_SIZE);
|
||||
buffer[MAX_STRING_SIZE] = 0;
|
||||
/*Strip trailing blanks*/
|
||||
len = strlen(buffer);
|
||||
for(j=len-1; j>0; j--) {
|
||||
if(buffer[j]==' ')
|
||||
buffer[j] = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
lastblank = strrchr(buffer,' ');
|
||||
if(lastblank) {
|
||||
if(strcmp(lastblank,"M")==0) {
|
||||
strcpy(lastblank,"MS");
|
||||
} else {
|
||||
if((strcmp(lastblank,"N")==0) || (strcmp(lastblank,"NM")==0)) {
|
||||
strcpy(lastblank,"NMS");
|
||||
}
|
||||
}
|
||||
}
|
||||
/*End kludge for old db_access MAX_STRING_SIZE*/
|
||||
dbLockSetGblLock();
|
||||
dbLockSetRecordLock(precord);
|
||||
if((plink->type == DB_LINK)||(plink->type == CA_LINK)) {
|
||||
if(plink->type == DB_LINK) {
|
||||
free(plink->value.pv_link.pvt);
|
||||
plink->value.pv_link.pvt = 0;
|
||||
plink->type = PV_LINK;
|
||||
dbLockSetSplit(precord);
|
||||
} else if(plink->type == CA_LINK) {
|
||||
dbCaRemoveLink(plink);
|
||||
}
|
||||
plink->value.pv_link.getCvt = 0;
|
||||
plink->value.pv_link.pvlMask = 0;
|
||||
plink->value.pv_link.lastGetdbrType = 0;
|
||||
plink->type = PV_LINK;
|
||||
}
|
||||
dbInitEntry(pdbbase,&dbEntry);
|
||||
status=dbFindRecord(&dbEntry,precord->name);
|
||||
if(!status) status=dbFindField(&dbEntry,pfldDes->name);
|
||||
if(!status && special) status = putSpecial(paddr,0);
|
||||
if(!status) status=dbPutString(&dbEntry,buffer);
|
||||
dbFinishEntry(&dbEntry);
|
||||
if(!status && special) status = putSpecial(paddr,1);
|
||||
if(status) goto done;
|
||||
if(plink->type == PV_LINK) {
|
||||
DBADDR dbaddr;
|
||||
if(dbfType>=DBF_INLINK && dbfType<=DBF_FWDLINK)
|
||||
return dbPutFieldLink(paddr,dbrType,pbuffer,nRequest);
|
||||
|
||||
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.precord = precord;
|
||||
plink->value.pv_link.pvt = pdbAddr;
|
||||
dbLockSetRecordLock(pdbAddr->precord);
|
||||
dbLockSetMerge(precord,pdbAddr->precord);
|
||||
} else {/*It is a CA link*/
|
||||
char *pperiod;
|
||||
|
||||
plink->type = CA_LINK;
|
||||
plink->value.pv_link.precord = precord;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
db_post_events(precord,plink,DBE_VALUE|DBE_LOG);
|
||||
done:
|
||||
dbLockSetGblUnlock();
|
||||
return(status);
|
||||
}
|
||||
dbScanLock(precord);
|
||||
status=dbPut(paddr,dbrType,pbuffer,nRequest);
|
||||
if(status==0){
|
||||
|
||||
@@ -184,6 +184,7 @@ struct dbr_alDouble {DBRalDouble};
|
||||
|
||||
#define S_db_Blocked (M_dbAccess|39) /*Request is Blocked*/
|
||||
#define S_db_putDisabled (M_dbAccess|41) /*putFields are disabled*/
|
||||
#define S_db_badHWaddr (M_dbAccess|43) /*Hardware link type not on INP/OUT*/
|
||||
#define S_db_bkptSet (M_dbAccess|53) /*Breakpoint already set*/
|
||||
#define S_db_bkptNotSet (M_dbAccess|55) /*No breakpoint set in record*/
|
||||
#define S_db_notStopped (M_dbAccess|57) /*Record not stopped*/
|
||||
@@ -227,6 +228,8 @@ 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(
|
||||
|
||||
@@ -41,6 +41,7 @@ typedef struct devSup {
|
||||
int link_type;
|
||||
/*Following only available on run time system*/
|
||||
struct dset *pdset;
|
||||
struct dsxt *pdsxt; /* Extended device support */
|
||||
}devSup;
|
||||
|
||||
typedef struct dbDeviceMenu {
|
||||
|
||||
@@ -3798,6 +3798,7 @@ void epicsShareAPI dbDumpDevice(DBBASE *pdbbase,const char *recordTypeName)
|
||||
printf("\t choice: %s\n",pdevSup->choice);
|
||||
printf("\tlink_type: %d\n",pdevSup->link_type);
|
||||
printf("\t pdset: %p\n",(void *)pdevSup->pdset);
|
||||
printf("\t pdsxt: %p\n",(void *)pdevSup->pdsxt);
|
||||
}
|
||||
if(recordTypeName) break;
|
||||
}
|
||||
|
||||
@@ -27,12 +27,19 @@ typedef long (*DEVSUPFUN)(); /* ptr to device support function*/
|
||||
typedef struct dset { /* device support entry table */
|
||||
long number; /*number of support routines*/
|
||||
DEVSUPFUN report; /*print report*/
|
||||
DEVSUPFUN init; /*init support*/
|
||||
DEVSUPFUN init_record; /*init support for particular record*/
|
||||
DEVSUPFUN init; /*init support layer*/
|
||||
DEVSUPFUN init_record; /*init device for particular record*/
|
||||
DEVSUPFUN get_ioint_info; /* get io interrupt information*/
|
||||
/*other functions are record dependent*/
|
||||
}dset;
|
||||
|
||||
struct dbCommon;
|
||||
typedef struct dsxt { /* device support extension table */
|
||||
long (*add_record)(struct dbCommon *precord);
|
||||
long (*del_record)(struct dbCommon *precord);
|
||||
/* Recordtypes are *not* allowed to extend this table */
|
||||
} dsxt;
|
||||
|
||||
#define S_dev_noDevSup (M_devSup| 1) /*SDR_DEVSUP: Device support missing*/
|
||||
#define S_dev_noDSET (M_devSup| 3) /*Missing device support entry table*/
|
||||
#define S_dev_missingSup (M_devSup| 5) /*Missing device support routine*/
|
||||
@@ -46,6 +53,12 @@ typedef struct dset { /* device support entry table */
|
||||
#define S_dev_Conflict (M_devSup|21) /*Multiple records accessing same signal*/
|
||||
#define S_dev_noDeviceFound (M_devSup|23) /*No device found at specified address*/
|
||||
|
||||
|
||||
/* This routine is defined in src/misc/iocInit.c */
|
||||
|
||||
extern void devExtend(dsxt *pdsxt);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
@@ -178,42 +178,62 @@ LOCAL void initRecSup(void)
|
||||
return;
|
||||
}
|
||||
|
||||
static long do_nothing(struct dbCommon *precord) { return 0; }
|
||||
|
||||
/* Dummy DSXT used for soft device supports */
|
||||
struct dsxt devSoft_DSXT = {
|
||||
do_nothing,
|
||||
do_nothing
|
||||
};
|
||||
|
||||
LOCAL devSup *pthisDevSup = NULL;
|
||||
|
||||
LOCAL void initDevSup(void)
|
||||
{
|
||||
dbRecordType *pdbRecordType;
|
||||
devSup *pdevSup;
|
||||
struct dset *pdset;
|
||||
|
||||
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
pdbRecordType;
|
||||
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||||
for(pdevSup = (devSup *)ellFirst(&pdbRecordType->devList); pdevSup;
|
||||
pdevSup = (devSup *)ellNext(&pdevSup->node)) {
|
||||
pdset = registryDeviceSupportFind(pdevSup->name);
|
||||
for (pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
pdbRecordType;
|
||||
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||||
for (pthisDevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
pthisDevSup;
|
||||
pthisDevSup = (devSup *)ellNext(&pthisDevSup->node)) {
|
||||
pdset = registryDeviceSupportFind(pthisDevSup->name);
|
||||
if (pdset==0) {
|
||||
errlogPrintf("device support %s not found\n",pdevSup->name);
|
||||
errlogPrintf("device support %s not found\n",pthisDevSup->name);
|
||||
continue;
|
||||
}
|
||||
pdevSup->pdset = pdset;
|
||||
if(pdset->init) (*pdset->init)(0);
|
||||
if (pthisDevSup->link_type == CONSTANT)
|
||||
pthisDevSup->pdsxt = &devSoft_DSXT;
|
||||
pthisDevSup->pdset = pdset;
|
||||
if (pdset->init) (*pdset->init)(0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void devExtend(dsxt *pdsxt)
|
||||
{
|
||||
if (!pthisDevSup)
|
||||
errlogPrintf("devExtend() called outside of initDevSup()\n");
|
||||
else
|
||||
pthisDevSup->pdsxt = pdsxt;
|
||||
}
|
||||
|
||||
LOCAL void finishDevSup(void)
|
||||
{
|
||||
dbRecordType *pdbRecordType;
|
||||
devSup *pdevSup;
|
||||
struct dset *pdset;
|
||||
|
||||
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
pdbRecordType;
|
||||
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||||
for(pdevSup = (devSup *)ellFirst(&pdbRecordType->devList); pdevSup;
|
||||
pdevSup = (devSup *)ellNext(&pdevSup->node)) {
|
||||
if(!(pdset = pdevSup->pdset)) continue;
|
||||
if(pdset->init) (*pdset->init)(1);
|
||||
for (pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
pdbRecordType;
|
||||
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||||
for (pthisDevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
pthisDevSup;
|
||||
pthisDevSup = (devSup *)ellNext(&pthisDevSup->node)) {
|
||||
pdset = pthisDevSup->pdset;
|
||||
if (pdset && pdset->init) (*pdset->init)(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -253,7 +273,7 @@ LOCAL void initDatabase(void)
|
||||
precord->pact=FALSE;
|
||||
|
||||
/* Init DSET NOTE that result may be NULL */
|
||||
pdevSup = (devSup *)ellNth(&pdbRecordType->devList,precord->dtyp+1);
|
||||
pdevSup = dbDTYPtoDevSup(pdbRecordType,precord->dtyp);
|
||||
pdset = (pdevSup ? pdevSup->pdset : 0);
|
||||
precord->dset = pdset;
|
||||
if(prset->init_record) (*prset->init_record)(precord,0);
|
||||
@@ -306,6 +326,12 @@ LOCAL void initDatabase(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
pdevSup = dbDTYPtoDevSup(pdbRecordType,precord->dtyp);
|
||||
if (pdevSup) {
|
||||
struct dsxt *pdsxt = pdevSup->pdsxt;
|
||||
if (pdsxt && pdsxt->add_record)
|
||||
(*pdsxt->add_record)(precord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user