Merge lp:~dirk.zimoch/epics-base/fix-aai-and-aao into lp:~epics-core/epics-base/3.14

Proposed by Dirk Zimoch
Status: Merged
Approved by: Andrew Johnson
Approved revision: 12079
Merge reported by: Andrew Johnson
Merged at revision: not available
Proposed branch: lp:~dirk.zimoch/epics-base/fix-aai-and-aao
Merge into: lp:~epics-core/epics-base/3.14
Diff against target: 895 lines (+434/-101)
10 files modified
documentation/RELEASE_NOTES.html (+7/-0)
src/dev/softDev/Makefile (+2/-0)
src/dev/softDev/devAaiSoft.c (+87/-0)
src/dev/softDev/devAaoSoft.c (+79/-0)
src/dev/softDev/devSoft.dbd (+2/-0)
src/misc/base.dbd (+2/-0)
src/rec/aaiRecord.c (+103/-52)
src/rec/aaiRecord.dbd (+25/-0)
src/rec/aaoRecord.c (+102/-49)
src/rec/aaoRecord.dbd (+25/-0)
To merge this branch: bzr merge lp:~dirk.zimoch/epics-base/fix-aai-and-aao
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Review via email: mp+26195@code.launchpad.net

This proposal supersedes a proposal from 2010-05-27.

Description of the change

* Bugfix: writing to aai/aao via db link crashed ioc. Memory allocation / device support init_record moved to pass 0.
* Soft device support for aai and aao added.
* Simulation mode fixed. SIOL link added. (sim handling is done in devsup!)
* Bugfix: writing to aai/aao modified NELM. Modify NORD instead.
* Hashing added to minimize monitor updates (like in waveform record)

Discussion:
Add features like RVAL->VAL conversion, scaling, smoothing, alarm limits?

To post a comment you must log in.
12076. By Dirk Zimoch <dirk@ubuntu>

release notes updated

12077. By Dirk Zimoch <dirk@ubuntu>

Merged with 3.14

Revision history for this message
Ralph Lange (ralph-lange) wrote : Posted in a previous version of this proposal

Looked at the code - the changes look fine to me.

As I never used the aai/aao records, I don't see me being the right person for testing and proper evaluation of the changes in behaviour, though.

Revision history for this message
Andrew Johnson (anj) wrote :

Hi Dirk,

When SIMM=YES, the aai record is put into alarm using the SIMS field for the severity. The aao record always goes to INVALID_ALARM in simulation mode.

Do you know under what circumstances a device support might want to set BPTR itself? The comment about calling the pdset->init_record() in pass 0 implies that run-time changes of the device address wouldn't be possible in that case (which is in the device support's power to allow if it uses devExtend(), but prevented if it doesn't).

Have you ever seen any written documentation for the aai/aao record types? There are no chapters for them in the Record Reference wiki yet.

I haven't started actually testing this code yet (that's my next task), but so far I think this work should be merged into R3.14.12.

- Andrew

Revision history for this message
Ben Franksen (bfrk) wrote :

On Freitag, 2. Juli 2010, Andrew Johnson wrote:
> Do you know under what circumstances a device support might want to set
> BPTR itself?

