Compare commits

..

25 Commits

Author SHA1 Message Date
Jim Kowalkowski
6931273fef New utilities to list PVs on an IOC and loaded applications. 1995-09-13 18:27:48 +00:00
Jim Kowalkowski
8d52177933 Fixed the address of ioc by name in BSlib.c.
Added app list to the services of PVSvx.
Removed rdbls from PVSserver - made it a separate file.
1995-09-13 18:26:42 +00:00
Jim Kowalkowski
b64fa8bd87 Fixed bug in TSinit - Gives defaults to TSdirectTime() and TSdriverInit() if
event time disabled with TSconfigure().
1995-09-12 15:01:09 +00:00
Janet B. Anderson
34ce2ab6ac Added include for sockio and a cast for tsin in memset. 1995-09-08 14:56:30 +00:00
Jim Kowalkowski
43ef20b90c Completed first version of vx info server and workstation utility.
Removed the stupid program PVSget.
1995-09-07 21:25:59 +00:00
Jim Kowalkowski
818bc0d475 New library and PV dump programs for IOC and client workstation 1995-09-06 21:06:07 +00:00
Jim Kowalkowski
ca2f9aff52 Corrected a problem with building dbLoadTemplate/subtool.
Added the BS and PVS test functions
1995-09-06 21:05:09 +00:00
Jim Kowalkowski
64a93df872 Changed the error message 1995-09-06 21:04:22 +00:00
Jim Kowalkowski
ecc03e9ad9 Cleanup and addition of application() to db file 1995-09-06 21:03:07 +00:00
John Winans
db1b46e5f9 Added ability to change default clock speed from shell. 1995-09-01 14:36:35 +00:00
Marty Kraimer
d87295397e Still new 1995-09-01 14:35:27 +00:00
Marty Kraimer
7277c336f7 Fixed bug causing memory problem 1995-09-01 14:31:32 +00:00
Marty Kraimer
30ad5b1149 Added so that individual files dont have to have long notice 1995-09-01 12:47:28 +00:00
Marty Kraimer
c6bcd1a10b Still new 1995-08-30 21:31:43 +00:00
Marty Kraimer
f3cf369071 made separate from recDynLink 1995-08-30 21:18:29 +00:00
Marty Kraimer
adffe02a2d Still new 1995-08-30 21:17:46 +00:00
Marty Kraimer
e635080cef Fixed problems with freeing pvd 1995-08-30 17:43:19 +00:00
Jim Kowalkowski
be85da6a3a *** empty log message *** 1995-08-30 15:38:39 +00:00
Marty Kraimer
c16006f34d recDynLink is new 1995-08-29 17:55:20 +00:00
Janet B. Anderson
72491d8829 Added startup directory to release tar file 1995-08-28 15:49:54 +00:00
Marty Kraimer
cb78c5adb8 Changes so that function prototype for db_post_event defined 1995-08-28 14:50:32 +00:00
Jeff Hill
1a2cd5953d added log entries 1995-08-23 00:35:17 +00:00
Jeff Hill
5da79a5f56 fixed vxWorks specific SPARC data alignment problem 1995-08-23 00:34:06 +00:00
Jeff Hill
9f2d9587f0 additional parenthesis in macro to be safe 1995-08-23 00:31:13 +00:00
cvs2svn
74e405969a This commit was manufactured by cvs2svn to create tag 'R3.12.1.1'. 1995-08-22 12:23:38 +00:00
31 changed files with 3147 additions and 65 deletions

View File

@@ -0,0 +1,45 @@
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE,
AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE
AND IN ALL SOURCE LISTINGS OF THE CODE.
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
Argonne National Laboratory (ANL), with facilities in the States of
Illinois and Idaho, is owned by the United States Government, and
operated by the University of Chicago under provision of a contract
with the Department of Energy.
Portions of this material resulted from work developed under a U.S.
Government contract and are subject to the following license: For
a period of five years from March 30, 1993, the Government is
granted for itself and others acting on its behalf a paid-up,
nonexclusive, irrevocable worldwide license in this computer
software to reproduce, prepare derivative works, and perform
publicly and display publicly. With the approval of DOE, this
period may be renewed for two additional five year periods.
Following the expiration of this period or periods, the Government
is granted for itself and others acting on its behalf, a paid-up,
nonexclusive, irrevocable worldwide license in this computer
software to reproduce, prepare derivative works, distribute copies
to the public, perform publicly and display publicly, and to permit
others to do so.
*****************************************************************
DISCLAIMER
*****************************************************************
NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR
THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS,
MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL
LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS
DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY
OWNED RIGHTS.
*****************************************************************
LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY
DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).

View File

@@ -10,6 +10,10 @@
# [-b] - For fully built release
#
# $Log$
# Revision 1.1 1995/08/17 20:14:56 jba
# Added base/tools scripts functionality to base/Makefile, removed scripts
# Moved base/tools/MakeRelease to base dir.
#
# Revision 1.14 1994/12/19 18:42:08 tang
# Make the args length compatible for HP and SUN.
#
@@ -100,6 +104,12 @@ ls base/README* | xargs tar cvf ${RELS}.Tar
ls base/Makefile* > /tmp/make_release.out.$$;
if [ -d startup ];
then
find startup -name CVS -prune -o ! -type d -print \
>> /tmp/make_release.out.$$;
fi
find config base/include base/man base/tools -name CVS -prune -o \
! -type d -print >> /tmp/make_release.out.$$;

View File

@@ -0,0 +1,10 @@
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
**********************************************************************/

View File

@@ -1,3 +1,4 @@
/* $Id$ */
/************************************************************************/
/* */
/* L O S A L A M O S */
@@ -98,6 +99,13 @@
/************************************************************************/
/*
* $Log$
* Revision 1.76 1995/08/23 00:34:06 jhill
* fixed vxWorks specific SPARC data alignment problem
*
* Revision 1.75 1995/08/22 00:15:19 jhill
* Use 1.0/USEC_PER_SEC and not 1.0e-6
* Check for S_db_Pending when calling dbPutNotify()
*
* Revision 1.74 1995/08/22 00:12:07 jhill
* *** empty log message ***
*
@@ -968,13 +976,14 @@ int epicsShareAPI ca_search_and_connect
* also allocate enough for the channel name & paddr
* block
*/
size = sizeof(*chix) + strcnt + sizeof(struct db_addr);
size = sizeof(*chix) + strcnt + sizeof(struct db_addr)
+CA_MESSAGE_ALIGN(1);
*chixptr = chix = (chid) calloc(1,size);
if (!chix){
return ECA_ALLOCMEM;
}
chix->id.paddr = (struct db_addr *)
(strcnt + (char *) (chix + 1));
CA_MESSAGE_ALIGN(strcnt+(char *)(chix+1));
*chix->id.paddr = tmp_paddr;
chix->puser = puser;
chix->pConnFunc = conn_func;

View File

