Initial revision
This commit is contained in:
5905
src/db/dbAccess.c
Normal file
5905
src/db/dbAccess.c
Normal file
File diff suppressed because it is too large
Load Diff
751
src/db/dbEvent.c
Normal file
751
src/db/dbEvent.c
Normal file
@ -0,0 +1,751 @@
|
||||
|
||||
/* dbEvent.c */
|
||||
/* share/src/db $Id$ */
|
||||
|
||||
/*
|
||||
|
||||
dbEvent.c
|
||||
|
||||
routines for scheduling events to lower priority tasks via the RT kernel
|
||||
|
||||
Modification History
|
||||
joh 00 30Mar89 Created
|
||||
joh 01 Apr 89 Init Release
|
||||
joh 02 06-14-89 changed DBCHK to PADDRCHK since we are checking
|
||||
precord instead of pfield now.
|
||||
joh 03 07-28-89 Added dynamic que size increase proportional
|
||||
to nevents
|
||||
joh 04 08-21-89 Added init function to args of db_start_events()
|
||||
joh 05 12-21-89 fixed bug where event que not completely
|
||||
dealloated when there are many events.
|
||||
joh 06 02-16-90 changed names here and in dbcommon to avoid
|
||||
confusion for those maintaining this code
|
||||
(this change does not modify obj code).
|
||||
mlok became mon_lock
|
||||
mlst became mon_list
|
||||
mrk(anl)07 09-18-90 Made changes for new record and device support
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
#include <wdLib.h>
|
||||
#include <lstLib.h>
|
||||
#include <semLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <dbCommon.h>
|
||||
#include <dbAccess.h>
|
||||
#include <taskParams.h>
|
||||
|
||||
|
||||
struct event_block{
|
||||
NODE node;
|
||||
struct dbAddr addr;
|
||||
void *pfield; /* I modify the copy of pfield above */
|
||||
void (*user_sub)();
|
||||
void *user_arg;
|
||||
struct event_que *ev_que;
|
||||
unsigned char select;
|
||||
char valque;
|
||||
unsigned short npend; /* number of times this event is on the que */
|
||||
};
|
||||
|
||||
union native_value{
|
||||
short bval;
|
||||
short eval;
|
||||
float rval;
|
||||
/*
|
||||
Strings left off for now
|
||||
- reliable interprocess communication may not be provided with strings
|
||||
since they will slow down events for more reasonable size values.
|
||||
|
||||
char sval[MAXSTRINGSIZE];
|
||||
*/
|
||||
};
|
||||
|
||||
#define EVENTQUESIZE EVENTENTRIES *32
|
||||
#define EVENTENTRIES 16 /* the number of que entries for each event */
|
||||
#define EVENTQEMPTY ((struct event_block *)NULL)
|
||||
|
||||
/*
|
||||
Reliable intertask communication requires copying the current value
|
||||
of the channel for later queing so 3 stepper motor steps of 10 each
|
||||
do not turn into only 10 or 20 total steps part of the time.
|
||||
|
||||
NOTE: locks on this data structure are optimized so a test and set
|
||||
call is made first. If the lock is allready set then the task
|
||||
pends on the lock pend sem. Test and set call is much faster than
|
||||
a semaphore. See LOCKEVUSER.
|
||||
*/
|
||||
/*
|
||||
really a ring buffer
|
||||
*/
|
||||
struct event_que{
|
||||
struct event_block *evque[EVENTQUESIZE];
|
||||
union native_value valque[EVENTQUESIZE];
|
||||
unsigned short putix;
|
||||
unsigned short getix;
|
||||
unsigned short quota; /* the number of assigned entries*/
|
||||
|
||||
/* lock writers to the ring buffer only */
|
||||
/* readers must never slow up writers */
|
||||
FAST_LOCK writelock;
|
||||
|
||||
struct event_que *nextque; /* in case que quota exceeded */
|
||||
struct event_user *evuser; /* event user parent struct */
|
||||
};
|
||||
|
||||
struct event_user{
|
||||
int taskid; /* event handler task id */
|
||||
int taskpri; /* event handler task priority */
|
||||
|
||||
char pendlck; /* Only one task can pend */
|
||||
SEMAPHORE pendsem; /* Wait while empty */
|
||||
unsigned char pendexit; /* exit pend task */
|
||||
|
||||
unsigned short queovr; /* event que overflow count */
|
||||
void (*overflow_sub)(); /* executed for overflow detect */
|
||||
void *overflow_arg; /* parameter to above routine */
|
||||
|
||||
struct event_que firstque; /* the first event que */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#define RNGINC(OLD)\
|
||||
((OLD)+1)>=EVENTQUESIZE ? 0 : ((OLD)+1)
|
||||
|
||||
|
||||
#define LOCKEVQUE(EV_QUE)\
|
||||
FASTLOCK(&(EV_QUE)->writelock);
|
||||
|
||||
#define UNLOCKEVQUE(EV_QUE)\
|
||||
FASTUNLOCK(&(EV_QUE)->writelock);
|
||||
|
||||
#define LOCKREC(RECPTR)\
|
||||
FASTLOCK(&(RECPTR)->mlok);
|
||||
|
||||
#define UNLOCKREC(RECPTR)\
|
||||
FASTUNLOCK(&(RECPTR)->mlok);
|
||||
|
||||
|
||||
#define VXTASKIDSELF 0
|
||||
|
||||
/*
|
||||
>> kernel dependent <<
|
||||
|
||||
This is so if we go to a kernel which has different
|
||||
priority order I can switch all priority inc/dec at once -joh
|
||||
|
||||
on VRTX a lower priority number runs first- hence the minus one
|
||||
*/
|
||||
#define HIGHERPRIORITYINC (-1)
|
||||
#define HIGHER_OR_SAME_PRIORITY_THAN <=
|
||||
|
||||
db_event_list(name)
|
||||
char *name;
|
||||
{
|
||||
struct dbAddr addr;
|
||||
int status;
|
||||
struct event_block *pevent;
|
||||
register struct dbCommon *precord;
|
||||
|
||||
status = dbNameToAddr(name, &addr);
|
||||
if(status==ERROR)
|
||||
return ERROR;
|
||||
|
||||
precord = (struct dbCommon *) addr.precord;
|
||||
|
||||
LOCKREC(precord);
|
||||
for( pevent = (struct event_block *) precord->mlis.node.next;
|
||||
pevent;
|
||||
pevent = (struct event_block *) pevent->node.next){
|
||||
printf(" ev %x\n",pevent);
|
||||
printf(" ev que %x\n",pevent->ev_que);
|
||||
printf(" ev user %x\n",pevent->ev_que->evuser);
|
||||
logMsg("Event for task %x \n", pevent->ev_que->evuser->taskid);
|
||||
}
|
||||
UNLOCKREC(precord);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Initialize the event facility for this task
|
||||
Must be called at least once by each task which uses the db event facility
|
||||
|
||||
returns:
|
||||
ptr to event user block or NULL if memory can't be allocated
|
||||
*/
|
||||
struct event_user
|
||||
*db_init_events()
|
||||
{
|
||||
register struct event_user *evuser;
|
||||
int logMsg();
|
||||
|
||||
evuser = (struct event_user *) malloc(sizeof(*evuser));
|
||||
if(!evuser)
|
||||
return NULL;
|
||||
|
||||
bfill(evuser, sizeof(*evuser), NULL);
|
||||
evuser->firstque.evuser = evuser;
|
||||
/*
|
||||
init_event_que(&evuser->firstevent);
|
||||
|
||||
evuser->overflow_sub = NULL;
|
||||
evuser->overflow_arg = NULL;
|
||||
evuser->pendlck = FALSE;
|
||||
evuser->taskid = VXTASKIDSELF;
|
||||
*/
|
||||
|
||||
return evuser;
|
||||
}
|
||||
|
||||
#ifdef ZEBRA
|
||||
static
|
||||
init_event_que(ev_que)
|
||||
struct event_que *ev_que;
|
||||
{
|
||||
register int i;
|
||||
|
||||
bfill(ev_que, sizeof*ev_que), NULL);
|
||||
|
||||
/*
|
||||
FASTLOCKINIT(&ev_que->writelock);
|
||||
semInit(&ev_que->pendsem);
|
||||
ev_que->putix = 0;
|
||||
ev_que->getix = 0;
|
||||
ev_que->queovr = 0;
|
||||
ev_que->quota = 0;
|
||||
ev_que->nextque = NULL;
|
||||
for(i=0; i<EVENTQUESIZE; i++)
|
||||
ev_que->evque[i] = (struct event_block *) EVENTQEMPTY;
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
db_close_events(evuser)
|
||||
register struct event_user *evuser;
|
||||
{
|
||||
/*
|
||||
Exit not forced on event blocks for now
|
||||
- this is left to channel access and any other tasks
|
||||
using this facility which can find them more efficiently.
|
||||
|
||||
NOTE: not deleting events before calling this routine
|
||||
could be hazardous to the system's health.
|
||||
*/
|
||||
|
||||
evuser->pendexit = TRUE;
|
||||
|
||||
/* notify the waiting task */
|
||||
semGive(&evuser->pendsem);
|
||||
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
So the event block structure size but not structure is exported
|
||||
(used by those who wish for the event block to be a sub structure)
|
||||
see pevent != NULL on db_add_event()
|
||||
*/
|
||||
db_sizeof_event_block()
|
||||
{
|
||||
return sizeof(struct event_block);
|
||||
}
|
||||
|
||||
db_add_event(evuser, paddr, user_sub, user_arg, select, pevent)
|
||||
register struct event_user *evuser;
|
||||
register struct dbAddr *paddr;
|
||||
register void (*user_sub)();
|
||||
register void *user_arg;
|
||||
register unsigned int select;
|
||||
register struct event_block *pevent; /* ptr to event blk (not required) */
|
||||
{
|
||||
register struct dbCommon *precord;
|
||||
register struct event_que *ev_que;
|
||||
register struct event_que *tmp_que;
|
||||
|
||||
precord = (struct dbCommon *) paddr->precord;
|
||||
|
||||
/*
|
||||
Don't add events which will not be triggered
|
||||
*/
|
||||
if(!select)
|
||||
return ERROR;
|
||||
|
||||
/* find an event que block with enough quota */
|
||||
/* otherwise add a new one to the list */
|
||||
ev_que = &evuser->firstque;
|
||||
while(TRUE){
|
||||
if(ev_que->quota < EVENTQUESIZE - EVENTENTRIES)
|
||||
break;
|
||||
if(!ev_que->nextque){
|
||||
tmp_que = (struct event_que *) malloc(sizeof(*tmp_que));
|
||||
if(!tmp_que)
|
||||
return ERROR;
|
||||
bfill(tmp_que, sizeof(*tmp_que), NULL);
|
||||
tmp_que->evuser = evuser;
|
||||
ev_que->nextque = tmp_que;
|
||||
ev_que = tmp_que;
|
||||
break;
|
||||
}
|
||||
ev_que = ev_que->nextque;
|
||||
}
|
||||
|
||||
if(!pevent){
|
||||
pevent = (struct event_block *) malloc(sizeof(*pevent));
|
||||
if(!pevent)
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
pevent->npend = 0;
|
||||
pevent->user_sub = user_sub;
|
||||
pevent->user_arg = user_arg;
|
||||
pevent->addr = *paddr;
|
||||
pevent->pfield = (void *) paddr->pfield; /* I modify the one above */
|
||||
pevent->select = select;
|
||||
|
||||
ev_que->quota += EVENTENTRIES;
|
||||
pevent->ev_que = ev_que;
|
||||
|
||||
|
||||
/*
|
||||
Simple types values queued up for reliable interprocess communication
|
||||
(for other types they get whatever happens to be there upon wakeup)
|
||||
*/
|
||||
if(paddr->no_elements != 1)
|
||||
pevent->valque = FALSE;
|
||||
else
|
||||
switch(paddr->field_type){
|
||||
case DBR_UCHAR:
|
||||
case DBR_SHORT:
|
||||
case DBR_LONG:
|
||||
case DBR_ULONG:
|
||||
case DBR_FLOAT:
|
||||
case DBR_ENUM:
|
||||
/* change pfield to point to the value que entry */
|
||||
pevent->valque = TRUE;
|
||||
break;
|
||||
default:
|
||||
/* leave pfield pointing to the database */
|
||||
pevent->valque = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
LOCKREC(precord);
|
||||
lstAdd(&precord->mlis, pevent);
|
||||
UNLOCKREC(precord);
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This routine does not prevent two threads from deleting one block at
|
||||
the same time.
|
||||
|
||||
This routine does not deallocate the event block since it normally
|
||||
will be part of a larger structure.
|
||||
*/
|
||||
db_cancel_event(pevent)
|
||||
register struct event_block *pevent;
|
||||
{
|
||||
register struct dbCommon *precord;
|
||||
int myprio;
|
||||
int evprio;
|
||||
|
||||
|
||||
/*
|
||||
Disable this event block
|
||||
*/
|
||||
pevent->select = NULL;
|
||||
|
||||
precord = (struct dbCommon *) pevent->addr.precord;
|
||||
|
||||
LOCKREC(precord);
|
||||
lstDelete( &precord->mlis, pevent);
|
||||
UNLOCKREC(precord);
|
||||
|
||||
/*
|
||||
Decrement event que quota
|
||||
*/
|
||||
pevent->ev_que->quota -= EVENTENTRIES;
|
||||
|
||||
/*
|
||||
Flush the event que so we know event block not left in use
|
||||
This requires temporarily dropping below the priority of the
|
||||
event handler. This task will not run again until the
|
||||
handler has flushed its que.
|
||||
*/
|
||||
evprio = pevent->ev_que->evuser->taskpri;
|
||||
if(taskPriorityGet(VXTASKIDSELF, &myprio)==ERROR)
|
||||
taskSuspend(VXTASKIDSELF);
|
||||
|
||||
/*
|
||||
go to a lower priority than the event handler- if not there allready
|
||||
*/
|
||||
if(myprio HIGHER_OR_SAME_PRIORITY_THAN evprio){
|
||||
if(taskPrioritySet(VXTASKIDSELF, evprio-HIGHERPRIORITYINC)==ERROR)
|
||||
taskSuspend(VXTASKIDSELF);
|
||||
|
||||
/*
|
||||
Insure that the que is purged of this event
|
||||
(in case the event task is pending in a user subroutine)
|
||||
*/
|
||||
while(pevent->npend)
|
||||
taskDelay(10);
|
||||
|
||||
/* return to origional priority */
|
||||
if(taskPrioritySet(VXTASKIDSELF, myprio)==ERROR)
|
||||
taskSuspend(VXTASKIDSELF);
|
||||
}
|
||||
else
|
||||
while(pevent->npend)
|
||||
taskDelay(10);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Specify a routine to be executed for event que overflow condition
|
||||
*/
|
||||
db_add_overflow_event(evuser, overflow_sub, overflow_arg)
|
||||
register struct event_user *evuser;
|
||||
register void (*overflow_sub)();
|
||||
register void *overflow_arg;
|
||||
{
|
||||
|
||||
evuser->overflow_sub = overflow_sub;
|
||||
evuser->overflow_arg = overflow_arg;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
db_post_single_event(pevent)
|
||||
register struct event_block *pevent;
|
||||
{
|
||||
register struct event_que *ev_que = pevent->ev_que;
|
||||
register unsigned int putix;
|
||||
|
||||
/*
|
||||
evuser ring buffer must be locked for the multiple
|
||||
threads writing to it
|
||||
*/
|
||||
LOCKEVQUE(ev_que)
|
||||
putix = ev_que->putix;
|
||||
|
||||
/* add to task local event que */
|
||||
if(ev_que->evque[putix] == EVENTQEMPTY){
|
||||
pevent->npend++;
|
||||
ev_que->evque[putix] = pevent;
|
||||
ev_que->valque[putix] = *(union native_value *)pevent->pfield;
|
||||
|
||||
/* notify the event handler */
|
||||
semGive(&ev_que->evuser->pendsem);
|
||||
ev_que->putix = RNGINC(putix);
|
||||
}
|
||||
else
|
||||
ev_que->evuser->queovr++;
|
||||
|
||||
UNLOCKEVQUE(ev_que)
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
db_post_events(precord,pvalue,select)
|
||||
register struct dbCommon *precord;
|
||||
register union native_value *pvalue;
|
||||
register unsigned int select;
|
||||
{
|
||||
register struct event_block *event;
|
||||
register struct event_que *ev_que;
|
||||
register unsigned int putix;
|
||||
|
||||
LOCKREC(precord);
|
||||
|
||||
for( event = (struct event_block *) precord->mlis.node.next;
|
||||
event;
|
||||
event = (struct event_block *) event->node.next){
|
||||
|
||||
ev_que = event->ev_que;
|
||||
/*
|
||||
Only send event msg if they are waiting on the field which changed
|
||||
*/
|
||||
if( (event->pfield == (void *)pvalue) && (select & event->select) ){
|
||||
/*
|
||||
evuser ring buffer must be locked for the multiple
|
||||
threads writing to it
|
||||
*/
|
||||
LOCKEVQUE(ev_que)
|
||||
putix = ev_que->putix;
|
||||
|
||||
/* add to task local event que */
|
||||
if(ev_que->evque[putix] == EVENTQEMPTY){
|
||||
|
||||
event->npend++;
|
||||
ev_que->evque[putix] = event;
|
||||
ev_que->valque[putix] = *pvalue;
|
||||
|
||||
/* notify the event handler */
|
||||
semGive(&ev_que->evuser->pendsem);
|
||||
|
||||
ev_que->putix = RNGINC(putix);
|
||||
}
|
||||
else
|
||||
ev_que->evuser->queovr++;
|
||||
|
||||
UNLOCKEVQUE(ev_que)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UNLOCKREC(precord);
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
db_start_events(evuser,taskname,init_func,init_func_arg)
|
||||
struct event_user *evuser;
|
||||
char *taskname; /* defaulted if NULL */
|
||||
void (*init_func)();
|
||||
int init_func_arg;
|
||||
{
|
||||
int myprio;
|
||||
int status;
|
||||
int event_task();
|
||||
|
||||
/* only one ca_pend_event thread may be started for each evuser ! */
|
||||
while(!vxTas(&evuser->pendlck))
|
||||
return ERROR;
|
||||
|
||||
status = taskPriorityGet(VXTASKIDSELF, &evuser->taskpri);
|
||||
if(status == ERROR)
|
||||
return ERROR;
|
||||
|
||||
evuser->taskpri += HIGHERPRIORITYINC;
|
||||
|
||||
evuser->pendexit = FALSE;
|
||||
|
||||
if(!taskname)
|
||||
taskname = EVENT_PEND_NAME;
|
||||
status =
|
||||
taskSpawn( taskname,
|
||||
evuser->taskpri,
|
||||
EVENT_PEND_OPT,
|
||||
EVENT_PEND_STACK,
|
||||
event_task,
|
||||
evuser,
|
||||
init_func,
|
||||
init_func_arg);
|
||||
if(status == ERROR)
|
||||
return ERROR;
|
||||
|
||||
evuser->taskid = status;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
event_task(evuser, init_func, init_func_arg)
|
||||
register struct event_user *evuser;
|
||||
register void (*init_func)();
|
||||
register int init_func_arg;
|
||||
{
|
||||
register struct event_que *ev_que;
|
||||
|
||||
/* init hook */
|
||||
if(init_func)
|
||||
(*init_func)(init_func_arg);
|
||||
|
||||
/*
|
||||
No need to lock getix as I only allow one thread to call this routine at a time
|
||||
*/
|
||||
do{
|
||||
semTake(&evuser->pendsem);
|
||||
|
||||
for(ev_que= &evuser->firstque; ev_que; ev_que = ev_que->nextque)
|
||||
event_read(ev_que);
|
||||
|
||||
/*
|
||||
The following do not introduce event latency since they are
|
||||
not between notification and posting events.
|
||||
*/
|
||||
if(evuser->queovr){
|
||||
if(evuser->overflow_sub)
|
||||
(*evuser->overflow_sub)(evuser->overflow_arg, evuser->queovr);
|
||||
else
|
||||
logMsg("Events lost, discard count was %d\n",evuser->queovr);
|
||||
evuser->queovr = 0;
|
||||
}
|
||||
|
||||
}while(!evuser->pendexit);
|
||||
|
||||
evuser->pendlck = FALSE;
|
||||
|
||||
/* joh- added this code to free additional event ques */
|
||||
{
|
||||
struct event_que *nextque;
|
||||
for(ev_que = evuser->firstque.nextque; ev_que; ev_que = nextque){
|
||||
nextque = ev_que->nextque;
|
||||
if(free(ev_que))
|
||||
logMsg("evtsk: event user sub que free fail\n");
|
||||
}
|
||||
}
|
||||
/* end added code */
|
||||
|
||||
if(free(evuser))
|
||||
logMsg("evtsk: evuser free fail\n");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
event_read(ev_que)
|
||||
register struct event_que *ev_que;
|
||||
{
|
||||
register struct event_block *event;
|
||||
register unsigned int getix;
|
||||
register unsigned int nextgetix;
|
||||
register struct dbAddr *paddr;
|
||||
register char *pfield;
|
||||
|
||||
/*
|
||||
Fetch fast register copy
|
||||
*/
|
||||
getix = ev_que->getix;
|
||||
|
||||
/*
|
||||
No need to lock getix as I only allow one thread to call this routine at a time
|
||||
*/
|
||||
|
||||
for( event=ev_que->evque[getix];
|
||||
(event) != EVENTQEMPTY;
|
||||
getix = nextgetix, event = ev_que->evque[nextgetix]){
|
||||
|
||||
/*
|
||||
So I can tell em if more are comming
|
||||
*/
|
||||
nextgetix = RNGINC(getix);
|
||||
|
||||
paddr = &event->addr;
|
||||
|
||||
/*
|
||||
Simple type values queued up for reliable interprocess communication.
|
||||
(for other types they get whatever happens to be there upon wakeup)
|
||||
*/
|
||||
if(event->valque)
|
||||
paddr->pfield = (char *) &ev_que->valque[getix];
|
||||
|
||||
|
||||
/*
|
||||
Next event pointer can be used by event tasks to determine
|
||||
if more events are waiting in the queue
|
||||
*/
|
||||
(*event->user_sub)( event->user_arg,
|
||||
paddr,
|
||||
ev_que->evque[nextgetix]); /* NULL if no next event */
|
||||
|
||||
ev_que->evque[getix] = (struct event_block *) NULL;
|
||||
event->npend--;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Store back to RAM copy
|
||||
*/
|
||||
ev_que->getix = getix;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef ZEBRA
|
||||
|
||||
struct event_user *tevuser;
|
||||
struct dbAddr taddr;
|
||||
|
||||
|
||||
db_test_event(precord_name)
|
||||
register char *precord_name;
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
|
||||
if(!tevuser){
|
||||
tevuser = db_init_events();
|
||||
|
||||
status = dbNameToAddr(precord_name, &taddr);
|
||||
if(status==ERROR)
|
||||
return ERROR;
|
||||
|
||||
|
||||
status = db_start_events(tevuser);
|
||||
if(status==ERROR)
|
||||
return ERROR;
|
||||
|
||||
status = db_add_event(tevuser, &taddr, logMsg, "Val\n", DBE_VALUE, NULL);
|
||||
if(status==ERROR)
|
||||
return ERROR;
|
||||
status = db_add_event(tevuser, &taddr, logMsg, "Log\n", DBE_LOG, NULL);
|
||||
if(status==ERROR)
|
||||
return ERROR;
|
||||
status = db_add_event(tevuser, &taddr, logMsg, "Alarm\n", DBE_ALARM, NULL);
|
||||
if(status==ERROR)
|
||||
return ERROR;
|
||||
|
||||
}
|
||||
/*
|
||||
timexN(db_post_events, taddr.precord, taddr.pfield, DBE_VALUE | DBE_LOG);
|
||||
*/
|
||||
/*
|
||||
gremlin(taddr.precord, taddr.pfield);
|
||||
while(TRUE)taskDelay(100);
|
||||
*/
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
gremlin(p1,p2)
|
||||
void *p1;
|
||||
void *p2;
|
||||
{
|
||||
static unsigned int myprio = 250;
|
||||
static unsigned int delay;
|
||||
static unsigned int cnt;
|
||||
|
||||
if(cnt<200)
|
||||
{
|
||||
/*
|
||||
taskDelay((delay++)&0x3);
|
||||
*/
|
||||
taskSpawn( "gremlin",
|
||||
myprio-- & 0xff,
|
||||
EVENT_PEND_OPT,
|
||||
EVENT_PEND_STACK,
|
||||
gremlin,
|
||||
p1,
|
||||
p2);
|
||||
|
||||
taskSpawn( "gremlin",
|
||||
myprio-- & 0xff,
|
||||
EVENT_PEND_OPT,
|
||||
EVENT_PEND_STACK,
|
||||
gremlin,
|
||||
p1,
|
||||
p2);
|
||||
db_post_events(p1,p2,DBE_VALUE | DBE_LOG);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
1746
src/db/dbScan.c
Normal file
1746
src/db/dbScan.c
Normal file
File diff suppressed because it is too large
Load Diff
780
src/db/dbTest.c
Normal file
780
src/db/dbTest.c
Normal file
@ -0,0 +1,780 @@
|
||||
|
||||
/* dbTest.c */
|
||||
/* share/src/db $Id$ */
|
||||
|
||||
/* dbTest.c
|
||||
*
|
||||
* database access test subroutines
|
||||
*
|
||||
* Author: Bob Dalesio(LANL) and Marty Kraimer(ANL)
|
||||
*
|
||||
* Control System Software for the GTA Project
|
||||
*
|
||||
* Copyright 1988, 1989, the Regents of the University of California.
|
||||
*
|
||||
* This software was produced under a U.S. Government contract
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
|
||||
* operated by the University of California for the U.S. Department
|
||||
* of Energy.
|
||||
*
|
||||
* Developed by the Controls and Automation Group (AT-8)
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Direct inqueries to:
|
||||
* Bob Dalesio, AT-8, Mail Stop H820
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
* Phone: (505) 667-3414
|
||||
* E-mail: dalesio@luke.lanl.gov
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .xx mm-dd-yy mrk Comment
|
||||
*
|
||||
*/
|
||||
|
||||
/* Global Database Test Routines - All can be invoked via vxWorks shell
|
||||
*
|
||||
* dbl(ptypeName) list record names.
|
||||
* char *ptypeName; Record type. If null all record types
|
||||
*
|
||||
* dbgf(pname) get field
|
||||
* char *pname;
|
||||
*
|
||||
* dbpf(pname,pvalue) put field
|
||||
* char *pname;
|
||||
* char *pvalue
|
||||
*
|
||||
* dbpr(pname) print record
|
||||
* char *pname;
|
||||
*
|
||||
* dbtr(pname) test record and print
|
||||
* char *pname;
|
||||
*
|
||||
* dbtgf(pname) test get field
|
||||
* char *pname;
|
||||
*
|
||||
* dbtpf(pname,pvalue) test put field
|
||||
* char *pname;
|
||||
* char *pvalue
|
||||
*
|
||||
* dbior(pname) io_report
|
||||
* char *pname Driver name. If null all drivers
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
#include <strLib.h>
|
||||
#include <stdioLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbRecType.h>
|
||||
#include <dbRecords.h>
|
||||
#include <dbCommon.h>
|
||||
#include <recSup.h>
|
||||
#include <drvSup.h>
|
||||
|
||||
#define MIN(x,y) ((x < y)?x:y)
|
||||
#define MAX(x,y) ((x > y)?x:y)
|
||||
|
||||
/* Local Routines */
|
||||
printDbAddr();
|
||||
printBuffer();
|
||||
|
||||
long dbl(ptypeName) /* list process variables for specified record type*/
|
||||
char *ptypeName;
|
||||
{
|
||||
int rectype,beg,end,recnum;
|
||||
struct recLoc *precLoc;
|
||||
struct dbCommon *precord;
|
||||
char *pstr;
|
||||
char name[PVNAME_SZ+1];
|
||||
|
||||
if(dbRecType==NULL || dbRecords==NULL) return(1);
|
||||
if(ptypeName==NULL) {
|
||||
beg=0;
|
||||
end=dbRecords->number - 1;
|
||||
}
|
||||
else {
|
||||
for(rectype=0; rectype<dbRecType->number; rectype++) {
|
||||
if(!(pstr=GET_PRECTYPE(rectype))) continue;
|
||||
if(strcmp(pstr,ptypeName)==0){
|
||||
beg=rectype;
|
||||
end=rectype;
|
||||
goto got_it;
|
||||
}
|
||||
}
|
||||
printf("Illegal Record Type\n");
|
||||
return(1);
|
||||
}
|
||||
got_it:
|
||||
for(rectype=beg; rectype<=end; rectype++) {
|
||||
if(!(precLoc=GET_PRECLOC(rectype))) continue;
|
||||
for(recnum=0; precord=(struct dbCommon *)(GET_PRECORD(precLoc,recnum));
|
||||
recnum++) {
|
||||
if(precord->name[0] == 0) continue; /*deleted record*/
|
||||
strncpy(name,precord->name,PVNAME_SZ);
|
||||
name[PVNAME_SZ]=0;
|
||||
printf("%s\n",name);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
long dbgf(pname) /* get field value*/
|
||||
char *pname;
|
||||
{
|
||||
/* declare buffer long just to ensure correct alignment */
|
||||
long buffer[100];
|
||||
long *pbuffer=&buffer[0];
|
||||
struct dbAddr addr;
|
||||
long status;
|
||||
long options,no_elements;
|
||||
|
||||
status=dbNameToAddr(pname,&addr);
|
||||
printDbAddr(status,&addr);
|
||||
if(status) return(1);
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
if(addr.dbr_field_type==DBR_ENUM) {
|
||||
status=dbGetField(&addr,DBR_STRING,pbuffer,&options,&no_elements);
|
||||
printBuffer(status,DBR_STRING,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
else {
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
long dbpf(pname,pvalue) /* put field value*/
|
||||
char *pname;
|
||||
char *pvalue;
|
||||
{
|
||||
/* declare buffer long just to ensure correct alignment */
|
||||
long buffer[100];
|
||||
long *pbuffer=&buffer[0];
|
||||
struct dbAddr addr;
|
||||
long status;
|
||||
long options,no_elements;
|
||||
|
||||
status=dbNameToAddr(pname,&addr);
|
||||
printDbAddr(status,&addr);
|
||||
if(status) return(1);
|
||||
status=dbPutField(&addr,DBR_STRING,pvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
return(0);
|
||||
}
|
||||
|
||||
long dbpr(pname) /* print record */
|
||||
char *pname;
|
||||
{
|
||||
struct dbAddr addr;
|
||||
long status;
|
||||
long options,no_elements;
|
||||
struct rset *prset;
|
||||
long int (*report)()=NULL;
|
||||
|
||||
status=dbNameToAddr(pname,&addr);
|
||||
printDbAddr(status,&addr);
|
||||
if(status) return(1);
|
||||
if(!(prset=GET_PRSET(addr.record_type))) {
|
||||
printf("No record Support for this record type\n");
|
||||
return(1);
|
||||
}
|
||||
if(!(report = (prset->report))) {
|
||||
printf("No report routine in RSET\n");
|
||||
return(1);
|
||||
}
|
||||
status=(*report)(stdout,&addr);
|
||||
fflush(stdout);
|
||||
if(!RTN_SUCCESS(status))
|
||||
recGblRecSupError(S_db_noSupport,&addr,"dbpr","report");
|
||||
return(0);
|
||||
}
|
||||
|
||||
long dbtr(pname) /* test record and print*/
|
||||
char *pname;
|
||||
{
|
||||
struct dbAddr addr;
|
||||
long status;
|
||||
long options,no_elements;
|
||||
struct rset *prset;
|
||||
long int (*process)()=NULL;
|
||||
|
||||
status=dbNameToAddr(pname,&addr);
|
||||
if(status) {
|
||||
printf("dbNameToAddr failed\n");
|
||||
return(1);
|
||||
}
|
||||
if(!(prset=GET_PRSET(addr.record_type))) {
|
||||
printf("No record Support for this record type\n");
|
||||
return(1);
|
||||
}
|
||||
if(!(process = (prset->process))) {
|
||||
printf("No process routine in RSET\n");
|
||||
return(1);
|
||||
}
|
||||
status=(*process)(addr.precord);
|
||||
if(!RTN_SUCCESS(status))
|
||||
recGblRecSupError(S_db_noSupport,&addr,"dbtr","process");
|
||||
dbpr(pname);
|
||||
return(0);
|
||||
}
|
||||
|
||||
long dbtgf(pname) /* test all options for dbGetField */
|
||||
char *pname;
|
||||
{
|
||||
/* declare buffer long just to ensure correct alignment */
|
||||
long buffer[300];
|
||||
long *pbuffer=&buffer[0];
|
||||
struct dbAddr addr;
|
||||
long status;
|
||||
long req_options,ret_options,no_elements;
|
||||
short dbr_type;
|
||||
|
||||
status=dbNameToAddr(pname,&addr);
|
||||
printDbAddr(status,&addr);
|
||||
if(status)return;
|
||||
/* try all options first */
|
||||
req_options=0xffffffff;
|
||||
ret_options=req_options;
|
||||
no_elements=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&ret_options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,
|
||||
req_options,ret_options,no_elements);
|
||||
/* Now try all request types */
|
||||
ret_options=0;
|
||||
dbr_type=DBR_STRING;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/MAX_STRING_SIZE));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_CHAR;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(char)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_UCHAR;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(unsigned char)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_SHORT;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(short)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_USHORT;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(unsigned short)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_LONG;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(long)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_ULONG;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(unsigned long)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_FLOAT;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(float)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_DOUBLE;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(double)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
dbr_type=DBR_ENUM;
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/sizeof(unsigned short)));
|
||||
status=dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements);
|
||||
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements);
|
||||
return(0);
|
||||
}
|
||||
|
||||
long dbtpf(pname,pvalue)/* test all options for dbPutField */
|
||||
char *pname;
|
||||
{
|
||||
/* declare buffer long just to ensure correct alignment */
|
||||
long buffer[100];
|
||||
long *pbuffer=&buffer[0];
|
||||
struct dbAddr addr;
|
||||
long status;
|
||||
long options,no_elements;
|
||||
char cvalue;
|
||||
unsigned char ucvalue;
|
||||
short svalue;
|
||||
unsigned short usvalue;
|
||||
long lvalue;
|
||||
unsigned long ulvalue;
|
||||
float fvalue;
|
||||
double dvalue;
|
||||
|
||||
status=dbNameToAddr(pname,&addr);
|
||||
printDbAddr(status,&addr);
|
||||
if(status) return(1);
|
||||
/* DBR_STRING */
|
||||
status=dbPutField(&addr,DBR_STRING,pvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_STRING ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
/* DBR_CHAR */
|
||||
if(sscanf(pvalue,"%hd",&svalue)==1) {
|
||||
cvalue = (char)svalue;
|
||||
status=dbPutField(&addr,DBR_CHAR,&cvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_UCHAR ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_CHAR\n");
|
||||
/* DBR_UCHAR */
|
||||
if(sscanf(pvalue,"%hu",&usvalue)==1) {
|
||||
ucvalue = (unsigned char)usvalue;
|
||||
status=dbPutField(&addr,DBR_UCHAR,&ucvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_UCHAR ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_UCHAR\n");
|
||||
/* DBR_SHORT */
|
||||
if(sscanf(pvalue,"%hd",&svalue)==1) {
|
||||
status=dbPutField(&addr,DBR_SHORT,&svalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_SHORT ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_SHORT\n");
|
||||
/* DBR_USHORT */
|
||||
if(sscanf(pvalue,"%hu",&usvalue)==1) {
|
||||
status=dbPutField(&addr,DBR_USHORT,&usvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_USHORT ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_USHORT\n");
|
||||
/* DBR_LONG */
|
||||
if(sscanf(pvalue,"%ld",&lvalue)==1) {
|
||||
status=dbPutField(&addr,DBR_LONG,&lvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_LONG ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_LONG\n");
|
||||
/* DBR_ULONG */
|
||||
if(sscanf(pvalue,"%lu",&ulvalue)==1) {
|
||||
status=dbPutField(&addr,DBR_ULONG,&ulvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_ULONG ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_ULONG\n");
|
||||
/* DBR_FLOAT */
|
||||
if(sscanf(pvalue,"%e",&fvalue)==1) {
|
||||
status=dbPutField(&addr,DBR_FLOAT,&fvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_FLOAT ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_FLOAT\n");
|
||||
/* DBR_DOUBLE */
|
||||
if(sscanf(pvalue,"%le",&dvalue)==1) {
|
||||
status=dbPutField(&addr,DBR_DOUBLE,&dvalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_DOUBLE ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_DOUBLE\n");
|
||||
/* DBR_ENUM */
|
||||
if(sscanf(pvalue,"%hu",&svalue)==1) {
|
||||
status=dbPutField(&addr,DBR_ENUM,&svalue,1L);
|
||||
if(status!=0) errPrint(status);
|
||||
else {
|
||||
printf("DBR_ENUM ok\n");
|
||||
no_elements=MIN(addr.no_elements,((sizeof(buffer)*4)/addr.field_size));
|
||||
options=0;
|
||||
status=dbGetField(&addr,addr.dbr_field_type,pbuffer,
|
||||
&options,&no_elements);
|
||||
printBuffer(status,addr.dbr_field_type,pbuffer,0L,0L,no_elements);
|
||||
}
|
||||
} else printf("sscanf failed for DBR_SHORT\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
long printDbAddr(status,paddr)
|
||||
long status;
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
|
||||
if(status!=0) {
|
||||
errPrint(status);
|
||||
}
|
||||
printf("Record Address: 0x%x",paddr->precord);
|
||||
printf(" Field Address: 0x%x",paddr->pfield);
|
||||
printf(" Field Description: 0x%x\n",paddr->pfldDes);
|
||||
printf(" No Elements: %ld\n",paddr->no_elements);
|
||||
printf(" Record Type: %d\n",paddr->record_type);
|
||||
printf(" Field Type: %d\n",paddr->field_type);
|
||||
printf(" Field Size: %d\n",paddr->field_size);
|
||||
printf(" Special: %d\n",paddr->special);
|
||||
printf(" Choice Set: %d\n",paddr->choice_set);
|
||||
printf("DBR Field Type: %d\n",paddr->dbr_field_type);
|
||||
}
|
||||
|
||||
long printBuffer(status,dbr_type,pbuffer,reqOptions,retOptions,no_elements)
|
||||
long status;
|
||||
short dbr_type;
|
||||
char *pbuffer;
|
||||
long reqOptions;
|
||||
long retOptions;
|
||||
long no_elements;
|
||||
{
|
||||
unsigned short stat,severity;
|
||||
long precision;
|
||||
unsigned long epoch_seconds;
|
||||
unsigned long nano_seconds;
|
||||
unsigned long no_strs;
|
||||
short sarr[6];
|
||||
short svalue;
|
||||
unsigned short usarr[6];
|
||||
unsigned short usvalue;
|
||||
int i;
|
||||
|
||||
if(reqOptions&DBR_STATUS) {
|
||||
if(retOptions&DBR_STATUS) {
|
||||
stat = *((unsigned short*)pbuffer);
|
||||
severity = *((unsigned short*)(pbuffer+2));
|
||||
printf("status=%u severity=%u\n",stat,severity);
|
||||
} else printf("status and severity not returned\n");
|
||||
pbuffer += dbr_status_size;
|
||||
}
|
||||
if(reqOptions&DBR_UNITS) {
|
||||
if(retOptions&DBR_UNITS) printf("units=%-8s\n",pbuffer);
|
||||
else printf("units not returned\n");
|
||||
pbuffer += dbr_units_size;
|
||||
}
|
||||
if(reqOptions&DBR_PRECISION) {
|
||||
precision = *((long*)pbuffer);
|
||||
if(retOptions&DBR_PRECISION) printf("precision=%ld\n",precision);
|
||||
else printf("precision not returned\n");
|
||||
pbuffer += dbr_precision_size;
|
||||
}
|
||||
if(reqOptions&DBR_TIME) {
|
||||
epoch_seconds = *((unsigned long*)pbuffer);
|
||||
nano_seconds = *((unsigned long*)(pbuffer+4));
|
||||
if(retOptions&DBR_TIME)
|
||||
printf("time=%lu %lu\n",epoch_seconds,nano_seconds);
|
||||
else printf("time not returned\n");
|
||||
pbuffer += dbr_time_size;
|
||||
}
|
||||
if(reqOptions&DBR_ENUM_STRS) {
|
||||
if(retOptions&DBR_ENUM_STRS) {
|
||||
no_strs = *((unsigned long*)pbuffer);
|
||||
printf("no_strs=%lu\n",no_strs);
|
||||
for(i=0; i < *((unsigned long *)pbuffer); i++)
|
||||
printf("%s\n",(pbuffer + 4 + i*26));
|
||||
} else printf("enum strings not returned\n");
|
||||
pbuffer += dbr_enumStrs_size;
|
||||
}
|
||||
if(reqOptions&DBR_GR_UCHAR) {
|
||||
usarr[0]=*((unsigned char *)pbuffer);
|
||||
usarr[1]=*((unsigned char *)(pbuffer+1));
|
||||
usarr[2]=*((unsigned char *)(pbuffer+2));
|
||||
usarr[3]=*((unsigned char *)(pbuffer+3));
|
||||
usarr[4]=*((unsigned char *)(pbuffer+4));
|
||||
usarr[5]=*((unsigned char *)(pbuffer+5));
|
||||
if(retOptions&DBR_GR_UCHAR)
|
||||
printf("grUchar: %u %u %u %u %u %u\n",
|
||||
usarr[0],usarr[1],usarr[2],usarr[3],usarr[4],usarr[5]);
|
||||
else printf("DBRgrUchar not returned\n");
|
||||
pbuffer += dbr_grUchar_size;
|
||||
}
|
||||
if(reqOptions&DBR_GR_SHORT) {
|
||||
if(retOptions&DBR_GR_SHORT)
|
||||
printf("grShort: %d %d %d %d %d %d\n",
|
||||
*(short *)(pbuffer),
|
||||
*(short *)(pbuffer+2),
|
||||
*(short *)(pbuffer+4),
|
||||
*(short *)(pbuffer+6),
|
||||
*(short *)(pbuffer+8),
|
||||
*(short *)(pbuffer+10));
|
||||
else printf("DBRgrShort not returned\n");
|
||||
pbuffer += dbr_grShort_size;
|
||||
}
|
||||
if(reqOptions&DBR_GR_LONG) {
|
||||
if(retOptions&DBR_GR_LONG)
|
||||
printf("grLong: %ld %ld %ld %ld %ld %ld\n",
|
||||
*(long *)(pbuffer),
|
||||
*(long *)(pbuffer+4),
|
||||
*(long *)(pbuffer+8),
|
||||
*(long *)(pbuffer+12),
|
||||
*(long *)(pbuffer+16),
|
||||
*(long *)(pbuffer+20));
|
||||
else printf("DBRgrLong not returned\n");
|
||||
pbuffer += dbr_grLong_size;
|
||||
}
|
||||
if(reqOptions&DBR_GR_ULONG) {
|
||||
if(retOptions&DBR_GR_ULONG)
|
||||
printf("grUlong: %lu %lu %lu %lu %lu %lu\n",
|
||||
*(unsigned long *)(pbuffer),
|
||||
*(unsigned long *)(pbuffer+4),
|
||||
*(unsigned long *)(pbuffer+8),
|
||||
*(unsigned long *)(pbuffer+12),
|
||||
*(unsigned long *)(pbuffer+16),
|
||||
*(unsigned long *)(pbuffer+20));
|
||||
else printf("DBRgrUlong not returned\n");
|
||||
pbuffer += dbr_grUlong_size;
|
||||
}
|
||||
if(reqOptions&DBR_GR_FLOAT) {
|
||||
if(retOptions&DBR_GR_FLOAT)
|
||||
printf("grFloat: %g %g %g %g %g %g\n",
|
||||
*(float *)(pbuffer),
|
||||
*(float *)(pbuffer+4),
|
||||
*(float *)(pbuffer+8),
|
||||
*(float *)(pbuffer+12),
|
||||
*(float *)(pbuffer+16),
|
||||
*(float *)(pbuffer+20));
|
||||
else printf("DBRgrFloat not returned\n");
|
||||
pbuffer += dbr_grFloat_size;
|
||||
}
|
||||
if(reqOptions&DBR_GR_DOUBLE) {
|
||||
if(retOptions&DBR_GR_DOUBLE)
|
||||
printf("grDouble: %lg %lg %lg %lg %lg %lg\n",
|
||||
*(double *)(pbuffer),
|
||||
*(double *)(pbuffer+8),
|
||||
*(double *)(pbuffer+16),
|
||||
*(double *)(pbuffer+24),
|
||||
*(double *)(pbuffer+32),
|
||||
*(double *)(pbuffer+40));
|
||||
else printf("DBRgrDouble not returned\n");
|
||||
pbuffer += dbr_grDouble_size;
|
||||
}
|
||||
if(reqOptions&DBR_CTRL_UCHAR) {
|
||||
usarr[0]=*((unsigned char *)pbuffer);
|
||||
usarr[1]=*((unsigned char *)(pbuffer+1));
|
||||
if(retOptions&DBR_CTRL_UCHAR)
|
||||
printf("ctrlUchar: %u %u\n",
|
||||
usarr[0],usarr[1]);
|
||||
else printf("DBRctrlUchar not returned\n");
|
||||
pbuffer += dbr_ctrlUchar_size;
|
||||
}
|
||||
if(reqOptions&DBR_CTRL_SHORT) {
|
||||
if(retOptions&DBR_CTRL_SHORT)
|
||||
printf("ctrlShort: %d %d\n",
|
||||
*(short *)(pbuffer),
|
||||
*(short *)(pbuffer+2));
|
||||
else printf("DBRctrlShort not returned\n");
|
||||
pbuffer += dbr_ctrlShort_size;
|
||||
}
|
||||
if(reqOptions&DBR_CTRL_LONG) {
|
||||
if(retOptions&DBR_CTRL_LONG)
|
||||
printf("ctrlLong: %ld %ld\n",
|
||||
*(long *)(pbuffer),
|
||||
*(long *)(pbuffer+4));
|
||||
else printf("DBRctrlLong not returned\n");
|
||||
pbuffer += dbr_ctrlLong_size;
|
||||
}
|
||||
if(reqOptions&DBR_CTRL_ULONG) {
|
||||
if(retOptions&DBR_CTRL_ULONG)
|
||||
printf("ctrlUlong: %lu %lu\n",
|
||||
*(unsigned long *)(pbuffer),
|
||||
*(unsigned long *)(pbuffer+4));
|
||||
else printf("DBRctrlUlong not returned\n");
|
||||
pbuffer += dbr_ctrlUlong_size;
|
||||
}
|
||||
if(reqOptions&DBR_CTRL_FLOAT) {
|
||||
if(retOptions&DBR_CTRL_FLOAT)
|
||||
printf("ctrlFloat: %g %g\n",
|
||||
*(float *)(pbuffer),
|
||||
*(float *)(pbuffer+4));
|
||||
else printf("DBRctrlFloat not returned\n");
|
||||
pbuffer += dbr_ctrlFloat_size;
|
||||
}
|
||||
if(reqOptions&DBR_CTRL_DOUBLE) {
|
||||
if(retOptions&DBR_CTRL_DOUBLE)
|
||||
printf("ctrlDouble: %lg %lg\n",
|
||||
*(double *)(pbuffer),
|
||||
*(double *)(pbuffer+8));
|
||||
else printf("DBRctrlDouble not returned\n");
|
||||
pbuffer += dbr_ctrlDouble_size;
|
||||
}
|
||||
/*Now print values*/
|
||||
if(no_elements==0)return;
|
||||
switch(dbr_type) {
|
||||
case(DBR_STRING):
|
||||
if(status!=0) {printf("DBR_STRING: failed."); break;}
|
||||
printf("DBR_STRING: %s",pbuffer);
|
||||
break;
|
||||
case(DBR_CHAR):
|
||||
printf("DBR_CHAR: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
svalue=*(char*)pbuffer;
|
||||
printf("%-3d ",svalue);
|
||||
if (i%10 == 9) printf("\n");
|
||||
pbuffer += 1;
|
||||
}
|
||||
break;
|
||||
case(DBR_UCHAR):
|
||||
printf("DBR_UCHAR: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
usvalue=*(unsigned char*)pbuffer;
|
||||
printf("%-3d ",usvalue);
|
||||
if (i%10 == 9) printf("\n");
|
||||
pbuffer += 1;
|
||||
}
|
||||
break;
|
||||
case(DBR_SHORT):
|
||||
printf("DBR_SHORT: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
printf("%-6d ",*((short *)pbuffer));
|
||||
if (i%10 == 9) printf("\n");
|
||||
pbuffer += 2;
|
||||
}
|
||||
break;
|
||||
case(DBR_USHORT):
|
||||
printf("DBR_USHORT: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
printf("%-6u ",*((unsigned short *)pbuffer));
|
||||
if (i%10 == 9) printf("\n");
|
||||
pbuffer += 2;
|
||||
}
|
||||
break;
|
||||
case(DBR_LONG):
|
||||
printf("DBR_LONG: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
printf("%-10ld ",*((long *)pbuffer));
|
||||
if (i%5 == 4) printf("\n");
|
||||
pbuffer += 4;
|
||||
}
|
||||
break;
|
||||
case(DBR_ULONG):
|
||||
printf("DBR_ULONG: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
printf("0x%-8lx ",*((unsigned long *)pbuffer));
|
||||
if (i%5 == 4) printf("\n");
|
||||
pbuffer += 4;
|
||||
}
|
||||
break;
|
||||
case(DBR_FLOAT):
|
||||
printf("DBR_FLOAT: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
printf("%-9.2g ",*((float *)pbuffer));
|
||||
if (i%10 == 9) printf("\n");
|
||||
pbuffer += 4;
|
||||
}
|
||||
break;
|
||||
case(DBR_DOUBLE):
|
||||
printf("DBR_DOUBLE: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
printf("%-9.2g ",*((double *)pbuffer));
|
||||
if (i%10 == 9) printf("\n");
|
||||
pbuffer += 8;
|
||||
}
|
||||
break;
|
||||
case(DBR_ENUM):
|
||||
printf("DBR_ENUM: ");
|
||||
if(status!=0) {printf(" failed."); break;}
|
||||
for(i=0; i<no_elements; i++) {
|
||||
printf("%-6u ",*((unsigned short *)pbuffer));
|
||||
if (i%10 == 9) printf("\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf(" illegal request type.");
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
long dbior(pdrvName)
|
||||
char *pdrvName;
|
||||
{
|
||||
int i;
|
||||
char *pname;
|
||||
struct drvet *pdrvet;
|
||||
int printIt;
|
||||
|
||||
if(!drvSup) {
|
||||
printf("No drivers\n");
|
||||
return(0);
|
||||
}
|
||||
for (i=0; i<drvSup->number; i++) {
|
||||
if((pname=drvSup->drvetName[i])==NULL) continue;
|
||||
if(pdrvName==NULL)
|
||||
printIt=TRUE;
|
||||
else {
|
||||
printIt = (strcmp(pdrvName,pname)==0 ? TRUE : FALSE);
|
||||
if(!printIt) continue;
|
||||
}
|
||||
if((pdrvet=drvSup->papDrvet[i])==NULL) {
|
||||
printf("No driver entry table is present for %s\n",pname);
|
||||
continue;
|
||||
}
|
||||
if(pdrvet->report==NULL) {
|
||||
if(printIt&&(pdrvName!=NULL)) printf("No report available\n");
|
||||
}
|
||||
else {
|
||||
printf("Driver: %s\n",pname);
|
||||
(*pdrvet->report)();
|
||||
}
|
||||
if(pdrvName!=NULL) break;
|
||||
}
|
||||
return(0);
|
||||
}
|
364
src/db/db_access.c
Normal file
364
src/db/db_access.c
Normal file
@ -0,0 +1,364 @@
|
||||
|
||||
/* db_access.c */
|
||||
/* share/src/db $Id$ */
|
||||
/* db_access.c - Interface between old database access and new */
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
|
||||
#include <fioLib.h>
|
||||
#include <strLib.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbCommon.h>
|
||||
#include <errMdef.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#define oldDBF_STRING 0
|
||||
#define oldDBF_INT 1
|
||||
#define oldDBF_FLOAT 2
|
||||
#define oldDBF_ENUM 3
|
||||
#define oldDBF_NO_ACCESS 4
|
||||
|
||||
/* data request buffer types */
|
||||
#define oldDBR_STRING oldDBF_STRING
|
||||
#define oldDBR_INT oldDBF_INT
|
||||
#define oldDBR_FLOAT oldDBF_FLOAT
|
||||
#define oldDBR_ENUM oldDBF_ENUM
|
||||
#define oldDBR_STS_STRING 4
|
||||
#define oldDBR_STS_INT 5
|
||||
#define oldDBR_STS_FLOAT 6
|
||||
#define oldDBR_STS_ENUM 7
|
||||
#define oldDBR_GR_INT 8
|
||||
#define oldDBR_GR_FLOAT 9
|
||||
#define oldDBR_CTRL_INT 10
|
||||
#define oldDBR_CTRL_FLOAT 11
|
||||
#define oldDBR_CTRL_ENUM 12
|
||||
|
||||
/* structures needed by db_put_field */
|
||||
struct dbr_ctrl_short{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
char units[8]; /* units of value */
|
||||
short upper_disp_limit; /* upper limit of graph */
|
||||
short lower_disp_limit; /* lower limit of graph */
|
||||
short upper_alarm_limit;
|
||||
short upper_warning_limit;
|
||||
short lower_warning_limit;
|
||||
short lower_alarm_limit;
|
||||
short upper_ctrl_limit; /* upper control limit */
|
||||
short lower_ctrl_limit; /* lower control limit */
|
||||
short value; /* current value */
|
||||
};
|
||||
/* structure for a control floating point field */
|
||||
struct dbr_ctrl_float{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
short precision; /* number of decimal places */
|
||||
char units[8]; /* units of value */
|
||||
float upper_disp_limit; /* upper limit of graph */
|
||||
float lower_disp_limit; /* lower limit of graph */
|
||||
float upper_alarm_limit;
|
||||
float upper_warning_limit;
|
||||
float lower_warning_limit;
|
||||
float lower_alarm_limit;
|
||||
float upper_ctrl_limit; /* upper control limit */
|
||||
float lower_ctrl_limit; /* lower control limit */
|
||||
float value; /* current value */
|
||||
};
|
||||
|
||||
/* From $cs/dblib/src/dbiocsubs.c
|
||||
* subroutines
|
||||
*
|
||||
* db_process process a database record
|
||||
* args
|
||||
* pdb_addr pointer to a database address
|
||||
* command_mask mask of operations to perform
|
||||
* new_alarm send an alarm message (NYI!!!!!)
|
||||
* fill fill a buffer with a character
|
||||
* args
|
||||
* pbuffer pointer to the buffer
|
||||
* size number of characters
|
||||
* fillchar character with which to fill
|
||||
*/
|
||||
|
||||
/*
|
||||
* DB_PROCESS
|
||||
*
|
||||
* process database records
|
||||
*/
|
||||
db_process(pdb_addr)
|
||||
register struct db_addr *pdb_addr;
|
||||
{
|
||||
long status;
|
||||
|
||||
status=dbProcess(pdb_addr);
|
||||
if(!RTN_SUCCESS(status)) errMessage(status,"db_process failed");
|
||||
return;
|
||||
}
|
||||
|
||||
new_alarm(){
|
||||
return;
|
||||
}
|
||||
/* FILL fill a buffer with the designated character */
|
||||
fill(pbuffer,size,fillchar)
|
||||
register char *pbuffer;
|
||||
register short size;
|
||||
register char fillchar;
|
||||
{
|
||||
register short i;
|
||||
|
||||
for (i=0; i<size; i++){
|
||||
*pbuffer = fillchar;
|
||||
pbuffer++;
|
||||
}
|
||||
}
|
||||
|
||||
/* IOCDBACCESS.C
|
||||
* Global Subroutines
|
||||
*
|
||||
* db_name_to_addr converts a database name in the format "pv<.field>"
|
||||
* to a database address
|
||||
* args
|
||||
* pname pointer to the database name
|
||||
* paddr pointer to the database address structure
|
||||
* returns
|
||||
* 0 successful
|
||||
* -1 not successful
|
||||
* pv portion failed - node, record type and record number are -1
|
||||
* field portion failed - field type, offset, size and ext are -1
|
||||
*
|
||||
*
|
||||
* db_get_field get a field from the database and convert it to
|
||||
* the specified type.
|
||||
*
|
||||
* args
|
||||
* paddr pointer to the database address structure
|
||||
* buffer_type the type of data to return
|
||||
* see DBR_ defines in db_access.h
|
||||
* pbuffer return buffer
|
||||
* no_elements number of elements
|
||||
* returns
|
||||
* 0 successful
|
||||
* -1 failed
|
||||
*
|
||||
* db_put_field put a converted buffer into the database
|
||||
* args
|
||||
* paddr pointer to the database address structure
|
||||
* buffer_type the type of data to be converted and stored
|
||||
* see DBR_ defines in db_access.h
|
||||
* pbuffer return buffer
|
||||
* returns
|
||||
* 0 successful
|
||||
* -1 failed
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* DB_NAME_TO_ADDR
|
||||
*/
|
||||
static short mapNewToOld[]={0,1,1,1,1,2,2,3,4};
|
||||
|
||||
db_name_to_addr(pname,paddr)
|
||||
register char *pname;
|
||||
register struct dbAddr *paddr;
|
||||
{
|
||||
long status;
|
||||
short ftype;
|
||||
|
||||
status=dbNameToAddr(pname,paddr);
|
||||
if(RTN_SUCCESS(status)) {
|
||||
ftype = paddr->dbr_field_type;
|
||||
if(ftype<0 || ftype> (sizeof(mapNewToOld)/sizeof(short))) {
|
||||
printf("db_name_to_addr: Illegal dbr_field_type\n");
|
||||
exit(-1);
|
||||
}
|
||||
paddr->dbr_field_type = mapNewToOld[paddr->dbr_field_type];
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* DB_GET_FIELD get a field and convert it to the desired type */
|
||||
|
||||
db_get_field(paddr,buffer_type,pbuffer,no_elements)
|
||||
struct dbAddr *paddr;
|
||||
short buffer_type;
|
||||
char *pbuffer;
|
||||
unsigned short no_elements;
|
||||
{
|
||||
long status;
|
||||
long options;
|
||||
long nRequest;
|
||||
long precision;
|
||||
short severity;
|
||||
short no_str;
|
||||
|
||||
|
||||
switch(buffer_type) {
|
||||
case(oldDBR_STRING):
|
||||
options=0;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_STRING,pbuffer,&options,&nRequest);
|
||||
break;
|
||||
case(oldDBR_INT):
|
||||
options=0;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_SHORT,pbuffer,&options,&nRequest);
|
||||
break;
|
||||
case(oldDBR_FLOAT):
|
||||
options=0;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_FLOAT,pbuffer,&options,&nRequest);
|
||||
break;
|
||||
case(oldDBR_ENUM):
|
||||
options=0;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_ENUM,pbuffer,&options,&nRequest);
|
||||
break;
|
||||
case(oldDBR_STS_STRING):
|
||||
options=DBR_STATUS;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_STRING,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
break;
|
||||
case(oldDBR_STS_INT):
|
||||
options=DBR_STATUS;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_SHORT,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
break;
|
||||
case(oldDBR_STS_FLOAT):
|
||||
options=DBR_STATUS;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_FLOAT,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
break;
|
||||
case(oldDBR_STS_ENUM):
|
||||
options=DBR_STATUS;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_ENUM,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
break;
|
||||
case(oldDBR_GR_INT):
|
||||
options=DBR_STATUS|DBR_UNITS|DBR_GR_SHORT;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_SHORT,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
break;
|
||||
case(oldDBR_GR_FLOAT):
|
||||
/* First get status and precision */
|
||||
options=DBR_STATUS|DBR_PRECISION;
|
||||
nRequest=0;
|
||||
status = dbGetField(paddr,DBR_FLOAT,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
pbuffer += 2*sizeof(short);/*point pbuffer to precision value*/
|
||||
precision = *((long *)pbuffer);
|
||||
*(((short *)pbuffer)++) = (short)precision; /* convert it to short*/
|
||||
/* get units and graphics float*/
|
||||
options=DBR_UNITS|DBR_GR_FLOAT;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_FLOAT,pbuffer,&options,&nRequest);
|
||||
if(status!=0) {
|
||||
/* VMS OPI asks for this for all variables at init. Must return success*/
|
||||
float *pb=(float *)pbuffer;
|
||||
|
||||
while(nRequest>0) {
|
||||
*pbuffer++ = 0;
|
||||
nRequest--;
|
||||
}
|
||||
status=0;
|
||||
}
|
||||
break;
|
||||
case(oldDBR_CTRL_INT):
|
||||
options=DBR_STATUS|DBR_UNITS|DBR_GR_SHORT|DBR_CTRL_SHORT;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_SHORT,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
break;
|
||||
case(oldDBR_CTRL_FLOAT):
|
||||
/* First get status and precision */
|
||||
options=DBR_STATUS|DBR_PRECISION;
|
||||
nRequest=0;
|
||||
status = dbGetField(paddr,DBR_FLOAT,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
pbuffer += 2*sizeof(short);/*point pbuffer to precision value*/
|
||||
precision = *((long *)pbuffer);
|
||||
*(((short *)pbuffer)++) = (short)precision; /* convert it to short*/
|
||||
/* get units and graphics float and control*/
|
||||
options=DBR_UNITS|DBR_GR_FLOAT|DBR_CTRL_FLOAT;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_FLOAT,pbuffer,&options,&nRequest);
|
||||
break;
|
||||
case(oldDBR_CTRL_ENUM):
|
||||
/* first get status and severity */
|
||||
options=DBR_STATUS;
|
||||
nRequest=0;
|
||||
status = dbGetField(paddr,DBR_ENUM,pbuffer,&options,&nRequest);
|
||||
adjust_severity(pbuffer);
|
||||
/* adjust pbuffer so it points to old severity and save it*/
|
||||
pbuffer += sizeof(short);
|
||||
severity = *((short *)pbuffer);
|
||||
/* now get enum strs */
|
||||
options=DBR_ENUM_STRS;
|
||||
nRequest=no_elements;
|
||||
status = dbGetField(paddr,DBR_ENUM,pbuffer,&options,&nRequest);
|
||||
/* no_str was returned as unsigned long. Convert and restore serv*/
|
||||
no_str = (short )(*((unsigned long*)pbuffer));
|
||||
*(((short *)pbuffer)++) = severity;
|
||||
*((short *)pbuffer) = no_str;
|
||||
break;
|
||||
default:
|
||||
return(-1);
|
||||
}
|
||||
if(!RTN_SUCCESS(status)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* the old software did not have a severity of INFO */
|
||||
static adjust_severity(pbuffer)
|
||||
struct dbr_ctrl_short *pbuffer;
|
||||
{
|
||||
if (pbuffer->severity > 0) pbuffer->severity--;
|
||||
}
|
||||
|
||||
/* DB_PUT_FIELD put a field and convert it to the desired type */
|
||||
|
||||
db_put_field(paddr,src_type,psrc,no_elements)
|
||||
struct dbAddr *paddr; /* where to put it */
|
||||
short src_type,no_elements;
|
||||
char *psrc; /* where to get it from */
|
||||
{
|
||||
long status;
|
||||
|
||||
|
||||
switch(src_type) {
|
||||
case(oldDBR_STRING):
|
||||
status = dbPutField(paddr,DBR_STRING,psrc,(long)no_elements);
|
||||
break;
|
||||
case(oldDBR_INT):
|
||||
status = dbPutField(paddr,DBR_SHORT,psrc,(long)no_elements);
|
||||
break;
|
||||
case(oldDBR_FLOAT):
|
||||
status = dbPutField(paddr,DBR_FLOAT,psrc,(long)no_elements);
|
||||
break;
|
||||
case(oldDBR_ENUM):
|
||||
status = dbPutField(paddr,DBR_ENUM,psrc,(long)no_elements);
|
||||
break;
|
||||
case(oldDBR_CTRL_INT):
|
||||
status = dbPutField(paddr,DBR_SHORT,
|
||||
&(((struct dbr_ctrl_short *)psrc)->value),(long)no_elements);
|
||||
break;
|
||||
case(oldDBR_CTRL_FLOAT):
|
||||
status = dbPutField(paddr,DBR_FLOAT,
|
||||
&(((struct dbr_ctrl_float *)psrc)->value),(long)no_elements);
|
||||
break;
|
||||
default:
|
||||
return(-1);
|
||||
}
|
||||
if(!RTN_SUCCESS(status)) return(-1);
|
||||
return(0);
|
||||
}
|
341
src/db/db_test.c
Normal file
341
src/db/db_test.c
Normal file
@ -0,0 +1,341 @@
|
||||
|
||||
/* db_test.c */
|
||||
/* share/src/db $Id$ */
|
||||
|
||||
/*
|
||||
*
|
||||
* database access subroutines
|
||||
*
|
||||
* Author: Bob Dalesio
|
||||
* Date: 4/15/88
|
||||
* @(#)iocdbaccess.c 1.1 9/22/88
|
||||
*
|
||||
* Control System Software for the GTA Project
|
||||
*
|
||||
* Copyright 1988, 1989, the Regents of the University of California.
|
||||
*
|
||||
* This software was produced under a U.S. Government contract
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
|
||||
* operated by the University of California for the U.S. Department
|
||||
* of Energy.
|
||||
*
|
||||
* Developed by the Controls and Automation Group (AT-8)
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Direct inqueries to:
|
||||
* Bob Dalesio, AT-8, Mail Stop H820
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
* Phone: (505) 667-3414
|
||||
* E-mail: dalesio@luke.lanl.gov
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
#include <db_access.h>
|
||||
|
||||
/*
|
||||
* TGF
|
||||
* Test get field
|
||||
*/
|
||||
char tgf_buffer[1200];
|
||||
#define MAX_ELEMS 250
|
||||
int tgf(name,index)
|
||||
char *name;
|
||||
register short index;
|
||||
{
|
||||
struct db_addr addr;
|
||||
struct db_addr *paddr = &addr;
|
||||
short number_elements;
|
||||
|
||||
/* convert name to database address */
|
||||
db_name_to_addr(name,&addr,index);
|
||||
|
||||
printf(" Record Type: %d\n",addr.record_type);
|
||||
printf("Record Address: 0x%x\n",addr.precord);
|
||||
printf(" Field Type: %d\n",addr.field_type);
|
||||
printf(" Field Address: 0x%x\n",addr.pfield);
|
||||
printf(" Field Size: %d\n",addr.field_size);
|
||||
printf(" No Elements: %d\n",addr.no_elements);
|
||||
printf(" Special: %d\n",addr.special);
|
||||
printf(" Choice Set: %d\n",addr.choice_set);
|
||||
number_elements =
|
||||
((addr.no_elements > MAX_ELEMS)?MAX_ELEMS:addr.no_elements);
|
||||
|
||||
/* failedfetch as each type */
|
||||
if (db_get_field(paddr,DBR_STRING,tgf_buffer,1) < 0)
|
||||
printf("DBR_STRING failed\n");
|
||||
else print_returned(DBR_STRING,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_INT,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_INT failed\n");
|
||||
else print_returned(DBR_INT,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_FLOAT,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_FLOAT failed\n");
|
||||
else print_returned(DBR_FLOAT,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_ENUM,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_ENUM failed\n");
|
||||
else print_returned(DBR_ENUM,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_STS_STRING,tgf_buffer,1) < 0)
|
||||
printf("DBR_STS_STRING failed\n");
|
||||
else print_returned(DBR_STS_STRING,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_STS_INT,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_STS_INT failed\n");
|
||||
else print_returned(DBR_STS_INT,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_STS_FLOAT,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_STS_FLOAT failed\n");
|
||||
else print_returned(DBR_STS_FLOAT,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_STS_ENUM,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_STS_ENUM failed\n");
|
||||
else print_returned(DBR_STS_ENUM,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_GR_INT,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_GR_INT failed\n");
|
||||
else print_returned(DBR_GR_INT,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_GR_FLOAT,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_GR_FLOAT failed\n");
|
||||
else print_returned(DBR_GR_FLOAT,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_CTRL_INT,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_CTRL_INT failed\n");
|
||||
else print_returned(DBR_CTRL_INT,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_CTRL_FLOAT,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_CTRL_FLOAT failed\n");
|
||||
else print_returned(DBR_CTRL_FLOAT,tgf_buffer,number_elements);
|
||||
if (db_get_field(paddr,DBR_CTRL_ENUM,tgf_buffer,number_elements) < 0)
|
||||
printf("DBR_CTRL_ENUM failed\n");
|
||||
else print_returned(DBR_CTRL_ENUM,tgf_buffer,number_elements);
|
||||
printf("\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* TPF
|
||||
* Test put field
|
||||
*/
|
||||
int tpf(pname,pvalue,index)
|
||||
char *pname;
|
||||
char *pvalue;
|
||||
register short index;
|
||||
{
|
||||
struct db_addr addr;
|
||||
struct db_addr *paddr = &addr;
|
||||
char buffer[500];
|
||||
struct dbr_ctrl_enum test_enum;
|
||||
register short i;
|
||||
short shortvalue;
|
||||
long longvalue;
|
||||
float floatvalue;
|
||||
unsigned char charvalue;
|
||||
double doublevalue;
|
||||
|
||||
if (((*pname < ' ') || (*pname > 'z'))
|
||||
|| ((*pvalue < ' ') || (*pvalue > 'z'))){
|
||||
printf("\nusage \"pv name\",\"value\"\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* convert name to database address */
|
||||
db_name_to_addr(pname,&addr,index);
|
||||
printf(" Record Type: %d\n",addr.record_type);
|
||||
printf("Record Address: 0x%x\n",addr.precord);
|
||||
printf(" Field Type: %d\n",addr.field_type);
|
||||
printf(" Field Address: 0x%x\n",addr.pfield);
|
||||
printf(" Field Size: %d\n",addr.field_size);
|
||||
printf(" No Elements: %d\n",addr.no_elements);
|
||||
printf(" Special: %d\n",addr.special);
|
||||
printf(" Choice Set: %d\n",addr.choice_set);
|
||||
if (db_put_field(paddr,DBR_STRING,pvalue,1) < 0) printf(" failed\n");
|
||||
if (db_get_field(paddr,DBR_STRING,buffer,1) < 0) printf("failed\n");
|
||||
else print_returned(DBR_STRING,buffer,1);
|
||||
if(addr.field_type<=DBF_STRING || addr.field_type>=DBF_NO_ACCESS)return(0);
|
||||
if(sscanf(pvalue,"%hd",&shortvalue)==1) {
|
||||
if (db_put_field(paddr,DBR_INT,&shortvalue,1) < 0) printf(" INT failed\n");
|
||||
if (db_get_field(paddr,DBR_INT,buffer,1) < 0) printf("INT GET failed\n");
|
||||
else print_returned(DBR_INT,buffer,1);
|
||||
}
|
||||
if(sscanf(pvalue,"%f",&floatvalue)==1) {
|
||||
if (db_put_field(paddr,DBR_FLOAT,&floatvalue,1) < 0) printf("FLOAT failed\n");
|
||||
if (db_get_field(paddr,DBR_FLOAT,buffer,1) < 0) printf("FLOAT GET failed\n");
|
||||
else print_returned(DBR_FLOAT,buffer,1);
|
||||
}
|
||||
if(sscanf(pvalue,"%hu",&shortvalue)==1) {
|
||||
if (db_put_field(paddr,DBR_ENUM,&shortvalue,1) < 0) printf("ENUM failed\n");
|
||||
if (db_get_field(paddr,DBR_ENUM,buffer,1) < 0) printf("ENUM GET failed\n");
|
||||
else print_returned(DBR_ENUM,buffer,1);
|
||||
}
|
||||
printf("\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* PRINT_RETURNED
|
||||
*
|
||||
* print out the values in a database access interface structure
|
||||
*/
|
||||
static print_returned(type,pbuffer,count)
|
||||
register short type;
|
||||
register char *pbuffer;
|
||||
short count;
|
||||
{
|
||||
register short i;
|
||||
|
||||
switch(type){
|
||||
case (DBR_STRING):
|
||||
printf("DBR_STRING: %s",pbuffer);
|
||||
break;
|
||||
case (DBR_INT):
|
||||
{
|
||||
register short *pvalue = (short *)pbuffer;
|
||||
printf("DBR_INT: ");
|
||||
for (i = 0; i < count; i++,pvalue++){
|
||||
printf("%d ",*(short *)pvalue);
|
||||
if ((i % 16) == 15) printf("\t\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DBR_FLOAT):
|
||||
{
|
||||
register float *pvalue = (float *)pbuffer;
|
||||
printf("DBR_FLOAT: ");
|
||||
for (i = 0; i < count; i++,pvalue++){
|
||||
printf("%6.4f ",*(float *)pvalue);
|
||||
if ((i % 16) == 15) printf("\n\t");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DBR_ENUM):
|
||||
{
|
||||
register short *pvalue = (short *)pbuffer;
|
||||
printf("DBR_ENUM: %d",*pvalue);
|
||||
break;
|
||||
}
|
||||
case (DBR_STS_STRING):
|
||||
{
|
||||
register struct dbr_sts_string *pvalue
|
||||
= (struct dbr_sts_string *) pbuffer;
|
||||
printf("DBR_STS_STRING %2d %2d",pvalue->status,pvalue->severity);
|
||||
printf("\tValue: %s",pvalue->value);
|
||||
break;
|
||||
}
|
||||
case (DBR_STS_INT):
|
||||
{
|
||||
register struct dbr_sts_int *pvalue
|
||||
= (struct dbr_sts_int *)pbuffer;
|
||||
register short *pshort = &pvalue->value;
|
||||
printf("DBR_STS_INT %2d %2d",pvalue->status,pvalue->severity);
|
||||
printf("\tValue: ");
|
||||
for (i = 0; i < count; i++,pshort++){
|
||||
printf("%d ",*pshort);
|
||||
if ((i % 16) == 15) printf("\n\t");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DBR_STS_FLOAT):
|
||||
{
|
||||
register struct dbr_sts_float *pvalue
|
||||
= (struct dbr_sts_float *)pbuffer;
|
||||
register float *pfloat = &pvalue->value;
|
||||
printf("DBR_STS_FLOAT %2d %2d",pvalue->status,pvalue->severity);
|
||||
printf("\tValue: ");
|
||||
for (i = 0; i < count; i++,pfloat++){
|
||||
printf("%6.4f ",*pfloat);
|
||||
if ((i % 16) == 15) printf("\n\t");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DBR_STS_ENUM):
|
||||
{
|
||||
register struct dbr_sts_enum *pvalue
|
||||
= (struct dbr_sts_enum *)pbuffer;
|
||||
printf("DBR_STS_ENUM %2d %2d",pvalue->status,pvalue->severity);
|
||||
printf("\tValue: %d",pvalue->value);
|
||||
break;
|
||||
}
|
||||
case (DBR_GR_INT):
|
||||
{
|
||||
register struct dbr_gr_int *pvalue
|
||||
= (struct dbr_gr_int *)pbuffer;
|
||||
register short *pshort = &pvalue->value;
|
||||
printf("DBR_GR_INT %2d %2d",pvalue->status,pvalue->severity);
|
||||
printf(" %.8s %6d %6d %6d %6d %6d %6d",pvalue->units,
|
||||
pvalue->upper_disp_limit,pvalue->lower_disp_limit,
|
||||
pvalue->upper_alarm_limit,pvalue->upper_warning_limit,
|
||||
pvalue->lower_warning_limit,pvalue->lower_alarm_limit);
|
||||
printf("\nValue:\t");
|
||||
for (i = 0; i < count; i++,pshort++){
|
||||
printf("%d ",*pshort);
|
||||
if ((i % 16) == 15) printf("\n\t");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DBR_GR_FLOAT):
|
||||
{
|
||||
register struct dbr_gr_float *pvalue
|
||||
= (struct dbr_gr_float *)pbuffer;
|
||||
register float *pfloat = &pvalue->value;
|
||||
printf("DBR_GR_FLOAT%2d %2d",pvalue->status,pvalue->severity);
|
||||
printf(" %3d %.8s\n\t%6.4f %6.4f %6.4f %6.4f %6.4f %6.4f",
|
||||
pvalue->precision, pvalue->units,
|
||||
pvalue->upper_disp_limit,pvalue->lower_disp_limit,
|
||||
pvalue->upper_alarm_limit,pvalue->upper_warning_limit,
|
||||
pvalue->lower_warning_limit,pvalue->lower_alarm_limit);
|
||||
printf("\nValue\t");
|
||||
for (i = 0; i < count; i++,pfloat++){
|
||||
printf("%6.4f ",*pfloat);
|
||||
if ((i % 16) == 15) printf("\n\t");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DBR_CTRL_INT):
|
||||
{
|
||||
register struct dbr_ctrl_int *pvalue
|
||||
= (struct dbr_ctrl_int *)pbuffer;
|
||||
register short *pshort = &pvalue->value;
|
||||
printf("DBR_CTRL_INT %2d %2d",pvalue->status,pvalue->severity);
|
||||
printf(" %.8s\n\t%6d %6d %6d %6d %6d %6d",pvalue->units,
|
||||
pvalue->upper_disp_limit,pvalue->lower_disp_limit,
|
||||
pvalue->upper_alarm_limit,pvalue->upper_warning_limit,
|
||||
pvalue->lower_warning_limit,pvalue->lower_alarm_limit);
|
||||
printf(" %6d %6d",
|
||||
pvalue->upper_ctrl_limit,pvalue->lower_ctrl_limit);
|
||||
printf("\n\t");
|
||||
for (i = 0; i < count; i++,pshort++){
|
||||
printf("%d ",*pshort);
|
||||
if ((i % 16) == 15) printf("\n\t");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DBR_CTRL_FLOAT):
|
||||
{
|
||||
register struct dbr_ctrl_float *pvalue
|
||||
= (struct dbr_ctrl_float *)pbuffer;
|
||||
register float *pfloat = &pvalue->value;
|
||||
printf("DBR_CTRL_FLOAT %2d %2d",pvalue->status,pvalue->severity);
|
||||
printf(" %3d %.8s\n\t%6.4f %6.4f %6.4f %6.4f %6.4f %6.4f",
|
||||
pvalue->precision, pvalue->units,
|
||||
pvalue->upper_disp_limit,pvalue->lower_disp_limit,
|
||||
pvalue->upper_alarm_limit,pvalue->upper_warning_limit,
|
||||
pvalue->lower_warning_limit,pvalue->lower_alarm_limit);
|
||||
printf(" %6.4f %6.4f",
|
||||
pvalue->upper_ctrl_limit,pvalue->lower_ctrl_limit);
|
||||
printf("\n\t");
|
||||
for (i = 0; i < count; i++,pfloat++){
|
||||
printf("%6.4f ",*pfloat);
|
||||
if ((i % 16) == 15) printf("\n\t");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DBR_CTRL_ENUM):
|
||||
{
|
||||
register struct dbr_ctrl_enum *pvalue
|
||||
= (struct dbr_ctrl_enum *)pbuffer;
|
||||
printf("DBR_GR_ENUM%2d %2d",pvalue->status,pvalue->severity);
|
||||
printf("\n\t%3d",pvalue->no_str);
|
||||
for (i = 0; i < pvalue->no_str; i++)
|
||||
printf("\n\t%.26s",pvalue->strs[i]);
|
||||
printf("Value: %d",pvalue->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
1055
src/db/dbls.c
Normal file
1055
src/db/dbls.c
Normal file
File diff suppressed because it is too large
Load Diff
398
src/db/iocInit.c
Normal file
398
src/db/iocInit.c
Normal file
@ -0,0 +1,398 @@
|
||||
|
||||
/* iocInit.c ioc initialization */
|
||||
/* share/src/db $Id$ */
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
#include <lstLib.h>
|
||||
#include <memLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <symLib.h>
|
||||
#include <sysSymTbl.h> /* for sysSymTbl*/
|
||||
#include <a_out.h> /* for N_TEXT */
|
||||
#include <stdioLib.h>
|
||||
#include <strLib.h>
|
||||
|
||||
#include <fast_lock.h>
|
||||
#include <choice.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbCommon.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <dbRecDes.h>
|
||||
#include <dbRecType.h>
|
||||
#include <dbRecords.h>
|
||||
#include <devSup.h>
|
||||
#include <drvSup.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
|
||||
static initialized=FALSE;
|
||||
|
||||
|
||||
/* define forward references*/
|
||||
long initBusController();
|
||||
long sdrLoad();
|
||||
long initDrvSup();
|
||||
long initDevSup();
|
||||
long initRecSup();
|
||||
long initDatabase();
|
||||
long addToSet();
|
||||
|
||||
|
||||
iocInit(pfilename)
|
||||
char * pfilename;
|
||||
{
|
||||
long status;
|
||||
|
||||
if(initialized) {
|
||||
logMsg("iocInit can only be called once\n");
|
||||
return(-1);
|
||||
}
|
||||
initialized = TRUE;
|
||||
if(status=initBusController()) {
|
||||
logMsg("iocInit aborting because initBusController failed\n");
|
||||
return(-1);
|
||||
}
|
||||
if(status=sdrLoad(pfilename)) {
|
||||
logMsg("iocInit aborting because sdrLoad failed\n");
|
||||
return(-1);
|
||||
}
|
||||
logMsg("sdrLoad completed\n");
|
||||
/* enable interrupt level 5 */
|
||||
sysIntEnable(5);
|
||||
if(initDrvSup()==0) logMsg("Drivers Initialized\n");
|
||||
if(initDevSup()==0) logMsg("Device Support Initialized\n");
|
||||
if(initRecSup()==0) logMsg("Record Support Initialized\n");
|
||||
if(initDatabase()==0) logMsg("Database Initialized\n");
|
||||
scan_init();
|
||||
logMsg("Scanners Initialized\n");
|
||||
rsrv_init();
|
||||
logMsg("Channel Access Servers Initialized\n");
|
||||
logMsg("iocInit: All initialization complete\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
#include <module_types.h>
|
||||
|
||||
long initBusController(){ /*static */
|
||||
char ctemp;
|
||||
|
||||
/* initialize the Xycom SRM010 bus controller card */
|
||||
ctemp = XY_LED;
|
||||
if (vxMemProbe(SRM010_ADDR, WRITE,1,&ctemp) == -1) {
|
||||
logMsg("Xycom SRM010 Bus Controller Not Present\n");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long initDrvSup() /* Locate all driver support entry tables */
|
||||
{
|
||||
char *pname;
|
||||
char name[40];
|
||||
int i;
|
||||
UTINY type;
|
||||
char message[100];
|
||||
long status;
|
||||
long rtnval=0;
|
||||
|
||||
if(!drvSup) {
|
||||
status = S_drv_noDrvSup;
|
||||
errMessage(status,"drvSup is NULL, i.e. No device drivers are defined");
|
||||
return(status);
|
||||
}
|
||||
for(i=0; i< (drvSup->number); i++) {
|
||||
if(!(pname = drvSup->drvetName[i])) continue;
|
||||
strcpy(name,"_");
|
||||
strcat(name,pname);
|
||||
rtnval = symFindByName(sysSymTbl,name,&(drvSup->papDrvet[i]),&type);
|
||||
if( rtnval!=OK || ( type&N_TEXT == 0) ) {
|
||||
strcpy(message,"driver entry table not found for ");
|
||||
strcat(message,pname);
|
||||
status = S_drv_noDrvet;
|
||||
errMessage(-1L,message);
|
||||
if(rtnval==OK) rtnval=status;
|
||||
continue;
|
||||
}
|
||||
status = (*(drvSup->papDrvet[i]->init))();
|
||||
if(rtnval==OK) rtnval=status;
|
||||
}
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
static long initDevSup() /* Locate all device support entry tables */
|
||||
{
|
||||
char *pname;
|
||||
char name[40];
|
||||
int i,j;
|
||||
UTINY type;
|
||||
char message[100];
|
||||
struct devSup *pdevSup;
|
||||
long status;
|
||||
long rtnval=0; /*rtnval will be 0 or first error found*/
|
||||
|
||||
if(!devSup) {
|
||||
status = S_dev_noDevSup;
|
||||
errMessage(status,"devSup is NULL, i.e. No device support is defined");
|
||||
return(status);
|
||||
}
|
||||
for(i=0; i< (devSup->number); i++) {
|
||||
if((pdevSup = devSup->papDevSup[i]) == NULL) continue;
|
||||
for(j=0; j < (pdevSup->number); j++) {
|
||||
if(!(pname = pdevSup->dsetName[j])) continue;
|
||||
strcpy(name,"_");
|
||||
strcat(name,pname);
|
||||
rtnval = (long)symFindByName(sysSymTbl,name,
|
||||
&(pdevSup->papDset[j]),&type);
|
||||
if( rtnval!=OK || ( type&N_TEXT == 0) ) {
|
||||
strcpy(message,"device support entry table not found for ");
|
||||
strcat(message,pname);
|
||||
status = S_dev_noDSET;
|
||||
errMessage(-1L,message);
|
||||
if(rtnval==OK)rtnval=status;
|
||||
continue;
|
||||
}
|
||||
if(!(pdevSup->papDset[j]->init)) continue;
|
||||
status = (*(pdevSup->papDset[j]->init))();
|
||||
if(rtnval==OK)rtnval=status;
|
||||
}
|
||||
}
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
static long initRecSup()
|
||||
{
|
||||
char name[40];
|
||||
int i;
|
||||
UTINY type;
|
||||
char message[100];
|
||||
long status;
|
||||
long rtnval=0; /*rtnval will be 0 or first error found*/
|
||||
int nbytes;
|
||||
|
||||
if(!dbRecType) {
|
||||
status = S_rectype_noRecs;
|
||||
errMessage(status,"dbRecType is NULL, i.e. no record types defined");
|
||||
return(status);
|
||||
}
|
||||
nbytes = sizeof(struct recSup) + dbRecType->number*sizeof(caddr_t);
|
||||
recSup = (struct recSup *)calloc(1,nbytes);
|
||||
recSup->number = dbRecType->number;
|
||||
(long)recSup->papRset = (long)recSup + (long)sizeof(struct recSup);
|
||||
for(i=0; i< (recSup->number); i++) {
|
||||
if(dbRecType->papName[i] == NULL)continue;
|
||||
strcpy(name,"_");
|
||||
strcat(name,dbRecType->papName[i]);
|
||||
strcat(name,"RSET");
|
||||
rtnval = symFindByName(sysSymTbl,name,&(recSup->papRset[i]),&type);
|
||||
if( rtnval!=OK || ( type&N_TEXT == 0) ) {
|
||||
strcpy(message,"record support entry table not found for ");
|
||||
strcat(message,name);
|
||||
status = S_rec_noRSET;
|
||||
errMessage(-1L,message);
|
||||
if(rtnval==OK)rtnval=status;
|
||||
continue;
|
||||
}
|
||||
if(!(recSup->papRset[i]->init)) continue;
|
||||
else {
|
||||
status = (*(recSup->papRset[i]->init))();
|
||||
if(rtnval==OK)rtnval=status;
|
||||
}
|
||||
}
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
static long initDatabase()
|
||||
{
|
||||
char name[PVNAME_SZ+FLDNAME_SZ+1];
|
||||
short i,j,k;
|
||||
char message[120];
|
||||
long status;
|
||||
long rtnval=0; /*rtnval will be 0 or first error found*/
|
||||
short nset=0;
|
||||
short lookAhead;
|
||||
struct recLoc *precLoc;
|
||||
struct rset *prset;
|
||||
struct devSup *pdevSup;
|
||||
struct recTypDes *precTypDes;
|
||||
struct fldDes *pfldDes;
|
||||
struct dbCommon *precord;
|
||||
struct dbAddr dbAddr;
|
||||
struct link *plink;
|
||||
|
||||
if(!dbRecords) {
|
||||
status = S_record_noRecords;
|
||||
errMessage(status,"No database records are defined");
|
||||
return(status);
|
||||
}
|
||||
for(i=0; i< (dbRecords->number); i++) {
|
||||
if(!(precLoc = dbRecords->papRecLoc[i]))continue;
|
||||
if(!(prset=GET_PRSET(i))) {
|
||||
strcpy(name,dbRecType->papName[i]);
|
||||
strcat(name,"RSET");
|
||||
strcpy(message,"record support entry table not found for ");
|
||||
strcat(message,name);
|
||||
status = S_rec_noRSET;
|
||||
errMessage(-1L,message);
|
||||
if(rtnval==OK) rtnval = status;
|
||||
continue;
|
||||
}
|
||||
pdevSup=GET_DEVSUP(i); /* pdevSup may be NULL */
|
||||
precTypDes = dbRecDes->papRecTypDes[i];
|
||||
for(j=0, ((char *)precord) = precLoc->pFirst;
|
||||
j<precLoc->no_records;
|
||||
j++, ((char *)precord) += precLoc->rec_size ) {
|
||||
/* If NAME is null then skip this record*/
|
||||
if(!(precord->name[0])) continue;
|
||||
|
||||
/* initialize mlok and mlis*/
|
||||
FASTLOCKINIT(&precord->mlok);
|
||||
lstInit(&(precord->mlis));
|
||||
precord->pact=FALSE;
|
||||
|
||||
/* set lset=0 See determine lock set below.*/
|
||||
precord->lset = 0;
|
||||
|
||||
/* Init DSET NOTE that result may be NULL*/
|
||||
precord->dset=(struct dset *)GET_PDSET(pdevSup,precord->dtyp);
|
||||
|
||||
/* Convert all PV_LINKs to DB_LINKs or CA_LINKs*/
|
||||
for(k=0; k<precTypDes->no_links; k++) {
|
||||
pfldDes = precTypDes->papFldDes[precTypDes->link_ind[k]];
|
||||
plink = (struct link *)((char *)precord + pfldDes->offset);
|
||||
if(plink->type == PV_LINK) {
|
||||
strncpy(name,plink->value.pv_link.pvname,PVNAME_SZ);
|
||||
strcat(name,".");
|
||||
strncat(name,plink->value.pv_link.fldname,FLDNAME_SZ);
|
||||
if(dbNameToAddr(name,&dbAddr) == 0) {
|
||||
plink->type = DB_LINK;
|
||||
plink->value.db_link.paddr =
|
||||
(caddr_t)calloc(1,sizeof(struct dbAddr));
|
||||
*((struct dbAddr *)(plink->value.db_link.paddr))=dbAddr;
|
||||
/* show that refered to record has link. */
|
||||
/* See determine lock set below.*/
|
||||
((struct dbCommon *)(dbAddr.precord))->lset = -1;
|
||||
}
|
||||
else {
|
||||
/*This will be replaced by channel access call*/
|
||||
strncpy(message,precord->name,PVNAME_SZ);
|
||||
strcat(message,".");
|
||||
strncat(message,pfldDes->fldname,FLDNAME_SZ);
|
||||
strcat(message,": link process variable =");
|
||||
strcat(message,name);
|
||||
strcat(message," not found");
|
||||
status = S_db_notFound;
|
||||
errMessage(-1L,message);
|
||||
if(rtnval==OK) rtnval=status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* call record support init_record routine */
|
||||
if(!(recSup->papRset[i]->init_record)) continue;
|
||||
status = (*(recSup->papRset[i]->init_record))(precord);
|
||||
if(rtnval==OK)rtnval=status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now determine lock sets*/
|
||||
/* When each record is examined lset has one of the following values
|
||||
* -1 Record is not in a set and at least one following record refers
|
||||
* to this record
|
||||
* 0 record is not in a set and no following records refer to it.
|
||||
* >0 Record is already in a set
|
||||
*/
|
||||
for(i=0; i<dbRecords->number; i++) {
|
||||
if(!(precLoc = dbRecords->papRecLoc[i]))continue;
|
||||
precTypDes = dbRecDes->papRecTypDes[i];
|
||||
for(j=0, ((char *)precord) = precLoc->pFirst;
|
||||
j<precLoc->no_records;
|
||||
j++, ((char *)precord) += precLoc->rec_size ) {
|
||||
/* If NAME is null then skip this record*/
|
||||
if(!(precord->name[0])) continue;
|
||||
if(precord->lset > 0) continue; /*already in a lock set */
|
||||
lookAhead = ( (precord->lset == -1) ? TRUE : FALSE);
|
||||
nset++;
|
||||
status = addToSet(precord,i,lookAhead,i,j,nset);
|
||||
if(status) return(status);
|
||||
}
|
||||
}
|
||||
dbScanLockInit(nset);
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
static long addToSet(precord,record_type,lookAhead,i,j,lset)
|
||||
struct dbCommon *precord; /* record being added to lock set*/
|
||||
short record_type; /* record being added to lock set*/
|
||||
short lookAhead; /*should following records be checked*/
|
||||
short i; /*record before 1st following: index into papRecLoc*/
|
||||
short j; /*record before 1st following: record number */
|
||||
short lset; /* current lock set */
|
||||
{
|
||||
short k,in,itemp,jn,j1st;
|
||||
long status;
|
||||
struct fldDes *pfldDes;
|
||||
struct link *plink;
|
||||
struct dbCommon *ptemp;
|
||||
struct dbCommon *ptemp1;
|
||||
struct recTypDes *precTypDes;
|
||||
struct recLoc *precLoc;
|
||||
|
||||
|
||||
if(precord->lset = -1) precord->lset=0;
|
||||
if(precord->lset != 0) {
|
||||
if(precord->lset == lset) return(0);
|
||||
status = S_db_lsetLogic;
|
||||
errMessage(status,"Logic Error in iocInit(addToSet)");
|
||||
return(status);
|
||||
}
|
||||
precord->lset = lset;
|
||||
/* add all DB_LINKs in this record to the set */
|
||||
precTypDes = dbRecDes->papRecTypDes[record_type];
|
||||
for(k=0; k<precTypDes->no_links; k++) {
|
||||
pfldDes = precTypDes->papFldDes[precTypDes->link_ind[k]];
|
||||
plink = (struct link *)((char *)precord + pfldDes->offset);
|
||||
if(plink->type != DB_LINK) continue;
|
||||
status = addToSet(
|
||||
((struct dbAddr *)(plink->value.db_link.paddr))->precord,
|
||||
((struct dbAddr *)(plink->value.db_link.paddr))->record_type,
|
||||
TRUE,i,j,lset);
|
||||
if(status) return(status);
|
||||
}
|
||||
/* Now look for all later records that refer to this record*/
|
||||
/* remember that all earlier records already have lock set determined*/
|
||||
if(!lookAhead) return(0);
|
||||
j1st=j+1;
|
||||
for(in=i; in<dbRecords->number; in++) {
|
||||
if(!(precLoc = dbRecords->papRecLoc[in])) continue;
|
||||
precTypDes = dbRecDes->papRecTypDes[in];
|
||||
for(jn=j1st,
|
||||
(char *)ptemp= (char *)(precLoc->pFirst) + jn*(precLoc->rec_size);
|
||||
jn<precLoc->no_records;
|
||||
jn++, ((char *)ptemp) += precLoc->rec_size) {
|
||||
/* If NAME is null then skip this record*/
|
||||
if(!(ptemp->name[0])) continue;
|
||||
for(k=0; k<precTypDes->no_links; k++) {
|
||||
pfldDes = precTypDes->papFldDes[precTypDes->link_ind[k]];
|
||||
plink = (struct link *)((char *)ptemp + pfldDes->offset);
|
||||
if(plink->type != DB_LINK) continue;
|
||||
ptemp1 = (struct dbCommon *)
|
||||
(((struct dbAddr *)(plink->value.db_link.paddr))->precord);
|
||||
if(ptemp1 != precord) continue;
|
||||
if(ptemp->lset != 0) {
|
||||
if(ptemp->lset == lset) continue;
|
||||
status = S_db_lsetLogic;
|
||||
errMessage(status,"Logic Error in iocInit(addToSet)");
|
||||
return(status);
|
||||
}
|
||||
itemp = ((struct dbAddr *)(plink->value.db_link.paddr))->record_type;
|
||||
status = addToSet(ptemp1,itemp,TRUE,i,j,lset);
|
||||
if(status) return(status);
|
||||
}
|
||||
}
|
||||
j1st = 0;
|
||||
}
|
||||
return(0);
|
||||
}
|
350
src/db/recGbl.c
Normal file
350
src/db/recGbl.c
Normal file
@ -0,0 +1,350 @@
|
||||
/* recGbl.c - Global record processing routines */
|
||||
/* share/src/db $Id$ */
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
#include <stdioLib.h>
|
||||
#include <strLib.h>
|
||||
|
||||
#include <choice.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbRecType.h>
|
||||
#include <dbRecDes.h>
|
||||
#include <link.h>
|
||||
#include <devSup.h>
|
||||
#include <dbCommon.h>
|
||||
|
||||
/***********************************************************************
|
||||
* The following are the global record processing rouitines
|
||||
*
|
||||
*void recGblDbaddrError(status,paddr,pcaller_name)
|
||||
* long status;
|
||||
* struct dbAddr *paddr;
|
||||
* char *pcaller_name; * calling routine name *
|
||||
*
|
||||
*void recGblRecordError(status,precord,pcaller_name)
|
||||
* long status;
|
||||
* caddr_t precord; * addr of record *
|
||||
* char *pcaller_name; * calling routine name *
|
||||
*
|
||||
*void recGblRecSupError(status,paddr,pcaller_name,psupport_name)
|
||||
* long status;
|
||||
* struct dbAddr *paddr;
|
||||
* char *pcaller_name; * calling routine name *
|
||||
* char *psupport_name; * support routine name *
|
||||
*
|
||||
* int recGblGetTypeIndex(prec_name,ptypeIndex)
|
||||
* char *prec_name;
|
||||
* int *ptypeIndex;
|
||||
*
|
||||
* int recGblReportDbCommon(fp,paddr))
|
||||
* FILE *fp;
|
||||
* struct dbAddr *paddr;
|
||||
*
|
||||
* int recGblReportLink(fp,pfield_name,plink)
|
||||
* FILE *fp;
|
||||
* char *pfield_name;
|
||||
* struct link *plink;
|
||||
*
|
||||
* int recGblReportCvtChoice(fp,pfield_name,choice_value)
|
||||
* FILE *fp;
|
||||
* char *pfield_name;
|
||||
* unsigned short choice_value;
|
||||
*
|
||||
* int recGblReportGblChoice(fp,precord,pfield_name,choice_value)
|
||||
* FILE *fp;
|
||||
* struct dbCommon *precord;
|
||||
* char *pfield_name;
|
||||
* unsigned short choice_value;
|
||||
*
|
||||
* int recGblReportRecChoice(fp,precord,pfield_name,choice_value)
|
||||
* FILE *fp;
|
||||
* struct dbCommon *precord;
|
||||
* char *pfield_name;
|
||||
* unsigned short choice_value;
|
||||
**************************************************************************/
|
||||
|
||||
recGblDbaddrError(status,paddr,pcaller_name)
|
||||
long status;
|
||||
struct dbAddr *paddr;
|
||||
char *pcaller_name; /* calling routine name*/
|
||||
{
|
||||
char buffer[200];
|
||||
struct dbCommon *precord;
|
||||
int i,n;
|
||||
struct fldDes *pfldDes=(struct fldDes *)(paddr->pfldDes);
|
||||
|
||||
buffer[0]=0;
|
||||
if(paddr) { /* print process variable name */
|
||||
precord=(struct dbCommon *)(paddr->precord);
|
||||
strcat(buffer,"PV: ");
|
||||
strncat(buffer,precord->name,PVNAME_SZ);
|
||||
n=strlen(buffer);
|
||||
for(i=n; (i>0 && buffer[i]==' '); i--) buffer[i]=0;
|
||||
strcat(buffer,".");
|
||||
strncat(buffer,pfldDes->fldname,FLDNAME_SZ);
|
||||
strcat(buffer," ");
|
||||
}
|
||||
if(pcaller_name) {
|
||||
strcat(buffer,"error detected in routine: ");
|
||||
strcat(buffer,pcaller_name);
|
||||
}
|
||||
errMessage(status,buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
recGblRecordError(status,precord,pcaller_name)
|
||||
long status;
|
||||
struct dbCommon *precord;
|
||||
char *pcaller_name; /* calling routine name*/
|
||||
{
|
||||
char buffer[200];
|
||||
int i,n;
|
||||
|
||||
buffer[0]=0;
|
||||
if(precord) { /* print process variable name */
|
||||
strcat(buffer,"PV: ");
|
||||
strncat(buffer,precord->name,PVNAME_SZ);
|
||||
n=strlen(buffer);
|
||||
for(i=n; (i>0 && buffer[i]==' '); i--) buffer[i]=0;
|
||||
strcat(buffer," ");
|
||||
}
|
||||
if(pcaller_name) {
|
||||
strcat(buffer,"error detected in routine: ");
|
||||
strcat(buffer,pcaller_name);
|
||||
}
|
||||
errMessage(status,buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
recGblRecSupError(status,paddr,pcaller_name,psupport_name)
|
||||
long status;
|
||||
struct dbAddr *paddr;
|
||||
char *pcaller_name;
|
||||
char *psupport_name;
|
||||
{
|
||||
char buffer[200];
|
||||
char *pstr;
|
||||
struct dbCommon *precord;
|
||||
int i,n;
|
||||
struct fldDes *pfldDes=(struct fldDes *)(paddr->pfldDes);
|
||||
|
||||
buffer[0]=0;
|
||||
strcat(buffer,"Record Support Routine (");
|
||||
if(psupport_name)
|
||||
strcat(buffer,psupport_name);
|
||||
else
|
||||
strcat(buffer,"Unknown");
|
||||
strcat(buffer,") not available.\nRecord Type is ");
|
||||
if(pstr=GET_PRECTYPE(paddr->record_type))
|
||||
strcat(buffer,pstr);
|
||||
else
|
||||
strcat(buffer,"BAD");
|
||||
if(paddr) { /* print process variable name */
|
||||
precord=(struct dbCommon *)(paddr->precord);
|
||||
strcat(buffer,", PV is ");
|
||||
strncat(buffer,precord->name,PVNAME_SZ);
|
||||
n=strlen(buffer);
|
||||
for(i=n; (i>0 && buffer[i]==' '); i--) buffer[i]=0;
|
||||
strcat(buffer,".");
|
||||
strncat(buffer,pfldDes->fldname,FLDNAME_SZ);
|
||||
strcat(buffer," ");
|
||||
}
|
||||
if(pcaller_name) {
|
||||
strcat(buffer,"\nerror detected in routine: ");
|
||||
strcat(buffer,pcaller_name);
|
||||
}
|
||||
errMessage(status,buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
int recGblGetTypeIndex(prec_name,ptypeIndex)
|
||||
char *prec_name;
|
||||
int *ptypeIndex;
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < dbRecType->number; i++) {
|
||||
if(!(dbRecType->papName[i])) continue;
|
||||
if(strcmp(dbRecType->papName[i],prec_name) == 0) {
|
||||
*ptypeIndex = i;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int recGblReportDbCommon(fp,paddr)
|
||||
FILE *fp;
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct dbCommon *precord=(struct dbCommon *)(paddr->precord);
|
||||
struct devSup *pdevSup;
|
||||
|
||||
if(fprintf(fp,"NAME %-28s\nDESC %-28s\n",precord->name,precord->desc)<0)
|
||||
return(-1);
|
||||
if(recGblReportGblChoice(fp,precord,"SCAN",precord->scan)) return(-1);
|
||||
if(fprintf(fp,"PHAS %d\tEVNT %d\n",
|
||||
precord->phas,precord->evnt)<0) return(-1);
|
||||
if(fprintf(fp,"STAT %d\tSEVR %d\nDTYP %5d\n",
|
||||
precord->stat,precord->sevr,precord->dtyp)<0) return(-1);
|
||||
if(precord->dset != NULL) {
|
||||
if(!(pdevSup=GET_DEVSUP(paddr->record_type))) return(-1);
|
||||
if(fprintf(fp,"DSET %s\n",(pdevSup->dsetName[precord->dtyp]))<0)
|
||||
return(-1);
|
||||
}
|
||||
if(recGblReportLink(fp,"SDIS",&(precord->sdis))) return(-1);
|
||||
if(fprintf(fp,"DISA %d\tPACT %d\t",precord->disa,precord->pact)<0)
|
||||
return(-1);
|
||||
if(fprintf(fp,"LSET %d\n",precord->lset)<0) return(-1);
|
||||
if(fprintf(fp,"ESEC 0x%lx\tNSEC 0x%lx\n",precord->esec,precord->nsec)<0)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int recGblReportLink(fp,pfield_name,plink)
|
||||
FILE *fp;
|
||||
char *pfield_name;
|
||||
struct link *plink;
|
||||
{
|
||||
switch(plink->type) {
|
||||
case CONSTANT:
|
||||
if(fprintf(fp,"%4s %12.4G\n",
|
||||
pfield_name,
|
||||
plink->value.value)<0) return(-1);
|
||||
break;
|
||||
case PV_LINK:
|
||||
if(fprintf(fp,"%4s %28s.%4s\n",
|
||||
pfield_name,
|
||||
plink->value.pv_link.pvname,
|
||||
plink->value.pv_link.fldname)<0) return(-1);
|
||||
break;
|
||||
case VME_IO:
|
||||
if(fprintf(fp,"%4s VME: card=%2d signal=%2d\n",
|
||||
pfield_name,
|
||||
plink->value.vmeio.card,plink->value.vmeio.card)<0) return(-1);
|
||||
break;
|
||||
case CAMAC_IO:
|
||||
if(fprintf(fp,
|
||||
"%4s CAMAC: branch=%2d crate=%2d slot=%2d channel=%2d\n",
|
||||
pfield_name,
|
||||
plink->value.camacio.branch,plink->value.camacio.crate,
|
||||
plink->value.camacio.slot,plink->value.camacio.channel)<0)
|
||||
return(-1);
|
||||
break;
|
||||
case AB_IO:
|
||||
if(fprintf(fp,
|
||||
"%4s ABIO: link=%2d adaptor=%2d card=%2d signal=%2d flag=%1d\n",
|
||||
pfield_name,
|
||||
plink->value.abio.link,plink->value.abio.adapter,
|
||||
plink->value.abio.card,plink->value.abio.signal,
|
||||
plink->value.abio.plc_flag)<0) return(-1);
|
||||
break;
|
||||
case GPIB_IO:
|
||||
if(fprintf(fp, "%4s GPIB: link=%2d taddr=%2d laddr=%2d signal=%3d\n",
|
||||
pfield_name,
|
||||
plink->value.gpibio.link,plink->value.gpibio.taddr,
|
||||
plink->value.gpibio.laddr,plink->value.gpibio.signal)<0)
|
||||
return(-1);
|
||||
break;
|
||||
case BITBUS_IO:
|
||||
if(fprintf(fp, "%4s BITBUS: link=%2d addr=%2d signal=%3d\n",
|
||||
pfield_name,
|
||||
plink->value.bitbusio.link,plink->value.bitbusio.addr,
|
||||
plink->value.bitbusio.signal)<0) return(-1);
|
||||
break;
|
||||
case DB_LINK:
|
||||
if(fprintf(fp,"%4s DB_LINK: %28s\n",
|
||||
pfield_name,
|
||||
((struct dbCommon *)(
|
||||
((struct dbAddr *)plink->value.db_link.paddr)
|
||||
->precord))->name)<0)
|
||||
return(-1);
|
||||
break;
|
||||
case CA_LINK:
|
||||
if(fprintf(fp,"%4s CA_LINK: Not Yet Implemented\n",
|
||||
pfield_name)<0) return(-1);
|
||||
break;
|
||||
default:
|
||||
errMessage(S_db_badField,"recGblReportLink: Illegal link.type");
|
||||
break;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int recGblReportCvtChoice(fp,pfield_name,choice_value)
|
||||
FILE *fp;
|
||||
char *pfield_name;
|
||||
unsigned short choice_value;
|
||||
{
|
||||
char *pchoice;
|
||||
|
||||
if(!(pchoice=GET_CHOICE(choiceCvt,choice_value))) {
|
||||
if(fprintf(fp,"%4s Illegal Choice\n",pfield_name)<0) return(-1);
|
||||
}
|
||||
else {
|
||||
if(fprintf(fp,"%4s: %s\n",pfield_name,pchoice)<0) return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int recGblReportGblChoice(fp,precord,pfield_name,choice_value)
|
||||
FILE *fp;
|
||||
struct dbCommon *precord;
|
||||
char *pfield_name;
|
||||
unsigned short choice_value;
|
||||
{
|
||||
char name[PVNAME_SZ+1+FLDNAME_SZ+1];
|
||||
struct dbAddr dbAddr;
|
||||
struct choiceSet *pchoiceSet;
|
||||
char *pchoice;
|
||||
|
||||
strncpy(name,precord->name,PVNAME_SZ);
|
||||
strcat(name,".");
|
||||
strncat(name,pfield_name,FLDNAME_SZ);
|
||||
if(dbNameToAddr(name,&dbAddr)) {
|
||||
if(fprintf(fp,"%4s dbNameToAddr failed?\n",pfield_name)<0)return(-1);
|
||||
return(0);
|
||||
}
|
||||
if( !(pchoiceSet=GET_PCHOICE_SET(choiceGbl,dbAddr.choice_set))
|
||||
|| !(pchoice=GET_CHOICE(pchoiceSet,choice_value))) {
|
||||
if(fprintf(fp,"%4s Cant find Choice\n",pfield_name)<0) return(-1);
|
||||
}
|
||||
else {
|
||||
if(fprintf(fp,"%4s: %s\n",pfield_name,pchoice)<0) return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int recGblReportRecChoice(fp,precord,pfield_name,choice_value)
|
||||
FILE *fp;
|
||||
struct dbCommon *precord;
|
||||
char *pfield_name;
|
||||
unsigned short choice_value;
|
||||
{
|
||||
char name[PVNAME_SZ+1+FLDNAME_SZ+1];
|
||||
struct dbAddr dbAddr;
|
||||
struct arrChoiceSet *parrChoiceSet;
|
||||
struct choiceSet *pchoiceSet;
|
||||
char *pchoice;
|
||||
|
||||
strncpy(name,precord->name,PVNAME_SZ);
|
||||
strcat(name,".");
|
||||
strncat(name,pfield_name,FLDNAME_SZ);
|
||||
if(dbNameToAddr(name,&dbAddr)) {
|
||||
if(fprintf(fp,"%4s dbNameToAddr failed?\n",pfield_name)<0)return(-1);
|
||||
return(0);
|
||||
}
|
||||
if( !(parrChoiceSet=GET_PARR_CHOICE_SET(choiceRec,dbAddr.record_type))
|
||||
|| !(pchoiceSet=GET_PCHOICE_SET(parrChoiceSet,dbAddr.choice_set))
|
||||
|| !(pchoice=GET_CHOICE(pchoiceSet,choice_value))) {
|
||||
if(fprintf(fp,"%4s Cant find Choice\n",pfield_name)<0) return(-1);
|
||||
}
|
||||
else {
|
||||
if(fprintf(fp,"%4s: %s\n",pfield_name,pchoice)<0) return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
Reference in New Issue
Block a user