Slightly off-topic, but I suggest removing BPTR and use VAL field instead.
VAL is not used for anything at the moment, AFAIR, and is also
DBF_NOACCESS, so this is even compatible (but not for device support, maybe
this is the reason this hasn't been done before?).

Same for waveform record, BTW.

Cheers
Ben

Revision history for this message
Andrew Johnson (anj) wrote :

Hi Ben,

Interesting point, although not relevant to the review of this particular branch. Making that change to the records would require a corresponding modification to all device supports, so it's not something I'd want to do for 3.14.12. I guess removing the BPTR fields completely would cause any unmodified code to fail at compile-time (which is what we'd want), so it's not an impossible idea for 3.15.

Thanks,

- Andrew

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

Andrew,

> The aao record always goes to INVALID_ALARM in simulation mode.
I missed that. It should use the SIMS field as well. As soon as I get bazaar installed on this computer, I will fix that.

I have never seen documentation on the aai/aao records, but I guess that the intention was to set BPTR directly to memory mapped register space to save the time for copying data. But this has several disadvantages:
* BPTR must be set early enough (fixed now)
* BPTR must not change at run time (e.g. no double buffering). I have to check what devExtend() does to solve this problem.
* As a result, BPTR may contain inconsistent data if the hardware modifies the buffer while it is being read (e.g. by a CA read or monitor)

I kept the memory allocation model to stay compatible to old device supports. Additionally I allow for new device supports not to set BPTR. Also to stay compatible, I do not want to switch from BPTR to VAL.

Basically the aai is the same as the waveform record except that it does not have a RARM field. The aao is the only record that is intended to write arrays. (The waveform can write through its INP if the device support allows. But if we do so, why do we need ai/ao, mbbi/mbbo, etc. pairs?)

Revision history for this message
Andrew Johnson (anj) wrote :

On Monday 05 July 2010 03:02:23 Dirk Zimoch wrote:
>
> * BPTR must not change at run time (e.g. no double buffering). I have to
> check what devExtend() does to solve this problem.

Sorry, devExtend() is the way that a device support tells the iocCore code
that it can accept address changes at runtime; it doesn't solve that problem.
The devExtend() routine must be called from a dset->init() routine and points
to a dsxt structure with the add_record() and del_record() routines that
support those runtime changes for this device support. My point was merely
that if BPTR can't be changed after rset->init_record(0) returns [presumably
because this somehow stops DB links from working] that it's not going to be
possible to have extended device support that sets BPTR. Not a major issue,
and there are no incompatibilities here.

> I kept the memory allocation model to stay compatible to old device
> supports. Additionally I allow for new device supports not to set BPTR.
> Also to stay compatible, I do not want to switch from BPTR to VAL.

I agree that this is the best solution for now.

Thanks,

- Andrew
--
The best FOSS code is written to be read by other humans -- Harald Welte

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

What we really need to make this work as intended, i.e. modify BPTR at run-time to point to the current data, is a way to tell a link, a CA connection, and maybe other EPICS components that the address of the data has changed. But this is a completely different problem.

12078. By Dirk Zimoch <dirk@ubuntu>

Bugfix: use SIMS for simulation severity

12079. By Dirk Zimoch <dirk@ubuntu>

Merged with mirror-3.14

Revision history for this message
Andrew Johnson (anj) wrote :

Asynchronous processing doesn't work because of the line
    if (pact) return 0;
in the process() routines of both record types.

With those lines removed I'm happy with the result, so I will merge the code.

Thanks,

- Andrew

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'documentation/RELEASE_NOTES.html'
2--- documentation/RELEASE_NOTES.html 2010-07-01 16:59:22 +0000
3+++ documentation/RELEASE_NOTES.html 2010-07-07 17:48:44 +0000
4@@ -11,6 +11,13 @@
5
6 <h2 align="center">Changes between 3.14.11 and 3.14.12</h2>
7 <!-- Insert new items immediately below here ... -->
8+<h4>Record Types aai and aao</h4>
9+<p>Fixed bug in memory allocation that caused crashes when linking other records
10+to aai or aao.
11+Fixed bug where NELM was modified instead of NORD.
12+Added Soft Channel device support.
13+Added SIOL link and proper simulation mode for Soft Channel support.
14+Added MPST, APST and HASH fields for monitor on change support like in waveform record.
15
16
17 <h4>devLib cleanup</h4>
18
19=== modified file 'src/dev/softDev/Makefile'
20--- src/dev/softDev/Makefile 2008-09-24 22:40:37 +0000
21+++ src/dev/softDev/Makefile 2010-07-07 17:48:44 +0000
22@@ -12,6 +12,8 @@
23
24 DBD += devSoft.dbd
25
26+LIBSRCS += devAaiSoft.c
27+LIBSRCS += devAaoSoft.c
28 LIBSRCS += devAiSoft.c
29 LIBSRCS += devAiSoftRaw.c
30 LIBSRCS += devAoSoft.c
31
32=== added file 'src/dev/softDev/devAaiSoft.c'
33--- src/dev/softDev/devAaiSoft.c 1970-01-01 00:00:00 +0000
34+++ src/dev/softDev/devAaiSoft.c 2010-07-07 17:48:44 +0000
35@@ -0,0 +1,87 @@
36+/*************************************************************************\
37+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
38+* National Laboratory.
39+* Copyright (c) 2002 The Regents of the University of California, as
40+* Operator of Los Alamos National Laboratory.
41+* EPICS BASE is distributed subject to a Software License Agreement found
42+* in file LICENSE that is included with this distribution.
43+\*************************************************************************/
44+
45+/* $Id$
46+ * devAaiSoft.c - Device Support Routines for soft Waveform Records
47+ *
48+ * Original Author: Bob Dalesio
49+ * Current Author: Dirk Zimoch
50+ * Date: 27-MAY-2010
51+ */
52+
53+#include <stdlib.h>
54+#include <stdio.h>
55+#include <string.h>
56+
57+#include "alarm.h"
58+#include "dbDefs.h"
59+#include "dbAccess.h"
60+#include "recGbl.h"
61+#include "devSup.h"
62+#include "cantProceed.h"
63+#include "menuYesNo.h"
64+#include "aaiRecord.h"
65+#include "epicsExport.h"
66+
67+/* Create the dset for devAaiSoft */
68+static long init_record();
69+static long read_aai();
70+
71+struct {
72+ long number;
73+ DEVSUPFUN report;
74+ DEVSUPFUN init;
75+ DEVSUPFUN init_record;
76+ DEVSUPFUN get_ioint_info;
77+ DEVSUPFUN read_aai;
78+} devAaiSoft = {
79+ 5,
80+ NULL,
81+ NULL,
82+ init_record,
83+ NULL,
84+ read_aai
85+};
86+epicsExportAddress(dset,devAaiSoft);
87+
88+static long init_record(aaiRecord *prec)
89+{
90+ /* INP must be a CONSTANT or a PV_LINK or a DB_LINK or a CA_LINK*/
91+ switch (prec->inp.type) {
92+ case CONSTANT:
93+ prec->nord = 0;
94+ break;
95+ case PV_LINK:
96+ case DB_LINK:
97+ case CA_LINK:
98+ break;
99+ default :
100+ recGblRecordError(S_db_badField, (void *)prec,
101+ "devAaiSoft (init_record) Illegal INP field");
102+ return(S_db_badField);
103+ }
104+ return 0;
105+}
106+
107+static long read_aai(aaiRecord *prec)
108+{
109+ long nRequest = prec->nelm;
110+
111+ dbGetLink(prec->simm == menuYesNoYES ? &prec->siol : &prec->inp,
112+ prec->ftvl, prec->bptr, 0, &nRequest);
113+ if (nRequest > 0) {
114+ prec->nord = nRequest;
115+ prec->udf=FALSE;
116+ if (prec->tsel.type == CONSTANT &&
117+ prec->tse == epicsTimeEventDeviceTime)
118+ dbGetTimeStamp(&prec->inp, &prec->time);
119+ }
120+
121+ return 0;
122+}
123
124=== added file 'src/dev/softDev/devAaoSoft.c'
125--- src/dev/softDev/devAaoSoft.c 1970-01-01 00:00:00 +0000
126+++ src/dev/softDev/devAaoSoft.c 2010-07-07 17:48:44 +0000
127@@ -0,0 +1,79 @@
128+/*************************************************************************\
129+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
130+* National Laboratory.
131+* Copyright (c) 2002 The Regents of the University of California, as
132+* Operator of Los Alamos National Laboratory.
133+* EPICS BASE is distributed subject to a Software License Agreement found
134+* in file LICENSE that is included with this distribution.
135+\*************************************************************************/
136+
137+/* $Id$
138+ * devAaoSoft.c - Device Support Routines for soft Waveform Records
139+ *
140+ * Original Author: Bob Dalesio
141+ * Current Author: Dirk Zimoch
142+ * Date: 27-MAY-2010
143+ */
144+
145+#include <stdlib.h>
146+#include <stdio.h>
147+#include <string.h>
148+
149+#include "alarm.h"
150+#include "dbDefs.h"
151+#include "dbAccess.h"
152+#include "recGbl.h"
153+#include "devSup.h"
154+#include "cantProceed.h"
155+#include "menuYesNo.h"
156+#include "aaoRecord.h"
157+#include "epicsExport.h"
158+
159+/* Create the dset for devAaoSoft */
160+static long init_record();
161+static long write_aao();
162+
163+struct {
164+ long number;
165+ DEVSUPFUN report;
166+ DEVSUPFUN init;
167+ DEVSUPFUN init_record;
168+ DEVSUPFUN get_ioint_info;
169+ DEVSUPFUN read_aao;
170+} devAaoSoft = {
171+ 5,
172+ NULL,
173+ NULL,
174+ init_record,
175+ NULL,
176+ write_aao
177+};
178+epicsExportAddress(dset,devAaoSoft);
179+
180+static long init_record(aaoRecord *prec)
181+{
182+ /* OUT must be a CONSTANT or a PV_LINK or a DB_LINK or a CA_LINK*/
183+ switch (prec->out.type) {
184+ case CONSTANT:
185+ prec->nord = 0;
186+ break;
187+ case PV_LINK:
188+ case DB_LINK:
189+ case CA_LINK:
190+ break;
191+ default :
192+ recGblRecordError(S_db_badField, prec,
193+ "devAaoSoft (init_record) Illegal OUT field");
194+ return(S_db_badField);
195+ }
196+ return 0;
197+}
198+
199+static long write_aao(aaoRecord *prec)
200+{
201+ long nRequest = prec->nord;
202+ dbPutLink(prec->simm == menuYesNoYES ? &prec->siol : &prec->out,
203+ prec->ftvl, prec->bptr, nRequest);
204+
205+ return 0;
206+}
207
208=== modified file 'src/dev/softDev/devSoft.dbd'
209--- src/dev/softDev/devSoft.dbd 2008-09-24 22:40:37 +0000
210+++ src/dev/softDev/devSoft.dbd 2010-07-07 17:48:44 +0000
211@@ -1,3 +1,5 @@
212+device(aai,CONSTANT,devAaiSoft,"Soft Channel")
213+device(aao,CONSTANT,devAaoSoft,"Soft Channel")
214 device(ai,CONSTANT,devAiSoft,"Soft Channel")
215 device(ao,CONSTANT,devAoSoft,"Soft Channel")
216 device(bi,CONSTANT,devBiSoft,"Soft Channel")
217
218=== modified file 'src/misc/base.dbd'
219--- src/misc/base.dbd 2008-08-14 20:41:05 +0000
220+++ src/misc/base.dbd 2010-07-07 17:48:44 +0000
221@@ -8,6 +8,8 @@
222 include "menuConvert.dbd"
223
224 # Record types
225+include "aaiRecord.dbd"
226+include "aaoRecord.dbd"
227 include "aiRecord.dbd"
228 include "aoRecord.dbd"
229 include "aSubRecord.dbd"
230
231=== modified file 'src/rec/aaiRecord.c'
232--- src/rec/aaiRecord.c 2009-07-08 18:14:11 +0000
233+++ src/rec/aaiRecord.c 2010-07-07 17:48:44 +0000
234@@ -9,7 +9,6 @@
235 /* recAai.c - Record Support Routines for Array Analog In records */
236 /*
237 * Original Author: Dave Barker
238- * Date: 10/24/93
239 *
240 * C E B A F
241 *
242@@ -18,6 +17,8 @@
243 *
244 * Copyright SURA CEBAF 1993.
245 *
246+ * Current Author: Dirk Zimoch <dirk.zimoch@psi.ch>
247+ * Date: 27-MAY-2010
248 */
249
250 #include <stddef.h>
251@@ -28,14 +29,17 @@
252
253 #include "dbDefs.h"
254 #include "epicsPrint.h"
255+#include "epicsString.h"
256 #include "alarm.h"
257 #include "dbAccess.h"
258+#include "dbEvent.h"
259+#include "dbFldTypes.h"
260 #include "dbScan.h"
261-#include "dbEvent.h"
262 #include "devSup.h"
263 #include "errMdef.h"
264 #include "recSup.h"
265 #include "recGbl.h"
266+#include "cantProceed.h"
267 #include "menuYesNo.h"
268 #define GEN_SIZE_OFFSET
269 #include "aaiRecord.h"
270@@ -48,7 +52,7 @@
271 static long init_record(aaiRecord *, int);
272 static long process(aaiRecord *);
273 #define special NULL
274-static long get_value(aaiRecord *, struct valueDes *);
275+#define get_value NULL
276 static long cvt_dbaddr(DBADDR *);
277 static long get_array_info(DBADDR *, long *, long *);
278 static long put_array_info(DBADDR *, long);
279@@ -84,43 +88,67 @@
280 epicsExportAddress(rset,aaiRSET);
281
282 struct aaidset { /* aai dset */
283- long number;
284- DEVSUPFUN dev_report;
285- DEVSUPFUN init;
286- DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
287- DEVSUPFUN get_ioint_info;
288- DEVSUPFUN read_aai; /*returns: (-1,0)=>(failure,success)*/
289+ long number;
290+ DEVSUPFUN dev_report;
291+ DEVSUPFUN init;
292+ DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
293+ DEVSUPFUN get_ioint_info;
294+ DEVSUPFUN read_aai; /*returns: (-1,0)=>(failure,success)*/
295 };
296
297 static void monitor(aaiRecord *);
298 static long readValue(aaiRecord *);
299
300-
301 static long init_record(aaiRecord *prec, int pass)
302 {
303- struct aaidset *pdset;
304 long status;
305+ struct aaidset *pdset = (struct aaidset *)(prec->dset);
306
307+ /* must have dset defined */
308+ if (!pdset) {
309+ recGblRecordError(S_dev_noDSET, prec, "aai: init_record");
310+ return S_dev_noDSET;
311+ }
312+
313 if (pass == 0) {
314- if (prec->nelm <= 0) prec->nelm = 1;
315+ if (prec->nelm <= 0)
316+ prec->nelm = 1;
317+ if (prec->ftvl > DBF_ENUM)
318+ prec->ftvl = DBF_UCHAR;
319+ if (prec->nelm == 1) {
320+ prec->nord = 1;
321+ } else {
322+ prec->nord = 0;
323+ }
324+
325+ /* we must call pdset->init_record in pass 0
326+ because it may set prec->bptr which must
327+ not change after links are established before pass 1
328+ */
329+
330+ if (pdset->init_record) {
331+ /* init_record may set the bptr to point to the data */
332+ if ((status = pdset->init_record(prec)))
333+ return status;
334+ }
335+ if (!prec->bptr) {
336+ /* device support did not allocate memory so we must do it */
337+ prec->bptr = callocMustSucceed(prec->nelm, dbValueSize(prec->ftvl),
338+ "aai: buffer calloc failed");
339+ }
340 return 0;
341 }
342- recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
343- /* must have dset defined */
344- if (!(pdset = (struct aaidset *)(prec->dset))) {
345- recGblRecordError(S_dev_noDSET, (void *)prec, "aai: init_record");
346- return S_dev_noDSET;
347+
348+ /* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */
349+ if (prec->siml.type == CONSTANT) {
350+ recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
351 }
352+
353 /* must have read_aai function defined */
354 if (pdset->number < 5 || pdset->read_aai == NULL) {
355- recGblRecordError(S_dev_missingSup, (void *)prec, "aai: init_record");
356+ recGblRecordError(S_dev_missingSup, prec, "aai: init_record");
357 return S_dev_missingSup;
358 }
359- if (pdset->init_record) {
360- /* init_record sets the bptr to point to the data */
361- if ((status = pdset->init_record(prec)))
362- return status;
363- }
364 return 0;
365 }
366
367@@ -132,14 +160,13 @@
368
369 if (pdset == NULL || pdset->read_aai == NULL) {
370 prec->pact = TRUE;
371- recGblRecordError(S_dev_missingSup, (void *)prec, "read_aai");
372+ recGblRecordError(S_dev_missingSup, prec, "read_aai");
373 return S_dev_missingSup;
374 }
375
376 if (pact) return 0;
377
378 status = readValue(prec); /* read the new value */
379- /* check if device support set pact */
380 if (!pact && prec->pact) return 0;
381 prec->pact = TRUE;
382
383@@ -151,22 +178,14 @@
384 recGblFwdLink(prec);
385
386 prec->pact = FALSE;
387- return 0;
388-}
389-
390-static long get_value(aaiRecord *prec, struct valueDes *pvdes)
391-{
392- pvdes->no_elements = prec->nelm;
393- pvdes->pvalue = prec->bptr;
394- pvdes->field_type = prec->ftvl;
395- return 0;
396+ return status;
397 }
398
399 static long cvt_dbaddr(DBADDR *paddr)
400 {
401 aaiRecord *prec = (aaiRecord *)paddr->precord;
402
403- paddr->pfield = (void *)(prec->bptr);
404+ paddr->pfield = prec->bptr;
405 paddr->no_elements = prec->nelm;
406 paddr->field_type = prec->ftvl;
407 paddr->field_size = dbValueSize(prec->ftvl);
408@@ -178,7 +197,7 @@
409 {
410 aaiRecord *prec = (aaiRecord *)paddr->precord;
411
412- *no_elements = prec->nelm;
413+ *no_elements = prec->nord;
414 *offset = 0;
415 return 0;
416 }
417@@ -187,7 +206,9 @@
418 {
419 aaiRecord *prec = (aaiRecord *)paddr->precord;
420
421- prec->nelm = nNew;
422+ prec->nord = nNew;
423+ if (prec->nord > prec->nelm)
424+ prec->nord = prec->nelm;
425 return 0;
426 }
427
428@@ -204,7 +225,7 @@
429 aaiRecord *prec = (aaiRecord *)paddr->precord;
430
431 *precision = prec->prec;
432- if (paddr->pfield == (void *)prec->bptr) return 0;
433+ if (paddr->pfield == prec->bptr) return 0;
434 recGblGetPrec(paddr, precision);
435 return 0;
436 }
437@@ -213,7 +234,7 @@
438 {
439 aaiRecord *prec = (aaiRecord *)paddr->precord;
440
441- if (paddr->pfield == (void *)prec->bptr) {
442+ if (paddr->pfield == prec->bptr) {
443 pgd->upper_disp_limit = prec->hopr;
444 pgd->lower_disp_limit = prec->lopr;
445 } else recGblGetGraphicDouble(paddr, pgd);
446@@ -224,7 +245,7 @@
447 {
448 aaiRecord *prec = (aaiRecord *)paddr->precord;
449
450- if (paddr->pfield == (void *)prec->bptr) {
451+ if (paddr->pfield == prec->bptr) {
452 pcd->upper_ctrl_limit = prec->hopr;
453 pcd->lower_ctrl_limit = prec->lopr;
454 } else recGblGetControlDouble(paddr, pcd);
455@@ -234,9 +255,35 @@
456 static void monitor(aaiRecord *prec)
457 {
458 unsigned short monitor_mask;
459+ unsigned int hash = 0;
460
461 monitor_mask = recGblResetAlarms(prec);
462- monitor_mask |= (DBE_LOG | DBE_VALUE);
463+
464+ if (prec->mpst == aaiPOST_Always)
465+ monitor_mask |= DBE_VALUE;
466+ if (prec->apst == aaiPOST_Always)
467+ monitor_mask |= DBE_LOG;
468+
469+ /* Calculate hash if we are interested in OnChange events. */
470+ if ((prec->mpst == aaiPOST_OnChange) ||
471+ (prec->apst == aaiPOST_OnChange)) {
472+ hash = epicsMemHash(prec->bptr,
473+ prec->nord * dbValueSize(prec->ftvl), 0);
474+
475+ /* Only post OnChange values if the hash is different. */
476+ if (hash != prec->hash) {
477+ if (prec->mpst == aaiPOST_OnChange)
478+ monitor_mask |= DBE_VALUE;
479+ if (prec->apst == aaiPOST_OnChange)
480+ monitor_mask |= DBE_LOG;
481+
482+ /* Store hash for next process. */
483+ prec->hash = hash;
484+ /* Post HASH. */
485+ db_post_events(prec, &prec->hash, DBE_VALUE);
486+ }
487+ }
488+
489 if (monitor_mask)
490 db_post_events(prec, prec->bptr, monitor_mask);
491 }
492@@ -253,21 +300,25 @@
493
494 status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0);
495 if (status)
496- return(status);
497+ return status;
498
499 if (prec->simm == menuYesNoNO){
500- /* Call dev support */
501- status = pdset->read_aai(prec);
502- return status;
503+ return pdset->read_aai(prec);
504 }
505+
506 if (prec->simm == menuYesNoYES){
507- /* Simm processing split performed in devSup */
508- /* Call dev support */
509- status = pdset->read_aai(prec);
510- return status;
511+ /* Device suport is responsible for buffer
512+ which might be read-only so we may not be
513+ allowed to call dbGetLink on it.
514+ Maybe also device support has an advanced
515+ simulation mode.
516+ Thus call device now.
517+ */
518+ recGblSetSevr(prec, SIMM_ALARM, prec->sims);
519+ return pdset->read_aai(prec);
520 }
521- status = -1;
522- recGblSetSevr(prec, SIMM_ALARM, INVALID_ALARM);
523- return status;
524+
525+ recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
526+ return -1;
527 }
528
529
530=== modified file 'src/rec/aaiRecord.dbd'
531--- src/rec/aaiRecord.dbd 2002-07-12 21:35:43 +0000
532+++ src/rec/aaiRecord.dbd 2010-07-07 17:48:44 +0000
533@@ -7,6 +7,10 @@
534 # and higher are distributed subject to a Software License Agreement found
535 # in file LICENSE that is included with this distribution.
536 #*************************************************************************
537+menu(aaiPOST) {
538+ choice(aaiPOST_Always,"Always")
539+ choice(aaiPOST_OnChange,"On Change")
540+}
541 recordtype(aai) {
542 include "dbCommon.dbd"
543 field(VAL,DBF_NOACCESS) {
544@@ -82,4 +86,25 @@
545 interest(2)
546 menu(menuAlarmSevr)
547 }
548+ field(SIOL,DBF_INLINK) {
549+ prompt("Sim Input Specifctn")
550+ promptgroup(GUI_INPUTS)
551+ interest(1)
552+ }
553+ field(MPST,DBF_MENU) {
554+ prompt("Post Value Monitors")
555+ promptgroup(GUI_DISPLAY)
556+ interest(1)
557+ menu(aaiPOST)
558+ }
559+ field(APST,DBF_MENU) {
560+ prompt("Post Archive Monitors")
561+ promptgroup(GUI_DISPLAY)
562+ interest(1)
563+ menu(aaiPOST)
564+ }
565+ field(HASH,DBF_ULONG) {
566+ prompt("Hash of OnChange data.")
567+ interest(3)
568+ }
569 }
570
571=== modified file 'src/rec/aaoRecord.c'
572--- src/rec/aaoRecord.c 2009-07-08 18:14:11 +0000
573+++ src/rec/aaoRecord.c 2010-07-07 17:48:44 +0000
574@@ -9,7 +9,6 @@
575 /* recAao.c - Record Support Routines for Array Analog Out records */
576 /*
577 * Original Author: Dave Barker
578- * Date: 10/28/93
579 *
580 * C E B A F
581 *
582@@ -18,6 +17,8 @@
583 *
584 * Copyright SURA CEBAF 1993.
585 *
586+ * Current Author: Dirk Zimoch <dirk.zimoch@psi.ch>
587+ * Date: 27-MAY-2010
588 */
589
590 #include <stddef.h>
591@@ -28,14 +29,17 @@
592
593 #include "dbDefs.h"
594 #include "epicsPrint.h"
595+#include "epicsString.h"
596 #include "alarm.h"
597 #include "dbAccess.h"
598+#include "dbEvent.h"
599 #include "dbFldTypes.h"
600 #include "dbScan.h"
601-#include "dbEvent.h"
602 #include "devSup.h"
603+#include "errMdef.h"
604 #include "recSup.h"
605 #include "recGbl.h"
606+#include "cantProceed.h"
607 #include "menuYesNo.h"
608 #define GEN_SIZE_OFFSET
609 #include "aaoRecord.h"
610@@ -48,7 +52,7 @@
611 static long init_record(aaoRecord *, int);
612 static long process(aaoRecord *);
613 #define special NULL
614-static long get_value(aaoRecord *, struct valueDes *);
615+#define get_value NULL
616 static long cvt_dbaddr(DBADDR *);
617 static long get_array_info(DBADDR *, long *, long *);
618 static long put_array_info(DBADDR *, long);
619@@ -84,43 +88,67 @@
620 epicsExportAddress(rset,aaoRSET);
621
622 struct aaodset { /* aao dset */
623- long number;
624- DEVSUPFUN dev_report;
625- DEVSUPFUN init;
626- DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
627- DEVSUPFUN get_ioint_info;
628- DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/
629+ long number;
630+ DEVSUPFUN dev_report;
631+ DEVSUPFUN init;
632+ DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
633+ DEVSUPFUN get_ioint_info;
634+ DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/
635 };
636
637 static void monitor(aaoRecord *);
638 static long writeValue(aaoRecord *);
639
640-
641 static long init_record(aaoRecord *prec, int pass)
642 {
643- struct aaodset *pdset;
644 long status;
645+ struct aaodset *pdset = (struct aaodset *)(prec->dset);
646
647- if (pass == 0) {
648- if (prec->nelm <= 0) prec->nelm = 1;
649- return 0;
650- }
651- recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
652 /* must have dset defined */
653- if (!(pdset = (struct aaodset *)(prec->dset))) {
654- recGblRecordError(S_dev_noDSET, (void *)prec, "aao: init_record");
655+ if (!pdset) {
656+ recGblRecordError(S_dev_noDSET, prec, "aao: init_record");
657 return S_dev_noDSET;
658 }
659+
660+ if (pass == 0) {
661+ if (prec->nelm <= 0)
662+ prec->nelm = 1;
663+ if (prec->ftvl > DBF_ENUM)
664+ prec->ftvl = DBF_UCHAR;
665+ if (prec->nelm == 1) {
666+ prec->nord = 1;
667+ } else {
668+ prec->nord = 0;
669+ }
670+
671+ /* we must call pdset->init_record in pass 0
672+ because it may set prec->bptr which must
673+ not change after links are established before pass 1
674+ */
675+
676+ if (pdset->init_record) {
677+ /* init_record may set the bptr to point to the data */
678+ if ((status = pdset->init_record(prec)))
679+ return status;
680+ }
681+ if (!prec->bptr) {
682+ /* device support did not allocate memory so we must do it */
683+ prec->bptr = callocMustSucceed(prec->nelm, dbValueSize(prec->ftvl),
684+ "aao: buffer calloc failed");
685+ }
686+ return 0;
687+ }
688+
689+ /* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */
690+ if (prec->siml.type == CONSTANT) {
691+ recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
692+ }
693+
694 /* must have write_aao function defined */
695 if (pdset->number < 5 || pdset->write_aao == NULL) {
696- recGblRecordError(S_dev_missingSup, (void *)prec, "aao: init_record");
697+ recGblRecordError(S_dev_missingSup, prec, "aao: init_record");
698 return S_dev_missingSup;
699 }
700- if (pdset->init_record) {
701- /* init records sets the bptr to point to the data */
702- if ((status = pdset->init_record(prec)))
703- return status;
704- }
705 return 0;
706 }
707
708@@ -132,13 +160,15 @@
709
710 if (pdset == NULL || pdset->write_aao == NULL) {
711 prec->pact = TRUE;
712- recGblRecordError(S_dev_missingSup, (void *)prec, "write_aao");
713+ recGblRecordError(S_dev_missingSup, prec, "write_aao");
714 return S_dev_missingSup;
715 }
716
717 if (pact) return 0;
718
719 status = writeValue(prec); /* write the data */
720+ if (!pact && prec->pact) return 0;
721+ prec->pact = TRUE;
722
723 prec->udf = FALSE;
724 recGblGetTimeStamp(prec);
725@@ -148,22 +178,14 @@
726 recGblFwdLink(prec);
727
728 prec->pact = FALSE;
729- return 0;
730-}
731-
732-static long get_value(aaoRecord *prec, struct valueDes *pvdes)
733-{
734- pvdes->no_elements = prec->nelm;
735- pvdes->pvalue = prec->bptr;
736- pvdes->field_type = prec->ftvl;
737- return 0;
738+ return status;
739 }
740
741 static long cvt_dbaddr(DBADDR *paddr)
742 {
743 aaoRecord *prec = (aaoRecord *)paddr->precord;
744
745- paddr->pfield = (void *)(prec->bptr);
746+ paddr->pfield = prec->bptr;
747 paddr->no_elements = prec->nelm;
748 paddr->field_type = prec->ftvl;
749 paddr->field_size = dbValueSize(prec->ftvl);
750@@ -175,7 +197,7 @@
751 {
752 aaoRecord *prec = (aaoRecord *)paddr->precord;
753
754- *no_elements = prec->nelm;
755+ *no_elements = prec->nord;
756 *offset = 0;
757 return 0;
758 }
759@@ -184,7 +206,9 @@
760 {
761 aaoRecord *prec = (aaoRecord *)paddr->precord;
762
763- prec->nelm = nNew;
764+ prec->nord = nNew;
765+ if (prec->nord > prec->nelm)
766+ prec->nord = prec->nelm;
767 return 0;
768 }
769
770@@ -210,7 +234,7 @@
771 {
772 aaoRecord *prec = (aaoRecord *)paddr->precord;
773
774- if (paddr->pfield == (void *)prec->bptr) {
775+ if (paddr->pfield == prec->bptr) {
776 pgd->upper_disp_limit = prec->hopr;
777 pgd->lower_disp_limit = prec->lopr;
778 } else recGblGetGraphicDouble(paddr,pgd);
779@@ -221,7 +245,7 @@
780 {
781 aaoRecord *prec = (aaoRecord *)paddr->precord;
782
783- if(paddr->pfield==(void *)prec->bptr){
784+ if(paddr->pfield == prec->bptr){
785 pcd->upper_ctrl_limit = prec->hopr;
786 pcd->lower_ctrl_limit = prec->lopr;
787 } else recGblGetControlDouble(paddr,pcd);
788@@ -231,9 +255,35 @@
789 static void monitor(aaoRecord *prec)
790 {
791 unsigned short monitor_mask;
792+ unsigned int hash = 0;
793
794 monitor_mask = recGblResetAlarms(prec);
795- monitor_mask |= (DBE_LOG | DBE_VALUE);
796+
797+ if (prec->mpst == aaoPOST_Always)
798+ monitor_mask |= DBE_VALUE;
799+ if (prec->apst == aaoPOST_Always)
800+ monitor_mask |= DBE_LOG;
801+
802+ /* Calculate hash if we are interested in OnChange events. */
803+ if ((prec->mpst == aaoPOST_OnChange) ||
804+ (prec->apst == aaoPOST_OnChange)) {
805+ hash = epicsMemHash(prec->bptr,
806+ prec->nord * dbValueSize(prec->ftvl), 0);
807+
808+ /* Only post OnChange values if the hash is different. */
809+ if (hash != prec->hash) {
810+ if (prec->mpst == aaoPOST_OnChange)
811+ monitor_mask |= DBE_VALUE;
812+ if (prec->apst == aaoPOST_OnChange)
813+ monitor_mask |= DBE_LOG;
814+
815+ /* Store hash for next process. */
816+ prec->hash = hash;
817+ /* Post HASH. */
818+ db_post_events(prec, &prec->hash, DBE_VALUE);
819+ }
820+ }
821+
822 if (monitor_mask)
823 db_post_events(prec, prec->bptr, monitor_mask);
824 }
825@@ -253,17 +303,20 @@
826 return status;
827
828 if (prec->simm == menuYesNoNO) {
829- /* Call dev support */
830- status = pdset->write_aao(prec);
831- return status;
832+ return pdset->write_aao(prec);
833 }
834 if (prec->simm == menuYesNoYES) {
835- /* Call dev support */
836- status = pdset->write_aao(prec);
837- return status;
838+ /* Device suport is responsible for buffer
839+ which might be write-only so we may not be
840+ allowed to call dbPutLink on it.
841+ Maybe also device support has an advanced
842+ simulation mode.
843+ Thus call device now.
844+ */
845+ recGblSetSevr(prec, SIMM_ALARM, prec->sims);
846+ return pdset->write_aao(prec);
847 }
848- status = -1;
849- recGblSetSevr(prec, SIMM_ALARM, INVALID_ALARM);
850- return status;
851+ recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
852+ return -1;
853 }
854
855
856=== modified file 'src/rec/aaoRecord.dbd'
857--- src/rec/aaoRecord.dbd 2002-07-12 21:35:43 +0000
858+++ src/rec/aaoRecord.dbd 2010-07-07 17:48:44 +0000
859@@ -7,6 +7,10 @@
860 # and higher are distributed subject to a Software License Agreement found
861 # in file LICENSE that is included with this distribution.
862 #*************************************************************************
863+menu(aaoPOST) {
864+ choice(aaoPOST_Always,"Always")
865+ choice(aaoPOST_OnChange,"On Change")
866+}
867 recordtype(aao) {
868 include "dbCommon.dbd"
869 field(VAL,DBF_NOACCESS) {
870@@ -82,4 +86,25 @@
871 interest(2)
872 menu(menuAlarmSevr)
873 }
874+ field(SIOL,DBF_OUTLINK) {
875+ prompt("Sim Output Specifctn")
876+ promptgroup(GUI_INPUTS)
877+ interest(1)
878+ }
879+ field(MPST,DBF_MENU) {
880+ prompt("Post Value Monitors")
881+ promptgroup(GUI_DISPLAY)
882+ interest(1)
883+ menu(aaoPOST)
884+ }
885+ field(APST,DBF_MENU) {
886+ prompt("Post Archive Monitors")
887+ promptgroup(GUI_DISPLAY)
888+ interest(1)
889+ menu(aaoPOST)
890+ }
891+ field(HASH,DBF_ULONG) {
892+ prompt("Hash of OnChange data.")
893+ interest(3)
894+ }
895 }

Subscribers

People subscribed via source and target branches