Subject: |
Re: Re[2]: Portable CA Server |
From: |
[email protected] (Jeff Hill) |
Date: |
Fri, 19 May 95 16:47:24 MDT |
----------
X-Sun-Data-Type: text
X-Sun-Data-Description: text
X-Sun-Data-Name: text
X-Sun-Content-Lines: 18
Hello,
Attached are the header files for the new CA server API. All comments
are appreciated.
casdef.h - new ca server API
exampleCaServer.c - simple application of the new ca server library
epicsTypes.h - new core architecture independent types for EPICS
alarm.h - def of alarm codes (new enum added)
tsDefs.h - def of time stamp structure (unchanged)
Jeff
______________________________________________________________________
Jeffrey O. Hill Internet [email protected]
LANL MS H820 Voice 505 665 1831
Los Alamos, NM 87545 USA FAX 505 665 5107
----------
X-Sun-Data-Type: h-file
X-Sun-Data-Description: h-file
X-Sun-Data-Name: epicsTypes.h
X-Sun-Content-Lines: 230
/* $Id */
/*
* Author: Jeff Hill
* Date: 5-95
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .00 mm-dd-yy iii Comment
*/
#ifndef INCepicsTypesh
#define INCepicsTypesh 1
#define stringOf(TOKEN) #TOKEN
typedef enum {
epicsFalse=0,
epicsTrue=1 } epicsBoolean;
/*
* Architecture Independent Data Types
* (so far this is sufficient for all archs we have ported to)
*/
typedef char epicsInt8;
typedef unsigned char epicsUInt8;
typedef short epicsInt16;
typedef unsigned short epicsUInt16;
typedef epicsUInt16 epicsEnum16;
typedef int epicsInt32;
typedef unsigned epicsUInt32;
typedef float epicsFloat32;
typedef double epicsFloat64;
typedef struct {
unsigned length;
char *pString;
}epicsString;
/*
* !! Dont use this - it may vanish in the future !!
*
* Provided only for backwards compatibility with
* db_access.h
*
* The dimension of this must match MAX_STRING_SIZE
* in db_access.h (if it doesnt the CA server will
* refuse to init)
*/
typedef char epicsWeirdString[40];
/*
* union of all types
*
* Strings included here as pointers only so that we support
* large string types.
*/
typedef union {
epicsInt8 int8;
epicsUInt8 uInt8;
epicsInt16 int16;
epicsUInt16 uInt16;
epicsEnum16 enum16;
epicsInt32 int32;
epicsUInt32 uInt32;
epicsFloat32 float32;
epicsFloat64 float64;
epicsString string;
}epicsAny;
/*
* Corresponding Type Codes
* (this enum must start at zero)
*
* !! Update epicsTypeToDBR_XXXX[] and DBR_XXXXToEpicsType
* in db_access.h if you edit this enum !!
*/
typedef enum {
epicsInt8T,
epicsUInt8T,
epicsInt16T,
epicsUInt16T,
epicsEnum16T,
epicsInt32T,
epicsUInt32T,
epicsFloat32T,
epicsFloat64T,
epicsStringT,
epicsWeirdStringT
}epicsType;
#define firstEpicsType epicsInt8T
#define lastEpicsType epicsWeirdStringT
#define validEpicsType(x) ((x>=firstEpicsType) && (x<=lastEpicsType))
#define invalidEpicsType(x) ((x<firstEpicsType) || (x>lastEpicsType))
/*
* The enumeration "epicsType" is an index to this array
* of type name strings.
*/
#ifdef epicsTypesGLOBAL
const char *epicsTypeNames [lastEpicsType+1] = {
stringOf (epicsInt8),
stringOf (epicsUInt8),
stringOf (epicsInt16),
stringOf (epicsUInt16),
stringOf (epicsEnum16),
stringOf (epicsInt32),
stringOf (epicsUInt32),
stringOf (epicsFloat32),
stringOf (epicsFloat64),
stringOf (epicsString),
stringOf (epicsWeirdString),
};
#else /* epicsTypesGLOBAL */
extern const char *epicsTypeNames [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
/*
* The enumeration "epicsType" is an index to this array
* of type code name strings.
*/
#ifdef epicsTypesGLOBAL
const char *epicsTypeCodeNames [lastEpicsType+1] = {
stringOf (epicsInt8T),
stringOf (epicsUInt8T),
stringOf (epicsInt16T),
stringOf (epicsUInt16T),
stringOf (epicsEnum16T),
stringOf (epicsInt32T),
stringOf (epicsUInt32T),
stringOf (epicsFloat32T),
stringOf (epicsFloat64T),
stringOf (epicsStringT),
stringOf (epicsWeirdStringT),
};
#else /* epicsTypesGLOBAL */
extern const char *epicsTypeCodeNames [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
#ifdef epicsTypesGLOBAL
const unsigned epicsTypeSizes [lastEpicsType+1] = {
sizeof (epicsInt8),
sizeof (epicsUInt8),
sizeof (epicsInt16),
sizeof (epicsUInt16),
sizeof (epicsEnum16),
sizeof (epicsInt32),
sizeof (epicsUInt32),
sizeof (epicsFloat32),
sizeof (epicsFloat64),
sizeof (epicsString),
sizeof (epicsWeirdString),
};
#else /* epicsTypesGLOBAL */
extern const unsigned epicsTypeSizes [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
/*
* The enumeration "epicsType" is an index to this array
* of type class identifiers.
*/
typedef enum {
epicsIntC,
epicsUIntC,
epicsEnumC,
epicsFloatC,
epicsStringC,
epicsWeirdStringC} epicsTypeClass;
#ifdef epicsTypesGLOBAL
const epicsTypeClass epicsTypeClasses [lastEpicsType+1] = {
epicsIntC,
epicsUIntC,
epicsIntC,
epicsUIntC,
epicsEnumC,
epicsIntC,
epicsUIntC,
epicsFloatC,
epicsFloatC,
epicsStringC,
epicsWeirdStringC
};
#else /* epicsTypesGLOBAL */
extern const epicsTypeClass epicsTypeClasses [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
#ifdef epicsTypesGLOBAL
const char *epicsTypeAnyFieldName [lastEpicsType+1] = {
stringOf (int8),
stringOf (uInt8),
stringOf (int16),
stringOf (uInt16),
stringOf (enum16),
stringOf (int32),
stringOf (uInt32),
stringOf (float32),
stringOf (float64),
stringOf (string),
"", /* Weird Strings will not be in epicsAny type */
};
#else /* epicsTypesGLOBAL */
extern const char *epicsTypeAnyFieldName [lastEpicsType+1];
#endif /* epicsTypesGLOBAL */
#endif /* INCepicsTypesh */
----------
X-Sun-Data-Type: h-file
X-Sun-Data-Description: h-file
X-Sun-Data-Name: alarm.h
X-Sun-Content-Lines: 107
/* Alarm definitions (Must Match choiceGbl.ascii) */
/* $Id: alarm.h,v 1.9 1994/07/13 02:24:04 bordua Exp $ */
/*
* Original Author: Bob Dalesio
* Current Author: Marty Kraimer
* Date: 11-7-90
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .00 mm-dd-yy iii Comment
* .01 07-16-92 jba changed VALID_ALARM to INVALID_ALARM
* .02 08-11-92 jba added new status DISABLE_ALARM, SIMM_ALARM
* .03 05-11-94 jba added new status READ_ACCESS_ALARM, WRITE_ACCESS_ALARM
*/
#ifndef INCalarmh
#define INCalarmh 1
/* defines for the choice fields */
/* ALARM SEVERITIES - NOTE: must match defs in choiceGbl.ascii GBL_ALARM_SEV */
#define NO_ALARM 0x0
#define MINOR_ALARM 0x1
#define MAJOR_ALARM 0x2
#define INVALID_ALARM 0x3
#define ALARM_NSEV INVALID_ALARM+1
typedef enum {
epicsSevNone = NO_ALARM,
epicsSevMajor = MINOR_ALARM,
epicsSevInvalid = MAJOR_ALARM
}epicsAlarmSeverity;
/* ALARM STATUS -NOTE: must match defs in choiceGbl.ascii GBL_ALARM_STAT */
/* NO_ALARM = 0 as above */
#define READ_ALARM 1
#define WRITE_ALARM 2
/* ANALOG ALARMS */
#define HIHI_ALARM 3
#define HIGH_ALARM 4
#define LOLO_ALARM 5
#define LOW_ALARM 6
/* BINARY ALARMS */
#define STATE_ALARM 7
#define COS_ALARM 8
/* other alarms */
#define COMM_ALARM 9
#define TIMEOUT_ALARM 10
#define HW_LIMIT_ALARM 11
#define CALC_ALARM 12
#define SCAN_ALARM 13
#define LINK_ALARM 14
#define SOFT_ALARM 15
#define BAD_SUB_ALARM 16
#define UDF_ALARM 17
#define DISABLE_ALARM 18
#define SIMM_ALARM 19
#define READ_ACCESS_ALARM 20
#define WRITE_ACCESS_ALARM 21
#define ALARM_NSTATUS WRITE_ACCESS_ALARM + 1
typedef enum {
epicsAlarmRead = READ_ALARM,
epicsAlarmWrite = WRITE_ALARM,
epicsAlarmHiHi = HIHI_ALARM,
epicsAlarmHigh = HIGH_ALARM,
epicsAlarmLoLo = LOLO_ALARM,
epicsAlarmLow = LOW_ALARM,
epicsAlarmState = STATE_ALARM,
epicsAlarmCos = COS_ALARM,
epicsAlarmComm = COMM_ALARM,
epicsAlarmTimeout = TIMEOUT_ALARM,
epicsAlarmHwLimit = HW_LIMIT_ALARM,
epicsAlarmCalc = CALC_ALARM,
epicsAlarmScan = SCAN_ALARM,
epicsAlarmLink = LINK_ALARM,
epicsAlarmSoft = SOFT_ALARM,
epicsAlarmBadSub = BAD_SUB_ALARM,
epicsAlarmUDF = UDF_ALARM,
epicsAlarmDisable = DISABLE_ALARM,
epicsAlarmSimm = SIMM_ALARM,
epicsAlarmReadAccess = READ_ACCESS_ALARM,
epicsAlarmWriteAccess = WRITE_ACCESS_ALARM
}epicsAlarmCondition;
#endif
----------
X-Sun-Data-Type: h-file
X-Sun-Data-Description: h-file
X-Sun-Data-Name: tsDefs.h
X-Sun-Content-Lines: 286
#ifndef INC_tsDefs_h
#define INC_tsDefs_h
/* $Id: tsDefs.h,v 1.12 1994/11/17 19:08:49 jhill Exp $
* Author: Roger A. Cole
* Date: 08-09-90
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991-92, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 08-09-90 rac initial version
* .02 06-18-91 rac installed in SCCS
* .03 08-03-92 rac added tsRound routines
*
*/
/*+/mod***********************************************************************
* TITLE tsDefs.h - time-stamp related definitions
*
* DESCRIPTION
*
* BUGS
* o only a single, manually configured, conversion between local
* time and GMT is supported. Thus, if a new `rule' for daylight
* savings time were invented, then this code would be `broken'
* until this file were configured for the new rule. BUT, then
* this code is `broken' for the period prior to the new rule's
* effect.
* o only dates following Jan 1, 1990 are handled; stamps on Jan 1,
* 1990 are treated as `dateless' times.
*
*-***************************************************************************/
#include <errMdef.h> /* get M_ts for this subsystem's `number' */
/*---------------------------------------------------------------------------
-
* TS_STAMP
*
* This is the form taken by time stamps in GTACS, and is the form used
* by the various tools used for dealing with time stamps.
*
* The time stamp represents the number of nanoseconds past 0000 Jan 1, 199
0,
* GMT (or UTC, if you prefer).
*
*----------------------------------------------------------------------------
*/
typedef struct {
unsigned secPastEpoch; /* seconds since 0000 Jan 1, 1990 */
unsigned nsec; /* nanoseconds within second */
} TS_STAMP;
/*----------------------------------------------------------------------------
* TS_TEXT_xxx text type codes for converting between text and time stamp
*
* TS_TEXT_MONDDYYYY Mon dd, yyyy hh:mm:ss.nano-secs
* TS_TEXT_MMDDYY mm/dd/yy hh:mm:ss.nano-secs
* 123456789012345678901234567890123456789
* 0 1 2 3
*----------------------------------------------------------------------------*/
enum tsTextType{
TS_TEXT_MONDDYYYY,
TS_TEXT_MMDDYY
};
/*/subhead configuration------------------------------------------------------
* C O N F I G U R A T I O N D E F I N I T I O N S
*
* TS_DST_BEGIN the day number for starting DST
* TS_DST_END the day number for ending DST
* TS_MIN_WEST the number of minutes west of GMT for time zone (zones east
* will have negative values)
* TS_DST_HOUR_ON the hour (standard time) when DST turns on
* TS_DST_HOUR_OFF the hour (standard time) when DST turns off
* TS_DST_HRS_ADD hours to add when DST is on
*
* day numbers start with 0 for Jan 1; day numbers in these defines are
* based on a NON-leap year. The start and end days for DST are assumed to be
* Sundays. A negative day indicates that the following Sunday is to be used;
* a positive day indicates the prior Sunday. If the begin date is larger than
* the end date, then DST overlaps the change of the year (e.g., for southern
* hemisphere).
*
* Note well that TS_DST_HOUR_ON and TS_DST_HOUR_OFF are both STANDARD time.
* So, if dst begins at 2 a.m. (standard time) and ends at 2 a.m. (daylight
* time), the two values would be 2 and 1, respectively (assuming
* TS_DST_HRS_ADD is 1).
*----------------------------------------------------------------------------*/
#define TS_DST_BEGIN -90 /* first Sun in Apr (Apr 1 = 90) */
#define TS_DST_END 303 /* last Sun in Oct (Oct 31 = 303) */
#define TS_DST_HOUR_ON 2 /* 2 a.m. (standard time) */
#define TS_DST_HOUR_OFF 1 /* 2 a.m. (1 a.m. standard time) */
#define TS_DST_HRS_ADD 1 /* add one hour */
#define TS_MIN_WEST 7 * 60 /* USA mountain time zone */
#if 0 /* first set is for testing only */
#define TS_EPOCH_YEAR 1989
#define TS_EPOCH_SEC_PAST_1970 6940*86400 /* 1/1/89 19 yr (5 leap) of seconds */
#define TS_EPOCH_WDAY_NUM 0 /* Jan 1 1989 was Sun (wkday num = 0) */
#else
#define TS_EPOCH_YEAR 1990
#define TS_EPOCH_SEC_PAST_1970 7305*86400 /* 1/1/90 20 yr (5 leap) of seconds */
#define TS_EPOCH_WDAY_NUM 1 /* Jan 1 1990 was Mon (wkday num = 1) */
#endif
#define TS_MAX_YEAR TS_EPOCH_YEAR+134 /* ULONG can handle 135 years */
#define TS_TRUNC 1000000 /* truncate to milli-second significance */
/*/subhead struct tsDetail----------------------------------------------------
* breakdown structure for working with secPastEpoch
*----------------------------------------------------------------------------*/
struct tsDetail {
int year; /* 4 digit year */
int dayYear; /* day number in year; 0 = Jan 1 */
int monthNum; /* month number; 0 = Jan */
int dayMonth; /* day number; 0 = 1st of month */
int hours; /* hours within day */
int minutes; /* minutes within hour */
int seconds; /* seconds within minute */
int dayOfWeek; /* weekday number; 0 = Sun */
int leapYear; /* (0, 1) for year (isn't, is) a leap year */
char dstOverlapChar; /* indicator for distinguishing duplicate
times in the `switch to standard' time period:
':'--time isn't ambiguous;
's'--time is standard time
'd'--time is daylight time */
};
/*/subhead status codes-------------------------------------------------------
* S T A T U S C O D E S
*
*
* Status codes for time stamp routines have the form S_ts_briefMessage .
*
* The macro TsStatusToText(stat) can be used to obtain a text string
* corresponding to a status code.
*
*----------------------------------------------------------------------------*/
#define S_ts_OK (M_ts|0| 0<<1) /* success */
#define S_ts_sysTimeError (M_ts|1| 1<<1) /* error getting system time */
#define S_ts_badTextCode (M_ts|1| 2<<1) /* invalid TS_TEXT_xxx code */
#define S_ts_inputTextError (M_ts|1| 3<<1) /* error in text date or time */
#define S_ts_timeSkippedDST (M_ts|1| 4<<1) /* time skipped on switch to DST */
#define S_ts_badRoundInterval (M_ts|1| 5<<1) /* invalid rounding interval */
#define TS_S_PAST 6 /* one past last legal code */
#define TsStatusToIndex(status) \
( ((status&0xffff0000)!=M_ts) \
? TS_S_PAST \
: ( (((status&0xffff)>>1)>=TS_S_PAST) \
? TS_S_PAST \
: ((status&0xffff)>>1) \
) \
)
#define TsStatusToText(status) \
(glTsStatText[TsStatusToIndex(status)])
#ifndef TS_PRIVATE_DATA
extern char *glTsStatText[];
#else
char *glTsStatText[] = {
/* S_ts_OK */ "success",
/* S_ts_sysTimeError */ "error getting system time",
/* S_ts_badTextCode */ "invalid TS_TEXT_xxx code",
/* S_ts_inputTextError */ "error in text date or time",
/* S_ts_timeSkippedDST */ "time skipped on switch to DST",
/* S_ts_badRoundInterval */ "rounding interval is invalid",
/* TS_S_PAST */ "illegal TS status code",
};
#endif
/*/subhead macros-------------------------------------------------------------
* arithmetic macros
*
* care has been taken in writing these macros that the result can
* be stored back into either operand time stamp. For example,
* both of the following (as well as other variations) are legal:
* TsAddStamps(pS1, pS1, pS2);
* TsDiffAsStamp(pS2, pS1, pS2);
*----------------------------------------------------------------------------*/
#define TsAddDouble(pSum, pS1, dbl) \
(void)( \
dbl >= 0. \
? ((*pSum).secPastEpoch = (*pS1).secPastEpoch + (unsigned long)dbl, \
( ((*pSum).nsec = (*pS1).nsec + (unsigned long)(1000000000. * \
(dbl - (double)((unsigned long)dbl))) ) ) \
>= 1000000000 \
?((*pSum).secPastEpoch += (*pSum).nsec/1000000000, \
(*pSum).nsec %= 1000000000) \
:0) \
: ((*pSum).secPastEpoch = (*pS1).secPastEpoch - (unsigned long)(-dbl), \
(*pS1).nsec >= (unsigned long)(1000000000. * \
((-dbl) - (double)((unsigned long)(-dbl)))) \
?( (*pSum).nsec = (*pS1).nsec - (unsigned long)(1000000000.* \
((-dbl) - (double)((unsigned long)(-dbl))))) \
:( (*pSum).nsec = (*pS1).nsec + 1000000000 - \
(unsigned long)(1000000000.* \
((-dbl) - (double)((unsigned long)(-dbl)))), \
(*pSum).secPastEpoch -= 1) ) )
#define TsAddStamps(pSum, pS1, pS2) \
(void)( \
((*pSum).secPastEpoch = (*pS1).secPastEpoch + (*pS2).secPastEpoch) , \
( ((*pSum).nsec = (*pS1).nsec + (*pS2).nsec) >= 1000000000 \
?((*pSum).secPastEpoch += (*pSum).nsec/1000000000, \
(*pSum).nsec %= 1000000000) \
:0) )
#define TsDiffAsDouble(pDbl, pS1, pS2) \
(void)( \
*pDbl = ((double)(*pS1).nsec - (double)(*pS2).nsec)/1000000000., \
*pDbl += (double)(*pS1).secPastEpoch - (double)(*pS2).secPastEpoch )
/* TsDiffAsStamp() assumes that stamp1 >= stamp2 */
#define TsDiffAsStamp(pDiff, pS1, pS2) \
(void)( \
(*pDiff).secPastEpoch = (*pS1).secPastEpoch - (*pS2).secPastEpoch , \
(*pS1).nsec >= (*pS2).nsec \
?( (*pDiff).nsec = (*pS1).nsec - (*pS2).nsec ) \
:( (*pDiff).nsec = ((*pS1).nsec + 1000000000) - (*pS2).nsec, \
(*pDiff).secPastEpoch -= 1 ) )
/*----------------------------------------------------------------------------
* comparison macros
*----------------------------------------------------------------------------*/
#define TsCmpStampsEQ(pS1, pS2) \
(((*pS1).secPastEpoch) == ((*pS2).secPastEpoch) && \
((*pS1).nsec) == ((*pS2).nsec))
#define TsCmpStampsNE(pS1, pS2) \
(((*pS1).secPastEpoch) != ((*pS2).secPastEpoch) || \
((*pS1).nsec) != ((*pS2).nsec))
#define TsCmpStampsGT(pS1, pS2) \
((((*pS1).secPastEpoch) > ((*pS2).secPastEpoch)) \
?1 \
:((((*pS1).secPastEpoch) == ((*pS2).secPastEpoch)) \
?((((*pS1).nsec) > ((*pS2).nsec)) ? 1 : 0) \
:0 ))
#define TsCmpStampsGE(pS1, pS2) \
((((*pS1).secPastEpoch) > ((*pS2).secPastEpoch)) \
?1 \
:((((*pS1).secPastEpoch) == ((*pS2).secPastEpoch)) \
?((((*pS1).nsec) >= ((*pS2).nsec)) ? 1 : 0) \
:0 ))
#define TsCmpStampsLT(pS1, pS2) \
((((*pS1).secPastEpoch) < ((*pS2).secPastEpoch)) \
?1 \
:((((*pS1).secPastEpoch) == ((*pS2).secPastEpoch)) \
?((((*pS1).nsec) < ((*pS2).nsec)) ? 1 : 0) \
:0 ))
#define TsCmpStampsLE(pS1, pS2) \
((((*pS1).secPastEpoch) < ((*pS2).secPastEpoch)) \
?1 \
:((((*pS1).secPastEpoch) == ((*pS2).secPastEpoch)) \
?((((*pS1).nsec) <= ((*pS2).nsec)) ? 1 : 0) \
:0 ))
/*----------------------------------------------------------------------------
* `prototypes'
*----------------------------------------------------------------------------*/
long tsLocalTime (TS_STAMP *pStamp);
void tsAddDouble();
int tsCmpStamps();
void tsDiffAsDouble();
long tsRoundDownLocal();
long tsRoundUpLocal();
char *tsStampToText();
long tsTextToStamp();
long tsTimeTextToStamp();
#endif
----------
X-Sun-Data-Type: h-file
X-Sun-Data-Description: h-file
X-Sun-Data-Name: errMdef.h
X-Sun-Content-Lines: 114
/* errMdef.h err.h - Error Handling definitions */
/* share/epicsH $Id: errMdef.h,v 1.20 1995/02/18 01:44:05 jhill Exp $ */
/*
* Author: Marty Kraimer
* Date: 6-1-90
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 mm-dd-yy iii Comment
* .02 12-02-91 jrw added GPIB and BB message codes
* .03 03-11-93 joh added __FILE__ and __LINE__ to errMessage()
* .04 04-01-93 joh added vxi
* .05 04-29-93 joh added errPrintStatus() func proto
* .06 09-04-93 rcz added functions ... for errSymLib.c merge
* .07 02-03-94 mrk RTN_SUCCESS is true only if status=0
* .08 02-03-94 mrk Add access security library
*/
#ifndef INCerrMdefh
#define INCerrMdefh
#ifdef __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#include <ellLib.h>
#define RTN_SUCCESS(STATUS) ((STATUS)==0)
#define M_dbAccess (501 <<16) /*Database Access Routines */
#define M_sdr (502 <<16) /*Self Defining Records */
#define M_drvSup (503 <<16) /*Driver Support*/
#define M_devSup (504 <<16) /*Device Support*/
#define M_recSup (505 <<16) /*Record Support*/
#define M_recType (506 <<16) /*Record Type*/
#define M_record (507 <<16) /*Database Records*/
#define M_ar (508 <<16) /*Archiver; see arDefs.h*/
#define M_ts (509 <<16) /*Time Stamp Routines; see tsDefs.h*/
#define M_arAcc (510 <<16) /*Archive Access Library Routines*/
#define M_bf (511 <<16) /*Block File Routines; see bfDefs.h*/
#define M_syd (512 <<16) /*Sync Data Routines; see sydDefs.h*/
#define M_ppr (513 <<16) /*Portable Plot Routines; see pprPlotDefs.h*/
#define M_env (514 <<16) /*Environment Routines; see envDefs.h*/
#define M_gen (515 <<16) /*General Purpose Routines; see genDefs.h*/
#define M_gpib (516 <<16) /*Gpib driver & device support; see drvGpibInterface.h*/
#define M_bitbus (517 <<16) /*Bitbus driver & device support; see drvBitBusInterface.h*/
#define M_dbCa (518 <<16) /*CA_LINKs; see calink.h*/
#define M_dbLib (519 <<16) /*Static Database Access */
#define M_epvxi (520 <<16) /*VXI Driver*/
#define M_devLib (521 <<16) /*Device Resource Registration*/
#define M_asLib (522 <<16) /*Access Security */
#define M_cas (523 <<16) /*CA server*/
#define M_casApp (524 <<16) /*CA server application*/
/*
* redefine errMessage with a macro so we can print
* the file and line number
*/
#define errMessage(S, PM) \
errPrintf(S, __FILE__, __LINE__, PM)
#ifdef __STDC__
int errSymFind(long status, char *name);
int UnixSymFind(long status, char *name, long *value);
int ModSymFind(long status, char *name, long *value);
void errSymTest(unsigned short modnum, unsigned short begErrNum, unsigned short endErrNum);
void errSymTestPrint(long errNum);
int errSymBld();
int errSymbolAdd (long errNum,char *name);
void errPrintf(long status, const char *pFileName,
int lineno, const char *pformat, ...);
void errSymDump();
void tstErrSymFind();
#else /*__STDC__*/
void errSymTest();
int errSymFind();
int UnixSymFind();
int ModSymFind();
void errSymTestPrint();
int errSymBld();
int errSymbolAdd();
void errPrintf();
void errSymDump();
void tstErrSymFind();
#endif /*__STDC__*/
extern int errVerbose;
#endif /*INCerrMdefh*/
----------
X-Sun-Data-Type: h-file
X-Sun-Data-Description: h-file
X-Sun-Data-Name: casdef.h
X-Sun-Content-Lines: 359
/*
* Author: Jeffrey O. Hill
* [email protected]
* (505) 665 1831
* Date: 1-95
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
*/
/*
* to do
*
* 1) how do they delete a pv out from under CA
*
*/
#include <epicsTypes.h> /* EPICS arch independent types */
#include <tsDefs.h> /* EPICS time stamp */
#include <alarm.h> /* EPICS alarm severity and alarm condition */
#include <errMdef.h> /* EPICS error codes */
typedef int caStatus;
typedef unsigned caid;
typedef caid chId;
typedef caid pvId;
typedef struct{
unsigned long sec; /* seconds */
unsigned long nsec; /* nano - seconds */
}caTime;
/*
* ===========================================================
* provided by the application (and called by the server via
* a jump table)
*
* All of these operations need to return without delay
* if we are to avoid hanging a single threaded server.
* ===========================================================
*/
/*
* return true if the named PV exists and false if it does not
*
* Canonical name is copied by the application into the buf pointed to by
* officialPVNameBuf. Copy no more than officialPVNameBufSize
* characters and null terminate.
*
* This is intended to support PV name aliases.
*/
typedef epicsBoolean pvExistTest(const char *pPVName, char *officialPVNameBuf,
unsigned officialPVNameBufSize);
/*
* The application supplied entry point pvAddrCreate() will
* be called by the server library each time that
* CA attaches a channel to a process varible for
* the first time.
*
* The application typically will allocate an application specific
* address structure with caMalloc() and return a pointer to it
* in *ppPVAddr.
*/
typedef caStatus pvAddrCreate (const char *pvNameString,
pvId id, void **ppPVAddr);
/*
* The application supplied entry point pvAddrDelete() will
* be called by the server library each time that
* the number of CA attachments to a particular PV
* decrements to zero. This routine provide an opportunity
* for the application to delete any resources allocated
* during pvAddrCreate(). Typically caFree() will be called
* to free memmory allocated inside of pvAddrCreate() above.
*/
typedef caStatus pvAddrDelete (void *pPVAddr);
/*
* The application supplied entry point pvInterestRegister ()
* will be called each time that the server wishes to
* subscripe for PV value change events via caServerPostEvents()
*/
typedef caStatus pvInterestRegister (void *pPVAddr, unsigned select);
/*
* The application supplied entry point pvInterestDelete ()
* will be called each time that the server wishes to
* remove its subscription for PV value change events
* via caServerPostEvents()
*/
typedef caStatus pvInterestDelete (void *pPVAddr);
/*
* No changes to a PV while the lock is applied
*
* allows updates to a record to be postponed while
* options are being read so that the value and options
* are consistent.
*/
typedef caStatus pvLock (void *pPVAddr);
typedef caStatus pvUnlock (void *pPVAddr);
/*
* Always called just after any write to the native
* address (with the lock on)
*
* If this operation will not complete immediately
* then the application is required to return
* S_casApp_asyncCompletion and then call
* caServerPostPVIOCompletion ()
* when the operation actually completes.
* The server will allow only one asynchronous IO
* operation at a time to be pending on a PV.
*/
typedef caStatus pvWriteAction (void *pPVAddr);
/*
* always called just prior to a read from the native
* address (with the lock on)
*
* If this operation will not complete immediately
* then the application is required to return
* S_casApp_asyncCompletion and then call
* caServerPostPVIOCompletion ()
* when the operation actually completes.
* The server will allow only one asynchronous IO
* operation at a time to be pending on a PV.
*/
typedef caStatus pvReadAction (void *pPVAddr);
/*
* allowed to change during an id's lifetime ??
*/
typedef caStatus pvNativeType (void *pPVAddr, epicsType *pType);
typedef caStatus pvBestExternalType (void *pPVAddr, epicsType *pType);
typedef caStatus pvNativeElementCount (void *pPVAddr, unsigned long *pCount);
typedef caStatus pvNativeAddress (void *pPVAddr, void **pPointer);
/* ring index certainly will chnage during the PV's lifespan) */
typedef caStatus pvNativeRingIndex (void *pPVAddr, unsigned long *pIndex);
/*
* frequently change during an id's lifetime
*/
typedef caStatus pvAlarmStatus (void *pPVAddr, epicsAlarmSeverity *pSeverity,
epicsAlarmCondition *pStatus);
typedef caStatus pvTimeStamp (void *pPVAddr, TS_STAMP *pTimeStamp);
/*
* Will cause operational problems for existing clients coded to the
* current interface if these change during an id's lifetime. Future
* client interface will provide for change notification. Perhaps
* we should just disconnect the client if these parameters change.
*/
typedef caStatus pvUnits (void *pPVAddr, unsigned bufByteSize,
char *pStringBuf);
typedef caStatus pvPrecision (void *pPVAddr, unsigned *pPrecision);
typedef caStatus pvEnumStateCount (void *pPVAddr, unsigned nStatesMax,
unsigned *nStates);
typedef caStatus pvEnumStateString (void *pPVAddr, unsigned stateNumber,
unsigned bufByteSize, char *pStringBuf);
typedef caStatus pvGraphLimits (void *pPVAddr, double *pUpperLimit,
double *pLowerLimit);
typedef caStatus pvControlLimits (void *pPVAddr, double *pUpperLimit,
double *pLowerLimit);
typedef caStatus pvAlarmLimits (void *pPVAddr, double *pUpperAlarmLimit,
double *pUpperWarningLimit, double *pLowerWarningLimit,
double *pLowerAlarmLimit);
/*
* Optional per channel interface
*
* Per channel state required if the application
* implements access control
*/
typedef caStatus chAddrCreate (void *pPVAddr, chId id, void **ppChanAddr);
typedef caStatus chAddrDelete (void *pChAddr);
typedef caStatus chSetOwner (void *pChAddr, const char *pUser, const char *pHost);
#define channelInterest_AccessRights (1<<0)
typedef caStatus chInterestRegister (void *pChAddr, unsigned select);
typedef caStatus chInterestDelete (void *pChAddr);
typedef epicsBoolean chReadAccess (void *pChAddr);
typedef epicsBoolean chWriteAccess (void *pChAddr);
/*
* If an entry point isnt supplied by the application
* (set to NULL) then the server lib will fill in
* a default action
*/
typedef struct cas_application_entry_table{
pvExistTest *pPVExistTest;
pvAddrCreate *pPVAddrCreate;
pvAddrDelete *pPVAddrDelete;
pvInterestRegister *pPVInterestRegister;
pvInterestDelete *pPVInterestDelete;
pvLock *pPVLock;
pvUnlock *pPVUnlock;
pvWriteAction *pPVWriteAction;
pvReadAction *pPVReadAction;
pvAlarmStatus *pPVAlarmStatus;
pvTimeStamp *pPVTimeStamp;
pvNativeType *pPVNativeType;
pvBestExternalType *pPVBestExternalType;
pvNativeElementCount *pPVNativeElementCount;
pvNativeAddress *pPVNativeAddress;
pvNativeRingIndex *pPVNativeRingIndex;
pvUnits *pPVUnits;
pvPrecision *pPVPrecision;
pvEnumStateCount *pPVEnumStateCount;
pvEnumStateString *pPVEnumStateString;
pvGraphLimits *pPVGraphLimits;
pvControlLimits *pPVControlLimits;
pvAlarmLimits *pPVAlarmLimits;
chAddrCreate *pChAddrCreate;
chAddrDelete *pChAddrDelete;
chSetOwner *pChSetOwner;
chInterestRegister *pChInterestRegister;
chInterestDelete *pChInterestDelete;
chReadAccess *pChReadAccess;
chWriteAccess *pChWriteAccess;
}casAppEntryTable;
/*
* ===========================================================
* called by the application
* ===========================================================
*/
/*
* Context used when creating a server.
* Set appropriate flag in the "flags"
* field for each parameter that does
* not default.
*/
#define casCreateCtx_pvCountEstimate (1<<1)
#define casCreateCtx_pvMaxNameLength (2<<1) /* required */
typedef struct {
unsigned flags;
unsigned pvCountEstimate; /* estimated max PV's in this server*/
unsigned pvMaxNameLength; /* ma char in PV name - required */
}casCreateCtx;
void *caMalloc (size_t size);
void *caCalloc (size_t count, size_t size);
void caFree (void *pBlock);
/*
* NOTE: Always force casAppEntryTable to zero prior to initializatiion
* so that if new entries are added to the bottom of the structure
* existing code will specify nill entries for any new entry points
* and therefore take the default.
*/
typedef void *caServerId;
caStatus caServerCreate (const casAppEntryTable *pTable,
const casCreateCtx *pCtx, caServerId *pId);
caStatus caServerDelete (caServerId id);
caStatus caServerProcess (caServerId id, const caTime *pDelay);
typedef unsigned caServerTimerId;
caStatus caServerAddTimeout (caServerId id, const caTime *pDelay,
void (*pFunc)(void *pParam), void *pParam,
caServerTimerId *pAlarmId);
caStatus caServerDeleteTimeout (caServerId id, caServerTimerId alarmId);
caStatus caServerSetDebugLevel (caServerId id, unsigned level);
caStatus caServerShow (caServerId id, unsigned level);
/*
* Application calls this function if a PV's state is modified.
*/
caStatus caServerPostPVEvent (caServerId casid, pvId id,
unsigned eventSelect);
/*
* Application calls this function when an asynchronous IO operation
* completes.
*/
caStatus caServerPostPVIOCompletion (caServerId casid,
pvId id, caStatus status);
/*
* Application calls this function if a channel's state is modified.
* For example, the access rights change for a particular client attached
* to a particular PV may change.
*/
caStatus caServerPostChEvent (caServerId casid, chId id,
unsigned eventSelect);
/*
* ===========================================================
* for internal use by the server library
* (and potentially returned to the server application)
* ===========================================================
*/
#define S_cas_success 0
#define S_cas_internal (M_cas| 1) /*Internal failure*/
#define S_cas_noMemory (M_cas| 2) /*Memory allocation failed*/
#define S_cas_portInUse (M_cas| 3) /*IP port already in use*/
#define S_cas_hugeRequest (M_cas | 4) /*Requested op does not fit*/
#define S_cas_sendBlocked (M_cas | 5) /*Blocked for send q space*/
#define S_cas_badElementCount (M_cas | 6) /*Bad element count*/
#define S_cas_noConvert (M_cas | 7) /*No conversion between src & dest types*/
#define S_cas_badWriteType (M_cas | 8) /*Src type inappropriate for write*/
#define S_cas_ioBlocked (M_cas | 9) /*Blocked for io completion*/
#define S_cas_partialMessage (M_cas | 10) /*Partial message*/
#define S_cas_noContext (M_cas | 11) /*Context parameter is required*/
#define S_cas_disconnect (M_cas | 12) /*Lost connection to server*/
#define S_cas_recvBlocked (M_cas | 13) /*Recv blocked*/
#define S_cas_badType (M_cas | 14) /*Bad data type*/
#define S_cas_timerDoesNotExist (M_cas | 15) /*Timer does not exist*/
/*
* ===========================================================
* returned by the application (to the server library)
* ===========================================================
*/
#define S_casApp_success 0
#define S_casApp_noMemory (M_casApp | 1) /*Memory allocation failed*/
#define S_casApp_pvNotFound (M_casApp | 2) /*PV not found*/
#define S_casApp_badPVId (M_casApp | 3) /*Unknown PV identifier*/
#define S_casApp_noSupport (M_casApp | 4) /*No application support for op*/
#define S_casApp_asyncCompletion (M_casApp | 5) /*Operation will complete asynchronously*/
----------
X-Sun-Data-Type: c-file
X-Sun-Data-Description: c-file
X-Sun-Data-Name: exampleCaServer.c
X-Sun-Content-Lines: 812
/*
*
* Example CA server
*
* This is intended to run in a single threaded Process
*/
/*
* ANSI
*/
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
/*
* EPICS
*/
#include <casdef.h>
#ifndef max
#define max(A,B) ((A)<(B)?(B):(A))
#endif
#ifndef min
#define min(A,B) ((A)>(B)?(B):(A))
#endif
#ifndef NELEMENTS
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
#endif
#define LOCAL static
LOCAL pvExistTest excasPVExistTest;
LOCAL pvAddrCreate excasPVAddrCreate;
LOCAL pvAddrDelete excasPVAddrDelete;
LOCAL pvInterestRegister excasPVInterestRegister;
LOCAL pvInterestDelete excasPVInterestDelete;
LOCAL pvLock excasPVLock;
LOCAL pvUnlock excasPVUnlock;
LOCAL pvWriteAction excasPVWriteAction;
LOCAL pvReadAction excasPVReadAction;
LOCAL pvAlarmStatus excasPVAlarmStatus;
LOCAL pvTimeStamp excasPVTimeStamp;
LOCAL pvNativeType excasPVNativeType;
LOCAL pvBestExternalType excasPVBestExternalType;
LOCAL pvNativeElementCount excasPVNativeElementCount;
LOCAL pvNativeAddress excasPVNativeAddress;
LOCAL pvNativeRingIndex excasPVNativeRingIndex;
LOCAL pvUnits excasPVUnits;
LOCAL pvPrecision excasPVPrecision;
LOCAL pvEnumStateCount excasPVEnumStateCount;
LOCAL pvEnumStateString excasPVEnumStateString;
LOCAL pvGraphLimits excasPVGraphLimits;
LOCAL pvControlLimits excasPVControlLimits;
LOCAL pvAlarmLimits excasPVAlarmLimits;
LOCAL chAddrCreate excasChAddrCreate;
LOCAL chAddrDelete excasChAddrDelete;
LOCAL chSetOwner excasChSetOwner;
LOCAL chInterestRegister excasChInterestRegister;
LOCAL chInterestDelete excasChInterestDelete;
LOCAL chReadAccess excasChReadAccess;
LOCAL chWriteAccess excasChWriteAccess;
casAppEntryTable excasAET = {
excasPVExistTest,
excasPVAddrCreate,
excasPVAddrDelete,
excasPVInterestRegister,
excasPVInterestDelete,
excasPVLock,
excasPVUnlock,
excasPVWriteAction,
excasPVReadAction,
excasPVAlarmStatus,
excasPVTimeStamp,
excasPVNativeType,
excasPVBestExternalType,
excasPVNativeElementCount,
excasPVNativeAddress,
excasPVNativeRingIndex,
excasPVUnits,
excasPVPrecision,
excasPVEnumStateCount,
excasPVEnumStateString,
excasPVGraphLimits,
excasPVControlLimits,
excasPVAlarmLimits,
excasChAddrCreate,
excasChAddrDelete,
excasChSetOwner,
excasChInterestRegister,
excasChInterestDelete,
excasChReadAccess,
excasChWriteAccess
};
LOCAL void scanPV (void *pParam);
LOCAL void asyncWriteDone (void *pParam);
LOCAL void asyncReadDone (void *pParam);
typedef enum {excasIoSync, excasIoAsync} excasIoType;
typedef struct {
ELLNODE node;
caTime scanRate;
char *pName;
epicsFloat32 value;
epicsFloat32 hopr;
epicsFloat32 lopr;
excasIoType ioType;
caServerTimerId scanTimerId;
caServerTimerId asyncIoTimerId;
epicsBoolean scanPending;
epicsBoolean ioPending;
epicsBoolean interest;
pvId id;
}excasPV;
typedef struct{
excasPV *pPV;
chId id;
}excasCh;
LOCAL caServerId excas;
LOCAL excasPV pvList[] = {
{{0,0}, {1,0}, "jane", 8.0, 10.0, -10.0, excasIoAsync},
{{0,0}, {1,0}, "fred", 0.8, 1.0, -1.0, excasIoSync}
};
#define myPI 3.14159265358979323846
/*
* main ()
*/
int main (int argc, char **argv)
{
caTime delay;
casCreateCtx ctx;
int status;
ctx.flags = casCreateCtx_pvCountEstimate |
casCreateCtx_pvMaxNameLength;
ctx.pvCountEstimate = 1;
ctx.pvMaxNameLength = 32;
status = caServerCreate (&excasAET, &ctx, &excas);
if (status != S_casApp_success) {
errMessage (status, "Unable to start the server");
return status;
}
if (argc > 1) {
status = caServerSetDebugLevel (excas, 10);
assert (status == S_casApp_success);
}
while (epicsTrue) {
delay.sec = 1;
delay.nsec = 0;
status = caServerProcess (excas, &delay);
if (status) {
errMessage (status, "Server processing failed");
return status;
}
}
}
/*
* scanPV ()
*/
LOCAL void scanPV (void *pParam)
{
excasPV *pPV = pParam;
double radians;
caStatus status;
pPV->scanPending = epicsFalse;
radians = (rand () * 2.0 * myPI)/RAND_MAX;
pPV->value += sin (radians) / 10.0;
pPV->value = min (pPV->value, pPV->hopr);
pPV->value = max (pPV->value, pPV->lopr);
if (pPV->interest==epicsTrue) {
status = caServerPostPVEvent (excas, pPV->id, ~0);
if (status) {
errMessage (status, "Server event post failed");
}
status = caServerAddTimeout (excas, &pPV->scanRate,
scanPV, pParam, &pPV->scanTimerId);
if (status) {
errPrintf (status, __FILE__, __LINE__,
"Scan init for %s failed\n", pPV->pName);
}
else {
pPV->scanPending = epicsTrue;
}
}
}
/*
* excasPVExistTest()
*/
LOCAL epicsBoolean excasPVExistTest(
const char *pvName,
char *pOfficialNameBuf,
unsigned bufSize)
{
caStatus status;
unsigned size;
epicsBoolean match = epicsFalse;
excasPV *pPV;
excasPV *pPVAfter = &pvList[NELEMENTS(pvList)];
size = strlen(pvName);
if (size>bufSize-1) {
return epicsFalse;
}
pPV = pvList;
for (pPV = pvList; pPV < pPVAfter; pPV++) {
if (strcmp (pvName, pPV->pName) == '\0') {
match = epicsTrue;
break;
}
}
if (match==epicsTrue) {
/*
* there are no name aliases in this
* server's PV name syntax
*/
strncpy (pOfficialNameBuf, pvName, bufSize);
}
return match;
}
/*
* excasPVAddrCreate()
*/
LOCAL caStatus excasPVAddrCreate(
const char *pvNameString,
chId id,
void **ppPVAddr)
{
caStatus status;
epicsBoolean match = epicsFalse;
excasPV *pPV; /* per PV */
excasPV *pNewPV; /* per PV */
excasPV *pPVAfter = &pvList[NELEMENTS(pvList)];
pPV = pvList;
for (pPV = pvList; pPV < pPVAfter; pPV++) {
if (strcmp (pvNameString, pPV->pName) == '\0') {
match = epicsTrue;
break;
}
}
if (match == epicsFalse) {
return S_casApp_pvNotFound;
}
pNewPV = caMalloc (sizeof (*pNewPV));
if (!pNewPV) {
return S_casApp_noMemory;
}
*pNewPV = *pPV;
pNewPV->id = id;
*ppPVAddr = pNewPV;
return S_casApp_success;
}
/*
* excasPVAddrDelete()
*/
LOCAL caStatus excasPVAddrDelete(void *pPVAddr)
{
caStatus status;
excasPV *pPV = pPVAddr;
if (pPV->ioPending == epicsTrue) {
status = caServerDeleteTimeout (excas, pPV->asyncIoTimerId);
if (status) {
errPrintf (status, __FILE__, __LINE__,
"Async IO delete for %s failed\n",
pPV->pName);
}
}
if (pPV->scanPending == epicsTrue) {
status = caServerDeleteTimeout (excas, pPV->scanTimerId);
if (status) {
errPrintf (status, __FILE__, __LINE__,
"Scan delete for %s failed\n",
pPV->pName);
}
}
caFree (pPV);
return S_casApp_success;
}
/*
* excasPVInterestRegister ()
*/
LOCAL caStatus excasPVInterestRegister (void *pPVAddr, unsigned select)
{
caStatus status;
excasPV *pPV = pPVAddr;
if (!pPV->scanPending) {
status = caServerAddTimeout (excas, &pPV->scanRate,
scanPV, pPV, &pPV->scanTimerId);
if (status) {
errPrintf (status, __FILE__, __LINE__,
"Scan init for %s failed\n", pPV->pName);
}
else {
pPV->scanPending = epicsTrue;
}
}
pPV->interest = epicsTrue;
return S_casApp_success;
}
/*
* excasPVInterestDelete ()
*/
LOCAL caStatus excasPVInterestDelete (void *pPVAddr)
{
caStatus status;
excasPV *pPV = pPVAddr;
if (pPV->scanPending==epicsTrue) {
status = caServerDeleteTimeout (excas, pPV->scanTimerId);
if (status) {
errPrintf (status, __FILE__, __LINE__,
"Scan delete for %s failed\n",
pPV->pName);
}
pPV->scanPending = epicsFalse;
}
pPV->interest = epicsFalse;
return S_casApp_success;
}
/*
* excasPVLock ()
*/
LOCAL caStatus excasPVLock (void *pPVAddr)
{
excasPV *pPV = pPVAddr;
return S_casApp_success;
}
/*
* excasPVUnlock ()
*/
LOCAL caStatus excasPVUnlock (void *pPVAddr)
{
excasPV *pPV = pPVAddr;
return S_casApp_success;
}
/*
* excasPVWriteAction ()
*/
LOCAL caStatus excasPVWriteAction (void *pPVAddr)
{
excasPV *pPV = pPVAddr;
long status;
if (pPV->ioType == excasIoAsync) {
caTime asyncDelay = {1,0};
status = caServerAddTimeout (excas, &asyncDelay,
asyncWriteDone, pPVAddr,
&pPV->asyncIoTimerId);
if (status) {
errPrintf (
status,
__FILE__,
__LINE__,
"Async IO init for %s failed\n",
pPV->pName);
return status;
}
else {
pPV->ioPending = epicsTrue;
}
return S_casApp_asyncCompletion;
}
else if (pPV->interest==epicsTrue) {
status = caServerPostPVEvent (excas, pPV->id, ~0);
if (status) {
errMessage (status, "Server event post failed");
}
}
return status;
}
/*
* asyncWriteDone ()
*/
LOCAL void asyncWriteDone (void *pParam)
{
excasPV *pPV = pParam;
caStatus status;
pPV->ioPending = epicsFalse;
status = caServerPostPVIOCompletion (
excas, pPV->id, S_casApp_success);
if (status) {
errMessage (status, "Server io done post failed");
}
if (pPV->interest==epicsTrue) {
status = caServerPostPVEvent (excas, pPV->id, ~0);
if (status) {
errMessage (status,
"Server io done event post failed");
}
}
}
/*
* excasPVReadAction ()
*/
LOCAL caStatus excasPVReadAction (void *pPVAddr)
{
excasPV *pPV = pPVAddr;
caStatus status;
if (pPV->ioType == excasIoAsync) {
caTime asyncDelay = {1,0};
status = caServerAddTimeout (excas, &asyncDelay,
asyncReadDone, pPVAddr,
&pPV->asyncIoTimerId);
if (status) {
errPrintf (
status,
__FILE__,
__LINE__,
"Async Read IO init for %s failed\n",
pPV->pName);
return status;
}
else {
pPV->ioPending = epicsTrue;
}
return S_casApp_asyncCompletion;
}
return S_casApp_success;
}
/*
* asyncReadDone ()
*/
LOCAL void asyncReadDone (void *pParam)
{
excasPV *pPV = pParam;
caStatus status;
pPV->ioPending = epicsFalse;
status = caServerPostPVIOCompletion (
excas, pPV->id, S_casApp_success);
if (status) {
errMessage (status, "Server io done post failed");
}
if (pPV->interest==epicsTrue) {
status = caServerPostPVEvent (excas, pPV->id, ~0);
if (status) {
errMessage (status,
"Server io done event post failed");
}
}
}
/*
* excasPVAlarmStatus ()
*/
LOCAL caStatus excasPVAlarmStatus (void *pPVAddr,
epicsAlarmSeverity *pSeverity, epicsAlarmCondition *pCondition)
{
excasPV *pPV = pPVAddr;
*pSeverity = epicsSevNone;
*pCondition = epicsAlarmRead; /* dont care */
return S_casApp_success;
}
/*
* excasPVTimeStamp ()
*/
LOCAL caStatus excasPVTimeStamp (void *pPVAddr, TS_STAMP *pTimeStamp)
{
long tsStatus;
excasPV *pPV = pPVAddr;
/*
* tsLocalTime () does not return zero on success
*/
tsStatus = tsLocalTime (pTimeStamp);
if (tsStatus == S_ts_OK) {
return S_casApp_success;
}
else {
return tsStatus;
}
}
/*
* excasPVNativeType ()
*/
LOCAL caStatus excasPVNativeType (void *pPVAddr, epicsType *pType)
{
excasPV *pPV = pPVAddr;
*pType = epicsFloat32T;
return S_casApp_success;
}
/*
* excasPVBestExternalType()
*/
LOCAL caStatus excasPVBestExternalType (void *pPVAddr, epicsType *pType)
{
excasPV *pPV = pPVAddr;
*pType = epicsFloat32T;
return S_casApp_success;
}
/*
* excasPVNativeElementCount()
*/
LOCAL caStatus excasPVNativeElementCount (void *pPVAddr, unsigned long *pCount)
{
excasPV *pPV = pPVAddr;
*pCount = 1;
return S_casApp_success;
}
/*
* excasPVNativeAddress()
*/
LOCAL caStatus excasPVNativeAddress (void *pPVAddr, void **pPointer)
{
excasPV *pPV = pPVAddr;
*pPointer = &pPV->value;
return S_casApp_success;
}
/*
* excasPVNativeRingIndex()
*/
LOCAL caStatus excasPVNativeRingIndex (void *pPVAddr, unsigned long *pIndex)
{
excasPV *pPV = pPVAddr;
*pIndex = 0;
return S_casApp_success;
}
/*
* excasPVUnits()
*/
LOCAL caStatus excasPVUnits (void *pPVAddr, unsigned bufByteSize,
char *pStringBuf)
{
excasPV *pPV = pPVAddr;
unsigned newsize = bufByteSize-1;
strncpy (pStringBuf, "@#$%", newsize);
pStringBuf[newsize] = '\0';
return S_casApp_success;
}
/*
* excasPVPrecision()
*/
LOCAL caStatus excasPVPrecision (void *pPVAddr, unsigned *pPrecision)
{
excasPV *pPV = pPVAddr;
*pPrecision = 4U;
return S_casApp_success;
}
/*
* excasPVEnumStateCount ()
*/
LOCAL caStatus excasPVEnumStateCount (void *pPVAddr,
unsigned nStatesMax, unsigned *nStates)
{
excasPV *pPV = pPVAddr;
*nStates = 0;
return S_casApp_success;
}
/*
* excasPVEnumStateString ()
*/
LOCAL caStatus excasPVEnumStateString (void *pPVAddr, unsigned stateNumber,
unsigned bufByteSize, char *pStringBuf)
{
excasPV *pPV = pPVAddr;
return S_casApp_noSupport;
}
/*
* excasPVGraphLimits()
*/
LOCAL caStatus excasPVGraphLimits (void *pPVAddr, double *pUpperLimit,
double *pLowerLimit)
{
excasPV *pPV = pPVAddr;
*pUpperLimit = pPV->hopr;
*pLowerLimit = pPV->lopr;
return S_casApp_success;
}
/*
* excasPVControlLimits()
*/
LOCAL caStatus excasPVControlLimits (
void *pPVAddr,
double *pUpperLimit,
double *pLowerLimit)
{
excasPV *pPV = pPVAddr;
*pUpperLimit = pPV->hopr;
*pLowerLimit = pPV->lopr;
return S_casApp_success;
}
/*
* excasPVAlarmLimits()
*/
LOCAL caStatus excasPVAlarmLimits (
void *pPVAddr,
double *pUpperAlarmLimit,
double *pUpperWarningLimit,
double *pLowerWarningLimit,
double *pLowerAlarmLimit)
{
excasPV *pPV = pPVAddr;
epicsFloat32 diff;
diff = pPV->hopr-pPV->lopr;
*pUpperAlarmLimit = diff * 0.8 + pPV->lopr;
*pUpperWarningLimit = diff * 0.7 + pPV->lopr;
*pLowerWarningLimit = diff * 0.3 + pPV->lopr;
*pLowerAlarmLimit = diff * 0.2 + pPV->lopr;
return S_casApp_success;
}
/*
* excasChAddrCreate ()
*/
LOCAL caStatus excasChAddrCreate (void *pPVAddr, chId id, void **ppChanAddr)
{
excasCh *pCh;
pCh = caCalloc(sizeof(*pCh), 1);
if(!pCh){
return S_casApp_noMemory;
}
pCh->id = id;
pCh->pPV = pPVAddr;
*ppChanAddr = pCh;
return S_casApp_success;
}
/*
* excasChAddrDelete ()
*/
LOCAL caStatus excasChAddrDelete (void *pChAddr)
{
excasCh *pCh = pChAddr;
int status;
caFree(pCh);
return S_casApp_success;
}
/*
* excasChSetOwner ()
*/
LOCAL caStatus excasChSetOwner (void *pChAddr, const char *pUser,
const char *pHost)
{
return S_casApp_success;
}
/*
* excasChInterestRegister ()
*/
LOCAL caStatus excasChInterestRegister (void *pPVAddr, unsigned select)
{
return S_casApp_success;
}
/*
* excasChInterestDelete()
*/
LOCAL caStatus excasChInterestDelete (void *pPVAddr)
{
return S_casApp_success;
}
/*
* excasChReadAccess ()
*/
LOCAL epicsBoolean excasChReadAccess (void *pChAddr)
{
excasCh *pCh = pChAddr;
return epicsTrue;
}
/*
* excasChWriteAccess ()
*/
LOCAL epicsBoolean excasChWriteAccess (void *pChAddr)
{
excasCh *pCh = pChAddr;
return epicsTrue;
}
- Navigate by Date:
- Prev:
Re: Anyone using fast ethernet in their IOCs? Mark Rivers
- Next:
Re[4]: Portable CA Server Rick McGonegal
- Index:
1994
<1995>
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: Anyone using fast ethernet in their IOCs? Mark Rivers
- Next:
Re[4]: Portable CA Server Rick McGonegal
- Index:
1994
<1995>
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|