|
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
2025
2026
- 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
2025
2026
|