@@ -1,4 +1,5 @@
#ifndef __IOCMSG__
/* $Id$ */
/*
* History
* .01 01xx90 joh removed status field in favor of a independent m_cmmd-
@@ -23,6 +24,7 @@
* .09 050594 joh New command added for CA V4.3 - repeater fanout register
*
* .10 050594 joh New command added for CA V4.3 - wakeup the server
* $Log$
*/
#define __IOCMSG__
@@ -113,15 +115,15 @@ typedef ca_uint32_t caResId;
#define DONTREPLY 5
/* size of object in bytes rounded up to nearest oct word */
#define OCT_ROUND(A) ((((unsigned long)A)+7)>>3)
#define OCT_ROUND(A) ((((unsigned long)(A))+7)>>3)
#define OCT_SIZEOF(A) (OCT_ROUND(sizeof(A)))
/* size of object in bytes rounded up to nearest long word */
#define QUAD_ROUND(A) (((unsigned long)A)+3)>>2)
#define QUAD_ROUND(A) (((unsigned long)(A))+3)>>2)
#define QUAD_SIZEOF(A) (QUAD_ROUND(sizeof(A)))
/* size of object in bytes rounded up to nearest short word */
#define BI_ROUND(A) ((((unsigned long)A)+1)>>1)
#define BI_ROUND(A) ((((unsigned long)(A))+1)>>1)
#define BI_SIZEOF(A) (BI_ROUND(sizeof(A)))
/*

View File

@@ -90,6 +90,7 @@
#include <dbFldTypes.h>
#include <dbRecDes.h>
#include <dbRecType.h>
#include <dbEvent.h>
#include <db_field_log.h>
#include <errMdef.h>
#include <recSup.h>

View File

@@ -622,14 +622,16 @@ int db_post_single_event(struct event_block *pevent)
*
*/
int db_post_events(
struct dbCommon *precord,
union native_value *pvalue,
unsigned int select
void *prec,
void *pval,
unsigned int select
)
{
struct event_block *event;
struct event_que *ev_que;
unsigned int putix;
struct dbCommon *precord = (struct dbCommon *)prec;
union native_value *pvalue = (union native_value *)pval;
struct event_block *event;
struct event_que *ev_que;
unsigned int putix;
if (precord->mlis.count == 0) return OK; /* no monitors set */

View File

@@ -83,6 +83,7 @@
#include <dbFldTypes.h>
#include <dbRecDes.h>
#include <dbRecType.h>
#include <dbEvent.h>
#include <db_field_log.h>
#include <errMdef.h>
#include <recSup.h>

View File

@@ -51,6 +51,7 @@
#include <ellLib.h>
#include <vxLib.h>
#include <tickLib.h>
#include <sysLib.h>
#include <dbDefs.h>
#include <dbAccess.h>

View File

@@ -439,7 +439,6 @@ DBBASE *pdbbase;
ELLLIST *preclist;
int recType;
if (!pdbbase || !ppvd || !precType) return;
dbPvdFreeMem(pdbbase);
/* loop thru the recLocs - removing lists then recLoc only */
for (recType = 0; recType < precType->number; recType++) {
if (!(precLoc = GET_PRECLOC(precHeader, recType))) continue;
@@ -461,6 +460,7 @@ DBBASE *pdbbase;
free((void *) precLoc);
}
/* free the rest of the memory allocations */
dbPvdFreeMem(pdbbase);
if (pdbbase->pchoiceCvt)
free((void *) pdbbase->pchoiceCvt);
if (pdbbase->pchoiceDev)
@@ -4316,7 +4316,8 @@ RECNODE *precnode;
ppvdlist=ppvd[hashInd];
ppvdNode = (PVDENTRY *) ellFirst(ppvdlist);
while(ppvdNode) {
if(strcmp(name,(char *)ppvdNode->precnode->precord) == 0) {
if(ppvdNode->precnode && ppvdNode->precnode->precord
&& strcmp(name,(char *)ppvdNode->precnode->precord) == 0) {
ellDelete(ppvdlist, (ELLNODE*)ppvdNode);
free((void *)ppvdNode);
return;

View File

@@ -96,6 +96,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <timexLib.h>
#include <ellLib.h>
#include <fast_lock.h>
@@ -112,6 +113,7 @@
#include <special.h>
#include <dbRecDes.h>
#include <dbStaticLib.h>
#include <dbEvent.h>
#include <ellLib.h>
#include <callback.h>
@@ -170,18 +172,6 @@ long dba(char*pname)
if(status) return(1); else return(0);
}
/*Following definition is from dbEvent.c*/
struct event_block{
ELLNODE node;
struct dbAddr *paddr;
void (*user_sub)();
void *user_arg;
struct event_que *ev_que;
unsigned char select;
char valque;
unsigned short npend; /* n times this event is on the que */
};
long dbel(char*pname)
{
struct dbAddr addr;
@@ -200,7 +190,7 @@ long dbel(char*pname)
return(0);
}
while(peb) {
pfldDes = peb->paddr->pfldDes;
pfldDes = ((struct dbAddr *)peb->paddr)->pfldDes;
printf("%4.4s",&pfldDes->fldname[0]);
if(peb->select&&DBE_VALUE) printf(" VALUE");
if(peb->select&&DBE_LOG) printf(" LOG");
@@ -1756,7 +1746,8 @@ char *record_name;
* Time the record
*/
dbScanLock(precord);
timexN(timing_routine, precord);
timexN((FUNCPTR)timing_routine, (int)precord,
0,0,0,0,0,0,0);
dbScanUnlock(precord);
return(0);

View File

@@ -1,6 +1,12 @@
/*
* $Log$
* Revision 1.14 1995/08/30 15:38:39 jbk
* *** empty log message ***
*
* Revision 1.13 1995/08/18 13:19:31 mrk
* Made changes for ansi c
*
* Revision 1.12 1995/08/17 20:35:09 jbk
* fixed all the -pendantic errors (pain)
*
@@ -99,7 +105,8 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
*/
#define MAKE_DEBUG TSdriverDebug
#define TS_DRIVER
#define TS_DRIVER 1
#define TS_ALLOW_FORCE 1
#include <vxWorks.h>
#include <vme.h>
@@ -213,6 +220,9 @@ TSinfo TSdata = { TS_master_dead, TS_async_slave, TS_async_none,
extern char* sysBootLine;
int TSdirectTimeVar = 0; /* aother way to indicate direct time */
int TSgoodTimeStamps = 0; /* a way to force use of accurate time stamps */
static WDOG_ID wd;
static long correction_factor = 0;
static long correction_count = 0;
@@ -383,8 +393,13 @@ long TSgetTimeStamp(int event_number,struct timespec* sp)
switch(event_number)
{
case 0:
*sp = TSdata.event_table[0]; /* one tick watch dog maintains */
break;
#ifdef TS_ALLOW_FORCE
if(TSgoodTimeStamps==0)
#endif
{
*sp = TSdata.event_table[0]; /* one tick watch dog maintains */
break;
}
case -1:
{
struct timespec ts;
@@ -494,6 +509,8 @@ long TSinit(void)
TSregisterErrorHandler = TSregisterErrorHandlerError;
TSforceSync = TSforceSoftSync;
TSgetTime = TSgetCurrentTime;
TSdriverInit = TSdriverInitError;
TSdirectTime = TSdirectTimeError;
TSdata.sync_event=ER_EVENT_RESET_TICK;
}
@@ -518,7 +535,7 @@ long TSinit(void)
else
TSdata.has_event_system = 1;
if(TSdirectTime()>0) TSdata.has_direct_time=1;
if(TSdirectTime()>0 || TSdirectTimeVar>0) TSdata.has_direct_time=1;
/* allocate the event table */
TSdata.event_table=(struct timespec*)malloc(

View File

@@ -52,6 +52,7 @@
#include <dbBase.h>
#include <dbRecType.h>
#include <dbRecDes.h>
#include <dbEvent.h>
#include <dbAccess.h>
#include <dbScan.h>
#include <devSup.h>

986
src/dbtools/BSlib.c Normal file
View File

@@ -0,0 +1,986 @@
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include "BSlib.h"
#ifdef linux
#include <sys/time.h>
#include <sys/resource.h>
#endif
#ifdef vxWorks
#include <vxWorks.h>
#include <in.h>
#include <ioctl.h>
#include <inetLib.h>
#include <taskLib.h>
#include <ioLib.h>
#include <sockLib.h>
#include <selectLib.h>
#else
#include <sys/sockio.h>
#include <sys/time.h>
#include <netdb.h>
#include <fcntl.h>
#endif
#ifdef SOLARIS
#define BSD_COMP
#include <sys/ioctl.h>
#endif
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <net/if.h>
static long BSgetBroadcastAddr(int soc, struct sockaddr* sin);
/* ---------------------------------------------------------------------- */
/* server mode functions */
#ifndef vxWorks /* server mode functions */
static char* filename=(char*)NULL;
/* ----------------------------- */
/* signal catcher for the server */
/* ----------------------------- */
static void catch_sig(int sig)
{
fprintf(stderr,"\nbdt server exiting\n");
unlink(filename);
exit(0);
}
/* -------------------------------- */
/* child reaper for the server mode */
/* -------------------------------- */
static void get_child(int sig)
{
#ifdef SOLARIS
while(waitpid(-1,(int*)NULL,WNOHANG)>0);
#else
while(wait3((int *)NULL,WNOHANG,(struct rusage *)NULL)>0);
#endif
#if defined linux || defined SOLARIS
signal(SIGCHLD,get_child); /* for reaping children */
#endif
}
/* ------------------------------- */
/* Clear the signals for a process */
/* ------------------------------- */
int BSserverClearSignals()
{
signal(SIGCHLD,SIG_DFL);
signal(SIGHUP,SIG_DFL);
signal(SIGINT,SIG_DFL);
signal(SIGTERM,SIG_DFL);
signal(SIGQUIT,SIG_DFL);
return 0;
}
/* ----------------------------------------------------- */
/* Make a unix process into a generic background process */
/* ----------------------------------------------------- */
int BSmakeServer(char** argv)
{
FILE* fd;
if(filename) return -1;
/* set up signal handling for the server */
signal(SIGCHLD,get_child); /* for reaping children */
signal(SIGHUP,catch_sig);
signal(SIGINT,catch_sig);
signal(SIGTERM,catch_sig);
signal(SIGQUIT,catch_sig);
/* disconnect from parent */
switch(fork())
{
case -1: /* error */
perror("Cannot fork");
return -1;
case 0: /* child */
#if defined linux || defined SOLARIS
setpgrp();
#else
setpgrp(0,0);
#endif
setsid();
break;
default: /* parent goes away */
exit(0);
}
/* save process ID */
filename=(char*)malloc(strlen(argv[0])+10);
sprintf(filename,"%s.%d",argv[0],getpid());
fd=fopen(filename,"w");
fprintf(fd,"%d",getpid());
fprintf(stderr,"\npv server pid: %d\n",getpid());
fclose(fd);
return 0;
}
#endif /* server mode functions */
/* --------------------------------------------------------------- */
/* open a bulk data socket to a server given the server IP address */
/* --------------------------------------------------------------- */
BS* BSipOpen(char* address, int Port)
{
struct hostent* pHostent;
unsigned long addr;
BSDATA info;
struct sockaddr_in* tsin;
tsin=(struct sockaddr_in*)&(info.sin);
#ifndef vxWorks
/* Deal with the name -vs- IP number issue. */
if (isdigit(address[0]))
{
#endif
addr=inet_addr(address);
#ifndef vxWorks
}
else
{
if((pHostent=gethostbyname(address))==NULL) return NULL;
memcpy((char*)&addr,pHostent->h_addr,sizeof(addr));
}
#endif
tsin->sin_port=htons(Port);
tsin->sin_family=AF_INET;
memcpy((char*)&(tsin->sin_addr),(char*)&addr,sizeof(addr));
return BSipOpenData(&info);
}
BS* BSipOpenData(BSDATA* info)
{
struct sockaddr_in tsin;
int osoc;
BS* bdt;
tsin.sin_port=0;
tsin.sin_family=AF_INET;
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
if((osoc=socket(AF_INET,SOCK_STREAM,BS_TCP))<0)
{
perror("BSipOpen: create socket failed");
return (BS*)NULL;
}
if((bind(osoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
{
perror("BSipOpen: local address bind failed");
return (BS*)NULL;
}
if(connect(osoc,(struct sockaddr*)&(info->sin),sizeof(info->sin))<0)
{
perror("BSipOpen: connect failed");
close(osoc);
return (BS*)NULL;
}
bdt=(BS*)malloc(sizeof(BS));
bdt->soc=osoc;
bdt->remaining_send=0;
bdt->remaining_recv=0;
bdt->state=BSidle;
#ifndef vxWorks
{
int j;
j = fcntl(bdt->soc, F_GETFL, 0);
fcntl(bdt->soc, F_SETFL, j|O_NDELAY);
}
#endif
/* now connected to the bulk data socket on the IOC */
return bdt;
}
/* -------------------------------------- */
/* write size bytes from buffer to socket */
/* -------------------------------------- */
int BSwrite(int soc,void* buffer,int size)
{
int rc;
int total;
unsigned char* data;
fd_set fds;
struct timeval to;
data=(unsigned char*)buffer;
total=size;
to.tv_sec = 5;
to.tv_usec = 0;
do
{
FD_ZERO(&fds);
FD_SET(soc, &fds);
if(select(FD_SETSIZE,NULL,&fds,NULL,&to) != 1)
{
printf("BSwrite: timeout waiting to write data\n");
return -1;
}
/* send block of data */
if((rc=send(soc,(char*)&data[size-total],total,0))<0)
{
if(errno == EINTR)
rc = 0;
else
perror("BSwrite: Send to remote failed");
}
else
total-=rc;
}
while(rc>0 && total>0);
return (rc<=0)?-1:0;
}
/* --------------------------------------- */
/* send a message header down a BS socket */
/* --------------------------------------- */
int BSsendHeader(BS* bdt,unsigned short verb,int size)
{
BSmsgHead buf;
if(bdt->state!=BSidle)
{
fprintf(stderr,"BSsendHeader: Interface not idle\n");
bdt->state=BSbad;
return -1;
}
buf.verb=htons(verb);
buf.size=htonl((unsigned long)size);
if(BSwrite(bdt->soc,&buf.verb, sizeof(buf.verb))<0)
{
fprintf(stderr,"BSsendHeader: write to remote failed");
return -1;
}
if(BSwrite(bdt->soc,&buf.size, sizeof(buf.size))<0)
{
fprintf(stderr,"BSsendHeader: write to remote failed");
return -1;
}
/* don't wait for response if data must go out */
if(size)
{
bdt->remaining_send=size;
bdt->state=BSsData;
}
return 0;
}
/* ------------------------------------------- */
/* send a message data chunk down a BS socket */
/* ------------------------------------------- */
int BSsendData(BS* bdt,void* buffer,int size)
{
int len;
int remaining;
int rc;
if(bdt->state!=BSsData)
{
fprintf(stderr,"BSsendData: Interface not in send data mode\n");
bdt->state=BSbad;
return -1;
}
remaining=bdt->remaining_send-size;
if(remaining<0)
{
fprintf(stderr,"WARNING -- BSsendData: To much data to send\n");
len=bdt->remaining_send;
}
else
len=size;
if (BSwrite(bdt->soc, buffer, len) < 0)
return -1;
bdt->remaining_send-=len;
if(bdt->remaining_send<0)
{
fprintf(stderr,"BSsendData: To much data Sent\n");
bdt->remaining_send=0;
}
if(bdt->remaining_send==0)
bdt->state=BSidle;
return len;
}
int BSflushOutput(BS* bdt)
{
#ifdef vxWorks
ioctl(bdt->soc, FIOWFLUSH, 0);
#endif
return 0;
}
/* ------------------------------------- */
/* Read exactly size bytes from remote */
/* ------------------------------------- */
int BSread(int soc,void* buffer,int size)
{
int rc,total;
unsigned char* data;
fd_set fds;
struct timeval to;
to.tv_sec = 5;
to.tv_usec = 0;
data=(unsigned char*)buffer;
total=size;
do
{
#if 1
/* wait for data chunk */
FD_ZERO(&fds);
FD_SET(soc, &fds);
if (select(soc+1, &fds, NULL, NULL, &to) != 1)
{
printf("BSread: timeout waiting for data\n");
return(-1);
}
#endif
if((rc=recv(soc,(char*)&data[size-total],total,0))<0)
{
if(errno==EINTR)
{
printf("BSread: EINTR");
rc=0;
}
else
{
perror("BSread: Receive data chunk failed");
}
}
else
total-=rc;
}
while(rc>0 && total>0);
return (rc<=0)?-1:0;
}
/* ------------------------------------- */
/* wait for a message header from remote */
/* ------------------------------------- */
int BSreceiveHeader(BS* bdt,int* verb,int* size)
{
BSmsgHead buf;
/* can only receive header when in the idle state */
if (bdt->state == BSeof)
return -1;
if(bdt->state != BSidle)
{
fprintf(stderr,"BSreceiveHeader: Interface not idle\n");
bdt->state=BSbad;
return -1;
}
if(BSread(bdt->soc,&buf.verb,sizeof(buf.verb))<0)
{
fprintf(stderr,"BSreceiveHeader: Read failed\n");
return -1;
}
if(BSread(bdt->soc,&buf.size,sizeof(buf.size))<0)
{
fprintf(stderr,"BSreceiveHeader: Read failed\n");
return -1;
}
/* copy message data to user */
*verb=ntohs(buf.verb);
*size=ntohl(buf.size);
if(*size)
bdt->state=BSrData;
bdt->remaining_recv=*size;
return 0;
}
/* ------------------------------------------------------------------------
Wait for a chunk of data from remote.
User can continually call this with a maximum size until it return 0.
------------------------------------------------------------------------ */
int BSreceiveData(BS* bdt,void* buffer,int size)
{
int rc;
/* can only receive data when in the receive data state */
switch(bdt->state)
{
case BSrData: break;
case BSidle: return 0;
default:
fprintf(stderr,"BSreceiveData: bad receive state\n");
bdt->state=BSbad;
break;
}
if (bdt->remaining_recv < size)
size = bdt->remaining_recv;
if(BSread(bdt->soc,buffer,size)<0)
{
fprintf(stderr,"BSreceiveData: Read failed\n");
bdt->state = BSeof;
return -1;
}
bdt->remaining_recv-=size;
if(bdt->remaining_recv<0)
{
fprintf(stderr,"BSreceiveData: To much data received\n");
bdt->remaining_recv=0;
}
if(bdt->remaining_recv==0)
bdt->state=BSidle;
return size;
}
/* -------------------- */
/* close the connection */
/* -------------------- */
int BSclose(BS* bdt)
{
int verb,size,done;
/* send a close message out */
if(BSsendHeader(bdt,BS_Close,0)<0)
{
fprintf(stderr,"BSclose: Cannot send close message\n");
return -1;
}
done=0;
do
{
/* check response */
if(BSreceiveHeader(bdt,&verb,&size)<0)
{
fprintf(stderr,"BSclose: Close message response error\n");
return -1;
}
switch(verb)
{
case BS_Ok:
done=1;
break;
case BS_Error:
fprintf(stderr,"BSclose: Close rejected\n");
return -1;
default: break;
}
}
while(done==0);
BSfreeBS(bdt);
return 0;
}
/* --------------------------------------- */
/* make a listener socket for UDP - simple */
/* --------------------------------------- */
int BSopenListenerUDP(int Port)
{
int nsoc;
struct sockaddr_in tsin;
tsin.sin_port=htons(Port);
tsin.sin_family=AF_INET;
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
if((nsoc=socket(AF_INET,SOCK_DGRAM,BS_UDP))<0)
{
perror("BSopenListenerUDP: open socket failed");
return -1;
}
if((bind(nsoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
{
perror("BSopenListenerUDP: local bind failed");
close(nsoc);
return -1;
}
return nsoc;
}
/* --------------------------------------- */
/* make a listener socket for TCP - simple */
/* --------------------------------------- */
int BSopenListenerTCP(int Port)
{
int nsoc;
struct sockaddr_in tsin;
memset ((void *)&tsin, 0, sizeof(struct sockaddr_in));
tsin.sin_port=htons(Port);
tsin.sin_family=htons(AF_INET);
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
if((nsoc=socket(AF_INET,SOCK_STREAM,BS_TCP))<0)
{
perror("BSopenListenerTCP: open socket failed");
return -1;
}
if((bind(nsoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
{
perror("BSopenListenerTCP: local bind failed");
close(nsoc);
return -1;
}
listen(nsoc,5);
return nsoc;
}
/* ------------------------------- */
/* make BS from a socket - simple */
/* ------------------------------- */
BS* BSmakeBS(int soc)
{
BS* bdt;
bdt=(BS*)malloc(sizeof(BS));
bdt->soc=soc;
bdt->remaining_send=0;
bdt->remaining_recv=0;
bdt->state=BSidle;
return bdt;
}
/* --------------------------- */
/* free a BS and close socket */
/* --------------------------- */
int BSfreeBS(BS* bdt)
{
close(bdt->soc);
free(bdt);
return 0;
}
/*-----------------------------------------------------------------------*/
/*
Next three function adjust the fields of the BSDATA structure.
*/
/*-----------------------------------------------------------------------*/
int BSgetAddressPort(BSDATA* info, char* ip_addr, int* dest_port)
{
char* name;
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
*dest_port=sin->sin_port;
name=inet_ntoa(sin->sin_addr);
strcpy(ip_addr,name);
return 0;
}
int BSsetAddressPort(BSDATA* info, char* ip_addr, int dest_port)
{
BSsetPort(info, dest_port);
return BSsetAddress(info, ip_addr);
}
int BSsetPort(BSDATA* info, int dest_port)
{
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
sin->sin_family=AF_INET;
sin->sin_port=htons(dest_port);
return 0;
}
int BSsetAddress(BSDATA* info, char* ip_addr)
{
struct hostent *pHostent;
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
unsigned long addr;
#ifndef vxWorks
/* Deal with the name -vs- IP number issue. */
if (isdigit(ip_addr[0]))
{
#endif
if((addr=inet_addr(ip_addr))==-1) return -1;
#ifndef vxWorks
}
else
{
if((pHostent=gethostbyname(ip_addr))==NULL) return -1;
memcpy((char*)&addr,pHostent->h_addr,sizeof(addr));
}
#endif
sin->sin_family=AF_INET;
memcpy((char*)&(sin->sin_addr),(char*)&addr,sizeof(addr));
return 0;
}
/* ----------------------------------------------------------------- */
/*
All this function does is send a broadcast message and return the
addressing info to the caller of a responder to the broadcast.
arguments:
soc - broadcast socket to use for sending data
trys - number of times to send if no response
o_info - outgoing BSDATA, address/port info
i_info - incoming BSDATA, address/port where response came from
omsg/osize - outgoing message and size
imsg/isize - incoming message and buffer size
Returns the number of bytes read.
*/
/* ----------------------------------------------------------------- */
int BSbroadcastTrans(int soc,int trys,BSDATA* o_info,BSDATA* i_info,
void* omsg,int osize,void* imsg,int isize)
{
int i;
int rc=0;
for(i=0;rc==0 && i<trys;i++)
{
/* send out the message */
rc=BSwriteUDP(soc,o_info,omsg,osize);
if(rc<0) return rc;
/* wait for a response */
rc=BSreadUDP(soc,i_info,1,imsg,isize);
}
return rc;
}
int BSbroadcast(int soc,BSDATA* o_info, void* omsg,int osize)
{
int rc;
/* send out the message */
rc=BSwriteUDP(soc,o_info,omsg,osize);
return rc;
}
/* ----------------------------------------------------------------------- */
/*
This function waits for a message and sends out an ACK when it gets one.
addressing info to the caller of a responder to the broadcast.
Lots of arguments:
soc - The socket to send the message down.
info - The socket information telling where the data read came from
(returned to the user).
tout - Timeout for read in seconds. 0=no wait, -1=wait forever.
buf - Buffer to populate with read data.
size - Size of the buf.
returns the length the read message, 0 is timeout, -1 is error
*/
/* ----------------------------------------------------------------------- */
int BSreadUDP(int soc,BSDATA* info,BS_ULONG tout,void* buf,int size)
{
int mlen,rc;
fd_set fds;
struct timeval to;
int error=0;
do
{
FD_ZERO(&fds);
FD_SET(soc, &fds);
if(tout==-1)
rc=select(FD_SETSIZE,&fds,NULL,NULL,NULL);
else
{
to.tv_sec=tout;
to.tv_usec=0;
rc=select(FD_SETSIZE,&fds,NULL,NULL,&to);
}
switch(rc)
{
case -1: /* bad */
switch(errno)
{
case EINTR: break;
default: error=-1; break;
}
break;
case 0: /* timeout */
break;
default: /* data ready */
break;
}
}
while(rc<0 && error==0);
error=0;
if(rc>0)
{
error=0;
do
{
info->len=sizeof(info->sin);
mlen=recvfrom(soc,(char*)buf,size,0, &info->sin,&info->len);
if(mlen<0)
{
switch(errno)
{
case EINTR: break;
default: error=-1; break;
}
}
}
while(mlen<0 && error==0);
if(mlen<0)
rc=-1;
else
rc=mlen;
}
return rc;
}
/*-----------------------------------------------------------------------*/
/*
Write a chuck of data to a UDP socket at an internet address
*/
/*-----------------------------------------------------------------------*/
int BSwriteDataUDP(int soc,int dest_port,char* ip_addr,void* buf,int size)
{
BSDATA data;
BSsetAddress(&data,ip_addr);
BSsetPort(&data,dest_port);
return BSwriteUDP(soc,&data,buf,size);
}
/*-----------------------------------------------------------------------*/
/*
Write a chunk of data to a UDP socket using BSDATA.
Arguments:
*/
/*-----------------------------------------------------------------------*/
int BSwriteUDP(int soc,BSDATA* info,void* obuf,int osize)
{
int mlen;
mlen=sendto(soc,(char*)obuf,osize,0,&info->sin,sizeof(info->sin));
return mlen;
}
/*-----------------------------------------------------------------------*/
/*
Write/Read a chuck of data to a UDP socket using BSDATA.
Arguments:
soc - socket to send message down and read from
info - address/port to send message to
obuf/osize - outgoing message and size of it.
ibuf/isize - incoming message and size of the buffer.
Returns the number of bytes read, -1 for error.
*/
/*-----------------------------------------------------------------------*/
int BStransUDP(int soc,BSDATA* info,void* obuf,int osize,void* ibuf,int isize)
{
int done,i,mlen,flen;
struct sockaddr fromsin;
fd_set fds;
struct timeval tout;
done=0;
mlen=0;
for(i=0;i<BS_RETRY_COUNT && done==0;i++)
{
mlen=sendto(soc,(char*)obuf,osize,0,&(info->sin),sizeof(info->sin));
if(mlen<0)
{
printf("send failed\n");
return -1;
}
tout.tv_sec=0;
tout.tv_usec=200000;
FD_ZERO(&fds);
FD_SET(soc,&fds);
switch(select(FD_SETSIZE,&fds,(fd_set*)0,(fd_set*)0,&tout))
{
case 0: /* timeout */ break;
case -1: /* error */
printf("select failed\n");
return -1;
default: /* data ready */
flen=sizeof(fromsin);
mlen=recvfrom(soc,(char*)ibuf,isize,0,&fromsin,&flen);
if(mlen<0) return -1;
done=1;
break;
}
}
if(i>=BS_RETRY_COUNT) return 0;
return mlen;
}
/*-----------------------------------------------------------------------*/
/*
Open a broadcast socket and set port to a default.
*/
/*-----------------------------------------------------------------------*/
int BSipBroadcastOpen(BSDATA* info, int default_dest_port)
{
struct sockaddr_in* sin;
int soc;
sin=(struct sockaddr_in*)&(info->sin);
if( (soc=BSgetBroadcastSocket(0,sin)) <0) return -1;
sin->sin_port=htons(default_dest_port);
return soc;
}
/*-----------------------------------------------------------------------*/
/*
BSgetBroadcastSocket() - return a broadcast socket for a port, return
a sockaddr also.
*/
/*-----------------------------------------------------------------------*/
int BSgetBroadcastSocket(int port, struct sockaddr_in* sin)
{
int on=1;
int soc;
BS bs;
sin->sin_port=htons(port);
sin->sin_family=AF_INET;
sin->sin_addr.s_addr=htonl(INADDR_ANY);
if( (soc=socket(AF_INET,SOCK_DGRAM,BS_UDP)) < 0 )
{
perror("socket create failed");
return -1;
}
setsockopt(soc,SOL_SOCKET,SO_BROADCAST,(char*)&on,sizeof(on));
if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 )
{
perror("socket bind failed");
close(soc);
return -1;
}
if( BSgetBroadcastAddr(soc,(struct sockaddr*)sin) < 0 )
return -1;
return soc;
}
/*-----------------------------------------------------------------------*/
/*
BSgetBroadcastAddr() - Determine the broadcast address, this is
directly from the Sun Network Programmer's guide.
*/
/*-----------------------------------------------------------------------*/
static long BSgetBroadcastAddr(int soc, struct sockaddr* sin)
{
struct ifconf ifc;
struct ifreq* ifr;
struct ifreq* save;
char buf[BUFSIZ];
int tot,i;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if(ioctl(soc,SIOCGIFCONF,(int)&ifc) < 0)
{ perror("ioctl SIOCGIFCONF failed"); return -1; }
ifr = ifc.ifc_req;
tot = ifc.ifc_len/sizeof(struct ifreq);
save=(struct ifreq*)NULL;
i=0;
do
{
if(ifr[i].ifr_addr.sa_family==AF_INET)
{
if(ioctl(soc,SIOCGIFFLAGS,(int)&ifr[i])<0)
{ perror("ioctl SIOCGIFFLAGS failed"); return -1; }
if( (ifr[i].ifr_flags&IFF_UP) &&
!(ifr[i].ifr_flags&IFF_LOOPBACK) &&
(ifr[i].ifr_flags&IFF_BROADCAST))
{ save=&ifr[i]; }
}
} while( !save && ++i<tot );
if(save)
{
if(ioctl(soc,SIOCGIFBRDADDR,(int)save)<0)
{ perror("ioctl SIOCGIFBRDADDR failed"); return -1; }
memcpy((char*)sin,(char*)&save->ifr_broadaddr,
sizeof(save->ifr_broadaddr));
}
else
return -1;
return 0;
}

188
src/dbtools/BSlib.h Normal file
View File

@@ -0,0 +1,188 @@
#ifndef ___BS_H
#define ___BS_H
/*
* $Log$
*/
/*
Author: Jim Kowalkowski
Date: 9/1/95
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* got from protocols(5) (cheated) or /etc/protocols */
#define BS_UDP 17
#define BS_TCP 6
/* server ports - in the user reserved area - above 50000 */
#define BS_UDP_PORT 50296
#define BS_TCP_PORT 50297
/* message types */
#define BS_Ok 0
#define BS_Error 1
#define BS_Close 2
#define BS_Ping 3
#define BS_Done 4
#define BS_LAST_VERB 4
#define BS_RETRY_COUNT 3
/* protocol states */
typedef enum { BSidle,BSunbound,BSsData,BSrData,BSbad,BSeof } BSstate;
struct bs
{
int soc;
int remaining_send;
int remaining_recv;
BSstate state;
};
typedef struct bs BS;
struct bs_udp_data
{
struct sockaddr sin;
int len;
};
typedef struct bs_udp_data BSDATA;
struct BSmsgHead
{
unsigned short verb;
unsigned long size;
};
typedef struct BSmsgHead BSmsgHead;
typedef unsigned long BS_ULONG;
#define BSgetSocket(BS) (BS->soc)
#define BSgetResidualWrite(BS) (BS->remaining_send)
#define BSgetResidualRead(BS) (BS->remaining_recv)
#define BSgetProtoState(BS) (BS->state)
/* ------------------------------------------------------------------------
Server functions:
BSopenListenerTCP:
Open a socket locally bound to the bulk data transfer TCP server port.
Set the socket up as a listener. Return the open socket.
BSopenListenerUDP:
Open a socket locally bound to the bulk data transfer UDP server port.
Return the open socket.
------------------------------------------------------------------------ */
int BSopenListenerTCP(int Port);
int BSopenListenerUDP(int Port);
int BSopenTCP(BSDATA*);
/* ------------------------------------------------------------------------
Utilities functions:
BSmakeServer:
Available under unix only. Put process in the background, disassociate
process from controlling terminal and parent process, and prepare
signals for reaping children spawned by the process.
BSserverClearSignals:
Clear the signal handlers for a process, set them to default.
BSmakeBS:
Allocate and initialize a BS from a socket.
BSfreeBS:
Close the open socket and free the memory for the BS.
------------------------------------------------------------------------ */
#ifndef vxWorks
int BSmakeServer(char** argv);
int BSserverClearSignals();
#endif
BS* BSmakeBS(int socket); /* make a BS from a socket */
int BSfreeBS(BS* bdt); /* free a BS */
int BSgetBroadcastSocket(int port, struct sockaddr_in* sin);
int BSipBroadcastOpen(BSDATA* info, int default_dest_port);
int BSgetAddressPort(BSDATA* info,char* ip_addr, int* dest_port);
int BSsetAddressPort(BSDATA* info,char* ip_addr, int dest_port);
int BSsetAddress(BSDATA* info,char* ip_addr);
int BSsetPort(BSDATA* info,int dest_port);
/* ------------------------------------------------------------------------
UDP functions:
------------------------------------------------------------------------ */
int BStransUDP(int soc,BSDATA* info,void* obuf,int osize,void* ibuf,int isize);
int BSwriteUDP(int soc,BSDATA* info,void* obuf,int osize);
int BSwriteDataUDP(int soc,int dest_port, char* ip_addr,void* obuf,int osize);
int BSreadUDP(int soc,BSDATA* info,BS_ULONG tout,void* buf,int size);
int BSbroadcast(int soc,BSDATA* info,void* buf,int size);
int BSbroadcastTrans(int soc,int trys,BSDATA* o_info,BSDATA* i_info,
void* obuf,int osize,void* ibuf,int isize);
/* ------------------------------------------------------------------------
Client functions:
BSipOpen:
Open a connection to an bulk data transfer given the IP address of the
machine where the server exists. The returned BS is returned unbound,
a connect must be issued before data transactions can take place.
BSclose:
Completely close a connection to a server and free the BS.
------------------------------------------------------------------------ */
BS* BSipOpen(char* address, int port);
BS* BSipOpenData(BSDATA* info);
int BSclose(BS* bdt);
/* ------------------------------------------------------------------------
Client and Server shared functions:
BSsendHeader:
Send a message header out to a connect BS with command and message body
size information.
BSsendData:
Send a portion or all the message body out a connected BS. A header
must have previously been sent with length information. The interface
will only allow the amount of data specified in the header to be sent.
BSwrite:
This call will block until all the data specified in the size parameter
are sent down the socket.
BSread:
This call will block until all the data specified in the size parameter
is read from the socket.
BSreceiveHeader:
Wait until a message header appears at the BS, return the action and
remaining message body size.
BSreceiveData:
Wait for a chunk or the entire body of a message to appear at the BS.
Put the data into the buffer for a maximum size. Return the amount of
data actually received, or zero if there is no data remaining for the
current message.
------------------------------------------------------------------------ */
int BSsendHeader(BS* bdt, unsigned short verb, int size);
int BSsendData(BS* bdt, void* buffer, int size);
int BSreceiveHeader(BS* bdt, int* verb, int* size);
int BSreceiveData(BS* bdt, void* buffer, int size);
int BSread(int socket, void* buffer, int size);
int BSwrite(int socket, void* buffer, int size);
int BSflushOutput(BS* bdt);
#endif

View File

@@ -2,29 +2,45 @@ EPICS = ../../../..
include Target.include
include $(EPICS)/config/CONFIG_BASE
# USR_CFLAGS = -v
LEX = $(ELEX)
YACC = $(EYACC)
YACCOPT = -l
LEXOPT = -L
SRCS.c = ../dbVarSub.c dbLoadTemplate_lex.c dbLoadTemplate.c \
dbLoadRecords_lex.c dbLoadRecords.c
dbLoadRecords_lex.c dbLoadRecords.c \
../BSlib.c ../PVSserver.c ../rdbapplist.c ../rdbls.o
OBJS = dbVarSub.o dbLoadTemplate.o dbLoadRecords.o
VAR_OBJS = dbVarSub.o dbLoadTemplate.o dbLoadRecords.o
OBJS = $(VAR_OBJS) BSlib.o PVSserver.o rdbapplist.o rdbls.o
PROD = subtool dbLoadTemplate
PROD = subtool dbLoadTemplate rdbls rdbapplist
TARGETS = PVSserver
include $(EPICS)/config/RULES.Unix
dbLoadTemplate.o: dbLoadTemplate_lex.c
dbLoadRecords.o: dbLoadRecords_lex.c
subtool: dbLoadTemplate.c dbLoadTemplate_lex.c dbVarSub.o
$(RM) $@
$(LINK.c) $(CFLAGS) -DSUB_TOOL -o subtool dbLoadTemplate.c dbVarSub.o -s
PVSserver: PVSserver.o BSlib.o
$(LINK.c) $(ARCH_DEP_LDLIBS) $(LDFLAGS) -o $@ $^
dbLoadTemplate: $(OBJS)
$(LINK.c) -o $@ $(OBJS) $(LDLIBS) -lDb
rdbls: rdbls.o BSlib.o
$(LINK.c) $(ARCH_DEP_LDLIBS) $(LDFLAGS) -o $@ $^
rdbapplist: rdbapplist.o BSlib.o
$(LINK.c) $(ARCH_DEP_LDLIBS) $(LDFLAGS) -o $@ $^
subtool.o: dbLoadTemplate.c dbLoadTemplate_lex.c
$(COMPILE.c) $(CFLAGS) -DSUB_TOOL -o $@ $<
subtool: subtool.o dbVarSub.o
$(LINK.c) $(CFLAGS) -DSUB_TOOL -o $@ $^ -s
dbLoadTemplate: $(VAR_OBJS)
$(LINK.c) -o $@ $^ $(LDLIBS) -lDb
clean::
@$(RM) dbLoadTemplate_lex.c dbLoadTemplate.c dbLoadRecords_lex.c \

View File

@@ -8,8 +8,9 @@ YACCOPT = -l
LEXOPT = -L
SRCS.c = ../dbVarSub.c dbLoadTemplate_lex.c dbLoadTemplate.c \
dbLoadRecords_lex.c dbLoadRecords.c
LIBOBJS = dbVarSub.o dbLoadTemplate.o dbLoadRecords.o
dbLoadRecords_lex.c dbLoadRecords.c ../BSlib.c ../PVSvx.c
LIBOBJS = dbVarSub.o dbLoadTemplate.o dbLoadRecords.o BSlib.o PVSvx.o
LIBNAME = dbSubs

31
src/dbtools/PVS.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef __PVS_H
#define __PVS_H
#include "BSlib.h"
#define PVS_RETRY_COUNT 4
#define PVS_TRANSFER_SIZE 1024
#define PVS_UDP 17
#define PVS_TCP 6
#define PVS_UDP_PORT 50298
#define PVS_TCP_PORT 50299
#define PVS_UDP_CPORT 50300
#define PVS_Data (BS_LAST_VERB+1)
#define PVS_Alive (BS_LAST_VERB+2)
#define PVS_RecList (BS_LAST_VERB+3)
#define PVS_AppList (BS_LAST_VERB+4)
#define PVS_RecDump (BS_LAST_VERB+5)
#define PVS_LAST_VERB PVS_RecDump
struct pvs_info_packet
{
unsigned short cmd;
char text[90];
};
typedef struct pvs_info_packet PVS_INFO_PACKET;
#define PVS_SET_CMD(pvs_info,command) (pvs_info)->cmd=htons(command)
#endif

263
src/dbtools/PVSserver.c Normal file
View File

@@ -0,0 +1,263 @@
/* only runable on work station now */
#include "PVS.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
struct PVSnode
{
BSDATA info;
int alive;
struct PVSnode* next;
};
typedef struct PVSnode PVSNODE;
static PVSNODE* ioc_list = (PVSNODE*)NULL;
static int read_pvs(BSDATA* info,int serv,char* sname);
#ifndef PVS_SERVER_PROG
int main(int argc,char** argv)
{
BSDATA info;
int serv;
int rc;
if(argc<4)
{
fprintf(stderr,"usage: %s IOC-name server-number [server-name]\n",
argv[0]);
return -1;
}
serv=atoi(argv[2]);
BSsetAddress(&info,argv[1]);
if(serv>PVS_LAST_VERB)
rc=read_pvs(&info,serv,argv[3]);
else
rc=read_pvs(&info,serv,(char*)NULL);
if(rc<0) fprintf(stderr,"read of data failed horribly\n");
return 0;
}
#else
int main(int argc,char** argv)
{
int soc,mlen;
unsigned short buf,in_buf,ping;
BSDATA info;
PVSNODE* node;
if(BSmakeServer(argv)<0)
{
fprintf(stderr,"Cannot make into a server\n");
return -1;
}
if((soc=BSopenListenerUDP(PVS_UDP_PORT))<0)
{
fprintf(stderr,"Open of UDP listener socket failed\n");
return -1;
}
buf=htons(BS_Ok); /* always sends this out */
ping=htons(BS_Ping); /* always sends this out */
while(1)
{
/* wait forever until a message comes in */
mlen=BSreadUDP(soc,&info,7,&in_buf,sizeof(in_buf));
/* check for errors */
switch(mlen)
{
case 0: /* timeout */
printf("Why did a timeout occur?\n");
/* send out a ping to each of the IOCs in the ioc_list */
for(node=ioc_list;node;node=node->next)
{
mlen=BStransUDP(soc,&(node->info),&ping,sizeof(ping),
&in_buf,sizeof(in_buf));
/* check for errors */
switch(mlen)
{
case 0: /* timeout */
printf("IOC dead\n");
node->alive=0;
break;
case -1: /* error */
printf("Communications failed\n");
break;
default: /* ok */
if(node->alive==0)
{
switch(fork())
{
case -1: /* error */
perror("fork failure");
break;
case 0: /* child */
close(soc);
BSserverClearSignals();
sleep(1);
if(read_pvs(&(node->info))==0)
node->alive=1;
default: /* parent */
break;
}
}
break;
}
}
break;
case -1: /* error */
fprintf(stderr,"Communications failure\n");
break;
default: /* ok */
if(BSwriteUDP(soc,&info,&buf,sizeof(buf))<0)
fprintf(stderr,"respone send failed\n");
else
{
node=(PVSNODE*)malloc(sizeof(PVSNODE));
node->alive=1;
node->info=info;
BSsetPort(&(node->info),PVS_UDP_CPORT);
node->next=ioc_list;
ioc_list=node;
switch(fork())
{
case -1: /* error */
perror("fork failure");
break;
case 0: /* child */
close(soc);
BSserverClearSignals();
sleep(1);
return read_pvs(&info,PVS_RecList,NULL);
default: /* parent */
break;
}
}
break;
}
}
close(soc);
return 0;
}
#endif
static int read_pvs(BSDATA* info,int serv,char* sname)
{
BS* bs;
int verb,size,done,len,i,port,rsize;
char* buffer;
char ip_from[40];
FILE* fd;
BSgetAddressPort(info,ip_from,&port);
/* printf("IOC %s starting\n",ip_from); */
/* verify ioc not already added */
if(access(ip_from,F_OK)==0)
{
/* delete the existing file for this IOC */
unlink(ip_from);
}
done=0;
BSsetPort(info,PVS_TCP_PORT);
if((bs=BSipOpenData(info))==NULL)
{
fprintf(stderr,"Open of socket to IOC failed\n");
return -1;
}
if(serv>PVS_LAST_VERB)
rsize=strlen(sname)+1;
else
rsize=0;
if(BSsendHeader(bs,serv,rsize)<0)
{
fprintf(stderr,"Command send failed\n");
return -1;
}
if(rsize>0)
{
if(BSsendData(bs,sname,rsize)<0)
{
fprintf(stderr,"send of command name failed\n");
return -1;
}
}
#ifdef PVS_SERVER_PROG
if((fd=fopen(ip_from,"w"))==(FILE*)NULL)
{
fprintf(stderr,"Open of name file failed\n");
return -1;
}
#else
fd=stdout;
#endif
buffer=(char*)malloc(PVS_TRANSFER_SIZE+2);
while(done==0)
{
if(BSreceiveHeader(bs,&verb,&size)<0)
{
fprintf(stderr,"Receive header failed\n");
done=-1;
}
else
{
switch(verb)
{
case PVS_Data: /* read a block of names */
if((len=BSreceiveData(bs,buffer,size))<0)
{
fprintf(stderr,"Receive data failed\n");
}
else
{
for(i=0;i<len;i++)
{
if(buffer[i]==' ') buffer[i]='\n';
}
buffer[len]='\n';
buffer[len+1]='\0';
fputs(buffer,fd);
}
break;
case BS_Done: /* transfers complete */
BSclose(bs);
done=-1;
break;
default:
if(size>0) done=-1;
break;
}
}
}
#ifdef PVS_SERVER_PROG
fclose(fd);
#endif
free(buffer);
return 0;
}

361
src/dbtools/PVSvx.c Normal file
View File

@@ -0,0 +1,361 @@
/* This file not really set up to run under Unix yet, just under vxWorks. */
#include "PVS.h"
#include <string.h>
#include <stdio.h>
#ifdef vxWorks
#include <vxWorks.h>
#include <iv.h>
#include <taskLib.h>
#include <sysSymTbl.h>
#include <sysLib.h>
#include <symLib.h>
#include <dbStaticLib.h>
extern struct dbBase *pdbBase;
#else
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#endif
static void PVSserver(int want_annouce,char* name);
static int PVSannouce(int want_annouce,char* name);
static void handle_requests(BS* bs);
static void handle_reclist(BS* bs);
static void handle_applist(BS* bs);
static void handle_recdump(BS* bs);
static void handle_spylist(BS* bs);
static void handle_tasklist(BS* bs);
void PVS_test_server(BS* bs);
static char* names = (char*)NULL;
static char* buffer = (char*)NULL;
#ifdef vxWorks
int PVSstart(int want_annouce, char* name)
#else
int main(int argc,char** argv)
#endif
{
#ifndef vxWorks
char* name;
int want_annouce;
#endif
#ifndef vxWorks
if(argc<3)
{
fprintf(stderr,"bad args\n");
fprintf(stderr," usage: %s a_flag host_name\n",
argv[0]);
fprintf(stderr," where\n");
fprintf(stderr," a_flag=0(want),1(don't want) to annouce boot\n");
fprintf(stderr," host_name=PV master host (if one exists)\n");
return -1;
}
name=argv[2];
if(sscanf(argv[1],"%d",&want_annouce)<1)
{
fprintf(stderr,"bad a_flag\n");
return -1;
}
#endif
taskSpawn("PVS",150,VX_FP_TASK|VX_STDIO,5000,
(FUNCPTR)PVSserver,want_annouce,(int)name,0,0,0,0,0,0,0,0);
return 0;
}
static int PVSannouce(int want_annouce,char* name)
{
int soc,mlen;
PVS_INFO_PACKET buf,in_buf;
BSDATA info,in_info;
if(want_annouce==0 && name)
{
if((soc=BSopenListenerUDP(0))<0)
{
printf("Open of UDP socket failed\n");
return -1;
}
if(BSsetAddressPort(&info,name,PVS_UDP_PORT)<0)
{
printf("Set send port failed\n");
return -1;
}
PVS_SET_CMD(&buf,PVS_Alive);
mlen=BStransUDP(soc,&info,&buf,sizeof(buf),&in_buf,sizeof(in_buf));
/* check for errors */
switch(mlen)
{
case 0: /* timeout */
printf("No server running on host\n");
break;
case -1: /* error */
printf("Communications failed\n");
break;
default: /* ok */
break;
}
close(soc);
}
return 0;
}
static void PVSserver(int want_annouce,char* name)
{
fd_set fds,rfds;
int tsoc,usoc,nsoc,len,s;
struct sockaddr stemp;
int stemp_len;
PVS_INFO_PACKET buf;
BSDATA info;
BS* bs;
bs=(BS*)NULL;
buffer=(char*)malloc(100); /* just make the buffer */
names=(char*)malloc(PVS_TRANSFER_SIZE);
if((tsoc=BSopenListenerTCP(PVS_TCP_PORT))<0)
{
printf("PVSserver: Open of TCP listener socket failed\n");
return;
}
if((usoc=BSopenListenerUDP(PVS_UDP_CPORT))<0)
{
printf("PVSserver: Open of UDP listener socket failed\n");
return;
}
FD_ZERO(&fds);
FD_SET(tsoc,&fds);
FD_SET(usoc,&fds);
PVSannouce(want_annouce,name);
while(1)
{
rfds=fds;
if(select(FD_SETSIZE,&rfds,(fd_set*)NULL,(fd_set*)NULL,
(struct timeval*)NULL)<0)
{
printf("PVSserver: Select failure\n");
}
else
{
if(FD_ISSET(tsoc,&rfds))
{
/* handle the request here - single threaded server */
stemp_len=sizeof(stemp);
if((nsoc=accept(tsoc,&stemp,&stemp_len))<0)
printf("PVSserver: Bad accept\n");
else
{
bs=BSmakeBS(nsoc);
handle_requests(bs);
BSfreeBS(bs);
}
}
if(FD_ISSET(usoc,&rfds))
{
/* only pings will come in here for now */
len=BSreadUDP(usoc,&info,0,&buf,sizeof(buf));
if(len<=0)
printf("PVSserver: UDP listener read failure\n");
else
{
if(BSwriteUDP(usoc,&info,&buf,sizeof(buf))<0)
printf("PVSserver: UDP listener ping write failure\n");
}
}
}
}
}
static void handle_reclist(BS* bs)
{
DBENTRY db;
long rc;
char* n;
unsigned long names_len;
int s;
dbInitEntry(pdbBase,&db);
names_len=0;
for(rc=dbFirstRecdes(&db);rc==0;rc=dbNextRecdes(&db))
{
for(rc=dbFirstRecord(&db);rc==0;rc=dbNextRecord(&db))
{
/* collect the names util we excede the max */
n=dbGetRecordName(&db);
s=strlen(n);
if((names_len+s)>PVS_TRANSFER_SIZE)
{
names[names_len++]='\0';
if(BSsendHeader(bs,PVS_Data,names_len)<0)
printf("PVSserver: data cmd failed\n");
else
{
if(BSsendData(bs,names,names_len)<0)
printf("PVSserver: data send failed\n");
}
names_len=0;
}
memcpy(&names[names_len],n,s);
names_len+=s;
names[names_len++]=' ';
}
}
if(names_len>0)
{
names[names_len++]='\0';
if(BSsendHeader(bs,PVS_Data,names_len)<0)
printf("PVSserver: data cmd failed\n");
else
{
if(BSsendData(bs,names,names_len)<0)
printf("PVSserver: data send failed\n");
}
}
BSsendHeader(bs,BS_Done,0);
}
static void handle_requests(BS* bs)
{
int verb,size,notdone,len;
void (*func)(BS*);
SYM_TYPE stype;
notdone=1;
while(notdone)
{
/* at this point I should be getting a command */
if(BSreceiveHeader(bs,&verb,&size)<0)
{
printf("PVSserver: receive header failed\n");
notdone=0;
}
else
{
switch(verb)
{
case PVS_RecList: handle_reclist(bs); break;
case PVS_AppList: handle_applist(bs); break;
case PVS_RecDump: handle_recdump(bs); break;
case BS_Close:
BSsendHeader(bs,BS_Ok,0);
notdone=0;
break;
case PVS_Data: break;
case PVS_Alive: break;
case BS_Ok: break;
case BS_Error: break;
case BS_Ping: break;
case BS_Done: break;
default:
/* custom service */
if(size>0)
{
/* this should be the name of the service */
/* look up the symbol name in buffer and call as
subroutine, passing it the BS */
len=BSreceiveData(bs,&buffer[1],size);
switch(len)
{
case 0: /* timeout */ notdone=0; break;
case -1: /* error */ notdone=0; break;
default:
buffer[0]='_';
if(strncmp(buffer,"_PVS",4)==0)
{
if(symFindByName(sysSymTbl,buffer,
(char**)&func,&stype)==ERROR)
func=(void (*)(BS*))NULL;
if(func)
func(bs);
else
BSsendHeader(bs,BS_Done,0);
}
else
BSsendHeader(bs,BS_Done,0);
}
}
else
printf("PVSserver: unknown command received\n");
}
}
}
}
/* --------------------------------------------------------------- */
struct dbnode
{
char* name;
struct dbnode* next;
};
typedef struct dbnode DBNODE;
extern DBNODE* DbApplList;
void handle_applist(BS* bs)
{
DBNODE* n;
int size,len;
len=0;
for(n=DbApplList;n;n=n->next)
{
len=strlen(n->name)+1;
if(BSsendHeader(bs,PVS_Data,len)<0)
printf("PVSserver: data cmd failed\n");
else
{
if(BSsendData(bs,n->name,len)<0)
printf("PVSserver: data send failed\n");
}
}
BSsendHeader(bs,BS_Done,0);
}
/* --------------------------------------------------------------- */
void handle_recdump(BS* bs)
{
printf("RecDump server invoked\n");
BSsendHeader(bs,BS_Done,0);
}
void PVS_test_server(BS* bs)
{
printf("PVS_test_server invoked\n");
BSsendHeader(bs,BS_Done,0);
}
void handle_spylist(BS* bs)
{
printf("PVS spy list server invoked\n");
}
void handle_tasklist(BS* bs)
{
printf("PVS task list server invoked\n");
}

View File

@@ -49,6 +49,17 @@ static char subst_buffer[VAR_MAX_SUB_SIZE];
static int subst_used;
static int line_num;
struct db_app_node
{
char* name;
struct db_app_node* next;
};
typedef struct db_app_node DB_APP_NODE;
DB_APP_NODE* DbApplList=(DB_APP_NODE*)NULL;
static DB_APP_NODE* DbCurrentListHead=(DB_APP_NODE*)NULL;
static DB_APP_NODE* DbCurrentListTail=(DB_APP_NODE*)NULL;
static int yyerror();
static void sub_pvname(char*,char*);
@@ -65,8 +76,9 @@ extern struct dbBase *pdbBase;
%token <Str> WORD VALUE
%token <Str> FIELD
%left O_BRACE C_BRACE O_PAREN C_PAREN
%left DATABASE CONTAINER RECORD
%left NOWHERE
%left DATABASE RECORD
%left NOWHERE
%token APPL
%union
{
@@ -105,18 +117,39 @@ n_body: O_BRACE records C_BRACE
;
db_components: /* null */
| db_components container
| db_components applic
| db_components record
;
container: CONTAINER c_head c_body
;
applic: APPL O_PAREN VALUE C_PAREN
{
DB_APP_NODE* an=(DB_APP_NODE*)malloc(sizeof(DB_APP_NODE*));
c_head: O_PAREN WORD C_PAREN
{ free($2); }
;
if(subst_used)
{
strcpy(subst_buffer,$<Str>3);
if(dbDoSubst(subst_buffer,sizeof(subst_buffer),NULL)!=0)
fprintf(stderr,"dbDoSubst failed\n");
#ifdef vxWorks
an->name=strdup(subst_buffer);
free($3);
#else
printf("\napplication(\"%s\")\n",subst_buffer);
#endif
}
else
{
#ifdef vxWorks
an->name=$<Str>3;
#else
printf("\napplication(\"%s\")\n",$<Str>3);
#endif
}
if(DbCurrentListHead==(DB_APP_NODE*)NULL) DbCurrentListTail=an;
c_body: O_BRACE db_components C_BRACE
an->next=DbCurrentListHead;
DbCurrentListHead=an;
}
;
records: /* null */
@@ -190,13 +223,24 @@ field: FIELD O_PAREN WORD COMMA VALUE C_PAREN
static int yyerror(str)
char *str;
{ fprintf(stderr,"db file parse, Error line %d : %s\n",line_num, yytext); }
#ifdef vxWorks
static char* strdup(char* x)
{
char* c;
c=(char*)malloc(strlen(x)+1);
strcpy(c,x);
return c;
}
#endif
static int is_not_inited = 1;
int dbLoadRecords(char* pfilename, char* pattern, char* container)
int dbLoadRecords(char* pfilename, char* pattern)
{
FILE* fp;
long status;
DB_APP_NODE* an;
#ifdef vxWorks
if(pdbBase==NULL)
@@ -243,6 +287,21 @@ int dbLoadRecords(char* pfilename, char* pattern, char* container)
if(subst_used) dbFreeSubst();
fclose(fp);
if(DbCurrentListHead==(DB_APP_NODE*)NULL)
{
/* set up a default list to put on the master application list */
DbCurrentListHead=(DB_APP_NODE*)malloc(sizeof(DB_APP_NODE));
DbCurrentListTail=DbCurrentListHead;
DbCurrentListHead->name=strdup(pfilename);
DbCurrentListHead->next=(DB_APP_NODE*)NULL;
}
DbCurrentListTail->next=DbApplList;
DbApplList=DbCurrentListHead;
DbCurrentListHead=(DB_APP_NODE*)NULL;
DbCurrentListTail=(DB_APP_NODE*)NULL;
return 0;
}
@@ -276,3 +335,14 @@ static void sub_pvname(char* type, char* name)
}
}
#ifdef vxWorks
int dbAppList()
{
DB_APP_NODE* an;
for(an=DbApplList;an;an=an->next)
printf("%s\n",an->name);
return 0;
}
#endif

View File

@@ -12,9 +12,9 @@ value [a-zA-Z0-9_\,\^~\./\*#\[\]%: ;!|\'\-&\(\)@\?\+<>=\$\{\}]
"field" { return(FIELD); }
"grecord" { return(RECORD); }
"record" { return(RECORD); }
"container" { return(CONTAINER); }
"database" { return(DATABASE); }
"nowhere" { return(NOWHERE); }
"application" { return(APPL); }
\"{value}*\" { yylval.Str=(char *)malloc(strlen(yytext)+1); strcpy(yylval.Str,yytext+1); yylval.Str[strlen(yylval.Str)-1] = '\0'; return(VALUE); }

View File

@@ -276,9 +276,11 @@ sub_pat: WORD EQUALS WORD
#include "dbLoadTemplate_lex.c"
static int yyerror(str)
char *str;
{ fprintf(stderr,"templ file parse, Error line %d : %s\n",line_num, yytext); }
static int yyerror(char* str)
{
fprintf(stderr,"Substitution file parse error\n");
fprintf(stderr,"line %d:%s\n",line_num,yytext);
}
static int is_not_inited = 1;

116
src/dbtools/rdbapplist.c Normal file
View File

@@ -0,0 +1,116 @@
/* only runable on work station now */
#include "PVS.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
static int read_pvs(BSDATA* info,int serv,char* sname);
int main(int argc,char** argv)
{
BSDATA info;
int rc;
if(argc<2)
{
fprintf(stderr,"usage: %s IOC-ip-address\n",argv[0]);
return -1;
}
if(BSsetAddress(&info,argv[1])<0)
{
fprintf(stderr,"Cannot determine address for %s\n",argv[1]);
return -1;
}
rc=read_pvs(&info,PVS_AppList,(char*)NULL);
if(rc<0) fprintf(stderr,"read of data failed horribly\n");
return 0;
}
static int read_pvs(BSDATA* info,int serv,char* sname)
{
BS* bs;
int verb,size,done,len,i,port,rsize;
char* buffer;
char ip_from[40];
FILE* fd;
BSgetAddressPort(info,ip_from,&port);
/* verify ioc not already added */
if(access(ip_from,F_OK)==0)
{
/* delete the existing file for this IOC */
unlink(ip_from);
}
done=0;
BSsetPort(info,PVS_TCP_PORT);
if((bs=BSipOpenData(info))==NULL)
{
fprintf(stderr,"Open of socket to IOC failed\n");
return -1;
}
if(serv>PVS_LAST_VERB)
rsize=strlen(sname)+1;
else
rsize=0;
if(BSsendHeader(bs,serv,rsize)<0)
{
fprintf(stderr,"Command send failed\n");
return -1;
}
if(rsize>0)
{
if(BSsendData(bs,sname,rsize)<0)
{
fprintf(stderr,"send of command name failed\n");
return -1;
}
}
fd=stdout;
buffer=(char*)malloc(PVS_TRANSFER_SIZE+2);
while(done==0)
{
if(BSreceiveHeader(bs,&verb,&size)<0)
{
fprintf(stderr,"Receive header failed\n");
done=-1;
}
else
{
switch(verb)
{
case PVS_Data: /* read a block of names */
if((len=BSreceiveData(bs,buffer,size))<0)
fprintf(stderr,"Receive data failed\n");
else
fputs(buffer,fd);
fputc('\n',fd);
break;
case BS_Done: /* transfers complete */
BSclose(bs);
done=-1;
break;
default:
if(size>0) done=-1;
break;
}
}
}
free(buffer);
return 0;
}

128
src/dbtools/rdbls.c Normal file
View File

@@ -0,0 +1,128 @@
/* only runable on work station now */
#include "PVS.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
static int read_pvs(BSDATA* info,int serv,char* sname);
int main(int argc,char** argv)
{
BSDATA info;
int rc;
if(argc<2)
{
fprintf(stderr,"usage: %s IOC-ip-address\n",argv[0]);
return -1;
}
if(BSsetAddress(&info,argv[1])<0)
{
fprintf(stderr,"Cannot determine address for %s\n",argv[1]);
return -1;
}
rc=read_pvs(&info,PVS_RecList,(char*)NULL);
if(rc<0) fprintf(stderr,"read of data failed horribly\n");
return 0;
}
static int read_pvs(BSDATA* info,int serv,char* sname)
{
BS* bs;
int verb,size,done,len,i,port,rsize;
char* buffer;
char ip_from[40];
FILE* fd;
BSgetAddressPort(info,ip_from,&port);
/* printf("IOC %s starting\n",ip_from); */
/* verify ioc not already added */
if(access(ip_from,F_OK)==0)
{
/* delete the existing file for this IOC */
unlink(ip_from);
}
done=0;
BSsetPort(info,PVS_TCP_PORT);
if((bs=BSipOpenData(info))==NULL)
{
fprintf(stderr,"Open of socket to IOC failed\n");
return -1;
}
if(serv>PVS_LAST_VERB)
rsize=strlen(sname)+1;
else
rsize=0;
if(BSsendHeader(bs,serv,rsize)<0)
{
fprintf(stderr,"Command send failed\n");
return -1;
}
if(rsize>0)
{
if(BSsendData(bs,sname,rsize)<0)
{
fprintf(stderr,"send of command name failed\n");
return -1;
}
}
fd=stdout;
buffer=(char*)malloc(PVS_TRANSFER_SIZE+2);
while(done==0)
{
if(BSreceiveHeader(bs,&verb,&size)<0)
{
fprintf(stderr,"Receive header failed\n");
done=-1;
}
else
{
switch(verb)
{
case PVS_Data: /* read a block of names */
if((len=BSreceiveData(bs,buffer,size))<0)
{
fprintf(stderr,"Receive data failed\n");
}
else
{
for(i=0;i<len;i++)
{
if(buffer[i]==' ') buffer[i]='\n';
}
buffer[len]='\n';
buffer[len+1]='\0';
fputs(buffer,fd);
}
break;
case BS_Done: /* transfers complete */
BSclose(bs);
done=-1;
break;
default:
if(size>0) done=-1;
break;
}
}
}
free(buffer);
return 0;
}

View File

@@ -122,6 +122,9 @@
* for the DMA buffer that is appropriate.
*
* $Log$
* Revision 1.1 1995/03/30 19:35:14 jba
* Seperated drv files into ansi and old dirs. Added combine dir.
*
* Revision 1.22 1995/01/06 17:03:43 winans
* Added some ifdef'd out test code to see if the end of the sequence program
* could be updated to NOT cause an extra sample from port zero to be taken
@@ -181,7 +184,7 @@ static char *SccsId = "$Id$";
#define ADVANCE_HOLD 0xC0
#define RESTART 0x00
/* analogic 2502 memory structure */
/* Analogic 2502 memory structure */
struct dvx_2502
{
unsigned short dev_id; /* device id code (CFF5) */
@@ -205,7 +208,7 @@ struct dvx_inbuf
short *data; /* data buffer */
};
/* analogic 2502 control structure */
/* Analogic 2502 control structure */
struct dvx_rec
{
struct dvx_2502 *pdvx2502; /* pointer to device registers */
@@ -224,6 +227,8 @@ struct dvx_rec
int RearmMode; /* zero if auto-rearm, else manual */
unsigned short ScanRate; /* User settable scan rate */
IOSCANPVT *pioscanpvt;
};
@@ -304,19 +309,19 @@ struct {
static struct dvx_rec dvx[MAX_DVX_CARDS] = {
{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}
,{0, 0, 0, 0, 0, 0, 0, 0},
0 , NULL
0 , DVX_DRATE, NULL
},
{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}
,{0, 0, 0, 0, 0, 0, 0, 0},
0, NULL
0, DVX_DRATE, NULL
},
{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}
,{0, 0, 0, 0, 0, 0, 0, 0},
0, NULL
0, DVX_DRATE, NULL
},
{ NULL, NULL, NULL, -1, -1, -1, -1, -1, 128, 0, {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}
,{0, 0, 0, 0, 0, 0, 0, 0},
0, NULL
0, DVX_DRATE, NULL
}
};
@@ -425,6 +430,16 @@ dvx_int(struct dvx_rec *dvxptr)
cptr->csr = dvxptr->csr_shadow;
}
int dvx_SetScanRate(int Card, unsigned int Rate)
{
/* make sure hardware exists */
if ((Card >= ai_num_cards[DVX2502]) || (Card < 0))
return(-1);
dvx[Card].ScanRate = Rate & 0x0000FFFF;
dvx[Card].pdvx2502->samp_rate = dvx[Card].ScanRate;
return(0);
}
int dvx_RearmModeSet(int card, int mode)
{
/* make sure hardware exists */
@@ -672,7 +687,11 @@ LOCAL long dvx_driver_init(void)
/*
* set scan rate and enable external start
*/
#if 0
pDvxA16->samp_rate = DVX_DRATE; /* scan rate of 184 KHz */
#else
pDvxA16->samp_rate = dvx[i].ScanRate; /* Set scan rate */
#endif
dvx[i].csr_shadow |= CSR_M_ESTART; /* enable ext start (shadow csr) */
pDvxA16->csr = dvx[i].csr_shadow; /* enable external start */
dvx[i].mode = RUN_MODE; /* ready to aquire data */
@@ -904,12 +923,17 @@ int sramld(int card)
#endif
/* set scan rate and run it once */
#if 0
dvx[card].pdvx2502->samp_rate = DVX_DRATE;
#else
dvx[card].pdvx2502->samp_rate = dvx[card].ScanRate; /* Set scan rate */
#endif
dvx[card].pdvx2502->csr = dvx[card].csr_shadow | CSR_M_START;
taskDelay(sysClkRateGet()); /* let scan run */
dvx[card].pdvx2502->csr = dvx[card].csr_shadow; /* restore csr */
}
/*
* dvx_driver
*

View File

@@ -45,6 +45,8 @@ SRCS.c += ../recSubArray.c
SRCS.c += ../recTimer.c
SRCS.c += ../recWait.c
SRCS.c += ../recWaitCa.c
SRCS.c += ../recDynLink.c
SRCS.c += ../recDynLinkTest.c
SRCS.c += ../recWaveform.c
# LIBOBJS += recAai.o
@@ -88,6 +90,8 @@ LIBOBJS += recSubArray.o
LIBOBJS += recTimer.o
LIBOBJS += recWait.o
LIBOBJS += recWaitCa.o
LIBOBJS += recDynLink.o
LIBOBJS += recDynLinkTest.o
LIBOBJS += recWaveform.o
LIBNAME = recSup

542
src/rec/recDynLink.c Normal file
View File

@@ -0,0 +1,542 @@
/*recDynLink.c*/
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
**********************************************************************/
#include <vxWorks.h>
#include <taskLib.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <rngLib.h>
#include <vxLib.h>
#include <semLib.h>
#include <sysLib.h>
#include <dbDefs.h>
#include <taskwd.h>
#include <fast_lock.h>
#include <db_access.h>
#include <cadef.h>
#include <caerr.h>
#include <caeventmask.h>
#include <calink.h>
#include <tsDefs.h>
#include <task_params.h>
#include <recDynLink.h>
/*Definitions to map between old and new database access*/
/*because we are using CA must include db_access.h*/
/* new field types */
#define newDBF_STRING 0
#define newDBF_CHAR 1
#define newDBF_UCHAR 2
#define newDBF_SHORT 3
#define newDBF_USHORT 4
#define newDBF_LONG 5
#define newDBF_ULONG 6
#define newDBF_FLOAT 7
#define newDBF_DOUBLE 8
#define newDBF_ENUM 9
/* new data request buffer types */
#define newDBR_STRING newDBF_STRING
#define newDBR_CHAR newDBF_CHAR
#define newDBR_UCHAR newDBF_UCHAR
#define newDBR_SHORT newDBF_SHORT
#define newDBR_USHORT newDBF_USHORT
#define newDBR_LONG newDBF_LONG
#define newDBR_ULONG newDBF_ULONG
#define newDBR_FLOAT newDBF_FLOAT
#define newDBR_DOUBLE newDBF_DOUBLE
#define newDBR_ENUM newDBF_ENUM
#define VALID_newDB_REQ(x) ((x >= 0) && (x <= newDBR_ENUM))
static short mapOldToNew[DBF_DOUBLE+1] = {
newDBR_STRING,newDBR_SHORT,newDBR_FLOAT,newDBR_ENUM,
newDBR_CHAR,newDBR_LONG,newDBR_DOUBLE};
static short mapNewToOld[newDBR_ENUM+1] = {
DBF_STRING,DBF_CHAR,DBF_CHAR,DBF_SHORT,DBF_SHORT,
DBF_LONG,DBF_LONG,DBF_FLOAT,DBF_DOUBLE,DBF_ENUM};
extern int interruptAccept;
int recDynLinkQsize = 256;
LOCAL int inpTaskId=0;
LOCAL int outTaskId=0;
LOCAL RING_ID inpRingQ;;
LOCAL RING_ID outRingQ;;
LOCAL SEM_ID wakeUpSem;
typedef enum{cmdSearch,cmdClear,cmdPut} cmdType;
typedef enum{ioInput,ioOutput}ioType;
typedef enum{stateStarting,stateSearching,stateGetting,stateConnected}stateType;
typedef struct dynLinkPvt{
FAST_LOCK lock;
char *pvname;
chid chid;
evid evid;
recDynCallback searchCallback;
recDynCallback monitorCallback;
TS_STAMP timestamp;
short status;
short severity;
void *pbuffer;
size_t nRequest;
short dbrType;
double graphicLow,graphHigh;
double controlLow,controlHigh;
char units[MAX_UNITS_SIZE];
short precision;
ioType io;
stateType state;
short scalar;
} dynLinkPvt;
/*For cmdClear data is chid. For all other commands precDynLink*/
typedef struct {
union {
recDynLink *precDynLink;
dynLinkPvt *pdynLinkPvt;
}data;
cmdType cmd;
}ringBufCmd;
LOCAL void recDynLinkStartInput(void);
LOCAL void recDynLinkStartOutput(void);
LOCAL void connectCallback(struct connection_handler_args cha);
LOCAL void getCallback(struct event_handler_args eha);
LOCAL void monitorCallback(struct event_handler_args eha);
LOCAL void recDynLinkInp(void);
LOCAL void recDynLinkOut(void);
long recDynLinkAddInput(recDynLink *precDynLink,char *pvname,
short dbrType,int options,
recDynCallback searchCallback,recDynCallback monitorCallback)
{
dynLinkPvt *pdynLinkPvt;
struct db_addr dbaddr;
ringBufCmd cmd;
if(options&rdlDBONLY && db_name_to_addr(pvname,&dbaddr))return(-1);
if(!inpTaskId) recDynLinkStartInput();
if(precDynLink->pdynLinkPvt) recDynLinkClear(precDynLink);
pdynLinkPvt = (dynLinkPvt *)calloc(1,sizeof(dynLinkPvt));
if(!pdynLinkPvt) {
printf("recDynLinkAddInput can't allocate storage");
taskSuspend(0);
}
FASTLOCKINIT(&pdynLinkPvt->lock);
precDynLink->pdynLinkPvt = pdynLinkPvt;
pdynLinkPvt->pvname = pvname;
pdynLinkPvt->dbrType = dbrType;
pdynLinkPvt->searchCallback = searchCallback;
pdynLinkPvt->monitorCallback = monitorCallback;
pdynLinkPvt->io = ioInput;
pdynLinkPvt->scalar = (options&rdlSCALAR) ? TRUE : FALSE;
pdynLinkPvt->state = stateStarting;
cmd.data.precDynLink = precDynLink;
cmd.cmd = cmdSearch;
if(rngBufPut(inpRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
errMessage(0,"recDynLinkAddInput: rngBufPut error");
return(0);
}
long recDynLinkAddOutput(recDynLink *precDynLink,char *pvname,
short dbrType,int options,
recDynCallback searchCallback)
{
dynLinkPvt *pdynLinkPvt;
struct db_addr dbaddr;
ringBufCmd cmd;
if(options&rdlDBONLY && db_name_to_addr(pvname,&dbaddr))return(-1);
if(!outTaskId) recDynLinkStartOutput();
if(precDynLink->pdynLinkPvt) recDynLinkClear(precDynLink);
pdynLinkPvt = (dynLinkPvt *)calloc(1,sizeof(dynLinkPvt));
if(!pdynLinkPvt) {
printf("recDynLinkAddOutput can't allocate storage");
taskSuspend(0);
}
FASTLOCKINIT(&pdynLinkPvt->lock);
precDynLink->pdynLinkPvt = pdynLinkPvt;
pdynLinkPvt->pvname = pvname;
pdynLinkPvt->dbrType = dbrType;
pdynLinkPvt->searchCallback = searchCallback;
pdynLinkPvt->io = ioOutput;
pdynLinkPvt->scalar = (options&rdlSCALAR) ? TRUE : FALSE;
pdynLinkPvt->state = stateStarting;
cmd.data.precDynLink = precDynLink;
cmd.cmd = cmdSearch;
if(rngBufPut(outRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
errMessage(0,"recDynLinkAddInput: rngBufPut error");
semGive(wakeUpSem);
return(0);
}
long recDynLinkClear(recDynLink *precDynLink)
{
dynLinkPvt *pdynLinkPvt;
ringBufCmd cmd;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(!pdynLinkPvt) {
printf("recDynLinkClear. recDynLinkSearch was never called\n");
taskSuspend(0);
}
if(pdynLinkPvt->chid) ca_puser(pdynLinkPvt->chid) = NULL;
cmd.data.pdynLinkPvt = pdynLinkPvt;
cmd.cmd = cmdClear;
if(pdynLinkPvt->io==ioInput) {
if(rngBufPut(inpRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
errMessage(0,"recDynLinkClear: rngBufPut error");
} else {
if(rngBufPut(outRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
errMessage(0,"recDynLinkClear: rngBufPut error");
}
precDynLink->pdynLinkPvt = NULL;
return(0);
}
long recDynLinkConnectionStatus(recDynLink *precDynLink)
{
dynLinkPvt *pdynLinkPvt;
long status;
pdynLinkPvt = precDynLink->pdynLinkPvt;
status = (ca_state(pdynLinkPvt->chid)==cs_conn) ? 0 : -1;
return(status);
}
long recDynLinkGetNelem(recDynLink *precDynLink,size_t *nelem)
{
dynLinkPvt *pdynLinkPvt;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(ca_state(pdynLinkPvt->chid)!=cs_conn) return(-1);
*nelem = ca_element_count(pdynLinkPvt->chid);
return(0);
}
long recDynLinkGetControlLimits(recDynLink *precDynLink,
double *low,double *high)
{
dynLinkPvt *pdynLinkPvt;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(pdynLinkPvt->state!=stateConnected) return(-1);
if(low) *low = pdynLinkPvt->controlLow;
if(high) *high = pdynLinkPvt->controlHigh;
return(0);
}
long recDynLinkGetGraphicLimits(recDynLink *precDynLink,
double *low,double *high)
{
dynLinkPvt *pdynLinkPvt;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(pdynLinkPvt->state!=stateConnected) return(-1);
if(low) *low = pdynLinkPvt->graphicLow;
if(high) *high = pdynLinkPvt->graphHigh;
return(0);
}
long recDynLinkGetPrecision(recDynLink *precDynLink,int *prec)
{
dynLinkPvt *pdynLinkPvt;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(pdynLinkPvt->state!=stateConnected) return(-1);
if(prec) *prec = pdynLinkPvt->precision;
return(0);
}
long recDynLinkGetUnits(recDynLink *precDynLink,char *units,int maxlen)
{
dynLinkPvt *pdynLinkPvt;
int maxToCopy;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(pdynLinkPvt->state!=stateConnected) return(-1);
maxToCopy = MAX_UNITS_SIZE;
if(maxlen<maxToCopy) maxToCopy = maxlen;
strncpy(units,pdynLinkPvt->units,maxToCopy);
if(maxToCopy<maxlen) units[maxToCopy] = '\0';
return(0);
}
long recDynLinkGet(recDynLink *precDynLink,void *pbuffer,size_t *nRequest,
TS_STAMP *timestamp,short *status,short *severity)
{
dynLinkPvt *pdynLinkPvt;
long caStatus;
pdynLinkPvt = precDynLink->pdynLinkPvt;
caStatus = (ca_state(pdynLinkPvt->chid)==cs_conn) ? 0 : -1;
if(caStatus) goto all_done;
if(*nRequest > pdynLinkPvt->nRequest) {
*nRequest = pdynLinkPvt->nRequest;
}
FASTLOCK(&pdynLinkPvt->lock);
memcpy(pbuffer,pdynLinkPvt->pbuffer,
(*nRequest * dbr_size[mapNewToOld[pdynLinkPvt->dbrType]]));
if(timestamp) *timestamp = pdynLinkPvt->timestamp; /*array copy*/
if(status) *status = pdynLinkPvt->status;
if(severity) *severity = pdynLinkPvt->severity;
FASTUNLOCK(&pdynLinkPvt->lock);
all_done:
return(caStatus);
}
long recDynLinkPut(recDynLink *precDynLink,void *pbuffer,size_t nRequest)
{
dynLinkPvt *pdynLinkPvt;
long status;
ringBufCmd cmd;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(pdynLinkPvt->io!=ioOutput || pdynLinkPvt->state!=stateConnected) {
status = -1;
} else {
status = (ca_state(pdynLinkPvt->chid)==cs_conn) ? 0 : -1;
}
if(status) goto all_done;
if(pdynLinkPvt->scalar) nRequest = 1;
if(nRequest>ca_element_count(pdynLinkPvt->chid))
nRequest = ca_element_count(pdynLinkPvt->chid);
pdynLinkPvt->nRequest = nRequest;
memcpy(pdynLinkPvt->pbuffer,pbuffer,
(nRequest * dbr_size[mapNewToOld[pdynLinkPvt->dbrType]]));
cmd.data.precDynLink = precDynLink;
cmd.cmd = cmdPut;
if(rngBufPut(outRingQ,(void *)&cmd,sizeof(cmd)) != sizeof(cmd))
errMessage(0,"recDynLinkPut: rngBufPut error");
semGive(wakeUpSem);
all_done:
return(status);
}
LOCAL void recDynLinkStartInput(void)
{
if((inpRingQ = rngCreate(sizeof(ringBufCmd) * recDynLinkQsize)) == NULL) {
errMessage(0,"recDynLinkStart failed");
exit(1);
}
inpTaskId = taskSpawn("recDynINP",CA_CLIENT_PRI-1,VX_FP_TASK,
CA_CLIENT_STACK,(FUNCPTR)recDynLinkInp,0,0,0,0,0,0,0,0,0,0);
if(inpTaskId==ERROR) {
errMessage(0,"recDynLinkStartInput: taskSpawn Failure\n");
}
}
LOCAL void recDynLinkStartOutput(void)
{
if((wakeUpSem=semBCreate(SEM_Q_FIFO,SEM_EMPTY))==NULL)
errMessage(0,"semBcreate failed in recDynLinkStart");
if((outRingQ = rngCreate(sizeof(ringBufCmd) * recDynLinkQsize)) == NULL) {
errMessage(0,"recDynLinkStartOutput failed");
exit(1);
}
outTaskId = taskSpawn("recDynOUT",CA_CLIENT_PRI-1,VX_FP_TASK,
CA_CLIENT_STACK,(FUNCPTR)recDynLinkOut,0,0,0,0,0,0,0,0,0,0);
if(outTaskId==ERROR) {
errMessage(0,"recDynLinkStart: taskSpawn Failure\n");
}
}
LOCAL void connectCallback(struct connection_handler_args cha)
{
chid chid = cha.chid;
recDynLink *precDynLink;
dynLinkPvt *pdynLinkPvt;
precDynLink = (recDynLink *)ca_puser(cha.chid);
if(!precDynLink) return;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(ca_state(chid)==cs_conn) {
pdynLinkPvt->state = stateGetting;
SEVCHK(ca_get_callback(DBR_CTRL_DOUBLE,chid,getCallback,precDynLink),
"ca_get_callback");
} else {
if(pdynLinkPvt->searchCallback)
(pdynLinkPvt->searchCallback)(precDynLink);
}
}
LOCAL void getCallback(struct event_handler_args eha)
{
struct dbr_ctrl_double *pdata = (struct dbr_ctrl_double *)eha.dbr;
recDynLink *precDynLink;
dynLinkPvt *pdynLinkPvt;
size_t nRequest;
precDynLink = (recDynLink *)ca_puser(eha.chid);
if(!precDynLink) return;
pdynLinkPvt = precDynLink->pdynLinkPvt;
pdynLinkPvt -> graphicLow = pdata->lower_disp_limit;
pdynLinkPvt -> graphHigh = pdata->upper_disp_limit;
pdynLinkPvt -> controlLow = pdata->lower_ctrl_limit;
pdynLinkPvt -> controlHigh = pdata->upper_ctrl_limit;
pdynLinkPvt -> precision = pdata->precision;
strncpy(pdynLinkPvt->units,pdata->units,MAX_UNITS_SIZE);
if(pdynLinkPvt->scalar) {
pdynLinkPvt->nRequest = 1;
} else {
pdynLinkPvt->nRequest = ca_element_count(pdynLinkPvt->chid);
}
nRequest = pdynLinkPvt->nRequest;
pdynLinkPvt->pbuffer = calloc(nRequest,
dbr_size[mapNewToOld[pdynLinkPvt->dbrType]]);
if(pdynLinkPvt->io==ioInput) {
SEVCHK(ca_add_array_event(
dbf_type_to_DBR_TIME(mapNewToOld[pdynLinkPvt->dbrType]),
pdynLinkPvt->nRequest,
pdynLinkPvt->chid,monitorCallback,precDynLink,
0.0,0.0,0.0,
&pdynLinkPvt->evid),"ca_add_array_event");
}
pdynLinkPvt->state = stateConnected;
if(pdynLinkPvt->searchCallback) (pdynLinkPvt->searchCallback)(precDynLink);
}
LOCAL void monitorCallback(struct event_handler_args eha)
{
recDynLink *precDynLink;
dynLinkPvt *pdynLinkPvt;
long count = eha.count;
void *pbuffer = eha.dbr;
struct dbr_time_string *pdbr_time_string;
void *pdata;
short timeType;
precDynLink = (recDynLink *)ca_puser(eha.chid);
if(!precDynLink) return;
pdynLinkPvt = precDynLink->pdynLinkPvt;
if(pdynLinkPvt->pbuffer) {
FASTLOCK(&pdynLinkPvt->lock);
if(count>=pdynLinkPvt->nRequest)
count = pdynLinkPvt->nRequest;
pdbr_time_string = (struct dbr_time_string *)pbuffer;
timeType = dbf_type_to_DBR_TIME(mapNewToOld[pdynLinkPvt->dbrType]);
pdata = (void *)((char *)pbuffer + dbr_value_offset[timeType]);
pdynLinkPvt->timestamp = pdbr_time_string->stamp; /*array copy*/
pdynLinkPvt->status = pdbr_time_string->status;
pdynLinkPvt->severity = pdbr_time_string->severity;
memcpy(pdynLinkPvt->pbuffer,pdata,
(count * dbr_size[mapNewToOld[pdynLinkPvt->dbrType]]));
FASTUNLOCK(&pdynLinkPvt->lock);
}
if(pdynLinkPvt->monitorCallback)
(*pdynLinkPvt->monitorCallback)(precDynLink);
}
LOCAL void recDynLinkInp(void)
{
int status;
recDynLink *precDynLink;
dynLinkPvt *pdynLinkPvt;
int caStatus;
ringBufCmd cmd;
taskwdInsert(taskIdSelf(),NULL,NULL);
SEVCHK(ca_task_initialize(),"ca_task_initialize");
while(TRUE) {
while (rngNBytes(inpRingQ)>=sizeof(cmd) && interruptAccept){
if(rngBufGet(inpRingQ,(void *)&cmd,sizeof(cmd))
!=sizeof(cmd)) {
errMessage(0,"recDynLinkTask: rngBufGet error");
continue;
}
if(cmd.cmd==cmdClear) {
pdynLinkPvt = cmd.data.pdynLinkPvt;
if(pdynLinkPvt->chid)
SEVCHK(ca_clear_channel(pdynLinkPvt->chid),
"ca_clear_channel");
free(pdynLinkPvt->pbuffer);
free((void *)pdynLinkPvt);
continue;
}
precDynLink = cmd.data.precDynLink;
pdynLinkPvt = precDynLink->pdynLinkPvt;
switch(cmd.cmd) {
case(cmdSearch) :
SEVCHK(ca_search_and_connect(pdynLinkPvt->pvname,
&pdynLinkPvt->chid, connectCallback,precDynLink),
"ca_search_and_connect");
break;
default:
epicsPrintf("Logic error statement in recDynLinkTask\n");
}
}
status = ca_pend_event(.1);
if(status!=ECA_NORMAL && status!=ECA_TIMEOUT)
SEVCHK(status,"ca_pend_event");
}
}
LOCAL void recDynLinkOut(void)
{
int status;
recDynLink *precDynLink;
dynLinkPvt *pdynLinkPvt;
ringBufCmd cmd;
int caStatus;
taskwdInsert(taskIdSelf(),NULL,NULL);
SEVCHK(ca_task_initialize(),"ca_task_initialize");
while(TRUE) {
semTake(wakeUpSem,sysClkRateGet());
while (rngNBytes(outRingQ)>=sizeof(cmd) && interruptAccept){
if(rngBufGet(outRingQ,(void *)&cmd,sizeof(cmd))
!=sizeof(cmd)) {
errMessage(0,"recDynLinkTask: rngBufGet error");
continue;
}
if(cmd.cmd==cmdClear) {
pdynLinkPvt = cmd.data.pdynLinkPvt;
if(pdynLinkPvt->chid)
SEVCHK(ca_clear_channel(pdynLinkPvt->chid),
"ca_clear_channel");
free(pdynLinkPvt->pbuffer);
free((void *)pdynLinkPvt);
continue;
}
precDynLink = cmd.data.precDynLink;
pdynLinkPvt = precDynLink->pdynLinkPvt;
switch(cmd.cmd) {
case(cmdSearch) :
SEVCHK(ca_search_and_connect(pdynLinkPvt->pvname,
&pdynLinkPvt->chid, connectCallback,precDynLink),
"ca_search_and_connect");
break;
case(cmdPut) :
caStatus = ca_array_put(
mapNewToOld[pdynLinkPvt->dbrType],
pdynLinkPvt->nRequest,pdynLinkPvt->chid,
pdynLinkPvt->pbuffer);
if(caStatus!=ECA_NORMAL) {
epicsPrintf("recDynLinkTask pv=%s CA Error %s\n",
pdynLinkPvt->pvname,ca_message(caStatus));
}
break;
default:
epicsPrintf("Logic error statement in recDynLinkTask\n");
}
}
status = ca_pend_event(.00001);
if(status!=ECA_NORMAL && status!=ECA_TIMEOUT)
SEVCHK(status,"ca_pend_event");
}
}

51
src/rec/recDynLink.h Normal file
View File

@@ -0,0 +1,51 @@
/*recDynLink.c*/
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
*******************************************************************/
#ifndef INCrecDynLinkh
#define INCrecDynLinkh
#include <tsDefs.h>
typedef struct recDynLink{
void *puserPvt;
void *pdynLinkPvt;
} recDynLink;
typedef void (*recDynCallback)(recDynLink *);
#define rdlDBONLY 0x1
#define rdlSCALAR 0x2
long recDynLinkAddInput(recDynLink *precDynLink,char *pvname,
short dbrType,int options,
recDynCallback searchCallback,recDynCallback monitorCallback);
long recDynLinkAddOutput(recDynLink *precDynLink,char *pvname,
short dbrType,int options,
recDynCallback searchCallback);
long recDynLinkClear(recDynLink *precDynLink);
/*The following routine returns (0,-1) for (connected,not connected)*/
long recDynLinkConnectionStatus(recDynLink *precDynLink);
/*thye following routine returns (0,-1) if (connected,not connected)*/
long recDynLinkGetNelem(recDynLink *precDynLink,size_t *nelem);
/*The following 4 routines return (0,-1) if data (is, is not) yet available*/
/*searchCallback is not called until this info is available*/
long recDynLinkGetControlLimits(recDynLink *precDynLink,
double *low,double *high);
long recDynLinkGetGraphicLimits(recDynLink *precDynLink,
double *low,double *high);
long recDynLinkGetPrecision(recDynLink *precDynLink,int *prec);
long recDynLinkGetUnits(recDynLink *precDynLink,char *units,int maxlen);
/*get only valid mfor rdlINPUT. put only valid for rdlOUTPUT*/
long recDynLinkGet(recDynLink *precDynLink,
void *pbuffer, size_t *nRequest,
TS_STAMP *timestamp,short *status,short *severity);
long recDynLinkPut(recDynLink *precDynLink,void *pbuffer,size_t nRequest);
#endif /*INCrecDynLinkh*/

191
src/rec/recDynLinkTest.c Normal file
View File

@@ -0,0 +1,191 @@
/*recDynLinkTest.c */
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
***********************************************************************/
#include <vxWorks.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <dbDefs.h>
#include <tsDefs.h>
#include <recDynLink.h>
#include <dbAccess.h>
/*The remainder of this source module is test code */
typedef struct userPvt {
char *pvname;
double *pbuffer;
size_t nRequest;
}userPvt;
LOCAL void mymonitorCallback(recDynLink *precDynLink)
{
userPvt *puserPvt;
long status;
size_t nRequest;
TS_STAMP timestamp;
short AlarmStatus,AlarmSeverity;
int i;
char timeStr[40];
puserPvt = (userPvt *)precDynLink->puserPvt;
printf("mymonitorCallback: %s\n",puserPvt->pvname);
if(recDynLinkConnectionStatus(precDynLink)!=0) {
printf(" not connected\n");
return;
}
nRequest = puserPvt->nRequest;
status = recDynLinkGet(precDynLink,puserPvt->pbuffer,&nRequest,
&timestamp,&AlarmStatus,&AlarmSeverity);
if(status) {
printf("recDynLinkGet returned illegal status\n");
return;
}
tsStampToText(&timestamp,TS_TEXT_MMDDYY,timeStr);
printf("date %s status %hd severity %hd ",
timeStr,AlarmStatus,AlarmSeverity);
for(i=0; i<puserPvt->nRequest; i++) {
printf(" %f",puserPvt->pbuffer[i]);
}
printf("\n");
}
LOCAL void mysearchCallback(recDynLink *precDynLink)
{
userPvt *puserPvt;
size_t nelem;
double controlLow,controlHigh;
double graphicLow,graphicHigh;
int prec;
char units[20];
long status;
puserPvt = (userPvt *)precDynLink->puserPvt;
printf("mysearchCallback: %s ",puserPvt->pvname);
if(recDynLinkConnectionStatus(precDynLink)==0) {
printf("connected\n");
status = recDynLinkGetNelem(precDynLink,&nelem);
if(status) {
printf("recDynLinkGetNelem failed\n");
}else{
printf("nelem = %u\n",nelem);
}
status=recDynLinkGetControlLimits(precDynLink,&controlLow,&controlHigh);
if(status) {
printf("recDynLinkGetControlLimits failed\n");
}else{
printf("controlLow %f controlHigh %f\n",controlLow,controlHigh);
}
status=recDynLinkGetGraphicLimits(precDynLink,&graphicLow,&graphicHigh);
if(status) {
printf("recDynLinkGetGraphicLimits failed\n");
}else{
printf("graphicLow %f graphicHigh %f\n",graphicLow,graphicHigh);
}
status = recDynLinkGetPrecision(precDynLink,&prec);
if(status) {
printf("recDynLinkGetPrecision failed\n");
}else{
printf("prec = %d\n",prec);
}
status = recDynLinkGetUnits(precDynLink,units,20);
if(status) {
printf("recDynLinkGetUnits failed\n");
}else{
printf("units = %s\n",units);
}
} else {
printf(" not connected\n");
}
}
LOCAL recDynLink getDynlink = {NULL,NULL};
LOCAL recDynLink putDynlink = {NULL,NULL};
int recDynTestInput(char *pvname,int nRequest)
{
userPvt *puserPvt= getDynlink.puserPvt;
long status;
int options=0;
if(puserPvt) {
recDynLinkClear(&getDynlink);
free(puserPvt->pbuffer);
free(getDynlink.puserPvt);
getDynlink.puserPvt = NULL;
}
getDynlink.puserPvt = puserPvt = (userPvt *)calloc(1,sizeof(userPvt));
puserPvt->pbuffer = calloc(nRequest,sizeof(double));
puserPvt->nRequest = nRequest;
puserPvt->pvname = pvname;
if(nRequest==1) options=rdlSCALAR;;
status = recDynLinkAddInput(&getDynlink,pvname,
DBR_DOUBLE,options,
mysearchCallback,mymonitorCallback);
if(status) return(status);
return(status);
}
int recDynTestNewOutput(char *pvname,int nRequest)
{
userPvt *puserPvt= putDynlink.puserPvt;
long status;
int options=0;
if(puserPvt) {
recDynLinkClear(&putDynlink);
free(puserPvt->pbuffer);
free(putDynlink.puserPvt);
putDynlink.puserPvt = NULL;
}
putDynlink.puserPvt = puserPvt = (userPvt *)calloc(1,sizeof(userPvt));
puserPvt->pbuffer = calloc(nRequest,sizeof(double));
puserPvt->nRequest = nRequest;
puserPvt->pvname = pvname;
if(nRequest==1) options=rdlSCALAR;;
status = recDynLinkAddOutput(&putDynlink,pvname,
DBR_DOUBLE,options,mysearchCallback);
return(status);
}
int recDynTestOutput(int startValue)
{
userPvt *puserPvt= putDynlink.puserPvt;
long status;
int i;
for(i=0; i<puserPvt->nRequest; i++) puserPvt->pbuffer[i] = startValue + i;
status = recDynLinkPut(&putDynlink,puserPvt->pbuffer,puserPvt->nRequest);
return(status);
}
int recDynTestClearInput(void)
{
userPvt *puserPvt= getDynlink.puserPvt;
recDynLinkClear(&getDynlink);
free(puserPvt->pbuffer);
free(getDynlink.puserPvt);
getDynlink.puserPvt = NULL;
return(0);
}
int recDynTestClearOutput(void)
{
userPvt *puserPvt= putDynlink.puserPvt;
recDynLinkClear(&putDynlink);
free(puserPvt->pbuffer);
free(putDynlink.puserPvt);
putDynlink.puserPvt = NULL;
return(0);
}

View File

@@ -1,6 +1,12 @@
/*
* $Log$
* Revision 1.14 1995/08/30 15:38:39 jbk
* *** empty log message ***
*
* Revision 1.13 1995/08/18 13:19:31 mrk
* Made changes for ansi c
*
* Revision 1.12 1995/08/17 20:35:09 jbk
* fixed all the -pendantic errors (pain)
*
@@ -99,7 +105,8 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
*/
#define MAKE_DEBUG TSdriverDebug
#define TS_DRIVER
#define TS_DRIVER 1
#define TS_ALLOW_FORCE 1
#include <vxWorks.h>
#include <vme.h>
@@ -213,6 +220,9 @@ TSinfo TSdata = { TS_master_dead, TS_async_slave, TS_async_none,
extern char* sysBootLine;
int TSdirectTimeVar = 0; /* aother way to indicate direct time */
int TSgoodTimeStamps = 0; /* a way to force use of accurate time stamps */
static WDOG_ID wd;
static long correction_factor = 0;
static long correction_count = 0;
@@ -383,8 +393,13 @@ long TSgetTimeStamp(int event_number,struct timespec* sp)
switch(event_number)
{
case 0:
*sp = TSdata.event_table[0]; /* one tick watch dog maintains */
break;
#ifdef TS_ALLOW_FORCE
if(TSgoodTimeStamps==0)
#endif
{
*sp = TSdata.event_table[0]; /* one tick watch dog maintains */
break;
}
case -1:
{
struct timespec ts;
@@ -494,6 +509,8 @@ long TSinit(void)
TSregisterErrorHandler = TSregisterErrorHandlerError;
TSforceSync = TSforceSoftSync;
TSgetTime = TSgetCurrentTime;
TSdriverInit = TSdriverInitError;
TSdirectTime = TSdirectTimeError;
TSdata.sync_event=ER_EVENT_RESET_TICK;
}
@@ -518,7 +535,7 @@ long TSinit(void)
else
TSdata.has_event_system = 1;
if(TSdirectTime()>0) TSdata.has_direct_time=1;
if(TSdirectTime()>0 || TSdirectTimeVar>0) TSdata.has_direct_time=1;
/* allocate the event table */
TSdata.event_table=(struct timespec*)malloc(