diff --git a/src/rec/aaoRecord.c b/src/rec/aaoRecord.c index 954df058f..a1a24a302 100644 --- a/src/rec/aaoRecord.c +++ b/src/rec/aaoRecord.c @@ -9,7 +9,6 @@ /* recAao.c - Record Support Routines for Array Analog Out records */ /* * Original Author: Dave Barker - * Date: 10/28/93 * * C E B A F * @@ -18,6 +17,8 @@ * * Copyright SURA CEBAF 1993. * + * Current Author: Dirk Zimoch + * Date: 27-MAY-2010 */ #include @@ -30,12 +31,14 @@ #include "epicsPrint.h" #include "alarm.h" #include "dbAccess.h" +#include "dbEvent.h" #include "dbFldTypes.h" #include "dbScan.h" -#include "dbEvent.h" #include "devSup.h" +#include "errMdef.h" #include "recSup.h" #include "recGbl.h" +#include "cantProceed.h" #include "menuYesNo.h" #define GEN_SIZE_OFFSET #include "aaoRecord.h" @@ -84,43 +87,67 @@ rset aaoRSET={ epicsExportAddress(rset,aaoRSET); struct aaodset { /* aao dset */ - long number; - DEVSUPFUN dev_report; - DEVSUPFUN init; - DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/ - DEVSUPFUN get_ioint_info; - DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/ + long number; + DEVSUPFUN dev_report; + DEVSUPFUN init; + DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/ + DEVSUPFUN get_ioint_info; + DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/ }; static void monitor(aaoRecord *); static long writeValue(aaoRecord *); - static long init_record(aaoRecord *prec, int pass) { - struct aaodset *pdset; long status; + struct aaodset *pdset = (struct aaodset *)(prec->dset); - if (pass == 0) { - if (prec->nelm <= 0) prec->nelm = 1; - return 0; - } - recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm); /* must have dset defined */ - if (!(pdset = (struct aaodset *)(prec->dset))) { - recGblRecordError(S_dev_noDSET, (void *)prec, "aao: init_record"); + if (!pdset) { + recGblRecordError(S_dev_noDSET, prec, "aao: init_record"); return S_dev_noDSET; } + + if (pass == 0) { + if (prec->nelm <= 0) + prec->nelm = 1; + if (prec->ftvl > DBF_ENUM) + prec->ftvl = DBF_UCHAR; + if (prec->nelm == 1) { + prec->nord = 1; + } else { + prec->nord = 0; + } + + /* we must call pdset->init_record in pass 0 + because it may set prec->bptr which must + not change after links are established before pass 1 + */ + + if (pdset->init_record) { + /* init_record may set the bptr to point to the data */ + if ((status = pdset->init_record(prec))) + return status; + } + if (!prec->bptr) { + /* device support did not allocate memory so we must do it */ + prec->bptr = callocMustSucceed(prec->nelm, dbValueSize(prec->ftvl), + "aao: buffer calloc failed"); + } + return 0; + } + + /* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */ + if (prec->siml.type == CONSTANT) { + recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm); + } + /* must have write_aao function defined */ if (pdset->number < 5 || pdset->write_aao == NULL) { - recGblRecordError(S_dev_missingSup, (void *)prec, "aao: init_record"); + recGblRecordError(S_dev_missingSup, prec, "aao: init_record"); return S_dev_missingSup; } - if (pdset->init_record) { - /* init records sets the bptr to point to the data */ - if ((status = pdset->init_record(prec))) - return status; - } return 0; } @@ -132,13 +159,15 @@ static long process(aaoRecord *prec) if (pdset == NULL || pdset->write_aao == NULL) { prec->pact = TRUE; - recGblRecordError(S_dev_missingSup, (void *)prec, "write_aao"); + recGblRecordError(S_dev_missingSup, prec, "write_aao"); return S_dev_missingSup; } if (pact) return 0; status = writeValue(prec); /* write the data */ + if (!pact && prec->pact) return 0; + prec->pact = TRUE; prec->udf = FALSE; recGblGetTimeStamp(prec); @@ -148,7 +177,7 @@ static long process(aaoRecord *prec) recGblFwdLink(prec); prec->pact = FALSE; - return 0; + return status; } static long get_value(aaoRecord *prec, struct valueDes *pvdes) @@ -163,7 +192,7 @@ static long cvt_dbaddr(DBADDR *paddr) { aaoRecord *prec = (aaoRecord *)paddr->precord; - paddr->pfield = (void *)(prec->bptr); + paddr->pfield = prec->bptr; paddr->no_elements = prec->nelm; paddr->field_type = prec->ftvl; paddr->field_size = dbValueSize(prec->ftvl); @@ -175,7 +204,7 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset) { aaoRecord *prec = (aaoRecord *)paddr->precord; - *no_elements = prec->nelm; + *no_elements = prec->nord; *offset = 0; return 0; } @@ -184,7 +213,9 @@ static long put_array_info(DBADDR *paddr, long nNew) { aaoRecord *prec = (aaoRecord *)paddr->precord; - prec->nelm = nNew; + prec->nord = nNew; + if (prec->nord > prec->nelm) + prec->nord = prec->nelm; return 0; } @@ -210,7 +241,7 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd) { aaoRecord *prec = (aaoRecord *)paddr->precord; - if (paddr->pfield == (void *)prec->bptr) { + if (paddr->pfield == prec->bptr) { pgd->upper_disp_limit = prec->hopr; pgd->lower_disp_limit = prec->lopr; } else recGblGetGraphicDouble(paddr,pgd); @@ -221,7 +252,7 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd) { aaoRecord *prec = (aaoRecord *)paddr->precord; - if(paddr->pfield==(void *)prec->bptr){ + if(paddr->pfield == prec->bptr){ pcd->upper_ctrl_limit = prec->hopr; pcd->lower_ctrl_limit = prec->lopr; } else recGblGetControlDouble(paddr,pcd); @@ -253,17 +284,20 @@ static long writeValue(aaoRecord *prec) return status; if (prec->simm == menuYesNoNO) { - /* Call dev support */ - status = pdset->write_aao(prec); - return status; + return pdset->write_aao(prec); } if (prec->simm == menuYesNoYES) { - /* Call dev support */ - status = pdset->write_aao(prec); - return status; + /* Device suport is responsible for buffer + which might be write-only so we may not be + allowed to call dbPutLink on it. + Maybe also device support has an advanced + simulation mode. + Thus call device now. + */ + recGblSetSevr(prec, SIMM_ALARM, INVALID_ALARM); + return pdset->write_aao(prec); } - status = -1; - recGblSetSevr(prec, SIMM_ALARM, INVALID_ALARM); - return status; + recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); + return -1; } diff --git a/src/rec/aaoRecord.dbd b/src/rec/aaoRecord.dbd index 1952f8f5b..ad29fb648 100644 --- a/src/rec/aaoRecord.dbd +++ b/src/rec/aaoRecord.dbd @@ -82,4 +82,9 @@ recordtype(aao) { interest(2) menu(menuAlarmSevr) } + field(SIOL,DBF_OUTLINK) { + prompt("Sim Output Specifctn") + promptgroup(GUI_INPUTS) + interest(1) + } }