Initial revision

This commit is contained in:
Bob Zieman
1990-10-17 05:53:39 +00:00
parent 7d92d60ecb
commit e27769db68
9 changed files with 11690 additions and 0 deletions

5905
src/db/dbAccess.c Normal file

File diff suppressed because it is too large Load Diff

751
src/db/dbEvent.c Normal file
View 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

File diff suppressed because it is too large Load Diff

780
src/db/dbTest.c Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

398
src/db/iocInit.c Normal file
View 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
View 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);
}